Merge branch 'master' into rubybuilder
diff --git a/.github/mergeable.yml b/.github/mergeable.yml
index a827eb7..ade6c67 100644
--- a/.github/mergeable.yml
+++ b/.github/mergeable.yml
@@ -11,8 +11,8 @@
                 regex: 'release notes: yes'
                 message: 'Please include release notes: yes'
             - must_include:
-                regex: '^(c#|c\+\+|cleanup|conformance tests|integration|java|javascript|go|objective-c|php|python|ruby|bazel)'
-                message: 'Please include at least a language label (e.g., c++, java, python). Or apply one of the following labels: bazel, cleanup, conformance tests, integration.'
+                regex: '^(autotools|bazel|c#|c\+\+|cleanup|cmake|conformance tests|integration|go|java|javascript|objective-c|php|protoc|python|ruby|kotlin)'
+                message: 'Please include at least a language label (e.g., c++, java, python). Or apply one of the following labels: autotools, bazel, cmake, cleanup, conformance tests, integration, protoc.'
           - must_include:
               regex: 'release notes: no'
               message: 'Please include release notes: no'
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
new file mode 100644
index 0000000..497e811
--- /dev/null
+++ b/.github/workflows/codespell.yml
@@ -0,0 +1,16 @@
+# GitHub Action to automate the identification of common misspellings in text files.
+# https://github.com/codespell-project/actions-codespell
+# https://github.com/codespell-project/codespell
+name: codespell
+on: [push, pull_request]
+jobs:
+  codespell:
+    name: Check for spelling errors
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: codespell-project/actions-codespell@master
+        with:
+          check_filenames: true
+          skip: ./.git,./conformance/third_party,*.snk,*.pb,*.pb.cc,*.pb.h,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal,./.github/workflows/codespell.yml
+          ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,sur"
diff --git a/.gitignore b/.gitignore
index 500072b..4e52414 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,9 +82,7 @@
 src/**/*.trs
 
 # JavaBuild output.
-java/core/target
-java/util/target
-javanano/target
+java/**/target
 java/.idea
 java/**/*.iml
 
@@ -104,7 +102,7 @@
 # needed to trigger "pod install" to rerun the preinstall commands.
 Pods/
 
-# Comformance test output
+# Conformance test output
 conformance/.libs/
 conformance/com/
 conformance/conformance-cpp
@@ -137,19 +135,25 @@
 
 # php test output
 composer.lock
+php/.phpunit.result.cache
+php/tests/.phpunit.result.cache
 php/tests/generated/
 php/tests/old_protoc
+php/tests/phpunit-9.phar
 php/tests/protobuf/
 php/tests/core
 php/tests/vgcore*
 php/tests/multirequest.result
 php/tests/nohup.out
+php/tests/.phpunit.result.cache
+php/tests/phpunit-*
 php/ext/google/protobuf/.libs/
 php/ext/google/protobuf/Makefile.fragments
 php/ext/google/protobuf/Makefile.global
 php/ext/google/protobuf/Makefile.objects
 php/ext/google/protobuf/acinclude.m4
 php/ext/google/protobuf/build/
+php/ext/google/protobuf/bundled_php.c
 php/ext/google/protobuf/config.h
 php/ext/google/protobuf/config.h.in~
 php/ext/google/protobuf/config.nice
@@ -157,6 +161,7 @@
 php/ext/google/protobuf/configure.in
 php/ext/google/protobuf/mkinstalldirs
 php/ext/google/protobuf/run-tests.php
+php/ext/google/protobuf/third_party/
 vendor/
 
 # JavaScript artifacts
@@ -184,6 +189,7 @@
 ruby/tests/test_import_pb.rb
 ruby/tests/test_ruby_package_pb.rb
 ruby/tests/generated_code_proto2_pb.rb
+ruby/tests/multi_level_nesting_test_pb.rb
 ruby/tests/test_import_proto2_pb.rb
 ruby/tests/test_ruby_package_proto2_pb.rb
 ruby/Gemfile.lock
@@ -208,3 +214,6 @@
 # IntelliJ
 .idea
 *.iml
+
+# BenchmarkDotNet
+BenchmarkDotNet.Artifacts/
diff --git a/BUILD b/BUILD
index 8ab4cb4..441f28b 100644
--- a/BUILD
+++ b/BUILD
@@ -3,8 +3,8 @@
 load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
 load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test", "objc_library", native_cc_proto_library = "cc_proto_library")
 load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library")
-load("@rules_proto//proto/private:native.bzl", "native_proto_common")
 load("@rules_python//python:defs.bzl", "py_library")
+load("@rules_java//java:defs.bzl", "java_binary", "java_proto_library", "java_lite_proto_library")
 load(":cc_proto_blacklist_test.bzl", "cc_proto_blacklist_test")
 
 licenses(["notice"])
@@ -15,38 +15,6 @@
 # build configuration
 ################################################################################
 
-string_flag(
-    name = "incompatible_use_com_google_googletest",
-    # TODO(yannic): Flip to `true` for `3.13.0`.
-    build_setting_default = "false",
-    values = ["true", "false"]
-)
-
-config_setting(
-    name = "use_com_google_googletest",
-    flag_values = {
-        "//:incompatible_use_com_google_googletest": "true"
-    },
-)
-
-GTEST = select({
-    "//:use_com_google_googletest": [
-        "@com_google_googletest//:gtest",
-    ],
-    "//conditions:default": [
-        "//external:gtest",
-    ],
-})
-
-GTEST_MAIN = select({
-    "//:use_com_google_googletest": [
-        "@com_google_googletest//:gtest_main",
-    ],
-    "//conditions:default": [
-        "//external:gtest_main",
-    ],
-})
-
 ################################################################################
 # ZLIB configuration
 ################################################################################
@@ -165,6 +133,7 @@
         # AUTOGEN(protobuf_lite_srcs)
         "src/google/protobuf/any_lite.cc",
         "src/google/protobuf/arena.cc",
+        "src/google/protobuf/arenastring.cc",
         "src/google/protobuf/extension_set.cc",
         "src/google/protobuf/generated_enum_util.cc",
         "src/google/protobuf/generated_message_table_driven_lite.cc",
@@ -176,6 +145,7 @@
         "src/google/protobuf/io/zero_copy_stream.cc",
         "src/google/protobuf/io/zero_copy_stream_impl.cc",
         "src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
+        "src/google/protobuf/map.cc",
         "src/google/protobuf/message_lite.cc",
         "src/google/protobuf/parse_context.cc",
         "src/google/protobuf/repeated_field.cc",
@@ -222,6 +192,7 @@
         "src/google/protobuf/dynamic_message.cc",
         "src/google/protobuf/empty.pb.cc",
         "src/google/protobuf/extension_set_heavy.cc",
+        "src/google/protobuf/field_access_listener.cc",
         "src/google/protobuf/field_mask.pb.cc",
         "src/google/protobuf/generated_message_reflection.cc",
         "src/google/protobuf/generated_message_table_driven.cc",
@@ -322,12 +293,45 @@
 
 WELL_KNOWN_PROTOS = [value[0] for value in WELL_KNOWN_PROTO_MAP.values()]
 
+LITE_WELL_KNOWN_PROTO_MAP = {
+    "any": ("src/google/protobuf/any.proto", []),
+    "api": (
+        "src/google/protobuf/api.proto",
+        [
+            "source_context",
+            "type",
+        ],
+    ),
+    "duration": ("src/google/protobuf/duration.proto", []),
+    "empty": ("src/google/protobuf/empty.proto", []),
+    "field_mask": ("src/google/protobuf/field_mask.proto", []),
+    "source_context": ("src/google/protobuf/source_context.proto", []),
+    "struct": ("src/google/protobuf/struct.proto", []),
+    "timestamp": ("src/google/protobuf/timestamp.proto", []),
+    "type": (
+        "src/google/protobuf/type.proto",
+        [
+            "any",
+            "source_context",
+        ],
+    ),
+    "wrappers": ("src/google/protobuf/wrappers.proto", []),
+}
+
+LITE_WELL_KNOWN_PROTOS = [value[0] for value in LITE_WELL_KNOWN_PROTO_MAP.values()]
+
 filegroup(
     name = "well_known_protos",
     srcs = WELL_KNOWN_PROTOS,
     visibility = ["//visibility:public"],
 )
 
+filegroup(
+    name = "lite_well_known_protos",
+    srcs = LITE_WELL_KNOWN_PROTOS,
+    visibility = ["//visibility:public"],
+)
+
 adapt_proto_library(
     name = "cc_wkt_protos_genproto",
     deps = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()],
@@ -368,7 +372,15 @@
 
 cc_proto_blacklist_test(
     name = "cc_proto_blacklist_test",
-    deps = [proto + "_cc_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()]
+    deps = [proto + "_cc_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()],
+    tags = [
+        # Exclude this target from wildcard expansion (//...). Due to
+        # https://github.com/bazelbuild/bazel/issues/10590, this test has to
+        # be nominated using the `@com_google_protobuf//` prefix. We do that,
+        # e.g., in kokoro/linux/bazel/build.sh.
+        # See also https://github.com/protocolbuffers/protobuf/pull/7096.
+        "manual",
+    ],
 )
 
 ################################################################################
@@ -392,6 +404,7 @@
         "src/google/protobuf/compiler/cpp/cpp_message.cc",
         "src/google/protobuf/compiler/cpp/cpp_message_field.cc",
         "src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc",
+        "src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc",
         "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
         "src/google/protobuf/compiler/cpp/cpp_service.cc",
         "src/google/protobuf/compiler/cpp/cpp_string_field.cc",
@@ -424,6 +437,7 @@
         "src/google/protobuf/compiler/java/java_generator.cc",
         "src/google/protobuf/compiler/java/java_generator_factory.cc",
         "src/google/protobuf/compiler/java/java_helpers.cc",
+        "src/google/protobuf/compiler/java/java_kotlin_generator.cc",
         "src/google/protobuf/compiler/java/java_map_field.cc",
         "src/google/protobuf/compiler/java/java_map_field_lite.cc",
         "src/google/protobuf/compiler/java/java_message.cc",
@@ -480,13 +494,18 @@
 # Tests
 ################################################################################
 
+filegroup(
+    name = "testdata",
+    visibility = ["//:__subpackages__"],
+    srcs = glob(["src/google/protobuf/testdata/**/*"]),
+)
+
 RELATIVE_LITE_TEST_PROTOS = [
     # AUTOGEN(lite_test_protos)
     "google/protobuf/map_lite_unittest.proto",
     "google/protobuf/unittest_import_lite.proto",
     "google/protobuf/unittest_import_public_lite.proto",
     "google/protobuf/unittest_lite.proto",
-    "google/protobuf/unittest_no_arena_lite.proto",
 ]
 
 LITE_TEST_PROTOS = ["src/" + s for s in RELATIVE_LITE_TEST_PROTOS]
@@ -513,8 +532,6 @@
     "google/protobuf/unittest_lite_imports_nonlite.proto",
     "google/protobuf/unittest_mset.proto",
     "google/protobuf/unittest_mset_wire_format.proto",
-    "google/protobuf/unittest_no_arena.proto",
-    "google/protobuf/unittest_no_arena_import.proto",
     "google/protobuf/unittest_no_field_presence.proto",
     "google/protobuf/unittest_no_generic_services.proto",
     "google/protobuf/unittest_optimize_for.proto",
@@ -544,6 +561,57 @@
 
 TEST_PROTOS = ["src/" + s for s in RELATIVE_TEST_PROTOS]
 
+GENERIC_RELATIVE_TEST_PROTOS = [
+    "google/protobuf/unittest.proto",
+    "google/protobuf/unittest_arena.proto",
+    "google/protobuf/unittest_custom_options.proto",
+    "google/protobuf/unittest_drop_unknown_fields.proto",
+    "google/protobuf/unittest_embed_optimize_for.proto",
+    "google/protobuf/unittest_empty.proto",
+    "google/protobuf/unittest_enormous_descriptor.proto",
+    "google/protobuf/unittest_import.proto",
+    "google/protobuf/unittest_import_public.proto",
+    "google/protobuf/unittest_lazy_dependencies.proto",
+    "google/protobuf/unittest_lazy_dependencies_custom_option.proto",
+    "google/protobuf/unittest_lazy_dependencies_enum.proto",
+    "google/protobuf/unittest_lite_imports_nonlite.proto",
+    "google/protobuf/unittest_mset.proto",
+    "google/protobuf/unittest_mset_wire_format.proto",
+    "google/protobuf/unittest_no_field_presence.proto",
+    "google/protobuf/unittest_no_generic_services.proto",
+    "google/protobuf/unittest_optimize_for.proto",
+    "google/protobuf/unittest_preserve_unknown_enum.proto",
+    "google/protobuf/unittest_preserve_unknown_enum2.proto",
+    "google/protobuf/unittest_proto3.proto",
+    "google/protobuf/unittest_proto3_arena.proto",
+    "google/protobuf/unittest_proto3_arena_lite.proto",
+    "google/protobuf/unittest_proto3_lite.proto",
+    "google/protobuf/unittest_proto3_optional.proto",
+    "google/protobuf/unittest_well_known_types.proto",
+]
+
+GENERIC_TEST_PROTOS = ["src/" + s for s in GENERIC_RELATIVE_TEST_PROTOS]
+
+proto_library(
+    name = "generic_test_protos",
+    visibility = ["//:__subpackages__"], 
+    strip_import_prefix = "src",
+    srcs = LITE_TEST_PROTOS + GENERIC_TEST_PROTOS,
+    deps = [
+        "//:any_proto",
+        "//:api_proto",
+        "//:descriptor_proto",
+        "//:duration_proto",
+        "//:empty_proto",
+        "//:field_mask_proto",
+        "//:source_context_proto",
+        "//:struct_proto",
+        "//:timestamp_proto",
+        "//:type_proto",
+        "//:wrappers_proto",
+    ],
+)
+
 cc_proto_library(
     name = "cc_test_protos",
     srcs = LITE_TEST_PROTOS + TEST_PROTOS,
@@ -565,6 +633,7 @@
 
 cc_binary(
     name = "test_plugin",
+    testonly = True,
     srcs = [
         # AUTOGEN(test_plugin_srcs)
         "src/google/protobuf/compiler/mock_code_generator.cc",
@@ -574,7 +643,8 @@
     deps = [
         ":protobuf",
         ":protoc_lib",
-    ] + GTEST,
+        "@com_google_googletest//:gtest",
+    ],
 )
 
 cc_test(
@@ -586,7 +656,9 @@
     ],
     deps = [
         ":protobuf_lite",
-    ] + GTEST_MAIN,
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
 )
 
 cc_test(
@@ -689,7 +761,9 @@
         ":cc_test_protos",
         ":protobuf",
         ":protoc_lib",
-    ] + PROTOBUF_DEPS + GTEST_MAIN,
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ] + PROTOBUF_DEPS,
 )
 
 ################################################################################
@@ -704,6 +778,15 @@
     ],
 )
 
+internal_gen_well_known_protos_java(
+    name = "gen_well_known_protos_javalite",
+    deps = [proto + "_proto" for proto in LITE_WELL_KNOWN_PROTO_MAP.keys()],
+    javalite = True,
+    visibility = [
+        "//java:__subpackages__",
+    ],
+)
+
 alias(
     name = "protobuf_java",
     actual = "//java/core",
@@ -742,10 +825,9 @@
     name = "python_srcs",
     srcs = glob(
         [
-            "python/google/**/*.py",
+            "python/google/protobuf/**/*.py",
         ],
         exclude = [
-            "python/google/protobuf/**/__init__.py",
             "python/google/protobuf/internal/*_test.py",
             "python/google/protobuf/internal/test_util.py",
         ],
@@ -760,6 +842,13 @@
     copts = COPTS + [
         "-DPYTHON_PROTO2_CPP_IMPL_V2",
     ],
+    tags = [
+        # Exclude this target from wildcard expansion (//...) because it may
+        # not even be buildable. It will be built if it is needed according
+        # to :use_fast_cpp_protos.
+        # https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes
+        "manual",
+    ],
     linkshared = 1,
     linkstatic = 1,
     deps = select({
@@ -784,6 +873,13 @@
         "python/",
         "src/",
     ],
+    tags = [
+        # Exclude this target from wildcard expansion (//...) because it may
+        # not even be buildable. It will be built if it is needed according
+        # to :use_fast_cpp_protos.
+        # https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes
+        "manual",
+    ],
     linkshared = 1,
     linkstatic = 1,
     deps = [
@@ -846,7 +942,6 @@
     }),
     default_runtime = "",
     protoc = ":protoc",
-    py_extra_srcs = glob(["python/**/__init__.py"]),
     py_libs = [
         ":python_srcs",
         "@six//:six",
@@ -948,13 +1043,9 @@
     ],
 )
 
-# Note: We use `native_proto_common` here because we depend on an implementation-detail of
-# `proto_lang_toolchain`, which may not be available on `proto_common`.
-reject_blacklisted_files = hasattr(native_proto_common, "proto_lang_toolchain_rejects_files_do_not_use_or_we_will_break_you_without_mercy")
-cc_toolchain_blacklisted_protos = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()] if reject_blacklisted_files else [":well_known_protos"]
 proto_lang_toolchain(
     name = "cc_toolchain",
-    blacklisted_protos = cc_toolchain_blacklisted_protos,
+    blacklisted_protos = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()],
     command_line = "--cpp_out=$(OUT)",
     runtime = ":protobuf",
     visibility = ["//visibility:public"],
@@ -962,86 +1053,13 @@
 
 alias(
     name = "objectivec",
-    actual = ":protobuf_objc",
+    actual = "//objectivec",
     visibility = ["//visibility:public"],
 )
 
-objc_library(
+alias(
     name = "protobuf_objc",
-    hdrs = [
-        "objectivec/GPBArray.h",
-        "objectivec/GPBBootstrap.h",
-        "objectivec/GPBCodedInputStream.h",
-        "objectivec/GPBCodedOutputStream.h",
-        "objectivec/GPBDescriptor.h",
-        "objectivec/GPBDictionary.h",
-        "objectivec/GPBExtensionInternals.h",
-        "objectivec/GPBExtensionRegistry.h",
-        "objectivec/GPBMessage.h",
-        "objectivec/GPBProtocolBuffers.h",
-        "objectivec/GPBProtocolBuffers_RuntimeSupport.h",
-        "objectivec/GPBRootObject.h",
-        "objectivec/GPBRuntimeTypes.h",
-        "objectivec/GPBUnknownField.h",
-        "objectivec/GPBUnknownFieldSet.h",
-        "objectivec/GPBUtilities.h",
-        "objectivec/GPBWellKnownTypes.h",
-        "objectivec/GPBWireFormat.h",
-        "objectivec/google/protobuf/Any.pbobjc.h",
-        "objectivec/google/protobuf/Api.pbobjc.h",
-        "objectivec/google/protobuf/Duration.pbobjc.h",
-        "objectivec/google/protobuf/Empty.pbobjc.h",
-        "objectivec/google/protobuf/FieldMask.pbobjc.h",
-        "objectivec/google/protobuf/SourceContext.pbobjc.h",
-        "objectivec/google/protobuf/Struct.pbobjc.h",
-        "objectivec/google/protobuf/Timestamp.pbobjc.h",
-        "objectivec/google/protobuf/Type.pbobjc.h",
-        "objectivec/google/protobuf/Wrappers.pbobjc.h",
-        # Package private headers, but exposed because the generated sources
-        # need to use them.
-        "objectivec/GPBArray_PackagePrivate.h",
-        "objectivec/GPBCodedInputStream_PackagePrivate.h",
-        "objectivec/GPBCodedOutputStream_PackagePrivate.h",
-        "objectivec/GPBDescriptor_PackagePrivate.h",
-        "objectivec/GPBDictionary_PackagePrivate.h",
-        "objectivec/GPBMessage_PackagePrivate.h",
-        "objectivec/GPBRootObject_PackagePrivate.h",
-        "objectivec/GPBUnknownFieldSet_PackagePrivate.h",
-        "objectivec/GPBUnknownField_PackagePrivate.h",
-        "objectivec/GPBUtilities_PackagePrivate.h",
-    ],
-    copts = [
-        "-Wno-vla",
-    ],
-    includes = [
-        "objectivec",
-    ],
-    non_arc_srcs = [
-        "objectivec/GPBArray.m",
-        "objectivec/GPBCodedInputStream.m",
-        "objectivec/GPBCodedOutputStream.m",
-        "objectivec/GPBDescriptor.m",
-        "objectivec/GPBDictionary.m",
-        "objectivec/GPBExtensionInternals.m",
-        "objectivec/GPBExtensionRegistry.m",
-        "objectivec/GPBMessage.m",
-        "objectivec/GPBRootObject.m",
-        "objectivec/GPBUnknownField.m",
-        "objectivec/GPBUnknownFieldSet.m",
-        "objectivec/GPBUtilities.m",
-        "objectivec/GPBWellKnownTypes.m",
-        "objectivec/GPBWireFormat.m",
-        "objectivec/google/protobuf/Any.pbobjc.m",
-        "objectivec/google/protobuf/Api.pbobjc.m",
-        "objectivec/google/protobuf/Duration.pbobjc.m",
-        "objectivec/google/protobuf/Empty.pbobjc.m",
-        "objectivec/google/protobuf/FieldMask.pbobjc.m",
-        "objectivec/google/protobuf/SourceContext.pbobjc.m",
-        "objectivec/google/protobuf/Struct.pbobjc.m",
-        "objectivec/google/protobuf/Timestamp.pbobjc.m",
-        "objectivec/google/protobuf/Type.pbobjc.m",
-        "objectivec/google/protobuf/Wrappers.pbobjc.m",
-    ],
+    actual = "//objectivec",
     visibility = ["//visibility:public"],
 )
 
@@ -1195,3 +1213,91 @@
         "update_file_lists.sh",
     ],
 )
+
+java_proto_library(
+    name = "test_messages_proto2_java_proto",
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    deps = [":test_messages_proto2_proto"],
+)
+
+java_proto_library(
+    name = "test_messages_proto3_java_proto",
+    visibility = [
+        "//java:__subpackages__",
+    ], 
+    deps = [":test_messages_proto3_proto"],
+)
+
+java_proto_library(
+    name = "conformance_java_proto",
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    deps = [":conformance_proto"],
+)
+
+java_lite_proto_library(
+    name = "test_messages_proto2_java_proto_lite",
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    deps = [":test_messages_proto2_proto"],
+)
+
+java_lite_proto_library(
+  name = "conformance_java_proto_lite",
+  visibility = [
+        "//java:__subpackages__",
+  ],
+  deps = [":conformance_proto"],
+)
+
+java_lite_proto_library(
+    name = "test_messages_proto3_java_proto_lite",
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    deps = [":test_messages_proto3_proto"],
+)
+
+java_binary(
+    name = "conformance_java",
+    srcs = ["conformance/ConformanceJava.java"],
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    main_class = "ConformanceJava",
+    deps = [
+        ":conformance_java_proto",
+        ":test_messages_proto2_java_proto",
+        ":test_messages_proto3_java_proto",
+        "//:protobuf_java",
+        "//:protobuf_java_util",
+    ],
+)
+
+java_binary(
+    name = "conformance_java_lite",
+    srcs = ["conformance/ConformanceJavaLite.java"],
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    main_class = "ConformanceJavaLite",
+    deps = [
+        ":conformance_java_proto_lite",
+        ":test_messages_proto2_java_proto_lite",
+        ":test_messages_proto3_java_proto_lite",
+        "//:protobuf_javalite",
+        "//:protobuf_java_util",
+    ],
+)
+
+exports_files([
+    "conformance/conformance_test_runner.sh",
+    "conformance/failure_list_java.txt",
+    "conformance/failure_list_java_lite.txt",
+    "conformance/text_format_failure_list_java.txt",
+    "conformance/text_format_failure_list_java_lite.txt",
+])
diff --git a/CHANGES.txt b/CHANGES.txt
index cbd3a20..f614602 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,601 @@
+2021-06-04 version 3.17.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+  C++
+  * Introduce FieldAccessListener.
+  * Stop emitting boilerplate {Copy/Merge}From in each ProtoBuf class
+  * Fixed some uninitialized variable warnings in generated_message_reflection.cc.
+
+  Kotlin
+  * Fix duplicate proto files error (#8699)
+
+  Java
+  * Fixed parser to check that we are at a proper limit when a sub-message has
+    finished parsing.
+
+2021-05-25 version 3.17.2 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+  Kotlin
+  * Fix duplicate class error (#8653)
+
+  PHP
+  * Fixed SEGV in sub-message getters for well-known types when message is unset
+    (#8670)
+
+2021-05-07 version 3.17.1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+  PHP
+  * Fixed PHP memory leaks and arginfo errors. (#8614)
+  * Fixed JSON parser to allow multiple values from the same oneof as long as
+    all but one are null.
+
+  Ruby
+  * Fixed memory bug: properly root repeated/map field when assigning. (#8639)
+  * Fixed JSON parser to allow multiple values from the same oneof as long as
+    all but one are null.
+
+
+2021-05-07 version 3.17.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Protocol Compiler
+  * Fix the generated source information for reserved values in Enums.
+
+  C++
+  * Fix -Wunused-parameter in map<string, int> fields (fixes #8494) (#8500)
+  * Use byteswap.h when building against musl libc (#8503)
+  * Fix -Wundefined-inline error when using SharedCtor() or SharedDtor() (#8532)
+  * Fix bug where `Descriptor::DebugString()` printed proto3 synthetic oneofs.
+  * Provide stable versions of `SortAndUnique()`.
+  * Make sure to cache proto3 optional message fields when they are cleared.
+  * Expose UnsafeArena methods to Reflection.
+  * Use std::string::empty() rather than std::string::size() > 0.
+
+  Kotlin
+  * Restrict extension setter and getter operators to non-nullable T.
+
+  Java
+  * updating GSON and Guava to more recent versions (#8524)
+  * Reduce the time spent evaluating isExtensionNumber by storing the extension
+    ranges in a TreeMap for faster queries. This is particularly relevant for
+    protos which define a large number of extension ranges, for example when
+    each tag is defined as an extension.
+  * Fix java bytecode estimation logic for optional fields.
+  * Optimize Descriptor.isExtensionNumber.
+
+  Python
+  * Add MethodDescriptor.CopyToProto() (#8327)
+  * Remove unused python_protobuf.{cc,h} (#8513)
+  * Start publishing python aarch64 manylinux wheels normally (#8530)
+  * Fix constness issue detected by MSVC standard conforming mode (#8568)
+  * Make JSON parsing match C++ and Java when multiple fields from the same
+    oneof are present and all but one is null.
+
+  Ruby
+  * Add support for proto3 json_name in compiler and field definitions (#8356)
+  * Fixed memory leak of Ruby arena objects. (#8461)
+  * Fix source gem compilation (#8471)
+  * Fix various exceptions in Ruby on 64-bit Windows (#8563)
+  * Fix crash when calculating Message hash values on 64-bit Windows (#8565)
+
+  Conformance Tests
+  * Added a conformance test for the case of multiple fields from the same
+    oneof.
+
+2021-04-06 version 3.16.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+  Other
+  * Opensourcing kotlin protos (#8272)
+  * Use a newer version of rules_proto, with the new rule `proto_descriptor_set` (#8469)
+
+  C++
+  * Fix compiler warnings issue found in conformance_test_runner #8189 (#8190)
+  * Fix MinGW-w64 build issues. (#8286)
+  * [Protoc] C++ Resolved an issue where NO_DESTROY and CONSTINIT are in incorrect order (#8296)
+  * Fix PROTOBUF_CONSTINIT macro redefinition (#8323)
+  * Delete StringPiecePod (#8353)
+  * Fix gcc error: comparison of unsigned expression in '>= 0' is always … (#8309)
+  * Fix cmake install on iOS (#8301)
+  * Create a CMake option to control whether or not RTTI is enabled (#8347)
+  * Fix endian.h location on FreeBSD (#8351)
+  * Refactor util::Status (#8354)
+  * Make util::Status more similar to absl::Status (#8405)
+  * Fix -Wsuggest-destructor-override for generated C++ proto classes. (#8408)
+  * Refactor StatusOr and StringPiece (#8406)
+  * Refactor uint128 (#8416)
+  * The ::pb namespace is no longer exposed due to conflicts.
+  * Allow MessageDifferencer::TreatAsSet() (and friends) to override previous
+    calls instead of crashing.
+  * Reduce the size of generated proto headers for protos with `string` or
+    `bytes` fields.
+  * Move arena() operation on uncommon path to out-of-line routine
+  * For iterator-pair function parameter types, take both iterators by value.
+  * Code-space savings and perhaps some modest performance improvements in
+    RepeatedPtrField.
+  * Eliminate nullptr check from every tag parse.
+  * Remove unused _$name$_cached_byte_size_ fields.
+  * Serialize extension ranges together when not broken by a proto field in the
+    middle.
+  * Do out-of-line allocation and deallocation of string object in ArenaString.
+  * Streamline ParseContext::ParseMessage<T> to avoid code bloat and improve
+    performance.
+  * New member functions RepeatedField::Assign, RepeatedPtrField::{Add, Assign}.
+  * Fix undefined behavior warning due to innocuous uninitialization of value
+    on an error path.
+  * Avoid expensive inlined code space for encoding message length for messages
+    >= 128 bytes and instead do a procedure call to a shared out-of-line routine.
+  * util::DefaultFieldComparator will be final in a future version of protobuf.
+    Subclasses should inherit from SimpleFieldComparator instead.
+
+  C#
+  * Add .NET 5 target and improve WriteString performance with SIMD (#8147)
+
+  Java
+  * deps: update JUnit and Truth (#8319)
+  * Detect invalid overflow of byteLimit and return InvalidProtocolBufferException as documented.
+  * Exceptions thrown while reading from an InputStream in parseFrom are now
+    included as causes.
+  * Support potentially more efficient proto parsing from RopeByteStrings.
+  * Clarify runtime of ByteString.Output.toStringBuffer().
+  * Added UnsafeByteOperations to protobuf-lite (#8426)
+
+  JavaScript
+  * Make Any.pack() chainable.
+
+  Python
+  * Fix some constness / char literal issues being found by MSVC standard conforming mode (#8344)
+  * Switch on "new" buffer API (#8339)
+  * Enable crosscompiling aarch64 python wheels under dockcross manylinux docker image (#8280)
+  * Fixed a bug in text format where a trailing colon was printed for repeated field.
+  * When TextFormat encounters a duplicate message map key, replace the current
+    one instead of merging.
+
+  Objective-C
+  * Move the class map to a CFDictionary. (#8328)
+
+  PHP
+  * read_property() handler is not supposed to return NULL (#8362)
+  * Changed parameter type from long to integer (#7613)
+  * fix: README supported PHP version for C extension (#8236)
+
+  Ruby
+  * Fixed quadratic memory usage when appending to arrays. (#8364)
+  * Fixed memory leak of Ruby arena objects. (#8461)
+  * Add support for proto3 json_name in compiler and field definitions. (#8356)
+
+  Other
+  * Some doc on AOT compilation and protobuf (#8294)
+  * [CMake] Ability to pass options to protoc executable from cmake (#8374)
+  * Add --fatal_warnings flag to treat warnings as errors (#8131)
+  * [bazel] Remove deprecated way to depend on googletest (#8396)
+  * add error returns missing from protoc to prevent it from exiting with… (#8409)
+
+
+2021-04-07 version 3.15.8 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Fixed memory leak of Ruby arena objects (#8461)
+
+2021-04-02 version 3.15.7 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  C++
+  * Remove the ::pb namespace (alias) (#8423)
+
+  Ruby
+  * Fix unbounded memory growth for Ruby <2.7 (#8429)
+  * Fixed message equality in cases where the message type is different (#8434)
+
+2021-03-10 version 3.15.6 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Fixed bug in string comparison logic (#8386)
+
+2021-03-04 version 3.15.5 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Fixed quadratic memory use in array append (#8379)
+
+  PHP
+  * Fixed quadratic memory use in array append (#8379)
+
+  C++
+  * Do not disable RTTI by default in the CMake build (#8377)
+
+2021-03-02 version 3.15.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Fixed SEGV when users pass nil messages (#8363)
+  * Fixed quadratic memory usage when appending to arrays (#8364)
+
+  C++
+  * Create a CMake option to control whether or not RTTI is enabled (#8361)
+
+  PHP
+  * read_property() handler is not supposed to return NULL (#8362)
+
+2021-02-25 version 3.15.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Ruby <2.7 now uses WeakMap too, which prevents memory leaks. (#8341)
+
+2021-02-23 version 3.15.2 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Fix for FieldDescriptor.get(msg) (#8330)
+
+  C++
+  * Fix PROTOBUF_CONSTINIT macro redefinition (#8323)
+
+2021-02-05 version 3.15.1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Bugfix for Message.[] for repeated or map fields (#8313)
+
+2021-02-05 version 3.15.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Protocol Compiler
+  * Optional fields for proto3 are enabled by default, and no longer require
+    the --experimental_allow_proto3_optional flag.
+
+  C++
+  * MessageDifferencer: fixed bug when using custom ignore with multiple
+    unknown fields
+  * Use init_seg in MSVC to push initialization to an earlier phase.
+  * Runtime no longer triggers -Wsign-compare warnings.
+  * Fixed -Wtautological-constant-out-of-range-compare warning.
+  * DynamicCastToGenerated works for nullptr input for even if RTTI is disabled
+  * Arena is refactored and optimized.
+  * Clarified/specified that the exact value of Arena::SpaceAllocated() is an
+    implementation detail users must not rely on. It should not be used in
+    unit tests.
+  * Change the signature of Any::PackFrom() to return false on error.
+  * Add fast reflection getter API for strings.
+  * Constant initialize the global message instances
+  * Avoid potential for missed wakeup in UnknownFieldSet
+  * Now Proto3 Oneof fields have "has" methods for checking their presence in
+    C++.
+  * Bugfix for NVCC
+  * Return early in _InternalSerialize for empty maps.
+  * Adding functionality for outputting map key values in proto path logging
+    output (does not affect comparison logic) and stop printing 'value' in the
+    path. The modified print functionality is in the
+    MessageDifferencer::StreamReporter.
+  * Fixed https://github.com/protocolbuffers/protobuf/issues/8129
+  * Ensure that null char symbol, package and file names do not result in a
+    crash.
+  * Constant initialize the global message instances
+  * Pretty print 'max' instead of numeric values in reserved ranges.
+  * Removed remaining instances of std::is_pod, which is deprecated in C++20.
+  * Changes to reduce code size for unknown field handling by making uncommon
+    cases out of line.
+  * Fix std::is_pod deprecated in C++20 (#7180)
+  * Fix some -Wunused-parameter warnings (#8053)
+  * Fix detecting file as directory on zOS issue #8051 (#8052)
+  * Don't include sys/param.h for _BYTE_ORDER (#8106)
+  * remove CMAKE_THREAD_LIBS_INIT from pkgconfig CFLAGS (#8154)
+  * Fix TextFormatMapTest.DynamicMessage issue#5136 (#8159)
+  * Fix for compiler warning issue#8145 (#8160)
+  * fix: support deprecated enums for GCC < 6 (#8164)
+  * Fix some warning when compiling with Visual Studio 2019 on x64 target (#8125)
+
+  Python
+  * Provided an override for the reverse() method that will reverse the internal
+    collection directly instead of using the other methods of the BaseContainer.
+  * MessageFactory.CreateProtoype can be overridden to customize class creation.
+  * Fix PyUnknownFields memory leak (#7928)
+  * Add macOS Big Sur compatibility (#8126)
+
+  JavaScript
+  * Generate `getDescriptor` methods with `*` as their `this` type.
+  * Enforce `let/const` for generated messages.
+  * js/binary/utils.js: Fix jspb.utils.joinUnsignedDecimalString to work with negative bitsLow and low but non-zero bitsHigh parameter. (#8170)
+
+  PHP
+  * Added support for PHP 8. (#8105)
+  * unregister INI entries and fix invalid read on shutdown (#8042)
+  * Fix PhpDoc comments for message accessors to include "|null". (#8136)
+  * fix: convert native PHP floats to single precision (#8187)
+  * Fixed PHP to support field numbers >=2**28. (#8235)
+  * feat: add support for deprecated fields to PHP compiler (#8223)
+  * Protect against stack overflow if the user derives from Message. (#8248)
+  * Fixed clone for Message, RepeatedField, and MapField. (#8245)
+  * Updated upb to allow nonzero offset minutes in JSON timestamps. (#8258)
+
+  Ruby
+  * Added support for Ruby 3. (#8184)
+  * Rewrote the data storage layer to be based on upb_msg objects from the
+    upb library. This should lead to much better parsing performance,
+    particularly for large messages. (#8184).
+  * Fill out JRuby support (#7923)
+  * [Ruby] Fix: (SIGSEGV) gRPC-Ruby issue on Windows. memory alloc infinite
+    recursion/run out of memory (#8195)
+  * Fix jruby support to handle messages nested more than 1 level deep (#8194)
+
+  Java
+  * Avoid possible UnsupportedOperationException when using CodedInputSteam
+    with a direct ByteBuffer.
+  * Make Durations.comparator() and Timestamps.comparator() Serializable.
+  * Add more detailed error information for dynamic message field type
+    validation failure
+  * Removed declarations of functions declared in java_names.h from
+    java_helpers.h.
+  * Now Proto3 Oneof fields have "has" methods for checking their presence in
+    Java.
+  * Annotates Java proto generated *_FIELD_NUMBER constants.
+  * Add -assumevalues to remove JvmMemoryAccessor on Android.
+
+  C#
+  * Fix parsing negative Int32Value that crosses segment boundary (#8035)
+  * Change ByteString to use memory and support unsafe create without copy (#7645)
+  * Optimize MapField serialization by removing MessageAdapter (#8143)
+  * Allow FileDescriptors to be parsed with extension registries (#8220)
+  * Optimize writing small strings (#8149)
+
+2020-11-11 version 3.14.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Protocol Compiler
+  * The proto compiler no longer requires a .proto filename when it is not
+    generating code.
+  * Added flag `--deterministic_output` to `protoc --encode=...`.
+  * Fixed deadlock when using google.protobuf.Any embedded in aggregate options.
+
+  C++
+  * Arenas are now unconditionally enabled. cc_enable_arenas no longer has
+    any effect.
+  * Removed inlined string support, which is incompatible with arenas.
+  * Fix a memory corruption bug in reflection when mixing optional and
+    non-optional fields.
+  * Make SpaceUsed() calculation more thorough for map fields.
+  * Add stack overflow protection for text format with unknown field values.
+  * FieldPath::FollowAll() now returns a bool to signal if an out-of-bounds
+    error was encountered.
+  * Performance improvements for Map.
+  * Minor formatting fix when dumping a descriptor to .proto format with
+    DebugString.
+  * UBSAN fix in RepeatedField (#2073).
+  * When running under ASAN, skip a test that makes huge allocations.
+  * Fixed a crash that could happen when creating more than 256 extensions in
+    a single message.
+  * Fix a crash in BuildFile when passing in invalid descriptor proto.
+  * Parser security fix when operating with CodedInputStream.
+  * Warn against the use of AllowUnknownExtension.
+  * Migrated to C++11 for-range loops instead of index-based loops where
+    possible. This fixes a lot of warnings when compiling with -Wsign-compare.
+  * Fix segment fault for proto3 optional (#7805)
+  * Adds a CMake option to build `libprotoc` separately (#7949)
+
+  Java
+  * Bugfix in mergeFrom() when a oneof has multiple message fields.
+  * Fix RopeByteString.RopeInputStream.read() returning -1 when told to read
+    0 bytes when not at EOF.
+  * Redefine remove(Object) on primitive repeated field Lists to avoid
+    autoboxing.
+  * Support "\u" escapes in textformat string literals.
+  * Trailing empty spaces are no longer ignored for FieldMask.
+  * Fix FieldMaskUtil.subtract to recursively remove mask.
+  * Mark enums with `@java.lang.Deprecated` if the proto enum has option
+    `deprecated = true;`.
+  * Adding forgotten duration.proto to the lite library (#7738)
+
+  Python
+  * Print google.protobuf.NullValue as null instead of "NULL_VALUE" when it is
+    used outside WKT Value/Struct.
+  * Fix bug occurring when attempting to deep copy an enum type in python 3.
+  * Add a setuptools extension for generating Python protobufs (#7783)
+  * Remove uses of pkg_resources in non-namespace packages. (#7902)
+  * [bazel/py] Omit google/__init__.py from the Protobuf runtime. (#7908)
+  * Removed the unnecessary setuptools package dependency for Python package (#7511)
+  * Fix PyUnknownFields memory leak (#7928)
+
+  PHP
+  * Added support for "==" to the PHP C extension (#7883)
+  * Added `==` operators for Map and Array. (#7900)
+  * Native C well-known types (#7944)
+  * Optimized away hex2bin() call in generated code (#8006)
+  * New version of upb, and a new hash function wyhash in third_party. (#8000)
+  * add missing hasOneof method to check presence of oneof fields (#8003)
+
+  Go:
+  * Update go_package options to reference google.golang.org/protobuf module.
+
+  C#:
+  * annotate ByteString.CopyFrom(ReadOnlySpan<byte>) as SecuritySafeCritical (#7701)
+  * Fix C# optional field reflection when there are regular fields too (#7705)
+  * Fix parsing negative Int32Value that crosses segment boundary (#8035)
+
+  Javascript:
+  * JS: parse (un)packed fields conditionally (#7379)
+
+2020-07-14 version 3.13.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  PHP:
+  * The C extension is completely rewritten. The new C extension has significantly
+    better parsing performance and fixes a handful of conformance issues. It will
+    also make it easier to add support for more features like proto2 and proto3 presence.
+  * The new C extension does not support PHP 5.x. PHP 5.x users can still use pure-PHP.
+
+  C++:
+  * Removed deprecated unsafe arena string accessors
+  * Enabled heterogeneous lookup for std::string keys in maps.
+  * Removed implicit conversion from StringPiece to std::string
+  * Fix use-after-destroy bug when the Map is allocated in the arena.
+  * Improved the randomness of map ordering
+  * Added stack overflow protection for text format with unknown fields
+  * Use std::hash for proto maps to help with portability.
+  * Added more Windows macros to proto whitelist.
+  * Arena constructors for map entry messages are now marked "explicit"
+    (for regular messages they were already explicit).
+  * Fix subtle aliasing bug in RepeatedField::Add
+  * Fix mismatch between MapEntry ByteSize and Serialize with respect to unset
+    fields.
+
+  Python:
+  * JSON format conformance fixes:
+    * Reject lowercase t for Timestamp json format.
+    * Print full_name directly for extensions (no camelCase).
+    * Reject boolean values for integer fields.
+    * Reject NaN, Infinity, -Infinity that is not quoted.
+    * Base64 fixes for bytes fields: accept URL-safe base64 and missing padding.
+  * Bugfix for fields/files named "async" or "await".
+  * Improved the error message when AttributeError is returned from __getattr__
+    in EnumTypeWrapper.
+
+  Java:
+  * Fixed a bug where setting optional proto3 enums with setFooValue() would
+    not mark the value as present.
+  * Add Subtract function to FieldMaskUtil.
+
+  C#:
+  * Dropped support for netstandard1.0 (replaced by support for netstandard1.1).
+    This was required to modernize the parsing stack to use the `Span<byte>`
+    type internally. (#7351)
+  * Add `ParseFrom(ReadOnlySequence<byte>)` method to enable GC friendly
+    parsing with reduced allocations and buffer copies. (#7351)
+  * Add support for serialization directly to a `IBufferWriter<byte>` or
+    to a `Span<byte>` to enable GC friendly serialization.
+    The new API is available as extension methods on the `IMessage` type. (#7576)
+  * Add `GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE` define to make
+    generated code compatible with old C# compilers (pre-roslyn compilers
+    from .NET framework and old versions of mono) that do not support
+    ref structs. Users that are still on a legacy stack that does
+    not support C# 7.2 compiler might need to use the new define
+    in their projects to be able to build the newly generated code. (#7490)
+  * Due to the major overhaul of parsing and serialization internals (#7351 and #7576),
+    it is recommended to regenerate your generated code to achieve the best
+    performance (the legacy generated code will still work, but might incur
+    a slight performance penalty).
+
+2020-07-28 version 3.12.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+This release contains no significant changes, but exists because 3.12.3 was
+mistakenly tagged at the wrong commit.
+
+2020-06-01 version 3.12.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Objective-C
+  * Tweak the union used for Extensions to support old generated code. #7573
+
+2020-05-26 version 3.12.2 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  C++
+  * Simplified the template export macros to fix the build for mingw32. (#7539)
+
+  Objective-C
+  * Fix for the :protobuf_objc target in the Bazel BUILD file. (#7538)
+
+2020-05-20 version 3.12.1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Ruby
+  * Re-add binary gems for Ruby 2.3 and 2.4. These are EOL upstream, however
+    many people still use them and dropping support will require more
+    coordination.
+
+2020-05-12 version 3.12.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  Protocol Compiler
+  * [experimental] Singular, non-message typed fields in proto3 now support
+    presence tracking. This is enabled by adding the "optional" field label and
+    passing the --experimental_allow_proto3_optional flag to protoc.
+    * For usage info, see docs/field_presence.md.
+    * During this experimental phase, code generators should update to support
+      proto3 presence, see docs/implementing_proto3_presence.md for instructions.
+  * Allow duplicate symbol names when multiple descriptor sets are passed on
+    the command-line, to match the behavior when multiple .proto files are passed.
+  * Deterministic `protoc --descriptor_set_out` (#7175)
+
+  C++
+  * [experimental] Added proto3 presence support.
+  * New descriptor APIs to support proto3 presence.
+  * Enable Arenas by default on all .proto files.
+  * Documented that users are not allowed to subclass Message or MessageLite.
+  * Mark generated classes as final; inheriting from protos is strongly discouraged.
+  * Add stack overflow protection for text format with unknown fields.
+  * Add accessors for map key and value FieldDescriptors.
+  * Add FieldMaskUtil::FromFieldNumbers().
+  * MessageDifferencer: use ParsePartial() on Any fields so the diff does not
+    fail when there are missing required fields.
+  * ReflectionOps::Merge(): lookup messages in the right factory, if it can.
+  * Added Descriptor::WellKnownTypes enum and Descriptor::well_known_type()
+    accessor as an easier way of determining if a message is a Well-Known Type.
+  * Optimized RepeatedField::Add() when it is used in a loop.
+  * Made proto move/swap more efficient.
+  * De-virtualize the GetArena() method in MessageLite.
+  * Improves performance of json_stream_parser.cc by factor 1000 (#7230)
+  * bug: #7076 undefine Windows OUT and OPTIONAL macros (#7087)
+  * Fixed a bug in FieldDescriptor::DebugString() that would erroneously print
+    an "optional" label for a field in a oneof.
+  * Fix bug in parsing bool extensions that assumed they are always 1 byte.
+  * Fix off-by-one error in FieldOptions::ByteSize() when extensions are present.
+  * Clarified the comments to show an example of the difference between
+    Descriptor::extension and DescriptorPool::FindAllExtensions.
+  * Add a compiler option 'code_size' to force optimize_for=code_size on all
+    protos where this is possible.
+
+  Java
+  * [experimental] Added proto3 presence support.
+  * Mark java enum _VALUE constants as @Deprecated if the enum field is deprecated
+  * reduce <clinit> size for enums with allow_alias set to true.
+  * Sort map fields alphabetically by the field's key when printing textproto.
+  * Fixed a bug in map sorting that appeared in -rc1 and -rc2 (#7508).
+  * TextFormat.merge() handles Any as top level type.
+  * Throw a descriptive IllegalArgumentException when calling
+    getValueDescriptor() on enum special value UNRECOGNIZED instead of
+    ArrayIndexOutOfBoundsException.
+  * Fixed an issue with JsonFormat.printer() where setting printingEnumsAsInts()
+    would override the configuration passed into includingDefaultValueFields().
+  * Implement overrides of indexOf() and contains() on primitive lists returned
+    for repeated fields to avoid autoboxing the list contents.
+  * Add overload to FieldMaskUtil.fromStringList that accepts a descriptor.
+  * [bazel] Move Java runtime/toolchains into //java (#7190)
+
+  Python
+  * [experimental] Added proto3 presence support.
+  * [experimental] fast import protobuf module, only works with cpp generated code linked in.
+  * Truncate 'float' fields to 4 bytes of precision in setters for pure-Python
+    implementation (C++ extension was already doing this).
+  * Fixed a memory leak in C++ bindings.
+  * Added a deprecation warning when code tries to create Descriptor objects
+    directly.
+  * Fix unintended comparison between bytes and string in descriptor.py.
+  * Avoid printing excess digits for float fields in TextFormat.
+  * Remove Python 2.5 syntax compatibility from the proto compiler generated _pb2.py module code.
+  * Drop 3.3, 3.4 and use single version docker images for all python tests (#7396)
+
+  JavaScript
+  * Fix js message pivot selection (#6813)
+
+  PHP
+  * Persistent Descriptor Pool (#6899)
+  * Implement lazy loading of php class for proto messages (#6911)
+  * Correct @return in Any.unpack docblock (#7089)
+  * Ignore unknown enum value when ignore_unknown specified (#7455)
+
+  Ruby
+  * [experimental] Implemented proto3 presence for Ruby. (#7406)
+  * Stop building binary gems for ruby <2.5 (#7453)
+  * Fix for wrappers with a zero value (#7195)
+  * Fix for JSON serialization of 0/empty-valued wrapper types (#7198)
+  * Call "Class#new" over rb_class_new_instance in decoding (#7352)
+  * Build extensions for Ruby 2.7 (#7027)
+  * assigning 'nil' to submessage should clear the field. (#7397)
+
+  C#
+  * [experimental] Add support for proto3 presence fields in C# (#7382)
+  * Mark GetOption API as obsolete and expose the "GetOptions()" method on descriptors instead (#7491)
+  * Remove Has/Clear members for C# message fields in proto2 (#7429)
+  * Enforce recursion depth checking for unknown fields (#7132)
+  * Fix conformance test failures for Google.Protobuf (#6910)
+  * Cleanup various bits of Google.Protobuf (#6674)
+  * Fix latest ArgumentException for C# extensions (#6938)
+  * Remove unnecessary branch from ReadTag (#7289)
+
+  Objective-C
+  * [experimental] ObjC Proto3 optional support (#7421)
+  * Block subclassing of generated classes (#7124)
+  * Use references to Obj C classes instead of names in descriptors. (#7026)
+  * Revisit how the WKTs are bundled with ObjC. (#7173)
+
+  Other
+  * Add a proto_lang_toolchain for javalite (#6882)
+  * [bazel] Update gtest and deprecate //external:{gtest,gtest_main} (#7237)
+  * Add application note for explicit presence tracking. (#7390)
+  * Howto doc for implementing proto3 presence in a code generator. (#7407)
+
+
 2020-02-14 version 3.11.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
   
   C#
diff --git a/Makefile.am b/Makefile.am
index 090e503..a71f4d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,7 @@
   csharp/protos/unittest_import.proto                                        \
   csharp/protos/unittest_issues.proto                                        \
   csharp/protos/unittest_proto3.proto                                        \
+  csharp/protos/unittest_selfreferential_options.proto                       \
   csharp/protos/unittest.proto                                               \
   csharp/src/AddressBook/AddPerson.cs                                        \
   csharp/src/AddressBook/Addressbook.cs                                      \
@@ -88,18 +89,22 @@
   csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs            \
   csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs           \
   csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs                        \
+  csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs               \
   csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj    \
   csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs            \
-  csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs       \
   csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs            \
+  csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs       \
   csharp/src/Google.Protobuf.Benchmarks/Program.cs                           \
   csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto     \
   csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs          \
+  csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs            \
+  csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs       \
   csharp/src/Google.Protobuf.Conformance/Conformance.cs                      \
   csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj  \
   csharp/src/Google.Protobuf.Conformance/Program.cs                          \
   csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj        \
   csharp/src/Google.Protobuf.JsonDump/Program.cs                             \
+  csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs               \
   csharp/src/Google.Protobuf.Test/ByteStringTest.cs                          \
   csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs              \
   csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs                    \
@@ -122,6 +127,11 @@
   csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs                       \
   csharp/src/Google.Protobuf.Test/JsonParserTest.cs                          \
   csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs                       \
+  csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs                 \
+  csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs                   \
+  csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs                      \
+  csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs                 \
+  csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs              \
   csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs            \
   csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs    \
   csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs              \
@@ -148,6 +158,8 @@
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs                  \
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs                  \
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs                  \
+  csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs          \
+  csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs  \
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs          \
   csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs                        \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs                  \
@@ -160,6 +172,7 @@
   csharp/src/Google.Protobuf.sln                                             \
   csharp/src/Google.Protobuf/ByteArray.cs                                    \
   csharp/src/Google.Protobuf/ByteString.cs                                   \
+  csharp/src/Google.Protobuf/ByteStringAsync.cs                              \
   csharp/src/Google.Protobuf/CodedInputStream.cs                             \
   csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs                \
   csharp/src/Google.Protobuf/CodedOutputStream.cs                            \
@@ -180,6 +193,7 @@
   csharp/src/Google.Protobuf/FieldMaskTree.cs                                \
   csharp/src/Google.Protobuf/FrameworkPortability.cs                         \
   csharp/src/Google.Protobuf/Google.Protobuf.csproj                          \
+  csharp/src/Google.Protobuf/IBufferMessage.cs                               \
   csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs                     \
   csharp/src/Google.Protobuf/IDeepCloneable.cs                               \
   csharp/src/Google.Protobuf/IExtendableMessage.cs                           \
@@ -194,7 +208,13 @@
   csharp/src/Google.Protobuf/MessageExtensions.cs                            \
   csharp/src/Google.Protobuf/MessageParser.cs                                \
   csharp/src/Google.Protobuf/ObjectIntPair.cs                                \
+  csharp/src/Google.Protobuf/ParseContext.cs                                 \
+  csharp/src/Google.Protobuf/ParserInternalState.cs                          \
+  csharp/src/Google.Protobuf/ParsingPrimitives.cs                            \
+  csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs                    \
+  csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs                    \
   csharp/src/Google.Protobuf/ProtoPreconditions.cs                           \
+  csharp/src/Google.Protobuf/SegmentedBufferHelper.cs                        \
   csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs                      \
   csharp/src/Google.Protobuf/Reflection/CustomOptions.cs                     \
   csharp/src/Google.Protobuf/Reflection/Descriptor.cs                        \
@@ -244,17 +264,23 @@
   csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs                      \
   csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs               \
   csharp/src/Google.Protobuf/WireFormat.cs                                   \
+  csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs                    \
+  csharp/src/Google.Protobuf/WritingPrimitives.cs                            \
+  csharp/src/Google.Protobuf/WriterInternalState.cs                          \
+  csharp/src/Google.Protobuf/WriteContext.cs                                 \
+  csharp/src/Google.Protobuf/WriteBufferHelper.cs                            \
   csharp/src/Google.Protobuf/UnknownField.cs                                 \
-  csharp/src/Google.Protobuf/UnknownFieldSet.cs
+  csharp/src/Google.Protobuf/UnknownFieldSet.cs                              \
+  csharp/src/Google.Protobuf/UnsafeByteOperations.cs
 
 java_EXTRA_DIST=                                                                   \
-  java/BUILD                                                                       \
   java/README.md                                                                   \
   java/bom/pom.xml                                                                 \
   java/core/BUILD                                                                  \
   java/core/generate-sources-build.xml                                             \
   java/core/generate-test-sources-build.xml                                        \
   java/core/pom.xml                                                                \
+  java/core/pom_template.xml                                                       \
   java/core/src/main/java/com/google/protobuf/AbstractMessage.java                 \
   java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java             \
   java/core/src/main/java/com/google/protobuf/AbstractParser.java                  \
@@ -504,38 +530,70 @@
   java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto               \
   java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto          \
   java/core/src/test/proto/com/google/protobuf/test_custom_options.proto           \
-  java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto         \
   java/core/src/test/proto/com/google/protobuf/wrappers_test.proto                 \
+  java/internal/BUILD                                                              \
+  java/internal/testing.bzl                                                        \
+  java/kotlin/generate-sources-build.xml                                           \
+  java/kotlin/generate-test-sources-build.xml                                      \
+  java/kotlin/pom.xml                                                              \
+  java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt                       \
+  java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt                        \
+  java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt                      \
+  java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt   \
+  java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt\
+  java/kotlin/src/main/kotlin/com/google/protobuf/ExtensionList.kt                 \
+  java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt\
+  java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt                \
+  java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt       \
+  java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt                   \
+  java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt                    \
+  java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt\
+  java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt             \
+  java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt                    \
+  java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt                    \
+  java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto           \
+  java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto           \
+  java/kotlin/src/test/proto/com/google/protobuf/example_extensible_message.proto  \
+  java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto       \
+  java/kotlin-lite/generate-sources-build.xml                                      \
+  java/kotlin-lite/generate-test-sources-build.xml                                 \
+  java/kotlin-lite/lite.awk                                                        \
+  java/kotlin-lite/pom.xml                                                         \
+  java/kotlin-lite/process-lite-sources-build.xml                                  \
+  java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt\
+  java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt           \
   java/lite.md                                                                     \
   java/lite/BUILD                                                                  \
   java/lite/generate-sources-build.xml                                             \
   java/lite/generate-test-sources-build.xml                                        \
   java/lite/lite.awk                                                               \
   java/lite/pom.xml                                                                \
+  java/lite/pom_template.xml                                                       \
   java/lite/process-lite-sources-build.xml                                         \
   java/lite/src/test/java/com/google/protobuf/LiteTest.java                        \
   java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java    \
+  java/BUILD                                                                       \
   java/pom.xml                                                                     \
   java/util/BUILD                                                                  \
   java/util/pom.xml                                                                \
+  java/util/pom_template.xml                                                       \
   java/util/src/main/java/com/google/protobuf/util/Durations.java                  \
   java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java              \
   java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java              \
   java/util/src/main/java/com/google/protobuf/util/JsonFormat.java                 \
-  java/util/src/main/java/com/google/protobuf/util/TimeUtil.java                   \
   java/util/src/main/java/com/google/protobuf/util/Structs.java                    \
   java/util/src/main/java/com/google/protobuf/util/Timestamps.java                 \
   java/util/src/main/java/com/google/protobuf/util/Values.java                     \
   java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java          \
   java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java          \
   java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java             \
-  java/util/src/test/java/com/google/protobuf/util/StructsTest.java                 \
-  java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java               \
+  java/util/src/test/java/com/google/protobuf/util/StructsTest.java                \
   java/util/src/test/java/com/google/protobuf/util/ValuesTest.java                 \
   java/util/src/test/proto/com/google/protobuf/util/json_test.proto
 
 objectivec_EXTRA_DIST=                                                       \
   objectivec/.clang-format                                                   \
+  objectivec/BUILD                                                           \
   objectivec/DevTools/check_version_stamps.sh                                \
   objectivec/DevTools/compile_testing_protos.sh                              \
   objectivec/DevTools/full_mac_build.sh                                      \
@@ -744,25 +802,32 @@
 php_EXTRA_DIST=                                                       \
   composer.json                                                       \
   php/README.md                                                       \
+  php/REFCOUNTING.md                                                  \
   php/composer.json                                                   \
+  php/ext/google/protobuf/arena.c                                     \
+  php/ext/google/protobuf/arena.h                                     \
   php/ext/google/protobuf/array.c                                     \
-  php/ext/google/protobuf/builtin_descriptors.inc                     \
+  php/ext/google/protobuf/array.h                                     \
   php/ext/google/protobuf/config.m4                                   \
+  php/ext/google/protobuf/convert.c                                   \
+  php/ext/google/protobuf/convert.h                                   \
   php/ext/google/protobuf/def.c                                       \
-  php/ext/google/protobuf/encode_decode.c                             \
+  php/ext/google/protobuf/def.h                                       \
   php/ext/google/protobuf/map.c                                       \
+  php/ext/google/protobuf/map.h                                       \
   php/ext/google/protobuf/message.c                                   \
+  php/ext/google/protobuf/message.h                                   \
+  php/ext/google/protobuf/names.c                                     \
+  php/ext/google/protobuf/names.h                                     \
   php/ext/google/protobuf/package.xml                                 \
+  php/ext/google/protobuf/php-upb.c                                   \
+  php/ext/google/protobuf/php-upb.h                                   \
   php/ext/google/protobuf/protobuf.c                                  \
   php/ext/google/protobuf/protobuf.h                                  \
-  php/ext/google/protobuf/storage.c                                   \
-  php/ext/google/protobuf/type_check.c                                \
-  php/ext/google/protobuf/upb.c                                       \
-  php/ext/google/protobuf/upb.h                                       \
-  php/ext/google/protobuf/utf8.c                                      \
-  php/ext/google/protobuf/utf8.h                                      \
+  php/ext/google/protobuf/wkt.inc                                     \
   php/generate_descriptor_protos.sh                                   \
-  php/phpunit.xml                                                     \
+  php/generate_test_protos.sh                                         \
+  php/prepare_c_extension.sh                                          \
   php/release.sh                                                      \
   php/src/GPBMetadata/Google/Protobuf/Any.php                         \
   php/src/GPBMetadata/Google/Protobuf/Api.php                         \
@@ -798,6 +863,7 @@
   php/src/Google/Protobuf/GPBEmpty.php                                \
   php/src/Google/Protobuf/Int32Value.php                              \
   php/src/Google/Protobuf/Int64Value.php                              \
+  php/src/Google/Protobuf/Internal/AnyBase.php                        \
   php/src/Google/Protobuf/Internal/CodedInputStream.php               \
   php/src/Google/Protobuf/Internal/CodedOutputStream.php              \
   php/src/Google/Protobuf/Internal/Descriptor.php                     \
@@ -857,6 +923,7 @@
   php/src/Google/Protobuf/Internal/ServiceOptions.php                 \
   php/src/Google/Protobuf/Internal/SourceCodeInfo.php                 \
   php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php        \
+  php/src/Google/Protobuf/Internal/TimestampBase.php                  \
   php/src/Google/Protobuf/Internal/UninterpretedOption.php            \
   php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php   \
   php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php \
@@ -887,22 +954,21 @@
   php/src/Google/Protobuf/UInt64Value.php                             \
   php/src/Google/Protobuf/Value.php                                   \
   php/src/phpdoc.dist.xml                                             \
-  php/tests/array_test.php                                            \
-  php/tests/autoload.php                                              \
-  php/tests/bootstrap_phpunit.php                                     \
+  php/tests/ArrayTest.php                                             \
   php/tests/compatibility_test.sh                                     \
   php/tests/compile_extension.sh                                      \
-  php/tests/descriptors_test.php                                      \
-  php/tests/encode_decode_test.php                                    \
+  php/tests/DescriptorsTest.php                                       \
+  php/tests/EncodeDecodeTest.php                                      \
+  php/tests/force_c_ext.php                                           \
   php/tests/gdb_test.sh                                               \
-  php/tests/generated_class_test.php                                  \
-  php/tests/generated_phpdoc_test.php                                 \
-  php/tests/generated_service_test.php                                \
-  php/tests/map_field_test.php                                        \
+  php/tests/GeneratedClassTest.php                                    \
+  php/tests/GeneratedPhpdocTest.php                                   \
+  php/tests/GeneratedServiceTest.php                                  \
+  php/tests/MapFieldTest.php                                          \
   php/tests/memory_leak_test.php                                      \
   php/tests/multirequest.php                                          \
   php/tests/multirequest.sh                                           \
-  php/tests/php_implementation_test.php                               \
+  php/tests/PhpImplementationTest.php                                 \
   php/tests/proto/empty/echo.proto                                    \
   php/tests/proto/test.proto                                          \
   php/tests/proto/test_descriptors.proto                              \
@@ -921,12 +987,11 @@
   php/tests/proto/test_service.proto                                  \
   php/tests/proto/test_service_namespace.proto                        \
   php/tests/proto/test_wrapper_type_setters.proto                     \
-  php/tests/test.sh                                                   \
   php/tests/test_base.php                                             \
   php/tests/test_util.php                                             \
-  php/tests/undefined_test.php                                        \
-  php/tests/well_known_test.php                                       \
-  php/tests/wrapper_type_setters_test.php
+  php/tests/valgrind.supp                                             \
+  php/tests/WellKnownTest.php                                         \
+  php/tests/WrapperTypeSettersTest.php
 
 python_EXTRA_DIST=                                                           \
   python/MANIFEST.in                                                         \
@@ -973,7 +1038,6 @@
   python/google/protobuf/internal/packed_field_test.proto                    \
   python/google/protobuf/internal/proto_builder_test.py                      \
   python/google/protobuf/internal/python_message.py                          \
-  python/google/protobuf/internal/python_protobuf.cc                         \
   python/google/protobuf/internal/reflection_test.py                         \
   python/google/protobuf/internal/service_reflection_test.py                 \
   python/google/protobuf/internal/symbol_database_test.py                    \
@@ -994,7 +1058,6 @@
   python/google/protobuf/json_format.py                                      \
   python/google/protobuf/message.py                                          \
   python/google/protobuf/message_factory.py                                  \
-  python/google/protobuf/python_protobuf.h                                   \
   python/google/protobuf/proto_api.h                                         \
   python/google/protobuf/proto_builder.py                                    \
   python/google/protobuf/pyext/README                                        \
@@ -1058,17 +1121,21 @@
   ruby/compatibility_tests/v3.0.0/test.sh                                    \
   ruby/compatibility_tests/v3.0.0/Rakefile                                   \
   ruby/compatibility_tests/v3.0.0/README.md                                  \
+  ruby/ext/google/protobuf_c/convert.c                                       \
+  ruby/ext/google/protobuf_c/convert.h                                       \
   ruby/ext/google/protobuf_c/defs.c                                          \
-  ruby/ext/google/protobuf_c/encode_decode.c                                 \
+  ruby/ext/google/protobuf_c/defs.h                                          \
   ruby/ext/google/protobuf_c/extconf.rb                                      \
   ruby/ext/google/protobuf_c/map.c                                           \
+  ruby/ext/google/protobuf_c/map.h                                           \
   ruby/ext/google/protobuf_c/message.c                                       \
+  ruby/ext/google/protobuf_c/message.h                                       \
   ruby/ext/google/protobuf_c/protobuf.c                                      \
   ruby/ext/google/protobuf_c/protobuf.h                                      \
   ruby/ext/google/protobuf_c/repeated_field.c                                \
-  ruby/ext/google/protobuf_c/storage.c                                       \
-  ruby/ext/google/protobuf_c/upb.c                                           \
-  ruby/ext/google/protobuf_c/upb.h                                           \
+  ruby/ext/google/protobuf_c/repeated_field.h                                \
+  ruby/ext/google/protobuf_c/ruby-upb.c                                      \
+  ruby/ext/google/protobuf_c/ruby-upb.h                                      \
   ruby/ext/google/protobuf_c/wrap_memcpy.c                                   \
   ruby/google-protobuf.gemspec                                               \
   ruby/lib/google/protobuf/message_exts.rb                                   \
@@ -1079,13 +1146,15 @@
   ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java              \
   ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java           \
   ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java       \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java                 \
   ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java   \
   ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java       \
-  ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java                 \
   ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java      \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java   \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java       \
   ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java                  \
-  ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java \
   ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java              \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java \
   ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java  \
   ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java      \
   ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java             \
@@ -1106,6 +1175,8 @@
   ruby/tests/generated_code_proto2_test.rb                                   \
   ruby/tests/generated_code_proto2.proto                                     \
   ruby/tests/generated_code.proto                                            \
+  ruby/tests/multi_level_nesting_test.proto                                  \
+  ruby/tests/multi_level_nesting_test.rb                                     \
   ruby/tests/test_import_proto2.proto                                        \
   ruby/tests/test_import.proto                                               \
   ruby/tests/test_ruby_package_proto2.proto                                  \
@@ -1193,6 +1264,10 @@
   js/data.proto                                                        \
   js/debug.js                                                          \
   js/debug_test.js                                                     \
+  js/experimental/runtime/kernel/message_set.js                        \
+  js/experimental/runtime/kernel/message_set_test.js                   \
+  js/experimental/runtime/kernel/tag.js                                \
+  js/experimental/runtime/kernel/tag_test.js                           \
   js/gulpfile.js                                                       \
   js/jasmine.json                                                      \
   js/map.js                                                            \
@@ -1349,13 +1424,12 @@
   examples/pubspec.yaml                  \
   protobuf.bzl                           \
   protobuf_deps.bzl                      \
-  python/release/wheel/build_wheel_manylinux.sh  \
-  python/release/wheel/Dockerfile                \
-  python/release/wheel/protobuf_optimized_pip.sh \
-  python/release/wheel/README.md         \
   third_party/six.BUILD                  \
   third_party/zlib.BUILD                 \
-  util/python/BUILD
+  third_party/wyhash/LICENSE             \
+  third_party/wyhash/wyhash.h            \
+  util/python/BUILD                      \
+  internal.bzl
 
 
 # Deletes all the files generated by autogen.sh.
diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec
index dcb9f4d..2e81a7c 100644
--- a/Protobuf-C++.podspec
+++ b/Protobuf-C++.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name     = 'Protobuf-C++'
-  s.version  = '3.11.4'
+  s.version  = '3.17.3'
   s.summary  = 'Protocol Buffers v3 runtime library for C++.'
   s.homepage = 'https://github.com/google/protobuf'
   s.license  = '3-Clause BSD License'
diff --git a/Protobuf.podspec b/Protobuf.podspec
index d6d6a8e..c1b4795 100644
--- a/Protobuf.podspec
+++ b/Protobuf.podspec
@@ -5,7 +5,7 @@
 # dependent projects use the :git notation to refer to the library.
 Pod::Spec.new do |s|
   s.name     = 'Protobuf'
-  s.version  = '3.11.4'
+  s.version  = '3.17.3'
   s.summary  = 'Protocol Buffers v.3 runtime library for Objective-C.'
   s.homepage = 'https://github.com/protocolbuffers/protobuf'
   s.license  = '3-Clause BSD License'
@@ -34,7 +34,7 @@
   s.user_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' }
   s.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' }
 
-  s.ios.deployment_target = '7.0'
+  s.ios.deployment_target = '9.0'
   s.osx.deployment_target = '10.9'
   s.tvos.deployment_target = '9.0'
   s.watchos.deployment_target = '2.0'
diff --git a/README.md b/README.md
index 2f42c6c..618dc2a 100644
--- a/README.md
+++ b/README.md
@@ -52,18 +52,18 @@
 language, you can find instructions in the corresponding source directory about
 how to install protobuf runtime for that specific language:
 
-| Language                             | Source                                                      | Ubuntu | MacOS | Windows |
-|--------------------------------------|-------------------------------------------------------------|--------|-------|---------|
-| C++ (include C++ runtime and protoc) | [src](src)                                                  | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcpp_distcheck%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-bazel.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fbazel%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-dist_install.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fdist_install%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp_distcheck%2Fcontinuous) | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) |
-| Java                                 | [java](java)                                                | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_compatibility%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_jdk7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_jdk7%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_oracle7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_oracle7%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_linkage_monitor.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_linkage_monitor%2Fcontinuous) | | |
-| Python                               | [python](python)                                            | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fpython_release%2Fcontinuous) |
-| Objective-C                          | [objectivec](objectivec)                                    | | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_cocoapods_integration.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_cocoapods_integration%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_debug.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_debug%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_release%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_osx.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_osx%2Fcontinuous) | |
-| C#                                   | [csharp](csharp)                                            | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-csharp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcsharp%2Fcontinuous) | | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-csharp-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fcsharp_release%2Fcontinuous) |
-| JavaScript                           | [js](js)                                                    | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) | |
-| Ruby                                 | [ruby](ruby)                                                | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby23%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby24%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby25%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby26.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby26%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby23%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby24%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby25%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby26.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby26%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby_release%2Fcontinuous) | |
-| Go                                   | [golang/protobuf](https://github.com/golang/protobuf)       | | | |
-| PHP                                  | [php](php)                                                  | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-php_all.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fphp_all%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-32-bit.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2F32-bit%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php5.6_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp5.6_mac%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php7.0_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp7.0_mac%2Fcontinuous) | |
-| Dart                                 | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) | [![Build Status](https://travis-ci.org/dart-lang/protobuf.svg?branch=master)](https://travis-ci.org/dart-lang/protobuf) | | |
+| Language                             | Source                                                      |
+|--------------------------------------|-------------------------------------------------------------|
+| C++ (include C++ runtime and protoc) | [src](src)                                                  |
+| Java                                 | [java](java)                                                |
+| Python                               | [python](python)                                            |
+| Objective-C                          | [objectivec](objectivec)                                    |
+| C#                                   | [csharp](csharp)                                            |
+| JavaScript                           | [js](js)                                                    |
+| Ruby                                 | [ruby](ruby)                                                |
+| Go                                   | [protocolbuffers/protobuf-go](https://github.com/protocolbuffers/protobuf-go)|
+| PHP                                  | [php](php)                                                  |
+| Dart                                 | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) |
 
 Quick Start
 -----------
diff --git a/WORKSPACE b/WORKSPACE
index cb16ae8..94aa8d8 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -17,76 +17,82 @@
     ],
 )
 
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-load("//:protobuf_deps.bzl", "protobuf_deps")
+http_archive(
+    name = "com_github_google_benchmark",
+    sha256 = "2a778d821997df7d8646c9c59b8edb9a573a6e04c534c01892a40aa524a7b68c",
+    strip_prefix = "benchmark-bf585a2789e30585b4e3ce6baf11ef2750b54677",
+    urls = [
+        "https://github.com/google/benchmark/archive/bf585a2789e30585b4e3ce6baf11ef2750b54677.zip",
+    ],
+)
 
 # Load common dependencies.
+load("//:protobuf_deps.bzl", "protobuf_deps")
 protobuf_deps()
-load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external")
 
 bind(
     name = "python_headers",
     actual = "//util/python:python_headers",
 )
 
-# TODO(yannic): Remove in 3.13.0.
-bind(
-    name = "gtest",
-    actual = "@com_google_googletest//:gtest",
-)
-
-# TODO(yannic): Remove in 3.13.0.
-bind(
-    name = "gtest_main",
-    actual = "@com_google_googletest//:gtest_main",
-)
-
-jvm_maven_import_external(
-    name = "guava_maven",
-    artifact = "com.google.guava:guava:18.0",
-    artifact_sha256 = "d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99",
-    server_urls = [
-        "https://jcenter.bintray.com/",
-        "https://repo1.maven.org/maven2",
+load("@rules_jvm_external//:defs.bzl", "maven_install")
+maven_install(
+    artifacts = [
+        "com.google.code.gson:gson:2.8.6",
+        "com.google.errorprone:error_prone_annotations:2.3.2",
+        "com.google.guava:guava:30.1.1-jre",
+        "com.google.truth:truth:1.1.2",
+        "junit:junit:4.12",
+        "org.easymock:easymock:3.2",
+        "org.easymock:easymockclassextension:3.2",
     ],
+    repositories = [
+        "https://repo1.maven.org/maven2",
+        "https://repo.maven.apache.org/maven2",
+    ],
+    # For updating instructions, see: 
+    # https://github.com/bazelbuild/rules_jvm_external#updating-maven_installjson
+    maven_install_json = "//:maven_install.json",
 )
 
+load("@maven//:defs.bzl", "pinned_maven_install")
+pinned_maven_install()
+
 bind(
     name = "guava",
-    actual = "@guava_maven//jar",
-)
-
-jvm_maven_import_external(
-    name = "gson_maven",
-    artifact = "com.google.code.gson:gson:2.7",
-    artifact_sha256 = "2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32",
-    server_urls = [
-        "https://jcenter.bintray.com/",
-        "https://repo1.maven.org/maven2",
-    ],
+    actual = "@maven//:com_google_guava_guava",
 )
 
 bind(
     name = "gson",
-    actual = "@gson_maven//jar",
-)
-
-jvm_maven_import_external(
-    name = "error_prone_annotations_maven",
-    artifact = "com.google.errorprone:error_prone_annotations:2.3.2",
-    artifact_sha256 = "357cd6cfb067c969226c442451502aee13800a24e950fdfde77bcdb4565a668d",
-    server_urls = [
-        "https://jcenter.bintray.com/",
-        "https://repo1.maven.org/maven2",
-    ],
+    actual = "@maven//:com_google_code_gson_gson",
 )
 
 bind(
     name = "error_prone_annotations",
-    actual = "@error_prone_annotations_maven//jar",
+    actual = "@maven//:com_google_errorprone_error_prone_annotations",
 )
 
-# For `cc_proto_blacklist_test`.
-load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
+bind(
+    name = "junit",
+    actual = "@maven//:junit_junit",
+)
 
+bind(
+    name = "easymock",
+    actual = "@maven//:org_easymock_easymock",
+)
+
+bind(
+    name = "easymock_classextension",
+    actual = "@maven//:org_easymock_easymockclassextension",
+)
+
+bind(
+    name = "truth",
+    actual = "@maven//:com_google_truth_truth",
+)
+
+# For `cc_proto_blacklist_test` and `build_test`.
+load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
 bazel_skylib_workspace()
diff --git a/autogen.sh b/autogen.sh
index d00d217..105bf09 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -30,8 +30,12 @@
 
 # The absence of a m4 directory in googletest causes autoreconf to fail when
 # building under the CentOS docker image. It's a warning in regular build on
-# Ubuntu/gLinux as well.
-mkdir -p third_party/googletest/m4
+# Ubuntu/gLinux as well. (This is only needed if git submodules have been
+# initialized, which is typically only needed for testing; see the installation
+# instructions for details.)
+if test -d third_party/googletest; then
+  mkdir -p third_party/googletest/m4
+fi
 
 # TODO(kenton):  Remove the ",no-obsolete" part and fix the resulting warnings.
 autoreconf -f -i -Wall,no-obsolete
diff --git a/benchmarks/BUILD b/benchmarks/BUILD
new file mode 100644
index 0000000..8e6063b
--- /dev/null
+++ b/benchmarks/BUILD
@@ -0,0 +1,65 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+proto_library(
+    name = "benchmarks_proto",
+    srcs = [
+        "benchmarks.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmarks_cc_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "benchmarks_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmarks_java_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "benchmarks_proto",
+    ],
+)
+
+proto_library(
+    name = "google_size_proto",
+    srcs = [
+        "google_size.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+)
+
+cc_proto_library(
+    name = "google_size_cc_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "google_size_proto",
+    ],
+)
+
+java_proto_library(
+    name = "google_size_java_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "google_size_proto",
+    ],
+)
diff --git a/benchmarks/README.md b/benchmarks/README.md
index 436c148..7678817 100644
--- a/benchmarks/README.md
+++ b/benchmarks/README.md
@@ -135,7 +135,7 @@
 
 
 ### PHP
-We have two version of php protobuf implemention: pure php, php with c extension. To run these version benchmark, you need to:
+We have two version of php protobuf implementation: pure php, php with c extension. To run these version benchmark, you need to:
 #### Pure PHP
 ```
 $ make php
diff --git a/benchmarks/cpp/BUILD b/benchmarks/cpp/BUILD
new file mode 100644
index 0000000..b744f89
--- /dev/null
+++ b/benchmarks/cpp/BUILD
@@ -0,0 +1,15 @@
+load("@rules_cc//cc:defs.bzl", "cc_binary")
+
+cc_binary(
+    name = "cpp",
+    srcs = [
+        "cpp_benchmark.cc",
+    ],
+    tags = ["benchmark"],
+    deps = [
+        "//:protobuf",
+        "//benchmarks:benchmarks_cc_proto",
+        "//benchmarks/datasets:cc_protos",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
diff --git a/benchmarks/datasets/BUILD b/benchmarks/datasets/BUILD
new file mode 100644
index 0000000..f29a276
--- /dev/null
+++ b/benchmarks/datasets/BUILD
@@ -0,0 +1,59 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@rules_java//java:defs.bzl", "java_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "//benchmarks/datasets/google_message1/proto2:datasets",
+        "//benchmarks/datasets/google_message1/proto3:datasets",
+        "//benchmarks/datasets/google_message2:datasets",
+        "//benchmarks/datasets/google_message3:datasets",
+        "//benchmarks/datasets/google_message4:datasets",
+    ],
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+)
+
+proto_library(
+    name = "protos",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "//benchmarks/datasets/google_message1/proto2:benchmark_message1_proto2_proto",
+        "//benchmarks/datasets/google_message1/proto3:benchmark_message1_proto3_proto",
+        "//benchmarks/datasets/google_message2:benchmark_message2_proto",
+        "//benchmarks/datasets/google_message3:benchmark_message3_proto",
+        "//benchmarks/datasets/google_message4:benchmark_message4_proto",
+    ],
+)
+
+cc_library(
+    name = "cc_protos",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "//benchmarks/datasets/google_message1/proto2:benchmark_message1_proto2_cc_proto",
+        "//benchmarks/datasets/google_message1/proto3:benchmark_message1_proto3_cc_proto",
+        "//benchmarks/datasets/google_message2:benchmark_message2_cc_proto",
+        "//benchmarks/datasets/google_message3:benchmark_message3_cc_proto",
+        "//benchmarks/datasets/google_message4:benchmark_message4_cc_proto",
+    ],
+)
+
+java_library(
+    name = "java_protos",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    exports = [
+        "//benchmarks/datasets/google_message1/proto2:benchmark_message1_proto2_java_proto",
+        "//benchmarks/datasets/google_message1/proto3:benchmark_message1_proto3_java_proto",
+        "//benchmarks/datasets/google_message2:benchmark_message2_java_proto",
+        "//benchmarks/datasets/google_message3:benchmark_message3_java_proto",
+        "//benchmarks/datasets/google_message4:benchmark_message4_java_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message1/proto2/BUILD b/benchmarks/datasets/google_message1/proto2/BUILD
new file mode 100644
index 0000000..d4d38ce
--- /dev/null
+++ b/benchmarks/datasets/google_message1/proto2/BUILD
@@ -0,0 +1,44 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "dataset.google_message1_proto2.pb",
+    ],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message1_proto2_proto",
+    srcs = [
+        "benchmark_message1_proto2.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message1_proto2_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto2_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message1_proto2_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto2_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message1/proto3/BUILD b/benchmarks/datasets/google_message1/proto3/BUILD
new file mode 100644
index 0000000..c2d627a
--- /dev/null
+++ b/benchmarks/datasets/google_message1/proto3/BUILD
@@ -0,0 +1,44 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "dataset.google_message1_proto3.pb",
+    ],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message1_proto3_proto",
+    srcs = [
+        "benchmark_message1_proto3.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message1_proto3_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto3_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message1_proto3_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto3_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message2/BUILD b/benchmarks/datasets/google_message2/BUILD
new file mode 100644
index 0000000..1ca87fb
--- /dev/null
+++ b/benchmarks/datasets/google_message2/BUILD
@@ -0,0 +1,44 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "dataset.google_message2.pb",
+    ],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message2_proto",
+    srcs = [
+        "benchmark_message2.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message2_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message2_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message2_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message2_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message3/BUILD b/benchmarks/datasets/google_message3/BUILD
new file mode 100644
index 0000000..9a00294
--- /dev/null
+++ b/benchmarks/datasets/google_message3/BUILD
@@ -0,0 +1,50 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message3_proto",
+    srcs = [
+        "benchmark_message3.proto",
+        "benchmark_message3_1.proto",
+        "benchmark_message3_2.proto",
+        "benchmark_message3_3.proto",
+        "benchmark_message3_4.proto",
+        "benchmark_message3_5.proto",
+        "benchmark_message3_6.proto",
+        "benchmark_message3_7.proto",
+        "benchmark_message3_8.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message3_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message3_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message3_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message3_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message4/BUILD b/benchmarks/datasets/google_message4/BUILD
new file mode 100644
index 0000000..b23a4c9
--- /dev/null
+++ b/benchmarks/datasets/google_message4/BUILD
@@ -0,0 +1,45 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message4_proto",
+    srcs = [
+        "benchmark_message4.proto",
+        "benchmark_message4_1.proto",
+        "benchmark_message4_2.proto",
+        "benchmark_message4_3.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message4_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message4_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message4_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message4_proto",
+    ],
+)
diff --git a/benchmarks/download_data.sh b/benchmarks/download_data.sh
deleted file mode 100755
index fa0729e..0000000
--- a/benchmarks/download_data.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /bin/sh
-
-curl -O https://storage.googleapis.com/protobuf_opensource_benchmark_data/datasets.tar.gz
-tar -zvxf datasets.tar.gz
-
diff --git a/benchmarks/java/pom.xml b/benchmarks/java/pom.xml
index 570bd66..c0dc940 100644
--- a/benchmarks/java/pom.xml
+++ b/benchmarks/java/pom.xml
@@ -22,7 +22,7 @@
     <dependency>
       <groupId>com.google.caliper</groupId>
       <artifactId>caliper</artifactId>
-      <version>1.0-beta-2</version>
+      <version>1.0-beta-3</version>
     </dependency>
   </dependencies>
 
diff --git a/benchmarks/js/js_benchmark.js b/benchmarks/js/js_benchmark.js
index c44fee0..9ba4828 100644
--- a/benchmarks/js/js_benchmark.js
+++ b/benchmarks/js/js_benchmark.js
@@ -41,9 +41,9 @@
     totalBytes += onePayload.length;
   });
 
-  var senarios = benchmarkSuite.newBenchmark(
+  var scenarios = benchmarkSuite.newBenchmark(
       benchmarkDataset.getMessageName(), filename, "js");
-  senarios.suite
+  scenarios.suite
   .add("js deserialize", function() {
     benchmarkDataset.getPayloadList().forEach(function(onePayload) {
       var protoType = getNewPrototype(benchmarkDataset.getMessageName());
@@ -61,15 +61,15 @@
   results.push({
     filename: filename,
     benchmarks: {
-      protobufjs_decoding: senarios.benches[0] * totalBytes / 1024 / 1024,
-      protobufjs_encoding: senarios.benches[1] * totalBytes / 1024 / 1024
+      protobufjs_decoding: scenarios.benches[0] * totalBytes / 1024 / 1024,
+      protobufjs_encoding: scenarios.benches[1] * totalBytes / 1024 / 1024
     }
   })
 
   console.log("Throughput for deserialize: "
-    + senarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" );
+    + scenarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" );
   console.log("Throughput for serialize: "
-    + senarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" );
+    + scenarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" );
   console.log("");
 });
 console.log("#####################################################");
diff --git a/benchmarks/protobuf.js/protobufjs_benchmark.js b/benchmarks/protobuf.js/protobufjs_benchmark.js
index 19e5497..e062d1c 100644
--- a/benchmarks/protobuf.js/protobufjs_benchmark.js
+++ b/benchmarks/protobuf.js/protobufjs_benchmark.js
@@ -31,9 +31,9 @@
     totalBytes += onePayload.length;
   });
 
-  var senarios = benchmarkSuite.newBenchmark(
+  var scenarios = benchmarkSuite.newBenchmark(
     benchmarkDataset.messageName, filename, "protobufjs");
-  senarios.suite
+  scenarios.suite
   .add("protobuf.js static decoding", function() {
     benchmarkDataset.payload.forEach(function(onePayload) {
       var protoType = getNewPrototype(benchmarkDataset.messageName);
@@ -51,15 +51,15 @@
   results.push({
     filename: filename,
     benchmarks: {
-      protobufjs_decoding: senarios.benches[0] * totalBytes,
-      protobufjs_encoding: senarios.benches[1] * totalBytes
+      protobufjs_decoding: scenarios.benches[0] * totalBytes,
+      protobufjs_encoding: scenarios.benches[1] * totalBytes
     }
   })
 
   console.log("Throughput for decoding: "
-    + senarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" );
+    + scenarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" );
   console.log("Throughput for encoding: "
-    + senarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" );
+    + scenarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" );
   console.log("");
 });
 console.log("#####################################################");
diff --git a/benchmarks/util/result_parser.py b/benchmarks/util/result_parser.py
index b09f387..896f47a 100644
--- a/benchmarks/util/result_parser.py
+++ b/benchmarks/util/result_parser.py
@@ -1,5 +1,6 @@
 # This import depends on the automake rule protoc_middleman, please make sure
 # protoc_middleman has been built before run this file.
+import argparse
 import json
 import re
 import os.path
@@ -298,3 +299,39 @@
     __parse_php_result(php_c_file, "php")
 
   return __results
+
+if __name__ == "__main__":
+  parser = argparse.ArgumentParser()
+  parser.add_argument("-cpp", "--cpp_input_file",
+                      help="The CPP benchmark result file's name",
+                      default="")
+  parser.add_argument("-java", "--java_input_file",
+                      help="The Java benchmark result file's name",
+                      default="")
+  parser.add_argument("-python", "--python_input_file",
+                      help="The Python benchmark result file's name",
+                      default="")
+  parser.add_argument("-go", "--go_input_file",
+                      help="The golang benchmark result file's name",
+                      default="")
+  parser.add_argument("-node", "--node_input_file",
+                      help="The node.js benchmark result file's name",
+                      default="")
+  parser.add_argument("-php", "--php_input_file",
+                      help="The pure php benchmark result file's name",
+                      default="")
+  parser.add_argument("-php_c", "--php_c_input_file",
+                      help="The php with c ext benchmark result file's name",
+                      default="")
+  args = parser.parse_args()
+
+  results = get_result_from_file(
+      cpp_file=args.cpp_input_file,
+      java_file=args.java_input_file,
+      python_file=args.python_input_file,
+      go_file=args.go_input_file,
+      node_file=args.node_input_file,
+      php_file=args.php_input_file,
+      php_c_file=args.php_c_input_file,
+  )
+  print(json.dumps(results, indent=2))
diff --git a/build_files_updated_unittest.sh b/build_files_updated_unittest.sh
index c863071..87541c3 100755
--- a/build_files_updated_unittest.sh
+++ b/build_files_updated_unittest.sh
@@ -58,5 +58,5 @@
 
 # Test whether there are any differences
 for file in ${generated_files[@]}; do
-  diff "${golden_dir}/${file}" "${test_dir}/${file}"
+  diff -du "${golden_dir}/${file}" "${test_dir}/${file}"
 done
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 8496799..61a5c3d 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -29,7 +29,7 @@
 endif()
 
 # The Intel compiler isn't able to deal with noinline member functions of
-# template classses defined in headers.  As such it spams the output with
+# template classes defined in headers.  As such it spams the output with
 #   warning #2196: routine is both "inline" and "noinline"
 # This silences that warning.
 if (CMAKE_CXX_COMPILER_ID MATCHES Intel)
@@ -37,10 +37,15 @@
 endif()
 
 # Options
+if(WITH_PROTOC)
+  set(protobuf_PROTOC_EXE ${WITH_PROTOC} CACHE FILEPATH "Protocol Buffer Compiler executable" FORCE)
+endif()
 option(protobuf_BUILD_TESTS "Build tests" ON)
 option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF)
 option(protobuf_BUILD_EXAMPLES "Build examples" OFF)
 option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON)
+option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF)
+option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF)
 if (BUILD_SHARED_LIBS)
   set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON)
 else (BUILD_SHARED_LIBS)
@@ -58,6 +63,10 @@
 # User options
 include(protobuf-options.cmake)
 
+# Overrides for option dependencies
+if (protobuf_BUILD_PROTOC_BINARIES OR protobuf_BUILD_TESTS)
+  set(protobuf_BUILD_LIBPROTOC ON)
+endif ()
 # Path to main configure script
 set(protobuf_CONFIGURE_SCRIPT "../configure.ac")
 
@@ -109,6 +118,10 @@
 
 add_definitions(-DGOOGLE_PROTOBUF_CMAKE_BUILD)
 
+if (protobuf_DISABLE_RTTI)
+  add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=1)
+endif()
+
 find_package(Threads REQUIRED)
 if (CMAKE_USE_PTHREADS_INIT)
   add_definitions(-DHAVE_PTHREAD)
@@ -180,8 +193,10 @@
 endif (protobuf_BUILD_SHARED_LIBS)
 
 if (MSVC)
-  # Build with multiple processes
-  add_definitions(/MP)
+  if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+    # Build with multiple processes
+    add_definitions(/MP)
+  endif()
   # MSVC warning suppressions
   add_definitions(
     /wd4018 # 'expression' : signed/unsigned mismatch
@@ -209,12 +224,14 @@
   # Suppress linker warnings about files with no symbols defined.
   set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
 
-  # Configure Resource Compiler
-  enable_language(RC)
-  # use English language (0x409) in resource compiler
-  set(rc_flags "/l0x409")
-  # fix rc.exe invocations because of usage of add_definitions()
-  set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> ${rc_flags} <DEFINES> /fo<OBJECT> <SOURCE>")
+  if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+    # Configure Resource Compiler
+    enable_language(RC)
+    # use English language (0x409) in resource compiler
+    set(rc_flags "/l0x409")
+    # fix rc.exe invocations because of usage of add_definitions()
+    set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> ${rc_flags} <DEFINES> /fo<OBJECT> <SOURCE>")
+  endif()
 
   configure_file(version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
 endif (MSVC)
@@ -242,11 +259,29 @@
 
 include(libprotobuf-lite.cmake)
 include(libprotobuf.cmake)
-if (protobuf_BUILD_PROTOC_BINARIES)
+if (protobuf_BUILD_LIBPROTOC)
   include(libprotoc.cmake)
+endif (protobuf_BUILD_LIBPROTOC)
+if (protobuf_BUILD_PROTOC_BINARIES)
   include(protoc.cmake)
+  if (NOT DEFINED protobuf_PROTOC_EXE)
+    set(protobuf_PROTOC_EXE protoc)
+  endif (NOT DEFINED protobuf_PROTOC_EXE)
 endif (protobuf_BUILD_PROTOC_BINARIES)
 
+# Ensure we have a protoc executable if we need one
+if (protobuf_BUILD_TESTS OR protobuf_BUILD_CONFORMANCE OR protobuf_BUILD_EXAMPLES)
+  if (NOT DEFINED protobuf_PROTOC_EXE)
+    find_program(protobuf_PROTOC_EXE protoc)
+    if (NOT protobuf_PROTOC_EXE)
+      message(FATAL "Build requires 'protoc' but binary not found and not building protoc.")
+    endif ()
+  endif ()
+  if(protobuf_VERBOSE)
+    message(STATUS "Using protoc : ${protobuf_PROTOC_EXE}")
+  endif(protobuf_VERBOSE)
+endif ()
+
 if (protobuf_BUILD_TESTS)
   include(tests.cmake)
 endif (protobuf_BUILD_TESTS)
@@ -262,5 +297,5 @@
 endif (protobuf_BUILD_EXAMPLES)
 
 if(protobuf_VERBOSE)
-    message(STATUS "Protocol Buffers Configuring done")
-endif()
+  message(STATUS "Protocol Buffers Configuring done")
+endif(protobuf_VERBOSE)
diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake
index 82b4cf5..056b5d0 100644
--- a/cmake/conformance.cmake
+++ b/cmake/conformance.cmake
@@ -1,8 +1,8 @@
 
 add_custom_command(
   OUTPUT ${protobuf_source_dir}/conformance/conformance.pb.cc
-  DEPENDS protoc ${protobuf_source_dir}/conformance/conformance.proto
-  COMMAND protoc ${protobuf_source_dir}/conformance/conformance.proto
+  DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/conformance/conformance.proto
+  COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/conformance/conformance.proto
       --proto_path=${protobuf_source_dir}/conformance
       --cpp_out=${protobuf_source_dir}/conformance
 )
@@ -10,9 +10,9 @@
 add_custom_command(
   OUTPUT ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc
          ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc
-  DEPENDS protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
-          protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
-  COMMAND protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
+  DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
+          ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
+  COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
                  ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
       --proto_path=${protobuf_source_dir}/src
       --cpp_out=${protobuf_source_dir}/src
@@ -21,7 +21,6 @@
 add_executable(conformance_test_runner
   ${protobuf_source_dir}/conformance/conformance.pb.cc
   ${protobuf_source_dir}/conformance/conformance_test.cc
-  ${protobuf_source_dir}/conformance/binary_json_conformance_main.cc
   ${protobuf_source_dir}/conformance/binary_json_conformance_suite.cc
   ${protobuf_source_dir}/conformance/binary_json_conformance_suite.h
   ${protobuf_source_dir}/conformance/conformance_test_runner.cc
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in
index 007cc80..d2ab2de 100644
--- a/cmake/extract_includes.bat.in
+++ b/cmake/extract_includes.bat.in
@@ -26,6 +26,7 @@
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h" include\google\protobuf\compiler\csharp\csharp_names.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h" include\google\protobuf\compiler\importer.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h" include\google\protobuf\compiler\java\java_generator.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_kotlin_generator.h" include\google\protobuf\compiler\java\java_kotlin_generator.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h" include\google\protobuf\compiler\java\java_names.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\js_generator.h" include\google\protobuf\compiler\js\js_generator.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\well_known_types_embed.h" include\google\protobuf\compiler\js\well_known_types_embed.h
@@ -45,15 +46,18 @@
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.pb.h" include\google\protobuf\empty.pb.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set.h" include\google\protobuf\extension_set.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set_inl.h" include\google\protobuf\extension_set_inl.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_access_listener.h" include\google\protobuf\field_access_listener.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h" include\google\protobuf\field_mask.pb.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h" include\google\protobuf\generated_enum_reflection.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h" include\google\protobuf\generated_enum_util.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h" include\google\protobuf\generated_message_reflection.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven.h" include\google\protobuf\generated_message_table_driven.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_decl.h" include\google\protobuf\generated_message_tctable_decl.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_impl.h" include\google\protobuf\generated_message_tctable_impl.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_impl.inc" include\google\protobuf\generated_message_tctable_impl.inc
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\implicit_weak_message.h" include\google\protobuf\implicit_weak_message.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\inlined_string_field.h" include\google\protobuf\inlined_string_field.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h" include\google\protobuf\io\gzip_stream.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\io_win32.h" include\google\protobuf\io\io_win32.h
@@ -88,7 +92,6 @@
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" include\google\protobuf\stubs\casts.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h" include\google\protobuf\stubs\common.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h" include\google\protobuf\stubs\fastmem.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h" include\google\protobuf\stubs\hash.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h" include\google\protobuf\stubs\logging.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h" include\google\protobuf\stubs\macros.h
diff --git a/cmake/install.cmake b/cmake/install.cmake
index be47c54..ef5bb13 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -6,9 +6,9 @@
                ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc @ONLY)
 
 set(_protobuf_libraries libprotobuf-lite libprotobuf)
-if (protobuf_BUILD_PROTOC_BINARIES)
+if (protobuf_BUILD_LIBPROTOC)
     list(APPEND _protobuf_libraries libprotoc)
-endif (protobuf_BUILD_PROTOC_BINARIES)
+endif (protobuf_BUILD_LIBPROTOC)
 
 foreach(_library ${_protobuf_libraries})
   set_property(TARGET ${_library}
@@ -30,7 +30,9 @@
 
 if (protobuf_BUILD_PROTOC_BINARIES)
   install(TARGETS protoc EXPORT protobuf-targets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
+    COMPONENT protoc)
   if (UNIX AND NOT APPLE)
     set_property(TARGET protoc
       PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
@@ -102,12 +104,16 @@
 
 # Install configuration
 set(_cmakedir_desc "Directory relative to CMAKE_INSTALL to install the cmake configuration files")
+set(_exampledir_desc "Directory relative to CMAKE_INSTALL_DATA to install examples")
 if(NOT MSVC)
   set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/protobuf" CACHE STRING "${_cmakedir_desc}")
+  set(CMAKE_INSTALL_EXAMPLEDIR "${CMAKE_INSTALL_DATADIR}/protobuf/examples" CACHE STRING "${_exampledir_desc}")
 else()
   set(CMAKE_INSTALL_CMAKEDIR "cmake" CACHE STRING "${_cmakedir_desc}")
+  set(CMAKE_INSTALL_EXAMPLEDIR "examples" CACHE STRING "${_exampledir_desc}")
 endif()
 mark_as_advanced(CMAKE_INSTALL_CMAKEDIR)
+mark_as_advanced(CMAKE_INSTALL_EXAMPLEDIR)
 
 configure_file(protobuf-config.cmake.in
   ${CMAKE_INSTALL_CMAKEDIR}/protobuf-config.cmake @ONLY)
@@ -145,6 +151,7 @@
 
 option(protobuf_INSTALL_EXAMPLES "Install the examples folder" OFF)
 if(protobuf_INSTALL_EXAMPLES)
-  install(DIRECTORY ../examples/ DESTINATION examples
+  install(DIRECTORY ../examples/
+    DESTINATION "${CMAKE_INSTALL_EXAMPLEDIR}"
     COMPONENT protobuf-examples)
 endif()
diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake
index 6bf86a2..e6fab3b 100644
--- a/cmake/libprotobuf-lite.cmake
+++ b/cmake/libprotobuf-lite.cmake
@@ -1,6 +1,7 @@
 set(libprotobuf_lite_files
   ${protobuf_source_dir}/src/google/protobuf/any_lite.cc
   ${protobuf_source_dir}/src/google/protobuf/arena.cc
+  ${protobuf_source_dir}/src/google/protobuf/arenastring.cc
   ${protobuf_source_dir}/src/google/protobuf/extension_set.cc
   ${protobuf_source_dir}/src/google/protobuf/generated_enum_util.cc
   ${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven_lite.cc
@@ -12,6 +13,7 @@
   ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc
   ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc
   ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/map.cc
   ${protobuf_source_dir}/src/google/protobuf/message_lite.cc
   ${protobuf_source_dir}/src/google/protobuf/parse_context.cc
   ${protobuf_source_dir}/src/google/protobuf/repeated_field.cc
@@ -55,7 +57,7 @@
   ${protobuf_source_dir}/src/google/protobuf/wire_format_lite.h
 )
 
-if (MSVC)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
 set(libprotobuf_lite_rc_files
   ${CMAKE_CURRENT_BINARY_DIR}/version.rc
 )
@@ -67,6 +69,9 @@
 if(protobuf_LINK_LIBATOMIC)
   target_link_libraries(libprotobuf-lite atomic)
 endif()
+if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+	target_link_libraries(libprotobuf-lite log)
+endif()
 target_include_directories(libprotobuf-lite PUBLIC ${protobuf_source_dir}/src)
 if(MSVC AND protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotobuf-lite
diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake
index 0c12596..f5a70be 100644
--- a/cmake/libprotobuf.cmake
+++ b/cmake/libprotobuf.cmake
@@ -11,6 +11,7 @@
   ${protobuf_source_dir}/src/google/protobuf/dynamic_message.cc
   ${protobuf_source_dir}/src/google/protobuf/empty.pb.cc
   ${protobuf_source_dir}/src/google/protobuf/extension_set_heavy.cc
+  ${protobuf_source_dir}/src/google/protobuf/field_access_listener.cc
   ${protobuf_source_dir}/src/google/protobuf/field_mask.pb.cc
   ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection.cc
   ${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven.cc
@@ -65,6 +66,7 @@
   ${protobuf_source_dir}/src/google/protobuf/duration.pb.h
   ${protobuf_source_dir}/src/google/protobuf/dynamic_message.h
   ${protobuf_source_dir}/src/google/protobuf/empty.pb.h
+  ${protobuf_source_dir}/src/google/protobuf/field_access_listener.h
   ${protobuf_source_dir}/src/google/protobuf/field_mask.pb.h
   ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection.h
   ${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.h
@@ -106,7 +108,7 @@
   ${protobuf_source_dir}/src/google/protobuf/wrappers.pb.h
 )
 
-if (MSVC)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
 set(libprotobuf_rc_files
   ${CMAKE_CURRENT_BINARY_DIR}/version.rc
 )
@@ -121,6 +123,9 @@
 if(protobuf_LINK_LIBATOMIC)
   target_link_libraries(libprotobuf atomic)
 endif()
+if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+	target_link_libraries(libprotobuf log)
+endif()
 target_include_directories(libprotobuf PUBLIC ${protobuf_source_dir}/src)
 if(MSVC AND protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotobuf
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index b71f2f1..a6f7919 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -12,6 +12,7 @@
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -44,6 +45,7 @@
   ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator_factory.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_kotlin_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field_lite.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message.cc
@@ -93,8 +95,10 @@
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_names.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_options.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -159,7 +163,7 @@
   ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.h
 )
 
-if (MSVC)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
 set(libprotoc_rc_files
   ${CMAKE_CURRENT_BINARY_DIR}/version.rc
 )
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index 11b85d3..9197625 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -15,7 +15,7 @@
   if(COMMAND target_sources)
     list(APPEND _singleargs TARGET)
   endif()
-  set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS)
+  set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS)
 
   cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
 
@@ -99,13 +99,17 @@
   foreach(_proto ${protobuf_generate_PROTOS})
     get_filename_component(_abs_file ${_proto} ABSOLUTE)
     get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
-    get_filename_component(_basename ${_proto} NAME_WLE)
+
+    get_filename_component(_file_full_name ${_proto} NAME)
+    string(FIND "${_file_full_name}" "." _file_last_ext_pos REVERSE)
+    string(SUBSTRING "${_file_full_name}" 0 ${_file_last_ext_pos} _basename)
 
     set(_suitable_include_found FALSE)
     foreach(DIR ${_protobuf_include_path})
       if(NOT DIR STREQUAL "-I")
         file(RELATIVE_PATH _rel_dir ${DIR} ${_abs_dir})
-        if(NOT "${_rel_dir}" MATCHES "^\.\.[/\\].*")
+        string(FIND "${_rel_dir}" "../" _is_in_parent_folder)
+        if (NOT ${_is_in_parent_folder} EQUAL 0)
           set(_suitable_include_found TRUE)
           break()
         endif()
@@ -126,9 +130,9 @@
     add_custom_command(
       OUTPUT ${_generated_srcs}
       COMMAND  protobuf::protoc
-      ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
+      ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
       DEPENDS ${_abs_file} protobuf::protoc
-      COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}"
+      COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}. Custom options: ${protobuf_generate_PROTOC_OPTIONS}"
       VERBATIM )
   endforeach()
 
diff --git a/cmake/protobuf-lite.pc.cmake b/cmake/protobuf-lite.pc.cmake
index cbe5426..9745cb8 100644
--- a/cmake/protobuf-lite.pc.cmake
+++ b/cmake/protobuf-lite.pc.cmake
@@ -7,5 +7,5 @@
 Description: Google's Data Interchange Format
 Version: @protobuf_VERSION@
 Libs: -L${libdir} -lprotobuf-lite @CMAKE_THREAD_LIBS_INIT@
-Cflags: -I${includedir} @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir}
 Conflicts: protobuf
diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in
index 74c5488..810256e 100644
--- a/cmake/protobuf-module.cmake.in
+++ b/cmake/protobuf-module.cmake.in
@@ -97,6 +97,10 @@
   else()
     get_target_property(${name}_LIBRARY_RELEASE protobuf::lib${filename}
       LOCATION_RELEASE)
+    get_target_property(${name}_LIBRARY_RELWITHDEBINFO protobuf::lib${filename}
+      LOCATION_RELWITHDEBINFO)
+    get_target_property(${name}_LIBRARY_MINSIZEREL protobuf::lib${filename}
+      LOCATION_MINSIZEREL)
     get_target_property(${name}_LIBRARY_DEBUG protobuf::lib${filename}
       LOCATION_DEBUG)
 
@@ -148,6 +152,14 @@
   IMPORTED_LOCATION_RELEASE)
 if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
   get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+    IMPORTED_LOCATION_RELWITHDEBINFO)
+endif()
+if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
+  get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+    IMPORTED_LOCATION_MINSIZEREL)
+endif()
+if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
+  get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
     IMPORTED_LOCATION_DEBUG)
 endif()
 if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
diff --git a/cmake/protobuf-options.cmake b/cmake/protobuf-options.cmake
index 47fb158..93ec898 100644
--- a/cmake/protobuf-options.cmake
+++ b/cmake/protobuf-options.cmake
@@ -2,6 +2,6 @@
 option(protobuf_VERBOSE "Enable for verbose output" OFF)
 mark_as_advanced(protobuf_VERBOSE)
 
-# FindProtobuf module compatibel
-option(protobuf_MODULE_COMPATIBLE "CMake build-in FindProtobuf.cmake module compatible" OFF)
+# FindProtobuf module compatible
+option(protobuf_MODULE_COMPATIBLE "CMake built-in FindProtobuf.cmake module compatible" OFF)
 mark_as_advanced(protobuf_MODULE_COMPATIBLE)
diff --git a/cmake/protobuf.pc.cmake b/cmake/protobuf.pc.cmake
index d33e98c..f068e69 100644
--- a/cmake/protobuf.pc.cmake
+++ b/cmake/protobuf.pc.cmake
@@ -7,5 +7,5 @@
 Description: Google's Data Interchange Format
 Version: @protobuf_VERSION@
 Libs: -L${libdir} -lprotobuf @CMAKE_THREAD_LIBS_INIT@
-Cflags: -I${includedir} @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir}
 Conflicts: protobuf-lite
diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake
index f90e525..c86d662 100644
--- a/cmake/protoc.cmake
+++ b/cmake/protoc.cmake
@@ -2,7 +2,7 @@
   ${protobuf_source_dir}/src/google/protobuf/compiler/main.cc
 )
 
-if (MSVC)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
 set(protoc_rc_files
   ${CMAKE_CURRENT_BINARY_DIR}/version.rc
 )
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index c3ef730..4a54b70 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -33,7 +33,6 @@
   google/protobuf/unittest_import_lite.proto
   google/protobuf/unittest_import_public_lite.proto
   google/protobuf/unittest_lite.proto
-  google/protobuf/unittest_no_arena_lite.proto
 )
 
 set(tests_protos
@@ -56,8 +55,6 @@
   google/protobuf/unittest_lite_imports_nonlite.proto
   google/protobuf/unittest_mset.proto
   google/protobuf/unittest_mset_wire_format.proto
-  google/protobuf/unittest_no_arena.proto
-  google/protobuf/unittest_no_arena_import.proto
   google/protobuf/unittest_no_field_presence.proto
   google/protobuf/unittest_no_generic_services.proto
   google/protobuf/unittest_optimize_for.proto
@@ -90,8 +87,8 @@
   get_filename_component(basename ${filename} NAME_WE)
   add_custom_command(
     OUTPUT ${protobuf_source_dir}/src/${dirname}/${basename}.pb.cc
-    DEPENDS protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
-    COMMAND protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+    DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+    COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/${dirname}/${basename}.proto
         --proto_path=${protobuf_source_dir}/src
         --cpp_out=${protobuf_source_dir}/src
         --experimental_allow_proto3_optional
diff --git a/configure.ac b/configure.ac
index a86499a..a3309b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
 # In the SVN trunk, the version should always be the next anticipated release
 # version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
 # the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.11.4],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.17.3],[protobuf@googlegroups.com],[protobuf])
 
 AM_MAINTAINER_MODE([enable])
 
@@ -125,7 +125,7 @@
   [have_ld_version_script=yes; AC_MSG_RESULT(yes)],
   [have_ld_version_script=no; AC_MSG_RESULT(no)])
 LDFLAGS=$save_LDFLAGS
-AM_CONDITIONAL([HAVE_LD_VERSION_SCRIPT], [test "$have_ld_version_script" == "yes"])
+AM_CONDITIONAL([HAVE_LD_VERSION_SCRIPT], [test "$have_ld_version_script" = "yes"])
 
 # Checks for header files.
 AC_HEADER_STDC
@@ -223,6 +223,19 @@
 esac
 AM_CONDITIONAL([OBJC_CONFORMANCE_TEST], [test $OBJC_CONFORMANCE_TEST = 1])
 
+AC_MSG_CHECKING(whether -llog is needed)
+ANDROID_TEST=no
+case "$target_os" in
+  *android*)
+    ANDROID_TEST=yes
+    ;;
+esac
+AC_MSG_RESULT($ANDROID_TEST)
+if test "x$ANDROID_TEST" = xyes; then
+  LIBLOG_LIBS="-llog"
+fi
+AC_SUBST([LIBLOG_LIBS])
+
 # HACK:  Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS,
 #   since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock
 #   too.
diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java
index fa4dfb7..100bec4 100644
--- a/conformance/ConformanceJava.java
+++ b/conformance/ConformanceJava.java
@@ -54,7 +54,7 @@
     while (len > 0) {
       int read = System.in.read(buf, ofs, len);
       if (read == -1) {
-        return false;  // EOF
+        return false; // EOF
       }
       ofs += read;
       len -= read;
@@ -81,10 +81,10 @@
 
   private void writeLittleEndianIntToStdout(int val) throws Exception {
     byte[] buf = new byte[4];
-    buf[0] = (byte)val;
-    buf[1] = (byte)(val >> 8);
-    buf[2] = (byte)(val >> 16);
-    buf[3] = (byte)(val >> 24);
+    buf[0] = (byte) val;
+    buf[1] = (byte) (val >> 8);
+    buf[2] = (byte) (val >> 16);
+    buf[3] = (byte) (val >> 24);
     writeToStdout(buf);
   }
 
@@ -98,85 +98,71 @@
     INPUT_STREAM_DECODER;
   }
 
-  private static class BinaryDecoder <MessageType extends AbstractMessage> {
-    public MessageType decode (ByteString bytes, BinaryDecoderType type,
-        Parser <MessageType> parser, ExtensionRegistry extensions)
-      throws InvalidProtocolBufferException {
+  private static class BinaryDecoder<T extends AbstractMessage> {
+    public T decode(
+        ByteString bytes, BinaryDecoderType type, Parser<T> parser, ExtensionRegistry extensions)
+        throws InvalidProtocolBufferException {
       switch (type) {
         case BTYE_STRING_DECODER:
-          return parser.parseFrom(bytes, extensions);
         case BYTE_ARRAY_DECODER:
-          return parser.parseFrom(bytes.toByteArray(), extensions);
-        case ARRAY_BYTE_BUFFER_DECODER: {
-          ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
-          bytes.copyTo(buffer);
-          buffer.flip();
-          try {
+          return parser.parseFrom(bytes, extensions);
+        case ARRAY_BYTE_BUFFER_DECODER:
+          {
+            ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
+            bytes.copyTo(buffer);
+            buffer.flip();
             return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
-          } catch (InvalidProtocolBufferException e) {
-            throw e;
           }
-        }
-        case READONLY_ARRAY_BYTE_BUFFER_DECODER: {
-          try {
+        case READONLY_ARRAY_BYTE_BUFFER_DECODER:
+          {
             return parser.parseFrom(
                 CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
-          } catch (InvalidProtocolBufferException e) {
-            throw e;
           }
-        }
-        case DIRECT_BYTE_BUFFER_DECODER: {
-          ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
-          bytes.copyTo(buffer);
-          buffer.flip();
-          try {
+        case DIRECT_BYTE_BUFFER_DECODER:
+          {
+            ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+            bytes.copyTo(buffer);
+            buffer.flip();
             return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
-          } catch (InvalidProtocolBufferException e) {
-            throw e;
           }
-        }
-        case READONLY_DIRECT_BYTE_BUFFER_DECODER: {
-          ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
-          bytes.copyTo(buffer);
-          buffer.flip();
-          try {
+        case READONLY_DIRECT_BYTE_BUFFER_DECODER:
+          {
+            ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+            bytes.copyTo(buffer);
+            buffer.flip();
             return parser.parseFrom(
                 CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
-          } catch (InvalidProtocolBufferException e) {
-            throw e;
           }
-        }
-        case INPUT_STREAM_DECODER: {
-          try {
+        case INPUT_STREAM_DECODER:
+          {
             return parser.parseFrom(bytes.newInput(), extensions);
-          } catch (InvalidProtocolBufferException e) {
-            throw e;
           }
-        }
-        default :
-          return null;
       }
+      return null;
     }
   }
 
-  private <MessageType extends AbstractMessage> MessageType parseBinary(
-      ByteString bytes, Parser <MessageType> parser, ExtensionRegistry extensions)
+  private <T extends AbstractMessage> T parseBinary(
+      ByteString bytes, Parser<T> parser, ExtensionRegistry extensions)
       throws InvalidProtocolBufferException {
-    ArrayList <MessageType> messages = new ArrayList <MessageType> ();
-    ArrayList <InvalidProtocolBufferException> exceptions =
-        new ArrayList <InvalidProtocolBufferException>();
+    ArrayList<T> messages = new ArrayList<>();
+    ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>();
 
     for (int i = 0; i < BinaryDecoderType.values().length; i++) {
       messages.add(null);
       exceptions.add(null);
     }
-    BinaryDecoder <MessageType> decoder = new BinaryDecoder <MessageType> ();
+    if (messages.isEmpty()) {
+      throw new RuntimeException("binary decoder types missing");
+    }
+
+    BinaryDecoder<T> decoder = new BinaryDecoder<>();
 
     boolean hasMessage = false;
     boolean hasException = false;
     for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
       try {
-        //= BinaryDecoderType.values()[i].parseProto3(bytes);
+        // = BinaryDecoderType.values()[i].parseProto3(bytes);
         messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions));
         hasMessage = true;
       } catch (InvalidProtocolBufferException e) {
@@ -202,7 +188,15 @@
     if (hasException) {
       // We do not check if exceptions are equal. Different implementations may return different
       // exception messages. Throw an arbitrary one out instead.
-      throw exceptions.get(0);
+      InvalidProtocolBufferException exception = null;
+      for (InvalidProtocolBufferException e : exceptions) {
+        if (exception != null) {
+          exception.addSuppressed(e);
+        } else {
+          exception = e;
+        }
+      }
+      throw exception;
     }
 
     // Fast path comparing all the messages with the first message, assuming equality being
@@ -236,110 +230,144 @@
 
   private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
     com.google.protobuf.AbstractMessage testMessage;
-    boolean isProto3 = request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3");
-    boolean isProto2 = request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");
+    boolean isProto3 =
+        request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3");
+    boolean isProto2 =
+        request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");
 
     switch (request.getPayloadCase()) {
-      case PROTOBUF_PAYLOAD: {
-        if (isProto3) {
-          try {
-            ExtensionRegistry extensions = ExtensionRegistry.newInstance();
-            TestMessagesProto3.registerAllExtensions(extensions);
-            testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
-          } catch (InvalidProtocolBufferException e) {
-            return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
-          }
-        } else if (isProto2) {
-          try {
-            ExtensionRegistry extensions = ExtensionRegistry.newInstance();
-            TestMessagesProto2.registerAllExtensions(extensions);
-            testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
-          } catch (InvalidProtocolBufferException e) {
-            return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
-          }
-        } else {
-          throw new RuntimeException("Protobuf request doesn't have specific payload type.");
-        }
-        break;
-      }
-      case JSON_PAYLOAD: {
-        try {
-          TestMessagesProto3.TestAllTypesProto3.Builder builder =
-              TestMessagesProto3.TestAllTypesProto3.newBuilder();
-          JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry);
-          if (request.getTestCategory()
-              == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) {
-            parser = parser.ignoringUnknownFields();
-          }
-          parser.merge(request.getJsonPayload(), builder);
-          testMessage = builder.build();
-        } catch (InvalidProtocolBufferException e) {
-          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
-        }
-        break;
-      }
-      case TEXT_PAYLOAD: {
-        if (isProto3) {
-          try {
-            TestMessagesProto3.TestAllTypesProto3.Builder builder =
-                TestMessagesProto3.TestAllTypesProto3.newBuilder();
-            TextFormat.merge(request.getTextPayload(), builder);
-            testMessage = builder.build();
-          } catch (TextFormat.ParseException e) {
+      case PROTOBUF_PAYLOAD:
+        {
+          if (isProto3) {
+            try {
+              ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+              TestMessagesProto3.registerAllExtensions(extensions);
+              testMessage =
+                  parseBinary(
+                      request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
+            } catch (InvalidProtocolBufferException e) {
               return Conformance.ConformanceResponse.newBuilder()
                   .setParseError(e.getMessage())
                   .build();
-          }
-        } else if (isProto2) {
-          try {
-            TestMessagesProto2.TestAllTypesProto2.Builder builder =
-                TestMessagesProto2.TestAllTypesProto2.newBuilder();
-            TextFormat.merge(request.getTextPayload(), builder);
-            testMessage = builder.build();
-          } catch (TextFormat.ParseException e) {
+            }
+          } else if (isProto2) {
+            try {
+              ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+              TestMessagesProto2.registerAllExtensions(extensions);
+              testMessage =
+                  parseBinary(
+                      request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
+            } catch (InvalidProtocolBufferException e) {
               return Conformance.ConformanceResponse.newBuilder()
                   .setParseError(e.getMessage())
                   .build();
+            }
+          } else {
+            throw new RuntimeException("Protobuf request doesn't have specific payload type.");
           }
-        } else {
-          throw new RuntimeException("Protobuf request doesn't have specific payload type.");
+          break;
         }
-        break;
-      }
-      case PAYLOAD_NOT_SET: {
-        throw new RuntimeException("Request didn't have payload.");
-      }
+      case JSON_PAYLOAD:
+        {
+          try {
+            JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry);
+            if (request.getTestCategory()
+                == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) {
+              parser = parser.ignoringUnknownFields();
+            }
+            if (isProto3) {
+              TestMessagesProto3.TestAllTypesProto3.Builder builder =
+                  TestMessagesProto3.TestAllTypesProto3.newBuilder();
+              parser.merge(request.getJsonPayload(), builder);
+              testMessage = builder.build();
+            } else if (isProto2) {
+              TestMessagesProto2.TestAllTypesProto2.Builder builder =
+                  TestMessagesProto2.TestAllTypesProto2.newBuilder();
+              parser.merge(request.getJsonPayload(), builder);
+              testMessage = builder.build();
+            } else {
+              throw new RuntimeException("Protobuf request doesn't have specific payload type.");
+            }
+          } catch (InvalidProtocolBufferException e) {
+            return Conformance.ConformanceResponse.newBuilder()
+                .setParseError(e.getMessage())
+                .build();
+          }
+          break;
+        }
+      case TEXT_PAYLOAD:
+        {
+          if (isProto3) {
+            try {
+              TestMessagesProto3.TestAllTypesProto3.Builder builder =
+                  TestMessagesProto3.TestAllTypesProto3.newBuilder();
+              TextFormat.merge(request.getTextPayload(), builder);
+              testMessage = builder.build();
+            } catch (TextFormat.ParseException e) {
+              return Conformance.ConformanceResponse.newBuilder()
+                  .setParseError(e.getMessage())
+                  .build();
+            }
+          } else if (isProto2) {
+            try {
+              TestMessagesProto2.TestAllTypesProto2.Builder builder =
+                  TestMessagesProto2.TestAllTypesProto2.newBuilder();
+              TextFormat.merge(request.getTextPayload(), builder);
+              testMessage = builder.build();
+            } catch (TextFormat.ParseException e) {
+              return Conformance.ConformanceResponse.newBuilder()
+                  .setParseError(e.getMessage())
+                  .build();
+            }
+          } else {
+            throw new RuntimeException("Protobuf request doesn't have specific payload type.");
+          }
+          break;
+        }
+      case PAYLOAD_NOT_SET:
+        {
+          throw new RuntimeException("Request didn't have payload.");
+        }
 
-      default: {
-        throw new RuntimeException("Unexpected payload case.");
-      }
+      default:
+        {
+          throw new RuntimeException("Unexpected payload case.");
+        }
     }
 
     switch (request.getRequestedOutputFormat()) {
       case UNSPECIFIED:
         throw new RuntimeException("Unspecified output format.");
 
-      case PROTOBUF: {
-        ByteString MessageString = testMessage.toByteString();
-        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(MessageString).build();
-      }
+      case PROTOBUF:
+        {
+          ByteString messageString = testMessage.toByteString();
+          return Conformance.ConformanceResponse.newBuilder()
+              .setProtobufPayload(messageString)
+              .build();
+        }
 
       case JSON:
         try {
-          return Conformance.ConformanceResponse.newBuilder().setJsonPayload(
-              JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)).build();
+          return Conformance.ConformanceResponse.newBuilder()
+              .setJsonPayload(
+                  JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage))
+              .build();
         } catch (InvalidProtocolBufferException | IllegalArgumentException e) {
-          return Conformance.ConformanceResponse.newBuilder().setSerializeError(
-              e.getMessage()).build();
+          return Conformance.ConformanceResponse.newBuilder()
+              .setSerializeError(e.getMessage())
+              .build();
         }
 
       case TEXT_FORMAT:
-        return Conformance.ConformanceResponse.newBuilder().setTextPayload(
-            TextFormat.printToString(testMessage)).build();
+        return Conformance.ConformanceResponse.newBuilder()
+            .setTextPayload(TextFormat.printToString(testMessage))
+            .build();
 
-      default: {
-        throw new RuntimeException("Unexpected request output.");
-      }
+      default:
+        {
+          throw new RuntimeException("Unexpected request output.");
+        }
     }
   }
 
@@ -347,7 +375,7 @@
     int bytes = readLittleEndianIntFromStdin();
 
     if (bytes == -1) {
-      return false;  // EOF
+      return false; // EOF
     }
 
     byte[] serializedInput = new byte[bytes];
@@ -368,14 +396,16 @@
   }
 
   public void run() throws Exception {
-    typeRegistry = TypeRegistry.newBuilder().add(
-        TestMessagesProto3.TestAllTypesProto3.getDescriptor()).build();
+    typeRegistry =
+        TypeRegistry.newBuilder()
+            .add(TestMessagesProto3.TestAllTypesProto3.getDescriptor())
+            .build();
     while (doTestIo()) {
       this.testCount++;
     }
 
-    System.err.println("ConformanceJava: received EOF from test runner after " +
-        this.testCount + " tests");
+    System.err.println(
+        "ConformanceJava: received EOF from test runner after " + this.testCount + " tests");
   }
 
   public static void main(String[] args) throws Exception {
diff --git a/conformance/ConformanceJavaLite.java b/conformance/ConformanceJavaLite.java
index 147738d..eb3d06a 100644
--- a/conformance/ConformanceJavaLite.java
+++ b/conformance/ConformanceJavaLite.java
@@ -28,8 +28,19 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.ExtensionRegistryLite;
 import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.MessageLite;
+import com.google.protobuf.Parser;
+import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
 
 class ConformanceJavaLite {
   private int testCount = 0;
@@ -39,7 +50,7 @@
     while (len > 0) {
       int read = System.in.read(buf, ofs, len);
       if (read == -1) {
-        return false;  // EOF
+        return false; // EOF
       }
       ofs += read;
       len -= read;
@@ -66,36 +77,214 @@
 
   private void writeLittleEndianIntToStdout(int val) throws Exception {
     byte[] buf = new byte[4];
-    buf[0] = (byte)val;
-    buf[1] = (byte)(val >> 8);
-    buf[2] = (byte)(val >> 16);
-    buf[3] = (byte)(val >> 24);
+    buf[0] = (byte) val;
+    buf[1] = (byte) (val >> 8);
+    buf[2] = (byte) (val >> 16);
+    buf[3] = (byte) (val >> 24);
     writeToStdout(buf);
   }
 
-  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
-    Conformance.TestAllTypes testMessage;
+  private enum BinaryDecoderType {
+    BTYE_STRING_DECODER,
+    BYTE_ARRAY_DECODER,
+    ARRAY_BYTE_BUFFER_DECODER,
+    READONLY_ARRAY_BYTE_BUFFER_DECODER,
+    DIRECT_BYTE_BUFFER_DECODER,
+    READONLY_DIRECT_BYTE_BUFFER_DECODER,
+    INPUT_STREAM_DECODER;
+  }
 
-    switch (request.getPayloadCase()) {
-      case PROTOBUF_PAYLOAD: {
-        try {
-          testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
-        } catch (InvalidProtocolBufferException e) {
-          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+  private static class BinaryDecoder<T extends MessageLite> {
+    public T decode(
+        ByteString bytes,
+        BinaryDecoderType type,
+        Parser<T> parser,
+        ExtensionRegistryLite extensions)
+        throws InvalidProtocolBufferException {
+      switch (type) {
+        case BTYE_STRING_DECODER:
+        case BYTE_ARRAY_DECODER:
+          return parser.parseFrom(bytes, extensions);
+        case ARRAY_BYTE_BUFFER_DECODER:
+          {
+            ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
+            bytes.copyTo(buffer);
+            buffer.flip();
+            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+          }
+        case READONLY_ARRAY_BYTE_BUFFER_DECODER:
+          {
+            return parser.parseFrom(
+                CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
+          }
+        case DIRECT_BYTE_BUFFER_DECODER:
+          {
+            ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+            bytes.copyTo(buffer);
+            buffer.flip();
+            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+          }
+        case READONLY_DIRECT_BYTE_BUFFER_DECODER:
+          {
+            ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+            bytes.copyTo(buffer);
+            buffer.flip();
+            return parser.parseFrom(
+                CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
+          }
+        case INPUT_STREAM_DECODER:
+          {
+            return parser.parseFrom(bytes.newInput(), extensions);
+          }
+      }
+      return null;
+    }
+  }
+
+  private <T extends MessageLite> T parseBinary(
+      ByteString bytes, Parser<T> parser, ExtensionRegistryLite extensions)
+      throws InvalidProtocolBufferException {
+    ArrayList<T> messages = new ArrayList<>();
+    ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>();
+
+    for (int i = 0; i < BinaryDecoderType.values().length; i++) {
+      messages.add(null);
+      exceptions.add(null);
+    }
+    if (messages.isEmpty()) {
+      throw new RuntimeException("binary decoder types missing");
+    }
+
+    BinaryDecoder<T> decoder = new BinaryDecoder<>();
+
+    boolean hasMessage = false;
+    boolean hasException = false;
+    for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
+      try {
+        messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions));
+        hasMessage = true;
+      } catch (InvalidProtocolBufferException e) {
+        exceptions.set(i, e);
+        hasException = true;
+      }
+    }
+
+    if (hasMessage && hasException) {
+      StringBuilder sb =
+          new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n");
+      for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
+        sb.append(BinaryDecoderType.values()[i].name());
+        if (messages.get(i) != null) {
+          sb.append(" accepted the payload.\n");
+        } else {
+          sb.append(" rejected the payload.\n");
         }
+      }
+      throw new RuntimeException(sb.toString());
+    }
+
+    if (hasException) {
+      // We do not check if exceptions are equal. Different implementations may return different
+      // exception messages. Throw an arbitrary one out instead.
+      InvalidProtocolBufferException exception = null;
+      for (InvalidProtocolBufferException e : exceptions) {
+        if (exception != null) {
+          exception.addSuppressed(e);
+        } else {
+          exception = e;
+        }
+      }
+      throw exception;
+    }
+
+    // Fast path comparing all the messages with the first message, assuming equality being
+    // symmetric and transitive.
+    boolean allEqual = true;
+    for (int i = 1; i < messages.size(); ++i) {
+      if (!messages.get(0).equals(messages.get(i))) {
+        allEqual = false;
         break;
       }
-      case JSON_PAYLOAD: {
-        return Conformance.ConformanceResponse.newBuilder().setSkipped(
-            "Lite runtime does not support JSON format.").build();
-      }
-      case PAYLOAD_NOT_SET: {
-        throw new RuntimeException("Request didn't have payload.");
-      }
+    }
 
-      default: {
-        throw new RuntimeException("Unexpected payload case.");
+    // Slow path: compare and find out all unequal pairs.
+    if (!allEqual) {
+      StringBuilder sb = new StringBuilder();
+      for (int i = 0; i < messages.size() - 1; ++i) {
+        for (int j = i + 1; j < messages.size(); ++j) {
+          if (!messages.get(i).equals(messages.get(j))) {
+            sb.append(BinaryDecoderType.values()[i].name())
+                .append(" and ")
+                .append(BinaryDecoderType.values()[j].name())
+                .append(" parsed the payload differently.\n");
+          }
+        }
       }
+      throw new RuntimeException(sb.toString());
+    }
+
+    return messages.get(0);
+  }
+
+  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
+    com.google.protobuf.MessageLite testMessage;
+    boolean isProto3 =
+        request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3");
+    boolean isProto2 =
+        request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");
+
+    switch (request.getPayloadCase()) {
+      case PROTOBUF_PAYLOAD:
+        {
+          if (isProto3) {
+            try {
+              ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance();
+              TestMessagesProto3.registerAllExtensions(extensions);
+              testMessage =
+                  parseBinary(
+                      request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
+            } catch (InvalidProtocolBufferException e) {
+              return Conformance.ConformanceResponse.newBuilder()
+                  .setParseError(e.getMessage())
+                  .build();
+            }
+          } else if (isProto2) {
+            try {
+              ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance();
+              TestMessagesProto2.registerAllExtensions(extensions);
+              testMessage =
+                  parseBinary(
+                      request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
+            } catch (InvalidProtocolBufferException e) {
+              return Conformance.ConformanceResponse.newBuilder()
+                  .setParseError(e.getMessage())
+                  .build();
+            }
+          } else {
+            throw new RuntimeException("Protobuf request doesn't have specific payload type.");
+          }
+          break;
+        }
+      case JSON_PAYLOAD:
+        {
+          return Conformance.ConformanceResponse.newBuilder()
+              .setSkipped("Lite runtime does not support JSON format.")
+              .build();
+        }
+      case TEXT_PAYLOAD:
+        {
+          return Conformance.ConformanceResponse.newBuilder()
+              .setSkipped("Lite runtime does not support Text format.")
+              .build();
+        }
+      case PAYLOAD_NOT_SET:
+        {
+          throw new RuntimeException("Request didn't have payload.");
+        }
+      default:
+        {
+          throw new RuntimeException("Unexpected payload case.");
+        }
     }
 
     switch (request.getRequestedOutputFormat()) {
@@ -103,15 +292,23 @@
         throw new RuntimeException("Unspecified output format.");
 
       case PROTOBUF:
-        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+        return Conformance.ConformanceResponse.newBuilder()
+            .setProtobufPayload(testMessage.toByteString())
+            .build();
 
       case JSON:
-        return Conformance.ConformanceResponse.newBuilder().setSkipped(
-            "Lite runtime does not support JSON format.").build();
+        return Conformance.ConformanceResponse.newBuilder()
+            .setSkipped("Lite runtime does not support JSON format.")
+            .build();
 
-      default: {
-        throw new RuntimeException("Unexpected request output.");
-      }
+      case TEXT_FORMAT:
+        return Conformance.ConformanceResponse.newBuilder()
+            .setSkipped("Lite runtime does not support Text format.")
+            .build();
+      default:
+        {
+          throw new RuntimeException("Unexpected request output.");
+        }
     }
   }
 
@@ -119,7 +316,7 @@
     int bytes = readLittleEndianIntFromStdin();
 
     if (bytes == -1) {
-      return false;  // EOF
+      return false; // EOF
     }
 
     byte[] serializedInput = new byte[bytes];
@@ -144,8 +341,8 @@
       this.testCount++;
     }
 
-    System.err.println("ConformanceJavaLite: received EOF from test runner after " +
-        this.testCount + " tests");
+    System.err.println(
+        "ConformanceJavaLite: received EOF from test runner after " + this.testCount + " tests");
   }
 
   public static void main(String[] args) throws Exception {
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
index 6815c73..b281f9c 100644
--- a/conformance/Makefile.am
+++ b/conformance/Makefile.am
@@ -5,7 +5,7 @@
   $(top_srcdir)/src/google/protobuf/test_messages_proto3.proto
 
 # proto2 input files, should be separated with proto3, as we
-# can't generate proto2 files for ruby, php and objc
+# can't generate proto2 files for php.
 conformance_proto2_protoc_inputs =                             \
   $(top_srcdir)/src/google/protobuf/test_messages_proto2.proto
 
@@ -261,7 +261,7 @@
 # Some implementations include pre-generated versions of well-known types.
 protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
 	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs)
-	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs)
+	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs)
 	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs)
 	## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
 	touch protoc_middleman
@@ -273,7 +273,7 @@
 # building out-of-tree.
 protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
 	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) )
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --objc_out=. --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) )
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) )
 	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) )
 	## @mkdir -p lite
 	## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )
@@ -333,7 +333,7 @@
 
 # Targets for actually running tests.
 test_cpp: protoc_middleman conformance-test-runner conformance-cpp
-	./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt ./conformance-cpp
+	./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt --text_format_failure_list text_format_failure_list_cpp.txt ./conformance-cpp
 
 test_java: protoc_middleman conformance-test-runner conformance-java
 	./conformance-test-runner --enforce_recommended --failure_list failure_list_java.txt --text_format_failure_list text_format_failure_list_java.txt ./conformance-java
@@ -347,22 +347,36 @@
 test_ruby: protoc_middleman conformance-test-runner $(other_language_protoc_outputs)
 	RUBYLIB=../ruby/lib:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_ruby.txt --text_format_failure_list text_format_failure_list_ruby.txt ./conformance_ruby.rb
 
+test_jruby: protoc_middleman conformance-test-runner $(other_language_protoc_outputs)
+	RUBYLIB=../ruby/lib:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_jruby.txt --text_format_failure_list text_format_failure_list_jruby.txt ./conformance_ruby.rb
+
 test_php: protoc_middleman conformance-test-runner conformance-php $(other_language_protoc_outputs)
 	./conformance-test-runner --enforce_recommended --failure_list failure_list_php.txt --text_format_failure_list text_format_failure_list_php.txt ./conformance-php
 
 test_php_c: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs)
 	./conformance-test-runner --enforce_recommended --failure_list failure_list_php_c.txt --text_format_failure_list text_format_failure_list_php.txt ./conformance-php-c
 
-test_php_c_32: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs)
-	./conformance-test-runner --enforce_recommended --failure_list failure_list_php_c_32.txt --text_format_failure_list text_format_failure_list_php.txt ./conformance-php-c
-
 # These depend on library paths being properly set up.  The easiest way to
 # run them is to just use "tox" from the python dir.
 test_python: protoc_middleman conformance-test-runner
-	./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python.txt ./conformance_python.py
+	VERSION="$(shell python --version 2>&1)"; \
+	if [[ "$$VERSION"  == "Python 2.7"* ]]; then \
+	  echo "Using Python 2.7 failure list."; \
+	  ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python_2.7.txt ./conformance_python.py; \
+	else \
+	  echo "Using Python >2.7 failure list."; \
+	  ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python.txt ./conformance_python.py; \
+	fi
 
 test_python_cpp: protoc_middleman conformance-test-runner
-	./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt ./conformance_python.py
+	VERSION="$(shell python --version 2>&1)"; \
+	if [[ "$$VERSION"  == "Python 2.7"* ]]; then \
+	  echo "Using Python 2.7 failure list."; \
+	  ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp_2.7.txt ./conformance_python.py; \
+	else \
+	  echo "Using Python >2.7 failure list."; \
+	  ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp.txt ./conformance_python.py; \
+	fi
 
 test_nodejs: protoc_middleman conformance-test-runner $(other_language_protoc_outputs)
 	NODE_PATH=../js:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_js.txt ./conformance_nodejs.js
diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc
index 93f43dc..0275e2e 100644
--- a/conformance/binary_json_conformance_suite.cc
+++ b/conformance/binary_json_conformance_suite.cc
@@ -300,7 +300,7 @@
 }
 
 string UpperCase(string str) {
-  for (int i = 0; i < str.size(); i++) {
+  for (size_t i = 0; i < str.size(); i++) {
     str[i] = toupper(str[i]);
   }
   return str;
@@ -556,24 +556,24 @@
                        equivalent_text_format, is_proto3);
 }
 
-// According to proto3 JSON specification, JSON serializers follow more strict
+// According to proto JSON specification, JSON serializers follow more strict
 // rules than parsers (e.g., a serializer must serialize int32 values as JSON
 // numbers while the parser is allowed to accept them as JSON strings). This
-// method allows strict checking on a proto3 JSON serializer by inspecting
+// method allows strict checking on a proto JSON serializer by inspecting
 // the JSON output directly.
 void BinaryAndJsonConformanceSuite::RunValidJsonTestWithValidator(
     const string& test_name, ConformanceLevel level, const string& input_json,
-    const Validator& validator) {
-  TestAllTypesProto3 prototype;
-  ConformanceRequestSetting setting(
-      level, conformance::JSON, conformance::JSON,
-      conformance::JSON_TEST,
-      prototype, test_name, input_json);
+    const Validator& validator, bool is_proto3) {
+  std::unique_ptr<Message> prototype = NewTestMessage(is_proto3);
+  ConformanceRequestSetting setting(level, conformance::JSON, conformance::JSON,
+                                    conformance::JSON_TEST, *prototype,
+                                    test_name, input_json);
   const ConformanceRequest& request = setting.GetRequest();
   ConformanceResponse response;
   string effective_test_name =
       StrCat(setting.ConformanceLevelToString(level),
-                   ".Proto3.JsonInput.", test_name, ".Validator");
+                   is_proto3 ? ".Proto3.JsonInput." : ".Proto2.JsonInput.",
+                   test_name, ".Validator");
 
   RunTest(effective_test_name, request, &response);
 
@@ -1800,7 +1800,8 @@
             value.isMember("fieldName2") &&
             value.isMember("FieldName3") &&
             value.isMember("fieldName4");
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "FieldNameWithNumbers", REQUIRED,
       R"({
@@ -1810,7 +1811,8 @@
       [](const Json::Value& value) {
         return value.isMember("field0name5") &&
             value.isMember("field0Name6");
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "FieldNameWithMixedCases", REQUIRED,
       R"({
@@ -1828,7 +1830,8 @@
             value.isMember("FieldName10") &&
             value.isMember("FIELDNAME11") &&
             value.isMember("FIELDName12");
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "FieldNameWithDoubleUnderscores", RECOMMENDED,
       R"({
@@ -1846,7 +1849,32 @@
             value.isMember("fieldName16") &&
             value.isMember("fieldName17") &&
             value.isMember("FieldName18");
-      });
+      },
+      true);
+  RunValidJsonTestWithValidator(
+      "StoresDefaultPrimitive", REQUIRED,
+      R"({
+        "FieldName13": 0
+      })",
+      [](const Json::Value& value) { return value.isMember("FieldName13"); },
+      false);
+  RunValidJsonTestWithValidator(
+      "SkipsDefaultPrimitive", REQUIRED,
+      R"({
+        "FieldName13": 0
+      })",
+      [](const Json::Value& value) { return !value.isMember("FieldName13"); },
+      true);
+  RunValidJsonTestWithValidator(
+      "FieldNameExtension", RECOMMENDED,
+      R"({
+        "[protobuf_test_messages.proto2.extension_int32]": 1
+      })",
+      [](const Json::Value& value) {
+        return value.isMember(
+            "[protobuf_test_messages.proto2.extension_int32]");
+      },
+      false);
 }
 
 void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() {
@@ -1995,19 +2023,19 @@
 
   // 64-bit values are serialized as strings.
   RunValidJsonTestWithValidator(
-      "Int64FieldBeString", RECOMMENDED,
-      R"({"optionalInt64": 1})",
+      "Int64FieldBeString", RECOMMENDED, R"({"optionalInt64": 1})",
       [](const Json::Value& value) {
         return value["optionalInt64"].type() == Json::stringValue &&
             value["optionalInt64"].asString() == "1";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
-      "Uint64FieldBeString", RECOMMENDED,
-      R"({"optionalUint64": 1})",
+      "Uint64FieldBeString", RECOMMENDED, R"({"optionalUint64": 1})",
       [](const Json::Value& value) {
         return value["optionalUint64"].type() == Json::stringValue &&
             value["optionalUint64"].asString() == "1";
-      });
+      },
+      true);
 
   // Bool fields.
   RunValidJsonTest(
@@ -2223,12 +2251,12 @@
       "optional_nested_enum: BAR");
   // Unknown enum values are represented as numeric values.
   RunValidJsonTestWithValidator(
-      "EnumFieldUnknownValue", REQUIRED,
-      R"({"optionalNestedEnum": 123})",
+      "EnumFieldUnknownValue", REQUIRED, R"({"optionalNestedEnum": 123})",
       [](const Json::Value& value) {
         return value["optionalNestedEnum"].type() == Json::intValue &&
             value["optionalNestedEnum"].asInt() == 123;
-      });
+      },
+      true);
 
   // String fields.
   RunValidJsonTest(
@@ -2301,6 +2329,12 @@
   ExpectParseFailureForJson(
       "OneofFieldDuplicate", REQUIRED,
       R"({"oneofUint32": 1, "oneofString": "test"})");
+  RunValidJsonTest("OneofFieldNullFirst", REQUIRED,
+                   R"({"oneofUint32": null, "oneofString": "test"})",
+                   "oneof_string: \"test\"");
+  RunValidJsonTest("OneofFieldNullSecond", REQUIRED,
+                   R"({"oneofString": "test", "oneofUint32": null})",
+                   "oneof_string: \"test\"");
   // Ensure zero values for oneof make it out/backs.
   TestAllTypesProto3 messageProto3;
   TestAllTypesProto2 messageProto2;
@@ -2712,25 +2746,29 @@
       R"({"optionalDuration": "1.000000000s"})",
       [](const Json::Value& value) {
         return value["optionalDuration"].asString() == "1s";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "DurationHas3FractionalDigits", RECOMMENDED,
       R"({"optionalDuration": "1.010000000s"})",
       [](const Json::Value& value) {
         return value["optionalDuration"].asString() == "1.010s";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "DurationHas6FractionalDigits", RECOMMENDED,
       R"({"optionalDuration": "1.000010000s"})",
       [](const Json::Value& value) {
         return value["optionalDuration"].asString() == "1.000010s";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "DurationHas9FractionalDigits", RECOMMENDED,
       R"({"optionalDuration": "1.000000010s"})",
       [](const Json::Value& value) {
         return value["optionalDuration"].asString() == "1.000000010s";
-      });
+      },
+      true);
 
   // Timestamp
   RunValidJsonTest(
@@ -2794,34 +2832,39 @@
       R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
       [](const Json::Value& value) {
         return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "TimestampHasZeroFractionalDigit", RECOMMENDED,
       R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})",
       [](const Json::Value& value) {
         return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "TimestampHas3FractionalDigits", RECOMMENDED,
       R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})",
       [](const Json::Value& value) {
         return value["optionalTimestamp"].asString() ==
                "1970-01-01T00:00:00.010Z";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "TimestampHas6FractionalDigits", RECOMMENDED,
       R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})",
       [](const Json::Value& value) {
         return value["optionalTimestamp"].asString() ==
                "1970-01-01T00:00:00.000010Z";
-      });
+      },
+      true);
   RunValidJsonTestWithValidator(
       "TimestampHas9FractionalDigits", RECOMMENDED,
       R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})",
       [](const Json::Value& value) {
         return value["optionalTimestamp"].asString() ==
                "1970-01-01T00:00:00.000000010Z";
-      });
+      },
+      true);
 }
 
 void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldMask() {
@@ -3014,6 +3057,29 @@
           }
         ]
       )");
+  RunValidJsonTestWithValidator(
+      "NullValueInOtherOneofOldFormat", RECOMMENDED,
+      R"({"oneofNullValue": "NULL_VALUE"})",
+      [](const Json::Value& value) {
+        return (value.isMember("oneofNullValue") &&
+                value["oneofNullValue"].isNull());
+      },
+      true);
+  RunValidJsonTestWithValidator(
+      "NullValueInOtherOneofNewFormat", RECOMMENDED,
+      R"({"oneofNullValue": null})",
+      [](const Json::Value& value) {
+        return (value.isMember("oneofNullValue") &&
+                value["oneofNullValue"].isNull());
+      },
+      true);
+  RunValidJsonTestWithValidator(
+      "NullValueInNormalMessage", RECOMMENDED,
+      R"({"optionalNullValue": null})",
+      [](const Json::Value& value) {
+        return value.empty();
+      },
+      true);
 }
 
 void BinaryAndJsonConformanceSuite::RunJsonTestsForAny() {
diff --git a/conformance/binary_json_conformance_suite.h b/conformance/binary_json_conformance_suite.h
index aaf8bb4..280ff95 100644
--- a/conformance/binary_json_conformance_suite.h
+++ b/conformance/binary_json_conformance_suite.h
@@ -42,7 +42,7 @@
   BinaryAndJsonConformanceSuite() {}
 
  private:
-  void RunSuiteImpl();
+  void RunSuiteImpl() override;
   void RunJsonTests();
   void RunJsonTestsForFieldNameConvention();
   void RunJsonTestsForNonRepeatedTypes();
@@ -53,35 +53,34 @@
   void RunJsonTestsForStruct();
   void RunJsonTestsForValue();
   void RunJsonTestsForAny();
-  void RunValidJsonTest(const string& test_name,
-                        ConformanceLevel level,
-                        const string& input_json,
-                        const string& equivalent_text_format);
+  void RunValidJsonTest(const std::string& test_name, ConformanceLevel level,
+                        const std::string& input_json,
+                        const std::string& equivalent_text_format);
   void RunValidJsonTestWithProtobufInput(
-      const string& test_name,
-      ConformanceLevel level,
+      const std::string& test_name, ConformanceLevel level,
       const protobuf_test_messages::proto3::TestAllTypesProto3& input,
-      const string& equivalent_text_format);
-  void RunValidJsonIgnoreUnknownTest(
-      const string& test_name, ConformanceLevel level, const string& input_json,
-      const string& equivalent_text_format);
-  void RunValidProtobufTest(const string& test_name, ConformanceLevel level,
-                            const string& input_protobuf,
-                            const string& equivalent_text_format,
+      const std::string& equivalent_text_format);
+  void RunValidJsonIgnoreUnknownTest(const std::string& test_name,
+                                     ConformanceLevel level,
+                                     const std::string& input_json,
+                                     const std::string& equivalent_text_format);
+  void RunValidProtobufTest(const std::string& test_name,
+                            ConformanceLevel level,
+                            const std::string& input_protobuf,
+                            const std::string& equivalent_text_format,
                             bool is_proto3);
-  void RunValidBinaryProtobufTest(const string& test_name,
+  void RunValidBinaryProtobufTest(const std::string& test_name,
                                   ConformanceLevel level,
-                                  const string& input_protobuf,
+                                  const std::string& input_protobuf,
                                   bool is_proto3);
-  void RunValidBinaryProtobufTest(const string& test_name,
+  void RunValidBinaryProtobufTest(const std::string& test_name,
                                   ConformanceLevel level,
-                                  const string& input_protobuf,
-                                  const string& expected_protobuf,
+                                  const std::string& input_protobuf,
+                                  const std::string& expected_protobuf,
                                   bool is_proto3);
   void RunValidProtobufTestWithMessage(
-      const string& test_name, ConformanceLevel level,
-      const Message *input,
-      const string& equivalent_text_format,
+      const std::string& test_name, ConformanceLevel level,
+      const Message* input, const std::string& equivalent_text_format,
       bool is_proto3);
 
   bool ParseJsonResponse(
@@ -93,20 +92,21 @@
       Message* test_message) override;
 
   typedef std::function<bool(const Json::Value&)> Validator;
-  void RunValidJsonTestWithValidator(const string& test_name,
+  void RunValidJsonTestWithValidator(const std::string& test_name,
                                      ConformanceLevel level,
-                                     const string& input_json,
-                                     const Validator& validator);
-  void ExpectParseFailureForJson(const string& test_name,
+                                     const std::string& input_json,
+                                     const Validator& validator,
+                                     bool is_proto3);
+  void ExpectParseFailureForJson(const std::string& test_name,
                                  ConformanceLevel level,
-                                 const string& input_json);
-  void ExpectSerializeFailureForJson(const string& test_name,
+                                 const std::string& input_json);
+  void ExpectSerializeFailureForJson(const std::string& test_name,
                                      ConformanceLevel level,
-                                     const string& text_format);
-  void ExpectParseFailureForProtoWithProtoVersion (const string& proto,
-                                                   const string& test_name,
-                                                   ConformanceLevel level,
-                                                   bool is_proto3);
+                                     const std::string& text_format);
+  void ExpectParseFailureForProtoWithProtoVersion(const std::string& proto,
+                                                  const std::string& test_name,
+                                                  ConformanceLevel level,
+                                                  bool is_proto3);
   void ExpectParseFailureForProto(const std::string& proto,
                                   const std::string& test_name,
                                   ConformanceLevel level);
diff --git a/conformance/conformance.proto b/conformance/conformance.proto
index 26c0bd2..49608b3 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -64,7 +64,7 @@
   BINARY_TEST = 1;  // Test binary wire format.
   JSON_TEST = 2;    // Test json wire format.
   // Similar to JSON_TEST. However, during parsing json, testee should ignore
-  // unknown fields. This feature is optional. Each implementation can descide
+  // unknown fields. This feature is optional. Each implementation can decide
   // whether to support it.  See
   // https://developers.google.com/protocol-buffers/docs/proto3#json_options
   // for more detail.
@@ -113,7 +113,7 @@
   string message_type = 4;
 
   // Each test is given a specific test category. Some category may need
-  // spedific support in testee programs. Refer to the definition of TestCategory
+  // specific support in testee programs. Refer to the definition of TestCategory
   // for more information.
   TestCategory test_category = 5;
 
diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc
index 1cdfdae..5782789 100644
--- a/conformance/conformance_cpp.cc
+++ b/conformance/conformance_cpp.cc
@@ -36,6 +36,7 @@
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/util/json_util.h>
 #include <google/protobuf/util/type_resolver_util.h>
+#include <google/protobuf/stubs/status.h>
 #include "conformance.pb.h"
 #include <google/protobuf/test_messages_proto2.pb.h>
 #include <google/protobuf/test_messages_proto3.pb.h>
@@ -54,6 +55,7 @@
 using google::protobuf::util::NewTypeResolverForDescriptorPool;
 using google::protobuf::util::TypeResolver;
 using protobuf_test_messages::proto3::TestAllTypesProto3;
+using protobuf_test_messages::proto2::TestAllTypesProto2;
 using std::string;
 
 static const char kTypeUrlPrefix[] = "type.googleapis.com";
@@ -101,6 +103,8 @@
 
 void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
   Message *test_message;
+  google::protobuf::LinkMessageReflection<TestAllTypesProto2>();
+  google::protobuf::LinkMessageReflection<TestAllTypesProto3>();
   const Descriptor *descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(
       request.message_type());
   if (!descriptor) {
@@ -125,12 +129,12 @@
       options.ignore_unknown_fields =
           (request.test_category() ==
               conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST);
-      Status status = JsonToBinaryString(type_resolver, *type_url,
-                                         request.json_payload(), &proto_binary,
-                                         options);
+      util::Status status =
+          JsonToBinaryString(type_resolver, *type_url, request.json_payload(),
+                             &proto_binary, options);
       if (!status.ok()) {
         response->set_parse_error(string("Parse error: ") +
-                                  std::string(status.error_message()));
+                                  std::string(status.message()));
         return;
       }
 
@@ -179,12 +183,13 @@
     case conformance::JSON: {
       string proto_binary;
       GOOGLE_CHECK(test_message->SerializeToString(&proto_binary));
-      Status status = BinaryToJsonString(type_resolver, *type_url, proto_binary,
-                                         response->mutable_json_payload());
+      util::Status status =
+          BinaryToJsonString(type_resolver, *type_url, proto_binary,
+                             response->mutable_json_payload());
       if (!status.ok()) {
         response->set_serialize_error(
             string("Failed to serialize JSON output: ") +
-            std::string(status.error_message()));
+            std::string(status.message()));
         return;
       }
       break;
diff --git a/conformance/conformance_ruby.rb b/conformance/conformance_ruby.rb
index 79d8d3d..4af7659 100755
--- a/conformance/conformance_ruby.rb
+++ b/conformance/conformance_ruby.rb
@@ -32,6 +32,7 @@
 
 require 'conformance_pb'
 require 'google/protobuf/test_messages_proto3_pb'
+require 'google/protobuf/test_messages_proto2_pb'
 
 $test_count = 0
 $verbose = false
@@ -39,39 +40,39 @@
 def do_test(request)
   test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.new
   response = Conformance::ConformanceResponse.new
+  descriptor = Google::Protobuf::DescriptorPool.generated_pool.lookup(request.message_type)
+
+  unless descriptor
+    response.skipped = "Unknown message type: " + request.message_type
+  end
 
   begin
     case request.payload
     when :protobuf_payload
-      if request.message_type.eql?('protobuf_test_messages.proto3.TestAllTypesProto3')
-        begin
-          test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode(
-              request.protobuf_payload)
-        rescue Google::Protobuf::ParseError => err
-          response.parse_error = err.message.encode('utf-8')
-          return response
-        end
-      elsif request.message_type.eql?('protobuf_test_messages.proto2.TestAllTypesProto2')
-        response.skipped = "Ruby doesn't support proto2"
-        return response
-      else
-        fail "Protobuf request doesn't have specific payload type"
-      end
-
-    when :json_payload
       begin
-        test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode_json(
-            request.json_payload)
+        test_message = descriptor.msgclass.decode(request.protobuf_payload)
       rescue Google::Protobuf::ParseError => err
         response.parse_error = err.message.encode('utf-8')
         return response
       end
-	
-	when :text_payload
-	  begin
-		response.skipped = "Ruby doesn't support proto2"
-        return response   
-	  end
+
+    when :json_payload
+      begin
+        options = {}
+        if request.test_category == :JSON_IGNORE_UNKNOWN_PARSING_TEST
+          options[:ignore_unknown_fields] = true
+        end
+        test_message = descriptor.msgclass.decode_json(request.json_payload, options)
+      rescue Google::Protobuf::ParseError => err
+        response.parse_error = err.message.encode('utf-8')
+        return response
+      end
+
+    when :text_payload
+      begin
+        response.skipped = "Ruby doesn't support text format"
+        return response
+      end
 
     when nil
       fail "Request didn't have payload"
@@ -82,10 +83,18 @@
       fail 'Unspecified output format'
 
     when :PROTOBUF
-      response.protobuf_payload = test_message.to_proto
+      begin
+        response.protobuf_payload = test_message.to_proto
+      rescue Google::Protobuf::ParseError => err
+        response.serialize_error = err.message.encode('utf-8')
+      end
 
     when :JSON
-      response.json_payload = test_message.to_json
+      begin
+        response.json_payload = test_message.to_json
+      rescue Google::Protobuf::ParseError => err
+        response.serialize_error = err.message.encode('utf-8')
+      end
 
     when nil
       fail "Request didn't have requested output format"
diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h
index 417ec4e..76bd1bc 100644
--- a/conformance/conformance_test.h
+++ b/conformance/conformance_test.h
@@ -88,7 +88,7 @@
                  const std::vector<ConformanceTestSuite*>& suites);
 
   ForkPipeRunner(const std::string& executable,
-                 const std::vector<string>& executable_args)
+                 const std::vector<std::string>& executable_args)
       : child_pid_(-1),
         executable_(executable),
         executable_args_(executable_args) {}
@@ -113,7 +113,7 @@
   int read_fd_;
   pid_t child_pid_;
   std::string executable_;
-  const std::vector<string> executable_args_;
+  const std::vector<std::string> executable_args_;
   std::string current_test_name_;
 };
 
@@ -168,9 +168,7 @@
 
   // Gets the flag name to the failure list file.
   // By default, this would return --failure_list
-  string GetFailureListFlagName() {
-    return failure_list_flag_name_;
-  }
+  std::string GetFailureListFlagName() { return failure_list_flag_name_; }
 
   void SetFailureListFlagName(const std::string& failure_list_flag_name) {
     failure_list_flag_name_ = failure_list_flag_name;
@@ -207,18 +205,18 @@
 
   class ConformanceRequestSetting {
    public:
-    ConformanceRequestSetting(
-        ConformanceLevel level,
-        conformance::WireFormat input_format,
-        conformance::WireFormat output_format,
-        conformance::TestCategory test_category,
-        const Message& prototype_message,
-        const string& test_name, const string& input);
+    ConformanceRequestSetting(ConformanceLevel level,
+                              conformance::WireFormat input_format,
+                              conformance::WireFormat output_format,
+                              conformance::TestCategory test_category,
+                              const Message& prototype_message,
+                              const std::string& test_name,
+                              const std::string& input);
     virtual ~ConformanceRequestSetting() {}
 
     std::unique_ptr<Message> NewTestMessage() const;
 
-    string GetTestName() const;
+    std::string GetTestName() const;
 
     const conformance::ConformanceRequest& GetRequest() const {
       return request_;
@@ -228,7 +226,7 @@
       return level_;
     }
 
-    string ConformanceLevelToString(ConformanceLevel level) const;
+    std::string ConformanceLevelToString(ConformanceLevel level) const;
 
     void SetPrintUnknownFields(bool print_unknown_fields) {
       request_.set_print_unknown_fields(true);
@@ -239,8 +237,9 @@
     }
 
    protected:
-    virtual string InputFormatString(conformance::WireFormat format) const;
-    virtual string OutputFormatString(conformance::WireFormat format) const;
+    virtual std::string InputFormatString(conformance::WireFormat format) const;
+    virtual std::string OutputFormatString(
+        conformance::WireFormat format) const;
     conformance::ConformanceRequest request_;
 
    private:
@@ -249,12 +248,12 @@
     ::conformance::WireFormat output_format_;
     const Message& prototype_message_;
     std::unique_ptr<Message> prototype_message_for_compare_;
-    string test_name_;
+    std::string test_name_;
   };
 
-  bool CheckSetEmpty(const std::set<string>& set_to_check,
+  bool CheckSetEmpty(const std::set<std::string>& set_to_check,
                      const std::string& write_to_file, const std::string& msg);
-  string WireFormatToString(conformance::WireFormat wire_format);
+  std::string WireFormatToString(conformance::WireFormat wire_format);
 
   // Parse payload in the response to the given message. Returns true on
   // success.
@@ -264,24 +263,23 @@
       Message* test_message) = 0;
 
   void VerifyResponse(const ConformanceRequestSetting& setting,
-                      const string& equivalent_wire_format,
+                      const std::string& equivalent_wire_format,
                       const conformance::ConformanceResponse& response,
                       bool need_report_success, bool require_same_wire_format);
 
   void ReportSuccess(const std::string& test_name);
-  void ReportFailure(const string& test_name,
-                     ConformanceLevel level,
+  void ReportFailure(const std::string& test_name, ConformanceLevel level,
                      const conformance::ConformanceRequest& request,
                      const conformance::ConformanceResponse& response,
                      const char* fmt, ...);
-  void ReportSkip(const string& test_name,
+  void ReportSkip(const std::string& test_name,
                   const conformance::ConformanceRequest& request,
                   const conformance::ConformanceResponse& response);
 
   void RunValidInputTest(const ConformanceRequestSetting& setting,
-                         const string& equivalent_text_format);
+                         const std::string& equivalent_text_format);
   void RunValidBinaryInputTest(const ConformanceRequestSetting& setting,
-                               const string& equivalent_wire_format,
+                               const std::string& equivalent_wire_format,
                                bool require_same_wire_format = false);
 
   void RunTest(const std::string& test_name,
diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc
index 9f893cb..1572ac0 100644
--- a/conformance/conformance_test_runner.cc
+++ b/conformance/conformance_test_runner.cc
@@ -297,7 +297,7 @@
 
     std::vector<const char *> argv;
     argv.push_back(executable.get());
-    for (int i = 0; i < executable_args_.size(); ++i) {
+    for (size_t i = 0; i < executable_args_.size(); ++i) {
       argv.push_back(executable_args_[i].c_str());
     }
     argv.push_back(nullptr);
@@ -307,7 +307,7 @@
 }
 
 void ForkPipeRunner::CheckedWrite(int fd, const void *buf, size_t len) {
-  if (write(fd, buf, len) != len) {
+  if (static_cast<size_t>(write(fd, buf, len)) != len) {
     GOOGLE_LOG(FATAL) << current_test_name_
                << ": error writing to test program: " << strerror(errno);
   }
diff --git a/conformance/conformance_test_runner.sh b/conformance/conformance_test_runner.sh
new file mode 100755
index 0000000..e9b2e4f
--- /dev/null
+++ b/conformance/conformance_test_runner.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+set -x
+echo $@
+
+set -euo pipefail
+# --- begin runfiles.bash initialization ---
+if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
+    if [[ -f "$0.runfiles_manifest" ]]; then
+      export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
+    elif [[ -f "$0.runfiles/MANIFEST" ]]; then
+      export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
+    elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
+      export RUNFILES_DIR="$0.runfiles"
+    fi
+fi
+if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
+  source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
+elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
+  source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
+            "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
+else
+  echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
+  exit 1
+fi
+# --- end runfiles.bash initialization ---
+
+TESTEE=unset
+FAILURE_LIST=unset
+TEXT_FORMAT_FAILURE_LIST=unset
+
+while [[ -n "$@" ]]; do
+  arg="$1"; shift
+  val="$1"; shift
+  case "$arg" in
+    "--testee") TESTEE="$val" ;;
+    "--failure_list") FAILURE_LIST="$val" ;;
+    "--text_format_failure_list") TEXT_FORMAT_FAILURE_LIST="$val" ;;
+    *) echo "Flag $arg is not recognized." && exit 1 ;;
+  esac
+done
+
+conformance_test_runner=$(rlocation com_google_protobuf/conformance_test_runner)
+conformance_testee=$(rlocation $TESTEE)
+args=(--enforce_recommended)
+
+failure_list=$(rlocation $FAILURE_LIST)
+if [ "$failure_list" != "1" ] ; then
+  args+=(--failure_list $failure_list)
+fi
+
+text_format_failure_list=$(rlocation $TEXT_FORMAT_FAILURE_LIST)
+if [ "$text_format_failure_list" != "1" ]; then
+  args+=(--text_format_failure_list $text_format_failure_list)
+fi
+
+$conformance_test_runner "${args[@]}" $conformance_testee
diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt
index 0c01e1e..d55fa9f 100644
--- a/conformance/failure_list_cpp.txt
+++ b/conformance/failure_list_cpp.txt
@@ -34,3 +34,4 @@
 Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines
 Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace
 Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
+Recommended.Proto2.JsonInput.FieldNameExtension.Validator
diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt
index 2a20aa7..bba295e 100644
--- a/conformance/failure_list_csharp.txt
+++ b/conformance/failure_list_csharp.txt
@@ -1,2 +1,7 @@
+Recommended.Proto2.JsonInput.FieldNameExtension.Validator
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Required.Proto3.JsonInput.OneofFieldNullFirst.JsonOutput
+Required.Proto3.JsonInput.OneofFieldNullFirst.ProtobufOutput
+Required.Proto3.JsonInput.OneofFieldNullSecond.JsonOutput
+Required.Proto3.JsonInput.OneofFieldNullSecond.ProtobufOutput
diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt
index dc1f9ba..808e230 100644
--- a/conformance/failure_list_java.txt
+++ b/conformance/failure_list_java.txt
@@ -34,6 +34,7 @@
 Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
 Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
 Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
+Recommended.Proto2.JsonInput.FieldNameExtension.Validator
 Required.Proto3.JsonInput.EnumFieldNotQuoted
 Required.Proto3.JsonInput.Int32FieldLeadingZero
 Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
@@ -41,7 +42,3 @@
 Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
 Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
 Required.Proto3.JsonInput.StringFieldNotAString
-Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
-Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
diff --git a/conformance/failure_list_java_lite.txt b/conformance/failure_list_java_lite.txt
new file mode 100644
index 0000000..57a082e
--- /dev/null
+++ b/conformance/failure_list_java_lite.txt
@@ -0,0 +1,10 @@
+# This is the list of conformance tests that are known to fail for the Java
+# implementation right now. These should be fixed.
+#
+# By listing them here we can keep tabs on which ones are failing and be sure
+# that we don't introduce regressions in other tests.
+
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
diff --git a/conformance/failure_list_jruby.txt b/conformance/failure_list_jruby.txt
new file mode 100644
index 0000000..ceaaf92
--- /dev/null
+++ b/conformance/failure_list_jruby.txt
@@ -0,0 +1,810 @@
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.Proto2.JsonInput.FieldNameExtension.Validator
+Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
+Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue
+Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse
+Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
+Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
+Recommended.Proto3.JsonInput.FieldNameDuplicate
+Recommended.Proto3.JsonInput.FieldNameNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.JsonWithComments
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
+Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
+Recommended.Proto3.ProtobufInput.OneofZeroBool.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroBool.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroDouble.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroDouble.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroEnum.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroEnum.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroFloat.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroFloat.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroMessage.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroMessage.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroUint32.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroUint32.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroUint64.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroUint64.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.DefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForDifferentField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForSameField.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.NonDefaultValue.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[4].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[5].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[6].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BYTES[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[0].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[5].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED32[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED64[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[4].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[4].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[5].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[6].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[7].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[8].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[9].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[0].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[4].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[4].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[5].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[6].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[2].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[3].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[4].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[5].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[6].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[7].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[8].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[9].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[1].ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[2].ProtobufOutput
+Required.DurationProtoInputTooLarge.JsonOutput
+Required.DurationProtoInputTooSmall.JsonOutput
+Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
+Required.Proto3.JsonInput.Any.JsonOutput
+Required.Proto3.JsonInput.Any.ProtobufOutput
+Required.Proto3.JsonInput.AnyNested.JsonOutput
+Required.Proto3.JsonInput.AnyNested.ProtobufOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
+Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
+Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.EnumFieldNotQuoted
+Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldLeadingZero
+Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
+Required.Proto3.JsonInput.Int32FieldPlusSign
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+Required.Proto3.JsonInput.StringFieldNotAString
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BOOL
+Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT32
+Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT64
+Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT32
+Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT64
+Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT32
+Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT64
+Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.JsonOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
+Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].JsonOutput
+Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].ProtobufOutput
+Required.TimestampProtoInputTooLarge.JsonOutput
+Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_js.txt b/conformance/failure_list_js.txt
index ef9131a..e69de29 100644
--- a/conformance/failure_list_js.txt
+++ b/conformance/failure_list_js.txt
@@ -1,115 +0,0 @@
-
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput
diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt
index 7ee5b9a..667f80c 100644
--- a/conformance/failure_list_php.txt
+++ b/conformance/failure_list_php.txt
@@ -1,72 +1,20 @@
 Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
 Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.Proto2.JsonInput.FieldNameExtension.Validator
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
 Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
 Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
+Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
 Required.Proto3.JsonInput.DoubleFieldTooSmall
 Required.Proto3.JsonInput.FloatFieldTooLarge
 Required.Proto3.JsonInput.FloatFieldTooSmall
 Required.Proto3.JsonInput.Int32FieldNotInteger
 Required.Proto3.JsonInput.Int64FieldNotInteger
 Required.Proto3.JsonInput.OneofFieldDuplicate
+Required.Proto3.JsonInput.OneofFieldNullSecond.JsonOutput
+Required.Proto3.JsonInput.OneofFieldNullSecond.ProtobufOutput
 Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
 Required.Proto3.JsonInput.RepeatedListValue.JsonOutput
 Required.Proto3.JsonInput.RepeatedListValue.ProtobufOutput
@@ -75,8 +23,8 @@
 Required.Proto3.JsonInput.Uint64FieldNotInteger
 Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput
 Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput
 Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
 Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
 Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput
diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt
index 6a6949f..63c7e8a 100644
--- a/conformance/failure_list_php_c.txt
+++ b/conformance/failure_list_php_c.txt
@@ -1,109 +1,2 @@
-Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
-Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
-Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
-Recommended.Proto3.JsonInput.MapFieldValueIsNull
-Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
-Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
-Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Required.DurationProtoInputTooLarge.JsonOutput
-Required.DurationProtoInputTooSmall.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
-Required.Proto3.JsonInput.DurationMinValue.JsonOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.Proto3.JsonInput.OneofFieldDuplicate
-Required.Proto3.JsonInput.RejectTopLevelNull
-Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.TimestampProtoInputTooLarge.JsonOutput
-Required.TimestampProtoInputTooSmall.JsonOutput
+Recommended.Proto2.JsonInput.FieldNameExtension.Validator
+Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
diff --git a/conformance/failure_list_php_c_32.txt b/conformance/failure_list_php_c_32.txt
deleted file mode 100644
index f516f13..0000000
--- a/conformance/failure_list_php_c_32.txt
+++ /dev/null
@@ -1,142 +0,0 @@
-Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
-Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
-Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
-Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
-Recommended.Proto3.JsonInput.MapFieldValueIsNull
-Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
-Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
-Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator
-Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator
-Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Required.DurationProtoInputTooLarge.JsonOutput
-Required.DurationProtoInputTooSmall.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
-Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
-Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
-Required.Proto3.JsonInput.DurationMinValue.JsonOutput
-Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
-Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMaxValue.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput
-Required.Proto3.JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
-Required.Proto3.JsonInput.Int64FieldMinValue.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput
-Required.Proto3.JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMinValueNotQuoted.ProtobufOutput
-Required.Proto3.JsonInput.OneofFieldDuplicate
-Required.Proto3.JsonInput.RejectTopLevelNull
-Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.Proto3.JsonInput.TimestampLeap.JsonOutput
-Required.Proto3.JsonInput.TimestampLeap.ProtobufOutput
-Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput
-Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput
-Required.Proto3.JsonInput.TimestampMinValue.JsonOutput
-Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput
-Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
-Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput
-Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
-Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput
-Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValue.JsonOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.TimestampProtoInputTooLarge.JsonOutput
-Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt
index f551227..e69de29 100644
--- a/conformance/failure_list_python.txt
+++ b/conformance/failure_list_python.txt
@@ -1,31 +0,0 @@
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
-Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
-Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BYTES[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED32[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED64[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[6].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[5].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[0].ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldTooSmall
-Required.Proto3.JsonInput.FloatFieldTooLarge
-Required.Proto3.JsonInput.FloatFieldTooSmall
-Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-Required.Proto3.JsonInput.TimestampJsonInputLowercaseT
diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt
index 59a969d..9efb6cf 100644
--- a/conformance/failure_list_python_cpp.txt
+++ b/conformance/failure_list_python_cpp.txt
@@ -6,17 +6,3 @@
 #
 # TODO(haberman): insert links to corresponding bugs tracking the issue.
 # Should we use GitHub issues or the Google-internal bug tracker?
-
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
-Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
-Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
-Required.Proto3.JsonInput.DoubleFieldTooSmall
-Required.Proto3.JsonInput.FloatFieldTooLarge
-Required.Proto3.JsonInput.FloatFieldTooSmall
-Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-Required.Proto3.JsonInput.TimestampJsonInputLowercaseT
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index f9533ae..4938202 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -1,109 +1,58 @@
-Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
-Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
-Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
-Recommended.Proto3.JsonInput.MapFieldValueIsNull
-Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
-Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.JsonInput.FieldNameExtension.Validator
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Required.DurationProtoInputTooLarge.JsonOutput
-Required.DurationProtoInputTooSmall.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
-Required.Proto3.JsonInput.DurationMinValue.JsonOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
-Required.Proto3.JsonInput.OneofFieldDuplicate
-Required.Proto3.JsonInput.RejectTopLevelNull
-Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.TimestampProtoInputTooLarge.JsonOutput
-Required.TimestampProtoInputTooSmall.JsonOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc
index 6574b10..460bc24 100644
--- a/conformance/text_format_conformance_suite.cc
+++ b/conformance/text_format_conformance_suite.cc
@@ -258,6 +258,84 @@
   RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED,
                          "optional_float: 18446744073709551616");
 
+  // String literals x {Strings, Bytes}
+  for (const auto& field_type : std::vector<std::string>{"String", "Bytes"}) {
+    const std::string field_name =
+        field_type == "String" ? "optional_string" : "optional_bytes";
+    RunValidTextFormatTest(
+        StrCat("StringLiteralConcat", field_type), REQUIRED,
+        StrCat(field_name, ": 'first' \"second\"\n'third'"));
+    RunValidTextFormatTest(
+        StrCat("StringLiteralBasicEscapes", field_type), REQUIRED,
+        StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'"));
+    RunValidTextFormatTest(
+        StrCat("StringLiteralOctalEscapes", field_type), REQUIRED,
+        StrCat(field_name, ": '\\341\\210\\264'"));
+    RunValidTextFormatTest(StrCat("StringLiteralHexEscapes", field_type),
+                           REQUIRED,
+                           StrCat(field_name, ": '\\xe1\\x88\\xb4'"));
+    RunValidTextFormatTest(
+        StrCat("StringLiteralShortUnicodeEscape", field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\u1234'"));
+    RunValidTextFormatTest(
+        StrCat("StringLiteralLongUnicodeEscapes", field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\U00001234\\U00010437'"));
+    // String literals don't include line feeds.
+    ExpectParseFailure(StrCat("StringLiteralIncludesLF", field_type),
+                       REQUIRED,
+                       StrCat(field_name, ": 'first line\nsecond line'"));
+    // Unicode escapes don't include code points that lie beyond the planes
+    // (> 0x10ffff).
+    ExpectParseFailure(
+        StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type),
+        REQUIRED, StrCat(field_name, ": '\\U00110000'"));
+    // Unicode escapes don't include surrogates.
+    ExpectParseFailure(
+        StrCat("StringLiteralShortUnicodeEscapeSurrogatePair",
+                     field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\ud801\\udc37'"));
+    ExpectParseFailure(
+        StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly",
+                     field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\ud800'"));
+    ExpectParseFailure(
+        StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly",
+                     field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\udc00'"));
+    ExpectParseFailure(
+        StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly",
+                     field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\U0000d800'"));
+    ExpectParseFailure(
+        StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly",
+                     field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\U0000dc00'"));
+    ExpectParseFailure(
+        StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\U00000dc37'"));
+    ExpectParseFailure(
+        StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort",
+                     field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\udc37'"));
+    ExpectParseFailure(
+        StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong",
+                     field_type),
+        RECOMMENDED, StrCat(field_name, ": '\\ud801\\U0000dc37'"));
+
+    // The following method depend on the type of field, as strings have extra
+    // validation.
+    const auto test_method =
+        field_type == "String"
+            ? &TextFormatConformanceTestSuite::ExpectParseFailure
+            : &TextFormatConformanceTestSuite::RunValidTextFormatTest;
+
+    // String fields reject invalid UTF-8 byte sequences; bytes fields don't.
+    (this->*test_method)(StrCat(field_type, "FieldBadUTF8Octal"),
+                         REQUIRED, StrCat(field_name, ": '\\300'"));
+    (this->*test_method)(StrCat(field_type, "FieldBadUTF8Hex"), REQUIRED,
+                         StrCat(field_name, ": '\\xc0'"));
+  }
+
   // Group fields
   RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED,
                                "Data { group_int32: 1 }");
@@ -373,6 +451,27 @@
       }
       )",
                                     prototype);
+
+  prototype.Clear();
+  ConformanceRequestSetting setting_map(
+      REQUIRED, conformance::TEXT_FORMAT, conformance::PROTOBUF,
+      conformance::TEXT_FORMAT_TEST, prototype, "DuplicateMapKey", R"(
+      map_string_nested_message {
+        key: "duplicate"
+        value: { a: 123 }
+      }
+      map_string_nested_message {
+        key: "duplicate"
+        value: { corecursive: {} }
+      }
+      )");
+  // The last-specified value will be retained in a parsed map
+  RunValidInputTest(setting_map, R"(
+      map_string_nested_message {
+        key: "duplicate"
+        value: { corecursive: {} }
+      }
+      )");
 }
 
 }  // namespace protobuf
diff --git a/conformance/text_format_conformance_suite.h b/conformance/text_format_conformance_suite.h
index dd258f5..e875f31 100644
--- a/conformance/text_format_conformance_suite.h
+++ b/conformance/text_format_conformance_suite.h
@@ -41,20 +41,20 @@
   TextFormatConformanceTestSuite();
 
  private:
-  void RunSuiteImpl();
-  void RunValidTextFormatTest(const string& test_name, ConformanceLevel level,
-                              const string& input);
-  void RunValidTextFormatTestProto2(const string& test_name,
+  void RunSuiteImpl() override;
+  void RunValidTextFormatTest(const std::string& test_name,
+                              ConformanceLevel level, const std::string& input);
+  void RunValidTextFormatTestProto2(const std::string& test_name,
                                     ConformanceLevel level,
-                                    const string& input);
-  void RunValidTextFormatTestWithMessage(const string& test_name,
+                                    const std::string& input);
+  void RunValidTextFormatTestWithMessage(const std::string& test_name,
                                          ConformanceLevel level,
-                                         const string& input_text,
+                                         const std::string& input_text,
                                          const Message& prototype);
-  void RunValidUnknownTextFormatTest(const string& test_name,
+  void RunValidUnknownTextFormatTest(const std::string& test_name,
                                      const Message& message);
-  void ExpectParseFailure(const string& test_name, ConformanceLevel level,
-                          const string& input);
+  void ExpectParseFailure(const std::string& test_name, ConformanceLevel level,
+                          const std::string& input);
   bool ParseTextFormatResponse(const conformance::ConformanceResponse& response,
                                const ConformanceRequestSetting& setting,
                                Message* test_message);
diff --git a/conformance/text_format_failure_list_cpp.txt b/conformance/text_format_failure_list_cpp.txt
new file mode 100644
index 0000000..a25f04f
--- /dev/null
+++ b/conformance/text_format_failure_list_cpp.txt
@@ -0,0 +1,20 @@
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
+Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex
+Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal
+Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes
+Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString
diff --git a/conformance/text_format_failure_list_java.txt b/conformance/text_format_failure_list_java.txt
index 81433b4..71e3242 100644
--- a/conformance/text_format_failure_list_java.txt
+++ b/conformance/text_format_failure_list_java.txt
@@ -4,3 +4,10 @@
 Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
 Required.Proto3.TextFormatInput.AnyField.ProtobufOutput
 Required.Proto3.TextFormatInput.AnyField.TextFormatOutput
+
+Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex
+Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput
diff --git a/conformance/text_format_failure_list_java_lite.txt b/conformance/text_format_failure_list_java_lite.txt
new file mode 100644
index 0000000..61f1a96
--- /dev/null
+++ b/conformance/text_format_failure_list_java_lite.txt
@@ -0,0 +1,5 @@
+# This is the list of conformance tests that are known to fail for the Java
+# Lite TextFormat implementation right now. These should be fixed.
+#
+# By listing them here we can keep tabs on which ones are failing and be sure
+# that we don't introduce regressions in other tests.
diff --git a/conformance/text_format_failure_list_jruby.txt b/conformance/text_format_failure_list_jruby.txt
new file mode 100644
index 0000000..404b64a
--- /dev/null
+++ b/conformance/text_format_failure_list_jruby.txt
@@ -0,0 +1,8 @@
+Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput
+Recommended.Proto3.ProtobufInput.GroupUnknownFields_Print.TextFormatOutput
+Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput
+Recommended.Proto3.ProtobufInput.MessageUnknownFields_Print.TextFormatOutput
+Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
+Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput
+Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
+Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Print.TextFormatOutput
diff --git a/conformance/text_format_failure_list_python.txt b/conformance/text_format_failure_list_python.txt
index b2db95e..6bf7c1a 100644
--- a/conformance/text_format_failure_list_python.txt
+++ b/conformance/text_format_failure_list_python.txt
@@ -3,3 +3,32 @@
 # TODO: These should be fixed.
 Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput
 Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput
+
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput
diff --git a/conformance/text_format_failure_list_python_2.7.txt b/conformance/text_format_failure_list_python_2.7.txt
new file mode 100644
index 0000000..cada2bc
--- /dev/null
+++ b/conformance/text_format_failure_list_python_2.7.txt
@@ -0,0 +1,36 @@
+# This is the list of text format conformance tests that are known to fail right
+# now.
+# TODO: These should be fixed.
+Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput
+Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput
+
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput
+Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes
+Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString
diff --git a/conformance/text_format_failure_list_python_cpp.txt b/conformance/text_format_failure_list_python_cpp.txt
new file mode 100644
index 0000000..91fc2ea
--- /dev/null
+++ b/conformance/text_format_failure_list_python_cpp.txt
@@ -0,0 +1,28 @@
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput
diff --git a/conformance/text_format_failure_list_python_cpp_2.7.txt b/conformance/text_format_failure_list_python_cpp_2.7.txt
new file mode 100644
index 0000000..ba2089b
--- /dev/null
+++ b/conformance/text_format_failure_list_python_cpp_2.7.txt
@@ -0,0 +1,30 @@
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
+Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
+Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
+Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput
+Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes
+Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString
diff --git a/conformance/third_party/jsoncpp/json.h b/conformance/third_party/jsoncpp/json.h
index 5639c92..373ec98 100644
--- a/conformance/third_party/jsoncpp/json.h
+++ b/conformance/third_party/jsoncpp/json.h
@@ -1371,7 +1371,7 @@
    */
   std::string getFormattedErrorMessages() const;
 
-  /** \brief Returns a vector of structured errors encounted while parsing.
+  /** \brief Returns a vector of structured errors encountered while parsing.
    * \return A (possibly empty) vector of StructuredError objects. Currently
    *         only one error can be returned, but the caller should tolerate
    * multiple
@@ -1867,7 +1867,7 @@
  *     - otherwise, it the values do not fit on one line, or the array contains
  *       object or non empty array, then print one value per line.
  *
- * If the Value have comments then they are outputed according to their
+ * If the Value have comments then they are outputted according to their
  *#CommentPlacement.
  *
  * \sa Reader, Value, Value::setComment()
@@ -1928,7 +1928,7 @@
  *     - otherwise, it the values do not fit on one line, or the array contains
  *       object or non empty array, then print one value per line.
  *
- * If the Value have comments then they are outputed according to their
+ * If the Value have comments then they are outputted according to their
  #CommentPlacement.
  *
  * \param indentation Each level will be indented by this amount extra.
diff --git a/conformance/third_party/jsoncpp/jsoncpp.cpp b/conformance/third_party/jsoncpp/jsoncpp.cpp
index d313d05..78919ea 100644
--- a/conformance/third_party/jsoncpp/jsoncpp.cpp
+++ b/conformance/third_party/jsoncpp/jsoncpp.cpp
@@ -142,7 +142,7 @@
 typedef char UIntToStringBuffer[uintToStringBufferSize];
 
 /** Converts an unsigned integer to string.
- * @param value Unsigned interger to convert to string
+ * @param value Unsigned integer to convert to string
  * @param current Input/Output string buffer.
  *        Must have at least uintToStringBufferSize chars free.
  */
diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec
index 91d28ed..cca07ba 100644
--- a/csharp/Google.Protobuf.Tools.nuspec
+++ b/csharp/Google.Protobuf.Tools.nuspec
@@ -5,7 +5,7 @@
     <title>Google Protocol Buffers tools</title>
     <summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
     <description>See project site for more info.</description>
-    <version>3.11.4</version>
+    <version>3.17.3</version>
     <authors>Google Inc.</authors>
     <owners>protobuf-packages</owners>
     <licenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</licenseUrl>
diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index 73a578d..11d06f1 100644
--- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -201,29 +201,29 @@
         [Test]

         public void DecodeZigZag32()

         {

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2));

-            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));

-            Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));

-            Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));

-            Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));

-            Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(0));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(1));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(2));

+            Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag32(3));

+            Assert.AreEqual(0x3FFFFFFF, ParsingPrimitives.DecodeZigZag32(0x7FFFFFFE));

+            Assert.AreEqual(unchecked((int) 0xC0000000), ParsingPrimitives.DecodeZigZag32(0x7FFFFFFF));

+            Assert.AreEqual(0x7FFFFFFF, ParsingPrimitives.DecodeZigZag32(0xFFFFFFFE));

+            Assert.AreEqual(unchecked((int) 0x80000000), ParsingPrimitives.DecodeZigZag32(0xFFFFFFFF));

         }

 

         [Test]

         public void DecodeZigZag64()

         {

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2));

-            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));

-            Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));

-            Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));

-            Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));

-            Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));

-            Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));

-            Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(0));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(1));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(2));

+            Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag64(3));

+            Assert.AreEqual(0x000000003FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFEL));

+            Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFFL));

+            Assert.AreEqual(0x000000007FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFEL));

+            Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFFL));

+            Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));

+            Assert.AreEqual(unchecked((long) 0x8000000000000000L), ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));

         }

         

         [Test]

diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
index 01bd321..e9b4ea8 100644
--- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
+++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -211,35 +211,35 @@
         [Test]

         public void EncodeZigZag32()

         {

-            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0));

-            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1));

-            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1));

-            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2));

-            Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));

-            Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000)));

-            Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));

-            Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000)));

+            Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0));

+            Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1));

+            Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1));

+            Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2));

+            Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF));

+            Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000)));

+            Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF));

+            Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000)));

         }

 

         [Test]

         public void EncodeZigZag64()

         {

-            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0));

-            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1));

-            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1));

-            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2));

+            Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0));

+            Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1));

+            Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1));

+            Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2));

             Assert.AreEqual(0x000000007FFFFFFEuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));

             Assert.AreEqual(0x000000007FFFFFFFuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));

             Assert.AreEqual(0x00000000FFFFFFFEuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));

             Assert.AreEqual(0x00000000FFFFFFFFuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));

             Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));

             Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));

         }

 

         [Test]

@@ -247,26 +247,26 @@
         {

             // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)

             // were chosen semi-randomly via keyboard bashing.

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));

-            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));

-            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0)));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1)));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1)));

+            Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927)));

+            Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612)));

         }

 

         [Test]

         public void RoundTripZigZag64()

         {

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));

-            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));

-            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0)));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1)));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1)));

+            Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927)));

+            Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612)));

 

             Assert.AreEqual(856912304801416L,

-                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));

+                            ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L)));

             Assert.AreEqual(-75123905439571256L,

-                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));

+                            ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L)));

         }

 

         [Test]

@@ -395,7 +395,7 @@
             Assert.IsTrue(memoryStream.CanWrite);

             using (var cos = new CodedOutputStream(memoryStream))

             {

-                cos.WriteRawByte(0);

+                cos.WriteRawBytes(new byte[] {0});

                 Assert.AreEqual(0, memoryStream.Position); // Not flushed yet

             }

             Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream

@@ -409,7 +409,7 @@
             Assert.IsTrue(memoryStream.CanWrite);

             using (var cos = new CodedOutputStream(memoryStream, true))

             {

-                cos.WriteRawByte(0);

+                cos.WriteRawBytes(new byte[] {0});

                 Assert.AreEqual(0, memoryStream.Position); // Not flushed yet

             }

             Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream

diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs
index 3907666..18e8767 100644
--- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs
+++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs
@@ -124,11 +124,20 @@
             {
                 var stream = new MemoryStream();
                 var codedOutput = new CodedOutputStream(stream);
-                codec.ValueWriter(codedOutput, sampleValue);
+                WriteContext.Initialize(codedOutput, out WriteContext ctx);
+                try
+                {
+                    // only write the value using the codec
+                    codec.ValueWriter(ref ctx, sampleValue);
+                }
+                finally
+                {
+                    ctx.CopyStateTo(codedOutput);
+                }
                 codedOutput.Flush();
                 stream.Position = 0;
                 var codedInput = new CodedInputStream(stream);
-                Assert.AreEqual(sampleValue, codec.ValueReader(codedInput));
+                Assert.AreEqual(sampleValue, codec.Read(codedInput));
                 Assert.IsTrue(codedInput.IsAtEnd);
             }
 
@@ -172,13 +181,22 @@
                 if (codec.DefaultValue != null) // This part isn't appropriate for message types.
                 {
                     codedOutput = new CodedOutputStream(stream);
-                    codec.ValueWriter(codedOutput, codec.DefaultValue);
+                    WriteContext.Initialize(codedOutput, out WriteContext ctx);
+                    try
+                    {
+                        // only write the value using the codec
+                        codec.ValueWriter(ref ctx, codec.DefaultValue);
+                    }
+                    finally
+                    {
+                        ctx.CopyStateTo(codedOutput);
+                    }
                     codedOutput.Flush();
                     Assert.AreNotEqual(0, stream.Position);
                     Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
                     stream.Position = 0;
                     var codedInput = new CodedInputStream(stream);
-                    Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput));
+                    Assert.AreEqual(codec.DefaultValue, codec.Read(codedInput));
                 }
             }
 
diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
index d9b1e86..cbb6fee 100644
--- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -5,7 +5,6 @@
     <TargetFrameworks>net451;netcoreapp2.1</TargetFrameworks>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
-    <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
     <IsPackable>False</IsPackable>
   </PropertyGroup>
 
diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh
index e6687c3..b663138 100755
--- a/csharp/generate_protos.sh
+++ b/csharp/generate_protos.sh
@@ -45,6 +45,7 @@
 # and old_extensions2.proto, which are generated with an older version
 # of protoc.
 $PROTOC -Isrc -Icsharp/protos \
+    --experimental_allow_proto3_optional \
     --csharp_out=csharp/src/Google.Protobuf.Test.TestProtos \
     --descriptor_set_out=csharp/src/Google.Protobuf.Test/testprotos.pb \
     --include_source_info \
@@ -61,9 +62,11 @@
     csharp/protos/unittest_issue6936_a.proto \
     csharp/protos/unittest_issue6936_b.proto \
     csharp/protos/unittest_issue6936_c.proto \
+    csharp/protos/unittest_selfreferential_options.proto \
     src/google/protobuf/unittest_well_known_types.proto \
     src/google/protobuf/test_messages_proto3.proto \
-    src/google/protobuf/test_messages_proto2.proto
+    src/google/protobuf/test_messages_proto2.proto \
+    src/google/protobuf/unittest_proto3_optional.proto
 
 # AddressBook sample protos
 $PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \
diff --git a/csharp/install_dotnet_sdk.ps1 b/csharp/install_dotnet_sdk.ps1
index 9e300ed..c78655c 100755
--- a/csharp/install_dotnet_sdk.ps1
+++ b/csharp/install_dotnet_sdk.ps1
@@ -1,5 +1,5 @@
 #!/usr/bin/env powershell
-# Install dotnet SDK based on the SDK version from global.json
+# Install dotnet SDK using the official dotnet-install.ps1 script
 
 Set-StrictMode -Version 2
 $ErrorActionPreference = 'Stop'
@@ -9,16 +9,12 @@
 
 $InstallScriptUrl = 'https://dot.net/v1/dotnet-install.ps1'
 $InstallScriptPath = Join-Path  "$env:TEMP" 'dotnet-install.ps1'
-$GlobalJsonPath = Join-Path $PSScriptRoot '..' | Join-Path -ChildPath 'global.json'
-
-# Resolve SDK version from global.json file
-$GlobalJson = Get-Content -Raw $GlobalJsonPath | ConvertFrom-Json
-$SDKVersion = $GlobalJson.sdk.version
 
 # Download install script
 Write-Host "Downloading install script: $InstallScriptUrl => $InstallScriptPath"
 Invoke-WebRequest -Uri $InstallScriptUrl -OutFile $InstallScriptPath
-&$InstallScriptPath -Version $SDKVersion
 
-# Also install dotnet SDK LTS which is required to run some of the tests
+# The SDK versions to install should be kept in sync with versions
+# installed by kokoro/linux/dockerfile/test/csharp/Dockerfile
 &$InstallScriptPath -Version 2.1.802
+&$InstallScriptPath -Version 5.0.102
diff --git a/csharp/protos/unittest_issues.proto b/csharp/protos/unittest_issues.proto
index b4a88d8..388998f 100644
--- a/csharp/protos/unittest_issues.proto
+++ b/csharp/protos/unittest_issues.proto
@@ -8,6 +8,8 @@
 
 package unittest_issues;
 
+import "google/protobuf/struct.proto";
+
 // Issue 307: when generating doubly-nested types, any references
 // should be of the form A.Types.B.Types.C.
 message Issue307 {
@@ -137,4 +139,20 @@
     string text = 1;
     Nested nested = 2;
   }
-}
\ No newline at end of file
+}
+
+message NullValueOutsideStruct {
+  oneof value {
+    string string_value = 1;
+    google.protobuf.NullValue null_value = 2;
+  }
+}
+
+message NullValueNotInOneof {
+  google.protobuf.NullValue null_value = 2;
+}
+
+message MixedRegularAndOptional {
+  string regular_field = 1;
+  optional string optional_field = 2;
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto b/csharp/protos/unittest_selfreferential_options.proto
similarity index 65%
rename from java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
rename to csharp/protos/unittest_selfreferential_options.proto
index d41b7a1..22f16cf 100644
--- a/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
+++ b/csharp/protos/unittest_selfreferential_options.proto
@@ -28,29 +28,37 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: Darick Tong (darick@google.com)
 syntax = "proto2";
 
-package protobuf_unittest;
+package protobuf_unittest_selfreferential_options;
+option csharp_namespace = "UnitTest.Issues.TestProtos.SelfreferentialOptions";
 
-message Proto1 {
-  option experimental_java_message_interface =
-      "com.google.protobuf.ExtraInterfaces.HasBoolValue";
-  option experimental_java_message_interface =
-      "com.google.protobuf.ExtraInterfaces.HasStringValue<Proto1>";
-  option experimental_java_builder_interface =
-      "com.google.protobuf.ExtraInterfaces.HasStringValueBuilder"
-      "<Proto1, Builder>";
+import "google/protobuf/descriptor.proto";
 
-  optional string string_value = 1;
-  optional bool bool_value = 2;
-  optional bytes byte_value = 3;
-  optional int32 int_value = 4;
+message FooOptions {
+  // Custom field option used in definition of the extension message.
+  optional int32 int_opt = 1 [(foo_options) = {
+    int_opt: 1
+    [foo_int_opt]: 2
+    [foo_foo_opt]: {
+      int_opt: 3
+    }
+  }];
+
+  // Custom field option used in definition of the custom option's message.
+  optional int32 foo = 2 [(foo_options) = {foo: 1234}];
+
+  extensions 1000 to max;
 }
 
-message Proto2 {
-  option experimental_java_message_interface =
-      "com.google.protobuf.ExtraInterfaces.HasBoolValue";
+extend google.protobuf.FieldOptions {
+  // Custom field option used on the definition of that field option.
+  optional int32 bar_options = 1000 [(bar_options) = 1234];
 
-  optional bool bool_value = 1;
+  optional FooOptions foo_options = 1001;
+}
+
+extend FooOptions {
+   optional int32 foo_int_opt = 1000;
+   optional FooOptions foo_foo_opt = 1001;
 }
diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs
index cbd9772..2e88db9 100644
--- a/csharp/src/AddressBook/Addressbook.cs
+++ b/csharp/src/AddressBook/Addressbook.cs
@@ -32,9 +32,9 @@
             "Eg4KBm51bWJlchgBIAEoCRIoCgR0eXBlGAIgASgOMhoudHV0b3JpYWwuUGVy",
             "c29uLlBob25lVHlwZSIrCglQaG9uZVR5cGUSCgoGTU9CSUxFEAASCAoESE9N",
             "RRABEggKBFdPUksQAiIvCgtBZGRyZXNzQm9vaxIgCgZwZW9wbGUYASADKAsy",
-            "EC50dXRvcmlhbC5QZXJzb25CUAoUY29tLmV4YW1wbGUudHV0b3JpYWxCEUFk",
-            "ZHJlc3NCb29rUHJvdG9zqgIkR29vZ2xlLlByb3RvYnVmLkV4YW1wbGVzLkFk",
-            "ZHJlc3NCb29rYgZwcm90bzM="));
+            "EC50dXRvcmlhbC5QZXJzb25CZgobY29tLmV4YW1wbGUudHV0b3JpYWwucHJv",
+            "dG9zQhFBZGRyZXNzQm9va1Byb3Rvc1ABWgsuLi90dXRvcmlhbKoCJEdvb2ds",
+            "ZS5Qcm90b2J1Zi5FeGFtcGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -49,23 +49,31 @@
   /// <summary>
   /// [START messages]
   /// </summary>
-  public sealed partial class Person : pb::IMessage<Person> {
+  public sealed partial class Person : pb::IMessage<Person>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Person> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Examples.AddressBook.AddressbookReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Person() {
       OnConstruction();
     }
@@ -73,6 +81,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Person(Person other) : this() {
       name_ = other.name_;
       id_ = other.id_;
@@ -83,6 +92,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Person Clone() {
       return new Person(this);
     }
@@ -91,6 +101,7 @@
     public const int NameFieldNumber = 1;
     private string name_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -105,6 +116,7 @@
     /// Unique ID number for this person.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Id {
       get { return id_; }
       set {
@@ -116,6 +128,7 @@
     public const int EmailFieldNumber = 3;
     private string email_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Email {
       get { return email_; }
       set {
@@ -129,6 +142,7 @@
         = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> phones_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> Phones {
       get { return phones_; }
     }
@@ -137,6 +151,7 @@
     public const int LastUpdatedFieldNumber = 5;
     private global::Google.Protobuf.WellKnownTypes.Timestamp lastUpdated_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Timestamp LastUpdated {
       get { return lastUpdated_; }
       set {
@@ -145,11 +160,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Person);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Person other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -166,6 +183,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -180,12 +198,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -206,9 +229,38 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Id != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Id);
+      }
+      if (Email.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(Email);
+      }
+      phones_.WriteTo(ref output, _repeated_phones_codec);
+      if (lastUpdated_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(LastUpdated);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -231,6 +283,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Person other) {
       if (other == null) {
         return;
@@ -255,7 +308,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -287,11 +344,51 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            Id = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            Email = input.ReadString();
+            break;
+          }
+          case 34: {
+            phones_.AddEntriesFrom(ref input, _repeated_phones_codec);
+            break;
+          }
+          case 42: {
+            if (lastUpdated_ == null) {
+              LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            }
+            input.ReadMessage(LastUpdated);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the Person message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum PhoneType {
         [pbr::OriginalName("MOBILE")] Mobile = 0,
@@ -299,23 +396,31 @@
         [pbr::OriginalName("WORK")] Work = 2,
       }
 
-      public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> {
+      public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Examples.AddressBook.Person.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public PhoneNumber() {
           OnConstruction();
         }
@@ -323,6 +428,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public PhoneNumber(PhoneNumber other) : this() {
           number_ = other.number_;
           type_ = other.type_;
@@ -330,6 +436,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public PhoneNumber Clone() {
           return new PhoneNumber(this);
         }
@@ -338,6 +445,7 @@
         public const int NumberFieldNumber = 1;
         private string number_ = "";
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string Number {
           get { return number_; }
           set {
@@ -349,6 +457,7 @@
         public const int TypeFieldNumber = 2;
         private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType Type {
           get { return type_; }
           set {
@@ -357,11 +466,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as PhoneNumber);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(PhoneNumber other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -375,6 +486,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (Number.Length != 0) hash ^= Number.GetHashCode();
@@ -386,12 +498,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (Number.Length != 0) {
             output.WriteRawTag(10);
             output.WriteString(Number);
@@ -403,9 +520,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (Number.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(Number);
+          }
+          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) {
+            output.WriteRawTag(16);
+            output.WriteEnum((int) Type);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (Number.Length != 0) {
@@ -421,6 +558,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(PhoneNumber other) {
           if (other == null) {
             return;
@@ -435,7 +573,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -452,8 +594,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                Number = input.ReadString();
+                break;
+              }
+              case 16: {
+                Type = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -464,23 +630,31 @@
   /// <summary>
   /// Our address book file is just one of these.
   /// </summary>
-  public sealed partial class AddressBook : pb::IMessage<AddressBook> {
+  public sealed partial class AddressBook : pb::IMessage<AddressBook>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Examples.AddressBook.AddressbookReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public AddressBook() {
       OnConstruction();
     }
@@ -488,12 +662,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public AddressBook(AddressBook other) : this() {
       people_ = other.people_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public AddressBook Clone() {
       return new AddressBook(this);
     }
@@ -504,16 +680,19 @@
         = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Examples.AddressBook.Person.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> people_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> People {
       get { return people_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as AddressBook);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(AddressBook other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -526,6 +705,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= people_.GetHashCode();
@@ -536,19 +716,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       people_.WriteTo(output, _repeated_people_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      people_.WriteTo(ref output, _repeated_people_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += people_.CalculateSize(_repeated_people_codec);
@@ -559,6 +757,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(AddressBook other) {
       if (other == null) {
         return;
@@ -568,7 +767,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -581,8 +784,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            people_.AddEntriesFrom(ref input, _repeated_people_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/AddressBook/Program.cs b/csharp/src/AddressBook/Program.cs
index ff7b9c0..de4867a 100644
--- a/csharp/src/AddressBook/Program.cs
+++ b/csharp/src/AddressBook/Program.cs
@@ -37,7 +37,7 @@
     /// <summary>

     /// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour

     /// to individual actions. Each action has its own Main method, so that it can be used as an

-    /// invidual complete program.

+    /// individual complete program.

     /// </summary>

     internal class Program

     {

diff --git a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs
index 9e8c330..4124404 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs
+++ b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs
@@ -64,23 +64,31 @@
 
   }
   #region Messages
-  public sealed partial class GoogleMessage1 : pb::IMessage<GoogleMessage1> {
+  public sealed partial class GoogleMessage1 : pb::IMessage<GoogleMessage1>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<GoogleMessage1> _parser = new pb::MessageParser<GoogleMessage1>(() => new GoogleMessage1());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<GoogleMessage1> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Benchmarks.Proto3.BenchmarkMessage1Proto3Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GoogleMessage1() {
       OnConstruction();
     }
@@ -88,6 +96,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GoogleMessage1(GoogleMessage1 other) : this() {
       field1_ = other.field1_;
       field9_ = other.field9_;
@@ -134,6 +143,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GoogleMessage1 Clone() {
       return new GoogleMessage1(this);
     }
@@ -142,6 +152,7 @@
     public const int Field1FieldNumber = 1;
     private string field1_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field1 {
       get { return field1_; }
       set {
@@ -153,6 +164,7 @@
     public const int Field9FieldNumber = 9;
     private string field9_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field9 {
       get { return field9_; }
       set {
@@ -164,6 +176,7 @@
     public const int Field18FieldNumber = 18;
     private string field18_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field18 {
       get { return field18_; }
       set {
@@ -175,6 +188,7 @@
     public const int Field80FieldNumber = 80;
     private bool field80_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field80 {
       get { return field80_; }
       set {
@@ -186,6 +200,7 @@
     public const int Field81FieldNumber = 81;
     private bool field81_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field81 {
       get { return field81_; }
       set {
@@ -197,6 +212,7 @@
     public const int Field2FieldNumber = 2;
     private int field2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field2 {
       get { return field2_; }
       set {
@@ -208,6 +224,7 @@
     public const int Field3FieldNumber = 3;
     private int field3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field3 {
       get { return field3_; }
       set {
@@ -219,6 +236,7 @@
     public const int Field280FieldNumber = 280;
     private int field280_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field280 {
       get { return field280_; }
       set {
@@ -230,6 +248,7 @@
     public const int Field6FieldNumber = 6;
     private int field6_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field6 {
       get { return field6_; }
       set {
@@ -241,6 +260,7 @@
     public const int Field22FieldNumber = 22;
     private long field22_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Field22 {
       get { return field22_; }
       set {
@@ -252,6 +272,7 @@
     public const int Field4FieldNumber = 4;
     private string field4_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field4 {
       get { return field4_; }
       set {
@@ -265,6 +286,7 @@
         = pb::FieldCodec.ForFixed64(42);
     private readonly pbc::RepeatedField<ulong> field5_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> Field5 {
       get { return field5_; }
     }
@@ -273,6 +295,7 @@
     public const int Field59FieldNumber = 59;
     private bool field59_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field59 {
       get { return field59_; }
       set {
@@ -284,6 +307,7 @@
     public const int Field7FieldNumber = 7;
     private string field7_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field7 {
       get { return field7_; }
       set {
@@ -295,6 +319,7 @@
     public const int Field16FieldNumber = 16;
     private int field16_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field16 {
       get { return field16_; }
       set {
@@ -306,6 +331,7 @@
     public const int Field130FieldNumber = 130;
     private int field130_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field130 {
       get { return field130_; }
       set {
@@ -317,6 +343,7 @@
     public const int Field12FieldNumber = 12;
     private bool field12_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field12 {
       get { return field12_; }
       set {
@@ -328,6 +355,7 @@
     public const int Field17FieldNumber = 17;
     private bool field17_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field17 {
       get { return field17_; }
       set {
@@ -339,6 +367,7 @@
     public const int Field13FieldNumber = 13;
     private bool field13_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field13 {
       get { return field13_; }
       set {
@@ -350,6 +379,7 @@
     public const int Field14FieldNumber = 14;
     private bool field14_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field14 {
       get { return field14_; }
       set {
@@ -361,6 +391,7 @@
     public const int Field104FieldNumber = 104;
     private int field104_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field104 {
       get { return field104_; }
       set {
@@ -372,6 +403,7 @@
     public const int Field100FieldNumber = 100;
     private int field100_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field100 {
       get { return field100_; }
       set {
@@ -383,6 +415,7 @@
     public const int Field101FieldNumber = 101;
     private int field101_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field101 {
       get { return field101_; }
       set {
@@ -394,6 +427,7 @@
     public const int Field102FieldNumber = 102;
     private string field102_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field102 {
       get { return field102_; }
       set {
@@ -405,6 +439,7 @@
     public const int Field103FieldNumber = 103;
     private string field103_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field103 {
       get { return field103_; }
       set {
@@ -416,6 +451,7 @@
     public const int Field29FieldNumber = 29;
     private int field29_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field29 {
       get { return field29_; }
       set {
@@ -427,6 +463,7 @@
     public const int Field30FieldNumber = 30;
     private bool field30_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field30 {
       get { return field30_; }
       set {
@@ -438,6 +475,7 @@
     public const int Field60FieldNumber = 60;
     private int field60_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field60 {
       get { return field60_; }
       set {
@@ -449,6 +487,7 @@
     public const int Field271FieldNumber = 271;
     private int field271_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field271 {
       get { return field271_; }
       set {
@@ -460,6 +499,7 @@
     public const int Field272FieldNumber = 272;
     private int field272_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field272 {
       get { return field272_; }
       set {
@@ -471,6 +511,7 @@
     public const int Field150FieldNumber = 150;
     private int field150_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field150 {
       get { return field150_; }
       set {
@@ -482,6 +523,7 @@
     public const int Field23FieldNumber = 23;
     private int field23_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field23 {
       get { return field23_; }
       set {
@@ -493,6 +535,7 @@
     public const int Field24FieldNumber = 24;
     private bool field24_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field24 {
       get { return field24_; }
       set {
@@ -504,6 +547,7 @@
     public const int Field25FieldNumber = 25;
     private int field25_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field25 {
       get { return field25_; }
       set {
@@ -515,6 +559,7 @@
     public const int Field15FieldNumber = 15;
     private global::Benchmarks.Proto3.GoogleMessage1SubMessage field15_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Benchmarks.Proto3.GoogleMessage1SubMessage Field15 {
       get { return field15_; }
       set {
@@ -526,6 +571,7 @@
     public const int Field78FieldNumber = 78;
     private bool field78_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field78 {
       get { return field78_; }
       set {
@@ -537,6 +583,7 @@
     public const int Field67FieldNumber = 67;
     private int field67_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field67 {
       get { return field67_; }
       set {
@@ -548,6 +595,7 @@
     public const int Field68FieldNumber = 68;
     private int field68_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field68 {
       get { return field68_; }
       set {
@@ -559,6 +607,7 @@
     public const int Field128FieldNumber = 128;
     private int field128_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field128 {
       get { return field128_; }
       set {
@@ -570,6 +619,7 @@
     public const int Field129FieldNumber = 129;
     private string field129_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field129 {
       get { return field129_; }
       set {
@@ -581,6 +631,7 @@
     public const int Field131FieldNumber = 131;
     private int field131_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field131 {
       get { return field131_; }
       set {
@@ -589,11 +640,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as GoogleMessage1);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(GoogleMessage1 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -646,6 +699,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Field1.Length != 0) hash ^= Field1.GetHashCode();
@@ -696,12 +750,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Field1.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Field1);
@@ -866,9 +925,182 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Field1.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Field1);
+      }
+      if (Field2 != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Field2);
+      }
+      if (Field3 != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Field3);
+      }
+      if (Field4.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(Field4);
+      }
+      field5_.WriteTo(ref output, _repeated_field5_codec);
+      if (Field6 != 0) {
+        output.WriteRawTag(48);
+        output.WriteInt32(Field6);
+      }
+      if (Field7.Length != 0) {
+        output.WriteRawTag(58);
+        output.WriteString(Field7);
+      }
+      if (Field9.Length != 0) {
+        output.WriteRawTag(74);
+        output.WriteString(Field9);
+      }
+      if (Field12 != false) {
+        output.WriteRawTag(96);
+        output.WriteBool(Field12);
+      }
+      if (Field13 != false) {
+        output.WriteRawTag(104);
+        output.WriteBool(Field13);
+      }
+      if (Field14 != false) {
+        output.WriteRawTag(112);
+        output.WriteBool(Field14);
+      }
+      if (field15_ != null) {
+        output.WriteRawTag(122);
+        output.WriteMessage(Field15);
+      }
+      if (Field16 != 0) {
+        output.WriteRawTag(128, 1);
+        output.WriteInt32(Field16);
+      }
+      if (Field17 != false) {
+        output.WriteRawTag(136, 1);
+        output.WriteBool(Field17);
+      }
+      if (Field18.Length != 0) {
+        output.WriteRawTag(146, 1);
+        output.WriteString(Field18);
+      }
+      if (Field22 != 0L) {
+        output.WriteRawTag(176, 1);
+        output.WriteInt64(Field22);
+      }
+      if (Field23 != 0) {
+        output.WriteRawTag(184, 1);
+        output.WriteInt32(Field23);
+      }
+      if (Field24 != false) {
+        output.WriteRawTag(192, 1);
+        output.WriteBool(Field24);
+      }
+      if (Field25 != 0) {
+        output.WriteRawTag(200, 1);
+        output.WriteInt32(Field25);
+      }
+      if (Field29 != 0) {
+        output.WriteRawTag(232, 1);
+        output.WriteInt32(Field29);
+      }
+      if (Field30 != false) {
+        output.WriteRawTag(240, 1);
+        output.WriteBool(Field30);
+      }
+      if (Field59 != false) {
+        output.WriteRawTag(216, 3);
+        output.WriteBool(Field59);
+      }
+      if (Field60 != 0) {
+        output.WriteRawTag(224, 3);
+        output.WriteInt32(Field60);
+      }
+      if (Field67 != 0) {
+        output.WriteRawTag(152, 4);
+        output.WriteInt32(Field67);
+      }
+      if (Field68 != 0) {
+        output.WriteRawTag(160, 4);
+        output.WriteInt32(Field68);
+      }
+      if (Field78 != false) {
+        output.WriteRawTag(240, 4);
+        output.WriteBool(Field78);
+      }
+      if (Field80 != false) {
+        output.WriteRawTag(128, 5);
+        output.WriteBool(Field80);
+      }
+      if (Field81 != false) {
+        output.WriteRawTag(136, 5);
+        output.WriteBool(Field81);
+      }
+      if (Field100 != 0) {
+        output.WriteRawTag(160, 6);
+        output.WriteInt32(Field100);
+      }
+      if (Field101 != 0) {
+        output.WriteRawTag(168, 6);
+        output.WriteInt32(Field101);
+      }
+      if (Field102.Length != 0) {
+        output.WriteRawTag(178, 6);
+        output.WriteString(Field102);
+      }
+      if (Field103.Length != 0) {
+        output.WriteRawTag(186, 6);
+        output.WriteString(Field103);
+      }
+      if (Field104 != 0) {
+        output.WriteRawTag(192, 6);
+        output.WriteInt32(Field104);
+      }
+      if (Field128 != 0) {
+        output.WriteRawTag(128, 8);
+        output.WriteInt32(Field128);
+      }
+      if (Field129.Length != 0) {
+        output.WriteRawTag(138, 8);
+        output.WriteString(Field129);
+      }
+      if (Field130 != 0) {
+        output.WriteRawTag(144, 8);
+        output.WriteInt32(Field130);
+      }
+      if (Field131 != 0) {
+        output.WriteRawTag(152, 8);
+        output.WriteInt32(Field131);
+      }
+      if (Field150 != 0) {
+        output.WriteRawTag(176, 9);
+        output.WriteInt32(Field150);
+      }
+      if (Field271 != 0) {
+        output.WriteRawTag(248, 16);
+        output.WriteInt32(Field271);
+      }
+      if (Field272 != 0) {
+        output.WriteRawTag(128, 17);
+        output.WriteInt32(Field272);
+      }
+      if (Field280 != 0) {
+        output.WriteRawTag(192, 17);
+        output.WriteInt32(Field280);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Field1.Length != 0) {
@@ -999,6 +1231,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(GoogleMessage1 other) {
       if (other == null) {
         return;
@@ -1131,7 +1364,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1308,27 +1545,219 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Field1 = input.ReadString();
+            break;
+          }
+          case 16: {
+            Field2 = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Field3 = input.ReadInt32();
+            break;
+          }
+          case 34: {
+            Field4 = input.ReadString();
+            break;
+          }
+          case 42:
+          case 41: {
+            field5_.AddEntriesFrom(ref input, _repeated_field5_codec);
+            break;
+          }
+          case 48: {
+            Field6 = input.ReadInt32();
+            break;
+          }
+          case 58: {
+            Field7 = input.ReadString();
+            break;
+          }
+          case 74: {
+            Field9 = input.ReadString();
+            break;
+          }
+          case 96: {
+            Field12 = input.ReadBool();
+            break;
+          }
+          case 104: {
+            Field13 = input.ReadBool();
+            break;
+          }
+          case 112: {
+            Field14 = input.ReadBool();
+            break;
+          }
+          case 122: {
+            if (field15_ == null) {
+              Field15 = new global::Benchmarks.Proto3.GoogleMessage1SubMessage();
+            }
+            input.ReadMessage(Field15);
+            break;
+          }
+          case 128: {
+            Field16 = input.ReadInt32();
+            break;
+          }
+          case 136: {
+            Field17 = input.ReadBool();
+            break;
+          }
+          case 146: {
+            Field18 = input.ReadString();
+            break;
+          }
+          case 176: {
+            Field22 = input.ReadInt64();
+            break;
+          }
+          case 184: {
+            Field23 = input.ReadInt32();
+            break;
+          }
+          case 192: {
+            Field24 = input.ReadBool();
+            break;
+          }
+          case 200: {
+            Field25 = input.ReadInt32();
+            break;
+          }
+          case 232: {
+            Field29 = input.ReadInt32();
+            break;
+          }
+          case 240: {
+            Field30 = input.ReadBool();
+            break;
+          }
+          case 472: {
+            Field59 = input.ReadBool();
+            break;
+          }
+          case 480: {
+            Field60 = input.ReadInt32();
+            break;
+          }
+          case 536: {
+            Field67 = input.ReadInt32();
+            break;
+          }
+          case 544: {
+            Field68 = input.ReadInt32();
+            break;
+          }
+          case 624: {
+            Field78 = input.ReadBool();
+            break;
+          }
+          case 640: {
+            Field80 = input.ReadBool();
+            break;
+          }
+          case 648: {
+            Field81 = input.ReadBool();
+            break;
+          }
+          case 800: {
+            Field100 = input.ReadInt32();
+            break;
+          }
+          case 808: {
+            Field101 = input.ReadInt32();
+            break;
+          }
+          case 818: {
+            Field102 = input.ReadString();
+            break;
+          }
+          case 826: {
+            Field103 = input.ReadString();
+            break;
+          }
+          case 832: {
+            Field104 = input.ReadInt32();
+            break;
+          }
+          case 1024: {
+            Field128 = input.ReadInt32();
+            break;
+          }
+          case 1034: {
+            Field129 = input.ReadString();
+            break;
+          }
+          case 1040: {
+            Field130 = input.ReadInt32();
+            break;
+          }
+          case 1048: {
+            Field131 = input.ReadInt32();
+            break;
+          }
+          case 1200: {
+            Field150 = input.ReadInt32();
+            break;
+          }
+          case 2168: {
+            Field271 = input.ReadInt32();
+            break;
+          }
+          case 2176: {
+            Field272 = input.ReadInt32();
+            break;
+          }
+          case 2240: {
+            Field280 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class GoogleMessage1SubMessage : pb::IMessage<GoogleMessage1SubMessage> {
+  public sealed partial class GoogleMessage1SubMessage : pb::IMessage<GoogleMessage1SubMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<GoogleMessage1SubMessage> _parser = new pb::MessageParser<GoogleMessage1SubMessage>(() => new GoogleMessage1SubMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<GoogleMessage1SubMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Benchmarks.Proto3.BenchmarkMessage1Proto3Reflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GoogleMessage1SubMessage() {
       OnConstruction();
     }
@@ -1336,6 +1765,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GoogleMessage1SubMessage(GoogleMessage1SubMessage other) : this() {
       field1_ = other.field1_;
       field2_ = other.field2_;
@@ -1361,6 +1791,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GoogleMessage1SubMessage Clone() {
       return new GoogleMessage1SubMessage(this);
     }
@@ -1369,6 +1800,7 @@
     public const int Field1FieldNumber = 1;
     private int field1_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field1 {
       get { return field1_; }
       set {
@@ -1380,6 +1812,7 @@
     public const int Field2FieldNumber = 2;
     private int field2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field2 {
       get { return field2_; }
       set {
@@ -1391,6 +1824,7 @@
     public const int Field3FieldNumber = 3;
     private int field3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field3 {
       get { return field3_; }
       set {
@@ -1402,6 +1836,7 @@
     public const int Field15FieldNumber = 15;
     private string field15_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field15 {
       get { return field15_; }
       set {
@@ -1413,6 +1848,7 @@
     public const int Field12FieldNumber = 12;
     private bool field12_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field12 {
       get { return field12_; }
       set {
@@ -1424,6 +1860,7 @@
     public const int Field13FieldNumber = 13;
     private long field13_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Field13 {
       get { return field13_; }
       set {
@@ -1435,6 +1872,7 @@
     public const int Field14FieldNumber = 14;
     private long field14_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Field14 {
       get { return field14_; }
       set {
@@ -1446,6 +1884,7 @@
     public const int Field16FieldNumber = 16;
     private int field16_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field16 {
       get { return field16_; }
       set {
@@ -1457,6 +1896,7 @@
     public const int Field19FieldNumber = 19;
     private int field19_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field19 {
       get { return field19_; }
       set {
@@ -1468,6 +1908,7 @@
     public const int Field20FieldNumber = 20;
     private bool field20_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field20 {
       get { return field20_; }
       set {
@@ -1479,6 +1920,7 @@
     public const int Field28FieldNumber = 28;
     private bool field28_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field28 {
       get { return field28_; }
       set {
@@ -1490,6 +1932,7 @@
     public const int Field21FieldNumber = 21;
     private ulong field21_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong Field21 {
       get { return field21_; }
       set {
@@ -1501,6 +1944,7 @@
     public const int Field22FieldNumber = 22;
     private int field22_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field22 {
       get { return field22_; }
       set {
@@ -1512,6 +1956,7 @@
     public const int Field23FieldNumber = 23;
     private bool field23_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field23 {
       get { return field23_; }
       set {
@@ -1523,6 +1968,7 @@
     public const int Field206FieldNumber = 206;
     private bool field206_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Field206 {
       get { return field206_; }
       set {
@@ -1534,6 +1980,7 @@
     public const int Field203FieldNumber = 203;
     private uint field203_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint Field203 {
       get { return field203_; }
       set {
@@ -1545,6 +1992,7 @@
     public const int Field204FieldNumber = 204;
     private int field204_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field204 {
       get { return field204_; }
       set {
@@ -1556,6 +2004,7 @@
     public const int Field205FieldNumber = 205;
     private string field205_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field205 {
       get { return field205_; }
       set {
@@ -1567,6 +2016,7 @@
     public const int Field207FieldNumber = 207;
     private ulong field207_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong Field207 {
       get { return field207_; }
       set {
@@ -1578,6 +2028,7 @@
     public const int Field300FieldNumber = 300;
     private ulong field300_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong Field300 {
       get { return field300_; }
       set {
@@ -1586,11 +2037,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as GoogleMessage1SubMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(GoogleMessage1SubMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1622,6 +2075,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Field1 != 0) hash ^= Field1.GetHashCode();
@@ -1651,12 +2105,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Field1 != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Field1);
@@ -1740,9 +2199,101 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Field1 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Field1);
+      }
+      if (Field2 != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Field2);
+      }
+      if (Field3 != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Field3);
+      }
+      if (Field12 != false) {
+        output.WriteRawTag(96);
+        output.WriteBool(Field12);
+      }
+      if (Field13 != 0L) {
+        output.WriteRawTag(104);
+        output.WriteInt64(Field13);
+      }
+      if (Field14 != 0L) {
+        output.WriteRawTag(112);
+        output.WriteInt64(Field14);
+      }
+      if (Field15.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteString(Field15);
+      }
+      if (Field16 != 0) {
+        output.WriteRawTag(128, 1);
+        output.WriteInt32(Field16);
+      }
+      if (Field19 != 0) {
+        output.WriteRawTag(152, 1);
+        output.WriteInt32(Field19);
+      }
+      if (Field20 != false) {
+        output.WriteRawTag(160, 1);
+        output.WriteBool(Field20);
+      }
+      if (Field21 != 0UL) {
+        output.WriteRawTag(169, 1);
+        output.WriteFixed64(Field21);
+      }
+      if (Field22 != 0) {
+        output.WriteRawTag(176, 1);
+        output.WriteInt32(Field22);
+      }
+      if (Field23 != false) {
+        output.WriteRawTag(184, 1);
+        output.WriteBool(Field23);
+      }
+      if (Field28 != false) {
+        output.WriteRawTag(224, 1);
+        output.WriteBool(Field28);
+      }
+      if (Field203 != 0) {
+        output.WriteRawTag(221, 12);
+        output.WriteFixed32(Field203);
+      }
+      if (Field204 != 0) {
+        output.WriteRawTag(224, 12);
+        output.WriteInt32(Field204);
+      }
+      if (Field205.Length != 0) {
+        output.WriteRawTag(234, 12);
+        output.WriteString(Field205);
+      }
+      if (Field206 != false) {
+        output.WriteRawTag(240, 12);
+        output.WriteBool(Field206);
+      }
+      if (Field207 != 0UL) {
+        output.WriteRawTag(248, 12);
+        output.WriteUInt64(Field207);
+      }
+      if (Field300 != 0UL) {
+        output.WriteRawTag(224, 18);
+        output.WriteUInt64(Field300);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Field1 != 0) {
@@ -1812,6 +2363,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(GoogleMessage1SubMessage other) {
       if (other == null) {
         return;
@@ -1880,7 +2432,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1969,8 +2525,104 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Field1 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Field2 = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Field3 = input.ReadInt32();
+            break;
+          }
+          case 96: {
+            Field12 = input.ReadBool();
+            break;
+          }
+          case 104: {
+            Field13 = input.ReadInt64();
+            break;
+          }
+          case 112: {
+            Field14 = input.ReadInt64();
+            break;
+          }
+          case 122: {
+            Field15 = input.ReadString();
+            break;
+          }
+          case 128: {
+            Field16 = input.ReadInt32();
+            break;
+          }
+          case 152: {
+            Field19 = input.ReadInt32();
+            break;
+          }
+          case 160: {
+            Field20 = input.ReadBool();
+            break;
+          }
+          case 169: {
+            Field21 = input.ReadFixed64();
+            break;
+          }
+          case 176: {
+            Field22 = input.ReadInt32();
+            break;
+          }
+          case 184: {
+            Field23 = input.ReadBool();
+            break;
+          }
+          case 224: {
+            Field28 = input.ReadBool();
+            break;
+          }
+          case 1629: {
+            Field203 = input.ReadFixed32();
+            break;
+          }
+          case 1632: {
+            Field204 = input.ReadInt32();
+            break;
+          }
+          case 1642: {
+            Field205 = input.ReadString();
+            break;
+          }
+          case 1648: {
+            Field206 = input.ReadBool();
+            break;
+          }
+          case 1656: {
+            Field207 = input.ReadUInt64();
+            break;
+          }
+          case 2400: {
+            Field300 = input.ReadUInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs b/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs
index 01dfcd7..faa37b0 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs
+++ b/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs
@@ -38,23 +38,31 @@
 
   }
   #region Messages
-  public sealed partial class BenchmarkDataset : pb::IMessage<BenchmarkDataset> {
+  public sealed partial class BenchmarkDataset : pb::IMessage<BenchmarkDataset>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BenchmarkDataset> _parser = new pb::MessageParser<BenchmarkDataset>(() => new BenchmarkDataset());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BenchmarkDataset> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Benchmarks.BenchmarksReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BenchmarkDataset() {
       OnConstruction();
     }
@@ -62,6 +70,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BenchmarkDataset(BenchmarkDataset other) : this() {
       name_ = other.name_;
       messageName_ = other.messageName_;
@@ -70,6 +79,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BenchmarkDataset Clone() {
       return new BenchmarkDataset(this);
     }
@@ -82,6 +92,7 @@
     /// Should only contain word characters: [a-zA-Z0-9_]
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -102,6 +113,7 @@
     /// in those files.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string MessageName {
       get { return messageName_; }
       set {
@@ -130,16 +142,19 @@
     /// good branch prediction performance.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> Payload {
       get { return payload_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BenchmarkDataset);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BenchmarkDataset other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -154,6 +169,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -166,12 +182,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -184,9 +205,30 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (MessageName.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(MessageName);
+      }
+      payload_.WriteTo(ref output, _repeated_payload_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -203,6 +245,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BenchmarkDataset other) {
       if (other == null) {
         return;
@@ -218,7 +261,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -239,8 +286,36 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            MessageName = input.ReadString();
+            break;
+          }
+          case 26: {
+            payload_.AddEntriesFrom(ref input, _repeated_payload_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs
new file mode 100644
index 0000000..a755850
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs
@@ -0,0 +1,72 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2019 Google Inc.  All rights reserved.
+// https://github.com/protocolbuffers/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using BenchmarkDotNet.Attributes;
+
+namespace Google.Protobuf.Benchmarks
+{
+    /// <summary>
+    /// Benchmarks using ByteString.
+    /// </summary>
+    [MemoryDiagnoser]
+    public class ByteStringBenchmark
+    {
+        private const int Zero = 0;
+        private const int Kilobyte = 1024;
+        private const int _128Kilobytes = 1024 * 128;
+        private const int Megabyte = 1024 * 1024;
+        private const int _10Megabytes = 1024 * 1024 * 10;
+
+        byte[] byteBuffer;
+
+        [GlobalSetup]
+        public void GlobalSetup()
+        {
+            byteBuffer = new byte[PayloadSize];
+        }
+
+        [Params(Zero, Kilobyte, _128Kilobytes, Megabyte, _10Megabytes)]
+        public int PayloadSize { get; set; }
+
+        [Benchmark]
+        public ByteString CopyFrom()
+        {
+            return ByteString.CopyFrom(byteBuffer);
+        }
+
+        [Benchmark]
+        public ByteString UnsafeWrap()
+        {
+            return UnsafeByteOperations.UnsafeWrap(byteBuffer);
+        }
+    }
+}
diff --git a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
index ecc064e..ac8e009a 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
+++ b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
@@ -2,12 +2,20 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <TargetFramework>net5.0</TargetFramework>
+    <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+    <SignAssembly>true</SignAssembly>
     <IsPackable>False</IsPackable>
+    <DebugType>pdbonly</DebugType>
+    <DebugSymbols>true</DebugSymbols>
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="BenchmarkDotNet" Version="0.11.4" />
+    <Compile Include="..\Google.Protobuf.Test\ReadOnlySequenceFactory.cs" Link="ReadOnlySequenceFactory.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
     <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj" />
   </ItemGroup>
 
diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs
index cbc4732..8e6710b 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs
+++ b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs
@@ -37,6 +37,7 @@
 using System.Linq;
 using System.Buffers;
 using Google.Protobuf.WellKnownTypes;
+using Benchmarks.Proto3;
 
 namespace Google.Protobuf.Benchmarks
 {
@@ -50,6 +51,7 @@
 
         SubTest manyWrapperFieldsTest = new SubTest(CreateManyWrapperFieldsMessage(), ManyWrapperFieldsMessage.Parser, () => new ManyWrapperFieldsMessage(), MaxMessages);
         SubTest manyPrimitiveFieldsTest = new SubTest(CreateManyPrimitiveFieldsMessage(), ManyPrimitiveFieldsMessage.Parser, () => new ManyPrimitiveFieldsMessage(), MaxMessages);
+        SubTest repeatedFieldTest = new SubTest(CreateRepeatedFieldMessage(), GoogleMessage1.Parser, () => new GoogleMessage1(), MaxMessages);
         SubTest emptyMessageTest = new SubTest(new Empty(), Empty.Parser, () => new Empty(), MaxMessages);
 
         public IEnumerable<int> MessageCountValues => new[] { 10, 100 };
@@ -66,18 +68,48 @@
         }
 
         [Benchmark]
+        public IMessage ManyWrapperFieldsMessage_ParseFromReadOnlySequence()
+        {
+            return manyWrapperFieldsTest.ParseFromReadOnlySequence();
+        }
+
+        [Benchmark]
         public IMessage ManyPrimitiveFieldsMessage_ParseFromByteArray()
         {
             return manyPrimitiveFieldsTest.ParseFromByteArray();
         }
 
         [Benchmark]
+        public IMessage ManyPrimitiveFieldsMessage_ParseFromReadOnlySequence()
+        {
+            return manyPrimitiveFieldsTest.ParseFromReadOnlySequence();
+        }
+
+        [Benchmark]
+        public IMessage RepeatedFieldMessage_ParseFromByteArray()
+        {
+            return repeatedFieldTest.ParseFromByteArray();
+        }
+
+        [Benchmark]
+        public IMessage RepeatedFieldMessage_ParseFromReadOnlySequence()
+        {
+            return repeatedFieldTest.ParseFromReadOnlySequence();
+        }
+
+        [Benchmark]
         public IMessage EmptyMessage_ParseFromByteArray()
         {
             return emptyMessageTest.ParseFromByteArray();
         }
 
         [Benchmark]
+        public IMessage EmptyMessage_ParseFromReadOnlySequence()
+        {
+            return emptyMessageTest.ParseFromReadOnlySequence();
+        }
+
+        [Benchmark]
         [ArgumentsSource(nameof(MessageCountValues))]
         public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount)
         {
@@ -86,12 +118,40 @@
 
         [Benchmark]
         [ArgumentsSource(nameof(MessageCountValues))]
+        public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount)
+        {
+            manyWrapperFieldsTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount);
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
         public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount)
         {
             manyPrimitiveFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount);
         }
 
-        private static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage()
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
+        public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount)
+        {
+            manyPrimitiveFieldsTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount);
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
+        public void RepeatedFieldMessage_ParseDelimitedMessagesFromByteArray(int messageCount)
+        {
+            repeatedFieldTest.ParseDelimitedMessagesFromByteArray(messageCount);
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
+        public void RepeatedFieldMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount)
+        {
+            repeatedFieldTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount);
+        }
+
+        public static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage()
         {
             // Example data match data of an internal benchmarks
             return new ManyWrapperFieldsMessage()
@@ -108,7 +168,7 @@
             };
         }
 
-        private static ManyPrimitiveFieldsMessage CreateManyPrimitiveFieldsMessage()
+        public static ManyPrimitiveFieldsMessage CreateManyPrimitiveFieldsMessage()
         {
             // Example data match data of an internal benchmarks
             return new ManyPrimitiveFieldsMessage()
@@ -125,6 +185,17 @@
             };
         }
 
+        public static GoogleMessage1 CreateRepeatedFieldMessage()
+        {
+            // Message with a repeated fixed length item collection
+            var message = new GoogleMessage1();
+            for (ulong i = 0; i < 1000; i++)
+            {
+                message.Field5.Add(i);
+            }
+            return message;
+        }
+
         private class SubTest
         {
             private readonly IMessage message;
@@ -133,6 +204,9 @@
             private readonly byte[] data;
             private readonly byte[] multipleMessagesData;
 
+            private ReadOnlySequence<byte> dataSequence;
+            private ReadOnlySequence<byte> multipleMessagesDataSequence;
+
             public SubTest(IMessage message, MessageParser parser, Func<IMessage> factory, int maxMessageCount)
             {
                 this.message = message;
@@ -140,10 +214,14 @@
                 this.factory = factory;
                 this.data = message.ToByteArray();
                 this.multipleMessagesData = CreateBufferWithMultipleMessages(message, maxMessageCount);
+                this.dataSequence = new ReadOnlySequence<byte>(this.data);
+                this.multipleMessagesDataSequence = new ReadOnlySequence<byte>(this.multipleMessagesData);
             }
 
             public IMessage ParseFromByteArray() => parser.ParseFrom(data);
 
+            public IMessage ParseFromReadOnlySequence() => parser.ParseFrom(dataSequence);
+
             public void ParseDelimitedMessagesFromByteArray(int messageCount)
             {
                 var input = new CodedInputStream(multipleMessagesData);
@@ -154,6 +232,16 @@
                 }
             }
 
+            public void ParseDelimitedMessagesFromReadOnlySequence(int messageCount)
+            {
+                ParseContext.Initialize(multipleMessagesDataSequence, out ParseContext ctx);
+                for (int i = 0; i < messageCount; i++)
+                {
+                    var msg = factory();
+                    ctx.ReadMessage(msg);
+                }
+            }
+
             private static byte[] CreateBufferWithMultipleMessages(IMessage msg, int msgCount)
             {
                 var ms = new MemoryStream();
diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
index 44dde2f..6df1c87 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
+++ b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
@@ -35,6 +35,7 @@
 using System.Buffers.Binary;
 using System.Collections.Generic;
 using System.IO;
+using System.Buffers;
 
 namespace Google.Protobuf.Benchmarks
 {
@@ -51,8 +52,15 @@
         byte[] floatInputBuffer;
         byte[] fixedIntInputBuffer;
 
+        // key is the encodedSize of string values
+        Dictionary<int, byte[]> stringInputBuffers;
+        Dictionary<int, ReadOnlySequence<byte>> stringInputBuffersSegmented;
+
         Random random = new Random(417384220);  // random but deterministic seed
 
+        public IEnumerable<int> StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 };
+        public IEnumerable<int> StringSegmentedEncodedSizes => new[] { 105, 10080 };
+
         [GlobalSetup]
         public void GlobalSetup()
         {
@@ -70,6 +78,20 @@
             doubleInputBuffer = CreateBufferWithRandomDoubles(random, BytesToParse / sizeof(double), paddingValueCount);
             floatInputBuffer = CreateBufferWithRandomFloats(random, BytesToParse / sizeof(float), paddingValueCount);
             fixedIntInputBuffer = CreateBufferWithRandomData(random, BytesToParse / sizeof(long), sizeof(long), paddingValueCount);
+
+            stringInputBuffers = new Dictionary<int, byte[]>();
+            foreach (var encodedSize in StringEncodedSizes)
+            {
+                byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1 );
+                stringInputBuffers.Add(encodedSize, buffer);
+            }
+
+            stringInputBuffersSegmented = new Dictionary<int, ReadOnlySequence<byte>>();
+            foreach (var encodedSize in StringSegmentedEncodedSizes)
+            {
+                byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1);
+                stringInputBuffersSegmented.Add(encodedSize, ReadOnlySequenceFactory.CreateWithContent(buffer, segmentSize: 128, addEmptySegmentDelimiters: false));
+            }
         }
 
         // Total number of bytes that each benchmark will parse.
@@ -85,7 +107,7 @@
         [Arguments(3)]
         [Arguments(4)]
         [Arguments(5)]
-        public int ParseRawVarint32(int encodedSize)
+        public int ParseRawVarint32_CodedInputStream(int encodedSize)
         {
             CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]);
             int sum = 0;
@@ -102,12 +124,29 @@
         [Arguments(3)]
         [Arguments(4)]
         [Arguments(5)]
+        public int ParseRawVarint32_ParseContext(int encodedSize)
+        {
+            InitializeParseContext(varintInputBuffers[encodedSize], out ParseContext ctx);
+            int sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadInt32();
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        [Arguments(1)]
+        [Arguments(2)]
+        [Arguments(3)]
+        [Arguments(4)]
+        [Arguments(5)]
         [Arguments(6)]
         [Arguments(7)]
         [Arguments(8)]
         [Arguments(9)]
         [Arguments(10)]
-        public long ParseRawVarint64(int encodedSize)
+        public long ParseRawVarint64_CodedInputStream(int encodedSize)
         {
             CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]);
             long sum = 0;
@@ -119,7 +158,29 @@
         }
 
         [Benchmark]
-        public uint ParseFixed32()
+        [Arguments(1)]
+        [Arguments(2)]
+        [Arguments(3)]
+        [Arguments(4)]
+        [Arguments(5)]
+        [Arguments(6)]
+        [Arguments(7)]
+        [Arguments(8)]
+        [Arguments(9)]
+        [Arguments(10)]
+        public long ParseRawVarint64_ParseContext(int encodedSize)
+        {
+            InitializeParseContext(varintInputBuffers[encodedSize], out ParseContext ctx);
+            long sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadInt64();
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        public uint ParseFixed32_CodedInputStream()
         {
             const int encodedSize = sizeof(uint);
             CodedInputStream cis = new CodedInputStream(fixedIntInputBuffer);
@@ -132,7 +193,20 @@
         }
 
         [Benchmark]
-        public ulong ParseFixed64()
+        public uint ParseFixed32_ParseContext()
+        {
+            const int encodedSize = sizeof(uint);
+            InitializeParseContext(fixedIntInputBuffer, out ParseContext ctx);
+            uint sum = 0;
+            for (uint i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadFixed32();
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        public ulong ParseFixed64_CodedInputStream()
         {
             const int encodedSize = sizeof(ulong);
             CodedInputStream cis = new CodedInputStream(fixedIntInputBuffer);
@@ -145,7 +219,20 @@
         }
 
         [Benchmark]
-        public float ParseRawFloat()
+        public ulong ParseFixed64_ParseContext()
+        {
+            const int encodedSize = sizeof(ulong);
+            InitializeParseContext(fixedIntInputBuffer, out ParseContext ctx);
+            ulong sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadFixed64();
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        public float ParseRawFloat_CodedInputStream()
         {
             const int encodedSize = sizeof(float);
             CodedInputStream cis = new CodedInputStream(floatInputBuffer);
@@ -158,7 +245,20 @@
         }
 
         [Benchmark]
-        public double ParseRawDouble()
+        public float ParseRawFloat_ParseContext()
+        {
+            const int encodedSize = sizeof(float);
+            InitializeParseContext(floatInputBuffer, out ParseContext ctx);
+            float sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+               sum += ctx.ReadFloat();
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        public double ParseRawDouble_CodedInputStream()
         {
             const int encodedSize = sizeof(double);
             CodedInputStream cis = new CodedInputStream(doubleInputBuffer);
@@ -170,13 +270,114 @@
             return sum;
         }
 
+        [Benchmark]
+        public double ParseRawDouble_ParseContext()
+        {
+            const int encodedSize = sizeof(double);
+            InitializeParseContext(doubleInputBuffer, out ParseContext ctx);
+            double sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadDouble();
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public int ParseString_CodedInputStream(int encodedSize)
+        {
+            CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]);
+            int sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += cis.ReadString().Length;
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public int ParseString_ParseContext(int encodedSize)
+        {
+            InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx);
+            int sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadString().Length;
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringSegmentedEncodedSizes))]
+        public int ParseString_ParseContext_MultipleSegments(int encodedSize)
+        {
+            InitializeParseContext(stringInputBuffersSegmented[encodedSize], out ParseContext ctx);
+            int sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadString().Length;
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public int ParseBytes_CodedInputStream(int encodedSize)
+        {
+            CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]);
+            int sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += cis.ReadBytes().Length;
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public int ParseBytes_ParseContext(int encodedSize)
+        {
+            InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx);
+            int sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadBytes().Length;
+            }
+            return sum;
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringSegmentedEncodedSizes))]
+        public int ParseBytes_ParseContext_MultipleSegments(int encodedSize)
+        {
+            InitializeParseContext(stringInputBuffersSegmented[encodedSize], out ParseContext ctx);
+            int sum = 0;
+            for (int i = 0; i < BytesToParse / encodedSize; i++)
+            {
+                sum += ctx.ReadBytes().Length;
+            }
+            return sum;
+        }
+
+        private static void InitializeParseContext(byte[] buffer, out ParseContext ctx)
+        {
+            ParseContext.Initialize(new ReadOnlySequence<byte>(buffer), out ctx);
+        }
+
+        private static void InitializeParseContext(ReadOnlySequence<byte> buffer, out ParseContext ctx)
+        {
+            ParseContext.Initialize(buffer, out ctx);
+        }
+
         private static byte[] CreateBufferWithRandomVarints(Random random, int valueCount, int encodedSize, int paddingValueCount)
         {
             MemoryStream ms = new MemoryStream();
             CodedOutputStream cos = new CodedOutputStream(ms);
             for (int i = 0; i < valueCount + paddingValueCount; i++)
             {
-                cos.WriteUInt64(RandomUnsignedVarint(random, encodedSize));
+                cos.WriteUInt64(RandomUnsignedVarint(random, encodedSize, false));
             }
             cos.Flush();
             var buffer = ms.ToArray();
@@ -225,11 +426,11 @@
         /// <summary>
         /// Generate a random value that will take exactly "encodedSize" bytes when varint-encoded.
         /// </summary>
-        private static ulong RandomUnsignedVarint(Random random, int encodedSize)
+        public static ulong RandomUnsignedVarint(Random random, int encodedSize, bool fitsIn32Bits)
         {
             Span<byte> randomBytesBuffer = stackalloc byte[8];
 
-            if (encodedSize < 1 || encodedSize > 10)
+            if (encodedSize < 1 || encodedSize > 10 || (fitsIn32Bits && encodedSize > 5))
             {
                 throw new ArgumentException("Illegal encodedSize value requested", nameof(encodedSize));
             }
@@ -245,6 +446,12 @@
                 ulong bitmask = encodedSize < 10 ? ((1UL << (encodedSize * bitsPerByte)) - 1) : ulong.MaxValue;
                 result = randomValue & bitmask;
 
+                if (fitsIn32Bits)
+                {
+                    // make sure the resulting value is representable by a uint.
+                    result &= uint.MaxValue;
+                }
+
                 if (encodedSize == 10)
                 {
                     // for 10-byte values the highest bit always needs to be set (7*9=63)
@@ -261,5 +468,69 @@
             }
             return result;
         }
+
+        private static byte[] CreateBufferWithStrings(int valueCount, int encodedSize, int paddingValueCount)
+        {
+            var str = CreateStringWithEncodedSize(encodedSize);
+
+            MemoryStream ms = new MemoryStream();
+            CodedOutputStream cos = new CodedOutputStream(ms);
+            for (int i = 0; i < valueCount + paddingValueCount; i++)
+            {
+                cos.WriteString(str);
+            }
+            cos.Flush();
+            var buffer = ms.ToArray();
+
+            if (buffer.Length != encodedSize * (valueCount + paddingValueCount))
+            {
+                throw new InvalidOperationException($"Unexpected output buffer length {buffer.Length}");
+            }
+            return buffer;
+        }
+
+        public static string CreateStringWithEncodedSize(int encodedSize)
+        {
+            var str = new string('a', encodedSize);
+            while (CodedOutputStream.ComputeStringSize(str) > encodedSize)
+            {
+                str = str.Substring(1);
+            }
+
+            if (CodedOutputStream.ComputeStringSize(str) != encodedSize)
+            {
+                throw new InvalidOperationException($"Generated string with wrong encodedSize");
+            }
+            return str;
+        }
+
+        public static string CreateNonAsciiStringWithEncodedSize(int encodedSize)
+        {
+            if (encodedSize < 3)
+            {
+                throw new ArgumentException("Illegal encoded size for a string with non-ascii chars.");
+            }
+            var twoByteChar = '\u00DC';  // U-umlaut, UTF8 encoding has 2 bytes
+            var str = new string(twoByteChar, encodedSize / 2);
+            while (CodedOutputStream.ComputeStringSize(str) > encodedSize)
+            {
+                str = str.Substring(1);
+            }
+
+            // add padding of ascii characters to reach the desired encoded size.
+            while (CodedOutputStream.ComputeStringSize(str) < encodedSize)
+            {
+                str += 'a';
+            }
+
+            // Note that for a few specific encodedSize values, it might be impossible to generate
+            // the string with the desired encodedSize using the algorithm above. For testing purposes, checking that
+            // the encoded size we got is actually correct is good enough.
+            if (CodedOutputStream.ComputeStringSize(str) != encodedSize)
+            {
+                throw new InvalidOperationException($"Generated string with wrong encodedSize");
+            }
+            return str;
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs
index 0cc86e2..df427e8 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs
+++ b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs
@@ -237,23 +237,31 @@
   /// a message that has a large number of wrapper fields
   /// obfuscated version of an internal message
   /// </summary>
-  public sealed partial class ManyWrapperFieldsMessage : pb::IMessage<ManyWrapperFieldsMessage> {
+  public sealed partial class ManyWrapperFieldsMessage : pb::IMessage<ManyWrapperFieldsMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ManyWrapperFieldsMessage> _parser = new pb::MessageParser<ManyWrapperFieldsMessage>(() => new ManyWrapperFieldsMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ManyWrapperFieldsMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Benchmarks.WrapperBenchmarkMessagesReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ManyWrapperFieldsMessage() {
       OnConstruction();
     }
@@ -261,6 +269,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ManyWrapperFieldsMessage(ManyWrapperFieldsMessage other) : this() {
       DoubleField95 = other.DoubleField95;
       DoubleField1 = other.DoubleField1;
@@ -377,6 +386,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ManyWrapperFieldsMessage Clone() {
       return new ManyWrapperFieldsMessage(this);
     }
@@ -386,6 +396,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField95_codec = pb::FieldCodec.ForStructWrapper<double>(762);
     private double? doubleField95_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField95 {
       get { return doubleField95_; }
       set {
@@ -399,6 +410,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField1_codec = pb::FieldCodec.ForStructWrapper<double>(10);
     private double? doubleField1_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField1 {
       get { return doubleField1_; }
       set {
@@ -412,6 +424,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField79_codec = pb::FieldCodec.ForStructWrapper<double>(634);
     private double? doubleField79_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField79 {
       get { return doubleField79_; }
       set {
@@ -425,6 +438,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field2_codec = pb::FieldCodec.ForStructWrapper<long>(18);
     private long? int64Field2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field2 {
       get { return int64Field2_; }
       set {
@@ -438,6 +452,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField96_codec = pb::FieldCodec.ForStructWrapper<double>(770);
     private double? doubleField96_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField96 {
       get { return doubleField96_; }
       set {
@@ -451,6 +466,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field3_codec = pb::FieldCodec.ForStructWrapper<long>(26);
     private long? int64Field3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field3 {
       get { return int64Field3_; }
       set {
@@ -464,6 +480,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field4_codec = pb::FieldCodec.ForStructWrapper<long>(34);
     private long? int64Field4_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field4 {
       get { return int64Field4_; }
       set {
@@ -477,6 +494,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField97_codec = pb::FieldCodec.ForStructWrapper<double>(778);
     private double? doubleField97_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField97 {
       get { return doubleField97_; }
       set {
@@ -490,6 +508,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField65_codec = pb::FieldCodec.ForStructWrapper<double>(522);
     private double? doubleField65_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField65 {
       get { return doubleField65_; }
       set {
@@ -503,6 +522,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField66_codec = pb::FieldCodec.ForStructWrapper<double>(530);
     private double? doubleField66_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField66 {
       get { return doubleField66_; }
       set {
@@ -516,6 +536,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField7_codec = pb::FieldCodec.ForStructWrapper<double>(58);
     private double? doubleField7_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField7 {
       get { return doubleField7_; }
       set {
@@ -529,6 +550,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField62_codec = pb::FieldCodec.ForStructWrapper<double>(498);
     private double? doubleField62_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField62 {
       get { return doubleField62_; }
       set {
@@ -542,6 +564,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField118_codec = pb::FieldCodec.ForStructWrapper<double>(946);
     private double? doubleField118_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField118 {
       get { return doubleField118_; }
       set {
@@ -555,6 +578,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField119_codec = pb::FieldCodec.ForStructWrapper<double>(954);
     private double? doubleField119_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField119 {
       get { return doubleField119_; }
       set {
@@ -568,6 +592,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField67_codec = pb::FieldCodec.ForStructWrapper<double>(538);
     private double? doubleField67_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField67 {
       get { return doubleField67_; }
       set {
@@ -581,6 +606,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField120_codec = pb::FieldCodec.ForStructWrapper<double>(962);
     private double? doubleField120_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField120 {
       get { return doubleField120_; }
       set {
@@ -594,6 +620,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField121_codec = pb::FieldCodec.ForStructWrapper<double>(970);
     private double? doubleField121_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField121 {
       get { return doubleField121_; }
       set {
@@ -607,6 +634,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField122_codec = pb::FieldCodec.ForStructWrapper<double>(978);
     private double? doubleField122_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField122 {
       get { return doubleField122_; }
       set {
@@ -620,6 +648,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField123_codec = pb::FieldCodec.ForStructWrapper<double>(986);
     private double? doubleField123_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField123 {
       get { return doubleField123_; }
       set {
@@ -633,6 +662,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField124_codec = pb::FieldCodec.ForStructWrapper<double>(994);
     private double? doubleField124_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField124 {
       get { return doubleField124_; }
       set {
@@ -646,6 +676,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField8_codec = pb::FieldCodec.ForStructWrapper<double>(66);
     private double? doubleField8_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField8 {
       get { return doubleField8_; }
       set {
@@ -659,6 +690,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField9_codec = pb::FieldCodec.ForStructWrapper<double>(74);
     private double? doubleField9_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField9 {
       get { return doubleField9_; }
       set {
@@ -672,6 +704,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField98_codec = pb::FieldCodec.ForStructWrapper<double>(786);
     private double? doubleField98_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField98 {
       get { return doubleField98_; }
       set {
@@ -685,6 +718,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField10_codec = pb::FieldCodec.ForStructWrapper<double>(82);
     private double? doubleField10_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField10 {
       get { return doubleField10_; }
       set {
@@ -698,6 +732,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField11_codec = pb::FieldCodec.ForStructWrapper<double>(90);
     private double? doubleField11_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField11 {
       get { return doubleField11_; }
       set {
@@ -711,6 +746,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField99_codec = pb::FieldCodec.ForStructWrapper<double>(794);
     private double? doubleField99_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField99 {
       get { return doubleField99_; }
       set {
@@ -724,6 +760,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField84_codec = pb::FieldCodec.ForStructWrapper<double>(674);
     private double? doubleField84_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField84 {
       get { return doubleField84_; }
       set {
@@ -737,6 +774,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField14_codec = pb::FieldCodec.ForStructWrapper<double>(114);
     private double? doubleField14_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField14 {
       get { return doubleField14_; }
       set {
@@ -750,6 +788,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField77_codec = pb::FieldCodec.ForStructWrapper<double>(618);
     private double? doubleField77_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField77 {
       get { return doubleField77_; }
       set {
@@ -763,6 +802,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField15_codec = pb::FieldCodec.ForStructWrapper<double>(122);
     private double? doubleField15_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField15 {
       get { return doubleField15_; }
       set {
@@ -776,6 +816,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field19_codec = pb::FieldCodec.ForStructWrapper<long>(154);
     private long? int64Field19_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field19 {
       get { return int64Field19_; }
       set {
@@ -789,6 +830,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field115_codec = pb::FieldCodec.ForStructWrapper<long>(922);
     private long? int64Field115_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field115 {
       get { return int64Field115_; }
       set {
@@ -802,6 +844,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField116_codec = pb::FieldCodec.ForStructWrapper<double>(930);
     private double? doubleField116_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField116 {
       get { return doubleField116_; }
       set {
@@ -815,6 +858,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field117_codec = pb::FieldCodec.ForStructWrapper<long>(938);
     private long? int64Field117_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field117 {
       get { return int64Field117_; }
       set {
@@ -828,6 +872,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField20_codec = pb::FieldCodec.ForStructWrapper<double>(162);
     private double? doubleField20_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField20 {
       get { return doubleField20_; }
       set {
@@ -841,6 +886,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField21_codec = pb::FieldCodec.ForStructWrapper<double>(170);
     private double? doubleField21_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField21 {
       get { return doubleField21_; }
       set {
@@ -854,6 +900,7 @@
     private static readonly pb::FieldCodec<string> _single_stringField73_codec = pb::FieldCodec.ForClassWrapper<string>(586);
     private string stringField73_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField73 {
       get { return stringField73_; }
       set {
@@ -867,6 +914,7 @@
     private static readonly pb::FieldCodec<string> _single_stringField74_codec = pb::FieldCodec.ForClassWrapper<string>(594);
     private string stringField74_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField74 {
       get { return stringField74_; }
       set {
@@ -880,6 +928,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField22_codec = pb::FieldCodec.ForStructWrapper<double>(178);
     private double? doubleField22_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField22 {
       get { return doubleField22_; }
       set {
@@ -893,6 +942,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField69_codec = pb::FieldCodec.ForStructWrapper<double>(554);
     private double? doubleField69_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField69 {
       get { return doubleField69_; }
       set {
@@ -906,6 +956,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField70_codec = pb::FieldCodec.ForStructWrapper<double>(562);
     private double? doubleField70_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField70 {
       get { return doubleField70_; }
       set {
@@ -919,6 +970,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField71_codec = pb::FieldCodec.ForStructWrapper<double>(570);
     private double? doubleField71_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField71 {
       get { return doubleField71_; }
       set {
@@ -932,6 +984,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField72_codec = pb::FieldCodec.ForStructWrapper<double>(578);
     private double? doubleField72_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField72 {
       get { return doubleField72_; }
       set {
@@ -945,6 +998,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField25_codec = pb::FieldCodec.ForStructWrapper<double>(202);
     private double? doubleField25_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField25 {
       get { return doubleField25_; }
       set {
@@ -958,6 +1012,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field26_codec = pb::FieldCodec.ForStructWrapper<long>(210);
     private long? int64Field26_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field26 {
       get { return int64Field26_; }
       set {
@@ -971,6 +1026,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField68_codec = pb::FieldCodec.ForStructWrapper<double>(546);
     private double? doubleField68_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField68 {
       get { return doubleField68_; }
       set {
@@ -984,6 +1040,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField28_codec = pb::FieldCodec.ForStructWrapper<double>(226);
     private double? doubleField28_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField28 {
       get { return doubleField28_; }
       set {
@@ -997,6 +1054,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField106_codec = pb::FieldCodec.ForStructWrapper<double>(850);
     private double? doubleField106_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField106 {
       get { return doubleField106_; }
       set {
@@ -1010,6 +1068,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField29_codec = pb::FieldCodec.ForStructWrapper<double>(234);
     private double? doubleField29_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField29 {
       get { return doubleField29_; }
       set {
@@ -1023,6 +1082,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField30_codec = pb::FieldCodec.ForStructWrapper<double>(242);
     private double? doubleField30_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField30 {
       get { return doubleField30_; }
       set {
@@ -1036,6 +1096,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField101_codec = pb::FieldCodec.ForStructWrapper<double>(810);
     private double? doubleField101_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField101 {
       get { return doubleField101_; }
       set {
@@ -1049,6 +1110,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField102_codec = pb::FieldCodec.ForStructWrapper<double>(818);
     private double? doubleField102_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField102 {
       get { return doubleField102_; }
       set {
@@ -1062,6 +1124,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField103_codec = pb::FieldCodec.ForStructWrapper<double>(826);
     private double? doubleField103_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField103 {
       get { return doubleField103_; }
       set {
@@ -1075,6 +1138,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField104_codec = pb::FieldCodec.ForStructWrapper<double>(834);
     private double? doubleField104_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField104 {
       get { return doubleField104_; }
       set {
@@ -1088,6 +1152,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField105_codec = pb::FieldCodec.ForStructWrapper<double>(842);
     private double? doubleField105_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField105 {
       get { return doubleField105_; }
       set {
@@ -1101,6 +1166,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField31_codec = pb::FieldCodec.ForStructWrapper<double>(250);
     private double? doubleField31_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField31 {
       get { return doubleField31_; }
       set {
@@ -1114,6 +1180,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field32_codec = pb::FieldCodec.ForStructWrapper<long>(258);
     private long? int64Field32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field32 {
       get { return int64Field32_; }
       set {
@@ -1127,6 +1194,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField75_codec = pb::FieldCodec.ForStructWrapper<double>(602);
     private double? doubleField75_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField75 {
       get { return doubleField75_; }
       set {
@@ -1140,6 +1208,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField129_codec = pb::FieldCodec.ForStructWrapper<double>(1034);
     private double? doubleField129_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField129 {
       get { return doubleField129_; }
       set {
@@ -1152,6 +1221,7 @@
     public const int EnumField80FieldNumber = 80;
     private int enumField80_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int EnumField80 {
       get { return enumField80_; }
       set {
@@ -1163,6 +1233,7 @@
     public const int EnumField81FieldNumber = 81;
     private int enumField81_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int EnumField81 {
       get { return enumField81_; }
       set {
@@ -1175,6 +1246,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field82_codec = pb::FieldCodec.ForStructWrapper<long>(658);
     private long? int64Field82_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field82 {
       get { return int64Field82_; }
       set {
@@ -1187,6 +1259,7 @@
     public const int EnumField83FieldNumber = 83;
     private int enumField83_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int EnumField83 {
       get { return enumField83_; }
       set {
@@ -1199,6 +1272,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field85_codec = pb::FieldCodec.ForStructWrapper<long>(682);
     private long? int64Field85_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field85 {
       get { return int64Field85_; }
       set {
@@ -1212,6 +1286,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field86_codec = pb::FieldCodec.ForStructWrapper<long>(690);
     private long? int64Field86_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field86 {
       get { return int64Field86_; }
       set {
@@ -1225,6 +1300,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field87_codec = pb::FieldCodec.ForStructWrapper<long>(698);
     private long? int64Field87_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field87 {
       get { return int64Field87_; }
       set {
@@ -1238,6 +1314,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field125_codec = pb::FieldCodec.ForStructWrapper<long>(1002);
     private long? int64Field125_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field125 {
       get { return int64Field125_; }
       set {
@@ -1251,6 +1328,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field37_codec = pb::FieldCodec.ForStructWrapper<long>(298);
     private long? int64Field37_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field37 {
       get { return int64Field37_; }
       set {
@@ -1264,6 +1342,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField38_codec = pb::FieldCodec.ForStructWrapper<double>(306);
     private double? doubleField38_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField38 {
       get { return doubleField38_; }
       set {
@@ -1277,6 +1356,7 @@
     private static readonly pb::FieldCodec<long?> _single_interactions_codec = pb::FieldCodec.ForStructWrapper<long>(314);
     private long? interactions_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Interactions {
       get { return interactions_; }
       set {
@@ -1291,6 +1371,7 @@
         = pb::FieldCodec.ForInt32(802);
     private readonly pbc::RepeatedField<int> repeatedIntField100_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedIntField100 {
       get { return repeatedIntField100_; }
     }
@@ -1300,6 +1381,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField40_codec = pb::FieldCodec.ForStructWrapper<double>(322);
     private double? doubleField40_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField40 {
       get { return doubleField40_; }
       set {
@@ -1313,6 +1395,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field41_codec = pb::FieldCodec.ForStructWrapper<long>(330);
     private long? int64Field41_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field41 {
       get { return int64Field41_; }
       set {
@@ -1326,6 +1409,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field126_codec = pb::FieldCodec.ForStructWrapper<long>(1010);
     private long? int64Field126_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field126 {
       get { return int64Field126_; }
       set {
@@ -1339,6 +1423,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field127_codec = pb::FieldCodec.ForStructWrapper<long>(1018);
     private long? int64Field127_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field127 {
       get { return int64Field127_; }
       set {
@@ -1352,6 +1437,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField128_codec = pb::FieldCodec.ForStructWrapper<double>(1026);
     private double? doubleField128_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField128 {
       get { return doubleField128_; }
       set {
@@ -1365,6 +1451,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField109_codec = pb::FieldCodec.ForStructWrapper<double>(874);
     private double? doubleField109_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField109 {
       get { return doubleField109_; }
       set {
@@ -1378,6 +1465,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field110_codec = pb::FieldCodec.ForStructWrapper<long>(882);
     private long? int64Field110_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field110 {
       get { return int64Field110_; }
       set {
@@ -1391,6 +1479,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField111_codec = pb::FieldCodec.ForStructWrapper<double>(890);
     private double? doubleField111_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField111 {
       get { return doubleField111_; }
       set {
@@ -1404,6 +1493,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field112_codec = pb::FieldCodec.ForStructWrapper<long>(898);
     private long? int64Field112_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field112 {
       get { return int64Field112_; }
       set {
@@ -1417,6 +1507,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField113_codec = pb::FieldCodec.ForStructWrapper<double>(906);
     private double? doubleField113_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField113 {
       get { return doubleField113_; }
       set {
@@ -1430,6 +1521,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field114_codec = pb::FieldCodec.ForStructWrapper<long>(914);
     private long? int64Field114_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field114 {
       get { return int64Field114_; }
       set {
@@ -1443,6 +1535,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField42_codec = pb::FieldCodec.ForStructWrapper<double>(338);
     private double? doubleField42_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField42 {
       get { return doubleField42_; }
       set {
@@ -1456,6 +1549,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field43_codec = pb::FieldCodec.ForStructWrapper<long>(346);
     private long? int64Field43_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field43 {
       get { return int64Field43_; }
       set {
@@ -1469,6 +1563,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field44_codec = pb::FieldCodec.ForStructWrapper<long>(354);
     private long? int64Field44_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field44 {
       get { return int64Field44_; }
       set {
@@ -1482,6 +1577,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField45_codec = pb::FieldCodec.ForStructWrapper<double>(362);
     private double? doubleField45_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField45 {
       get { return doubleField45_; }
       set {
@@ -1495,6 +1591,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField46_codec = pb::FieldCodec.ForStructWrapper<double>(370);
     private double? doubleField46_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField46 {
       get { return doubleField46_; }
       set {
@@ -1508,6 +1605,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField78_codec = pb::FieldCodec.ForStructWrapper<double>(626);
     private double? doubleField78_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField78 {
       get { return doubleField78_; }
       set {
@@ -1521,6 +1619,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField88_codec = pb::FieldCodec.ForStructWrapper<double>(706);
     private double? doubleField88_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField88 {
       get { return doubleField88_; }
       set {
@@ -1534,6 +1633,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField47_codec = pb::FieldCodec.ForStructWrapper<double>(378);
     private double? doubleField47_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField47 {
       get { return doubleField47_; }
       set {
@@ -1547,6 +1647,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField89_codec = pb::FieldCodec.ForStructWrapper<double>(714);
     private double? doubleField89_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField89 {
       get { return doubleField89_; }
       set {
@@ -1560,6 +1661,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField48_codec = pb::FieldCodec.ForStructWrapper<double>(386);
     private double? doubleField48_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField48 {
       get { return doubleField48_; }
       set {
@@ -1573,6 +1675,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField49_codec = pb::FieldCodec.ForStructWrapper<double>(394);
     private double? doubleField49_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField49 {
       get { return doubleField49_; }
       set {
@@ -1586,6 +1689,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField50_codec = pb::FieldCodec.ForStructWrapper<double>(402);
     private double? doubleField50_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField50 {
       get { return doubleField50_; }
       set {
@@ -1599,6 +1703,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField90_codec = pb::FieldCodec.ForStructWrapper<double>(722);
     private double? doubleField90_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField90 {
       get { return doubleField90_; }
       set {
@@ -1612,6 +1717,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField51_codec = pb::FieldCodec.ForStructWrapper<double>(410);
     private double? doubleField51_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField51 {
       get { return doubleField51_; }
       set {
@@ -1625,6 +1731,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField91_codec = pb::FieldCodec.ForStructWrapper<double>(730);
     private double? doubleField91_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField91 {
       get { return doubleField91_; }
       set {
@@ -1638,6 +1745,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField92_codec = pb::FieldCodec.ForStructWrapper<double>(738);
     private double? doubleField92_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField92 {
       get { return doubleField92_; }
       set {
@@ -1651,6 +1759,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field107_codec = pb::FieldCodec.ForStructWrapper<long>(858);
     private long? int64Field107_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field107 {
       get { return int64Field107_; }
       set {
@@ -1664,6 +1773,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField93_codec = pb::FieldCodec.ForStructWrapper<double>(746);
     private double? doubleField93_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField93 {
       get { return doubleField93_; }
       set {
@@ -1677,6 +1787,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField108_codec = pb::FieldCodec.ForStructWrapper<double>(866);
     private double? doubleField108_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField108 {
       get { return doubleField108_; }
       set {
@@ -1690,6 +1801,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField52_codec = pb::FieldCodec.ForStructWrapper<double>(418);
     private double? doubleField52_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField52 {
       get { return doubleField52_; }
       set {
@@ -1703,6 +1815,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField53_codec = pb::FieldCodec.ForStructWrapper<double>(426);
     private double? doubleField53_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField53 {
       get { return doubleField53_; }
       set {
@@ -1716,6 +1829,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField94_codec = pb::FieldCodec.ForStructWrapper<double>(754);
     private double? doubleField94_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField94 {
       get { return doubleField94_; }
       set {
@@ -1729,6 +1843,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField54_codec = pb::FieldCodec.ForStructWrapper<double>(434);
     private double? doubleField54_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField54 {
       get { return doubleField54_; }
       set {
@@ -1742,6 +1857,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField55_codec = pb::FieldCodec.ForStructWrapper<double>(442);
     private double? doubleField55_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField55 {
       get { return doubleField55_; }
       set {
@@ -1755,6 +1871,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField56_codec = pb::FieldCodec.ForStructWrapper<double>(450);
     private double? doubleField56_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField56 {
       get { return doubleField56_; }
       set {
@@ -1768,6 +1885,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField57_codec = pb::FieldCodec.ForStructWrapper<double>(458);
     private double? doubleField57_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField57 {
       get { return doubleField57_; }
       set {
@@ -1781,6 +1899,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField58_codec = pb::FieldCodec.ForStructWrapper<double>(466);
     private double? doubleField58_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField58 {
       get { return doubleField58_; }
       set {
@@ -1794,6 +1913,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field59_codec = pb::FieldCodec.ForStructWrapper<long>(474);
     private long? int64Field59_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field59 {
       get { return int64Field59_; }
       set {
@@ -1807,6 +1927,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field60_codec = pb::FieldCodec.ForStructWrapper<long>(482);
     private long? int64Field60_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field60 {
       get { return int64Field60_; }
       set {
@@ -1816,11 +1937,13 @@
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ManyWrapperFieldsMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ManyWrapperFieldsMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1943,6 +2066,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (doubleField95_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField95);
@@ -2063,12 +2187,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (doubleField1_ != null) {
         _single_doubleField1_codec.WriteTagAndValue(output, DoubleField1);
       }
@@ -2406,9 +2535,355 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (doubleField1_ != null) {
+        _single_doubleField1_codec.WriteTagAndValue(ref output, DoubleField1);
+      }
+      if (int64Field2_ != null) {
+        _single_int64Field2_codec.WriteTagAndValue(ref output, Int64Field2);
+      }
+      if (int64Field3_ != null) {
+        _single_int64Field3_codec.WriteTagAndValue(ref output, Int64Field3);
+      }
+      if (int64Field4_ != null) {
+        _single_int64Field4_codec.WriteTagAndValue(ref output, Int64Field4);
+      }
+      if (doubleField7_ != null) {
+        _single_doubleField7_codec.WriteTagAndValue(ref output, DoubleField7);
+      }
+      if (doubleField8_ != null) {
+        _single_doubleField8_codec.WriteTagAndValue(ref output, DoubleField8);
+      }
+      if (doubleField9_ != null) {
+        _single_doubleField9_codec.WriteTagAndValue(ref output, DoubleField9);
+      }
+      if (doubleField10_ != null) {
+        _single_doubleField10_codec.WriteTagAndValue(ref output, DoubleField10);
+      }
+      if (doubleField11_ != null) {
+        _single_doubleField11_codec.WriteTagAndValue(ref output, DoubleField11);
+      }
+      if (doubleField14_ != null) {
+        _single_doubleField14_codec.WriteTagAndValue(ref output, DoubleField14);
+      }
+      if (doubleField15_ != null) {
+        _single_doubleField15_codec.WriteTagAndValue(ref output, DoubleField15);
+      }
+      if (int64Field19_ != null) {
+        _single_int64Field19_codec.WriteTagAndValue(ref output, Int64Field19);
+      }
+      if (doubleField20_ != null) {
+        _single_doubleField20_codec.WriteTagAndValue(ref output, DoubleField20);
+      }
+      if (doubleField21_ != null) {
+        _single_doubleField21_codec.WriteTagAndValue(ref output, DoubleField21);
+      }
+      if (doubleField22_ != null) {
+        _single_doubleField22_codec.WriteTagAndValue(ref output, DoubleField22);
+      }
+      if (doubleField25_ != null) {
+        _single_doubleField25_codec.WriteTagAndValue(ref output, DoubleField25);
+      }
+      if (int64Field26_ != null) {
+        _single_int64Field26_codec.WriteTagAndValue(ref output, Int64Field26);
+      }
+      if (doubleField28_ != null) {
+        _single_doubleField28_codec.WriteTagAndValue(ref output, DoubleField28);
+      }
+      if (doubleField29_ != null) {
+        _single_doubleField29_codec.WriteTagAndValue(ref output, DoubleField29);
+      }
+      if (doubleField30_ != null) {
+        _single_doubleField30_codec.WriteTagAndValue(ref output, DoubleField30);
+      }
+      if (doubleField31_ != null) {
+        _single_doubleField31_codec.WriteTagAndValue(ref output, DoubleField31);
+      }
+      if (int64Field32_ != null) {
+        _single_int64Field32_codec.WriteTagAndValue(ref output, Int64Field32);
+      }
+      if (int64Field37_ != null) {
+        _single_int64Field37_codec.WriteTagAndValue(ref output, Int64Field37);
+      }
+      if (doubleField38_ != null) {
+        _single_doubleField38_codec.WriteTagAndValue(ref output, DoubleField38);
+      }
+      if (interactions_ != null) {
+        _single_interactions_codec.WriteTagAndValue(ref output, Interactions);
+      }
+      if (doubleField40_ != null) {
+        _single_doubleField40_codec.WriteTagAndValue(ref output, DoubleField40);
+      }
+      if (int64Field41_ != null) {
+        _single_int64Field41_codec.WriteTagAndValue(ref output, Int64Field41);
+      }
+      if (doubleField42_ != null) {
+        _single_doubleField42_codec.WriteTagAndValue(ref output, DoubleField42);
+      }
+      if (int64Field43_ != null) {
+        _single_int64Field43_codec.WriteTagAndValue(ref output, Int64Field43);
+      }
+      if (int64Field44_ != null) {
+        _single_int64Field44_codec.WriteTagAndValue(ref output, Int64Field44);
+      }
+      if (doubleField45_ != null) {
+        _single_doubleField45_codec.WriteTagAndValue(ref output, DoubleField45);
+      }
+      if (doubleField46_ != null) {
+        _single_doubleField46_codec.WriteTagAndValue(ref output, DoubleField46);
+      }
+      if (doubleField47_ != null) {
+        _single_doubleField47_codec.WriteTagAndValue(ref output, DoubleField47);
+      }
+      if (doubleField48_ != null) {
+        _single_doubleField48_codec.WriteTagAndValue(ref output, DoubleField48);
+      }
+      if (doubleField49_ != null) {
+        _single_doubleField49_codec.WriteTagAndValue(ref output, DoubleField49);
+      }
+      if (doubleField50_ != null) {
+        _single_doubleField50_codec.WriteTagAndValue(ref output, DoubleField50);
+      }
+      if (doubleField51_ != null) {
+        _single_doubleField51_codec.WriteTagAndValue(ref output, DoubleField51);
+      }
+      if (doubleField52_ != null) {
+        _single_doubleField52_codec.WriteTagAndValue(ref output, DoubleField52);
+      }
+      if (doubleField53_ != null) {
+        _single_doubleField53_codec.WriteTagAndValue(ref output, DoubleField53);
+      }
+      if (doubleField54_ != null) {
+        _single_doubleField54_codec.WriteTagAndValue(ref output, DoubleField54);
+      }
+      if (doubleField55_ != null) {
+        _single_doubleField55_codec.WriteTagAndValue(ref output, DoubleField55);
+      }
+      if (doubleField56_ != null) {
+        _single_doubleField56_codec.WriteTagAndValue(ref output, DoubleField56);
+      }
+      if (doubleField57_ != null) {
+        _single_doubleField57_codec.WriteTagAndValue(ref output, DoubleField57);
+      }
+      if (doubleField58_ != null) {
+        _single_doubleField58_codec.WriteTagAndValue(ref output, DoubleField58);
+      }
+      if (int64Field59_ != null) {
+        _single_int64Field59_codec.WriteTagAndValue(ref output, Int64Field59);
+      }
+      if (int64Field60_ != null) {
+        _single_int64Field60_codec.WriteTagAndValue(ref output, Int64Field60);
+      }
+      if (doubleField62_ != null) {
+        _single_doubleField62_codec.WriteTagAndValue(ref output, DoubleField62);
+      }
+      if (doubleField65_ != null) {
+        _single_doubleField65_codec.WriteTagAndValue(ref output, DoubleField65);
+      }
+      if (doubleField66_ != null) {
+        _single_doubleField66_codec.WriteTagAndValue(ref output, DoubleField66);
+      }
+      if (doubleField67_ != null) {
+        _single_doubleField67_codec.WriteTagAndValue(ref output, DoubleField67);
+      }
+      if (doubleField68_ != null) {
+        _single_doubleField68_codec.WriteTagAndValue(ref output, DoubleField68);
+      }
+      if (doubleField69_ != null) {
+        _single_doubleField69_codec.WriteTagAndValue(ref output, DoubleField69);
+      }
+      if (doubleField70_ != null) {
+        _single_doubleField70_codec.WriteTagAndValue(ref output, DoubleField70);
+      }
+      if (doubleField71_ != null) {
+        _single_doubleField71_codec.WriteTagAndValue(ref output, DoubleField71);
+      }
+      if (doubleField72_ != null) {
+        _single_doubleField72_codec.WriteTagAndValue(ref output, DoubleField72);
+      }
+      if (stringField73_ != null) {
+        _single_stringField73_codec.WriteTagAndValue(ref output, StringField73);
+      }
+      if (stringField74_ != null) {
+        _single_stringField74_codec.WriteTagAndValue(ref output, StringField74);
+      }
+      if (doubleField75_ != null) {
+        _single_doubleField75_codec.WriteTagAndValue(ref output, DoubleField75);
+      }
+      if (doubleField77_ != null) {
+        _single_doubleField77_codec.WriteTagAndValue(ref output, DoubleField77);
+      }
+      if (doubleField78_ != null) {
+        _single_doubleField78_codec.WriteTagAndValue(ref output, DoubleField78);
+      }
+      if (doubleField79_ != null) {
+        _single_doubleField79_codec.WriteTagAndValue(ref output, DoubleField79);
+      }
+      if (EnumField80 != 0) {
+        output.WriteRawTag(128, 5);
+        output.WriteInt32(EnumField80);
+      }
+      if (EnumField81 != 0) {
+        output.WriteRawTag(136, 5);
+        output.WriteInt32(EnumField81);
+      }
+      if (int64Field82_ != null) {
+        _single_int64Field82_codec.WriteTagAndValue(ref output, Int64Field82);
+      }
+      if (EnumField83 != 0) {
+        output.WriteRawTag(152, 5);
+        output.WriteInt32(EnumField83);
+      }
+      if (doubleField84_ != null) {
+        _single_doubleField84_codec.WriteTagAndValue(ref output, DoubleField84);
+      }
+      if (int64Field85_ != null) {
+        _single_int64Field85_codec.WriteTagAndValue(ref output, Int64Field85);
+      }
+      if (int64Field86_ != null) {
+        _single_int64Field86_codec.WriteTagAndValue(ref output, Int64Field86);
+      }
+      if (int64Field87_ != null) {
+        _single_int64Field87_codec.WriteTagAndValue(ref output, Int64Field87);
+      }
+      if (doubleField88_ != null) {
+        _single_doubleField88_codec.WriteTagAndValue(ref output, DoubleField88);
+      }
+      if (doubleField89_ != null) {
+        _single_doubleField89_codec.WriteTagAndValue(ref output, DoubleField89);
+      }
+      if (doubleField90_ != null) {
+        _single_doubleField90_codec.WriteTagAndValue(ref output, DoubleField90);
+      }
+      if (doubleField91_ != null) {
+        _single_doubleField91_codec.WriteTagAndValue(ref output, DoubleField91);
+      }
+      if (doubleField92_ != null) {
+        _single_doubleField92_codec.WriteTagAndValue(ref output, DoubleField92);
+      }
+      if (doubleField93_ != null) {
+        _single_doubleField93_codec.WriteTagAndValue(ref output, DoubleField93);
+      }
+      if (doubleField94_ != null) {
+        _single_doubleField94_codec.WriteTagAndValue(ref output, DoubleField94);
+      }
+      if (doubleField95_ != null) {
+        _single_doubleField95_codec.WriteTagAndValue(ref output, DoubleField95);
+      }
+      if (doubleField96_ != null) {
+        _single_doubleField96_codec.WriteTagAndValue(ref output, DoubleField96);
+      }
+      if (doubleField97_ != null) {
+        _single_doubleField97_codec.WriteTagAndValue(ref output, DoubleField97);
+      }
+      if (doubleField98_ != null) {
+        _single_doubleField98_codec.WriteTagAndValue(ref output, DoubleField98);
+      }
+      if (doubleField99_ != null) {
+        _single_doubleField99_codec.WriteTagAndValue(ref output, DoubleField99);
+      }
+      repeatedIntField100_.WriteTo(ref output, _repeated_repeatedIntField100_codec);
+      if (doubleField101_ != null) {
+        _single_doubleField101_codec.WriteTagAndValue(ref output, DoubleField101);
+      }
+      if (doubleField102_ != null) {
+        _single_doubleField102_codec.WriteTagAndValue(ref output, DoubleField102);
+      }
+      if (doubleField103_ != null) {
+        _single_doubleField103_codec.WriteTagAndValue(ref output, DoubleField103);
+      }
+      if (doubleField104_ != null) {
+        _single_doubleField104_codec.WriteTagAndValue(ref output, DoubleField104);
+      }
+      if (doubleField105_ != null) {
+        _single_doubleField105_codec.WriteTagAndValue(ref output, DoubleField105);
+      }
+      if (doubleField106_ != null) {
+        _single_doubleField106_codec.WriteTagAndValue(ref output, DoubleField106);
+      }
+      if (int64Field107_ != null) {
+        _single_int64Field107_codec.WriteTagAndValue(ref output, Int64Field107);
+      }
+      if (doubleField108_ != null) {
+        _single_doubleField108_codec.WriteTagAndValue(ref output, DoubleField108);
+      }
+      if (doubleField109_ != null) {
+        _single_doubleField109_codec.WriteTagAndValue(ref output, DoubleField109);
+      }
+      if (int64Field110_ != null) {
+        _single_int64Field110_codec.WriteTagAndValue(ref output, Int64Field110);
+      }
+      if (doubleField111_ != null) {
+        _single_doubleField111_codec.WriteTagAndValue(ref output, DoubleField111);
+      }
+      if (int64Field112_ != null) {
+        _single_int64Field112_codec.WriteTagAndValue(ref output, Int64Field112);
+      }
+      if (doubleField113_ != null) {
+        _single_doubleField113_codec.WriteTagAndValue(ref output, DoubleField113);
+      }
+      if (int64Field114_ != null) {
+        _single_int64Field114_codec.WriteTagAndValue(ref output, Int64Field114);
+      }
+      if (int64Field115_ != null) {
+        _single_int64Field115_codec.WriteTagAndValue(ref output, Int64Field115);
+      }
+      if (doubleField116_ != null) {
+        _single_doubleField116_codec.WriteTagAndValue(ref output, DoubleField116);
+      }
+      if (int64Field117_ != null) {
+        _single_int64Field117_codec.WriteTagAndValue(ref output, Int64Field117);
+      }
+      if (doubleField118_ != null) {
+        _single_doubleField118_codec.WriteTagAndValue(ref output, DoubleField118);
+      }
+      if (doubleField119_ != null) {
+        _single_doubleField119_codec.WriteTagAndValue(ref output, DoubleField119);
+      }
+      if (doubleField120_ != null) {
+        _single_doubleField120_codec.WriteTagAndValue(ref output, DoubleField120);
+      }
+      if (doubleField121_ != null) {
+        _single_doubleField121_codec.WriteTagAndValue(ref output, DoubleField121);
+      }
+      if (doubleField122_ != null) {
+        _single_doubleField122_codec.WriteTagAndValue(ref output, DoubleField122);
+      }
+      if (doubleField123_ != null) {
+        _single_doubleField123_codec.WriteTagAndValue(ref output, DoubleField123);
+      }
+      if (doubleField124_ != null) {
+        _single_doubleField124_codec.WriteTagAndValue(ref output, DoubleField124);
+      }
+      if (int64Field125_ != null) {
+        _single_int64Field125_codec.WriteTagAndValue(ref output, Int64Field125);
+      }
+      if (int64Field126_ != null) {
+        _single_int64Field126_codec.WriteTagAndValue(ref output, Int64Field126);
+      }
+      if (int64Field127_ != null) {
+        _single_int64Field127_codec.WriteTagAndValue(ref output, Int64Field127);
+      }
+      if (doubleField128_ != null) {
+        _single_doubleField128_codec.WriteTagAndValue(ref output, DoubleField128);
+      }
+      if (doubleField129_ != null) {
+        _single_doubleField129_codec.WriteTagAndValue(ref output, DoubleField129);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (doubleField95_ != null) {
@@ -2749,6 +3224,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ManyWrapperFieldsMessage other) {
       if (other == null) {
         return;
@@ -3302,7 +3778,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4077,31 +4557,821 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            double? value = _single_doubleField1_codec.Read(ref input);
+            if (doubleField1_ == null || value != 0D) {
+              DoubleField1 = value;
+            }
+            break;
+          }
+          case 18: {
+            long? value = _single_int64Field2_codec.Read(ref input);
+            if (int64Field2_ == null || value != 0L) {
+              Int64Field2 = value;
+            }
+            break;
+          }
+          case 26: {
+            long? value = _single_int64Field3_codec.Read(ref input);
+            if (int64Field3_ == null || value != 0L) {
+              Int64Field3 = value;
+            }
+            break;
+          }
+          case 34: {
+            long? value = _single_int64Field4_codec.Read(ref input);
+            if (int64Field4_ == null || value != 0L) {
+              Int64Field4 = value;
+            }
+            break;
+          }
+          case 58: {
+            double? value = _single_doubleField7_codec.Read(ref input);
+            if (doubleField7_ == null || value != 0D) {
+              DoubleField7 = value;
+            }
+            break;
+          }
+          case 66: {
+            double? value = _single_doubleField8_codec.Read(ref input);
+            if (doubleField8_ == null || value != 0D) {
+              DoubleField8 = value;
+            }
+            break;
+          }
+          case 74: {
+            double? value = _single_doubleField9_codec.Read(ref input);
+            if (doubleField9_ == null || value != 0D) {
+              DoubleField9 = value;
+            }
+            break;
+          }
+          case 82: {
+            double? value = _single_doubleField10_codec.Read(ref input);
+            if (doubleField10_ == null || value != 0D) {
+              DoubleField10 = value;
+            }
+            break;
+          }
+          case 90: {
+            double? value = _single_doubleField11_codec.Read(ref input);
+            if (doubleField11_ == null || value != 0D) {
+              DoubleField11 = value;
+            }
+            break;
+          }
+          case 114: {
+            double? value = _single_doubleField14_codec.Read(ref input);
+            if (doubleField14_ == null || value != 0D) {
+              DoubleField14 = value;
+            }
+            break;
+          }
+          case 122: {
+            double? value = _single_doubleField15_codec.Read(ref input);
+            if (doubleField15_ == null || value != 0D) {
+              DoubleField15 = value;
+            }
+            break;
+          }
+          case 154: {
+            long? value = _single_int64Field19_codec.Read(ref input);
+            if (int64Field19_ == null || value != 0L) {
+              Int64Field19 = value;
+            }
+            break;
+          }
+          case 162: {
+            double? value = _single_doubleField20_codec.Read(ref input);
+            if (doubleField20_ == null || value != 0D) {
+              DoubleField20 = value;
+            }
+            break;
+          }
+          case 170: {
+            double? value = _single_doubleField21_codec.Read(ref input);
+            if (doubleField21_ == null || value != 0D) {
+              DoubleField21 = value;
+            }
+            break;
+          }
+          case 178: {
+            double? value = _single_doubleField22_codec.Read(ref input);
+            if (doubleField22_ == null || value != 0D) {
+              DoubleField22 = value;
+            }
+            break;
+          }
+          case 202: {
+            double? value = _single_doubleField25_codec.Read(ref input);
+            if (doubleField25_ == null || value != 0D) {
+              DoubleField25 = value;
+            }
+            break;
+          }
+          case 210: {
+            long? value = _single_int64Field26_codec.Read(ref input);
+            if (int64Field26_ == null || value != 0L) {
+              Int64Field26 = value;
+            }
+            break;
+          }
+          case 226: {
+            double? value = _single_doubleField28_codec.Read(ref input);
+            if (doubleField28_ == null || value != 0D) {
+              DoubleField28 = value;
+            }
+            break;
+          }
+          case 234: {
+            double? value = _single_doubleField29_codec.Read(ref input);
+            if (doubleField29_ == null || value != 0D) {
+              DoubleField29 = value;
+            }
+            break;
+          }
+          case 242: {
+            double? value = _single_doubleField30_codec.Read(ref input);
+            if (doubleField30_ == null || value != 0D) {
+              DoubleField30 = value;
+            }
+            break;
+          }
+          case 250: {
+            double? value = _single_doubleField31_codec.Read(ref input);
+            if (doubleField31_ == null || value != 0D) {
+              DoubleField31 = value;
+            }
+            break;
+          }
+          case 258: {
+            long? value = _single_int64Field32_codec.Read(ref input);
+            if (int64Field32_ == null || value != 0L) {
+              Int64Field32 = value;
+            }
+            break;
+          }
+          case 298: {
+            long? value = _single_int64Field37_codec.Read(ref input);
+            if (int64Field37_ == null || value != 0L) {
+              Int64Field37 = value;
+            }
+            break;
+          }
+          case 306: {
+            double? value = _single_doubleField38_codec.Read(ref input);
+            if (doubleField38_ == null || value != 0D) {
+              DoubleField38 = value;
+            }
+            break;
+          }
+          case 314: {
+            long? value = _single_interactions_codec.Read(ref input);
+            if (interactions_ == null || value != 0L) {
+              Interactions = value;
+            }
+            break;
+          }
+          case 322: {
+            double? value = _single_doubleField40_codec.Read(ref input);
+            if (doubleField40_ == null || value != 0D) {
+              DoubleField40 = value;
+            }
+            break;
+          }
+          case 330: {
+            long? value = _single_int64Field41_codec.Read(ref input);
+            if (int64Field41_ == null || value != 0L) {
+              Int64Field41 = value;
+            }
+            break;
+          }
+          case 338: {
+            double? value = _single_doubleField42_codec.Read(ref input);
+            if (doubleField42_ == null || value != 0D) {
+              DoubleField42 = value;
+            }
+            break;
+          }
+          case 346: {
+            long? value = _single_int64Field43_codec.Read(ref input);
+            if (int64Field43_ == null || value != 0L) {
+              Int64Field43 = value;
+            }
+            break;
+          }
+          case 354: {
+            long? value = _single_int64Field44_codec.Read(ref input);
+            if (int64Field44_ == null || value != 0L) {
+              Int64Field44 = value;
+            }
+            break;
+          }
+          case 362: {
+            double? value = _single_doubleField45_codec.Read(ref input);
+            if (doubleField45_ == null || value != 0D) {
+              DoubleField45 = value;
+            }
+            break;
+          }
+          case 370: {
+            double? value = _single_doubleField46_codec.Read(ref input);
+            if (doubleField46_ == null || value != 0D) {
+              DoubleField46 = value;
+            }
+            break;
+          }
+          case 378: {
+            double? value = _single_doubleField47_codec.Read(ref input);
+            if (doubleField47_ == null || value != 0D) {
+              DoubleField47 = value;
+            }
+            break;
+          }
+          case 386: {
+            double? value = _single_doubleField48_codec.Read(ref input);
+            if (doubleField48_ == null || value != 0D) {
+              DoubleField48 = value;
+            }
+            break;
+          }
+          case 394: {
+            double? value = _single_doubleField49_codec.Read(ref input);
+            if (doubleField49_ == null || value != 0D) {
+              DoubleField49 = value;
+            }
+            break;
+          }
+          case 402: {
+            double? value = _single_doubleField50_codec.Read(ref input);
+            if (doubleField50_ == null || value != 0D) {
+              DoubleField50 = value;
+            }
+            break;
+          }
+          case 410: {
+            double? value = _single_doubleField51_codec.Read(ref input);
+            if (doubleField51_ == null || value != 0D) {
+              DoubleField51 = value;
+            }
+            break;
+          }
+          case 418: {
+            double? value = _single_doubleField52_codec.Read(ref input);
+            if (doubleField52_ == null || value != 0D) {
+              DoubleField52 = value;
+            }
+            break;
+          }
+          case 426: {
+            double? value = _single_doubleField53_codec.Read(ref input);
+            if (doubleField53_ == null || value != 0D) {
+              DoubleField53 = value;
+            }
+            break;
+          }
+          case 434: {
+            double? value = _single_doubleField54_codec.Read(ref input);
+            if (doubleField54_ == null || value != 0D) {
+              DoubleField54 = value;
+            }
+            break;
+          }
+          case 442: {
+            double? value = _single_doubleField55_codec.Read(ref input);
+            if (doubleField55_ == null || value != 0D) {
+              DoubleField55 = value;
+            }
+            break;
+          }
+          case 450: {
+            double? value = _single_doubleField56_codec.Read(ref input);
+            if (doubleField56_ == null || value != 0D) {
+              DoubleField56 = value;
+            }
+            break;
+          }
+          case 458: {
+            double? value = _single_doubleField57_codec.Read(ref input);
+            if (doubleField57_ == null || value != 0D) {
+              DoubleField57 = value;
+            }
+            break;
+          }
+          case 466: {
+            double? value = _single_doubleField58_codec.Read(ref input);
+            if (doubleField58_ == null || value != 0D) {
+              DoubleField58 = value;
+            }
+            break;
+          }
+          case 474: {
+            long? value = _single_int64Field59_codec.Read(ref input);
+            if (int64Field59_ == null || value != 0L) {
+              Int64Field59 = value;
+            }
+            break;
+          }
+          case 482: {
+            long? value = _single_int64Field60_codec.Read(ref input);
+            if (int64Field60_ == null || value != 0L) {
+              Int64Field60 = value;
+            }
+            break;
+          }
+          case 498: {
+            double? value = _single_doubleField62_codec.Read(ref input);
+            if (doubleField62_ == null || value != 0D) {
+              DoubleField62 = value;
+            }
+            break;
+          }
+          case 522: {
+            double? value = _single_doubleField65_codec.Read(ref input);
+            if (doubleField65_ == null || value != 0D) {
+              DoubleField65 = value;
+            }
+            break;
+          }
+          case 530: {
+            double? value = _single_doubleField66_codec.Read(ref input);
+            if (doubleField66_ == null || value != 0D) {
+              DoubleField66 = value;
+            }
+            break;
+          }
+          case 538: {
+            double? value = _single_doubleField67_codec.Read(ref input);
+            if (doubleField67_ == null || value != 0D) {
+              DoubleField67 = value;
+            }
+            break;
+          }
+          case 546: {
+            double? value = _single_doubleField68_codec.Read(ref input);
+            if (doubleField68_ == null || value != 0D) {
+              DoubleField68 = value;
+            }
+            break;
+          }
+          case 554: {
+            double? value = _single_doubleField69_codec.Read(ref input);
+            if (doubleField69_ == null || value != 0D) {
+              DoubleField69 = value;
+            }
+            break;
+          }
+          case 562: {
+            double? value = _single_doubleField70_codec.Read(ref input);
+            if (doubleField70_ == null || value != 0D) {
+              DoubleField70 = value;
+            }
+            break;
+          }
+          case 570: {
+            double? value = _single_doubleField71_codec.Read(ref input);
+            if (doubleField71_ == null || value != 0D) {
+              DoubleField71 = value;
+            }
+            break;
+          }
+          case 578: {
+            double? value = _single_doubleField72_codec.Read(ref input);
+            if (doubleField72_ == null || value != 0D) {
+              DoubleField72 = value;
+            }
+            break;
+          }
+          case 586: {
+            string value = _single_stringField73_codec.Read(ref input);
+            if (stringField73_ == null || value != "") {
+              StringField73 = value;
+            }
+            break;
+          }
+          case 594: {
+            string value = _single_stringField74_codec.Read(ref input);
+            if (stringField74_ == null || value != "") {
+              StringField74 = value;
+            }
+            break;
+          }
+          case 602: {
+            double? value = _single_doubleField75_codec.Read(ref input);
+            if (doubleField75_ == null || value != 0D) {
+              DoubleField75 = value;
+            }
+            break;
+          }
+          case 618: {
+            double? value = _single_doubleField77_codec.Read(ref input);
+            if (doubleField77_ == null || value != 0D) {
+              DoubleField77 = value;
+            }
+            break;
+          }
+          case 626: {
+            double? value = _single_doubleField78_codec.Read(ref input);
+            if (doubleField78_ == null || value != 0D) {
+              DoubleField78 = value;
+            }
+            break;
+          }
+          case 634: {
+            double? value = _single_doubleField79_codec.Read(ref input);
+            if (doubleField79_ == null || value != 0D) {
+              DoubleField79 = value;
+            }
+            break;
+          }
+          case 640: {
+            EnumField80 = input.ReadInt32();
+            break;
+          }
+          case 648: {
+            EnumField81 = input.ReadInt32();
+            break;
+          }
+          case 658: {
+            long? value = _single_int64Field82_codec.Read(ref input);
+            if (int64Field82_ == null || value != 0L) {
+              Int64Field82 = value;
+            }
+            break;
+          }
+          case 664: {
+            EnumField83 = input.ReadInt32();
+            break;
+          }
+          case 674: {
+            double? value = _single_doubleField84_codec.Read(ref input);
+            if (doubleField84_ == null || value != 0D) {
+              DoubleField84 = value;
+            }
+            break;
+          }
+          case 682: {
+            long? value = _single_int64Field85_codec.Read(ref input);
+            if (int64Field85_ == null || value != 0L) {
+              Int64Field85 = value;
+            }
+            break;
+          }
+          case 690: {
+            long? value = _single_int64Field86_codec.Read(ref input);
+            if (int64Field86_ == null || value != 0L) {
+              Int64Field86 = value;
+            }
+            break;
+          }
+          case 698: {
+            long? value = _single_int64Field87_codec.Read(ref input);
+            if (int64Field87_ == null || value != 0L) {
+              Int64Field87 = value;
+            }
+            break;
+          }
+          case 706: {
+            double? value = _single_doubleField88_codec.Read(ref input);
+            if (doubleField88_ == null || value != 0D) {
+              DoubleField88 = value;
+            }
+            break;
+          }
+          case 714: {
+            double? value = _single_doubleField89_codec.Read(ref input);
+            if (doubleField89_ == null || value != 0D) {
+              DoubleField89 = value;
+            }
+            break;
+          }
+          case 722: {
+            double? value = _single_doubleField90_codec.Read(ref input);
+            if (doubleField90_ == null || value != 0D) {
+              DoubleField90 = value;
+            }
+            break;
+          }
+          case 730: {
+            double? value = _single_doubleField91_codec.Read(ref input);
+            if (doubleField91_ == null || value != 0D) {
+              DoubleField91 = value;
+            }
+            break;
+          }
+          case 738: {
+            double? value = _single_doubleField92_codec.Read(ref input);
+            if (doubleField92_ == null || value != 0D) {
+              DoubleField92 = value;
+            }
+            break;
+          }
+          case 746: {
+            double? value = _single_doubleField93_codec.Read(ref input);
+            if (doubleField93_ == null || value != 0D) {
+              DoubleField93 = value;
+            }
+            break;
+          }
+          case 754: {
+            double? value = _single_doubleField94_codec.Read(ref input);
+            if (doubleField94_ == null || value != 0D) {
+              DoubleField94 = value;
+            }
+            break;
+          }
+          case 762: {
+            double? value = _single_doubleField95_codec.Read(ref input);
+            if (doubleField95_ == null || value != 0D) {
+              DoubleField95 = value;
+            }
+            break;
+          }
+          case 770: {
+            double? value = _single_doubleField96_codec.Read(ref input);
+            if (doubleField96_ == null || value != 0D) {
+              DoubleField96 = value;
+            }
+            break;
+          }
+          case 778: {
+            double? value = _single_doubleField97_codec.Read(ref input);
+            if (doubleField97_ == null || value != 0D) {
+              DoubleField97 = value;
+            }
+            break;
+          }
+          case 786: {
+            double? value = _single_doubleField98_codec.Read(ref input);
+            if (doubleField98_ == null || value != 0D) {
+              DoubleField98 = value;
+            }
+            break;
+          }
+          case 794: {
+            double? value = _single_doubleField99_codec.Read(ref input);
+            if (doubleField99_ == null || value != 0D) {
+              DoubleField99 = value;
+            }
+            break;
+          }
+          case 802:
+          case 800: {
+            repeatedIntField100_.AddEntriesFrom(ref input, _repeated_repeatedIntField100_codec);
+            break;
+          }
+          case 810: {
+            double? value = _single_doubleField101_codec.Read(ref input);
+            if (doubleField101_ == null || value != 0D) {
+              DoubleField101 = value;
+            }
+            break;
+          }
+          case 818: {
+            double? value = _single_doubleField102_codec.Read(ref input);
+            if (doubleField102_ == null || value != 0D) {
+              DoubleField102 = value;
+            }
+            break;
+          }
+          case 826: {
+            double? value = _single_doubleField103_codec.Read(ref input);
+            if (doubleField103_ == null || value != 0D) {
+              DoubleField103 = value;
+            }
+            break;
+          }
+          case 834: {
+            double? value = _single_doubleField104_codec.Read(ref input);
+            if (doubleField104_ == null || value != 0D) {
+              DoubleField104 = value;
+            }
+            break;
+          }
+          case 842: {
+            double? value = _single_doubleField105_codec.Read(ref input);
+            if (doubleField105_ == null || value != 0D) {
+              DoubleField105 = value;
+            }
+            break;
+          }
+          case 850: {
+            double? value = _single_doubleField106_codec.Read(ref input);
+            if (doubleField106_ == null || value != 0D) {
+              DoubleField106 = value;
+            }
+            break;
+          }
+          case 858: {
+            long? value = _single_int64Field107_codec.Read(ref input);
+            if (int64Field107_ == null || value != 0L) {
+              Int64Field107 = value;
+            }
+            break;
+          }
+          case 866: {
+            double? value = _single_doubleField108_codec.Read(ref input);
+            if (doubleField108_ == null || value != 0D) {
+              DoubleField108 = value;
+            }
+            break;
+          }
+          case 874: {
+            double? value = _single_doubleField109_codec.Read(ref input);
+            if (doubleField109_ == null || value != 0D) {
+              DoubleField109 = value;
+            }
+            break;
+          }
+          case 882: {
+            long? value = _single_int64Field110_codec.Read(ref input);
+            if (int64Field110_ == null || value != 0L) {
+              Int64Field110 = value;
+            }
+            break;
+          }
+          case 890: {
+            double? value = _single_doubleField111_codec.Read(ref input);
+            if (doubleField111_ == null || value != 0D) {
+              DoubleField111 = value;
+            }
+            break;
+          }
+          case 898: {
+            long? value = _single_int64Field112_codec.Read(ref input);
+            if (int64Field112_ == null || value != 0L) {
+              Int64Field112 = value;
+            }
+            break;
+          }
+          case 906: {
+            double? value = _single_doubleField113_codec.Read(ref input);
+            if (doubleField113_ == null || value != 0D) {
+              DoubleField113 = value;
+            }
+            break;
+          }
+          case 914: {
+            long? value = _single_int64Field114_codec.Read(ref input);
+            if (int64Field114_ == null || value != 0L) {
+              Int64Field114 = value;
+            }
+            break;
+          }
+          case 922: {
+            long? value = _single_int64Field115_codec.Read(ref input);
+            if (int64Field115_ == null || value != 0L) {
+              Int64Field115 = value;
+            }
+            break;
+          }
+          case 930: {
+            double? value = _single_doubleField116_codec.Read(ref input);
+            if (doubleField116_ == null || value != 0D) {
+              DoubleField116 = value;
+            }
+            break;
+          }
+          case 938: {
+            long? value = _single_int64Field117_codec.Read(ref input);
+            if (int64Field117_ == null || value != 0L) {
+              Int64Field117 = value;
+            }
+            break;
+          }
+          case 946: {
+            double? value = _single_doubleField118_codec.Read(ref input);
+            if (doubleField118_ == null || value != 0D) {
+              DoubleField118 = value;
+            }
+            break;
+          }
+          case 954: {
+            double? value = _single_doubleField119_codec.Read(ref input);
+            if (doubleField119_ == null || value != 0D) {
+              DoubleField119 = value;
+            }
+            break;
+          }
+          case 962: {
+            double? value = _single_doubleField120_codec.Read(ref input);
+            if (doubleField120_ == null || value != 0D) {
+              DoubleField120 = value;
+            }
+            break;
+          }
+          case 970: {
+            double? value = _single_doubleField121_codec.Read(ref input);
+            if (doubleField121_ == null || value != 0D) {
+              DoubleField121 = value;
+            }
+            break;
+          }
+          case 978: {
+            double? value = _single_doubleField122_codec.Read(ref input);
+            if (doubleField122_ == null || value != 0D) {
+              DoubleField122 = value;
+            }
+            break;
+          }
+          case 986: {
+            double? value = _single_doubleField123_codec.Read(ref input);
+            if (doubleField123_ == null || value != 0D) {
+              DoubleField123 = value;
+            }
+            break;
+          }
+          case 994: {
+            double? value = _single_doubleField124_codec.Read(ref input);
+            if (doubleField124_ == null || value != 0D) {
+              DoubleField124 = value;
+            }
+            break;
+          }
+          case 1002: {
+            long? value = _single_int64Field125_codec.Read(ref input);
+            if (int64Field125_ == null || value != 0L) {
+              Int64Field125 = value;
+            }
+            break;
+          }
+          case 1010: {
+            long? value = _single_int64Field126_codec.Read(ref input);
+            if (int64Field126_ == null || value != 0L) {
+              Int64Field126 = value;
+            }
+            break;
+          }
+          case 1018: {
+            long? value = _single_int64Field127_codec.Read(ref input);
+            if (int64Field127_ == null || value != 0L) {
+              Int64Field127 = value;
+            }
+            break;
+          }
+          case 1026: {
+            double? value = _single_doubleField128_codec.Read(ref input);
+            if (doubleField128_ == null || value != 0D) {
+              DoubleField128 = value;
+            }
+            break;
+          }
+          case 1034: {
+            double? value = _single_doubleField129_codec.Read(ref input);
+            if (doubleField129_ == null || value != 0D) {
+              DoubleField129 = value;
+            }
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// same as ManyWrapperFieldsMessages, but with primitive fields
   /// for comparison.
   /// </summary>
-  public sealed partial class ManyPrimitiveFieldsMessage : pb::IMessage<ManyPrimitiveFieldsMessage> {
+  public sealed partial class ManyPrimitiveFieldsMessage : pb::IMessage<ManyPrimitiveFieldsMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ManyPrimitiveFieldsMessage> _parser = new pb::MessageParser<ManyPrimitiveFieldsMessage>(() => new ManyPrimitiveFieldsMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ManyPrimitiveFieldsMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Benchmarks.WrapperBenchmarkMessagesReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ManyPrimitiveFieldsMessage() {
       OnConstruction();
     }
@@ -4109,6 +5379,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ManyPrimitiveFieldsMessage(ManyPrimitiveFieldsMessage other) : this() {
       doubleField95_ = other.doubleField95_;
       doubleField1_ = other.doubleField1_;
@@ -4225,6 +5496,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ManyPrimitiveFieldsMessage Clone() {
       return new ManyPrimitiveFieldsMessage(this);
     }
@@ -4233,6 +5505,7 @@
     public const int DoubleField95FieldNumber = 95;
     private double doubleField95_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField95 {
       get { return doubleField95_; }
       set {
@@ -4244,6 +5517,7 @@
     public const int DoubleField1FieldNumber = 1;
     private double doubleField1_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField1 {
       get { return doubleField1_; }
       set {
@@ -4255,6 +5529,7 @@
     public const int DoubleField79FieldNumber = 79;
     private double doubleField79_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField79 {
       get { return doubleField79_; }
       set {
@@ -4266,6 +5541,7 @@
     public const int Int64Field2FieldNumber = 2;
     private long int64Field2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field2 {
       get { return int64Field2_; }
       set {
@@ -4277,6 +5553,7 @@
     public const int DoubleField96FieldNumber = 96;
     private double doubleField96_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField96 {
       get { return doubleField96_; }
       set {
@@ -4288,6 +5565,7 @@
     public const int Int64Field3FieldNumber = 3;
     private long int64Field3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field3 {
       get { return int64Field3_; }
       set {
@@ -4299,6 +5577,7 @@
     public const int Int64Field4FieldNumber = 4;
     private long int64Field4_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field4 {
       get { return int64Field4_; }
       set {
@@ -4310,6 +5589,7 @@
     public const int DoubleField97FieldNumber = 97;
     private double doubleField97_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField97 {
       get { return doubleField97_; }
       set {
@@ -4321,6 +5601,7 @@
     public const int DoubleField65FieldNumber = 65;
     private double doubleField65_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField65 {
       get { return doubleField65_; }
       set {
@@ -4332,6 +5613,7 @@
     public const int DoubleField66FieldNumber = 66;
     private double doubleField66_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField66 {
       get { return doubleField66_; }
       set {
@@ -4343,6 +5625,7 @@
     public const int DoubleField7FieldNumber = 7;
     private double doubleField7_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField7 {
       get { return doubleField7_; }
       set {
@@ -4354,6 +5637,7 @@
     public const int DoubleField62FieldNumber = 62;
     private double doubleField62_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField62 {
       get { return doubleField62_; }
       set {
@@ -4365,6 +5649,7 @@
     public const int DoubleField118FieldNumber = 118;
     private double doubleField118_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField118 {
       get { return doubleField118_; }
       set {
@@ -4376,6 +5661,7 @@
     public const int DoubleField119FieldNumber = 119;
     private double doubleField119_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField119 {
       get { return doubleField119_; }
       set {
@@ -4387,6 +5673,7 @@
     public const int DoubleField67FieldNumber = 67;
     private double doubleField67_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField67 {
       get { return doubleField67_; }
       set {
@@ -4398,6 +5685,7 @@
     public const int DoubleField120FieldNumber = 120;
     private double doubleField120_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField120 {
       get { return doubleField120_; }
       set {
@@ -4409,6 +5697,7 @@
     public const int DoubleField121FieldNumber = 121;
     private double doubleField121_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField121 {
       get { return doubleField121_; }
       set {
@@ -4420,6 +5709,7 @@
     public const int DoubleField122FieldNumber = 122;
     private double doubleField122_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField122 {
       get { return doubleField122_; }
       set {
@@ -4431,6 +5721,7 @@
     public const int DoubleField123FieldNumber = 123;
     private double doubleField123_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField123 {
       get { return doubleField123_; }
       set {
@@ -4442,6 +5733,7 @@
     public const int DoubleField124FieldNumber = 124;
     private double doubleField124_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField124 {
       get { return doubleField124_; }
       set {
@@ -4453,6 +5745,7 @@
     public const int DoubleField8FieldNumber = 8;
     private double doubleField8_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField8 {
       get { return doubleField8_; }
       set {
@@ -4464,6 +5757,7 @@
     public const int DoubleField9FieldNumber = 9;
     private double doubleField9_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField9 {
       get { return doubleField9_; }
       set {
@@ -4475,6 +5769,7 @@
     public const int DoubleField98FieldNumber = 98;
     private double doubleField98_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField98 {
       get { return doubleField98_; }
       set {
@@ -4486,6 +5781,7 @@
     public const int DoubleField10FieldNumber = 10;
     private double doubleField10_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField10 {
       get { return doubleField10_; }
       set {
@@ -4497,6 +5793,7 @@
     public const int DoubleField11FieldNumber = 11;
     private double doubleField11_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField11 {
       get { return doubleField11_; }
       set {
@@ -4508,6 +5805,7 @@
     public const int DoubleField99FieldNumber = 99;
     private double doubleField99_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField99 {
       get { return doubleField99_; }
       set {
@@ -4519,6 +5817,7 @@
     public const int DoubleField84FieldNumber = 84;
     private double doubleField84_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField84 {
       get { return doubleField84_; }
       set {
@@ -4530,6 +5829,7 @@
     public const int DoubleField14FieldNumber = 14;
     private double doubleField14_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField14 {
       get { return doubleField14_; }
       set {
@@ -4541,6 +5841,7 @@
     public const int DoubleField77FieldNumber = 77;
     private double doubleField77_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField77 {
       get { return doubleField77_; }
       set {
@@ -4552,6 +5853,7 @@
     public const int DoubleField15FieldNumber = 15;
     private double doubleField15_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField15 {
       get { return doubleField15_; }
       set {
@@ -4563,6 +5865,7 @@
     public const int Int64Field19FieldNumber = 19;
     private long int64Field19_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field19 {
       get { return int64Field19_; }
       set {
@@ -4574,6 +5877,7 @@
     public const int Int64Field115FieldNumber = 115;
     private long int64Field115_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field115 {
       get { return int64Field115_; }
       set {
@@ -4585,6 +5889,7 @@
     public const int DoubleField116FieldNumber = 116;
     private double doubleField116_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField116 {
       get { return doubleField116_; }
       set {
@@ -4596,6 +5901,7 @@
     public const int Int64Field117FieldNumber = 117;
     private long int64Field117_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field117 {
       get { return int64Field117_; }
       set {
@@ -4607,6 +5913,7 @@
     public const int DoubleField20FieldNumber = 20;
     private double doubleField20_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField20 {
       get { return doubleField20_; }
       set {
@@ -4618,6 +5925,7 @@
     public const int DoubleField21FieldNumber = 21;
     private double doubleField21_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField21 {
       get { return doubleField21_; }
       set {
@@ -4629,6 +5937,7 @@
     public const int StringField73FieldNumber = 73;
     private string stringField73_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField73 {
       get { return stringField73_; }
       set {
@@ -4640,6 +5949,7 @@
     public const int StringField74FieldNumber = 74;
     private string stringField74_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField74 {
       get { return stringField74_; }
       set {
@@ -4651,6 +5961,7 @@
     public const int DoubleField22FieldNumber = 22;
     private double doubleField22_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField22 {
       get { return doubleField22_; }
       set {
@@ -4662,6 +5973,7 @@
     public const int DoubleField69FieldNumber = 69;
     private double doubleField69_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField69 {
       get { return doubleField69_; }
       set {
@@ -4673,6 +5985,7 @@
     public const int DoubleField70FieldNumber = 70;
     private double doubleField70_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField70 {
       get { return doubleField70_; }
       set {
@@ -4684,6 +5997,7 @@
     public const int DoubleField71FieldNumber = 71;
     private double doubleField71_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField71 {
       get { return doubleField71_; }
       set {
@@ -4695,6 +6009,7 @@
     public const int DoubleField72FieldNumber = 72;
     private double doubleField72_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField72 {
       get { return doubleField72_; }
       set {
@@ -4706,6 +6021,7 @@
     public const int DoubleField25FieldNumber = 25;
     private double doubleField25_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField25 {
       get { return doubleField25_; }
       set {
@@ -4717,6 +6033,7 @@
     public const int Int64Field26FieldNumber = 26;
     private long int64Field26_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field26 {
       get { return int64Field26_; }
       set {
@@ -4728,6 +6045,7 @@
     public const int DoubleField68FieldNumber = 68;
     private double doubleField68_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField68 {
       get { return doubleField68_; }
       set {
@@ -4739,6 +6057,7 @@
     public const int DoubleField28FieldNumber = 28;
     private double doubleField28_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField28 {
       get { return doubleField28_; }
       set {
@@ -4750,6 +6069,7 @@
     public const int DoubleField106FieldNumber = 106;
     private double doubleField106_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField106 {
       get { return doubleField106_; }
       set {
@@ -4761,6 +6081,7 @@
     public const int DoubleField29FieldNumber = 29;
     private double doubleField29_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField29 {
       get { return doubleField29_; }
       set {
@@ -4772,6 +6093,7 @@
     public const int DoubleField30FieldNumber = 30;
     private double doubleField30_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField30 {
       get { return doubleField30_; }
       set {
@@ -4783,6 +6105,7 @@
     public const int DoubleField101FieldNumber = 101;
     private double doubleField101_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField101 {
       get { return doubleField101_; }
       set {
@@ -4794,6 +6117,7 @@
     public const int DoubleField102FieldNumber = 102;
     private double doubleField102_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField102 {
       get { return doubleField102_; }
       set {
@@ -4805,6 +6129,7 @@
     public const int DoubleField103FieldNumber = 103;
     private double doubleField103_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField103 {
       get { return doubleField103_; }
       set {
@@ -4816,6 +6141,7 @@
     public const int DoubleField104FieldNumber = 104;
     private double doubleField104_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField104 {
       get { return doubleField104_; }
       set {
@@ -4827,6 +6153,7 @@
     public const int DoubleField105FieldNumber = 105;
     private double doubleField105_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField105 {
       get { return doubleField105_; }
       set {
@@ -4838,6 +6165,7 @@
     public const int DoubleField31FieldNumber = 31;
     private double doubleField31_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField31 {
       get { return doubleField31_; }
       set {
@@ -4849,6 +6177,7 @@
     public const int Int64Field32FieldNumber = 32;
     private long int64Field32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field32 {
       get { return int64Field32_; }
       set {
@@ -4860,6 +6189,7 @@
     public const int DoubleField75FieldNumber = 75;
     private double doubleField75_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField75 {
       get { return doubleField75_; }
       set {
@@ -4871,6 +6201,7 @@
     public const int DoubleField129FieldNumber = 129;
     private double doubleField129_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField129 {
       get { return doubleField129_; }
       set {
@@ -4882,6 +6213,7 @@
     public const int EnumField80FieldNumber = 80;
     private int enumField80_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int EnumField80 {
       get { return enumField80_; }
       set {
@@ -4893,6 +6225,7 @@
     public const int EnumField81FieldNumber = 81;
     private int enumField81_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int EnumField81 {
       get { return enumField81_; }
       set {
@@ -4904,6 +6237,7 @@
     public const int Int64Field82FieldNumber = 82;
     private long int64Field82_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field82 {
       get { return int64Field82_; }
       set {
@@ -4915,6 +6249,7 @@
     public const int EnumField83FieldNumber = 83;
     private int enumField83_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int EnumField83 {
       get { return enumField83_; }
       set {
@@ -4926,6 +6261,7 @@
     public const int Int64Field85FieldNumber = 85;
     private long int64Field85_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field85 {
       get { return int64Field85_; }
       set {
@@ -4937,6 +6273,7 @@
     public const int Int64Field86FieldNumber = 86;
     private long int64Field86_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field86 {
       get { return int64Field86_; }
       set {
@@ -4948,6 +6285,7 @@
     public const int Int64Field87FieldNumber = 87;
     private long int64Field87_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field87 {
       get { return int64Field87_; }
       set {
@@ -4959,6 +6297,7 @@
     public const int Int64Field125FieldNumber = 125;
     private long int64Field125_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field125 {
       get { return int64Field125_; }
       set {
@@ -4970,6 +6309,7 @@
     public const int Int64Field37FieldNumber = 37;
     private long int64Field37_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field37 {
       get { return int64Field37_; }
       set {
@@ -4981,6 +6321,7 @@
     public const int DoubleField38FieldNumber = 38;
     private double doubleField38_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField38 {
       get { return doubleField38_; }
       set {
@@ -4992,6 +6333,7 @@
     public const int InteractionsFieldNumber = 39;
     private long interactions_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Interactions {
       get { return interactions_; }
       set {
@@ -5005,6 +6347,7 @@
         = pb::FieldCodec.ForInt32(802);
     private readonly pbc::RepeatedField<int> repeatedIntField100_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedIntField100 {
       get { return repeatedIntField100_; }
     }
@@ -5013,6 +6356,7 @@
     public const int DoubleField40FieldNumber = 40;
     private double doubleField40_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField40 {
       get { return doubleField40_; }
       set {
@@ -5024,6 +6368,7 @@
     public const int Int64Field41FieldNumber = 41;
     private long int64Field41_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field41 {
       get { return int64Field41_; }
       set {
@@ -5035,6 +6380,7 @@
     public const int Int64Field126FieldNumber = 126;
     private long int64Field126_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field126 {
       get { return int64Field126_; }
       set {
@@ -5046,6 +6392,7 @@
     public const int Int64Field127FieldNumber = 127;
     private long int64Field127_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field127 {
       get { return int64Field127_; }
       set {
@@ -5057,6 +6404,7 @@
     public const int DoubleField128FieldNumber = 128;
     private double doubleField128_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField128 {
       get { return doubleField128_; }
       set {
@@ -5068,6 +6416,7 @@
     public const int DoubleField109FieldNumber = 109;
     private double doubleField109_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField109 {
       get { return doubleField109_; }
       set {
@@ -5079,6 +6428,7 @@
     public const int Int64Field110FieldNumber = 110;
     private long int64Field110_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field110 {
       get { return int64Field110_; }
       set {
@@ -5090,6 +6440,7 @@
     public const int DoubleField111FieldNumber = 111;
     private double doubleField111_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField111 {
       get { return doubleField111_; }
       set {
@@ -5101,6 +6452,7 @@
     public const int Int64Field112FieldNumber = 112;
     private long int64Field112_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field112 {
       get { return int64Field112_; }
       set {
@@ -5112,6 +6464,7 @@
     public const int DoubleField113FieldNumber = 113;
     private double doubleField113_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField113 {
       get { return doubleField113_; }
       set {
@@ -5123,6 +6476,7 @@
     public const int Int64Field114FieldNumber = 114;
     private long int64Field114_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field114 {
       get { return int64Field114_; }
       set {
@@ -5134,6 +6488,7 @@
     public const int DoubleField42FieldNumber = 42;
     private double doubleField42_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField42 {
       get { return doubleField42_; }
       set {
@@ -5145,6 +6500,7 @@
     public const int Int64Field43FieldNumber = 43;
     private long int64Field43_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field43 {
       get { return int64Field43_; }
       set {
@@ -5156,6 +6512,7 @@
     public const int Int64Field44FieldNumber = 44;
     private long int64Field44_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field44 {
       get { return int64Field44_; }
       set {
@@ -5167,6 +6524,7 @@
     public const int DoubleField45FieldNumber = 45;
     private double doubleField45_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField45 {
       get { return doubleField45_; }
       set {
@@ -5178,6 +6536,7 @@
     public const int DoubleField46FieldNumber = 46;
     private double doubleField46_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField46 {
       get { return doubleField46_; }
       set {
@@ -5189,6 +6548,7 @@
     public const int DoubleField78FieldNumber = 78;
     private double doubleField78_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField78 {
       get { return doubleField78_; }
       set {
@@ -5200,6 +6560,7 @@
     public const int DoubleField88FieldNumber = 88;
     private double doubleField88_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField88 {
       get { return doubleField88_; }
       set {
@@ -5211,6 +6572,7 @@
     public const int DoubleField47FieldNumber = 47;
     private double doubleField47_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField47 {
       get { return doubleField47_; }
       set {
@@ -5222,6 +6584,7 @@
     public const int DoubleField89FieldNumber = 89;
     private double doubleField89_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField89 {
       get { return doubleField89_; }
       set {
@@ -5233,6 +6596,7 @@
     public const int DoubleField48FieldNumber = 48;
     private double doubleField48_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField48 {
       get { return doubleField48_; }
       set {
@@ -5244,6 +6608,7 @@
     public const int DoubleField49FieldNumber = 49;
     private double doubleField49_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField49 {
       get { return doubleField49_; }
       set {
@@ -5255,6 +6620,7 @@
     public const int DoubleField50FieldNumber = 50;
     private double doubleField50_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField50 {
       get { return doubleField50_; }
       set {
@@ -5266,6 +6632,7 @@
     public const int DoubleField90FieldNumber = 90;
     private double doubleField90_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField90 {
       get { return doubleField90_; }
       set {
@@ -5277,6 +6644,7 @@
     public const int DoubleField51FieldNumber = 51;
     private double doubleField51_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField51 {
       get { return doubleField51_; }
       set {
@@ -5288,6 +6656,7 @@
     public const int DoubleField91FieldNumber = 91;
     private double doubleField91_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField91 {
       get { return doubleField91_; }
       set {
@@ -5299,6 +6668,7 @@
     public const int DoubleField92FieldNumber = 92;
     private double doubleField92_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField92 {
       get { return doubleField92_; }
       set {
@@ -5310,6 +6680,7 @@
     public const int Int64Field107FieldNumber = 107;
     private long int64Field107_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field107 {
       get { return int64Field107_; }
       set {
@@ -5321,6 +6692,7 @@
     public const int DoubleField93FieldNumber = 93;
     private double doubleField93_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField93 {
       get { return doubleField93_; }
       set {
@@ -5332,6 +6704,7 @@
     public const int DoubleField108FieldNumber = 108;
     private double doubleField108_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField108 {
       get { return doubleField108_; }
       set {
@@ -5343,6 +6716,7 @@
     public const int DoubleField52FieldNumber = 52;
     private double doubleField52_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField52 {
       get { return doubleField52_; }
       set {
@@ -5354,6 +6728,7 @@
     public const int DoubleField53FieldNumber = 53;
     private double doubleField53_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField53 {
       get { return doubleField53_; }
       set {
@@ -5365,6 +6740,7 @@
     public const int DoubleField94FieldNumber = 94;
     private double doubleField94_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField94 {
       get { return doubleField94_; }
       set {
@@ -5376,6 +6752,7 @@
     public const int DoubleField54FieldNumber = 54;
     private double doubleField54_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField54 {
       get { return doubleField54_; }
       set {
@@ -5387,6 +6764,7 @@
     public const int DoubleField55FieldNumber = 55;
     private double doubleField55_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField55 {
       get { return doubleField55_; }
       set {
@@ -5398,6 +6776,7 @@
     public const int DoubleField56FieldNumber = 56;
     private double doubleField56_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField56 {
       get { return doubleField56_; }
       set {
@@ -5409,6 +6788,7 @@
     public const int DoubleField57FieldNumber = 57;
     private double doubleField57_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField57 {
       get { return doubleField57_; }
       set {
@@ -5420,6 +6800,7 @@
     public const int DoubleField58FieldNumber = 58;
     private double doubleField58_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleField58 {
       get { return doubleField58_; }
       set {
@@ -5431,6 +6812,7 @@
     public const int Int64Field59FieldNumber = 59;
     private long int64Field59_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field59 {
       get { return int64Field59_; }
       set {
@@ -5442,6 +6824,7 @@
     public const int Int64Field60FieldNumber = 60;
     private long int64Field60_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Int64Field60 {
       get { return int64Field60_; }
       set {
@@ -5450,11 +6833,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ManyPrimitiveFieldsMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ManyPrimitiveFieldsMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5577,6 +6962,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (DoubleField95 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField95);
@@ -5697,12 +7083,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (DoubleField1 != 0D) {
         output.WriteRawTag(9);
         output.WriteDouble(DoubleField1);
@@ -6147,9 +7538,462 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (DoubleField1 != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(DoubleField1);
+      }
+      if (Int64Field2 != 0L) {
+        output.WriteRawTag(16);
+        output.WriteInt64(Int64Field2);
+      }
+      if (Int64Field3 != 0L) {
+        output.WriteRawTag(24);
+        output.WriteInt64(Int64Field3);
+      }
+      if (Int64Field4 != 0L) {
+        output.WriteRawTag(32);
+        output.WriteInt64(Int64Field4);
+      }
+      if (DoubleField7 != 0D) {
+        output.WriteRawTag(57);
+        output.WriteDouble(DoubleField7);
+      }
+      if (DoubleField8 != 0D) {
+        output.WriteRawTag(65);
+        output.WriteDouble(DoubleField8);
+      }
+      if (DoubleField9 != 0D) {
+        output.WriteRawTag(73);
+        output.WriteDouble(DoubleField9);
+      }
+      if (DoubleField10 != 0D) {
+        output.WriteRawTag(81);
+        output.WriteDouble(DoubleField10);
+      }
+      if (DoubleField11 != 0D) {
+        output.WriteRawTag(89);
+        output.WriteDouble(DoubleField11);
+      }
+      if (DoubleField14 != 0D) {
+        output.WriteRawTag(113);
+        output.WriteDouble(DoubleField14);
+      }
+      if (DoubleField15 != 0D) {
+        output.WriteRawTag(121);
+        output.WriteDouble(DoubleField15);
+      }
+      if (Int64Field19 != 0L) {
+        output.WriteRawTag(152, 1);
+        output.WriteInt64(Int64Field19);
+      }
+      if (DoubleField20 != 0D) {
+        output.WriteRawTag(161, 1);
+        output.WriteDouble(DoubleField20);
+      }
+      if (DoubleField21 != 0D) {
+        output.WriteRawTag(169, 1);
+        output.WriteDouble(DoubleField21);
+      }
+      if (DoubleField22 != 0D) {
+        output.WriteRawTag(177, 1);
+        output.WriteDouble(DoubleField22);
+      }
+      if (DoubleField25 != 0D) {
+        output.WriteRawTag(201, 1);
+        output.WriteDouble(DoubleField25);
+      }
+      if (Int64Field26 != 0L) {
+        output.WriteRawTag(208, 1);
+        output.WriteInt64(Int64Field26);
+      }
+      if (DoubleField28 != 0D) {
+        output.WriteRawTag(225, 1);
+        output.WriteDouble(DoubleField28);
+      }
+      if (DoubleField29 != 0D) {
+        output.WriteRawTag(233, 1);
+        output.WriteDouble(DoubleField29);
+      }
+      if (DoubleField30 != 0D) {
+        output.WriteRawTag(241, 1);
+        output.WriteDouble(DoubleField30);
+      }
+      if (DoubleField31 != 0D) {
+        output.WriteRawTag(249, 1);
+        output.WriteDouble(DoubleField31);
+      }
+      if (Int64Field32 != 0L) {
+        output.WriteRawTag(128, 2);
+        output.WriteInt64(Int64Field32);
+      }
+      if (Int64Field37 != 0L) {
+        output.WriteRawTag(168, 2);
+        output.WriteInt64(Int64Field37);
+      }
+      if (DoubleField38 != 0D) {
+        output.WriteRawTag(177, 2);
+        output.WriteDouble(DoubleField38);
+      }
+      if (Interactions != 0L) {
+        output.WriteRawTag(184, 2);
+        output.WriteInt64(Interactions);
+      }
+      if (DoubleField40 != 0D) {
+        output.WriteRawTag(193, 2);
+        output.WriteDouble(DoubleField40);
+      }
+      if (Int64Field41 != 0L) {
+        output.WriteRawTag(200, 2);
+        output.WriteInt64(Int64Field41);
+      }
+      if (DoubleField42 != 0D) {
+        output.WriteRawTag(209, 2);
+        output.WriteDouble(DoubleField42);
+      }
+      if (Int64Field43 != 0L) {
+        output.WriteRawTag(216, 2);
+        output.WriteInt64(Int64Field43);
+      }
+      if (Int64Field44 != 0L) {
+        output.WriteRawTag(224, 2);
+        output.WriteInt64(Int64Field44);
+      }
+      if (DoubleField45 != 0D) {
+        output.WriteRawTag(233, 2);
+        output.WriteDouble(DoubleField45);
+      }
+      if (DoubleField46 != 0D) {
+        output.WriteRawTag(241, 2);
+        output.WriteDouble(DoubleField46);
+      }
+      if (DoubleField47 != 0D) {
+        output.WriteRawTag(249, 2);
+        output.WriteDouble(DoubleField47);
+      }
+      if (DoubleField48 != 0D) {
+        output.WriteRawTag(129, 3);
+        output.WriteDouble(DoubleField48);
+      }
+      if (DoubleField49 != 0D) {
+        output.WriteRawTag(137, 3);
+        output.WriteDouble(DoubleField49);
+      }
+      if (DoubleField50 != 0D) {
+        output.WriteRawTag(145, 3);
+        output.WriteDouble(DoubleField50);
+      }
+      if (DoubleField51 != 0D) {
+        output.WriteRawTag(153, 3);
+        output.WriteDouble(DoubleField51);
+      }
+      if (DoubleField52 != 0D) {
+        output.WriteRawTag(161, 3);
+        output.WriteDouble(DoubleField52);
+      }
+      if (DoubleField53 != 0D) {
+        output.WriteRawTag(169, 3);
+        output.WriteDouble(DoubleField53);
+      }
+      if (DoubleField54 != 0D) {
+        output.WriteRawTag(177, 3);
+        output.WriteDouble(DoubleField54);
+      }
+      if (DoubleField55 != 0D) {
+        output.WriteRawTag(185, 3);
+        output.WriteDouble(DoubleField55);
+      }
+      if (DoubleField56 != 0D) {
+        output.WriteRawTag(193, 3);
+        output.WriteDouble(DoubleField56);
+      }
+      if (DoubleField57 != 0D) {
+        output.WriteRawTag(201, 3);
+        output.WriteDouble(DoubleField57);
+      }
+      if (DoubleField58 != 0D) {
+        output.WriteRawTag(209, 3);
+        output.WriteDouble(DoubleField58);
+      }
+      if (Int64Field59 != 0L) {
+        output.WriteRawTag(216, 3);
+        output.WriteInt64(Int64Field59);
+      }
+      if (Int64Field60 != 0L) {
+        output.WriteRawTag(224, 3);
+        output.WriteInt64(Int64Field60);
+      }
+      if (DoubleField62 != 0D) {
+        output.WriteRawTag(241, 3);
+        output.WriteDouble(DoubleField62);
+      }
+      if (DoubleField65 != 0D) {
+        output.WriteRawTag(137, 4);
+        output.WriteDouble(DoubleField65);
+      }
+      if (DoubleField66 != 0D) {
+        output.WriteRawTag(145, 4);
+        output.WriteDouble(DoubleField66);
+      }
+      if (DoubleField67 != 0D) {
+        output.WriteRawTag(153, 4);
+        output.WriteDouble(DoubleField67);
+      }
+      if (DoubleField68 != 0D) {
+        output.WriteRawTag(161, 4);
+        output.WriteDouble(DoubleField68);
+      }
+      if (DoubleField69 != 0D) {
+        output.WriteRawTag(169, 4);
+        output.WriteDouble(DoubleField69);
+      }
+      if (DoubleField70 != 0D) {
+        output.WriteRawTag(177, 4);
+        output.WriteDouble(DoubleField70);
+      }
+      if (DoubleField71 != 0D) {
+        output.WriteRawTag(185, 4);
+        output.WriteDouble(DoubleField71);
+      }
+      if (DoubleField72 != 0D) {
+        output.WriteRawTag(193, 4);
+        output.WriteDouble(DoubleField72);
+      }
+      if (StringField73.Length != 0) {
+        output.WriteRawTag(202, 4);
+        output.WriteString(StringField73);
+      }
+      if (StringField74.Length != 0) {
+        output.WriteRawTag(210, 4);
+        output.WriteString(StringField74);
+      }
+      if (DoubleField75 != 0D) {
+        output.WriteRawTag(217, 4);
+        output.WriteDouble(DoubleField75);
+      }
+      if (DoubleField77 != 0D) {
+        output.WriteRawTag(233, 4);
+        output.WriteDouble(DoubleField77);
+      }
+      if (DoubleField78 != 0D) {
+        output.WriteRawTag(241, 4);
+        output.WriteDouble(DoubleField78);
+      }
+      if (DoubleField79 != 0D) {
+        output.WriteRawTag(249, 4);
+        output.WriteDouble(DoubleField79);
+      }
+      if (EnumField80 != 0) {
+        output.WriteRawTag(128, 5);
+        output.WriteInt32(EnumField80);
+      }
+      if (EnumField81 != 0) {
+        output.WriteRawTag(136, 5);
+        output.WriteInt32(EnumField81);
+      }
+      if (Int64Field82 != 0L) {
+        output.WriteRawTag(144, 5);
+        output.WriteInt64(Int64Field82);
+      }
+      if (EnumField83 != 0) {
+        output.WriteRawTag(152, 5);
+        output.WriteInt32(EnumField83);
+      }
+      if (DoubleField84 != 0D) {
+        output.WriteRawTag(161, 5);
+        output.WriteDouble(DoubleField84);
+      }
+      if (Int64Field85 != 0L) {
+        output.WriteRawTag(168, 5);
+        output.WriteInt64(Int64Field85);
+      }
+      if (Int64Field86 != 0L) {
+        output.WriteRawTag(176, 5);
+        output.WriteInt64(Int64Field86);
+      }
+      if (Int64Field87 != 0L) {
+        output.WriteRawTag(184, 5);
+        output.WriteInt64(Int64Field87);
+      }
+      if (DoubleField88 != 0D) {
+        output.WriteRawTag(193, 5);
+        output.WriteDouble(DoubleField88);
+      }
+      if (DoubleField89 != 0D) {
+        output.WriteRawTag(201, 5);
+        output.WriteDouble(DoubleField89);
+      }
+      if (DoubleField90 != 0D) {
+        output.WriteRawTag(209, 5);
+        output.WriteDouble(DoubleField90);
+      }
+      if (DoubleField91 != 0D) {
+        output.WriteRawTag(217, 5);
+        output.WriteDouble(DoubleField91);
+      }
+      if (DoubleField92 != 0D) {
+        output.WriteRawTag(225, 5);
+        output.WriteDouble(DoubleField92);
+      }
+      if (DoubleField93 != 0D) {
+        output.WriteRawTag(233, 5);
+        output.WriteDouble(DoubleField93);
+      }
+      if (DoubleField94 != 0D) {
+        output.WriteRawTag(241, 5);
+        output.WriteDouble(DoubleField94);
+      }
+      if (DoubleField95 != 0D) {
+        output.WriteRawTag(249, 5);
+        output.WriteDouble(DoubleField95);
+      }
+      if (DoubleField96 != 0D) {
+        output.WriteRawTag(129, 6);
+        output.WriteDouble(DoubleField96);
+      }
+      if (DoubleField97 != 0D) {
+        output.WriteRawTag(137, 6);
+        output.WriteDouble(DoubleField97);
+      }
+      if (DoubleField98 != 0D) {
+        output.WriteRawTag(145, 6);
+        output.WriteDouble(DoubleField98);
+      }
+      if (DoubleField99 != 0D) {
+        output.WriteRawTag(153, 6);
+        output.WriteDouble(DoubleField99);
+      }
+      repeatedIntField100_.WriteTo(ref output, _repeated_repeatedIntField100_codec);
+      if (DoubleField101 != 0D) {
+        output.WriteRawTag(169, 6);
+        output.WriteDouble(DoubleField101);
+      }
+      if (DoubleField102 != 0D) {
+        output.WriteRawTag(177, 6);
+        output.WriteDouble(DoubleField102);
+      }
+      if (DoubleField103 != 0D) {
+        output.WriteRawTag(185, 6);
+        output.WriteDouble(DoubleField103);
+      }
+      if (DoubleField104 != 0D) {
+        output.WriteRawTag(193, 6);
+        output.WriteDouble(DoubleField104);
+      }
+      if (DoubleField105 != 0D) {
+        output.WriteRawTag(201, 6);
+        output.WriteDouble(DoubleField105);
+      }
+      if (DoubleField106 != 0D) {
+        output.WriteRawTag(209, 6);
+        output.WriteDouble(DoubleField106);
+      }
+      if (Int64Field107 != 0L) {
+        output.WriteRawTag(216, 6);
+        output.WriteInt64(Int64Field107);
+      }
+      if (DoubleField108 != 0D) {
+        output.WriteRawTag(225, 6);
+        output.WriteDouble(DoubleField108);
+      }
+      if (DoubleField109 != 0D) {
+        output.WriteRawTag(233, 6);
+        output.WriteDouble(DoubleField109);
+      }
+      if (Int64Field110 != 0L) {
+        output.WriteRawTag(240, 6);
+        output.WriteInt64(Int64Field110);
+      }
+      if (DoubleField111 != 0D) {
+        output.WriteRawTag(249, 6);
+        output.WriteDouble(DoubleField111);
+      }
+      if (Int64Field112 != 0L) {
+        output.WriteRawTag(128, 7);
+        output.WriteInt64(Int64Field112);
+      }
+      if (DoubleField113 != 0D) {
+        output.WriteRawTag(137, 7);
+        output.WriteDouble(DoubleField113);
+      }
+      if (Int64Field114 != 0L) {
+        output.WriteRawTag(144, 7);
+        output.WriteInt64(Int64Field114);
+      }
+      if (Int64Field115 != 0L) {
+        output.WriteRawTag(152, 7);
+        output.WriteInt64(Int64Field115);
+      }
+      if (DoubleField116 != 0D) {
+        output.WriteRawTag(161, 7);
+        output.WriteDouble(DoubleField116);
+      }
+      if (Int64Field117 != 0L) {
+        output.WriteRawTag(168, 7);
+        output.WriteInt64(Int64Field117);
+      }
+      if (DoubleField118 != 0D) {
+        output.WriteRawTag(177, 7);
+        output.WriteDouble(DoubleField118);
+      }
+      if (DoubleField119 != 0D) {
+        output.WriteRawTag(185, 7);
+        output.WriteDouble(DoubleField119);
+      }
+      if (DoubleField120 != 0D) {
+        output.WriteRawTag(193, 7);
+        output.WriteDouble(DoubleField120);
+      }
+      if (DoubleField121 != 0D) {
+        output.WriteRawTag(201, 7);
+        output.WriteDouble(DoubleField121);
+      }
+      if (DoubleField122 != 0D) {
+        output.WriteRawTag(209, 7);
+        output.WriteDouble(DoubleField122);
+      }
+      if (DoubleField123 != 0D) {
+        output.WriteRawTag(217, 7);
+        output.WriteDouble(DoubleField123);
+      }
+      if (DoubleField124 != 0D) {
+        output.WriteRawTag(225, 7);
+        output.WriteDouble(DoubleField124);
+      }
+      if (Int64Field125 != 0L) {
+        output.WriteRawTag(232, 7);
+        output.WriteInt64(Int64Field125);
+      }
+      if (Int64Field126 != 0L) {
+        output.WriteRawTag(240, 7);
+        output.WriteInt64(Int64Field126);
+      }
+      if (Int64Field127 != 0L) {
+        output.WriteRawTag(248, 7);
+        output.WriteInt64(Int64Field127);
+      }
+      if (DoubleField128 != 0D) {
+        output.WriteRawTag(129, 8);
+        output.WriteDouble(DoubleField128);
+      }
+      if (DoubleField129 != 0D) {
+        output.WriteRawTag(137, 8);
+        output.WriteDouble(DoubleField129);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (DoubleField95 != 0D) {
@@ -6490,6 +8334,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ManyPrimitiveFieldsMessage other) {
       if (other == null) {
         return;
@@ -6829,7 +8674,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7283,8 +9132,469 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 9: {
+            DoubleField1 = input.ReadDouble();
+            break;
+          }
+          case 16: {
+            Int64Field2 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            Int64Field3 = input.ReadInt64();
+            break;
+          }
+          case 32: {
+            Int64Field4 = input.ReadInt64();
+            break;
+          }
+          case 57: {
+            DoubleField7 = input.ReadDouble();
+            break;
+          }
+          case 65: {
+            DoubleField8 = input.ReadDouble();
+            break;
+          }
+          case 73: {
+            DoubleField9 = input.ReadDouble();
+            break;
+          }
+          case 81: {
+            DoubleField10 = input.ReadDouble();
+            break;
+          }
+          case 89: {
+            DoubleField11 = input.ReadDouble();
+            break;
+          }
+          case 113: {
+            DoubleField14 = input.ReadDouble();
+            break;
+          }
+          case 121: {
+            DoubleField15 = input.ReadDouble();
+            break;
+          }
+          case 152: {
+            Int64Field19 = input.ReadInt64();
+            break;
+          }
+          case 161: {
+            DoubleField20 = input.ReadDouble();
+            break;
+          }
+          case 169: {
+            DoubleField21 = input.ReadDouble();
+            break;
+          }
+          case 177: {
+            DoubleField22 = input.ReadDouble();
+            break;
+          }
+          case 201: {
+            DoubleField25 = input.ReadDouble();
+            break;
+          }
+          case 208: {
+            Int64Field26 = input.ReadInt64();
+            break;
+          }
+          case 225: {
+            DoubleField28 = input.ReadDouble();
+            break;
+          }
+          case 233: {
+            DoubleField29 = input.ReadDouble();
+            break;
+          }
+          case 241: {
+            DoubleField30 = input.ReadDouble();
+            break;
+          }
+          case 249: {
+            DoubleField31 = input.ReadDouble();
+            break;
+          }
+          case 256: {
+            Int64Field32 = input.ReadInt64();
+            break;
+          }
+          case 296: {
+            Int64Field37 = input.ReadInt64();
+            break;
+          }
+          case 305: {
+            DoubleField38 = input.ReadDouble();
+            break;
+          }
+          case 312: {
+            Interactions = input.ReadInt64();
+            break;
+          }
+          case 321: {
+            DoubleField40 = input.ReadDouble();
+            break;
+          }
+          case 328: {
+            Int64Field41 = input.ReadInt64();
+            break;
+          }
+          case 337: {
+            DoubleField42 = input.ReadDouble();
+            break;
+          }
+          case 344: {
+            Int64Field43 = input.ReadInt64();
+            break;
+          }
+          case 352: {
+            Int64Field44 = input.ReadInt64();
+            break;
+          }
+          case 361: {
+            DoubleField45 = input.ReadDouble();
+            break;
+          }
+          case 369: {
+            DoubleField46 = input.ReadDouble();
+            break;
+          }
+          case 377: {
+            DoubleField47 = input.ReadDouble();
+            break;
+          }
+          case 385: {
+            DoubleField48 = input.ReadDouble();
+            break;
+          }
+          case 393: {
+            DoubleField49 = input.ReadDouble();
+            break;
+          }
+          case 401: {
+            DoubleField50 = input.ReadDouble();
+            break;
+          }
+          case 409: {
+            DoubleField51 = input.ReadDouble();
+            break;
+          }
+          case 417: {
+            DoubleField52 = input.ReadDouble();
+            break;
+          }
+          case 425: {
+            DoubleField53 = input.ReadDouble();
+            break;
+          }
+          case 433: {
+            DoubleField54 = input.ReadDouble();
+            break;
+          }
+          case 441: {
+            DoubleField55 = input.ReadDouble();
+            break;
+          }
+          case 449: {
+            DoubleField56 = input.ReadDouble();
+            break;
+          }
+          case 457: {
+            DoubleField57 = input.ReadDouble();
+            break;
+          }
+          case 465: {
+            DoubleField58 = input.ReadDouble();
+            break;
+          }
+          case 472: {
+            Int64Field59 = input.ReadInt64();
+            break;
+          }
+          case 480: {
+            Int64Field60 = input.ReadInt64();
+            break;
+          }
+          case 497: {
+            DoubleField62 = input.ReadDouble();
+            break;
+          }
+          case 521: {
+            DoubleField65 = input.ReadDouble();
+            break;
+          }
+          case 529: {
+            DoubleField66 = input.ReadDouble();
+            break;
+          }
+          case 537: {
+            DoubleField67 = input.ReadDouble();
+            break;
+          }
+          case 545: {
+            DoubleField68 = input.ReadDouble();
+            break;
+          }
+          case 553: {
+            DoubleField69 = input.ReadDouble();
+            break;
+          }
+          case 561: {
+            DoubleField70 = input.ReadDouble();
+            break;
+          }
+          case 569: {
+            DoubleField71 = input.ReadDouble();
+            break;
+          }
+          case 577: {
+            DoubleField72 = input.ReadDouble();
+            break;
+          }
+          case 586: {
+            StringField73 = input.ReadString();
+            break;
+          }
+          case 594: {
+            StringField74 = input.ReadString();
+            break;
+          }
+          case 601: {
+            DoubleField75 = input.ReadDouble();
+            break;
+          }
+          case 617: {
+            DoubleField77 = input.ReadDouble();
+            break;
+          }
+          case 625: {
+            DoubleField78 = input.ReadDouble();
+            break;
+          }
+          case 633: {
+            DoubleField79 = input.ReadDouble();
+            break;
+          }
+          case 640: {
+            EnumField80 = input.ReadInt32();
+            break;
+          }
+          case 648: {
+            EnumField81 = input.ReadInt32();
+            break;
+          }
+          case 656: {
+            Int64Field82 = input.ReadInt64();
+            break;
+          }
+          case 664: {
+            EnumField83 = input.ReadInt32();
+            break;
+          }
+          case 673: {
+            DoubleField84 = input.ReadDouble();
+            break;
+          }
+          case 680: {
+            Int64Field85 = input.ReadInt64();
+            break;
+          }
+          case 688: {
+            Int64Field86 = input.ReadInt64();
+            break;
+          }
+          case 696: {
+            Int64Field87 = input.ReadInt64();
+            break;
+          }
+          case 705: {
+            DoubleField88 = input.ReadDouble();
+            break;
+          }
+          case 713: {
+            DoubleField89 = input.ReadDouble();
+            break;
+          }
+          case 721: {
+            DoubleField90 = input.ReadDouble();
+            break;
+          }
+          case 729: {
+            DoubleField91 = input.ReadDouble();
+            break;
+          }
+          case 737: {
+            DoubleField92 = input.ReadDouble();
+            break;
+          }
+          case 745: {
+            DoubleField93 = input.ReadDouble();
+            break;
+          }
+          case 753: {
+            DoubleField94 = input.ReadDouble();
+            break;
+          }
+          case 761: {
+            DoubleField95 = input.ReadDouble();
+            break;
+          }
+          case 769: {
+            DoubleField96 = input.ReadDouble();
+            break;
+          }
+          case 777: {
+            DoubleField97 = input.ReadDouble();
+            break;
+          }
+          case 785: {
+            DoubleField98 = input.ReadDouble();
+            break;
+          }
+          case 793: {
+            DoubleField99 = input.ReadDouble();
+            break;
+          }
+          case 802:
+          case 800: {
+            repeatedIntField100_.AddEntriesFrom(ref input, _repeated_repeatedIntField100_codec);
+            break;
+          }
+          case 809: {
+            DoubleField101 = input.ReadDouble();
+            break;
+          }
+          case 817: {
+            DoubleField102 = input.ReadDouble();
+            break;
+          }
+          case 825: {
+            DoubleField103 = input.ReadDouble();
+            break;
+          }
+          case 833: {
+            DoubleField104 = input.ReadDouble();
+            break;
+          }
+          case 841: {
+            DoubleField105 = input.ReadDouble();
+            break;
+          }
+          case 849: {
+            DoubleField106 = input.ReadDouble();
+            break;
+          }
+          case 856: {
+            Int64Field107 = input.ReadInt64();
+            break;
+          }
+          case 865: {
+            DoubleField108 = input.ReadDouble();
+            break;
+          }
+          case 873: {
+            DoubleField109 = input.ReadDouble();
+            break;
+          }
+          case 880: {
+            Int64Field110 = input.ReadInt64();
+            break;
+          }
+          case 889: {
+            DoubleField111 = input.ReadDouble();
+            break;
+          }
+          case 896: {
+            Int64Field112 = input.ReadInt64();
+            break;
+          }
+          case 905: {
+            DoubleField113 = input.ReadDouble();
+            break;
+          }
+          case 912: {
+            Int64Field114 = input.ReadInt64();
+            break;
+          }
+          case 920: {
+            Int64Field115 = input.ReadInt64();
+            break;
+          }
+          case 929: {
+            DoubleField116 = input.ReadDouble();
+            break;
+          }
+          case 936: {
+            Int64Field117 = input.ReadInt64();
+            break;
+          }
+          case 945: {
+            DoubleField118 = input.ReadDouble();
+            break;
+          }
+          case 953: {
+            DoubleField119 = input.ReadDouble();
+            break;
+          }
+          case 961: {
+            DoubleField120 = input.ReadDouble();
+            break;
+          }
+          case 969: {
+            DoubleField121 = input.ReadDouble();
+            break;
+          }
+          case 977: {
+            DoubleField122 = input.ReadDouble();
+            break;
+          }
+          case 985: {
+            DoubleField123 = input.ReadDouble();
+            break;
+          }
+          case 993: {
+            DoubleField124 = input.ReadDouble();
+            break;
+          }
+          case 1000: {
+            Int64Field125 = input.ReadInt64();
+            break;
+          }
+          case 1008: {
+            Int64Field126 = input.ReadInt64();
+            break;
+          }
+          case 1016: {
+            Int64Field127 = input.ReadInt64();
+            break;
+          }
+          case 1025: {
+            DoubleField128 = input.ReadDouble();
+            break;
+          }
+          case 1033: {
+            DoubleField129 = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs
new file mode 100644
index 0000000..5a3bba7
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs
@@ -0,0 +1,198 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2019 Google Inc.  All rights reserved.
+// https://github.com/protocolbuffers/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using BenchmarkDotNet.Attributes;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Buffers;
+using Google.Protobuf.WellKnownTypes;
+
+namespace Google.Protobuf.Benchmarks
+{
+    /// <summary>
+    /// Benchmark that tests writing performance for various messages.
+    /// </summary>
+    [MemoryDiagnoser]
+    public class WriteMessagesBenchmark
+    {
+        const int MaxMessages = 100;
+
+        SubTest manyWrapperFieldsTest = new SubTest(ParseMessagesBenchmark.CreateManyWrapperFieldsMessage(), MaxMessages);
+        SubTest manyPrimitiveFieldsTest = new SubTest(ParseMessagesBenchmark.CreateManyPrimitiveFieldsMessage(), MaxMessages);
+        SubTest emptyMessageTest = new SubTest(new Empty(), MaxMessages);
+
+        public IEnumerable<int> MessageCountValues => new[] { 10, 100 };
+
+        [GlobalSetup]
+        public void GlobalSetup()
+        {
+        }
+
+        [Benchmark]
+        public byte[] ManyWrapperFieldsMessage_ToByteArray()
+        {
+            return manyWrapperFieldsTest.ToByteArray();
+        }
+
+        [Benchmark]
+        public byte[] ManyWrapperFieldsMessage_WriteToCodedOutputStream()
+        {
+            return manyWrapperFieldsTest.WriteToCodedOutputStream_PreAllocatedBuffer();
+        }
+
+        [Benchmark]
+        public byte[] ManyWrapperFieldsMessage_WriteToSpan()
+        {
+            return manyWrapperFieldsTest.WriteToSpan_PreAllocatedBuffer();
+        }
+
+
+        [Benchmark]
+        public byte[] ManyPrimitiveFieldsMessage_ToByteArray()
+        {
+            return manyPrimitiveFieldsTest.ToByteArray();
+        }
+
+        [Benchmark]
+        public byte[] ManyPrimitiveFieldsMessage_WriteToCodedOutputStream()
+        {
+            return manyPrimitiveFieldsTest.WriteToCodedOutputStream_PreAllocatedBuffer();
+        }
+
+        [Benchmark]
+        public byte[] ManyPrimitiveFieldsMessage_WriteToSpan()
+        {
+            return manyPrimitiveFieldsTest.WriteToSpan_PreAllocatedBuffer();
+        }
+
+        [Benchmark]
+        public byte[] EmptyMessage_ToByteArray()
+        {
+            return emptyMessageTest.ToByteArray();
+        }
+
+        [Benchmark]
+        public byte[] EmptyMessage_WriteToCodedOutputStream()
+        {
+            return emptyMessageTest.WriteToCodedOutputStream_PreAllocatedBuffer();
+        }
+
+        [Benchmark]
+        public byte[] EmptyMessage_WriteToSpan()
+        {
+            return emptyMessageTest.WriteToSpan_PreAllocatedBuffer();
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
+        public void ManyWrapperFieldsMessage_WriteDelimitedMessagesToCodedOutputStream(int messageCount)
+        {
+            manyWrapperFieldsTest.WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(messageCount);
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
+        public void ManyWrapperFieldsMessage_WriteDelimitedMessagesToSpan(int messageCount)
+        {
+            manyWrapperFieldsTest.WriteDelimitedMessagesToSpan_PreAllocatedBuffer(messageCount);
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
+        public void ManyPrimitiveFieldsMessage_WriteDelimitedMessagesToCodedOutputStream(int messageCount)
+        {
+            manyPrimitiveFieldsTest.WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(messageCount);
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(MessageCountValues))]
+        public void ManyPrimitiveFieldsMessage_WriteDelimitedMessagesToSpan(int messageCount)
+        {
+            manyPrimitiveFieldsTest.WriteDelimitedMessagesToSpan_PreAllocatedBuffer(messageCount);
+        }
+
+        private class SubTest
+        {
+            private readonly IMessage message;
+            private readonly byte[] outputBuffer;
+            private readonly byte[] multipleMessagesOutputBuffer;
+
+            public SubTest(IMessage message, int maxMessageCount)
+            {
+                this.message = message;
+
+                int messageSize = message.CalculateSize();
+                this.outputBuffer = new byte[messageSize];
+                this.multipleMessagesOutputBuffer = new byte[maxMessageCount * (messageSize + CodedOutputStream.ComputeLengthSize(messageSize))];
+            }
+
+            public byte[] ToByteArray() => message.ToByteArray();
+
+            public byte[] WriteToCodedOutputStream_PreAllocatedBuffer()
+            {
+                var cos = new CodedOutputStream(outputBuffer);  // use pre-existing output buffer
+                message.WriteTo(cos);
+                return outputBuffer;
+            }
+
+            public byte[] WriteToSpan_PreAllocatedBuffer()
+            {
+                var span = new Span<byte>(outputBuffer);  // use pre-existing output buffer
+                message.WriteTo(span);
+                return outputBuffer;
+            }
+
+            public byte[] WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(int messageCount)
+            {
+                var cos = new CodedOutputStream(multipleMessagesOutputBuffer);  // use pre-existing output buffer
+                for (int i = 0; i < messageCount; i++)
+                {
+                    cos.WriteMessage(message);
+                }
+                return multipleMessagesOutputBuffer;
+            }
+
+            public byte[] WriteDelimitedMessagesToSpan_PreAllocatedBuffer(int messageCount)
+            {
+                var span = new Span<byte>(multipleMessagesOutputBuffer);  // use pre-existing output buffer
+                WriteContext.Initialize(ref span, out WriteContext ctx);
+                for (int i = 0; i < messageCount; i++)
+                {
+                    ctx.WriteMessage(message);
+                }
+                return multipleMessagesOutputBuffer;
+            }
+        }
+    }
+}
diff --git a/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs
new file mode 100644
index 0000000..66b6b4a
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs
@@ -0,0 +1,519 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2019 Google Inc.  All rights reserved.
+// https://github.com/protocolbuffers/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using BenchmarkDotNet.Attributes;
+using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Buffers;
+using System.Text;
+
+namespace Google.Protobuf.Benchmarks
+{
+    /// <summary>
+    /// Benchmarks throughput when writing raw primitives.
+    /// </summary>
+    [MemoryDiagnoser]
+    public class WriteRawPrimitivesBenchmark
+    {
+        // key is the encodedSize of varint values
+        Dictionary<int, uint[]> varint32Values;
+        Dictionary<int, ulong[]> varint64Values;
+
+        double[] doubleValues;
+        float[] floatValues;
+
+        // key is the encodedSize of string values
+        Dictionary<int, string[]> stringValues;
+
+        // key is the encodedSize of string values
+        Dictionary<int, string[]> nonAsciiStringValues;
+
+        // key is the encodedSize of string values
+        Dictionary<int, ByteString[]> byteStringValues;
+
+        // the buffer to which all the data will be written
+        byte[] outputBuffer;
+
+        Random random = new Random(417384220);  // random but deterministic seed
+
+        public IEnumerable<int> StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 };
+
+        public IEnumerable<int> NonAsciiStringEncodedSizes => new[] { 4, 10, 105, 10080 };
+
+        [GlobalSetup]
+        public void GlobalSetup()
+        {
+            outputBuffer = new byte[BytesToWrite];
+
+            varint32Values = new Dictionary<int, uint[]>();
+            varint64Values = new Dictionary<int, ulong[]>();
+            for (int encodedSize = 1; encodedSize <= 10; encodedSize++)
+            {
+                if (encodedSize <= 5)
+                {
+                    varint32Values.Add(encodedSize, CreateRandomVarints32(random, BytesToWrite / encodedSize, encodedSize));
+                }
+                varint64Values.Add(encodedSize, CreateRandomVarints64(random, BytesToWrite / encodedSize, encodedSize));
+            }
+
+            doubleValues = CreateRandomDoubles(random, BytesToWrite / sizeof(double));
+            floatValues = CreateRandomFloats(random, BytesToWrite / sizeof(float));
+
+            stringValues = new Dictionary<int, string[]>();
+
+            byteStringValues = new Dictionary<int, ByteString[]>();
+            foreach(var encodedSize in StringEncodedSizes)
+            {
+                stringValues.Add(encodedSize, CreateStrings(BytesToWrite / encodedSize, encodedSize));
+                byteStringValues.Add(encodedSize, CreateByteStrings(BytesToWrite / encodedSize, encodedSize));
+            }
+
+            nonAsciiStringValues = new Dictionary<int, string[]>();
+            foreach(var encodedSize in NonAsciiStringEncodedSizes)
+            {
+                nonAsciiStringValues.Add(encodedSize, CreateNonAsciiStrings(BytesToWrite / encodedSize, encodedSize));
+            }
+        }
+
+        // Total number of bytes that each benchmark will write.
+        // Measuring the time taken to write buffer of given size makes it easier to compare parsing speed for different
+        // types and makes it easy to calculate the througput (in MB/s)
+        // 10800 bytes is chosen because it is divisible by all possible encoded sizes for all primitive types {1..10}
+        [Params(10080)]
+        public int BytesToWrite { get; set; }
+
+        [Benchmark]
+        [Arguments(1)]
+        [Arguments(2)]
+        [Arguments(3)]
+        [Arguments(4)]
+        [Arguments(5)]
+        public void WriteRawVarint32_CodedOutputStream(int encodedSize)
+        {
+            var values = varint32Values[encodedSize];
+            var cos = new CodedOutputStream(outputBuffer);
+            for (int i = 0; i < values.Length; i++)
+            {
+                cos.WriteRawVarint32(values[i]);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [Arguments(1)]
+        [Arguments(2)]
+        [Arguments(3)]
+        [Arguments(4)]
+        [Arguments(5)]
+        public void WriteRawVarint32_WriteContext(int encodedSize)
+        {
+            var values = varint32Values[encodedSize];
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            for (int i = 0; i < values.Length; i++)
+            {
+                ctx.WriteUInt32(values[i]);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [Arguments(1)]
+        [Arguments(2)]
+        [Arguments(3)]
+        [Arguments(4)]
+        [Arguments(5)]
+        [Arguments(6)]
+        [Arguments(7)]
+        [Arguments(8)]
+        [Arguments(9)]
+        [Arguments(10)]
+        public void WriteRawVarint64_CodedOutputStream(int encodedSize)
+        {
+            var values = varint64Values[encodedSize];
+            var cos = new CodedOutputStream(outputBuffer);
+            for (int i = 0; i < values.Length; i++)
+            {
+                cos.WriteRawVarint64(values[i]);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [Arguments(1)]
+        [Arguments(2)]
+        [Arguments(3)]
+        [Arguments(4)]
+        [Arguments(5)]
+        [Arguments(6)]
+        [Arguments(7)]
+        [Arguments(8)]
+        [Arguments(9)]
+        [Arguments(10)]
+        public void WriteRawVarint64_WriteContext(int encodedSize)
+        {
+            var values = varint64Values[encodedSize];
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            for (int i = 0; i < values.Length; i++)
+            {
+                ctx.WriteUInt64(values[i]);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteFixed32_CodedOutputStream()
+        {
+            const int encodedSize = sizeof(uint);
+            var cos = new CodedOutputStream(outputBuffer);
+            for (int i = 0; i < BytesToWrite / encodedSize; i++)
+            {
+                cos.WriteFixed32(12345);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteFixed32_WriteContext()
+        {
+            const int encodedSize = sizeof(uint);
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            for (uint i = 0; i < BytesToWrite / encodedSize; i++)
+            {
+                ctx.WriteFixed32(12345);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteFixed64_CodedOutputStream()
+        {
+            const int encodedSize = sizeof(ulong);
+            var cos = new CodedOutputStream(outputBuffer);
+            for(int i = 0; i < BytesToWrite / encodedSize; i++)
+            {
+                cos.WriteFixed64(123456789);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteFixed64_WriteContext()
+        {
+            const int encodedSize = sizeof(ulong);
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            for (uint i = 0; i < BytesToWrite / encodedSize; i++)
+            {
+                ctx.WriteFixed64(123456789);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteRawTag_OneByte_WriteContext()
+        {
+            const int encodedSize = 1;
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            for (uint i = 0; i < BytesToWrite / encodedSize; i++)
+            {
+                ctx.WriteRawTag(16);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteRawTag_TwoBytes_WriteContext()
+        {
+            const int encodedSize = 2;
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            for (uint i = 0; i < BytesToWrite / encodedSize; i++)
+            {
+                ctx.WriteRawTag(137, 6);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteRawTag_ThreeBytes_WriteContext()
+        {
+            const int encodedSize = 3;
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            for (uint i = 0; i < BytesToWrite / encodedSize; i++)
+            {
+                ctx.WriteRawTag(160, 131, 1);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void Baseline_WriteContext()
+        {
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            ctx.state.position = outputBuffer.Length;
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteRawFloat_CodedOutputStream()
+        {
+            var cos = new CodedOutputStream(outputBuffer);
+            foreach (var value in floatValues)
+            {
+                cos.WriteFloat(value);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteRawFloat_WriteContext()
+        {
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            foreach (var value in floatValues)
+            {
+                ctx.WriteFloat(value);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteRawDouble_CodedOutputStream()
+        {
+            var cos = new CodedOutputStream(outputBuffer);
+            foreach (var value in doubleValues)
+            {
+                cos.WriteDouble(value);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        public void WriteRawDouble_WriteContext()
+        {
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            foreach (var value in doubleValues)
+            {
+                ctx.WriteDouble(value);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public void WriteString_CodedOutputStream(int encodedSize)
+        {
+            var values = stringValues[encodedSize];
+            var cos = new CodedOutputStream(outputBuffer);
+            foreach (var value in values)
+            {
+                cos.WriteString(value);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public void WriteString_WriteContext(int encodedSize)
+        {
+            var values = stringValues[encodedSize];
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            foreach (var value in values)
+            {
+                ctx.WriteString(value);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))]
+        public void WriteNonAsciiString_CodedOutputStream(int encodedSize)
+        {
+            var values = nonAsciiStringValues[encodedSize];
+            var cos = new CodedOutputStream(outputBuffer);
+            foreach (var value in values)
+            {
+                cos.WriteString(value);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))]
+        public void WriteNonAsciiString_WriteContext(int encodedSize)
+        {
+            var values = nonAsciiStringValues[encodedSize];
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            foreach (var value in values)
+            {
+                ctx.WriteString(value);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public void WriteBytes_CodedOutputStream(int encodedSize)
+        {
+            var values = byteStringValues[encodedSize];
+            var cos = new CodedOutputStream(outputBuffer);
+            foreach (var value in values)
+            {
+                cos.WriteBytes(value);
+            }
+            cos.Flush();
+            cos.CheckNoSpaceLeft();
+        }
+
+        [Benchmark]
+        [ArgumentsSource(nameof(StringEncodedSizes))]
+        public void WriteBytes_WriteContext(int encodedSize)
+        {
+            var values = byteStringValues[encodedSize];
+            var span = new Span<byte>(outputBuffer);
+            WriteContext.Initialize(ref span, out WriteContext ctx);
+            foreach (var value in values)
+            {
+                ctx.WriteBytes(value);
+            }
+            ctx.Flush();
+            ctx.CheckNoSpaceLeft();
+        }
+
+        private static uint[] CreateRandomVarints32(Random random, int valueCount, int encodedSize)
+        {
+            var result = new uint[valueCount];
+            for (int i = 0; i < valueCount; i++)
+            {
+                result[i] = (uint) ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, true);
+            }
+            return result;
+        }
+
+        private static ulong[] CreateRandomVarints64(Random random, int valueCount, int encodedSize)
+        {            
+            var result = new ulong[valueCount];
+            for (int i = 0; i < valueCount; i++)
+            {
+                result[i] = ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, false);
+            }
+            return result;
+        }
+
+        private static float[] CreateRandomFloats(Random random, int valueCount)
+        {
+            var result = new float[valueCount];
+            for (int i = 0; i < valueCount; i++)
+            {
+                result[i] = (float)random.NextDouble();
+            }
+            return result;
+        }
+
+        private static double[] CreateRandomDoubles(Random random, int valueCount)
+        {
+            var result = new double[valueCount];
+            for (int i = 0; i < valueCount; i++)
+            {
+                result[i] = random.NextDouble();
+            }
+            return result;
+        }
+
+        private static string[] CreateStrings(int valueCount, int encodedSize)
+        {
+            var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize);
+
+            var result = new string[valueCount];
+            for (int i = 0; i < valueCount; i++)
+            {
+                result[i] = str;
+            }
+            return result;
+        }
+
+        private static string[] CreateNonAsciiStrings(int valueCount, int encodedSize)
+        {
+            var str = ParseRawPrimitivesBenchmark.CreateNonAsciiStringWithEncodedSize(encodedSize);
+
+            var result = new string[valueCount];
+            for (int i = 0; i < valueCount; i++)
+            {
+                result[i] = str;
+            }
+            return result;
+        }
+
+        private static ByteString[] CreateByteStrings(int valueCount, int encodedSize)
+        {
+            var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize);
+
+            var result = new ByteString[valueCount];
+            for (int i = 0; i < valueCount; i++)
+            {
+                result[i] = ByteString.CopyFrom(Encoding.UTF8.GetBytes(str));
+            }
+            return result;
+        }
+    }
+}
diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
index 23894ad..fb053b2 100644
--- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
@@ -82,7 +82,7 @@
     [pbr::OriginalName("JSON_TEST")] JsonTest = 2,
     /// <summary>
     /// Similar to JSON_TEST. However, during parsing json, testee should ignore
-    /// unknown fields. This feature is optional. Each implementation can descide
+    /// unknown fields. This feature is optional. Each implementation can decide
     /// whether to support it.  See
     /// https://developers.google.com/protocol-buffers/docs/proto3#json_options
     /// for more detail.
@@ -107,23 +107,31 @@
   /// This will be known by message_type == "conformance.FailureSet", a conformance
   /// test should return a serialized FailureSet in protobuf_payload.
   /// </summary>
-  public sealed partial class FailureSet : pb::IMessage<FailureSet> {
+  public sealed partial class FailureSet : pb::IMessage<FailureSet>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FailureSet> _parser = new pb::MessageParser<FailureSet>(() => new FailureSet());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FailureSet> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FailureSet() {
       OnConstruction();
     }
@@ -131,12 +139,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FailureSet(FailureSet other) : this() {
       failure_ = other.failure_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FailureSet Clone() {
       return new FailureSet(this);
     }
@@ -147,16 +157,19 @@
         = pb::FieldCodec.ForString(10);
     private readonly pbc::RepeatedField<string> failure_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> Failure {
       get { return failure_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FailureSet);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FailureSet other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -169,6 +182,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= failure_.GetHashCode();
@@ -179,19 +193,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       failure_.WriteTo(output, _repeated_failure_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      failure_.WriteTo(ref output, _repeated_failure_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += failure_.CalculateSize(_repeated_failure_codec);
@@ -202,6 +234,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FailureSet other) {
       if (other == null) {
         return;
@@ -211,7 +244,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -224,8 +261,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            failure_.AddEntriesFrom(ref input, _repeated_failure_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -235,23 +292,31 @@
   ///   2. parse the protobuf or JSON payload in "payload" (which may fail)
   ///   3. if the parse succeeded, serialize the message in the requested format.
   /// </summary>
-  public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
+  public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ConformanceRequest() {
       OnConstruction();
     }
@@ -259,6 +324,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ConformanceRequest(ConformanceRequest other) : this() {
       requestedOutputFormat_ = other.requestedOutputFormat_;
       messageType_ = other.messageType_;
@@ -284,6 +350,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ConformanceRequest Clone() {
       return new ConformanceRequest(this);
     }
@@ -291,6 +358,7 @@
     /// <summary>Field number for the "protobuf_payload" field.</summary>
     public const int ProtobufPayloadFieldNumber = 1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString ProtobufPayload {
       get { return payloadCase_ == PayloadOneofCase.ProtobufPayload ? (pb::ByteString) payload_ : pb::ByteString.Empty; }
       set {
@@ -302,6 +370,7 @@
     /// <summary>Field number for the "json_payload" field.</summary>
     public const int JsonPayloadFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JsonPayload {
       get { return payloadCase_ == PayloadOneofCase.JsonPayload ? (string) payload_ : ""; }
       set {
@@ -316,6 +385,7 @@
     /// Google internal only.  Opensource testees just skip it.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JspbPayload {
       get { return payloadCase_ == PayloadOneofCase.JspbPayload ? (string) payload_ : ""; }
       set {
@@ -327,6 +397,7 @@
     /// <summary>Field number for the "text_payload" field.</summary>
     public const int TextPayloadFieldNumber = 8;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string TextPayload {
       get { return payloadCase_ == PayloadOneofCase.TextPayload ? (string) payload_ : ""; }
       set {
@@ -342,6 +413,7 @@
     /// Which format should the testee serialize its message to?
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Conformance.WireFormat RequestedOutputFormat {
       get { return requestedOutputFormat_; }
       set {
@@ -358,6 +430,7 @@
     /// protobuf_test_messages.proto2.TestAllTypesProto2.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string MessageType {
       get { return messageType_; }
       set {
@@ -370,10 +443,11 @@
     private global::Conformance.TestCategory testCategory_ = global::Conformance.TestCategory.UnspecifiedTest;
     /// <summary>
     /// Each test is given a specific test category. Some category may need
-    /// spedific support in testee programs. Refer to the definition of TestCategory
+    /// specific support in testee programs. Refer to the definition of TestCategory
     /// for more information.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Conformance.TestCategory TestCategory {
       get { return testCategory_; }
       set {
@@ -388,6 +462,7 @@
     /// Specify details for how to encode jspb.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Conformance.JspbEncodingConfig JspbEncodingOptions {
       get { return jspbEncodingOptions_; }
       set {
@@ -403,6 +478,7 @@
     /// unknown fields instead of ignore. This feature is optional.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool PrintUnknownFields {
       get { return printUnknownFields_; }
       set {
@@ -421,22 +497,26 @@
     }
     private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public PayloadOneofCase PayloadCase {
       get { return payloadCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPayload() {
       payloadCase_ = PayloadOneofCase.None;
       payload_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ConformanceRequest);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ConformanceRequest other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -458,6 +538,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
@@ -477,12 +558,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
         output.WriteRawTag(10);
         output.WriteBytes(ProtobufPayload);
@@ -522,9 +608,57 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
+        output.WriteRawTag(10);
+        output.WriteBytes(ProtobufPayload);
+      }
+      if (payloadCase_ == PayloadOneofCase.JsonPayload) {
+        output.WriteRawTag(18);
+        output.WriteString(JsonPayload);
+      }
+      if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) {
+        output.WriteRawTag(24);
+        output.WriteEnum((int) RequestedOutputFormat);
+      }
+      if (MessageType.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(MessageType);
+      }
+      if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) TestCategory);
+      }
+      if (jspbEncodingOptions_ != null) {
+        output.WriteRawTag(50);
+        output.WriteMessage(JspbEncodingOptions);
+      }
+      if (payloadCase_ == PayloadOneofCase.JspbPayload) {
+        output.WriteRawTag(58);
+        output.WriteString(JspbPayload);
+      }
+      if (payloadCase_ == PayloadOneofCase.TextPayload) {
+        output.WriteRawTag(66);
+        output.WriteString(TextPayload);
+      }
+      if (PrintUnknownFields != false) {
+        output.WriteRawTag(72);
+        output.WriteBool(PrintUnknownFields);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
@@ -561,6 +695,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ConformanceRequest other) {
       if (other == null) {
         return;
@@ -602,7 +737,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -650,30 +789,93 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            ProtobufPayload = input.ReadBytes();
+            break;
+          }
+          case 18: {
+            JsonPayload = input.ReadString();
+            break;
+          }
+          case 24: {
+            RequestedOutputFormat = (global::Conformance.WireFormat) input.ReadEnum();
+            break;
+          }
+          case 34: {
+            MessageType = input.ReadString();
+            break;
+          }
+          case 40: {
+            TestCategory = (global::Conformance.TestCategory) input.ReadEnum();
+            break;
+          }
+          case 50: {
+            if (jspbEncodingOptions_ == null) {
+              JspbEncodingOptions = new global::Conformance.JspbEncodingConfig();
+            }
+            input.ReadMessage(JspbEncodingOptions);
+            break;
+          }
+          case 58: {
+            JspbPayload = input.ReadString();
+            break;
+          }
+          case 66: {
+            TextPayload = input.ReadString();
+            break;
+          }
+          case 72: {
+            PrintUnknownFields = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Represents a single test case's output.
   /// </summary>
-  public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
+  public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ConformanceResponse() {
       OnConstruction();
     }
@@ -681,6 +883,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ConformanceResponse(ConformanceResponse other) : this() {
       switch (other.ResultCase) {
         case ResultOneofCase.ParseError:
@@ -713,6 +916,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ConformanceResponse Clone() {
       return new ConformanceResponse(this);
     }
@@ -727,6 +931,7 @@
     /// test.  Some of the test cases are intentionally invalid input.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string ParseError {
       get { return resultCase_ == ResultOneofCase.ParseError ? (string) result_ : ""; }
       set {
@@ -743,6 +948,7 @@
     /// this field.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string SerializeError {
       get { return resultCase_ == ResultOneofCase.SerializeError ? (string) result_ : ""; }
       set {
@@ -759,6 +965,7 @@
     /// about the failure.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string RuntimeError {
       get { return resultCase_ == ResultOneofCase.RuntimeError ? (string) result_ : ""; }
       set {
@@ -774,6 +981,7 @@
     /// protobuf, serialize it to protobuf and set it in this field.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString ProtobufPayload {
       get { return resultCase_ == ResultOneofCase.ProtobufPayload ? (pb::ByteString) result_ : pb::ByteString.Empty; }
       set {
@@ -789,6 +997,7 @@
     /// serialize to JSON and set it in this field.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JsonPayload {
       get { return resultCase_ == ResultOneofCase.JsonPayload ? (string) result_ : ""; }
       set {
@@ -804,6 +1013,7 @@
     /// wasn't supported, like JSON input/output.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Skipped {
       get { return resultCase_ == ResultOneofCase.Skipped ? (string) result_ : ""; }
       set {
@@ -820,6 +1030,7 @@
     /// format. Opensource testees can just skip it.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JspbPayload {
       get { return resultCase_ == ResultOneofCase.JspbPayload ? (string) result_ : ""; }
       set {
@@ -835,6 +1046,7 @@
     /// TEXT_FORMAT, serialize to TEXT_FORMAT and set it in this field.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string TextPayload {
       get { return resultCase_ == ResultOneofCase.TextPayload ? (string) result_ : ""; }
       set {
@@ -858,22 +1070,26 @@
     }
     private ResultOneofCase resultCase_ = ResultOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ResultOneofCase ResultCase {
       get { return resultCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearResult() {
       resultCase_ = ResultOneofCase.None;
       result_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ConformanceResponse);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ConformanceResponse other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -894,6 +1110,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (resultCase_ == ResultOneofCase.ParseError) hash ^= ParseError.GetHashCode();
@@ -912,12 +1129,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (resultCase_ == ResultOneofCase.ParseError) {
         output.WriteRawTag(10);
         output.WriteString(ParseError);
@@ -953,9 +1175,53 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (resultCase_ == ResultOneofCase.ParseError) {
+        output.WriteRawTag(10);
+        output.WriteString(ParseError);
+      }
+      if (resultCase_ == ResultOneofCase.RuntimeError) {
+        output.WriteRawTag(18);
+        output.WriteString(RuntimeError);
+      }
+      if (resultCase_ == ResultOneofCase.ProtobufPayload) {
+        output.WriteRawTag(26);
+        output.WriteBytes(ProtobufPayload);
+      }
+      if (resultCase_ == ResultOneofCase.JsonPayload) {
+        output.WriteRawTag(34);
+        output.WriteString(JsonPayload);
+      }
+      if (resultCase_ == ResultOneofCase.Skipped) {
+        output.WriteRawTag(42);
+        output.WriteString(Skipped);
+      }
+      if (resultCase_ == ResultOneofCase.SerializeError) {
+        output.WriteRawTag(50);
+        output.WriteString(SerializeError);
+      }
+      if (resultCase_ == ResultOneofCase.JspbPayload) {
+        output.WriteRawTag(58);
+        output.WriteString(JspbPayload);
+      }
+      if (resultCase_ == ResultOneofCase.TextPayload) {
+        output.WriteRawTag(66);
+        output.WriteString(TextPayload);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (resultCase_ == ResultOneofCase.ParseError) {
@@ -989,6 +1255,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ConformanceResponse other) {
       if (other == null) {
         return;
@@ -1024,7 +1291,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1065,30 +1336,86 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            ParseError = input.ReadString();
+            break;
+          }
+          case 18: {
+            RuntimeError = input.ReadString();
+            break;
+          }
+          case 26: {
+            ProtobufPayload = input.ReadBytes();
+            break;
+          }
+          case 34: {
+            JsonPayload = input.ReadString();
+            break;
+          }
+          case 42: {
+            Skipped = input.ReadString();
+            break;
+          }
+          case 50: {
+            SerializeError = input.ReadString();
+            break;
+          }
+          case 58: {
+            JspbPayload = input.ReadString();
+            break;
+          }
+          case 66: {
+            TextPayload = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Encoding options for jspb format.
   /// </summary>
-  public sealed partial class JspbEncodingConfig : pb::IMessage<JspbEncodingConfig> {
+  public sealed partial class JspbEncodingConfig : pb::IMessage<JspbEncodingConfig>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<JspbEncodingConfig> _parser = new pb::MessageParser<JspbEncodingConfig>(() => new JspbEncodingConfig());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<JspbEncodingConfig> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public JspbEncodingConfig() {
       OnConstruction();
     }
@@ -1096,12 +1423,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public JspbEncodingConfig(JspbEncodingConfig other) : this() {
       useJspbArrayAnyFormat_ = other.useJspbArrayAnyFormat_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public JspbEncodingConfig Clone() {
       return new JspbEncodingConfig(this);
     }
@@ -1113,6 +1442,7 @@
     /// Encode the value field of Any as jspb array if true, otherwise binary.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool UseJspbArrayAnyFormat {
       get { return useJspbArrayAnyFormat_; }
       set {
@@ -1121,11 +1451,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as JspbEncodingConfig);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(JspbEncodingConfig other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1138,6 +1470,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (UseJspbArrayAnyFormat != false) hash ^= UseJspbArrayAnyFormat.GetHashCode();
@@ -1148,12 +1481,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (UseJspbArrayAnyFormat != false) {
         output.WriteRawTag(8);
         output.WriteBool(UseJspbArrayAnyFormat);
@@ -1161,9 +1499,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (UseJspbArrayAnyFormat != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(UseJspbArrayAnyFormat);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (UseJspbArrayAnyFormat != false) {
@@ -1176,6 +1530,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(JspbEncodingConfig other) {
       if (other == null) {
         return;
@@ -1187,7 +1542,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1200,8 +1559,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            UseJspbArrayAnyFormat = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs
index d1093ab..d721ecf 100644
--- a/csharp/src/Google.Protobuf.Conformance/Program.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Program.cs
@@ -83,44 +83,52 @@
 
         private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
         {
+            ExtensionRegistry proto2ExtensionRegistry = new ExtensionRegistry
+            {
+                ProtobufTestMessages.Proto2.TestMessagesProto2Extensions.ExtensionInt32,
+                ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Extensions.MessageSetExtension,
+                ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Extensions.MessageSetExtension
+            };
             IMessage message;
             try
             {
                 switch (request.PayloadCase)
                 {
                     case ConformanceRequest.PayloadOneofCase.JsonPayload:
-                        if (request.TestCategory == global::Conformance.TestCategory.JsonIgnoreUnknownParsingTest) {
+                        if (request.TestCategory == global::Conformance.TestCategory.JsonIgnoreUnknownParsingTest)
+                        {
                             return new ConformanceResponse { Skipped = "CSharp doesn't support skipping unknown fields in json parsing." };
                         }
                         var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry));
-                        message = parser.Parse<ProtobufTestMessages.Proto3.TestAllTypesProto3>(request.JsonPayload);
+                        switch (request.MessageType)
+                        {
+                            case "protobuf_test_messages.proto3.TestAllTypesProto3":
+                                message = parser.Parse<ProtobufTestMessages.Proto3.TestAllTypesProto3>(request.JsonPayload);
+                                break;
+                            case "protobuf_test_messages.proto2.TestAllTypesProto2":
+                                message = parser.Parse<ProtobufTestMessages.Proto2.TestAllTypesProto2>(request.JsonPayload);
+                                break;
+                            default:
+                                throw new Exception($" Protobuf request doesn't have specific payload type ({request.MessageType})");
+                        }
                         break;
                     case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
-                    {
-                        if (request.MessageType.Equals("protobuf_test_messages.proto3.TestAllTypesProto3"))
+                        switch (request.MessageType)
                         {
-                            message = ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(request.ProtobufPayload);
-                        }
-                        else if (request.MessageType.Equals("protobuf_test_messages.proto2.TestAllTypesProto2"))
-                        {
-                            ExtensionRegistry registry = new ExtensionRegistry()
-                            {
-                                ProtobufTestMessages.Proto2.TestMessagesProto2Extensions.ExtensionInt32,
-                                ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Extensions.MessageSetExtension,
-                                ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Extensions.MessageSetExtension
-                            };
-                            message = ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser.WithExtensionRegistry(registry).ParseFrom(request.ProtobufPayload);
-                        }
-                        else
-                        {
-                            throw new Exception(" Protobuf request doesn't have specific payload type");
+                            case "protobuf_test_messages.proto3.TestAllTypesProto3":
+                                message = ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(request.ProtobufPayload);
+                                break;
+                            case "protobuf_test_messages.proto2.TestAllTypesProto2":
+                                message = ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser
+                                    .WithExtensionRegistry(proto2ExtensionRegistry)
+                                    .ParseFrom(request.ProtobufPayload);
+                                break;
+                            default:
+                                throw new Exception($" Protobuf request doesn't have specific payload type ({request.MessageType})");
                         }
                         break;
-                    }
 					case ConformanceRequest.PayloadOneofCase.TextPayload:
-					{
 						return new ConformanceResponse { Skipped = "CSharp doesn't support text format" };
-					}
                     default:
                         throw new Exception("Unsupported request payload: " + request.PayloadCase);
                 }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj b/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj
index 5b70580..9f2ba6b 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj
@@ -6,11 +6,10 @@
     and without the internal visibility from the test project (all of which have caused issues in the past).

   -->

   <PropertyGroup>

-    <TargetFrameworks>net45;netstandard1.0;netstandard2.0</TargetFrameworks>

+    <TargetFrameworks>net45;netstandard1.1;netstandard2.0</TargetFrameworks>

     <LangVersion>3.0</LangVersion>

     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>

     <SignAssembly>true</SignAssembly>

-    <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>

     <IsPackable>False</IsPackable>

   </PropertyGroup>

 

diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
index 197b197..4791b73 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
@@ -176,23 +176,31 @@
   /// <summary>
   /// Tests maps.
   /// </summary>
-  public sealed partial class TestMap : pb::IMessage<TestMap> {
+  public sealed partial class TestMap : pb::IMessage<TestMap>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMap> _parser = new pb::MessageParser<TestMap>(() => new TestMap());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMap> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMap() {
       OnConstruction();
     }
@@ -200,6 +208,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMap(TestMap other) : this() {
       mapInt32Int32_ = other.mapInt32Int32_.Clone();
       mapInt64Int64_ = other.mapInt64Int64_.Clone();
@@ -222,6 +231,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMap Clone() {
       return new TestMap(this);
     }
@@ -232,6 +242,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10);
     private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapInt32Int32 {
       get { return mapInt32Int32_; }
     }
@@ -242,6 +253,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 18);
     private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapInt64Int64 {
       get { return mapInt64Int64_; }
     }
@@ -252,6 +264,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 26);
     private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapUint32Uint32 {
       get { return mapUint32Uint32_; }
     }
@@ -262,6 +275,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 34);
     private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapUint64Uint64 {
       get { return mapUint64Uint64_; }
     }
@@ -272,6 +286,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 42);
     private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSint32Sint32 {
       get { return mapSint32Sint32_; }
     }
@@ -282,6 +297,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 50);
     private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSint64Sint64 {
       get { return mapSint64Sint64_; }
     }
@@ -292,6 +308,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 58);
     private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapFixed32Fixed32 {
       get { return mapFixed32Fixed32_; }
     }
@@ -302,6 +319,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 66);
     private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
       get { return mapFixed64Fixed64_; }
     }
@@ -312,6 +330,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 74);
     private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSfixed32Sfixed32 {
       get { return mapSfixed32Sfixed32_; }
     }
@@ -322,6 +341,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 82);
     private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSfixed64Sfixed64 {
       get { return mapSfixed64Sfixed64_; }
     }
@@ -332,6 +352,7 @@
         = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 90);
     private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, float> MapInt32Float {
       get { return mapInt32Float_; }
     }
@@ -342,6 +363,7 @@
         = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 98);
     private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, double> MapInt32Double {
       get { return mapInt32Double_; }
     }
@@ -352,6 +374,7 @@
         = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 106);
     private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<bool, bool> MapBoolBool {
       get { return mapBoolBool_; }
     }
@@ -362,6 +385,7 @@
         = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 114);
     private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, string> MapStringString {
       get { return mapStringString_; }
     }
@@ -372,6 +396,7 @@
         = new pbc::MapField<int, pb::ByteString>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForBytes(18, pb::ByteString.Empty), 122);
     private readonly pbc::MapField<int, pb::ByteString> mapInt32Bytes_ = new pbc::MapField<int, pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, pb::ByteString> MapInt32Bytes {
       get { return mapInt32Bytes_; }
     }
@@ -382,6 +407,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x, global::Google.Protobuf.TestProtos.MapEnum.Foo), 130);
     private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> mapInt32Enum_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> MapInt32Enum {
       get { return mapInt32Enum_; }
     }
@@ -392,16 +418,19 @@
         = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 138);
     private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> mapInt32ForeignMessage_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> MapInt32ForeignMessage {
       get { return mapInt32ForeignMessage_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMap);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMap other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -430,6 +459,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= MapInt32Int32.GetHashCode();
@@ -456,12 +486,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec);
       mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec);
       mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec);
@@ -482,9 +517,38 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec);
+      mapStringString_.WriteTo(ref output, _map_mapStringString_codec);
+      mapInt32Bytes_.WriteTo(ref output, _map_mapInt32Bytes_codec);
+      mapInt32Enum_.WriteTo(ref output, _map_mapInt32Enum_codec);
+      mapInt32ForeignMessage_.WriteTo(ref output, _map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec);
@@ -511,6 +575,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMap other) {
       if (other == null) {
         return;
@@ -536,7 +601,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -613,27 +682,119 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 18: {
+            mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 26: {
+            mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 34: {
+            mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 42: {
+            mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 50: {
+            mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 58: {
+            mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 66: {
+            mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 74: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 82: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 90: {
+            mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 98: {
+            mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 106: {
+            mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 114: {
+            mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec);
+            break;
+          }
+          case 122: {
+            mapInt32Bytes_.AddEntriesFrom(ref input, _map_mapInt32Bytes_codec);
+            break;
+          }
+          case 130: {
+            mapInt32Enum_.AddEntriesFrom(ref input, _map_mapInt32Enum_codec);
+            break;
+          }
+          case 138: {
+            mapInt32ForeignMessage_.AddEntriesFrom(ref input, _map_mapInt32ForeignMessage_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestMapSubmessage : pb::IMessage<TestMapSubmessage> {
+  public sealed partial class TestMapSubmessage : pb::IMessage<TestMapSubmessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMapSubmessage> _parser = new pb::MessageParser<TestMapSubmessage>(() => new TestMapSubmessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMapSubmessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMapSubmessage() {
       OnConstruction();
     }
@@ -641,12 +802,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMapSubmessage(TestMapSubmessage other) : this() {
       testMap_ = other.testMap_ != null ? other.testMap_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMapSubmessage Clone() {
       return new TestMapSubmessage(this);
     }
@@ -655,6 +818,7 @@
     public const int TestMapFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.TestMap testMap_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestMap TestMap {
       get { return testMap_; }
       set {
@@ -663,11 +827,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMapSubmessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMapSubmessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -680,6 +846,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (testMap_ != null) hash ^= TestMap.GetHashCode();
@@ -690,12 +857,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (testMap_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(TestMap);
@@ -703,9 +875,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (testMap_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(TestMap);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (testMap_ != null) {
@@ -718,6 +906,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMapSubmessage other) {
       if (other == null) {
         return;
@@ -732,7 +921,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -748,27 +941,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (testMap_ == null) {
+              TestMap = new global::Google.Protobuf.TestProtos.TestMap();
+            }
+            input.ReadMessage(TestMap);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestMessageMap : pb::IMessage<TestMessageMap> {
+  public sealed partial class TestMessageMap : pb::IMessage<TestMessageMap>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMessageMap> _parser = new pb::MessageParser<TestMessageMap>(() => new TestMessageMap());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMessageMap> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMessageMap() {
       OnConstruction();
     }
@@ -776,12 +1000,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMessageMap(TestMessageMap other) : this() {
       mapInt32Message_ = other.mapInt32Message_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMessageMap Clone() {
       return new TestMessageMap(this);
     }
@@ -792,16 +1018,19 @@
         = new pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.TestAllTypes.Parser), 10);
     private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes> mapInt32Message_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes> MapInt32Message {
       get { return mapInt32Message_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMessageMap);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMessageMap other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -814,6 +1043,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= MapInt32Message.GetHashCode();
@@ -824,19 +1054,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      mapInt32Message_.WriteTo(ref output, _map_mapInt32Message_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec);
@@ -847,6 +1095,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMessageMap other) {
       if (other == null) {
         return;
@@ -856,7 +1105,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -869,30 +1122,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            mapInt32Message_.AddEntriesFrom(ref input, _map_mapInt32Message_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Two map fields share the same entry default instance.
   /// </summary>
-  public sealed partial class TestSameTypeMap : pb::IMessage<TestSameTypeMap> {
+  public sealed partial class TestSameTypeMap : pb::IMessage<TestSameTypeMap>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestSameTypeMap> _parser = new pb::MessageParser<TestSameTypeMap>(() => new TestSameTypeMap());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestSameTypeMap> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestSameTypeMap() {
       OnConstruction();
     }
@@ -900,6 +1181,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestSameTypeMap(TestSameTypeMap other) : this() {
       map1_ = other.map1_.Clone();
       map2_ = other.map2_.Clone();
@@ -907,6 +1189,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestSameTypeMap Clone() {
       return new TestSameTypeMap(this);
     }
@@ -917,6 +1200,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10);
     private readonly pbc::MapField<int, int> map1_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> Map1 {
       get { return map1_; }
     }
@@ -927,16 +1211,19 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 18);
     private readonly pbc::MapField<int, int> map2_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> Map2 {
       get { return map2_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestSameTypeMap);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestSameTypeMap other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -950,6 +1237,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Map1.GetHashCode();
@@ -961,20 +1249,39 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       map1_.WriteTo(output, _map_map1_codec);
       map2_.WriteTo(output, _map_map2_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      map1_.WriteTo(ref output, _map_map1_codec);
+      map2_.WriteTo(ref output, _map_map2_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += map1_.CalculateSize(_map_map1_codec);
@@ -986,6 +1293,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestSameTypeMap other) {
       if (other == null) {
         return;
@@ -996,7 +1304,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1013,27 +1325,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            map1_.AddEntriesFrom(ref input, _map_map1_codec);
+            break;
+          }
+          case 18: {
+            map2_.AddEntriesFrom(ref input, _map_map2_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestArenaMap : pb::IMessage<TestArenaMap> {
+  public sealed partial class TestArenaMap : pb::IMessage<TestArenaMap>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestArenaMap> _parser = new pb::MessageParser<TestArenaMap>(() => new TestArenaMap());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestArenaMap> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestArenaMap() {
       OnConstruction();
     }
@@ -1041,6 +1385,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestArenaMap(TestArenaMap other) : this() {
       mapInt32Int32_ = other.mapInt32Int32_.Clone();
       mapInt64Int64_ = other.mapInt64Int64_.Clone();
@@ -1061,6 +1406,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestArenaMap Clone() {
       return new TestArenaMap(this);
     }
@@ -1071,6 +1417,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10);
     private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapInt32Int32 {
       get { return mapInt32Int32_; }
     }
@@ -1081,6 +1428,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 18);
     private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapInt64Int64 {
       get { return mapInt64Int64_; }
     }
@@ -1091,6 +1439,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 26);
     private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapUint32Uint32 {
       get { return mapUint32Uint32_; }
     }
@@ -1101,6 +1450,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 34);
     private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapUint64Uint64 {
       get { return mapUint64Uint64_; }
     }
@@ -1111,6 +1461,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 42);
     private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSint32Sint32 {
       get { return mapSint32Sint32_; }
     }
@@ -1121,6 +1472,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 50);
     private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSint64Sint64 {
       get { return mapSint64Sint64_; }
     }
@@ -1131,6 +1483,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 58);
     private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapFixed32Fixed32 {
       get { return mapFixed32Fixed32_; }
     }
@@ -1141,6 +1494,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 66);
     private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
       get { return mapFixed64Fixed64_; }
     }
@@ -1151,6 +1505,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 74);
     private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSfixed32Sfixed32 {
       get { return mapSfixed32Sfixed32_; }
     }
@@ -1161,6 +1516,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 82);
     private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSfixed64Sfixed64 {
       get { return mapSfixed64Sfixed64_; }
     }
@@ -1171,6 +1527,7 @@
         = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 90);
     private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, float> MapInt32Float {
       get { return mapInt32Float_; }
     }
@@ -1181,6 +1538,7 @@
         = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 98);
     private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, double> MapInt32Double {
       get { return mapInt32Double_; }
     }
@@ -1191,6 +1549,7 @@
         = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 106);
     private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<bool, bool> MapBoolBool {
       get { return mapBoolBool_; }
     }
@@ -1201,6 +1560,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x, global::Google.Protobuf.TestProtos.MapEnum.Foo), 114);
     private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> mapInt32Enum_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> MapInt32Enum {
       get { return mapInt32Enum_; }
     }
@@ -1211,16 +1571,19 @@
         = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 122);
     private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> mapInt32ForeignMessage_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> MapInt32ForeignMessage {
       get { return mapInt32ForeignMessage_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestArenaMap);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestArenaMap other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1247,6 +1610,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= MapInt32Int32.GetHashCode();
@@ -1271,12 +1635,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec);
       mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec);
       mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec);
@@ -1295,9 +1664,36 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec);
+      mapInt32Enum_.WriteTo(ref output, _map_mapInt32Enum_codec);
+      mapInt32ForeignMessage_.WriteTo(ref output, _map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec);
@@ -1322,6 +1718,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestArenaMap other) {
       if (other == null) {
         return;
@@ -1345,7 +1742,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1414,31 +1815,115 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 18: {
+            mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 26: {
+            mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 34: {
+            mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 42: {
+            mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 50: {
+            mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 58: {
+            mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 66: {
+            mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 74: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 82: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 90: {
+            mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 98: {
+            mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 106: {
+            mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 114: {
+            mapInt32Enum_.AddEntriesFrom(ref input, _map_mapInt32Enum_codec);
+            break;
+          }
+          case 122: {
+            mapInt32ForeignMessage_.AddEntriesFrom(ref input, _map_mapInt32ForeignMessage_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Previously, message containing enum called Type cannot be used as value of
   /// map field.
   /// </summary>
-  public sealed partial class MessageContainingEnumCalledType : pb::IMessage<MessageContainingEnumCalledType> {
+  public sealed partial class MessageContainingEnumCalledType : pb::IMessage<MessageContainingEnumCalledType>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MessageContainingEnumCalledType> _parser = new pb::MessageParser<MessageContainingEnumCalledType>(() => new MessageContainingEnumCalledType());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MessageContainingEnumCalledType> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageContainingEnumCalledType() {
       OnConstruction();
     }
@@ -1446,12 +1931,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() {
       type_ = other.type_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageContainingEnumCalledType Clone() {
       return new MessageContainingEnumCalledType(this);
     }
@@ -1462,16 +1949,19 @@
         = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser), 10);
     private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> type_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> Type {
       get { return type_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MessageContainingEnumCalledType);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MessageContainingEnumCalledType other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1484,6 +1974,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Type.GetHashCode();
@@ -1494,19 +1985,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       type_.WriteTo(output, _map_type_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      type_.WriteTo(ref output, _map_type_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += type_.CalculateSize(_map_type_codec);
@@ -1517,6 +2026,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MessageContainingEnumCalledType other) {
       if (other == null) {
         return;
@@ -1526,7 +2036,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1539,11 +2053,32 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            type_.AddEntriesFrom(ref input, _map_type_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the MessageContainingEnumCalledType message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum Type {
         [pbr::OriginalName("TYPE_FOO")] Foo = 0,
@@ -1557,23 +2092,31 @@
   /// <summary>
   /// Previously, message cannot contain map field called "entry".
   /// </summary>
-  public sealed partial class MessageContainingMapCalledEntry : pb::IMessage<MessageContainingMapCalledEntry> {
+  public sealed partial class MessageContainingMapCalledEntry : pb::IMessage<MessageContainingMapCalledEntry>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MessageContainingMapCalledEntry> _parser = new pb::MessageParser<MessageContainingMapCalledEntry>(() => new MessageContainingMapCalledEntry());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MessageContainingMapCalledEntry> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageContainingMapCalledEntry() {
       OnConstruction();
     }
@@ -1581,12 +2124,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() {
       entry_ = other.entry_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageContainingMapCalledEntry Clone() {
       return new MessageContainingMapCalledEntry(this);
     }
@@ -1597,16 +2142,19 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10);
     private readonly pbc::MapField<int, int> entry_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> Entry {
       get { return entry_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MessageContainingMapCalledEntry);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MessageContainingMapCalledEntry other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1619,6 +2167,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Entry.GetHashCode();
@@ -1629,19 +2178,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       entry_.WriteTo(output, _map_entry_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      entry_.WriteTo(ref output, _map_entry_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += entry_.CalculateSize(_map_entry_codec);
@@ -1652,6 +2219,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MessageContainingMapCalledEntry other) {
       if (other == null) {
         return;
@@ -1661,7 +2229,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1674,8 +2246,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            entry_.AddEntriesFrom(ref input, _map_entry_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
index 350fb7c..48f9b80 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
@@ -244,7 +244,11 @@
   /// could trigger bugs that occur in any message type in this file.  We verify
   /// this stays true in a unit test.
   /// </summary>
-  public sealed partial class TestAllTypesProto2 : pb::IExtendableMessage<TestAllTypesProto2> {
+  public sealed partial class TestAllTypesProto2 : pb::IExtendableMessage<TestAllTypesProto2>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestAllTypesProto2> _parser = new pb::MessageParser<TestAllTypesProto2>(() => new TestAllTypesProto2());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestAllTypesProto2> _extensions;
@@ -252,19 +256,23 @@
     private int _hasBits0;
     private int _hasBits1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestAllTypesProto2> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypesProto2() {
       OnConstruction();
     }
@@ -272,6 +280,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypesProto2(TestAllTypesProto2 other) : this() {
       _hasBits0 = other._hasBits0;
       _hasBits1 = other._hasBits1;
@@ -290,13 +299,13 @@
       optionalBool_ = other.optionalBool_;
       optionalString_ = other.optionalString_;
       optionalBytes_ = other.optionalBytes_;
-      optionalNestedMessage_ = other.HasOptionalNestedMessage ? other.optionalNestedMessage_.Clone() : null;
-      optionalForeignMessage_ = other.HasOptionalForeignMessage ? other.optionalForeignMessage_.Clone() : null;
+      optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
+      optionalForeignMessage_ = other.optionalForeignMessage_ != null ? other.optionalForeignMessage_.Clone() : null;
       optionalNestedEnum_ = other.optionalNestedEnum_;
       optionalForeignEnum_ = other.optionalForeignEnum_;
       optionalStringPiece_ = other.optionalStringPiece_;
       optionalCord_ = other.optionalCord_;
-      recursiveMessage_ = other.HasRecursiveMessage ? other.recursiveMessage_.Clone() : null;
+      recursiveMessage_ = other.recursiveMessage_ != null ? other.recursiveMessage_.Clone() : null;
       repeatedInt32_ = other.repeatedInt32_.Clone();
       repeatedInt64_ = other.repeatedInt64_.Clone();
       repeatedUint32_ = other.repeatedUint32_.Clone();
@@ -419,6 +428,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypesProto2 Clone() {
       return new TestAllTypesProto2(this);
     }
@@ -432,6 +442,7 @@
     /// Singular
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalInt32 {
       get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } }
       set {
@@ -441,11 +452,13 @@
     }
     /// <summary>Gets whether the "optional_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalInt32 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "optional_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalInt32() {
       _hasBits0 &= ~1;
     }
@@ -456,6 +469,7 @@
 
     private long optionalInt64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalInt64 {
       get { if ((_hasBits0 & 2) != 0) { return optionalInt64_; } else { return OptionalInt64DefaultValue; } }
       set {
@@ -465,11 +479,13 @@
     }
     /// <summary>Gets whether the "optional_int64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalInt64 {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "optional_int64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalInt64() {
       _hasBits0 &= ~2;
     }
@@ -480,6 +496,7 @@
 
     private uint optionalUint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OptionalUint32 {
       get { if ((_hasBits0 & 4) != 0) { return optionalUint32_; } else { return OptionalUint32DefaultValue; } }
       set {
@@ -489,11 +506,13 @@
     }
     /// <summary>Gets whether the "optional_uint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalUint32 {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "optional_uint32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalUint32() {
       _hasBits0 &= ~4;
     }
@@ -504,6 +523,7 @@
 
     private ulong optionalUint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OptionalUint64 {
       get { if ((_hasBits0 & 8) != 0) { return optionalUint64_; } else { return OptionalUint64DefaultValue; } }
       set {
@@ -513,11 +533,13 @@
     }
     /// <summary>Gets whether the "optional_uint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalUint64 {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "optional_uint64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalUint64() {
       _hasBits0 &= ~8;
     }
@@ -528,6 +550,7 @@
 
     private int optionalSint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalSint32 {
       get { if ((_hasBits0 & 16) != 0) { return optionalSint32_; } else { return OptionalSint32DefaultValue; } }
       set {
@@ -537,11 +560,13 @@
     }
     /// <summary>Gets whether the "optional_sint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSint32 {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "optional_sint32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSint32() {
       _hasBits0 &= ~16;
     }
@@ -552,6 +577,7 @@
 
     private long optionalSint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalSint64 {
       get { if ((_hasBits0 & 32) != 0) { return optionalSint64_; } else { return OptionalSint64DefaultValue; } }
       set {
@@ -561,11 +587,13 @@
     }
     /// <summary>Gets whether the "optional_sint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSint64 {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "optional_sint64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSint64() {
       _hasBits0 &= ~32;
     }
@@ -576,6 +604,7 @@
 
     private uint optionalFixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OptionalFixed32 {
       get { if ((_hasBits0 & 64) != 0) { return optionalFixed32_; } else { return OptionalFixed32DefaultValue; } }
       set {
@@ -585,11 +614,13 @@
     }
     /// <summary>Gets whether the "optional_fixed32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalFixed32 {
       get { return (_hasBits0 & 64) != 0; }
     }
     /// <summary>Clears the value of the "optional_fixed32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalFixed32() {
       _hasBits0 &= ~64;
     }
@@ -600,6 +631,7 @@
 
     private ulong optionalFixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OptionalFixed64 {
       get { if ((_hasBits0 & 128) != 0) { return optionalFixed64_; } else { return OptionalFixed64DefaultValue; } }
       set {
@@ -609,11 +641,13 @@
     }
     /// <summary>Gets whether the "optional_fixed64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalFixed64 {
       get { return (_hasBits0 & 128) != 0; }
     }
     /// <summary>Clears the value of the "optional_fixed64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalFixed64() {
       _hasBits0 &= ~128;
     }
@@ -624,6 +658,7 @@
 
     private int optionalSfixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalSfixed32 {
       get { if ((_hasBits0 & 256) != 0) { return optionalSfixed32_; } else { return OptionalSfixed32DefaultValue; } }
       set {
@@ -633,11 +668,13 @@
     }
     /// <summary>Gets whether the "optional_sfixed32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSfixed32 {
       get { return (_hasBits0 & 256) != 0; }
     }
     /// <summary>Clears the value of the "optional_sfixed32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSfixed32() {
       _hasBits0 &= ~256;
     }
@@ -648,6 +685,7 @@
 
     private long optionalSfixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalSfixed64 {
       get { if ((_hasBits0 & 512) != 0) { return optionalSfixed64_; } else { return OptionalSfixed64DefaultValue; } }
       set {
@@ -657,11 +695,13 @@
     }
     /// <summary>Gets whether the "optional_sfixed64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSfixed64 {
       get { return (_hasBits0 & 512) != 0; }
     }
     /// <summary>Clears the value of the "optional_sfixed64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSfixed64() {
       _hasBits0 &= ~512;
     }
@@ -672,6 +712,7 @@
 
     private float optionalFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float OptionalFloat {
       get { if ((_hasBits0 & 1024) != 0) { return optionalFloat_; } else { return OptionalFloatDefaultValue; } }
       set {
@@ -681,11 +722,13 @@
     }
     /// <summary>Gets whether the "optional_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalFloat {
       get { return (_hasBits0 & 1024) != 0; }
     }
     /// <summary>Clears the value of the "optional_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalFloat() {
       _hasBits0 &= ~1024;
     }
@@ -696,6 +739,7 @@
 
     private double optionalDouble_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double OptionalDouble {
       get { if ((_hasBits0 & 2048) != 0) { return optionalDouble_; } else { return OptionalDoubleDefaultValue; } }
       set {
@@ -705,11 +749,13 @@
     }
     /// <summary>Gets whether the "optional_double" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalDouble {
       get { return (_hasBits0 & 2048) != 0; }
     }
     /// <summary>Clears the value of the "optional_double" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalDouble() {
       _hasBits0 &= ~2048;
     }
@@ -720,6 +766,7 @@
 
     private bool optionalBool_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool OptionalBool {
       get { if ((_hasBits0 & 4096) != 0) { return optionalBool_; } else { return OptionalBoolDefaultValue; } }
       set {
@@ -729,11 +776,13 @@
     }
     /// <summary>Gets whether the "optional_bool" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalBool {
       get { return (_hasBits0 & 4096) != 0; }
     }
     /// <summary>Clears the value of the "optional_bool" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalBool() {
       _hasBits0 &= ~4096;
     }
@@ -744,6 +793,7 @@
 
     private string optionalString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalString {
       get { return optionalString_ ?? OptionalStringDefaultValue; }
       set {
@@ -752,11 +802,13 @@
     }
     /// <summary>Gets whether the "optional_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalString {
       get { return optionalString_ != null; }
     }
     /// <summary>Clears the value of the "optional_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalString() {
       optionalString_ = null;
     }
@@ -767,6 +819,7 @@
 
     private pb::ByteString optionalBytes_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OptionalBytes {
       get { return optionalBytes_ ?? OptionalBytesDefaultValue; }
       set {
@@ -775,11 +828,13 @@
     }
     /// <summary>Gets whether the "optional_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalBytes {
       get { return optionalBytes_ != null; }
     }
     /// <summary>Clears the value of the "optional_bytes" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalBytes() {
       optionalBytes_ = null;
     }
@@ -788,43 +843,25 @@
     public const int OptionalNestedMessageFieldNumber = 18;
     private global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage optionalNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage OptionalNestedMessage {
       get { return optionalNestedMessage_; }
       set {
         optionalNestedMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_nested_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalNestedMessage {
-      get { return optionalNestedMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_nested_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalNestedMessage() {
-      optionalNestedMessage_ = null;
-    }
 
     /// <summary>Field number for the "optional_foreign_message" field.</summary>
     public const int OptionalForeignMessageFieldNumber = 19;
     private global::ProtobufTestMessages.Proto2.ForeignMessageProto2 optionalForeignMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.ForeignMessageProto2 OptionalForeignMessage {
       get { return optionalForeignMessage_; }
       set {
         optionalForeignMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_foreign_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalForeignMessage {
-      get { return optionalForeignMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_foreign_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalForeignMessage() {
-      optionalForeignMessage_ = null;
-    }
 
     /// <summary>Field number for the "optional_nested_enum" field.</summary>
     public const int OptionalNestedEnumFieldNumber = 21;
@@ -832,6 +869,7 @@
 
     private global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum optionalNestedEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum OptionalNestedEnum {
       get { if ((_hasBits0 & 8192) != 0) { return optionalNestedEnum_; } else { return OptionalNestedEnumDefaultValue; } }
       set {
@@ -841,11 +879,13 @@
     }
     /// <summary>Gets whether the "optional_nested_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalNestedEnum {
       get { return (_hasBits0 & 8192) != 0; }
     }
     /// <summary>Clears the value of the "optional_nested_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalNestedEnum() {
       _hasBits0 &= ~8192;
     }
@@ -856,6 +896,7 @@
 
     private global::ProtobufTestMessages.Proto2.ForeignEnumProto2 optionalForeignEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.ForeignEnumProto2 OptionalForeignEnum {
       get { if ((_hasBits0 & 16384) != 0) { return optionalForeignEnum_; } else { return OptionalForeignEnumDefaultValue; } }
       set {
@@ -865,11 +906,13 @@
     }
     /// <summary>Gets whether the "optional_foreign_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalForeignEnum {
       get { return (_hasBits0 & 16384) != 0; }
     }
     /// <summary>Clears the value of the "optional_foreign_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalForeignEnum() {
       _hasBits0 &= ~16384;
     }
@@ -880,6 +923,7 @@
 
     private string optionalStringPiece_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalStringPiece {
       get { return optionalStringPiece_ ?? OptionalStringPieceDefaultValue; }
       set {
@@ -888,11 +932,13 @@
     }
     /// <summary>Gets whether the "optional_string_piece" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalStringPiece {
       get { return optionalStringPiece_ != null; }
     }
     /// <summary>Clears the value of the "optional_string_piece" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalStringPiece() {
       optionalStringPiece_ = null;
     }
@@ -903,6 +949,7 @@
 
     private string optionalCord_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalCord {
       get { return optionalCord_ ?? OptionalCordDefaultValue; }
       set {
@@ -911,11 +958,13 @@
     }
     /// <summary>Gets whether the "optional_cord" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalCord {
       get { return optionalCord_ != null; }
     }
     /// <summary>Clears the value of the "optional_cord" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalCord() {
       optionalCord_ = null;
     }
@@ -924,22 +973,13 @@
     public const int RecursiveMessageFieldNumber = 27;
     private global::ProtobufTestMessages.Proto2.TestAllTypesProto2 recursiveMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.TestAllTypesProto2 RecursiveMessage {
       get { return recursiveMessage_; }
       set {
         recursiveMessage_ = value;
       }
     }
-    /// <summary>Gets whether the recursive_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasRecursiveMessage {
-      get { return recursiveMessage_ != null; }
-    }
-    /// <summary>Clears the value of the recursive_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearRecursiveMessage() {
-      recursiveMessage_ = null;
-    }
 
     /// <summary>Field number for the "repeated_int32" field.</summary>
     public const int RepeatedInt32FieldNumber = 31;
@@ -950,6 +990,7 @@
     /// Repeated
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
@@ -960,6 +1001,7 @@
         = pb::FieldCodec.ForInt64(256);
     private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedInt64 {
       get { return repeatedInt64_; }
     }
@@ -970,6 +1012,7 @@
         = pb::FieldCodec.ForUInt32(264);
     private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedUint32 {
       get { return repeatedUint32_; }
     }
@@ -980,6 +1023,7 @@
         = pb::FieldCodec.ForUInt64(272);
     private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedUint64 {
       get { return repeatedUint64_; }
     }
@@ -990,6 +1034,7 @@
         = pb::FieldCodec.ForSInt32(280);
     private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSint32 {
       get { return repeatedSint32_; }
     }
@@ -1000,6 +1045,7 @@
         = pb::FieldCodec.ForSInt64(288);
     private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSint64 {
       get { return repeatedSint64_; }
     }
@@ -1010,6 +1056,7 @@
         = pb::FieldCodec.ForFixed32(301);
     private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedFixed32 {
       get { return repeatedFixed32_; }
     }
@@ -1020,6 +1067,7 @@
         = pb::FieldCodec.ForFixed64(305);
     private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedFixed64 {
       get { return repeatedFixed64_; }
     }
@@ -1030,6 +1078,7 @@
         = pb::FieldCodec.ForSFixed32(317);
     private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSfixed32 {
       get { return repeatedSfixed32_; }
     }
@@ -1040,6 +1089,7 @@
         = pb::FieldCodec.ForSFixed64(321);
     private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSfixed64 {
       get { return repeatedSfixed64_; }
     }
@@ -1050,6 +1100,7 @@
         = pb::FieldCodec.ForFloat(333);
     private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> RepeatedFloat {
       get { return repeatedFloat_; }
     }
@@ -1060,6 +1111,7 @@
         = pb::FieldCodec.ForDouble(337);
     private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> RepeatedDouble {
       get { return repeatedDouble_; }
     }
@@ -1070,6 +1122,7 @@
         = pb::FieldCodec.ForBool(344);
     private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> RepeatedBool {
       get { return repeatedBool_; }
     }
@@ -1080,6 +1133,7 @@
         = pb::FieldCodec.ForString(354);
     private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedString {
       get { return repeatedString_; }
     }
@@ -1090,6 +1144,7 @@
         = pb::FieldCodec.ForBytes(362);
     private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
       get { return repeatedBytes_; }
     }
@@ -1100,6 +1155,7 @@
         = pb::FieldCodec.ForMessage(386, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage.Parser);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage> RepeatedNestedMessage {
       get { return repeatedNestedMessage_; }
     }
@@ -1110,6 +1166,7 @@
         = pb::FieldCodec.ForMessage(394, global::ProtobufTestMessages.Proto2.ForeignMessageProto2.Parser);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto2.ForeignMessageProto2> repeatedForeignMessage_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto2.ForeignMessageProto2>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto2.ForeignMessageProto2> RepeatedForeignMessage {
       get { return repeatedForeignMessage_; }
     }
@@ -1120,6 +1177,7 @@
         = pb::FieldCodec.ForEnum(408, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> RepeatedNestedEnum {
       get { return repeatedNestedEnum_; }
     }
@@ -1130,6 +1188,7 @@
         = pb::FieldCodec.ForEnum(416, x => (int) x, x => (global::ProtobufTestMessages.Proto2.ForeignEnumProto2) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto2.ForeignEnumProto2> repeatedForeignEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto2.ForeignEnumProto2>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto2.ForeignEnumProto2> RepeatedForeignEnum {
       get { return repeatedForeignEnum_; }
     }
@@ -1140,6 +1199,7 @@
         = pb::FieldCodec.ForString(434);
     private readonly pbc::RepeatedField<string> repeatedStringPiece_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedStringPiece {
       get { return repeatedStringPiece_; }
     }
@@ -1150,6 +1210,7 @@
         = pb::FieldCodec.ForString(442);
     private readonly pbc::RepeatedField<string> repeatedCord_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedCord {
       get { return repeatedCord_; }
     }
@@ -1163,6 +1224,7 @@
     /// Packed
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedInt32 {
       get { return packedInt32_; }
     }
@@ -1173,6 +1235,7 @@
         = pb::FieldCodec.ForInt64(610);
     private readonly pbc::RepeatedField<long> packedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedInt64 {
       get { return packedInt64_; }
     }
@@ -1183,6 +1246,7 @@
         = pb::FieldCodec.ForUInt32(618);
     private readonly pbc::RepeatedField<uint> packedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedUint32 {
       get { return packedUint32_; }
     }
@@ -1193,6 +1257,7 @@
         = pb::FieldCodec.ForUInt64(626);
     private readonly pbc::RepeatedField<ulong> packedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedUint64 {
       get { return packedUint64_; }
     }
@@ -1203,6 +1268,7 @@
         = pb::FieldCodec.ForSInt32(634);
     private readonly pbc::RepeatedField<int> packedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSint32 {
       get { return packedSint32_; }
     }
@@ -1213,6 +1279,7 @@
         = pb::FieldCodec.ForSInt64(642);
     private readonly pbc::RepeatedField<long> packedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSint64 {
       get { return packedSint64_; }
     }
@@ -1223,6 +1290,7 @@
         = pb::FieldCodec.ForFixed32(650);
     private readonly pbc::RepeatedField<uint> packedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedFixed32 {
       get { return packedFixed32_; }
     }
@@ -1233,6 +1301,7 @@
         = pb::FieldCodec.ForFixed64(658);
     private readonly pbc::RepeatedField<ulong> packedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedFixed64 {
       get { return packedFixed64_; }
     }
@@ -1243,6 +1312,7 @@
         = pb::FieldCodec.ForSFixed32(666);
     private readonly pbc::RepeatedField<int> packedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSfixed32 {
       get { return packedSfixed32_; }
     }
@@ -1253,6 +1323,7 @@
         = pb::FieldCodec.ForSFixed64(674);
     private readonly pbc::RepeatedField<long> packedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSfixed64 {
       get { return packedSfixed64_; }
     }
@@ -1263,6 +1334,7 @@
         = pb::FieldCodec.ForFloat(682);
     private readonly pbc::RepeatedField<float> packedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> PackedFloat {
       get { return packedFloat_; }
     }
@@ -1273,6 +1345,7 @@
         = pb::FieldCodec.ForDouble(690);
     private readonly pbc::RepeatedField<double> packedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> PackedDouble {
       get { return packedDouble_; }
     }
@@ -1283,6 +1356,7 @@
         = pb::FieldCodec.ForBool(698);
     private readonly pbc::RepeatedField<bool> packedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> PackedBool {
       get { return packedBool_; }
     }
@@ -1293,6 +1367,7 @@
         = pb::FieldCodec.ForEnum(706, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> packedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> PackedNestedEnum {
       get { return packedNestedEnum_; }
     }
@@ -1306,6 +1381,7 @@
     /// Unpacked
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedInt32 {
       get { return unpackedInt32_; }
     }
@@ -1316,6 +1392,7 @@
         = pb::FieldCodec.ForInt64(720);
     private readonly pbc::RepeatedField<long> unpackedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedInt64 {
       get { return unpackedInt64_; }
     }
@@ -1326,6 +1403,7 @@
         = pb::FieldCodec.ForUInt32(728);
     private readonly pbc::RepeatedField<uint> unpackedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedUint32 {
       get { return unpackedUint32_; }
     }
@@ -1336,6 +1414,7 @@
         = pb::FieldCodec.ForUInt64(736);
     private readonly pbc::RepeatedField<ulong> unpackedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedUint64 {
       get { return unpackedUint64_; }
     }
@@ -1346,6 +1425,7 @@
         = pb::FieldCodec.ForSInt32(744);
     private readonly pbc::RepeatedField<int> unpackedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSint32 {
       get { return unpackedSint32_; }
     }
@@ -1356,6 +1436,7 @@
         = pb::FieldCodec.ForSInt64(752);
     private readonly pbc::RepeatedField<long> unpackedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSint64 {
       get { return unpackedSint64_; }
     }
@@ -1366,6 +1447,7 @@
         = pb::FieldCodec.ForFixed32(765);
     private readonly pbc::RepeatedField<uint> unpackedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedFixed32 {
       get { return unpackedFixed32_; }
     }
@@ -1376,6 +1458,7 @@
         = pb::FieldCodec.ForFixed64(769);
     private readonly pbc::RepeatedField<ulong> unpackedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedFixed64 {
       get { return unpackedFixed64_; }
     }
@@ -1386,6 +1469,7 @@
         = pb::FieldCodec.ForSFixed32(781);
     private readonly pbc::RepeatedField<int> unpackedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSfixed32 {
       get { return unpackedSfixed32_; }
     }
@@ -1396,6 +1480,7 @@
         = pb::FieldCodec.ForSFixed64(785);
     private readonly pbc::RepeatedField<long> unpackedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSfixed64 {
       get { return unpackedSfixed64_; }
     }
@@ -1406,6 +1491,7 @@
         = pb::FieldCodec.ForFloat(797);
     private readonly pbc::RepeatedField<float> unpackedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> UnpackedFloat {
       get { return unpackedFloat_; }
     }
@@ -1416,6 +1502,7 @@
         = pb::FieldCodec.ForDouble(801);
     private readonly pbc::RepeatedField<double> unpackedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> UnpackedDouble {
       get { return unpackedDouble_; }
     }
@@ -1426,6 +1513,7 @@
         = pb::FieldCodec.ForBool(808);
     private readonly pbc::RepeatedField<bool> unpackedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> UnpackedBool {
       get { return unpackedBool_; }
     }
@@ -1436,6 +1524,7 @@
         = pb::FieldCodec.ForEnum(816, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> unpackedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> UnpackedNestedEnum {
       get { return unpackedNestedEnum_; }
     }
@@ -1449,6 +1538,7 @@
     /// Map
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapInt32Int32 {
       get { return mapInt32Int32_; }
     }
@@ -1459,6 +1549,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 458);
     private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapInt64Int64 {
       get { return mapInt64Int64_; }
     }
@@ -1469,6 +1560,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 466);
     private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapUint32Uint32 {
       get { return mapUint32Uint32_; }
     }
@@ -1479,6 +1571,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 474);
     private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapUint64Uint64 {
       get { return mapUint64Uint64_; }
     }
@@ -1489,6 +1582,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 482);
     private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSint32Sint32 {
       get { return mapSint32Sint32_; }
     }
@@ -1499,6 +1593,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 490);
     private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSint64Sint64 {
       get { return mapSint64Sint64_; }
     }
@@ -1509,6 +1604,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 498);
     private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapFixed32Fixed32 {
       get { return mapFixed32Fixed32_; }
     }
@@ -1519,6 +1615,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 506);
     private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
       get { return mapFixed64Fixed64_; }
     }
@@ -1529,6 +1626,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 514);
     private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSfixed32Sfixed32 {
       get { return mapSfixed32Sfixed32_; }
     }
@@ -1539,6 +1637,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 522);
     private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSfixed64Sfixed64 {
       get { return mapSfixed64Sfixed64_; }
     }
@@ -1549,6 +1648,7 @@
         = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 530);
     private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, float> MapInt32Float {
       get { return mapInt32Float_; }
     }
@@ -1559,6 +1659,7 @@
         = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 538);
     private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, double> MapInt32Double {
       get { return mapInt32Double_; }
     }
@@ -1569,6 +1670,7 @@
         = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 546);
     private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<bool, bool> MapBoolBool {
       get { return mapBoolBool_; }
     }
@@ -1579,6 +1681,7 @@
         = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 554);
     private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, string> MapStringString {
       get { return mapStringString_; }
     }
@@ -1589,6 +1692,7 @@
         = new pbc::MapField<string, pb::ByteString>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForBytes(18, pb::ByteString.Empty), 562);
     private readonly pbc::MapField<string, pb::ByteString> mapStringBytes_ = new pbc::MapField<string, pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, pb::ByteString> MapStringBytes {
       get { return mapStringBytes_; }
     }
@@ -1599,6 +1703,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage.Parser), 570);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage> mapStringNestedMessage_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage> MapStringNestedMessage {
       get { return mapStringNestedMessage_; }
     }
@@ -1609,6 +1714,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignMessageProto2>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto2.ForeignMessageProto2.Parser), 578);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignMessageProto2> mapStringForeignMessage_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignMessageProto2>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignMessageProto2> MapStringForeignMessage {
       get { return mapStringForeignMessage_; }
     }
@@ -1619,6 +1725,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum.Foo), 586);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> mapStringNestedEnum_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum> MapStringNestedEnum {
       get { return mapStringNestedEnum_; }
     }
@@ -1629,6 +1736,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignEnumProto2>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto2.ForeignEnumProto2) x, global::ProtobufTestMessages.Proto2.ForeignEnumProto2.ForeignFoo), 594);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignEnumProto2> mapStringForeignEnum_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignEnumProto2>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto2.ForeignEnumProto2> MapStringForeignEnum {
       get { return mapStringForeignEnum_; }
     }
@@ -1636,6 +1744,7 @@
     /// <summary>Field number for the "oneof_uint32" field.</summary>
     public const int OneofUint32FieldNumber = 111;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OneofUint32 {
       get { return HasOneofUint32 ? (uint) oneofField_ : 0; }
       set {
@@ -1645,11 +1754,13 @@
     }
     /// <summary>Gets whether the "oneof_uint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofUint32 {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_uint32" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofUint32() {
       if (HasOneofUint32) {
         ClearOneofField();
@@ -1659,29 +1770,19 @@
     /// <summary>Field number for the "oneof_nested_message" field.</summary>
     public const int OneofNestedMessageFieldNumber = 112;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage OneofNestedMessage {
-      get { return HasOneofNestedMessage ? (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage) oneofField_ : null; }
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage) oneofField_ : null; }
       set {
         oneofField_ = value;
         oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
       }
     }
-    /// <summary>Gets whether the "oneof_nested_message" field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOneofNestedMessage {
-      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; }
-    }
-    /// <summary> Clears the value of the oneof if it's currently set to "oneof_nested_message" </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOneofNestedMessage() {
-      if (HasOneofNestedMessage) {
-        ClearOneofField();
-      }
-    }
 
     /// <summary>Field number for the "oneof_string" field.</summary>
     public const int OneofStringFieldNumber = 113;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OneofString {
       get { return HasOneofString ? (string) oneofField_ : ""; }
       set {
@@ -1691,11 +1792,13 @@
     }
     /// <summary>Gets whether the "oneof_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofString {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_string" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofString() {
       if (HasOneofString) {
         ClearOneofField();
@@ -1705,6 +1808,7 @@
     /// <summary>Field number for the "oneof_bytes" field.</summary>
     public const int OneofBytesFieldNumber = 114;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OneofBytes {
       get { return HasOneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
       set {
@@ -1714,11 +1818,13 @@
     }
     /// <summary>Gets whether the "oneof_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofBytes {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_bytes" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofBytes() {
       if (HasOneofBytes) {
         ClearOneofField();
@@ -1728,6 +1834,7 @@
     /// <summary>Field number for the "oneof_bool" field.</summary>
     public const int OneofBoolFieldNumber = 115;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool OneofBool {
       get { return HasOneofBool ? (bool) oneofField_ : false; }
       set {
@@ -1737,11 +1844,13 @@
     }
     /// <summary>Gets whether the "oneof_bool" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofBool {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBool; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_bool" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofBool() {
       if (HasOneofBool) {
         ClearOneofField();
@@ -1751,6 +1860,7 @@
     /// <summary>Field number for the "oneof_uint64" field.</summary>
     public const int OneofUint64FieldNumber = 116;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OneofUint64 {
       get { return HasOneofUint64 ? (ulong) oneofField_ : 0UL; }
       set {
@@ -1760,11 +1870,13 @@
     }
     /// <summary>Gets whether the "oneof_uint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofUint64 {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint64; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_uint64" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofUint64() {
       if (HasOneofUint64) {
         ClearOneofField();
@@ -1774,6 +1886,7 @@
     /// <summary>Field number for the "oneof_float" field.</summary>
     public const int OneofFloatFieldNumber = 117;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float OneofFloat {
       get { return HasOneofFloat ? (float) oneofField_ : 0F; }
       set {
@@ -1783,11 +1896,13 @@
     }
     /// <summary>Gets whether the "oneof_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofFloat {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofFloat; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_float" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofFloat() {
       if (HasOneofFloat) {
         ClearOneofField();
@@ -1797,6 +1912,7 @@
     /// <summary>Field number for the "oneof_double" field.</summary>
     public const int OneofDoubleFieldNumber = 118;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double OneofDouble {
       get { return HasOneofDouble ? (double) oneofField_ : 0D; }
       set {
@@ -1806,11 +1922,13 @@
     }
     /// <summary>Gets whether the "oneof_double" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofDouble {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofDouble; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_double" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofDouble() {
       if (HasOneofDouble) {
         ClearOneofField();
@@ -1820,6 +1938,7 @@
     /// <summary>Field number for the "oneof_enum" field.</summary>
     public const int OneofEnumFieldNumber = 119;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum OneofEnum {
       get { return HasOneofEnum ? (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) oneofField_ : global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum.Foo; }
       set {
@@ -1829,11 +1948,13 @@
     }
     /// <summary>Gets whether the "oneof_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofEnum {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_enum" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofEnum() {
       if (HasOneofEnum) {
         ClearOneofField();
@@ -1844,6 +1965,7 @@
     public const int DataFieldNumber = 201;
     private global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data Data {
       get { return data_; }
       set {
@@ -1852,11 +1974,13 @@
     }
     /// <summary>Gets whether the data field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return data_ != null; }
     }
     /// <summary>Clears the value of the data field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       data_ = null;
     }
@@ -1871,22 +1995,25 @@
     /// (protobuf says names can be any valid C/C++ identifier.)
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Fieldname1 {
-      get { if ((_hasBits0 & 2097152) != 0) { return fieldname1_; } else { return Fieldname1DefaultValue; } }
+      get { if ((_hasBits0 & 32768) != 0) { return fieldname1_; } else { return Fieldname1DefaultValue; } }
       set {
-        _hasBits0 |= 2097152;
+        _hasBits0 |= 32768;
         fieldname1_ = value;
       }
     }
     /// <summary>Gets whether the "fieldname1" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldname1 {
-      get { return (_hasBits0 & 2097152) != 0; }
+      get { return (_hasBits0 & 32768) != 0; }
     }
     /// <summary>Clears the value of the "fieldname1" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldname1() {
-      _hasBits0 &= ~2097152;
+      _hasBits0 &= ~32768;
     }
 
     /// <summary>Field number for the "field_name2" field.</summary>
@@ -1895,22 +2022,25 @@
 
     private int fieldName2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName2 {
-      get { if ((_hasBits0 & 4194304) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } }
+      get { if ((_hasBits0 & 65536) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } }
       set {
-        _hasBits0 |= 4194304;
+        _hasBits0 |= 65536;
         fieldName2_ = value;
       }
     }
     /// <summary>Gets whether the "field_name2" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName2 {
-      get { return (_hasBits0 & 4194304) != 0; }
+      get { return (_hasBits0 & 65536) != 0; }
     }
     /// <summary>Clears the value of the "field_name2" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName2() {
-      _hasBits0 &= ~4194304;
+      _hasBits0 &= ~65536;
     }
 
     /// <summary>Field number for the "_field_name3" field.</summary>
@@ -1919,22 +2049,25 @@
 
     private int FieldName3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName3 {
-      get { if ((_hasBits0 & 8388608) != 0) { return FieldName3_; } else { return FieldName3DefaultValue; } }
+      get { if ((_hasBits0 & 131072) != 0) { return FieldName3_; } else { return FieldName3DefaultValue; } }
       set {
-        _hasBits0 |= 8388608;
+        _hasBits0 |= 131072;
         FieldName3_ = value;
       }
     }
     /// <summary>Gets whether the "_field_name3" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName3 {
-      get { return (_hasBits0 & 8388608) != 0; }
+      get { return (_hasBits0 & 131072) != 0; }
     }
     /// <summary>Clears the value of the "_field_name3" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName3() {
-      _hasBits0 &= ~8388608;
+      _hasBits0 &= ~131072;
     }
 
     /// <summary>Field number for the "field__name4_" field.</summary>
@@ -1943,22 +2076,25 @@
 
     private int fieldName4_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName4 {
-      get { if ((_hasBits0 & 16777216) != 0) { return fieldName4_; } else { return FieldName4DefaultValue; } }
+      get { if ((_hasBits0 & 262144) != 0) { return fieldName4_; } else { return FieldName4DefaultValue; } }
       set {
-        _hasBits0 |= 16777216;
+        _hasBits0 |= 262144;
         fieldName4_ = value;
       }
     }
     /// <summary>Gets whether the "field__name4_" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName4 {
-      get { return (_hasBits0 & 16777216) != 0; }
+      get { return (_hasBits0 & 262144) != 0; }
     }
     /// <summary>Clears the value of the "field__name4_" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName4() {
-      _hasBits0 &= ~16777216;
+      _hasBits0 &= ~262144;
     }
 
     /// <summary>Field number for the "field0name5" field.</summary>
@@ -1967,22 +2103,25 @@
 
     private int field0Name5_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field0Name5 {
-      get { if ((_hasBits0 & 33554432) != 0) { return field0Name5_; } else { return Field0Name5DefaultValue; } }
+      get { if ((_hasBits0 & 524288) != 0) { return field0Name5_; } else { return Field0Name5DefaultValue; } }
       set {
-        _hasBits0 |= 33554432;
+        _hasBits0 |= 524288;
         field0Name5_ = value;
       }
     }
     /// <summary>Gets whether the "field0name5" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField0Name5 {
-      get { return (_hasBits0 & 33554432) != 0; }
+      get { return (_hasBits0 & 524288) != 0; }
     }
     /// <summary>Clears the value of the "field0name5" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField0Name5() {
-      _hasBits0 &= ~33554432;
+      _hasBits0 &= ~524288;
     }
 
     /// <summary>Field number for the "field_0_name6" field.</summary>
@@ -1991,22 +2130,25 @@
 
     private int field0Name6_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field0Name6 {
-      get { if ((_hasBits0 & 67108864) != 0) { return field0Name6_; } else { return Field0Name6DefaultValue; } }
+      get { if ((_hasBits0 & 1048576) != 0) { return field0Name6_; } else { return Field0Name6DefaultValue; } }
       set {
-        _hasBits0 |= 67108864;
+        _hasBits0 |= 1048576;
         field0Name6_ = value;
       }
     }
     /// <summary>Gets whether the "field_0_name6" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField0Name6 {
-      get { return (_hasBits0 & 67108864) != 0; }
+      get { return (_hasBits0 & 1048576) != 0; }
     }
     /// <summary>Clears the value of the "field_0_name6" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField0Name6() {
-      _hasBits0 &= ~67108864;
+      _hasBits0 &= ~1048576;
     }
 
     /// <summary>Field number for the "fieldName7" field.</summary>
@@ -2015,22 +2157,25 @@
 
     private int fieldName7_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName7 {
-      get { if ((_hasBits0 & 134217728) != 0) { return fieldName7_; } else { return FieldName7DefaultValue; } }
+      get { if ((_hasBits0 & 2097152) != 0) { return fieldName7_; } else { return FieldName7DefaultValue; } }
       set {
-        _hasBits0 |= 134217728;
+        _hasBits0 |= 2097152;
         fieldName7_ = value;
       }
     }
     /// <summary>Gets whether the "fieldName7" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName7 {
-      get { return (_hasBits0 & 134217728) != 0; }
+      get { return (_hasBits0 & 2097152) != 0; }
     }
     /// <summary>Clears the value of the "fieldName7" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName7() {
-      _hasBits0 &= ~134217728;
+      _hasBits0 &= ~2097152;
     }
 
     /// <summary>Field number for the "FieldName8" field.</summary>
@@ -2039,22 +2184,25 @@
 
     private int fieldName8_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName8 {
-      get { if ((_hasBits0 & 268435456) != 0) { return fieldName8_; } else { return FieldName8DefaultValue; } }
+      get { if ((_hasBits0 & 4194304) != 0) { return fieldName8_; } else { return FieldName8DefaultValue; } }
       set {
-        _hasBits0 |= 268435456;
+        _hasBits0 |= 4194304;
         fieldName8_ = value;
       }
     }
     /// <summary>Gets whether the "FieldName8" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName8 {
-      get { return (_hasBits0 & 268435456) != 0; }
+      get { return (_hasBits0 & 4194304) != 0; }
     }
     /// <summary>Clears the value of the "FieldName8" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName8() {
-      _hasBits0 &= ~268435456;
+      _hasBits0 &= ~4194304;
     }
 
     /// <summary>Field number for the "field_Name9" field.</summary>
@@ -2063,22 +2211,25 @@
 
     private int fieldName9_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName9 {
-      get { if ((_hasBits0 & 536870912) != 0) { return fieldName9_; } else { return FieldName9DefaultValue; } }
+      get { if ((_hasBits0 & 8388608) != 0) { return fieldName9_; } else { return FieldName9DefaultValue; } }
       set {
-        _hasBits0 |= 536870912;
+        _hasBits0 |= 8388608;
         fieldName9_ = value;
       }
     }
     /// <summary>Gets whether the "field_Name9" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName9 {
-      get { return (_hasBits0 & 536870912) != 0; }
+      get { return (_hasBits0 & 8388608) != 0; }
     }
     /// <summary>Clears the value of the "field_Name9" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName9() {
-      _hasBits0 &= ~536870912;
+      _hasBits0 &= ~8388608;
     }
 
     /// <summary>Field number for the "Field_Name10" field.</summary>
@@ -2087,22 +2238,25 @@
 
     private int fieldName10_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName10 {
-      get { if ((_hasBits0 & 1073741824) != 0) { return fieldName10_; } else { return FieldName10DefaultValue; } }
+      get { if ((_hasBits0 & 16777216) != 0) { return fieldName10_; } else { return FieldName10DefaultValue; } }
       set {
-        _hasBits0 |= 1073741824;
+        _hasBits0 |= 16777216;
         fieldName10_ = value;
       }
     }
     /// <summary>Gets whether the "Field_Name10" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName10 {
-      get { return (_hasBits0 & 1073741824) != 0; }
+      get { return (_hasBits0 & 16777216) != 0; }
     }
     /// <summary>Clears the value of the "Field_Name10" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName10() {
-      _hasBits0 &= ~1073741824;
+      _hasBits0 &= ~16777216;
     }
 
     /// <summary>Field number for the "FIELD_NAME11" field.</summary>
@@ -2111,22 +2265,25 @@
 
     private int fIELDNAME11_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FIELDNAME11 {
-      get { if ((_hasBits0 & -2147483648) != 0) { return fIELDNAME11_; } else { return FIELDNAME11DefaultValue; } }
+      get { if ((_hasBits0 & 33554432) != 0) { return fIELDNAME11_; } else { return FIELDNAME11DefaultValue; } }
       set {
-        _hasBits0 |= -2147483648;
+        _hasBits0 |= 33554432;
         fIELDNAME11_ = value;
       }
     }
     /// <summary>Gets whether the "FIELD_NAME11" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFIELDNAME11 {
-      get { return (_hasBits0 & -2147483648) != 0; }
+      get { return (_hasBits0 & 33554432) != 0; }
     }
     /// <summary>Clears the value of the "FIELD_NAME11" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFIELDNAME11() {
-      _hasBits0 &= ~-2147483648;
+      _hasBits0 &= ~33554432;
     }
 
     /// <summary>Field number for the "FIELD_name12" field.</summary>
@@ -2135,22 +2292,25 @@
 
     private int fIELDName12_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FIELDName12 {
-      get { if ((_hasBits1 & 1) != 0) { return fIELDName12_; } else { return FIELDName12DefaultValue; } }
+      get { if ((_hasBits0 & 67108864) != 0) { return fIELDName12_; } else { return FIELDName12DefaultValue; } }
       set {
-        _hasBits1 |= 1;
+        _hasBits0 |= 67108864;
         fIELDName12_ = value;
       }
     }
     /// <summary>Gets whether the "FIELD_name12" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFIELDName12 {
-      get { return (_hasBits1 & 1) != 0; }
+      get { return (_hasBits0 & 67108864) != 0; }
     }
     /// <summary>Clears the value of the "FIELD_name12" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFIELDName12() {
-      _hasBits1 &= ~1;
+      _hasBits0 &= ~67108864;
     }
 
     /// <summary>Field number for the "__field_name13" field.</summary>
@@ -2159,22 +2319,25 @@
 
     private int FieldName13_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName13 {
-      get { if ((_hasBits1 & 2) != 0) { return FieldName13_; } else { return FieldName13DefaultValue; } }
+      get { if ((_hasBits0 & 134217728) != 0) { return FieldName13_; } else { return FieldName13DefaultValue; } }
       set {
-        _hasBits1 |= 2;
+        _hasBits0 |= 134217728;
         FieldName13_ = value;
       }
     }
     /// <summary>Gets whether the "__field_name13" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName13 {
-      get { return (_hasBits1 & 2) != 0; }
+      get { return (_hasBits0 & 134217728) != 0; }
     }
     /// <summary>Clears the value of the "__field_name13" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName13() {
-      _hasBits1 &= ~2;
+      _hasBits0 &= ~134217728;
     }
 
     /// <summary>Field number for the "__Field_name14" field.</summary>
@@ -2183,22 +2346,25 @@
 
     private int FieldName14_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName14 {
-      get { if ((_hasBits1 & 4) != 0) { return FieldName14_; } else { return FieldName14DefaultValue; } }
+      get { if ((_hasBits0 & 268435456) != 0) { return FieldName14_; } else { return FieldName14DefaultValue; } }
       set {
-        _hasBits1 |= 4;
+        _hasBits0 |= 268435456;
         FieldName14_ = value;
       }
     }
     /// <summary>Gets whether the "__Field_name14" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName14 {
-      get { return (_hasBits1 & 4) != 0; }
+      get { return (_hasBits0 & 268435456) != 0; }
     }
     /// <summary>Clears the value of the "__Field_name14" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName14() {
-      _hasBits1 &= ~4;
+      _hasBits0 &= ~268435456;
     }
 
     /// <summary>Field number for the "field__name15" field.</summary>
@@ -2207,22 +2373,25 @@
 
     private int fieldName15_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName15 {
-      get { if ((_hasBits1 & 8) != 0) { return fieldName15_; } else { return FieldName15DefaultValue; } }
+      get { if ((_hasBits0 & 536870912) != 0) { return fieldName15_; } else { return FieldName15DefaultValue; } }
       set {
-        _hasBits1 |= 8;
+        _hasBits0 |= 536870912;
         fieldName15_ = value;
       }
     }
     /// <summary>Gets whether the "field__name15" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName15 {
-      get { return (_hasBits1 & 8) != 0; }
+      get { return (_hasBits0 & 536870912) != 0; }
     }
     /// <summary>Clears the value of the "field__name15" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName15() {
-      _hasBits1 &= ~8;
+      _hasBits0 &= ~536870912;
     }
 
     /// <summary>Field number for the "field__Name16" field.</summary>
@@ -2231,22 +2400,25 @@
 
     private int fieldName16_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName16 {
-      get { if ((_hasBits1 & 16) != 0) { return fieldName16_; } else { return FieldName16DefaultValue; } }
+      get { if ((_hasBits0 & 1073741824) != 0) { return fieldName16_; } else { return FieldName16DefaultValue; } }
       set {
-        _hasBits1 |= 16;
+        _hasBits0 |= 1073741824;
         fieldName16_ = value;
       }
     }
     /// <summary>Gets whether the "field__Name16" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName16 {
-      get { return (_hasBits1 & 16) != 0; }
+      get { return (_hasBits0 & 1073741824) != 0; }
     }
     /// <summary>Clears the value of the "field__Name16" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName16() {
-      _hasBits1 &= ~16;
+      _hasBits0 &= ~1073741824;
     }
 
     /// <summary>Field number for the "field_name17__" field.</summary>
@@ -2255,22 +2427,25 @@
 
     private int fieldName17_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName17 {
-      get { if ((_hasBits1 & 32) != 0) { return fieldName17_; } else { return FieldName17DefaultValue; } }
+      get { if ((_hasBits0 & -2147483648) != 0) { return fieldName17_; } else { return FieldName17DefaultValue; } }
       set {
-        _hasBits1 |= 32;
+        _hasBits0 |= -2147483648;
         fieldName17_ = value;
       }
     }
     /// <summary>Gets whether the "field_name17__" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName17 {
-      get { return (_hasBits1 & 32) != 0; }
+      get { return (_hasBits0 & -2147483648) != 0; }
     }
     /// <summary>Clears the value of the "field_name17__" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName17() {
-      _hasBits1 &= ~32;
+      _hasBits0 &= ~-2147483648;
     }
 
     /// <summary>Field number for the "Field_name18__" field.</summary>
@@ -2279,22 +2454,25 @@
 
     private int fieldName18_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName18 {
-      get { if ((_hasBits1 & 64) != 0) { return fieldName18_; } else { return FieldName18DefaultValue; } }
+      get { if ((_hasBits1 & 1) != 0) { return fieldName18_; } else { return FieldName18DefaultValue; } }
       set {
-        _hasBits1 |= 64;
+        _hasBits1 |= 1;
         fieldName18_ = value;
       }
     }
     /// <summary>Gets whether the "Field_name18__" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName18 {
-      get { return (_hasBits1 & 64) != 0; }
+      get { return (_hasBits1 & 1) != 0; }
     }
     /// <summary>Clears the value of the "Field_name18__" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName18() {
-      _hasBits1 &= ~64;
+      _hasBits1 &= ~1;
     }
 
     private object oneofField_;
@@ -2313,22 +2491,26 @@
     }
     private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofFieldOneofCase OneofFieldCase {
       get { return oneofFieldCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofField() {
       oneofFieldCase_ = OneofFieldOneofCase.None;
       oneofField_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestAllTypesProto2);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestAllTypesProto2 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2462,6 +2644,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode();
@@ -2479,13 +2662,13 @@
       if (HasOptionalBool) hash ^= OptionalBool.GetHashCode();
       if (HasOptionalString) hash ^= OptionalString.GetHashCode();
       if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode();
-      if (HasOptionalNestedMessage) hash ^= OptionalNestedMessage.GetHashCode();
-      if (HasOptionalForeignMessage) hash ^= OptionalForeignMessage.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
+      if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode();
       if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode();
       if (HasOptionalForeignEnum) hash ^= OptionalForeignEnum.GetHashCode();
       if (HasOptionalStringPiece) hash ^= OptionalStringPiece.GetHashCode();
       if (HasOptionalCord) hash ^= OptionalCord.GetHashCode();
-      if (HasRecursiveMessage) hash ^= RecursiveMessage.GetHashCode();
+      if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode();
       hash ^= repeatedInt32_.GetHashCode();
       hash ^= repeatedInt64_.GetHashCode();
       hash ^= repeatedUint32_.GetHashCode();
@@ -2555,7 +2738,7 @@
       hash ^= MapStringNestedEnum.GetHashCode();
       hash ^= MapStringForeignEnum.GetHashCode();
       if (HasOneofUint32) hash ^= OneofUint32.GetHashCode();
-      if (HasOneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
       if (HasOneofString) hash ^= OneofString.GetHashCode();
       if (HasOneofBytes) hash ^= OneofBytes.GetHashCode();
       if (HasOneofBool) hash ^= OneofBool.GetHashCode();
@@ -2593,12 +2776,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasOptionalInt32) {
         output.WriteRawTag(8);
         output.WriteInt32(OptionalInt32);
@@ -2659,11 +2847,11 @@
         output.WriteRawTag(122);
         output.WriteBytes(OptionalBytes);
       }
-      if (HasOptionalNestedMessage) {
+      if (optionalNestedMessage_ != null) {
         output.WriteRawTag(146, 1);
         output.WriteMessage(OptionalNestedMessage);
       }
-      if (HasOptionalForeignMessage) {
+      if (optionalForeignMessage_ != null) {
         output.WriteRawTag(154, 1);
         output.WriteMessage(OptionalForeignMessage);
       }
@@ -2683,7 +2871,7 @@
         output.WriteRawTag(202, 1);
         output.WriteString(OptionalCord);
       }
-      if (HasRecursiveMessage) {
+      if (recursiveMessage_ != null) {
         output.WriteRawTag(218, 1);
         output.WriteMessage(RecursiveMessage);
       }
@@ -2759,7 +2947,7 @@
         output.WriteRawTag(248, 6);
         output.WriteUInt32(OneofUint32);
       }
-      if (HasOneofNestedMessage) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
         output.WriteRawTag(130, 7);
         output.WriteMessage(OneofNestedMessage);
       }
@@ -2874,9 +3062,293 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasOptionalInt32) {
+        output.WriteRawTag(8);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (HasOptionalInt64) {
+        output.WriteRawTag(16);
+        output.WriteInt64(OptionalInt64);
+      }
+      if (HasOptionalUint32) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(OptionalUint32);
+      }
+      if (HasOptionalUint64) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(OptionalUint64);
+      }
+      if (HasOptionalSint32) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(OptionalSint32);
+      }
+      if (HasOptionalSint64) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(OptionalSint64);
+      }
+      if (HasOptionalFixed32) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(OptionalFixed32);
+      }
+      if (HasOptionalFixed64) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(OptionalFixed64);
+      }
+      if (HasOptionalSfixed32) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(OptionalSfixed32);
+      }
+      if (HasOptionalSfixed64) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(OptionalSfixed64);
+      }
+      if (HasOptionalFloat) {
+        output.WriteRawTag(93);
+        output.WriteFloat(OptionalFloat);
+      }
+      if (HasOptionalDouble) {
+        output.WriteRawTag(97);
+        output.WriteDouble(OptionalDouble);
+      }
+      if (HasOptionalBool) {
+        output.WriteRawTag(104);
+        output.WriteBool(OptionalBool);
+      }
+      if (HasOptionalString) {
+        output.WriteRawTag(114);
+        output.WriteString(OptionalString);
+      }
+      if (HasOptionalBytes) {
+        output.WriteRawTag(122);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (optionalForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(OptionalForeignMessage);
+      }
+      if (HasOptionalNestedEnum) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) OptionalNestedEnum);
+      }
+      if (HasOptionalForeignEnum) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) OptionalForeignEnum);
+      }
+      if (HasOptionalStringPiece) {
+        output.WriteRawTag(194, 1);
+        output.WriteString(OptionalStringPiece);
+      }
+      if (HasOptionalCord) {
+        output.WriteRawTag(202, 1);
+        output.WriteString(OptionalCord);
+      }
+      if (recursiveMessage_ != null) {
+        output.WriteRawTag(218, 1);
+        output.WriteMessage(RecursiveMessage);
+      }
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec);
+      repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec);
+      repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec);
+      repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec);
+      repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec);
+      mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec);
+      mapStringString_.WriteTo(ref output, _map_mapStringString_codec);
+      mapStringBytes_.WriteTo(ref output, _map_mapStringBytes_codec);
+      mapStringNestedMessage_.WriteTo(ref output, _map_mapStringNestedMessage_codec);
+      mapStringForeignMessage_.WriteTo(ref output, _map_mapStringForeignMessage_codec);
+      mapStringNestedEnum_.WriteTo(ref output, _map_mapStringNestedEnum_codec);
+      mapStringForeignEnum_.WriteTo(ref output, _map_mapStringForeignEnum_codec);
+      packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec);
+      packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec);
+      packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec);
+      packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec);
+      packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec);
+      packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec);
+      packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec);
+      packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec);
+      packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec);
+      packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec);
+      packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec);
+      packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec);
+      packedBool_.WriteTo(ref output, _repeated_packedBool_codec);
+      packedNestedEnum_.WriteTo(ref output, _repeated_packedNestedEnum_codec);
+      unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec);
+      unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec);
+      unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec);
+      unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec);
+      unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec);
+      unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec);
+      unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec);
+      unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec);
+      unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec);
+      unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec);
+      unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec);
+      unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec);
+      unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec);
+      unpackedNestedEnum_.WriteTo(ref output, _repeated_unpackedNestedEnum_codec);
+      if (HasOneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (HasOneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (HasOneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+      if (HasOneofBool) {
+        output.WriteRawTag(152, 7);
+        output.WriteBool(OneofBool);
+      }
+      if (HasOneofUint64) {
+        output.WriteRawTag(160, 7);
+        output.WriteUInt64(OneofUint64);
+      }
+      if (HasOneofFloat) {
+        output.WriteRawTag(173, 7);
+        output.WriteFloat(OneofFloat);
+      }
+      if (HasOneofDouble) {
+        output.WriteRawTag(177, 7);
+        output.WriteDouble(OneofDouble);
+      }
+      if (HasOneofEnum) {
+        output.WriteRawTag(184, 7);
+        output.WriteEnum((int) OneofEnum);
+      }
+      if (HasData) {
+        output.WriteRawTag(203, 12);
+        output.WriteGroup(Data);
+        output.WriteRawTag(204, 12);
+      }
+      if (HasFieldname1) {
+        output.WriteRawTag(136, 25);
+        output.WriteInt32(Fieldname1);
+      }
+      if (HasFieldName2) {
+        output.WriteRawTag(144, 25);
+        output.WriteInt32(FieldName2);
+      }
+      if (HasFieldName3) {
+        output.WriteRawTag(152, 25);
+        output.WriteInt32(FieldName3);
+      }
+      if (HasFieldName4) {
+        output.WriteRawTag(160, 25);
+        output.WriteInt32(FieldName4);
+      }
+      if (HasField0Name5) {
+        output.WriteRawTag(168, 25);
+        output.WriteInt32(Field0Name5);
+      }
+      if (HasField0Name6) {
+        output.WriteRawTag(176, 25);
+        output.WriteInt32(Field0Name6);
+      }
+      if (HasFieldName7) {
+        output.WriteRawTag(184, 25);
+        output.WriteInt32(FieldName7);
+      }
+      if (HasFieldName8) {
+        output.WriteRawTag(192, 25);
+        output.WriteInt32(FieldName8);
+      }
+      if (HasFieldName9) {
+        output.WriteRawTag(200, 25);
+        output.WriteInt32(FieldName9);
+      }
+      if (HasFieldName10) {
+        output.WriteRawTag(208, 25);
+        output.WriteInt32(FieldName10);
+      }
+      if (HasFIELDNAME11) {
+        output.WriteRawTag(216, 25);
+        output.WriteInt32(FIELDNAME11);
+      }
+      if (HasFIELDName12) {
+        output.WriteRawTag(224, 25);
+        output.WriteInt32(FIELDName12);
+      }
+      if (HasFieldName13) {
+        output.WriteRawTag(232, 25);
+        output.WriteInt32(FieldName13);
+      }
+      if (HasFieldName14) {
+        output.WriteRawTag(240, 25);
+        output.WriteInt32(FieldName14);
+      }
+      if (HasFieldName15) {
+        output.WriteRawTag(248, 25);
+        output.WriteInt32(FieldName15);
+      }
+      if (HasFieldName16) {
+        output.WriteRawTag(128, 26);
+        output.WriteInt32(FieldName16);
+      }
+      if (HasFieldName17) {
+        output.WriteRawTag(136, 26);
+        output.WriteInt32(FieldName17);
+      }
+      if (HasFieldName18) {
+        output.WriteRawTag(144, 26);
+        output.WriteInt32(FieldName18);
+      }
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasOptionalInt32) {
@@ -2924,10 +3396,10 @@
       if (HasOptionalBytes) {
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes);
       }
-      if (HasOptionalNestedMessage) {
+      if (optionalNestedMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
       }
-      if (HasOptionalForeignMessage) {
+      if (optionalForeignMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage);
       }
       if (HasOptionalNestedEnum) {
@@ -2942,7 +3414,7 @@
       if (HasOptionalCord) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord);
       }
-      if (HasRecursiveMessage) {
+      if (recursiveMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage);
       }
       size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
@@ -3016,7 +3488,7 @@
       if (HasOneofUint32) {
         size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
       }
-      if (HasOneofNestedMessage) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage);
       }
       if (HasOneofString) {
@@ -3107,6 +3579,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestAllTypesProto2 other) {
       if (other == null) {
         return;
@@ -3156,14 +3629,14 @@
       if (other.HasOptionalBytes) {
         OptionalBytes = other.OptionalBytes;
       }
-      if (other.HasOptionalNestedMessage) {
-        if (!HasOptionalNestedMessage) {
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
           OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
         }
         OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
       }
-      if (other.HasOptionalForeignMessage) {
-        if (!HasOptionalForeignMessage) {
+      if (other.optionalForeignMessage_ != null) {
+        if (optionalForeignMessage_ == null) {
           OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
         }
         OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage);
@@ -3180,8 +3653,8 @@
       if (other.HasOptionalCord) {
         OptionalCord = other.OptionalCord;
       }
-      if (other.HasRecursiveMessage) {
-        if (!HasRecursiveMessage) {
+      if (other.recursiveMessage_ != null) {
+        if (recursiveMessage_ == null) {
           RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
         }
         RecursiveMessage.MergeFrom(other.RecursiveMessage);
@@ -3352,7 +3825,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3422,14 +3899,14 @@
             break;
           }
           case 146: {
-            if (!HasOptionalNestedMessage) {
+            if (optionalNestedMessage_ == null) {
               OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
             }
             input.ReadMessage(OptionalNestedMessage);
             break;
           }
           case 154: {
-            if (!HasOptionalForeignMessage) {
+            if (optionalForeignMessage_ == null) {
               OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
             }
             input.ReadMessage(OptionalForeignMessage);
@@ -3452,7 +3929,7 @@
             break;
           }
           case 218: {
-            if (!HasRecursiveMessage) {
+            if (recursiveMessage_ == null) {
               RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
             }
             input.ReadMessage(RecursiveMessage);
@@ -3779,7 +4256,557 @@
           }
           case 898: {
             global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
-            if (HasOneofNestedMessage) {
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+          case 920: {
+            OneofBool = input.ReadBool();
+            break;
+          }
+          case 928: {
+            OneofUint64 = input.ReadUInt64();
+            break;
+          }
+          case 941: {
+            OneofFloat = input.ReadFloat();
+            break;
+          }
+          case 945: {
+            OneofDouble = input.ReadDouble();
+            break;
+          }
+          case 952: {
+            oneofField_ = input.ReadEnum();
+            oneofFieldCase_ = OneofFieldOneofCase.OneofEnum;
+            break;
+          }
+          case 1611: {
+            if (!HasData) {
+              Data = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data();
+            }
+            input.ReadGroup(Data);
+            break;
+          }
+          case 3208: {
+            Fieldname1 = input.ReadInt32();
+            break;
+          }
+          case 3216: {
+            FieldName2 = input.ReadInt32();
+            break;
+          }
+          case 3224: {
+            FieldName3 = input.ReadInt32();
+            break;
+          }
+          case 3232: {
+            FieldName4 = input.ReadInt32();
+            break;
+          }
+          case 3240: {
+            Field0Name5 = input.ReadInt32();
+            break;
+          }
+          case 3248: {
+            Field0Name6 = input.ReadInt32();
+            break;
+          }
+          case 3256: {
+            FieldName7 = input.ReadInt32();
+            break;
+          }
+          case 3264: {
+            FieldName8 = input.ReadInt32();
+            break;
+          }
+          case 3272: {
+            FieldName9 = input.ReadInt32();
+            break;
+          }
+          case 3280: {
+            FieldName10 = input.ReadInt32();
+            break;
+          }
+          case 3288: {
+            FIELDNAME11 = input.ReadInt32();
+            break;
+          }
+          case 3296: {
+            FIELDName12 = input.ReadInt32();
+            break;
+          }
+          case 3304: {
+            FieldName13 = input.ReadInt32();
+            break;
+          }
+          case 3312: {
+            FieldName14 = input.ReadInt32();
+            break;
+          }
+          case 3320: {
+            FieldName15 = input.ReadInt32();
+            break;
+          }
+          case 3328: {
+            FieldName16 = input.ReadInt32();
+            break;
+          }
+          case 3336: {
+            FieldName17 = input.ReadInt32();
+            break;
+          }
+          case 3344: {
+            FieldName18 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            OptionalInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            OptionalUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            OptionalUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            OptionalSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            OptionalSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            OptionalFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            OptionalFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            OptionalSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            OptionalSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            OptionalFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            OptionalDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 122: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 146: {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+          case 154: {
+            if (optionalForeignMessage_ == null) {
+              OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
+            }
+            input.ReadMessage(OptionalForeignMessage);
+            break;
+          }
+          case 168: {
+            OptionalNestedEnum = (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            OptionalForeignEnum = (global::ProtobufTestMessages.Proto2.ForeignEnumProto2) input.ReadEnum();
+            break;
+          }
+          case 194: {
+            OptionalStringPiece = input.ReadString();
+            break;
+          }
+          case 202: {
+            OptionalCord = input.ReadString();
+            break;
+          }
+          case 218: {
+            if (recursiveMessage_ == null) {
+              RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
+            }
+            input.ReadMessage(RecursiveMessage);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec);
+            break;
+          }
+          case 442: {
+            repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec);
+            break;
+          }
+          case 450: {
+            mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 458: {
+            mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 466: {
+            mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 474: {
+            mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 482: {
+            mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 490: {
+            mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 498: {
+            mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 506: {
+            mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 514: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 522: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 530: {
+            mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 538: {
+            mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 546: {
+            mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 554: {
+            mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec);
+            break;
+          }
+          case 562: {
+            mapStringBytes_.AddEntriesFrom(ref input, _map_mapStringBytes_codec);
+            break;
+          }
+          case 570: {
+            mapStringNestedMessage_.AddEntriesFrom(ref input, _map_mapStringNestedMessage_codec);
+            break;
+          }
+          case 578: {
+            mapStringForeignMessage_.AddEntriesFrom(ref input, _map_mapStringForeignMessage_codec);
+            break;
+          }
+          case 586: {
+            mapStringNestedEnum_.AddEntriesFrom(ref input, _map_mapStringNestedEnum_codec);
+            break;
+          }
+          case 594: {
+            mapStringForeignEnum_.AddEntriesFrom(ref input, _map_mapStringForeignEnum_codec);
+            break;
+          }
+          case 602:
+          case 600: {
+            packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec);
+            break;
+          }
+          case 610:
+          case 608: {
+            packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec);
+            break;
+          }
+          case 618:
+          case 616: {
+            packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec);
+            break;
+          }
+          case 626:
+          case 624: {
+            packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec);
+            break;
+          }
+          case 634:
+          case 632: {
+            packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec);
+            break;
+          }
+          case 642:
+          case 640: {
+            packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec);
+            break;
+          }
+          case 650:
+          case 653: {
+            packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec);
+            break;
+          }
+          case 658:
+          case 657: {
+            packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec);
+            break;
+          }
+          case 666:
+          case 669: {
+            packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec);
+            break;
+          }
+          case 674:
+          case 673: {
+            packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec);
+            break;
+          }
+          case 682:
+          case 685: {
+            packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec);
+            break;
+          }
+          case 690:
+          case 689: {
+            packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec);
+            break;
+          }
+          case 698:
+          case 696: {
+            packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec);
+            break;
+          }
+          case 706:
+          case 704: {
+            packedNestedEnum_.AddEntriesFrom(ref input, _repeated_packedNestedEnum_codec);
+            break;
+          }
+          case 714:
+          case 712: {
+            unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec);
+            break;
+          }
+          case 722:
+          case 720: {
+            unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec);
+            break;
+          }
+          case 762:
+          case 765: {
+            unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec);
+            break;
+          }
+          case 770:
+          case 769: {
+            unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec);
+            break;
+          }
+          case 778:
+          case 781: {
+            unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec);
+            break;
+          }
+          case 786:
+          case 785: {
+            unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec);
+            break;
+          }
+          case 794:
+          case 797: {
+            unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec);
+            break;
+          }
+          case 802:
+          case 801: {
+            unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec);
+            break;
+          }
+          case 810:
+          case 808: {
+            unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            unpackedNestedEnum_.AddEntriesFrom(ref input, _repeated_unpackedNestedEnum_codec);
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
               subBuilder.MergeFrom(OneofNestedMessage);
             }
             input.ReadMessage(subBuilder);
@@ -3897,6 +4924,7 @@
         }
       }
     }
+    #endif
 
     public TValue GetExtension<TValue>(pb::Extension<TestAllTypesProto2, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
@@ -3923,6 +4951,7 @@
     #region Nested types
     /// <summary>Container for nested types declared in the TestAllTypesProto2 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum NestedEnum {
         [pbr::OriginalName("FOO")] Foo = 0,
@@ -3934,24 +4963,32 @@
         [pbr::OriginalName("NEG")] Neg = -1,
       }
 
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -3959,14 +4996,16 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
-          corecursive_ = other.HasCorecursive ? other.corecursive_.Clone() : null;
+          corecursive_ = other.corecursive_ != null ? other.corecursive_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -3977,6 +5016,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -3986,11 +5026,13 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
@@ -3999,29 +5041,22 @@
         public const int CorecursiveFieldNumber = 2;
         private global::ProtobufTestMessages.Proto2.TestAllTypesProto2 corecursive_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::ProtobufTestMessages.Proto2.TestAllTypesProto2 Corecursive {
           get { return corecursive_; }
           set {
             corecursive_ = value;
           }
         }
-        /// <summary>Gets whether the corecursive field is set</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public bool HasCorecursive {
-          get { return corecursive_ != null; }
-        }
-        /// <summary>Clears the value of the corecursive field</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public void ClearCorecursive() {
-          corecursive_ = null;
-        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4035,10 +5070,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
-          if (HasCorecursive) hash ^= Corecursive.GetHashCode();
+          if (corecursive_ != null) hash ^= Corecursive.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -4046,32 +5082,57 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(8);
             output.WriteInt32(A);
           }
-          if (HasCorecursive) {
+          if (corecursive_ != null) {
             output.WriteRawTag(18);
             output.WriteMessage(Corecursive);
           }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(8);
+            output.WriteInt32(A);
+          }
+          if (corecursive_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Corecursive);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(A);
           }
-          if (HasCorecursive) {
+          if (corecursive_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive);
           }
           if (_unknownFields != null) {
@@ -4081,6 +5142,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -4088,8 +5150,8 @@
           if (other.HasA) {
             A = other.A;
           }
-          if (other.HasCorecursive) {
-            if (!HasCorecursive) {
+          if (other.corecursive_ != null) {
+            if (corecursive_ == null) {
               Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
             }
             Corecursive.MergeFrom(other.Corecursive);
@@ -4098,7 +5160,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4110,7 +5176,33 @@
                 break;
               }
               case 18: {
-                if (!HasCorecursive) {
+                if (corecursive_ == null) {
+                  Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
+                }
+                input.ReadMessage(Corecursive);
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                A = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (corecursive_ == null) {
                   Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
                 }
                 input.ReadMessage(Corecursive);
@@ -4119,30 +5211,39 @@
             }
           }
         }
+        #endif
 
       }
 
       /// <summary>
       /// groups
       /// </summary>
-      public sealed partial class Data : pb::IMessage<Data> {
+      public sealed partial class Data : pb::IMessage<Data>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<Data> _parser = new pb::MessageParser<Data>(() => new Data());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<Data> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[20]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Data() {
           OnConstruction();
         }
@@ -4150,6 +5251,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Data(Data other) : this() {
           _hasBits0 = other._hasBits0;
           groupInt32_ = other.groupInt32_;
@@ -4158,6 +5260,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Data Clone() {
           return new Data(this);
         }
@@ -4168,6 +5271,7 @@
 
         private int groupInt32_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int GroupInt32 {
           get { if ((_hasBits0 & 1) != 0) { return groupInt32_; } else { return GroupInt32DefaultValue; } }
           set {
@@ -4177,11 +5281,13 @@
         }
         /// <summary>Gets whether the "group_int32" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasGroupInt32 {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "group_int32" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearGroupInt32() {
           _hasBits0 &= ~1;
         }
@@ -4192,6 +5298,7 @@
 
         private uint groupUint32_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public uint GroupUint32 {
           get { if ((_hasBits0 & 2) != 0) { return groupUint32_; } else { return GroupUint32DefaultValue; } }
           set {
@@ -4201,21 +5308,25 @@
         }
         /// <summary>Gets whether the "group_uint32" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasGroupUint32 {
           get { return (_hasBits0 & 2) != 0; }
         }
         /// <summary>Clears the value of the "group_uint32" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearGroupUint32() {
           _hasBits0 &= ~2;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as Data);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(Data other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4229,6 +5340,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasGroupInt32) hash ^= GroupInt32.GetHashCode();
@@ -4240,12 +5352,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasGroupInt32) {
             output.WriteRawTag(208, 12);
             output.WriteInt32(GroupInt32);
@@ -4257,9 +5374,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasGroupInt32) {
+            output.WriteRawTag(208, 12);
+            output.WriteInt32(GroupInt32);
+          }
+          if (HasGroupUint32) {
+            output.WriteRawTag(216, 12);
+            output.WriteUInt32(GroupUint32);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasGroupInt32) {
@@ -4275,6 +5412,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(Data other) {
           if (other == null) {
             return;
@@ -4289,7 +5427,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4308,32 +5450,66 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 1612:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 1616: {
+                GroupInt32 = input.ReadInt32();
+                break;
+              }
+              case 1624: {
+                GroupUint32 = input.ReadUInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
       /// <summary>
       /// message_set test case.
       /// </summary>
-      public sealed partial class MessageSetCorrect : pb::IExtendableMessage<MessageSetCorrect> {
+      public sealed partial class MessageSetCorrect : pb::IExtendableMessage<MessageSetCorrect>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<MessageSetCorrect> _parser = new pb::MessageParser<MessageSetCorrect>(() => new MessageSetCorrect());
         private pb::UnknownFieldSet _unknownFields;
         private pb::ExtensionSet<MessageSetCorrect> _extensions;
         private pb::ExtensionSet<MessageSetCorrect> _Extensions { get { return _extensions; } }
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<MessageSetCorrect> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[21]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrect() {
           OnConstruction();
         }
@@ -4341,22 +5517,26 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrect(MessageSetCorrect other) : this() {
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
           _extensions = pb::ExtensionSet.Clone(other._extensions);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrect Clone() {
           return new MessageSetCorrect(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as MessageSetCorrect);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(MessageSetCorrect other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4371,6 +5551,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (_extensions != null) {
@@ -4383,21 +5564,41 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (_extensions != null) {
             _extensions.WriteTo(output);
           }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (_extensions != null) {
+            _extensions.WriteTo(ref output);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (_extensions != null) {
@@ -4410,6 +5611,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(MessageSetCorrect other) {
           if (other == null) {
             return;
@@ -4419,7 +5621,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4430,8 +5636,26 @@
                 break;
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+                  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                }
+                break;
+            }
+          }
+        }
+        #endif
+
         public TValue GetExtension<TValue>(pb::Extension<MessageSetCorrect, TValue> extension) {
           return pb::ExtensionSet.Get(ref _extensions, extension);
         }
@@ -4456,23 +5680,31 @@
 
       }
 
-      public sealed partial class MessageSetCorrectExtension1 : pb::IMessage<MessageSetCorrectExtension1> {
+      public sealed partial class MessageSetCorrectExtension1 : pb::IMessage<MessageSetCorrectExtension1>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<MessageSetCorrectExtension1> _parser = new pb::MessageParser<MessageSetCorrectExtension1>(() => new MessageSetCorrectExtension1());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<MessageSetCorrectExtension1> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[22]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrectExtension1() {
           OnConstruction();
         }
@@ -4480,12 +5712,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrectExtension1(MessageSetCorrectExtension1 other) : this() {
           str_ = other.str_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrectExtension1 Clone() {
           return new MessageSetCorrectExtension1(this);
         }
@@ -4496,6 +5730,7 @@
 
         private string str_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string Str {
           get { return str_ ?? StrDefaultValue; }
           set {
@@ -4504,21 +5739,25 @@
         }
         /// <summary>Gets whether the "str" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasStr {
           get { return str_ != null; }
         }
         /// <summary>Clears the value of the "str" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearStr() {
           str_ = null;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as MessageSetCorrectExtension1);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(MessageSetCorrectExtension1 other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4531,6 +5770,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasStr) hash ^= Str.GetHashCode();
@@ -4541,12 +5781,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasStr) {
             output.WriteRawTag(202, 1);
             output.WriteString(Str);
@@ -4554,9 +5799,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasStr) {
+            output.WriteRawTag(202, 1);
+            output.WriteString(Str);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasStr) {
@@ -4569,6 +5830,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(MessageSetCorrectExtension1 other) {
           if (other == null) {
             return;
@@ -4580,7 +5842,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4593,11 +5859,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 202: {
+                Str = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
         #region Extensions
         /// <summary>Container for extensions for other messages declared in the MessageSetCorrectExtension1 message type.</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static partial class Extensions {
           public static readonly pb::Extension<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrect, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1> MessageSetExtension =
             new pb::Extension<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrect, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1>(1547769, pb::FieldCodec.ForMessage(12382154, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Parser));
@@ -4606,24 +5893,32 @@
 
       }
 
-      public sealed partial class MessageSetCorrectExtension2 : pb::IMessage<MessageSetCorrectExtension2> {
+      public sealed partial class MessageSetCorrectExtension2 : pb::IMessage<MessageSetCorrectExtension2>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<MessageSetCorrectExtension2> _parser = new pb::MessageParser<MessageSetCorrectExtension2>(() => new MessageSetCorrectExtension2());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<MessageSetCorrectExtension2> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[23]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrectExtension2() {
           OnConstruction();
         }
@@ -4631,6 +5926,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrectExtension2(MessageSetCorrectExtension2 other) : this() {
           _hasBits0 = other._hasBits0;
           i_ = other.i_;
@@ -4638,6 +5934,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public MessageSetCorrectExtension2 Clone() {
           return new MessageSetCorrectExtension2(this);
         }
@@ -4648,6 +5945,7 @@
 
         private int i_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int I {
           get { if ((_hasBits0 & 1) != 0) { return i_; } else { return IDefaultValue; } }
           set {
@@ -4657,21 +5955,25 @@
         }
         /// <summary>Gets whether the "i" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasI {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "i" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearI() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as MessageSetCorrectExtension2);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(MessageSetCorrectExtension2 other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4684,6 +5986,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasI) hash ^= I.GetHashCode();
@@ -4694,12 +5997,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasI) {
             output.WriteRawTag(72);
             output.WriteInt32(I);
@@ -4707,9 +6015,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasI) {
+            output.WriteRawTag(72);
+            output.WriteInt32(I);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasI) {
@@ -4722,6 +6046,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(MessageSetCorrectExtension2 other) {
           if (other == null) {
             return;
@@ -4733,7 +6058,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4746,11 +6075,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 72: {
+                I = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
         #region Extensions
         /// <summary>Container for extensions for other messages declared in the MessageSetCorrectExtension2 message type.</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static partial class Extensions {
           public static readonly pb::Extension<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrect, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2> MessageSetExtension =
             new pb::Extension<global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrect, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2>(4135312, pb::FieldCodec.ForMessage(33082498, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Parser));
@@ -4764,24 +6114,32 @@
 
   }
 
-  public sealed partial class ForeignMessageProto2 : pb::IMessage<ForeignMessageProto2> {
+  public sealed partial class ForeignMessageProto2 : pb::IMessage<ForeignMessageProto2>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ForeignMessageProto2> _parser = new pb::MessageParser<ForeignMessageProto2>(() => new ForeignMessageProto2());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ForeignMessageProto2> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessageProto2() {
       OnConstruction();
     }
@@ -4789,6 +6147,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessageProto2(ForeignMessageProto2 other) : this() {
       _hasBits0 = other._hasBits0;
       c_ = other.c_;
@@ -4796,6 +6155,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessageProto2 Clone() {
       return new ForeignMessageProto2(this);
     }
@@ -4806,6 +6166,7 @@
 
     private int c_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int C {
       get { if ((_hasBits0 & 1) != 0) { return c_; } else { return CDefaultValue; } }
       set {
@@ -4815,21 +6176,25 @@
     }
     /// <summary>Gets whether the "c" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasC {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "c" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearC() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ForeignMessageProto2);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ForeignMessageProto2 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4842,6 +6207,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasC) hash ^= C.GetHashCode();
@@ -4852,12 +6218,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasC) {
         output.WriteRawTag(8);
         output.WriteInt32(C);
@@ -4865,9 +6236,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasC) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasC) {
@@ -4880,6 +6267,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ForeignMessageProto2 other) {
       if (other == null) {
         return;
@@ -4891,7 +6279,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4904,28 +6296,56 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class UnknownToTestAllTypes : pb::IMessage<UnknownToTestAllTypes> {
+  public sealed partial class UnknownToTestAllTypes : pb::IMessage<UnknownToTestAllTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<UnknownToTestAllTypes> _parser = new pb::MessageParser<UnknownToTestAllTypes>(() => new UnknownToTestAllTypes());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<UnknownToTestAllTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UnknownToTestAllTypes() {
       OnConstruction();
     }
@@ -4933,11 +6353,12 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UnknownToTestAllTypes(UnknownToTestAllTypes other) : this() {
       _hasBits0 = other._hasBits0;
       optionalInt32_ = other.optionalInt32_;
       optionalString_ = other.optionalString_;
-      nestedMessage_ = other.HasNestedMessage ? other.nestedMessage_.Clone() : null;
+      nestedMessage_ = other.nestedMessage_ != null ? other.nestedMessage_.Clone() : null;
       optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null;
       optionalBool_ = other.optionalBool_;
       repeatedInt32_ = other.repeatedInt32_.Clone();
@@ -4945,6 +6366,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UnknownToTestAllTypes Clone() {
       return new UnknownToTestAllTypes(this);
     }
@@ -4955,6 +6377,7 @@
 
     private int optionalInt32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalInt32 {
       get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } }
       set {
@@ -4964,11 +6387,13 @@
     }
     /// <summary>Gets whether the "optional_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalInt32 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "optional_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalInt32() {
       _hasBits0 &= ~1;
     }
@@ -4979,6 +6404,7 @@
 
     private string optionalString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalString {
       get { return optionalString_ ?? OptionalStringDefaultValue; }
       set {
@@ -4987,11 +6413,13 @@
     }
     /// <summary>Gets whether the "optional_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalString {
       get { return optionalString_ != null; }
     }
     /// <summary>Clears the value of the "optional_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalString() {
       optionalString_ = null;
     }
@@ -5000,27 +6428,19 @@
     public const int NestedMessageFieldNumber = 1003;
     private global::ProtobufTestMessages.Proto2.ForeignMessageProto2 nestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.ForeignMessageProto2 NestedMessage {
       get { return nestedMessage_; }
       set {
         nestedMessage_ = value;
       }
     }
-    /// <summary>Gets whether the nested_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasNestedMessage {
-      get { return nestedMessage_ != null; }
-    }
-    /// <summary>Clears the value of the nested_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearNestedMessage() {
-      nestedMessage_ = null;
-    }
 
     /// <summary>Field number for the "optionalgroup" field.</summary>
     public const int OptionalGroupFieldNumber = 1004;
     private global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup optionalGroup_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup OptionalGroup {
       get { return optionalGroup_; }
       set {
@@ -5029,11 +6449,13 @@
     }
     /// <summary>Gets whether the optionalgroup field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalGroup {
       get { return optionalGroup_ != null; }
     }
     /// <summary>Clears the value of the optionalgroup field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalGroup() {
       optionalGroup_ = null;
     }
@@ -5044,6 +6466,7 @@
 
     private bool optionalBool_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool OptionalBool {
       get { if ((_hasBits0 & 2) != 0) { return optionalBool_; } else { return OptionalBoolDefaultValue; } }
       set {
@@ -5053,11 +6476,13 @@
     }
     /// <summary>Gets whether the "optional_bool" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalBool {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "optional_bool" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalBool() {
       _hasBits0 &= ~2;
     }
@@ -5068,16 +6493,19 @@
         = pb::FieldCodec.ForInt32(8088);
     private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as UnknownToTestAllTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(UnknownToTestAllTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5095,11 +6523,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode();
       if (HasOptionalString) hash ^= OptionalString.GetHashCode();
-      if (HasNestedMessage) hash ^= NestedMessage.GetHashCode();
+      if (nestedMessage_ != null) hash ^= NestedMessage.GetHashCode();
       if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode();
       if (HasOptionalBool) hash ^= OptionalBool.GetHashCode();
       hash ^= repeatedInt32_.GetHashCode();
@@ -5110,12 +6539,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasOptionalInt32) {
         output.WriteRawTag(200, 62);
         output.WriteInt32(OptionalInt32);
@@ -5124,7 +6558,7 @@
         output.WriteRawTag(210, 62);
         output.WriteString(OptionalString);
       }
-      if (HasNestedMessage) {
+      if (nestedMessage_ != null) {
         output.WriteRawTag(218, 62);
         output.WriteMessage(NestedMessage);
       }
@@ -5141,9 +6575,43 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasOptionalInt32) {
+        output.WriteRawTag(200, 62);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (HasOptionalString) {
+        output.WriteRawTag(210, 62);
+        output.WriteString(OptionalString);
+      }
+      if (nestedMessage_ != null) {
+        output.WriteRawTag(218, 62);
+        output.WriteMessage(NestedMessage);
+      }
+      if (HasOptionalGroup) {
+        output.WriteRawTag(227, 62);
+        output.WriteGroup(OptionalGroup);
+        output.WriteRawTag(228, 62);
+      }
+      if (HasOptionalBool) {
+        output.WriteRawTag(240, 62);
+        output.WriteBool(OptionalBool);
+      }
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasOptionalInt32) {
@@ -5152,7 +6620,7 @@
       if (HasOptionalString) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalString);
       }
-      if (HasNestedMessage) {
+      if (nestedMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(NestedMessage);
       }
       if (HasOptionalGroup) {
@@ -5169,6 +6637,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(UnknownToTestAllTypes other) {
       if (other == null) {
         return;
@@ -5179,8 +6648,8 @@
       if (other.HasOptionalString) {
         OptionalString = other.OptionalString;
       }
-      if (other.HasNestedMessage) {
-        if (!HasNestedMessage) {
+      if (other.nestedMessage_ != null) {
+        if (nestedMessage_ == null) {
           NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
         }
         NestedMessage.MergeFrom(other.NestedMessage);
@@ -5199,7 +6668,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5215,7 +6688,7 @@
             break;
           }
           case 8026: {
-            if (!HasNestedMessage) {
+            if (nestedMessage_ == null) {
               NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
             }
             input.ReadMessage(NestedMessage);
@@ -5239,30 +6712,86 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8008: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 8018: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 8026: {
+            if (nestedMessage_ == null) {
+              NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
+            }
+            input.ReadMessage(NestedMessage);
+            break;
+          }
+          case 8035: {
+            if (!HasOptionalGroup) {
+              OptionalGroup = new global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup();
+            }
+            input.ReadGroup(OptionalGroup);
+            break;
+          }
+          case 8048: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 8090:
+          case 8088: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the UnknownToTestAllTypes message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup> {
+      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<OptionalGroup> _parser = new pb::MessageParser<OptionalGroup>(() => new OptionalGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<OptionalGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup() {
           OnConstruction();
         }
@@ -5270,6 +6799,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup(OptionalGroup other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -5277,6 +6807,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup Clone() {
           return new OptionalGroup(this);
         }
@@ -5287,6 +6818,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -5296,21 +6828,25 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as OptionalGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(OptionalGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -5323,6 +6859,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -5333,12 +6870,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(8);
             output.WriteInt32(A);
@@ -5346,9 +6888,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(8);
+            output.WriteInt32(A);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -5361,6 +6919,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(OptionalGroup other) {
           if (other == null) {
             return;
@@ -5372,7 +6931,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -5387,8 +6950,30 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 8036:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                A = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
index 064d0c0..0e00150 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
@@ -29,7 +29,7 @@
             "dWYvYW55LnByb3RvGh5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8a",
             "IGdvb2dsZS9wcm90b2J1Zi9maWVsZF9tYXNrLnByb3RvGhxnb29nbGUvcHJv",
             "dG9idWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1w",
-            "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8iv0QKElRl",
+            "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8isUUKElRl",
             "c3RBbGxUeXBlc1Byb3RvMxIWCg5vcHRpb25hbF9pbnQzMhgBIAEoBRIWCg5v",
             "cHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25hbF91aW50MzIYAyABKA0S",
             "FwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29wdGlvbmFsX3NpbnQzMhgF",
@@ -140,99 +140,101 @@
             "IAEoBEgAEhUKC29uZW9mX2Zsb2F0GHUgASgCSAASFgoMb25lb2ZfZG91Ymxl",
             "GHYgASgBSAASUgoKb25lb2ZfZW51bRh3IAEoDjI8LnByb3RvYnVmX3Rlc3Rf",
             "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVt",
-            "SAASOgoVb3B0aW9uYWxfYm9vbF93cmFwcGVyGMkBIAEoCzIaLmdvb2dsZS5w",
-            "cm90b2J1Zi5Cb29sVmFsdWUSPAoWb3B0aW9uYWxfaW50MzJfd3JhcHBlchjK",
-            "ASABKAsyGy5nb29nbGUucHJvdG9idWYuSW50MzJWYWx1ZRI8ChZvcHRpb25h",
-            "bF9pbnQ2NF93cmFwcGVyGMsBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2",
-            "NFZhbHVlEj4KF29wdGlvbmFsX3VpbnQzMl93cmFwcGVyGMwBIAEoCzIcLmdv",
-            "b2dsZS5wcm90b2J1Zi5VSW50MzJWYWx1ZRI+ChdvcHRpb25hbF91aW50NjRf",
-            "d3JhcHBlchjNASABKAsyHC5nb29nbGUucHJvdG9idWYuVUludDY0VmFsdWUS",
-            "PAoWb3B0aW9uYWxfZmxvYXRfd3JhcHBlchjOASABKAsyGy5nb29nbGUucHJv",
-            "dG9idWYuRmxvYXRWYWx1ZRI+ChdvcHRpb25hbF9kb3VibGVfd3JhcHBlchjP",
-            "ASABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSPgoXb3B0aW9u",
-            "YWxfc3RyaW5nX3dyYXBwZXIY0AEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0",
-            "cmluZ1ZhbHVlEjwKFm9wdGlvbmFsX2J5dGVzX3dyYXBwZXIY0QEgASgLMhsu",
-            "Z29vZ2xlLnByb3RvYnVmLkJ5dGVzVmFsdWUSOgoVcmVwZWF0ZWRfYm9vbF93",
-            "cmFwcGVyGNMBIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWUSPAoW",
-            "cmVwZWF0ZWRfaW50MzJfd3JhcHBlchjUASADKAsyGy5nb29nbGUucHJvdG9i",
-            "dWYuSW50MzJWYWx1ZRI8ChZyZXBlYXRlZF9pbnQ2NF93cmFwcGVyGNUBIAMo",
-            "CzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEj4KF3JlcGVhdGVkX3Vp",
-            "bnQzMl93cmFwcGVyGNYBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50MzJW",
-            "YWx1ZRI+ChdyZXBlYXRlZF91aW50NjRfd3JhcHBlchjXASADKAsyHC5nb29n",
-            "bGUucHJvdG9idWYuVUludDY0VmFsdWUSPAoWcmVwZWF0ZWRfZmxvYXRfd3Jh",
-            "cHBlchjYASADKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRI+Chdy",
-            "ZXBlYXRlZF9kb3VibGVfd3JhcHBlchjZASADKAsyHC5nb29nbGUucHJvdG9i",
-            "dWYuRG91YmxlVmFsdWUSPgoXcmVwZWF0ZWRfc3RyaW5nX3dyYXBwZXIY2gEg",
-            "AygLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEjwKFnJlcGVhdGVk",
-            "X2J5dGVzX3dyYXBwZXIY2wEgAygLMhsuZ29vZ2xlLnByb3RvYnVmLkJ5dGVz",
-            "VmFsdWUSNQoRb3B0aW9uYWxfZHVyYXRpb24YrQIgASgLMhkuZ29vZ2xlLnBy",
-            "b3RvYnVmLkR1cmF0aW9uEjcKEm9wdGlvbmFsX3RpbWVzdGFtcBiuAiABKAsy",
-            "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjgKE29wdGlvbmFsX2ZpZWxk",
-            "X21hc2sYrwIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFzaxIxCg9v",
-            "cHRpb25hbF9zdHJ1Y3QYsAIgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVj",
-            "dBIrCgxvcHRpb25hbF9hbnkYsQIgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFu",
-            "eRIvCg5vcHRpb25hbF92YWx1ZRiyAiABKAsyFi5nb29nbGUucHJvdG9idWYu",
-            "VmFsdWUSNQoRcmVwZWF0ZWRfZHVyYXRpb24YtwIgAygLMhkuZ29vZ2xlLnBy",
-            "b3RvYnVmLkR1cmF0aW9uEjcKEnJlcGVhdGVkX3RpbWVzdGFtcBi4AiADKAsy",
-            "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjcKEnJlcGVhdGVkX2ZpZWxk",
-            "bWFzaxi5AiADKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrEjEKD3Jl",
-            "cGVhdGVkX3N0cnVjdBjEAiADKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0",
-            "EisKDHJlcGVhdGVkX2FueRi7AiADKAsyFC5nb29nbGUucHJvdG9idWYuQW55",
-            "Ei8KDnJlcGVhdGVkX3ZhbHVlGLwCIAMoCzIWLmdvb2dsZS5wcm90b2J1Zi5W",
-            "YWx1ZRI4ChNyZXBlYXRlZF9saXN0X3ZhbHVlGL0CIAMoCzIaLmdvb2dsZS5w",
-            "cm90b2J1Zi5MaXN0VmFsdWUSEwoKZmllbGRuYW1lMRiRAyABKAUSFAoLZmll",
-            "bGRfbmFtZTIYkgMgASgFEhUKDF9maWVsZF9uYW1lMxiTAyABKAUSFgoNZmll",
-            "bGRfX25hbWU0XxiUAyABKAUSFAoLZmllbGQwbmFtZTUYlQMgASgFEhYKDWZp",
-            "ZWxkXzBfbmFtZTYYlgMgASgFEhMKCmZpZWxkTmFtZTcYlwMgASgFEhMKCkZp",
-            "ZWxkTmFtZTgYmAMgASgFEhQKC2ZpZWxkX05hbWU5GJkDIAEoBRIVCgxGaWVs",
-            "ZF9OYW1lMTAYmgMgASgFEhUKDEZJRUxEX05BTUUxMRibAyABKAUSFQoMRklF",
-            "TERfbmFtZTEyGJwDIAEoBRIXCg5fX2ZpZWxkX25hbWUxMxidAyABKAUSFwoO",
-            "X19GaWVsZF9uYW1lMTQYngMgASgFEhYKDWZpZWxkX19uYW1lMTUYnwMgASgF",
-            "EhYKDWZpZWxkX19OYW1lMTYYoAMgASgFEhcKDmZpZWxkX25hbWUxN19fGKED",
-            "IAEoBRIXCg5GaWVsZF9uYW1lMThfXxiiAyABKAUaYgoNTmVzdGVkTWVzc2Fn",
-            "ZRIJCgFhGAEgASgFEkYKC2NvcmVjdXJzaXZlGAIgASgLMjEucHJvdG9idWZf",
-            "dGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zGjQKEk1h",
-            "cEludDMySW50MzJFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6",
-            "AjgBGjQKEk1hcEludDY0SW50NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFs",
-            "dWUYAiABKAM6AjgBGjYKFE1hcFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgB",
-            "IAEoDRINCgV2YWx1ZRgCIAEoDToCOAEaNgoUTWFwVWludDY0VWludDY0RW50",
-            "cnkSCwoDa2V5GAEgASgEEg0KBXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50",
-            "MzJTaW50MzJFbnRyeRILCgNrZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgB",
-            "GjYKFE1hcFNpbnQ2NFNpbnQ2NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1",
-            "ZRgCIAEoEjoCOAEaOAoWTWFwRml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkY",
-            "ASABKAcSDQoFdmFsdWUYAiABKAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0",
-            "RW50cnkSCwoDa2V5GAEgASgGEg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBT",
-            "Zml4ZWQzMlNmaXhlZDMyRW50cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIg",
-            "ASgPOgI4ARo6ChhNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEg",
-            "ASgQEg0KBXZhbHVlGAIgASgQOgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkS",
-            "CwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRv",
-            "dWJsZUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQ",
-            "TWFwQm9vbEJvb2xFbnRyeRILCgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6",
-            "AjgBGjYKFE1hcFN0cmluZ1N0cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2",
-            "YWx1ZRgCIAEoCToCOAEaNQoTTWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkY",
-            "ASABKAkSDQoFdmFsdWUYAiABKAw6AjgBGn4KG01hcFN0cmluZ05lc3RlZE1l",
-            "c3NhZ2VFbnRyeRILCgNrZXkYASABKAkSTgoFdmFsdWUYAiABKAsyPy5wcm90",
-            "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMu",
-            "TmVzdGVkTWVzc2FnZToCOAEabQocTWFwU3RyaW5nRm9yZWlnbk1lc3NhZ2VF",
-            "bnRyeRILCgNrZXkYASABKAkSPAoFdmFsdWUYAiABKAsyLS5wcm90b2J1Zl90",
-            "ZXN0X21lc3NhZ2VzLnByb3RvMy5Gb3JlaWduTWVzc2FnZToCOAEaeAoYTWFw",
-            "U3RyaW5nTmVzdGVkRW51bUVudHJ5EgsKA2tleRgBIAEoCRJLCgV2YWx1ZRgC",
-            "IAEoDjI8LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxU",
-            "eXBlc1Byb3RvMy5OZXN0ZWRFbnVtOgI4ARpnChlNYXBTdHJpbmdGb3JlaWdu",
-            "RW51bUVudHJ5EgsKA2tleRgBIAEoCRI5CgV2YWx1ZRgCIAEoDjIqLnByb3Rv",
-            "YnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25FbnVtOgI4ASI5CgpO",
-            "ZXN0ZWRFbnVtEgcKA0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD/",
-            "//////////8BIlkKC0FsaWFzZWRFbnVtEg0KCUFMSUFTX0ZPTxAAEg0KCUFM",
-            "SUFTX0JBUhABEg0KCUFMSUFTX0JBWhACEgcKA1FVWBACEgcKA3F1eBACEgcK",
-            "A2JBehACGgIQAUINCgtvbmVvZl9maWVsZEoGCPUDEP8DIhsKDkZvcmVpZ25N",
-            "ZXNzYWdlEgkKAWMYASABKAUqQAoLRm9yZWlnbkVudW0SDwoLRk9SRUlHTl9G",
-            "T08QABIPCgtGT1JFSUdOX0JBUhABEg8KC0ZPUkVJR05fQkFaEAJCOAooY29t",
-            "Lmdvb2dsZS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvM0gB+AEBogIG",
-            "UHJvdG8zYgZwcm90bzM="));
+            "SAASNgoQb25lb2ZfbnVsbF92YWx1ZRh4IAEoDjIaLmdvb2dsZS5wcm90b2J1",
+            "Zi5OdWxsVmFsdWVIABI6ChVvcHRpb25hbF9ib29sX3dyYXBwZXIYyQEgASgL",
+            "MhouZ29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZRI8ChZvcHRpb25hbF9pbnQz",
+            "Ml93cmFwcGVyGMoBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVl",
+            "EjwKFm9wdGlvbmFsX2ludDY0X3dyYXBwZXIYywEgASgLMhsuZ29vZ2xlLnBy",
+            "b3RvYnVmLkludDY0VmFsdWUSPgoXb3B0aW9uYWxfdWludDMyX3dyYXBwZXIY",
+            "zAEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEj4KF29wdGlv",
+            "bmFsX3VpbnQ2NF93cmFwcGVyGM0BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5V",
+            "SW50NjRWYWx1ZRI8ChZvcHRpb25hbF9mbG9hdF93cmFwcGVyGM4BIAEoCzIb",
+            "Lmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZhbHVlEj4KF29wdGlvbmFsX2RvdWJs",
+            "ZV93cmFwcGVyGM8BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1",
+            "ZRI+ChdvcHRpb25hbF9zdHJpbmdfd3JhcHBlchjQASABKAsyHC5nb29nbGUu",
+            "cHJvdG9idWYuU3RyaW5nVmFsdWUSPAoWb3B0aW9uYWxfYnl0ZXNfd3JhcHBl",
+            "chjRASABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRI6ChVyZXBl",
+            "YXRlZF9ib29sX3dyYXBwZXIY0wEgAygLMhouZ29vZ2xlLnByb3RvYnVmLkJv",
+            "b2xWYWx1ZRI8ChZyZXBlYXRlZF9pbnQzMl93cmFwcGVyGNQBIAMoCzIbLmdv",
+            "b2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjwKFnJlcGVhdGVkX2ludDY0X3dy",
+            "YXBwZXIY1QEgAygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSPgoX",
+            "cmVwZWF0ZWRfdWludDMyX3dyYXBwZXIY1gEgAygLMhwuZ29vZ2xlLnByb3Rv",
+            "YnVmLlVJbnQzMlZhbHVlEj4KF3JlcGVhdGVkX3VpbnQ2NF93cmFwcGVyGNcB",
+            "IAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZRI8ChZyZXBlYXRl",
+            "ZF9mbG9hdF93cmFwcGVyGNgBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5GbG9h",
+            "dFZhbHVlEj4KF3JlcGVhdGVkX2RvdWJsZV93cmFwcGVyGNkBIAMoCzIcLmdv",
+            "b2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI+ChdyZXBlYXRlZF9zdHJpbmdf",
+            "d3JhcHBlchjaASADKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUS",
+            "PAoWcmVwZWF0ZWRfYnl0ZXNfd3JhcHBlchjbASADKAsyGy5nb29nbGUucHJv",
+            "dG9idWYuQnl0ZXNWYWx1ZRI1ChFvcHRpb25hbF9kdXJhdGlvbhitAiABKAsy",
+            "GS5nb29nbGUucHJvdG9idWYuRHVyYXRpb24SNwoSb3B0aW9uYWxfdGltZXN0",
+            "YW1wGK4CIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASOAoTb3B0",
+            "aW9uYWxfZmllbGRfbWFzaxivAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmll",
+            "bGRNYXNrEjEKD29wdGlvbmFsX3N0cnVjdBiwAiABKAsyFy5nb29nbGUucHJv",
+            "dG9idWYuU3RydWN0EisKDG9wdGlvbmFsX2FueRixAiABKAsyFC5nb29nbGUu",
+            "cHJvdG9idWYuQW55Ei8KDm9wdGlvbmFsX3ZhbHVlGLICIAEoCzIWLmdvb2ds",
+            "ZS5wcm90b2J1Zi5WYWx1ZRI4ChNvcHRpb25hbF9udWxsX3ZhbHVlGLMCIAEo",
+            "DjIaLmdvb2dsZS5wcm90b2J1Zi5OdWxsVmFsdWUSNQoRcmVwZWF0ZWRfZHVy",
+            "YXRpb24YtwIgAygLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEjcKEnJl",
+            "cGVhdGVkX3RpbWVzdGFtcBi4AiADKAsyGi5nb29nbGUucHJvdG9idWYuVGlt",
+            "ZXN0YW1wEjcKEnJlcGVhdGVkX2ZpZWxkbWFzaxi5AiADKAsyGi5nb29nbGUu",
+            "cHJvdG9idWYuRmllbGRNYXNrEjEKD3JlcGVhdGVkX3N0cnVjdBjEAiADKAsy",
+            "Fy5nb29nbGUucHJvdG9idWYuU3RydWN0EisKDHJlcGVhdGVkX2FueRi7AiAD",
+            "KAsyFC5nb29nbGUucHJvdG9idWYuQW55Ei8KDnJlcGVhdGVkX3ZhbHVlGLwC",
+            "IAMoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRI4ChNyZXBlYXRlZF9saXN0",
+            "X3ZhbHVlGL0CIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5MaXN0VmFsdWUSEwoK",
+            "ZmllbGRuYW1lMRiRAyABKAUSFAoLZmllbGRfbmFtZTIYkgMgASgFEhUKDF9m",
+            "aWVsZF9uYW1lMxiTAyABKAUSFgoNZmllbGRfX25hbWU0XxiUAyABKAUSFAoL",
+            "ZmllbGQwbmFtZTUYlQMgASgFEhYKDWZpZWxkXzBfbmFtZTYYlgMgASgFEhMK",
+            "CmZpZWxkTmFtZTcYlwMgASgFEhMKCkZpZWxkTmFtZTgYmAMgASgFEhQKC2Zp",
+            "ZWxkX05hbWU5GJkDIAEoBRIVCgxGaWVsZF9OYW1lMTAYmgMgASgFEhUKDEZJ",
+            "RUxEX05BTUUxMRibAyABKAUSFQoMRklFTERfbmFtZTEyGJwDIAEoBRIXCg5f",
+            "X2ZpZWxkX25hbWUxMxidAyABKAUSFwoOX19GaWVsZF9uYW1lMTQYngMgASgF",
+            "EhYKDWZpZWxkX19uYW1lMTUYnwMgASgFEhYKDWZpZWxkX19OYW1lMTYYoAMg",
+            "ASgFEhcKDmZpZWxkX25hbWUxN19fGKEDIAEoBRIXCg5GaWVsZF9uYW1lMThf",
+            "XxiiAyABKAUaYgoNTmVzdGVkTWVzc2FnZRIJCgFhGAEgASgFEkYKC2NvcmVj",
+            "dXJzaXZlGAIgASgLMjEucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMu",
+            "VGVzdEFsbFR5cGVzUHJvdG8zGjQKEk1hcEludDMySW50MzJFbnRyeRILCgNr",
+            "ZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50NjRF",
+            "bnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1hcFVp",
+            "bnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEoDToC",
+            "OAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0KBXZh",
+            "bHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNrZXkY",
+            "ASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2NEVu",
+            "dHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFwRml4",
+            "ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiABKAc6",
+            "AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgGEg0K",
+            "BXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50cnkS",
+            "CwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4ZWQ2",
+            "NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQOgI4",
+            "ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVl",
+            "GAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgBIAEo",
+            "BRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRILCgNr",
+            "ZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1hcFN0cmluZ1N0cmlu",
+            "Z0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEaNQoTTWFw",
+            "U3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAw6",
+            "AjgBGn4KG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRILCgNrZXkYASAB",
+            "KAkSTgoFdmFsdWUYAiABKAsyPy5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnBy",
+            "b3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTmVzdGVkTWVzc2FnZToCOAEabQoc",
+            "TWFwU3RyaW5nRm9yZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAkSPAoF",
+            "dmFsdWUYAiABKAsyLS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5G",
+            "b3JlaWduTWVzc2FnZToCOAEaeAoYTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5",
+            "EgsKA2tleRgBIAEoCRJLCgV2YWx1ZRgCIAEoDjI8LnByb3RvYnVmX3Rlc3Rf",
+            "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVt",
+            "OgI4ARpnChlNYXBTdHJpbmdGb3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEo",
+            "CRI5CgV2YWx1ZRgCIAEoDjIqLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv",
+            "dG8zLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0ZWRFbnVtEgcKA0ZPTxAAEgcK",
+            "A0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8BIlkKC0FsaWFzZWRF",
+            "bnVtEg0KCUFMSUFTX0ZPTxAAEg0KCUFMSUFTX0JBUhABEg0KCUFMSUFTX0JB",
+            "WhACEgcKA1FVWBACEgcKA3F1eBACEgcKA2JBehACGgIQAUINCgtvbmVvZl9m",
+            "aWVsZEoGCPUDEP8DIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUqQAoL",
+            "Rm9yZWlnbkVudW0SDwoLRk9SRUlHTl9GT08QABIPCgtGT1JFSUdOX0JBUhAB",
+            "Eg8KC0ZPUkVJR05fQkFaEAJCOAooY29tLmdvb2dsZS5wcm90b2J1Zl90ZXN0",
+            "X21lc3NhZ2VzLnByb3RvM0gB+AEBogIGUHJvdG8zYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Proto3.ForeignEnum), }, null, new pbr::GeneratedClrTypeInfo[] {
-            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalAliasedEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedNestedEnum", "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedNestedEnum", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "RepeatedListValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum), typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalAliasedEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedNestedEnum", "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedNestedEnum", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OneofNullValue", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "OptionalNullValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "RepeatedListValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum), typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null, null),
             null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
             new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.ForeignMessage), global::ProtobufTestMessages.Proto3.ForeignMessage.Parser, new[]{ "C" }, null, null, null, null)
           }));
@@ -259,23 +261,31 @@
   /// could trigger bugs that occur in any message type in this file.  We verify
   /// this stays true in a unit test.
   /// </summary>
-  public sealed partial class TestAllTypesProto3 : pb::IMessage<TestAllTypesProto3> {
+  public sealed partial class TestAllTypesProto3 : pb::IMessage<TestAllTypesProto3>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestAllTypesProto3> _parser = new pb::MessageParser<TestAllTypesProto3>(() => new TestAllTypesProto3());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestAllTypesProto3> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypesProto3() {
       OnConstruction();
     }
@@ -283,6 +293,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypesProto3(TestAllTypesProto3 other) : this() {
       optionalInt32_ = other.optionalInt32_;
       optionalInt64_ = other.optionalInt64_;
@@ -399,6 +410,7 @@
       optionalStruct_ = other.optionalStruct_ != null ? other.optionalStruct_.Clone() : null;
       optionalAny_ = other.optionalAny_ != null ? other.optionalAny_.Clone() : null;
       optionalValue_ = other.optionalValue_ != null ? other.optionalValue_.Clone() : null;
+      optionalNullValue_ = other.optionalNullValue_;
       repeatedDuration_ = other.repeatedDuration_.Clone();
       repeatedTimestamp_ = other.repeatedTimestamp_.Clone();
       repeatedFieldmask_ = other.repeatedFieldmask_.Clone();
@@ -452,12 +464,16 @@
         case OneofFieldOneofCase.OneofEnum:
           OneofEnum = other.OneofEnum;
           break;
+        case OneofFieldOneofCase.OneofNullValue:
+          OneofNullValue = other.OneofNullValue;
+          break;
       }
 
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypesProto3 Clone() {
       return new TestAllTypesProto3(this);
     }
@@ -469,6 +485,7 @@
     /// Singular
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalInt32 {
       get { return optionalInt32_; }
       set {
@@ -480,6 +497,7 @@
     public const int OptionalInt64FieldNumber = 2;
     private long optionalInt64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalInt64 {
       get { return optionalInt64_; }
       set {
@@ -491,6 +509,7 @@
     public const int OptionalUint32FieldNumber = 3;
     private uint optionalUint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OptionalUint32 {
       get { return optionalUint32_; }
       set {
@@ -502,6 +521,7 @@
     public const int OptionalUint64FieldNumber = 4;
     private ulong optionalUint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OptionalUint64 {
       get { return optionalUint64_; }
       set {
@@ -513,6 +533,7 @@
     public const int OptionalSint32FieldNumber = 5;
     private int optionalSint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalSint32 {
       get { return optionalSint32_; }
       set {
@@ -524,6 +545,7 @@
     public const int OptionalSint64FieldNumber = 6;
     private long optionalSint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalSint64 {
       get { return optionalSint64_; }
       set {
@@ -535,6 +557,7 @@
     public const int OptionalFixed32FieldNumber = 7;
     private uint optionalFixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OptionalFixed32 {
       get { return optionalFixed32_; }
       set {
@@ -546,6 +569,7 @@
     public const int OptionalFixed64FieldNumber = 8;
     private ulong optionalFixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OptionalFixed64 {
       get { return optionalFixed64_; }
       set {
@@ -557,6 +581,7 @@
     public const int OptionalSfixed32FieldNumber = 9;
     private int optionalSfixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalSfixed32 {
       get { return optionalSfixed32_; }
       set {
@@ -568,6 +593,7 @@
     public const int OptionalSfixed64FieldNumber = 10;
     private long optionalSfixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalSfixed64 {
       get { return optionalSfixed64_; }
       set {
@@ -579,6 +605,7 @@
     public const int OptionalFloatFieldNumber = 11;
     private float optionalFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float OptionalFloat {
       get { return optionalFloat_; }
       set {
@@ -590,6 +617,7 @@
     public const int OptionalDoubleFieldNumber = 12;
     private double optionalDouble_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double OptionalDouble {
       get { return optionalDouble_; }
       set {
@@ -601,6 +629,7 @@
     public const int OptionalBoolFieldNumber = 13;
     private bool optionalBool_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool OptionalBool {
       get { return optionalBool_; }
       set {
@@ -612,6 +641,7 @@
     public const int OptionalStringFieldNumber = 14;
     private string optionalString_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalString {
       get { return optionalString_; }
       set {
@@ -623,6 +653,7 @@
     public const int OptionalBytesFieldNumber = 15;
     private pb::ByteString optionalBytes_ = pb::ByteString.Empty;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OptionalBytes {
       get { return optionalBytes_; }
       set {
@@ -634,6 +665,7 @@
     public const int OptionalNestedMessageFieldNumber = 18;
     private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage optionalNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OptionalNestedMessage {
       get { return optionalNestedMessage_; }
       set {
@@ -645,6 +677,7 @@
     public const int OptionalForeignMessageFieldNumber = 19;
     private global::ProtobufTestMessages.Proto3.ForeignMessage optionalForeignMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.ForeignMessage OptionalForeignMessage {
       get { return optionalForeignMessage_; }
       set {
@@ -656,6 +689,7 @@
     public const int OptionalNestedEnumFieldNumber = 21;
     private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum optionalNestedEnum_ = global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OptionalNestedEnum {
       get { return optionalNestedEnum_; }
       set {
@@ -667,6 +701,7 @@
     public const int OptionalForeignEnumFieldNumber = 22;
     private global::ProtobufTestMessages.Proto3.ForeignEnum optionalForeignEnum_ = global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.ForeignEnum OptionalForeignEnum {
       get { return optionalForeignEnum_; }
       set {
@@ -678,6 +713,7 @@
     public const int OptionalAliasedEnumFieldNumber = 23;
     private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum optionalAliasedEnum_ = global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum OptionalAliasedEnum {
       get { return optionalAliasedEnum_; }
       set {
@@ -689,6 +725,7 @@
     public const int OptionalStringPieceFieldNumber = 24;
     private string optionalStringPiece_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalStringPiece {
       get { return optionalStringPiece_; }
       set {
@@ -700,6 +737,7 @@
     public const int OptionalCordFieldNumber = 25;
     private string optionalCord_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalCord {
       get { return optionalCord_; }
       set {
@@ -711,6 +749,7 @@
     public const int RecursiveMessageFieldNumber = 27;
     private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 recursiveMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 RecursiveMessage {
       get { return recursiveMessage_; }
       set {
@@ -727,6 +766,7 @@
     /// Repeated
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
@@ -737,6 +777,7 @@
         = pb::FieldCodec.ForInt64(258);
     private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedInt64 {
       get { return repeatedInt64_; }
     }
@@ -747,6 +788,7 @@
         = pb::FieldCodec.ForUInt32(266);
     private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedUint32 {
       get { return repeatedUint32_; }
     }
@@ -757,6 +799,7 @@
         = pb::FieldCodec.ForUInt64(274);
     private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedUint64 {
       get { return repeatedUint64_; }
     }
@@ -767,6 +810,7 @@
         = pb::FieldCodec.ForSInt32(282);
     private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSint32 {
       get { return repeatedSint32_; }
     }
@@ -777,6 +821,7 @@
         = pb::FieldCodec.ForSInt64(290);
     private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSint64 {
       get { return repeatedSint64_; }
     }
@@ -787,6 +832,7 @@
         = pb::FieldCodec.ForFixed32(298);
     private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedFixed32 {
       get { return repeatedFixed32_; }
     }
@@ -797,6 +843,7 @@
         = pb::FieldCodec.ForFixed64(306);
     private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedFixed64 {
       get { return repeatedFixed64_; }
     }
@@ -807,6 +854,7 @@
         = pb::FieldCodec.ForSFixed32(314);
     private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSfixed32 {
       get { return repeatedSfixed32_; }
     }
@@ -817,6 +865,7 @@
         = pb::FieldCodec.ForSFixed64(322);
     private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSfixed64 {
       get { return repeatedSfixed64_; }
     }
@@ -827,6 +876,7 @@
         = pb::FieldCodec.ForFloat(330);
     private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> RepeatedFloat {
       get { return repeatedFloat_; }
     }
@@ -837,6 +887,7 @@
         = pb::FieldCodec.ForDouble(338);
     private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> RepeatedDouble {
       get { return repeatedDouble_; }
     }
@@ -847,6 +898,7 @@
         = pb::FieldCodec.ForBool(346);
     private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> RepeatedBool {
       get { return repeatedBool_; }
     }
@@ -857,6 +909,7 @@
         = pb::FieldCodec.ForString(354);
     private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedString {
       get { return repeatedString_; }
     }
@@ -867,6 +920,7 @@
         = pb::FieldCodec.ForBytes(362);
     private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
       get { return repeatedBytes_; }
     }
@@ -877,6 +931,7 @@
         = pb::FieldCodec.ForMessage(386, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> RepeatedNestedMessage {
       get { return repeatedNestedMessage_; }
     }
@@ -887,6 +942,7 @@
         = pb::FieldCodec.ForMessage(394, global::ProtobufTestMessages.Proto3.ForeignMessage.Parser);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.ForeignMessage> RepeatedForeignMessage {
       get { return repeatedForeignMessage_; }
     }
@@ -897,6 +953,7 @@
         = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> RepeatedNestedEnum {
       get { return repeatedNestedEnum_; }
     }
@@ -907,6 +964,7 @@
         = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::ProtobufTestMessages.Proto3.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.ForeignEnum> RepeatedForeignEnum {
       get { return repeatedForeignEnum_; }
     }
@@ -917,6 +975,7 @@
         = pb::FieldCodec.ForString(434);
     private readonly pbc::RepeatedField<string> repeatedStringPiece_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedStringPiece {
       get { return repeatedStringPiece_; }
     }
@@ -927,6 +986,7 @@
         = pb::FieldCodec.ForString(442);
     private readonly pbc::RepeatedField<string> repeatedCord_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedCord {
       get { return repeatedCord_; }
     }
@@ -940,6 +1000,7 @@
     /// Packed
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedInt32 {
       get { return packedInt32_; }
     }
@@ -950,6 +1011,7 @@
         = pb::FieldCodec.ForInt64(610);
     private readonly pbc::RepeatedField<long> packedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedInt64 {
       get { return packedInt64_; }
     }
@@ -960,6 +1022,7 @@
         = pb::FieldCodec.ForUInt32(618);
     private readonly pbc::RepeatedField<uint> packedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedUint32 {
       get { return packedUint32_; }
     }
@@ -970,6 +1033,7 @@
         = pb::FieldCodec.ForUInt64(626);
     private readonly pbc::RepeatedField<ulong> packedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedUint64 {
       get { return packedUint64_; }
     }
@@ -980,6 +1044,7 @@
         = pb::FieldCodec.ForSInt32(634);
     private readonly pbc::RepeatedField<int> packedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSint32 {
       get { return packedSint32_; }
     }
@@ -990,6 +1055,7 @@
         = pb::FieldCodec.ForSInt64(642);
     private readonly pbc::RepeatedField<long> packedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSint64 {
       get { return packedSint64_; }
     }
@@ -1000,6 +1066,7 @@
         = pb::FieldCodec.ForFixed32(650);
     private readonly pbc::RepeatedField<uint> packedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedFixed32 {
       get { return packedFixed32_; }
     }
@@ -1010,6 +1077,7 @@
         = pb::FieldCodec.ForFixed64(658);
     private readonly pbc::RepeatedField<ulong> packedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedFixed64 {
       get { return packedFixed64_; }
     }
@@ -1020,6 +1088,7 @@
         = pb::FieldCodec.ForSFixed32(666);
     private readonly pbc::RepeatedField<int> packedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSfixed32 {
       get { return packedSfixed32_; }
     }
@@ -1030,6 +1099,7 @@
         = pb::FieldCodec.ForSFixed64(674);
     private readonly pbc::RepeatedField<long> packedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSfixed64 {
       get { return packedSfixed64_; }
     }
@@ -1040,6 +1110,7 @@
         = pb::FieldCodec.ForFloat(682);
     private readonly pbc::RepeatedField<float> packedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> PackedFloat {
       get { return packedFloat_; }
     }
@@ -1050,6 +1121,7 @@
         = pb::FieldCodec.ForDouble(690);
     private readonly pbc::RepeatedField<double> packedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> PackedDouble {
       get { return packedDouble_; }
     }
@@ -1060,6 +1132,7 @@
         = pb::FieldCodec.ForBool(698);
     private readonly pbc::RepeatedField<bool> packedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> PackedBool {
       get { return packedBool_; }
     }
@@ -1070,6 +1143,7 @@
         = pb::FieldCodec.ForEnum(706, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> packedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> PackedNestedEnum {
       get { return packedNestedEnum_; }
     }
@@ -1083,6 +1157,7 @@
     /// Unpacked
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedInt32 {
       get { return unpackedInt32_; }
     }
@@ -1093,6 +1168,7 @@
         = pb::FieldCodec.ForInt64(720);
     private readonly pbc::RepeatedField<long> unpackedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedInt64 {
       get { return unpackedInt64_; }
     }
@@ -1103,6 +1179,7 @@
         = pb::FieldCodec.ForUInt32(728);
     private readonly pbc::RepeatedField<uint> unpackedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedUint32 {
       get { return unpackedUint32_; }
     }
@@ -1113,6 +1190,7 @@
         = pb::FieldCodec.ForUInt64(736);
     private readonly pbc::RepeatedField<ulong> unpackedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedUint64 {
       get { return unpackedUint64_; }
     }
@@ -1123,6 +1201,7 @@
         = pb::FieldCodec.ForSInt32(744);
     private readonly pbc::RepeatedField<int> unpackedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSint32 {
       get { return unpackedSint32_; }
     }
@@ -1133,6 +1212,7 @@
         = pb::FieldCodec.ForSInt64(752);
     private readonly pbc::RepeatedField<long> unpackedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSint64 {
       get { return unpackedSint64_; }
     }
@@ -1143,6 +1223,7 @@
         = pb::FieldCodec.ForFixed32(765);
     private readonly pbc::RepeatedField<uint> unpackedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedFixed32 {
       get { return unpackedFixed32_; }
     }
@@ -1153,6 +1234,7 @@
         = pb::FieldCodec.ForFixed64(769);
     private readonly pbc::RepeatedField<ulong> unpackedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedFixed64 {
       get { return unpackedFixed64_; }
     }
@@ -1163,6 +1245,7 @@
         = pb::FieldCodec.ForSFixed32(781);
     private readonly pbc::RepeatedField<int> unpackedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSfixed32 {
       get { return unpackedSfixed32_; }
     }
@@ -1173,6 +1256,7 @@
         = pb::FieldCodec.ForSFixed64(785);
     private readonly pbc::RepeatedField<long> unpackedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSfixed64 {
       get { return unpackedSfixed64_; }
     }
@@ -1183,6 +1267,7 @@
         = pb::FieldCodec.ForFloat(797);
     private readonly pbc::RepeatedField<float> unpackedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> UnpackedFloat {
       get { return unpackedFloat_; }
     }
@@ -1193,6 +1278,7 @@
         = pb::FieldCodec.ForDouble(801);
     private readonly pbc::RepeatedField<double> unpackedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> UnpackedDouble {
       get { return unpackedDouble_; }
     }
@@ -1203,6 +1289,7 @@
         = pb::FieldCodec.ForBool(808);
     private readonly pbc::RepeatedField<bool> unpackedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> UnpackedBool {
       get { return unpackedBool_; }
     }
@@ -1213,6 +1300,7 @@
         = pb::FieldCodec.ForEnum(816, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> unpackedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> UnpackedNestedEnum {
       get { return unpackedNestedEnum_; }
     }
@@ -1226,6 +1314,7 @@
     /// Map
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapInt32Int32 {
       get { return mapInt32Int32_; }
     }
@@ -1236,6 +1325,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 458);
     private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapInt64Int64 {
       get { return mapInt64Int64_; }
     }
@@ -1246,6 +1336,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 466);
     private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapUint32Uint32 {
       get { return mapUint32Uint32_; }
     }
@@ -1256,6 +1347,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 474);
     private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapUint64Uint64 {
       get { return mapUint64Uint64_; }
     }
@@ -1266,6 +1358,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 482);
     private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSint32Sint32 {
       get { return mapSint32Sint32_; }
     }
@@ -1276,6 +1369,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 490);
     private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSint64Sint64 {
       get { return mapSint64Sint64_; }
     }
@@ -1286,6 +1380,7 @@
         = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 498);
     private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<uint, uint> MapFixed32Fixed32 {
       get { return mapFixed32Fixed32_; }
     }
@@ -1296,6 +1391,7 @@
         = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 506);
     private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
       get { return mapFixed64Fixed64_; }
     }
@@ -1306,6 +1402,7 @@
         = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 514);
     private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int> MapSfixed32Sfixed32 {
       get { return mapSfixed32Sfixed32_; }
     }
@@ -1316,6 +1413,7 @@
         = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 522);
     private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<long, long> MapSfixed64Sfixed64 {
       get { return mapSfixed64Sfixed64_; }
     }
@@ -1326,6 +1424,7 @@
         = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 530);
     private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, float> MapInt32Float {
       get { return mapInt32Float_; }
     }
@@ -1336,6 +1435,7 @@
         = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 538);
     private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, double> MapInt32Double {
       get { return mapInt32Double_; }
     }
@@ -1346,6 +1446,7 @@
         = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 546);
     private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<bool, bool> MapBoolBool {
       get { return mapBoolBool_; }
     }
@@ -1356,6 +1457,7 @@
         = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 554);
     private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, string> MapStringString {
       get { return mapStringString_; }
     }
@@ -1366,6 +1468,7 @@
         = new pbc::MapField<string, pb::ByteString>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForBytes(18, pb::ByteString.Empty), 562);
     private readonly pbc::MapField<string, pb::ByteString> mapStringBytes_ = new pbc::MapField<string, pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, pb::ByteString> MapStringBytes {
       get { return mapStringBytes_; }
     }
@@ -1376,6 +1479,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser), 570);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> mapStringNestedMessage_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> MapStringNestedMessage {
       get { return mapStringNestedMessage_; }
     }
@@ -1386,6 +1490,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignMessage>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.ForeignMessage.Parser), 578);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignMessage> mapStringForeignMessage_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignMessage> MapStringForeignMessage {
       get { return mapStringForeignMessage_; }
     }
@@ -1396,6 +1501,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo), 586);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> mapStringNestedEnum_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> MapStringNestedEnum {
       get { return mapStringNestedEnum_; }
     }
@@ -1406,6 +1512,7 @@
         = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignEnum>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.ForeignEnum) x, global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo), 594);
     private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignEnum> mapStringForeignEnum_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::ProtobufTestMessages.Proto3.ForeignEnum> MapStringForeignEnum {
       get { return mapStringForeignEnum_; }
     }
@@ -1413,6 +1520,7 @@
     /// <summary>Field number for the "oneof_uint32" field.</summary>
     public const int OneofUint32FieldNumber = 111;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OneofUint32 {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; }
       set {
@@ -1424,6 +1532,7 @@
     /// <summary>Field number for the "oneof_nested_message" field.</summary>
     public const int OneofNestedMessageFieldNumber = 112;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OneofNestedMessage {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage) oneofField_ : null; }
       set {
@@ -1435,6 +1544,7 @@
     /// <summary>Field number for the "oneof_string" field.</summary>
     public const int OneofStringFieldNumber = 113;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OneofString {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; }
       set {
@@ -1446,6 +1556,7 @@
     /// <summary>Field number for the "oneof_bytes" field.</summary>
     public const int OneofBytesFieldNumber = 114;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OneofBytes {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
       set {
@@ -1457,6 +1568,7 @@
     /// <summary>Field number for the "oneof_bool" field.</summary>
     public const int OneofBoolFieldNumber = 115;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool OneofBool {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBool ? (bool) oneofField_ : false; }
       set {
@@ -1468,6 +1580,7 @@
     /// <summary>Field number for the "oneof_uint64" field.</summary>
     public const int OneofUint64FieldNumber = 116;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OneofUint64 {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint64 ? (ulong) oneofField_ : 0UL; }
       set {
@@ -1479,6 +1592,7 @@
     /// <summary>Field number for the "oneof_float" field.</summary>
     public const int OneofFloatFieldNumber = 117;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float OneofFloat {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofFloat ? (float) oneofField_ : 0F; }
       set {
@@ -1490,6 +1604,7 @@
     /// <summary>Field number for the "oneof_double" field.</summary>
     public const int OneofDoubleFieldNumber = 118;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double OneofDouble {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofDouble ? (double) oneofField_ : 0D; }
       set {
@@ -1501,6 +1616,7 @@
     /// <summary>Field number for the "oneof_enum" field.</summary>
     public const int OneofEnumFieldNumber = 119;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OneofEnum {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) oneofField_ : global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo; }
       set {
@@ -1509,6 +1625,18 @@
       }
     }
 
+    /// <summary>Field number for the "oneof_null_value" field.</summary>
+    public const int OneofNullValueFieldNumber = 120;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::Google.Protobuf.WellKnownTypes.NullValue OneofNullValue {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) oneofField_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue;
+      }
+    }
+
     /// <summary>Field number for the "optional_bool_wrapper" field.</summary>
     public const int OptionalBoolWrapperFieldNumber = 201;
     private static readonly pb::FieldCodec<bool?> _single_optionalBoolWrapper_codec = pb::FieldCodec.ForStructWrapper<bool>(1610);
@@ -1517,6 +1645,7 @@
     /// Well-known types
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool? OptionalBoolWrapper {
       get { return optionalBoolWrapper_; }
       set {
@@ -1530,6 +1659,7 @@
     private static readonly pb::FieldCodec<int?> _single_optionalInt32Wrapper_codec = pb::FieldCodec.ForStructWrapper<int>(1618);
     private int? optionalInt32Wrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int? OptionalInt32Wrapper {
       get { return optionalInt32Wrapper_; }
       set {
@@ -1543,6 +1673,7 @@
     private static readonly pb::FieldCodec<long?> _single_optionalInt64Wrapper_codec = pb::FieldCodec.ForStructWrapper<long>(1626);
     private long? optionalInt64Wrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? OptionalInt64Wrapper {
       get { return optionalInt64Wrapper_; }
       set {
@@ -1556,6 +1687,7 @@
     private static readonly pb::FieldCodec<uint?> _single_optionalUint32Wrapper_codec = pb::FieldCodec.ForStructWrapper<uint>(1634);
     private uint? optionalUint32Wrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint? OptionalUint32Wrapper {
       get { return optionalUint32Wrapper_; }
       set {
@@ -1569,6 +1701,7 @@
     private static readonly pb::FieldCodec<ulong?> _single_optionalUint64Wrapper_codec = pb::FieldCodec.ForStructWrapper<ulong>(1642);
     private ulong? optionalUint64Wrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong? OptionalUint64Wrapper {
       get { return optionalUint64Wrapper_; }
       set {
@@ -1582,6 +1715,7 @@
     private static readonly pb::FieldCodec<float?> _single_optionalFloatWrapper_codec = pb::FieldCodec.ForStructWrapper<float>(1650);
     private float? optionalFloatWrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float? OptionalFloatWrapper {
       get { return optionalFloatWrapper_; }
       set {
@@ -1595,6 +1729,7 @@
     private static readonly pb::FieldCodec<double?> _single_optionalDoubleWrapper_codec = pb::FieldCodec.ForStructWrapper<double>(1658);
     private double? optionalDoubleWrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? OptionalDoubleWrapper {
       get { return optionalDoubleWrapper_; }
       set {
@@ -1608,6 +1743,7 @@
     private static readonly pb::FieldCodec<string> _single_optionalStringWrapper_codec = pb::FieldCodec.ForClassWrapper<string>(1666);
     private string optionalStringWrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalStringWrapper {
       get { return optionalStringWrapper_; }
       set {
@@ -1621,6 +1757,7 @@
     private static readonly pb::FieldCodec<pb::ByteString> _single_optionalBytesWrapper_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1674);
     private pb::ByteString optionalBytesWrapper_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OptionalBytesWrapper {
       get { return optionalBytesWrapper_; }
       set {
@@ -1635,6 +1772,7 @@
         = pb::FieldCodec.ForStructWrapper<bool>(1690);
     private readonly pbc::RepeatedField<bool?> repeatedBoolWrapper_ = new pbc::RepeatedField<bool?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool?> RepeatedBoolWrapper {
       get { return repeatedBoolWrapper_; }
     }
@@ -1645,6 +1783,7 @@
         = pb::FieldCodec.ForStructWrapper<int>(1698);
     private readonly pbc::RepeatedField<int?> repeatedInt32Wrapper_ = new pbc::RepeatedField<int?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int?> RepeatedInt32Wrapper {
       get { return repeatedInt32Wrapper_; }
     }
@@ -1655,6 +1794,7 @@
         = pb::FieldCodec.ForStructWrapper<long>(1706);
     private readonly pbc::RepeatedField<long?> repeatedInt64Wrapper_ = new pbc::RepeatedField<long?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long?> RepeatedInt64Wrapper {
       get { return repeatedInt64Wrapper_; }
     }
@@ -1665,6 +1805,7 @@
         = pb::FieldCodec.ForStructWrapper<uint>(1714);
     private readonly pbc::RepeatedField<uint?> repeatedUint32Wrapper_ = new pbc::RepeatedField<uint?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint?> RepeatedUint32Wrapper {
       get { return repeatedUint32Wrapper_; }
     }
@@ -1675,6 +1816,7 @@
         = pb::FieldCodec.ForStructWrapper<ulong>(1722);
     private readonly pbc::RepeatedField<ulong?> repeatedUint64Wrapper_ = new pbc::RepeatedField<ulong?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong?> RepeatedUint64Wrapper {
       get { return repeatedUint64Wrapper_; }
     }
@@ -1685,6 +1827,7 @@
         = pb::FieldCodec.ForStructWrapper<float>(1730);
     private readonly pbc::RepeatedField<float?> repeatedFloatWrapper_ = new pbc::RepeatedField<float?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float?> RepeatedFloatWrapper {
       get { return repeatedFloatWrapper_; }
     }
@@ -1695,6 +1838,7 @@
         = pb::FieldCodec.ForStructWrapper<double>(1738);
     private readonly pbc::RepeatedField<double?> repeatedDoubleWrapper_ = new pbc::RepeatedField<double?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double?> RepeatedDoubleWrapper {
       get { return repeatedDoubleWrapper_; }
     }
@@ -1705,6 +1849,7 @@
         = pb::FieldCodec.ForClassWrapper<string>(1746);
     private readonly pbc::RepeatedField<string> repeatedStringWrapper_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedStringWrapper {
       get { return repeatedStringWrapper_; }
     }
@@ -1715,6 +1860,7 @@
         = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1754);
     private readonly pbc::RepeatedField<pb::ByteString> repeatedBytesWrapper_ = new pbc::RepeatedField<pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> RepeatedBytesWrapper {
       get { return repeatedBytesWrapper_; }
     }
@@ -1723,6 +1869,7 @@
     public const int OptionalDurationFieldNumber = 301;
     private global::Google.Protobuf.WellKnownTypes.Duration optionalDuration_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Duration OptionalDuration {
       get { return optionalDuration_; }
       set {
@@ -1734,6 +1881,7 @@
     public const int OptionalTimestampFieldNumber = 302;
     private global::Google.Protobuf.WellKnownTypes.Timestamp optionalTimestamp_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Timestamp OptionalTimestamp {
       get { return optionalTimestamp_; }
       set {
@@ -1745,6 +1893,7 @@
     public const int OptionalFieldMaskFieldNumber = 303;
     private global::Google.Protobuf.WellKnownTypes.FieldMask optionalFieldMask_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.FieldMask OptionalFieldMask {
       get { return optionalFieldMask_; }
       set {
@@ -1756,6 +1905,7 @@
     public const int OptionalStructFieldNumber = 304;
     private global::Google.Protobuf.WellKnownTypes.Struct optionalStruct_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Struct OptionalStruct {
       get { return optionalStruct_; }
       set {
@@ -1767,6 +1917,7 @@
     public const int OptionalAnyFieldNumber = 305;
     private global::Google.Protobuf.WellKnownTypes.Any optionalAny_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Any OptionalAny {
       get { return optionalAny_; }
       set {
@@ -1778,6 +1929,7 @@
     public const int OptionalValueFieldNumber = 306;
     private global::Google.Protobuf.WellKnownTypes.Value optionalValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Value OptionalValue {
       get { return optionalValue_; }
       set {
@@ -1785,12 +1937,25 @@
       }
     }
 
+    /// <summary>Field number for the "optional_null_value" field.</summary>
+    public const int OptionalNullValueFieldNumber = 307;
+    private global::Google.Protobuf.WellKnownTypes.NullValue optionalNullValue_ = global::Google.Protobuf.WellKnownTypes.NullValue.NullValue;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::Google.Protobuf.WellKnownTypes.NullValue OptionalNullValue {
+      get { return optionalNullValue_; }
+      set {
+        optionalNullValue_ = value;
+      }
+    }
+
     /// <summary>Field number for the "repeated_duration" field.</summary>
     public const int RepeatedDurationFieldNumber = 311;
     private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Duration> _repeated_repeatedDuration_codec
         = pb::FieldCodec.ForMessage(2490, global::Google.Protobuf.WellKnownTypes.Duration.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> repeatedDuration_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> RepeatedDuration {
       get { return repeatedDuration_; }
     }
@@ -1801,6 +1966,7 @@
         = pb::FieldCodec.ForMessage(2498, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> repeatedTimestamp_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> RepeatedTimestamp {
       get { return repeatedTimestamp_; }
     }
@@ -1811,6 +1977,7 @@
         = pb::FieldCodec.ForMessage(2506, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> repeatedFieldmask_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> RepeatedFieldmask {
       get { return repeatedFieldmask_; }
     }
@@ -1821,6 +1988,7 @@
         = pb::FieldCodec.ForMessage(2594, global::Google.Protobuf.WellKnownTypes.Struct.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> repeatedStruct_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> RepeatedStruct {
       get { return repeatedStruct_; }
     }
@@ -1831,6 +1999,7 @@
         = pb::FieldCodec.ForMessage(2522, global::Google.Protobuf.WellKnownTypes.Any.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> repeatedAny_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> RepeatedAny {
       get { return repeatedAny_; }
     }
@@ -1841,6 +2010,7 @@
         = pb::FieldCodec.ForMessage(2530, global::Google.Protobuf.WellKnownTypes.Value.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> repeatedValue_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> RepeatedValue {
       get { return repeatedValue_; }
     }
@@ -1851,6 +2021,7 @@
         = pb::FieldCodec.ForMessage(2538, global::Google.Protobuf.WellKnownTypes.ListValue.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.ListValue> repeatedListValue_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.ListValue>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.ListValue> RepeatedListValue {
       get { return repeatedListValue_; }
     }
@@ -1863,6 +2034,7 @@
     /// (protobuf says names can be any valid C/C++ identifier.)
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Fieldname1 {
       get { return fieldname1_; }
       set {
@@ -1874,6 +2046,7 @@
     public const int FieldName2FieldNumber = 402;
     private int fieldName2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName2 {
       get { return fieldName2_; }
       set {
@@ -1885,6 +2058,7 @@
     public const int FieldName3FieldNumber = 403;
     private int FieldName3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName3 {
       get { return FieldName3_; }
       set {
@@ -1896,6 +2070,7 @@
     public const int FieldName4FieldNumber = 404;
     private int fieldName4_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName4 {
       get { return fieldName4_; }
       set {
@@ -1907,6 +2082,7 @@
     public const int Field0Name5FieldNumber = 405;
     private int field0Name5_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field0Name5 {
       get { return field0Name5_; }
       set {
@@ -1918,6 +2094,7 @@
     public const int Field0Name6FieldNumber = 406;
     private int field0Name6_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field0Name6 {
       get { return field0Name6_; }
       set {
@@ -1929,6 +2106,7 @@
     public const int FieldName7FieldNumber = 407;
     private int fieldName7_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName7 {
       get { return fieldName7_; }
       set {
@@ -1940,6 +2118,7 @@
     public const int FieldName8FieldNumber = 408;
     private int fieldName8_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName8 {
       get { return fieldName8_; }
       set {
@@ -1951,6 +2130,7 @@
     public const int FieldName9FieldNumber = 409;
     private int fieldName9_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName9 {
       get { return fieldName9_; }
       set {
@@ -1962,6 +2142,7 @@
     public const int FieldName10FieldNumber = 410;
     private int fieldName10_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName10 {
       get { return fieldName10_; }
       set {
@@ -1973,6 +2154,7 @@
     public const int FIELDNAME11FieldNumber = 411;
     private int fIELDNAME11_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FIELDNAME11 {
       get { return fIELDNAME11_; }
       set {
@@ -1984,6 +2166,7 @@
     public const int FIELDName12FieldNumber = 412;
     private int fIELDName12_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FIELDName12 {
       get { return fIELDName12_; }
       set {
@@ -1995,6 +2178,7 @@
     public const int FieldName13FieldNumber = 413;
     private int FieldName13_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName13 {
       get { return FieldName13_; }
       set {
@@ -2006,6 +2190,7 @@
     public const int FieldName14FieldNumber = 414;
     private int FieldName14_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName14 {
       get { return FieldName14_; }
       set {
@@ -2017,6 +2202,7 @@
     public const int FieldName15FieldNumber = 415;
     private int fieldName15_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName15 {
       get { return fieldName15_; }
       set {
@@ -2028,6 +2214,7 @@
     public const int FieldName16FieldNumber = 416;
     private int fieldName16_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName16 {
       get { return fieldName16_; }
       set {
@@ -2039,6 +2226,7 @@
     public const int FieldName17FieldNumber = 417;
     private int fieldName17_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName17 {
       get { return fieldName17_; }
       set {
@@ -2050,6 +2238,7 @@
     public const int FieldName18FieldNumber = 418;
     private int fieldName18_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName18 {
       get { return fieldName18_; }
       set {
@@ -2070,25 +2259,30 @@
       OneofFloat = 117,
       OneofDouble = 118,
       OneofEnum = 119,
+      OneofNullValue = 120,
     }
     private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofFieldOneofCase OneofFieldCase {
       get { return oneofFieldCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofField() {
       oneofFieldCase_ = OneofFieldOneofCase.None;
       oneofField_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestAllTypesProto3);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestAllTypesProto3 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2196,6 +2390,7 @@
       if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OneofFloat, other.OneofFloat)) return false;
       if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OneofDouble, other.OneofDouble)) return false;
       if (OneofEnum != other.OneofEnum) return false;
+      if (OneofNullValue != other.OneofNullValue) return false;
       if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false;
       if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false;
       if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false;
@@ -2220,6 +2415,7 @@
       if (!object.Equals(OptionalStruct, other.OptionalStruct)) return false;
       if (!object.Equals(OptionalAny, other.OptionalAny)) return false;
       if (!object.Equals(OptionalValue, other.OptionalValue)) return false;
+      if (OptionalNullValue != other.OptionalNullValue) return false;
       if(!repeatedDuration_.Equals(other.repeatedDuration_)) return false;
       if(!repeatedTimestamp_.Equals(other.repeatedTimestamp_)) return false;
       if(!repeatedFieldmask_.Equals(other.repeatedFieldmask_)) return false;
@@ -2250,6 +2446,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode();
@@ -2352,6 +2549,7 @@
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OneofFloat);
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OneofDouble);
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) hash ^= OneofEnum.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) hash ^= OneofNullValue.GetHashCode();
       if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode();
       if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode();
       if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode();
@@ -2376,6 +2574,7 @@
       if (optionalStruct_ != null) hash ^= OptionalStruct.GetHashCode();
       if (optionalAny_ != null) hash ^= OptionalAny.GetHashCode();
       if (optionalValue_ != null) hash ^= OptionalValue.GetHashCode();
+      if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) hash ^= OptionalNullValue.GetHashCode();
       hash ^= repeatedDuration_.GetHashCode();
       hash ^= repeatedTimestamp_.GetHashCode();
       hash ^= repeatedFieldmask_.GetHashCode();
@@ -2409,12 +2608,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (OptionalInt32 != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(OptionalInt32);
@@ -2611,6 +2815,10 @@
         output.WriteRawTag(184, 7);
         output.WriteEnum((int) OneofEnum);
       }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) {
+        output.WriteRawTag(192, 7);
+        output.WriteEnum((int) OneofNullValue);
+      }
       if (optionalBoolWrapper_ != null) {
         _single_optionalBoolWrapper_codec.WriteTagAndValue(output, OptionalBoolWrapper);
       }
@@ -2671,6 +2879,10 @@
         output.WriteRawTag(146, 19);
         output.WriteMessage(OptionalValue);
       }
+      if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        output.WriteRawTag(152, 19);
+        output.WriteEnum((int) OptionalNullValue);
+      }
       repeatedDuration_.WriteTo(output, _repeated_repeatedDuration_codec);
       repeatedTimestamp_.WriteTo(output, _repeated_repeatedTimestamp_codec);
       repeatedFieldmask_.WriteTo(output, _repeated_repeatedFieldmask_codec);
@@ -2753,9 +2965,364 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (OptionalInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (OptionalInt64 != 0L) {
+        output.WriteRawTag(16);
+        output.WriteInt64(OptionalInt64);
+      }
+      if (OptionalUint32 != 0) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(OptionalUint32);
+      }
+      if (OptionalUint64 != 0UL) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(OptionalUint64);
+      }
+      if (OptionalSint32 != 0) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(OptionalSint32);
+      }
+      if (OptionalSint64 != 0L) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(OptionalSint64);
+      }
+      if (OptionalFixed32 != 0) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(OptionalFixed32);
+      }
+      if (OptionalFixed64 != 0UL) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(OptionalFixed64);
+      }
+      if (OptionalSfixed32 != 0) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(OptionalSfixed32);
+      }
+      if (OptionalSfixed64 != 0L) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(OptionalSfixed64);
+      }
+      if (OptionalFloat != 0F) {
+        output.WriteRawTag(93);
+        output.WriteFloat(OptionalFloat);
+      }
+      if (OptionalDouble != 0D) {
+        output.WriteRawTag(97);
+        output.WriteDouble(OptionalDouble);
+      }
+      if (OptionalBool != false) {
+        output.WriteRawTag(104);
+        output.WriteBool(OptionalBool);
+      }
+      if (OptionalString.Length != 0) {
+        output.WriteRawTag(114);
+        output.WriteString(OptionalString);
+      }
+      if (OptionalBytes.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (optionalForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(OptionalForeignMessage);
+      }
+      if (OptionalNestedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) OptionalNestedEnum);
+      }
+      if (OptionalForeignEnum != global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) OptionalForeignEnum);
+      }
+      if (OptionalAliasedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo) {
+        output.WriteRawTag(184, 1);
+        output.WriteEnum((int) OptionalAliasedEnum);
+      }
+      if (OptionalStringPiece.Length != 0) {
+        output.WriteRawTag(194, 1);
+        output.WriteString(OptionalStringPiece);
+      }
+      if (OptionalCord.Length != 0) {
+        output.WriteRawTag(202, 1);
+        output.WriteString(OptionalCord);
+      }
+      if (recursiveMessage_ != null) {
+        output.WriteRawTag(218, 1);
+        output.WriteMessage(RecursiveMessage);
+      }
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec);
+      repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec);
+      repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec);
+      repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec);
+      repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec);
+      mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec);
+      mapStringString_.WriteTo(ref output, _map_mapStringString_codec);
+      mapStringBytes_.WriteTo(ref output, _map_mapStringBytes_codec);
+      mapStringNestedMessage_.WriteTo(ref output, _map_mapStringNestedMessage_codec);
+      mapStringForeignMessage_.WriteTo(ref output, _map_mapStringForeignMessage_codec);
+      mapStringNestedEnum_.WriteTo(ref output, _map_mapStringNestedEnum_codec);
+      mapStringForeignEnum_.WriteTo(ref output, _map_mapStringForeignEnum_codec);
+      packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec);
+      packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec);
+      packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec);
+      packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec);
+      packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec);
+      packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec);
+      packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec);
+      packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec);
+      packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec);
+      packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec);
+      packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec);
+      packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec);
+      packedBool_.WriteTo(ref output, _repeated_packedBool_codec);
+      packedNestedEnum_.WriteTo(ref output, _repeated_packedNestedEnum_codec);
+      unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec);
+      unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec);
+      unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec);
+      unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec);
+      unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec);
+      unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec);
+      unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec);
+      unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec);
+      unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec);
+      unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec);
+      unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec);
+      unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec);
+      unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec);
+      unpackedNestedEnum_.WriteTo(ref output, _repeated_unpackedNestedEnum_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) {
+        output.WriteRawTag(152, 7);
+        output.WriteBool(OneofBool);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) {
+        output.WriteRawTag(160, 7);
+        output.WriteUInt64(OneofUint64);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) {
+        output.WriteRawTag(173, 7);
+        output.WriteFloat(OneofFloat);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) {
+        output.WriteRawTag(177, 7);
+        output.WriteDouble(OneofDouble);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) {
+        output.WriteRawTag(184, 7);
+        output.WriteEnum((int) OneofEnum);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) {
+        output.WriteRawTag(192, 7);
+        output.WriteEnum((int) OneofNullValue);
+      }
+      if (optionalBoolWrapper_ != null) {
+        _single_optionalBoolWrapper_codec.WriteTagAndValue(ref output, OptionalBoolWrapper);
+      }
+      if (optionalInt32Wrapper_ != null) {
+        _single_optionalInt32Wrapper_codec.WriteTagAndValue(ref output, OptionalInt32Wrapper);
+      }
+      if (optionalInt64Wrapper_ != null) {
+        _single_optionalInt64Wrapper_codec.WriteTagAndValue(ref output, OptionalInt64Wrapper);
+      }
+      if (optionalUint32Wrapper_ != null) {
+        _single_optionalUint32Wrapper_codec.WriteTagAndValue(ref output, OptionalUint32Wrapper);
+      }
+      if (optionalUint64Wrapper_ != null) {
+        _single_optionalUint64Wrapper_codec.WriteTagAndValue(ref output, OptionalUint64Wrapper);
+      }
+      if (optionalFloatWrapper_ != null) {
+        _single_optionalFloatWrapper_codec.WriteTagAndValue(ref output, OptionalFloatWrapper);
+      }
+      if (optionalDoubleWrapper_ != null) {
+        _single_optionalDoubleWrapper_codec.WriteTagAndValue(ref output, OptionalDoubleWrapper);
+      }
+      if (optionalStringWrapper_ != null) {
+        _single_optionalStringWrapper_codec.WriteTagAndValue(ref output, OptionalStringWrapper);
+      }
+      if (optionalBytesWrapper_ != null) {
+        _single_optionalBytesWrapper_codec.WriteTagAndValue(ref output, OptionalBytesWrapper);
+      }
+      repeatedBoolWrapper_.WriteTo(ref output, _repeated_repeatedBoolWrapper_codec);
+      repeatedInt32Wrapper_.WriteTo(ref output, _repeated_repeatedInt32Wrapper_codec);
+      repeatedInt64Wrapper_.WriteTo(ref output, _repeated_repeatedInt64Wrapper_codec);
+      repeatedUint32Wrapper_.WriteTo(ref output, _repeated_repeatedUint32Wrapper_codec);
+      repeatedUint64Wrapper_.WriteTo(ref output, _repeated_repeatedUint64Wrapper_codec);
+      repeatedFloatWrapper_.WriteTo(ref output, _repeated_repeatedFloatWrapper_codec);
+      repeatedDoubleWrapper_.WriteTo(ref output, _repeated_repeatedDoubleWrapper_codec);
+      repeatedStringWrapper_.WriteTo(ref output, _repeated_repeatedStringWrapper_codec);
+      repeatedBytesWrapper_.WriteTo(ref output, _repeated_repeatedBytesWrapper_codec);
+      if (optionalDuration_ != null) {
+        output.WriteRawTag(234, 18);
+        output.WriteMessage(OptionalDuration);
+      }
+      if (optionalTimestamp_ != null) {
+        output.WriteRawTag(242, 18);
+        output.WriteMessage(OptionalTimestamp);
+      }
+      if (optionalFieldMask_ != null) {
+        output.WriteRawTag(250, 18);
+        output.WriteMessage(OptionalFieldMask);
+      }
+      if (optionalStruct_ != null) {
+        output.WriteRawTag(130, 19);
+        output.WriteMessage(OptionalStruct);
+      }
+      if (optionalAny_ != null) {
+        output.WriteRawTag(138, 19);
+        output.WriteMessage(OptionalAny);
+      }
+      if (optionalValue_ != null) {
+        output.WriteRawTag(146, 19);
+        output.WriteMessage(OptionalValue);
+      }
+      if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        output.WriteRawTag(152, 19);
+        output.WriteEnum((int) OptionalNullValue);
+      }
+      repeatedDuration_.WriteTo(ref output, _repeated_repeatedDuration_codec);
+      repeatedTimestamp_.WriteTo(ref output, _repeated_repeatedTimestamp_codec);
+      repeatedFieldmask_.WriteTo(ref output, _repeated_repeatedFieldmask_codec);
+      repeatedAny_.WriteTo(ref output, _repeated_repeatedAny_codec);
+      repeatedValue_.WriteTo(ref output, _repeated_repeatedValue_codec);
+      repeatedListValue_.WriteTo(ref output, _repeated_repeatedListValue_codec);
+      repeatedStruct_.WriteTo(ref output, _repeated_repeatedStruct_codec);
+      if (Fieldname1 != 0) {
+        output.WriteRawTag(136, 25);
+        output.WriteInt32(Fieldname1);
+      }
+      if (FieldName2 != 0) {
+        output.WriteRawTag(144, 25);
+        output.WriteInt32(FieldName2);
+      }
+      if (FieldName3 != 0) {
+        output.WriteRawTag(152, 25);
+        output.WriteInt32(FieldName3);
+      }
+      if (FieldName4 != 0) {
+        output.WriteRawTag(160, 25);
+        output.WriteInt32(FieldName4);
+      }
+      if (Field0Name5 != 0) {
+        output.WriteRawTag(168, 25);
+        output.WriteInt32(Field0Name5);
+      }
+      if (Field0Name6 != 0) {
+        output.WriteRawTag(176, 25);
+        output.WriteInt32(Field0Name6);
+      }
+      if (FieldName7 != 0) {
+        output.WriteRawTag(184, 25);
+        output.WriteInt32(FieldName7);
+      }
+      if (FieldName8 != 0) {
+        output.WriteRawTag(192, 25);
+        output.WriteInt32(FieldName8);
+      }
+      if (FieldName9 != 0) {
+        output.WriteRawTag(200, 25);
+        output.WriteInt32(FieldName9);
+      }
+      if (FieldName10 != 0) {
+        output.WriteRawTag(208, 25);
+        output.WriteInt32(FieldName10);
+      }
+      if (FIELDNAME11 != 0) {
+        output.WriteRawTag(216, 25);
+        output.WriteInt32(FIELDNAME11);
+      }
+      if (FIELDName12 != 0) {
+        output.WriteRawTag(224, 25);
+        output.WriteInt32(FIELDName12);
+      }
+      if (FieldName13 != 0) {
+        output.WriteRawTag(232, 25);
+        output.WriteInt32(FieldName13);
+      }
+      if (FieldName14 != 0) {
+        output.WriteRawTag(240, 25);
+        output.WriteInt32(FieldName14);
+      }
+      if (FieldName15 != 0) {
+        output.WriteRawTag(248, 25);
+        output.WriteInt32(FieldName15);
+      }
+      if (FieldName16 != 0) {
+        output.WriteRawTag(128, 26);
+        output.WriteInt32(FieldName16);
+      }
+      if (FieldName17 != 0) {
+        output.WriteRawTag(136, 26);
+        output.WriteInt32(FieldName17);
+      }
+      if (FieldName18 != 0) {
+        output.WriteRawTag(144, 26);
+        output.WriteInt32(FieldName18);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (OptionalInt32 != 0) {
@@ -2922,6 +3489,9 @@
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) {
         size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofEnum);
       }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofNullValue);
+      }
       if (optionalBoolWrapper_ != null) {
         size += _single_optionalBoolWrapper_codec.CalculateSizeWithTag(OptionalBoolWrapper);
       }
@@ -2976,6 +3546,9 @@
       if (optionalValue_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalValue);
       }
+      if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNullValue);
+      }
       size += repeatedDuration_.CalculateSize(_repeated_repeatedDuration_codec);
       size += repeatedTimestamp_.CalculateSize(_repeated_repeatedTimestamp_codec);
       size += repeatedFieldmask_.CalculateSize(_repeated_repeatedFieldmask_codec);
@@ -3044,6 +3617,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestAllTypesProto3 other) {
       if (other == null) {
         return;
@@ -3284,6 +3858,9 @@
         }
         OptionalValue.MergeFrom(other.OptionalValue);
       }
+      if (other.OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        OptionalNullValue = other.OptionalNullValue;
+      }
       repeatedDuration_.Add(other.repeatedDuration_);
       repeatedTimestamp_.Add(other.repeatedTimestamp_);
       repeatedFieldmask_.Add(other.repeatedFieldmask_);
@@ -3376,13 +3953,20 @@
         case OneofFieldOneofCase.OneofEnum:
           OneofEnum = other.OneofEnum;
           break;
+        case OneofFieldOneofCase.OneofNullValue:
+          OneofNullValue = other.OneofNullValue;
+          break;
       }
 
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3847,6 +4431,11 @@
             oneofFieldCase_ = OneofFieldOneofCase.OneofEnum;
             break;
           }
+          case 960: {
+            oneofField_ = input.ReadEnum();
+            oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue;
+            break;
+          }
           case 1610: {
             bool? value = _single_optionalBoolWrapper_codec.Read(input);
             if (optionalBoolWrapper_ == null || value != false) {
@@ -3988,6 +4577,10 @@
             input.ReadMessage(OptionalValue);
             break;
           }
+          case 2456: {
+            OptionalNullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum();
+            break;
+          }
           case 2490: {
             repeatedDuration_.AddEntriesFrom(input, _repeated_repeatedDuration_codec);
             break;
@@ -4090,11 +4683,736 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            OptionalInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            OptionalUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            OptionalUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            OptionalSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            OptionalSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            OptionalFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            OptionalFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            OptionalSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            OptionalSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            OptionalFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            OptionalDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 122: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 146: {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+          case 154: {
+            if (optionalForeignMessage_ == null) {
+              OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage();
+            }
+            input.ReadMessage(OptionalForeignMessage);
+            break;
+          }
+          case 168: {
+            OptionalNestedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            OptionalForeignEnum = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 184: {
+            OptionalAliasedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) input.ReadEnum();
+            break;
+          }
+          case 194: {
+            OptionalStringPiece = input.ReadString();
+            break;
+          }
+          case 202: {
+            OptionalCord = input.ReadString();
+            break;
+          }
+          case 218: {
+            if (recursiveMessage_ == null) {
+              RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
+            }
+            input.ReadMessage(RecursiveMessage);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec);
+            break;
+          }
+          case 442: {
+            repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec);
+            break;
+          }
+          case 450: {
+            mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 458: {
+            mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 466: {
+            mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 474: {
+            mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 482: {
+            mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 490: {
+            mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 498: {
+            mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 506: {
+            mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 514: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 522: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 530: {
+            mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 538: {
+            mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 546: {
+            mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 554: {
+            mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec);
+            break;
+          }
+          case 562: {
+            mapStringBytes_.AddEntriesFrom(ref input, _map_mapStringBytes_codec);
+            break;
+          }
+          case 570: {
+            mapStringNestedMessage_.AddEntriesFrom(ref input, _map_mapStringNestedMessage_codec);
+            break;
+          }
+          case 578: {
+            mapStringForeignMessage_.AddEntriesFrom(ref input, _map_mapStringForeignMessage_codec);
+            break;
+          }
+          case 586: {
+            mapStringNestedEnum_.AddEntriesFrom(ref input, _map_mapStringNestedEnum_codec);
+            break;
+          }
+          case 594: {
+            mapStringForeignEnum_.AddEntriesFrom(ref input, _map_mapStringForeignEnum_codec);
+            break;
+          }
+          case 602:
+          case 600: {
+            packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec);
+            break;
+          }
+          case 610:
+          case 608: {
+            packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec);
+            break;
+          }
+          case 618:
+          case 616: {
+            packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec);
+            break;
+          }
+          case 626:
+          case 624: {
+            packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec);
+            break;
+          }
+          case 634:
+          case 632: {
+            packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec);
+            break;
+          }
+          case 642:
+          case 640: {
+            packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec);
+            break;
+          }
+          case 650:
+          case 653: {
+            packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec);
+            break;
+          }
+          case 658:
+          case 657: {
+            packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec);
+            break;
+          }
+          case 666:
+          case 669: {
+            packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec);
+            break;
+          }
+          case 674:
+          case 673: {
+            packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec);
+            break;
+          }
+          case 682:
+          case 685: {
+            packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec);
+            break;
+          }
+          case 690:
+          case 689: {
+            packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec);
+            break;
+          }
+          case 698:
+          case 696: {
+            packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec);
+            break;
+          }
+          case 706:
+          case 704: {
+            packedNestedEnum_.AddEntriesFrom(ref input, _repeated_packedNestedEnum_codec);
+            break;
+          }
+          case 714:
+          case 712: {
+            unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec);
+            break;
+          }
+          case 722:
+          case 720: {
+            unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec);
+            break;
+          }
+          case 762:
+          case 765: {
+            unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec);
+            break;
+          }
+          case 770:
+          case 769: {
+            unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec);
+            break;
+          }
+          case 778:
+          case 781: {
+            unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec);
+            break;
+          }
+          case 786:
+          case 785: {
+            unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec);
+            break;
+          }
+          case 794:
+          case 797: {
+            unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec);
+            break;
+          }
+          case 802:
+          case 801: {
+            unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec);
+            break;
+          }
+          case 810:
+          case 808: {
+            unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            unpackedNestedEnum_.AddEntriesFrom(ref input, _repeated_unpackedNestedEnum_codec);
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+          case 920: {
+            OneofBool = input.ReadBool();
+            break;
+          }
+          case 928: {
+            OneofUint64 = input.ReadUInt64();
+            break;
+          }
+          case 941: {
+            OneofFloat = input.ReadFloat();
+            break;
+          }
+          case 945: {
+            OneofDouble = input.ReadDouble();
+            break;
+          }
+          case 952: {
+            oneofField_ = input.ReadEnum();
+            oneofFieldCase_ = OneofFieldOneofCase.OneofEnum;
+            break;
+          }
+          case 960: {
+            oneofField_ = input.ReadEnum();
+            oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue;
+            break;
+          }
+          case 1610: {
+            bool? value = _single_optionalBoolWrapper_codec.Read(ref input);
+            if (optionalBoolWrapper_ == null || value != false) {
+              OptionalBoolWrapper = value;
+            }
+            break;
+          }
+          case 1618: {
+            int? value = _single_optionalInt32Wrapper_codec.Read(ref input);
+            if (optionalInt32Wrapper_ == null || value != 0) {
+              OptionalInt32Wrapper = value;
+            }
+            break;
+          }
+          case 1626: {
+            long? value = _single_optionalInt64Wrapper_codec.Read(ref input);
+            if (optionalInt64Wrapper_ == null || value != 0L) {
+              OptionalInt64Wrapper = value;
+            }
+            break;
+          }
+          case 1634: {
+            uint? value = _single_optionalUint32Wrapper_codec.Read(ref input);
+            if (optionalUint32Wrapper_ == null || value != 0) {
+              OptionalUint32Wrapper = value;
+            }
+            break;
+          }
+          case 1642: {
+            ulong? value = _single_optionalUint64Wrapper_codec.Read(ref input);
+            if (optionalUint64Wrapper_ == null || value != 0UL) {
+              OptionalUint64Wrapper = value;
+            }
+            break;
+          }
+          case 1650: {
+            float? value = _single_optionalFloatWrapper_codec.Read(ref input);
+            if (optionalFloatWrapper_ == null || value != 0F) {
+              OptionalFloatWrapper = value;
+            }
+            break;
+          }
+          case 1658: {
+            double? value = _single_optionalDoubleWrapper_codec.Read(ref input);
+            if (optionalDoubleWrapper_ == null || value != 0D) {
+              OptionalDoubleWrapper = value;
+            }
+            break;
+          }
+          case 1666: {
+            string value = _single_optionalStringWrapper_codec.Read(ref input);
+            if (optionalStringWrapper_ == null || value != "") {
+              OptionalStringWrapper = value;
+            }
+            break;
+          }
+          case 1674: {
+            pb::ByteString value = _single_optionalBytesWrapper_codec.Read(ref input);
+            if (optionalBytesWrapper_ == null || value != pb::ByteString.Empty) {
+              OptionalBytesWrapper = value;
+            }
+            break;
+          }
+          case 1690: {
+            repeatedBoolWrapper_.AddEntriesFrom(ref input, _repeated_repeatedBoolWrapper_codec);
+            break;
+          }
+          case 1698: {
+            repeatedInt32Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedInt32Wrapper_codec);
+            break;
+          }
+          case 1706: {
+            repeatedInt64Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedInt64Wrapper_codec);
+            break;
+          }
+          case 1714: {
+            repeatedUint32Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedUint32Wrapper_codec);
+            break;
+          }
+          case 1722: {
+            repeatedUint64Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedUint64Wrapper_codec);
+            break;
+          }
+          case 1730: {
+            repeatedFloatWrapper_.AddEntriesFrom(ref input, _repeated_repeatedFloatWrapper_codec);
+            break;
+          }
+          case 1738: {
+            repeatedDoubleWrapper_.AddEntriesFrom(ref input, _repeated_repeatedDoubleWrapper_codec);
+            break;
+          }
+          case 1746: {
+            repeatedStringWrapper_.AddEntriesFrom(ref input, _repeated_repeatedStringWrapper_codec);
+            break;
+          }
+          case 1754: {
+            repeatedBytesWrapper_.AddEntriesFrom(ref input, _repeated_repeatedBytesWrapper_codec);
+            break;
+          }
+          case 2410: {
+            if (optionalDuration_ == null) {
+              OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration();
+            }
+            input.ReadMessage(OptionalDuration);
+            break;
+          }
+          case 2418: {
+            if (optionalTimestamp_ == null) {
+              OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            }
+            input.ReadMessage(OptionalTimestamp);
+            break;
+          }
+          case 2426: {
+            if (optionalFieldMask_ == null) {
+              OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            }
+            input.ReadMessage(OptionalFieldMask);
+            break;
+          }
+          case 2434: {
+            if (optionalStruct_ == null) {
+              OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct();
+            }
+            input.ReadMessage(OptionalStruct);
+            break;
+          }
+          case 2442: {
+            if (optionalAny_ == null) {
+              OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any();
+            }
+            input.ReadMessage(OptionalAny);
+            break;
+          }
+          case 2450: {
+            if (optionalValue_ == null) {
+              OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value();
+            }
+            input.ReadMessage(OptionalValue);
+            break;
+          }
+          case 2456: {
+            OptionalNullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum();
+            break;
+          }
+          case 2490: {
+            repeatedDuration_.AddEntriesFrom(ref input, _repeated_repeatedDuration_codec);
+            break;
+          }
+          case 2498: {
+            repeatedTimestamp_.AddEntriesFrom(ref input, _repeated_repeatedTimestamp_codec);
+            break;
+          }
+          case 2506: {
+            repeatedFieldmask_.AddEntriesFrom(ref input, _repeated_repeatedFieldmask_codec);
+            break;
+          }
+          case 2522: {
+            repeatedAny_.AddEntriesFrom(ref input, _repeated_repeatedAny_codec);
+            break;
+          }
+          case 2530: {
+            repeatedValue_.AddEntriesFrom(ref input, _repeated_repeatedValue_codec);
+            break;
+          }
+          case 2538: {
+            repeatedListValue_.AddEntriesFrom(ref input, _repeated_repeatedListValue_codec);
+            break;
+          }
+          case 2594: {
+            repeatedStruct_.AddEntriesFrom(ref input, _repeated_repeatedStruct_codec);
+            break;
+          }
+          case 3208: {
+            Fieldname1 = input.ReadInt32();
+            break;
+          }
+          case 3216: {
+            FieldName2 = input.ReadInt32();
+            break;
+          }
+          case 3224: {
+            FieldName3 = input.ReadInt32();
+            break;
+          }
+          case 3232: {
+            FieldName4 = input.ReadInt32();
+            break;
+          }
+          case 3240: {
+            Field0Name5 = input.ReadInt32();
+            break;
+          }
+          case 3248: {
+            Field0Name6 = input.ReadInt32();
+            break;
+          }
+          case 3256: {
+            FieldName7 = input.ReadInt32();
+            break;
+          }
+          case 3264: {
+            FieldName8 = input.ReadInt32();
+            break;
+          }
+          case 3272: {
+            FieldName9 = input.ReadInt32();
+            break;
+          }
+          case 3280: {
+            FieldName10 = input.ReadInt32();
+            break;
+          }
+          case 3288: {
+            FIELDNAME11 = input.ReadInt32();
+            break;
+          }
+          case 3296: {
+            FIELDName12 = input.ReadInt32();
+            break;
+          }
+          case 3304: {
+            FieldName13 = input.ReadInt32();
+            break;
+          }
+          case 3312: {
+            FieldName14 = input.ReadInt32();
+            break;
+          }
+          case 3320: {
+            FieldName15 = input.ReadInt32();
+            break;
+          }
+          case 3328: {
+            FieldName16 = input.ReadInt32();
+            break;
+          }
+          case 3336: {
+            FieldName17 = input.ReadInt32();
+            break;
+          }
+          case 3344: {
+            FieldName18 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestAllTypesProto3 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum NestedEnum {
         [pbr::OriginalName("FOO")] Foo = 0,
@@ -4115,23 +5433,31 @@
         [pbr::OriginalName("bAz", PreferredAlias = false)] BAz = 2,
       }
 
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -4139,6 +5465,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           a_ = other.a_;
           corecursive_ = other.corecursive_ != null ? other.corecursive_.Clone() : null;
@@ -4146,6 +5473,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -4154,6 +5482,7 @@
         public const int AFieldNumber = 1;
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { return a_; }
           set {
@@ -4165,6 +5494,7 @@
         public const int CorecursiveFieldNumber = 2;
         private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 corecursive_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 Corecursive {
           get { return corecursive_; }
           set {
@@ -4173,11 +5503,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4191,6 +5523,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (A != 0) hash ^= A.GetHashCode();
@@ -4202,12 +5535,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (A != 0) {
             output.WriteRawTag(8);
             output.WriteInt32(A);
@@ -4219,9 +5557,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (A != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(A);
+          }
+          if (corecursive_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Corecursive);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (A != 0) {
@@ -4237,6 +5595,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -4254,7 +5613,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4274,8 +5637,35 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                A = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (corecursive_ == null) {
+                  Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
+                }
+                input.ReadMessage(Corecursive);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -4283,23 +5673,31 @@
 
   }
 
-  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
+  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage() {
       OnConstruction();
     }
@@ -4307,12 +5705,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage(ForeignMessage other) : this() {
       c_ = other.c_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage Clone() {
       return new ForeignMessage(this);
     }
@@ -4321,6 +5721,7 @@
     public const int CFieldNumber = 1;
     private int c_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int C {
       get { return c_; }
       set {
@@ -4329,11 +5730,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ForeignMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ForeignMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4346,6 +5749,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (C != 0) hash ^= C.GetHashCode();
@@ -4356,12 +5760,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (C != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(C);
@@ -4369,9 +5778,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (C != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (C != 0) {
@@ -4384,6 +5809,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ForeignMessage other) {
       if (other == null) {
         return;
@@ -4395,7 +5821,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4408,8 +5838,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
index a35b6e0..706b7c4 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
@@ -1120,25 +1120,33 @@
   /// This proto includes every type of field in both singular and repeated
   /// forms.
   /// </summary>
-  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> {
+  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     private int _hasBits1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypes() {
       OnConstruction();
     }
@@ -1146,6 +1154,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypes(TestAllTypes other) : this() {
       _hasBits0 = other._hasBits0;
       _hasBits1 = other._hasBits1;
@@ -1165,16 +1174,16 @@
       optionalString_ = other.optionalString_;
       optionalBytes_ = other.optionalBytes_;
       optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null;
-      optionalNestedMessage_ = other.HasOptionalNestedMessage ? other.optionalNestedMessage_.Clone() : null;
-      optionalForeignMessage_ = other.HasOptionalForeignMessage ? other.optionalForeignMessage_.Clone() : null;
-      optionalImportMessage_ = other.HasOptionalImportMessage ? other.optionalImportMessage_.Clone() : null;
+      optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
+      optionalForeignMessage_ = other.optionalForeignMessage_ != null ? other.optionalForeignMessage_.Clone() : null;
+      optionalImportMessage_ = other.optionalImportMessage_ != null ? other.optionalImportMessage_.Clone() : null;
       optionalNestedEnum_ = other.optionalNestedEnum_;
       optionalForeignEnum_ = other.optionalForeignEnum_;
       optionalImportEnum_ = other.optionalImportEnum_;
       optionalStringPiece_ = other.optionalStringPiece_;
       optionalCord_ = other.optionalCord_;
-      optionalPublicImportMessage_ = other.HasOptionalPublicImportMessage ? other.optionalPublicImportMessage_.Clone() : null;
-      optionalLazyMessage_ = other.HasOptionalLazyMessage ? other.optionalLazyMessage_.Clone() : null;
+      optionalPublicImportMessage_ = other.optionalPublicImportMessage_ != null ? other.optionalPublicImportMessage_.Clone() : null;
+      optionalLazyMessage_ = other.optionalLazyMessage_ != null ? other.optionalLazyMessage_.Clone() : null;
       repeatedInt32_ = other.repeatedInt32_.Clone();
       repeatedInt64_ = other.repeatedInt64_.Clone();
       repeatedUint32_ = other.repeatedUint32_.Clone();
@@ -1239,6 +1248,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypes Clone() {
       return new TestAllTypes(this);
     }
@@ -1252,6 +1262,7 @@
     /// Singular
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalInt32 {
       get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } }
       set {
@@ -1261,11 +1272,13 @@
     }
     /// <summary>Gets whether the "optional_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalInt32 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "optional_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalInt32() {
       _hasBits0 &= ~1;
     }
@@ -1276,6 +1289,7 @@
 
     private long optionalInt64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalInt64 {
       get { if ((_hasBits0 & 2) != 0) { return optionalInt64_; } else { return OptionalInt64DefaultValue; } }
       set {
@@ -1285,11 +1299,13 @@
     }
     /// <summary>Gets whether the "optional_int64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalInt64 {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "optional_int64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalInt64() {
       _hasBits0 &= ~2;
     }
@@ -1300,6 +1316,7 @@
 
     private uint optionalUint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OptionalUint32 {
       get { if ((_hasBits0 & 4) != 0) { return optionalUint32_; } else { return OptionalUint32DefaultValue; } }
       set {
@@ -1309,11 +1326,13 @@
     }
     /// <summary>Gets whether the "optional_uint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalUint32 {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "optional_uint32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalUint32() {
       _hasBits0 &= ~4;
     }
@@ -1324,6 +1343,7 @@
 
     private ulong optionalUint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OptionalUint64 {
       get { if ((_hasBits0 & 8) != 0) { return optionalUint64_; } else { return OptionalUint64DefaultValue; } }
       set {
@@ -1333,11 +1353,13 @@
     }
     /// <summary>Gets whether the "optional_uint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalUint64 {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "optional_uint64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalUint64() {
       _hasBits0 &= ~8;
     }
@@ -1348,6 +1370,7 @@
 
     private int optionalSint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalSint32 {
       get { if ((_hasBits0 & 16) != 0) { return optionalSint32_; } else { return OptionalSint32DefaultValue; } }
       set {
@@ -1357,11 +1380,13 @@
     }
     /// <summary>Gets whether the "optional_sint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSint32 {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "optional_sint32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSint32() {
       _hasBits0 &= ~16;
     }
@@ -1372,6 +1397,7 @@
 
     private long optionalSint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalSint64 {
       get { if ((_hasBits0 & 32) != 0) { return optionalSint64_; } else { return OptionalSint64DefaultValue; } }
       set {
@@ -1381,11 +1407,13 @@
     }
     /// <summary>Gets whether the "optional_sint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSint64 {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "optional_sint64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSint64() {
       _hasBits0 &= ~32;
     }
@@ -1396,6 +1424,7 @@
 
     private uint optionalFixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OptionalFixed32 {
       get { if ((_hasBits0 & 64) != 0) { return optionalFixed32_; } else { return OptionalFixed32DefaultValue; } }
       set {
@@ -1405,11 +1434,13 @@
     }
     /// <summary>Gets whether the "optional_fixed32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalFixed32 {
       get { return (_hasBits0 & 64) != 0; }
     }
     /// <summary>Clears the value of the "optional_fixed32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalFixed32() {
       _hasBits0 &= ~64;
     }
@@ -1420,6 +1451,7 @@
 
     private ulong optionalFixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong OptionalFixed64 {
       get { if ((_hasBits0 & 128) != 0) { return optionalFixed64_; } else { return OptionalFixed64DefaultValue; } }
       set {
@@ -1429,11 +1461,13 @@
     }
     /// <summary>Gets whether the "optional_fixed64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalFixed64 {
       get { return (_hasBits0 & 128) != 0; }
     }
     /// <summary>Clears the value of the "optional_fixed64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalFixed64() {
       _hasBits0 &= ~128;
     }
@@ -1444,6 +1478,7 @@
 
     private int optionalSfixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalSfixed32 {
       get { if ((_hasBits0 & 256) != 0) { return optionalSfixed32_; } else { return OptionalSfixed32DefaultValue; } }
       set {
@@ -1453,11 +1488,13 @@
     }
     /// <summary>Gets whether the "optional_sfixed32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSfixed32 {
       get { return (_hasBits0 & 256) != 0; }
     }
     /// <summary>Clears the value of the "optional_sfixed32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSfixed32() {
       _hasBits0 &= ~256;
     }
@@ -1468,6 +1505,7 @@
 
     private long optionalSfixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long OptionalSfixed64 {
       get { if ((_hasBits0 & 512) != 0) { return optionalSfixed64_; } else { return OptionalSfixed64DefaultValue; } }
       set {
@@ -1477,11 +1515,13 @@
     }
     /// <summary>Gets whether the "optional_sfixed64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalSfixed64 {
       get { return (_hasBits0 & 512) != 0; }
     }
     /// <summary>Clears the value of the "optional_sfixed64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalSfixed64() {
       _hasBits0 &= ~512;
     }
@@ -1492,6 +1532,7 @@
 
     private float optionalFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float OptionalFloat {
       get { if ((_hasBits0 & 1024) != 0) { return optionalFloat_; } else { return OptionalFloatDefaultValue; } }
       set {
@@ -1501,11 +1542,13 @@
     }
     /// <summary>Gets whether the "optional_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalFloat {
       get { return (_hasBits0 & 1024) != 0; }
     }
     /// <summary>Clears the value of the "optional_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalFloat() {
       _hasBits0 &= ~1024;
     }
@@ -1516,6 +1559,7 @@
 
     private double optionalDouble_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double OptionalDouble {
       get { if ((_hasBits0 & 2048) != 0) { return optionalDouble_; } else { return OptionalDoubleDefaultValue; } }
       set {
@@ -1525,11 +1569,13 @@
     }
     /// <summary>Gets whether the "optional_double" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalDouble {
       get { return (_hasBits0 & 2048) != 0; }
     }
     /// <summary>Clears the value of the "optional_double" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalDouble() {
       _hasBits0 &= ~2048;
     }
@@ -1540,6 +1586,7 @@
 
     private bool optionalBool_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool OptionalBool {
       get { if ((_hasBits0 & 4096) != 0) { return optionalBool_; } else { return OptionalBoolDefaultValue; } }
       set {
@@ -1549,11 +1596,13 @@
     }
     /// <summary>Gets whether the "optional_bool" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalBool {
       get { return (_hasBits0 & 4096) != 0; }
     }
     /// <summary>Clears the value of the "optional_bool" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalBool() {
       _hasBits0 &= ~4096;
     }
@@ -1564,6 +1613,7 @@
 
     private string optionalString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalString {
       get { return optionalString_ ?? OptionalStringDefaultValue; }
       set {
@@ -1572,11 +1622,13 @@
     }
     /// <summary>Gets whether the "optional_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalString {
       get { return optionalString_ != null; }
     }
     /// <summary>Clears the value of the "optional_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalString() {
       optionalString_ = null;
     }
@@ -1587,6 +1639,7 @@
 
     private pb::ByteString optionalBytes_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OptionalBytes {
       get { return optionalBytes_ ?? OptionalBytesDefaultValue; }
       set {
@@ -1595,11 +1648,13 @@
     }
     /// <summary>Gets whether the "optional_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalBytes {
       get { return optionalBytes_ != null; }
     }
     /// <summary>Clears the value of the "optional_bytes" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalBytes() {
       optionalBytes_ = null;
     }
@@ -1608,6 +1663,7 @@
     public const int OptionalGroupFieldNumber = 16;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup optionalGroup_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup OptionalGroup {
       get { return optionalGroup_; }
       set {
@@ -1616,11 +1672,13 @@
     }
     /// <summary>Gets whether the optionalgroup field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalGroup {
       get { return optionalGroup_ != null; }
     }
     /// <summary>Clears the value of the optionalgroup field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalGroup() {
       optionalGroup_ = null;
     }
@@ -1629,64 +1687,37 @@
     public const int OptionalNestedMessageFieldNumber = 18;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage optionalNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage OptionalNestedMessage {
       get { return optionalNestedMessage_; }
       set {
         optionalNestedMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_nested_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalNestedMessage {
-      get { return optionalNestedMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_nested_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalNestedMessage() {
-      optionalNestedMessage_ = null;
-    }
 
     /// <summary>Field number for the "optional_foreign_message" field.</summary>
     public const int OptionalForeignMessageFieldNumber = 19;
     private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage optionalForeignMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage OptionalForeignMessage {
       get { return optionalForeignMessage_; }
       set {
         optionalForeignMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_foreign_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalForeignMessage {
-      get { return optionalForeignMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_foreign_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalForeignMessage() {
-      optionalForeignMessage_ = null;
-    }
 
     /// <summary>Field number for the "optional_import_message" field.</summary>
     public const int OptionalImportMessageFieldNumber = 20;
     private global::Google.Protobuf.TestProtos.Proto2.ImportMessage optionalImportMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ImportMessage OptionalImportMessage {
       get { return optionalImportMessage_; }
       set {
         optionalImportMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_import_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalImportMessage {
-      get { return optionalImportMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_import_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalImportMessage() {
-      optionalImportMessage_ = null;
-    }
 
     /// <summary>Field number for the "optional_nested_enum" field.</summary>
     public const int OptionalNestedEnumFieldNumber = 21;
@@ -1694,6 +1725,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum optionalNestedEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum OptionalNestedEnum {
       get { if ((_hasBits0 & 8192) != 0) { return optionalNestedEnum_; } else { return OptionalNestedEnumDefaultValue; } }
       set {
@@ -1703,11 +1735,13 @@
     }
     /// <summary>Gets whether the "optional_nested_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalNestedEnum {
       get { return (_hasBits0 & 8192) != 0; }
     }
     /// <summary>Clears the value of the "optional_nested_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalNestedEnum() {
       _hasBits0 &= ~8192;
     }
@@ -1718,6 +1752,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum optionalForeignEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalForeignEnum {
       get { if ((_hasBits0 & 16384) != 0) { return optionalForeignEnum_; } else { return OptionalForeignEnumDefaultValue; } }
       set {
@@ -1727,11 +1762,13 @@
     }
     /// <summary>Gets whether the "optional_foreign_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalForeignEnum {
       get { return (_hasBits0 & 16384) != 0; }
     }
     /// <summary>Clears the value of the "optional_foreign_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalForeignEnum() {
       _hasBits0 &= ~16384;
     }
@@ -1742,6 +1779,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ImportEnum optionalImportEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ImportEnum OptionalImportEnum {
       get { if ((_hasBits0 & 32768) != 0) { return optionalImportEnum_; } else { return OptionalImportEnumDefaultValue; } }
       set {
@@ -1751,11 +1789,13 @@
     }
     /// <summary>Gets whether the "optional_import_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalImportEnum {
       get { return (_hasBits0 & 32768) != 0; }
     }
     /// <summary>Clears the value of the "optional_import_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalImportEnum() {
       _hasBits0 &= ~32768;
     }
@@ -1766,6 +1806,7 @@
 
     private string optionalStringPiece_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalStringPiece {
       get { return optionalStringPiece_ ?? OptionalStringPieceDefaultValue; }
       set {
@@ -1774,11 +1815,13 @@
     }
     /// <summary>Gets whether the "optional_string_piece" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalStringPiece {
       get { return optionalStringPiece_ != null; }
     }
     /// <summary>Clears the value of the "optional_string_piece" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalStringPiece() {
       optionalStringPiece_ = null;
     }
@@ -1789,6 +1832,7 @@
 
     private string optionalCord_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalCord {
       get { return optionalCord_ ?? OptionalCordDefaultValue; }
       set {
@@ -1797,11 +1841,13 @@
     }
     /// <summary>Gets whether the "optional_cord" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalCord {
       get { return optionalCord_ != null; }
     }
     /// <summary>Clears the value of the "optional_cord" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalCord() {
       optionalCord_ = null;
     }
@@ -1813,43 +1859,25 @@
     /// Defined in unittest_import_public.proto
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage OptionalPublicImportMessage {
       get { return optionalPublicImportMessage_; }
       set {
         optionalPublicImportMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_public_import_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalPublicImportMessage {
-      get { return optionalPublicImportMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_public_import_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalPublicImportMessage() {
-      optionalPublicImportMessage_ = null;
-    }
 
     /// <summary>Field number for the "optional_lazy_message" field.</summary>
     public const int OptionalLazyMessageFieldNumber = 27;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage optionalLazyMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage OptionalLazyMessage {
       get { return optionalLazyMessage_; }
       set {
         optionalLazyMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_lazy_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalLazyMessage {
-      get { return optionalLazyMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_lazy_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalLazyMessage() {
-      optionalLazyMessage_ = null;
-    }
 
     /// <summary>Field number for the "repeated_int32" field.</summary>
     public const int RepeatedInt32FieldNumber = 31;
@@ -1860,6 +1888,7 @@
     /// Repeated
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
@@ -1870,6 +1899,7 @@
         = pb::FieldCodec.ForInt64(256);
     private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedInt64 {
       get { return repeatedInt64_; }
     }
@@ -1880,6 +1910,7 @@
         = pb::FieldCodec.ForUInt32(264);
     private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedUint32 {
       get { return repeatedUint32_; }
     }
@@ -1890,6 +1921,7 @@
         = pb::FieldCodec.ForUInt64(272);
     private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedUint64 {
       get { return repeatedUint64_; }
     }
@@ -1900,6 +1932,7 @@
         = pb::FieldCodec.ForSInt32(280);
     private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSint32 {
       get { return repeatedSint32_; }
     }
@@ -1910,6 +1943,7 @@
         = pb::FieldCodec.ForSInt64(288);
     private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSint64 {
       get { return repeatedSint64_; }
     }
@@ -1920,6 +1954,7 @@
         = pb::FieldCodec.ForFixed32(301);
     private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedFixed32 {
       get { return repeatedFixed32_; }
     }
@@ -1930,6 +1965,7 @@
         = pb::FieldCodec.ForFixed64(305);
     private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedFixed64 {
       get { return repeatedFixed64_; }
     }
@@ -1940,6 +1976,7 @@
         = pb::FieldCodec.ForSFixed32(317);
     private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSfixed32 {
       get { return repeatedSfixed32_; }
     }
@@ -1950,6 +1987,7 @@
         = pb::FieldCodec.ForSFixed64(321);
     private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSfixed64 {
       get { return repeatedSfixed64_; }
     }
@@ -1960,6 +1998,7 @@
         = pb::FieldCodec.ForFloat(333);
     private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> RepeatedFloat {
       get { return repeatedFloat_; }
     }
@@ -1970,6 +2009,7 @@
         = pb::FieldCodec.ForDouble(337);
     private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> RepeatedDouble {
       get { return repeatedDouble_; }
     }
@@ -1980,6 +2020,7 @@
         = pb::FieldCodec.ForBool(344);
     private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> RepeatedBool {
       get { return repeatedBool_; }
     }
@@ -1990,6 +2031,7 @@
         = pb::FieldCodec.ForString(354);
     private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedString {
       get { return repeatedString_; }
     }
@@ -2000,6 +2042,7 @@
         = pb::FieldCodec.ForBytes(362);
     private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
       get { return repeatedBytes_; }
     }
@@ -2010,6 +2053,7 @@
         = pb::FieldCodec.ForGroup(371, 372, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.RepeatedGroup.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.RepeatedGroup> repeatedGroup_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.RepeatedGroup>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.RepeatedGroup> RepeatedGroup {
       get { return repeatedGroup_; }
     }
@@ -2020,6 +2064,7 @@
         = pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage {
       get { return repeatedNestedMessage_; }
     }
@@ -2030,6 +2075,7 @@
         = pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage> RepeatedForeignMessage {
       get { return repeatedForeignMessage_; }
     }
@@ -2040,6 +2086,7 @@
         = pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.Proto2.ImportMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ImportMessage> repeatedImportMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ImportMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ImportMessage> RepeatedImportMessage {
       get { return repeatedImportMessage_; }
     }
@@ -2050,6 +2097,7 @@
         = pb::FieldCodec.ForEnum(408, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
       get { return repeatedNestedEnum_; }
     }
@@ -2060,6 +2108,7 @@
         = pb::FieldCodec.ForEnum(416, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> RepeatedForeignEnum {
       get { return repeatedForeignEnum_; }
     }
@@ -2070,6 +2119,7 @@
         = pb::FieldCodec.ForEnum(424, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ImportEnum> repeatedImportEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ImportEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ImportEnum> RepeatedImportEnum {
       get { return repeatedImportEnum_; }
     }
@@ -2080,6 +2130,7 @@
         = pb::FieldCodec.ForString(434);
     private readonly pbc::RepeatedField<string> repeatedStringPiece_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedStringPiece {
       get { return repeatedStringPiece_; }
     }
@@ -2090,6 +2141,7 @@
         = pb::FieldCodec.ForString(442);
     private readonly pbc::RepeatedField<string> repeatedCord_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedCord {
       get { return repeatedCord_; }
     }
@@ -2100,6 +2152,7 @@
         = pb::FieldCodec.ForMessage(458, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage> repeatedLazyMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage> RepeatedLazyMessage {
       get { return repeatedLazyMessage_; }
     }
@@ -2113,6 +2166,7 @@
     /// Singular with defaults
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int DefaultInt32 {
       get { if ((_hasBits0 & 65536) != 0) { return defaultInt32_; } else { return DefaultInt32DefaultValue; } }
       set {
@@ -2122,11 +2176,13 @@
     }
     /// <summary>Gets whether the "default_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultInt32 {
       get { return (_hasBits0 & 65536) != 0; }
     }
     /// <summary>Clears the value of the "default_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultInt32() {
       _hasBits0 &= ~65536;
     }
@@ -2137,6 +2193,7 @@
 
     private long defaultInt64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long DefaultInt64 {
       get { if ((_hasBits0 & 131072) != 0) { return defaultInt64_; } else { return DefaultInt64DefaultValue; } }
       set {
@@ -2146,11 +2203,13 @@
     }
     /// <summary>Gets whether the "default_int64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultInt64 {
       get { return (_hasBits0 & 131072) != 0; }
     }
     /// <summary>Clears the value of the "default_int64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultInt64() {
       _hasBits0 &= ~131072;
     }
@@ -2161,6 +2220,7 @@
 
     private uint defaultUint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint DefaultUint32 {
       get { if ((_hasBits0 & 262144) != 0) { return defaultUint32_; } else { return DefaultUint32DefaultValue; } }
       set {
@@ -2170,11 +2230,13 @@
     }
     /// <summary>Gets whether the "default_uint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultUint32 {
       get { return (_hasBits0 & 262144) != 0; }
     }
     /// <summary>Clears the value of the "default_uint32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultUint32() {
       _hasBits0 &= ~262144;
     }
@@ -2185,6 +2247,7 @@
 
     private ulong defaultUint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong DefaultUint64 {
       get { if ((_hasBits0 & 524288) != 0) { return defaultUint64_; } else { return DefaultUint64DefaultValue; } }
       set {
@@ -2194,11 +2257,13 @@
     }
     /// <summary>Gets whether the "default_uint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultUint64 {
       get { return (_hasBits0 & 524288) != 0; }
     }
     /// <summary>Clears the value of the "default_uint64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultUint64() {
       _hasBits0 &= ~524288;
     }
@@ -2209,6 +2274,7 @@
 
     private int defaultSint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int DefaultSint32 {
       get { if ((_hasBits0 & 1048576) != 0) { return defaultSint32_; } else { return DefaultSint32DefaultValue; } }
       set {
@@ -2218,11 +2284,13 @@
     }
     /// <summary>Gets whether the "default_sint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultSint32 {
       get { return (_hasBits0 & 1048576) != 0; }
     }
     /// <summary>Clears the value of the "default_sint32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultSint32() {
       _hasBits0 &= ~1048576;
     }
@@ -2233,6 +2301,7 @@
 
     private long defaultSint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long DefaultSint64 {
       get { if ((_hasBits0 & 2097152) != 0) { return defaultSint64_; } else { return DefaultSint64DefaultValue; } }
       set {
@@ -2242,11 +2311,13 @@
     }
     /// <summary>Gets whether the "default_sint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultSint64 {
       get { return (_hasBits0 & 2097152) != 0; }
     }
     /// <summary>Clears the value of the "default_sint64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultSint64() {
       _hasBits0 &= ~2097152;
     }
@@ -2257,6 +2328,7 @@
 
     private uint defaultFixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint DefaultFixed32 {
       get { if ((_hasBits0 & 4194304) != 0) { return defaultFixed32_; } else { return DefaultFixed32DefaultValue; } }
       set {
@@ -2266,11 +2338,13 @@
     }
     /// <summary>Gets whether the "default_fixed32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultFixed32 {
       get { return (_hasBits0 & 4194304) != 0; }
     }
     /// <summary>Clears the value of the "default_fixed32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultFixed32() {
       _hasBits0 &= ~4194304;
     }
@@ -2281,6 +2355,7 @@
 
     private ulong defaultFixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong DefaultFixed64 {
       get { if ((_hasBits0 & 8388608) != 0) { return defaultFixed64_; } else { return DefaultFixed64DefaultValue; } }
       set {
@@ -2290,11 +2365,13 @@
     }
     /// <summary>Gets whether the "default_fixed64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultFixed64 {
       get { return (_hasBits0 & 8388608) != 0; }
     }
     /// <summary>Clears the value of the "default_fixed64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultFixed64() {
       _hasBits0 &= ~8388608;
     }
@@ -2305,6 +2382,7 @@
 
     private int defaultSfixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int DefaultSfixed32 {
       get { if ((_hasBits0 & 16777216) != 0) { return defaultSfixed32_; } else { return DefaultSfixed32DefaultValue; } }
       set {
@@ -2314,11 +2392,13 @@
     }
     /// <summary>Gets whether the "default_sfixed32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultSfixed32 {
       get { return (_hasBits0 & 16777216) != 0; }
     }
     /// <summary>Clears the value of the "default_sfixed32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultSfixed32() {
       _hasBits0 &= ~16777216;
     }
@@ -2329,6 +2409,7 @@
 
     private long defaultSfixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long DefaultSfixed64 {
       get { if ((_hasBits0 & 33554432) != 0) { return defaultSfixed64_; } else { return DefaultSfixed64DefaultValue; } }
       set {
@@ -2338,11 +2419,13 @@
     }
     /// <summary>Gets whether the "default_sfixed64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultSfixed64 {
       get { return (_hasBits0 & 33554432) != 0; }
     }
     /// <summary>Clears the value of the "default_sfixed64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultSfixed64() {
       _hasBits0 &= ~33554432;
     }
@@ -2353,6 +2436,7 @@
 
     private float defaultFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float DefaultFloat {
       get { if ((_hasBits0 & 67108864) != 0) { return defaultFloat_; } else { return DefaultFloatDefaultValue; } }
       set {
@@ -2362,11 +2446,13 @@
     }
     /// <summary>Gets whether the "default_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultFloat {
       get { return (_hasBits0 & 67108864) != 0; }
     }
     /// <summary>Clears the value of the "default_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultFloat() {
       _hasBits0 &= ~67108864;
     }
@@ -2377,6 +2463,7 @@
 
     private double defaultDouble_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DefaultDouble {
       get { if ((_hasBits0 & 134217728) != 0) { return defaultDouble_; } else { return DefaultDoubleDefaultValue; } }
       set {
@@ -2386,11 +2473,13 @@
     }
     /// <summary>Gets whether the "default_double" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultDouble {
       get { return (_hasBits0 & 134217728) != 0; }
     }
     /// <summary>Clears the value of the "default_double" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultDouble() {
       _hasBits0 &= ~134217728;
     }
@@ -2401,6 +2490,7 @@
 
     private bool defaultBool_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool DefaultBool {
       get { if ((_hasBits0 & 268435456) != 0) { return defaultBool_; } else { return DefaultBoolDefaultValue; } }
       set {
@@ -2410,11 +2500,13 @@
     }
     /// <summary>Gets whether the "default_bool" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultBool {
       get { return (_hasBits0 & 268435456) != 0; }
     }
     /// <summary>Clears the value of the "default_bool" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultBool() {
       _hasBits0 &= ~268435456;
     }
@@ -2425,6 +2517,7 @@
 
     private string defaultString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string DefaultString {
       get { return defaultString_ ?? DefaultStringDefaultValue; }
       set {
@@ -2433,11 +2526,13 @@
     }
     /// <summary>Gets whether the "default_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultString {
       get { return defaultString_ != null; }
     }
     /// <summary>Clears the value of the "default_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultString() {
       defaultString_ = null;
     }
@@ -2448,6 +2543,7 @@
 
     private pb::ByteString defaultBytes_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString DefaultBytes {
       get { return defaultBytes_ ?? DefaultBytesDefaultValue; }
       set {
@@ -2456,11 +2552,13 @@
     }
     /// <summary>Gets whether the "default_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultBytes {
       get { return defaultBytes_ != null; }
     }
     /// <summary>Clears the value of the "default_bytes" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultBytes() {
       defaultBytes_ = null;
     }
@@ -2471,6 +2569,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum defaultNestedEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum DefaultNestedEnum {
       get { if ((_hasBits0 & 536870912) != 0) { return defaultNestedEnum_; } else { return DefaultNestedEnumDefaultValue; } }
       set {
@@ -2480,11 +2579,13 @@
     }
     /// <summary>Gets whether the "default_nested_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultNestedEnum {
       get { return (_hasBits0 & 536870912) != 0; }
     }
     /// <summary>Clears the value of the "default_nested_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultNestedEnum() {
       _hasBits0 &= ~536870912;
     }
@@ -2495,6 +2596,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum defaultForeignEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum DefaultForeignEnum {
       get { if ((_hasBits0 & 1073741824) != 0) { return defaultForeignEnum_; } else { return DefaultForeignEnumDefaultValue; } }
       set {
@@ -2504,11 +2606,13 @@
     }
     /// <summary>Gets whether the "default_foreign_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultForeignEnum {
       get { return (_hasBits0 & 1073741824) != 0; }
     }
     /// <summary>Clears the value of the "default_foreign_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultForeignEnum() {
       _hasBits0 &= ~1073741824;
     }
@@ -2519,6 +2623,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ImportEnum defaultImportEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ImportEnum DefaultImportEnum {
       get { if ((_hasBits0 & -2147483648) != 0) { return defaultImportEnum_; } else { return DefaultImportEnumDefaultValue; } }
       set {
@@ -2528,11 +2633,13 @@
     }
     /// <summary>Gets whether the "default_import_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultImportEnum {
       get { return (_hasBits0 & -2147483648) != 0; }
     }
     /// <summary>Clears the value of the "default_import_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultImportEnum() {
       _hasBits0 &= ~-2147483648;
     }
@@ -2543,6 +2650,7 @@
 
     private string defaultStringPiece_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string DefaultStringPiece {
       get { return defaultStringPiece_ ?? DefaultStringPieceDefaultValue; }
       set {
@@ -2551,11 +2659,13 @@
     }
     /// <summary>Gets whether the "default_string_piece" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultStringPiece {
       get { return defaultStringPiece_ != null; }
     }
     /// <summary>Clears the value of the "default_string_piece" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultStringPiece() {
       defaultStringPiece_ = null;
     }
@@ -2566,6 +2676,7 @@
 
     private string defaultCord_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string DefaultCord {
       get { return defaultCord_ ?? DefaultCordDefaultValue; }
       set {
@@ -2574,11 +2685,13 @@
     }
     /// <summary>Gets whether the "default_cord" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultCord {
       get { return defaultCord_ != null; }
     }
     /// <summary>Clears the value of the "default_cord" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultCord() {
       defaultCord_ = null;
     }
@@ -2586,6 +2699,7 @@
     /// <summary>Field number for the "oneof_uint32" field.</summary>
     public const int OneofUint32FieldNumber = 111;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OneofUint32 {
       get { return HasOneofUint32 ? (uint) oneofField_ : 0; }
       set {
@@ -2595,11 +2709,13 @@
     }
     /// <summary>Gets whether the "oneof_uint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofUint32 {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_uint32" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofUint32() {
       if (HasOneofUint32) {
         ClearOneofField();
@@ -2609,29 +2725,19 @@
     /// <summary>Field number for the "oneof_nested_message" field.</summary>
     public const int OneofNestedMessageFieldNumber = 112;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage OneofNestedMessage {
-      get { return HasOneofNestedMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
       set {
         oneofField_ = value;
         oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
       }
     }
-    /// <summary>Gets whether the "oneof_nested_message" field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOneofNestedMessage {
-      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; }
-    }
-    /// <summary> Clears the value of the oneof if it's currently set to "oneof_nested_message" </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOneofNestedMessage() {
-      if (HasOneofNestedMessage) {
-        ClearOneofField();
-      }
-    }
 
     /// <summary>Field number for the "oneof_string" field.</summary>
     public const int OneofStringFieldNumber = 113;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OneofString {
       get { return HasOneofString ? (string) oneofField_ : ""; }
       set {
@@ -2641,11 +2747,13 @@
     }
     /// <summary>Gets whether the "oneof_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofString {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_string" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofString() {
       if (HasOneofString) {
         ClearOneofField();
@@ -2655,6 +2763,7 @@
     /// <summary>Field number for the "oneof_bytes" field.</summary>
     public const int OneofBytesFieldNumber = 114;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OneofBytes {
       get { return HasOneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
       set {
@@ -2664,11 +2773,13 @@
     }
     /// <summary>Gets whether the "oneof_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofBytes {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_bytes" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofBytes() {
       if (HasOneofBytes) {
         ClearOneofField();
@@ -2686,22 +2797,26 @@
     }
     private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofFieldOneofCase OneofFieldCase {
       get { return oneofFieldCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofField() {
       oneofFieldCase_ = OneofFieldOneofCase.None;
       oneofField_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestAllTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestAllTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2789,6 +2904,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode();
@@ -2807,16 +2923,16 @@
       if (HasOptionalString) hash ^= OptionalString.GetHashCode();
       if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode();
       if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode();
-      if (HasOptionalNestedMessage) hash ^= OptionalNestedMessage.GetHashCode();
-      if (HasOptionalForeignMessage) hash ^= OptionalForeignMessage.GetHashCode();
-      if (HasOptionalImportMessage) hash ^= OptionalImportMessage.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
+      if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode();
+      if (optionalImportMessage_ != null) hash ^= OptionalImportMessage.GetHashCode();
       if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode();
       if (HasOptionalForeignEnum) hash ^= OptionalForeignEnum.GetHashCode();
       if (HasOptionalImportEnum) hash ^= OptionalImportEnum.GetHashCode();
       if (HasOptionalStringPiece) hash ^= OptionalStringPiece.GetHashCode();
       if (HasOptionalCord) hash ^= OptionalCord.GetHashCode();
-      if (HasOptionalPublicImportMessage) hash ^= OptionalPublicImportMessage.GetHashCode();
-      if (HasOptionalLazyMessage) hash ^= OptionalLazyMessage.GetHashCode();
+      if (optionalPublicImportMessage_ != null) hash ^= OptionalPublicImportMessage.GetHashCode();
+      if (optionalLazyMessage_ != null) hash ^= OptionalLazyMessage.GetHashCode();
       hash ^= repeatedInt32_.GetHashCode();
       hash ^= repeatedInt64_.GetHashCode();
       hash ^= repeatedUint32_.GetHashCode();
@@ -2863,7 +2979,7 @@
       if (HasDefaultStringPiece) hash ^= DefaultStringPiece.GetHashCode();
       if (HasDefaultCord) hash ^= DefaultCord.GetHashCode();
       if (HasOneofUint32) hash ^= OneofUint32.GetHashCode();
-      if (HasOneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
       if (HasOneofString) hash ^= OneofString.GetHashCode();
       if (HasOneofBytes) hash ^= OneofBytes.GetHashCode();
       hash ^= (int) oneofFieldCase_;
@@ -2874,12 +2990,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasOptionalInt32) {
         output.WriteRawTag(8);
         output.WriteInt32(OptionalInt32);
@@ -2945,15 +3066,15 @@
         output.WriteGroup(OptionalGroup);
         output.WriteRawTag(132, 1);
       }
-      if (HasOptionalNestedMessage) {
+      if (optionalNestedMessage_ != null) {
         output.WriteRawTag(146, 1);
         output.WriteMessage(OptionalNestedMessage);
       }
-      if (HasOptionalForeignMessage) {
+      if (optionalForeignMessage_ != null) {
         output.WriteRawTag(154, 1);
         output.WriteMessage(OptionalForeignMessage);
       }
-      if (HasOptionalImportMessage) {
+      if (optionalImportMessage_ != null) {
         output.WriteRawTag(162, 1);
         output.WriteMessage(OptionalImportMessage);
       }
@@ -2977,11 +3098,11 @@
         output.WriteRawTag(202, 1);
         output.WriteString(OptionalCord);
       }
-      if (HasOptionalPublicImportMessage) {
+      if (optionalPublicImportMessage_ != null) {
         output.WriteRawTag(210, 1);
         output.WriteMessage(OptionalPublicImportMessage);
       }
-      if (HasOptionalLazyMessage) {
+      if (optionalLazyMessage_ != null) {
         output.WriteRawTag(218, 1);
         output.WriteMessage(OptionalLazyMessage);
       }
@@ -3094,7 +3215,7 @@
         output.WriteRawTag(248, 6);
         output.WriteUInt32(OneofUint32);
       }
-      if (HasOneofNestedMessage) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
         output.WriteRawTag(130, 7);
         output.WriteMessage(OneofNestedMessage);
       }
@@ -3109,9 +3230,247 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasOptionalInt32) {
+        output.WriteRawTag(8);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (HasOptionalInt64) {
+        output.WriteRawTag(16);
+        output.WriteInt64(OptionalInt64);
+      }
+      if (HasOptionalUint32) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(OptionalUint32);
+      }
+      if (HasOptionalUint64) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(OptionalUint64);
+      }
+      if (HasOptionalSint32) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(OptionalSint32);
+      }
+      if (HasOptionalSint64) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(OptionalSint64);
+      }
+      if (HasOptionalFixed32) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(OptionalFixed32);
+      }
+      if (HasOptionalFixed64) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(OptionalFixed64);
+      }
+      if (HasOptionalSfixed32) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(OptionalSfixed32);
+      }
+      if (HasOptionalSfixed64) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(OptionalSfixed64);
+      }
+      if (HasOptionalFloat) {
+        output.WriteRawTag(93);
+        output.WriteFloat(OptionalFloat);
+      }
+      if (HasOptionalDouble) {
+        output.WriteRawTag(97);
+        output.WriteDouble(OptionalDouble);
+      }
+      if (HasOptionalBool) {
+        output.WriteRawTag(104);
+        output.WriteBool(OptionalBool);
+      }
+      if (HasOptionalString) {
+        output.WriteRawTag(114);
+        output.WriteString(OptionalString);
+      }
+      if (HasOptionalBytes) {
+        output.WriteRawTag(122);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (HasOptionalGroup) {
+        output.WriteRawTag(131, 1);
+        output.WriteGroup(OptionalGroup);
+        output.WriteRawTag(132, 1);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (optionalForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(OptionalForeignMessage);
+      }
+      if (optionalImportMessage_ != null) {
+        output.WriteRawTag(162, 1);
+        output.WriteMessage(OptionalImportMessage);
+      }
+      if (HasOptionalNestedEnum) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) OptionalNestedEnum);
+      }
+      if (HasOptionalForeignEnum) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) OptionalForeignEnum);
+      }
+      if (HasOptionalImportEnum) {
+        output.WriteRawTag(184, 1);
+        output.WriteEnum((int) OptionalImportEnum);
+      }
+      if (HasOptionalStringPiece) {
+        output.WriteRawTag(194, 1);
+        output.WriteString(OptionalStringPiece);
+      }
+      if (HasOptionalCord) {
+        output.WriteRawTag(202, 1);
+        output.WriteString(OptionalCord);
+      }
+      if (optionalPublicImportMessage_ != null) {
+        output.WriteRawTag(210, 1);
+        output.WriteMessage(OptionalPublicImportMessage);
+      }
+      if (optionalLazyMessage_ != null) {
+        output.WriteRawTag(218, 1);
+        output.WriteMessage(OptionalLazyMessage);
+      }
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec);
+      repeatedGroup_.WriteTo(ref output, _repeated_repeatedGroup_codec);
+      repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec);
+      repeatedImportMessage_.WriteTo(ref output, _repeated_repeatedImportMessage_codec);
+      repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec);
+      repeatedImportEnum_.WriteTo(ref output, _repeated_repeatedImportEnum_codec);
+      repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec);
+      repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec);
+      repeatedLazyMessage_.WriteTo(ref output, _repeated_repeatedLazyMessage_codec);
+      if (HasDefaultInt32) {
+        output.WriteRawTag(232, 3);
+        output.WriteInt32(DefaultInt32);
+      }
+      if (HasDefaultInt64) {
+        output.WriteRawTag(240, 3);
+        output.WriteInt64(DefaultInt64);
+      }
+      if (HasDefaultUint32) {
+        output.WriteRawTag(248, 3);
+        output.WriteUInt32(DefaultUint32);
+      }
+      if (HasDefaultUint64) {
+        output.WriteRawTag(128, 4);
+        output.WriteUInt64(DefaultUint64);
+      }
+      if (HasDefaultSint32) {
+        output.WriteRawTag(136, 4);
+        output.WriteSInt32(DefaultSint32);
+      }
+      if (HasDefaultSint64) {
+        output.WriteRawTag(144, 4);
+        output.WriteSInt64(DefaultSint64);
+      }
+      if (HasDefaultFixed32) {
+        output.WriteRawTag(157, 4);
+        output.WriteFixed32(DefaultFixed32);
+      }
+      if (HasDefaultFixed64) {
+        output.WriteRawTag(161, 4);
+        output.WriteFixed64(DefaultFixed64);
+      }
+      if (HasDefaultSfixed32) {
+        output.WriteRawTag(173, 4);
+        output.WriteSFixed32(DefaultSfixed32);
+      }
+      if (HasDefaultSfixed64) {
+        output.WriteRawTag(177, 4);
+        output.WriteSFixed64(DefaultSfixed64);
+      }
+      if (HasDefaultFloat) {
+        output.WriteRawTag(189, 4);
+        output.WriteFloat(DefaultFloat);
+      }
+      if (HasDefaultDouble) {
+        output.WriteRawTag(193, 4);
+        output.WriteDouble(DefaultDouble);
+      }
+      if (HasDefaultBool) {
+        output.WriteRawTag(200, 4);
+        output.WriteBool(DefaultBool);
+      }
+      if (HasDefaultString) {
+        output.WriteRawTag(210, 4);
+        output.WriteString(DefaultString);
+      }
+      if (HasDefaultBytes) {
+        output.WriteRawTag(218, 4);
+        output.WriteBytes(DefaultBytes);
+      }
+      if (HasDefaultNestedEnum) {
+        output.WriteRawTag(136, 5);
+        output.WriteEnum((int) DefaultNestedEnum);
+      }
+      if (HasDefaultForeignEnum) {
+        output.WriteRawTag(144, 5);
+        output.WriteEnum((int) DefaultForeignEnum);
+      }
+      if (HasDefaultImportEnum) {
+        output.WriteRawTag(152, 5);
+        output.WriteEnum((int) DefaultImportEnum);
+      }
+      if (HasDefaultStringPiece) {
+        output.WriteRawTag(162, 5);
+        output.WriteString(DefaultStringPiece);
+      }
+      if (HasDefaultCord) {
+        output.WriteRawTag(170, 5);
+        output.WriteString(DefaultCord);
+      }
+      if (HasOneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (HasOneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (HasOneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasOptionalInt32) {
@@ -3162,13 +3521,13 @@
       if (HasOptionalGroup) {
         size += 4 + pb::CodedOutputStream.ComputeGroupSize(OptionalGroup);
       }
-      if (HasOptionalNestedMessage) {
+      if (optionalNestedMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
       }
-      if (HasOptionalForeignMessage) {
+      if (optionalForeignMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage);
       }
-      if (HasOptionalImportMessage) {
+      if (optionalImportMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalImportMessage);
       }
       if (HasOptionalNestedEnum) {
@@ -3186,10 +3545,10 @@
       if (HasOptionalCord) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord);
       }
-      if (HasOptionalPublicImportMessage) {
+      if (optionalPublicImportMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalPublicImportMessage);
       }
-      if (HasOptionalLazyMessage) {
+      if (optionalLazyMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalLazyMessage);
       }
       size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
@@ -3280,7 +3639,7 @@
       if (HasOneofUint32) {
         size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
       }
-      if (HasOneofNestedMessage) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage);
       }
       if (HasOneofString) {
@@ -3296,6 +3655,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestAllTypes other) {
       if (other == null) {
         return;
@@ -3351,20 +3711,20 @@
         }
         OptionalGroup.MergeFrom(other.OptionalGroup);
       }
-      if (other.HasOptionalNestedMessage) {
-        if (!HasOptionalNestedMessage) {
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
           OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
         }
         OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
       }
-      if (other.HasOptionalForeignMessage) {
-        if (!HasOptionalForeignMessage) {
+      if (other.optionalForeignMessage_ != null) {
+        if (optionalForeignMessage_ == null) {
           OptionalForeignMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
         }
         OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage);
       }
-      if (other.HasOptionalImportMessage) {
-        if (!HasOptionalImportMessage) {
+      if (other.optionalImportMessage_ != null) {
+        if (optionalImportMessage_ == null) {
           OptionalImportMessage = new global::Google.Protobuf.TestProtos.Proto2.ImportMessage();
         }
         OptionalImportMessage.MergeFrom(other.OptionalImportMessage);
@@ -3384,14 +3744,14 @@
       if (other.HasOptionalCord) {
         OptionalCord = other.OptionalCord;
       }
-      if (other.HasOptionalPublicImportMessage) {
-        if (!HasOptionalPublicImportMessage) {
+      if (other.optionalPublicImportMessage_ != null) {
+        if (optionalPublicImportMessage_ == null) {
           OptionalPublicImportMessage = new global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage();
         }
         OptionalPublicImportMessage.MergeFrom(other.OptionalPublicImportMessage);
       }
-      if (other.HasOptionalLazyMessage) {
-        if (!HasOptionalLazyMessage) {
+      if (other.optionalLazyMessage_ != null) {
+        if (optionalLazyMessage_ == null) {
           OptionalLazyMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
         }
         OptionalLazyMessage.MergeFrom(other.OptionalLazyMessage);
@@ -3503,7 +3863,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3578,21 +3942,21 @@
             break;
           }
           case 146: {
-            if (!HasOptionalNestedMessage) {
+            if (optionalNestedMessage_ == null) {
               OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
             }
             input.ReadMessage(OptionalNestedMessage);
             break;
           }
           case 154: {
-            if (!HasOptionalForeignMessage) {
+            if (optionalForeignMessage_ == null) {
               OptionalForeignMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
             }
             input.ReadMessage(OptionalForeignMessage);
             break;
           }
           case 162: {
-            if (!HasOptionalImportMessage) {
+            if (optionalImportMessage_ == null) {
               OptionalImportMessage = new global::Google.Protobuf.TestProtos.Proto2.ImportMessage();
             }
             input.ReadMessage(OptionalImportMessage);
@@ -3619,14 +3983,14 @@
             break;
           }
           case 210: {
-            if (!HasOptionalPublicImportMessage) {
+            if (optionalPublicImportMessage_ == null) {
               OptionalPublicImportMessage = new global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage();
             }
             input.ReadMessage(OptionalPublicImportMessage);
             break;
           }
           case 218: {
-            if (!HasOptionalLazyMessage) {
+            if (optionalLazyMessage_ == null) {
               OptionalLazyMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
             }
             input.ReadMessage(OptionalLazyMessage);
@@ -3834,7 +4198,361 @@
           }
           case 898: {
             global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
-            if (HasOneofNestedMessage) {
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            OptionalInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            OptionalUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            OptionalUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            OptionalSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            OptionalSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            OptionalFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            OptionalFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            OptionalSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            OptionalSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            OptionalFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            OptionalDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 122: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 131: {
+            if (!HasOptionalGroup) {
+              OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup();
+            }
+            input.ReadGroup(OptionalGroup);
+            break;
+          }
+          case 146: {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+          case 154: {
+            if (optionalForeignMessage_ == null) {
+              OptionalForeignMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
+            }
+            input.ReadMessage(OptionalForeignMessage);
+            break;
+          }
+          case 162: {
+            if (optionalImportMessage_ == null) {
+              OptionalImportMessage = new global::Google.Protobuf.TestProtos.Proto2.ImportMessage();
+            }
+            input.ReadMessage(OptionalImportMessage);
+            break;
+          }
+          case 168: {
+            OptionalNestedEnum = (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            OptionalForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 184: {
+            OptionalImportEnum = (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) input.ReadEnum();
+            break;
+          }
+          case 194: {
+            OptionalStringPiece = input.ReadString();
+            break;
+          }
+          case 202: {
+            OptionalCord = input.ReadString();
+            break;
+          }
+          case 210: {
+            if (optionalPublicImportMessage_ == null) {
+              OptionalPublicImportMessage = new global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage();
+            }
+            input.ReadMessage(OptionalPublicImportMessage);
+            break;
+          }
+          case 218: {
+            if (optionalLazyMessage_ == null) {
+              OptionalLazyMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalLazyMessage);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 371: {
+            repeatedGroup_.AddEntriesFrom(ref input, _repeated_repeatedGroup_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 402: {
+            repeatedImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedImportMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 426:
+          case 424: {
+            repeatedImportEnum_.AddEntriesFrom(ref input, _repeated_repeatedImportEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec);
+            break;
+          }
+          case 442: {
+            repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec);
+            break;
+          }
+          case 458: {
+            repeatedLazyMessage_.AddEntriesFrom(ref input, _repeated_repeatedLazyMessage_codec);
+            break;
+          }
+          case 488: {
+            DefaultInt32 = input.ReadInt32();
+            break;
+          }
+          case 496: {
+            DefaultInt64 = input.ReadInt64();
+            break;
+          }
+          case 504: {
+            DefaultUint32 = input.ReadUInt32();
+            break;
+          }
+          case 512: {
+            DefaultUint64 = input.ReadUInt64();
+            break;
+          }
+          case 520: {
+            DefaultSint32 = input.ReadSInt32();
+            break;
+          }
+          case 528: {
+            DefaultSint64 = input.ReadSInt64();
+            break;
+          }
+          case 541: {
+            DefaultFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 545: {
+            DefaultFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 557: {
+            DefaultSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 561: {
+            DefaultSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 573: {
+            DefaultFloat = input.ReadFloat();
+            break;
+          }
+          case 577: {
+            DefaultDouble = input.ReadDouble();
+            break;
+          }
+          case 584: {
+            DefaultBool = input.ReadBool();
+            break;
+          }
+          case 594: {
+            DefaultString = input.ReadString();
+            break;
+          }
+          case 602: {
+            DefaultBytes = input.ReadBytes();
+            break;
+          }
+          case 648: {
+            DefaultNestedEnum = (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 656: {
+            DefaultForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 664: {
+            DefaultImportEnum = (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) input.ReadEnum();
+            break;
+          }
+          case 674: {
+            DefaultStringPiece = input.ReadString();
+            break;
+          }
+          case 682: {
+            DefaultCord = input.ReadString();
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
               subBuilder.MergeFrom(OneofNestedMessage);
             }
             input.ReadMessage(subBuilder);
@@ -3852,10 +4570,12 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestAllTypes message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum NestedEnum {
         [pbr::OriginalName("FOO")] Foo = 1,
@@ -3867,24 +4587,32 @@
         [pbr::OriginalName("NEG")] Neg = -1,
       }
 
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -3892,6 +4620,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           _hasBits0 = other._hasBits0;
           bb_ = other.bb_;
@@ -3899,6 +4628,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -3914,6 +4644,7 @@
         /// This file needs to compile in proto1 to test backwards-compatibility.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Bb {
           get { if ((_hasBits0 & 1) != 0) { return bb_; } else { return BbDefaultValue; } }
           set {
@@ -3923,21 +4654,25 @@
         }
         /// <summary>Gets whether the "bb" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasBb {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "bb" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearBb() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -3950,6 +4685,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasBb) hash ^= Bb.GetHashCode();
@@ -3960,12 +4696,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasBb) {
             output.WriteRawTag(8);
             output.WriteInt32(Bb);
@@ -3973,9 +4714,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasBb) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasBb) {
@@ -3988,6 +4745,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -3999,7 +4757,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4012,28 +4774,56 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
-      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup> {
+      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<OptionalGroup> _parser = new pb::MessageParser<OptionalGroup>(() => new OptionalGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<OptionalGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Descriptor.NestedTypes[1]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup() {
           OnConstruction();
         }
@@ -4041,6 +4831,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup(OptionalGroup other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -4048,6 +4839,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup Clone() {
           return new OptionalGroup(this);
         }
@@ -4058,6 +4850,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -4067,21 +4860,25 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as OptionalGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(OptionalGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4094,6 +4891,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -4104,12 +4902,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(136, 1);
             output.WriteInt32(A);
@@ -4117,9 +4920,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(136, 1);
+            output.WriteInt32(A);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -4132,6 +4951,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(OptionalGroup other) {
           if (other == null) {
             return;
@@ -4143,7 +4963,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4158,28 +4982,58 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 132:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 136: {
+                A = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
-      public sealed partial class RepeatedGroup : pb::IMessage<RepeatedGroup> {
+      public sealed partial class RepeatedGroup : pb::IMessage<RepeatedGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<RepeatedGroup> _parser = new pb::MessageParser<RepeatedGroup>(() => new RepeatedGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<RepeatedGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Descriptor.NestedTypes[2]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedGroup() {
           OnConstruction();
         }
@@ -4187,6 +5041,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedGroup(RepeatedGroup other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -4194,6 +5049,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedGroup Clone() {
           return new RepeatedGroup(this);
         }
@@ -4204,6 +5060,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -4213,21 +5070,25 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as RepeatedGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(RepeatedGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -4240,6 +5101,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -4250,12 +5112,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(248, 2);
             output.WriteInt32(A);
@@ -4263,9 +5130,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(248, 2);
+            output.WriteInt32(A);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -4278,6 +5161,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(RepeatedGroup other) {
           if (other == null) {
             return;
@@ -4289,7 +5173,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -4304,8 +5192,30 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 372:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 376: {
+                A = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -4316,23 +5226,31 @@
   /// <summary>
   /// This proto includes a recursively nested message.
   /// </summary>
-  public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes> {
+  public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<NestedTestAllTypes> _parser = new pb::MessageParser<NestedTestAllTypes>(() => new NestedTestAllTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<NestedTestAllTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedTestAllTypes() {
       OnConstruction();
     }
@@ -4340,14 +5258,16 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedTestAllTypes(NestedTestAllTypes other) : this() {
-      child_ = other.HasChild ? other.child_.Clone() : null;
-      payload_ = other.HasPayload ? other.payload_.Clone() : null;
+      child_ = other.child_ != null ? other.child_.Clone() : null;
+      payload_ = other.payload_ != null ? other.payload_.Clone() : null;
       repeatedChild_ = other.repeatedChild_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedTestAllTypes Clone() {
       return new NestedTestAllTypes(this);
     }
@@ -4356,43 +5276,25 @@
     public const int ChildFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes child_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes Child {
       get { return child_; }
       set {
         child_ = value;
       }
     }
-    /// <summary>Gets whether the child field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasChild {
-      get { return child_ != null; }
-    }
-    /// <summary>Clears the value of the child field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearChild() {
-      child_ = null;
-    }
 
     /// <summary>Field number for the "payload" field.</summary>
     public const int PayloadFieldNumber = 2;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes payload_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes Payload {
       get { return payload_; }
       set {
         payload_ = value;
       }
     }
-    /// <summary>Gets whether the payload field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasPayload {
-      get { return payload_ != null; }
-    }
-    /// <summary>Clears the value of the payload field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearPayload() {
-      payload_ = null;
-    }
 
     /// <summary>Field number for the "repeated_child" field.</summary>
     public const int RepeatedChildFieldNumber = 3;
@@ -4400,16 +5302,19 @@
         = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes> repeatedChild_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes> RepeatedChild {
       get { return repeatedChild_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as NestedTestAllTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(NestedTestAllTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4424,10 +5329,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasChild) hash ^= Child.GetHashCode();
-      if (HasPayload) hash ^= Payload.GetHashCode();
+      if (child_ != null) hash ^= Child.GetHashCode();
+      if (payload_ != null) hash ^= Payload.GetHashCode();
       hash ^= repeatedChild_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -4436,17 +5342,22 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasChild) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (child_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(Child);
       }
-      if (HasPayload) {
+      if (payload_ != null) {
         output.WriteRawTag(18);
         output.WriteMessage(Payload);
       }
@@ -4454,15 +5365,36 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (child_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Child);
+      }
+      if (payload_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Payload);
+      }
+      repeatedChild_.WriteTo(ref output, _repeated_repeatedChild_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasChild) {
+      if (child_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Child);
       }
-      if (HasPayload) {
+      if (payload_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
       }
       size += repeatedChild_.CalculateSize(_repeated_repeatedChild_codec);
@@ -4473,18 +5405,19 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(NestedTestAllTypes other) {
       if (other == null) {
         return;
       }
-      if (other.HasChild) {
-        if (!HasChild) {
+      if (other.child_ != null) {
+        if (child_ == null) {
           Child = new global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes();
         }
         Child.MergeFrom(other.Child);
       }
-      if (other.HasPayload) {
-        if (!HasPayload) {
+      if (other.payload_ != null) {
+        if (payload_ == null) {
           Payload = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
         }
         Payload.MergeFrom(other.Payload);
@@ -4494,7 +5427,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4502,14 +5439,14 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasChild) {
+            if (child_ == null) {
               Child = new global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes();
             }
             input.ReadMessage(Child);
             break;
           }
           case 18: {
-            if (!HasPayload) {
+            if (payload_ == null) {
               Payload = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             input.ReadMessage(Payload);
@@ -4521,28 +5458,70 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (child_ == null) {
+              Child = new global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes();
+            }
+            input.ReadMessage(Child);
+            break;
+          }
+          case 18: {
+            if (payload_ == null) {
+              Payload = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            }
+            input.ReadMessage(Payload);
+            break;
+          }
+          case 26: {
+            repeatedChild_.AddEntriesFrom(ref input, _repeated_repeatedChild_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestDeprecatedFields : pb::IMessage<TestDeprecatedFields> {
+  public sealed partial class TestDeprecatedFields : pb::IMessage<TestDeprecatedFields>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestDeprecatedFields> _parser = new pb::MessageParser<TestDeprecatedFields>(() => new TestDeprecatedFields());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestDeprecatedFields> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedFields() {
       OnConstruction();
     }
@@ -4550,6 +5529,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedFields(TestDeprecatedFields other) : this() {
       _hasBits0 = other._hasBits0;
       deprecatedInt32_ = other.deprecatedInt32_;
@@ -4563,6 +5543,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedFields Clone() {
       return new TestDeprecatedFields(this);
     }
@@ -4574,6 +5555,7 @@
     private int deprecatedInt32_;
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int DeprecatedInt32 {
       get { if ((_hasBits0 & 1) != 0) { return deprecatedInt32_; } else { return DeprecatedInt32DefaultValue; } }
       set {
@@ -4584,12 +5566,14 @@
     /// <summary>Gets whether the "deprecated_int32" field is set</summary>
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecatedInt32 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "deprecated_int32" field</summary>
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecatedInt32() {
       _hasBits0 &= ~1;
     }
@@ -4598,6 +5582,7 @@
     public const int DeprecatedInt32InOneofFieldNumber = 2;
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int DeprecatedInt32InOneof {
       get { return HasDeprecatedInt32InOneof ? (int) oneofFields_ : 0; }
       set {
@@ -4608,12 +5593,14 @@
     /// <summary>Gets whether the "deprecated_int32_in_oneof" field is set</summary>
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecatedInt32InOneof {
       get { return oneofFieldsCase_ == OneofFieldsOneofCase.DeprecatedInt32InOneof; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "deprecated_int32_in_oneof" </summary>
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecatedInt32InOneof() {
       if (HasDeprecatedInt32InOneof) {
         ClearOneofFields();
@@ -4628,22 +5615,26 @@
     }
     private OneofFieldsOneofCase oneofFieldsCase_ = OneofFieldsOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofFieldsOneofCase OneofFieldsCase {
       get { return oneofFieldsCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofFields() {
       oneofFieldsCase_ = OneofFieldsOneofCase.None;
       oneofFields_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestDeprecatedFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestDeprecatedFields other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4658,6 +5649,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasDeprecatedInt32) hash ^= DeprecatedInt32.GetHashCode();
@@ -4670,12 +5662,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasDeprecatedInt32) {
         output.WriteRawTag(8);
         output.WriteInt32(DeprecatedInt32);
@@ -4687,9 +5684,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasDeprecatedInt32) {
+        output.WriteRawTag(8);
+        output.WriteInt32(DeprecatedInt32);
+      }
+      if (HasDeprecatedInt32InOneof) {
+        output.WriteRawTag(16);
+        output.WriteInt32(DeprecatedInt32InOneof);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasDeprecatedInt32) {
@@ -4705,6 +5722,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestDeprecatedFields other) {
       if (other == null) {
         return;
@@ -4722,7 +5740,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4739,28 +5761,60 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            DeprecatedInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            DeprecatedInt32InOneof = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   [global::System.ObsoleteAttribute]
-  public sealed partial class TestDeprecatedMessage : pb::IMessage<TestDeprecatedMessage> {
+  public sealed partial class TestDeprecatedMessage : pb::IMessage<TestDeprecatedMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestDeprecatedMessage> _parser = new pb::MessageParser<TestDeprecatedMessage>(() => new TestDeprecatedMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestDeprecatedMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedMessage() {
       OnConstruction();
     }
@@ -4768,21 +5822,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedMessage(TestDeprecatedMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedMessage Clone() {
       return new TestDeprecatedMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestDeprecatedMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestDeprecatedMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4794,6 +5852,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -4803,18 +5862,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -4824,6 +5900,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestDeprecatedMessage other) {
       if (other == null) {
         return;
@@ -4832,7 +5909,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4841,32 +5922,56 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Define these after TestAllTypes to make sure the compiler can handle
   /// that.
   /// </summary>
-  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
+  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage() {
       OnConstruction();
     }
@@ -4874,6 +5979,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage(ForeignMessage other) : this() {
       _hasBits0 = other._hasBits0;
       c_ = other.c_;
@@ -4882,6 +5988,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage Clone() {
       return new ForeignMessage(this);
     }
@@ -4892,6 +5999,7 @@
 
     private int c_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int C {
       get { if ((_hasBits0 & 1) != 0) { return c_; } else { return CDefaultValue; } }
       set {
@@ -4901,11 +6009,13 @@
     }
     /// <summary>Gets whether the "c" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasC {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "c" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearC() {
       _hasBits0 &= ~1;
     }
@@ -4916,6 +6026,7 @@
 
     private int d_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int D {
       get { if ((_hasBits0 & 2) != 0) { return d_; } else { return DDefaultValue; } }
       set {
@@ -4925,21 +6036,25 @@
     }
     /// <summary>Gets whether the "d" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasD {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "d" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearD() {
       _hasBits0 &= ~2;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ForeignMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ForeignMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4953,6 +6068,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasC) hash ^= C.GetHashCode();
@@ -4964,12 +6080,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasC) {
         output.WriteRawTag(8);
         output.WriteInt32(C);
@@ -4981,9 +6102,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasC) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+      if (HasD) {
+        output.WriteRawTag(16);
+        output.WriteInt32(D);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasC) {
@@ -4999,6 +6140,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ForeignMessage other) {
       if (other == null) {
         return;
@@ -5013,7 +6155,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5030,27 +6176,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            D = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestReservedFields : pb::IMessage<TestReservedFields> {
+  public sealed partial class TestReservedFields : pb::IMessage<TestReservedFields>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestReservedFields> _parser = new pb::MessageParser<TestReservedFields>(() => new TestReservedFields());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestReservedFields> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReservedFields() {
       OnConstruction();
     }
@@ -5058,21 +6236,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReservedFields(TestReservedFields other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReservedFields Clone() {
       return new TestReservedFields(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestReservedFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestReservedFields other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5084,6 +6266,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -5093,18 +6276,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -5114,6 +6314,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestReservedFields other) {
       if (other == null) {
         return;
@@ -5122,7 +6323,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5131,29 +6336,53 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestAllExtensions : pb::IExtendableMessage<TestAllExtensions> {
+  public sealed partial class TestAllExtensions : pb::IExtendableMessage<TestAllExtensions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestAllExtensions> _parser = new pb::MessageParser<TestAllExtensions>(() => new TestAllExtensions());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestAllExtensions> _extensions;
     private pb::ExtensionSet<TestAllExtensions> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestAllExtensions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllExtensions() {
       OnConstruction();
     }
@@ -5161,22 +6390,26 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllExtensions(TestAllExtensions other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _extensions = pb::ExtensionSet.Clone(other._extensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllExtensions Clone() {
       return new TestAllExtensions(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestAllExtensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestAllExtensions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5191,6 +6424,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_extensions != null) {
@@ -5203,21 +6437,41 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_extensions != null) {
         _extensions.WriteTo(output);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_extensions != null) {
@@ -5230,6 +6484,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestAllExtensions other) {
       if (other == null) {
         return;
@@ -5239,7 +6494,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5250,8 +6509,26 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestAllExtensions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -5276,24 +6553,32 @@
 
   }
 
-  public sealed partial class OptionalGroup_extension : pb::IMessage<OptionalGroup_extension> {
+  public sealed partial class OptionalGroup_extension : pb::IMessage<OptionalGroup_extension>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OptionalGroup_extension> _parser = new pb::MessageParser<OptionalGroup_extension>(() => new OptionalGroup_extension());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OptionalGroup_extension> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[7]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OptionalGroup_extension() {
       OnConstruction();
     }
@@ -5301,6 +6586,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OptionalGroup_extension(OptionalGroup_extension other) : this() {
       _hasBits0 = other._hasBits0;
       a_ = other.a_;
@@ -5308,6 +6594,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OptionalGroup_extension Clone() {
       return new OptionalGroup_extension(this);
     }
@@ -5318,6 +6605,7 @@
 
     private int a_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int A {
       get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
       set {
@@ -5327,21 +6615,25 @@
     }
     /// <summary>Gets whether the "a" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasA {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "a" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearA() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OptionalGroup_extension);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OptionalGroup_extension other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5354,6 +6646,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasA) hash ^= A.GetHashCode();
@@ -5364,12 +6657,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasA) {
         output.WriteRawTag(136, 1);
         output.WriteInt32(A);
@@ -5377,9 +6675,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasA) {
+        output.WriteRawTag(136, 1);
+        output.WriteInt32(A);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasA) {
@@ -5392,6 +6706,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OptionalGroup_extension other) {
       if (other == null) {
         return;
@@ -5403,7 +6718,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5418,28 +6737,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          case 132:
+            return;
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 136: {
+            A = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class RepeatedGroup_extension : pb::IMessage<RepeatedGroup_extension> {
+  public sealed partial class RepeatedGroup_extension : pb::IMessage<RepeatedGroup_extension>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<RepeatedGroup_extension> _parser = new pb::MessageParser<RepeatedGroup_extension>(() => new RepeatedGroup_extension());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<RepeatedGroup_extension> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[8]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public RepeatedGroup_extension() {
       OnConstruction();
     }
@@ -5447,6 +6796,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public RepeatedGroup_extension(RepeatedGroup_extension other) : this() {
       _hasBits0 = other._hasBits0;
       a_ = other.a_;
@@ -5454,6 +6804,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public RepeatedGroup_extension Clone() {
       return new RepeatedGroup_extension(this);
     }
@@ -5464,6 +6815,7 @@
 
     private int a_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int A {
       get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
       set {
@@ -5473,21 +6825,25 @@
     }
     /// <summary>Gets whether the "a" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasA {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "a" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearA() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as RepeatedGroup_extension);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(RepeatedGroup_extension other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5500,6 +6856,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasA) hash ^= A.GetHashCode();
@@ -5510,12 +6867,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasA) {
         output.WriteRawTag(248, 2);
         output.WriteInt32(A);
@@ -5523,9 +6885,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasA) {
+        output.WriteRawTag(248, 2);
+        output.WriteInt32(A);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasA) {
@@ -5538,6 +6916,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(RepeatedGroup_extension other) {
       if (other == null) {
         return;
@@ -5549,7 +6928,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5564,28 +6947,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          case 372:
+            return;
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 376: {
+            A = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestGroup : pb::IMessage<TestGroup> {
+  public sealed partial class TestGroup : pb::IMessage<TestGroup>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestGroup> _parser = new pb::MessageParser<TestGroup>(() => new TestGroup());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestGroup> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[9]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestGroup() {
       OnConstruction();
     }
@@ -5593,6 +7006,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestGroup(TestGroup other) : this() {
       _hasBits0 = other._hasBits0;
       optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null;
@@ -5601,6 +7015,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestGroup Clone() {
       return new TestGroup(this);
     }
@@ -5609,6 +7024,7 @@
     public const int OptionalGroupFieldNumber = 16;
     private global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup optionalGroup_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup OptionalGroup {
       get { return optionalGroup_; }
       set {
@@ -5617,11 +7033,13 @@
     }
     /// <summary>Gets whether the optionalgroup field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalGroup {
       get { return optionalGroup_ != null; }
     }
     /// <summary>Clears the value of the optionalgroup field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalGroup() {
       optionalGroup_ = null;
     }
@@ -5632,6 +7050,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum optionalForeignEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalForeignEnum {
       get { if ((_hasBits0 & 1) != 0) { return optionalForeignEnum_; } else { return OptionalForeignEnumDefaultValue; } }
       set {
@@ -5641,21 +7060,25 @@
     }
     /// <summary>Gets whether the "optional_foreign_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalForeignEnum {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "optional_foreign_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalForeignEnum() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestGroup);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestGroup other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5669,6 +7092,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode();
@@ -5680,12 +7104,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasOptionalGroup) {
         output.WriteRawTag(131, 1);
         output.WriteGroup(OptionalGroup);
@@ -5698,9 +7127,30 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasOptionalGroup) {
+        output.WriteRawTag(131, 1);
+        output.WriteGroup(OptionalGroup);
+        output.WriteRawTag(132, 1);
+      }
+      if (HasOptionalForeignEnum) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) OptionalForeignEnum);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasOptionalGroup) {
@@ -5716,6 +7166,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestGroup other) {
       if (other == null) {
         return;
@@ -5733,7 +7184,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5753,30 +7208,66 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 131: {
+            if (!HasOptionalGroup) {
+              OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup();
+            }
+            input.ReadGroup(OptionalGroup);
+            break;
+          }
+          case 176: {
+            OptionalForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestGroup message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup> {
+      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<OptionalGroup> _parser = new pb::MessageParser<OptionalGroup>(() => new OptionalGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<OptionalGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestGroup.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup() {
           OnConstruction();
         }
@@ -5784,6 +7275,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup(OptionalGroup other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -5791,6 +7283,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup Clone() {
           return new OptionalGroup(this);
         }
@@ -5801,6 +7294,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -5810,21 +7304,25 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as OptionalGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(OptionalGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -5837,6 +7335,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -5847,12 +7346,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(136, 1);
             output.WriteInt32(A);
@@ -5860,9 +7364,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(136, 1);
+            output.WriteInt32(A);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -5875,6 +7395,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(OptionalGroup other) {
           if (other == null) {
             return;
@@ -5886,7 +7407,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -5901,8 +7426,30 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 132:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 136: {
+                A = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -5910,25 +7457,33 @@
 
   }
 
-  public sealed partial class TestGroupExtension : pb::IExtendableMessage<TestGroupExtension> {
+  public sealed partial class TestGroupExtension : pb::IExtendableMessage<TestGroupExtension>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestGroupExtension> _parser = new pb::MessageParser<TestGroupExtension>(() => new TestGroupExtension());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestGroupExtension> _extensions;
     private pb::ExtensionSet<TestGroupExtension> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestGroupExtension> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[10]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestGroupExtension() {
       OnConstruction();
     }
@@ -5936,22 +7491,26 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestGroupExtension(TestGroupExtension other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _extensions = pb::ExtensionSet.Clone(other._extensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestGroupExtension Clone() {
       return new TestGroupExtension(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestGroupExtension);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestGroupExtension other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5966,6 +7525,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_extensions != null) {
@@ -5978,21 +7538,41 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_extensions != null) {
         _extensions.WriteTo(output);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_extensions != null) {
@@ -6005,6 +7585,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestGroupExtension other) {
       if (other == null) {
         return;
@@ -6014,7 +7595,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6025,8 +7610,26 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestGroupExtension, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -6051,23 +7654,31 @@
 
   }
 
-  public sealed partial class TestNestedExtension : pb::IMessage<TestNestedExtension> {
+  public sealed partial class TestNestedExtension : pb::IMessage<TestNestedExtension>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestNestedExtension> _parser = new pb::MessageParser<TestNestedExtension>(() => new TestNestedExtension());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestNestedExtension> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[11]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestNestedExtension() {
       OnConstruction();
     }
@@ -6075,21 +7686,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestNestedExtension(TestNestedExtension other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestNestedExtension Clone() {
       return new TestNestedExtension(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestNestedExtension);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestNestedExtension other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6101,6 +7716,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -6110,18 +7726,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -6131,6 +7764,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestNestedExtension other) {
       if (other == null) {
         return;
@@ -6139,7 +7773,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6148,30 +7786,55 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestNestedExtension message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class OptionalGroup_extension : pb::IMessage<OptionalGroup_extension> {
+      public sealed partial class OptionalGroup_extension : pb::IMessage<OptionalGroup_extension>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<OptionalGroup_extension> _parser = new pb::MessageParser<OptionalGroup_extension>(() => new OptionalGroup_extension());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<OptionalGroup_extension> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup_extension() {
           OnConstruction();
         }
@@ -6179,6 +7842,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup_extension(OptionalGroup_extension other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -6186,6 +7850,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup_extension Clone() {
           return new OptionalGroup_extension(this);
         }
@@ -6196,6 +7861,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -6205,21 +7871,25 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as OptionalGroup_extension);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(OptionalGroup_extension other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -6232,6 +7902,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -6242,12 +7913,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(136, 1);
             output.WriteInt32(A);
@@ -6255,9 +7931,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(136, 1);
+            output.WriteInt32(A);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -6270,6 +7962,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(OptionalGroup_extension other) {
           if (other == null) {
             return;
@@ -6281,7 +7974,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -6296,8 +7993,30 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 132:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 136: {
+                A = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -6306,6 +8025,7 @@
     #region Extensions
     /// <summary>Container for extensions for other messages declared in the TestNestedExtension message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Extensions {
       /// <summary>
       /// Check for bug where string extensions declared in tested scope did not
@@ -6335,25 +8055,33 @@
   /// required filed because the code output is basically identical to
   /// optional fields for all types.
   /// </summary>
-  public sealed partial class TestRequired : pb::IMessage<TestRequired> {
+  public sealed partial class TestRequired : pb::IMessage<TestRequired>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRequired> _parser = new pb::MessageParser<TestRequired>(() => new TestRequired());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     private int _hasBits1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRequired> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[12]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequired() {
       OnConstruction();
     }
@@ -6361,6 +8089,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequired(TestRequired other) : this() {
       _hasBits0 = other._hasBits0;
       _hasBits1 = other._hasBits1;
@@ -6401,6 +8130,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequired Clone() {
       return new TestRequired(this);
     }
@@ -6411,6 +8141,7 @@
 
     private int a_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int A {
       get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
       set {
@@ -6420,11 +8151,13 @@
     }
     /// <summary>Gets whether the "a" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasA {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "a" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearA() {
       _hasBits0 &= ~1;
     }
@@ -6435,6 +8168,7 @@
 
     private int dummy2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy2 {
       get { if ((_hasBits0 & 2) != 0) { return dummy2_; } else { return Dummy2DefaultValue; } }
       set {
@@ -6444,11 +8178,13 @@
     }
     /// <summary>Gets whether the "dummy2" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy2 {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "dummy2" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy2() {
       _hasBits0 &= ~2;
     }
@@ -6459,6 +8195,7 @@
 
     private int b_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int B {
       get { if ((_hasBits0 & 4) != 0) { return b_; } else { return BDefaultValue; } }
       set {
@@ -6468,11 +8205,13 @@
     }
     /// <summary>Gets whether the "b" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasB {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "b" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearB() {
       _hasBits0 &= ~4;
     }
@@ -6487,6 +8226,7 @@
     /// properly checks multiple elements of has_bits_.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy4 {
       get { if ((_hasBits0 & 8) != 0) { return dummy4_; } else { return Dummy4DefaultValue; } }
       set {
@@ -6496,11 +8236,13 @@
     }
     /// <summary>Gets whether the "dummy4" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy4 {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "dummy4" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy4() {
       _hasBits0 &= ~8;
     }
@@ -6511,6 +8253,7 @@
 
     private int dummy5_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy5 {
       get { if ((_hasBits0 & 16) != 0) { return dummy5_; } else { return Dummy5DefaultValue; } }
       set {
@@ -6520,11 +8263,13 @@
     }
     /// <summary>Gets whether the "dummy5" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy5 {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "dummy5" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy5() {
       _hasBits0 &= ~16;
     }
@@ -6535,6 +8280,7 @@
 
     private int dummy6_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy6 {
       get { if ((_hasBits0 & 32) != 0) { return dummy6_; } else { return Dummy6DefaultValue; } }
       set {
@@ -6544,11 +8290,13 @@
     }
     /// <summary>Gets whether the "dummy6" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy6 {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "dummy6" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy6() {
       _hasBits0 &= ~32;
     }
@@ -6559,6 +8307,7 @@
 
     private int dummy7_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy7 {
       get { if ((_hasBits0 & 64) != 0) { return dummy7_; } else { return Dummy7DefaultValue; } }
       set {
@@ -6568,11 +8317,13 @@
     }
     /// <summary>Gets whether the "dummy7" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy7 {
       get { return (_hasBits0 & 64) != 0; }
     }
     /// <summary>Clears the value of the "dummy7" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy7() {
       _hasBits0 &= ~64;
     }
@@ -6583,6 +8334,7 @@
 
     private int dummy8_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy8 {
       get { if ((_hasBits0 & 128) != 0) { return dummy8_; } else { return Dummy8DefaultValue; } }
       set {
@@ -6592,11 +8344,13 @@
     }
     /// <summary>Gets whether the "dummy8" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy8 {
       get { return (_hasBits0 & 128) != 0; }
     }
     /// <summary>Clears the value of the "dummy8" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy8() {
       _hasBits0 &= ~128;
     }
@@ -6607,6 +8361,7 @@
 
     private int dummy9_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy9 {
       get { if ((_hasBits0 & 256) != 0) { return dummy9_; } else { return Dummy9DefaultValue; } }
       set {
@@ -6616,11 +8371,13 @@
     }
     /// <summary>Gets whether the "dummy9" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy9 {
       get { return (_hasBits0 & 256) != 0; }
     }
     /// <summary>Clears the value of the "dummy9" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy9() {
       _hasBits0 &= ~256;
     }
@@ -6631,6 +8388,7 @@
 
     private int dummy10_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy10 {
       get { if ((_hasBits0 & 512) != 0) { return dummy10_; } else { return Dummy10DefaultValue; } }
       set {
@@ -6640,11 +8398,13 @@
     }
     /// <summary>Gets whether the "dummy10" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy10 {
       get { return (_hasBits0 & 512) != 0; }
     }
     /// <summary>Clears the value of the "dummy10" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy10() {
       _hasBits0 &= ~512;
     }
@@ -6655,6 +8415,7 @@
 
     private int dummy11_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy11 {
       get { if ((_hasBits0 & 1024) != 0) { return dummy11_; } else { return Dummy11DefaultValue; } }
       set {
@@ -6664,11 +8425,13 @@
     }
     /// <summary>Gets whether the "dummy11" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy11 {
       get { return (_hasBits0 & 1024) != 0; }
     }
     /// <summary>Clears the value of the "dummy11" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy11() {
       _hasBits0 &= ~1024;
     }
@@ -6679,6 +8442,7 @@
 
     private int dummy12_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy12 {
       get { if ((_hasBits0 & 2048) != 0) { return dummy12_; } else { return Dummy12DefaultValue; } }
       set {
@@ -6688,11 +8452,13 @@
     }
     /// <summary>Gets whether the "dummy12" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy12 {
       get { return (_hasBits0 & 2048) != 0; }
     }
     /// <summary>Clears the value of the "dummy12" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy12() {
       _hasBits0 &= ~2048;
     }
@@ -6703,6 +8469,7 @@
 
     private int dummy13_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy13 {
       get { if ((_hasBits0 & 4096) != 0) { return dummy13_; } else { return Dummy13DefaultValue; } }
       set {
@@ -6712,11 +8479,13 @@
     }
     /// <summary>Gets whether the "dummy13" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy13 {
       get { return (_hasBits0 & 4096) != 0; }
     }
     /// <summary>Clears the value of the "dummy13" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy13() {
       _hasBits0 &= ~4096;
     }
@@ -6727,6 +8496,7 @@
 
     private int dummy14_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy14 {
       get { if ((_hasBits0 & 8192) != 0) { return dummy14_; } else { return Dummy14DefaultValue; } }
       set {
@@ -6736,11 +8506,13 @@
     }
     /// <summary>Gets whether the "dummy14" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy14 {
       get { return (_hasBits0 & 8192) != 0; }
     }
     /// <summary>Clears the value of the "dummy14" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy14() {
       _hasBits0 &= ~8192;
     }
@@ -6751,6 +8523,7 @@
 
     private int dummy15_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy15 {
       get { if ((_hasBits0 & 16384) != 0) { return dummy15_; } else { return Dummy15DefaultValue; } }
       set {
@@ -6760,11 +8533,13 @@
     }
     /// <summary>Gets whether the "dummy15" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy15 {
       get { return (_hasBits0 & 16384) != 0; }
     }
     /// <summary>Clears the value of the "dummy15" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy15() {
       _hasBits0 &= ~16384;
     }
@@ -6775,6 +8550,7 @@
 
     private int dummy16_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy16 {
       get { if ((_hasBits0 & 32768) != 0) { return dummy16_; } else { return Dummy16DefaultValue; } }
       set {
@@ -6784,11 +8560,13 @@
     }
     /// <summary>Gets whether the "dummy16" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy16 {
       get { return (_hasBits0 & 32768) != 0; }
     }
     /// <summary>Clears the value of the "dummy16" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy16() {
       _hasBits0 &= ~32768;
     }
@@ -6799,6 +8577,7 @@
 
     private int dummy17_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy17 {
       get { if ((_hasBits0 & 65536) != 0) { return dummy17_; } else { return Dummy17DefaultValue; } }
       set {
@@ -6808,11 +8587,13 @@
     }
     /// <summary>Gets whether the "dummy17" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy17 {
       get { return (_hasBits0 & 65536) != 0; }
     }
     /// <summary>Clears the value of the "dummy17" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy17() {
       _hasBits0 &= ~65536;
     }
@@ -6823,6 +8604,7 @@
 
     private int dummy18_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy18 {
       get { if ((_hasBits0 & 131072) != 0) { return dummy18_; } else { return Dummy18DefaultValue; } }
       set {
@@ -6832,11 +8614,13 @@
     }
     /// <summary>Gets whether the "dummy18" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy18 {
       get { return (_hasBits0 & 131072) != 0; }
     }
     /// <summary>Clears the value of the "dummy18" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy18() {
       _hasBits0 &= ~131072;
     }
@@ -6847,6 +8631,7 @@
 
     private int dummy19_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy19 {
       get { if ((_hasBits0 & 262144) != 0) { return dummy19_; } else { return Dummy19DefaultValue; } }
       set {
@@ -6856,11 +8641,13 @@
     }
     /// <summary>Gets whether the "dummy19" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy19 {
       get { return (_hasBits0 & 262144) != 0; }
     }
     /// <summary>Clears the value of the "dummy19" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy19() {
       _hasBits0 &= ~262144;
     }
@@ -6871,6 +8658,7 @@
 
     private int dummy20_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy20 {
       get { if ((_hasBits0 & 524288) != 0) { return dummy20_; } else { return Dummy20DefaultValue; } }
       set {
@@ -6880,11 +8668,13 @@
     }
     /// <summary>Gets whether the "dummy20" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy20 {
       get { return (_hasBits0 & 524288) != 0; }
     }
     /// <summary>Clears the value of the "dummy20" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy20() {
       _hasBits0 &= ~524288;
     }
@@ -6895,6 +8685,7 @@
 
     private int dummy21_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy21 {
       get { if ((_hasBits0 & 1048576) != 0) { return dummy21_; } else { return Dummy21DefaultValue; } }
       set {
@@ -6904,11 +8695,13 @@
     }
     /// <summary>Gets whether the "dummy21" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy21 {
       get { return (_hasBits0 & 1048576) != 0; }
     }
     /// <summary>Clears the value of the "dummy21" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy21() {
       _hasBits0 &= ~1048576;
     }
@@ -6919,6 +8712,7 @@
 
     private int dummy22_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy22 {
       get { if ((_hasBits0 & 2097152) != 0) { return dummy22_; } else { return Dummy22DefaultValue; } }
       set {
@@ -6928,11 +8722,13 @@
     }
     /// <summary>Gets whether the "dummy22" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy22 {
       get { return (_hasBits0 & 2097152) != 0; }
     }
     /// <summary>Clears the value of the "dummy22" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy22() {
       _hasBits0 &= ~2097152;
     }
@@ -6943,6 +8739,7 @@
 
     private int dummy23_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy23 {
       get { if ((_hasBits0 & 4194304) != 0) { return dummy23_; } else { return Dummy23DefaultValue; } }
       set {
@@ -6952,11 +8749,13 @@
     }
     /// <summary>Gets whether the "dummy23" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy23 {
       get { return (_hasBits0 & 4194304) != 0; }
     }
     /// <summary>Clears the value of the "dummy23" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy23() {
       _hasBits0 &= ~4194304;
     }
@@ -6967,6 +8766,7 @@
 
     private int dummy24_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy24 {
       get { if ((_hasBits0 & 8388608) != 0) { return dummy24_; } else { return Dummy24DefaultValue; } }
       set {
@@ -6976,11 +8776,13 @@
     }
     /// <summary>Gets whether the "dummy24" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy24 {
       get { return (_hasBits0 & 8388608) != 0; }
     }
     /// <summary>Clears the value of the "dummy24" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy24() {
       _hasBits0 &= ~8388608;
     }
@@ -6991,6 +8793,7 @@
 
     private int dummy25_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy25 {
       get { if ((_hasBits0 & 16777216) != 0) { return dummy25_; } else { return Dummy25DefaultValue; } }
       set {
@@ -7000,11 +8803,13 @@
     }
     /// <summary>Gets whether the "dummy25" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy25 {
       get { return (_hasBits0 & 16777216) != 0; }
     }
     /// <summary>Clears the value of the "dummy25" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy25() {
       _hasBits0 &= ~16777216;
     }
@@ -7015,6 +8820,7 @@
 
     private int dummy26_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy26 {
       get { if ((_hasBits0 & 33554432) != 0) { return dummy26_; } else { return Dummy26DefaultValue; } }
       set {
@@ -7024,11 +8830,13 @@
     }
     /// <summary>Gets whether the "dummy26" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy26 {
       get { return (_hasBits0 & 33554432) != 0; }
     }
     /// <summary>Clears the value of the "dummy26" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy26() {
       _hasBits0 &= ~33554432;
     }
@@ -7039,6 +8847,7 @@
 
     private int dummy27_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy27 {
       get { if ((_hasBits0 & 67108864) != 0) { return dummy27_; } else { return Dummy27DefaultValue; } }
       set {
@@ -7048,11 +8857,13 @@
     }
     /// <summary>Gets whether the "dummy27" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy27 {
       get { return (_hasBits0 & 67108864) != 0; }
     }
     /// <summary>Clears the value of the "dummy27" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy27() {
       _hasBits0 &= ~67108864;
     }
@@ -7063,6 +8874,7 @@
 
     private int dummy28_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy28 {
       get { if ((_hasBits0 & 134217728) != 0) { return dummy28_; } else { return Dummy28DefaultValue; } }
       set {
@@ -7072,11 +8884,13 @@
     }
     /// <summary>Gets whether the "dummy28" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy28 {
       get { return (_hasBits0 & 134217728) != 0; }
     }
     /// <summary>Clears the value of the "dummy28" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy28() {
       _hasBits0 &= ~134217728;
     }
@@ -7087,6 +8901,7 @@
 
     private int dummy29_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy29 {
       get { if ((_hasBits0 & 268435456) != 0) { return dummy29_; } else { return Dummy29DefaultValue; } }
       set {
@@ -7096,11 +8911,13 @@
     }
     /// <summary>Gets whether the "dummy29" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy29 {
       get { return (_hasBits0 & 268435456) != 0; }
     }
     /// <summary>Clears the value of the "dummy29" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy29() {
       _hasBits0 &= ~268435456;
     }
@@ -7111,6 +8928,7 @@
 
     private int dummy30_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy30 {
       get { if ((_hasBits0 & 536870912) != 0) { return dummy30_; } else { return Dummy30DefaultValue; } }
       set {
@@ -7120,11 +8938,13 @@
     }
     /// <summary>Gets whether the "dummy30" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy30 {
       get { return (_hasBits0 & 536870912) != 0; }
     }
     /// <summary>Clears the value of the "dummy30" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy30() {
       _hasBits0 &= ~536870912;
     }
@@ -7135,6 +8955,7 @@
 
     private int dummy31_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy31 {
       get { if ((_hasBits0 & 1073741824) != 0) { return dummy31_; } else { return Dummy31DefaultValue; } }
       set {
@@ -7144,11 +8965,13 @@
     }
     /// <summary>Gets whether the "dummy31" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy31 {
       get { return (_hasBits0 & 1073741824) != 0; }
     }
     /// <summary>Clears the value of the "dummy31" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy31() {
       _hasBits0 &= ~1073741824;
     }
@@ -7159,6 +8982,7 @@
 
     private int dummy32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy32 {
       get { if ((_hasBits0 & -2147483648) != 0) { return dummy32_; } else { return Dummy32DefaultValue; } }
       set {
@@ -7168,11 +8992,13 @@
     }
     /// <summary>Gets whether the "dummy32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy32 {
       get { return (_hasBits0 & -2147483648) != 0; }
     }
     /// <summary>Clears the value of the "dummy32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy32() {
       _hasBits0 &= ~-2147483648;
     }
@@ -7183,6 +9009,7 @@
 
     private int c_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int C {
       get { if ((_hasBits1 & 1) != 0) { return c_; } else { return CDefaultValue; } }
       set {
@@ -7192,21 +9019,25 @@
     }
     /// <summary>Gets whether the "c" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasC {
       get { return (_hasBits1 & 1) != 0; }
     }
     /// <summary>Clears the value of the "c" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearC() {
       _hasBits1 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRequired);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRequired other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7251,6 +9082,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasA) hash ^= A.GetHashCode();
@@ -7293,12 +9125,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasA) {
         output.WriteRawTag(8);
         output.WriteInt32(A);
@@ -7434,9 +9271,153 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasA) {
+        output.WriteRawTag(8);
+        output.WriteInt32(A);
+      }
+      if (HasDummy2) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Dummy2);
+      }
+      if (HasB) {
+        output.WriteRawTag(24);
+        output.WriteInt32(B);
+      }
+      if (HasDummy4) {
+        output.WriteRawTag(32);
+        output.WriteInt32(Dummy4);
+      }
+      if (HasDummy5) {
+        output.WriteRawTag(40);
+        output.WriteInt32(Dummy5);
+      }
+      if (HasDummy6) {
+        output.WriteRawTag(48);
+        output.WriteInt32(Dummy6);
+      }
+      if (HasDummy7) {
+        output.WriteRawTag(56);
+        output.WriteInt32(Dummy7);
+      }
+      if (HasDummy8) {
+        output.WriteRawTag(64);
+        output.WriteInt32(Dummy8);
+      }
+      if (HasDummy9) {
+        output.WriteRawTag(72);
+        output.WriteInt32(Dummy9);
+      }
+      if (HasDummy10) {
+        output.WriteRawTag(80);
+        output.WriteInt32(Dummy10);
+      }
+      if (HasDummy11) {
+        output.WriteRawTag(88);
+        output.WriteInt32(Dummy11);
+      }
+      if (HasDummy12) {
+        output.WriteRawTag(96);
+        output.WriteInt32(Dummy12);
+      }
+      if (HasDummy13) {
+        output.WriteRawTag(104);
+        output.WriteInt32(Dummy13);
+      }
+      if (HasDummy14) {
+        output.WriteRawTag(112);
+        output.WriteInt32(Dummy14);
+      }
+      if (HasDummy15) {
+        output.WriteRawTag(120);
+        output.WriteInt32(Dummy15);
+      }
+      if (HasDummy16) {
+        output.WriteRawTag(128, 1);
+        output.WriteInt32(Dummy16);
+      }
+      if (HasDummy17) {
+        output.WriteRawTag(136, 1);
+        output.WriteInt32(Dummy17);
+      }
+      if (HasDummy18) {
+        output.WriteRawTag(144, 1);
+        output.WriteInt32(Dummy18);
+      }
+      if (HasDummy19) {
+        output.WriteRawTag(152, 1);
+        output.WriteInt32(Dummy19);
+      }
+      if (HasDummy20) {
+        output.WriteRawTag(160, 1);
+        output.WriteInt32(Dummy20);
+      }
+      if (HasDummy21) {
+        output.WriteRawTag(168, 1);
+        output.WriteInt32(Dummy21);
+      }
+      if (HasDummy22) {
+        output.WriteRawTag(176, 1);
+        output.WriteInt32(Dummy22);
+      }
+      if (HasDummy23) {
+        output.WriteRawTag(184, 1);
+        output.WriteInt32(Dummy23);
+      }
+      if (HasDummy24) {
+        output.WriteRawTag(192, 1);
+        output.WriteInt32(Dummy24);
+      }
+      if (HasDummy25) {
+        output.WriteRawTag(200, 1);
+        output.WriteInt32(Dummy25);
+      }
+      if (HasDummy26) {
+        output.WriteRawTag(208, 1);
+        output.WriteInt32(Dummy26);
+      }
+      if (HasDummy27) {
+        output.WriteRawTag(216, 1);
+        output.WriteInt32(Dummy27);
+      }
+      if (HasDummy28) {
+        output.WriteRawTag(224, 1);
+        output.WriteInt32(Dummy28);
+      }
+      if (HasDummy29) {
+        output.WriteRawTag(232, 1);
+        output.WriteInt32(Dummy29);
+      }
+      if (HasDummy30) {
+        output.WriteRawTag(240, 1);
+        output.WriteInt32(Dummy30);
+      }
+      if (HasDummy31) {
+        output.WriteRawTag(248, 1);
+        output.WriteInt32(Dummy31);
+      }
+      if (HasDummy32) {
+        output.WriteRawTag(128, 2);
+        output.WriteInt32(Dummy32);
+      }
+      if (HasC) {
+        output.WriteRawTag(136, 2);
+        output.WriteInt32(C);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasA) {
@@ -7545,6 +9526,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRequired other) {
       if (other == null) {
         return;
@@ -7652,7 +9634,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7793,11 +9779,160 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            A = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Dummy2 = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            B = input.ReadInt32();
+            break;
+          }
+          case 32: {
+            Dummy4 = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            Dummy5 = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            Dummy6 = input.ReadInt32();
+            break;
+          }
+          case 56: {
+            Dummy7 = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            Dummy8 = input.ReadInt32();
+            break;
+          }
+          case 72: {
+            Dummy9 = input.ReadInt32();
+            break;
+          }
+          case 80: {
+            Dummy10 = input.ReadInt32();
+            break;
+          }
+          case 88: {
+            Dummy11 = input.ReadInt32();
+            break;
+          }
+          case 96: {
+            Dummy12 = input.ReadInt32();
+            break;
+          }
+          case 104: {
+            Dummy13 = input.ReadInt32();
+            break;
+          }
+          case 112: {
+            Dummy14 = input.ReadInt32();
+            break;
+          }
+          case 120: {
+            Dummy15 = input.ReadInt32();
+            break;
+          }
+          case 128: {
+            Dummy16 = input.ReadInt32();
+            break;
+          }
+          case 136: {
+            Dummy17 = input.ReadInt32();
+            break;
+          }
+          case 144: {
+            Dummy18 = input.ReadInt32();
+            break;
+          }
+          case 152: {
+            Dummy19 = input.ReadInt32();
+            break;
+          }
+          case 160: {
+            Dummy20 = input.ReadInt32();
+            break;
+          }
+          case 168: {
+            Dummy21 = input.ReadInt32();
+            break;
+          }
+          case 176: {
+            Dummy22 = input.ReadInt32();
+            break;
+          }
+          case 184: {
+            Dummy23 = input.ReadInt32();
+            break;
+          }
+          case 192: {
+            Dummy24 = input.ReadInt32();
+            break;
+          }
+          case 200: {
+            Dummy25 = input.ReadInt32();
+            break;
+          }
+          case 208: {
+            Dummy26 = input.ReadInt32();
+            break;
+          }
+          case 216: {
+            Dummy27 = input.ReadInt32();
+            break;
+          }
+          case 224: {
+            Dummy28 = input.ReadInt32();
+            break;
+          }
+          case 232: {
+            Dummy29 = input.ReadInt32();
+            break;
+          }
+          case 240: {
+            Dummy30 = input.ReadInt32();
+            break;
+          }
+          case 248: {
+            Dummy31 = input.ReadInt32();
+            break;
+          }
+          case 256: {
+            Dummy32 = input.ReadInt32();
+            break;
+          }
+          case 264: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Extensions
     /// <summary>Container for extensions for other messages declared in the TestRequired message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Extensions {
       public static readonly pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestAllExtensions, global::Google.Protobuf.TestProtos.Proto2.TestRequired> Single =
         new pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestAllExtensions, global::Google.Protobuf.TestProtos.Proto2.TestRequired>(1000, pb::FieldCodec.ForMessage(8002, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser));
@@ -7808,24 +9943,32 @@
 
   }
 
-  public sealed partial class TestRequiredForeign : pb::IMessage<TestRequiredForeign> {
+  public sealed partial class TestRequiredForeign : pb::IMessage<TestRequiredForeign>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRequiredForeign> _parser = new pb::MessageParser<TestRequiredForeign>(() => new TestRequiredForeign());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRequiredForeign> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[13]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredForeign() {
       OnConstruction();
     }
@@ -7833,15 +9976,17 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredForeign(TestRequiredForeign other) : this() {
       _hasBits0 = other._hasBits0;
-      optionalMessage_ = other.HasOptionalMessage ? other.optionalMessage_.Clone() : null;
+      optionalMessage_ = other.optionalMessage_ != null ? other.optionalMessage_.Clone() : null;
       repeatedMessage_ = other.repeatedMessage_.Clone();
       dummy_ = other.dummy_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredForeign Clone() {
       return new TestRequiredForeign(this);
     }
@@ -7850,22 +9995,13 @@
     public const int OptionalMessageFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestRequired optionalMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestRequired OptionalMessage {
       get { return optionalMessage_; }
       set {
         optionalMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalMessage {
-      get { return optionalMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalMessage() {
-      optionalMessage_ = null;
-    }
 
     /// <summary>Field number for the "repeated_message" field.</summary>
     public const int RepeatedMessageFieldNumber = 2;
@@ -7873,6 +10009,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestRequired> repeatedMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestRequired>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestRequired> RepeatedMessage {
       get { return repeatedMessage_; }
     }
@@ -7883,6 +10020,7 @@
 
     private int dummy_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Dummy {
       get { if ((_hasBits0 & 1) != 0) { return dummy_; } else { return DummyDefaultValue; } }
       set {
@@ -7892,21 +10030,25 @@
     }
     /// <summary>Gets whether the "dummy" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDummy {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "dummy" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDummy() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRequiredForeign);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRequiredForeign other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7921,9 +10063,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasOptionalMessage) hash ^= OptionalMessage.GetHashCode();
+      if (optionalMessage_ != null) hash ^= OptionalMessage.GetHashCode();
       hash ^= repeatedMessage_.GetHashCode();
       if (HasDummy) hash ^= Dummy.GetHashCode();
       if (_unknownFields != null) {
@@ -7933,13 +10076,18 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasOptionalMessage) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (optionalMessage_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(OptionalMessage);
       }
@@ -7951,12 +10099,33 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (optionalMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(OptionalMessage);
+      }
+      repeatedMessage_.WriteTo(ref output, _repeated_repeatedMessage_codec);
+      if (HasDummy) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Dummy);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasOptionalMessage) {
+      if (optionalMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalMessage);
       }
       size += repeatedMessage_.CalculateSize(_repeated_repeatedMessage_codec);
@@ -7970,12 +10139,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRequiredForeign other) {
       if (other == null) {
         return;
       }
-      if (other.HasOptionalMessage) {
-        if (!HasOptionalMessage) {
+      if (other.optionalMessage_ != null) {
+        if (optionalMessage_ == null) {
           OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
         }
         OptionalMessage.MergeFrom(other.OptionalMessage);
@@ -7988,7 +10158,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7996,7 +10170,7 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasOptionalMessage) {
+            if (optionalMessage_ == null) {
               OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
             }
             input.ReadMessage(OptionalMessage);
@@ -8012,27 +10186,66 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (optionalMessage_ == null) {
+              OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
+            }
+            input.ReadMessage(OptionalMessage);
+            break;
+          }
+          case 18: {
+            repeatedMessage_.AddEntriesFrom(ref input, _repeated_repeatedMessage_codec);
+            break;
+          }
+          case 24: {
+            Dummy = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestRequiredMessage : pb::IMessage<TestRequiredMessage> {
+  public sealed partial class TestRequiredMessage : pb::IMessage<TestRequiredMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRequiredMessage> _parser = new pb::MessageParser<TestRequiredMessage>(() => new TestRequiredMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRequiredMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[14]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredMessage() {
       OnConstruction();
     }
@@ -8040,14 +10253,16 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredMessage(TestRequiredMessage other) : this() {
-      optionalMessage_ = other.HasOptionalMessage ? other.optionalMessage_.Clone() : null;
+      optionalMessage_ = other.optionalMessage_ != null ? other.optionalMessage_.Clone() : null;
       repeatedMessage_ = other.repeatedMessage_.Clone();
-      requiredMessage_ = other.HasRequiredMessage ? other.requiredMessage_.Clone() : null;
+      requiredMessage_ = other.requiredMessage_ != null ? other.requiredMessage_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredMessage Clone() {
       return new TestRequiredMessage(this);
     }
@@ -8056,22 +10271,13 @@
     public const int OptionalMessageFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestRequired optionalMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestRequired OptionalMessage {
       get { return optionalMessage_; }
       set {
         optionalMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalMessage {
-      get { return optionalMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalMessage() {
-      optionalMessage_ = null;
-    }
 
     /// <summary>Field number for the "repeated_message" field.</summary>
     public const int RepeatedMessageFieldNumber = 2;
@@ -8079,6 +10285,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestRequired> repeatedMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestRequired>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestRequired> RepeatedMessage {
       get { return repeatedMessage_; }
     }
@@ -8087,29 +10294,22 @@
     public const int RequiredMessageFieldNumber = 3;
     private global::Google.Protobuf.TestProtos.Proto2.TestRequired requiredMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestRequired RequiredMessage {
       get { return requiredMessage_; }
       set {
         requiredMessage_ = value;
       }
     }
-    /// <summary>Gets whether the required_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasRequiredMessage {
-      get { return requiredMessage_ != null; }
-    }
-    /// <summary>Clears the value of the required_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearRequiredMessage() {
-      requiredMessage_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRequiredMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRequiredMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -8124,11 +10324,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasOptionalMessage) hash ^= OptionalMessage.GetHashCode();
+      if (optionalMessage_ != null) hash ^= OptionalMessage.GetHashCode();
       hash ^= repeatedMessage_.GetHashCode();
-      if (HasRequiredMessage) hash ^= RequiredMessage.GetHashCode();
+      if (requiredMessage_ != null) hash ^= RequiredMessage.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -8136,34 +10337,60 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasOptionalMessage) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (optionalMessage_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(OptionalMessage);
       }
       repeatedMessage_.WriteTo(output, _repeated_repeatedMessage_codec);
-      if (HasRequiredMessage) {
+      if (requiredMessage_ != null) {
         output.WriteRawTag(26);
         output.WriteMessage(RequiredMessage);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (optionalMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(OptionalMessage);
+      }
+      repeatedMessage_.WriteTo(ref output, _repeated_repeatedMessage_codec);
+      if (requiredMessage_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(RequiredMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasOptionalMessage) {
+      if (optionalMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalMessage);
       }
       size += repeatedMessage_.CalculateSize(_repeated_repeatedMessage_codec);
-      if (HasRequiredMessage) {
+      if (requiredMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(RequiredMessage);
       }
       if (_unknownFields != null) {
@@ -8173,19 +10400,20 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRequiredMessage other) {
       if (other == null) {
         return;
       }
-      if (other.HasOptionalMessage) {
-        if (!HasOptionalMessage) {
+      if (other.optionalMessage_ != null) {
+        if (optionalMessage_ == null) {
           OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
         }
         OptionalMessage.MergeFrom(other.OptionalMessage);
       }
       repeatedMessage_.Add(other.repeatedMessage_);
-      if (other.HasRequiredMessage) {
-        if (!HasRequiredMessage) {
+      if (other.requiredMessage_ != null) {
+        if (requiredMessage_ == null) {
           RequiredMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
         }
         RequiredMessage.MergeFrom(other.RequiredMessage);
@@ -8194,7 +10422,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -8202,7 +10434,7 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasOptionalMessage) {
+            if (optionalMessage_ == null) {
               OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
             }
             input.ReadMessage(OptionalMessage);
@@ -8213,7 +10445,40 @@
             break;
           }
           case 26: {
-            if (!HasRequiredMessage) {
+            if (requiredMessage_ == null) {
+              RequiredMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
+            }
+            input.ReadMessage(RequiredMessage);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (optionalMessage_ == null) {
+              OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
+            }
+            input.ReadMessage(OptionalMessage);
+            break;
+          }
+          case 18: {
+            repeatedMessage_.AddEntriesFrom(ref input, _repeated_repeatedMessage_codec);
+            break;
+          }
+          case 26: {
+            if (requiredMessage_ == null) {
               RequiredMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired();
             }
             input.ReadMessage(RequiredMessage);
@@ -8222,29 +10487,38 @@
         }
       }
     }
+    #endif
 
   }
 
   /// <summary>
   /// Test that we can use NestedMessage from outside TestAllTypes.
   /// </summary>
-  public sealed partial class TestForeignNested : pb::IMessage<TestForeignNested> {
+  public sealed partial class TestForeignNested : pb::IMessage<TestForeignNested>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestForeignNested> _parser = new pb::MessageParser<TestForeignNested>(() => new TestForeignNested());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestForeignNested> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[15]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestForeignNested() {
       OnConstruction();
     }
@@ -8252,12 +10526,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestForeignNested(TestForeignNested other) : this() {
-      foreignNested_ = other.HasForeignNested ? other.foreignNested_.Clone() : null;
+      foreignNested_ = other.foreignNested_ != null ? other.foreignNested_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestForeignNested Clone() {
       return new TestForeignNested(this);
     }
@@ -8266,29 +10542,22 @@
     public const int ForeignNestedFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage foreignNested_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage ForeignNested {
       get { return foreignNested_; }
       set {
         foreignNested_ = value;
       }
     }
-    /// <summary>Gets whether the foreign_nested field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasForeignNested {
-      get { return foreignNested_ != null; }
-    }
-    /// <summary>Clears the value of the foreign_nested field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearForeignNested() {
-      foreignNested_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestForeignNested);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestForeignNested other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -8301,9 +10570,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasForeignNested) hash ^= ForeignNested.GetHashCode();
+      if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -8311,25 +10581,46 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasForeignNested) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (foreignNested_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(ForeignNested);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (foreignNested_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(ForeignNested);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasForeignNested) {
+      if (foreignNested_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ForeignNested);
       }
       if (_unknownFields != null) {
@@ -8339,12 +10630,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestForeignNested other) {
       if (other == null) {
         return;
       }
-      if (other.HasForeignNested) {
-        if (!HasForeignNested) {
+      if (other.foreignNested_ != null) {
+        if (foreignNested_ == null) {
           ForeignNested = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
         }
         ForeignNested.MergeFrom(other.ForeignNested);
@@ -8353,7 +10645,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -8361,7 +10657,29 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasForeignNested) {
+            if (foreignNested_ == null) {
+              ForeignNested = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(ForeignNested);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (foreignNested_ == null) {
               ForeignNested = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage();
             }
             input.ReadMessage(ForeignNested);
@@ -8370,29 +10688,38 @@
         }
       }
     }
+    #endif
 
   }
 
   /// <summary>
   /// TestEmptyMessage is used to test unknown field support.
   /// </summary>
-  public sealed partial class TestEmptyMessage : pb::IMessage<TestEmptyMessage> {
+  public sealed partial class TestEmptyMessage : pb::IMessage<TestEmptyMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestEmptyMessage> _parser = new pb::MessageParser<TestEmptyMessage>(() => new TestEmptyMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestEmptyMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[16]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessage() {
       OnConstruction();
     }
@@ -8400,21 +10727,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessage(TestEmptyMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessage Clone() {
       return new TestEmptyMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestEmptyMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestEmptyMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -8426,6 +10757,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -8435,18 +10767,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -8456,6 +10805,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestEmptyMessage other) {
       if (other == null) {
         return;
@@ -8464,7 +10814,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -8473,33 +10827,57 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Like above, but declare all field numbers as potential extensions.  No
   /// actual extensions should ever be defined for this type.
   /// </summary>
-  public sealed partial class TestEmptyMessageWithExtensions : pb::IExtendableMessage<TestEmptyMessageWithExtensions> {
+  public sealed partial class TestEmptyMessageWithExtensions : pb::IExtendableMessage<TestEmptyMessageWithExtensions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestEmptyMessageWithExtensions> _parser = new pb::MessageParser<TestEmptyMessageWithExtensions>(() => new TestEmptyMessageWithExtensions());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestEmptyMessageWithExtensions> _extensions;
     private pb::ExtensionSet<TestEmptyMessageWithExtensions> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestEmptyMessageWithExtensions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[17]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessageWithExtensions() {
       OnConstruction();
     }
@@ -8507,22 +10885,26 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessageWithExtensions(TestEmptyMessageWithExtensions other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _extensions = pb::ExtensionSet.Clone(other._extensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessageWithExtensions Clone() {
       return new TestEmptyMessageWithExtensions(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestEmptyMessageWithExtensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestEmptyMessageWithExtensions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -8537,6 +10919,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_extensions != null) {
@@ -8549,21 +10932,41 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_extensions != null) {
         _extensions.WriteTo(output);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_extensions != null) {
@@ -8576,6 +10979,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestEmptyMessageWithExtensions other) {
       if (other == null) {
         return;
@@ -8585,7 +10989,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -8596,8 +11004,26 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestEmptyMessageWithExtensions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -8622,25 +11048,33 @@
 
   }
 
-  public sealed partial class TestMultipleExtensionRanges : pb::IExtendableMessage<TestMultipleExtensionRanges> {
+  public sealed partial class TestMultipleExtensionRanges : pb::IExtendableMessage<TestMultipleExtensionRanges>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMultipleExtensionRanges> _parser = new pb::MessageParser<TestMultipleExtensionRanges>(() => new TestMultipleExtensionRanges());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestMultipleExtensionRanges> _extensions;
     private pb::ExtensionSet<TestMultipleExtensionRanges> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMultipleExtensionRanges> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[18]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMultipleExtensionRanges() {
       OnConstruction();
     }
@@ -8648,22 +11082,26 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMultipleExtensionRanges(TestMultipleExtensionRanges other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _extensions = pb::ExtensionSet.Clone(other._extensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMultipleExtensionRanges Clone() {
       return new TestMultipleExtensionRanges(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMultipleExtensionRanges);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMultipleExtensionRanges other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -8678,6 +11116,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_extensions != null) {
@@ -8690,21 +11129,41 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_extensions != null) {
         _extensions.WriteTo(output);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_extensions != null) {
@@ -8717,6 +11176,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMultipleExtensionRanges other) {
       if (other == null) {
         return;
@@ -8726,7 +11186,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -8737,8 +11201,26 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestMultipleExtensionRanges, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -8766,24 +11248,32 @@
   /// <summary>
   /// Test that really large tag numbers don't break anything.
   /// </summary>
-  public sealed partial class TestReallyLargeTagNumber : pb::IMessage<TestReallyLargeTagNumber> {
+  public sealed partial class TestReallyLargeTagNumber : pb::IMessage<TestReallyLargeTagNumber>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestReallyLargeTagNumber> _parser = new pb::MessageParser<TestReallyLargeTagNumber>(() => new TestReallyLargeTagNumber());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestReallyLargeTagNumber> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[19]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReallyLargeTagNumber() {
       OnConstruction();
     }
@@ -8791,6 +11281,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() {
       _hasBits0 = other._hasBits0;
       a_ = other.a_;
@@ -8799,6 +11290,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReallyLargeTagNumber Clone() {
       return new TestReallyLargeTagNumber(this);
     }
@@ -8813,6 +11305,7 @@
     /// three bits to communicate wire type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int A {
       get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
       set {
@@ -8822,11 +11315,13 @@
     }
     /// <summary>Gets whether the "a" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasA {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "a" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearA() {
       _hasBits0 &= ~1;
     }
@@ -8837,6 +11332,7 @@
 
     private int bb_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Bb {
       get { if ((_hasBits0 & 2) != 0) { return bb_; } else { return BbDefaultValue; } }
       set {
@@ -8846,21 +11342,25 @@
     }
     /// <summary>Gets whether the "bb" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBb {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "bb" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBb() {
       _hasBits0 &= ~2;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestReallyLargeTagNumber);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestReallyLargeTagNumber other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -8874,6 +11374,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasA) hash ^= A.GetHashCode();
@@ -8885,12 +11386,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasA) {
         output.WriteRawTag(8);
         output.WriteInt32(A);
@@ -8902,9 +11408,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasA) {
+        output.WriteRawTag(8);
+        output.WriteInt32(A);
+      }
+      if (HasBb) {
+        output.WriteRawTag(248, 255, 255, 255, 7);
+        output.WriteInt32(Bb);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasA) {
@@ -8920,6 +11446,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestReallyLargeTagNumber other) {
       if (other == null) {
         return;
@@ -8934,7 +11461,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -8951,28 +11482,60 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            A = input.ReadInt32();
+            break;
+          }
+          case 2147483640: {
+            Bb = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestRecursiveMessage : pb::IMessage<TestRecursiveMessage> {
+  public sealed partial class TestRecursiveMessage : pb::IMessage<TestRecursiveMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRecursiveMessage> _parser = new pb::MessageParser<TestRecursiveMessage>(() => new TestRecursiveMessage());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRecursiveMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[20]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRecursiveMessage() {
       OnConstruction();
     }
@@ -8980,14 +11543,16 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRecursiveMessage(TestRecursiveMessage other) : this() {
       _hasBits0 = other._hasBits0;
-      a_ = other.HasA ? other.a_.Clone() : null;
+      a_ = other.a_ != null ? other.a_.Clone() : null;
       i_ = other.i_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRecursiveMessage Clone() {
       return new TestRecursiveMessage(this);
     }
@@ -8996,22 +11561,13 @@
     public const int AFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage a_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage A {
       get { return a_; }
       set {
         a_ = value;
       }
     }
-    /// <summary>Gets whether the a field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasA {
-      get { return a_ != null; }
-    }
-    /// <summary>Clears the value of the a field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearA() {
-      a_ = null;
-    }
 
     /// <summary>Field number for the "i" field.</summary>
     public const int IFieldNumber = 2;
@@ -9019,6 +11575,7 @@
 
     private int i_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int I {
       get { if ((_hasBits0 & 1) != 0) { return i_; } else { return IDefaultValue; } }
       set {
@@ -9028,21 +11585,25 @@
     }
     /// <summary>Gets whether the "i" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasI {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "i" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearI() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRecursiveMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRecursiveMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -9056,9 +11617,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasA) hash ^= A.GetHashCode();
+      if (a_ != null) hash ^= A.GetHashCode();
       if (HasI) hash ^= I.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -9067,13 +11629,18 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasA) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (a_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(A);
       }
@@ -9084,12 +11651,32 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (HasI) {
+        output.WriteRawTag(16);
+        output.WriteInt32(I);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasA) {
+      if (a_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(A);
       }
       if (HasI) {
@@ -9102,12 +11689,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRecursiveMessage other) {
       if (other == null) {
         return;
       }
-      if (other.HasA) {
-        if (!HasA) {
+      if (other.a_ != null) {
+        if (a_ == null) {
           A = new global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage();
         }
         A.MergeFrom(other.A);
@@ -9119,7 +11707,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -9127,7 +11719,33 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasA) {
+            if (a_ == null) {
+              A = new global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage();
+            }
+            input.ReadMessage(A);
+            break;
+          }
+          case 16: {
+            I = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (a_ == null) {
               A = new global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage();
             }
             input.ReadMessage(A);
@@ -9140,29 +11758,38 @@
         }
       }
     }
+    #endif
 
   }
 
   /// <summary>
   /// Test that mutual recursion works.
   /// </summary>
-  public sealed partial class TestMutualRecursionA : pb::IMessage<TestMutualRecursionA> {
+  public sealed partial class TestMutualRecursionA : pb::IMessage<TestMutualRecursionA>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMutualRecursionA> _parser = new pb::MessageParser<TestMutualRecursionA>(() => new TestMutualRecursionA());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMutualRecursionA> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[21]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionA() {
       OnConstruction();
     }
@@ -9170,13 +11797,15 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionA(TestMutualRecursionA other) : this() {
-      bb_ = other.HasBb ? other.bb_.Clone() : null;
+      bb_ = other.bb_ != null ? other.bb_.Clone() : null;
       subGroup_ = other.HasSubGroup ? other.subGroup_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionA Clone() {
       return new TestMutualRecursionA(this);
     }
@@ -9185,27 +11814,19 @@
     public const int BbFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB bb_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB Bb {
       get { return bb_; }
       set {
         bb_ = value;
       }
     }
-    /// <summary>Gets whether the bb field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasBb {
-      get { return bb_ != null; }
-    }
-    /// <summary>Clears the value of the bb field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearBb() {
-      bb_ = null;
-    }
 
     /// <summary>Field number for the "subgroup" field.</summary>
     public const int SubGroupFieldNumber = 2;
     private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup subGroup_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup SubGroup {
       get { return subGroup_; }
       set {
@@ -9214,21 +11835,25 @@
     }
     /// <summary>Gets whether the subgroup field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSubGroup {
       get { return subGroup_ != null; }
     }
     /// <summary>Clears the value of the subgroup field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSubGroup() {
       subGroup_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMutualRecursionA);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMutualRecursionA other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -9242,9 +11867,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasBb) hash ^= Bb.GetHashCode();
+      if (bb_ != null) hash ^= Bb.GetHashCode();
       if (HasSubGroup) hash ^= SubGroup.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -9253,13 +11879,18 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasBb) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (bb_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(Bb);
       }
@@ -9271,12 +11902,33 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (bb_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Bb);
+      }
+      if (HasSubGroup) {
+        output.WriteRawTag(19);
+        output.WriteGroup(SubGroup);
+        output.WriteRawTag(20);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasBb) {
+      if (bb_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb);
       }
       if (HasSubGroup) {
@@ -9289,12 +11941,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMutualRecursionA other) {
       if (other == null) {
         return;
       }
-      if (other.HasBb) {
-        if (!HasBb) {
+      if (other.bb_ != null) {
+        if (bb_ == null) {
           Bb = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB();
         }
         Bb.MergeFrom(other.Bb);
@@ -9309,7 +11962,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -9317,7 +11974,36 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasBb) {
+            if (bb_ == null) {
+              Bb = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB();
+            }
+            input.ReadMessage(Bb);
+            break;
+          }
+          case 19: {
+            if (!HasSubGroup) {
+              SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup();
+            }
+            input.ReadGroup(SubGroup);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (bb_ == null) {
               Bb = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB();
             }
             input.ReadMessage(Bb);
@@ -9333,28 +12019,38 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestMutualRecursionA message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class SubMessage : pb::IMessage<SubMessage> {
+      public sealed partial class SubMessage : pb::IMessage<SubMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<SubMessage> _parser = new pb::MessageParser<SubMessage>(() => new SubMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<SubMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubMessage() {
           OnConstruction();
         }
@@ -9362,12 +12058,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubMessage(SubMessage other) : this() {
-          b_ = other.HasB ? other.b_.Clone() : null;
+          b_ = other.b_ != null ? other.b_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubMessage Clone() {
           return new SubMessage(this);
         }
@@ -9376,29 +12074,22 @@
         public const int BFieldNumber = 1;
         private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB b_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB B {
           get { return b_; }
           set {
             b_ = value;
           }
         }
-        /// <summary>Gets whether the b field is set</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public bool HasB {
-          get { return b_ != null; }
-        }
-        /// <summary>Clears the value of the b field</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public void ClearB() {
-          b_ = null;
-        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as SubMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(SubMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -9411,9 +12102,10 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
-          if (HasB) hash ^= B.GetHashCode();
+          if (b_ != null) hash ^= B.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -9421,25 +12113,46 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (HasB) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
+          if (b_ != null) {
             output.WriteRawTag(10);
             output.WriteMessage(B);
           }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (b_ != null) {
+            output.WriteRawTag(10);
+            output.WriteMessage(B);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
-          if (HasB) {
+          if (b_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(B);
           }
           if (_unknownFields != null) {
@@ -9449,12 +12162,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(SubMessage other) {
           if (other == null) {
             return;
           }
-          if (other.HasB) {
-            if (!HasB) {
+          if (other.b_ != null) {
+            if (b_ == null) {
               B = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB();
             }
             B.MergeFrom(other.B);
@@ -9463,7 +12177,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -9471,7 +12189,29 @@
                 _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
               case 10: {
-                if (!HasB) {
+                if (b_ == null) {
+                  B = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB();
+                }
+                input.ReadMessage(B);
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                if (b_ == null) {
                   B = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB();
                 }
                 input.ReadMessage(B);
@@ -9480,26 +12220,35 @@
             }
           }
         }
+        #endif
 
       }
 
-      public sealed partial class SubGroup : pb::IMessage<SubGroup> {
+      public sealed partial class SubGroup : pb::IMessage<SubGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<SubGroup> _parser = new pb::MessageParser<SubGroup>(() => new SubGroup());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<SubGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Descriptor.NestedTypes[1]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubGroup() {
           OnConstruction();
         }
@@ -9507,13 +12256,15 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubGroup(SubGroup other) : this() {
-          subMessage_ = other.HasSubMessage ? other.subMessage_.Clone() : null;
-          notInThisScc_ = other.HasNotInThisScc ? other.notInThisScc_.Clone() : null;
+          subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null;
+          notInThisScc_ = other.notInThisScc_ != null ? other.notInThisScc_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubGroup Clone() {
           return new SubGroup(this);
         }
@@ -9525,50 +12276,34 @@
         /// Needed because of bug in javatest
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage SubMessage {
           get { return subMessage_; }
           set {
             subMessage_ = value;
           }
         }
-        /// <summary>Gets whether the sub_message field is set</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public bool HasSubMessage {
-          get { return subMessage_ != null; }
-        }
-        /// <summary>Clears the value of the sub_message field</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public void ClearSubMessage() {
-          subMessage_ = null;
-        }
 
         /// <summary>Field number for the "not_in_this_scc" field.</summary>
         public const int NotInThisSccFieldNumber = 4;
         private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes notInThisScc_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes NotInThisScc {
           get { return notInThisScc_; }
           set {
             notInThisScc_ = value;
           }
         }
-        /// <summary>Gets whether the not_in_this_scc field is set</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public bool HasNotInThisScc {
-          get { return notInThisScc_ != null; }
-        }
-        /// <summary>Clears the value of the not_in_this_scc field</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public void ClearNotInThisScc() {
-          notInThisScc_ = null;
-        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as SubGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(SubGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -9582,10 +12317,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
-          if (HasSubMessage) hash ^= SubMessage.GetHashCode();
-          if (HasNotInThisScc) hash ^= NotInThisScc.GetHashCode();
+          if (subMessage_ != null) hash ^= SubMessage.GetHashCode();
+          if (notInThisScc_ != null) hash ^= NotInThisScc.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -9593,32 +12329,57 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (HasSubMessage) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
+          if (subMessage_ != null) {
             output.WriteRawTag(26);
             output.WriteMessage(SubMessage);
           }
-          if (HasNotInThisScc) {
+          if (notInThisScc_ != null) {
             output.WriteRawTag(34);
             output.WriteMessage(NotInThisScc);
           }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (subMessage_ != null) {
+            output.WriteRawTag(26);
+            output.WriteMessage(SubMessage);
+          }
+          if (notInThisScc_ != null) {
+            output.WriteRawTag(34);
+            output.WriteMessage(NotInThisScc);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
-          if (HasSubMessage) {
+          if (subMessage_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage);
           }
-          if (HasNotInThisScc) {
+          if (notInThisScc_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(NotInThisScc);
           }
           if (_unknownFields != null) {
@@ -9628,18 +12389,19 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(SubGroup other) {
           if (other == null) {
             return;
           }
-          if (other.HasSubMessage) {
-            if (!HasSubMessage) {
+          if (other.subMessage_ != null) {
+            if (subMessage_ == null) {
               SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage();
             }
             SubMessage.MergeFrom(other.SubMessage);
           }
-          if (other.HasNotInThisScc) {
-            if (!HasNotInThisScc) {
+          if (other.notInThisScc_ != null) {
+            if (notInThisScc_ == null) {
               NotInThisScc = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             NotInThisScc.MergeFrom(other.NotInThisScc);
@@ -9648,7 +12410,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -9658,14 +12424,45 @@
                 _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
               case 26: {
-                if (!HasSubMessage) {
+                if (subMessage_ == null) {
                   SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage();
                 }
                 input.ReadMessage(SubMessage);
                 break;
               }
               case 34: {
-                if (!HasNotInThisScc) {
+                if (notInThisScc_ == null) {
+                  NotInThisScc = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+                }
+                input.ReadMessage(NotInThisScc);
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 20:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 26: {
+                if (subMessage_ == null) {
+                  SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage();
+                }
+                input.ReadMessage(SubMessage);
+                break;
+              }
+              case 34: {
+                if (notInThisScc_ == null) {
                   NotInThisScc = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
                 }
                 input.ReadMessage(NotInThisScc);
@@ -9674,6 +12471,7 @@
             }
           }
         }
+        #endif
 
       }
 
@@ -9682,24 +12480,32 @@
 
   }
 
-  public sealed partial class TestMutualRecursionB : pb::IMessage<TestMutualRecursionB> {
+  public sealed partial class TestMutualRecursionB : pb::IMessage<TestMutualRecursionB>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMutualRecursionB> _parser = new pb::MessageParser<TestMutualRecursionB>(() => new TestMutualRecursionB());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMutualRecursionB> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[22]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionB() {
       OnConstruction();
     }
@@ -9707,14 +12513,16 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionB(TestMutualRecursionB other) : this() {
       _hasBits0 = other._hasBits0;
-      a_ = other.HasA ? other.a_.Clone() : null;
+      a_ = other.a_ != null ? other.a_.Clone() : null;
       optionalInt32_ = other.optionalInt32_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionB Clone() {
       return new TestMutualRecursionB(this);
     }
@@ -9723,22 +12531,13 @@
     public const int AFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA a_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA A {
       get { return a_; }
       set {
         a_ = value;
       }
     }
-    /// <summary>Gets whether the a field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasA {
-      get { return a_ != null; }
-    }
-    /// <summary>Clears the value of the a field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearA() {
-      a_ = null;
-    }
 
     /// <summary>Field number for the "optional_int32" field.</summary>
     public const int OptionalInt32FieldNumber = 2;
@@ -9746,6 +12545,7 @@
 
     private int optionalInt32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalInt32 {
       get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } }
       set {
@@ -9755,21 +12555,25 @@
     }
     /// <summary>Gets whether the "optional_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalInt32 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "optional_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalInt32() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMutualRecursionB);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMutualRecursionB other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -9783,9 +12587,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasA) hash ^= A.GetHashCode();
+      if (a_ != null) hash ^= A.GetHashCode();
       if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -9794,13 +12599,18 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasA) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (a_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(A);
       }
@@ -9811,12 +12621,32 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (HasOptionalInt32) {
+        output.WriteRawTag(16);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasA) {
+      if (a_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(A);
       }
       if (HasOptionalInt32) {
@@ -9829,12 +12659,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMutualRecursionB other) {
       if (other == null) {
         return;
       }
-      if (other.HasA) {
-        if (!HasA) {
+      if (other.a_ != null) {
+        if (a_ == null) {
           A = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA();
         }
         A.MergeFrom(other.A);
@@ -9846,7 +12677,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -9854,7 +12689,33 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasA) {
+            if (a_ == null) {
+              A = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA();
+            }
+            input.ReadMessage(A);
+            break;
+          }
+          case 16: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (a_ == null) {
               A = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA();
             }
             input.ReadMessage(A);
@@ -9867,26 +12728,35 @@
         }
       }
     }
+    #endif
 
   }
 
-  public sealed partial class TestIsInitialized : pb::IMessage<TestIsInitialized> {
+  public sealed partial class TestIsInitialized : pb::IMessage<TestIsInitialized>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestIsInitialized> _parser = new pb::MessageParser<TestIsInitialized>(() => new TestIsInitialized());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestIsInitialized> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[23]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestIsInitialized() {
       OnConstruction();
     }
@@ -9894,12 +12764,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestIsInitialized(TestIsInitialized other) : this() {
-      subMessage_ = other.HasSubMessage ? other.subMessage_.Clone() : null;
+      subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestIsInitialized Clone() {
       return new TestIsInitialized(this);
     }
@@ -9908,29 +12780,22 @@
     public const int SubMessageFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage subMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage SubMessage {
       get { return subMessage_; }
       set {
         subMessage_ = value;
       }
     }
-    /// <summary>Gets whether the sub_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasSubMessage {
-      get { return subMessage_ != null; }
-    }
-    /// <summary>Clears the value of the sub_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearSubMessage() {
-      subMessage_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestIsInitialized);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestIsInitialized other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -9943,9 +12808,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasSubMessage) hash ^= SubMessage.GetHashCode();
+      if (subMessage_ != null) hash ^= SubMessage.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -9953,25 +12819,46 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasSubMessage) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (subMessage_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(SubMessage);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (subMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(SubMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasSubMessage) {
+      if (subMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage);
       }
       if (_unknownFields != null) {
@@ -9981,12 +12868,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestIsInitialized other) {
       if (other == null) {
         return;
       }
-      if (other.HasSubMessage) {
-        if (!HasSubMessage) {
+      if (other.subMessage_ != null) {
+        if (subMessage_ == null) {
           SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage();
         }
         SubMessage.MergeFrom(other.SubMessage);
@@ -9995,7 +12883,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -10003,7 +12895,29 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasSubMessage) {
+            if (subMessage_ == null) {
+              SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage();
+            }
+            input.ReadMessage(SubMessage);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (subMessage_ == null) {
               SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage();
             }
             input.ReadMessage(SubMessage);
@@ -10012,28 +12926,38 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestIsInitialized message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class SubMessage : pb::IMessage<SubMessage> {
+      public sealed partial class SubMessage : pb::IMessage<SubMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<SubMessage> _parser = new pb::MessageParser<SubMessage>(() => new SubMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<SubMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubMessage() {
           OnConstruction();
         }
@@ -10041,12 +12965,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubMessage(SubMessage other) : this() {
           subGroup_ = other.HasSubGroup ? other.subGroup_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SubMessage Clone() {
           return new SubMessage(this);
         }
@@ -10055,6 +12981,7 @@
         public const int SubGroupFieldNumber = 1;
         private global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup subGroup_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup SubGroup {
           get { return subGroup_; }
           set {
@@ -10063,21 +12990,25 @@
         }
         /// <summary>Gets whether the subgroup field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasSubGroup {
           get { return subGroup_ != null; }
         }
         /// <summary>Clears the value of the subgroup field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearSubGroup() {
           subGroup_ = null;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as SubMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(SubMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -10090,6 +13021,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasSubGroup) hash ^= SubGroup.GetHashCode();
@@ -10100,12 +13032,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasSubGroup) {
             output.WriteRawTag(11);
             output.WriteGroup(SubGroup);
@@ -10114,9 +13051,26 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasSubGroup) {
+            output.WriteRawTag(11);
+            output.WriteGroup(SubGroup);
+            output.WriteRawTag(12);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasSubGroup) {
@@ -10129,6 +13083,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(SubMessage other) {
           if (other == null) {
             return;
@@ -10143,7 +13098,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -10159,30 +13118,62 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 11: {
+                if (!HasSubGroup) {
+                  SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup();
+                }
+                input.ReadGroup(SubGroup);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
         #region Nested types
         /// <summary>Container for nested types declared in the SubMessage message type.</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static partial class Types {
-          public sealed partial class SubGroup : pb::IMessage<SubGroup> {
+          public sealed partial class SubGroup : pb::IMessage<SubGroup>
+          #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              , pb::IBufferMessage
+          #endif
+          {
             private static readonly pb::MessageParser<SubGroup> _parser = new pb::MessageParser<SubGroup>(() => new SubGroup());
             private pb::UnknownFieldSet _unknownFields;
             private int _hasBits0;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pb::MessageParser<SubGroup> Parser { get { return _parser; } }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pbr::MessageDescriptor Descriptor {
               get { return global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Descriptor.NestedTypes[0]; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             pbr::MessageDescriptor pb::IMessage.Descriptor {
               get { return Descriptor; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public SubGroup() {
               OnConstruction();
             }
@@ -10190,6 +13181,7 @@
             partial void OnConstruction();
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public SubGroup(SubGroup other) : this() {
               _hasBits0 = other._hasBits0;
               i_ = other.i_;
@@ -10197,6 +13189,7 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public SubGroup Clone() {
               return new SubGroup(this);
             }
@@ -10207,6 +13200,7 @@
 
             private int i_;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public int I {
               get { if ((_hasBits0 & 1) != 0) { return i_; } else { return IDefaultValue; } }
               set {
@@ -10216,21 +13210,25 @@
             }
             /// <summary>Gets whether the "i" field is set</summary>
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public bool HasI {
               get { return (_hasBits0 & 1) != 0; }
             }
             /// <summary>Clears the value of the "i" field</summary>
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void ClearI() {
               _hasBits0 &= ~1;
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override bool Equals(object other) {
               return Equals(other as SubGroup);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public bool Equals(SubGroup other) {
               if (ReferenceEquals(other, null)) {
                 return false;
@@ -10243,6 +13241,7 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override int GetHashCode() {
               int hash = 1;
               if (HasI) hash ^= I.GetHashCode();
@@ -10253,12 +13252,17 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override string ToString() {
               return pb::JsonFormatter.ToDiagnosticString(this);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void WriteTo(pb::CodedOutputStream output) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              output.WriteRawMessage(this);
+            #else
               if (HasI) {
                 output.WriteRawTag(16);
                 output.WriteInt32(I);
@@ -10266,9 +13270,25 @@
               if (_unknownFields != null) {
                 _unknownFields.WriteTo(output);
               }
+            #endif
             }
 
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+              if (HasI) {
+                output.WriteRawTag(16);
+                output.WriteInt32(I);
+              }
+              if (_unknownFields != null) {
+                _unknownFields.WriteTo(ref output);
+              }
+            }
+            #endif
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public int CalculateSize() {
               int size = 0;
               if (HasI) {
@@ -10281,6 +13301,7 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(SubGroup other) {
               if (other == null) {
                 return;
@@ -10292,7 +13313,11 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(pb::CodedInputStream input) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              input.ReadRawMessage(this);
+            #else
               uint tag;
               while ((tag = input.ReadTag()) != 0) {
                 switch(tag) {
@@ -10307,8 +13332,30 @@
                   }
                 }
               }
+            #endif
             }
 
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  case 12:
+                    return;
+                  default:
+                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                    break;
+                  case 16: {
+                    I = input.ReadInt32();
+                    break;
+                  }
+                }
+              }
+            }
+            #endif
+
           }
 
         }
@@ -10327,24 +13374,32 @@
   /// to compile with proto1, this will emit an error; so we only include it
   /// in protobuf_unittest_proto.
   /// </summary>
-  public sealed partial class TestDupFieldNumber : pb::IMessage<TestDupFieldNumber> {
+  public sealed partial class TestDupFieldNumber : pb::IMessage<TestDupFieldNumber>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestDupFieldNumber> _parser = new pb::MessageParser<TestDupFieldNumber>(() => new TestDupFieldNumber());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestDupFieldNumber> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[24]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDupFieldNumber() {
       OnConstruction();
     }
@@ -10352,6 +13407,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDupFieldNumber(TestDupFieldNumber other) : this() {
       _hasBits0 = other._hasBits0;
       a_ = other.a_;
@@ -10361,6 +13417,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDupFieldNumber Clone() {
       return new TestDupFieldNumber(this);
     }
@@ -10374,6 +13431,7 @@
     /// NO_PROTO1
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int A {
       get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
       set {
@@ -10383,11 +13441,13 @@
     }
     /// <summary>Gets whether the "a" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasA {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "a" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearA() {
       _hasBits0 &= ~1;
     }
@@ -10396,6 +13456,7 @@
     public const int FooFieldNumber = 2;
     private global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo foo_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo Foo {
       get { return foo_; }
       set {
@@ -10404,11 +13465,13 @@
     }
     /// <summary>Gets whether the foo field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFoo {
       get { return foo_ != null; }
     }
     /// <summary>Clears the value of the foo field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFoo() {
       foo_ = null;
     }
@@ -10417,6 +13480,7 @@
     public const int BarFieldNumber = 3;
     private global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar bar_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar Bar {
       get { return bar_; }
       set {
@@ -10425,21 +13489,25 @@
     }
     /// <summary>Gets whether the bar field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBar {
       get { return bar_ != null; }
     }
     /// <summary>Clears the value of the bar field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBar() {
       bar_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestDupFieldNumber);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestDupFieldNumber other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -10454,6 +13522,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasA) hash ^= A.GetHashCode();
@@ -10466,12 +13535,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasA) {
         output.WriteRawTag(8);
         output.WriteInt32(A);
@@ -10489,9 +13563,35 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasA) {
+        output.WriteRawTag(8);
+        output.WriteInt32(A);
+      }
+      if (HasFoo) {
+        output.WriteRawTag(19);
+        output.WriteGroup(Foo);
+        output.WriteRawTag(20);
+      }
+      if (HasBar) {
+        output.WriteRawTag(27);
+        output.WriteGroup(Bar);
+        output.WriteRawTag(28);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasA) {
@@ -10510,6 +13610,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestDupFieldNumber other) {
       if (other == null) {
         return;
@@ -10533,7 +13634,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -10560,30 +13665,73 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            A = input.ReadInt32();
+            break;
+          }
+          case 19: {
+            if (!HasFoo) {
+              Foo = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo();
+            }
+            input.ReadGroup(Foo);
+            break;
+          }
+          case 27: {
+            if (!HasBar) {
+              Bar = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar();
+            }
+            input.ReadGroup(Bar);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestDupFieldNumber message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class Foo : pb::IMessage<Foo> {
+      public sealed partial class Foo : pb::IMessage<Foo>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<Foo> _parser = new pb::MessageParser<Foo>(() => new Foo());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<Foo> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Foo() {
           OnConstruction();
         }
@@ -10591,6 +13739,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Foo(Foo other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -10598,6 +13747,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Foo Clone() {
           return new Foo(this);
         }
@@ -10608,6 +13758,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -10617,21 +13768,25 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as Foo);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(Foo other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -10644,6 +13799,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -10654,12 +13810,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(8);
             output.WriteInt32(A);
@@ -10667,9 +13828,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(8);
+            output.WriteInt32(A);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -10682,6 +13859,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(Foo other) {
           if (other == null) {
             return;
@@ -10693,7 +13871,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -10708,28 +13890,58 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 20:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                A = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
-      public sealed partial class Bar : pb::IMessage<Bar> {
+      public sealed partial class Bar : pb::IMessage<Bar>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<Bar> _parser = new pb::MessageParser<Bar>(() => new Bar());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<Bar> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Descriptor.NestedTypes[1]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Bar() {
           OnConstruction();
         }
@@ -10737,6 +13949,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Bar(Bar other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -10744,6 +13957,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Bar Clone() {
           return new Bar(this);
         }
@@ -10754,6 +13968,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -10763,21 +13978,25 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as Bar);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(Bar other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -10790,6 +14009,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -10800,12 +14020,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(8);
             output.WriteInt32(A);
@@ -10813,9 +14038,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(8);
+            output.WriteInt32(A);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -10828,6 +14069,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(Bar other) {
           if (other == null) {
             return;
@@ -10839,7 +14081,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -10854,8 +14100,30 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 28:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                A = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -10866,23 +14134,31 @@
   /// <summary>
   /// Additional messages for testing lazy fields.
   /// </summary>
-  public sealed partial class TestEagerMessage : pb::IMessage<TestEagerMessage> {
+  public sealed partial class TestEagerMessage : pb::IMessage<TestEagerMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestEagerMessage> _parser = new pb::MessageParser<TestEagerMessage>(() => new TestEagerMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestEagerMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[25]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEagerMessage() {
       OnConstruction();
     }
@@ -10890,12 +14166,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEagerMessage(TestEagerMessage other) : this() {
-      subMessage_ = other.HasSubMessage ? other.subMessage_.Clone() : null;
+      subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEagerMessage Clone() {
       return new TestEagerMessage(this);
     }
@@ -10904,29 +14182,22 @@
     public const int SubMessageFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes SubMessage {
       get { return subMessage_; }
       set {
         subMessage_ = value;
       }
     }
-    /// <summary>Gets whether the sub_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasSubMessage {
-      get { return subMessage_ != null; }
-    }
-    /// <summary>Clears the value of the sub_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearSubMessage() {
-      subMessage_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestEagerMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestEagerMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -10939,9 +14210,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasSubMessage) hash ^= SubMessage.GetHashCode();
+      if (subMessage_ != null) hash ^= SubMessage.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -10949,25 +14221,46 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasSubMessage) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (subMessage_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(SubMessage);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (subMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(SubMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasSubMessage) {
+      if (subMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage);
       }
       if (_unknownFields != null) {
@@ -10977,12 +14270,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestEagerMessage other) {
       if (other == null) {
         return;
       }
-      if (other.HasSubMessage) {
-        if (!HasSubMessage) {
+      if (other.subMessage_ != null) {
+        if (subMessage_ == null) {
           SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
         }
         SubMessage.MergeFrom(other.SubMessage);
@@ -10991,7 +14285,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -10999,7 +14297,29 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasSubMessage) {
+            if (subMessage_ == null) {
+              SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            }
+            input.ReadMessage(SubMessage);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (subMessage_ == null) {
               SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             input.ReadMessage(SubMessage);
@@ -11008,26 +14328,35 @@
         }
       }
     }
+    #endif
 
   }
 
-  public sealed partial class TestLazyMessage : pb::IMessage<TestLazyMessage> {
+  public sealed partial class TestLazyMessage : pb::IMessage<TestLazyMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestLazyMessage> _parser = new pb::MessageParser<TestLazyMessage>(() => new TestLazyMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestLazyMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[26]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestLazyMessage() {
       OnConstruction();
     }
@@ -11035,12 +14364,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestLazyMessage(TestLazyMessage other) : this() {
-      subMessage_ = other.HasSubMessage ? other.subMessage_.Clone() : null;
+      subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestLazyMessage Clone() {
       return new TestLazyMessage(this);
     }
@@ -11049,29 +14380,22 @@
     public const int SubMessageFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes SubMessage {
       get { return subMessage_; }
       set {
         subMessage_ = value;
       }
     }
-    /// <summary>Gets whether the sub_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasSubMessage {
-      get { return subMessage_ != null; }
-    }
-    /// <summary>Clears the value of the sub_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearSubMessage() {
-      subMessage_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestLazyMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestLazyMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -11084,9 +14408,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasSubMessage) hash ^= SubMessage.GetHashCode();
+      if (subMessage_ != null) hash ^= SubMessage.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -11094,25 +14419,46 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasSubMessage) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (subMessage_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(SubMessage);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (subMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(SubMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasSubMessage) {
+      if (subMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage);
       }
       if (_unknownFields != null) {
@@ -11122,12 +14468,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestLazyMessage other) {
       if (other == null) {
         return;
       }
-      if (other.HasSubMessage) {
-        if (!HasSubMessage) {
+      if (other.subMessage_ != null) {
+        if (subMessage_ == null) {
           SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
         }
         SubMessage.MergeFrom(other.SubMessage);
@@ -11136,7 +14483,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -11144,7 +14495,29 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasSubMessage) {
+            if (subMessage_ == null) {
+              SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            }
+            input.ReadMessage(SubMessage);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (subMessage_ == null) {
               SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             input.ReadMessage(SubMessage);
@@ -11153,29 +14526,38 @@
         }
       }
     }
+    #endif
 
   }
 
   /// <summary>
   /// Needed for a Python test.
   /// </summary>
-  public sealed partial class TestNestedMessageHasBits : pb::IMessage<TestNestedMessageHasBits> {
+  public sealed partial class TestNestedMessageHasBits : pb::IMessage<TestNestedMessageHasBits>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestNestedMessageHasBits> _parser = new pb::MessageParser<TestNestedMessageHasBits>(() => new TestNestedMessageHasBits());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestNestedMessageHasBits> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[27]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestNestedMessageHasBits() {
       OnConstruction();
     }
@@ -11183,12 +14565,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestNestedMessageHasBits(TestNestedMessageHasBits other) : this() {
-      optionalNestedMessage_ = other.HasOptionalNestedMessage ? other.optionalNestedMessage_.Clone() : null;
+      optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestNestedMessageHasBits Clone() {
       return new TestNestedMessageHasBits(this);
     }
@@ -11197,29 +14581,22 @@
     public const int OptionalNestedMessageFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage optionalNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage OptionalNestedMessage {
       get { return optionalNestedMessage_; }
       set {
         optionalNestedMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_nested_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalNestedMessage {
-      get { return optionalNestedMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_nested_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalNestedMessage() {
-      optionalNestedMessage_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestNestedMessageHasBits);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestNestedMessageHasBits other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -11232,9 +14609,10 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasOptionalNestedMessage) hash ^= OptionalNestedMessage.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -11242,25 +14620,46 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasOptionalNestedMessage) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (optionalNestedMessage_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(OptionalNestedMessage);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasOptionalNestedMessage) {
+      if (optionalNestedMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
       }
       if (_unknownFields != null) {
@@ -11270,12 +14669,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestNestedMessageHasBits other) {
       if (other == null) {
         return;
       }
-      if (other.HasOptionalNestedMessage) {
-        if (!HasOptionalNestedMessage) {
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
           OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage();
         }
         OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
@@ -11284,7 +14684,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -11292,7 +14696,29 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
-            if (!HasOptionalNestedMessage) {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (optionalNestedMessage_ == null) {
               OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage();
             }
             input.ReadMessage(OptionalNestedMessage);
@@ -11301,28 +14727,38 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestNestedMessageHasBits message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -11330,6 +14766,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           nestedmessageRepeatedInt32_ = other.nestedmessageRepeatedInt32_.Clone();
           nestedmessageRepeatedForeignmessage_ = other.nestedmessageRepeatedForeignmessage_.Clone();
@@ -11337,6 +14774,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -11347,6 +14785,7 @@
             = pb::FieldCodec.ForInt32(8);
         private readonly pbc::RepeatedField<int> nestedmessageRepeatedInt32_ = new pbc::RepeatedField<int>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<int> NestedmessageRepeatedInt32 {
           get { return nestedmessageRepeatedInt32_; }
         }
@@ -11357,16 +14796,19 @@
             = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage> nestedmessageRepeatedForeignmessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage> NestedmessageRepeatedForeignmessage {
           get { return nestedmessageRepeatedForeignmessage_; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -11380,6 +14822,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           hash ^= nestedmessageRepeatedInt32_.GetHashCode();
@@ -11391,20 +14834,39 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           nestedmessageRepeatedInt32_.WriteTo(output, _repeated_nestedmessageRepeatedInt32_codec);
           nestedmessageRepeatedForeignmessage_.WriteTo(output, _repeated_nestedmessageRepeatedForeignmessage_codec);
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          nestedmessageRepeatedInt32_.WriteTo(ref output, _repeated_nestedmessageRepeatedInt32_codec);
+          nestedmessageRepeatedForeignmessage_.WriteTo(ref output, _repeated_nestedmessageRepeatedForeignmessage_codec);
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           size += nestedmessageRepeatedInt32_.CalculateSize(_repeated_nestedmessageRepeatedInt32_codec);
@@ -11416,6 +14878,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -11426,7 +14889,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -11444,8 +14911,33 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10:
+              case 8: {
+                nestedmessageRepeatedInt32_.AddEntriesFrom(ref input, _repeated_nestedmessageRepeatedInt32_codec);
+                break;
+              }
+              case 18: {
+                nestedmessageRepeatedForeignmessage_.AddEntriesFrom(ref input, _repeated_nestedmessageRepeatedForeignmessage_codec);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -11457,24 +14949,32 @@
   /// Test message with CamelCase field names.  This violates Protocol Buffer
   /// standard style.
   /// </summary>
-  public sealed partial class TestCamelCaseFieldNames : pb::IMessage<TestCamelCaseFieldNames> {
+  public sealed partial class TestCamelCaseFieldNames : pb::IMessage<TestCamelCaseFieldNames>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestCamelCaseFieldNames> _parser = new pb::MessageParser<TestCamelCaseFieldNames>(() => new TestCamelCaseFieldNames());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestCamelCaseFieldNames> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[28]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCamelCaseFieldNames() {
       OnConstruction();
     }
@@ -11482,12 +14982,13 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() {
       _hasBits0 = other._hasBits0;
       primitiveField_ = other.primitiveField_;
       stringField_ = other.stringField_;
       enumField_ = other.enumField_;
-      messageField_ = other.HasMessageField ? other.messageField_.Clone() : null;
+      messageField_ = other.messageField_ != null ? other.messageField_.Clone() : null;
       stringPieceField_ = other.stringPieceField_;
       cordField_ = other.cordField_;
       repeatedPrimitiveField_ = other.repeatedPrimitiveField_.Clone();
@@ -11500,6 +15001,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCamelCaseFieldNames Clone() {
       return new TestCamelCaseFieldNames(this);
     }
@@ -11510,6 +15012,7 @@
 
     private int primitiveField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int PrimitiveField {
       get { if ((_hasBits0 & 1) != 0) { return primitiveField_; } else { return PrimitiveFieldDefaultValue; } }
       set {
@@ -11519,11 +15022,13 @@
     }
     /// <summary>Gets whether the "PrimitiveField" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPrimitiveField {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "PrimitiveField" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPrimitiveField() {
       _hasBits0 &= ~1;
     }
@@ -11534,6 +15039,7 @@
 
     private string stringField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField {
       get { return stringField_ ?? StringFieldDefaultValue; }
       set {
@@ -11542,11 +15048,13 @@
     }
     /// <summary>Gets whether the "StringField" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasStringField {
       get { return stringField_ != null; }
     }
     /// <summary>Clears the value of the "StringField" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearStringField() {
       stringField_ = null;
     }
@@ -11557,6 +15065,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum enumField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum EnumField {
       get { if ((_hasBits0 & 2) != 0) { return enumField_; } else { return EnumFieldDefaultValue; } }
       set {
@@ -11566,11 +15075,13 @@
     }
     /// <summary>Gets whether the "EnumField" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasEnumField {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "EnumField" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearEnumField() {
       _hasBits0 &= ~2;
     }
@@ -11579,22 +15090,13 @@
     public const int MessageFieldFieldNumber = 4;
     private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage messageField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage MessageField {
       get { return messageField_; }
       set {
         messageField_ = value;
       }
     }
-    /// <summary>Gets whether the MessageField field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasMessageField {
-      get { return messageField_ != null; }
-    }
-    /// <summary>Clears the value of the MessageField field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearMessageField() {
-      messageField_ = null;
-    }
 
     /// <summary>Field number for the "StringPieceField" field.</summary>
     public const int StringPieceFieldFieldNumber = 5;
@@ -11602,6 +15104,7 @@
 
     private string stringPieceField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringPieceField {
       get { return stringPieceField_ ?? StringPieceFieldDefaultValue; }
       set {
@@ -11610,11 +15113,13 @@
     }
     /// <summary>Gets whether the "StringPieceField" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasStringPieceField {
       get { return stringPieceField_ != null; }
     }
     /// <summary>Clears the value of the "StringPieceField" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearStringPieceField() {
       stringPieceField_ = null;
     }
@@ -11625,6 +15130,7 @@
 
     private string cordField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string CordField {
       get { return cordField_ ?? CordFieldDefaultValue; }
       set {
@@ -11633,11 +15139,13 @@
     }
     /// <summary>Gets whether the "CordField" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasCordField {
       get { return cordField_ != null; }
     }
     /// <summary>Clears the value of the "CordField" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearCordField() {
       cordField_ = null;
     }
@@ -11648,6 +15156,7 @@
         = pb::FieldCodec.ForInt32(56);
     private readonly pbc::RepeatedField<int> repeatedPrimitiveField_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedPrimitiveField {
       get { return repeatedPrimitiveField_; }
     }
@@ -11658,6 +15167,7 @@
         = pb::FieldCodec.ForString(66);
     private readonly pbc::RepeatedField<string> repeatedStringField_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedStringField {
       get { return repeatedStringField_; }
     }
@@ -11668,6 +15178,7 @@
         = pb::FieldCodec.ForEnum(72, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> repeatedEnumField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> RepeatedEnumField {
       get { return repeatedEnumField_; }
     }
@@ -11678,6 +15189,7 @@
         = pb::FieldCodec.ForMessage(82, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage> repeatedMessageField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignMessage> RepeatedMessageField {
       get { return repeatedMessageField_; }
     }
@@ -11688,6 +15200,7 @@
         = pb::FieldCodec.ForString(90);
     private readonly pbc::RepeatedField<string> repeatedStringPieceField_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedStringPieceField {
       get { return repeatedStringPieceField_; }
     }
@@ -11698,16 +15211,19 @@
         = pb::FieldCodec.ForString(98);
     private readonly pbc::RepeatedField<string> repeatedCordField_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedCordField {
       get { return repeatedCordField_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestCamelCaseFieldNames);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestCamelCaseFieldNames other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -11731,12 +15247,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasPrimitiveField) hash ^= PrimitiveField.GetHashCode();
       if (HasStringField) hash ^= StringField.GetHashCode();
       if (HasEnumField) hash ^= EnumField.GetHashCode();
-      if (HasMessageField) hash ^= MessageField.GetHashCode();
+      if (messageField_ != null) hash ^= MessageField.GetHashCode();
       if (HasStringPieceField) hash ^= StringPieceField.GetHashCode();
       if (HasCordField) hash ^= CordField.GetHashCode();
       hash ^= repeatedPrimitiveField_.GetHashCode();
@@ -11752,12 +15269,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasPrimitiveField) {
         output.WriteRawTag(8);
         output.WriteInt32(PrimitiveField);
@@ -11770,7 +15292,7 @@
         output.WriteRawTag(24);
         output.WriteEnum((int) EnumField);
       }
-      if (HasMessageField) {
+      if (messageField_ != null) {
         output.WriteRawTag(34);
         output.WriteMessage(MessageField);
       }
@@ -11791,9 +15313,51 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasPrimitiveField) {
+        output.WriteRawTag(8);
+        output.WriteInt32(PrimitiveField);
+      }
+      if (HasStringField) {
+        output.WriteRawTag(18);
+        output.WriteString(StringField);
+      }
+      if (HasEnumField) {
+        output.WriteRawTag(24);
+        output.WriteEnum((int) EnumField);
+      }
+      if (messageField_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(MessageField);
+      }
+      if (HasStringPieceField) {
+        output.WriteRawTag(42);
+        output.WriteString(StringPieceField);
+      }
+      if (HasCordField) {
+        output.WriteRawTag(50);
+        output.WriteString(CordField);
+      }
+      repeatedPrimitiveField_.WriteTo(ref output, _repeated_repeatedPrimitiveField_codec);
+      repeatedStringField_.WriteTo(ref output, _repeated_repeatedStringField_codec);
+      repeatedEnumField_.WriteTo(ref output, _repeated_repeatedEnumField_codec);
+      repeatedMessageField_.WriteTo(ref output, _repeated_repeatedMessageField_codec);
+      repeatedStringPieceField_.WriteTo(ref output, _repeated_repeatedStringPieceField_codec);
+      repeatedCordField_.WriteTo(ref output, _repeated_repeatedCordField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasPrimitiveField) {
@@ -11805,7 +15369,7 @@
       if (HasEnumField) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumField);
       }
-      if (HasMessageField) {
+      if (messageField_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageField);
       }
       if (HasStringPieceField) {
@@ -11827,6 +15391,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestCamelCaseFieldNames other) {
       if (other == null) {
         return;
@@ -11840,8 +15405,8 @@
       if (other.HasEnumField) {
         EnumField = other.EnumField;
       }
-      if (other.HasMessageField) {
-        if (!HasMessageField) {
+      if (other.messageField_ != null) {
+        if (messageField_ == null) {
           MessageField = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
         }
         MessageField.MergeFrom(other.MessageField);
@@ -11862,7 +15427,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -11882,7 +15451,7 @@
             break;
           }
           case 34: {
-            if (!HasMessageField) {
+            if (messageField_ == null) {
               MessageField = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
             }
             input.ReadMessage(MessageField);
@@ -11924,34 +15493,111 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            PrimitiveField = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            StringField = input.ReadString();
+            break;
+          }
+          case 24: {
+            EnumField = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 34: {
+            if (messageField_ == null) {
+              MessageField = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
+            }
+            input.ReadMessage(MessageField);
+            break;
+          }
+          case 42: {
+            StringPieceField = input.ReadString();
+            break;
+          }
+          case 50: {
+            CordField = input.ReadString();
+            break;
+          }
+          case 58:
+          case 56: {
+            repeatedPrimitiveField_.AddEntriesFrom(ref input, _repeated_repeatedPrimitiveField_codec);
+            break;
+          }
+          case 66: {
+            repeatedStringField_.AddEntriesFrom(ref input, _repeated_repeatedStringField_codec);
+            break;
+          }
+          case 74:
+          case 72: {
+            repeatedEnumField_.AddEntriesFrom(ref input, _repeated_repeatedEnumField_codec);
+            break;
+          }
+          case 82: {
+            repeatedMessageField_.AddEntriesFrom(ref input, _repeated_repeatedMessageField_codec);
+            break;
+          }
+          case 90: {
+            repeatedStringPieceField_.AddEntriesFrom(ref input, _repeated_repeatedStringPieceField_codec);
+            break;
+          }
+          case 98: {
+            repeatedCordField_.AddEntriesFrom(ref input, _repeated_repeatedCordField_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// We list fields out of order, to ensure that we're using field number and not
   /// field index to determine serialization order.
   /// </summary>
-  public sealed partial class TestFieldOrderings : pb::IExtendableMessage<TestFieldOrderings> {
+  public sealed partial class TestFieldOrderings : pb::IExtendableMessage<TestFieldOrderings>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestFieldOrderings> _parser = new pb::MessageParser<TestFieldOrderings>(() => new TestFieldOrderings());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestFieldOrderings> _extensions;
     private pb::ExtensionSet<TestFieldOrderings> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestFieldOrderings> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[29]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestFieldOrderings() {
       OnConstruction();
     }
@@ -11959,17 +15605,19 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestFieldOrderings(TestFieldOrderings other) : this() {
       _hasBits0 = other._hasBits0;
       myString_ = other.myString_;
       myInt_ = other.myInt_;
       myFloat_ = other.myFloat_;
-      optionalNestedMessage_ = other.HasOptionalNestedMessage ? other.optionalNestedMessage_.Clone() : null;
+      optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _extensions = pb::ExtensionSet.Clone(other._extensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestFieldOrderings Clone() {
       return new TestFieldOrderings(this);
     }
@@ -11980,6 +15628,7 @@
 
     private string myString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string MyString {
       get { return myString_ ?? MyStringDefaultValue; }
       set {
@@ -11988,11 +15637,13 @@
     }
     /// <summary>Gets whether the "my_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasMyString {
       get { return myString_ != null; }
     }
     /// <summary>Clears the value of the "my_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearMyString() {
       myString_ = null;
     }
@@ -12003,6 +15654,7 @@
 
     private long myInt_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long MyInt {
       get { if ((_hasBits0 & 1) != 0) { return myInt_; } else { return MyIntDefaultValue; } }
       set {
@@ -12012,11 +15664,13 @@
     }
     /// <summary>Gets whether the "my_int" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasMyInt {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "my_int" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearMyInt() {
       _hasBits0 &= ~1;
     }
@@ -12027,6 +15681,7 @@
 
     private float myFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float MyFloat {
       get { if ((_hasBits0 & 2) != 0) { return myFloat_; } else { return MyFloatDefaultValue; } }
       set {
@@ -12036,11 +15691,13 @@
     }
     /// <summary>Gets whether the "my_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasMyFloat {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "my_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearMyFloat() {
       _hasBits0 &= ~2;
     }
@@ -12049,29 +15706,22 @@
     public const int OptionalNestedMessageFieldNumber = 200;
     private global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage optionalNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage OptionalNestedMessage {
       get { return optionalNestedMessage_; }
       set {
         optionalNestedMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_nested_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalNestedMessage {
-      get { return optionalNestedMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_nested_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalNestedMessage() {
-      optionalNestedMessage_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestFieldOrderings);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestFieldOrderings other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -12090,12 +15740,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasMyString) hash ^= MyString.GetHashCode();
       if (HasMyInt) hash ^= MyInt.GetHashCode();
       if (HasMyFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(MyFloat);
-      if (HasOptionalNestedMessage) hash ^= OptionalNestedMessage.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
       if (_extensions != null) {
         hash ^= _extensions.GetHashCode();
       }
@@ -12106,12 +15757,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasMyInt) {
         output.WriteRawTag(8);
         output.WriteInt64(MyInt);
@@ -12124,7 +15780,7 @@
         output.WriteRawTag(173, 6);
         output.WriteFloat(MyFloat);
       }
-      if (HasOptionalNestedMessage) {
+      if (optionalNestedMessage_ != null) {
         output.WriteRawTag(194, 12);
         output.WriteMessage(OptionalNestedMessage);
       }
@@ -12134,9 +15790,40 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasMyInt) {
+        output.WriteRawTag(8);
+        output.WriteInt64(MyInt);
+      }
+      if (HasMyString) {
+        output.WriteRawTag(90);
+        output.WriteString(MyString);
+      }
+      if (HasMyFloat) {
+        output.WriteRawTag(173, 6);
+        output.WriteFloat(MyFloat);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(194, 12);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasMyString) {
@@ -12148,7 +15835,7 @@
       if (HasMyFloat) {
         size += 2 + 4;
       }
-      if (HasOptionalNestedMessage) {
+      if (optionalNestedMessage_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
       }
       if (_extensions != null) {
@@ -12161,6 +15848,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestFieldOrderings other) {
       if (other == null) {
         return;
@@ -12174,8 +15862,8 @@
       if (other.HasMyFloat) {
         MyFloat = other.MyFloat;
       }
-      if (other.HasOptionalNestedMessage) {
-        if (!HasOptionalNestedMessage) {
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
           OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage();
         }
         OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
@@ -12185,7 +15873,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -12207,7 +15899,43 @@
             break;
           }
           case 1602: {
-            if (!HasOptionalNestedMessage) {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            MyInt = input.ReadInt64();
+            break;
+          }
+          case 90: {
+            MyString = input.ReadString();
+            break;
+          }
+          case 813: {
+            MyFloat = input.ReadFloat();
+            break;
+          }
+          case 1602: {
+            if (optionalNestedMessage_ == null) {
               OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage();
             }
             input.ReadMessage(OptionalNestedMessage);
@@ -12216,6 +15944,7 @@
         }
       }
     }
+    #endif
 
     public TValue GetExtension<TValue>(pb::Extension<TestFieldOrderings, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
@@ -12242,25 +15971,34 @@
     #region Nested types
     /// <summary>Container for nested types declared in the TestFieldOrderings message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -12268,6 +16006,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           _hasBits0 = other._hasBits0;
           oo_ = other.oo_;
@@ -12276,6 +16015,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -12286,6 +16026,7 @@
 
         private long oo_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public long Oo {
           get { if ((_hasBits0 & 2) != 0) { return oo_; } else { return OoDefaultValue; } }
           set {
@@ -12295,11 +16036,13 @@
         }
         /// <summary>Gets whether the "oo" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasOo {
           get { return (_hasBits0 & 2) != 0; }
         }
         /// <summary>Clears the value of the "oo" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearOo() {
           _hasBits0 &= ~2;
         }
@@ -12315,6 +16058,7 @@
         /// This file needs to compile in proto1 to test backwards-compatibility.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Bb {
           get { if ((_hasBits0 & 1) != 0) { return bb_; } else { return BbDefaultValue; } }
           set {
@@ -12324,21 +16068,25 @@
         }
         /// <summary>Gets whether the "bb" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasBb {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "bb" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearBb() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -12352,6 +16100,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasOo) hash ^= Oo.GetHashCode();
@@ -12363,12 +16112,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasBb) {
             output.WriteRawTag(8);
             output.WriteInt32(Bb);
@@ -12380,9 +16134,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasBb) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (HasOo) {
+            output.WriteRawTag(16);
+            output.WriteInt64(Oo);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasOo) {
@@ -12398,6 +16172,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -12412,7 +16187,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -12429,8 +16208,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Oo = input.ReadInt64();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -12438,23 +16241,31 @@
 
   }
 
-  public sealed partial class TestExtensionOrderings1 : pb::IMessage<TestExtensionOrderings1> {
+  public sealed partial class TestExtensionOrderings1 : pb::IMessage<TestExtensionOrderings1>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestExtensionOrderings1> _parser = new pb::MessageParser<TestExtensionOrderings1>(() => new TestExtensionOrderings1());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestExtensionOrderings1> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[30]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionOrderings1() {
       OnConstruction();
     }
@@ -12462,12 +16273,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionOrderings1(TestExtensionOrderings1 other) : this() {
       myString_ = other.myString_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionOrderings1 Clone() {
       return new TestExtensionOrderings1(this);
     }
@@ -12478,6 +16291,7 @@
 
     private string myString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string MyString {
       get { return myString_ ?? MyStringDefaultValue; }
       set {
@@ -12486,21 +16300,25 @@
     }
     /// <summary>Gets whether the "my_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasMyString {
       get { return myString_ != null; }
     }
     /// <summary>Clears the value of the "my_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearMyString() {
       myString_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestExtensionOrderings1);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestExtensionOrderings1 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -12513,6 +16331,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasMyString) hash ^= MyString.GetHashCode();
@@ -12523,12 +16342,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasMyString) {
         output.WriteRawTag(10);
         output.WriteString(MyString);
@@ -12536,9 +16360,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasMyString) {
+        output.WriteRawTag(10);
+        output.WriteString(MyString);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasMyString) {
@@ -12551,6 +16391,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestExtensionOrderings1 other) {
       if (other == null) {
         return;
@@ -12562,7 +16403,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -12575,11 +16420,32 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            MyString = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Extensions
     /// <summary>Container for extensions for other messages declared in the TestExtensionOrderings1 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Extensions {
       public static readonly pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings1> TestExtOrderings1 =
         new pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings1>(13, pb::FieldCodec.ForMessage(106, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings1.Parser));
@@ -12588,23 +16454,31 @@
 
   }
 
-  public sealed partial class TestExtensionOrderings2 : pb::IMessage<TestExtensionOrderings2> {
+  public sealed partial class TestExtensionOrderings2 : pb::IMessage<TestExtensionOrderings2>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestExtensionOrderings2> _parser = new pb::MessageParser<TestExtensionOrderings2>(() => new TestExtensionOrderings2());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestExtensionOrderings2> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[31]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionOrderings2() {
       OnConstruction();
     }
@@ -12612,12 +16486,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionOrderings2(TestExtensionOrderings2 other) : this() {
       myString_ = other.myString_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionOrderings2 Clone() {
       return new TestExtensionOrderings2(this);
     }
@@ -12628,6 +16504,7 @@
 
     private string myString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string MyString {
       get { return myString_ ?? MyStringDefaultValue; }
       set {
@@ -12636,21 +16513,25 @@
     }
     /// <summary>Gets whether the "my_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasMyString {
       get { return myString_ != null; }
     }
     /// <summary>Clears the value of the "my_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearMyString() {
       myString_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestExtensionOrderings2);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestExtensionOrderings2 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -12663,6 +16544,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasMyString) hash ^= MyString.GetHashCode();
@@ -12673,12 +16555,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasMyString) {
         output.WriteRawTag(10);
         output.WriteString(MyString);
@@ -12686,9 +16573,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasMyString) {
+        output.WriteRawTag(10);
+        output.WriteString(MyString);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasMyString) {
@@ -12701,6 +16604,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestExtensionOrderings2 other) {
       if (other == null) {
         return;
@@ -12712,7 +16616,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -12725,29 +16633,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            MyString = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestExtensionOrderings2 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class TestExtensionOrderings3 : pb::IMessage<TestExtensionOrderings3> {
+      public sealed partial class TestExtensionOrderings3 : pb::IMessage<TestExtensionOrderings3>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<TestExtensionOrderings3> _parser = new pb::MessageParser<TestExtensionOrderings3>(() => new TestExtensionOrderings3());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<TestExtensionOrderings3> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public TestExtensionOrderings3() {
           OnConstruction();
         }
@@ -12755,12 +16692,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public TestExtensionOrderings3(TestExtensionOrderings3 other) : this() {
           myString_ = other.myString_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public TestExtensionOrderings3 Clone() {
           return new TestExtensionOrderings3(this);
         }
@@ -12771,6 +16710,7 @@
 
         private string myString_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string MyString {
           get { return myString_ ?? MyStringDefaultValue; }
           set {
@@ -12779,21 +16719,25 @@
         }
         /// <summary>Gets whether the "my_string" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasMyString {
           get { return myString_ != null; }
         }
         /// <summary>Clears the value of the "my_string" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearMyString() {
           myString_ = null;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as TestExtensionOrderings3);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(TestExtensionOrderings3 other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -12806,6 +16750,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasMyString) hash ^= MyString.GetHashCode();
@@ -12816,12 +16761,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasMyString) {
             output.WriteRawTag(10);
             output.WriteString(MyString);
@@ -12829,9 +16779,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasMyString) {
+            output.WriteRawTag(10);
+            output.WriteString(MyString);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasMyString) {
@@ -12844,6 +16810,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(TestExtensionOrderings3 other) {
           if (other == null) {
             return;
@@ -12855,7 +16822,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -12868,11 +16839,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                MyString = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
         #region Extensions
         /// <summary>Container for extensions for other messages declared in the TestExtensionOrderings3 message type.</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static partial class Extensions {
           public static readonly pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Types.TestExtensionOrderings3> TestExtOrderings3 =
             new pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Types.TestExtensionOrderings3>(14, pb::FieldCodec.ForMessage(114, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Types.TestExtensionOrderings3.Parser));
@@ -12887,6 +16879,7 @@
     #region Extensions
     /// <summary>Container for extensions for other messages declared in the TestExtensionOrderings2 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Extensions {
       public static readonly pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2> TestExtOrderings2 =
         new pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2>(12, pb::FieldCodec.ForMessage(98, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Parser));
@@ -12895,24 +16888,32 @@
 
   }
 
-  public sealed partial class TestExtremeDefaultValues : pb::IMessage<TestExtremeDefaultValues> {
+  public sealed partial class TestExtremeDefaultValues : pb::IMessage<TestExtremeDefaultValues>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestExtremeDefaultValues> _parser = new pb::MessageParser<TestExtremeDefaultValues>(() => new TestExtremeDefaultValues());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestExtremeDefaultValues> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[32]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtremeDefaultValues() {
       OnConstruction();
     }
@@ -12920,6 +16921,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtremeDefaultValues(TestExtremeDefaultValues other) : this() {
       _hasBits0 = other._hasBits0;
       escapedBytes_ = other.escapedBytes_;
@@ -12953,6 +16955,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtremeDefaultValues Clone() {
       return new TestExtremeDefaultValues(this);
     }
@@ -12963,6 +16966,7 @@
 
     private pb::ByteString escapedBytes_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString EscapedBytes {
       get { return escapedBytes_ ?? EscapedBytesDefaultValue; }
       set {
@@ -12971,11 +16975,13 @@
     }
     /// <summary>Gets whether the "escaped_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasEscapedBytes {
       get { return escapedBytes_ != null; }
     }
     /// <summary>Clears the value of the "escaped_bytes" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearEscapedBytes() {
       escapedBytes_ = null;
     }
@@ -12986,6 +16992,7 @@
 
     private uint largeUint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint LargeUint32 {
       get { if ((_hasBits0 & 1) != 0) { return largeUint32_; } else { return LargeUint32DefaultValue; } }
       set {
@@ -12995,11 +17002,13 @@
     }
     /// <summary>Gets whether the "large_uint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasLargeUint32 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "large_uint32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearLargeUint32() {
       _hasBits0 &= ~1;
     }
@@ -13010,6 +17019,7 @@
 
     private ulong largeUint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong LargeUint64 {
       get { if ((_hasBits0 & 2) != 0) { return largeUint64_; } else { return LargeUint64DefaultValue; } }
       set {
@@ -13019,11 +17029,13 @@
     }
     /// <summary>Gets whether the "large_uint64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasLargeUint64 {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "large_uint64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearLargeUint64() {
       _hasBits0 &= ~2;
     }
@@ -13034,6 +17046,7 @@
 
     private int smallInt32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int SmallInt32 {
       get { if ((_hasBits0 & 4) != 0) { return smallInt32_; } else { return SmallInt32DefaultValue; } }
       set {
@@ -13043,11 +17056,13 @@
     }
     /// <summary>Gets whether the "small_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSmallInt32 {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "small_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSmallInt32() {
       _hasBits0 &= ~4;
     }
@@ -13058,6 +17073,7 @@
 
     private long smallInt64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long SmallInt64 {
       get { if ((_hasBits0 & 8) != 0) { return smallInt64_; } else { return SmallInt64DefaultValue; } }
       set {
@@ -13067,11 +17083,13 @@
     }
     /// <summary>Gets whether the "small_int64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSmallInt64 {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "small_int64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSmallInt64() {
       _hasBits0 &= ~8;
     }
@@ -13082,6 +17100,7 @@
 
     private int reallySmallInt32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int ReallySmallInt32 {
       get { if ((_hasBits0 & 131072) != 0) { return reallySmallInt32_; } else { return ReallySmallInt32DefaultValue; } }
       set {
@@ -13091,11 +17110,13 @@
     }
     /// <summary>Gets whether the "really_small_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasReallySmallInt32 {
       get { return (_hasBits0 & 131072) != 0; }
     }
     /// <summary>Clears the value of the "really_small_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearReallySmallInt32() {
       _hasBits0 &= ~131072;
     }
@@ -13106,6 +17127,7 @@
 
     private long reallySmallInt64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long ReallySmallInt64 {
       get { if ((_hasBits0 & 262144) != 0) { return reallySmallInt64_; } else { return ReallySmallInt64DefaultValue; } }
       set {
@@ -13115,11 +17137,13 @@
     }
     /// <summary>Gets whether the "really_small_int64" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasReallySmallInt64 {
       get { return (_hasBits0 & 262144) != 0; }
     }
     /// <summary>Clears the value of the "really_small_int64" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearReallySmallInt64() {
       _hasBits0 &= ~262144;
     }
@@ -13135,6 +17159,7 @@
     /// lots of people use editors that would be confused by this.)
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Utf8String {
       get { return utf8String_ ?? Utf8StringDefaultValue; }
       set {
@@ -13143,11 +17168,13 @@
     }
     /// <summary>Gets whether the "utf8_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasUtf8String {
       get { return utf8String_ != null; }
     }
     /// <summary>Clears the value of the "utf8_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearUtf8String() {
       utf8String_ = null;
     }
@@ -13161,6 +17188,7 @@
     /// Tests for single-precision floating-point values.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float ZeroFloat {
       get { if ((_hasBits0 & 16) != 0) { return zeroFloat_; } else { return ZeroFloatDefaultValue; } }
       set {
@@ -13170,11 +17198,13 @@
     }
     /// <summary>Gets whether the "zero_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasZeroFloat {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "zero_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearZeroFloat() {
       _hasBits0 &= ~16;
     }
@@ -13185,6 +17215,7 @@
 
     private float oneFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float OneFloat {
       get { if ((_hasBits0 & 32) != 0) { return oneFloat_; } else { return OneFloatDefaultValue; } }
       set {
@@ -13194,11 +17225,13 @@
     }
     /// <summary>Gets whether the "one_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneFloat {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "one_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneFloat() {
       _hasBits0 &= ~32;
     }
@@ -13209,6 +17242,7 @@
 
     private float smallFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float SmallFloat {
       get { if ((_hasBits0 & 64) != 0) { return smallFloat_; } else { return SmallFloatDefaultValue; } }
       set {
@@ -13218,11 +17252,13 @@
     }
     /// <summary>Gets whether the "small_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSmallFloat {
       get { return (_hasBits0 & 64) != 0; }
     }
     /// <summary>Clears the value of the "small_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSmallFloat() {
       _hasBits0 &= ~64;
     }
@@ -13233,6 +17269,7 @@
 
     private float negativeOneFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float NegativeOneFloat {
       get { if ((_hasBits0 & 128) != 0) { return negativeOneFloat_; } else { return NegativeOneFloatDefaultValue; } }
       set {
@@ -13242,11 +17279,13 @@
     }
     /// <summary>Gets whether the "negative_one_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNegativeOneFloat {
       get { return (_hasBits0 & 128) != 0; }
     }
     /// <summary>Clears the value of the "negative_one_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNegativeOneFloat() {
       _hasBits0 &= ~128;
     }
@@ -13257,6 +17296,7 @@
 
     private float negativeFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float NegativeFloat {
       get { if ((_hasBits0 & 256) != 0) { return negativeFloat_; } else { return NegativeFloatDefaultValue; } }
       set {
@@ -13266,11 +17306,13 @@
     }
     /// <summary>Gets whether the "negative_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNegativeFloat {
       get { return (_hasBits0 & 256) != 0; }
     }
     /// <summary>Clears the value of the "negative_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNegativeFloat() {
       _hasBits0 &= ~256;
     }
@@ -13284,6 +17326,7 @@
     /// Using exponents
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float LargeFloat {
       get { if ((_hasBits0 & 512) != 0) { return largeFloat_; } else { return LargeFloatDefaultValue; } }
       set {
@@ -13293,11 +17336,13 @@
     }
     /// <summary>Gets whether the "large_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasLargeFloat {
       get { return (_hasBits0 & 512) != 0; }
     }
     /// <summary>Clears the value of the "large_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearLargeFloat() {
       _hasBits0 &= ~512;
     }
@@ -13308,6 +17353,7 @@
 
     private float smallNegativeFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float SmallNegativeFloat {
       get { if ((_hasBits0 & 1024) != 0) { return smallNegativeFloat_; } else { return SmallNegativeFloatDefaultValue; } }
       set {
@@ -13317,11 +17363,13 @@
     }
     /// <summary>Gets whether the "small_negative_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSmallNegativeFloat {
       get { return (_hasBits0 & 1024) != 0; }
     }
     /// <summary>Clears the value of the "small_negative_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSmallNegativeFloat() {
       _hasBits0 &= ~1024;
     }
@@ -13335,6 +17383,7 @@
     /// Text for nonfinite floating-point values.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double InfDouble {
       get { if ((_hasBits0 & 2048) != 0) { return infDouble_; } else { return InfDoubleDefaultValue; } }
       set {
@@ -13344,11 +17393,13 @@
     }
     /// <summary>Gets whether the "inf_double" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasInfDouble {
       get { return (_hasBits0 & 2048) != 0; }
     }
     /// <summary>Clears the value of the "inf_double" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearInfDouble() {
       _hasBits0 &= ~2048;
     }
@@ -13359,6 +17410,7 @@
 
     private double negInfDouble_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double NegInfDouble {
       get { if ((_hasBits0 & 4096) != 0) { return negInfDouble_; } else { return NegInfDoubleDefaultValue; } }
       set {
@@ -13368,11 +17420,13 @@
     }
     /// <summary>Gets whether the "neg_inf_double" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNegInfDouble {
       get { return (_hasBits0 & 4096) != 0; }
     }
     /// <summary>Clears the value of the "neg_inf_double" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNegInfDouble() {
       _hasBits0 &= ~4096;
     }
@@ -13383,6 +17437,7 @@
 
     private double nanDouble_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double NanDouble {
       get { if ((_hasBits0 & 8192) != 0) { return nanDouble_; } else { return NanDoubleDefaultValue; } }
       set {
@@ -13392,11 +17447,13 @@
     }
     /// <summary>Gets whether the "nan_double" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNanDouble {
       get { return (_hasBits0 & 8192) != 0; }
     }
     /// <summary>Clears the value of the "nan_double" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNanDouble() {
       _hasBits0 &= ~8192;
     }
@@ -13407,6 +17464,7 @@
 
     private float infFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float InfFloat {
       get { if ((_hasBits0 & 16384) != 0) { return infFloat_; } else { return InfFloatDefaultValue; } }
       set {
@@ -13416,11 +17474,13 @@
     }
     /// <summary>Gets whether the "inf_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasInfFloat {
       get { return (_hasBits0 & 16384) != 0; }
     }
     /// <summary>Clears the value of the "inf_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearInfFloat() {
       _hasBits0 &= ~16384;
     }
@@ -13431,6 +17491,7 @@
 
     private float negInfFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float NegInfFloat {
       get { if ((_hasBits0 & 32768) != 0) { return negInfFloat_; } else { return NegInfFloatDefaultValue; } }
       set {
@@ -13440,11 +17501,13 @@
     }
     /// <summary>Gets whether the "neg_inf_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNegInfFloat {
       get { return (_hasBits0 & 32768) != 0; }
     }
     /// <summary>Clears the value of the "neg_inf_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNegInfFloat() {
       _hasBits0 &= ~32768;
     }
@@ -13455,6 +17518,7 @@
 
     private float nanFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float NanFloat {
       get { if ((_hasBits0 & 65536) != 0) { return nanFloat_; } else { return NanFloatDefaultValue; } }
       set {
@@ -13464,11 +17528,13 @@
     }
     /// <summary>Gets whether the "nan_float" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNanFloat {
       get { return (_hasBits0 & 65536) != 0; }
     }
     /// <summary>Clears the value of the "nan_float" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNanFloat() {
       _hasBits0 &= ~65536;
     }
@@ -13486,6 +17552,7 @@
     /// literals.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string CppTrigraph {
       get { return cppTrigraph_ ?? CppTrigraphDefaultValue; }
       set {
@@ -13494,11 +17561,13 @@
     }
     /// <summary>Gets whether the "cpp_trigraph" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasCppTrigraph {
       get { return cppTrigraph_ != null; }
     }
     /// <summary>Clears the value of the "cpp_trigraph" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearCppTrigraph() {
       cppTrigraph_ = null;
     }
@@ -13512,6 +17581,7 @@
     /// String defaults containing the character '\000'
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringWithZero {
       get { return stringWithZero_ ?? StringWithZeroDefaultValue; }
       set {
@@ -13520,11 +17590,13 @@
     }
     /// <summary>Gets whether the "string_with_zero" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasStringWithZero {
       get { return stringWithZero_ != null; }
     }
     /// <summary>Clears the value of the "string_with_zero" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearStringWithZero() {
       stringWithZero_ = null;
     }
@@ -13535,6 +17607,7 @@
 
     private pb::ByteString bytesWithZero_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString BytesWithZero {
       get { return bytesWithZero_ ?? BytesWithZeroDefaultValue; }
       set {
@@ -13543,11 +17616,13 @@
     }
     /// <summary>Gets whether the "bytes_with_zero" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBytesWithZero {
       get { return bytesWithZero_ != null; }
     }
     /// <summary>Clears the value of the "bytes_with_zero" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBytesWithZero() {
       bytesWithZero_ = null;
     }
@@ -13558,6 +17633,7 @@
 
     private string stringPieceWithZero_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringPieceWithZero {
       get { return stringPieceWithZero_ ?? StringPieceWithZeroDefaultValue; }
       set {
@@ -13566,11 +17642,13 @@
     }
     /// <summary>Gets whether the "string_piece_with_zero" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasStringPieceWithZero {
       get { return stringPieceWithZero_ != null; }
     }
     /// <summary>Clears the value of the "string_piece_with_zero" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearStringPieceWithZero() {
       stringPieceWithZero_ = null;
     }
@@ -13581,6 +17659,7 @@
 
     private string cordWithZero_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string CordWithZero {
       get { return cordWithZero_ ?? CordWithZeroDefaultValue; }
       set {
@@ -13589,11 +17668,13 @@
     }
     /// <summary>Gets whether the "cord_with_zero" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasCordWithZero {
       get { return cordWithZero_ != null; }
     }
     /// <summary>Clears the value of the "cord_with_zero" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearCordWithZero() {
       cordWithZero_ = null;
     }
@@ -13604,6 +17685,7 @@
 
     private string replacementString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string ReplacementString {
       get { return replacementString_ ?? ReplacementStringDefaultValue; }
       set {
@@ -13612,21 +17694,25 @@
     }
     /// <summary>Gets whether the "replacement_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasReplacementString {
       get { return replacementString_ != null; }
     }
     /// <summary>Clears the value of the "replacement_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearReplacementString() {
       replacementString_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestExtremeDefaultValues);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestExtremeDefaultValues other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -13665,6 +17751,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasEscapedBytes) hash ^= EscapedBytes.GetHashCode();
@@ -13701,12 +17788,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasEscapedBytes) {
         output.WriteRawTag(10);
         output.WriteBytes(EscapedBytes);
@@ -13818,9 +17910,129 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasEscapedBytes) {
+        output.WriteRawTag(10);
+        output.WriteBytes(EscapedBytes);
+      }
+      if (HasLargeUint32) {
+        output.WriteRawTag(16);
+        output.WriteUInt32(LargeUint32);
+      }
+      if (HasLargeUint64) {
+        output.WriteRawTag(24);
+        output.WriteUInt64(LargeUint64);
+      }
+      if (HasSmallInt32) {
+        output.WriteRawTag(32);
+        output.WriteInt32(SmallInt32);
+      }
+      if (HasSmallInt64) {
+        output.WriteRawTag(40);
+        output.WriteInt64(SmallInt64);
+      }
+      if (HasUtf8String) {
+        output.WriteRawTag(50);
+        output.WriteString(Utf8String);
+      }
+      if (HasZeroFloat) {
+        output.WriteRawTag(61);
+        output.WriteFloat(ZeroFloat);
+      }
+      if (HasOneFloat) {
+        output.WriteRawTag(69);
+        output.WriteFloat(OneFloat);
+      }
+      if (HasSmallFloat) {
+        output.WriteRawTag(77);
+        output.WriteFloat(SmallFloat);
+      }
+      if (HasNegativeOneFloat) {
+        output.WriteRawTag(85);
+        output.WriteFloat(NegativeOneFloat);
+      }
+      if (HasNegativeFloat) {
+        output.WriteRawTag(93);
+        output.WriteFloat(NegativeFloat);
+      }
+      if (HasLargeFloat) {
+        output.WriteRawTag(101);
+        output.WriteFloat(LargeFloat);
+      }
+      if (HasSmallNegativeFloat) {
+        output.WriteRawTag(109);
+        output.WriteFloat(SmallNegativeFloat);
+      }
+      if (HasInfDouble) {
+        output.WriteRawTag(113);
+        output.WriteDouble(InfDouble);
+      }
+      if (HasNegInfDouble) {
+        output.WriteRawTag(121);
+        output.WriteDouble(NegInfDouble);
+      }
+      if (HasNanDouble) {
+        output.WriteRawTag(129, 1);
+        output.WriteDouble(NanDouble);
+      }
+      if (HasInfFloat) {
+        output.WriteRawTag(141, 1);
+        output.WriteFloat(InfFloat);
+      }
+      if (HasNegInfFloat) {
+        output.WriteRawTag(149, 1);
+        output.WriteFloat(NegInfFloat);
+      }
+      if (HasNanFloat) {
+        output.WriteRawTag(157, 1);
+        output.WriteFloat(NanFloat);
+      }
+      if (HasCppTrigraph) {
+        output.WriteRawTag(162, 1);
+        output.WriteString(CppTrigraph);
+      }
+      if (HasReallySmallInt32) {
+        output.WriteRawTag(168, 1);
+        output.WriteInt32(ReallySmallInt32);
+      }
+      if (HasReallySmallInt64) {
+        output.WriteRawTag(176, 1);
+        output.WriteInt64(ReallySmallInt64);
+      }
+      if (HasStringWithZero) {
+        output.WriteRawTag(186, 1);
+        output.WriteString(StringWithZero);
+      }
+      if (HasBytesWithZero) {
+        output.WriteRawTag(194, 1);
+        output.WriteBytes(BytesWithZero);
+      }
+      if (HasStringPieceWithZero) {
+        output.WriteRawTag(202, 1);
+        output.WriteString(StringPieceWithZero);
+      }
+      if (HasCordWithZero) {
+        output.WriteRawTag(210, 1);
+        output.WriteString(CordWithZero);
+      }
+      if (HasReplacementString) {
+        output.WriteRawTag(218, 1);
+        output.WriteString(ReplacementString);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasEscapedBytes) {
@@ -13911,6 +18123,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestExtremeDefaultValues other) {
       if (other == null) {
         return;
@@ -14000,7 +18213,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -14117,28 +18334,160 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            EscapedBytes = input.ReadBytes();
+            break;
+          }
+          case 16: {
+            LargeUint32 = input.ReadUInt32();
+            break;
+          }
+          case 24: {
+            LargeUint64 = input.ReadUInt64();
+            break;
+          }
+          case 32: {
+            SmallInt32 = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            SmallInt64 = input.ReadInt64();
+            break;
+          }
+          case 50: {
+            Utf8String = input.ReadString();
+            break;
+          }
+          case 61: {
+            ZeroFloat = input.ReadFloat();
+            break;
+          }
+          case 69: {
+            OneFloat = input.ReadFloat();
+            break;
+          }
+          case 77: {
+            SmallFloat = input.ReadFloat();
+            break;
+          }
+          case 85: {
+            NegativeOneFloat = input.ReadFloat();
+            break;
+          }
+          case 93: {
+            NegativeFloat = input.ReadFloat();
+            break;
+          }
+          case 101: {
+            LargeFloat = input.ReadFloat();
+            break;
+          }
+          case 109: {
+            SmallNegativeFloat = input.ReadFloat();
+            break;
+          }
+          case 113: {
+            InfDouble = input.ReadDouble();
+            break;
+          }
+          case 121: {
+            NegInfDouble = input.ReadDouble();
+            break;
+          }
+          case 129: {
+            NanDouble = input.ReadDouble();
+            break;
+          }
+          case 141: {
+            InfFloat = input.ReadFloat();
+            break;
+          }
+          case 149: {
+            NegInfFloat = input.ReadFloat();
+            break;
+          }
+          case 157: {
+            NanFloat = input.ReadFloat();
+            break;
+          }
+          case 162: {
+            CppTrigraph = input.ReadString();
+            break;
+          }
+          case 168: {
+            ReallySmallInt32 = input.ReadInt32();
+            break;
+          }
+          case 176: {
+            ReallySmallInt64 = input.ReadInt64();
+            break;
+          }
+          case 186: {
+            StringWithZero = input.ReadString();
+            break;
+          }
+          case 194: {
+            BytesWithZero = input.ReadBytes();
+            break;
+          }
+          case 202: {
+            StringPieceWithZero = input.ReadString();
+            break;
+          }
+          case 210: {
+            CordWithZero = input.ReadString();
+            break;
+          }
+          case 218: {
+            ReplacementString = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class SparseEnumMessage : pb::IMessage<SparseEnumMessage> {
+  public sealed partial class SparseEnumMessage : pb::IMessage<SparseEnumMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<SparseEnumMessage> _parser = new pb::MessageParser<SparseEnumMessage>(() => new SparseEnumMessage());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<SparseEnumMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[33]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SparseEnumMessage() {
       OnConstruction();
     }
@@ -14146,6 +18495,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SparseEnumMessage(SparseEnumMessage other) : this() {
       _hasBits0 = other._hasBits0;
       sparseEnum_ = other.sparseEnum_;
@@ -14153,6 +18503,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SparseEnumMessage Clone() {
       return new SparseEnumMessage(this);
     }
@@ -14163,6 +18514,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum sparseEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum SparseEnum {
       get { if ((_hasBits0 & 1) != 0) { return sparseEnum_; } else { return SparseEnumDefaultValue; } }
       set {
@@ -14172,21 +18524,25 @@
     }
     /// <summary>Gets whether the "sparse_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSparseEnum {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "sparse_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSparseEnum() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as SparseEnumMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(SparseEnumMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -14199,6 +18555,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasSparseEnum) hash ^= SparseEnum.GetHashCode();
@@ -14209,12 +18566,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasSparseEnum) {
         output.WriteRawTag(8);
         output.WriteEnum((int) SparseEnum);
@@ -14222,9 +18584,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasSparseEnum) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) SparseEnum);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasSparseEnum) {
@@ -14237,6 +18615,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(SparseEnumMessage other) {
       if (other == null) {
         return;
@@ -14248,7 +18627,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -14261,30 +18644,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            SparseEnum = (global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test String and Bytes: string is for valid UTF-8 strings
   /// </summary>
-  public sealed partial class OneString : pb::IMessage<OneString> {
+  public sealed partial class OneString : pb::IMessage<OneString>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneString> _parser = new pb::MessageParser<OneString>(() => new OneString());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneString> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[34]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneString() {
       OnConstruction();
     }
@@ -14292,12 +18703,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneString(OneString other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneString Clone() {
       return new OneString(this);
     }
@@ -14308,6 +18721,7 @@
 
     private string data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Data {
       get { return data_ ?? DataDefaultValue; }
       set {
@@ -14316,21 +18730,25 @@
     }
     /// <summary>Gets whether the "data" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return data_ != null; }
     }
     /// <summary>Clears the value of the "data" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       data_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneString);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneString other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -14343,6 +18761,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasData) hash ^= Data.GetHashCode();
@@ -14353,12 +18772,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasData) {
         output.WriteRawTag(10);
         output.WriteString(Data);
@@ -14366,9 +18790,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasData) {
+        output.WriteRawTag(10);
+        output.WriteString(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasData) {
@@ -14381,6 +18821,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneString other) {
       if (other == null) {
         return;
@@ -14392,7 +18833,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -14405,27 +18850,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Data = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class MoreString : pb::IMessage<MoreString> {
+  public sealed partial class MoreString : pb::IMessage<MoreString>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MoreString> _parser = new pb::MessageParser<MoreString>(() => new MoreString());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MoreString> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[35]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreString() {
       OnConstruction();
     }
@@ -14433,12 +18906,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreString(MoreString other) : this() {
       data_ = other.data_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreString Clone() {
       return new MoreString(this);
     }
@@ -14449,16 +18924,19 @@
         = pb::FieldCodec.ForString(10);
     private readonly pbc::RepeatedField<string> data_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> Data {
       get { return data_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MoreString);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MoreString other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -14471,6 +18949,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= data_.GetHashCode();
@@ -14481,19 +18960,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       data_.WriteTo(output, _repeated_data_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      data_.WriteTo(ref output, _repeated_data_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += data_.CalculateSize(_repeated_data_codec);
@@ -14504,6 +19001,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MoreString other) {
       if (other == null) {
         return;
@@ -14513,7 +19011,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -14526,27 +19028,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            data_.AddEntriesFrom(ref input, _repeated_data_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class OneBytes : pb::IMessage<OneBytes> {
+  public sealed partial class OneBytes : pb::IMessage<OneBytes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneBytes> _parser = new pb::MessageParser<OneBytes>(() => new OneBytes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneBytes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[36]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneBytes() {
       OnConstruction();
     }
@@ -14554,12 +19084,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneBytes(OneBytes other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneBytes Clone() {
       return new OneBytes(this);
     }
@@ -14570,6 +19102,7 @@
 
     private pb::ByteString data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString Data {
       get { return data_ ?? DataDefaultValue; }
       set {
@@ -14578,21 +19111,25 @@
     }
     /// <summary>Gets whether the "data" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return data_ != null; }
     }
     /// <summary>Clears the value of the "data" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       data_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneBytes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneBytes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -14605,6 +19142,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasData) hash ^= Data.GetHashCode();
@@ -14615,12 +19153,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasData) {
         output.WriteRawTag(10);
         output.WriteBytes(Data);
@@ -14628,9 +19171,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasData) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasData) {
@@ -14643,6 +19202,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneBytes other) {
       if (other == null) {
         return;
@@ -14654,7 +19214,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -14667,27 +19231,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Data = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class MoreBytes : pb::IMessage<MoreBytes> {
+  public sealed partial class MoreBytes : pb::IMessage<MoreBytes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MoreBytes> _parser = new pb::MessageParser<MoreBytes>(() => new MoreBytes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MoreBytes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[37]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreBytes() {
       OnConstruction();
     }
@@ -14695,12 +19287,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreBytes(MoreBytes other) : this() {
       data_ = other.data_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreBytes Clone() {
       return new MoreBytes(this);
     }
@@ -14711,16 +19305,19 @@
         = pb::FieldCodec.ForBytes(10);
     private readonly pbc::RepeatedField<pb::ByteString> data_ = new pbc::RepeatedField<pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> Data {
       get { return data_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MoreBytes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MoreBytes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -14733,6 +19330,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= data_.GetHashCode();
@@ -14743,19 +19341,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       data_.WriteTo(output, _repeated_data_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      data_.WriteTo(ref output, _repeated_data_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += data_.CalculateSize(_repeated_data_codec);
@@ -14766,6 +19382,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MoreBytes other) {
       if (other == null) {
         return;
@@ -14775,7 +19392,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -14788,31 +19409,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            data_.AddEntriesFrom(ref input, _repeated_data_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test int32, uint32, int64, uint64, and bool are all compatible
   /// </summary>
-  public sealed partial class Int32Message : pb::IMessage<Int32Message> {
+  public sealed partial class Int32Message : pb::IMessage<Int32Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Int32Message> _parser = new pb::MessageParser<Int32Message>(() => new Int32Message());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Int32Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[38]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Message() {
       OnConstruction();
     }
@@ -14820,6 +19469,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Message(Int32Message other) : this() {
       _hasBits0 = other._hasBits0;
       data_ = other.data_;
@@ -14827,6 +19477,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Message Clone() {
       return new Int32Message(this);
     }
@@ -14837,6 +19488,7 @@
 
     private int data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Data {
       get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } }
       set {
@@ -14846,21 +19498,25 @@
     }
     /// <summary>Gets whether the "data" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "data" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Int32Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Int32Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -14873,6 +19529,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasData) hash ^= Data.GetHashCode();
@@ -14883,12 +19540,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasData) {
         output.WriteRawTag(8);
         output.WriteInt32(Data);
@@ -14896,9 +19558,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasData) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasData) {
@@ -14911,6 +19589,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Int32Message other) {
       if (other == null) {
         return;
@@ -14922,7 +19601,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -14935,28 +19618,56 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class Uint32Message : pb::IMessage<Uint32Message> {
+  public sealed partial class Uint32Message : pb::IMessage<Uint32Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Uint32Message> _parser = new pb::MessageParser<Uint32Message>(() => new Uint32Message());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Uint32Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[39]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint32Message() {
       OnConstruction();
     }
@@ -14964,6 +19675,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint32Message(Uint32Message other) : this() {
       _hasBits0 = other._hasBits0;
       data_ = other.data_;
@@ -14971,6 +19683,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint32Message Clone() {
       return new Uint32Message(this);
     }
@@ -14981,6 +19694,7 @@
 
     private uint data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint Data {
       get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } }
       set {
@@ -14990,21 +19704,25 @@
     }
     /// <summary>Gets whether the "data" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "data" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Uint32Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Uint32Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -15017,6 +19735,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasData) hash ^= Data.GetHashCode();
@@ -15027,12 +19746,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasData) {
         output.WriteRawTag(8);
         output.WriteUInt32(Data);
@@ -15040,9 +19764,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasData) {
+        output.WriteRawTag(8);
+        output.WriteUInt32(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasData) {
@@ -15055,6 +19795,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Uint32Message other) {
       if (other == null) {
         return;
@@ -15066,7 +19807,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -15079,28 +19824,56 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadUInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class Int64Message : pb::IMessage<Int64Message> {
+  public sealed partial class Int64Message : pb::IMessage<Int64Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Int64Message> _parser = new pb::MessageParser<Int64Message>(() => new Int64Message());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Int64Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[40]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Message() {
       OnConstruction();
     }
@@ -15108,6 +19881,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Message(Int64Message other) : this() {
       _hasBits0 = other._hasBits0;
       data_ = other.data_;
@@ -15115,6 +19889,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Message Clone() {
       return new Int64Message(this);
     }
@@ -15125,6 +19900,7 @@
 
     private long data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Data {
       get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } }
       set {
@@ -15134,21 +19910,25 @@
     }
     /// <summary>Gets whether the "data" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "data" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Int64Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Int64Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -15161,6 +19941,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasData) hash ^= Data.GetHashCode();
@@ -15171,12 +19952,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasData) {
         output.WriteRawTag(8);
         output.WriteInt64(Data);
@@ -15184,9 +19970,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasData) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasData) {
@@ -15199,6 +20001,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Int64Message other) {
       if (other == null) {
         return;
@@ -15210,7 +20013,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -15223,28 +20030,56 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class Uint64Message : pb::IMessage<Uint64Message> {
+  public sealed partial class Uint64Message : pb::IMessage<Uint64Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Uint64Message> _parser = new pb::MessageParser<Uint64Message>(() => new Uint64Message());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Uint64Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[41]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint64Message() {
       OnConstruction();
     }
@@ -15252,6 +20087,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint64Message(Uint64Message other) : this() {
       _hasBits0 = other._hasBits0;
       data_ = other.data_;
@@ -15259,6 +20095,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint64Message Clone() {
       return new Uint64Message(this);
     }
@@ -15269,6 +20106,7 @@
 
     private ulong data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong Data {
       get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } }
       set {
@@ -15278,21 +20116,25 @@
     }
     /// <summary>Gets whether the "data" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "data" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Uint64Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Uint64Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -15305,6 +20147,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasData) hash ^= Data.GetHashCode();
@@ -15315,12 +20158,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasData) {
         output.WriteRawTag(8);
         output.WriteUInt64(Data);
@@ -15328,9 +20176,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasData) {
+        output.WriteRawTag(8);
+        output.WriteUInt64(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasData) {
@@ -15343,6 +20207,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Uint64Message other) {
       if (other == null) {
         return;
@@ -15354,7 +20219,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -15367,28 +20236,56 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadUInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class BoolMessage : pb::IMessage<BoolMessage> {
+  public sealed partial class BoolMessage : pb::IMessage<BoolMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BoolMessage> _parser = new pb::MessageParser<BoolMessage>(() => new BoolMessage());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BoolMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[42]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolMessage() {
       OnConstruction();
     }
@@ -15396,6 +20293,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolMessage(BoolMessage other) : this() {
       _hasBits0 = other._hasBits0;
       data_ = other.data_;
@@ -15403,6 +20301,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolMessage Clone() {
       return new BoolMessage(this);
     }
@@ -15413,6 +20312,7 @@
 
     private bool data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Data {
       get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } }
       set {
@@ -15422,21 +20322,25 @@
     }
     /// <summary>Gets whether the "data" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasData {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "data" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearData() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BoolMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BoolMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -15449,6 +20353,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasData) hash ^= Data.GetHashCode();
@@ -15459,12 +20364,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasData) {
         output.WriteRawTag(8);
         output.WriteBool(Data);
@@ -15472,9 +20382,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasData) {
+        output.WriteRawTag(8);
+        output.WriteBool(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasData) {
@@ -15487,6 +20413,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BoolMessage other) {
       if (other == null) {
         return;
@@ -15498,7 +20425,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -15511,31 +20442,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test oneofs.
   /// </summary>
-  public sealed partial class TestOneof : pb::IMessage<TestOneof> {
+  public sealed partial class TestOneof : pb::IMessage<TestOneof>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestOneof> _parser = new pb::MessageParser<TestOneof>(() => new TestOneof());
     private pb::UnknownFieldSet _unknownFields;
-    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestOneof> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[43]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof() {
       OnConstruction();
     }
@@ -15543,8 +20501,8 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof(TestOneof other) : this() {
-      _hasBits0 = other._hasBits0;
       switch (other.FooCase) {
         case FooOneofCase.FooInt:
           FooInt = other.FooInt;
@@ -15564,6 +20522,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof Clone() {
       return new TestOneof(this);
     }
@@ -15571,6 +20530,7 @@
     /// <summary>Field number for the "foo_int" field.</summary>
     public const int FooIntFieldNumber = 1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FooInt {
       get { return HasFooInt ? (int) foo_ : 0; }
       set {
@@ -15580,11 +20540,13 @@
     }
     /// <summary>Gets whether the "foo_int" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooInt {
       get { return fooCase_ == FooOneofCase.FooInt; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_int" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooInt() {
       if (HasFooInt) {
         ClearFoo();
@@ -15594,6 +20556,7 @@
     /// <summary>Field number for the "foo_string" field.</summary>
     public const int FooStringFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FooString {
       get { return HasFooString ? (string) foo_ : ""; }
       set {
@@ -15603,11 +20566,13 @@
     }
     /// <summary>Gets whether the "foo_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooString {
       get { return fooCase_ == FooOneofCase.FooString; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_string" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooString() {
       if (HasFooString) {
         ClearFoo();
@@ -15617,29 +20582,19 @@
     /// <summary>Field number for the "foo_message" field.</summary>
     public const int FooMessageFieldNumber = 3;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes FooMessage {
-      get { return HasFooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes) foo_ : null; }
+      get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes) foo_ : null; }
       set {
         foo_ = value;
         fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage;
       }
     }
-    /// <summary>Gets whether the "foo_message" field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasFooMessage {
-      get { return fooCase_ == FooOneofCase.FooMessage; }
-    }
-    /// <summary> Clears the value of the oneof if it's currently set to "foo_message" </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearFooMessage() {
-      if (HasFooMessage) {
-        ClearFoo();
-      }
-    }
 
     /// <summary>Field number for the "foogroup" field.</summary>
     public const int FooGroupFieldNumber = 4;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup FooGroup {
       get { return HasFooGroup ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup) foo_ : null; }
       set {
@@ -15649,11 +20604,13 @@
     }
     /// <summary>Gets whether the "foogroup" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooGroup {
       get { return fooCase_ == FooOneofCase.FooGroup; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foogroup" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooGroup() {
       if (HasFooGroup) {
         ClearFoo();
@@ -15671,22 +20628,26 @@
     }
     private FooOneofCase fooCase_ = FooOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooOneofCase FooCase {
       get { return fooCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFoo() {
       fooCase_ = FooOneofCase.None;
       foo_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestOneof);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestOneof other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -15703,11 +20664,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasFooInt) hash ^= FooInt.GetHashCode();
       if (HasFooString) hash ^= FooString.GetHashCode();
-      if (HasFooMessage) hash ^= FooMessage.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode();
       if (HasFooGroup) hash ^= FooGroup.GetHashCode();
       hash ^= (int) fooCase_;
       if (_unknownFields != null) {
@@ -15717,12 +20679,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasFooInt) {
         output.WriteRawTag(8);
         output.WriteInt32(FooInt);
@@ -15731,7 +20698,7 @@
         output.WriteRawTag(18);
         output.WriteString(FooString);
       }
-      if (HasFooMessage) {
+      if (fooCase_ == FooOneofCase.FooMessage) {
         output.WriteRawTag(26);
         output.WriteMessage(FooMessage);
       }
@@ -15743,9 +20710,38 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasFooInt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FooInt);
+      }
+      if (HasFooString) {
+        output.WriteRawTag(18);
+        output.WriteString(FooString);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        output.WriteRawTag(26);
+        output.WriteMessage(FooMessage);
+      }
+      if (HasFooGroup) {
+        output.WriteRawTag(35);
+        output.WriteGroup(FooGroup);
+        output.WriteRawTag(36);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasFooInt) {
@@ -15754,7 +20750,7 @@
       if (HasFooString) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString);
       }
-      if (HasFooMessage) {
+      if (fooCase_ == FooOneofCase.FooMessage) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage);
       }
       if (HasFooGroup) {
@@ -15767,6 +20763,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestOneof other) {
       if (other == null) {
         return;
@@ -15796,7 +20793,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -15813,7 +20814,48 @@
           }
           case 26: {
             global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
-            if (HasFooMessage) {
+            if (fooCase_ == FooOneofCase.FooMessage) {
+              subBuilder.MergeFrom(FooMessage);
+            }
+            input.ReadMessage(subBuilder);
+            FooMessage = subBuilder;
+            break;
+          }
+          case 35: {
+            global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup();
+            if (HasFooGroup) {
+              subBuilder.MergeFrom(FooGroup);
+            }
+            input.ReadGroup(subBuilder);
+            FooGroup = subBuilder;
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            FooInt = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            FooString = input.ReadString();
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            if (fooCase_ == FooOneofCase.FooMessage) {
               subBuilder.MergeFrom(FooMessage);
             }
             input.ReadMessage(subBuilder);
@@ -15832,29 +20874,39 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestOneof message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class FooGroup : pb::IMessage<FooGroup> {
+      public sealed partial class FooGroup : pb::IMessage<FooGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<FooGroup> _parser = new pb::MessageParser<FooGroup>(() => new FooGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<FooGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestOneof.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup() {
           OnConstruction();
         }
@@ -15862,6 +20914,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup(FooGroup other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -15870,6 +20923,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup Clone() {
           return new FooGroup(this);
         }
@@ -15880,6 +20934,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -15889,11 +20944,13 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
@@ -15904,6 +20961,7 @@
 
         private string b_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string B {
           get { return b_ ?? BDefaultValue; }
           set {
@@ -15912,21 +20970,25 @@
         }
         /// <summary>Gets whether the "b" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasB {
           get { return b_ != null; }
         }
         /// <summary>Clears the value of the "b" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearB() {
           b_ = null;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as FooGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(FooGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -15940,6 +21002,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -15951,12 +21014,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(40);
             output.WriteInt32(A);
@@ -15968,9 +21036,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(40);
+            output.WriteInt32(A);
+          }
+          if (HasB) {
+            output.WriteRawTag(50);
+            output.WriteString(B);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -15986,6 +21074,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(FooGroup other) {
           if (other == null) {
             return;
@@ -16000,7 +21089,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -16019,8 +21112,34 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 36:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 40: {
+                A = input.ReadInt32();
+                break;
+              }
+              case 50: {
+                B = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -16028,24 +21147,32 @@
 
   }
 
-  public sealed partial class TestOneofBackwardsCompatible : pb::IMessage<TestOneofBackwardsCompatible> {
+  public sealed partial class TestOneofBackwardsCompatible : pb::IMessage<TestOneofBackwardsCompatible>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestOneofBackwardsCompatible> _parser = new pb::MessageParser<TestOneofBackwardsCompatible>(() => new TestOneofBackwardsCompatible());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestOneofBackwardsCompatible> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[44]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneofBackwardsCompatible() {
       OnConstruction();
     }
@@ -16053,16 +21180,18 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneofBackwardsCompatible(TestOneofBackwardsCompatible other) : this() {
       _hasBits0 = other._hasBits0;
       fooInt_ = other.fooInt_;
       fooString_ = other.fooString_;
-      fooMessage_ = other.HasFooMessage ? other.fooMessage_.Clone() : null;
+      fooMessage_ = other.fooMessage_ != null ? other.fooMessage_.Clone() : null;
       fooGroup_ = other.HasFooGroup ? other.fooGroup_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneofBackwardsCompatible Clone() {
       return new TestOneofBackwardsCompatible(this);
     }
@@ -16073,6 +21202,7 @@
 
     private int fooInt_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FooInt {
       get { if ((_hasBits0 & 1) != 0) { return fooInt_; } else { return FooIntDefaultValue; } }
       set {
@@ -16082,11 +21212,13 @@
     }
     /// <summary>Gets whether the "foo_int" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooInt {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "foo_int" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooInt() {
       _hasBits0 &= ~1;
     }
@@ -16097,6 +21229,7 @@
 
     private string fooString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FooString {
       get { return fooString_ ?? FooStringDefaultValue; }
       set {
@@ -16105,11 +21238,13 @@
     }
     /// <summary>Gets whether the "foo_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooString {
       get { return fooString_ != null; }
     }
     /// <summary>Clears the value of the "foo_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooString() {
       fooString_ = null;
     }
@@ -16118,27 +21253,19 @@
     public const int FooMessageFieldNumber = 3;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes fooMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes FooMessage {
       get { return fooMessage_; }
       set {
         fooMessage_ = value;
       }
     }
-    /// <summary>Gets whether the foo_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasFooMessage {
-      get { return fooMessage_ != null; }
-    }
-    /// <summary>Clears the value of the foo_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearFooMessage() {
-      fooMessage_ = null;
-    }
 
     /// <summary>Field number for the "foogroup" field.</summary>
     public const int FooGroupFieldNumber = 4;
     private global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup fooGroup_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup FooGroup {
       get { return fooGroup_; }
       set {
@@ -16147,21 +21274,25 @@
     }
     /// <summary>Gets whether the foogroup field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooGroup {
       get { return fooGroup_ != null; }
     }
     /// <summary>Clears the value of the foogroup field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooGroup() {
       fooGroup_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestOneofBackwardsCompatible);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestOneofBackwardsCompatible other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -16177,11 +21308,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasFooInt) hash ^= FooInt.GetHashCode();
       if (HasFooString) hash ^= FooString.GetHashCode();
-      if (HasFooMessage) hash ^= FooMessage.GetHashCode();
+      if (fooMessage_ != null) hash ^= FooMessage.GetHashCode();
       if (HasFooGroup) hash ^= FooGroup.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -16190,12 +21322,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasFooInt) {
         output.WriteRawTag(8);
         output.WriteInt32(FooInt);
@@ -16204,7 +21341,7 @@
         output.WriteRawTag(18);
         output.WriteString(FooString);
       }
-      if (HasFooMessage) {
+      if (fooMessage_ != null) {
         output.WriteRawTag(26);
         output.WriteMessage(FooMessage);
       }
@@ -16216,9 +21353,38 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasFooInt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FooInt);
+      }
+      if (HasFooString) {
+        output.WriteRawTag(18);
+        output.WriteString(FooString);
+      }
+      if (fooMessage_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(FooMessage);
+      }
+      if (HasFooGroup) {
+        output.WriteRawTag(35);
+        output.WriteGroup(FooGroup);
+        output.WriteRawTag(36);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasFooInt) {
@@ -16227,7 +21393,7 @@
       if (HasFooString) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString);
       }
-      if (HasFooMessage) {
+      if (fooMessage_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage);
       }
       if (HasFooGroup) {
@@ -16240,6 +21406,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestOneofBackwardsCompatible other) {
       if (other == null) {
         return;
@@ -16250,8 +21417,8 @@
       if (other.HasFooString) {
         FooString = other.FooString;
       }
-      if (other.HasFooMessage) {
-        if (!HasFooMessage) {
+      if (other.fooMessage_ != null) {
+        if (fooMessage_ == null) {
           FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
         }
         FooMessage.MergeFrom(other.FooMessage);
@@ -16266,7 +21433,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -16282,7 +21453,44 @@
             break;
           }
           case 26: {
-            if (!HasFooMessage) {
+            if (fooMessage_ == null) {
+              FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            }
+            input.ReadMessage(FooMessage);
+            break;
+          }
+          case 35: {
+            if (!HasFooGroup) {
+              FooGroup = new global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup();
+            }
+            input.ReadGroup(FooGroup);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            FooInt = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            FooString = input.ReadString();
+            break;
+          }
+          case 26: {
+            if (fooMessage_ == null) {
               FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             input.ReadMessage(FooMessage);
@@ -16298,29 +21506,39 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestOneofBackwardsCompatible message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class FooGroup : pb::IMessage<FooGroup> {
+      public sealed partial class FooGroup : pb::IMessage<FooGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<FooGroup> _parser = new pb::MessageParser<FooGroup>(() => new FooGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<FooGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup() {
           OnConstruction();
         }
@@ -16328,6 +21546,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup(FooGroup other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -16336,6 +21555,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup Clone() {
           return new FooGroup(this);
         }
@@ -16346,6 +21566,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -16355,11 +21576,13 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
@@ -16370,6 +21593,7 @@
 
         private string b_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string B {
           get { return b_ ?? BDefaultValue; }
           set {
@@ -16378,21 +21602,25 @@
         }
         /// <summary>Gets whether the "b" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasB {
           get { return b_ != null; }
         }
         /// <summary>Clears the value of the "b" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearB() {
           b_ = null;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as FooGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(FooGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -16406,6 +21634,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -16417,12 +21646,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(40);
             output.WriteInt32(A);
@@ -16434,9 +21668,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(40);
+            output.WriteInt32(A);
+          }
+          if (HasB) {
+            output.WriteRawTag(50);
+            output.WriteString(B);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -16452,6 +21706,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(FooGroup other) {
           if (other == null) {
             return;
@@ -16466,7 +21721,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -16485,8 +21744,34 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 36:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 40: {
+                A = input.ReadInt32();
+                break;
+              }
+              case 50: {
+                B = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -16494,24 +21779,32 @@
 
   }
 
-  public sealed partial class TestOneof2 : pb::IMessage<TestOneof2> {
+  public sealed partial class TestOneof2 : pb::IMessage<TestOneof2>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestOneof2> _parser = new pb::MessageParser<TestOneof2>(() => new TestOneof2());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestOneof2> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[45]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof2() {
       OnConstruction();
     }
@@ -16519,6 +21812,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof2(TestOneof2 other) : this() {
       _hasBits0 = other._hasBits0;
       bazInt_ = other.bazInt_;
@@ -16578,6 +21872,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof2 Clone() {
       return new TestOneof2(this);
     }
@@ -16585,6 +21880,7 @@
     /// <summary>Field number for the "foo_int" field.</summary>
     public const int FooIntFieldNumber = 1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FooInt {
       get { return HasFooInt ? (int) foo_ : 0; }
       set {
@@ -16594,11 +21890,13 @@
     }
     /// <summary>Gets whether the "foo_int" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooInt {
       get { return fooCase_ == FooOneofCase.FooInt; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_int" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooInt() {
       if (HasFooInt) {
         ClearFoo();
@@ -16608,6 +21906,7 @@
     /// <summary>Field number for the "foo_string" field.</summary>
     public const int FooStringFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FooString {
       get { return HasFooString ? (string) foo_ : ""; }
       set {
@@ -16617,11 +21916,13 @@
     }
     /// <summary>Gets whether the "foo_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooString {
       get { return fooCase_ == FooOneofCase.FooString; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_string" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooString() {
       if (HasFooString) {
         ClearFoo();
@@ -16631,6 +21932,7 @@
     /// <summary>Field number for the "foo_cord" field.</summary>
     public const int FooCordFieldNumber = 3;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FooCord {
       get { return HasFooCord ? (string) foo_ : ""; }
       set {
@@ -16640,11 +21942,13 @@
     }
     /// <summary>Gets whether the "foo_cord" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooCord {
       get { return fooCase_ == FooOneofCase.FooCord; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_cord" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooCord() {
       if (HasFooCord) {
         ClearFoo();
@@ -16654,6 +21958,7 @@
     /// <summary>Field number for the "foo_string_piece" field.</summary>
     public const int FooStringPieceFieldNumber = 4;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FooStringPiece {
       get { return HasFooStringPiece ? (string) foo_ : ""; }
       set {
@@ -16663,11 +21968,13 @@
     }
     /// <summary>Gets whether the "foo_string_piece" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooStringPiece {
       get { return fooCase_ == FooOneofCase.FooStringPiece; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_string_piece" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooStringPiece() {
       if (HasFooStringPiece) {
         ClearFoo();
@@ -16677,6 +21984,7 @@
     /// <summary>Field number for the "foo_bytes" field.</summary>
     public const int FooBytesFieldNumber = 5;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString FooBytes {
       get { return HasFooBytes ? (pb::ByteString) foo_ : pb::ByteString.Empty; }
       set {
@@ -16686,11 +21994,13 @@
     }
     /// <summary>Gets whether the "foo_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooBytes {
       get { return fooCase_ == FooOneofCase.FooBytes; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_bytes" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooBytes() {
       if (HasFooBytes) {
         ClearFoo();
@@ -16700,6 +22010,7 @@
     /// <summary>Field number for the "foo_enum" field.</summary>
     public const int FooEnumFieldNumber = 6;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum FooEnum {
       get { return HasFooEnum ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum) foo_ : global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum.Foo; }
       set {
@@ -16709,11 +22020,13 @@
     }
     /// <summary>Gets whether the "foo_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooEnum {
       get { return fooCase_ == FooOneofCase.FooEnum; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_enum" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooEnum() {
       if (HasFooEnum) {
         ClearFoo();
@@ -16723,29 +22036,19 @@
     /// <summary>Field number for the "foo_message" field.</summary>
     public const int FooMessageFieldNumber = 7;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage FooMessage {
-      get { return HasFooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage) foo_ : null; }
+      get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage) foo_ : null; }
       set {
         foo_ = value;
         fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage;
       }
     }
-    /// <summary>Gets whether the "foo_message" field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasFooMessage {
-      get { return fooCase_ == FooOneofCase.FooMessage; }
-    }
-    /// <summary> Clears the value of the oneof if it's currently set to "foo_message" </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearFooMessage() {
-      if (HasFooMessage) {
-        ClearFoo();
-      }
-    }
 
     /// <summary>Field number for the "foogroup" field.</summary>
     public const int FooGroupFieldNumber = 8;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup FooGroup {
       get { return HasFooGroup ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup) foo_ : null; }
       set {
@@ -16755,11 +22058,13 @@
     }
     /// <summary>Gets whether the "foogroup" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooGroup {
       get { return fooCase_ == FooOneofCase.FooGroup; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foogroup" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooGroup() {
       if (HasFooGroup) {
         ClearFoo();
@@ -16769,29 +22074,19 @@
     /// <summary>Field number for the "foo_lazy_message" field.</summary>
     public const int FooLazyMessageFieldNumber = 11;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage FooLazyMessage {
-      get { return HasFooLazyMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage) foo_ : null; }
+      get { return fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage) foo_ : null; }
       set {
         foo_ = value;
         fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooLazyMessage;
       }
     }
-    /// <summary>Gets whether the "foo_lazy_message" field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasFooLazyMessage {
-      get { return fooCase_ == FooOneofCase.FooLazyMessage; }
-    }
-    /// <summary> Clears the value of the oneof if it's currently set to "foo_lazy_message" </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearFooLazyMessage() {
-      if (HasFooLazyMessage) {
-        ClearFoo();
-      }
-    }
 
     /// <summary>Field number for the "bar_int" field.</summary>
     public const int BarIntFieldNumber = 12;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int BarInt {
       get { return HasBarInt ? (int) bar_ : 5; }
       set {
@@ -16801,11 +22096,13 @@
     }
     /// <summary>Gets whether the "bar_int" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBarInt {
       get { return barCase_ == BarOneofCase.BarInt; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "bar_int" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBarInt() {
       if (HasBarInt) {
         ClearBar();
@@ -16815,6 +22112,7 @@
     /// <summary>Field number for the "bar_string" field.</summary>
     public const int BarStringFieldNumber = 13;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string BarString {
       get { return HasBarString ? (string) bar_ : global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("U1RSSU5H"), 0, 6); }
       set {
@@ -16824,11 +22122,13 @@
     }
     /// <summary>Gets whether the "bar_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBarString {
       get { return barCase_ == BarOneofCase.BarString; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "bar_string" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBarString() {
       if (HasBarString) {
         ClearBar();
@@ -16838,6 +22138,7 @@
     /// <summary>Field number for the "bar_cord" field.</summary>
     public const int BarCordFieldNumber = 14;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string BarCord {
       get { return HasBarCord ? (string) bar_ : global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("Q09SRA=="), 0, 4); }
       set {
@@ -16847,11 +22148,13 @@
     }
     /// <summary>Gets whether the "bar_cord" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBarCord {
       get { return barCase_ == BarOneofCase.BarCord; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "bar_cord" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBarCord() {
       if (HasBarCord) {
         ClearBar();
@@ -16861,6 +22164,7 @@
     /// <summary>Field number for the "bar_string_piece" field.</summary>
     public const int BarStringPieceFieldNumber = 15;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string BarStringPiece {
       get { return HasBarStringPiece ? (string) bar_ : global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("U1BJRUNF"), 0, 6); }
       set {
@@ -16870,11 +22174,13 @@
     }
     /// <summary>Gets whether the "bar_string_piece" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBarStringPiece {
       get { return barCase_ == BarOneofCase.BarStringPiece; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "bar_string_piece" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBarStringPiece() {
       if (HasBarStringPiece) {
         ClearBar();
@@ -16884,6 +22190,7 @@
     /// <summary>Field number for the "bar_bytes" field.</summary>
     public const int BarBytesFieldNumber = 16;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString BarBytes {
       get { return HasBarBytes ? (pb::ByteString) bar_ : pb::ByteString.FromBase64("QllURVM="); }
       set {
@@ -16893,11 +22200,13 @@
     }
     /// <summary>Gets whether the "bar_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBarBytes {
       get { return barCase_ == BarOneofCase.BarBytes; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "bar_bytes" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBarBytes() {
       if (HasBarBytes) {
         ClearBar();
@@ -16907,6 +22216,7 @@
     /// <summary>Field number for the "bar_enum" field.</summary>
     public const int BarEnumFieldNumber = 17;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum BarEnum {
       get { return HasBarEnum ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum) bar_ : global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum.Bar; }
       set {
@@ -16916,11 +22226,13 @@
     }
     /// <summary>Gets whether the "bar_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBarEnum {
       get { return barCase_ == BarOneofCase.BarEnum; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "bar_enum" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBarEnum() {
       if (HasBarEnum) {
         ClearBar();
@@ -16933,22 +22245,25 @@
 
     private int bazInt_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int BazInt {
-      get { if ((_hasBits0 & 16) != 0) { return bazInt_; } else { return BazIntDefaultValue; } }
+      get { if ((_hasBits0 & 1) != 0) { return bazInt_; } else { return BazIntDefaultValue; } }
       set {
-        _hasBits0 |= 16;
+        _hasBits0 |= 1;
         bazInt_ = value;
       }
     }
     /// <summary>Gets whether the "baz_int" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBazInt {
-      get { return (_hasBits0 & 16) != 0; }
+      get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "baz_int" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBazInt() {
-      _hasBits0 &= ~16;
+      _hasBits0 &= ~1;
     }
 
     /// <summary>Field number for the "baz_string" field.</summary>
@@ -16957,6 +22272,7 @@
 
     private string bazString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string BazString {
       get { return bazString_ ?? BazStringDefaultValue; }
       set {
@@ -16965,11 +22281,13 @@
     }
     /// <summary>Gets whether the "baz_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasBazString {
       get { return bazString_ != null; }
     }
     /// <summary>Clears the value of the "baz_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBazString() {
       bazString_ = null;
     }
@@ -16990,11 +22308,13 @@
     }
     private FooOneofCase fooCase_ = FooOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooOneofCase FooCase {
       get { return fooCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFoo() {
       fooCase_ = FooOneofCase.None;
       foo_ = null;
@@ -17013,22 +22333,26 @@
     }
     private BarOneofCase barCase_ = BarOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarOneofCase BarCase {
       get { return barCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearBar() {
       barCase_ = BarOneofCase.None;
       bar_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestOneof2);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestOneof2 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -17059,6 +22383,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasFooInt) hash ^= FooInt.GetHashCode();
@@ -17067,9 +22392,9 @@
       if (HasFooStringPiece) hash ^= FooStringPiece.GetHashCode();
       if (HasFooBytes) hash ^= FooBytes.GetHashCode();
       if (HasFooEnum) hash ^= FooEnum.GetHashCode();
-      if (HasFooMessage) hash ^= FooMessage.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode();
       if (HasFooGroup) hash ^= FooGroup.GetHashCode();
-      if (HasFooLazyMessage) hash ^= FooLazyMessage.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooLazyMessage) hash ^= FooLazyMessage.GetHashCode();
       if (HasBarInt) hash ^= BarInt.GetHashCode();
       if (HasBarString) hash ^= BarString.GetHashCode();
       if (HasBarCord) hash ^= BarCord.GetHashCode();
@@ -17087,12 +22412,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasFooInt) {
         output.WriteRawTag(8);
         output.WriteInt32(FooInt);
@@ -17117,7 +22447,7 @@
         output.WriteRawTag(48);
         output.WriteEnum((int) FooEnum);
       }
-      if (HasFooMessage) {
+      if (fooCase_ == FooOneofCase.FooMessage) {
         output.WriteRawTag(58);
         output.WriteMessage(FooMessage);
       }
@@ -17126,7 +22456,7 @@
         output.WriteGroup(FooGroup);
         output.WriteRawTag(68);
       }
-      if (HasFooLazyMessage) {
+      if (fooCase_ == FooOneofCase.FooLazyMessage) {
         output.WriteRawTag(90);
         output.WriteMessage(FooLazyMessage);
       }
@@ -17165,9 +22495,90 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasFooInt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FooInt);
+      }
+      if (HasFooString) {
+        output.WriteRawTag(18);
+        output.WriteString(FooString);
+      }
+      if (HasFooCord) {
+        output.WriteRawTag(26);
+        output.WriteString(FooCord);
+      }
+      if (HasFooStringPiece) {
+        output.WriteRawTag(34);
+        output.WriteString(FooStringPiece);
+      }
+      if (HasFooBytes) {
+        output.WriteRawTag(42);
+        output.WriteBytes(FooBytes);
+      }
+      if (HasFooEnum) {
+        output.WriteRawTag(48);
+        output.WriteEnum((int) FooEnum);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        output.WriteRawTag(58);
+        output.WriteMessage(FooMessage);
+      }
+      if (HasFooGroup) {
+        output.WriteRawTag(67);
+        output.WriteGroup(FooGroup);
+        output.WriteRawTag(68);
+      }
+      if (fooCase_ == FooOneofCase.FooLazyMessage) {
+        output.WriteRawTag(90);
+        output.WriteMessage(FooLazyMessage);
+      }
+      if (HasBarInt) {
+        output.WriteRawTag(96);
+        output.WriteInt32(BarInt);
+      }
+      if (HasBarString) {
+        output.WriteRawTag(106);
+        output.WriteString(BarString);
+      }
+      if (HasBarCord) {
+        output.WriteRawTag(114);
+        output.WriteString(BarCord);
+      }
+      if (HasBarStringPiece) {
+        output.WriteRawTag(122);
+        output.WriteString(BarStringPiece);
+      }
+      if (HasBarBytes) {
+        output.WriteRawTag(130, 1);
+        output.WriteBytes(BarBytes);
+      }
+      if (HasBarEnum) {
+        output.WriteRawTag(136, 1);
+        output.WriteEnum((int) BarEnum);
+      }
+      if (HasBazInt) {
+        output.WriteRawTag(144, 1);
+        output.WriteInt32(BazInt);
+      }
+      if (HasBazString) {
+        output.WriteRawTag(154, 1);
+        output.WriteString(BazString);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasFooInt) {
@@ -17188,13 +22599,13 @@
       if (HasFooEnum) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) FooEnum);
       }
-      if (HasFooMessage) {
+      if (fooCase_ == FooOneofCase.FooMessage) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage);
       }
       if (HasFooGroup) {
         size += 2 + pb::CodedOutputStream.ComputeGroupSize(FooGroup);
       }
-      if (HasFooLazyMessage) {
+      if (fooCase_ == FooOneofCase.FooLazyMessage) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooLazyMessage);
       }
       if (HasBarInt) {
@@ -17228,6 +22639,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestOneof2 other) {
       if (other == null) {
         return;
@@ -17302,7 +22714,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -17336,7 +22752,7 @@
           }
           case 58: {
             global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage();
-            if (HasFooMessage) {
+            if (fooCase_ == FooOneofCase.FooMessage) {
               subBuilder.MergeFrom(FooMessage);
             }
             input.ReadMessage(subBuilder);
@@ -17354,7 +22770,107 @@
           }
           case 90: {
             global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage();
-            if (HasFooLazyMessage) {
+            if (fooCase_ == FooOneofCase.FooLazyMessage) {
+              subBuilder.MergeFrom(FooLazyMessage);
+            }
+            input.ReadMessage(subBuilder);
+            FooLazyMessage = subBuilder;
+            break;
+          }
+          case 96: {
+            BarInt = input.ReadInt32();
+            break;
+          }
+          case 106: {
+            BarString = input.ReadString();
+            break;
+          }
+          case 114: {
+            BarCord = input.ReadString();
+            break;
+          }
+          case 122: {
+            BarStringPiece = input.ReadString();
+            break;
+          }
+          case 130: {
+            BarBytes = input.ReadBytes();
+            break;
+          }
+          case 136: {
+            bar_ = input.ReadEnum();
+            barCase_ = BarOneofCase.BarEnum;
+            break;
+          }
+          case 144: {
+            BazInt = input.ReadInt32();
+            break;
+          }
+          case 154: {
+            BazString = input.ReadString();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            FooInt = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            FooString = input.ReadString();
+            break;
+          }
+          case 26: {
+            FooCord = input.ReadString();
+            break;
+          }
+          case 34: {
+            FooStringPiece = input.ReadString();
+            break;
+          }
+          case 42: {
+            FooBytes = input.ReadBytes();
+            break;
+          }
+          case 48: {
+            foo_ = input.ReadEnum();
+            fooCase_ = FooOneofCase.FooEnum;
+            break;
+          }
+          case 58: {
+            global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage();
+            if (fooCase_ == FooOneofCase.FooMessage) {
+              subBuilder.MergeFrom(FooMessage);
+            }
+            input.ReadMessage(subBuilder);
+            FooMessage = subBuilder;
+            break;
+          }
+          case 67: {
+            global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup();
+            if (HasFooGroup) {
+              subBuilder.MergeFrom(FooGroup);
+            }
+            input.ReadGroup(subBuilder);
+            FooGroup = subBuilder;
+            break;
+          }
+          case 90: {
+            global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage();
+            if (fooCase_ == FooOneofCase.FooLazyMessage) {
               subBuilder.MergeFrom(FooLazyMessage);
             }
             input.ReadMessage(subBuilder);
@@ -17397,10 +22913,12 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestOneof2 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum NestedEnum {
         [pbr::OriginalName("FOO")] Foo = 1,
@@ -17408,24 +22926,32 @@
         [pbr::OriginalName("BAZ")] Baz = 3,
       }
 
-      public sealed partial class FooGroup : pb::IMessage<FooGroup> {
+      public sealed partial class FooGroup : pb::IMessage<FooGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<FooGroup> _parser = new pb::MessageParser<FooGroup>(() => new FooGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<FooGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup() {
           OnConstruction();
         }
@@ -17433,6 +22959,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup(FooGroup other) : this() {
           _hasBits0 = other._hasBits0;
           a_ = other.a_;
@@ -17441,6 +22968,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public FooGroup Clone() {
           return new FooGroup(this);
         }
@@ -17451,6 +22979,7 @@
 
         private int a_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int A {
           get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } }
           set {
@@ -17460,11 +22989,13 @@
         }
         /// <summary>Gets whether the "a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearA() {
           _hasBits0 &= ~1;
         }
@@ -17475,6 +23006,7 @@
 
         private string b_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string B {
           get { return b_ ?? BDefaultValue; }
           set {
@@ -17483,21 +23015,25 @@
         }
         /// <summary>Gets whether the "b" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasB {
           get { return b_ != null; }
         }
         /// <summary>Clears the value of the "b" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearB() {
           b_ = null;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as FooGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(FooGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -17511,6 +23047,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasA) hash ^= A.GetHashCode();
@@ -17522,12 +23059,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasA) {
             output.WriteRawTag(72);
             output.WriteInt32(A);
@@ -17539,9 +23081,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasA) {
+            output.WriteRawTag(72);
+            output.WriteInt32(A);
+          }
+          if (HasB) {
+            output.WriteRawTag(82);
+            output.WriteString(B);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasA) {
@@ -17557,6 +23119,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(FooGroup other) {
           if (other == null) {
             return;
@@ -17571,7 +23134,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -17590,28 +23157,62 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 68:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 72: {
+                A = input.ReadInt32();
+                break;
+              }
+              case 82: {
+                B = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Descriptor.NestedTypes[1]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -17619,6 +23220,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           _hasBits0 = other._hasBits0;
           quxInt_ = other.quxInt_;
@@ -17627,6 +23229,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -17637,6 +23240,7 @@
 
         private long quxInt_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public long QuxInt {
           get { if ((_hasBits0 & 1) != 0) { return quxInt_; } else { return QuxIntDefaultValue; } }
           set {
@@ -17646,11 +23250,13 @@
         }
         /// <summary>Gets whether the "qux_int" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasQuxInt {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "qux_int" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearQuxInt() {
           _hasBits0 &= ~1;
         }
@@ -17661,16 +23267,19 @@
             = pb::FieldCodec.ForInt32(16);
         private readonly pbc::RepeatedField<int> corgeInt_ = new pbc::RepeatedField<int>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<int> CorgeInt {
           get { return corgeInt_; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -17684,6 +23293,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasQuxInt) hash ^= QuxInt.GetHashCode();
@@ -17695,12 +23305,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasQuxInt) {
             output.WriteRawTag(8);
             output.WriteInt64(QuxInt);
@@ -17709,9 +23324,26 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasQuxInt) {
+            output.WriteRawTag(8);
+            output.WriteInt64(QuxInt);
+          }
+          corgeInt_.WriteTo(ref output, _repeated_corgeInt_codec);
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasQuxInt) {
@@ -17725,6 +23357,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -17737,7 +23370,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -17755,8 +23392,33 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                QuxInt = input.ReadInt64();
+                break;
+              }
+              case 18:
+              case 16: {
+                corgeInt_.AddEntriesFrom(ref input, _repeated_corgeInt_codec);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -17764,24 +23426,31 @@
 
   }
 
-  public sealed partial class TestRequiredOneof : pb::IMessage<TestRequiredOneof> {
+  public sealed partial class TestRequiredOneof : pb::IMessage<TestRequiredOneof>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRequiredOneof> _parser = new pb::MessageParser<TestRequiredOneof>(() => new TestRequiredOneof());
     private pb::UnknownFieldSet _unknownFields;
-    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRequiredOneof> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[46]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredOneof() {
       OnConstruction();
     }
@@ -17789,8 +23458,8 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredOneof(TestRequiredOneof other) : this() {
-      _hasBits0 = other._hasBits0;
       switch (other.FooCase) {
         case FooOneofCase.FooInt:
           FooInt = other.FooInt;
@@ -17807,6 +23476,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredOneof Clone() {
       return new TestRequiredOneof(this);
     }
@@ -17814,6 +23484,7 @@
     /// <summary>Field number for the "foo_int" field.</summary>
     public const int FooIntFieldNumber = 1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FooInt {
       get { return HasFooInt ? (int) foo_ : 0; }
       set {
@@ -17823,11 +23494,13 @@
     }
     /// <summary>Gets whether the "foo_int" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooInt {
       get { return fooCase_ == FooOneofCase.FooInt; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_int" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooInt() {
       if (HasFooInt) {
         ClearFoo();
@@ -17837,6 +23510,7 @@
     /// <summary>Field number for the "foo_string" field.</summary>
     public const int FooStringFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FooString {
       get { return HasFooString ? (string) foo_ : ""; }
       set {
@@ -17846,11 +23520,13 @@
     }
     /// <summary>Gets whether the "foo_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFooString {
       get { return fooCase_ == FooOneofCase.FooString; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "foo_string" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFooString() {
       if (HasFooString) {
         ClearFoo();
@@ -17860,25 +23536,14 @@
     /// <summary>Field number for the "foo_message" field.</summary>
     public const int FooMessageFieldNumber = 3;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage FooMessage {
-      get { return HasFooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage) foo_ : null; }
+      get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage) foo_ : null; }
       set {
         foo_ = value;
         fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage;
       }
     }
-    /// <summary>Gets whether the "foo_message" field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasFooMessage {
-      get { return fooCase_ == FooOneofCase.FooMessage; }
-    }
-    /// <summary> Clears the value of the oneof if it's currently set to "foo_message" </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearFooMessage() {
-      if (HasFooMessage) {
-        ClearFoo();
-      }
-    }
 
     private object foo_;
     /// <summary>Enum of possible cases for the "foo" oneof.</summary>
@@ -17890,22 +23555,26 @@
     }
     private FooOneofCase fooCase_ = FooOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooOneofCase FooCase {
       get { return fooCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFoo() {
       fooCase_ = FooOneofCase.None;
       foo_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRequiredOneof);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRequiredOneof other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -17921,11 +23590,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasFooInt) hash ^= FooInt.GetHashCode();
       if (HasFooString) hash ^= FooString.GetHashCode();
-      if (HasFooMessage) hash ^= FooMessage.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode();
       hash ^= (int) fooCase_;
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -17934,12 +23604,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasFooInt) {
         output.WriteRawTag(8);
         output.WriteInt32(FooInt);
@@ -17948,16 +23623,40 @@
         output.WriteRawTag(18);
         output.WriteString(FooString);
       }
-      if (HasFooMessage) {
+      if (fooCase_ == FooOneofCase.FooMessage) {
         output.WriteRawTag(26);
         output.WriteMessage(FooMessage);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasFooInt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FooInt);
+      }
+      if (HasFooString) {
+        output.WriteRawTag(18);
+        output.WriteString(FooString);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        output.WriteRawTag(26);
+        output.WriteMessage(FooMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasFooInt) {
@@ -17966,7 +23665,7 @@
       if (HasFooString) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString);
       }
-      if (HasFooMessage) {
+      if (fooCase_ == FooOneofCase.FooMessage) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage);
       }
       if (_unknownFields != null) {
@@ -17976,6 +23675,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRequiredOneof other) {
       if (other == null) {
         return;
@@ -17999,7 +23699,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -18016,7 +23720,39 @@
           }
           case 26: {
             global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage();
-            if (HasFooMessage) {
+            if (fooCase_ == FooOneofCase.FooMessage) {
+              subBuilder.MergeFrom(FooMessage);
+            }
+            input.ReadMessage(subBuilder);
+            FooMessage = subBuilder;
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            FooInt = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            FooString = input.ReadString();
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage();
+            if (fooCase_ == FooOneofCase.FooMessage) {
               subBuilder.MergeFrom(FooMessage);
             }
             input.ReadMessage(subBuilder);
@@ -18026,29 +23762,39 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the TestRequiredOneof message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -18056,6 +23802,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           _hasBits0 = other._hasBits0;
           requiredDouble_ = other.requiredDouble_;
@@ -18063,6 +23810,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -18073,6 +23821,7 @@
 
         private double requiredDouble_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public double RequiredDouble {
           get { if ((_hasBits0 & 1) != 0) { return requiredDouble_; } else { return RequiredDoubleDefaultValue; } }
           set {
@@ -18082,21 +23831,25 @@
         }
         /// <summary>Gets whether the "required_double" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasRequiredDouble {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "required_double" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearRequiredDouble() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -18109,6 +23862,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasRequiredDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(RequiredDouble);
@@ -18119,12 +23873,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasRequiredDouble) {
             output.WriteRawTag(9);
             output.WriteDouble(RequiredDouble);
@@ -18132,9 +23891,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasRequiredDouble) {
+            output.WriteRawTag(9);
+            output.WriteDouble(RequiredDouble);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasRequiredDouble) {
@@ -18147,6 +23922,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -18158,7 +23934,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -18171,8 +23951,28 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 9: {
+                RequiredDouble = input.ReadDouble();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -18180,23 +23980,31 @@
 
   }
 
-  public sealed partial class TestRequiredMap : pb::IMessage<TestRequiredMap> {
+  public sealed partial class TestRequiredMap : pb::IMessage<TestRequiredMap>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRequiredMap> _parser = new pb::MessageParser<TestRequiredMap>(() => new TestRequiredMap());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRequiredMap> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[47]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredMap() {
       OnConstruction();
     }
@@ -18204,12 +24012,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredMap(TestRequiredMap other) : this() {
       foo_ = other.foo_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRequiredMap Clone() {
       return new TestRequiredMap(this);
     }
@@ -18220,16 +24030,19 @@
         = new pbc::MapField<int, global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage.Parser), 10);
     private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage> foo_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage> Foo {
       get { return foo_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRequiredMap);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRequiredMap other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -18242,6 +24055,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Foo.GetHashCode();
@@ -18252,19 +24066,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       foo_.WriteTo(output, _map_foo_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      foo_.WriteTo(ref output, _map_foo_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += foo_.CalculateSize(_map_foo_codec);
@@ -18275,6 +24107,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRequiredMap other) {
       if (other == null) {
         return;
@@ -18284,7 +24117,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -18297,30 +24134,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            foo_.AddEntriesFrom(ref input, _map_foo_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestRequiredMap message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Descriptor.NestedTypes[1]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -18328,6 +24194,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           _hasBits0 = other._hasBits0;
           requiredInt32_ = other.requiredInt32_;
@@ -18335,6 +24202,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -18345,6 +24213,7 @@
 
         private int requiredInt32_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int RequiredInt32 {
           get { if ((_hasBits0 & 1) != 0) { return requiredInt32_; } else { return RequiredInt32DefaultValue; } }
           set {
@@ -18354,21 +24223,25 @@
         }
         /// <summary>Gets whether the "required_int32" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasRequiredInt32 {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "required_int32" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearRequiredInt32() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -18381,6 +24254,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasRequiredInt32) hash ^= RequiredInt32.GetHashCode();
@@ -18391,12 +24265,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasRequiredInt32) {
             output.WriteRawTag(8);
             output.WriteInt32(RequiredInt32);
@@ -18404,9 +24283,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasRequiredInt32) {
+            output.WriteRawTag(8);
+            output.WriteInt32(RequiredInt32);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasRequiredInt32) {
@@ -18419,6 +24314,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -18430,7 +24326,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -18443,8 +24343,28 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                RequiredInt32 = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -18452,23 +24372,31 @@
 
   }
 
-  public sealed partial class TestPackedTypes : pb::IMessage<TestPackedTypes> {
+  public sealed partial class TestPackedTypes : pb::IMessage<TestPackedTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestPackedTypes> _parser = new pb::MessageParser<TestPackedTypes>(() => new TestPackedTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestPackedTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[48]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedTypes() {
       OnConstruction();
     }
@@ -18476,6 +24404,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedTypes(TestPackedTypes other) : this() {
       packedInt32_ = other.packedInt32_.Clone();
       packedInt64_ = other.packedInt64_.Clone();
@@ -18495,6 +24424,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedTypes Clone() {
       return new TestPackedTypes(this);
     }
@@ -18505,6 +24435,7 @@
         = pb::FieldCodec.ForInt32(722);
     private readonly pbc::RepeatedField<int> packedInt32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedInt32 {
       get { return packedInt32_; }
     }
@@ -18515,6 +24446,7 @@
         = pb::FieldCodec.ForInt64(730);
     private readonly pbc::RepeatedField<long> packedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedInt64 {
       get { return packedInt64_; }
     }
@@ -18525,6 +24457,7 @@
         = pb::FieldCodec.ForUInt32(738);
     private readonly pbc::RepeatedField<uint> packedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedUint32 {
       get { return packedUint32_; }
     }
@@ -18535,6 +24468,7 @@
         = pb::FieldCodec.ForUInt64(746);
     private readonly pbc::RepeatedField<ulong> packedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedUint64 {
       get { return packedUint64_; }
     }
@@ -18545,6 +24479,7 @@
         = pb::FieldCodec.ForSInt32(754);
     private readonly pbc::RepeatedField<int> packedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSint32 {
       get { return packedSint32_; }
     }
@@ -18555,6 +24490,7 @@
         = pb::FieldCodec.ForSInt64(762);
     private readonly pbc::RepeatedField<long> packedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSint64 {
       get { return packedSint64_; }
     }
@@ -18565,6 +24501,7 @@
         = pb::FieldCodec.ForFixed32(770);
     private readonly pbc::RepeatedField<uint> packedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedFixed32 {
       get { return packedFixed32_; }
     }
@@ -18575,6 +24512,7 @@
         = pb::FieldCodec.ForFixed64(778);
     private readonly pbc::RepeatedField<ulong> packedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedFixed64 {
       get { return packedFixed64_; }
     }
@@ -18585,6 +24523,7 @@
         = pb::FieldCodec.ForSFixed32(786);
     private readonly pbc::RepeatedField<int> packedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSfixed32 {
       get { return packedSfixed32_; }
     }
@@ -18595,6 +24534,7 @@
         = pb::FieldCodec.ForSFixed64(794);
     private readonly pbc::RepeatedField<long> packedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSfixed64 {
       get { return packedSfixed64_; }
     }
@@ -18605,6 +24545,7 @@
         = pb::FieldCodec.ForFloat(802);
     private readonly pbc::RepeatedField<float> packedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> PackedFloat {
       get { return packedFloat_; }
     }
@@ -18615,6 +24556,7 @@
         = pb::FieldCodec.ForDouble(810);
     private readonly pbc::RepeatedField<double> packedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> PackedDouble {
       get { return packedDouble_; }
     }
@@ -18625,6 +24567,7 @@
         = pb::FieldCodec.ForBool(818);
     private readonly pbc::RepeatedField<bool> packedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> PackedBool {
       get { return packedBool_; }
     }
@@ -18635,16 +24578,19 @@
         = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> packedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> PackedEnum {
       get { return packedEnum_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestPackedTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestPackedTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -18670,6 +24616,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= packedInt32_.GetHashCode();
@@ -18693,12 +24640,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       packedInt32_.WriteTo(output, _repeated_packedInt32_codec);
       packedInt64_.WriteTo(output, _repeated_packedInt64_codec);
       packedUint32_.WriteTo(output, _repeated_packedUint32_codec);
@@ -18716,9 +24668,35 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec);
+      packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec);
+      packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec);
+      packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec);
+      packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec);
+      packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec);
+      packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec);
+      packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec);
+      packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec);
+      packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec);
+      packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec);
+      packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec);
+      packedBool_.WriteTo(ref output, _repeated_packedBool_codec);
+      packedEnum_.WriteTo(ref output, _repeated_packedEnum_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += packedInt32_.CalculateSize(_repeated_packedInt32_codec);
@@ -18742,6 +24720,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestPackedTypes other) {
       if (other == null) {
         return;
@@ -18764,7 +24743,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -18843,31 +24826,125 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 722:
+          case 720: {
+            packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            packedEnum_.AddEntriesFrom(ref input, _repeated_packedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// A message with the same fields as TestPackedTypes, but without packing. Used
   /// to test packed &lt;-> unpacked wire compatibility.
   /// </summary>
-  public sealed partial class TestUnpackedTypes : pb::IMessage<TestUnpackedTypes> {
+  public sealed partial class TestUnpackedTypes : pb::IMessage<TestUnpackedTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestUnpackedTypes> _parser = new pb::MessageParser<TestUnpackedTypes>(() => new TestUnpackedTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestUnpackedTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[49]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedTypes() {
       OnConstruction();
     }
@@ -18875,6 +24952,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedTypes(TestUnpackedTypes other) : this() {
       unpackedInt32_ = other.unpackedInt32_.Clone();
       unpackedInt64_ = other.unpackedInt64_.Clone();
@@ -18894,6 +24972,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedTypes Clone() {
       return new TestUnpackedTypes(this);
     }
@@ -18904,6 +24983,7 @@
         = pb::FieldCodec.ForInt32(720);
     private readonly pbc::RepeatedField<int> unpackedInt32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedInt32 {
       get { return unpackedInt32_; }
     }
@@ -18914,6 +24994,7 @@
         = pb::FieldCodec.ForInt64(728);
     private readonly pbc::RepeatedField<long> unpackedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedInt64 {
       get { return unpackedInt64_; }
     }
@@ -18924,6 +25005,7 @@
         = pb::FieldCodec.ForUInt32(736);
     private readonly pbc::RepeatedField<uint> unpackedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedUint32 {
       get { return unpackedUint32_; }
     }
@@ -18934,6 +25016,7 @@
         = pb::FieldCodec.ForUInt64(744);
     private readonly pbc::RepeatedField<ulong> unpackedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedUint64 {
       get { return unpackedUint64_; }
     }
@@ -18944,6 +25027,7 @@
         = pb::FieldCodec.ForSInt32(752);
     private readonly pbc::RepeatedField<int> unpackedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSint32 {
       get { return unpackedSint32_; }
     }
@@ -18954,6 +25038,7 @@
         = pb::FieldCodec.ForSInt64(760);
     private readonly pbc::RepeatedField<long> unpackedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSint64 {
       get { return unpackedSint64_; }
     }
@@ -18964,6 +25049,7 @@
         = pb::FieldCodec.ForFixed32(773);
     private readonly pbc::RepeatedField<uint> unpackedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedFixed32 {
       get { return unpackedFixed32_; }
     }
@@ -18974,6 +25060,7 @@
         = pb::FieldCodec.ForFixed64(777);
     private readonly pbc::RepeatedField<ulong> unpackedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedFixed64 {
       get { return unpackedFixed64_; }
     }
@@ -18984,6 +25071,7 @@
         = pb::FieldCodec.ForSFixed32(789);
     private readonly pbc::RepeatedField<int> unpackedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSfixed32 {
       get { return unpackedSfixed32_; }
     }
@@ -18994,6 +25082,7 @@
         = pb::FieldCodec.ForSFixed64(793);
     private readonly pbc::RepeatedField<long> unpackedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSfixed64 {
       get { return unpackedSfixed64_; }
     }
@@ -19004,6 +25093,7 @@
         = pb::FieldCodec.ForFloat(805);
     private readonly pbc::RepeatedField<float> unpackedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> UnpackedFloat {
       get { return unpackedFloat_; }
     }
@@ -19014,6 +25104,7 @@
         = pb::FieldCodec.ForDouble(809);
     private readonly pbc::RepeatedField<double> unpackedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> UnpackedDouble {
       get { return unpackedDouble_; }
     }
@@ -19024,6 +25115,7 @@
         = pb::FieldCodec.ForBool(816);
     private readonly pbc::RepeatedField<bool> unpackedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> UnpackedBool {
       get { return unpackedBool_; }
     }
@@ -19034,16 +25126,19 @@
         = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> unpackedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.ForeignEnum> UnpackedEnum {
       get { return unpackedEnum_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestUnpackedTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestUnpackedTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -19069,6 +25164,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= unpackedInt32_.GetHashCode();
@@ -19092,12 +25188,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec);
       unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec);
       unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec);
@@ -19115,9 +25216,35 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec);
+      unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec);
+      unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec);
+      unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec);
+      unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec);
+      unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec);
+      unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec);
+      unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec);
+      unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec);
+      unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec);
+      unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec);
+      unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec);
+      unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec);
+      unpackedEnum_.WriteTo(ref output, _repeated_unpackedEnum_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec);
@@ -19141,6 +25268,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestUnpackedTypes other) {
       if (other == null) {
         return;
@@ -19163,7 +25291,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -19242,29 +25374,123 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 722:
+          case 720: {
+            unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            unpackedEnum_.AddEntriesFrom(ref input, _repeated_unpackedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestPackedExtensions : pb::IExtendableMessage<TestPackedExtensions> {
+  public sealed partial class TestPackedExtensions : pb::IExtendableMessage<TestPackedExtensions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestPackedExtensions> _parser = new pb::MessageParser<TestPackedExtensions>(() => new TestPackedExtensions());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestPackedExtensions> _extensions;
     private pb::ExtensionSet<TestPackedExtensions> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestPackedExtensions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[50]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedExtensions() {
       OnConstruction();
     }
@@ -19272,22 +25498,26 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedExtensions(TestPackedExtensions other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _extensions = pb::ExtensionSet.Clone(other._extensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedExtensions Clone() {
       return new TestPackedExtensions(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestPackedExtensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestPackedExtensions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -19302,6 +25532,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_extensions != null) {
@@ -19314,21 +25545,41 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_extensions != null) {
         _extensions.WriteTo(output);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_extensions != null) {
@@ -19341,6 +25592,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestPackedExtensions other) {
       if (other == null) {
         return;
@@ -19350,7 +25602,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -19361,8 +25617,26 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestPackedExtensions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -19387,25 +25661,33 @@
 
   }
 
-  public sealed partial class TestUnpackedExtensions : pb::IExtendableMessage<TestUnpackedExtensions> {
+  public sealed partial class TestUnpackedExtensions : pb::IExtendableMessage<TestUnpackedExtensions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestUnpackedExtensions> _parser = new pb::MessageParser<TestUnpackedExtensions>(() => new TestUnpackedExtensions());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestUnpackedExtensions> _extensions;
     private pb::ExtensionSet<TestUnpackedExtensions> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestUnpackedExtensions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[51]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedExtensions() {
       OnConstruction();
     }
@@ -19413,22 +25695,26 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedExtensions(TestUnpackedExtensions other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _extensions = pb::ExtensionSet.Clone(other._extensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedExtensions Clone() {
       return new TestUnpackedExtensions(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestUnpackedExtensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestUnpackedExtensions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -19443,6 +25729,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_extensions != null) {
@@ -19455,21 +25742,41 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_extensions != null) {
         _extensions.WriteTo(output);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_extensions != null) {
@@ -19482,6 +25789,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestUnpackedExtensions other) {
       if (other == null) {
         return;
@@ -19491,7 +25799,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -19502,8 +25814,26 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestUnpackedExtensions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -19533,24 +25863,32 @@
   /// a set of extensions to TestAllExtensions dynamically, based on the fields
   /// of this message type.
   /// </summary>
-  public sealed partial class TestDynamicExtensions : pb::IMessage<TestDynamicExtensions> {
+  public sealed partial class TestDynamicExtensions : pb::IMessage<TestDynamicExtensions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestDynamicExtensions> _parser = new pb::MessageParser<TestDynamicExtensions>(() => new TestDynamicExtensions());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestDynamicExtensions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[52]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDynamicExtensions() {
       OnConstruction();
     }
@@ -19558,19 +25896,21 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDynamicExtensions(TestDynamicExtensions other) : this() {
       _hasBits0 = other._hasBits0;
       scalarExtension_ = other.scalarExtension_;
       enumExtension_ = other.enumExtension_;
       dynamicEnumExtension_ = other.dynamicEnumExtension_;
-      messageExtension_ = other.HasMessageExtension ? other.messageExtension_.Clone() : null;
-      dynamicMessageExtension_ = other.HasDynamicMessageExtension ? other.dynamicMessageExtension_.Clone() : null;
+      messageExtension_ = other.messageExtension_ != null ? other.messageExtension_.Clone() : null;
+      dynamicMessageExtension_ = other.dynamicMessageExtension_ != null ? other.dynamicMessageExtension_.Clone() : null;
       repeatedExtension_ = other.repeatedExtension_.Clone();
       packedExtension_ = other.packedExtension_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDynamicExtensions Clone() {
       return new TestDynamicExtensions(this);
     }
@@ -19581,6 +25921,7 @@
 
     private uint scalarExtension_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint ScalarExtension {
       get { if ((_hasBits0 & 1) != 0) { return scalarExtension_; } else { return ScalarExtensionDefaultValue; } }
       set {
@@ -19590,11 +25931,13 @@
     }
     /// <summary>Gets whether the "scalar_extension" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasScalarExtension {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "scalar_extension" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearScalarExtension() {
       _hasBits0 &= ~1;
     }
@@ -19605,6 +25948,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum enumExtension_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum EnumExtension {
       get { if ((_hasBits0 & 2) != 0) { return enumExtension_; } else { return EnumExtensionDefaultValue; } }
       set {
@@ -19614,11 +25958,13 @@
     }
     /// <summary>Gets whether the "enum_extension" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasEnumExtension {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "enum_extension" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearEnumExtension() {
       _hasBits0 &= ~2;
     }
@@ -19629,6 +25975,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType dynamicEnumExtension_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType DynamicEnumExtension {
       get { if ((_hasBits0 & 4) != 0) { return dynamicEnumExtension_; } else { return DynamicEnumExtensionDefaultValue; } }
       set {
@@ -19638,11 +25985,13 @@
     }
     /// <summary>Gets whether the "dynamic_enum_extension" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDynamicEnumExtension {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "dynamic_enum_extension" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDynamicEnumExtension() {
       _hasBits0 &= ~4;
     }
@@ -19651,43 +26000,25 @@
     public const int MessageExtensionFieldNumber = 2003;
     private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage messageExtension_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage MessageExtension {
       get { return messageExtension_; }
       set {
         messageExtension_ = value;
       }
     }
-    /// <summary>Gets whether the message_extension field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasMessageExtension {
-      get { return messageExtension_ != null; }
-    }
-    /// <summary>Clears the value of the message_extension field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearMessageExtension() {
-      messageExtension_ = null;
-    }
 
     /// <summary>Field number for the "dynamic_message_extension" field.</summary>
     public const int DynamicMessageExtensionFieldNumber = 2004;
     private global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType dynamicMessageExtension_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType DynamicMessageExtension {
       get { return dynamicMessageExtension_; }
       set {
         dynamicMessageExtension_ = value;
       }
     }
-    /// <summary>Gets whether the dynamic_message_extension field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasDynamicMessageExtension {
-      get { return dynamicMessageExtension_ != null; }
-    }
-    /// <summary>Clears the value of the dynamic_message_extension field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearDynamicMessageExtension() {
-      dynamicMessageExtension_ = null;
-    }
 
     /// <summary>Field number for the "repeated_extension" field.</summary>
     public const int RepeatedExtensionFieldNumber = 2005;
@@ -19695,6 +26026,7 @@
         = pb::FieldCodec.ForString(16042);
     private readonly pbc::RepeatedField<string> repeatedExtension_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedExtension {
       get { return repeatedExtension_; }
     }
@@ -19705,16 +26037,19 @@
         = pb::FieldCodec.ForSInt32(16050);
     private readonly pbc::RepeatedField<int> packedExtension_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedExtension {
       get { return packedExtension_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestDynamicExtensions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestDynamicExtensions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -19733,13 +26068,14 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasScalarExtension) hash ^= ScalarExtension.GetHashCode();
       if (HasEnumExtension) hash ^= EnumExtension.GetHashCode();
       if (HasDynamicEnumExtension) hash ^= DynamicEnumExtension.GetHashCode();
-      if (HasMessageExtension) hash ^= MessageExtension.GetHashCode();
-      if (HasDynamicMessageExtension) hash ^= DynamicMessageExtension.GetHashCode();
+      if (messageExtension_ != null) hash ^= MessageExtension.GetHashCode();
+      if (dynamicMessageExtension_ != null) hash ^= DynamicMessageExtension.GetHashCode();
       hash ^= repeatedExtension_.GetHashCode();
       hash ^= packedExtension_.GetHashCode();
       if (_unknownFields != null) {
@@ -19749,12 +26085,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasScalarExtension) {
         output.WriteRawTag(133, 125);
         output.WriteFixed32(ScalarExtension);
@@ -19767,11 +26108,11 @@
         output.WriteRawTag(144, 125);
         output.WriteEnum((int) DynamicEnumExtension);
       }
-      if (HasMessageExtension) {
+      if (messageExtension_ != null) {
         output.WriteRawTag(154, 125);
         output.WriteMessage(MessageExtension);
       }
-      if (HasDynamicMessageExtension) {
+      if (dynamicMessageExtension_ != null) {
         output.WriteRawTag(162, 125);
         output.WriteMessage(DynamicMessageExtension);
       }
@@ -19780,9 +26121,43 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasScalarExtension) {
+        output.WriteRawTag(133, 125);
+        output.WriteFixed32(ScalarExtension);
+      }
+      if (HasEnumExtension) {
+        output.WriteRawTag(136, 125);
+        output.WriteEnum((int) EnumExtension);
+      }
+      if (HasDynamicEnumExtension) {
+        output.WriteRawTag(144, 125);
+        output.WriteEnum((int) DynamicEnumExtension);
+      }
+      if (messageExtension_ != null) {
+        output.WriteRawTag(154, 125);
+        output.WriteMessage(MessageExtension);
+      }
+      if (dynamicMessageExtension_ != null) {
+        output.WriteRawTag(162, 125);
+        output.WriteMessage(DynamicMessageExtension);
+      }
+      repeatedExtension_.WriteTo(ref output, _repeated_repeatedExtension_codec);
+      packedExtension_.WriteTo(ref output, _repeated_packedExtension_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasScalarExtension) {
@@ -19794,10 +26169,10 @@
       if (HasDynamicEnumExtension) {
         size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) DynamicEnumExtension);
       }
-      if (HasMessageExtension) {
+      if (messageExtension_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(MessageExtension);
       }
-      if (HasDynamicMessageExtension) {
+      if (dynamicMessageExtension_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(DynamicMessageExtension);
       }
       size += repeatedExtension_.CalculateSize(_repeated_repeatedExtension_codec);
@@ -19809,6 +26184,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestDynamicExtensions other) {
       if (other == null) {
         return;
@@ -19822,14 +26198,14 @@
       if (other.HasDynamicEnumExtension) {
         DynamicEnumExtension = other.DynamicEnumExtension;
       }
-      if (other.HasMessageExtension) {
-        if (!HasMessageExtension) {
+      if (other.messageExtension_ != null) {
+        if (messageExtension_ == null) {
           MessageExtension = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
         }
         MessageExtension.MergeFrom(other.MessageExtension);
       }
-      if (other.HasDynamicMessageExtension) {
-        if (!HasDynamicMessageExtension) {
+      if (other.dynamicMessageExtension_ != null) {
+        if (dynamicMessageExtension_ == null) {
           DynamicMessageExtension = new global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType();
         }
         DynamicMessageExtension.MergeFrom(other.DynamicMessageExtension);
@@ -19840,7 +26216,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -19860,14 +26240,14 @@
             break;
           }
           case 16026: {
-            if (!HasMessageExtension) {
+            if (messageExtension_ == null) {
               MessageExtension = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
             }
             input.ReadMessage(MessageExtension);
             break;
           }
           case 16034: {
-            if (!HasDynamicMessageExtension) {
+            if (dynamicMessageExtension_ == null) {
               DynamicMessageExtension = new global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType();
             }
             input.ReadMessage(DynamicMessageExtension);
@@ -19884,11 +26264,63 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 16005: {
+            ScalarExtension = input.ReadFixed32();
+            break;
+          }
+          case 16008: {
+            EnumExtension = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 16016: {
+            DynamicEnumExtension = (global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType) input.ReadEnum();
+            break;
+          }
+          case 16026: {
+            if (messageExtension_ == null) {
+              MessageExtension = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
+            }
+            input.ReadMessage(MessageExtension);
+            break;
+          }
+          case 16034: {
+            if (dynamicMessageExtension_ == null) {
+              DynamicMessageExtension = new global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType();
+            }
+            input.ReadMessage(DynamicMessageExtension);
+            break;
+          }
+          case 16042: {
+            repeatedExtension_.AddEntriesFrom(ref input, _repeated_repeatedExtension_codec);
+            break;
+          }
+          case 16050:
+          case 16048: {
+            packedExtension_.AddEntriesFrom(ref input, _repeated_packedExtension_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestDynamicExtensions message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum DynamicEnumType {
         [pbr::OriginalName("DYNAMIC_FOO")] DynamicFoo = 2200,
@@ -19896,24 +26328,32 @@
         [pbr::OriginalName("DYNAMIC_BAZ")] DynamicBaz = 2202,
       }
 
-      public sealed partial class DynamicMessageType : pb::IMessage<DynamicMessageType> {
+      public sealed partial class DynamicMessageType : pb::IMessage<DynamicMessageType>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<DynamicMessageType> _parser = new pb::MessageParser<DynamicMessageType>(() => new DynamicMessageType());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<DynamicMessageType> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public DynamicMessageType() {
           OnConstruction();
         }
@@ -19921,6 +26361,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public DynamicMessageType(DynamicMessageType other) : this() {
           _hasBits0 = other._hasBits0;
           dynamicField_ = other.dynamicField_;
@@ -19928,6 +26369,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public DynamicMessageType Clone() {
           return new DynamicMessageType(this);
         }
@@ -19938,6 +26380,7 @@
 
         private int dynamicField_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int DynamicField {
           get { if ((_hasBits0 & 1) != 0) { return dynamicField_; } else { return DynamicFieldDefaultValue; } }
           set {
@@ -19947,21 +26390,25 @@
         }
         /// <summary>Gets whether the "dynamic_field" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasDynamicField {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "dynamic_field" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearDynamicField() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as DynamicMessageType);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(DynamicMessageType other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -19974,6 +26421,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasDynamicField) hash ^= DynamicField.GetHashCode();
@@ -19984,12 +26432,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasDynamicField) {
             output.WriteRawTag(160, 131, 1);
             output.WriteInt32(DynamicField);
@@ -19997,9 +26450,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasDynamicField) {
+            output.WriteRawTag(160, 131, 1);
+            output.WriteInt32(DynamicField);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasDynamicField) {
@@ -20012,6 +26481,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(DynamicMessageType other) {
           if (other == null) {
             return;
@@ -20023,7 +26493,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -20036,8 +26510,28 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 16800: {
+                DynamicField = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -20045,23 +26539,31 @@
 
   }
 
-  public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage<TestRepeatedScalarDifferentTagSizes> {
+  public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage<TestRepeatedScalarDifferentTagSizes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRepeatedScalarDifferentTagSizes> _parser = new pb::MessageParser<TestRepeatedScalarDifferentTagSizes>(() => new TestRepeatedScalarDifferentTagSizes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRepeatedScalarDifferentTagSizes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[53]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRepeatedScalarDifferentTagSizes() {
       OnConstruction();
     }
@@ -20069,6 +26571,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() {
       repeatedFixed32_ = other.repeatedFixed32_.Clone();
       repeatedInt32_ = other.repeatedInt32_.Clone();
@@ -20080,6 +26583,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRepeatedScalarDifferentTagSizes Clone() {
       return new TestRepeatedScalarDifferentTagSizes(this);
     }
@@ -20095,6 +26599,7 @@
     /// in TestAllTypes didn't trigger the check.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedFixed32 {
       get { return repeatedFixed32_; }
     }
@@ -20108,6 +26613,7 @@
     /// Check for a varint type, just for good measure.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
@@ -20121,6 +26627,7 @@
     /// These have two-byte tags.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedFixed64 {
       get { return repeatedFixed64_; }
     }
@@ -20131,6 +26638,7 @@
         = pb::FieldCodec.ForInt64(16376);
     private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedInt64 {
       get { return repeatedInt64_; }
     }
@@ -20144,6 +26652,7 @@
     /// Three byte tags.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> RepeatedFloat {
       get { return repeatedFloat_; }
     }
@@ -20154,16 +26663,19 @@
         = pb::FieldCodec.ForUInt64(2097144);
     private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedUint64 {
       get { return repeatedUint64_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRepeatedScalarDifferentTagSizes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRepeatedScalarDifferentTagSizes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -20181,6 +26693,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= repeatedFixed32_.GetHashCode();
@@ -20196,12 +26709,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
       repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
       repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
@@ -20211,9 +26729,27 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec);
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec);
+      repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec);
+      repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec);
+      repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
@@ -20229,6 +26765,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) {
       if (other == null) {
         return;
@@ -20243,7 +26780,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -20282,33 +26823,87 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 98:
+          case 101: {
+            repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 106:
+          case 104: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 16370:
+          case 16369: {
+            repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 16378:
+          case 16376: {
+            repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 2097138:
+          case 2097141: {
+            repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 2097146:
+          case 2097144: {
+            repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test that if an optional or required message/group field appears multiple
   /// times in the input, they need to be merged.
   /// </summary>
-  public sealed partial class TestParsingMerge : pb::IExtendableMessage<TestParsingMerge> {
+  public sealed partial class TestParsingMerge : pb::IExtendableMessage<TestParsingMerge>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestParsingMerge> _parser = new pb::MessageParser<TestParsingMerge>(() => new TestParsingMerge());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestParsingMerge> _extensions;
     private pb::ExtensionSet<TestParsingMerge> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestParsingMerge> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[54]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestParsingMerge() {
       OnConstruction();
     }
@@ -20316,9 +26911,10 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestParsingMerge(TestParsingMerge other) : this() {
-      requiredAllTypes_ = other.HasRequiredAllTypes ? other.requiredAllTypes_.Clone() : null;
-      optionalAllTypes_ = other.HasOptionalAllTypes ? other.optionalAllTypes_.Clone() : null;
+      requiredAllTypes_ = other.requiredAllTypes_ != null ? other.requiredAllTypes_.Clone() : null;
+      optionalAllTypes_ = other.optionalAllTypes_ != null ? other.optionalAllTypes_.Clone() : null;
       repeatedAllTypes_ = other.repeatedAllTypes_.Clone();
       optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null;
       repeatedGroup_ = other.repeatedGroup_.Clone();
@@ -20327,6 +26923,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestParsingMerge Clone() {
       return new TestParsingMerge(this);
     }
@@ -20335,43 +26932,25 @@
     public const int RequiredAllTypesFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes requiredAllTypes_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes RequiredAllTypes {
       get { return requiredAllTypes_; }
       set {
         requiredAllTypes_ = value;
       }
     }
-    /// <summary>Gets whether the required_all_types field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasRequiredAllTypes {
-      get { return requiredAllTypes_ != null; }
-    }
-    /// <summary>Clears the value of the required_all_types field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearRequiredAllTypes() {
-      requiredAllTypes_ = null;
-    }
 
     /// <summary>Field number for the "optional_all_types" field.</summary>
     public const int OptionalAllTypesFieldNumber = 2;
     private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes optionalAllTypes_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes OptionalAllTypes {
       get { return optionalAllTypes_; }
       set {
         optionalAllTypes_ = value;
       }
     }
-    /// <summary>Gets whether the optional_all_types field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalAllTypes {
-      get { return optionalAllTypes_ != null; }
-    }
-    /// <summary>Clears the value of the optional_all_types field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalAllTypes() {
-      optionalAllTypes_ = null;
-    }
 
     /// <summary>Field number for the "repeated_all_types" field.</summary>
     public const int RepeatedAllTypesFieldNumber = 3;
@@ -20379,6 +26958,7 @@
         = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> repeatedAllTypes_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> RepeatedAllTypes {
       get { return repeatedAllTypes_; }
     }
@@ -20387,6 +26967,7 @@
     public const int OptionalGroupFieldNumber = 10;
     private global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup optionalGroup_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup OptionalGroup {
       get { return optionalGroup_; }
       set {
@@ -20395,11 +26976,13 @@
     }
     /// <summary>Gets whether the optionalgroup field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalGroup {
       get { return optionalGroup_ != null; }
     }
     /// <summary>Clears the value of the optionalgroup field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalGroup() {
       optionalGroup_ = null;
     }
@@ -20410,16 +26993,19 @@
         = pb::FieldCodec.ForGroup(163, 164, global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedGroup.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedGroup> repeatedGroup_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedGroup>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedGroup> RepeatedGroup {
       get { return repeatedGroup_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestParsingMerge);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestParsingMerge other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -20439,10 +27025,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
-      if (HasRequiredAllTypes) hash ^= RequiredAllTypes.GetHashCode();
-      if (HasOptionalAllTypes) hash ^= OptionalAllTypes.GetHashCode();
+      if (requiredAllTypes_ != null) hash ^= RequiredAllTypes.GetHashCode();
+      if (optionalAllTypes_ != null) hash ^= OptionalAllTypes.GetHashCode();
       hash ^= repeatedAllTypes_.GetHashCode();
       if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode();
       hash ^= repeatedGroup_.GetHashCode();
@@ -20456,17 +27043,22 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (HasRequiredAllTypes) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (requiredAllTypes_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(RequiredAllTypes);
       }
-      if (HasOptionalAllTypes) {
+      if (optionalAllTypes_ != null) {
         output.WriteRawTag(18);
         output.WriteMessage(OptionalAllTypes);
       }
@@ -20483,15 +27075,45 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (requiredAllTypes_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(RequiredAllTypes);
+      }
+      if (optionalAllTypes_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(OptionalAllTypes);
+      }
+      repeatedAllTypes_.WriteTo(ref output, _repeated_repeatedAllTypes_codec);
+      if (HasOptionalGroup) {
+        output.WriteRawTag(83);
+        output.WriteGroup(OptionalGroup);
+        output.WriteRawTag(84);
+      }
+      repeatedGroup_.WriteTo(ref output, _repeated_repeatedGroup_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
-      if (HasRequiredAllTypes) {
+      if (requiredAllTypes_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(RequiredAllTypes);
       }
-      if (HasOptionalAllTypes) {
+      if (optionalAllTypes_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalAllTypes);
       }
       size += repeatedAllTypes_.CalculateSize(_repeated_repeatedAllTypes_codec);
@@ -20509,18 +27131,19 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestParsingMerge other) {
       if (other == null) {
         return;
       }
-      if (other.HasRequiredAllTypes) {
-        if (!HasRequiredAllTypes) {
+      if (other.requiredAllTypes_ != null) {
+        if (requiredAllTypes_ == null) {
           RequiredAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
         }
         RequiredAllTypes.MergeFrom(other.RequiredAllTypes);
       }
-      if (other.HasOptionalAllTypes) {
-        if (!HasOptionalAllTypes) {
+      if (other.optionalAllTypes_ != null) {
+        if (optionalAllTypes_ == null) {
           OptionalAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
         }
         OptionalAllTypes.MergeFrom(other.OptionalAllTypes);
@@ -20538,7 +27161,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -20548,14 +27175,14 @@
             }
             break;
           case 10: {
-            if (!HasRequiredAllTypes) {
+            if (requiredAllTypes_ == null) {
               RequiredAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             input.ReadMessage(RequiredAllTypes);
             break;
           }
           case 18: {
-            if (!HasOptionalAllTypes) {
+            if (optionalAllTypes_ == null) {
               OptionalAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             input.ReadMessage(OptionalAllTypes);
@@ -20578,8 +27205,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 10: {
+            if (requiredAllTypes_ == null) {
+              RequiredAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            }
+            input.ReadMessage(RequiredAllTypes);
+            break;
+          }
+          case 18: {
+            if (optionalAllTypes_ == null) {
+              OptionalAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            }
+            input.ReadMessage(OptionalAllTypes);
+            break;
+          }
+          case 26: {
+            repeatedAllTypes_.AddEntriesFrom(ref input, _repeated_repeatedAllTypes_codec);
+            break;
+          }
+          case 83: {
+            if (!HasOptionalGroup) {
+              OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup();
+            }
+            input.ReadGroup(OptionalGroup);
+            break;
+          }
+          case 163: {
+            repeatedGroup_.AddEntriesFrom(ref input, _repeated_repeatedGroup_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestParsingMerge, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -20605,6 +27279,7 @@
     #region Nested types
     /// <summary>Container for nested types declared in the TestParsingMerge message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
@@ -20613,23 +27288,31 @@
       /// Repeated fields in RepeatedFieldsGenerator are expected to be merged into
       /// the corresponding required/optional fields in TestParsingMerge.
       /// </summary>
-      public sealed partial class RepeatedFieldsGenerator : pb::IMessage<RepeatedFieldsGenerator> {
+      public sealed partial class RepeatedFieldsGenerator : pb::IMessage<RepeatedFieldsGenerator>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<RepeatedFieldsGenerator> _parser = new pb::MessageParser<RepeatedFieldsGenerator>(() => new RepeatedFieldsGenerator());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<RepeatedFieldsGenerator> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedFieldsGenerator() {
           OnConstruction();
         }
@@ -20637,6 +27320,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedFieldsGenerator(RepeatedFieldsGenerator other) : this() {
           field1_ = other.field1_.Clone();
           field2_ = other.field2_.Clone();
@@ -20649,6 +27333,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedFieldsGenerator Clone() {
           return new RepeatedFieldsGenerator(this);
         }
@@ -20659,6 +27344,7 @@
             = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> field1_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> Field1 {
           get { return field1_; }
         }
@@ -20669,6 +27355,7 @@
             = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> field2_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> Field2 {
           get { return field2_; }
         }
@@ -20679,6 +27366,7 @@
             = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> field3_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> Field3 {
           get { return field3_; }
         }
@@ -20689,6 +27377,7 @@
             = pb::FieldCodec.ForGroup(83, 84, global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group1.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group1> group1_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group1>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group1> Group1 {
           get { return group1_; }
         }
@@ -20699,6 +27388,7 @@
             = pb::FieldCodec.ForGroup(163, 164, global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group2.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group2> group2_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group2>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group2> Group2 {
           get { return group2_; }
         }
@@ -20709,6 +27399,7 @@
             = pb::FieldCodec.ForMessage(8002, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> ext1_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> Ext1 {
           get { return ext1_; }
         }
@@ -20719,16 +27410,19 @@
             = pb::FieldCodec.ForMessage(8010, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser);
         private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> ext2_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> Ext2 {
           get { return ext2_; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as RepeatedFieldsGenerator);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(RepeatedFieldsGenerator other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -20747,6 +27441,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           hash ^= field1_.GetHashCode();
@@ -20763,12 +27458,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           field1_.WriteTo(output, _repeated_field1_codec);
           field2_.WriteTo(output, _repeated_field2_codec);
           field3_.WriteTo(output, _repeated_field3_codec);
@@ -20779,9 +27479,28 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          field1_.WriteTo(ref output, _repeated_field1_codec);
+          field2_.WriteTo(ref output, _repeated_field2_codec);
+          field3_.WriteTo(ref output, _repeated_field3_codec);
+          group1_.WriteTo(ref output, _repeated_group1_codec);
+          group2_.WriteTo(ref output, _repeated_group2_codec);
+          ext1_.WriteTo(ref output, _repeated_ext1_codec);
+          ext2_.WriteTo(ref output, _repeated_ext2_codec);
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           size += field1_.CalculateSize(_repeated_field1_codec);
@@ -20798,6 +27517,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(RepeatedFieldsGenerator other) {
           if (other == null) {
             return;
@@ -20813,7 +27533,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -20850,29 +27574,82 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                field1_.AddEntriesFrom(ref input, _repeated_field1_codec);
+                break;
+              }
+              case 18: {
+                field2_.AddEntriesFrom(ref input, _repeated_field2_codec);
+                break;
+              }
+              case 26: {
+                field3_.AddEntriesFrom(ref input, _repeated_field3_codec);
+                break;
+              }
+              case 83: {
+                group1_.AddEntriesFrom(ref input, _repeated_group1_codec);
+                break;
+              }
+              case 163: {
+                group2_.AddEntriesFrom(ref input, _repeated_group2_codec);
+                break;
+              }
+              case 8002: {
+                ext1_.AddEntriesFrom(ref input, _repeated_ext1_codec);
+                break;
+              }
+              case 8010: {
+                ext2_.AddEntriesFrom(ref input, _repeated_ext2_codec);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
         #region Nested types
         /// <summary>Container for nested types declared in the RepeatedFieldsGenerator message type.</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static partial class Types {
-          public sealed partial class Group1 : pb::IMessage<Group1> {
+          public sealed partial class Group1 : pb::IMessage<Group1>
+          #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              , pb::IBufferMessage
+          #endif
+          {
             private static readonly pb::MessageParser<Group1> _parser = new pb::MessageParser<Group1>(() => new Group1());
             private pb::UnknownFieldSet _unknownFields;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pb::MessageParser<Group1> Parser { get { return _parser; } }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pbr::MessageDescriptor Descriptor {
               get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Descriptor.NestedTypes[0]; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             pbr::MessageDescriptor pb::IMessage.Descriptor {
               get { return Descriptor; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public Group1() {
               OnConstruction();
             }
@@ -20880,12 +27657,14 @@
             partial void OnConstruction();
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public Group1(Group1 other) : this() {
-              field1_ = other.HasField1 ? other.field1_.Clone() : null;
+              field1_ = other.field1_ != null ? other.field1_.Clone() : null;
               _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public Group1 Clone() {
               return new Group1(this);
             }
@@ -20894,29 +27673,22 @@
             public const int Field1FieldNumber = 11;
             private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes field1_;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes Field1 {
               get { return field1_; }
               set {
                 field1_ = value;
               }
             }
-            /// <summary>Gets whether the field1 field is set</summary>
-            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-            public bool HasField1 {
-              get { return field1_ != null; }
-            }
-            /// <summary>Clears the value of the field1 field</summary>
-            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-            public void ClearField1() {
-              field1_ = null;
-            }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override bool Equals(object other) {
               return Equals(other as Group1);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public bool Equals(Group1 other) {
               if (ReferenceEquals(other, null)) {
                 return false;
@@ -20929,9 +27701,10 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override int GetHashCode() {
               int hash = 1;
-              if (HasField1) hash ^= Field1.GetHashCode();
+              if (field1_ != null) hash ^= Field1.GetHashCode();
               if (_unknownFields != null) {
                 hash ^= _unknownFields.GetHashCode();
               }
@@ -20939,25 +27712,46 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override string ToString() {
               return pb::JsonFormatter.ToDiagnosticString(this);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void WriteTo(pb::CodedOutputStream output) {
-              if (HasField1) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              output.WriteRawMessage(this);
+            #else
+              if (field1_ != null) {
                 output.WriteRawTag(90);
                 output.WriteMessage(Field1);
               }
               if (_unknownFields != null) {
                 _unknownFields.WriteTo(output);
               }
+            #endif
             }
 
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+              if (field1_ != null) {
+                output.WriteRawTag(90);
+                output.WriteMessage(Field1);
+              }
+              if (_unknownFields != null) {
+                _unknownFields.WriteTo(ref output);
+              }
+            }
+            #endif
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public int CalculateSize() {
               int size = 0;
-              if (HasField1) {
+              if (field1_ != null) {
                 size += 1 + pb::CodedOutputStream.ComputeMessageSize(Field1);
               }
               if (_unknownFields != null) {
@@ -20967,12 +27761,13 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(Group1 other) {
               if (other == null) {
                 return;
               }
-              if (other.HasField1) {
-                if (!HasField1) {
+              if (other.field1_ != null) {
+                if (field1_ == null) {
                   Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
                 }
                 Field1.MergeFrom(other.Field1);
@@ -20981,7 +27776,11 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(pb::CodedInputStream input) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              input.ReadRawMessage(this);
+            #else
               uint tag;
               while ((tag = input.ReadTag()) != 0) {
                 switch(tag) {
@@ -20991,7 +27790,31 @@
                     _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                     break;
                   case 90: {
-                    if (!HasField1) {
+                    if (field1_ == null) {
+                      Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+                    }
+                    input.ReadMessage(Field1);
+                    break;
+                  }
+                }
+              }
+            #endif
+            }
+
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  case 84:
+                    return;
+                  default:
+                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                    break;
+                  case 90: {
+                    if (field1_ == null) {
                       Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
                     }
                     input.ReadMessage(Field1);
@@ -21000,26 +27823,35 @@
                 }
               }
             }
+            #endif
 
           }
 
-          public sealed partial class Group2 : pb::IMessage<Group2> {
+          public sealed partial class Group2 : pb::IMessage<Group2>
+          #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              , pb::IBufferMessage
+          #endif
+          {
             private static readonly pb::MessageParser<Group2> _parser = new pb::MessageParser<Group2>(() => new Group2());
             private pb::UnknownFieldSet _unknownFields;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pb::MessageParser<Group2> Parser { get { return _parser; } }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pbr::MessageDescriptor Descriptor {
               get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Descriptor.NestedTypes[1]; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             pbr::MessageDescriptor pb::IMessage.Descriptor {
               get { return Descriptor; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public Group2() {
               OnConstruction();
             }
@@ -21027,12 +27859,14 @@
             partial void OnConstruction();
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public Group2(Group2 other) : this() {
-              field1_ = other.HasField1 ? other.field1_.Clone() : null;
+              field1_ = other.field1_ != null ? other.field1_.Clone() : null;
               _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public Group2 Clone() {
               return new Group2(this);
             }
@@ -21041,29 +27875,22 @@
             public const int Field1FieldNumber = 21;
             private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes field1_;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes Field1 {
               get { return field1_; }
               set {
                 field1_ = value;
               }
             }
-            /// <summary>Gets whether the field1 field is set</summary>
-            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-            public bool HasField1 {
-              get { return field1_ != null; }
-            }
-            /// <summary>Clears the value of the field1 field</summary>
-            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-            public void ClearField1() {
-              field1_ = null;
-            }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override bool Equals(object other) {
               return Equals(other as Group2);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public bool Equals(Group2 other) {
               if (ReferenceEquals(other, null)) {
                 return false;
@@ -21076,9 +27903,10 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override int GetHashCode() {
               int hash = 1;
-              if (HasField1) hash ^= Field1.GetHashCode();
+              if (field1_ != null) hash ^= Field1.GetHashCode();
               if (_unknownFields != null) {
                 hash ^= _unknownFields.GetHashCode();
               }
@@ -21086,25 +27914,46 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override string ToString() {
               return pb::JsonFormatter.ToDiagnosticString(this);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void WriteTo(pb::CodedOutputStream output) {
-              if (HasField1) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              output.WriteRawMessage(this);
+            #else
+              if (field1_ != null) {
                 output.WriteRawTag(170, 1);
                 output.WriteMessage(Field1);
               }
               if (_unknownFields != null) {
                 _unknownFields.WriteTo(output);
               }
+            #endif
             }
 
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+              if (field1_ != null) {
+                output.WriteRawTag(170, 1);
+                output.WriteMessage(Field1);
+              }
+              if (_unknownFields != null) {
+                _unknownFields.WriteTo(ref output);
+              }
+            }
+            #endif
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public int CalculateSize() {
               int size = 0;
-              if (HasField1) {
+              if (field1_ != null) {
                 size += 2 + pb::CodedOutputStream.ComputeMessageSize(Field1);
               }
               if (_unknownFields != null) {
@@ -21114,12 +27963,13 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(Group2 other) {
               if (other == null) {
                 return;
               }
-              if (other.HasField1) {
-                if (!HasField1) {
+              if (other.field1_ != null) {
+                if (field1_ == null) {
                   Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
                 }
                 Field1.MergeFrom(other.Field1);
@@ -21128,7 +27978,11 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(pb::CodedInputStream input) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              input.ReadRawMessage(this);
+            #else
               uint tag;
               while ((tag = input.ReadTag()) != 0) {
                 switch(tag) {
@@ -21138,7 +27992,31 @@
                     _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                     break;
                   case 170: {
-                    if (!HasField1) {
+                    if (field1_ == null) {
+                      Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+                    }
+                    input.ReadMessage(Field1);
+                    break;
+                  }
+                }
+              }
+            #endif
+            }
+
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  case 164:
+                    return;
+                  default:
+                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                    break;
+                  case 170: {
+                    if (field1_ == null) {
                       Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
                     }
                     input.ReadMessage(Field1);
@@ -21147,6 +28025,7 @@
                 }
               }
             }
+            #endif
 
           }
 
@@ -21155,23 +28034,31 @@
 
       }
 
-      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup> {
+      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<OptionalGroup> _parser = new pb::MessageParser<OptionalGroup>(() => new OptionalGroup());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<OptionalGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Descriptor.NestedTypes[1]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup() {
           OnConstruction();
         }
@@ -21179,12 +28066,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup(OptionalGroup other) : this() {
-          optionalGroupAllTypes_ = other.HasOptionalGroupAllTypes ? other.optionalGroupAllTypes_.Clone() : null;
+          optionalGroupAllTypes_ = other.optionalGroupAllTypes_ != null ? other.optionalGroupAllTypes_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup Clone() {
           return new OptionalGroup(this);
         }
@@ -21193,29 +28082,22 @@
         public const int OptionalGroupAllTypesFieldNumber = 11;
         private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes optionalGroupAllTypes_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes OptionalGroupAllTypes {
           get { return optionalGroupAllTypes_; }
           set {
             optionalGroupAllTypes_ = value;
           }
         }
-        /// <summary>Gets whether the optional_group_all_types field is set</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public bool HasOptionalGroupAllTypes {
-          get { return optionalGroupAllTypes_ != null; }
-        }
-        /// <summary>Clears the value of the optional_group_all_types field</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public void ClearOptionalGroupAllTypes() {
-          optionalGroupAllTypes_ = null;
-        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as OptionalGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(OptionalGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -21228,9 +28110,10 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
-          if (HasOptionalGroupAllTypes) hash ^= OptionalGroupAllTypes.GetHashCode();
+          if (optionalGroupAllTypes_ != null) hash ^= OptionalGroupAllTypes.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -21238,25 +28121,46 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (HasOptionalGroupAllTypes) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
+          if (optionalGroupAllTypes_ != null) {
             output.WriteRawTag(90);
             output.WriteMessage(OptionalGroupAllTypes);
           }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (optionalGroupAllTypes_ != null) {
+            output.WriteRawTag(90);
+            output.WriteMessage(OptionalGroupAllTypes);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
-          if (HasOptionalGroupAllTypes) {
+          if (optionalGroupAllTypes_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalGroupAllTypes);
           }
           if (_unknownFields != null) {
@@ -21266,12 +28170,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(OptionalGroup other) {
           if (other == null) {
             return;
           }
-          if (other.HasOptionalGroupAllTypes) {
-            if (!HasOptionalGroupAllTypes) {
+          if (other.optionalGroupAllTypes_ != null) {
+            if (optionalGroupAllTypes_ == null) {
               OptionalGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             OptionalGroupAllTypes.MergeFrom(other.OptionalGroupAllTypes);
@@ -21280,7 +28185,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -21290,7 +28199,31 @@
                 _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
               case 90: {
-                if (!HasOptionalGroupAllTypes) {
+                if (optionalGroupAllTypes_ == null) {
+                  OptionalGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+                }
+                input.ReadMessage(OptionalGroupAllTypes);
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 84:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 90: {
+                if (optionalGroupAllTypes_ == null) {
                   OptionalGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
                 }
                 input.ReadMessage(OptionalGroupAllTypes);
@@ -21299,26 +28232,35 @@
             }
           }
         }
+        #endif
 
       }
 
-      public sealed partial class RepeatedGroup : pb::IMessage<RepeatedGroup> {
+      public sealed partial class RepeatedGroup : pb::IMessage<RepeatedGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<RepeatedGroup> _parser = new pb::MessageParser<RepeatedGroup>(() => new RepeatedGroup());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<RepeatedGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Descriptor.NestedTypes[2]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedGroup() {
           OnConstruction();
         }
@@ -21326,12 +28268,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedGroup(RepeatedGroup other) : this() {
-          repeatedGroupAllTypes_ = other.HasRepeatedGroupAllTypes ? other.repeatedGroupAllTypes_.Clone() : null;
+          repeatedGroupAllTypes_ = other.repeatedGroupAllTypes_ != null ? other.repeatedGroupAllTypes_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public RepeatedGroup Clone() {
           return new RepeatedGroup(this);
         }
@@ -21340,29 +28284,22 @@
         public const int RepeatedGroupAllTypesFieldNumber = 21;
         private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes repeatedGroupAllTypes_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes RepeatedGroupAllTypes {
           get { return repeatedGroupAllTypes_; }
           set {
             repeatedGroupAllTypes_ = value;
           }
         }
-        /// <summary>Gets whether the repeated_group_all_types field is set</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public bool HasRepeatedGroupAllTypes {
-          get { return repeatedGroupAllTypes_ != null; }
-        }
-        /// <summary>Clears the value of the repeated_group_all_types field</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public void ClearRepeatedGroupAllTypes() {
-          repeatedGroupAllTypes_ = null;
-        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as RepeatedGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(RepeatedGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -21375,9 +28312,10 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
-          if (HasRepeatedGroupAllTypes) hash ^= RepeatedGroupAllTypes.GetHashCode();
+          if (repeatedGroupAllTypes_ != null) hash ^= RepeatedGroupAllTypes.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -21385,25 +28323,46 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (HasRepeatedGroupAllTypes) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
+          if (repeatedGroupAllTypes_ != null) {
             output.WriteRawTag(170, 1);
             output.WriteMessage(RepeatedGroupAllTypes);
           }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (repeatedGroupAllTypes_ != null) {
+            output.WriteRawTag(170, 1);
+            output.WriteMessage(RepeatedGroupAllTypes);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
-          if (HasRepeatedGroupAllTypes) {
+          if (repeatedGroupAllTypes_ != null) {
             size += 2 + pb::CodedOutputStream.ComputeMessageSize(RepeatedGroupAllTypes);
           }
           if (_unknownFields != null) {
@@ -21413,12 +28372,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(RepeatedGroup other) {
           if (other == null) {
             return;
           }
-          if (other.HasRepeatedGroupAllTypes) {
-            if (!HasRepeatedGroupAllTypes) {
+          if (other.repeatedGroupAllTypes_ != null) {
+            if (repeatedGroupAllTypes_ == null) {
               RepeatedGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
             }
             RepeatedGroupAllTypes.MergeFrom(other.RepeatedGroupAllTypes);
@@ -21427,7 +28387,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -21437,7 +28401,31 @@
                 _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
               case 170: {
-                if (!HasRepeatedGroupAllTypes) {
+                if (repeatedGroupAllTypes_ == null) {
+                  RepeatedGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+                }
+                input.ReadMessage(RepeatedGroupAllTypes);
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 164:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 170: {
+                if (repeatedGroupAllTypes_ == null) {
                   RepeatedGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
                 }
                 input.ReadMessage(RepeatedGroupAllTypes);
@@ -21446,6 +28434,7 @@
             }
           }
         }
+        #endif
 
       }
 
@@ -21455,6 +28444,7 @@
     #region Extensions
     /// <summary>Container for extensions for other messages declared in the TestParsingMerge message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Extensions {
       public static readonly pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes> OptionalExt =
         new pb::Extension<global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes>(1000, pb::FieldCodec.ForMessage(8002, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser));
@@ -21465,23 +28455,31 @@
 
   }
 
-  public sealed partial class TestCommentInjectionMessage : pb::IMessage<TestCommentInjectionMessage> {
+  public sealed partial class TestCommentInjectionMessage : pb::IMessage<TestCommentInjectionMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestCommentInjectionMessage> _parser = new pb::MessageParser<TestCommentInjectionMessage>(() => new TestCommentInjectionMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestCommentInjectionMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[55]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCommentInjectionMessage() {
       OnConstruction();
     }
@@ -21489,12 +28487,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() {
       a_ = other.a_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCommentInjectionMessage Clone() {
       return new TestCommentInjectionMessage(this);
     }
@@ -21508,6 +28508,7 @@
     /// */ &lt;- This should not close the generated doc comment
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string A {
       get { return a_ ?? ADefaultValue; }
       set {
@@ -21516,21 +28517,25 @@
     }
     /// <summary>Gets whether the "a" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasA {
       get { return a_ != null; }
     }
     /// <summary>Clears the value of the "a" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearA() {
       a_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestCommentInjectionMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestCommentInjectionMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -21543,6 +28548,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasA) hash ^= A.GetHashCode();
@@ -21553,12 +28559,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasA) {
         output.WriteRawTag(10);
         output.WriteString(A);
@@ -21566,9 +28577,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasA) {
+        output.WriteRawTag(10);
+        output.WriteString(A);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasA) {
@@ -21581,6 +28608,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestCommentInjectionMessage other) {
       if (other == null) {
         return;
@@ -21592,7 +28620,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -21605,30 +28637,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            A = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test that RPC services work.
   /// </summary>
-  public sealed partial class FooRequest : pb::IMessage<FooRequest> {
+  public sealed partial class FooRequest : pb::IMessage<FooRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooRequest> _parser = new pb::MessageParser<FooRequest>(() => new FooRequest());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooRequest> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[56]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooRequest() {
       OnConstruction();
     }
@@ -21636,21 +28696,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooRequest(FooRequest other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooRequest Clone() {
       return new FooRequest(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooRequest);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooRequest other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -21662,6 +28726,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -21671,18 +28736,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -21692,6 +28774,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooRequest other) {
       if (other == null) {
         return;
@@ -21700,7 +28783,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -21709,27 +28796,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class FooResponse : pb::IMessage<FooResponse> {
+  public sealed partial class FooResponse : pb::IMessage<FooResponse>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooResponse> _parser = new pb::MessageParser<FooResponse>(() => new FooResponse());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooResponse> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[57]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooResponse() {
       OnConstruction();
     }
@@ -21737,21 +28848,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooResponse(FooResponse other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooResponse Clone() {
       return new FooResponse(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooResponse);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooResponse other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -21763,6 +28878,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -21772,18 +28888,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -21793,6 +28926,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooResponse other) {
       if (other == null) {
         return;
@@ -21801,7 +28935,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -21810,27 +28948,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class FooClientMessage : pb::IMessage<FooClientMessage> {
+  public sealed partial class FooClientMessage : pb::IMessage<FooClientMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooClientMessage> _parser = new pb::MessageParser<FooClientMessage>(() => new FooClientMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooClientMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[58]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooClientMessage() {
       OnConstruction();
     }
@@ -21838,21 +29000,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooClientMessage(FooClientMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooClientMessage Clone() {
       return new FooClientMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooClientMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooClientMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -21864,6 +29030,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -21873,18 +29040,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -21894,6 +29078,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooClientMessage other) {
       if (other == null) {
         return;
@@ -21902,7 +29087,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -21911,27 +29100,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class FooServerMessage : pb::IMessage<FooServerMessage> {
+  public sealed partial class FooServerMessage : pb::IMessage<FooServerMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooServerMessage> _parser = new pb::MessageParser<FooServerMessage>(() => new FooServerMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooServerMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[59]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooServerMessage() {
       OnConstruction();
     }
@@ -21939,21 +29152,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooServerMessage(FooServerMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooServerMessage Clone() {
       return new FooServerMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooServerMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooServerMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -21965,6 +29182,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -21974,18 +29192,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -21995,6 +29230,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooServerMessage other) {
       if (other == null) {
         return;
@@ -22003,7 +29239,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -22012,27 +29252,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class BarRequest : pb::IMessage<BarRequest> {
+  public sealed partial class BarRequest : pb::IMessage<BarRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BarRequest> _parser = new pb::MessageParser<BarRequest>(() => new BarRequest());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BarRequest> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[60]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarRequest() {
       OnConstruction();
     }
@@ -22040,21 +29304,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarRequest(BarRequest other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarRequest Clone() {
       return new BarRequest(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BarRequest);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BarRequest other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -22066,6 +29334,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -22075,18 +29344,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -22096,6 +29382,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BarRequest other) {
       if (other == null) {
         return;
@@ -22104,7 +29391,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -22113,27 +29404,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class BarResponse : pb::IMessage<BarResponse> {
+  public sealed partial class BarResponse : pb::IMessage<BarResponse>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BarResponse> _parser = new pb::MessageParser<BarResponse>(() => new BarResponse());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BarResponse> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[61]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarResponse() {
       OnConstruction();
     }
@@ -22141,21 +29456,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarResponse(BarResponse other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarResponse Clone() {
       return new BarResponse(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BarResponse);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BarResponse other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -22167,6 +29486,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -22176,18 +29496,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -22197,6 +29534,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BarResponse other) {
       if (other == null) {
         return;
@@ -22205,7 +29543,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -22214,28 +29556,52 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestJsonName : pb::IMessage<TestJsonName> {
+  public sealed partial class TestJsonName : pb::IMessage<TestJsonName>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestJsonName> _parser = new pb::MessageParser<TestJsonName>(() => new TestJsonName());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestJsonName> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[62]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonName() {
       OnConstruction();
     }
@@ -22243,6 +29609,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonName(TestJsonName other) : this() {
       _hasBits0 = other._hasBits0;
       fieldName1_ = other.fieldName1_;
@@ -22255,6 +29622,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonName Clone() {
       return new TestJsonName(this);
     }
@@ -22265,6 +29633,7 @@
 
     private int fieldName1_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName1 {
       get { if ((_hasBits0 & 1) != 0) { return fieldName1_; } else { return FieldName1DefaultValue; } }
       set {
@@ -22274,11 +29643,13 @@
     }
     /// <summary>Gets whether the "field_name1" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName1 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "field_name1" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName1() {
       _hasBits0 &= ~1;
     }
@@ -22289,6 +29660,7 @@
 
     private int fieldName2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName2 {
       get { if ((_hasBits0 & 2) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } }
       set {
@@ -22298,11 +29670,13 @@
     }
     /// <summary>Gets whether the "fieldName2" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName2 {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "fieldName2" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName2() {
       _hasBits0 &= ~2;
     }
@@ -22313,6 +29687,7 @@
 
     private int fieldName3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName3 {
       get { if ((_hasBits0 & 4) != 0) { return fieldName3_; } else { return FieldName3DefaultValue; } }
       set {
@@ -22322,11 +29697,13 @@
     }
     /// <summary>Gets whether the "FieldName3" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName3 {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "FieldName3" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName3() {
       _hasBits0 &= ~4;
     }
@@ -22337,6 +29714,7 @@
 
     private int FieldName4_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName4 {
       get { if ((_hasBits0 & 8) != 0) { return FieldName4_; } else { return FieldName4DefaultValue; } }
       set {
@@ -22346,11 +29724,13 @@
     }
     /// <summary>Gets whether the "_field_name4" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName4 {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "_field_name4" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName4() {
       _hasBits0 &= ~8;
     }
@@ -22361,6 +29741,7 @@
 
     private int fIELDNAME5_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FIELDNAME5 {
       get { if ((_hasBits0 & 16) != 0) { return fIELDNAME5_; } else { return FIELDNAME5DefaultValue; } }
       set {
@@ -22370,11 +29751,13 @@
     }
     /// <summary>Gets whether the "FIELD_NAME5" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFIELDNAME5 {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "FIELD_NAME5" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFIELDNAME5() {
       _hasBits0 &= ~16;
     }
@@ -22385,6 +29768,7 @@
 
     private int fieldName6_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FieldName6 {
       get { if ((_hasBits0 & 32) != 0) { return fieldName6_; } else { return FieldName6DefaultValue; } }
       set {
@@ -22394,21 +29778,25 @@
     }
     /// <summary>Gets whether the "field_name6" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFieldName6 {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "field_name6" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFieldName6() {
       _hasBits0 &= ~32;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestJsonName);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestJsonName other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -22426,6 +29814,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasFieldName1) hash ^= FieldName1.GetHashCode();
@@ -22441,12 +29830,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasFieldName1) {
         output.WriteRawTag(8);
         output.WriteInt32(FieldName1);
@@ -22474,9 +29868,45 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasFieldName1) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FieldName1);
+      }
+      if (HasFieldName2) {
+        output.WriteRawTag(16);
+        output.WriteInt32(FieldName2);
+      }
+      if (HasFieldName3) {
+        output.WriteRawTag(24);
+        output.WriteInt32(FieldName3);
+      }
+      if (HasFieldName4) {
+        output.WriteRawTag(32);
+        output.WriteInt32(FieldName4);
+      }
+      if (HasFIELDNAME5) {
+        output.WriteRawTag(40);
+        output.WriteInt32(FIELDNAME5);
+      }
+      if (HasFieldName6) {
+        output.WriteRawTag(48);
+        output.WriteInt32(FieldName6);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasFieldName1) {
@@ -22504,6 +29934,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestJsonName other) {
       if (other == null) {
         return;
@@ -22530,7 +29961,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -22563,30 +29998,78 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            FieldName1 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            FieldName2 = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            FieldName3 = input.ReadInt32();
+            break;
+          }
+          case 32: {
+            FieldName4 = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            FIELDNAME5 = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            FieldName6 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestHugeFieldNumbers : pb::IExtendableMessage<TestHugeFieldNumbers> {
+  public sealed partial class TestHugeFieldNumbers : pb::IExtendableMessage<TestHugeFieldNumbers>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestHugeFieldNumbers> _parser = new pb::MessageParser<TestHugeFieldNumbers>(() => new TestHugeFieldNumbers());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestHugeFieldNumbers> _extensions;
     private pb::ExtensionSet<TestHugeFieldNumbers> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestHugeFieldNumbers> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[63]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestHugeFieldNumbers() {
       OnConstruction();
     }
@@ -22594,6 +30077,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestHugeFieldNumbers(TestHugeFieldNumbers other) : this() {
       _hasBits0 = other._hasBits0;
       optionalInt32_ = other.optionalInt32_;
@@ -22603,7 +30087,7 @@
       optionalEnum_ = other.optionalEnum_;
       optionalString_ = other.optionalString_;
       optionalBytes_ = other.optionalBytes_;
-      optionalMessage_ = other.HasOptionalMessage ? other.optionalMessage_.Clone() : null;
+      optionalMessage_ = other.optionalMessage_ != null ? other.optionalMessage_.Clone() : null;
       optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null;
       stringStringMap_ = other.stringStringMap_.Clone();
       switch (other.OneofFieldCase) {
@@ -22626,6 +30110,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestHugeFieldNumbers Clone() {
       return new TestHugeFieldNumbers(this);
     }
@@ -22636,6 +30121,7 @@
 
     private int optionalInt32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalInt32 {
       get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } }
       set {
@@ -22645,11 +30131,13 @@
     }
     /// <summary>Gets whether the "optional_int32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalInt32 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "optional_int32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalInt32() {
       _hasBits0 &= ~1;
     }
@@ -22660,6 +30148,7 @@
 
     private int fixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Fixed32 {
       get { if ((_hasBits0 & 2) != 0) { return fixed32_; } else { return Fixed32DefaultValue; } }
       set {
@@ -22669,11 +30158,13 @@
     }
     /// <summary>Gets whether the "fixed_32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasFixed32 {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "fixed_32" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFixed32() {
       _hasBits0 &= ~2;
     }
@@ -22684,6 +30175,7 @@
         = pb::FieldCodec.ForInt32(4294960016);
     private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
@@ -22694,6 +30186,7 @@
         = pb::FieldCodec.ForInt32(4294960026);
     private readonly pbc::RepeatedField<int> packedInt32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedInt32 {
       get { return packedInt32_; }
     }
@@ -22704,6 +30197,7 @@
 
     private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum optionalEnum_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalEnum {
       get { if ((_hasBits0 & 4) != 0) { return optionalEnum_; } else { return OptionalEnumDefaultValue; } }
       set {
@@ -22713,11 +30207,13 @@
     }
     /// <summary>Gets whether the "optional_enum" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalEnum {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "optional_enum" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalEnum() {
       _hasBits0 &= ~4;
     }
@@ -22728,6 +30224,7 @@
 
     private string optionalString_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OptionalString {
       get { return optionalString_ ?? OptionalStringDefaultValue; }
       set {
@@ -22736,11 +30233,13 @@
     }
     /// <summary>Gets whether the "optional_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalString {
       get { return optionalString_ != null; }
     }
     /// <summary>Clears the value of the "optional_string" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalString() {
       optionalString_ = null;
     }
@@ -22751,6 +30250,7 @@
 
     private pb::ByteString optionalBytes_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OptionalBytes {
       get { return optionalBytes_ ?? OptionalBytesDefaultValue; }
       set {
@@ -22759,11 +30259,13 @@
     }
     /// <summary>Gets whether the "optional_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalBytes {
       get { return optionalBytes_ != null; }
     }
     /// <summary>Clears the value of the "optional_bytes" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalBytes() {
       optionalBytes_ = null;
     }
@@ -22772,27 +30274,19 @@
     public const int OptionalMessageFieldNumber = 536870007;
     private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage optionalMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage OptionalMessage {
       get { return optionalMessage_; }
       set {
         optionalMessage_ = value;
       }
     }
-    /// <summary>Gets whether the optional_message field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptionalMessage {
-      get { return optionalMessage_ != null; }
-    }
-    /// <summary>Clears the value of the optional_message field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptionalMessage() {
-      optionalMessage_ = null;
-    }
 
     /// <summary>Field number for the "optionalgroup" field.</summary>
     public const int OptionalGroupFieldNumber = 536870008;
     private global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup optionalGroup_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup OptionalGroup {
       get { return optionalGroup_; }
       set {
@@ -22801,11 +30295,13 @@
     }
     /// <summary>Gets whether the optionalgroup field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptionalGroup {
       get { return optionalGroup_ != null; }
     }
     /// <summary>Clears the value of the optionalgroup field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptionalGroup() {
       optionalGroup_ = null;
     }
@@ -22816,6 +30312,7 @@
         = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 4294960082);
     private readonly pbc::MapField<string, string> stringStringMap_ = new pbc::MapField<string, string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, string> StringStringMap {
       get { return stringStringMap_; }
     }
@@ -22823,6 +30320,7 @@
     /// <summary>Field number for the "oneof_uint32" field.</summary>
     public const int OneofUint32FieldNumber = 536870011;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OneofUint32 {
       get { return HasOneofUint32 ? (uint) oneofField_ : 0; }
       set {
@@ -22832,11 +30330,13 @@
     }
     /// <summary>Gets whether the "oneof_uint32" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofUint32 {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_uint32" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofUint32() {
       if (HasOneofUint32) {
         ClearOneofField();
@@ -22846,29 +30346,19 @@
     /// <summary>Field number for the "oneof_test_all_types" field.</summary>
     public const int OneofTestAllTypesFieldNumber = 536870012;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes OneofTestAllTypes {
-      get { return HasOneofTestAllTypes ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes) oneofField_ : null; }
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes) oneofField_ : null; }
       set {
         oneofField_ = value;
         oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofTestAllTypes;
       }
     }
-    /// <summary>Gets whether the "oneof_test_all_types" field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOneofTestAllTypes {
-      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes; }
-    }
-    /// <summary> Clears the value of the oneof if it's currently set to "oneof_test_all_types" </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOneofTestAllTypes() {
-      if (HasOneofTestAllTypes) {
-        ClearOneofField();
-      }
-    }
 
     /// <summary>Field number for the "oneof_string" field.</summary>
     public const int OneofStringFieldNumber = 536870013;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OneofString {
       get { return HasOneofString ? (string) oneofField_ : ""; }
       set {
@@ -22878,11 +30368,13 @@
     }
     /// <summary>Gets whether the "oneof_string" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofString {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_string" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofString() {
       if (HasOneofString) {
         ClearOneofField();
@@ -22892,6 +30384,7 @@
     /// <summary>Field number for the "oneof_bytes" field.</summary>
     public const int OneofBytesFieldNumber = 536870014;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OneofBytes {
       get { return HasOneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
       set {
@@ -22901,11 +30394,13 @@
     }
     /// <summary>Gets whether the "oneof_bytes" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofBytes {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; }
     }
     /// <summary> Clears the value of the oneof if it's currently set to "oneof_bytes" </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofBytes() {
       if (HasOneofBytes) {
         ClearOneofField();
@@ -22923,22 +30418,26 @@
     }
     private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofFieldOneofCase OneofFieldCase {
       get { return oneofFieldCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofField() {
       oneofFieldCase_ = OneofFieldOneofCase.None;
       oneofField_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestHugeFieldNumbers);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestHugeFieldNumbers other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -22968,6 +30467,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode();
@@ -22977,11 +30477,11 @@
       if (HasOptionalEnum) hash ^= OptionalEnum.GetHashCode();
       if (HasOptionalString) hash ^= OptionalString.GetHashCode();
       if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode();
-      if (HasOptionalMessage) hash ^= OptionalMessage.GetHashCode();
+      if (optionalMessage_ != null) hash ^= OptionalMessage.GetHashCode();
       if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode();
       hash ^= StringStringMap.GetHashCode();
       if (HasOneofUint32) hash ^= OneofUint32.GetHashCode();
-      if (HasOneofTestAllTypes) hash ^= OneofTestAllTypes.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) hash ^= OneofTestAllTypes.GetHashCode();
       if (HasOneofString) hash ^= OneofString.GetHashCode();
       if (HasOneofBytes) hash ^= OneofBytes.GetHashCode();
       hash ^= (int) oneofFieldCase_;
@@ -22995,12 +30495,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasOptionalInt32) {
         output.WriteRawTag(128, 199, 255, 255, 15);
         output.WriteInt32(OptionalInt32);
@@ -23023,7 +30528,7 @@
         output.WriteRawTag(178, 199, 255, 255, 15);
         output.WriteBytes(OptionalBytes);
       }
-      if (HasOptionalMessage) {
+      if (optionalMessage_ != null) {
         output.WriteRawTag(186, 199, 255, 255, 15);
         output.WriteMessage(OptionalMessage);
       }
@@ -23037,7 +30542,7 @@
         output.WriteRawTag(216, 199, 255, 255, 15);
         output.WriteUInt32(OneofUint32);
       }
-      if (HasOneofTestAllTypes) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) {
         output.WriteRawTag(226, 199, 255, 255, 15);
         output.WriteMessage(OneofTestAllTypes);
       }
@@ -23055,9 +30560,72 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasOptionalInt32) {
+        output.WriteRawTag(128, 199, 255, 255, 15);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (HasFixed32) {
+        output.WriteRawTag(136, 199, 255, 255, 15);
+        output.WriteInt32(Fixed32);
+      }
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec);
+      if (HasOptionalEnum) {
+        output.WriteRawTag(160, 199, 255, 255, 15);
+        output.WriteEnum((int) OptionalEnum);
+      }
+      if (HasOptionalString) {
+        output.WriteRawTag(170, 199, 255, 255, 15);
+        output.WriteString(OptionalString);
+      }
+      if (HasOptionalBytes) {
+        output.WriteRawTag(178, 199, 255, 255, 15);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (optionalMessage_ != null) {
+        output.WriteRawTag(186, 199, 255, 255, 15);
+        output.WriteMessage(OptionalMessage);
+      }
+      if (HasOptionalGroup) {
+        output.WriteRawTag(195, 199, 255, 255, 15);
+        output.WriteGroup(OptionalGroup);
+        output.WriteRawTag(196, 199, 255, 255, 15);
+      }
+      stringStringMap_.WriteTo(ref output, _map_stringStringMap_codec);
+      if (HasOneofUint32) {
+        output.WriteRawTag(216, 199, 255, 255, 15);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) {
+        output.WriteRawTag(226, 199, 255, 255, 15);
+        output.WriteMessage(OneofTestAllTypes);
+      }
+      if (HasOneofString) {
+        output.WriteRawTag(234, 199, 255, 255, 15);
+        output.WriteString(OneofString);
+      }
+      if (HasOneofBytes) {
+        output.WriteRawTag(242, 199, 255, 255, 15);
+        output.WriteBytes(OneofBytes);
+      }
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasOptionalInt32) {
@@ -23077,7 +30645,7 @@
       if (HasOptionalBytes) {
         size += 5 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes);
       }
-      if (HasOptionalMessage) {
+      if (optionalMessage_ != null) {
         size += 5 + pb::CodedOutputStream.ComputeMessageSize(OptionalMessage);
       }
       if (HasOptionalGroup) {
@@ -23087,7 +30655,7 @@
       if (HasOneofUint32) {
         size += 5 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
       }
-      if (HasOneofTestAllTypes) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) {
         size += 5 + pb::CodedOutputStream.ComputeMessageSize(OneofTestAllTypes);
       }
       if (HasOneofString) {
@@ -23106,6 +30674,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestHugeFieldNumbers other) {
       if (other == null) {
         return;
@@ -23127,8 +30696,8 @@
       if (other.HasOptionalBytes) {
         OptionalBytes = other.OptionalBytes;
       }
-      if (other.HasOptionalMessage) {
-        if (!HasOptionalMessage) {
+      if (other.optionalMessage_ != null) {
+        if (optionalMessage_ == null) {
           OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
         }
         OptionalMessage.MergeFrom(other.OptionalMessage);
@@ -23163,7 +30732,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -23203,7 +30776,7 @@
             break;
           }
           case 4294960058: {
-            if (!HasOptionalMessage) {
+            if (optionalMessage_ == null) {
               OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
             }
             input.ReadMessage(OptionalMessage);
@@ -23226,7 +30799,93 @@
           }
           case 4294960098: {
             global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
-            if (HasOneofTestAllTypes) {
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) {
+              subBuilder.MergeFrom(OneofTestAllTypes);
+            }
+            input.ReadMessage(subBuilder);
+            OneofTestAllTypes = subBuilder;
+            break;
+          }
+          case 4294960106: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 4294960114: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 4294960000: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 4294960008: {
+            Fixed32 = input.ReadInt32();
+            break;
+          }
+          case 4294960018:
+          case 4294960016: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 4294960026:
+          case 4294960024: {
+            packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec);
+            break;
+          }
+          case 4294960032: {
+            OptionalEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 4294960042: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 4294960050: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 4294960058: {
+            if (optionalMessage_ == null) {
+              OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage();
+            }
+            input.ReadMessage(OptionalMessage);
+            break;
+          }
+          case 4294960067: {
+            if (!HasOptionalGroup) {
+              OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup();
+            }
+            input.ReadGroup(OptionalGroup);
+            break;
+          }
+          case 4294960082: {
+            stringStringMap_.AddEntriesFrom(ref input, _map_stringStringMap_codec);
+            break;
+          }
+          case 4294960088: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 4294960098: {
+            global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) {
               subBuilder.MergeFrom(OneofTestAllTypes);
             }
             input.ReadMessage(subBuilder);
@@ -23244,6 +30903,7 @@
         }
       }
     }
+    #endif
 
     public TValue GetExtension<TValue>(pb::Extension<TestHugeFieldNumbers, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
@@ -23270,25 +30930,34 @@
     #region Nested types
     /// <summary>Container for nested types declared in the TestHugeFieldNumbers message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup> {
+      public sealed partial class OptionalGroup : pb::IMessage<OptionalGroup>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<OptionalGroup> _parser = new pb::MessageParser<OptionalGroup>(() => new OptionalGroup());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<OptionalGroup> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup() {
           OnConstruction();
         }
@@ -23296,6 +30965,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup(OptionalGroup other) : this() {
           _hasBits0 = other._hasBits0;
           groupA_ = other.groupA_;
@@ -23303,6 +30973,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public OptionalGroup Clone() {
           return new OptionalGroup(this);
         }
@@ -23313,6 +30984,7 @@
 
         private int groupA_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int GroupA {
           get { if ((_hasBits0 & 1) != 0) { return groupA_; } else { return GroupADefaultValue; } }
           set {
@@ -23322,21 +30994,25 @@
         }
         /// <summary>Gets whether the "group_a" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasGroupA {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "group_a" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearGroupA() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as OptionalGroup);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(OptionalGroup other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -23349,6 +31025,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasGroupA) hash ^= GroupA.GetHashCode();
@@ -23359,12 +31036,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasGroupA) {
             output.WriteRawTag(200, 199, 255, 255, 15);
             output.WriteInt32(GroupA);
@@ -23372,9 +31054,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasGroupA) {
+            output.WriteRawTag(200, 199, 255, 255, 15);
+            output.WriteInt32(GroupA);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasGroupA) {
@@ -23387,6 +31085,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(OptionalGroup other) {
           if (other == null) {
             return;
@@ -23398,7 +31097,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -23413,8 +31116,30 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              case 4294960068:
+                return;
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 4294960072: {
+                GroupA = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -23422,26 +31147,34 @@
 
   }
 
-  public sealed partial class TestExtensionInsideTable : pb::IExtendableMessage<TestExtensionInsideTable> {
+  public sealed partial class TestExtensionInsideTable : pb::IExtendableMessage<TestExtensionInsideTable>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestExtensionInsideTable> _parser = new pb::MessageParser<TestExtensionInsideTable>(() => new TestExtensionInsideTable());
     private pb::UnknownFieldSet _unknownFields;
     private pb::ExtensionSet<TestExtensionInsideTable> _extensions;
     private pb::ExtensionSet<TestExtensionInsideTable> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestExtensionInsideTable> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[64]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionInsideTable() {
       OnConstruction();
     }
@@ -23449,6 +31182,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionInsideTable(TestExtensionInsideTable other) : this() {
       _hasBits0 = other._hasBits0;
       field1_ = other.field1_;
@@ -23465,6 +31199,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestExtensionInsideTable Clone() {
       return new TestExtensionInsideTable(this);
     }
@@ -23475,6 +31210,7 @@
 
     private int field1_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field1 {
       get { if ((_hasBits0 & 1) != 0) { return field1_; } else { return Field1DefaultValue; } }
       set {
@@ -23484,11 +31220,13 @@
     }
     /// <summary>Gets whether the "field1" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField1 {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "field1" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField1() {
       _hasBits0 &= ~1;
     }
@@ -23499,6 +31237,7 @@
 
     private int field2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field2 {
       get { if ((_hasBits0 & 2) != 0) { return field2_; } else { return Field2DefaultValue; } }
       set {
@@ -23508,11 +31247,13 @@
     }
     /// <summary>Gets whether the "field2" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField2 {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "field2" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField2() {
       _hasBits0 &= ~2;
     }
@@ -23523,6 +31264,7 @@
 
     private int field3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field3 {
       get { if ((_hasBits0 & 4) != 0) { return field3_; } else { return Field3DefaultValue; } }
       set {
@@ -23532,11 +31274,13 @@
     }
     /// <summary>Gets whether the "field3" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField3 {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "field3" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField3() {
       _hasBits0 &= ~4;
     }
@@ -23547,6 +31291,7 @@
 
     private int field4_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field4 {
       get { if ((_hasBits0 & 8) != 0) { return field4_; } else { return Field4DefaultValue; } }
       set {
@@ -23556,11 +31301,13 @@
     }
     /// <summary>Gets whether the "field4" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField4 {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "field4" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField4() {
       _hasBits0 &= ~8;
     }
@@ -23571,6 +31318,7 @@
 
     private int field6_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field6 {
       get { if ((_hasBits0 & 16) != 0) { return field6_; } else { return Field6DefaultValue; } }
       set {
@@ -23580,11 +31328,13 @@
     }
     /// <summary>Gets whether the "field6" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField6 {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "field6" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField6() {
       _hasBits0 &= ~16;
     }
@@ -23595,6 +31345,7 @@
 
     private int field7_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field7 {
       get { if ((_hasBits0 & 32) != 0) { return field7_; } else { return Field7DefaultValue; } }
       set {
@@ -23604,11 +31355,13 @@
     }
     /// <summary>Gets whether the "field7" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField7 {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "field7" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField7() {
       _hasBits0 &= ~32;
     }
@@ -23619,6 +31372,7 @@
 
     private int field8_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field8 {
       get { if ((_hasBits0 & 64) != 0) { return field8_; } else { return Field8DefaultValue; } }
       set {
@@ -23628,11 +31382,13 @@
     }
     /// <summary>Gets whether the "field8" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField8 {
       get { return (_hasBits0 & 64) != 0; }
     }
     /// <summary>Clears the value of the "field8" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField8() {
       _hasBits0 &= ~64;
     }
@@ -23643,6 +31399,7 @@
 
     private int field9_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field9 {
       get { if ((_hasBits0 & 128) != 0) { return field9_; } else { return Field9DefaultValue; } }
       set {
@@ -23652,11 +31409,13 @@
     }
     /// <summary>Gets whether the "field9" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField9 {
       get { return (_hasBits0 & 128) != 0; }
     }
     /// <summary>Clears the value of the "field9" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField9() {
       _hasBits0 &= ~128;
     }
@@ -23667,6 +31426,7 @@
 
     private int field10_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Field10 {
       get { if ((_hasBits0 & 256) != 0) { return field10_; } else { return Field10DefaultValue; } }
       set {
@@ -23676,21 +31436,25 @@
     }
     /// <summary>Gets whether the "field10" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasField10 {
       get { return (_hasBits0 & 256) != 0; }
     }
     /// <summary>Clears the value of the "field10" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearField10() {
       _hasBits0 &= ~256;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestExtensionInsideTable);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestExtensionInsideTable other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -23714,6 +31478,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasField1) hash ^= Field1.GetHashCode();
@@ -23735,12 +31500,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasField1) {
         output.WriteRawTag(8);
         output.WriteInt32(Field1);
@@ -23783,9 +31553,60 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasField1) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Field1);
+      }
+      if (HasField2) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Field2);
+      }
+      if (HasField3) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Field3);
+      }
+      if (HasField4) {
+        output.WriteRawTag(32);
+        output.WriteInt32(Field4);
+      }
+      if (HasField6) {
+        output.WriteRawTag(48);
+        output.WriteInt32(Field6);
+      }
+      if (HasField7) {
+        output.WriteRawTag(56);
+        output.WriteInt32(Field7);
+      }
+      if (HasField8) {
+        output.WriteRawTag(64);
+        output.WriteInt32(Field8);
+      }
+      if (HasField9) {
+        output.WriteRawTag(72);
+        output.WriteInt32(Field9);
+      }
+      if (HasField10) {
+        output.WriteRawTag(80);
+        output.WriteInt32(Field10);
+      }
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasField1) {
@@ -23825,6 +31646,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestExtensionInsideTable other) {
       if (other == null) {
         return;
@@ -23861,7 +31683,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -23908,8 +31734,62 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            Field1 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Field2 = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Field3 = input.ReadInt32();
+            break;
+          }
+          case 32: {
+            Field4 = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            Field6 = input.ReadInt32();
+            break;
+          }
+          case 56: {
+            Field7 = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            Field8 = input.ReadInt32();
+            break;
+          }
+          case 72: {
+            Field9 = input.ReadInt32();
+            break;
+          }
+          case 80: {
+            Field10 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<TestExtensionInsideTable, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs
index cb5edf7..305dfe1 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs
@@ -257,23 +257,31 @@
   /// A test message with custom options at all possible locations (and also some
   /// regular options, to make sure they interact nicely).
   /// </summary>
-  public sealed partial class TestMessageWithCustomOptions : pb::IMessage<TestMessageWithCustomOptions> {
+  public sealed partial class TestMessageWithCustomOptions : pb::IMessage<TestMessageWithCustomOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMessageWithCustomOptions> _parser = new pb::MessageParser<TestMessageWithCustomOptions>(() => new TestMessageWithCustomOptions());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMessageWithCustomOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMessageWithCustomOptions() {
       OnConstruction();
     }
@@ -281,6 +289,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMessageWithCustomOptions(TestMessageWithCustomOptions other) : this() {
       field1_ = other.field1_;
       switch (other.AnOneofCase) {
@@ -293,6 +302,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMessageWithCustomOptions Clone() {
       return new TestMessageWithCustomOptions(this);
     }
@@ -301,6 +311,7 @@
     public const int Field1FieldNumber = 1;
     private string field1_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Field1 {
       get { return field1_; }
       set {
@@ -311,6 +322,7 @@
     /// <summary>Field number for the "oneof_field" field.</summary>
     public const int OneofFieldFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OneofField {
       get { return anOneofCase_ == AnOneofOneofCase.OneofField ? (int) anOneof_ : 0; }
       set {
@@ -327,22 +339,26 @@
     }
     private AnOneofOneofCase anOneofCase_ = AnOneofOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public AnOneofOneofCase AnOneofCase {
       get { return anOneofCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearAnOneof() {
       anOneofCase_ = AnOneofOneofCase.None;
       anOneof_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMessageWithCustomOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMessageWithCustomOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -357,6 +373,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Field1.Length != 0) hash ^= Field1.GetHashCode();
@@ -369,12 +386,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Field1.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Field1);
@@ -386,9 +408,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Field1.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Field1);
+      }
+      if (anOneofCase_ == AnOneofOneofCase.OneofField) {
+        output.WriteRawTag(16);
+        output.WriteInt32(OneofField);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Field1.Length != 0) {
@@ -404,6 +446,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMessageWithCustomOptions other) {
       if (other == null) {
         return;
@@ -421,7 +464,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -438,11 +485,36 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Field1 = input.ReadString();
+            break;
+          }
+          case 16: {
+            OneofField = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestMessageWithCustomOptions message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum AnEnum {
         [pbr::OriginalName("ANENUM_UNSPECIFIED")] Unspecified = 0,
@@ -459,23 +531,31 @@
   /// A test RPC service with custom options at all possible locations (and also
   /// some regular options, to make sure they interact nicely).
   /// </summary>
-  public sealed partial class CustomOptionFooRequest : pb::IMessage<CustomOptionFooRequest> {
+  public sealed partial class CustomOptionFooRequest : pb::IMessage<CustomOptionFooRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CustomOptionFooRequest> _parser = new pb::MessageParser<CustomOptionFooRequest>(() => new CustomOptionFooRequest());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CustomOptionFooRequest> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooRequest() {
       OnConstruction();
     }
@@ -483,21 +563,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooRequest(CustomOptionFooRequest other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooRequest Clone() {
       return new CustomOptionFooRequest(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CustomOptionFooRequest);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CustomOptionFooRequest other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -509,6 +593,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -518,18 +603,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -539,6 +641,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CustomOptionFooRequest other) {
       if (other == null) {
         return;
@@ -547,7 +650,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -556,27 +663,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class CustomOptionFooResponse : pb::IMessage<CustomOptionFooResponse> {
+  public sealed partial class CustomOptionFooResponse : pb::IMessage<CustomOptionFooResponse>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CustomOptionFooResponse> _parser = new pb::MessageParser<CustomOptionFooResponse>(() => new CustomOptionFooResponse());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CustomOptionFooResponse> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooResponse() {
       OnConstruction();
     }
@@ -584,21 +715,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooResponse(CustomOptionFooResponse other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooResponse Clone() {
       return new CustomOptionFooResponse(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CustomOptionFooResponse);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CustomOptionFooResponse other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -610,6 +745,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -619,18 +755,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -640,6 +793,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CustomOptionFooResponse other) {
       if (other == null) {
         return;
@@ -648,7 +802,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -657,27 +815,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class CustomOptionFooClientMessage : pb::IMessage<CustomOptionFooClientMessage> {
+  public sealed partial class CustomOptionFooClientMessage : pb::IMessage<CustomOptionFooClientMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CustomOptionFooClientMessage> _parser = new pb::MessageParser<CustomOptionFooClientMessage>(() => new CustomOptionFooClientMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CustomOptionFooClientMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooClientMessage() {
       OnConstruction();
     }
@@ -685,21 +867,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooClientMessage(CustomOptionFooClientMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooClientMessage Clone() {
       return new CustomOptionFooClientMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CustomOptionFooClientMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CustomOptionFooClientMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -711,6 +897,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -720,18 +907,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -741,6 +945,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CustomOptionFooClientMessage other) {
       if (other == null) {
         return;
@@ -749,7 +954,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -758,27 +967,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class CustomOptionFooServerMessage : pb::IMessage<CustomOptionFooServerMessage> {
+  public sealed partial class CustomOptionFooServerMessage : pb::IMessage<CustomOptionFooServerMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CustomOptionFooServerMessage> _parser = new pb::MessageParser<CustomOptionFooServerMessage>(() => new CustomOptionFooServerMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CustomOptionFooServerMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooServerMessage() {
       OnConstruction();
     }
@@ -786,21 +1019,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooServerMessage(CustomOptionFooServerMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionFooServerMessage Clone() {
       return new CustomOptionFooServerMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CustomOptionFooServerMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CustomOptionFooServerMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -812,6 +1049,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -821,18 +1059,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -842,6 +1097,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CustomOptionFooServerMessage other) {
       if (other == null) {
         return;
@@ -850,7 +1106,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -859,27 +1119,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class DummyMessageContainingEnum : pb::IMessage<DummyMessageContainingEnum> {
+  public sealed partial class DummyMessageContainingEnum : pb::IMessage<DummyMessageContainingEnum>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<DummyMessageContainingEnum> _parser = new pb::MessageParser<DummyMessageContainingEnum>(() => new DummyMessageContainingEnum());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<DummyMessageContainingEnum> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DummyMessageContainingEnum() {
       OnConstruction();
     }
@@ -887,21 +1171,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DummyMessageContainingEnum(DummyMessageContainingEnum other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DummyMessageContainingEnum Clone() {
       return new DummyMessageContainingEnum(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as DummyMessageContainingEnum);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(DummyMessageContainingEnum other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -913,6 +1201,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -922,18 +1211,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -943,6 +1249,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(DummyMessageContainingEnum other) {
       if (other == null) {
         return;
@@ -951,7 +1258,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -960,11 +1271,28 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the DummyMessageContainingEnum message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum TestEnumType {
         [pbr::OriginalName("TEST_OPTION_ENUM_UNSPECIFIED")] TestOptionEnumUnspecified = 0,
@@ -977,23 +1305,31 @@
 
   }
 
-  public sealed partial class DummyMessageInvalidAsOptionType : pb::IMessage<DummyMessageInvalidAsOptionType> {
+  public sealed partial class DummyMessageInvalidAsOptionType : pb::IMessage<DummyMessageInvalidAsOptionType>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<DummyMessageInvalidAsOptionType> _parser = new pb::MessageParser<DummyMessageInvalidAsOptionType>(() => new DummyMessageInvalidAsOptionType());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<DummyMessageInvalidAsOptionType> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DummyMessageInvalidAsOptionType() {
       OnConstruction();
     }
@@ -1001,21 +1337,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DummyMessageInvalidAsOptionType(DummyMessageInvalidAsOptionType other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DummyMessageInvalidAsOptionType Clone() {
       return new DummyMessageInvalidAsOptionType(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as DummyMessageInvalidAsOptionType);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(DummyMessageInvalidAsOptionType other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1027,6 +1367,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -1036,18 +1377,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -1057,6 +1415,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(DummyMessageInvalidAsOptionType other) {
       if (other == null) {
         return;
@@ -1065,7 +1424,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1074,27 +1437,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class CustomOptionMinIntegerValues : pb::IMessage<CustomOptionMinIntegerValues> {
+  public sealed partial class CustomOptionMinIntegerValues : pb::IMessage<CustomOptionMinIntegerValues>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CustomOptionMinIntegerValues> _parser = new pb::MessageParser<CustomOptionMinIntegerValues>(() => new CustomOptionMinIntegerValues());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CustomOptionMinIntegerValues> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[7]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionMinIntegerValues() {
       OnConstruction();
     }
@@ -1102,21 +1489,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionMinIntegerValues(CustomOptionMinIntegerValues other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionMinIntegerValues Clone() {
       return new CustomOptionMinIntegerValues(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CustomOptionMinIntegerValues);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CustomOptionMinIntegerValues other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1128,6 +1519,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -1137,18 +1529,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -1158,6 +1567,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CustomOptionMinIntegerValues other) {
       if (other == null) {
         return;
@@ -1166,7 +1576,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1175,27 +1589,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class CustomOptionMaxIntegerValues : pb::IMessage<CustomOptionMaxIntegerValues> {
+  public sealed partial class CustomOptionMaxIntegerValues : pb::IMessage<CustomOptionMaxIntegerValues>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CustomOptionMaxIntegerValues> _parser = new pb::MessageParser<CustomOptionMaxIntegerValues>(() => new CustomOptionMaxIntegerValues());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CustomOptionMaxIntegerValues> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[8]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionMaxIntegerValues() {
       OnConstruction();
     }
@@ -1203,21 +1641,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionMaxIntegerValues(CustomOptionMaxIntegerValues other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionMaxIntegerValues Clone() {
       return new CustomOptionMaxIntegerValues(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CustomOptionMaxIntegerValues);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CustomOptionMaxIntegerValues other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1229,6 +1671,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -1238,18 +1681,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -1259,6 +1719,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CustomOptionMaxIntegerValues other) {
       if (other == null) {
         return;
@@ -1267,7 +1728,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1276,27 +1741,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class CustomOptionOtherValues : pb::IMessage<CustomOptionOtherValues> {
+  public sealed partial class CustomOptionOtherValues : pb::IMessage<CustomOptionOtherValues>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CustomOptionOtherValues> _parser = new pb::MessageParser<CustomOptionOtherValues>(() => new CustomOptionOtherValues());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CustomOptionOtherValues> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[9]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionOtherValues() {
       OnConstruction();
     }
@@ -1304,21 +1793,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionOtherValues(CustomOptionOtherValues other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CustomOptionOtherValues Clone() {
       return new CustomOptionOtherValues(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CustomOptionOtherValues);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CustomOptionOtherValues other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1330,6 +1823,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -1339,18 +1833,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -1360,6 +1871,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CustomOptionOtherValues other) {
       if (other == null) {
         return;
@@ -1368,7 +1880,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1377,27 +1893,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class SettingRealsFromPositiveInts : pb::IMessage<SettingRealsFromPositiveInts> {
+  public sealed partial class SettingRealsFromPositiveInts : pb::IMessage<SettingRealsFromPositiveInts>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<SettingRealsFromPositiveInts> _parser = new pb::MessageParser<SettingRealsFromPositiveInts>(() => new SettingRealsFromPositiveInts());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<SettingRealsFromPositiveInts> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[10]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SettingRealsFromPositiveInts() {
       OnConstruction();
     }
@@ -1405,21 +1945,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SettingRealsFromPositiveInts(SettingRealsFromPositiveInts other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SettingRealsFromPositiveInts Clone() {
       return new SettingRealsFromPositiveInts(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as SettingRealsFromPositiveInts);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(SettingRealsFromPositiveInts other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1431,6 +1975,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -1440,18 +1985,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -1461,6 +2023,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(SettingRealsFromPositiveInts other) {
       if (other == null) {
         return;
@@ -1469,7 +2032,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1478,27 +2045,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class SettingRealsFromNegativeInts : pb::IMessage<SettingRealsFromNegativeInts> {
+  public sealed partial class SettingRealsFromNegativeInts : pb::IMessage<SettingRealsFromNegativeInts>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<SettingRealsFromNegativeInts> _parser = new pb::MessageParser<SettingRealsFromNegativeInts>(() => new SettingRealsFromNegativeInts());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<SettingRealsFromNegativeInts> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[11]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SettingRealsFromNegativeInts() {
       OnConstruction();
     }
@@ -1506,21 +2097,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SettingRealsFromNegativeInts(SettingRealsFromNegativeInts other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SettingRealsFromNegativeInts Clone() {
       return new SettingRealsFromNegativeInts(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as SettingRealsFromNegativeInts);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(SettingRealsFromNegativeInts other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1532,6 +2127,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -1541,18 +2137,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -1562,6 +2175,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(SettingRealsFromNegativeInts other) {
       if (other == null) {
         return;
@@ -1570,7 +2184,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1579,27 +2197,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class ComplexOptionType1 : pb::IMessage<ComplexOptionType1> {
+  public sealed partial class ComplexOptionType1 : pb::IMessage<ComplexOptionType1>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ComplexOptionType1> _parser = new pb::MessageParser<ComplexOptionType1>(() => new ComplexOptionType1());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ComplexOptionType1> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[12]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType1() {
       OnConstruction();
     }
@@ -1607,6 +2249,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType1(ComplexOptionType1 other) : this() {
       foo_ = other.foo_;
       foo2_ = other.foo2_;
@@ -1616,6 +2259,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType1 Clone() {
       return new ComplexOptionType1(this);
     }
@@ -1624,6 +2268,7 @@
     public const int FooFieldNumber = 1;
     private int foo_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Foo {
       get { return foo_; }
       set {
@@ -1635,6 +2280,7 @@
     public const int Foo2FieldNumber = 2;
     private int foo2_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Foo2 {
       get { return foo2_; }
       set {
@@ -1646,6 +2292,7 @@
     public const int Foo3FieldNumber = 3;
     private int foo3_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Foo3 {
       get { return foo3_; }
       set {
@@ -1659,16 +2306,19 @@
         = pb::FieldCodec.ForInt32(34);
     private readonly pbc::RepeatedField<int> foo4_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> Foo4 {
       get { return foo4_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ComplexOptionType1);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ComplexOptionType1 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1684,6 +2334,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Foo != 0) hash ^= Foo.GetHashCode();
@@ -1697,12 +2348,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Foo != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Foo);
@@ -1719,9 +2375,34 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Foo != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Foo);
+      }
+      if (Foo2 != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Foo2);
+      }
+      if (Foo3 != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Foo3);
+      }
+      foo4_.WriteTo(ref output, _repeated_foo4_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Foo != 0) {
@@ -1741,6 +2422,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ComplexOptionType1 other) {
       if (other == null) {
         return;
@@ -1759,7 +2441,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1785,27 +2471,68 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Foo = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Foo2 = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Foo3 = input.ReadInt32();
+            break;
+          }
+          case 34:
+          case 32: {
+            foo4_.AddEntriesFrom(ref input, _repeated_foo4_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class ComplexOptionType2 : pb::IMessage<ComplexOptionType2> {
+  public sealed partial class ComplexOptionType2 : pb::IMessage<ComplexOptionType2>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ComplexOptionType2> _parser = new pb::MessageParser<ComplexOptionType2>(() => new ComplexOptionType2());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ComplexOptionType2> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[13]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType2() {
       OnConstruction();
     }
@@ -1813,6 +2540,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType2(ComplexOptionType2 other) : this() {
       bar_ = other.bar_ != null ? other.bar_.Clone() : null;
       baz_ = other.baz_;
@@ -1822,6 +2550,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType2 Clone() {
       return new ComplexOptionType2(this);
     }
@@ -1830,6 +2559,7 @@
     public const int BarFieldNumber = 1;
     private global::UnitTest.Issues.TestProtos.ComplexOptionType1 bar_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.ComplexOptionType1 Bar {
       get { return bar_; }
       set {
@@ -1841,6 +2571,7 @@
     public const int BazFieldNumber = 2;
     private int baz_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Baz {
       get { return baz_; }
       set {
@@ -1852,6 +2583,7 @@
     public const int FredFieldNumber = 3;
     private global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 fred_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 Fred {
       get { return fred_; }
       set {
@@ -1865,16 +2597,19 @@
         = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser);
     private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> barney_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> Barney {
       get { return barney_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ComplexOptionType2);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ComplexOptionType2 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1890,6 +2625,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (bar_ != null) hash ^= Bar.GetHashCode();
@@ -1903,12 +2639,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (bar_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(Bar);
@@ -1925,9 +2666,34 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (bar_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Bar);
+      }
+      if (Baz != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Baz);
+      }
+      if (fred_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Fred);
+      }
+      barney_.WriteTo(ref output, _repeated_barney_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (bar_ != null) {
@@ -1947,6 +2713,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ComplexOptionType2 other) {
       if (other == null) {
         return;
@@ -1971,7 +2738,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2002,29 +2773,76 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (bar_ == null) {
+              Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
+            }
+            input.ReadMessage(Bar);
+            break;
+          }
+          case 16: {
+            Baz = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            if (fred_ == null) {
+              Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
+            }
+            input.ReadMessage(Fred);
+            break;
+          }
+          case 34: {
+            barney_.AddEntriesFrom(ref input, _repeated_barney_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the ComplexOptionType2 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class ComplexOptionType4 : pb::IMessage<ComplexOptionType4> {
+      public sealed partial class ComplexOptionType4 : pb::IMessage<ComplexOptionType4>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<ComplexOptionType4> _parser = new pb::MessageParser<ComplexOptionType4>(() => new ComplexOptionType4());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<ComplexOptionType4> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::UnitTest.Issues.TestProtos.ComplexOptionType2.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ComplexOptionType4() {
           OnConstruction();
         }
@@ -2032,12 +2850,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ComplexOptionType4(ComplexOptionType4 other) : this() {
           waldo_ = other.waldo_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ComplexOptionType4 Clone() {
           return new ComplexOptionType4(this);
         }
@@ -2046,6 +2866,7 @@
         public const int WaldoFieldNumber = 1;
         private int waldo_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Waldo {
           get { return waldo_; }
           set {
@@ -2054,11 +2875,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as ComplexOptionType4);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(ComplexOptionType4 other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -2071,6 +2894,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (Waldo != 0) hash ^= Waldo.GetHashCode();
@@ -2081,12 +2905,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (Waldo != 0) {
             output.WriteRawTag(8);
             output.WriteInt32(Waldo);
@@ -2094,9 +2923,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (Waldo != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Waldo);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (Waldo != 0) {
@@ -2109,6 +2954,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(ComplexOptionType4 other) {
           if (other == null) {
             return;
@@ -2120,7 +2966,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -2133,11 +2983,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Waldo = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
         #region Extensions
         /// <summary>Container for extensions for other messages declared in the ComplexOptionType4 message type.</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static partial class Extensions {
           public static readonly pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> ComplexOpt4 =
             new pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4>(7633546, pb::FieldCodec.ForMessage(61068370, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser));
@@ -2151,23 +3022,31 @@
 
   }
 
-  public sealed partial class ComplexOptionType3 : pb::IMessage<ComplexOptionType3> {
+  public sealed partial class ComplexOptionType3 : pb::IMessage<ComplexOptionType3>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ComplexOptionType3> _parser = new pb::MessageParser<ComplexOptionType3>(() => new ComplexOptionType3());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ComplexOptionType3> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[14]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType3() {
       OnConstruction();
     }
@@ -2175,12 +3054,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType3(ComplexOptionType3 other) : this() {
       qux_ = other.qux_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ComplexOptionType3 Clone() {
       return new ComplexOptionType3(this);
     }
@@ -2189,6 +3070,7 @@
     public const int QuxFieldNumber = 1;
     private int qux_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Qux {
       get { return qux_; }
       set {
@@ -2197,11 +3079,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ComplexOptionType3);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ComplexOptionType3 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2214,6 +3098,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Qux != 0) hash ^= Qux.GetHashCode();
@@ -2224,12 +3109,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Qux != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Qux);
@@ -2237,9 +3127,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Qux != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Qux);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Qux != 0) {
@@ -2252,6 +3158,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ComplexOptionType3 other) {
       if (other == null) {
         return;
@@ -2263,7 +3170,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2276,30 +3187,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Qux = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Note that we try various different ways of naming the same extension.
   /// </summary>
-  public sealed partial class VariousComplexOptions : pb::IMessage<VariousComplexOptions> {
+  public sealed partial class VariousComplexOptions : pb::IMessage<VariousComplexOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<VariousComplexOptions> _parser = new pb::MessageParser<VariousComplexOptions>(() => new VariousComplexOptions());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<VariousComplexOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[15]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public VariousComplexOptions() {
       OnConstruction();
     }
@@ -2307,21 +3246,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public VariousComplexOptions(VariousComplexOptions other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public VariousComplexOptions Clone() {
       return new VariousComplexOptions(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as VariousComplexOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(VariousComplexOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2333,6 +3276,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -2342,18 +3286,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -2363,6 +3324,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(VariousComplexOptions other) {
       if (other == null) {
         return;
@@ -2371,7 +3333,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2380,30 +3346,54 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// A helper type used to test aggregate option parsing
   /// </summary>
-  public sealed partial class Aggregate : pb::IMessage<Aggregate> {
+  public sealed partial class Aggregate : pb::IMessage<Aggregate>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Aggregate> _parser = new pb::MessageParser<Aggregate>(() => new Aggregate());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Aggregate> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[16]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Aggregate() {
       OnConstruction();
     }
@@ -2411,6 +3401,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Aggregate(Aggregate other) : this() {
       i_ = other.i_;
       s_ = other.s_;
@@ -2419,6 +3410,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Aggregate Clone() {
       return new Aggregate(this);
     }
@@ -2427,6 +3419,7 @@
     public const int IFieldNumber = 1;
     private int i_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int I {
       get { return i_; }
       set {
@@ -2438,6 +3431,7 @@
     public const int SFieldNumber = 2;
     private string s_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string S {
       get { return s_; }
       set {
@@ -2452,6 +3446,7 @@
     /// A nested object
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.Aggregate Sub {
       get { return sub_; }
       set {
@@ -2460,11 +3455,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Aggregate);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Aggregate other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2479,6 +3476,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (I != 0) hash ^= I.GetHashCode();
@@ -2491,12 +3489,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (I != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(I);
@@ -2512,9 +3515,33 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (I != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(I);
+      }
+      if (S.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(S);
+      }
+      if (sub_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Sub);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (I != 0) {
@@ -2533,6 +3560,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Aggregate other) {
       if (other == null) {
         return;
@@ -2553,7 +3581,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2577,27 +3609,66 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            I = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            S = input.ReadString();
+            break;
+          }
+          case 26: {
+            if (sub_ == null) {
+              Sub = new global::UnitTest.Issues.TestProtos.Aggregate();
+            }
+            input.ReadMessage(Sub);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class AggregateMessage : pb::IMessage<AggregateMessage> {
+  public sealed partial class AggregateMessage : pb::IMessage<AggregateMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<AggregateMessage> _parser = new pb::MessageParser<AggregateMessage>(() => new AggregateMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<AggregateMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[17]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public AggregateMessage() {
       OnConstruction();
     }
@@ -2605,12 +3676,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public AggregateMessage(AggregateMessage other) : this() {
       fieldname_ = other.fieldname_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public AggregateMessage Clone() {
       return new AggregateMessage(this);
     }
@@ -2619,6 +3692,7 @@
     public const int FieldnameFieldNumber = 1;
     private int fieldname_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Fieldname {
       get { return fieldname_; }
       set {
@@ -2627,11 +3701,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as AggregateMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(AggregateMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2644,6 +3720,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Fieldname != 0) hash ^= Fieldname.GetHashCode();
@@ -2654,12 +3731,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Fieldname != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Fieldname);
@@ -2667,9 +3749,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Fieldname != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Fieldname);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Fieldname != 0) {
@@ -2682,6 +3780,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(AggregateMessage other) {
       if (other == null) {
         return;
@@ -2693,7 +3792,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2706,30 +3809,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Fieldname = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test custom options for nested type.
   /// </summary>
-  public sealed partial class NestedOptionType : pb::IMessage<NestedOptionType> {
+  public sealed partial class NestedOptionType : pb::IMessage<NestedOptionType>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<NestedOptionType> _parser = new pb::MessageParser<NestedOptionType>(() => new NestedOptionType());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<NestedOptionType> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[18]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedOptionType() {
       OnConstruction();
     }
@@ -2737,21 +3868,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedOptionType(NestedOptionType other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedOptionType Clone() {
       return new NestedOptionType(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as NestedOptionType);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(NestedOptionType other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2763,6 +3898,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -2772,18 +3908,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -2793,6 +3946,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(NestedOptionType other) {
       if (other == null) {
         return;
@@ -2801,7 +3955,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2810,34 +3968,59 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the NestedOptionType message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum NestedEnum {
         [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0,
         [pbr::OriginalName("NESTED_ENUM_VALUE")] Value = 1,
       }
 
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::UnitTest.Issues.TestProtos.NestedOptionType.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -2845,12 +4028,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           nestedField_ = other.nestedField_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -2859,6 +4044,7 @@
         public const int NestedFieldFieldNumber = 1;
         private int nestedField_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int NestedField {
           get { return nestedField_; }
           set {
@@ -2867,11 +4053,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -2884,6 +4072,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (NestedField != 0) hash ^= NestedField.GetHashCode();
@@ -2894,12 +4083,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (NestedField != 0) {
             output.WriteRawTag(8);
             output.WriteInt32(NestedField);
@@ -2907,9 +4101,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (NestedField != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(NestedField);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (NestedField != 0) {
@@ -2922,6 +4132,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -2933,7 +4144,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -2946,8 +4161,28 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                NestedField = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs
index d5f8589..4f40564 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs
@@ -59,24 +59,32 @@
   #endregion
 
   #region Messages
-  public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
+  public sealed partial class ImportMessage : pb::IMessage<ImportMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestImportReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ImportMessage() {
       OnConstruction();
     }
@@ -84,6 +92,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ImportMessage(ImportMessage other) : this() {
       _hasBits0 = other._hasBits0;
       d_ = other.d_;
@@ -91,6 +100,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ImportMessage Clone() {
       return new ImportMessage(this);
     }
@@ -101,6 +111,7 @@
 
     private int d_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int D {
       get { if ((_hasBits0 & 1) != 0) { return d_; } else { return DDefaultValue; } }
       set {
@@ -110,21 +121,25 @@
     }
     /// <summary>Gets whether the "d" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasD {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "d" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearD() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ImportMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ImportMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -137,6 +152,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasD) hash ^= D.GetHashCode();
@@ -147,12 +163,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasD) {
         output.WriteRawTag(8);
         output.WriteInt32(D);
@@ -160,9 +181,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasD) {
+        output.WriteRawTag(8);
+        output.WriteInt32(D);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasD) {
@@ -175,6 +212,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ImportMessage other) {
       if (other == null) {
         return;
@@ -186,7 +224,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -199,8 +241,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            D = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs
index 19a1a34..a3ce7a2 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs
@@ -50,23 +50,31 @@
   #endregion
 
   #region Messages
-  public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
+  public sealed partial class ImportMessage : pb::IMessage<ImportMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ImportMessage() {
       OnConstruction();
     }
@@ -74,12 +82,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ImportMessage(ImportMessage other) : this() {
       d_ = other.d_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ImportMessage Clone() {
       return new ImportMessage(this);
     }
@@ -88,6 +98,7 @@
     public const int DFieldNumber = 1;
     private int d_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int D {
       get { return d_; }
       set {
@@ -96,11 +107,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ImportMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ImportMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -113,6 +126,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (D != 0) hash ^= D.GetHashCode();
@@ -123,12 +137,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (D != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(D);
@@ -136,9 +155,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (D != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(D);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (D != 0) {
@@ -151,6 +186,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ImportMessage other) {
       if (other == null) {
         return;
@@ -162,7 +198,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -175,8 +215,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            D = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs
index 77f2121..b1e0f30 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs
@@ -37,24 +37,32 @@
 
   }
   #region Messages
-  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
+  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.Proto2.UnittestImportPublicReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public PublicImportMessage() {
       OnConstruction();
     }
@@ -62,6 +70,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public PublicImportMessage(PublicImportMessage other) : this() {
       _hasBits0 = other._hasBits0;
       e_ = other.e_;
@@ -69,6 +78,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public PublicImportMessage Clone() {
       return new PublicImportMessage(this);
     }
@@ -79,6 +89,7 @@
 
     private int e_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int E {
       get { if ((_hasBits0 & 1) != 0) { return e_; } else { return EDefaultValue; } }
       set {
@@ -88,21 +99,25 @@
     }
     /// <summary>Gets whether the "e" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasE {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "e" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearE() {
       _hasBits0 &= ~1;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as PublicImportMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(PublicImportMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -115,6 +130,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasE) hash ^= E.GetHashCode();
@@ -125,12 +141,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasE) {
         output.WriteRawTag(8);
         output.WriteInt32(E);
@@ -138,9 +159,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasE) {
+        output.WriteRawTag(8);
+        output.WriteInt32(E);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasE) {
@@ -153,6 +190,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(PublicImportMessage other) {
       if (other == null) {
         return;
@@ -164,7 +202,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -177,8 +219,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            E = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs
index a455655..dde8b9b 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs
@@ -38,23 +38,31 @@
 
   }
   #region Messages
-  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
+  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public PublicImportMessage() {
       OnConstruction();
     }
@@ -62,12 +70,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public PublicImportMessage(PublicImportMessage other) : this() {
       e_ = other.e_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public PublicImportMessage Clone() {
       return new PublicImportMessage(this);
     }
@@ -76,6 +86,7 @@
     public const int EFieldNumber = 1;
     private int e_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int E {
       get { return e_; }
       set {
@@ -84,11 +95,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as PublicImportMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(PublicImportMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -101,6 +114,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (E != 0) hash ^= E.GetHashCode();
@@ -111,12 +125,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (E != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(E);
@@ -124,9 +143,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (E != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(E);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (E != 0) {
@@ -139,6 +174,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(PublicImportMessage other) {
       if (other == null) {
         return;
@@ -150,7 +186,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -163,8 +203,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            E = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs
index 6b816f7..1ac4a67 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs
@@ -37,23 +37,31 @@
 
   }
   #region Messages
-  public sealed partial class Foo : pb::IMessage<Foo> {
+  public sealed partial class Foo : pb::IMessage<Foo>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Foo> _parser = new pb::MessageParser<Foo>(() => new Foo());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Foo> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssue6936BReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Foo() {
       OnConstruction();
     }
@@ -61,21 +69,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Foo(Foo other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Foo Clone() {
       return new Foo(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Foo);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Foo other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -87,6 +99,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -96,18 +109,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -117,6 +147,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Foo other) {
       if (other == null) {
         return;
@@ -125,7 +156,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -134,8 +169,24 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs
index a8a73f6..d7789b8 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs
@@ -39,23 +39,31 @@
 
   }
   #region Messages
-  public sealed partial class Bar : pb::IMessage<Bar> {
+  public sealed partial class Bar : pb::IMessage<Bar>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Bar> _parser = new pb::MessageParser<Bar>(() => new Bar());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Bar> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssue6936CReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Bar() {
       OnConstruction();
     }
@@ -63,12 +71,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Bar(Bar other) : this() {
       foo_ = other.foo_ != null ? other.foo_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Bar Clone() {
       return new Bar(this);
     }
@@ -77,6 +87,7 @@
     public const int FooFieldNumber = 1;
     private global::UnitTest.Issues.TestProtos.Foo foo_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.Foo Foo {
       get { return foo_; }
       set {
@@ -85,11 +96,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Bar);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Bar other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -102,6 +115,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (foo_ != null) hash ^= Foo.GetHashCode();
@@ -112,12 +126,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (foo_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(Foo);
@@ -125,9 +144,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (foo_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Foo);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (foo_ != null) {
@@ -140,6 +175,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Bar other) {
       if (other == null) {
         return;
@@ -154,7 +190,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -170,8 +210,31 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (foo_ == null) {
+              Foo = new global::UnitTest.Issues.TestProtos.Foo();
+            }
+            input.ReadMessage(Foo);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
index f3f40c6..ec4c07b 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
@@ -24,36 +24,43 @@
     static UnittestIssuesReflection() {
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
-            "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ",
-            "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh",
-            "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz",
-            "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p",
-            "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO",
-            "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj",
-            "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt",
-            "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC",
-            "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E",
-            "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu",
-            "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1",
-            "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES",
-            "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0",
-            "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl",
-            "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa",
-            "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT",
-            "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv",
-            "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p",
-            "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y",
-            "IksKDFRlc3RKc29uTmFtZRIMCgRuYW1lGAEgASgJEhkKC2Rlc2NyaXB0aW9u",
-            "GAIgASgJUgRkZXNjEhIKBGd1aWQYAyABKAlSBGV4aWQifwoMT25lb2ZNZXJn",
-            "aW5nEg4KBHRleHQYASABKAlIABI2CgZuZXN0ZWQYAiABKAsyJC51bml0dGVz",
-            "dF9pc3N1ZXMuT25lb2ZNZXJnaW5nLk5lc3RlZEgAGh4KBk5lc3RlZBIJCgF4",
-            "GAEgASgFEgkKAXkYAiABKAVCBwoFdmFsdWUqVQoMTmVnYXRpdmVFbnVtEhYK",
-            "Ek5FR0FUSVZFX0VOVU1fWkVSTxAAEhYKCUZpdmVCZWxvdxD7//////////8B",
-            "EhUKCE1pbnVzT25lEP///////////wEqLgoORGVwcmVjYXRlZEVudW0SEwoP",
-            "REVQUkVDQVRFRF9aRVJPEAASBwoDb25lEAFCHaoCGlVuaXRUZXN0Lklzc3Vl",
-            "cy5UZXN0UHJvdG9zYgZwcm90bzM="));
+            "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcxocZ29v",
+            "Z2xlL3Byb3RvYnVmL3N0cnVjdC5wcm90byInCghJc3N1ZTMwNxobCgpOZXN0",
+            "ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdhdGl2ZUVudW1NZXNzYWdl",
+            "EiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51",
+            "bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9pc3N1ZXMuTmVnYXRpdmVF",
+            "bnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygOMh0udW5pdHRlc3RfaXNz",
+            "dWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVjYXRlZENoaWxkIrkCChdE",
+            "ZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5QcmltaXRpdmVWYWx1ZRgBIAEo",
+            "BUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVCAhgBEjoKDE1lc3NhZ2VW",
+            "YWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRC",
+            "AhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E",
+            "ZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1ZRgFIAEoDjIfLnVuaXR0",
+            "ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAESNgoJRW51bUFycmF5GAYg",
+            "AygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0ZWRFbnVtQgIYASIZCglJ",
+            "dGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNlcnZlZE5hbWVzEg0KBXR5",
+            "cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUaEAoOU29tZU5lc3RlZFR5",
+            "cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxITCgtwbGFpbl9pbnQzMhgE",
+            "IAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghvMV9pbnQzMhgFIAEoBUgA",
+            "EhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9pbnQzMhgGIAEoBUgBEhMK",
+            "CW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8yIksKDFRlc3RKc29uTmFt",
+            "ZRIMCgRuYW1lGAEgASgJEhkKC2Rlc2NyaXB0aW9uGAIgASgJUgRkZXNjEhIK",
+            "BGd1aWQYAyABKAlSBGV4aWQifwoMT25lb2ZNZXJnaW5nEg4KBHRleHQYASAB",
+            "KAlIABI2CgZuZXN0ZWQYAiABKAsyJC51bml0dGVzdF9pc3N1ZXMuT25lb2ZN",
+            "ZXJnaW5nLk5lc3RlZEgAGh4KBk5lc3RlZBIJCgF4GAEgASgFEgkKAXkYAiAB",
+            "KAVCBwoFdmFsdWUiawoWTnVsbFZhbHVlT3V0c2lkZVN0cnVjdBIWCgxzdHJp",
+            "bmdfdmFsdWUYASABKAlIABIwCgpudWxsX3ZhbHVlGAIgASgOMhouZ29vZ2xl",
+            "LnByb3RvYnVmLk51bGxWYWx1ZUgAQgcKBXZhbHVlIkUKE051bGxWYWx1ZU5v",
+            "dEluT25lb2YSLgoKbnVsbF92YWx1ZRgCIAEoDjIaLmdvb2dsZS5wcm90b2J1",
+            "Zi5OdWxsVmFsdWUiYAoXTWl4ZWRSZWd1bGFyQW5kT3B0aW9uYWwSFQoNcmVn",
+            "dWxhcl9maWVsZBgBIAEoCRIbCg5vcHRpb25hbF9maWVsZBgCIAEoCUgAiAEB",
+            "QhEKD19vcHRpb25hbF9maWVsZCpVCgxOZWdhdGl2ZUVudW0SFgoSTkVHQVRJ",
+            "VkVfRU5VTV9aRVJPEAASFgoJRml2ZUJlbG93EPv//////////wESFQoITWlu",
+            "dXNPbmUQ////////////ASouCg5EZXByZWNhdGVkRW51bRITCg9ERVBSRUNB",
+            "VEVEX1pFUk8QABIHCgNvbmUQAUIdqgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQ",
+            "cm90b3NiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
-          new pbr::FileDescriptor[] { },
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, null, new pbr::GeneratedClrTypeInfo[] {
             new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null, null)})}),
             new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null, null),
@@ -63,7 +70,10 @@
             new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonName), global::UnitTest.Issues.TestProtos.TestJsonName.Parser, new[]{ "Name", "Description", "Guid" }, null, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging), global::UnitTest.Issues.TestProtos.OneofMerging.Parser, new[]{ "Text", "Nested" }, new[]{ "Value" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested), global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested.Parser, new[]{ "X", "Y" }, null, null, null, null)})
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging), global::UnitTest.Issues.TestProtos.OneofMerging.Parser, new[]{ "Text", "Nested" }, new[]{ "Value" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested), global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested.Parser, new[]{ "X", "Y" }, null, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueOutsideStruct), global::UnitTest.Issues.TestProtos.NullValueOutsideStruct.Parser, new[]{ "StringValue", "NullValue" }, new[]{ "Value" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueNotInOneof), global::UnitTest.Issues.TestProtos.NullValueNotInOneof.Parser, new[]{ "NullValue" }, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.MixedRegularAndOptional), global::UnitTest.Issues.TestProtos.MixedRegularAndOptional.Parser, new[]{ "RegularField", "OptionalField" }, new[]{ "OptionalField" }, null, null, null)
           }));
     }
     #endregion
@@ -88,23 +98,31 @@
   /// Issue 307: when generating doubly-nested types, any references
   /// should be of the form A.Types.B.Types.C.
   /// </summary>
-  public sealed partial class Issue307 : pb::IMessage<Issue307> {
+  public sealed partial class Issue307 : pb::IMessage<Issue307>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Issue307> _parser = new pb::MessageParser<Issue307>(() => new Issue307());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Issue307> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Issue307() {
       OnConstruction();
     }
@@ -112,21 +130,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Issue307(Issue307 other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Issue307 Clone() {
       return new Issue307(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Issue307);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Issue307 other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -138,6 +160,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -147,18 +170,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -168,6 +208,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Issue307 other) {
       if (other == null) {
         return;
@@ -176,7 +217,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -185,29 +230,54 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the Issue307 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class NestedOnce : pb::IMessage<NestedOnce> {
+      public sealed partial class NestedOnce : pb::IMessage<NestedOnce>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedOnce> _parser = new pb::MessageParser<NestedOnce>(() => new NestedOnce());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedOnce> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedOnce() {
           OnConstruction();
         }
@@ -215,21 +285,25 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedOnce(NestedOnce other) : this() {
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedOnce Clone() {
           return new NestedOnce(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedOnce);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedOnce other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -241,6 +315,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (_unknownFields != null) {
@@ -250,18 +325,35 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (_unknownFields != null) {
@@ -271,6 +363,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedOnce other) {
           if (other == null) {
             return;
@@ -279,7 +372,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -288,29 +385,54 @@
                 break;
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+            }
+          }
+        }
+        #endif
+
         #region Nested types
         /// <summary>Container for nested types declared in the NestedOnce message type.</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static partial class Types {
-          public sealed partial class NestedTwice : pb::IMessage<NestedTwice> {
+          public sealed partial class NestedTwice : pb::IMessage<NestedTwice>
+          #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              , pb::IBufferMessage
+          #endif
+          {
             private static readonly pb::MessageParser<NestedTwice> _parser = new pb::MessageParser<NestedTwice>(() => new NestedTwice());
             private pb::UnknownFieldSet _unknownFields;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pb::MessageParser<NestedTwice> Parser { get { return _parser; } }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public static pbr::MessageDescriptor Descriptor {
               get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             pbr::MessageDescriptor pb::IMessage.Descriptor {
               get { return Descriptor; }
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public NestedTwice() {
               OnConstruction();
             }
@@ -318,21 +440,25 @@
             partial void OnConstruction();
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public NestedTwice(NestedTwice other) : this() {
               _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public NestedTwice Clone() {
               return new NestedTwice(this);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override bool Equals(object other) {
               return Equals(other as NestedTwice);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public bool Equals(NestedTwice other) {
               if (ReferenceEquals(other, null)) {
                 return false;
@@ -344,6 +470,7 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override int GetHashCode() {
               int hash = 1;
               if (_unknownFields != null) {
@@ -353,18 +480,35 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public override string ToString() {
               return pb::JsonFormatter.ToDiagnosticString(this);
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void WriteTo(pb::CodedOutputStream output) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              output.WriteRawMessage(this);
+            #else
               if (_unknownFields != null) {
                 _unknownFields.WriteTo(output);
               }
+            #endif
             }
 
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+              if (_unknownFields != null) {
+                _unknownFields.WriteTo(ref output);
+              }
+            }
+            #endif
+
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public int CalculateSize() {
               int size = 0;
               if (_unknownFields != null) {
@@ -374,6 +518,7 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(NestedTwice other) {
               if (other == null) {
                 return;
@@ -382,7 +527,11 @@
             }
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
             public void MergeFrom(pb::CodedInputStream input) {
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+              input.ReadRawMessage(this);
+            #else
               uint tag;
               while ((tag = input.ReadTag()) != 0) {
                 switch(tag) {
@@ -391,8 +540,24 @@
                     break;
                 }
               }
+            #endif
             }
 
+            #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+            [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+            [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+            void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  default:
+                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                    break;
+                }
+              }
+            }
+            #endif
+
           }
 
         }
@@ -405,23 +570,31 @@
 
   }
 
-  public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage> {
+  public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NegativeEnumMessage() {
       OnConstruction();
     }
@@ -429,6 +602,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NegativeEnumMessage(NegativeEnumMessage other) : this() {
       value_ = other.value_;
       values_ = other.values_.Clone();
@@ -437,6 +611,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NegativeEnumMessage Clone() {
       return new NegativeEnumMessage(this);
     }
@@ -445,6 +620,7 @@
     public const int ValueFieldNumber = 1;
     private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.Zero;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.NegativeEnum Value {
       get { return value_; }
       set {
@@ -458,6 +634,7 @@
         = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
     private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> Values {
       get { return values_; }
     }
@@ -468,16 +645,19 @@
         = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
     private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValues {
       get { return packedValues_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as NegativeEnumMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(NegativeEnumMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -492,6 +672,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) hash ^= Value.GetHashCode();
@@ -504,12 +685,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Value);
@@ -519,9 +705,27 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Value);
+      }
+      values_.WriteTo(ref output, _repeated_values_codec);
+      packedValues_.WriteTo(ref output, _repeated_packedValues_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) {
@@ -536,6 +740,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(NegativeEnumMessage other) {
       if (other == null) {
         return;
@@ -549,7 +754,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -572,27 +781,65 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Value = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
+            break;
+          }
+          case 18:
+          case 16: {
+            values_.AddEntriesFrom(ref input, _repeated_values_codec);
+            break;
+          }
+          case 26:
+          case 24: {
+            packedValues_.AddEntriesFrom(ref input, _repeated_packedValues_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild> {
+  public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DeprecatedChild() {
       OnConstruction();
     }
@@ -600,21 +847,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DeprecatedChild(DeprecatedChild other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DeprecatedChild Clone() {
       return new DeprecatedChild(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as DeprecatedChild);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(DeprecatedChild other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -626,6 +877,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -635,18 +887,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -656,6 +925,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(DeprecatedChild other) {
       if (other == null) {
         return;
@@ -664,7 +934,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -673,27 +947,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage> {
+  public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DeprecatedFieldsMessage() {
       OnConstruction();
     }
@@ -701,6 +999,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) : this() {
       primitiveValue_ = other.primitiveValue_;
       primitiveArray_ = other.primitiveArray_.Clone();
@@ -712,6 +1011,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DeprecatedFieldsMessage Clone() {
       return new DeprecatedFieldsMessage(this);
     }
@@ -721,6 +1021,7 @@
     private int primitiveValue_;
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int PrimitiveValue {
       get { return primitiveValue_; }
       set {
@@ -735,6 +1036,7 @@
     private readonly pbc::RepeatedField<int> primitiveArray_ = new pbc::RepeatedField<int>();
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PrimitiveArray {
       get { return primitiveArray_; }
     }
@@ -744,6 +1046,7 @@
     private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_;
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
       get { return messageValue_; }
       set {
@@ -758,6 +1061,7 @@
     private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> messageArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild>();
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArray {
       get { return messageArray_; }
     }
@@ -767,6 +1071,7 @@
     private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero;
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
       get { return enumValue_; }
       set {
@@ -781,16 +1086,19 @@
     private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArray {
       get { return enumArray_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as DeprecatedFieldsMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(DeprecatedFieldsMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -808,6 +1116,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (PrimitiveValue != 0) hash ^= PrimitiveValue.GetHashCode();
@@ -823,12 +1132,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (PrimitiveValue != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(PrimitiveValue);
@@ -847,9 +1161,36 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (PrimitiveValue != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(PrimitiveValue);
+      }
+      primitiveArray_.WriteTo(ref output, _repeated_primitiveArray_codec);
+      if (messageValue_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(MessageValue);
+      }
+      messageArray_.WriteTo(ref output, _repeated_messageArray_codec);
+      if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) EnumValue);
+      }
+      enumArray_.WriteTo(ref output, _repeated_enumArray_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (PrimitiveValue != 0) {
@@ -871,6 +1212,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(DeprecatedFieldsMessage other) {
       if (other == null) {
         return;
@@ -894,7 +1236,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -932,30 +1278,83 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            PrimitiveValue = input.ReadInt32();
+            break;
+          }
+          case 18:
+          case 16: {
+            primitiveArray_.AddEntriesFrom(ref input, _repeated_primitiveArray_codec);
+            break;
+          }
+          case 26: {
+            if (messageValue_ == null) {
+              MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
+            }
+            input.ReadMessage(MessageValue);
+            break;
+          }
+          case 34: {
+            messageArray_.AddEntriesFrom(ref input, _repeated_messageArray_codec);
+            break;
+          }
+          case 40: {
+            EnumValue = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
+            break;
+          }
+          case 50:
+          case 48: {
+            enumArray_.AddEntriesFrom(ref input, _repeated_enumArray_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
   /// </summary>
-  public sealed partial class ItemField : pb::IMessage<ItemField> {
+  public sealed partial class ItemField : pb::IMessage<ItemField>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ItemField> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ItemField() {
       OnConstruction();
     }
@@ -963,12 +1362,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ItemField(ItemField other) : this() {
       item_ = other.item_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ItemField Clone() {
       return new ItemField(this);
     }
@@ -977,6 +1378,7 @@
     public const int ItemFieldNumber = 1;
     private int item_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Item {
       get { return item_; }
       set {
@@ -985,11 +1387,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ItemField);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ItemField other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1002,6 +1406,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Item != 0) hash ^= Item.GetHashCode();
@@ -1012,12 +1417,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Item != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Item);
@@ -1025,9 +1435,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Item != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Item);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Item != 0) {
@@ -1040,6 +1466,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ItemField other) {
       if (other == null) {
         return;
@@ -1051,7 +1478,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1064,27 +1495,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Item = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class ReservedNames : pb::IMessage<ReservedNames> {
+  public sealed partial class ReservedNames : pb::IMessage<ReservedNames>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ReservedNames> _parser = new pb::MessageParser<ReservedNames>(() => new ReservedNames());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ReservedNames> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ReservedNames() {
       OnConstruction();
     }
@@ -1092,6 +1551,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ReservedNames(ReservedNames other) : this() {
       types_ = other.types_;
       descriptor_ = other.descriptor_;
@@ -1099,6 +1559,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ReservedNames Clone() {
       return new ReservedNames(this);
     }
@@ -1107,6 +1568,7 @@
     public const int Types_FieldNumber = 1;
     private int types_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Types_ {
       get { return types_; }
       set {
@@ -1118,6 +1580,7 @@
     public const int Descriptor_FieldNumber = 2;
     private int descriptor_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Descriptor_ {
       get { return descriptor_; }
       set {
@@ -1126,11 +1589,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ReservedNames);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ReservedNames other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1144,6 +1609,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Types_ != 0) hash ^= Types_.GetHashCode();
@@ -1155,12 +1621,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Types_ != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Types_);
@@ -1172,9 +1643,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Types_ != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Types_);
+      }
+      if (Descriptor_ != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Descriptor_);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Types_ != 0) {
@@ -1190,6 +1681,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ReservedNames other) {
       if (other == null) {
         return;
@@ -1204,7 +1696,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1221,32 +1717,65 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Types_ = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Descriptor_ = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the ReservedNames message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// Force a nested type called Types
       /// </summary>
-      public sealed partial class SomeNestedType : pb::IMessage<SomeNestedType> {
+      public sealed partial class SomeNestedType : pb::IMessage<SomeNestedType>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<SomeNestedType> _parser = new pb::MessageParser<SomeNestedType>(() => new SomeNestedType());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<SomeNestedType> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::UnitTest.Issues.TestProtos.ReservedNames.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SomeNestedType() {
           OnConstruction();
         }
@@ -1254,21 +1783,25 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SomeNestedType(SomeNestedType other) : this() {
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public SomeNestedType Clone() {
           return new SomeNestedType(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as SomeNestedType);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(SomeNestedType other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -1280,6 +1813,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (_unknownFields != null) {
@@ -1289,18 +1823,35 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (_unknownFields != null) {
@@ -1310,6 +1861,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(SomeNestedType other) {
           if (other == null) {
             return;
@@ -1318,7 +1870,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -1327,8 +1883,24 @@
                 break;
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -1348,23 +1920,31 @@
   /// Alternatively, consider just adding this to
   /// unittest_proto3.proto if multiple platforms want it.
   /// </summary>
-  public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering> {
+  public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestJsonFieldOrdering> _parser = new pb::MessageParser<TestJsonFieldOrdering>(() => new TestJsonFieldOrdering());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestJsonFieldOrdering> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonFieldOrdering() {
       OnConstruction();
     }
@@ -1372,6 +1952,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonFieldOrdering(TestJsonFieldOrdering other) : this() {
       plainInt32_ = other.plainInt32_;
       plainString_ = other.plainString_;
@@ -1397,6 +1978,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonFieldOrdering Clone() {
       return new TestJsonFieldOrdering(this);
     }
@@ -1405,6 +1987,7 @@
     public const int PlainInt32FieldNumber = 4;
     private int plainInt32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int PlainInt32 {
       get { return plainInt32_; }
       set {
@@ -1415,6 +1998,7 @@
     /// <summary>Field number for the "o1_string" field.</summary>
     public const int O1StringFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string O1String {
       get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; }
       set {
@@ -1426,6 +2010,7 @@
     /// <summary>Field number for the "o1_int32" field.</summary>
     public const int O1Int32FieldNumber = 5;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int O1Int32 {
       get { return o1Case_ == O1OneofCase.O1Int32 ? (int) o1_ : 0; }
       set {
@@ -1438,6 +2023,7 @@
     public const int PlainStringFieldNumber = 1;
     private string plainString_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string PlainString {
       get { return plainString_; }
       set {
@@ -1448,6 +2034,7 @@
     /// <summary>Field number for the "o2_int32" field.</summary>
     public const int O2Int32FieldNumber = 6;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int O2Int32 {
       get { return o2Case_ == O2OneofCase.O2Int32 ? (int) o2_ : 0; }
       set {
@@ -1459,6 +2046,7 @@
     /// <summary>Field number for the "o2_string" field.</summary>
     public const int O2StringFieldNumber = 3;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string O2String {
       get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; }
       set {
@@ -1476,11 +2064,13 @@
     }
     private O1OneofCase o1Case_ = O1OneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public O1OneofCase O1Case {
       get { return o1Case_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearO1() {
       o1Case_ = O1OneofCase.None;
       o1_ = null;
@@ -1495,22 +2085,26 @@
     }
     private O2OneofCase o2Case_ = O2OneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public O2OneofCase O2Case {
       get { return o2Case_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearO2() {
       o2Case_ = O2OneofCase.None;
       o2_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestJsonFieldOrdering);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestJsonFieldOrdering other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1530,6 +2124,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (PlainInt32 != 0) hash ^= PlainInt32.GetHashCode();
@@ -1547,12 +2142,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (PlainString.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(PlainString);
@@ -1580,9 +2180,45 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (PlainString.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(PlainString);
+      }
+      if (o1Case_ == O1OneofCase.O1String) {
+        output.WriteRawTag(18);
+        output.WriteString(O1String);
+      }
+      if (o2Case_ == O2OneofCase.O2String) {
+        output.WriteRawTag(26);
+        output.WriteString(O2String);
+      }
+      if (PlainInt32 != 0) {
+        output.WriteRawTag(32);
+        output.WriteInt32(PlainInt32);
+      }
+      if (o1Case_ == O1OneofCase.O1Int32) {
+        output.WriteRawTag(40);
+        output.WriteInt32(O1Int32);
+      }
+      if (o2Case_ == O2OneofCase.O2Int32) {
+        output.WriteRawTag(48);
+        output.WriteInt32(O2Int32);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (PlainInt32 != 0) {
@@ -1610,6 +2246,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestJsonFieldOrdering other) {
       if (other == null) {
         return;
@@ -1642,7 +2279,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1675,27 +2316,75 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            PlainString = input.ReadString();
+            break;
+          }
+          case 18: {
+            O1String = input.ReadString();
+            break;
+          }
+          case 26: {
+            O2String = input.ReadString();
+            break;
+          }
+          case 32: {
+            PlainInt32 = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            O1Int32 = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            O2Int32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestJsonName : pb::IMessage<TestJsonName> {
+  public sealed partial class TestJsonName : pb::IMessage<TestJsonName>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestJsonName> _parser = new pb::MessageParser<TestJsonName>(() => new TestJsonName());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestJsonName> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[7]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonName() {
       OnConstruction();
     }
@@ -1703,6 +2392,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonName(TestJsonName other) : this() {
       name_ = other.name_;
       description_ = other.description_;
@@ -1711,6 +2401,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestJsonName Clone() {
       return new TestJsonName(this);
     }
@@ -1722,6 +2413,7 @@
     /// Message for testing the effects for of the json_name option
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -1733,6 +2425,7 @@
     public const int DescriptionFieldNumber = 2;
     private string description_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Description {
       get { return description_; }
       set {
@@ -1744,6 +2437,7 @@
     public const int GuidFieldNumber = 3;
     private string guid_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Guid {
       get { return guid_; }
       set {
@@ -1752,11 +2446,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestJsonName);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestJsonName other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1771,6 +2467,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -1783,12 +2480,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -1804,9 +2506,33 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Description.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(Description);
+      }
+      if (Guid.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(Guid);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -1825,6 +2551,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestJsonName other) {
       if (other == null) {
         return;
@@ -1842,7 +2569,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1863,8 +2594,36 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Description = input.ReadString();
+            break;
+          }
+          case 26: {
+            Guid = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -1872,23 +2631,31 @@
   /// oneof case, which is itself a message type, the submessages should
   /// be merged.
   /// </summary>
-  public sealed partial class OneofMerging : pb::IMessage<OneofMerging> {
+  public sealed partial class OneofMerging : pb::IMessage<OneofMerging>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneofMerging> _parser = new pb::MessageParser<OneofMerging>(() => new OneofMerging());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneofMerging> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[8]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofMerging() {
       OnConstruction();
     }
@@ -1896,6 +2663,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofMerging(OneofMerging other) : this() {
       switch (other.ValueCase) {
         case ValueOneofCase.Text:
@@ -1910,6 +2678,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofMerging Clone() {
       return new OneofMerging(this);
     }
@@ -1917,6 +2686,7 @@
     /// <summary>Field number for the "text" field.</summary>
     public const int TextFieldNumber = 1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Text {
       get { return valueCase_ == ValueOneofCase.Text ? (string) value_ : ""; }
       set {
@@ -1928,6 +2698,7 @@
     /// <summary>Field number for the "nested" field.</summary>
     public const int NestedFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested Nested {
       get { return valueCase_ == ValueOneofCase.Nested ? (global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested) value_ : null; }
       set {
@@ -1945,22 +2716,26 @@
     }
     private ValueOneofCase valueCase_ = ValueOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ValueOneofCase ValueCase {
       get { return valueCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearValue() {
       valueCase_ = ValueOneofCase.None;
       value_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneofMerging);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneofMerging other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1975,6 +2750,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (valueCase_ == ValueOneofCase.Text) hash ^= Text.GetHashCode();
@@ -1987,12 +2763,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (valueCase_ == ValueOneofCase.Text) {
         output.WriteRawTag(10);
         output.WriteString(Text);
@@ -2004,9 +2785,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (valueCase_ == ValueOneofCase.Text) {
+        output.WriteRawTag(10);
+        output.WriteString(Text);
+      }
+      if (valueCase_ == ValueOneofCase.Nested) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Nested);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (valueCase_ == ValueOneofCase.Text) {
@@ -2022,6 +2823,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneofMerging other) {
       if (other == null) {
         return;
@@ -2042,7 +2844,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2064,29 +2870,67 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Text = input.ReadString();
+            break;
+          }
+          case 18: {
+            global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested subBuilder = new global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested();
+            if (valueCase_ == ValueOneofCase.Nested) {
+              subBuilder.MergeFrom(Nested);
+            }
+            input.ReadMessage(subBuilder);
+            Nested = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the OneofMerging message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class Nested : pb::IMessage<Nested> {
+      public sealed partial class Nested : pb::IMessage<Nested>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<Nested> _parser = new pb::MessageParser<Nested>(() => new Nested());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<Nested> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::UnitTest.Issues.TestProtos.OneofMerging.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Nested() {
           OnConstruction();
         }
@@ -2094,6 +2938,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Nested(Nested other) : this() {
           x_ = other.x_;
           y_ = other.y_;
@@ -2101,6 +2946,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Nested Clone() {
           return new Nested(this);
         }
@@ -2109,6 +2955,7 @@
         public const int XFieldNumber = 1;
         private int x_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int X {
           get { return x_; }
           set {
@@ -2120,6 +2967,7 @@
         public const int YFieldNumber = 2;
         private int y_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Y {
           get { return y_; }
           set {
@@ -2128,11 +2976,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as Nested);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(Nested other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -2146,6 +2996,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (X != 0) hash ^= X.GetHashCode();
@@ -2157,12 +3008,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (X != 0) {
             output.WriteRawTag(8);
             output.WriteInt32(X);
@@ -2174,9 +3030,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (X != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(X);
+          }
+          if (Y != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(Y);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (X != 0) {
@@ -2192,6 +3068,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(Nested other) {
           if (other == null) {
             return;
@@ -2206,7 +3083,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -2223,8 +3104,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                X = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Y = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -2232,6 +3137,694 @@
 
   }
 
+  public sealed partial class NullValueOutsideStruct : pb::IMessage<NullValueOutsideStruct>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<NullValueOutsideStruct> _parser = new pb::MessageParser<NullValueOutsideStruct>(() => new NullValueOutsideStruct());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<NullValueOutsideStruct> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[9]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public NullValueOutsideStruct() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public NullValueOutsideStruct(NullValueOutsideStruct other) : this() {
+      switch (other.ValueCase) {
+        case ValueOneofCase.StringValue:
+          StringValue = other.StringValue;
+          break;
+        case ValueOneofCase.NullValue:
+          NullValue = other.NullValue;
+          break;
+      }
+
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public NullValueOutsideStruct Clone() {
+      return new NullValueOutsideStruct(this);
+    }
+
+    /// <summary>Field number for the "string_value" field.</summary>
+    public const int StringValueFieldNumber = 1;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string StringValue {
+      get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; }
+      set {
+        value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        valueCase_ = ValueOneofCase.StringValue;
+      }
+    }
+
+    /// <summary>Field number for the "null_value" field.</summary>
+    public const int NullValueFieldNumber = 2;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::Google.Protobuf.WellKnownTypes.NullValue NullValue {
+      get { return valueCase_ == ValueOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) value_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; }
+      set {
+        value_ = value;
+        valueCase_ = ValueOneofCase.NullValue;
+      }
+    }
+
+    private object value_;
+    /// <summary>Enum of possible cases for the "value" oneof.</summary>
+    public enum ValueOneofCase {
+      None = 0,
+      StringValue = 1,
+      NullValue = 2,
+    }
+    private ValueOneofCase valueCase_ = ValueOneofCase.None;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ValueOneofCase ValueCase {
+      get { return valueCase_; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearValue() {
+      valueCase_ = ValueOneofCase.None;
+      value_ = null;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as NullValueOutsideStruct);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(NullValueOutsideStruct other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (StringValue != other.StringValue) return false;
+      if (NullValue != other.NullValue) return false;
+      if (ValueCase != other.ValueCase) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode();
+      if (valueCase_ == ValueOneofCase.NullValue) hash ^= NullValue.GetHashCode();
+      hash ^= (int) valueCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (valueCase_ == ValueOneofCase.StringValue) {
+        output.WriteRawTag(10);
+        output.WriteString(StringValue);
+      }
+      if (valueCase_ == ValueOneofCase.NullValue) {
+        output.WriteRawTag(16);
+        output.WriteEnum((int) NullValue);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (valueCase_ == ValueOneofCase.StringValue) {
+        output.WriteRawTag(10);
+        output.WriteString(StringValue);
+      }
+      if (valueCase_ == ValueOneofCase.NullValue) {
+        output.WriteRawTag(16);
+        output.WriteEnum((int) NullValue);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (valueCase_ == ValueOneofCase.StringValue) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
+      }
+      if (valueCase_ == ValueOneofCase.NullValue) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(NullValueOutsideStruct other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.ValueCase) {
+        case ValueOneofCase.StringValue:
+          StringValue = other.StringValue;
+          break;
+        case ValueOneofCase.NullValue:
+          NullValue = other.NullValue;
+          break;
+      }
+
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 10: {
+            StringValue = input.ReadString();
+            break;
+          }
+          case 16: {
+            value_ = input.ReadEnum();
+            valueCase_ = ValueOneofCase.NullValue;
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            StringValue = input.ReadString();
+            break;
+          }
+          case 16: {
+            value_ = input.ReadEnum();
+            valueCase_ = ValueOneofCase.NullValue;
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
+  public sealed partial class NullValueNotInOneof : pb::IMessage<NullValueNotInOneof>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<NullValueNotInOneof> _parser = new pb::MessageParser<NullValueNotInOneof>(() => new NullValueNotInOneof());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<NullValueNotInOneof> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[10]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public NullValueNotInOneof() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public NullValueNotInOneof(NullValueNotInOneof other) : this() {
+      nullValue_ = other.nullValue_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public NullValueNotInOneof Clone() {
+      return new NullValueNotInOneof(this);
+    }
+
+    /// <summary>Field number for the "null_value" field.</summary>
+    public const int NullValueFieldNumber = 2;
+    private global::Google.Protobuf.WellKnownTypes.NullValue nullValue_ = global::Google.Protobuf.WellKnownTypes.NullValue.NullValue;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::Google.Protobuf.WellKnownTypes.NullValue NullValue {
+      get { return nullValue_; }
+      set {
+        nullValue_ = value;
+      }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as NullValueNotInOneof);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(NullValueNotInOneof other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (NullValue != other.NullValue) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) hash ^= NullValue.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        output.WriteRawTag(16);
+        output.WriteEnum((int) NullValue);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        output.WriteRawTag(16);
+        output.WriteEnum((int) NullValue);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(NullValueNotInOneof other) {
+      if (other == null) {
+        return;
+      }
+      if (other.NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) {
+        NullValue = other.NullValue;
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 16: {
+            NullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 16: {
+            NullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
+  public sealed partial class MixedRegularAndOptional : pb::IMessage<MixedRegularAndOptional>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<MixedRegularAndOptional> _parser = new pb::MessageParser<MixedRegularAndOptional>(() => new MixedRegularAndOptional());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<MixedRegularAndOptional> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[11]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public MixedRegularAndOptional() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public MixedRegularAndOptional(MixedRegularAndOptional other) : this() {
+      regularField_ = other.regularField_;
+      optionalField_ = other.optionalField_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public MixedRegularAndOptional Clone() {
+      return new MixedRegularAndOptional(this);
+    }
+
+    /// <summary>Field number for the "regular_field" field.</summary>
+    public const int RegularFieldFieldNumber = 1;
+    private string regularField_ = "";
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string RegularField {
+      get { return regularField_; }
+      set {
+        regularField_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    /// <summary>Field number for the "optional_field" field.</summary>
+    public const int OptionalFieldFieldNumber = 2;
+    private string optionalField_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string OptionalField {
+      get { return optionalField_ ?? ""; }
+      set {
+        optionalField_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "optional_field" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalField {
+      get { return optionalField_ != null; }
+    }
+    /// <summary>Clears the value of the "optional_field" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalField() {
+      optionalField_ = null;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as MixedRegularAndOptional);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(MixedRegularAndOptional other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (RegularField != other.RegularField) return false;
+      if (OptionalField != other.OptionalField) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (RegularField.Length != 0) hash ^= RegularField.GetHashCode();
+      if (HasOptionalField) hash ^= OptionalField.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (RegularField.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(RegularField);
+      }
+      if (HasOptionalField) {
+        output.WriteRawTag(18);
+        output.WriteString(OptionalField);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (RegularField.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(RegularField);
+      }
+      if (HasOptionalField) {
+        output.WriteRawTag(18);
+        output.WriteString(OptionalField);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (RegularField.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(RegularField);
+      }
+      if (HasOptionalField) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalField);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(MixedRegularAndOptional other) {
+      if (other == null) {
+        return;
+      }
+      if (other.RegularField.Length != 0) {
+        RegularField = other.RegularField;
+      }
+      if (other.HasOptionalField) {
+        OptionalField = other.OptionalField;
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 10: {
+            RegularField = input.ReadString();
+            break;
+          }
+          case 18: {
+            OptionalField = input.ReadString();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            RegularField = input.ReadString();
+            break;
+          }
+          case 18: {
+            OptionalField = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
   #endregion
 
 }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs
index 3f01e38..1af0d9e 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs
@@ -254,23 +254,31 @@
   /// This proto includes every type of field in both singular and repeated
   /// forms.
   /// </summary>
-  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> {
+  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypes() {
       OnConstruction();
     }
@@ -278,6 +286,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypes(TestAllTypes other) : this() {
       singleInt32_ = other.singleInt32_;
       singleInt64_ = other.singleInt64_;
@@ -342,6 +351,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestAllTypes Clone() {
       return new TestAllTypes(this);
     }
@@ -353,6 +363,7 @@
     /// Singular
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int SingleInt32 {
       get { return singleInt32_; }
       set {
@@ -364,6 +375,7 @@
     public const int SingleInt64FieldNumber = 2;
     private long singleInt64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long SingleInt64 {
       get { return singleInt64_; }
       set {
@@ -375,6 +387,7 @@
     public const int SingleUint32FieldNumber = 3;
     private uint singleUint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint SingleUint32 {
       get { return singleUint32_; }
       set {
@@ -386,6 +399,7 @@
     public const int SingleUint64FieldNumber = 4;
     private ulong singleUint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong SingleUint64 {
       get { return singleUint64_; }
       set {
@@ -397,6 +411,7 @@
     public const int SingleSint32FieldNumber = 5;
     private int singleSint32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int SingleSint32 {
       get { return singleSint32_; }
       set {
@@ -408,6 +423,7 @@
     public const int SingleSint64FieldNumber = 6;
     private long singleSint64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long SingleSint64 {
       get { return singleSint64_; }
       set {
@@ -419,6 +435,7 @@
     public const int SingleFixed32FieldNumber = 7;
     private uint singleFixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint SingleFixed32 {
       get { return singleFixed32_; }
       set {
@@ -430,6 +447,7 @@
     public const int SingleFixed64FieldNumber = 8;
     private ulong singleFixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong SingleFixed64 {
       get { return singleFixed64_; }
       set {
@@ -441,6 +459,7 @@
     public const int SingleSfixed32FieldNumber = 9;
     private int singleSfixed32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int SingleSfixed32 {
       get { return singleSfixed32_; }
       set {
@@ -452,6 +471,7 @@
     public const int SingleSfixed64FieldNumber = 10;
     private long singleSfixed64_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long SingleSfixed64 {
       get { return singleSfixed64_; }
       set {
@@ -463,6 +483,7 @@
     public const int SingleFloatFieldNumber = 11;
     private float singleFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float SingleFloat {
       get { return singleFloat_; }
       set {
@@ -474,6 +495,7 @@
     public const int SingleDoubleFieldNumber = 12;
     private double singleDouble_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double SingleDouble {
       get { return singleDouble_; }
       set {
@@ -485,6 +507,7 @@
     public const int SingleBoolFieldNumber = 13;
     private bool singleBool_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool SingleBool {
       get { return singleBool_; }
       set {
@@ -496,6 +519,7 @@
     public const int SingleStringFieldNumber = 14;
     private string singleString_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string SingleString {
       get { return singleString_; }
       set {
@@ -507,6 +531,7 @@
     public const int SingleBytesFieldNumber = 15;
     private pb::ByteString singleBytes_ = pb::ByteString.Empty;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString SingleBytes {
       get { return singleBytes_; }
       set {
@@ -518,6 +543,7 @@
     public const int SingleNestedMessageFieldNumber = 18;
     private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage singleNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage SingleNestedMessage {
       get { return singleNestedMessage_; }
       set {
@@ -529,6 +555,7 @@
     public const int SingleForeignMessageFieldNumber = 19;
     private global::Google.Protobuf.TestProtos.ForeignMessage singleForeignMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.ForeignMessage SingleForeignMessage {
       get { return singleForeignMessage_; }
       set {
@@ -540,6 +567,7 @@
     public const int SingleImportMessageFieldNumber = 20;
     private global::Google.Protobuf.TestProtos.ImportMessage singleImportMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.ImportMessage SingleImportMessage {
       get { return singleImportMessage_; }
       set {
@@ -551,6 +579,7 @@
     public const int SingleNestedEnumFieldNumber = 21;
     private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum SingleNestedEnum {
       get { return singleNestedEnum_; }
       set {
@@ -562,6 +591,7 @@
     public const int SingleForeignEnumFieldNumber = 22;
     private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.ForeignEnum SingleForeignEnum {
       get { return singleForeignEnum_; }
       set {
@@ -573,6 +603,7 @@
     public const int SingleImportEnumFieldNumber = 23;
     private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = global::Google.Protobuf.TestProtos.ImportEnum.Unspecified;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.ImportEnum SingleImportEnum {
       get { return singleImportEnum_; }
       set {
@@ -587,6 +618,7 @@
     /// Defined in unittest_import_public.proto
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.PublicImportMessage SinglePublicImportMessage {
       get { return singlePublicImportMessage_; }
       set {
@@ -603,6 +635,7 @@
     /// Repeated
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
@@ -613,6 +646,7 @@
         = pb::FieldCodec.ForInt64(258);
     private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedInt64 {
       get { return repeatedInt64_; }
     }
@@ -623,6 +657,7 @@
         = pb::FieldCodec.ForUInt32(266);
     private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedUint32 {
       get { return repeatedUint32_; }
     }
@@ -633,6 +668,7 @@
         = pb::FieldCodec.ForUInt64(274);
     private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedUint64 {
       get { return repeatedUint64_; }
     }
@@ -643,6 +679,7 @@
         = pb::FieldCodec.ForSInt32(282);
     private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSint32 {
       get { return repeatedSint32_; }
     }
@@ -653,6 +690,7 @@
         = pb::FieldCodec.ForSInt64(290);
     private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSint64 {
       get { return repeatedSint64_; }
     }
@@ -663,6 +701,7 @@
         = pb::FieldCodec.ForFixed32(298);
     private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedFixed32 {
       get { return repeatedFixed32_; }
     }
@@ -673,6 +712,7 @@
         = pb::FieldCodec.ForFixed64(306);
     private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedFixed64 {
       get { return repeatedFixed64_; }
     }
@@ -683,6 +723,7 @@
         = pb::FieldCodec.ForSFixed32(314);
     private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedSfixed32 {
       get { return repeatedSfixed32_; }
     }
@@ -693,6 +734,7 @@
         = pb::FieldCodec.ForSFixed64(322);
     private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedSfixed64 {
       get { return repeatedSfixed64_; }
     }
@@ -703,6 +745,7 @@
         = pb::FieldCodec.ForFloat(330);
     private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> RepeatedFloat {
       get { return repeatedFloat_; }
     }
@@ -713,6 +756,7 @@
         = pb::FieldCodec.ForDouble(338);
     private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> RepeatedDouble {
       get { return repeatedDouble_; }
     }
@@ -723,6 +767,7 @@
         = pb::FieldCodec.ForBool(346);
     private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> RepeatedBool {
       get { return repeatedBool_; }
     }
@@ -733,6 +778,7 @@
         = pb::FieldCodec.ForString(354);
     private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedString {
       get { return repeatedString_; }
     }
@@ -743,6 +789,7 @@
         = pb::FieldCodec.ForBytes(362);
     private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
       get { return repeatedBytes_; }
     }
@@ -753,6 +800,7 @@
         = pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage {
       get { return repeatedNestedMessage_; }
     }
@@ -763,6 +811,7 @@
         = pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.ForeignMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> RepeatedForeignMessage {
       get { return repeatedForeignMessage_; }
     }
@@ -773,6 +822,7 @@
         = pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.ImportMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage> repeatedImportMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage> RepeatedImportMessage {
       get { return repeatedImportMessage_; }
     }
@@ -783,6 +833,7 @@
         = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
       get { return repeatedNestedEnum_; }
     }
@@ -793,6 +844,7 @@
         = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedForeignEnum {
       get { return repeatedForeignEnum_; }
     }
@@ -803,6 +855,7 @@
         = pb::FieldCodec.ForEnum(426, x => (int) x, x => (global::Google.Protobuf.TestProtos.ImportEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> repeatedImportEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> RepeatedImportEnum {
       get { return repeatedImportEnum_; }
     }
@@ -816,6 +869,7 @@
     /// Defined in unittest_import_public.proto
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.PublicImportMessage> RepeatedPublicImportMessage {
       get { return repeatedPublicImportMessage_; }
     }
@@ -823,6 +877,7 @@
     /// <summary>Field number for the "oneof_uint32" field.</summary>
     public const int OneofUint32FieldNumber = 111;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint OneofUint32 {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; }
       set {
@@ -834,6 +889,7 @@
     /// <summary>Field number for the "oneof_nested_message" field.</summary>
     public const int OneofNestedMessageFieldNumber = 112;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
       set {
@@ -845,6 +901,7 @@
     /// <summary>Field number for the "oneof_string" field.</summary>
     public const int OneofStringFieldNumber = 113;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OneofString {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; }
       set {
@@ -856,6 +913,7 @@
     /// <summary>Field number for the "oneof_bytes" field.</summary>
     public const int OneofBytesFieldNumber = 114;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString OneofBytes {
       get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
       set {
@@ -875,22 +933,26 @@
     }
     private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofFieldOneofCase OneofFieldCase {
       get { return oneofFieldCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofField() {
       oneofFieldCase_ = OneofFieldOneofCase.None;
       oneofField_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestAllTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestAllTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -951,6 +1013,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (SingleInt32 != 0) hash ^= SingleInt32.GetHashCode();
@@ -1009,12 +1072,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (SingleInt32 != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(SingleInt32);
@@ -1144,9 +1212,147 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (SingleInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(SingleInt32);
+      }
+      if (SingleInt64 != 0L) {
+        output.WriteRawTag(16);
+        output.WriteInt64(SingleInt64);
+      }
+      if (SingleUint32 != 0) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(SingleUint32);
+      }
+      if (SingleUint64 != 0UL) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(SingleUint64);
+      }
+      if (SingleSint32 != 0) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(SingleSint32);
+      }
+      if (SingleSint64 != 0L) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(SingleSint64);
+      }
+      if (SingleFixed32 != 0) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(SingleFixed32);
+      }
+      if (SingleFixed64 != 0UL) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(SingleFixed64);
+      }
+      if (SingleSfixed32 != 0) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(SingleSfixed32);
+      }
+      if (SingleSfixed64 != 0L) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(SingleSfixed64);
+      }
+      if (SingleFloat != 0F) {
+        output.WriteRawTag(93);
+        output.WriteFloat(SingleFloat);
+      }
+      if (SingleDouble != 0D) {
+        output.WriteRawTag(97);
+        output.WriteDouble(SingleDouble);
+      }
+      if (SingleBool != false) {
+        output.WriteRawTag(104);
+        output.WriteBool(SingleBool);
+      }
+      if (SingleString.Length != 0) {
+        output.WriteRawTag(114);
+        output.WriteString(SingleString);
+      }
+      if (SingleBytes.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteBytes(SingleBytes);
+      }
+      if (singleNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(SingleNestedMessage);
+      }
+      if (singleForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(SingleForeignMessage);
+      }
+      if (singleImportMessage_ != null) {
+        output.WriteRawTag(162, 1);
+        output.WriteMessage(SingleImportMessage);
+      }
+      if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) SingleNestedEnum);
+      }
+      if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) SingleForeignEnum);
+      }
+      if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.Unspecified) {
+        output.WriteRawTag(184, 1);
+        output.WriteEnum((int) SingleImportEnum);
+      }
+      if (singlePublicImportMessage_ != null) {
+        output.WriteRawTag(210, 1);
+        output.WriteMessage(SinglePublicImportMessage);
+      }
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec);
+      repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec);
+      repeatedImportMessage_.WriteTo(ref output, _repeated_repeatedImportMessage_codec);
+      repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec);
+      repeatedImportEnum_.WriteTo(ref output, _repeated_repeatedImportEnum_codec);
+      repeatedPublicImportMessage_.WriteTo(ref output, _repeated_repeatedPublicImportMessage_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (SingleInt32 != 0) {
@@ -1256,6 +1462,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestAllTypes other) {
       if (other == null) {
         return;
@@ -1382,7 +1589,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1616,11 +1827,253 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            SingleInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            SingleInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            SingleUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            SingleUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            SingleSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            SingleSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            SingleFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            SingleFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            SingleSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            SingleSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            SingleFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            SingleDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            SingleBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            SingleString = input.ReadString();
+            break;
+          }
+          case 122: {
+            SingleBytes = input.ReadBytes();
+            break;
+          }
+          case 146: {
+            if (singleNestedMessage_ == null) {
+              SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(SingleNestedMessage);
+            break;
+          }
+          case 154: {
+            if (singleForeignMessage_ == null) {
+              SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            input.ReadMessage(SingleForeignMessage);
+            break;
+          }
+          case 162: {
+            if (singleImportMessage_ == null) {
+              SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage();
+            }
+            input.ReadMessage(SingleImportMessage);
+            break;
+          }
+          case 168: {
+            SingleNestedEnum = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            SingleForeignEnum = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 184: {
+            SingleImportEnum = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum();
+            break;
+          }
+          case 210: {
+            if (singlePublicImportMessage_ == null) {
+              SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage();
+            }
+            input.ReadMessage(SinglePublicImportMessage);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 402: {
+            repeatedImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedImportMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 426:
+          case 424: {
+            repeatedImportEnum_.AddEntriesFrom(ref input, _repeated_repeatedImportEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedPublicImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedPublicImportMessage_codec);
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestAllTypes message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum NestedEnum {
         [pbr::OriginalName("NESTED_ENUM_UNSPECIFIED")] Unspecified = 0,
@@ -1633,23 +2086,31 @@
         [pbr::OriginalName("NEG")] Neg = -1,
       }
 
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.TestAllTypes.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -1657,12 +2118,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           bb_ = other.bb_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -1676,6 +2139,7 @@
         /// This file needs to compile in proto1 to test backwards-compatibility.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Bb {
           get { return bb_; }
           set {
@@ -1684,11 +2148,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -1701,6 +2167,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (Bb != 0) hash ^= Bb.GetHashCode();
@@ -1711,12 +2178,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (Bb != 0) {
             output.WriteRawTag(8);
             output.WriteInt32(Bb);
@@ -1724,9 +2196,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (Bb != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (Bb != 0) {
@@ -1739,6 +2227,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -1750,7 +2239,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -1763,8 +2256,28 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -1775,23 +2288,31 @@
   /// <summary>
   /// This proto includes a recursively nested message.
   /// </summary>
-  public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes> {
+  public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<NestedTestAllTypes> _parser = new pb::MessageParser<NestedTestAllTypes>(() => new NestedTestAllTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<NestedTestAllTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedTestAllTypes() {
       OnConstruction();
     }
@@ -1799,6 +2320,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedTestAllTypes(NestedTestAllTypes other) : this() {
       child_ = other.child_ != null ? other.child_.Clone() : null;
       payload_ = other.payload_ != null ? other.payload_.Clone() : null;
@@ -1807,6 +2329,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public NestedTestAllTypes Clone() {
       return new NestedTestAllTypes(this);
     }
@@ -1815,6 +2338,7 @@
     public const int ChildFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.NestedTestAllTypes child_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.NestedTestAllTypes Child {
       get { return child_; }
       set {
@@ -1826,6 +2350,7 @@
     public const int PayloadFieldNumber = 2;
     private global::Google.Protobuf.TestProtos.TestAllTypes payload_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestAllTypes Payload {
       get { return payload_; }
       set {
@@ -1839,16 +2364,19 @@
         = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes> repeatedChild_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes> RepeatedChild {
       get { return repeatedChild_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as NestedTestAllTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(NestedTestAllTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1863,6 +2391,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (child_ != null) hash ^= Child.GetHashCode();
@@ -1875,12 +2404,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (child_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(Child);
@@ -1893,9 +2427,30 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (child_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Child);
+      }
+      if (payload_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Payload);
+      }
+      repeatedChild_.WriteTo(ref output, _repeated_repeatedChild_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (child_ != null) {
@@ -1912,6 +2467,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(NestedTestAllTypes other) {
       if (other == null) {
         return;
@@ -1933,7 +2489,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1960,27 +2520,69 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (child_ == null) {
+              Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
+            }
+            input.ReadMessage(Child);
+            break;
+          }
+          case 18: {
+            if (payload_ == null) {
+              Payload = new global::Google.Protobuf.TestProtos.TestAllTypes();
+            }
+            input.ReadMessage(Payload);
+            break;
+          }
+          case 26: {
+            repeatedChild_.AddEntriesFrom(ref input, _repeated_repeatedChild_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestDeprecatedFields : pb::IMessage<TestDeprecatedFields> {
+  public sealed partial class TestDeprecatedFields : pb::IMessage<TestDeprecatedFields>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestDeprecatedFields> _parser = new pb::MessageParser<TestDeprecatedFields>(() => new TestDeprecatedFields());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestDeprecatedFields> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedFields() {
       OnConstruction();
     }
@@ -1988,12 +2590,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedFields(TestDeprecatedFields other) : this() {
       deprecatedInt32_ = other.deprecatedInt32_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestDeprecatedFields Clone() {
       return new TestDeprecatedFields(this);
     }
@@ -2003,6 +2607,7 @@
     private int deprecatedInt32_;
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int DeprecatedInt32 {
       get { return deprecatedInt32_; }
       set {
@@ -2011,11 +2616,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestDeprecatedFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestDeprecatedFields other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2028,6 +2635,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (DeprecatedInt32 != 0) hash ^= DeprecatedInt32.GetHashCode();
@@ -2038,12 +2646,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (DeprecatedInt32 != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(DeprecatedInt32);
@@ -2051,9 +2664,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (DeprecatedInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(DeprecatedInt32);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (DeprecatedInt32 != 0) {
@@ -2066,6 +2695,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestDeprecatedFields other) {
       if (other == null) {
         return;
@@ -2077,7 +2707,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2090,31 +2724,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            DeprecatedInt32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Define these after TestAllTypes to make sure the compiler can handle
   /// that.
   /// </summary>
-  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
+  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage() {
       OnConstruction();
     }
@@ -2122,12 +2784,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage(ForeignMessage other) : this() {
       c_ = other.c_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ForeignMessage Clone() {
       return new ForeignMessage(this);
     }
@@ -2136,6 +2800,7 @@
     public const int CFieldNumber = 1;
     private int c_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int C {
       get { return c_; }
       set {
@@ -2144,11 +2809,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ForeignMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ForeignMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2161,6 +2828,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (C != 0) hash ^= C.GetHashCode();
@@ -2171,12 +2839,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (C != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(C);
@@ -2184,9 +2857,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (C != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (C != 0) {
@@ -2199,6 +2888,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ForeignMessage other) {
       if (other == null) {
         return;
@@ -2210,7 +2900,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2223,27 +2917,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestReservedFields : pb::IMessage<TestReservedFields> {
+  public sealed partial class TestReservedFields : pb::IMessage<TestReservedFields>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestReservedFields> _parser = new pb::MessageParser<TestReservedFields>(() => new TestReservedFields());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestReservedFields> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReservedFields() {
       OnConstruction();
     }
@@ -2251,21 +2973,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReservedFields(TestReservedFields other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReservedFields Clone() {
       return new TestReservedFields(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestReservedFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestReservedFields other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2277,6 +3003,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -2286,18 +3013,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -2307,6 +3051,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestReservedFields other) {
       if (other == null) {
         return;
@@ -2315,7 +3060,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2324,30 +3073,54 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test that we can use NestedMessage from outside TestAllTypes.
   /// </summary>
-  public sealed partial class TestForeignNested : pb::IMessage<TestForeignNested> {
+  public sealed partial class TestForeignNested : pb::IMessage<TestForeignNested>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestForeignNested> _parser = new pb::MessageParser<TestForeignNested>(() => new TestForeignNested());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestForeignNested> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestForeignNested() {
       OnConstruction();
     }
@@ -2355,12 +3128,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestForeignNested(TestForeignNested other) : this() {
       foreignNested_ = other.foreignNested_ != null ? other.foreignNested_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestForeignNested Clone() {
       return new TestForeignNested(this);
     }
@@ -2369,6 +3144,7 @@
     public const int ForeignNestedFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage foreignNested_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage ForeignNested {
       get { return foreignNested_; }
       set {
@@ -2377,11 +3153,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestForeignNested);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestForeignNested other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2394,6 +3172,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode();
@@ -2404,12 +3183,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (foreignNested_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(ForeignNested);
@@ -2417,9 +3201,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (foreignNested_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(ForeignNested);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (foreignNested_ != null) {
@@ -2432,6 +3232,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestForeignNested other) {
       if (other == null) {
         return;
@@ -2446,7 +3247,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2462,30 +3267,61 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (foreignNested_ == null) {
+              ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(ForeignNested);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test that really large tag numbers don't break anything.
   /// </summary>
-  public sealed partial class TestReallyLargeTagNumber : pb::IMessage<TestReallyLargeTagNumber> {
+  public sealed partial class TestReallyLargeTagNumber : pb::IMessage<TestReallyLargeTagNumber>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestReallyLargeTagNumber> _parser = new pb::MessageParser<TestReallyLargeTagNumber>(() => new TestReallyLargeTagNumber());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestReallyLargeTagNumber> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReallyLargeTagNumber() {
       OnConstruction();
     }
@@ -2493,6 +3329,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() {
       a_ = other.a_;
       bb_ = other.bb_;
@@ -2500,6 +3337,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestReallyLargeTagNumber Clone() {
       return new TestReallyLargeTagNumber(this);
     }
@@ -2512,6 +3350,7 @@
     /// three bits to communicate wire type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int A {
       get { return a_; }
       set {
@@ -2523,6 +3362,7 @@
     public const int BbFieldNumber = 268435455;
     private int bb_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Bb {
       get { return bb_; }
       set {
@@ -2531,11 +3371,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestReallyLargeTagNumber);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestReallyLargeTagNumber other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2549,6 +3391,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (A != 0) hash ^= A.GetHashCode();
@@ -2560,12 +3403,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (A != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(A);
@@ -2577,9 +3425,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (A != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(A);
+      }
+      if (Bb != 0) {
+        output.WriteRawTag(248, 255, 255, 255, 7);
+        output.WriteInt32(Bb);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (A != 0) {
@@ -2595,6 +3463,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestReallyLargeTagNumber other) {
       if (other == null) {
         return;
@@ -2609,7 +3478,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2626,27 +3499,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            A = input.ReadInt32();
+            break;
+          }
+          case 2147483640: {
+            Bb = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestRecursiveMessage : pb::IMessage<TestRecursiveMessage> {
+  public sealed partial class TestRecursiveMessage : pb::IMessage<TestRecursiveMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRecursiveMessage> _parser = new pb::MessageParser<TestRecursiveMessage>(() => new TestRecursiveMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRecursiveMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[7]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRecursiveMessage() {
       OnConstruction();
     }
@@ -2654,6 +3559,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRecursiveMessage(TestRecursiveMessage other) : this() {
       a_ = other.a_ != null ? other.a_.Clone() : null;
       i_ = other.i_;
@@ -2661,6 +3567,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRecursiveMessage Clone() {
       return new TestRecursiveMessage(this);
     }
@@ -2669,6 +3576,7 @@
     public const int AFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.TestRecursiveMessage a_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestRecursiveMessage A {
       get { return a_; }
       set {
@@ -2680,6 +3588,7 @@
     public const int IFieldNumber = 2;
     private int i_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int I {
       get { return i_; }
       set {
@@ -2688,11 +3597,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRecursiveMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRecursiveMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2706,6 +3617,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (a_ != null) hash ^= A.GetHashCode();
@@ -2717,12 +3629,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (a_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(A);
@@ -2734,9 +3651,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (I != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(I);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (a_ != null) {
@@ -2752,6 +3689,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRecursiveMessage other) {
       if (other == null) {
         return;
@@ -2769,7 +3707,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2789,30 +3731,65 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (a_ == null) {
+              A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
+            }
+            input.ReadMessage(A);
+            break;
+          }
+          case 16: {
+            I = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test that mutual recursion works.
   /// </summary>
-  public sealed partial class TestMutualRecursionA : pb::IMessage<TestMutualRecursionA> {
+  public sealed partial class TestMutualRecursionA : pb::IMessage<TestMutualRecursionA>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMutualRecursionA> _parser = new pb::MessageParser<TestMutualRecursionA>(() => new TestMutualRecursionA());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMutualRecursionA> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[8]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionA() {
       OnConstruction();
     }
@@ -2820,12 +3797,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionA(TestMutualRecursionA other) : this() {
       bb_ = other.bb_ != null ? other.bb_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionA Clone() {
       return new TestMutualRecursionA(this);
     }
@@ -2834,6 +3813,7 @@
     public const int BbFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.TestMutualRecursionB bb_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestMutualRecursionB Bb {
       get { return bb_; }
       set {
@@ -2842,11 +3822,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMutualRecursionA);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMutualRecursionA other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2859,6 +3841,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (bb_ != null) hash ^= Bb.GetHashCode();
@@ -2869,12 +3852,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (bb_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(Bb);
@@ -2882,9 +3870,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (bb_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Bb);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (bb_ != null) {
@@ -2897,6 +3901,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMutualRecursionA other) {
       if (other == null) {
         return;
@@ -2911,7 +3916,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2927,27 +3936,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (bb_ == null) {
+              Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
+            }
+            input.ReadMessage(Bb);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestMutualRecursionB : pb::IMessage<TestMutualRecursionB> {
+  public sealed partial class TestMutualRecursionB : pb::IMessage<TestMutualRecursionB>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestMutualRecursionB> _parser = new pb::MessageParser<TestMutualRecursionB>(() => new TestMutualRecursionB());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestMutualRecursionB> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[9]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionB() {
       OnConstruction();
     }
@@ -2955,6 +3995,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionB(TestMutualRecursionB other) : this() {
       a_ = other.a_ != null ? other.a_.Clone() : null;
       optionalInt32_ = other.optionalInt32_;
@@ -2962,6 +4003,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestMutualRecursionB Clone() {
       return new TestMutualRecursionB(this);
     }
@@ -2970,6 +4012,7 @@
     public const int AFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.TestMutualRecursionA a_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestMutualRecursionA A {
       get { return a_; }
       set {
@@ -2981,6 +4024,7 @@
     public const int OptionalInt32FieldNumber = 2;
     private int optionalInt32_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OptionalInt32 {
       get { return optionalInt32_; }
       set {
@@ -2989,11 +4033,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestMutualRecursionB);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestMutualRecursionB other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3007,6 +4053,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (a_ != null) hash ^= A.GetHashCode();
@@ -3018,12 +4065,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (a_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(A);
@@ -3035,9 +4087,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (OptionalInt32 != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (a_ != null) {
@@ -3053,6 +4125,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestMutualRecursionB other) {
       if (other == null) {
         return;
@@ -3070,7 +4143,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3090,27 +4167,62 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (a_ == null) {
+              A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
+            }
+            input.ReadMessage(A);
+            break;
+          }
+          case 16: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestEnumAllowAlias : pb::IMessage<TestEnumAllowAlias> {
+  public sealed partial class TestEnumAllowAlias : pb::IMessage<TestEnumAllowAlias>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestEnumAllowAlias> _parser = new pb::MessageParser<TestEnumAllowAlias>(() => new TestEnumAllowAlias());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestEnumAllowAlias> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[10]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEnumAllowAlias() {
       OnConstruction();
     }
@@ -3118,12 +4230,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEnumAllowAlias(TestEnumAllowAlias other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEnumAllowAlias Clone() {
       return new TestEnumAllowAlias(this);
     }
@@ -3132,6 +4246,7 @@
     public const int ValueFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.TestEnumWithDupValue value_ = global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestEnumWithDupValue Value {
       get { return value_; }
       set {
@@ -3140,11 +4255,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestEnumAllowAlias);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestEnumAllowAlias other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3157,6 +4274,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) hash ^= Value.GetHashCode();
@@ -3167,12 +4285,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Value);
@@ -3180,9 +4303,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) {
@@ -3195,6 +4334,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestEnumAllowAlias other) {
       if (other == null) {
         return;
@@ -3206,7 +4346,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3219,31 +4363,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Value = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test message with CamelCase field names.  This violates Protocol Buffer
   /// standard style.
   /// </summary>
-  public sealed partial class TestCamelCaseFieldNames : pb::IMessage<TestCamelCaseFieldNames> {
+  public sealed partial class TestCamelCaseFieldNames : pb::IMessage<TestCamelCaseFieldNames>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestCamelCaseFieldNames> _parser = new pb::MessageParser<TestCamelCaseFieldNames>(() => new TestCamelCaseFieldNames());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestCamelCaseFieldNames> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[11]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCamelCaseFieldNames() {
       OnConstruction();
     }
@@ -3251,6 +4423,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() {
       primitiveField_ = other.primitiveField_;
       stringField_ = other.stringField_;
@@ -3264,6 +4437,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCamelCaseFieldNames Clone() {
       return new TestCamelCaseFieldNames(this);
     }
@@ -3272,6 +4446,7 @@
     public const int PrimitiveFieldFieldNumber = 1;
     private int primitiveField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int PrimitiveField {
       get { return primitiveField_; }
       set {
@@ -3283,6 +4458,7 @@
     public const int StringFieldFieldNumber = 2;
     private string stringField_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField {
       get { return stringField_; }
       set {
@@ -3294,6 +4470,7 @@
     public const int EnumFieldFieldNumber = 3;
     private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.ForeignEnum EnumField {
       get { return enumField_; }
       set {
@@ -3305,6 +4482,7 @@
     public const int MessageFieldFieldNumber = 4;
     private global::Google.Protobuf.TestProtos.ForeignMessage messageField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.ForeignMessage MessageField {
       get { return messageField_; }
       set {
@@ -3318,6 +4496,7 @@
         = pb::FieldCodec.ForInt32(58);
     private readonly pbc::RepeatedField<int> repeatedPrimitiveField_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedPrimitiveField {
       get { return repeatedPrimitiveField_; }
     }
@@ -3328,6 +4507,7 @@
         = pb::FieldCodec.ForString(66);
     private readonly pbc::RepeatedField<string> repeatedStringField_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> RepeatedStringField {
       get { return repeatedStringField_; }
     }
@@ -3338,6 +4518,7 @@
         = pb::FieldCodec.ForEnum(74, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedEnumField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedEnumField {
       get { return repeatedEnumField_; }
     }
@@ -3348,16 +4529,19 @@
         = pb::FieldCodec.ForMessage(82, global::Google.Protobuf.TestProtos.ForeignMessage.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> repeatedMessageField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> RepeatedMessageField {
       get { return repeatedMessageField_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestCamelCaseFieldNames);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestCamelCaseFieldNames other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3377,6 +4561,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (PrimitiveField != 0) hash ^= PrimitiveField.GetHashCode();
@@ -3394,12 +4579,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (PrimitiveField != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(PrimitiveField);
@@ -3423,9 +4613,41 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (PrimitiveField != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(PrimitiveField);
+      }
+      if (StringField.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(StringField);
+      }
+      if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) {
+        output.WriteRawTag(24);
+        output.WriteEnum((int) EnumField);
+      }
+      if (messageField_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(MessageField);
+      }
+      repeatedPrimitiveField_.WriteTo(ref output, _repeated_repeatedPrimitiveField_codec);
+      repeatedStringField_.WriteTo(ref output, _repeated_repeatedStringField_codec);
+      repeatedEnumField_.WriteTo(ref output, _repeated_repeatedEnumField_codec);
+      repeatedMessageField_.WriteTo(ref output, _repeated_repeatedMessageField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (PrimitiveField != 0) {
@@ -3451,6 +4673,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestCamelCaseFieldNames other) {
       if (other == null) {
         return;
@@ -3478,7 +4701,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3524,31 +4751,92 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            PrimitiveField = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            StringField = input.ReadString();
+            break;
+          }
+          case 24: {
+            EnumField = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 34: {
+            if (messageField_ == null) {
+              MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            input.ReadMessage(MessageField);
+            break;
+          }
+          case 58:
+          case 56: {
+            repeatedPrimitiveField_.AddEntriesFrom(ref input, _repeated_repeatedPrimitiveField_codec);
+            break;
+          }
+          case 66: {
+            repeatedStringField_.AddEntriesFrom(ref input, _repeated_repeatedStringField_codec);
+            break;
+          }
+          case 74:
+          case 72: {
+            repeatedEnumField_.AddEntriesFrom(ref input, _repeated_repeatedEnumField_codec);
+            break;
+          }
+          case 82: {
+            repeatedMessageField_.AddEntriesFrom(ref input, _repeated_repeatedMessageField_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// We list fields out of order, to ensure that we're using field number and not
   /// field index to determine serialization order.
   /// </summary>
-  public sealed partial class TestFieldOrderings : pb::IMessage<TestFieldOrderings> {
+  public sealed partial class TestFieldOrderings : pb::IMessage<TestFieldOrderings>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestFieldOrderings> _parser = new pb::MessageParser<TestFieldOrderings>(() => new TestFieldOrderings());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestFieldOrderings> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[12]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestFieldOrderings() {
       OnConstruction();
     }
@@ -3556,6 +4844,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestFieldOrderings(TestFieldOrderings other) : this() {
       myString_ = other.myString_;
       myInt_ = other.myInt_;
@@ -3565,6 +4854,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestFieldOrderings Clone() {
       return new TestFieldOrderings(this);
     }
@@ -3573,6 +4863,7 @@
     public const int MyStringFieldNumber = 11;
     private string myString_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string MyString {
       get { return myString_; }
       set {
@@ -3584,6 +4875,7 @@
     public const int MyIntFieldNumber = 1;
     private long myInt_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long MyInt {
       get { return myInt_; }
       set {
@@ -3595,6 +4887,7 @@
     public const int MyFloatFieldNumber = 101;
     private float myFloat_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float MyFloat {
       get { return myFloat_; }
       set {
@@ -3606,6 +4899,7 @@
     public const int SingleNestedMessageFieldNumber = 200;
     private global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage singleNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage SingleNestedMessage {
       get { return singleNestedMessage_; }
       set {
@@ -3614,11 +4908,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestFieldOrderings);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestFieldOrderings other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3634,6 +4930,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (MyString.Length != 0) hash ^= MyString.GetHashCode();
@@ -3647,12 +4944,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (MyInt != 0L) {
         output.WriteRawTag(8);
         output.WriteInt64(MyInt);
@@ -3672,9 +4974,37 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (MyInt != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(MyInt);
+      }
+      if (MyString.Length != 0) {
+        output.WriteRawTag(90);
+        output.WriteString(MyString);
+      }
+      if (MyFloat != 0F) {
+        output.WriteRawTag(173, 6);
+        output.WriteFloat(MyFloat);
+      }
+      if (singleNestedMessage_ != null) {
+        output.WriteRawTag(194, 12);
+        output.WriteMessage(SingleNestedMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (MyString.Length != 0) {
@@ -3696,6 +5026,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestFieldOrderings other) {
       if (other == null) {
         return;
@@ -3719,7 +5050,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3747,29 +5082,73 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            MyInt = input.ReadInt64();
+            break;
+          }
+          case 90: {
+            MyString = input.ReadString();
+            break;
+          }
+          case 813: {
+            MyFloat = input.ReadFloat();
+            break;
+          }
+          case 1602: {
+            if (singleNestedMessage_ == null) {
+              SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
+            }
+            input.ReadMessage(SingleNestedMessage);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the TestFieldOrderings message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.TestFieldOrderings.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage() {
           OnConstruction();
         }
@@ -3777,6 +5156,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage(NestedMessage other) : this() {
           oo_ = other.oo_;
           bb_ = other.bb_;
@@ -3784,6 +5164,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedMessage Clone() {
           return new NestedMessage(this);
         }
@@ -3792,6 +5173,7 @@
         public const int OoFieldNumber = 2;
         private long oo_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public long Oo {
           get { return oo_; }
           set {
@@ -3808,6 +5190,7 @@
         /// This file needs to compile in proto1 to test backwards-compatibility.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Bb {
           get { return bb_; }
           set {
@@ -3816,11 +5199,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -3834,6 +5219,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (Oo != 0L) hash ^= Oo.GetHashCode();
@@ -3845,12 +5231,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (Bb != 0) {
             output.WriteRawTag(8);
             output.WriteInt32(Bb);
@@ -3862,9 +5253,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (Bb != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (Oo != 0L) {
+            output.WriteRawTag(16);
+            output.WriteInt64(Oo);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (Oo != 0L) {
@@ -3880,6 +5291,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -3894,7 +5306,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -3911,8 +5327,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Oo = input.ReadInt64();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -3920,23 +5360,31 @@
 
   }
 
-  public sealed partial class SparseEnumMessage : pb::IMessage<SparseEnumMessage> {
+  public sealed partial class SparseEnumMessage : pb::IMessage<SparseEnumMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<SparseEnumMessage> _parser = new pb::MessageParser<SparseEnumMessage>(() => new SparseEnumMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<SparseEnumMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[13]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SparseEnumMessage() {
       OnConstruction();
     }
@@ -3944,12 +5392,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SparseEnumMessage(SparseEnumMessage other) : this() {
       sparseEnum_ = other.sparseEnum_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SparseEnumMessage Clone() {
       return new SparseEnumMessage(this);
     }
@@ -3958,6 +5408,7 @@
     public const int SparseEnumFieldNumber = 1;
     private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestSparseEnum SparseEnum {
       get { return sparseEnum_; }
       set {
@@ -3966,11 +5417,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as SparseEnumMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(SparseEnumMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3983,6 +5436,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) hash ^= SparseEnum.GetHashCode();
@@ -3993,12 +5447,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) {
         output.WriteRawTag(8);
         output.WriteEnum((int) SparseEnum);
@@ -4006,9 +5465,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) SparseEnum);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) {
@@ -4021,6 +5496,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(SparseEnumMessage other) {
       if (other == null) {
         return;
@@ -4032,7 +5508,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4045,30 +5525,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            SparseEnum = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test String and Bytes: string is for valid UTF-8 strings
   /// </summary>
-  public sealed partial class OneString : pb::IMessage<OneString> {
+  public sealed partial class OneString : pb::IMessage<OneString>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneString> _parser = new pb::MessageParser<OneString>(() => new OneString());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneString> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[14]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneString() {
       OnConstruction();
     }
@@ -4076,12 +5584,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneString(OneString other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneString Clone() {
       return new OneString(this);
     }
@@ -4090,6 +5600,7 @@
     public const int DataFieldNumber = 1;
     private string data_ = "";
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Data {
       get { return data_; }
       set {
@@ -4098,11 +5609,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneString);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneString other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4115,6 +5628,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data.Length != 0) hash ^= Data.GetHashCode();
@@ -4125,12 +5639,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Data);
@@ -4138,9 +5657,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data.Length != 0) {
@@ -4153,6 +5688,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneString other) {
       if (other == null) {
         return;
@@ -4164,7 +5700,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4177,27 +5717,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Data = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class MoreString : pb::IMessage<MoreString> {
+  public sealed partial class MoreString : pb::IMessage<MoreString>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MoreString> _parser = new pb::MessageParser<MoreString>(() => new MoreString());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MoreString> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[15]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreString() {
       OnConstruction();
     }
@@ -4205,12 +5773,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreString(MoreString other) : this() {
       data_ = other.data_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreString Clone() {
       return new MoreString(this);
     }
@@ -4221,16 +5791,19 @@
         = pb::FieldCodec.ForString(10);
     private readonly pbc::RepeatedField<string> data_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> Data {
       get { return data_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MoreString);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MoreString other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4243,6 +5816,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= data_.GetHashCode();
@@ -4253,19 +5827,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       data_.WriteTo(output, _repeated_data_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      data_.WriteTo(ref output, _repeated_data_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += data_.CalculateSize(_repeated_data_codec);
@@ -4276,6 +5868,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MoreString other) {
       if (other == null) {
         return;
@@ -4285,7 +5878,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4298,27 +5895,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            data_.AddEntriesFrom(ref input, _repeated_data_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class OneBytes : pb::IMessage<OneBytes> {
+  public sealed partial class OneBytes : pb::IMessage<OneBytes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneBytes> _parser = new pb::MessageParser<OneBytes>(() => new OneBytes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneBytes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[16]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneBytes() {
       OnConstruction();
     }
@@ -4326,12 +5951,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneBytes(OneBytes other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneBytes Clone() {
       return new OneBytes(this);
     }
@@ -4340,6 +5967,7 @@
     public const int DataFieldNumber = 1;
     private pb::ByteString data_ = pb::ByteString.Empty;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString Data {
       get { return data_; }
       set {
@@ -4348,11 +5976,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneBytes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneBytes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4365,6 +5995,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data.Length != 0) hash ^= Data.GetHashCode();
@@ -4375,12 +6006,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data.Length != 0) {
         output.WriteRawTag(10);
         output.WriteBytes(Data);
@@ -4388,9 +6024,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data.Length != 0) {
@@ -4403,6 +6055,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneBytes other) {
       if (other == null) {
         return;
@@ -4414,7 +6067,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4427,27 +6084,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Data = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class MoreBytes : pb::IMessage<MoreBytes> {
+  public sealed partial class MoreBytes : pb::IMessage<MoreBytes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MoreBytes> _parser = new pb::MessageParser<MoreBytes>(() => new MoreBytes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MoreBytes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[17]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreBytes() {
       OnConstruction();
     }
@@ -4455,12 +6140,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreBytes(MoreBytes other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MoreBytes Clone() {
       return new MoreBytes(this);
     }
@@ -4469,6 +6156,7 @@
     public const int DataFieldNumber = 1;
     private pb::ByteString data_ = pb::ByteString.Empty;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString Data {
       get { return data_; }
       set {
@@ -4477,11 +6165,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MoreBytes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MoreBytes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4494,6 +6184,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data.Length != 0) hash ^= Data.GetHashCode();
@@ -4504,12 +6195,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data.Length != 0) {
         output.WriteRawTag(10);
         output.WriteBytes(Data);
@@ -4517,9 +6213,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data.Length != 0) {
@@ -4532,6 +6244,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MoreBytes other) {
       if (other == null) {
         return;
@@ -4543,7 +6256,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4556,30 +6273,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Data = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test int32, uint32, int64, uint64, and bool are all compatible
   /// </summary>
-  public sealed partial class Int32Message : pb::IMessage<Int32Message> {
+  public sealed partial class Int32Message : pb::IMessage<Int32Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Int32Message> _parser = new pb::MessageParser<Int32Message>(() => new Int32Message());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Int32Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[18]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Message() {
       OnConstruction();
     }
@@ -4587,12 +6332,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Message(Int32Message other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Message Clone() {
       return new Int32Message(this);
     }
@@ -4601,6 +6348,7 @@
     public const int DataFieldNumber = 1;
     private int data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Data {
       get { return data_; }
       set {
@@ -4609,11 +6357,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Int32Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Int32Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4626,6 +6376,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data != 0) hash ^= Data.GetHashCode();
@@ -4636,12 +6387,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Data);
@@ -4649,9 +6405,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data != 0) {
@@ -4664,6 +6436,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Int32Message other) {
       if (other == null) {
         return;
@@ -4675,7 +6448,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4688,27 +6465,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class Uint32Message : pb::IMessage<Uint32Message> {
+  public sealed partial class Uint32Message : pb::IMessage<Uint32Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Uint32Message> _parser = new pb::MessageParser<Uint32Message>(() => new Uint32Message());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Uint32Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[19]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint32Message() {
       OnConstruction();
     }
@@ -4716,12 +6521,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint32Message(Uint32Message other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint32Message Clone() {
       return new Uint32Message(this);
     }
@@ -4730,6 +6537,7 @@
     public const int DataFieldNumber = 1;
     private uint data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint Data {
       get { return data_; }
       set {
@@ -4738,11 +6546,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Uint32Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Uint32Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4755,6 +6565,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data != 0) hash ^= Data.GetHashCode();
@@ -4765,12 +6576,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data != 0) {
         output.WriteRawTag(8);
         output.WriteUInt32(Data);
@@ -4778,9 +6594,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data != 0) {
+        output.WriteRawTag(8);
+        output.WriteUInt32(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data != 0) {
@@ -4793,6 +6625,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Uint32Message other) {
       if (other == null) {
         return;
@@ -4804,7 +6637,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4817,27 +6654,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadUInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class Int64Message : pb::IMessage<Int64Message> {
+  public sealed partial class Int64Message : pb::IMessage<Int64Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Int64Message> _parser = new pb::MessageParser<Int64Message>(() => new Int64Message());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Int64Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[20]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Message() {
       OnConstruction();
     }
@@ -4845,12 +6710,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Message(Int64Message other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Message Clone() {
       return new Int64Message(this);
     }
@@ -4859,6 +6726,7 @@
     public const int DataFieldNumber = 1;
     private long data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Data {
       get { return data_; }
       set {
@@ -4867,11 +6735,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Int64Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Int64Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4884,6 +6754,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data != 0L) hash ^= Data.GetHashCode();
@@ -4894,12 +6765,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data != 0L) {
         output.WriteRawTag(8);
         output.WriteInt64(Data);
@@ -4907,9 +6783,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data != 0L) {
@@ -4922,6 +6814,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Int64Message other) {
       if (other == null) {
         return;
@@ -4933,7 +6826,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4946,27 +6843,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class Uint64Message : pb::IMessage<Uint64Message> {
+  public sealed partial class Uint64Message : pb::IMessage<Uint64Message>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Uint64Message> _parser = new pb::MessageParser<Uint64Message>(() => new Uint64Message());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Uint64Message> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[21]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint64Message() {
       OnConstruction();
     }
@@ -4974,12 +6899,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint64Message(Uint64Message other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Uint64Message Clone() {
       return new Uint64Message(this);
     }
@@ -4988,6 +6915,7 @@
     public const int DataFieldNumber = 1;
     private ulong data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong Data {
       get { return data_; }
       set {
@@ -4996,11 +6924,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Uint64Message);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Uint64Message other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5013,6 +6943,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data != 0UL) hash ^= Data.GetHashCode();
@@ -5023,12 +6954,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data != 0UL) {
         output.WriteRawTag(8);
         output.WriteUInt64(Data);
@@ -5036,9 +6972,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data != 0UL) {
+        output.WriteRawTag(8);
+        output.WriteUInt64(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data != 0UL) {
@@ -5051,6 +7003,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Uint64Message other) {
       if (other == null) {
         return;
@@ -5062,7 +7015,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5075,27 +7032,55 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadUInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class BoolMessage : pb::IMessage<BoolMessage> {
+  public sealed partial class BoolMessage : pb::IMessage<BoolMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BoolMessage> _parser = new pb::MessageParser<BoolMessage>(() => new BoolMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BoolMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[22]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolMessage() {
       OnConstruction();
     }
@@ -5103,12 +7088,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolMessage(BoolMessage other) : this() {
       data_ = other.data_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolMessage Clone() {
       return new BoolMessage(this);
     }
@@ -5117,6 +7104,7 @@
     public const int DataFieldNumber = 1;
     private bool data_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Data {
       get { return data_; }
       set {
@@ -5125,11 +7113,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BoolMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BoolMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5142,6 +7132,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Data != false) hash ^= Data.GetHashCode();
@@ -5152,12 +7143,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Data != false) {
         output.WriteRawTag(8);
         output.WriteBool(Data);
@@ -5165,9 +7161,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Data != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(Data);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Data != false) {
@@ -5180,6 +7192,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BoolMessage other) {
       if (other == null) {
         return;
@@ -5191,7 +7204,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5204,30 +7221,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Data = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test oneofs.
   /// </summary>
-  public sealed partial class TestOneof : pb::IMessage<TestOneof> {
+  public sealed partial class TestOneof : pb::IMessage<TestOneof>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestOneof> _parser = new pb::MessageParser<TestOneof>(() => new TestOneof());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestOneof> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[23]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof() {
       OnConstruction();
     }
@@ -5235,6 +7280,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof(TestOneof other) : this() {
       switch (other.FooCase) {
         case FooOneofCase.FooInt:
@@ -5252,6 +7298,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestOneof Clone() {
       return new TestOneof(this);
     }
@@ -5259,6 +7306,7 @@
     /// <summary>Field number for the "foo_int" field.</summary>
     public const int FooIntFieldNumber = 1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int FooInt {
       get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; }
       set {
@@ -5270,6 +7318,7 @@
     /// <summary>Field number for the "foo_string" field.</summary>
     public const int FooStringFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FooString {
       get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; }
       set {
@@ -5281,6 +7330,7 @@
     /// <summary>Field number for the "foo_message" field.</summary>
     public const int FooMessageFieldNumber = 3;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.TestProtos.TestAllTypes FooMessage {
       get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes) foo_ : null; }
       set {
@@ -5299,22 +7349,26 @@
     }
     private FooOneofCase fooCase_ = FooOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooOneofCase FooCase {
       get { return fooCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearFoo() {
       fooCase_ = FooOneofCase.None;
       foo_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestOneof);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestOneof other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5330,6 +7384,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (fooCase_ == FooOneofCase.FooInt) hash ^= FooInt.GetHashCode();
@@ -5343,12 +7398,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (fooCase_ == FooOneofCase.FooInt) {
         output.WriteRawTag(8);
         output.WriteInt32(FooInt);
@@ -5364,9 +7424,33 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (fooCase_ == FooOneofCase.FooInt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FooInt);
+      }
+      if (fooCase_ == FooOneofCase.FooString) {
+        output.WriteRawTag(18);
+        output.WriteString(FooString);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        output.WriteRawTag(26);
+        output.WriteMessage(FooMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (fooCase_ == FooOneofCase.FooInt) {
@@ -5385,6 +7469,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestOneof other) {
       if (other == null) {
         return;
@@ -5408,7 +7493,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5434,27 +7523,68 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            FooInt = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            FooString = input.ReadString();
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.TestProtos.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes();
+            if (fooCase_ == FooOneofCase.FooMessage) {
+              subBuilder.MergeFrom(FooMessage);
+            }
+            input.ReadMessage(subBuilder);
+            FooMessage = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestPackedTypes : pb::IMessage<TestPackedTypes> {
+  public sealed partial class TestPackedTypes : pb::IMessage<TestPackedTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestPackedTypes> _parser = new pb::MessageParser<TestPackedTypes>(() => new TestPackedTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestPackedTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[24]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedTypes() {
       OnConstruction();
     }
@@ -5462,6 +7592,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedTypes(TestPackedTypes other) : this() {
       packedInt32_ = other.packedInt32_.Clone();
       packedInt64_ = other.packedInt64_.Clone();
@@ -5481,6 +7612,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestPackedTypes Clone() {
       return new TestPackedTypes(this);
     }
@@ -5491,6 +7623,7 @@
         = pb::FieldCodec.ForInt32(722);
     private readonly pbc::RepeatedField<int> packedInt32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedInt32 {
       get { return packedInt32_; }
     }
@@ -5501,6 +7634,7 @@
         = pb::FieldCodec.ForInt64(730);
     private readonly pbc::RepeatedField<long> packedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedInt64 {
       get { return packedInt64_; }
     }
@@ -5511,6 +7645,7 @@
         = pb::FieldCodec.ForUInt32(738);
     private readonly pbc::RepeatedField<uint> packedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedUint32 {
       get { return packedUint32_; }
     }
@@ -5521,6 +7656,7 @@
         = pb::FieldCodec.ForUInt64(746);
     private readonly pbc::RepeatedField<ulong> packedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedUint64 {
       get { return packedUint64_; }
     }
@@ -5531,6 +7667,7 @@
         = pb::FieldCodec.ForSInt32(754);
     private readonly pbc::RepeatedField<int> packedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSint32 {
       get { return packedSint32_; }
     }
@@ -5541,6 +7678,7 @@
         = pb::FieldCodec.ForSInt64(762);
     private readonly pbc::RepeatedField<long> packedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSint64 {
       get { return packedSint64_; }
     }
@@ -5551,6 +7689,7 @@
         = pb::FieldCodec.ForFixed32(770);
     private readonly pbc::RepeatedField<uint> packedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> PackedFixed32 {
       get { return packedFixed32_; }
     }
@@ -5561,6 +7700,7 @@
         = pb::FieldCodec.ForFixed64(778);
     private readonly pbc::RepeatedField<ulong> packedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> PackedFixed64 {
       get { return packedFixed64_; }
     }
@@ -5571,6 +7711,7 @@
         = pb::FieldCodec.ForSFixed32(786);
     private readonly pbc::RepeatedField<int> packedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PackedSfixed32 {
       get { return packedSfixed32_; }
     }
@@ -5581,6 +7722,7 @@
         = pb::FieldCodec.ForSFixed64(794);
     private readonly pbc::RepeatedField<long> packedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> PackedSfixed64 {
       get { return packedSfixed64_; }
     }
@@ -5591,6 +7733,7 @@
         = pb::FieldCodec.ForFloat(802);
     private readonly pbc::RepeatedField<float> packedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> PackedFloat {
       get { return packedFloat_; }
     }
@@ -5601,6 +7744,7 @@
         = pb::FieldCodec.ForDouble(810);
     private readonly pbc::RepeatedField<double> packedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> PackedDouble {
       get { return packedDouble_; }
     }
@@ -5611,6 +7755,7 @@
         = pb::FieldCodec.ForBool(818);
     private readonly pbc::RepeatedField<bool> packedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> PackedBool {
       get { return packedBool_; }
     }
@@ -5621,16 +7766,19 @@
         = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> packedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> PackedEnum {
       get { return packedEnum_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestPackedTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestPackedTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5656,6 +7804,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= packedInt32_.GetHashCode();
@@ -5679,12 +7828,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       packedInt32_.WriteTo(output, _repeated_packedInt32_codec);
       packedInt64_.WriteTo(output, _repeated_packedInt64_codec);
       packedUint32_.WriteTo(output, _repeated_packedUint32_codec);
@@ -5702,9 +7856,35 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec);
+      packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec);
+      packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec);
+      packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec);
+      packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec);
+      packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec);
+      packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec);
+      packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec);
+      packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec);
+      packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec);
+      packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec);
+      packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec);
+      packedBool_.WriteTo(ref output, _repeated_packedBool_codec);
+      packedEnum_.WriteTo(ref output, _repeated_packedEnum_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += packedInt32_.CalculateSize(_repeated_packedInt32_codec);
@@ -5728,6 +7908,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestPackedTypes other) {
       if (other == null) {
         return;
@@ -5750,7 +7931,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5829,31 +8014,125 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 722:
+          case 720: {
+            packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            packedEnum_.AddEntriesFrom(ref input, _repeated_packedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// A message with the same fields as TestPackedTypes, but without packing. Used
   /// to test packed &lt;-> unpacked wire compatibility.
   /// </summary>
-  public sealed partial class TestUnpackedTypes : pb::IMessage<TestUnpackedTypes> {
+  public sealed partial class TestUnpackedTypes : pb::IMessage<TestUnpackedTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestUnpackedTypes> _parser = new pb::MessageParser<TestUnpackedTypes>(() => new TestUnpackedTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestUnpackedTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[25]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedTypes() {
       OnConstruction();
     }
@@ -5861,6 +8140,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedTypes(TestUnpackedTypes other) : this() {
       unpackedInt32_ = other.unpackedInt32_.Clone();
       unpackedInt64_ = other.unpackedInt64_.Clone();
@@ -5880,6 +8160,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestUnpackedTypes Clone() {
       return new TestUnpackedTypes(this);
     }
@@ -5890,6 +8171,7 @@
         = pb::FieldCodec.ForInt32(720);
     private readonly pbc::RepeatedField<int> unpackedInt32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedInt32 {
       get { return unpackedInt32_; }
     }
@@ -5900,6 +8182,7 @@
         = pb::FieldCodec.ForInt64(728);
     private readonly pbc::RepeatedField<long> unpackedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedInt64 {
       get { return unpackedInt64_; }
     }
@@ -5910,6 +8193,7 @@
         = pb::FieldCodec.ForUInt32(736);
     private readonly pbc::RepeatedField<uint> unpackedUint32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedUint32 {
       get { return unpackedUint32_; }
     }
@@ -5920,6 +8204,7 @@
         = pb::FieldCodec.ForUInt64(744);
     private readonly pbc::RepeatedField<ulong> unpackedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedUint64 {
       get { return unpackedUint64_; }
     }
@@ -5930,6 +8215,7 @@
         = pb::FieldCodec.ForSInt32(752);
     private readonly pbc::RepeatedField<int> unpackedSint32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSint32 {
       get { return unpackedSint32_; }
     }
@@ -5940,6 +8226,7 @@
         = pb::FieldCodec.ForSInt64(760);
     private readonly pbc::RepeatedField<long> unpackedSint64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSint64 {
       get { return unpackedSint64_; }
     }
@@ -5950,6 +8237,7 @@
         = pb::FieldCodec.ForFixed32(773);
     private readonly pbc::RepeatedField<uint> unpackedFixed32_ = new pbc::RepeatedField<uint>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> UnpackedFixed32 {
       get { return unpackedFixed32_; }
     }
@@ -5960,6 +8248,7 @@
         = pb::FieldCodec.ForFixed64(777);
     private readonly pbc::RepeatedField<ulong> unpackedFixed64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> UnpackedFixed64 {
       get { return unpackedFixed64_; }
     }
@@ -5970,6 +8259,7 @@
         = pb::FieldCodec.ForSFixed32(789);
     private readonly pbc::RepeatedField<int> unpackedSfixed32_ = new pbc::RepeatedField<int>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> UnpackedSfixed32 {
       get { return unpackedSfixed32_; }
     }
@@ -5980,6 +8270,7 @@
         = pb::FieldCodec.ForSFixed64(793);
     private readonly pbc::RepeatedField<long> unpackedSfixed64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> UnpackedSfixed64 {
       get { return unpackedSfixed64_; }
     }
@@ -5990,6 +8281,7 @@
         = pb::FieldCodec.ForFloat(805);
     private readonly pbc::RepeatedField<float> unpackedFloat_ = new pbc::RepeatedField<float>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> UnpackedFloat {
       get { return unpackedFloat_; }
     }
@@ -6000,6 +8292,7 @@
         = pb::FieldCodec.ForDouble(809);
     private readonly pbc::RepeatedField<double> unpackedDouble_ = new pbc::RepeatedField<double>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double> UnpackedDouble {
       get { return unpackedDouble_; }
     }
@@ -6010,6 +8303,7 @@
         = pb::FieldCodec.ForBool(816);
     private readonly pbc::RepeatedField<bool> unpackedBool_ = new pbc::RepeatedField<bool>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool> UnpackedBool {
       get { return unpackedBool_; }
     }
@@ -6020,16 +8314,19 @@
         = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
     private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> unpackedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> UnpackedEnum {
       get { return unpackedEnum_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestUnpackedTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestUnpackedTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6055,6 +8352,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= unpackedInt32_.GetHashCode();
@@ -6078,12 +8376,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec);
       unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec);
       unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec);
@@ -6101,9 +8404,35 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec);
+      unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec);
+      unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec);
+      unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec);
+      unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec);
+      unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec);
+      unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec);
+      unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec);
+      unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec);
+      unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec);
+      unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec);
+      unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec);
+      unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec);
+      unpackedEnum_.WriteTo(ref output, _repeated_unpackedEnum_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec);
@@ -6127,6 +8456,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestUnpackedTypes other) {
       if (other == null) {
         return;
@@ -6149,7 +8479,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6228,27 +8562,121 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 722:
+          case 720: {
+            unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            unpackedEnum_.AddEntriesFrom(ref input, _repeated_unpackedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage<TestRepeatedScalarDifferentTagSizes> {
+  public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage<TestRepeatedScalarDifferentTagSizes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestRepeatedScalarDifferentTagSizes> _parser = new pb::MessageParser<TestRepeatedScalarDifferentTagSizes>(() => new TestRepeatedScalarDifferentTagSizes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestRepeatedScalarDifferentTagSizes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[26]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRepeatedScalarDifferentTagSizes() {
       OnConstruction();
     }
@@ -6256,6 +8684,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() {
       repeatedFixed32_ = other.repeatedFixed32_.Clone();
       repeatedInt32_ = other.repeatedInt32_.Clone();
@@ -6267,6 +8696,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestRepeatedScalarDifferentTagSizes Clone() {
       return new TestRepeatedScalarDifferentTagSizes(this);
     }
@@ -6282,6 +8712,7 @@
     /// in TestAllTypes didn't trigger the check.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint> RepeatedFixed32 {
       get { return repeatedFixed32_; }
     }
@@ -6295,6 +8726,7 @@
     /// Check for a varint type, just for good measure.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> RepeatedInt32 {
       get { return repeatedInt32_; }
     }
@@ -6308,6 +8740,7 @@
     /// These have two-byte tags.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedFixed64 {
       get { return repeatedFixed64_; }
     }
@@ -6318,6 +8751,7 @@
         = pb::FieldCodec.ForInt64(16378);
     private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long> RepeatedInt64 {
       get { return repeatedInt64_; }
     }
@@ -6331,6 +8765,7 @@
     /// Three byte tags.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float> RepeatedFloat {
       get { return repeatedFloat_; }
     }
@@ -6341,16 +8776,19 @@
         = pb::FieldCodec.ForUInt64(2097146);
     private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong> RepeatedUint64 {
       get { return repeatedUint64_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestRepeatedScalarDifferentTagSizes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestRepeatedScalarDifferentTagSizes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6368,6 +8806,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= repeatedFixed32_.GetHashCode();
@@ -6383,12 +8822,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
       repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
       repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
@@ -6398,9 +8842,27 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec);
+      repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec);
+      repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec);
+      repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec);
+      repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec);
+      repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
@@ -6416,6 +8878,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) {
       if (other == null) {
         return;
@@ -6430,7 +8893,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6469,27 +8936,81 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 98:
+          case 101: {
+            repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 106:
+          case 104: {
+            repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 16370:
+          case 16369: {
+            repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 16378:
+          case 16376: {
+            repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 2097138:
+          case 2097141: {
+            repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 2097146:
+          case 2097144: {
+            repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestCommentInjectionMessage : pb::IMessage<TestCommentInjectionMessage> {
+  public sealed partial class TestCommentInjectionMessage : pb::IMessage<TestCommentInjectionMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestCommentInjectionMessage> _parser = new pb::MessageParser<TestCommentInjectionMessage>(() => new TestCommentInjectionMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestCommentInjectionMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[27]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCommentInjectionMessage() {
       OnConstruction();
     }
@@ -6497,12 +9018,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() {
       a_ = other.a_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestCommentInjectionMessage Clone() {
       return new TestCommentInjectionMessage(this);
     }
@@ -6514,6 +9037,7 @@
     /// */ &lt;- This should not close the generated doc comment
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string A {
       get { return a_; }
       set {
@@ -6522,11 +9046,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestCommentInjectionMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestCommentInjectionMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6539,6 +9065,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (A.Length != 0) hash ^= A.GetHashCode();
@@ -6549,12 +9076,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (A.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(A);
@@ -6562,9 +9094,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (A.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(A);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (A.Length != 0) {
@@ -6577,6 +9125,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestCommentInjectionMessage other) {
       if (other == null) {
         return;
@@ -6588,7 +9137,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6601,30 +9154,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            A = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Test that RPC services work.
   /// </summary>
-  public sealed partial class FooRequest : pb::IMessage<FooRequest> {
+  public sealed partial class FooRequest : pb::IMessage<FooRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooRequest> _parser = new pb::MessageParser<FooRequest>(() => new FooRequest());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooRequest> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[28]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooRequest() {
       OnConstruction();
     }
@@ -6632,21 +9213,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooRequest(FooRequest other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooRequest Clone() {
       return new FooRequest(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooRequest);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooRequest other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6658,6 +9243,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -6667,18 +9253,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -6688,6 +9291,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooRequest other) {
       if (other == null) {
         return;
@@ -6696,7 +9300,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6705,27 +9313,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class FooResponse : pb::IMessage<FooResponse> {
+  public sealed partial class FooResponse : pb::IMessage<FooResponse>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooResponse> _parser = new pb::MessageParser<FooResponse>(() => new FooResponse());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooResponse> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[29]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooResponse() {
       OnConstruction();
     }
@@ -6733,21 +9365,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooResponse(FooResponse other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooResponse Clone() {
       return new FooResponse(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooResponse);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooResponse other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6759,6 +9395,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -6768,18 +9405,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -6789,6 +9443,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooResponse other) {
       if (other == null) {
         return;
@@ -6797,7 +9452,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6806,27 +9465,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class FooClientMessage : pb::IMessage<FooClientMessage> {
+  public sealed partial class FooClientMessage : pb::IMessage<FooClientMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooClientMessage> _parser = new pb::MessageParser<FooClientMessage>(() => new FooClientMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooClientMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[30]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooClientMessage() {
       OnConstruction();
     }
@@ -6834,21 +9517,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooClientMessage(FooClientMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooClientMessage Clone() {
       return new FooClientMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooClientMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooClientMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6860,6 +9547,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -6869,18 +9557,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -6890,6 +9595,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooClientMessage other) {
       if (other == null) {
         return;
@@ -6898,7 +9604,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6907,27 +9617,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class FooServerMessage : pb::IMessage<FooServerMessage> {
+  public sealed partial class FooServerMessage : pb::IMessage<FooServerMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FooServerMessage> _parser = new pb::MessageParser<FooServerMessage>(() => new FooServerMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FooServerMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[31]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooServerMessage() {
       OnConstruction();
     }
@@ -6935,21 +9669,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooServerMessage(FooServerMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FooServerMessage Clone() {
       return new FooServerMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FooServerMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FooServerMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6961,6 +9699,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -6970,18 +9709,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -6991,6 +9747,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FooServerMessage other) {
       if (other == null) {
         return;
@@ -6999,7 +9756,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7008,27 +9769,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class BarRequest : pb::IMessage<BarRequest> {
+  public sealed partial class BarRequest : pb::IMessage<BarRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BarRequest> _parser = new pb::MessageParser<BarRequest>(() => new BarRequest());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BarRequest> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[32]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarRequest() {
       OnConstruction();
     }
@@ -7036,21 +9821,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarRequest(BarRequest other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarRequest Clone() {
       return new BarRequest(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BarRequest);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BarRequest other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7062,6 +9851,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -7071,18 +9861,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -7092,6 +9899,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BarRequest other) {
       if (other == null) {
         return;
@@ -7100,7 +9908,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7109,27 +9921,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class BarResponse : pb::IMessage<BarResponse> {
+  public sealed partial class BarResponse : pb::IMessage<BarResponse>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BarResponse> _parser = new pb::MessageParser<BarResponse>(() => new BarResponse());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BarResponse> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[33]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarResponse() {
       OnConstruction();
     }
@@ -7137,21 +9973,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarResponse(BarResponse other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BarResponse Clone() {
       return new BarResponse(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BarResponse);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BarResponse other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7163,6 +10003,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -7172,18 +10013,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -7193,6 +10051,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BarResponse other) {
       if (other == null) {
         return;
@@ -7201,7 +10060,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7210,27 +10073,51 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class TestEmptyMessage : pb::IMessage<TestEmptyMessage> {
+  public sealed partial class TestEmptyMessage : pb::IMessage<TestEmptyMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestEmptyMessage> _parser = new pb::MessageParser<TestEmptyMessage>(() => new TestEmptyMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestEmptyMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[34]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessage() {
       OnConstruction();
     }
@@ -7238,21 +10125,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessage(TestEmptyMessage other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestEmptyMessage Clone() {
       return new TestEmptyMessage(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestEmptyMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestEmptyMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7264,6 +10155,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -7273,18 +10165,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -7294,6 +10203,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestEmptyMessage other) {
       if (other == null) {
         return;
@@ -7302,7 +10212,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7311,30 +10225,54 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// This is a leading comment
   /// </summary>
-  public sealed partial class CommentMessage : pb::IMessage<CommentMessage> {
+  public sealed partial class CommentMessage : pb::IMessage<CommentMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<CommentMessage> _parser = new pb::MessageParser<CommentMessage>(() => new CommentMessage());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<CommentMessage> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[35]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CommentMessage() {
       OnConstruction();
     }
@@ -7342,12 +10280,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CommentMessage(CommentMessage other) : this() {
       text_ = other.text_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public CommentMessage Clone() {
       return new CommentMessage(this);
     }
@@ -7359,6 +10299,7 @@
     /// Leading field comment
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Text {
       get { return text_; }
       set {
@@ -7367,11 +10308,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as CommentMessage);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(CommentMessage other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7384,6 +10327,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Text.Length != 0) hash ^= Text.GetHashCode();
@@ -7394,12 +10338,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Text.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Text);
@@ -7407,9 +10356,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Text.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Text);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Text.Length != 0) {
@@ -7422,6 +10387,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(CommentMessage other) {
       if (other == null) {
         return;
@@ -7433,7 +10399,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7446,11 +10416,32 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Text = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the CommentMessage message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// Leading nested enum comment
@@ -7465,23 +10456,31 @@
       /// <summary>
       /// Leading nested message comment
       /// </summary>
-      public sealed partial class NestedCommentMessage : pb::IMessage<NestedCommentMessage> {
+      public sealed partial class NestedCommentMessage : pb::IMessage<NestedCommentMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NestedCommentMessage> _parser = new pb::MessageParser<NestedCommentMessage>(() => new NestedCommentMessage());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NestedCommentMessage> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.TestProtos.CommentMessage.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedCommentMessage() {
           OnConstruction();
         }
@@ -7489,12 +10488,14 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedCommentMessage(NestedCommentMessage other) : this() {
           nestedText_ = other.nestedText_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NestedCommentMessage Clone() {
           return new NestedCommentMessage(this);
         }
@@ -7506,6 +10507,7 @@
         /// Leading nested message field comment
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string NestedText {
           get { return nestedText_; }
           set {
@@ -7514,11 +10516,13 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NestedCommentMessage);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NestedCommentMessage other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -7531,6 +10535,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (NestedText.Length != 0) hash ^= NestedText.GetHashCode();
@@ -7541,12 +10546,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (NestedText.Length != 0) {
             output.WriteRawTag(10);
             output.WriteString(NestedText);
@@ -7554,9 +10564,25 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (NestedText.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(NestedText);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (NestedText.Length != 0) {
@@ -7569,6 +10595,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NestedCommentMessage other) {
           if (other == null) {
             return;
@@ -7580,7 +10607,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -7593,8 +10624,28 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                NestedText = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
new file mode 100644
index 0000000..a41b890
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
@@ -0,0 +1,2092 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/unittest_proto3_optional.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace ProtobufUnittest {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/unittest_proto3_optional.proto</summary>
+  public static partial class UnittestProto3OptionalReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/unittest_proto3_optional.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestProto3OptionalReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Ci5nb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zX29wdGlvbmFsLnBy",
+            "b3RvEhFwcm90b2J1Zl91bml0dGVzdBogZ29vZ2xlL3Byb3RvYnVmL2Rlc2Ny",
+            "aXB0b3IucHJvdG8isQoKElRlc3RQcm90bzNPcHRpb25hbBIbCg5vcHRpb25h",
+            "bF9pbnQzMhgBIAEoBUgAiAEBEhsKDm9wdGlvbmFsX2ludDY0GAIgASgDSAGI",
+            "AQESHAoPb3B0aW9uYWxfdWludDMyGAMgASgNSAKIAQESHAoPb3B0aW9uYWxf",
+            "dWludDY0GAQgASgESAOIAQESHAoPb3B0aW9uYWxfc2ludDMyGAUgASgRSASI",
+            "AQESHAoPb3B0aW9uYWxfc2ludDY0GAYgASgSSAWIAQESHQoQb3B0aW9uYWxf",
+            "Zml4ZWQzMhgHIAEoB0gGiAEBEh0KEG9wdGlvbmFsX2ZpeGVkNjQYCCABKAZI",
+            "B4gBARIeChFvcHRpb25hbF9zZml4ZWQzMhgJIAEoD0gIiAEBEh4KEW9wdGlv",
+            "bmFsX3NmaXhlZDY0GAogASgQSAmIAQESGwoOb3B0aW9uYWxfZmxvYXQYCyAB",
+            "KAJICogBARIcCg9vcHRpb25hbF9kb3VibGUYDCABKAFIC4gBARIaCg1vcHRp",
+            "b25hbF9ib29sGA0gASgISAyIAQESHAoPb3B0aW9uYWxfc3RyaW5nGA4gASgJ",
+            "SA2IAQESGwoOb3B0aW9uYWxfYnl0ZXMYDyABKAxIDogBARIeCg1vcHRpb25h",
+            "bF9jb3JkGBAgASgJQgIIAUgPiAEBElkKF29wdGlvbmFsX25lc3RlZF9tZXNz",
+            "YWdlGBIgASgLMjMucHJvdG9idWZfdW5pdHRlc3QuVGVzdFByb3RvM09wdGlv",
+            "bmFsLk5lc3RlZE1lc3NhZ2VIEIgBARJZChNsYXp5X25lc3RlZF9tZXNzYWdl",
+            "GBMgASgLMjMucHJvdG9idWZfdW5pdHRlc3QuVGVzdFByb3RvM09wdGlvbmFs",
+            "Lk5lc3RlZE1lc3NhZ2VCAigBSBGIAQESUwoUb3B0aW9uYWxfbmVzdGVkX2Vu",
+            "dW0YFSABKA4yMC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJvdG8zT3B0aW9u",
+            "YWwuTmVzdGVkRW51bUgSiAEBEhYKDnNpbmd1bGFyX2ludDMyGBYgASgFEhYK",
+            "DnNpbmd1bGFyX2ludDY0GBcgASgDGicKDU5lc3RlZE1lc3NhZ2USDwoCYmIY",
+            "ASABKAVIAIgBAUIFCgNfYmIiSgoKTmVzdGVkRW51bRIPCgtVTlNQRUNJRklF",
+            "RBAAEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/////////",
+            "//8BQhEKD19vcHRpb25hbF9pbnQzMkIRCg9fb3B0aW9uYWxfaW50NjRCEgoQ",
+            "X29wdGlvbmFsX3VpbnQzMkISChBfb3B0aW9uYWxfdWludDY0QhIKEF9vcHRp",
+            "b25hbF9zaW50MzJCEgoQX29wdGlvbmFsX3NpbnQ2NEITChFfb3B0aW9uYWxf",
+            "Zml4ZWQzMkITChFfb3B0aW9uYWxfZml4ZWQ2NEIUChJfb3B0aW9uYWxfc2Zp",
+            "eGVkMzJCFAoSX29wdGlvbmFsX3NmaXhlZDY0QhEKD19vcHRpb25hbF9mbG9h",
+            "dEISChBfb3B0aW9uYWxfZG91YmxlQhAKDl9vcHRpb25hbF9ib29sQhIKEF9v",
+            "cHRpb25hbF9zdHJpbmdCEQoPX29wdGlvbmFsX2J5dGVzQhAKDl9vcHRpb25h",
+            "bF9jb3JkQhoKGF9vcHRpb25hbF9uZXN0ZWRfbWVzc2FnZUIWChRfbGF6eV9u",
+            "ZXN0ZWRfbWVzc2FnZUIXChVfb3B0aW9uYWxfbmVzdGVkX2VudW0iiQIKGVRl",
+            "c3RQcm90bzNPcHRpb25hbE1lc3NhZ2USUgoObmVzdGVkX21lc3NhZ2UYASAB",
+            "KAsyOi5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJvdG8zT3B0aW9uYWxNZXNz",
+            "YWdlLk5lc3RlZE1lc3NhZ2USYAoXb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2UY",
+            "AiABKAsyOi5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJvdG8zT3B0aW9uYWxN",
+            "ZXNzYWdlLk5lc3RlZE1lc3NhZ2VIAIgBARoaCg1OZXN0ZWRNZXNzYWdlEgkK",
+            "AXMYASABKAlCGgoYX29wdGlvbmFsX25lc3RlZF9tZXNzYWdlIqkBChhQcm90",
+            "bzNPcHRpb25hbEV4dGVuc2lvbnMyPAoPZXh0X25vX29wdGlvbmFsEh8uZ29v",
+            "Z2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGIjN2akBIAEoBTJBChFleHRf",
+            "d2l0aF9vcHRpb25hbBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9u",
+            "cxiJzdmpASABKAWIAQE6DMDozM0KCMjozM0KEEIlCiFjb20uZ29vZ2xlLnBy",
+            "b3RvYnVmLnRlc3RpbmcucHJvdG9QAWIGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional), global::ProtobufUnittest.TestProto3Optional.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum", "SingularInt32", "SingularInt64" }, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum" }, new[]{ typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage), global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage.Parser, new[]{ "Bb" }, new[]{ "Bb" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Parser, new[]{ "NestedMessage", "OptionalNestedMessage" }, new[]{ "OptionalNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage.Parser, new[]{ "S" }, null, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.Proto3OptionalExtensions), global::ProtobufUnittest.Proto3OptionalExtensions.Parser, null, null, null, new pb::Extension[] { global::ProtobufUnittest.Proto3OptionalExtensions.Extensions.ExtNoOptional, global::ProtobufUnittest.Proto3OptionalExtensions.Extensions.ExtWithOptional }, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  public sealed partial class TestProto3Optional : pb::IMessage<TestProto3Optional>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<TestProto3Optional> _parser = new pb::MessageParser<TestProto3Optional>(() => new TestProto3Optional());
+    private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<TestProto3Optional> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TestProto3Optional() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TestProto3Optional(TestProto3Optional other) : this() {
+      _hasBits0 = other._hasBits0;
+      optionalInt32_ = other.optionalInt32_;
+      optionalInt64_ = other.optionalInt64_;
+      optionalUint32_ = other.optionalUint32_;
+      optionalUint64_ = other.optionalUint64_;
+      optionalSint32_ = other.optionalSint32_;
+      optionalSint64_ = other.optionalSint64_;
+      optionalFixed32_ = other.optionalFixed32_;
+      optionalFixed64_ = other.optionalFixed64_;
+      optionalSfixed32_ = other.optionalSfixed32_;
+      optionalSfixed64_ = other.optionalSfixed64_;
+      optionalFloat_ = other.optionalFloat_;
+      optionalDouble_ = other.optionalDouble_;
+      optionalBool_ = other.optionalBool_;
+      optionalString_ = other.optionalString_;
+      optionalBytes_ = other.optionalBytes_;
+      optionalCord_ = other.optionalCord_;
+      optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
+      lazyNestedMessage_ = other.lazyNestedMessage_ != null ? other.lazyNestedMessage_.Clone() : null;
+      optionalNestedEnum_ = other.optionalNestedEnum_;
+      singularInt32_ = other.singularInt32_;
+      singularInt64_ = other.singularInt64_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TestProto3Optional Clone() {
+      return new TestProto3Optional(this);
+    }
+
+    /// <summary>Field number for the "optional_int32" field.</summary>
+    public const int OptionalInt32FieldNumber = 1;
+    private int optionalInt32_;
+    /// <summary>
+    /// Singular
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int OptionalInt32 {
+      get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return 0; } }
+      set {
+        _hasBits0 |= 1;
+        optionalInt32_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_int32" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalInt32 {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_int32" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalInt32() {
+      _hasBits0 &= ~1;
+    }
+
+    /// <summary>Field number for the "optional_int64" field.</summary>
+    public const int OptionalInt64FieldNumber = 2;
+    private long optionalInt64_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public long OptionalInt64 {
+      get { if ((_hasBits0 & 2) != 0) { return optionalInt64_; } else { return 0L; } }
+      set {
+        _hasBits0 |= 2;
+        optionalInt64_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_int64" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalInt64 {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_int64" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalInt64() {
+      _hasBits0 &= ~2;
+    }
+
+    /// <summary>Field number for the "optional_uint32" field.</summary>
+    public const int OptionalUint32FieldNumber = 3;
+    private uint optionalUint32_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public uint OptionalUint32 {
+      get { if ((_hasBits0 & 4) != 0) { return optionalUint32_; } else { return 0; } }
+      set {
+        _hasBits0 |= 4;
+        optionalUint32_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_uint32" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalUint32 {
+      get { return (_hasBits0 & 4) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_uint32" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalUint32() {
+      _hasBits0 &= ~4;
+    }
+
+    /// <summary>Field number for the "optional_uint64" field.</summary>
+    public const int OptionalUint64FieldNumber = 4;
+    private ulong optionalUint64_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ulong OptionalUint64 {
+      get { if ((_hasBits0 & 8) != 0) { return optionalUint64_; } else { return 0UL; } }
+      set {
+        _hasBits0 |= 8;
+        optionalUint64_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_uint64" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalUint64 {
+      get { return (_hasBits0 & 8) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_uint64" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalUint64() {
+      _hasBits0 &= ~8;
+    }
+
+    /// <summary>Field number for the "optional_sint32" field.</summary>
+    public const int OptionalSint32FieldNumber = 5;
+    private int optionalSint32_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int OptionalSint32 {
+      get { if ((_hasBits0 & 16) != 0) { return optionalSint32_; } else { return 0; } }
+      set {
+        _hasBits0 |= 16;
+        optionalSint32_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_sint32" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalSint32 {
+      get { return (_hasBits0 & 16) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_sint32" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalSint32() {
+      _hasBits0 &= ~16;
+    }
+
+    /// <summary>Field number for the "optional_sint64" field.</summary>
+    public const int OptionalSint64FieldNumber = 6;
+    private long optionalSint64_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public long OptionalSint64 {
+      get { if ((_hasBits0 & 32) != 0) { return optionalSint64_; } else { return 0L; } }
+      set {
+        _hasBits0 |= 32;
+        optionalSint64_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_sint64" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalSint64 {
+      get { return (_hasBits0 & 32) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_sint64" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalSint64() {
+      _hasBits0 &= ~32;
+    }
+
+    /// <summary>Field number for the "optional_fixed32" field.</summary>
+    public const int OptionalFixed32FieldNumber = 7;
+    private uint optionalFixed32_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public uint OptionalFixed32 {
+      get { if ((_hasBits0 & 64) != 0) { return optionalFixed32_; } else { return 0; } }
+      set {
+        _hasBits0 |= 64;
+        optionalFixed32_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_fixed32" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalFixed32 {
+      get { return (_hasBits0 & 64) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_fixed32" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalFixed32() {
+      _hasBits0 &= ~64;
+    }
+
+    /// <summary>Field number for the "optional_fixed64" field.</summary>
+    public const int OptionalFixed64FieldNumber = 8;
+    private ulong optionalFixed64_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ulong OptionalFixed64 {
+      get { if ((_hasBits0 & 128) != 0) { return optionalFixed64_; } else { return 0UL; } }
+      set {
+        _hasBits0 |= 128;
+        optionalFixed64_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_fixed64" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalFixed64 {
+      get { return (_hasBits0 & 128) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_fixed64" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalFixed64() {
+      _hasBits0 &= ~128;
+    }
+
+    /// <summary>Field number for the "optional_sfixed32" field.</summary>
+    public const int OptionalSfixed32FieldNumber = 9;
+    private int optionalSfixed32_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int OptionalSfixed32 {
+      get { if ((_hasBits0 & 256) != 0) { return optionalSfixed32_; } else { return 0; } }
+      set {
+        _hasBits0 |= 256;
+        optionalSfixed32_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_sfixed32" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalSfixed32 {
+      get { return (_hasBits0 & 256) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_sfixed32" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalSfixed32() {
+      _hasBits0 &= ~256;
+    }
+
+    /// <summary>Field number for the "optional_sfixed64" field.</summary>
+    public const int OptionalSfixed64FieldNumber = 10;
+    private long optionalSfixed64_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public long OptionalSfixed64 {
+      get { if ((_hasBits0 & 512) != 0) { return optionalSfixed64_; } else { return 0L; } }
+      set {
+        _hasBits0 |= 512;
+        optionalSfixed64_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_sfixed64" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalSfixed64 {
+      get { return (_hasBits0 & 512) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_sfixed64" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalSfixed64() {
+      _hasBits0 &= ~512;
+    }
+
+    /// <summary>Field number for the "optional_float" field.</summary>
+    public const int OptionalFloatFieldNumber = 11;
+    private float optionalFloat_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public float OptionalFloat {
+      get { if ((_hasBits0 & 1024) != 0) { return optionalFloat_; } else { return 0F; } }
+      set {
+        _hasBits0 |= 1024;
+        optionalFloat_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_float" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalFloat {
+      get { return (_hasBits0 & 1024) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_float" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalFloat() {
+      _hasBits0 &= ~1024;
+    }
+
+    /// <summary>Field number for the "optional_double" field.</summary>
+    public const int OptionalDoubleFieldNumber = 12;
+    private double optionalDouble_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public double OptionalDouble {
+      get { if ((_hasBits0 & 2048) != 0) { return optionalDouble_; } else { return 0D; } }
+      set {
+        _hasBits0 |= 2048;
+        optionalDouble_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_double" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalDouble {
+      get { return (_hasBits0 & 2048) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_double" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalDouble() {
+      _hasBits0 &= ~2048;
+    }
+
+    /// <summary>Field number for the "optional_bool" field.</summary>
+    public const int OptionalBoolFieldNumber = 13;
+    private bool optionalBool_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool OptionalBool {
+      get { if ((_hasBits0 & 4096) != 0) { return optionalBool_; } else { return false; } }
+      set {
+        _hasBits0 |= 4096;
+        optionalBool_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_bool" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalBool {
+      get { return (_hasBits0 & 4096) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_bool" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalBool() {
+      _hasBits0 &= ~4096;
+    }
+
+    /// <summary>Field number for the "optional_string" field.</summary>
+    public const int OptionalStringFieldNumber = 14;
+    private string optionalString_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string OptionalString {
+      get { return optionalString_ ?? ""; }
+      set {
+        optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "optional_string" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalString {
+      get { return optionalString_ != null; }
+    }
+    /// <summary>Clears the value of the "optional_string" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalString() {
+      optionalString_ = null;
+    }
+
+    /// <summary>Field number for the "optional_bytes" field.</summary>
+    public const int OptionalBytesFieldNumber = 15;
+    private pb::ByteString optionalBytes_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pb::ByteString OptionalBytes {
+      get { return optionalBytes_ ?? pb::ByteString.Empty; }
+      set {
+        optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "optional_bytes" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalBytes {
+      get { return optionalBytes_ != null; }
+    }
+    /// <summary>Clears the value of the "optional_bytes" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalBytes() {
+      optionalBytes_ = null;
+    }
+
+    /// <summary>Field number for the "optional_cord" field.</summary>
+    public const int OptionalCordFieldNumber = 16;
+    private string optionalCord_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string OptionalCord {
+      get { return optionalCord_ ?? ""; }
+      set {
+        optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "optional_cord" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalCord {
+      get { return optionalCord_ != null; }
+    }
+    /// <summary>Clears the value of the "optional_cord" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalCord() {
+      optionalCord_ = null;
+    }
+
+    /// <summary>Field number for the "optional_nested_message" field.</summary>
+    public const int OptionalNestedMessageFieldNumber = 18;
+    private global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage optionalNestedMessage_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage OptionalNestedMessage {
+      get { return optionalNestedMessage_; }
+      set {
+        optionalNestedMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "lazy_nested_message" field.</summary>
+    public const int LazyNestedMessageFieldNumber = 19;
+    private global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage lazyNestedMessage_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage LazyNestedMessage {
+      get { return lazyNestedMessage_; }
+      set {
+        lazyNestedMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_nested_enum" field.</summary>
+    public const int OptionalNestedEnumFieldNumber = 21;
+    private global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum optionalNestedEnum_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum OptionalNestedEnum {
+      get { if ((_hasBits0 & 8192) != 0) { return optionalNestedEnum_; } else { return global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum.Unspecified; } }
+      set {
+        _hasBits0 |= 8192;
+        optionalNestedEnum_ = value;
+      }
+    }
+    /// <summary>Gets whether the "optional_nested_enum" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasOptionalNestedEnum {
+      get { return (_hasBits0 & 8192) != 0; }
+    }
+    /// <summary>Clears the value of the "optional_nested_enum" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearOptionalNestedEnum() {
+      _hasBits0 &= ~8192;
+    }
+
+    /// <summary>Field number for the "singular_int32" field.</summary>
+    public const int SingularInt32FieldNumber = 22;
+    private int singularInt32_;
+    /// <summary>
+    /// Add some non-optional fields to verify we can mix them.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int SingularInt32 {
+      get { return singularInt32_; }
+      set {
+        singularInt32_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "singular_int64" field.</summary>
+    public const int SingularInt64FieldNumber = 23;
+    private long singularInt64_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public long SingularInt64 {
+      get { return singularInt64_; }
+      set {
+        singularInt64_ = value;
+      }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as TestProto3Optional);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(TestProto3Optional other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (OptionalInt32 != other.OptionalInt32) return false;
+      if (OptionalInt64 != other.OptionalInt64) return false;
+      if (OptionalUint32 != other.OptionalUint32) return false;
+      if (OptionalUint64 != other.OptionalUint64) return false;
+      if (OptionalSint32 != other.OptionalSint32) return false;
+      if (OptionalSint64 != other.OptionalSint64) return false;
+      if (OptionalFixed32 != other.OptionalFixed32) return false;
+      if (OptionalFixed64 != other.OptionalFixed64) return false;
+      if (OptionalSfixed32 != other.OptionalSfixed32) return false;
+      if (OptionalSfixed64 != other.OptionalSfixed64) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OptionalFloat, other.OptionalFloat)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OptionalDouble, other.OptionalDouble)) return false;
+      if (OptionalBool != other.OptionalBool) return false;
+      if (OptionalString != other.OptionalString) return false;
+      if (OptionalBytes != other.OptionalBytes) return false;
+      if (OptionalCord != other.OptionalCord) return false;
+      if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false;
+      if (!object.Equals(LazyNestedMessage, other.LazyNestedMessage)) return false;
+      if (OptionalNestedEnum != other.OptionalNestedEnum) return false;
+      if (SingularInt32 != other.SingularInt32) return false;
+      if (SingularInt64 != other.SingularInt64) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode();
+      if (HasOptionalInt64) hash ^= OptionalInt64.GetHashCode();
+      if (HasOptionalUint32) hash ^= OptionalUint32.GetHashCode();
+      if (HasOptionalUint64) hash ^= OptionalUint64.GetHashCode();
+      if (HasOptionalSint32) hash ^= OptionalSint32.GetHashCode();
+      if (HasOptionalSint64) hash ^= OptionalSint64.GetHashCode();
+      if (HasOptionalFixed32) hash ^= OptionalFixed32.GetHashCode();
+      if (HasOptionalFixed64) hash ^= OptionalFixed64.GetHashCode();
+      if (HasOptionalSfixed32) hash ^= OptionalSfixed32.GetHashCode();
+      if (HasOptionalSfixed64) hash ^= OptionalSfixed64.GetHashCode();
+      if (HasOptionalFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat);
+      if (HasOptionalDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble);
+      if (HasOptionalBool) hash ^= OptionalBool.GetHashCode();
+      if (HasOptionalString) hash ^= OptionalString.GetHashCode();
+      if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode();
+      if (HasOptionalCord) hash ^= OptionalCord.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
+      if (lazyNestedMessage_ != null) hash ^= LazyNestedMessage.GetHashCode();
+      if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode();
+      if (SingularInt32 != 0) hash ^= SingularInt32.GetHashCode();
+      if (SingularInt64 != 0L) hash ^= SingularInt64.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (HasOptionalInt32) {
+        output.WriteRawTag(8);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (HasOptionalInt64) {
+        output.WriteRawTag(16);
+        output.WriteInt64(OptionalInt64);
+      }
+      if (HasOptionalUint32) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(OptionalUint32);
+      }
+      if (HasOptionalUint64) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(OptionalUint64);
+      }
+      if (HasOptionalSint32) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(OptionalSint32);
+      }
+      if (HasOptionalSint64) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(OptionalSint64);
+      }
+      if (HasOptionalFixed32) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(OptionalFixed32);
+      }
+      if (HasOptionalFixed64) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(OptionalFixed64);
+      }
+      if (HasOptionalSfixed32) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(OptionalSfixed32);
+      }
+      if (HasOptionalSfixed64) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(OptionalSfixed64);
+      }
+      if (HasOptionalFloat) {
+        output.WriteRawTag(93);
+        output.WriteFloat(OptionalFloat);
+      }
+      if (HasOptionalDouble) {
+        output.WriteRawTag(97);
+        output.WriteDouble(OptionalDouble);
+      }
+      if (HasOptionalBool) {
+        output.WriteRawTag(104);
+        output.WriteBool(OptionalBool);
+      }
+      if (HasOptionalString) {
+        output.WriteRawTag(114);
+        output.WriteString(OptionalString);
+      }
+      if (HasOptionalBytes) {
+        output.WriteRawTag(122);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (HasOptionalCord) {
+        output.WriteRawTag(130, 1);
+        output.WriteString(OptionalCord);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (lazyNestedMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(LazyNestedMessage);
+      }
+      if (HasOptionalNestedEnum) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) OptionalNestedEnum);
+      }
+      if (SingularInt32 != 0) {
+        output.WriteRawTag(176, 1);
+        output.WriteInt32(SingularInt32);
+      }
+      if (SingularInt64 != 0L) {
+        output.WriteRawTag(184, 1);
+        output.WriteInt64(SingularInt64);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasOptionalInt32) {
+        output.WriteRawTag(8);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (HasOptionalInt64) {
+        output.WriteRawTag(16);
+        output.WriteInt64(OptionalInt64);
+      }
+      if (HasOptionalUint32) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(OptionalUint32);
+      }
+      if (HasOptionalUint64) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(OptionalUint64);
+      }
+      if (HasOptionalSint32) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(OptionalSint32);
+      }
+      if (HasOptionalSint64) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(OptionalSint64);
+      }
+      if (HasOptionalFixed32) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(OptionalFixed32);
+      }
+      if (HasOptionalFixed64) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(OptionalFixed64);
+      }
+      if (HasOptionalSfixed32) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(OptionalSfixed32);
+      }
+      if (HasOptionalSfixed64) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(OptionalSfixed64);
+      }
+      if (HasOptionalFloat) {
+        output.WriteRawTag(93);
+        output.WriteFloat(OptionalFloat);
+      }
+      if (HasOptionalDouble) {
+        output.WriteRawTag(97);
+        output.WriteDouble(OptionalDouble);
+      }
+      if (HasOptionalBool) {
+        output.WriteRawTag(104);
+        output.WriteBool(OptionalBool);
+      }
+      if (HasOptionalString) {
+        output.WriteRawTag(114);
+        output.WriteString(OptionalString);
+      }
+      if (HasOptionalBytes) {
+        output.WriteRawTag(122);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (HasOptionalCord) {
+        output.WriteRawTag(130, 1);
+        output.WriteString(OptionalCord);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (lazyNestedMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(LazyNestedMessage);
+      }
+      if (HasOptionalNestedEnum) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) OptionalNestedEnum);
+      }
+      if (SingularInt32 != 0) {
+        output.WriteRawTag(176, 1);
+        output.WriteInt32(SingularInt32);
+      }
+      if (SingularInt64 != 0L) {
+        output.WriteRawTag(184, 1);
+        output.WriteInt64(SingularInt64);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (HasOptionalInt32) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32);
+      }
+      if (HasOptionalInt64) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64);
+      }
+      if (HasOptionalUint32) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32);
+      }
+      if (HasOptionalUint64) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64);
+      }
+      if (HasOptionalSint32) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32);
+      }
+      if (HasOptionalSint64) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64);
+      }
+      if (HasOptionalFixed32) {
+        size += 1 + 4;
+      }
+      if (HasOptionalFixed64) {
+        size += 1 + 8;
+      }
+      if (HasOptionalSfixed32) {
+        size += 1 + 4;
+      }
+      if (HasOptionalSfixed64) {
+        size += 1 + 8;
+      }
+      if (HasOptionalFloat) {
+        size += 1 + 4;
+      }
+      if (HasOptionalDouble) {
+        size += 1 + 8;
+      }
+      if (HasOptionalBool) {
+        size += 1 + 1;
+      }
+      if (HasOptionalString) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString);
+      }
+      if (HasOptionalBytes) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes);
+      }
+      if (HasOptionalCord) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord);
+      }
+      if (optionalNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
+      }
+      if (lazyNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(LazyNestedMessage);
+      }
+      if (HasOptionalNestedEnum) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum);
+      }
+      if (SingularInt32 != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(SingularInt32);
+      }
+      if (SingularInt64 != 0L) {
+        size += 2 + pb::CodedOutputStream.ComputeInt64Size(SingularInt64);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(TestProto3Optional other) {
+      if (other == null) {
+        return;
+      }
+      if (other.HasOptionalInt32) {
+        OptionalInt32 = other.OptionalInt32;
+      }
+      if (other.HasOptionalInt64) {
+        OptionalInt64 = other.OptionalInt64;
+      }
+      if (other.HasOptionalUint32) {
+        OptionalUint32 = other.OptionalUint32;
+      }
+      if (other.HasOptionalUint64) {
+        OptionalUint64 = other.OptionalUint64;
+      }
+      if (other.HasOptionalSint32) {
+        OptionalSint32 = other.OptionalSint32;
+      }
+      if (other.HasOptionalSint64) {
+        OptionalSint64 = other.OptionalSint64;
+      }
+      if (other.HasOptionalFixed32) {
+        OptionalFixed32 = other.OptionalFixed32;
+      }
+      if (other.HasOptionalFixed64) {
+        OptionalFixed64 = other.OptionalFixed64;
+      }
+      if (other.HasOptionalSfixed32) {
+        OptionalSfixed32 = other.OptionalSfixed32;
+      }
+      if (other.HasOptionalSfixed64) {
+        OptionalSfixed64 = other.OptionalSfixed64;
+      }
+      if (other.HasOptionalFloat) {
+        OptionalFloat = other.OptionalFloat;
+      }
+      if (other.HasOptionalDouble) {
+        OptionalDouble = other.OptionalDouble;
+      }
+      if (other.HasOptionalBool) {
+        OptionalBool = other.OptionalBool;
+      }
+      if (other.HasOptionalString) {
+        OptionalString = other.OptionalString;
+      }
+      if (other.HasOptionalBytes) {
+        OptionalBytes = other.OptionalBytes;
+      }
+      if (other.HasOptionalCord) {
+        OptionalCord = other.OptionalCord;
+      }
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
+          OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage();
+        }
+        OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
+      }
+      if (other.lazyNestedMessage_ != null) {
+        if (lazyNestedMessage_ == null) {
+          LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage();
+        }
+        LazyNestedMessage.MergeFrom(other.LazyNestedMessage);
+      }
+      if (other.HasOptionalNestedEnum) {
+        OptionalNestedEnum = other.OptionalNestedEnum;
+      }
+      if (other.SingularInt32 != 0) {
+        SingularInt32 = other.SingularInt32;
+      }
+      if (other.SingularInt64 != 0L) {
+        SingularInt64 = other.SingularInt64;
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 8: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            OptionalInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            OptionalUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            OptionalUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            OptionalSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            OptionalSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            OptionalFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            OptionalFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            OptionalSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            OptionalSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            OptionalFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            OptionalDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 122: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 130: {
+            OptionalCord = input.ReadString();
+            break;
+          }
+          case 146: {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+          case 154: {
+            if (lazyNestedMessage_ == null) {
+              LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage();
+            }
+            input.ReadMessage(LazyNestedMessage);
+            break;
+          }
+          case 168: {
+            OptionalNestedEnum = (global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            SingularInt32 = input.ReadInt32();
+            break;
+          }
+          case 184: {
+            SingularInt64 = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            OptionalInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            OptionalUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            OptionalUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            OptionalSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            OptionalSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            OptionalFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            OptionalFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            OptionalSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            OptionalSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            OptionalFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            OptionalDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 122: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 130: {
+            OptionalCord = input.ReadString();
+            break;
+          }
+          case 146: {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+          case 154: {
+            if (lazyNestedMessage_ == null) {
+              LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage();
+            }
+            input.ReadMessage(LazyNestedMessage);
+            break;
+          }
+          case 168: {
+            OptionalNestedEnum = (global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            SingularInt32 = input.ReadInt32();
+            break;
+          }
+          case 184: {
+            SingularInt64 = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the TestProto3Optional message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static partial class Types {
+      public enum NestedEnum {
+        [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0,
+        [pbr::OriginalName("FOO")] Foo = 1,
+        [pbr::OriginalName("BAR")] Bar = 2,
+        [pbr::OriginalName("BAZ")] Baz = 3,
+        /// <summary>
+        /// Intentionally negative.
+        /// </summary>
+        [pbr::OriginalName("NEG")] Neg = -1,
+      }
+
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        private pb::UnknownFieldSet _unknownFields;
+        private int _hasBits0;
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::ProtobufUnittest.TestProto3Optional.Descriptor.NestedTypes[0]; }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public NestedMessage(NestedMessage other) : this() {
+          _hasBits0 = other._hasBits0;
+          bb_ = other.bb_;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        /// <summary>Field number for the "bb" field.</summary>
+        public const int BbFieldNumber = 1;
+        private int bb_;
+        /// <summary>
+        /// The field name "b" fails to compile in proto1 because it conflicts with
+        /// a local variable named "b" in one of the generated methods.  Doh.
+        /// This file needs to compile in proto1 to test backwards-compatibility.
+        /// </summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public int Bb {
+          get { if ((_hasBits0 & 1) != 0) { return bb_; } else { return 0; } }
+          set {
+            _hasBits0 |= 1;
+            bb_ = value;
+          }
+        }
+        /// <summary>Gets whether the "bb" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool HasBb {
+          get { return (_hasBits0 & 1) != 0; }
+        }
+        /// <summary>Clears the value of the "bb" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void ClearBb() {
+          _hasBits0 &= ~1;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Bb != other.Bb) return false;
+          return Equals(_unknownFields, other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override int GetHashCode() {
+          int hash = 1;
+          if (HasBb) hash ^= Bb.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
+          return hash;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
+          if (HasBb) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasBb) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public int CalculateSize() {
+          int size = 0;
+          if (HasBb) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb);
+          }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
+          return size;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.HasBb) {
+            Bb = other.Bb;
+          }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  public sealed partial class TestProto3OptionalMessage : pb::IMessage<TestProto3OptionalMessage>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<TestProto3OptionalMessage> _parser = new pb::MessageParser<TestProto3OptionalMessage>(() => new TestProto3OptionalMessage());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<TestProto3OptionalMessage> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[1]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TestProto3OptionalMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TestProto3OptionalMessage(TestProto3OptionalMessage other) : this() {
+      nestedMessage_ = other.nestedMessage_ != null ? other.nestedMessage_.Clone() : null;
+      optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public TestProto3OptionalMessage Clone() {
+      return new TestProto3OptionalMessage(this);
+    }
+
+    /// <summary>Field number for the "nested_message" field.</summary>
+    public const int NestedMessageFieldNumber = 1;
+    private global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage nestedMessage_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage NestedMessage {
+      get { return nestedMessage_; }
+      set {
+        nestedMessage_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "optional_nested_message" field.</summary>
+    public const int OptionalNestedMessageFieldNumber = 2;
+    private global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage optionalNestedMessage_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage OptionalNestedMessage {
+      get { return optionalNestedMessage_; }
+      set {
+        optionalNestedMessage_ = value;
+      }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as TestProto3OptionalMessage);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(TestProto3OptionalMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(NestedMessage, other.NestedMessage)) return false;
+      if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false;
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (nestedMessage_ != null) hash ^= NestedMessage.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (nestedMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(NestedMessage);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (nestedMessage_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(NestedMessage);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (nestedMessage_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(NestedMessage);
+      }
+      if (optionalNestedMessage_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(TestProto3OptionalMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.nestedMessage_ != null) {
+        if (nestedMessage_ == null) {
+          NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+        }
+        NestedMessage.MergeFrom(other.NestedMessage);
+      }
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
+          OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+        }
+        OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+          case 10: {
+            if (nestedMessage_ == null) {
+              NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+            }
+            input.ReadMessage(NestedMessage);
+            break;
+          }
+          case 18: {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (nestedMessage_ == null) {
+              NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+            }
+            input.ReadMessage(NestedMessage);
+            break;
+          }
+          case 18: {
+            if (optionalNestedMessage_ == null) {
+              OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+            }
+            input.ReadMessage(OptionalNestedMessage);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the TestProto3OptionalMessage message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static partial class Types {
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        private pb::UnknownFieldSet _unknownFields;
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::ProtobufUnittest.TestProto3OptionalMessage.Descriptor.NestedTypes[0]; }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public NestedMessage(NestedMessage other) : this() {
+          s_ = other.s_;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        /// <summary>Field number for the "s" field.</summary>
+        public const int SFieldNumber = 1;
+        private string s_ = "";
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public string S {
+          get { return s_; }
+          set {
+            s_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (S != other.S) return false;
+          return Equals(_unknownFields, other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override int GetHashCode() {
+          int hash = 1;
+          if (S.Length != 0) hash ^= S.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
+          return hash;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override string ToString() {
+          return pb::JsonFormatter.ToDiagnosticString(this);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
+          if (S.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(S);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (S.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(S);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public int CalculateSize() {
+          int size = 0;
+          if (S.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(S);
+          }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
+          return size;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.S.Length != 0) {
+            S = other.S;
+          }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                break;
+              case 10: {
+                S = input.ReadString();
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                S = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  public sealed partial class Proto3OptionalExtensions : pb::IMessage<Proto3OptionalExtensions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<Proto3OptionalExtensions> _parser = new pb::MessageParser<Proto3OptionalExtensions>(() => new Proto3OptionalExtensions());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<Proto3OptionalExtensions> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public Proto3OptionalExtensions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public Proto3OptionalExtensions(Proto3OptionalExtensions other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public Proto3OptionalExtensions Clone() {
+      return new Proto3OptionalExtensions(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as Proto3OptionalExtensions);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(Proto3OptionalExtensions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(Proto3OptionalExtensions other) {
+      if (other == null) {
+        return;
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
+    #region Extensions
+    /// <summary>Container for extensions for other messages declared in the Proto3OptionalExtensions message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static partial class Extensions {
+      public static readonly pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int> ExtNoOptional =
+        new pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int>(355886728, pb::FieldCodec.ForInt32(2847093824, 0));
+      public static readonly pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int> ExtWithOptional =
+        new pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int>(355886729, pb::FieldCodec.ForInt32(2847093832, 0));
+    }
+    #endregion
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs
new file mode 100644
index 0000000..7a8f72d
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs
@@ -0,0 +1,379 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: unittest_selfreferential_options.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace UnitTest.Issues.TestProtos.SelfreferentialOptions {
+
+  /// <summary>Holder for reflection information generated from unittest_selfreferential_options.proto</summary>
+  public static partial class UnittestSelfreferentialOptionsReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for unittest_selfreferential_options.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestSelfreferentialOptionsReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiZ1bml0dGVzdF9zZWxmcmVmZXJlbnRpYWxfb3B0aW9ucy5wcm90bxIpcHJv",
+            "dG9idWZfdW5pdHRlc3Rfc2VsZnJlZmVyZW50aWFsX29wdGlvbnMaIGdvb2ds",
+            "ZS9wcm90b2J1Zi9kZXNjcmlwdG9yLnByb3RvIkwKCkZvb09wdGlvbnMSHgoH",
+            "aW50X29wdBgBIAEoBUINyj4KCAHAPgLKPgIIAxITCgNmb28YAiABKAVCBso+",
+            "AxDSCSoJCOgHEICAgIACOjkKC2Jhcl9vcHRpb25zEh0uZ29vZ2xlLnByb3Rv",
+            "YnVmLkZpZWxkT3B0aW9ucxjoByABKAVCBMA+0gk6agoLZm9vX29wdGlvbnMS",
+            "HS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGOkHIAEoCzI1LnByb3Rv",
+            "YnVmX3VuaXR0ZXN0X3NlbGZyZWZlcmVudGlhbF9vcHRpb25zLkZvb09wdGlv",
+            "bnM6SwoLZm9vX2ludF9vcHQSNS5wcm90b2J1Zl91bml0dGVzdF9zZWxmcmVm",
+            "ZXJlbnRpYWxfb3B0aW9ucy5Gb29PcHRpb25zGOgHIAEoBTqCAQoLZm9vX2Zv",
+            "b19vcHQSNS5wcm90b2J1Zl91bml0dGVzdF9zZWxmcmVmZXJlbnRpYWxfb3B0",
+            "aW9ucy5Gb29PcHRpb25zGOkHIAEoCzI1LnByb3RvYnVmX3VuaXR0ZXN0X3Nl",
+            "bGZyZWZlcmVudGlhbF9vcHRpb25zLkZvb09wdGlvbnNCNKoCMVVuaXRUZXN0",
+            "Lklzc3Vlcy5UZXN0UHJvdG9zLlNlbGZyZWZlcmVudGlhbE9wdGlvbnM="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, new pb::Extension[] { UnittestSelfreferentialOptionsExtensions.BarOptions, UnittestSelfreferentialOptionsExtensions.FooOptions, UnittestSelfreferentialOptionsExtensions.FooIntOpt, UnittestSelfreferentialOptionsExtensions.FooFooOpt }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions), global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser, new[]{ "IntOpt", "Foo" }, null, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  /// <summary>Holder for extension identifiers generated from the top level of unittest_selfreferential_options.proto</summary>
+  public static partial class UnittestSelfreferentialOptionsExtensions {
+    /// <summary>
+    /// Custom field option used on the definition of that field option.
+    /// </summary>
+    public static readonly pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, int> BarOptions =
+      new pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, int>(1000, pb::FieldCodec.ForInt32(8000, 0));
+    public static readonly pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions> FooOptions =
+      new pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions>(1001, pb::FieldCodec.ForMessage(8010, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser));
+    public static readonly pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, int> FooIntOpt =
+      new pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, int>(1000, pb::FieldCodec.ForInt32(8000, 0));
+    public static readonly pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions> FooFooOpt =
+      new pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions>(1001, pb::FieldCodec.ForMessage(8010, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser));
+  }
+
+  #region Messages
+  public sealed partial class FooOptions : pb::IExtendableMessage<FooOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<FooOptions> _parser = new pb::MessageParser<FooOptions>(() => new FooOptions());
+    private pb::UnknownFieldSet _unknownFields;
+    private pb::ExtensionSet<FooOptions> _extensions;
+    private pb::ExtensionSet<FooOptions> _Extensions { get { return _extensions; } }
+    private int _hasBits0;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<FooOptions> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public FooOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public FooOptions(FooOptions other) : this() {
+      _hasBits0 = other._hasBits0;
+      intOpt_ = other.intOpt_;
+      foo_ = other.foo_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+      _extensions = pb::ExtensionSet.Clone(other._extensions);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public FooOptions Clone() {
+      return new FooOptions(this);
+    }
+
+    /// <summary>Field number for the "int_opt" field.</summary>
+    public const int IntOptFieldNumber = 1;
+    private readonly static int IntOptDefaultValue = 0;
+
+    private int intOpt_;
+    /// <summary>
+    /// Custom field option used in definition of the extension message.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int IntOpt {
+      get { if ((_hasBits0 & 1) != 0) { return intOpt_; } else { return IntOptDefaultValue; } }
+      set {
+        _hasBits0 |= 1;
+        intOpt_ = value;
+      }
+    }
+    /// <summary>Gets whether the "int_opt" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasIntOpt {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "int_opt" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearIntOpt() {
+      _hasBits0 &= ~1;
+    }
+
+    /// <summary>Field number for the "foo" field.</summary>
+    public const int FooFieldNumber = 2;
+    private readonly static int FooDefaultValue = 0;
+
+    private int foo_;
+    /// <summary>
+    /// Custom field option used in definition of the custom option's message.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Foo {
+      get { if ((_hasBits0 & 2) != 0) { return foo_; } else { return FooDefaultValue; } }
+      set {
+        _hasBits0 |= 2;
+        foo_ = value;
+      }
+    }
+    /// <summary>Gets whether the "foo" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasFoo {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "foo" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearFoo() {
+      _hasBits0 &= ~2;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as FooOptions);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(FooOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (IntOpt != other.IntOpt) return false;
+      if (Foo != other.Foo) return false;
+      if (!Equals(_extensions, other._extensions)) {
+        return false;
+      }
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (HasIntOpt) hash ^= IntOpt.GetHashCode();
+      if (HasFoo) hash ^= Foo.GetHashCode();
+      if (_extensions != null) {
+        hash ^= _extensions.GetHashCode();
+      }
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (HasIntOpt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(IntOpt);
+      }
+      if (HasFoo) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Foo);
+      }
+      if (_extensions != null) {
+        _extensions.WriteTo(output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasIntOpt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(IntOpt);
+      }
+      if (HasFoo) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Foo);
+      }
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize() {
+      int size = 0;
+      if (HasIntOpt) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntOpt);
+      }
+      if (HasFoo) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo);
+      }
+      if (_extensions != null) {
+        size += _extensions.CalculateSize();
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(FooOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.HasIntOpt) {
+        IntOpt = other.IntOpt;
+      }
+      if (other.HasFoo) {
+        Foo = other.Foo;
+      }
+      pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            }
+            break;
+          case 8: {
+            IntOpt = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Foo = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            IntOpt = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Foo = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+    public TValue GetExtension<TValue>(pb::Extension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.Get(ref _extensions, extension);
+    }
+    public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.Get(ref _extensions, extension);
+    }
+    public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
+    }
+    public void SetExtension<TValue>(pb::Extension<FooOptions, TValue> extension, TValue value) {
+      pb::ExtensionSet.Set(ref _extensions, extension, value);
+    }
+    public bool HasExtension<TValue>(pb::Extension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.Has(ref _extensions, extension);
+    }
+    public void ClearExtension<TValue>(pb::Extension<FooOptions, TValue> extension) {
+      pb::ExtensionSet.Clear(ref _extensions, extension);
+    }
+    public void ClearExtension<TValue>(pb::RepeatedExtension<FooOptions, TValue> extension) {
+      pb::ExtensionSet.Clear(ref _extensions, extension);
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
index 90b3384..58e866e 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
@@ -179,23 +179,31 @@
   /// Each wrapper type is included separately, as languages
   /// map handle different wrappers in different ways.
   /// </summary>
-  public sealed partial class TestWellKnownTypes : pb::IMessage<TestWellKnownTypes> {
+  public sealed partial class TestWellKnownTypes : pb::IMessage<TestWellKnownTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<TestWellKnownTypes> _parser = new pb::MessageParser<TestWellKnownTypes>(() => new TestWellKnownTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<TestWellKnownTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestWellKnownTypes() {
       OnConstruction();
     }
@@ -203,6 +211,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestWellKnownTypes(TestWellKnownTypes other) : this() {
       anyField_ = other.anyField_ != null ? other.anyField_.Clone() : null;
       apiField_ = other.apiField_ != null ? other.apiField_.Clone() : null;
@@ -227,6 +236,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public TestWellKnownTypes Clone() {
       return new TestWellKnownTypes(this);
     }
@@ -235,6 +245,7 @@
     public const int AnyFieldFieldNumber = 1;
     private global::Google.Protobuf.WellKnownTypes.Any anyField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Any AnyField {
       get { return anyField_; }
       set {
@@ -246,6 +257,7 @@
     public const int ApiFieldFieldNumber = 2;
     private global::Google.Protobuf.WellKnownTypes.Api apiField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Api ApiField {
       get { return apiField_; }
       set {
@@ -257,6 +269,7 @@
     public const int DurationFieldFieldNumber = 3;
     private global::Google.Protobuf.WellKnownTypes.Duration durationField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Duration DurationField {
       get { return durationField_; }
       set {
@@ -268,6 +281,7 @@
     public const int EmptyFieldFieldNumber = 4;
     private global::Google.Protobuf.WellKnownTypes.Empty emptyField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Empty EmptyField {
       get { return emptyField_; }
       set {
@@ -279,6 +293,7 @@
     public const int FieldMaskFieldFieldNumber = 5;
     private global::Google.Protobuf.WellKnownTypes.FieldMask fieldMaskField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.FieldMask FieldMaskField {
       get { return fieldMaskField_; }
       set {
@@ -290,6 +305,7 @@
     public const int SourceContextFieldFieldNumber = 6;
     private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContextField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContextField {
       get { return sourceContextField_; }
       set {
@@ -301,6 +317,7 @@
     public const int StructFieldFieldNumber = 7;
     private global::Google.Protobuf.WellKnownTypes.Struct structField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Struct StructField {
       get { return structField_; }
       set {
@@ -312,6 +329,7 @@
     public const int TimestampFieldFieldNumber = 8;
     private global::Google.Protobuf.WellKnownTypes.Timestamp timestampField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Timestamp TimestampField {
       get { return timestampField_; }
       set {
@@ -323,6 +341,7 @@
     public const int TypeFieldFieldNumber = 9;
     private global::Google.Protobuf.WellKnownTypes.Type typeField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Type TypeField {
       get { return typeField_; }
       set {
@@ -335,6 +354,7 @@
     private static readonly pb::FieldCodec<double?> _single_doubleField_codec = pb::FieldCodec.ForStructWrapper<double>(82);
     private double? doubleField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField {
       get { return doubleField_; }
       set {
@@ -348,6 +368,7 @@
     private static readonly pb::FieldCodec<float?> _single_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
     private float? floatField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float? FloatField {
       get { return floatField_; }
       set {
@@ -361,6 +382,7 @@
     private static readonly pb::FieldCodec<long?> _single_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
     private long? int64Field_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field {
       get { return int64Field_; }
       set {
@@ -374,6 +396,7 @@
     private static readonly pb::FieldCodec<ulong?> _single_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
     private ulong? uint64Field_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong? Uint64Field {
       get { return uint64Field_; }
       set {
@@ -387,6 +410,7 @@
     private static readonly pb::FieldCodec<int?> _single_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
     private int? int32Field_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int? Int32Field {
       get { return int32Field_; }
       set {
@@ -400,6 +424,7 @@
     private static readonly pb::FieldCodec<uint?> _single_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
     private uint? uint32Field_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint? Uint32Field {
       get { return uint32Field_; }
       set {
@@ -413,6 +438,7 @@
     private static readonly pb::FieldCodec<bool?> _single_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
     private bool? boolField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool? BoolField {
       get { return boolField_; }
       set {
@@ -426,6 +452,7 @@
     private static readonly pb::FieldCodec<string> _single_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
     private string stringField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField {
       get { return stringField_; }
       set {
@@ -439,6 +466,7 @@
     private static readonly pb::FieldCodec<pb::ByteString> _single_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
     private pb::ByteString bytesField_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString BytesField {
       get { return bytesField_; }
       set {
@@ -454,6 +482,7 @@
     /// Part of struct, but useful to be able to test separately
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Value ValueField {
       get { return valueField_; }
       set {
@@ -462,11 +491,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as TestWellKnownTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(TestWellKnownTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -497,6 +528,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (anyField_ != null) hash ^= AnyField.GetHashCode();
@@ -525,12 +557,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (anyField_ != null) {
         output.WriteRawTag(10);
         output.WriteMessage(AnyField);
@@ -601,9 +638,88 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (anyField_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(AnyField);
+      }
+      if (apiField_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(ApiField);
+      }
+      if (durationField_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(DurationField);
+      }
+      if (emptyField_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(EmptyField);
+      }
+      if (fieldMaskField_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(FieldMaskField);
+      }
+      if (sourceContextField_ != null) {
+        output.WriteRawTag(50);
+        output.WriteMessage(SourceContextField);
+      }
+      if (structField_ != null) {
+        output.WriteRawTag(58);
+        output.WriteMessage(StructField);
+      }
+      if (timestampField_ != null) {
+        output.WriteRawTag(66);
+        output.WriteMessage(TimestampField);
+      }
+      if (typeField_ != null) {
+        output.WriteRawTag(74);
+        output.WriteMessage(TypeField);
+      }
+      if (doubleField_ != null) {
+        _single_doubleField_codec.WriteTagAndValue(ref output, DoubleField);
+      }
+      if (floatField_ != null) {
+        _single_floatField_codec.WriteTagAndValue(ref output, FloatField);
+      }
+      if (int64Field_ != null) {
+        _single_int64Field_codec.WriteTagAndValue(ref output, Int64Field);
+      }
+      if (uint64Field_ != null) {
+        _single_uint64Field_codec.WriteTagAndValue(ref output, Uint64Field);
+      }
+      if (int32Field_ != null) {
+        _single_int32Field_codec.WriteTagAndValue(ref output, Int32Field);
+      }
+      if (uint32Field_ != null) {
+        _single_uint32Field_codec.WriteTagAndValue(ref output, Uint32Field);
+      }
+      if (boolField_ != null) {
+        _single_boolField_codec.WriteTagAndValue(ref output, BoolField);
+      }
+      if (stringField_ != null) {
+        _single_stringField_codec.WriteTagAndValue(ref output, StringField);
+      }
+      if (bytesField_ != null) {
+        _single_bytesField_codec.WriteTagAndValue(ref output, BytesField);
+      }
+      if (valueField_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(ValueField);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (anyField_ != null) {
@@ -670,6 +786,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(TestWellKnownTypes other) {
       if (other == null) {
         return;
@@ -783,7 +900,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -925,30 +1046,187 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            if (anyField_ == null) {
+              AnyField = new global::Google.Protobuf.WellKnownTypes.Any();
+            }
+            input.ReadMessage(AnyField);
+            break;
+          }
+          case 18: {
+            if (apiField_ == null) {
+              ApiField = new global::Google.Protobuf.WellKnownTypes.Api();
+            }
+            input.ReadMessage(ApiField);
+            break;
+          }
+          case 26: {
+            if (durationField_ == null) {
+              DurationField = new global::Google.Protobuf.WellKnownTypes.Duration();
+            }
+            input.ReadMessage(DurationField);
+            break;
+          }
+          case 34: {
+            if (emptyField_ == null) {
+              EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty();
+            }
+            input.ReadMessage(EmptyField);
+            break;
+          }
+          case 42: {
+            if (fieldMaskField_ == null) {
+              FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            }
+            input.ReadMessage(FieldMaskField);
+            break;
+          }
+          case 50: {
+            if (sourceContextField_ == null) {
+              SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(SourceContextField);
+            break;
+          }
+          case 58: {
+            if (structField_ == null) {
+              StructField = new global::Google.Protobuf.WellKnownTypes.Struct();
+            }
+            input.ReadMessage(StructField);
+            break;
+          }
+          case 66: {
+            if (timestampField_ == null) {
+              TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            }
+            input.ReadMessage(TimestampField);
+            break;
+          }
+          case 74: {
+            if (typeField_ == null) {
+              TypeField = new global::Google.Protobuf.WellKnownTypes.Type();
+            }
+            input.ReadMessage(TypeField);
+            break;
+          }
+          case 82: {
+            double? value = _single_doubleField_codec.Read(ref input);
+            if (doubleField_ == null || value != 0D) {
+              DoubleField = value;
+            }
+            break;
+          }
+          case 90: {
+            float? value = _single_floatField_codec.Read(ref input);
+            if (floatField_ == null || value != 0F) {
+              FloatField = value;
+            }
+            break;
+          }
+          case 98: {
+            long? value = _single_int64Field_codec.Read(ref input);
+            if (int64Field_ == null || value != 0L) {
+              Int64Field = value;
+            }
+            break;
+          }
+          case 106: {
+            ulong? value = _single_uint64Field_codec.Read(ref input);
+            if (uint64Field_ == null || value != 0UL) {
+              Uint64Field = value;
+            }
+            break;
+          }
+          case 114: {
+            int? value = _single_int32Field_codec.Read(ref input);
+            if (int32Field_ == null || value != 0) {
+              Int32Field = value;
+            }
+            break;
+          }
+          case 122: {
+            uint? value = _single_uint32Field_codec.Read(ref input);
+            if (uint32Field_ == null || value != 0) {
+              Uint32Field = value;
+            }
+            break;
+          }
+          case 130: {
+            bool? value = _single_boolField_codec.Read(ref input);
+            if (boolField_ == null || value != false) {
+              BoolField = value;
+            }
+            break;
+          }
+          case 138: {
+            string value = _single_stringField_codec.Read(ref input);
+            if (stringField_ == null || value != "") {
+              StringField = value;
+            }
+            break;
+          }
+          case 146: {
+            pb::ByteString value = _single_bytesField_codec.Read(ref input);
+            if (bytesField_ == null || value != pb::ByteString.Empty) {
+              BytesField = value;
+            }
+            break;
+          }
+          case 154: {
+            if (valueField_ == null) {
+              ValueField = new global::Google.Protobuf.WellKnownTypes.Value();
+            }
+            input.ReadMessage(ValueField);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// A repeated field for each well-known type.
   /// </summary>
-  public sealed partial class RepeatedWellKnownTypes : pb::IMessage<RepeatedWellKnownTypes> {
+  public sealed partial class RepeatedWellKnownTypes : pb::IMessage<RepeatedWellKnownTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<RepeatedWellKnownTypes> _parser = new pb::MessageParser<RepeatedWellKnownTypes>(() => new RepeatedWellKnownTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<RepeatedWellKnownTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public RepeatedWellKnownTypes() {
       OnConstruction();
     }
@@ -956,6 +1234,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public RepeatedWellKnownTypes(RepeatedWellKnownTypes other) : this() {
       anyField_ = other.anyField_.Clone();
       apiField_ = other.apiField_.Clone();
@@ -979,6 +1258,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public RepeatedWellKnownTypes Clone() {
       return new RepeatedWellKnownTypes(this);
     }
@@ -989,6 +1269,7 @@
         = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.WellKnownTypes.Any.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> anyField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> AnyField {
       get { return anyField_; }
     }
@@ -999,6 +1280,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api> apiField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api> ApiField {
       get { return apiField_; }
     }
@@ -1009,6 +1291,7 @@
         = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Duration.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> durationField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> DurationField {
       get { return durationField_; }
     }
@@ -1019,6 +1302,7 @@
         = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.WellKnownTypes.Empty.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty> emptyField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty> EmptyField {
       get { return emptyField_; }
     }
@@ -1029,6 +1313,7 @@
         = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> fieldMaskField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> FieldMaskField {
       get { return fieldMaskField_; }
     }
@@ -1039,6 +1324,7 @@
         = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext> sourceContextField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext> SourceContextField {
       get { return sourceContextField_; }
     }
@@ -1049,6 +1335,7 @@
         = pb::FieldCodec.ForMessage(58, global::Google.Protobuf.WellKnownTypes.Struct.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> structField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> StructField {
       get { return structField_; }
     }
@@ -1059,6 +1346,7 @@
         = pb::FieldCodec.ForMessage(66, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> timestampField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> TimestampField {
       get { return timestampField_; }
     }
@@ -1069,6 +1357,7 @@
         = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.WellKnownTypes.Type.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type> typeField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type> TypeField {
       get { return typeField_; }
     }
@@ -1082,6 +1371,7 @@
     /// These don't actually make a lot of sense, but they're not prohibited...
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<double?> DoubleField {
       get { return doubleField_; }
     }
@@ -1092,6 +1382,7 @@
         = pb::FieldCodec.ForStructWrapper<float>(90);
     private readonly pbc::RepeatedField<float?> floatField_ = new pbc::RepeatedField<float?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<float?> FloatField {
       get { return floatField_; }
     }
@@ -1102,6 +1393,7 @@
         = pb::FieldCodec.ForStructWrapper<long>(98);
     private readonly pbc::RepeatedField<long?> int64Field_ = new pbc::RepeatedField<long?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<long?> Int64Field {
       get { return int64Field_; }
     }
@@ -1112,6 +1404,7 @@
         = pb::FieldCodec.ForStructWrapper<ulong>(106);
     private readonly pbc::RepeatedField<ulong?> uint64Field_ = new pbc::RepeatedField<ulong?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<ulong?> Uint64Field {
       get { return uint64Field_; }
     }
@@ -1122,6 +1415,7 @@
         = pb::FieldCodec.ForStructWrapper<int>(114);
     private readonly pbc::RepeatedField<int?> int32Field_ = new pbc::RepeatedField<int?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int?> Int32Field {
       get { return int32Field_; }
     }
@@ -1132,6 +1426,7 @@
         = pb::FieldCodec.ForStructWrapper<uint>(122);
     private readonly pbc::RepeatedField<uint?> uint32Field_ = new pbc::RepeatedField<uint?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<uint?> Uint32Field {
       get { return uint32Field_; }
     }
@@ -1142,6 +1437,7 @@
         = pb::FieldCodec.ForStructWrapper<bool>(130);
     private readonly pbc::RepeatedField<bool?> boolField_ = new pbc::RepeatedField<bool?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<bool?> BoolField {
       get { return boolField_; }
     }
@@ -1152,6 +1448,7 @@
         = pb::FieldCodec.ForClassWrapper<string>(138);
     private readonly pbc::RepeatedField<string> stringField_ = new pbc::RepeatedField<string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> StringField {
       get { return stringField_; }
     }
@@ -1162,16 +1459,19 @@
         = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
     private readonly pbc::RepeatedField<pb::ByteString> bytesField_ = new pbc::RepeatedField<pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<pb::ByteString> BytesField {
       get { return bytesField_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as RepeatedWellKnownTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(RepeatedWellKnownTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1201,6 +1501,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= anyField_.GetHashCode();
@@ -1228,12 +1529,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       anyField_.WriteTo(output, _repeated_anyField_codec);
       apiField_.WriteTo(output, _repeated_apiField_codec);
       durationField_.WriteTo(output, _repeated_durationField_codec);
@@ -1255,9 +1561,39 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      anyField_.WriteTo(ref output, _repeated_anyField_codec);
+      apiField_.WriteTo(ref output, _repeated_apiField_codec);
+      durationField_.WriteTo(ref output, _repeated_durationField_codec);
+      emptyField_.WriteTo(ref output, _repeated_emptyField_codec);
+      fieldMaskField_.WriteTo(ref output, _repeated_fieldMaskField_codec);
+      sourceContextField_.WriteTo(ref output, _repeated_sourceContextField_codec);
+      structField_.WriteTo(ref output, _repeated_structField_codec);
+      timestampField_.WriteTo(ref output, _repeated_timestampField_codec);
+      typeField_.WriteTo(ref output, _repeated_typeField_codec);
+      doubleField_.WriteTo(ref output, _repeated_doubleField_codec);
+      floatField_.WriteTo(ref output, _repeated_floatField_codec);
+      int64Field_.WriteTo(ref output, _repeated_int64Field_codec);
+      uint64Field_.WriteTo(ref output, _repeated_uint64Field_codec);
+      int32Field_.WriteTo(ref output, _repeated_int32Field_codec);
+      uint32Field_.WriteTo(ref output, _repeated_uint32Field_codec);
+      boolField_.WriteTo(ref output, _repeated_boolField_codec);
+      stringField_.WriteTo(ref output, _repeated_stringField_codec);
+      bytesField_.WriteTo(ref output, _repeated_bytesField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += anyField_.CalculateSize(_repeated_anyField_codec);
@@ -1285,6 +1621,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(RepeatedWellKnownTypes other) {
       if (other == null) {
         return;
@@ -1311,7 +1648,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1392,27 +1733,123 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            anyField_.AddEntriesFrom(ref input, _repeated_anyField_codec);
+            break;
+          }
+          case 18: {
+            apiField_.AddEntriesFrom(ref input, _repeated_apiField_codec);
+            break;
+          }
+          case 26: {
+            durationField_.AddEntriesFrom(ref input, _repeated_durationField_codec);
+            break;
+          }
+          case 34: {
+            emptyField_.AddEntriesFrom(ref input, _repeated_emptyField_codec);
+            break;
+          }
+          case 42: {
+            fieldMaskField_.AddEntriesFrom(ref input, _repeated_fieldMaskField_codec);
+            break;
+          }
+          case 50: {
+            sourceContextField_.AddEntriesFrom(ref input, _repeated_sourceContextField_codec);
+            break;
+          }
+          case 58: {
+            structField_.AddEntriesFrom(ref input, _repeated_structField_codec);
+            break;
+          }
+          case 66: {
+            timestampField_.AddEntriesFrom(ref input, _repeated_timestampField_codec);
+            break;
+          }
+          case 74: {
+            typeField_.AddEntriesFrom(ref input, _repeated_typeField_codec);
+            break;
+          }
+          case 82: {
+            doubleField_.AddEntriesFrom(ref input, _repeated_doubleField_codec);
+            break;
+          }
+          case 90: {
+            floatField_.AddEntriesFrom(ref input, _repeated_floatField_codec);
+            break;
+          }
+          case 98: {
+            int64Field_.AddEntriesFrom(ref input, _repeated_int64Field_codec);
+            break;
+          }
+          case 106: {
+            uint64Field_.AddEntriesFrom(ref input, _repeated_uint64Field_codec);
+            break;
+          }
+          case 114: {
+            int32Field_.AddEntriesFrom(ref input, _repeated_int32Field_codec);
+            break;
+          }
+          case 122: {
+            uint32Field_.AddEntriesFrom(ref input, _repeated_uint32Field_codec);
+            break;
+          }
+          case 130: {
+            boolField_.AddEntriesFrom(ref input, _repeated_boolField_codec);
+            break;
+          }
+          case 138: {
+            stringField_.AddEntriesFrom(ref input, _repeated_stringField_codec);
+            break;
+          }
+          case 146: {
+            bytesField_.AddEntriesFrom(ref input, _repeated_bytesField_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
-  public sealed partial class OneofWellKnownTypes : pb::IMessage<OneofWellKnownTypes> {
+  public sealed partial class OneofWellKnownTypes : pb::IMessage<OneofWellKnownTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneofWellKnownTypes> _parser = new pb::MessageParser<OneofWellKnownTypes>(() => new OneofWellKnownTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneofWellKnownTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofWellKnownTypes() {
       OnConstruction();
     }
@@ -1420,6 +1857,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofWellKnownTypes(OneofWellKnownTypes other) : this() {
       switch (other.OneofFieldCase) {
         case OneofFieldOneofCase.AnyField:
@@ -1482,6 +1920,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofWellKnownTypes Clone() {
       return new OneofWellKnownTypes(this);
     }
@@ -1489,6 +1928,7 @@
     /// <summary>Field number for the "any_field" field.</summary>
     public const int AnyFieldFieldNumber = 1;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Any AnyField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.AnyField ? (global::Google.Protobuf.WellKnownTypes.Any) oneofField_ : null; }
       set {
@@ -1500,6 +1940,7 @@
     /// <summary>Field number for the "api_field" field.</summary>
     public const int ApiFieldFieldNumber = 2;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Api ApiField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.ApiField ? (global::Google.Protobuf.WellKnownTypes.Api) oneofField_ : null; }
       set {
@@ -1511,6 +1952,7 @@
     /// <summary>Field number for the "duration_field" field.</summary>
     public const int DurationFieldFieldNumber = 3;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Duration DurationField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.DurationField ? (global::Google.Protobuf.WellKnownTypes.Duration) oneofField_ : null; }
       set {
@@ -1522,6 +1964,7 @@
     /// <summary>Field number for the "empty_field" field.</summary>
     public const int EmptyFieldFieldNumber = 4;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Empty EmptyField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.EmptyField ? (global::Google.Protobuf.WellKnownTypes.Empty) oneofField_ : null; }
       set {
@@ -1533,6 +1976,7 @@
     /// <summary>Field number for the "field_mask_field" field.</summary>
     public const int FieldMaskFieldFieldNumber = 5;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.FieldMask FieldMaskField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField ? (global::Google.Protobuf.WellKnownTypes.FieldMask) oneofField_ : null; }
       set {
@@ -1544,6 +1988,7 @@
     /// <summary>Field number for the "source_context_field" field.</summary>
     public const int SourceContextFieldFieldNumber = 6;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContextField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.SourceContextField ? (global::Google.Protobuf.WellKnownTypes.SourceContext) oneofField_ : null; }
       set {
@@ -1555,6 +2000,7 @@
     /// <summary>Field number for the "struct_field" field.</summary>
     public const int StructFieldFieldNumber = 7;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Struct StructField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.StructField ? (global::Google.Protobuf.WellKnownTypes.Struct) oneofField_ : null; }
       set {
@@ -1566,6 +2012,7 @@
     /// <summary>Field number for the "timestamp_field" field.</summary>
     public const int TimestampFieldFieldNumber = 8;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Timestamp TimestampField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.TimestampField ? (global::Google.Protobuf.WellKnownTypes.Timestamp) oneofField_ : null; }
       set {
@@ -1577,6 +2024,7 @@
     /// <summary>Field number for the "type_field" field.</summary>
     public const int TypeFieldFieldNumber = 9;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Type TypeField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.TypeField ? (global::Google.Protobuf.WellKnownTypes.Type) oneofField_ : null; }
       set {
@@ -1589,6 +2037,7 @@
     public const int DoubleFieldFieldNumber = 10;
     private static readonly pb::FieldCodec<double?> _oneof_doubleField_codec = pb::FieldCodec.ForStructWrapper<double>(82);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double? DoubleField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.DoubleField ? (double?) oneofField_ : (double?) null; }
       set {
@@ -1601,6 +2050,7 @@
     public const int FloatFieldFieldNumber = 11;
     private static readonly pb::FieldCodec<float?> _oneof_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float? FloatField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.FloatField ? (float?) oneofField_ : (float?) null; }
       set {
@@ -1613,6 +2063,7 @@
     public const int Int64FieldFieldNumber = 12;
     private static readonly pb::FieldCodec<long?> _oneof_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long? Int64Field {
       get { return oneofFieldCase_ == OneofFieldOneofCase.Int64Field ? (long?) oneofField_ : (long?) null; }
       set {
@@ -1625,6 +2076,7 @@
     public const int Uint64FieldFieldNumber = 13;
     private static readonly pb::FieldCodec<ulong?> _oneof_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong? Uint64Field {
       get { return oneofFieldCase_ == OneofFieldOneofCase.Uint64Field ? (ulong?) oneofField_ : (ulong?) null; }
       set {
@@ -1637,6 +2089,7 @@
     public const int Int32FieldFieldNumber = 14;
     private static readonly pb::FieldCodec<int?> _oneof_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int? Int32Field {
       get { return oneofFieldCase_ == OneofFieldOneofCase.Int32Field ? (int?) oneofField_ : (int?) null; }
       set {
@@ -1649,6 +2102,7 @@
     public const int Uint32FieldFieldNumber = 15;
     private static readonly pb::FieldCodec<uint?> _oneof_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint? Uint32Field {
       get { return oneofFieldCase_ == OneofFieldOneofCase.Uint32Field ? (uint?) oneofField_ : (uint?) null; }
       set {
@@ -1661,6 +2115,7 @@
     public const int BoolFieldFieldNumber = 16;
     private static readonly pb::FieldCodec<bool?> _oneof_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool? BoolField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.BoolField ? (bool?) oneofField_ : (bool?) null; }
       set {
@@ -1673,6 +2128,7 @@
     public const int StringFieldFieldNumber = 17;
     private static readonly pb::FieldCodec<string> _oneof_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.StringField ? (string) oneofField_ : (string) null; }
       set {
@@ -1685,6 +2141,7 @@
     public const int BytesFieldFieldNumber = 18;
     private static readonly pb::FieldCodec<pb::ByteString> _oneof_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString BytesField {
       get { return oneofFieldCase_ == OneofFieldOneofCase.BytesField ? (pb::ByteString) oneofField_ : (pb::ByteString) null; }
       set {
@@ -1718,22 +2175,26 @@
     }
     private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofFieldOneofCase OneofFieldCase {
       get { return oneofFieldCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofField() {
       oneofFieldCase_ = OneofFieldOneofCase.None;
       oneofField_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneofWellKnownTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneofWellKnownTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1764,6 +2225,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) hash ^= AnyField.GetHashCode();
@@ -1792,12 +2254,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
         output.WriteRawTag(10);
         output.WriteMessage(AnyField);
@@ -1864,9 +2331,84 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+        output.WriteRawTag(10);
+        output.WriteMessage(AnyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+        output.WriteRawTag(18);
+        output.WriteMessage(ApiField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+        output.WriteRawTag(26);
+        output.WriteMessage(DurationField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+        output.WriteRawTag(34);
+        output.WriteMessage(EmptyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+        output.WriteRawTag(42);
+        output.WriteMessage(FieldMaskField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+        output.WriteRawTag(50);
+        output.WriteMessage(SourceContextField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+        output.WriteRawTag(58);
+        output.WriteMessage(StructField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+        output.WriteRawTag(66);
+        output.WriteMessage(TimestampField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+        output.WriteRawTag(74);
+        output.WriteMessage(TypeField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) {
+        _oneof_doubleField_codec.WriteTagAndValue(ref output, (double?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) {
+        _oneof_floatField_codec.WriteTagAndValue(ref output, (float?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) {
+        _oneof_int64Field_codec.WriteTagAndValue(ref output, (long?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) {
+        _oneof_uint64Field_codec.WriteTagAndValue(ref output, (ulong?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) {
+        _oneof_int32Field_codec.WriteTagAndValue(ref output, (int?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) {
+        _oneof_uint32Field_codec.WriteTagAndValue(ref output, (uint?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) {
+        _oneof_boolField_codec.WriteTagAndValue(ref output, (bool?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StringField) {
+        _oneof_stringField_codec.WriteTagAndValue(ref output, (string) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
+        _oneof_bytesField_codec.WriteTagAndValue(ref output, (pb::ByteString) oneofField_);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
@@ -1930,6 +2472,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneofWellKnownTypes other) {
       if (other == null) {
         return;
@@ -2022,7 +2565,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2148,8 +2695,141 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any();
+            if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+              subBuilder.MergeFrom(AnyField);
+            }
+            input.ReadMessage(subBuilder);
+            AnyField = subBuilder;
+            break;
+          }
+          case 18: {
+            global::Google.Protobuf.WellKnownTypes.Api subBuilder = new global::Google.Protobuf.WellKnownTypes.Api();
+            if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+              subBuilder.MergeFrom(ApiField);
+            }
+            input.ReadMessage(subBuilder);
+            ApiField = subBuilder;
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.WellKnownTypes.Duration subBuilder = new global::Google.Protobuf.WellKnownTypes.Duration();
+            if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+              subBuilder.MergeFrom(DurationField);
+            }
+            input.ReadMessage(subBuilder);
+            DurationField = subBuilder;
+            break;
+          }
+          case 34: {
+            global::Google.Protobuf.WellKnownTypes.Empty subBuilder = new global::Google.Protobuf.WellKnownTypes.Empty();
+            if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+              subBuilder.MergeFrom(EmptyField);
+            }
+            input.ReadMessage(subBuilder);
+            EmptyField = subBuilder;
+            break;
+          }
+          case 42: {
+            global::Google.Protobuf.WellKnownTypes.FieldMask subBuilder = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+              subBuilder.MergeFrom(FieldMaskField);
+            }
+            input.ReadMessage(subBuilder);
+            FieldMaskField = subBuilder;
+            break;
+          }
+          case 50: {
+            global::Google.Protobuf.WellKnownTypes.SourceContext subBuilder = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+              subBuilder.MergeFrom(SourceContextField);
+            }
+            input.ReadMessage(subBuilder);
+            SourceContextField = subBuilder;
+            break;
+          }
+          case 58: {
+            global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct();
+            if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+              subBuilder.MergeFrom(StructField);
+            }
+            input.ReadMessage(subBuilder);
+            StructField = subBuilder;
+            break;
+          }
+          case 66: {
+            global::Google.Protobuf.WellKnownTypes.Timestamp subBuilder = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+              subBuilder.MergeFrom(TimestampField);
+            }
+            input.ReadMessage(subBuilder);
+            TimestampField = subBuilder;
+            break;
+          }
+          case 74: {
+            global::Google.Protobuf.WellKnownTypes.Type subBuilder = new global::Google.Protobuf.WellKnownTypes.Type();
+            if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+              subBuilder.MergeFrom(TypeField);
+            }
+            input.ReadMessage(subBuilder);
+            TypeField = subBuilder;
+            break;
+          }
+          case 82: {
+            DoubleField = _oneof_doubleField_codec.Read(ref input);
+            break;
+          }
+          case 90: {
+            FloatField = _oneof_floatField_codec.Read(ref input);
+            break;
+          }
+          case 98: {
+            Int64Field = _oneof_int64Field_codec.Read(ref input);
+            break;
+          }
+          case 106: {
+            Uint64Field = _oneof_uint64Field_codec.Read(ref input);
+            break;
+          }
+          case 114: {
+            Int32Field = _oneof_int32Field_codec.Read(ref input);
+            break;
+          }
+          case 122: {
+            Uint32Field = _oneof_uint32Field_codec.Read(ref input);
+            break;
+          }
+          case 130: {
+            BoolField = _oneof_boolField_codec.Read(ref input);
+            break;
+          }
+          case 138: {
+            StringField = _oneof_stringField_codec.Read(ref input);
+            break;
+          }
+          case 146: {
+            BytesField = _oneof_bytesField_codec.Read(ref input);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -2157,23 +2837,31 @@
   /// need to worry about the value part of the map being the
   /// well-known types, as messages can't be map keys.
   /// </summary>
-  public sealed partial class MapWellKnownTypes : pb::IMessage<MapWellKnownTypes> {
+  public sealed partial class MapWellKnownTypes : pb::IMessage<MapWellKnownTypes>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MapWellKnownTypes> _parser = new pb::MessageParser<MapWellKnownTypes>(() => new MapWellKnownTypes());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MapWellKnownTypes> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MapWellKnownTypes() {
       OnConstruction();
     }
@@ -2181,6 +2869,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MapWellKnownTypes(MapWellKnownTypes other) : this() {
       anyField_ = other.anyField_.Clone();
       apiField_ = other.apiField_.Clone();
@@ -2204,6 +2893,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MapWellKnownTypes Clone() {
       return new MapWellKnownTypes(this);
     }
@@ -2214,6 +2904,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Any.Parser), 10);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any> anyField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any> AnyField {
       get { return anyField_; }
     }
@@ -2224,6 +2915,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser), 18);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api> apiField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api> ApiField {
       get { return apiField_; }
     }
@@ -2234,6 +2926,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Duration.Parser), 26);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration> durationField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration> DurationField {
       get { return durationField_; }
     }
@@ -2244,6 +2937,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Empty.Parser), 34);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty> emptyField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty> EmptyField {
       get { return emptyField_; }
     }
@@ -2254,6 +2948,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser), 42);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask> fieldMaskField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask> FieldMaskField {
       get { return fieldMaskField_; }
     }
@@ -2264,6 +2959,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser), 50);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext> sourceContextField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext> SourceContextField {
       get { return sourceContextField_; }
     }
@@ -2274,6 +2970,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Struct.Parser), 58);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct> structField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct> StructField {
       get { return structField_; }
     }
@@ -2284,6 +2981,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser), 66);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp> timestampField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp> TimestampField {
       get { return timestampField_; }
     }
@@ -2294,6 +2992,7 @@
         = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Type.Parser), 74);
     private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type> typeField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type> TypeField {
       get { return typeField_; }
     }
@@ -2304,6 +3003,7 @@
         = new pbc::MapField<int, double?>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper<double>(18), 82);
     private readonly pbc::MapField<int, double?> doubleField_ = new pbc::MapField<int, double?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, double?> DoubleField {
       get { return doubleField_; }
     }
@@ -2314,6 +3014,7 @@
         = new pbc::MapField<int, float?>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper<float>(18), 90);
     private readonly pbc::MapField<int, float?> floatField_ = new pbc::MapField<int, float?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, float?> FloatField {
       get { return floatField_; }
     }
@@ -2324,6 +3025,7 @@
         = new pbc::MapField<int, long?>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper<long>(18), 98);
     private readonly pbc::MapField<int, long?> int64Field_ = new pbc::MapField<int, long?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, long?> Int64Field {
       get { return int64Field_; }
     }
@@ -2334,6 +3036,7 @@
         = new pbc::MapField<int, ulong?>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper<ulong>(18), 106);
     private readonly pbc::MapField<int, ulong?> uint64Field_ = new pbc::MapField<int, ulong?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, ulong?> Uint64Field {
       get { return uint64Field_; }
     }
@@ -2344,6 +3047,7 @@
         = new pbc::MapField<int, int?>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper<int>(18), 114);
     private readonly pbc::MapField<int, int?> int32Field_ = new pbc::MapField<int, int?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, int?> Int32Field {
       get { return int32Field_; }
     }
@@ -2354,6 +3058,7 @@
         = new pbc::MapField<int, uint?>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper<uint>(18), 122);
     private readonly pbc::MapField<int, uint?> uint32Field_ = new pbc::MapField<int, uint?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, uint?> Uint32Field {
       get { return uint32Field_; }
     }
@@ -2364,6 +3069,7 @@
         = new pbc::MapField<int, bool?>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper<bool>(18), 130);
     private readonly pbc::MapField<int, bool?> boolField_ = new pbc::MapField<int, bool?>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, bool?> BoolField {
       get { return boolField_; }
     }
@@ -2374,6 +3080,7 @@
         = new pbc::MapField<int, string>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForClassWrapper<string>(18), 138);
     private readonly pbc::MapField<int, string> stringField_ = new pbc::MapField<int, string>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, string> StringField {
       get { return stringField_; }
     }
@@ -2384,16 +3091,19 @@
         = new pbc::MapField<int, pb::ByteString>.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForClassWrapper<pb::ByteString>(18), 146);
     private readonly pbc::MapField<int, pb::ByteString> bytesField_ = new pbc::MapField<int, pb::ByteString>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<int, pb::ByteString> BytesField {
       get { return bytesField_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MapWellKnownTypes);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MapWellKnownTypes other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2423,6 +3133,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= AnyField.GetHashCode();
@@ -2450,12 +3161,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       anyField_.WriteTo(output, _map_anyField_codec);
       apiField_.WriteTo(output, _map_apiField_codec);
       durationField_.WriteTo(output, _map_durationField_codec);
@@ -2477,9 +3193,39 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      anyField_.WriteTo(ref output, _map_anyField_codec);
+      apiField_.WriteTo(ref output, _map_apiField_codec);
+      durationField_.WriteTo(ref output, _map_durationField_codec);
+      emptyField_.WriteTo(ref output, _map_emptyField_codec);
+      fieldMaskField_.WriteTo(ref output, _map_fieldMaskField_codec);
+      sourceContextField_.WriteTo(ref output, _map_sourceContextField_codec);
+      structField_.WriteTo(ref output, _map_structField_codec);
+      timestampField_.WriteTo(ref output, _map_timestampField_codec);
+      typeField_.WriteTo(ref output, _map_typeField_codec);
+      doubleField_.WriteTo(ref output, _map_doubleField_codec);
+      floatField_.WriteTo(ref output, _map_floatField_codec);
+      int64Field_.WriteTo(ref output, _map_int64Field_codec);
+      uint64Field_.WriteTo(ref output, _map_uint64Field_codec);
+      int32Field_.WriteTo(ref output, _map_int32Field_codec);
+      uint32Field_.WriteTo(ref output, _map_uint32Field_codec);
+      boolField_.WriteTo(ref output, _map_boolField_codec);
+      stringField_.WriteTo(ref output, _map_stringField_codec);
+      bytesField_.WriteTo(ref output, _map_bytesField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += anyField_.CalculateSize(_map_anyField_codec);
@@ -2507,6 +3253,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MapWellKnownTypes other) {
       if (other == null) {
         return;
@@ -2533,7 +3280,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2614,8 +3365,96 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            anyField_.AddEntriesFrom(ref input, _map_anyField_codec);
+            break;
+          }
+          case 18: {
+            apiField_.AddEntriesFrom(ref input, _map_apiField_codec);
+            break;
+          }
+          case 26: {
+            durationField_.AddEntriesFrom(ref input, _map_durationField_codec);
+            break;
+          }
+          case 34: {
+            emptyField_.AddEntriesFrom(ref input, _map_emptyField_codec);
+            break;
+          }
+          case 42: {
+            fieldMaskField_.AddEntriesFrom(ref input, _map_fieldMaskField_codec);
+            break;
+          }
+          case 50: {
+            sourceContextField_.AddEntriesFrom(ref input, _map_sourceContextField_codec);
+            break;
+          }
+          case 58: {
+            structField_.AddEntriesFrom(ref input, _map_structField_codec);
+            break;
+          }
+          case 66: {
+            timestampField_.AddEntriesFrom(ref input, _map_timestampField_codec);
+            break;
+          }
+          case 74: {
+            typeField_.AddEntriesFrom(ref input, _map_typeField_codec);
+            break;
+          }
+          case 82: {
+            doubleField_.AddEntriesFrom(ref input, _map_doubleField_codec);
+            break;
+          }
+          case 90: {
+            floatField_.AddEntriesFrom(ref input, _map_floatField_codec);
+            break;
+          }
+          case 98: {
+            int64Field_.AddEntriesFrom(ref input, _map_int64Field_codec);
+            break;
+          }
+          case 106: {
+            uint64Field_.AddEntriesFrom(ref input, _map_uint64Field_codec);
+            break;
+          }
+          case 114: {
+            int32Field_.AddEntriesFrom(ref input, _map_int32Field_codec);
+            break;
+          }
+          case 122: {
+            uint32Field_.AddEntriesFrom(ref input, _map_uint32Field_codec);
+            break;
+          }
+          case 130: {
+            boolField_.AddEntriesFrom(ref input, _map_boolField_codec);
+            break;
+          }
+          case 138: {
+            stringField_.AddEntriesFrom(ref input, _map_stringField_codec);
+            break;
+          }
+          case 146: {
+            bytesField_.AddEntriesFrom(ref input, _map_bytesField_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs
new file mode 100644
index 0000000..a36a951
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs
@@ -0,0 +1,225 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Diagnostics;
+
+namespace Google.Protobuf.Buffers
+{
+    /// <summary>
+    /// Represents a heap-based, array-backed output sink into which <typeparam name="T"/> data can be written.
+    /// 
+    /// ArrayBufferWriter is originally from corefx, and has been contributed to Protobuf
+    /// https://github.com/dotnet/runtime/blob/071da4c41aa808c949a773b92dca6f88de9d11f3/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs
+    /// </summary>
+    internal sealed class TestArrayBufferWriter<T> : IBufferWriter<T>
+    {
+        private T[] _buffer;
+        private int _index;
+
+        private const int DefaultInitialBufferSize = 256;
+
+        /// <summary>
+        /// Creates an instance of an <see cref="TestArrayBufferWriter{T}"/>, in which data can be written to,
+        /// with the default initial capacity.
+        /// </summary>
+        public TestArrayBufferWriter()
+        {
+            _buffer = new T[0];
+            _index = 0;
+        }
+
+        /// <summary>
+        /// Useful for testing writing to buffer writer with a lot of small segments.
+        /// If set, it limits the max number of bytes by which the buffer grows by at once.
+        /// </summary>
+        public int? MaxGrowBy { get; set; }
+
+        /// <summary>
+        /// Creates an instance of an <see cref="TestArrayBufferWriter{T}"/>, in which data can be written to,
+        /// with an initial capacity specified.
+        /// </summary>
+        /// <param name="initialCapacity">The minimum capacity with which to initialize the underlying buffer.</param>
+        /// <exception cref="ArgumentException">
+        /// Thrown when <paramref name="initialCapacity"/> is not positive (i.e. less than or equal to 0).
+        /// </exception>
+        public TestArrayBufferWriter(int initialCapacity)
+        {
+            if (initialCapacity <= 0)
+                throw new ArgumentException(nameof(initialCapacity));
+
+            _buffer = new T[initialCapacity];
+            _index = 0;
+        }
+
+        /// <summary>
+        /// Returns the data written to the underlying buffer so far, as a <see cref="ReadOnlyMemory{T}"/>.
+        /// </summary>
+        public ReadOnlyMemory<T> WrittenMemory => _buffer.AsMemory(0, _index);
+
+        /// <summary>
+        /// Returns the data written to the underlying buffer so far, as a <see cref="ReadOnlySpan{T}"/>.
+        /// </summary>
+        public ReadOnlySpan<T> WrittenSpan => _buffer.AsSpan(0, _index);
+
+        /// <summary>
+        /// Returns the amount of data written to the underlying buffer so far.
+        /// </summary>
+        public int WrittenCount => _index;
+
+        /// <summary>
+        /// Returns the total amount of space within the underlying buffer.
+        /// </summary>
+        public int Capacity => _buffer.Length;
+
+        /// <summary>
+        /// Returns the amount of space available that can still be written into without forcing the underlying buffer to grow.
+        /// </summary>
+        public int FreeCapacity => _buffer.Length - _index;
+
+        /// <summary>
+        /// Clears the data written to the underlying buffer.
+        /// </summary>
+        /// <remarks>
+        /// You must clear the <see cref="TestArrayBufferWriter{T}"/> before trying to re-use it.
+        /// </remarks>
+        public void Clear()
+        {
+            Debug.Assert(_buffer.Length >= _index);
+            _buffer.AsSpan(0, _index).Clear();
+            _index = 0;
+        }
+
+        /// <summary>
+        /// Notifies <see cref="IBufferWriter{T}"/> that <paramref name="count"/> amount of data was written to the output <see cref="Span{T}"/>/<see cref="Memory{T}"/>
+        /// </summary>
+        /// <exception cref="ArgumentException">
+        /// Thrown when <paramref name="count"/> is negative.
+        /// </exception>
+        /// <exception cref="InvalidOperationException">
+        /// Thrown when attempting to advance past the end of the underlying buffer.
+        /// </exception>
+        /// <remarks>
+        /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer.
+        /// </remarks>
+        public void Advance(int count)
+        {
+            if (count < 0)
+                throw new ArgumentException(nameof(count));
+
+            if (_index > _buffer.Length - count)
+                throw new InvalidOperationException("Advanced past capacity.");
+
+            _index += count;
+        }
+
+        /// <summary>
+        /// Returns a <see cref="Memory{T}"/> to write to that is at least the requested length (specified by <paramref name="sizeHint"/>).
+        /// If no <paramref name="sizeHint"/> is provided (or it's equal to <code>0</code>), some non-empty buffer is returned.
+        /// </summary>
+        /// <exception cref="ArgumentException">
+        /// Thrown when <paramref name="sizeHint"/> is negative.
+        /// </exception>
+        /// <remarks>
+        /// This will never return an empty <see cref="Memory{T}"/>.
+        /// </remarks>
+        /// <remarks>
+        /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer.
+        /// </remarks>
+        /// <remarks>
+        /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer.
+        /// </remarks>
+        public Memory<T> GetMemory(int sizeHint = 0)
+        {
+            CheckAndResizeBuffer(sizeHint);
+            Debug.Assert(_buffer.Length > _index);
+            return _buffer.AsMemory(_index);
+        }
+
+        /// <summary>
+        /// Returns a <see cref="Span{T}"/> to write to that is at least the requested length (specified by <paramref name="sizeHint"/>).
+        /// If no <paramref name="sizeHint"/> is provided (or it's equal to <code>0</code>), some non-empty buffer is returned.
+        /// </summary>
+        /// <exception cref="ArgumentException">
+        /// Thrown when <paramref name="sizeHint"/> is negative.
+        /// </exception>
+        /// <remarks>
+        /// This will never return an empty <see cref="Span{T}"/>.
+        /// </remarks>
+        /// <remarks>
+        /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer.
+        /// </remarks>
+        /// <remarks>
+        /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer.
+        /// </remarks>
+        public Span<T> GetSpan(int sizeHint = 0)
+        {
+            CheckAndResizeBuffer(sizeHint);
+            Debug.Assert(_buffer.Length > _index);
+            return _buffer.AsSpan(_index);
+        }
+
+        private void CheckAndResizeBuffer(int sizeHint)
+        {
+            if (sizeHint < 0)
+                throw new ArgumentException(nameof(sizeHint));
+
+            if (sizeHint == 0)
+            {
+                sizeHint = 1;
+            }
+
+            if (sizeHint > FreeCapacity)
+            {
+                int growBy = Math.Max(sizeHint, _buffer.Length);
+
+                if (_buffer.Length == 0)
+                {
+                    growBy = Math.Max(growBy, DefaultInitialBufferSize);
+                }
+
+                // enable tests that write to small buffer segments
+                if (MaxGrowBy.HasValue && growBy > MaxGrowBy.Value)
+                {
+                    growBy = MaxGrowBy.Value;
+                }
+
+                int newSize = checked(_buffer.Length + growBy);
+
+                Array.Resize(ref _buffer, newSize);
+            }
+
+            Debug.Assert(FreeCapacity > 0 && FreeCapacity >= sizeHint);
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
index 84e6341..04d68b5 100644
--- a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
+++ b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
@@ -34,6 +34,13 @@
 using System.Text;

 using NUnit.Framework;

 using System.IO;

+using System.Collections.Generic;

+using System.Collections;

+using System.Linq;

+using System.Buffers;

+using System.Runtime.InteropServices;

+using System.Threading;

+using System.Runtime.CompilerServices;

 #if !NET35

 using System.Threading.Tasks;

 #endif

@@ -54,6 +61,7 @@
             EqualityTester.AssertInequality(b1, b3);

             EqualityTester.AssertInequality(b1, b4);

             EqualityTester.AssertInequality(b1, null);

+            EqualityTester.AssertEquality(ByteString.Empty, ByteString.Empty);

 #pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1)

             Assert.IsTrue(b1 == b1);

             Assert.IsTrue(b1 == b2);

@@ -63,6 +71,7 @@
             Assert.IsTrue((ByteString) null == null);

             Assert.IsFalse(b1 != b1);

             Assert.IsFalse(b1 != b2);

+            Assert.IsTrue(ByteString.Empty == ByteString.Empty);

 #pragma warning disable 1718

             Assert.IsTrue(b1 != b3);

             Assert.IsTrue(b1 != b4);

@@ -111,6 +120,18 @@
         }

 

         [Test]

+        public void CopyFromReadOnlySpanCopiesContents()

+        {

+            byte[] data = new byte[1];

+            data[0] = 10;

+            ReadOnlySpan<byte> byteSpan = data;

+            var bs = ByteString.CopyFrom(byteSpan);

+            Assert.AreEqual(10, bs[0]);

+            data[0] = 5;

+            Assert.AreEqual(10, bs[0]);

+        }

+

+        [Test]

         public void ToByteArrayCopiesContents()

         {

             ByteString bs = ByteString.CopyFromUtf8("Hello");

@@ -143,6 +164,100 @@
         }

 

         [Test]

+        public void CopyTo()

+        {

+            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };

+            ByteString bs = ByteString.CopyFrom(data);

+

+            byte[] dest = new byte[data.Length];

+            bs.CopyTo(dest, 0);

+

+            CollectionAssert.AreEqual(data, dest);

+        }

+

+        [Test]

+        public void GetEnumerator()

+        {

+            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };

+            ByteString bs = ByteString.CopyFrom(data);

+

+            IEnumerator<byte> genericEnumerator = bs.GetEnumerator();

+            Assert.IsTrue(genericEnumerator.MoveNext());

+            Assert.AreEqual(0, genericEnumerator.Current);

+

+            IEnumerator enumerator = ((IEnumerable)bs).GetEnumerator();

+            Assert.IsTrue(enumerator.MoveNext());

+            Assert.AreEqual(0, enumerator.Current);

+

+            // Call via LINQ

+            CollectionAssert.AreEqual(bs.Span.ToArray(), bs.ToArray());

+        }

+

+        [Test]

+        public void UnsafeWrap()

+        {

+            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };

+            ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));

+            ReadOnlySpan<byte> s = bs.Span;

+

+            Assert.AreEqual(3, s.Length);

+            Assert.AreEqual(2, s[0]);

+            Assert.AreEqual(3, s[1]);

+            Assert.AreEqual(4, s[2]);

+

+            // Check that the value is not a copy

+            data[2] = byte.MaxValue;

+            Assert.AreEqual(byte.MaxValue, s[0]);

+        }

+

+        [Test]

+        public void CreateCodedInput_FromArraySegment()

+        {

+            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };

+            ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));

+            CodedInputStream codedInputStream = bs.CreateCodedInput();

+

+            byte[] bytes = codedInputStream.ReadRawBytes(3);

+

+            Assert.AreEqual(3, bytes.Length);

+            Assert.AreEqual(2, bytes[0]);

+            Assert.AreEqual(3, bytes[1]);

+            Assert.AreEqual(4, bytes[2]);

+            Assert.IsTrue(codedInputStream.IsAtEnd);

+        }

+

+        [Test]

+        public void WriteToStream()

+        {

+            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };

+            ByteString bs = ByteString.CopyFrom(data);

+

+            MemoryStream ms = new MemoryStream();

+            bs.WriteTo(ms);

+

+            CollectionAssert.AreEqual(data, ms.ToArray());

+        }

+

+        [Test]

+        public void WriteToStream_Stackalloc()

+        {

+            byte[] data = Encoding.UTF8.GetBytes("Hello world");

+            Span<byte> s = stackalloc byte[data.Length];

+            data.CopyTo(s);

+

+            MemoryStream ms = new MemoryStream();

+

+            using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))

+            {

+                ByteString bs = ByteString.AttachBytes(manager.Memory);

+

+                bs.WriteTo(ms);

+            }

+

+            CollectionAssert.AreEqual(data, ms.ToArray());

+        }

+

+        [Test]

         public void ToStringUtf8()

         {

             ByteString bs = ByteString.CopyFromUtf8("\u20ac");

@@ -157,6 +272,21 @@
         }

 

         [Test]

+        public void ToString_Stackalloc()

+        {

+            byte[] data = Encoding.UTF8.GetBytes("Hello world");

+            Span<byte> s = stackalloc byte[data.Length];

+            data.CopyTo(s);

+

+            using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))

+            {

+                ByteString bs = ByteString.AttachBytes(manager.Memory);

+

+                Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8));

+            }

+        }

+

+        [Test]

         public void FromBase64_WithText()

         {

             byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};

@@ -173,6 +303,29 @@
         }

 

         [Test]

+        public void ToBase64_Array()

+        {

+            ByteString bs = ByteString.CopyFrom(Encoding.UTF8.GetBytes("Hello world"));

+

+            Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());

+        }

+

+        [Test]

+        public void ToBase64_Stackalloc()

+        {

+            byte[] data = Encoding.UTF8.GetBytes("Hello world");

+            Span<byte> s = stackalloc byte[data.Length];

+            data.CopyTo(s);

+

+            using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))

+            {

+                ByteString bs = ByteString.AttachBytes(manager.Memory);

+

+                Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());

+            }

+        }

+

+        [Test]

         public void FromStream_Seekable()

         {

             var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });

@@ -233,5 +386,54 @@
             ByteString b2 = ByteString.CopyFrom(200, 1, 2, 3, 4);

             Assert.AreNotEqual(b1.GetHashCode(), b2.GetHashCode());

         }

+

+        [Test]

+        public void GetContentsAsReadOnlySpan()

+        {

+            var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);

+            var copied = byteString.Span.ToArray();

+            CollectionAssert.AreEqual(byteString, copied);

+        }

+

+        [Test]

+        public void GetContentsAsReadOnlyMemory()

+        {

+            var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);

+            var copied = byteString.Memory.ToArray();

+            CollectionAssert.AreEqual(byteString, copied);

+        }

+

+        // Create Memory<byte> from non-array source.

+        // Use by ByteString tests that have optimized path for array backed Memory<byte>.

+        private sealed unsafe class UnmanagedMemoryManager<T> : MemoryManager<T> where T : unmanaged

+        {

+            private readonly T* _pointer;

+            private readonly int _length;

+

+            public UnmanagedMemoryManager(Span<T> span)

+            {

+                fixed (T* ptr = &MemoryMarshal.GetReference(span))

+                {

+                    _pointer = ptr;

+                    _length = span.Length;

+                }

+            }

+

+            public override Span<T> GetSpan() => new Span<T>(_pointer, _length);

+

+            public override MemoryHandle Pin(int elementIndex = 0)

+            {

+                if (elementIndex < 0 || elementIndex >= _length)

+                {

+                    throw new ArgumentOutOfRangeException(nameof(elementIndex));

+                }

+

+                return new MemoryHandle(_pointer + elementIndex);

+            }

+

+            public override void Unpin() { }

+

+            protected override void Dispose(bool disposing) { }

+        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index 5f360ff..5e72525 100644
--- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -31,6 +31,7 @@
 #endregion

 

 using System;

+using System.Buffers;

 using System.IO;

 using Google.Protobuf.TestProtos;

 using Proto2 = Google.Protobuf.TestProtos.Proto2;

@@ -62,11 +63,22 @@
         {

             CodedInputStream input = new CodedInputStream(data);

             Assert.AreEqual((uint) value, input.ReadRawVarint32());

+            Assert.IsTrue(input.IsAtEnd);

 

             input = new CodedInputStream(data);

             Assert.AreEqual(value, input.ReadRawVarint64());

             Assert.IsTrue(input.IsAtEnd);

 

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(data), (ref ParseContext ctx) =>

+            {

+                Assert.AreEqual((uint) value, ctx.ReadUInt32());

+            }, true);

+

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(data), (ref ParseContext ctx) =>

+            {

+                Assert.AreEqual(value, ctx.ReadUInt64());

+            }, true);

+

             // Try different block sizes.

             for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)

             {

@@ -76,6 +88,16 @@
                 input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));

                 Assert.AreEqual(value, input.ReadRawVarint64());

                 Assert.IsTrue(input.IsAtEnd);

+

+                AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, bufferSize), (ref ParseContext ctx) =>

+                {

+                    Assert.AreEqual((uint) value, ctx.ReadUInt32());

+                }, true);

+

+                AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, bufferSize), (ref ParseContext ctx) =>

+                {

+                    Assert.AreEqual(value, ctx.ReadUInt64());

+                }, true);

             }

 

             // Try reading directly from a MemoryStream. We want to verify that it

@@ -104,11 +126,58 @@
             exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64());

             Assert.AreEqual(expected.Message, exception.Message);

 

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(data), (ref ParseContext ctx) =>

+            {

+                try

+                {

+                    ctx.ReadUInt32();

+                    Assert.Fail();

+                }

+                catch (InvalidProtocolBufferException ex)

+                {

+                    Assert.AreEqual(expected.Message, ex.Message);

+                }

+            }, false);

+

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(data), (ref ParseContext ctx) =>

+            {

+                try

+                {

+                    ctx.ReadUInt64();

+                    Assert.Fail();

+                }

+                catch (InvalidProtocolBufferException ex)

+                {

+                    Assert.AreEqual(expected.Message, ex.Message);

+                }

+            }, false);

+

             // Make sure we get the same error when reading directly from a Stream.

             exception = Assert.Throws<InvalidProtocolBufferException>(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data)));

             Assert.AreEqual(expected.Message, exception.Message);

         }

 

+        private delegate void ParseContextAssertAction(ref ParseContext ctx);

+

+        private static void AssertReadFromParseContext(ReadOnlySequence<byte> input, ParseContextAssertAction assertAction, bool assertIsAtEnd)

+        {

+            // Check as ReadOnlySequence<byte>

+            ParseContext.Initialize(input, out ParseContext parseCtx);

+            assertAction(ref parseCtx);

+            if (assertIsAtEnd)

+            {

+                Assert.IsTrue(SegmentedBufferHelper.IsAtEnd(ref parseCtx.buffer, ref parseCtx.state));

+            }

+

+            // Check as ReadOnlySpan<byte>

+            ParseContext.Initialize(input.ToArray().AsSpan(), out ParseContext spanParseContext);

+            assertAction(ref spanParseContext);

+            if (assertIsAtEnd)

+            {

+                Assert.IsTrue(SegmentedBufferHelper.IsAtEnd(ref spanParseContext.buffer, ref spanParseContext.state));

+            }

+        }

+

         [Test]

         public void ReadVarint()

         {

@@ -157,6 +226,11 @@
             Assert.AreEqual(value, input.ReadRawLittleEndian32());

             Assert.IsTrue(input.IsAtEnd);

 

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(data), (ref ParseContext ctx) =>

+            {

+                Assert.AreEqual(value, ctx.ReadFixed32());

+            }, true);

+

             // Try different block sizes.

             for (int blockSize = 1; blockSize <= 16; blockSize *= 2)

             {

@@ -164,6 +238,11 @@
                     new SmallBlockInputStream(data, blockSize));

                 Assert.AreEqual(value, input.ReadRawLittleEndian32());

                 Assert.IsTrue(input.IsAtEnd);

+

+                AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, blockSize), (ref ParseContext ctx) =>

+                {

+                    Assert.AreEqual(value, ctx.ReadFixed32());

+                }, true);

             }

         }

 

@@ -177,6 +256,11 @@
             Assert.AreEqual(value, input.ReadRawLittleEndian64());

             Assert.IsTrue(input.IsAtEnd);

 

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(data), (ref ParseContext ctx) =>

+            {

+                Assert.AreEqual(value, ctx.ReadFixed64());

+            }, true);

+

             // Try different block sizes.

             for (int blockSize = 1; blockSize <= 16; blockSize *= 2)

             {

@@ -184,6 +268,11 @@
                     new SmallBlockInputStream(data, blockSize));

                 Assert.AreEqual(value, input.ReadRawLittleEndian64());

                 Assert.IsTrue(input.IsAtEnd);

+

+                AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, blockSize), (ref ParseContext ctx) =>

+                {

+                    Assert.AreEqual(value, ctx.ReadFixed64());

+                }, true);

             }

         }

 

@@ -202,29 +291,29 @@
         [Test]

         public void DecodeZigZag32()

         {

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2));

-            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));

-            Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));

-            Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));

-            Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));

-            Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(0));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(1));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(2));

+            Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag32(3));

+            Assert.AreEqual(0x3FFFFFFF, ParsingPrimitives.DecodeZigZag32(0x7FFFFFFE));

+            Assert.AreEqual(unchecked((int) 0xC0000000), ParsingPrimitives.DecodeZigZag32(0x7FFFFFFF));

+            Assert.AreEqual(0x7FFFFFFF, ParsingPrimitives.DecodeZigZag32(0xFFFFFFFE));

+            Assert.AreEqual(unchecked((int) 0x80000000), ParsingPrimitives.DecodeZigZag32(0xFFFFFFFF));

         }

 

         [Test]

         public void DecodeZigZag64()

         {

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2));

-            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));

-            Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));

-            Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));

-            Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));

-            Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));

-            Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));

-            Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(0));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(1));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(2));

+            Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag64(3));

+            Assert.AreEqual(0x000000003FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFEL));

+            Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFFL));

+            Assert.AreEqual(0x000000007FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFEL));

+            Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFFL));

+            Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));

+            Assert.AreEqual(unchecked((long) 0x8000000000000000L), ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));

         }

         

         [Test]

@@ -244,7 +333,44 @@
                 Assert.AreEqual(message, message2);

             }

         }

-                

+

+        [Test]

+        public void ReadWholeMessage_VaryingBlockSizes_FromSequence()

+        {

+            TestAllTypes message = SampleMessages.CreateFullTestAllTypes();

+

+            byte[] rawBytes = message.ToByteArray();

+            Assert.AreEqual(rawBytes.Length, message.CalculateSize());

+            TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes);

+            Assert.AreEqual(message, message2);

+

+            // Try different block sizes.

+            for (int blockSize = 1; blockSize < 256; blockSize *= 2)

+            {

+                message2 = TestAllTypes.Parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(rawBytes, blockSize));

+                Assert.AreEqual(message, message2);

+            }

+        }

+

+        [Test]

+        public void ReadInt32Wrapper_VariableBlockSizes()

+        {

+            byte[] rawBytes = new byte[] { 202, 1, 11, 8, 254, 255, 255, 255, 255, 255, 255, 255, 255, 1 };

+

+            for (int blockSize = 1; blockSize <= rawBytes.Length; blockSize++)

+            {

+                ReadOnlySequence<byte> data = ReadOnlySequenceFactory.CreateWithContent(rawBytes, blockSize);

+                AssertReadFromParseContext(data, (ref ParseContext ctx) =>

+                {

+                    ctx.ReadTag();

+

+                    var value = ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx);

+

+                    Assert.AreEqual(-2, value);

+                }, true);

+            }

+        }

+

         [Test]

         public void ReadHugeBlob()

         {

@@ -285,6 +411,70 @@
             Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());

         }

 

+        [Test]

+        public void ReadBlobGreaterThanCurrentLimit()

+        {

+            MemoryStream ms = new MemoryStream();

+            CodedOutputStream output = new CodedOutputStream(ms);

+            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);

+            output.WriteRawVarint32(tag);

+            output.WriteRawVarint32(4);

+            output.WriteRawBytes(new byte[4]); // Pad with a few random bytes.

+            output.Flush();

+            ms.Position = 0;

+

+            CodedInputStream input = new CodedInputStream(ms);

+            Assert.AreEqual(tag, input.ReadTag());

+

+            // Specify limit smaller than data length

+            input.PushLimit(3);

+            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());

+

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(ms.ToArray()), (ref ParseContext ctx) =>

+            {

+                Assert.AreEqual(tag, ctx.ReadTag());

+                SegmentedBufferHelper.PushLimit(ref ctx.state, 3);

+                try

+                {

+                    ctx.ReadBytes();

+                    Assert.Fail();

+                }

+                catch (InvalidProtocolBufferException) {}

+            }, true);

+        }

+

+        [Test]

+        public void ReadStringGreaterThanCurrentLimit()

+        {

+            MemoryStream ms = new MemoryStream();

+            CodedOutputStream output = new CodedOutputStream(ms);

+            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);

+            output.WriteRawVarint32(tag);

+            output.WriteRawVarint32(4);

+            output.WriteRawBytes(new byte[4]); // Pad with a few random bytes.

+            output.Flush();

+            ms.Position = 0;

+

+            CodedInputStream input = new CodedInputStream(ms.ToArray());

+            Assert.AreEqual(tag, input.ReadTag());

+

+            // Specify limit smaller than data length

+            input.PushLimit(3);

+            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadString());

+

+            AssertReadFromParseContext(new ReadOnlySequence<byte>(ms.ToArray()), (ref ParseContext ctx) =>

+            {

+                Assert.AreEqual(tag, ctx.ReadTag());

+                SegmentedBufferHelper.PushLimit(ref ctx.state, 3);

+                try

+                {

+                    ctx.ReadString();

+                    Assert.Fail();

+                }

+                catch (InvalidProtocolBufferException) { }

+            }, true);

+        }

+

         // Representations of a tag for field 0 with various wire types

         [Test]

         [TestCase(0)]

@@ -339,64 +529,64 @@
             Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(input));

         }

         

-        private static byte[] MakeMaliciousRecursionUnknownFieldsPayload(int recursionDepth)
-        {
-            // generate recursively nested groups that will be parsed as unknown fields
-            int unknownFieldNumber = 14;  // an unused field number
-            MemoryStream ms = new MemoryStream();
-            CodedOutputStream output = new CodedOutputStream(ms);
-            for (int i = 0; i < recursionDepth; i++)
-            {
-                output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.StartGroup));
-            }
-            for (int i = 0; i < recursionDepth; i++)
-            {
-                output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.EndGroup));
-            }
-            output.Flush();
-            return ms.ToArray();
+        private static byte[] MakeMaliciousRecursionUnknownFieldsPayload(int recursionDepth)

+        {

+            // generate recursively nested groups that will be parsed as unknown fields

+            int unknownFieldNumber = 14;  // an unused field number

+            MemoryStream ms = new MemoryStream();

+            CodedOutputStream output = new CodedOutputStream(ms);

+            for (int i = 0; i < recursionDepth; i++)

+            {

+                output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.StartGroup));

+            }

+            for (int i = 0; i < recursionDepth; i++)

+            {

+                output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.EndGroup));

+            }

+            output.Flush();

+            return ms.ToArray();

         }

 

         [Test]

         public void MaliciousRecursion_UnknownFields()

         {

-            byte[] payloadAtRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit);
-            byte[] payloadBeyondRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit + 1);
-            
-            Assert.DoesNotThrow(() => TestRecursiveMessage.Parser.ParseFrom(payloadAtRecursiveLimit));
+            byte[] payloadAtRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit);

+            byte[] payloadBeyondRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit + 1);

+            

+            Assert.DoesNotThrow(() => TestRecursiveMessage.Parser.ParseFrom(payloadAtRecursiveLimit));

             Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(payloadBeyondRecursiveLimit));

         }

 

         [Test]

         public void ReadGroup_WrongEndGroupTag()

-        {
-            int groupFieldNumber = Proto2.TestAllTypes.OptionalGroupFieldNumber;
-
-            // write Proto2.TestAllTypes with "optional_group" set, but use wrong EndGroup closing tag
-            MemoryStream ms = new MemoryStream();
-            CodedOutputStream output = new CodedOutputStream(ms);
-            output.WriteTag(WireFormat.MakeTag(groupFieldNumber, WireFormat.WireType.StartGroup));
-            output.WriteGroup(new Proto2.TestAllTypes.Types.OptionalGroup { A = 12345 });
-            // end group with different field number
-            output.WriteTag(WireFormat.MakeTag(groupFieldNumber + 1, WireFormat.WireType.EndGroup));
-            output.Flush();
-            var payload = ms.ToArray();
-
-            Assert.Throws<InvalidProtocolBufferException>(() => Proto2.TestAllTypes.Parser.ParseFrom(payload));
+        {

+            int groupFieldNumber = Proto2.TestAllTypes.OptionalGroupFieldNumber;

+

+            // write Proto2.TestAllTypes with "optional_group" set, but use wrong EndGroup closing tag

+            MemoryStream ms = new MemoryStream();

+            CodedOutputStream output = new CodedOutputStream(ms);

+            output.WriteTag(WireFormat.MakeTag(groupFieldNumber, WireFormat.WireType.StartGroup));

+            output.WriteGroup(new Proto2.TestAllTypes.Types.OptionalGroup { A = 12345 });

+            // end group with different field number

+            output.WriteTag(WireFormat.MakeTag(groupFieldNumber + 1, WireFormat.WireType.EndGroup));

+            output.Flush();

+            var payload = ms.ToArray();

+

+            Assert.Throws<InvalidProtocolBufferException>(() => Proto2.TestAllTypes.Parser.ParseFrom(payload));

         }

 

         [Test]

         public void ReadGroup_UnknownFields_WrongEndGroupTag()

-        {
-            MemoryStream ms = new MemoryStream();
-            CodedOutputStream output = new CodedOutputStream(ms);
-            output.WriteTag(WireFormat.MakeTag(14, WireFormat.WireType.StartGroup));
-            // end group with different field number
-            output.WriteTag(WireFormat.MakeTag(15, WireFormat.WireType.EndGroup));
-            output.Flush();
-            var payload = ms.ToArray();
-
-            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(payload));
+        {

+            MemoryStream ms = new MemoryStream();

+            CodedOutputStream output = new CodedOutputStream(ms);

+            output.WriteTag(WireFormat.MakeTag(14, WireFormat.WireType.StartGroup));

+            // end group with different field number

+            output.WriteTag(WireFormat.MakeTag(15, WireFormat.WireType.EndGroup));

+            output.Flush();

+            var payload = ms.ToArray();

+

+            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(payload));

         }

 

         [Test]

diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
index 98cabd5..1444009 100644
--- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -33,7 +33,9 @@
 using System;

 using System.IO;

 using Google.Protobuf.TestProtos;

+using Google.Protobuf.Buffers;

 using NUnit.Framework;

+using System.Text;

 

 namespace Google.Protobuf

 {

@@ -48,22 +50,39 @@
             // Only do 32-bit write if the value fits in 32 bits.

             if ((value >> 32) == 0)

             {

+                // CodedOutputStream

                 MemoryStream rawOutput = new MemoryStream();

                 CodedOutputStream output = new CodedOutputStream(rawOutput);

                 output.WriteRawVarint32((uint) value);

                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

+

+                // IBufferWriter

+                var bufferWriter = new TestArrayBufferWriter<byte>();

+                WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                ctx.WriteUInt32((uint) value);

+                ctx.Flush();

+                Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

+

                 // Also try computing size.

                 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));

             }

 

             {

+                // CodedOutputStream

                 MemoryStream rawOutput = new MemoryStream();

                 CodedOutputStream output = new CodedOutputStream(rawOutput);

                 output.WriteRawVarint64(value);

                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

 

+                // IBufferWriter

+                var bufferWriter = new TestArrayBufferWriter<byte>();

+                WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                ctx.WriteUInt64(value);

+                ctx.Flush();

+                Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

+

                 // Also try computing size.

                 Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));

             }

@@ -80,6 +99,13 @@
                     output.WriteRawVarint32((uint) value);

                     output.Flush();

                     Assert.AreEqual(data, rawOutput.ToArray());

+

+                    var bufferWriter = new TestArrayBufferWriter<byte>();

+                    bufferWriter.MaxGrowBy = bufferSize;

+                    WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                    ctx.WriteUInt32((uint) value);

+                    ctx.Flush();

+                    Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

                 }

 

                 {

@@ -88,7 +114,15 @@
                     output.WriteRawVarint64(value);

                     output.Flush();

                     Assert.AreEqual(data, rawOutput.ToArray());

+

+                    var bufferWriter = new TestArrayBufferWriter<byte>();

+                    bufferWriter.MaxGrowBy = bufferSize;

+                    WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                    ctx.WriteUInt64(value);

+                    ctx.Flush();

+                    Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

                 }

+

             }

         }

 

@@ -133,20 +167,35 @@
         /// </summary>

         private static void AssertWriteLittleEndian32(byte[] data, uint value)

         {

-            MemoryStream rawOutput = new MemoryStream();

-            CodedOutputStream output = new CodedOutputStream(rawOutput);

-            output.WriteRawLittleEndian32(value);

-            output.Flush();

-            Assert.AreEqual(data, rawOutput.ToArray());

+            {

+                var rawOutput = new MemoryStream();

+                var output = new CodedOutputStream(rawOutput);

+                output.WriteRawLittleEndian32(value);

+                output.Flush();

+                Assert.AreEqual(data, rawOutput.ToArray());

+

+                var bufferWriter = new TestArrayBufferWriter<byte>();

+                WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                ctx.WriteFixed32(value);

+                ctx.Flush();

+                Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

+            }

 

             // Try different buffer sizes.

             for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)

             {

-                rawOutput = new MemoryStream();

-                output = new CodedOutputStream(rawOutput, bufferSize);

+                var rawOutput = new MemoryStream();

+                var output = new CodedOutputStream(rawOutput, bufferSize);

                 output.WriteRawLittleEndian32(value);

                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

+

+                var bufferWriter = new TestArrayBufferWriter<byte>();

+                bufferWriter.MaxGrowBy = bufferSize;

+                WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                ctx.WriteFixed32(value);

+                ctx.Flush();

+                Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

             }

         }

 

@@ -156,20 +205,35 @@
         /// </summary>

         private static void AssertWriteLittleEndian64(byte[] data, ulong value)

         {

-            MemoryStream rawOutput = new MemoryStream();

-            CodedOutputStream output = new CodedOutputStream(rawOutput);

-            output.WriteRawLittleEndian64(value);

-            output.Flush();

-            Assert.AreEqual(data, rawOutput.ToArray());

+            {

+                var rawOutput = new MemoryStream();

+                var output = new CodedOutputStream(rawOutput);

+                output.WriteRawLittleEndian64(value);

+                output.Flush();

+                Assert.AreEqual(data, rawOutput.ToArray());

+

+                var bufferWriter = new TestArrayBufferWriter<byte>();

+                WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                ctx.WriteFixed64(value);

+                ctx.Flush();

+                Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

+            }

 

             // Try different block sizes.

             for (int blockSize = 1; blockSize <= 16; blockSize *= 2)

             {

-                rawOutput = new MemoryStream();

-                output = new CodedOutputStream(rawOutput, blockSize);

+                var rawOutput = new MemoryStream();

+                var output = new CodedOutputStream(rawOutput, blockSize);

                 output.WriteRawLittleEndian64(value);

                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

+

+                var bufferWriter = new TestArrayBufferWriter<byte>();

+                bufferWriter.MaxGrowBy = blockSize;

+                WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+                ctx.WriteFixed64(value);

+                ctx.Flush();

+                Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray());

             }

         }

 

@@ -205,41 +269,72 @@
                 message.WriteTo(output);

                 output.Flush();

                 Assert.AreEqual(rawBytes, rawOutput.ToArray());

+

+                var bufferWriter = new TestArrayBufferWriter<byte>();

+                bufferWriter.MaxGrowBy = blockSize;

+                message.WriteTo(bufferWriter);

+                Assert.AreEqual(rawBytes, bufferWriter.WrittenSpan.ToArray()); 

             }

         }

+

+        [Test]

+        public void WriteContext_WritesWithFlushes()

+        {

+            TestAllTypes message = SampleMessages.CreateFullTestAllTypes();

+

+            MemoryStream expectedOutput = new MemoryStream();

+            CodedOutputStream output = new CodedOutputStream(expectedOutput);

+            output.WriteMessage(message);

+            output.Flush();

+            byte[] expectedBytes1 = expectedOutput.ToArray();

+

+            output.WriteMessage(message);

+            output.Flush();

+            byte[] expectedBytes2 = expectedOutput.ToArray();

+

+            var bufferWriter = new TestArrayBufferWriter<byte>();

+            WriteContext.Initialize(bufferWriter, out WriteContext ctx);

+            ctx.WriteMessage(message);

+            ctx.Flush();

+            Assert.AreEqual(expectedBytes1, bufferWriter.WrittenSpan.ToArray());

+

+            ctx.WriteMessage(message);

+            ctx.Flush();

+            Assert.AreEqual(expectedBytes2, bufferWriter.WrittenSpan.ToArray());

+        }

         

         [Test]

         public void EncodeZigZag32()

         {

-            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0));

-            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1));

-            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1));

-            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2));

-            Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));

-            Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000)));

-            Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));

-            Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000)));

+            Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0));

+            Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1));

+            Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1));

+            Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2));

+            Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF));

+            Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000)));

+            Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF));

+            Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000)));

         }

 

         [Test]

         public void EncodeZigZag64()

         {

-            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0));

-            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1));

-            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1));

-            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2));

+            Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0));

+            Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1));

+            Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1));

+            Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2));

             Assert.AreEqual(0x000000007FFFFFFEuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));

             Assert.AreEqual(0x000000007FFFFFFFuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));

             Assert.AreEqual(0x00000000FFFFFFFEuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));

             Assert.AreEqual(0x00000000FFFFFFFFuL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));

             Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));

             Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,

-                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));

+                            WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));

         }

 

         [Test]

@@ -247,26 +342,26 @@
         {

             // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)

             // were chosen semi-randomly via keyboard bashing.

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));

-            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));

-            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0)));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1)));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1)));

+            Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927)));

+            Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612)));

         }

 

         [Test]

         public void RoundTripZigZag64()

         {

-            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));

-            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));

-            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));

-            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));

-            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));

+            Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0)));

+            Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1)));

+            Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1)));

+            Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927)));

+            Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612)));

 

             Assert.AreEqual(856912304801416L,

-                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));

+                            ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L)));

             Assert.AreEqual(-75123905439571256L,

-                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));

+                            ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L)));

         }

 

         [Test]

@@ -395,7 +490,7 @@
             Assert.IsTrue(memoryStream.CanWrite);

             using (var cos = new CodedOutputStream(memoryStream))

             {

-                cos.WriteRawByte(0);

+                cos.WriteRawBytes(new byte[] {0});

                 Assert.AreEqual(0, memoryStream.Position); // Not flushed yet

             }

             Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream

@@ -409,7 +504,7 @@
             Assert.IsTrue(memoryStream.CanWrite);

             using (var cos = new CodedOutputStream(memoryStream, true))

             {

-                cos.WriteRawByte(0);

+                cos.WriteRawBytes(new byte[] {0});

                 Assert.AreEqual(0, memoryStream.Position); // Not flushed yet

             }

             Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream

@@ -422,5 +517,67 @@
             var stream = new CodedOutputStream(new byte[10]);

             stream.Dispose();

         }

+

+        [Test]

+        public void WriteString_AsciiSmall_MaxUtf8SizeExceedsBuffer()

+        {

+            var buffer = new byte[5];

+            var output = new CodedOutputStream(buffer);

+            output.WriteString("ABC");

+

+            output.Flush();

+

+            // Verify written content

+            var input = new CodedInputStream(buffer);

+            Assert.AreEqual("ABC", input.ReadString());

+        }

+

+        [Test]

+        public void WriteStringsOfDifferentSizes_Ascii()

+        {

+            for (int i = 1; i <= 1024; i++)

+            {

+                var buffer = new byte[4096];

+                var output = new CodedOutputStream(buffer);

+                var sb = new StringBuilder();

+                for (int j = 0; j < i; j++)

+                {

+                    sb.Append((j % 10).ToString()); // incrementing numbers, repeating

+                }

+                var s = sb.ToString();

+                output.WriteString(s);

+

+                output.Flush();

+

+                // Verify written content

+                var input = new CodedInputStream(buffer);

+                Assert.AreEqual(s, input.ReadString());

+            }

+        }

+

+        [Test]

+        public void WriteStringsOfDifferentSizes_Unicode()

+        {

+            for (int i = 1; i <= 1024; i++)

+            {

+                var buffer = new byte[4096];

+                var output = new CodedOutputStream(buffer);

+                var sb = new StringBuilder();

+                for (int j = 0; j < i; j++)

+                {

+                    char c = (char)((j % 10) + 10112);

+                    sb.Append(c.ToString()); // incrementing unicode numbers, repeating

+                }

+                var s = sb.ToString();

+                output.WriteString(s);

+

+                output.Flush();

+

+                // Verify written content

+                var input = new CodedInputStream(buffer);

+

+                Assert.AreEqual(s, input.ReadString());

+            }

+        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
index f64ebac..d4c63dc 100644
--- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
@@ -31,6 +31,7 @@
 #endregion
 
 using System;
+using System.IO;
 using System.Collections.Generic;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
@@ -583,6 +584,59 @@
             Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out ignored));
         }
 
+        [Test]
+        public void AddEntriesFrom_CodedInputStream()
+        {
+            // map will have string key and string value
+            var keyTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            var valueTag = WireFormat.MakeTag(2, WireFormat.WireType.LengthDelimited);
+
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+            output.WriteLength(20);  // total of keyTag + key + valueTag + value
+            output.WriteTag(keyTag);
+            output.WriteString("the_key");
+            output.WriteTag(valueTag);
+            output.WriteString("the_value");
+            output.Flush();
+
+            var field = new MapField<string,string>();
+            var mapCodec = new MapField<string,string>.Codec(FieldCodec.ForString(keyTag, ""), FieldCodec.ForString(valueTag, ""), 10);
+            var input = new CodedInputStream(memoryStream.ToArray());
+
+            // test the legacy overload of AddEntriesFrom that takes a CodedInputStream
+            field.AddEntriesFrom(input, mapCodec);
+            CollectionAssert.AreEquivalent(new[] { "the_key" }, field.Keys);
+            CollectionAssert.AreEquivalent(new[] { "the_value" }, field.Values);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void AddEntriesFrom_CodedInputStream_MissingKey()
+        {
+            // map will have string key and string value
+            var keyTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            var valueTag = WireFormat.MakeTag(2, WireFormat.WireType.LengthDelimited);
+
+            var memoryStream = new MemoryStream();
+            var output = new CodedOutputStream(memoryStream);
+            output.WriteLength(11);  // total of valueTag + value
+            output.WriteTag(valueTag);
+            output.WriteString("the_value");
+            output.Flush();
+
+            Console.WriteLine(BitConverter.ToString(memoryStream.ToArray()));
+
+            var field = new MapField<string, string>();
+            var mapCodec = new MapField<string, string>.Codec(FieldCodec.ForString(keyTag, ""), FieldCodec.ForString(valueTag, ""), 10);
+            var input = new CodedInputStream(memoryStream.ToArray());
+
+            field.AddEntriesFrom(input, mapCodec);
+            CollectionAssert.AreEquivalent(new[] { "" }, field.Keys);
+            CollectionAssert.AreEquivalent(new[] { "the_value" }, field.Values);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
 #if !NET35
         [Test]
         public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()
diff --git a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
index 527c7d4..61453e5 100644
--- a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
@@ -595,6 +595,95 @@
             Assert.AreEqual(((SampleEnum)(-5)), values[5]);
         }
 
+        [Test]
+        public void TestPackedRepeatedFieldCollectionNonDivisibleLength()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var codec = FieldCodec.ForFixed32(tag);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(tag);
+            output.WriteString("A long string");
+            output.WriteTag(codec.Tag);
+            output.WriteRawVarint32((uint)codec.FixedSize - 1); // Length not divisible by FixedSize
+            output.WriteFixed32(uint.MaxValue);
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.ReadTag();
+            input.ReadString();
+            input.ReadTag();
+            var field = new RepeatedField<uint>();
+            Assert.Throws<InvalidProtocolBufferException>(() => field.AddEntriesFrom(input, codec));
+
+            // Collection was not pre-initialized
+            Assert.AreEqual(0, field.Count);
+        }
+
+        [Test]
+        public void TestPackedRepeatedFieldCollectionNotAllocatedWhenLengthExceedsBuffer()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var codec = FieldCodec.ForFixed32(tag);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(tag);
+            output.WriteString("A long string");
+            output.WriteTag(codec.Tag);
+            output.WriteRawVarint32((uint)codec.FixedSize);
+            // Note that there is no content for the packed field.
+            // The field length exceeds the remaining length of content.
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.ReadTag();
+            input.ReadString();
+            input.ReadTag();
+            var field = new RepeatedField<uint>();
+            Assert.Throws<InvalidProtocolBufferException>(() => field.AddEntriesFrom(input, codec));
+
+            // Collection was not pre-initialized
+            Assert.AreEqual(0, field.Count);
+        }
+
+        [Test]
+        public void TestPackedRepeatedFieldCollectionNotAllocatedWhenLengthExceedsRemainingData()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var codec = FieldCodec.ForFixed32(tag);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(tag);
+            output.WriteString("A long string");
+            output.WriteTag(codec.Tag);
+            output.WriteRawVarint32((uint)codec.FixedSize);
+            // Note that there is no content for the packed field.
+            // The field length exceeds the remaining length of the buffer.
+            output.Flush();
+            stream.Position = 0;
+
+            var sequence = ReadOnlySequenceFactory.CreateWithContent(stream.ToArray());
+            ParseContext.Initialize(sequence, out ParseContext ctx);
+
+            ctx.ReadTag();
+            ctx.ReadString();
+            ctx.ReadTag();
+            var field = new RepeatedField<uint>();
+            try
+            {
+                field.AddEntriesFrom(ref ctx, codec);
+                Assert.Fail();
+            }
+            catch (InvalidProtocolBufferException)
+            {
+            }
+
+            // Collection was not pre-initialized
+            Assert.AreEqual(0, field.Count);
+        }
+
         // Fairly perfunctory tests for the non-generic IList implementation
         [Test]
         public void IList_Indexer()
diff --git a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
index 33dc504..951e856 100644
--- a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
+++ b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
@@ -1,4 +1,4 @@
-using Google.Protobuf.TestProtos.Proto2;
+using Google.Protobuf.TestProtos.Proto2;

 using NUnit.Framework;

 

 using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;

@@ -34,12 +34,16 @@
             message.SetExtension(OptionalBoolExtension, true);

             var serialized = message.ToByteArray();

 

-            var other = TestAllExtensions.Parser

-                .WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension })

-                .ParseFrom(serialized);

+            MessageParsingHelpers.AssertWritingMessage(message);

 

-            Assert.AreEqual(message, other);

-            Assert.AreEqual(message.CalculateSize(), other.CalculateSize());

+            MessageParsingHelpers.AssertReadingMessage(

+                TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }),

+                serialized,

+                other =>

+                {

+                    Assert.AreEqual(message, other);

+                    Assert.AreEqual(message.CalculateSize(), other.CalculateSize());

+                });

         }

 

         [Test]

@@ -60,6 +64,22 @@
         }

 

         [Test]

+        public void TryMergeFieldFrom_CodedInputStream()

+        {

+            var message = new TestAllExtensions();

+            message.SetExtension(OptionalStringExtension, "abcd");

+

+            var input = new CodedInputStream(message.ToByteArray());

+            input.ExtensionRegistry = new ExtensionRegistry() { OptionalStringExtension };

+            input.ReadTag(); // TryMergeFieldFrom expects that a tag was just read and will inspect the LastTag value

+

+            ExtensionSet<TestAllExtensions> extensionSet = null;

+            // test the legacy overload of TryMergeFieldFrom that takes a CodedInputStream

+            Assert.IsTrue(ExtensionSet.TryMergeFieldFrom(ref extensionSet, input));

+            Assert.AreEqual("abcd", ExtensionSet.Get(ref extensionSet, OptionalStringExtension));

+        }

+

+        [Test]

         public void TestEquals()

         {

             var message = new TestAllExtensions();

@@ -96,7 +116,22 @@
             var other = message.Clone();

 

             Assert.AreEqual(message, other);

-            Assert.AreEqual(message.CalculateSize(), message.CalculateSize());

+            Assert.AreEqual(message.CalculateSize(), other.CalculateSize());

+        }

+

+        [Test]

+        public void TestDefaultValueRoundTrip()

+        {

+            var message = new TestAllExtensions();

+            message.SetExtension(OptionalBoolExtension, false);

+            Assert.IsFalse(message.GetExtension(OptionalBoolExtension));

+            Assert.IsTrue(message.HasExtension(OptionalBoolExtension));

+

+            var bytes = message.ToByteArray();

+            var registry = new ExtensionRegistry { OptionalBoolExtension };

+            var parsed = TestAllExtensions.Parser.WithExtensionRegistry(registry).ParseFrom(bytes);

+            Assert.IsFalse(parsed.GetExtension(OptionalBoolExtension));

+            Assert.IsTrue(parsed.HasExtension(OptionalBoolExtension));

         }

     }

 }

diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
index b20eccc..7f36692 100644
--- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
+++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
@@ -124,11 +124,21 @@
             {
                 var stream = new MemoryStream();
                 var codedOutput = new CodedOutputStream(stream);
-                codec.ValueWriter(codedOutput, sampleValue);
+                WriteContext.Initialize(codedOutput, out WriteContext ctx);
+                try
+                {
+                    // only write the value using the codec
+                    codec.ValueWriter(ref ctx, sampleValue);
+                }
+                finally
+                {
+                    ctx.CopyStateTo(codedOutput);
+                }
+                
                 codedOutput.Flush();
                 stream.Position = 0;
                 var codedInput = new CodedInputStream(stream);
-                Assert.AreEqual(sampleValue, codec.ValueReader(codedInput));
+                Assert.AreEqual(sampleValue, codec.Read(codedInput));
                 Assert.IsTrue(codedInput.IsAtEnd);
             }
 
@@ -158,7 +168,7 @@
             {
                 // WriteTagAndValue ignores default values
                 var stream = new MemoryStream();
-                CodedOutputStream codedOutput;

+                CodedOutputStream codedOutput;
 #if !NET35
                 codedOutput = new CodedOutputStream(stream);
                 codec.WriteTagAndValue(codedOutput, codec.DefaultValue);
@@ -175,13 +185,23 @@
                 if (codec.DefaultValue != null) // This part isn't appropriate for message types.
                 {
                     codedOutput = new CodedOutputStream(stream);
-                    codec.ValueWriter(codedOutput, codec.DefaultValue);
+                    WriteContext.Initialize(codedOutput, out WriteContext ctx);
+                    try
+                    {
+                        // only write the value using the codec
+                        codec.ValueWriter(ref ctx, codec.DefaultValue);
+                    }
+                    finally
+                    {
+                        ctx.CopyStateTo(codedOutput);
+                    }
+                    
                     codedOutput.Flush();
                     Assert.AreNotEqual(0, stream.Position);
                     Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
                     stream.Position = 0;
                     var codedInput = new CodedInputStream(stream);
-                    Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput));
+                    Assert.AreEqual(codec.DefaultValue, codec.Read(codedInput));
                 }
             }
 
diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
index 718c3ed..1abed60 100644
--- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
+++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
@@ -269,8 +269,8 @@
         [Test]

         public void RequiredFieldsNoThrow()

         {

-            Assert.DoesNotThrow(() => TestRequired.Parser.ParseFrom(new byte[0]));

-            Assert.DoesNotThrow(() => (TestRequired.Parser as MessageParser).ParseFrom(new byte[0]));

+            Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser, new byte[0], m => { }));

+            Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser as MessageParser, new byte[0], m => { }));

         }

 

         [Test]

@@ -344,9 +344,9 @@
                 }

             };

 

-            byte[] bytes = message.ToByteArray();

-            TestAllTypes parsed = Proto2.TestAllTypes.Parser.ParseFrom(bytes);

-            Assert.AreEqual(message, parsed);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(Proto2.TestAllTypes.Parser, message);

         }

 

         [Test]

@@ -361,9 +361,11 @@
                 new RepeatedGroup_extension { A = 30 }

             });

 

-            byte[] bytes = message.ToByteArray();

-            TestAllExtensions extendable_parsed = TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }).ParseFrom(bytes);

-            Assert.AreEqual(message, extendable_parsed);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(

+                TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }),

+                message);

         }

 

         [Test]

@@ -372,9 +374,11 @@
             var message = new TestGroupExtension();

             message.SetExtension(TestNestedExtension.Extensions.OptionalGroupExtension, new TestNestedExtension.Types.OptionalGroup_extension { A = 10 });

 

-            byte[] bytes = message.ToByteArray();

-            TestGroupExtension extendable_parsed = TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }).ParseFrom(bytes);

-            Assert.AreEqual(message, extendable_parsed);

+            MessageParsingHelpers.AssertWritingMessage(message);

+            

+            MessageParsingHelpers.AssertRoundtrip(

+                TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }),

+                message);

         }

     }

 }

diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
index 103df7d..06af5e9 100644
--- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
+++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
@@ -131,8 +131,10 @@
             // Without setting any values, there's nothing to write.

             byte[] bytes = message.ToByteArray();

             Assert.AreEqual(0, bytes.Length);

-            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);

-            Assert.AreEqual(message, parsed);

+

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message);

         }

 

         [Test]

@@ -164,9 +166,9 @@
                 SingleUint64 = ulong.MaxValue

             };

 

-            byte[] bytes = message.ToByteArray();

-            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);

-            Assert.AreEqual(message, parsed);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message);

         }

 

         [Test]

@@ -198,9 +200,9 @@
                 RepeatedUint64 = { ulong.MaxValue, uint.MinValue }

             };

 

-            byte[] bytes = message.ToByteArray();

-            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);

-            Assert.AreEqual(message, parsed);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message);

         }

 

         // Note that not every map within map_unittest_proto3 is used. They all go through very

@@ -230,9 +232,9 @@
                 }

             };

 

-            byte[] bytes = message.ToByteArray();

-            TestMap parsed = TestMap.Parser.ParseFrom(bytes);

-            Assert.AreEqual(message, parsed);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(TestMap.Parser, message);

         }

 

         [Test]

@@ -246,9 +248,16 @@
             byte[] bytes = message.ToByteArray();

             Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte)

 

-            var parsed = TestMap.Parser.ParseFrom(bytes);

-            Assert.AreEqual(1, parsed.MapInt32Bytes.Count);

-            Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                bytes,

+                parsed=>

+                {

+                    Assert.AreEqual(1, parsed.MapInt32Bytes.Count);

+                    Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);

+                });

         }

 

         [Test]

@@ -265,8 +274,13 @@
             output.WriteMessage(nestedMessage);

             output.Flush();

 

-            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());

-            Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]);

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                memoryStream.ToArray(),

+                parsed =>

+                {

+                    Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]);

+                });

         }

 

         [Test]

@@ -282,8 +296,13 @@
             output.WriteInt32(key);

             output.Flush();

 

-            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());

-            Assert.AreEqual(0.0, parsed.MapInt32Double[key]);

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                memoryStream.ToArray(),

+                parsed =>

+                {

+                    Assert.AreEqual(0.0, parsed.MapInt32Double[key]);

+                });

         }

 

         [Test]

@@ -299,8 +318,13 @@
             output.WriteInt32(key);

             output.Flush();

 

-            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());

-            Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]);

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                memoryStream.ToArray(),

+                parsed =>

+                {

+                    Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]);

+                });

         }

 

         [Test]

@@ -327,8 +351,13 @@
             output.WriteInt32(extra);

             output.Flush();

 

-            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());

-            Assert.AreEqual(value, parsed.MapInt32Int32[key]);

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                memoryStream.ToArray(),

+                parsed =>

+                {

+                    Assert.AreEqual(value, parsed.MapInt32Int32[key]);

+                });

         }

 

         [Test]

@@ -351,8 +380,13 @@
             output.WriteInt32(key);

             output.Flush();

 

-            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());

-            Assert.AreEqual(value, parsed.MapInt32Int32[key]);

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                memoryStream.ToArray(),

+                parsed =>

+                {

+                    Assert.AreEqual(value, parsed.MapInt32Int32[key]);

+                });

         }

 

         [Test]

@@ -397,13 +431,19 @@
             output.WriteInt32(value3);

 

             output.Flush();

-            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());

-            var expected = new TestMap

-            {

-                MapInt32Int32 = { { key1, value1 }, { key3, value3 } },

-                MapStringString = { { key2, value2 } }

-            };

-            Assert.AreEqual(expected, parsed);

+

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                memoryStream.ToArray(),

+                parsed =>

+                {

+                    var expected = new TestMap

+                    {

+                        MapInt32Int32 = { { key1, value1 }, { key3, value3 } },

+                        MapStringString = { { key2, value2 } }

+                    };

+                    Assert.AreEqual(expected, parsed);

+                });

         }

 

         [Test]

@@ -433,8 +473,13 @@
             output.WriteInt32(value2);

             output.Flush();

 

-            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());

-            Assert.AreEqual(value2, parsed.MapInt32Int32[key]);

+            MessageParsingHelpers.AssertReadingMessage(

+                TestMap.Parser,

+                memoryStream.ToArray(),

+                parsed =>

+                {

+                    Assert.AreEqual(value2, parsed.MapInt32Int32[key]);

+                });

         }

 

         [Test]

@@ -619,9 +664,12 @@
             var bytes = message.ToByteArray();

             Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!

 

-            var message2 = TestAllTypes.Parser.ParseFrom(bytes);

-            Assert.AreEqual(message, message2);

-            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage =>

+            {

+                Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase);

+            });

         }

 

         [Test]

@@ -633,9 +681,12 @@
             var bytes = message.ToByteArray();

             Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized

 

-            var message2 = TestAllTypes.Parser.ParseFrom(bytes);

-            Assert.AreEqual(message, message2);

-            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);

+            MessageParsingHelpers.AssertWritingMessage(message);

+

+            MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage =>

+            {

+                Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase);

+            });

         }

 

         [Test]

@@ -651,10 +702,14 @@
             message.WriteTo(output);

             output.Flush();

 

-            stream.Position = 0;

-            var parsed = TestAllTypes.Parser.ParseFrom(stream);

-            // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.

-            // Assert.AreEqual(message, parsed);

+            MessageParsingHelpers.AssertReadingMessage(

+                TestAllTypes.Parser,

+                stream.ToArray(),

+                parsed =>

+                {

+                    // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.

+                    // Assert.AreEqual(message, parsed);

+                });

         }

 

         [Test]

@@ -663,8 +718,15 @@
             // Simple way of ensuring we can skip all kinds of fields.

             var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();

             var empty = Empty.Parser.ParseFrom(data);

-            // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.

-            // Assert.AreNotEqual(new Empty(), empty);

+

+            MessageParsingHelpers.AssertReadingMessage(

+                Empty.Parser,

+                data,

+                parsed =>

+                {

+                    // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.

+                    // Assert.AreNotEqual(new Empty(), empty);

+                });

         }

 

         // This was originally seen as a conformance test failure.

@@ -674,7 +736,7 @@
             // 130, 3 is the message tag

             // 1 is the data length - but there's no data.

             var data = new byte[] { 130, 3, 1 };

-            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(data));

+            MessageParsingHelpers.AssertReadingMessageThrows<TestAllTypes, InvalidProtocolBufferException>(TestAllTypes.Parser, data);

         }

 

         /// <summary>

@@ -695,7 +757,7 @@
             output.Flush();

 

             stream.Position = 0;

-            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(stream));

+            MessageParsingHelpers.AssertReadingMessageThrows<TestAllTypes, InvalidProtocolBufferException>(TestAllTypes.Parser, stream.ToArray());

         }

 

         [Test]

diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
index 1a7953d..cdfa98e 100644
--- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -1,11 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net451;netcoreapp2.1</TargetFrameworks>
+    <TargetFrameworks>net451;netcoreapp2.1;net50</TargetFrameworks>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
-    <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
     <IsPackable>False</IsPackable>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/csharp/src/Google.Protobuf.Test/IssuesTest.cs b/csharp/src/Google.Protobuf.Test/IssuesTest.cs
index 941bce0..2904c46 100644
--- a/csharp/src/Google.Protobuf.Test/IssuesTest.cs
+++ b/csharp/src/Google.Protobuf.Test/IssuesTest.cs
@@ -108,7 +108,7 @@
 

             // we still must read the tag correctly, even though the tag is at the very end of our limited input

             // (which is a corner case and will most likely result in an error when trying to read value of the field

-            // decribed by this tag, but it would be a logical error not to read the tag that's actually present).

+            // described by this tag, but it would be a logical error not to read the tag that's actually present).

             // See https://github.com/protocolbuffers/protobuf/pull/7289

             cis.AssertNextTag(WireFormat.MakeTag(11, WireFormat.WireType.Varint));

         }

diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
index b07a841..1a65093 100644
--- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
@@ -40,6 +40,7 @@
 using static Google.Protobuf.JsonParserTest; // For WrapInQuotes
 using System.IO;
 using Google.Protobuf.Collections;
+using ProtobufUnittest;
 
 namespace Google.Protobuf
 {
@@ -154,6 +155,48 @@
         }
 
         [Test]
+        public void WithFormatDefaultValues_DoesNotAffectMessageFields()
+        {
+            var message = new TestAllTypes();
+            var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true));
+            var json = formatter.Format(message);
+            Assert.IsFalse(json.Contains("\"singleNestedMessage\""));
+            Assert.IsFalse(json.Contains("\"singleForeignMessage\""));
+            Assert.IsFalse(json.Contains("\"singleImportMessage\""));
+        }
+
+        [Test]
+        public void WithFormatDefaultValues_DoesNotAffectProto3OptionalFields()
+        {
+            var message = new TestProto3Optional();
+            message.OptionalInt32 = 0;
+            var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true));
+            var json = formatter.Format(message);
+            // The non-optional proto3 fields are formatted, as is the optional-but-specified field.
+            AssertJson("{ 'optionalInt32': 0, 'singularInt32': 0, 'singularInt64': '0' }", json);
+        }
+
+        [Test]
+        public void WithFormatDefaultValues_DoesNotAffectProto2Fields()
+        {
+            var message = new TestProtos.Proto2.ForeignMessage();
+            message.C = 0;
+            var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true));
+            var json = formatter.Format(message);
+            // The specified field is formatted, but the non-specified field (d) is not.
+            AssertJson("{ 'c': 0 }", json);
+        }
+
+        [Test]
+        public void WithFormatDefaultValues_DoesNotAffectOneofFields()
+        {
+            var message = new TestOneof();
+            var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true));
+            var json = formatter.Format(message);
+            AssertJson("{ }", json);
+        }
+
+        [Test]
         public void RepeatedField()
         {
             AssertJson("{ 'repeatedInt32': [ 1, 2, 3, 4, 5 ] }",
@@ -183,6 +226,28 @@
                 JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } }));
         }
 
+        [Test]
+        public void NullValueOutsideStruct()
+        {
+            var message = new NullValueOutsideStruct { NullValue = NullValue.NullValue };
+            AssertJson("{ 'nullValue': null }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void NullValueNotInOneof()
+        {
+            var message = new NullValueNotInOneof();
+            AssertJson("{ }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void NullValueNotInOneof_FormatDefaults()
+        {
+            var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true));
+            var message = new NullValueNotInOneof();
+            AssertJson("{ 'nullValue': null }", formatter.Format(message));
+        }
+
         [TestCase(1.0, "1")]
         [TestCase(double.NaN, "'NaN'")]
         [TestCase(double.PositiveInfinity, "'Infinity'")]
@@ -313,14 +378,16 @@
         }
 
         [Test]
-        public void WrapperFormatting_IncludeNull()
+        public void WrapperFormatting_FormatDefaultValuesDoesNotFormatNull()
         {
             // The actual JSON here is very large because there are lots of fields. Just test a couple of them.
             var message = new TestWellKnownTypes { Int32Field = 10 };
             var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true));
             var actualJson = formatter.Format(message);
-            Assert.IsTrue(actualJson.Contains("\"int64Field\": null"));
-            Assert.IsFalse(actualJson.Contains("\"int32Field\": null"));
+            // This *used* to include "int64Field": null, but that was a bug.
+            // WithDefaultValues should not affect message fields, including wrapper types.
+            Assert.IsFalse(actualJson.Contains("\"int64Field\": null"));
+            Assert.IsTrue(actualJson.Contains("\"int32Field\": 10"));
         }
 
         [Test]
@@ -602,6 +669,13 @@
             AssertWriteValue(value, "[ 1, 2, 3 ]");
         }
 
+        [Test]
+        public void Proto2_DefaultValuesWritten()
+        {
+            var value = new ProtobufTestMessages.Proto2.TestAllTypesProto2() { FieldName13 = 0 };
+            AssertWriteValue(value, "{ 'FieldName13': 0 }");
+        }
+
         private static void AssertWriteValue(object value, string expectedJson)
         {
             var writer = new StringWriter();
diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
index a6cf04a..69c9eb6 100644
--- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -34,7 +34,9 @@
 using Google.Protobuf.TestProtos;
 using Google.Protobuf.WellKnownTypes;
 using NUnit.Framework;
+using ProtobufTestMessages.Proto2;
 using System;
+using UnitTest.Issues.TestProtos;
 
 namespace Google.Protobuf
 {
@@ -549,9 +551,13 @@
         }
 
         [Test]
+        // Skip these test cases in .NET 5 because floating point parsing supports bigger values.
+        // These big values won't throw an error in the test.
+#if !NET5_0
         [TestCase("1.7977e308")]
         [TestCase("-1.7977e308")]
         [TestCase("1e309")]
+#endif
         [TestCase("1,0")]
         [TestCase("1.0.0")]
         [TestCase("+1")]
@@ -950,6 +956,16 @@
         }
 
         [Test]
+        public void Proto2_DefaultValuesPreserved()
+        {
+            string json = "{ \"FieldName13\": 0 }";
+            var parsed = TestAllTypesProto2.Parser.ParseJson(json);
+            Assert.False(parsed.HasFieldName10);
+            Assert.True(parsed.HasFieldName13);
+            Assert.AreEqual(0, parsed.FieldName13);
+        }
+
+        [Test]
         [TestCase("5")]
         [TestCase("\"text\"")]
         [TestCase("[0, 1, 2]")]
@@ -963,6 +979,43 @@
             Assert.AreEqual(expected, actual);
         }
 
+        [Test]
+        public void NullValueOutsideStruct_NullLiteral()
+        {
+            string json = "{ \"nullValue\": null }";
+            var message = NullValueOutsideStruct.Parser.ParseJson(json);
+            Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase);
+        }
+
+        [Test]
+        public void NullValueNotInOneof_NullLiteral()
+        {
+            // We'd only normally see this with FormatDefaultValues set to true.
+            string json = "{ \"nullValue\": null }";
+            var message = NullValueNotInOneof.Parser.ParseJson(json);
+            Assert.AreEqual(NullValue.NullValue, message.NullValue);
+        }
+
+        // NullValue used to only be converted to the null literal when part of a struct.
+        // Otherwise, it would end up as a string "NULL_VALUE" (the name of the enum value).
+        // We still parse that form, for compatibility.
+        [Test]
+        public void NullValueOutsideStruct_Compatibility()
+        {
+            string json = "{ \"nullValue\": \"NULL_VALUE\" }";
+            var message = NullValueOutsideStruct.Parser.ParseJson(json);
+            Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase);
+        }
+
+        [Test]
+        public void NullValueNotInOneof_Compatibility()
+        {
+            // We'd only normally see this with FormatDefaultValues set to true.
+            string json = "{ \"nullValue\": \"NULL_VALUE\" }";
+            var message = NullValueNotInOneof.Parser.ParseJson(json);
+            Assert.AreEqual(NullValue.NullValue, message.NullValue);
+        }
+
         /// <summary>
         /// Various tests use strings which have quotes round them for parsing or as the result
         /// of formatting, but without those quotes being specified in the tests (for the sake of readability).
diff --git a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
index df43eff..0cbc0a4 100644
--- a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
@@ -199,8 +199,12 @@
         [TestCase("1e-")]
         [TestCase("--")]
         [TestCase("--1")]
+        // Skip these test cases in .NET 5 because floating point parsing supports bigger values.
+        // These big values won't throw an error in the test.
+#if !NET5_0
         [TestCase("-1.7977e308")]
         [TestCase("1.7977e308")]
+#endif
         public void InvalidNumberValue(string json)
         {
             AssertThrowsAfter(json);
diff --git a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
new file mode 100644
index 0000000..22adcaa
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
@@ -0,0 +1,296 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+using Google.Protobuf;
+using Google.Protobuf.Reflection;
+using System.Buffers;
+using pb = global::Google.Protobuf;
+using pbr = global::Google.Protobuf.Reflection;
+using NUnit.Framework;
+using System.IO;
+using System;
+using Google.Protobuf.Buffers;
+
+namespace Google.Protobuf
+{
+    public class LegacyGeneratedCodeTest
+    {
+        [Test]
+        public void IntermixingOfNewAndLegacyGeneratedCodeWorksWithCodedInputStream()
+        {
+            var message = new ParseContextEnabledMessageB
+            {
+                A = new LegacyGeneratedCodeMessageA
+                {
+                    Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 }
+                },
+                OptionalInt32 = 6789
+            };
+            var data = message.ToByteArray();
+
+            // when parsing started using CodedInputStream and a message with legacy generated code
+            // is encountered somewhere in the parse tree, we still need to be able to use its
+            // MergeFrom(CodedInputStream) method to parse correctly.
+            var codedInput = new CodedInputStream(data);
+            var parsed = new ParseContextEnabledMessageB();
+            codedInput.ReadRawMessage(parsed);
+            Assert.IsTrue(codedInput.IsAtEnd);
+
+            Assert.AreEqual(12345, parsed.A.Bb.OptionalInt32);
+            Assert.AreEqual(6789, parsed.OptionalInt32);
+        }
+
+        [Test]
+        public void LegacyGeneratedCodeThrowsWithReadOnlySequence()
+        {
+            var message = new ParseContextEnabledMessageB
+            {
+                A = new LegacyGeneratedCodeMessageA
+                {
+                    Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 }
+                },
+                OptionalInt32 = 6789
+            };
+            var data = message.ToByteArray();
+
+            // if parsing started using ReadOnlySequence and we don't have a CodedInputStream
+            // instance at hand, we cannot fall back to the legacy MergeFrom(CodedInputStream)
+            // method and parsing will fail. As a consequence, one can only use parsing
+            // from ReadOnlySequence if all the messages in the parsing tree have their generated
+            // code up to date.
+            var exception = Assert.Throws<InvalidProtocolBufferException>(() =>
+            {
+                ParseContext.Initialize(new ReadOnlySequence<byte>(data), out ParseContext parseCtx);
+                var parsed = new ParseContextEnabledMessageB();
+                ParsingPrimitivesMessages.ReadRawMessage(ref parseCtx, parsed);
+            });
+            Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables ParseContext-based parsing. You might need to regenerate the generated protobuf code.", exception.Message);
+        }
+
+        [Test]
+        public void IntermixingOfNewAndLegacyGeneratedCodeWorksWithCodedOutputStream()
+        {
+            // when serialization started using CodedOutputStream and a message with legacy generated code
+            // is encountered somewhere in the parse tree, we still need to be able to use its
+            // WriteTo(CodedOutputStream) method to serialize correctly.
+            var ms = new MemoryStream();
+            var codedOutput = new CodedOutputStream(ms);
+            var message = new ParseContextEnabledMessageB
+            {
+                A = new LegacyGeneratedCodeMessageA
+                {
+                    Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 }
+                },
+                OptionalInt32 = 6789
+            };
+            message.WriteTo(codedOutput);
+            codedOutput.Flush();
+
+            var codedInput = new CodedInputStream(ms.ToArray());
+            var parsed = new ParseContextEnabledMessageB();
+            codedInput.ReadRawMessage(parsed);
+            Assert.IsTrue(codedInput.IsAtEnd);
+
+            Assert.AreEqual(12345, parsed.A.Bb.OptionalInt32);
+            Assert.AreEqual(6789, parsed.OptionalInt32);
+        }
+
+        [Test]
+        public void LegacyGeneratedCodeThrowsWithIBufferWriter()
+        {
+            // if serialization started using IBufferWriter and we don't have a CodedOutputStream
+            // instance at hand, we cannot fall back to the legacy WriteTo(CodedOutputStream)
+            // method and serializatin will fail. As a consequence, one can only use serialization
+            // to IBufferWriter if all the messages in the parsing tree have their generated
+            // code up to date.
+            var message = new ParseContextEnabledMessageB
+            {
+                A = new LegacyGeneratedCodeMessageA
+                {
+                    Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 }
+                },
+                OptionalInt32 = 6789
+            };
+            var exception = Assert.Throws<InvalidProtocolBufferException>(() =>
+            {
+                WriteContext.Initialize(new TestArrayBufferWriter<byte>(), out WriteContext writeCtx);
+                ((IBufferMessage)message).InternalWriteTo(ref writeCtx);
+            });
+            Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code.", exception.Message);
+        }
+
+        // hand-modified version of a generated message that only provides the legacy
+        // MergeFrom(CodedInputStream) method and doesn't implement IBufferMessage.
+        private sealed partial class LegacyGeneratedCodeMessageA : pb::IMessage {
+          private pb::UnknownFieldSet _unknownFields;
+
+          pbr::MessageDescriptor pb::IMessage.Descriptor => throw new System.NotImplementedException();
+
+          /// <summary>Field number for the "bb" field.</summary>
+          public const int BbFieldNumber = 1;
+          private ParseContextEnabledMessageB bb_;
+          public ParseContextEnabledMessageB Bb {
+            get { return bb_; }
+            set {
+              bb_ = value;
+            }
+          }
+
+          public void WriteTo(pb::CodedOutputStream output) {
+            if (bb_ != null) {
+              output.WriteRawTag(10);
+              output.WriteMessage(Bb);
+            }
+            if (_unknownFields != null) {
+              _unknownFields.WriteTo(output);
+            }
+          }
+
+          public int CalculateSize() {
+            int size = 0;
+            if (bb_ != null) {
+              size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb);
+            }
+            if (_unknownFields != null) {
+              size += _unknownFields.CalculateSize();
+            }
+            return size;
+          }
+
+          public void MergeFrom(pb::CodedInputStream input) {
+            uint tag;
+            while ((tag = input.ReadTag()) != 0) {
+              switch(tag) {
+                default:
+                  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+                  break;
+                case 10: {
+                  if (bb_ == null) {
+                    Bb = new ParseContextEnabledMessageB();
+                  }
+                  input.ReadMessage(Bb);
+                  break;
+                }
+              }
+            }
+          }
+        }
+
+        // hand-modified version of a generated message that does provide
+        // the new InternalMergeFrom(ref ParseContext) method.
+        private sealed partial class ParseContextEnabledMessageB : pb::IBufferMessage {
+          private pb::UnknownFieldSet _unknownFields;
+
+          pbr::MessageDescriptor pb::IMessage.Descriptor => throw new System.NotImplementedException();
+
+          /// <summary>Field number for the "a" field.</summary>
+          public const int AFieldNumber = 1;
+          private LegacyGeneratedCodeMessageA a_;
+          public LegacyGeneratedCodeMessageA A {
+            get { return a_; }
+            set {
+              a_ = value;
+            }
+          }
+
+          /// <summary>Field number for the "optional_int32" field.</summary>
+          public const int OptionalInt32FieldNumber = 2;
+          private int optionalInt32_;
+          public int OptionalInt32 {
+            get { return optionalInt32_; }
+            set {
+              optionalInt32_ = value;
+            }
+          }
+
+          public void WriteTo(pb::CodedOutputStream output) {
+            output.WriteRawMessage(this);
+          }
+
+          void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output)
+          {
+            if (a_ != null)
+            {
+              output.WriteRawTag(10);
+              output.WriteMessage(A);
+            }
+            if (OptionalInt32 != 0)
+            {
+              output.WriteRawTag(16);
+              output.WriteInt32(OptionalInt32);
+            }
+            if (_unknownFields != null)
+            {
+              _unknownFields.WriteTo(ref output);
+            }
+          }
+
+          public int CalculateSize() {
+            int size = 0;
+            if (a_ != null) {
+              size += 1 + pb::CodedOutputStream.ComputeMessageSize(A);
+            }
+            if (OptionalInt32 != 0) {
+              size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32);
+            }
+            if (_unknownFields != null) {
+              size += _unknownFields.CalculateSize();
+            }
+            return size;
+          }
+          public void MergeFrom(pb::CodedInputStream input) {
+            input.ReadRawMessage(this);
+          }
+
+          void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+            uint tag;
+            while ((tag = input.ReadTag()) != 0) {
+              switch(tag) {
+                default:
+                  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                  break;
+                case 10: {
+                  if (a_ == null) {
+                    A = new LegacyGeneratedCodeMessageA();
+                  }
+                  input.ReadMessage(A);
+                  break;
+                }
+                case 16: {
+                  OptionalInt32 = input.ReadInt32();
+                  break;
+                }
+              }
+            }
+          }
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
new file mode 100644
index 0000000..05f1e36
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
@@ -0,0 +1,154 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using NUnit.Framework;
+using System;
+using System.Buffers;
+using Google.Protobuf.Buffers;
+
+namespace Google.Protobuf
+{
+    public static class MessageParsingHelpers
+    {
+        public static void AssertReadingMessage<T>(MessageParser<T> parser, byte[] bytes, Action<T> assert) where T : IMessage<T>
+        {
+            var parsedMsg = parser.ParseFrom(bytes);
+            assert(parsedMsg);
+
+            // Load content as single segment
+            parsedMsg = parser.ParseFrom(new ReadOnlySequence<byte>(bytes));
+            assert(parsedMsg);
+
+            // Load content as multiple segments
+            parsedMsg = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes));
+            assert(parsedMsg);
+
+            // Load content as ReadOnlySpan
+            parsedMsg = parser.ParseFrom(new ReadOnlySpan<byte>(bytes));
+            assert(parsedMsg);
+        }
+
+        public static void AssertReadingMessage(MessageParser parser, byte[] bytes, Action<IMessage> assert)
+        {
+            var parsedMsg = parser.ParseFrom(bytes);
+            assert(parsedMsg);
+
+            // Load content as single segment
+            parsedMsg = parser.ParseFrom(new ReadOnlySequence<byte>(bytes));
+            assert(parsedMsg);
+
+            // Load content as multiple segments
+            parsedMsg = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes));
+            assert(parsedMsg);
+
+            // Load content as ReadOnlySpan
+            parsedMsg = parser.ParseFrom(new ReadOnlySpan<byte>(bytes));
+            assert(parsedMsg);
+        }
+
+        public static void AssertReadingMessageThrows<TMessage, TException>(MessageParser<TMessage> parser, byte[] bytes)
+            where TMessage : IMessage<TMessage>
+            where TException : Exception
+        {
+            Assert.Throws<TException>(() => parser.ParseFrom(bytes));
+
+            Assert.Throws<TException>(() => parser.ParseFrom(new ReadOnlySequence<byte>(bytes)));
+
+            Assert.Throws<TException>(() => parser.ParseFrom(new ReadOnlySpan<byte>(bytes)));
+        }
+
+        public static void AssertRoundtrip<T>(MessageParser<T> parser, T message, Action<T> additionalAssert = null) where T : IMessage<T>
+        {
+            var bytes = message.ToByteArray();
+
+            // also serialize using IBufferWriter and check it leads to the same data
+            var bufferWriter = new TestArrayBufferWriter<byte>();
+            message.WriteTo(bufferWriter);
+            Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray(), "Both serialization approaches need to result in the same data.");
+
+            var parsedMsg = parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsedMsg);
+            additionalAssert?.Invoke(parsedMsg);
+
+            // Load content as single segment
+            parsedMsg = parser.ParseFrom(new ReadOnlySequence<byte>(bytes));
+            Assert.AreEqual(message, parsedMsg);
+            additionalAssert?.Invoke(parsedMsg);
+
+            // Load content as multiple segments
+            parsedMsg = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes));
+            Assert.AreEqual(message, parsedMsg);
+            additionalAssert?.Invoke(parsedMsg);
+
+            // Load content as ReadOnlySpan
+            parsedMsg = parser.ParseFrom(new ReadOnlySpan<byte>(bytes));
+            Assert.AreEqual(message, parsedMsg);
+            additionalAssert?.Invoke(parsedMsg);
+        }
+
+        public static void AssertWritingMessage(IMessage message)
+        {
+            // serialize using CodedOutputStream
+            var bytes = message.ToByteArray();
+
+            int messageSize = message.CalculateSize(); 
+            Assert.AreEqual(message.CalculateSize(), bytes.Length);
+
+            // serialize using IBufferWriter and check it leads to the same output
+            var bufferWriter = new TestArrayBufferWriter<byte>();
+            message.WriteTo(bufferWriter);
+            Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray());
+
+            // serialize into a single span and check it leads to the same output
+            var singleSpan = new Span<byte>(new byte[messageSize]);
+            message.WriteTo(singleSpan);
+            Assert.AreEqual(bytes, singleSpan.ToArray());
+
+            // test for different IBufferWriter.GetSpan() segment sizes
+            for (int blockSize = 1; blockSize < 256; blockSize *= 2)
+            {
+                var segmentedBufferWriter = new TestArrayBufferWriter<byte>();
+                segmentedBufferWriter.MaxGrowBy = blockSize;
+                message.WriteTo(segmentedBufferWriter);
+                Assert.AreEqual(bytes, segmentedBufferWriter.WrittenSpan.ToArray());
+            }
+
+            // if the full message is small enough, try serializing directly into stack-allocated buffer
+            if (bytes.Length <= 256)
+            {
+                Span<byte> stackAllocBuffer = stackalloc byte[bytes.Length];
+                message.WriteTo(stackAllocBuffer);
+                Assert.AreEqual(bytes, stackAllocBuffer.ToArray());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs
new file mode 100644
index 0000000..46a8c57
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs
@@ -0,0 +1,153 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using NUnit.Framework;
+using ProtobufUnittest;
+using System;
+using System.IO;
+using UnitTest.Issues.TestProtos;
+
+namespace Google.Protobuf.Test
+{
+    class Proto3OptionalTest
+    {
+        [Test]
+        public void OptionalInt32FieldLifecycle()
+        {
+            var message = new TestProto3Optional();
+            Assert.IsFalse(message.HasOptionalInt32);
+            Assert.AreEqual(0, message.OptionalInt32);
+
+            message.OptionalInt32 = 5;
+            Assert.IsTrue(message.HasOptionalInt32);
+            Assert.AreEqual(5, message.OptionalInt32);
+
+            message.OptionalInt32 = 0;
+            Assert.IsTrue(message.HasOptionalInt32);
+            Assert.AreEqual(0, message.OptionalInt32);
+
+            message.ClearOptionalInt32();
+            Assert.IsFalse(message.HasOptionalInt32);
+            Assert.AreEqual(0, message.OptionalInt32);
+        }
+
+        [Test]
+        public void OptionalStringFieldLifecycle()
+        {
+            var message = new TestProto3Optional();
+            Assert.IsFalse(message.HasOptionalString);
+            Assert.AreEqual("", message.OptionalString);
+
+            message.OptionalString = "x";
+            Assert.IsTrue(message.HasOptionalString);
+            Assert.AreEqual("x", message.OptionalString);
+
+            message.OptionalString = "";
+            Assert.IsTrue(message.HasOptionalString);
+            Assert.AreEqual("", message.OptionalString);
+
+            message.ClearOptionalString();
+            Assert.IsFalse(message.HasOptionalString);
+            Assert.AreEqual("", message.OptionalString);
+
+            Assert.Throws<ArgumentNullException>(() => message.OptionalString = null);
+        }
+
+        [Test]
+        public void Clone()
+        {
+            var original = new TestProto3Optional { OptionalInt64 = 0L };
+
+            var clone = original.Clone();
+            Assert.False(clone.HasOptionalInt32);
+            Assert.AreEqual(0, clone.OptionalInt32);
+            Assert.True(clone.HasOptionalInt64);
+            Assert.AreEqual(0L, clone.OptionalInt64);
+        }
+
+        [Test]
+        public void Serialization_NotSet()
+        {
+            var stream = new MemoryStream();
+            var message = new TestProto3Optional();
+            message.WriteTo(stream);
+            Assert.AreEqual(0, stream.Length);
+        }
+
+        [Test]
+        public void Serialization_SetToDefault()
+        {
+            var stream = new MemoryStream();
+            var message = new TestProto3Optional { OptionalInt32 = 0 };
+            message.WriteTo(stream);
+            Assert.AreEqual(2, stream.Length); // Tag and value
+        }
+
+        [Test]
+        public void Serialization_Roundtrip()
+        {
+            var original = new TestProto3Optional { OptionalInt64 = 0L, OptionalFixed32 = 5U };
+            var stream = new MemoryStream();
+            original.WriteTo(stream);
+            stream.Position = 0;
+            var deserialized = TestProto3Optional.Parser.ParseFrom(stream);
+
+            Assert.AreEqual(0, deserialized.OptionalInt32);
+            Assert.IsFalse(deserialized.HasOptionalInt32);
+
+            Assert.AreEqual(0L, deserialized.OptionalInt64);
+            Assert.IsTrue(deserialized.HasOptionalInt64);
+
+            Assert.AreEqual(5U, deserialized.OptionalFixed32);
+            Assert.IsTrue(deserialized.HasOptionalFixed32);
+        }
+
+        [Test]
+        public void Equality_IgnoresPresence()
+        {
+            var message1 = new TestProto3Optional { OptionalInt32 = 0 };
+            var message2 = new TestProto3Optional();
+
+            Assert.IsTrue(message1.Equals(message2));
+            message1.ClearOptionalInt32();
+        }
+
+        [Test]
+        public void MixedFields()
+        {
+            var descriptor = MixedRegularAndOptional.Descriptor;
+            Assert.AreEqual(1, descriptor.Oneofs.Count);
+            Assert.AreEqual(0, descriptor.RealOneofCount);
+            Assert.True(descriptor.Oneofs[0].IsSynthetic);
+        }
+    }
+}
diff --git a/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
new file mode 100644
index 0000000..f0248ac
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
@@ -0,0 +1,139 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Google.Protobuf
+{
+    internal static class ReadOnlySequenceFactory
+    {
+        /// <summary>
+        /// Create a sequence from the specified data. The data will be divided up into segments in the sequence.
+        /// </summary>
+        public static ReadOnlySequence<byte> CreateWithContent(byte[] data, int segmentSize = 1, bool addEmptySegmentDelimiters = true)
+        {
+            var segments = new List<byte[]>();
+
+            if (addEmptySegmentDelimiters)
+            {
+                segments.Add(new byte[0]);
+            }
+
+            var currentIndex = 0;
+            while (currentIndex < data.Length)
+            {
+                var segment = new List<byte>();
+                while (segment.Count < segmentSize && currentIndex < data.Length)
+                {
+                    segment.Add(data[currentIndex++]);
+                }
+                segments.Add(segment.ToArray());
+
+                if (addEmptySegmentDelimiters)
+                {
+                    segments.Add(new byte[0]);
+                }
+            }
+
+            return CreateSegments(segments.ToArray());
+        }
+
+        /// <summary>
+        /// Originally from corefx, and has been contributed to Protobuf
+        /// https://github.com/dotnet/corefx/blob/e99ec129cfd594d53f4390bf97d1d736cff6f860/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs
+        /// </summary>
+        private static ReadOnlySequence<byte> CreateSegments(params byte[][] inputs)
+        {
+            if (inputs == null || inputs.Length == 0)
+            {
+                throw new InvalidOperationException();
+            }
+
+            int i = 0;
+
+            BufferSegment last = null;
+            BufferSegment first = null;
+
+            do
+            {
+                byte[] s = inputs[i];
+                int length = s.Length;
+                int dataOffset = length;
+                var chars = new byte[length * 2];
+
+                for (int j = 0; j < length; j++)
+                {
+                    chars[dataOffset + j] = s[j];
+                }
+
+                // Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array
+                var memory = new Memory<byte>(chars).Slice(length, length);
+
+                if (first == null)
+                {
+                    first = new BufferSegment(memory);
+                    last = first;
+                }
+                else
+                {
+                    last = last.Append(memory);
+                }
+                i++;
+            } while (i < inputs.Length);
+
+            return new ReadOnlySequence<byte>(first, 0, last, last.Memory.Length);
+        }
+
+        private class BufferSegment : ReadOnlySequenceSegment<byte>
+        {
+            public BufferSegment(Memory<byte> memory)
+            {
+                Memory = memory;
+            }
+
+            public BufferSegment Append(Memory<byte> memory)
+            {
+                var segment = new BufferSegment(memory)
+                {
+                    RunningIndex = RunningIndex + Memory.Length
+                };
+                Next = segment;
+                return segment;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs
new file mode 100644
index 0000000..f2d9a2d
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs
@@ -0,0 +1,119 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using NUnit.Framework;
+using System.Diagnostics;
+using System;
+using System.Reflection;
+using System.IO;
+
+namespace Google.Protobuf
+{
+    public class RefStructCompatibilityTest
+    {
+        /// <summary>
+        /// Checks that the generated code can be compiler with an old C# compiler.
+        /// The reason why this test is needed is that even though dotnet SDK projects allow to set LangVersion,
+        /// this setting doesn't accurately simulate compilation with an actual old pre-roslyn C# compiler.
+        /// For instance, the "ref struct" types are only supported by C# 7.2 and higher, but even if
+        /// LangVersion is set low, the roslyn compiler still understands the concept of ref struct
+        /// and silently accepts them. Therefore we try to build the generated code with an actual old C# compiler
+        /// to be able to catch these sort of compatibility problems.
+        /// </summary>
+        [Test]
+        public void GeneratedCodeCompilesWithOldCsharpCompiler()
+        {
+            if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+            {
+                // This tests needs old C# compiler which is only available on Windows. Skipping it on all other platforms.
+                return;
+            }
+
+            var currentAssemblyDir = Path.GetDirectoryName(typeof(RefStructCompatibilityTest).GetTypeInfo().Assembly.Location);
+            var testProtosProjectDir = Path.GetFullPath(Path.Combine(currentAssemblyDir, "..", "..", "..", "..", "Google.Protobuf.Test.TestProtos"));
+            var testProtosOutputDir = (currentAssemblyDir.Contains("bin/Debug/") || currentAssemblyDir.Contains("bin\\Debug\\")) ? "bin\\Debug\\net45" : "bin\\Release\\net45";
+
+            // If "ref struct" types are used in the generated code, compilation with an old compiler will fail with the following error:
+            // "XYZ is obsolete: 'Types with embedded references are not supported in this version of your compiler.'"
+            // We build the code with GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE to avoid the use of ref struct in the generated code.
+            var compatibilityFlag = "-define:GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE";
+            var sources = "*.cs";  // the generated sources from the TestProtos project
+            var args = $"-langversion:3 -target:library {compatibilityFlag} -reference:{testProtosOutputDir}\\Google.Protobuf.dll -out:{testProtosOutputDir}\\TestProtos.RefStructCompatibilityTest.OldCompiler.dll {sources}";
+            RunOldCsharpCompilerAndCheckSuccess(args, testProtosProjectDir);
+        }
+
+        /// <summary>
+        /// Invoke an old C# compiler in a subprocess and check it finished successful.
+        /// </summary>
+        /// <param name="args"></param>
+        /// <param name="workingDirectory"></param>
+        private void RunOldCsharpCompilerAndCheckSuccess(string args, string workingDirectory)
+        {  
+            using (var process = new Process())
+            {
+                // Get the path to the old C# 5 compiler from .NET framework. This approach is not 100% reliable, but works on most machines.
+                // Alternative way of getting the framework path is System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
+                // but it only works with the net45 target.
+                var oldCsharpCompilerPath = Path.Combine(Environment.GetEnvironmentVariable("WINDIR"), "Microsoft.NET", "Framework", "v4.0.30319", "csc.exe");
+                process.StartInfo.FileName = oldCsharpCompilerPath;
+                process.StartInfo.RedirectStandardOutput = true;
+                process.StartInfo.RedirectStandardError = true;
+                process.StartInfo.UseShellExecute = false;
+                process.StartInfo.Arguments = args;
+                process.StartInfo.WorkingDirectory = workingDirectory;
+
+                process.OutputDataReceived += (sender, e) =>
+                {
+                    if (e.Data != null)
+                    {
+                        Console.WriteLine(e.Data);
+                    }
+                };
+                process.ErrorDataReceived += (sender, e) =>
+                {
+                    if (e.Data != null)
+                    {
+                        Console.WriteLine(e.Data);
+                    }
+                };
+
+                process.Start();
+
+                process.BeginErrorReadLine();
+                process.BeginOutputReadLine();
+
+                process.WaitForExit();
+                Assert.AreEqual(0, process.ExitCode);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs
index bfee5f5..68b9bd3 100644
--- a/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs
@@ -1,4 +1,4 @@
-#region Copyright notice and license
+#region Copyright notice and license
 // Protocol Buffers - Google's data interchange format
 // Copyright 2017 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
@@ -72,24 +72,48 @@
         }
 
         [Test]
+        public void BuiltinOptionsCanBeRetrieved()
+        {
+            // non-custom options (that are not extensions but regular fields) can only be accessed via descriptor.Options
+            var fileOptions = UnittestProto3Reflection.Descriptor.GetOptions();
+            Assert.AreEqual("Google.Protobuf.TestProtos", fileOptions.CsharpNamespace);
+        }
+
+        [Test]
+        public void OptionPresenceCanBeDetected()
+        {
+            // case 1: the descriptor has no options at all so the options message is not present
+            Assert.IsNull(TestAllTypes.Descriptor.GetOptions());
+
+            // case 2: the descriptor has some options, but not the one we're looking for
+            // HasExtension will be false and GetExtension returns extension's default value
+            Assert.IsFalse(UnittestProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1));
+            Assert.AreEqual(0, UnittestProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1));
+
+            // case 3: option is present
+            Assert.IsTrue(UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1));
+            Assert.AreEqual(9876543210UL, UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1));
+        }
+
+        [Test]
         public void ScalarOptions()
         {
             var d = CustomOptionOtherValues.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(-100, options.TryGetInt32, Int32Opt, d.GetOption);
-            AssertOption(12.3456789f, options.TryGetFloat, FloatOpt, d.GetOption);
-            AssertOption(1.234567890123456789d, options.TryGetDouble, DoubleOpt, d.GetOption);
-            AssertOption("Hello, \"World\"", options.TryGetString, StringOpt, d.GetOption);
-            AssertOption(ByteString.CopyFromUtf8("Hello\0World"), options.TryGetBytes, BytesOpt, d.GetOption);
-            AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher<TestEnumType>(options), EnumOpt, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(-100, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(12.3456789f, customOptions.TryGetFloat, FloatOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(1.234567890123456789d, customOptions.TryGetDouble, DoubleOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption("Hello, \"World\"", customOptions.TryGetString, StringOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ByteString.CopyFromUtf8("Hello\0World"), customOptions.TryGetBytes, BytesOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher<TestEnumType>(customOptions), EnumOpt, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void MessageOptions()
         {
             var d = VariousComplexOptions.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, customOptions.TryGetMessage, ComplexOpt1, d.GetOption, d.GetOptions().GetExtension);
             AssertOption(new ComplexOptionType2
             {
                 Baz = 987,
@@ -97,85 +121,84 @@
                 Fred = new ComplexOptionType4 { Waldo = 321 },
                 Barney = { new ComplexOptionType4 { Waldo = 101 }, new ComplexOptionType4 { Waldo = 212 } }
             },
-                options.TryGetMessage, ComplexOpt2, d.GetOption);
-            AssertOption(new ComplexOptionType3 { Qux = 9 }, options.TryGetMessage, ComplexOpt3, d.GetOption);
+                customOptions.TryGetMessage, ComplexOpt2, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(new ComplexOptionType3 { Qux = 9 }, customOptions.TryGetMessage, ComplexOpt3, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void OptionLocations()
         {
-            var fileOptions = UnittestCustomOptionsProto3Reflection.Descriptor.CustomOptions;
-            AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1, UnittestCustomOptionsProto3Reflection.Descriptor.GetOption);
+            var fileDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor;
+            AssertOption(9876543210UL, fileDescriptor.CustomOptions.TryGetUInt64, FileOpt1, fileDescriptor.GetOption, fileDescriptor.GetOptions().GetExtension);
 
-            var messageOptions = TestMessageWithCustomOptions.Descriptor.CustomOptions;
-            AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1, TestMessageWithCustomOptions.Descriptor.GetOption);
+            var messageDescriptor = TestMessageWithCustomOptions.Descriptor;
+            AssertOption(-56, messageDescriptor.CustomOptions.TryGetInt32, MessageOpt1, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension);
 
-            var fieldOptions = TestMessageWithCustomOptions.Descriptor.Fields["field1"].CustomOptions;
-            AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1, TestMessageWithCustomOptions.Descriptor.Fields["field1"].GetOption);
+            var fieldDescriptor = TestMessageWithCustomOptions.Descriptor.Fields["field1"];
+            AssertOption(8765432109UL, fieldDescriptor.CustomOptions.TryGetFixed64, FieldOpt1, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension);
 
-            var oneofOptions = TestMessageWithCustomOptions.Descriptor.Oneofs[0].CustomOptions;
-            AssertOption(-99, oneofOptions.TryGetInt32, OneofOpt1, TestMessageWithCustomOptions.Descriptor.Oneofs[0].GetOption);
+            var oneofDescriptor = TestMessageWithCustomOptions.Descriptor.Oneofs[0];
+            AssertOption(-99, oneofDescriptor.CustomOptions.TryGetInt32, OneofOpt1, oneofDescriptor.GetOption, oneofDescriptor.GetOptions().GetExtension);
 
-            var enumOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].CustomOptions;
-            AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].GetOption);
+            var enumDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0];
+            AssertOption(-789, enumDescriptor.CustomOptions.TryGetSFixed32, EnumOpt1, enumDescriptor.GetOption, enumDescriptor.GetOptions().GetExtension);
 
-            var enumValueOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).CustomOptions;
-            AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).GetOption);
+            var enumValueDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2);
+            AssertOption(123, enumValueDescriptor.CustomOptions.TryGetInt32, EnumValueOpt1, enumValueDescriptor.GetOption, enumValueDescriptor.GetOptions().GetExtension);
 
-            var service = UnittestCustomOptionsProto3Reflection.Descriptor.Services
+            var serviceDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor.Services
                 .Single(s => s.Name == "TestServiceWithCustomOptions");
-            var serviceOptions = service.CustomOptions;
-            AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1, service.GetOption);
+            AssertOption(-9876543210, serviceDescriptor.CustomOptions.TryGetSInt64, ServiceOpt1, serviceDescriptor.GetOption, serviceDescriptor.GetOptions().GetExtension);
 
-            var methodOptions = service.Methods[0].CustomOptions;
-            AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher<UnitTest.Issues.TestProtos.MethodOpt1>(methodOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, service.Methods[0].GetOption);
+            var methodDescriptor = serviceDescriptor.Methods[0];
+            AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher<UnitTest.Issues.TestProtos.MethodOpt1>(methodDescriptor.CustomOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, methodDescriptor.GetOption, methodDescriptor.GetOptions().GetExtension);
         }
 
         [Test]
         public void MinValues()
         {
             var d = CustomOptionMinIntegerValues.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(false, options.TryGetBool, BoolOpt, d.GetOption);
-            AssertOption(int.MinValue, options.TryGetInt32, Int32Opt, d.GetOption);
-            AssertOption(long.MinValue, options.TryGetInt64, Int64Opt, d.GetOption);
-            AssertOption(uint.MinValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
-            AssertOption(ulong.MinValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
-            AssertOption(int.MinValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
-            AssertOption(long.MinValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
-            AssertOption(uint.MinValue, options.TryGetUInt32, Fixed32Opt, d.GetOption);
-            AssertOption(ulong.MinValue, options.TryGetUInt64, Fixed64Opt, d.GetOption);
-            AssertOption(int.MinValue, options.TryGetInt32, Sfixed32Opt, d.GetOption);
-            AssertOption(long.MinValue, options.TryGetInt64, Sfixed64Opt, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(false, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MinValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MinValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MinValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MinValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MinValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MinValue, customOptions.TryGetUInt32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MinValue, customOptions.TryGetInt32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MinValue, customOptions.TryGetInt64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void MaxValues()
         {
             var d = CustomOptionMaxIntegerValues.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(true, options.TryGetBool, BoolOpt, d.GetOption);
-            AssertOption(int.MaxValue, options.TryGetInt32, Int32Opt, d.GetOption);
-            AssertOption(long.MaxValue, options.TryGetInt64, Int64Opt, d.GetOption);
-            AssertOption(uint.MaxValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
-            AssertOption(ulong.MaxValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
-            AssertOption(int.MaxValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
-            AssertOption(long.MaxValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
-            AssertOption(uint.MaxValue, options.TryGetFixed32, Fixed32Opt, d.GetOption);
-            AssertOption(ulong.MaxValue, options.TryGetFixed64, Fixed64Opt, d.GetOption);
-            AssertOption(int.MaxValue, options.TryGetSFixed32, Sfixed32Opt, d.GetOption);
-            AssertOption(long.MaxValue, options.TryGetSFixed64, Sfixed64Opt, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(true, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MaxValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MaxValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MaxValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MaxValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MaxValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MaxValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MaxValue, customOptions.TryGetFixed32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MaxValue, customOptions.TryGetFixed64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MaxValue, customOptions.TryGetSFixed32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MaxValue, customOptions.TryGetSFixed64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void AggregateOptions()
         {
             // Just two examples
-            var messageOptions = AggregateMessage.Descriptor.CustomOptions;
-            AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, Msgopt, AggregateMessage.Descriptor.GetOption);
+            var messageDescriptor = AggregateMessage.Descriptor;
+            AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageDescriptor.CustomOptions.TryGetMessage, Msgopt, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension);
 
-            var fieldOptions = AggregateMessage.Descriptor.Fields["fieldname"].CustomOptions;
-            AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, Fieldopt, AggregateMessage.Descriptor.Fields["fieldname"].GetOption);
+            var fieldDescriptor = messageDescriptor.Fields["fieldname"];
+            AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldDescriptor.CustomOptions.TryGetMessage, Fieldopt, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension);
         }
 
         [Test]
@@ -199,16 +222,41 @@
             var descriptor = UnittestIssue6936CReflection.Descriptor;
             var foo = Foo.Descriptor;
             var bar = Bar.Descriptor;
-            AssertOption("foo", foo.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, foo.GetOption);
-            AssertOption("bar", bar.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, bar.GetOption);
+            AssertOption("foo", foo.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, foo.GetOption, foo.GetOptions().GetExtension);
+            AssertOption("bar", bar.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, bar.GetOption, bar.GetOptions().GetExtension);
         }
 
-        private void AssertOption<T, D>(T expected, OptionFetcher<T> fetcher, Extension<D, T> extension, Func<Extension<D, T>, T> descriptorOptionFetcher) where D : IExtendableMessage<D>
+        [Test]
+        public void SelfReferentialOptions()
         {
-            T customOptionsValue;
-            T extensionValue = descriptorOptionFetcher(extension);
-            Assert.IsTrue(fetcher(extension.FieldNumber, out customOptionsValue));
+            // Custom field option used in definition of the custom option's message.
+            var fooField = UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Descriptor.FindFieldByName("foo");
+            var fooFieldFooExtensionValue = fooField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooOptions);
+            Assert.AreEqual(1234, fooFieldFooExtensionValue.Foo);
+
+            // Custom field option used on the definition of that field option.
+            var fileDescriptor = UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsReflection.Descriptor;
+            var barOptionsField = fileDescriptor.Extensions.UnorderedExtensions.Single(field => field.Name == "bar_options");
+            var barExtensionValue = barOptionsField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.BarOptions);
+            Assert.AreEqual(1234, barExtensionValue);
+
+            // Custom field option used in definition of the extension message.
+            var intOptField = UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Descriptor.FindFieldByName("int_opt");
+            var intOptFieldFooExtensionValue = intOptField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooOptions);
+            Assert.AreEqual(1, intOptFieldFooExtensionValue.IntOpt);
+            Assert.AreEqual(2, intOptFieldFooExtensionValue.GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooIntOpt));
+            Assert.AreEqual(3, intOptFieldFooExtensionValue.GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooFooOpt).IntOpt);
+        }
+
+        private void AssertOption<T, D>(T expected, OptionFetcher<T> customOptionFetcher, Extension<D, T> extension, Func<Extension<D, T>, T> getOptionFetcher, Func<Extension<D, T>, T> extensionFetcher) where D : IExtendableMessage<D>
+        {
+            Assert.IsTrue(customOptionFetcher(extension.FieldNumber, out T customOptionsValue));
             Assert.AreEqual(expected, customOptionsValue);
+
+            T getOptionValue = getOptionFetcher(extension);
+            Assert.AreEqual(expected, getOptionValue);
+
+            T extensionValue = extensionFetcher(extension);
             Assert.AreEqual(expected, extensionValue);
         }
     }
diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
index 482db53..fab983d 100644
--- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
@@ -32,9 +32,12 @@
 
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
+using ProtobufUnittest;
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
+using UnitTest.Issues.TestProtos;
 
 namespace Google.Protobuf.Reflection
 {
@@ -69,6 +72,24 @@
             TestFileDescriptor(converted[2], converted[1], converted[0]);
         }
 
+        [Test]
+        public void FileDescriptor_BuildFromByteStrings_WithExtensionRegistry()
+        {
+            var extension = UnittestCustomOptionsProto3Extensions.MessageOpt1;
+
+            var byteStrings = new[]
+            {
+                DescriptorReflection.Descriptor.Proto.ToByteString(),
+                UnittestCustomOptionsProto3Reflection.Descriptor.Proto.ToByteString()
+            };
+            var registry = new ExtensionRegistry { extension };
+
+            var descriptor = FileDescriptor.BuildFromByteStrings(byteStrings, registry).Last();
+            var message = descriptor.MessageTypes.Single(t => t.Name == nameof(TestMessageWithCustomOptions));
+            var extensionValue = message.GetOptions().GetExtension(extension);
+            Assert.AreEqual(-56, extensionValue);
+        }
+
         private void TestFileDescriptor(FileDescriptor file, FileDescriptor importedFile, FileDescriptor importedPublicFile)
         {
             Assert.AreEqual("unittest_proto3.proto", file.Name);
@@ -247,6 +268,7 @@
             FieldDescriptor enumField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_nested_enum");
             FieldDescriptor foreignMessageField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_foreign_message");
             FieldDescriptor importMessageField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_import_message");
+            FieldDescriptor fieldInOneof = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("oneof_string");
 
             Assert.AreEqual("single_int32", primitiveField.Name);
             Assert.AreEqual("protobuf_unittest3.TestAllTypes.single_int32",
@@ -268,6 +290,10 @@
             Assert.AreEqual("single_import_message", importMessageField.Name);
             Assert.AreEqual(FieldType.Message, importMessageField.FieldType);
             Assert.AreEqual(importMessageDescriptor, importMessageField.MessageType);
+
+            // For a field in a regular onoef, ContainingOneof and RealContainingOneof should be the same.
+            Assert.AreEqual("oneof_field", fieldInOneof.ContainingOneof.Name);
+            Assert.AreSame(fieldInOneof.ContainingOneof, fieldInOneof.RealContainingOneof);
         }
 
         [Test]
@@ -318,6 +344,7 @@
         public void OneofDescriptor()
         {
             OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
+            Assert.IsFalse(descriptor.IsSynthetic);
             Assert.AreEqual("oneof_field", descriptor.Name);
             Assert.AreEqual("protobuf_unittest3.TestAllTypes.oneof_field", descriptor.FullName);
 
@@ -383,5 +410,48 @@
             var importingDescriptor = TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor;
             Assert.NotNull(importingDescriptor);
         }
+
+        [Test]
+        public void Proto3OptionalDescriptors()
+        {
+            var descriptor = TestProto3Optional.Descriptor;
+            var field = descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber];
+            Assert.NotNull(field.ContainingOneof);
+            Assert.IsTrue(field.ContainingOneof.IsSynthetic);
+            Assert.Null(field.RealContainingOneof);
+        }
+
+
+        [Test]
+        public void SyntheticOneofReflection()
+        {
+            // Expect every oneof in TestProto3Optional to be synthetic
+            var proto3OptionalDescriptor = TestProto3Optional.Descriptor;
+            Assert.AreEqual(0, proto3OptionalDescriptor.RealOneofCount);
+            foreach (var oneof in proto3OptionalDescriptor.Oneofs)
+            {
+                Assert.True(oneof.IsSynthetic);
+            }
+
+            // Expect no oneof in the original proto3 unit test file to be synthetic.
+            foreach (var descriptor in ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes)
+            {
+                Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount);
+                foreach (var oneof in descriptor.Oneofs)
+                {
+                    Assert.False(oneof.IsSynthetic);
+                }
+            }
+
+            // Expect no oneof in the original proto2 unit test file to be synthetic.
+            foreach (var descriptor in ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes)
+            {
+                Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount);
+                foreach (var oneof in descriptor.Oneofs)
+                {
+                    Assert.False(oneof.IsSynthetic);
+                }
+            }
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
index 9651ec3..b4dcdab 100644
--- a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
@@ -38,6 +38,7 @@
 using System.Collections.Generic;
 
 using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
+using ProtobufUnittest;
 
 namespace Google.Protobuf.Reflection
 {
@@ -97,7 +98,48 @@
         }
 
         [Test]
-        public void HasValue_Proto3()
+        public void HasValue_Proto3_Message()
+        {
+            var message = new TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor;
+            Assert.False(accessor.HasValue(message));
+            message.SingleForeignMessage = new ForeignMessage();
+            Assert.True(accessor.HasValue(message));
+            message.SingleForeignMessage = null;
+            Assert.False(accessor.HasValue(message));
+        }
+
+        [Test]
+        public void HasValue_Proto3_Oneof()
+        {
+            TestAllTypes message = new TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofStringFieldNumber].Accessor;
+            Assert.False(accessor.HasValue(message));
+            // Even though it's the default value, we still have a value.
+            message.OneofString = "";
+            Assert.True(accessor.HasValue(message));
+            message.OneofString = "hello";
+            Assert.True(accessor.HasValue(message));
+            message.OneofUint32 = 10;
+            Assert.False(accessor.HasValue(message));
+        }
+
+        [Test]
+        public void HasValue_Proto3_Primitive_Optional()
+        {
+            var message = new TestProto3Optional();
+            var accessor = ((IMessage) message).Descriptor.Fields[TestProto3Optional.OptionalInt64FieldNumber].Accessor;
+            Assert.IsFalse(accessor.HasValue(message));
+            message.OptionalInt64 = 5L;
+            Assert.IsTrue(accessor.HasValue(message));
+            message.ClearOptionalInt64();
+            Assert.IsFalse(accessor.HasValue(message));
+            message.OptionalInt64 = 0L;
+            Assert.IsTrue(accessor.HasValue(message));
+        }
+
+        [Test]
+        public void HasValue_Proto3_Primitive_NotOptional()
         {
             IMessage message = SampleMessages.CreateFullTestAllTypes();
             var fields = message.Descriptor.Fields;
@@ -105,22 +147,64 @@
         }
 
         [Test]
-        public void HasValue()
+        public void HasValue_Proto3_Repeated()
         {
-            IMessage message = new Proto2.TestAllTypes();
-            var fields = message.Descriptor.Fields;
-            var accessor = fields[Proto2.TestAllTypes.OptionalBoolFieldNumber].Accessor;
+            var message = new TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].Accessor;
+            Assert.Throws<InvalidOperationException>(() => accessor.HasValue(message));
+        }
 
+        [Test]
+        public void HasValue_Proto2_Primitive()
+        {
+            var message = new Proto2.TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalInt64FieldNumber].Accessor;
+
+            Assert.IsFalse(accessor.HasValue(message));
+            message.OptionalInt64 = 5L;
+            Assert.IsTrue(accessor.HasValue(message));
+            message.ClearOptionalInt64();
+            Assert.IsFalse(accessor.HasValue(message));
+            message.OptionalInt64 = 0L;
+            Assert.IsTrue(accessor.HasValue(message));
+        }
+
+        [Test]
+        public void HasValue_Proto2_Message()
+        {
+            var message = new Proto2.TestAllTypes();
+            var field = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber];
+            Assert.False(field.Accessor.HasValue(message));
+            message.OptionalForeignMessage = new Proto2.ForeignMessage();
+            Assert.True(field.Accessor.HasValue(message));
+            message.OptionalForeignMessage = null;
+            Assert.False(field.Accessor.HasValue(message));
+        }
+
+        [Test]
+        public void HasValue_Proto2_Oneof()
+        {
+            var message = new Proto2.TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofStringFieldNumber].Accessor;
             Assert.False(accessor.HasValue(message));
-
-            accessor.SetValue(message, true);
+            // Even though it's the default value, we still have a value.
+            message.OneofString = "";
             Assert.True(accessor.HasValue(message));
-
-            accessor.Clear(message);
+            message.OneofString = "hello";
+            Assert.True(accessor.HasValue(message));
+            message.OneofUint32 = 10;
             Assert.False(accessor.HasValue(message));
         }
 
         [Test]
+        public void HasValue_Proto2_Repeated()
+        {
+            var message = new Proto2.TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].Accessor;
+            Assert.Throws<InvalidOperationException>(() => accessor.HasValue(message));
+        }
+
+        [Test]
         public void SetValue_SingleFields()
         {
             // Just a sample (primitives, messages, enums, strings, byte strings)
@@ -226,6 +310,63 @@
         }
 
         [Test]
+        public void Clear_Proto3Optional()
+        {
+            TestProto3Optional message = new TestProto3Optional
+            {
+                OptionalInt32 = 0,
+                OptionalNestedMessage = new TestProto3Optional.Types.NestedMessage()
+            };
+            var primitiveField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber];
+            var messageField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalNestedMessageFieldNumber];
+
+            Assert.True(message.HasOptionalInt32);
+            Assert.NotNull(message.OptionalNestedMessage);
+
+            primitiveField.Accessor.Clear(message);
+            messageField.Accessor.Clear(message);
+
+            Assert.False(message.HasOptionalInt32);
+            Assert.Null(message.OptionalNestedMessage);
+        }
+
+        [Test]
+        public void Clear_Proto3_Oneof()
+        {
+            var message = new TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofUint32FieldNumber].Accessor;
+
+            // The field accessor Clear method only affects a oneof if the current case is the one being cleared.
+            message.OneofString = "hello";
+            Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
+            accessor.Clear(message);
+            Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
+
+            message.OneofUint32 = 100;
+            Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
+            accessor.Clear(message);
+            Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+        }
+
+        [Test]
+        public void Clear_Proto2_Oneof()
+        {
+            var message = new Proto2.TestAllTypes();
+            var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofUint32FieldNumber].Accessor;
+
+            // The field accessor Clear method only affects a oneof if the current case is the one being cleared.
+            message.OneofString = "hello";
+            Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
+            accessor.Clear(message);
+            Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
+
+            message.OneofUint32 = 100;
+            Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
+            accessor.Clear(message);
+            Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+        }
+
+        [Test]
         public void FieldDescriptor_ByName()
         {
             var descriptor = TestProtos.TestAllTypes.Descriptor;
@@ -264,5 +405,32 @@
             message.ClearExtension(RepeatedBoolExtension);
             Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
         }
+
+        [Test]
+        public void HasPresence()
+        {
+            // Proto3
+            var fields = TestProtos.TestAllTypes.Descriptor.Fields;
+            Assert.IsFalse(fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].HasPresence);
+            Assert.IsTrue(fields[TestProtos.TestAllTypes.OneofBytesFieldNumber].HasPresence);
+            Assert.IsTrue(fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].HasPresence);
+            Assert.IsFalse(fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].HasPresence);
+
+            fields = TestMap.Descriptor.Fields;
+            Assert.IsFalse(fields[TestMap.MapBoolBoolFieldNumber].HasPresence);
+
+            fields = TestProto3Optional.Descriptor.Fields;
+            Assert.IsTrue(fields[TestProto3Optional.OptionalBoolFieldNumber].HasPresence);
+
+            // Proto2
+            fields = Proto2.TestAllTypes.Descriptor.Fields;
+            Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalBoolFieldNumber].HasPresence);
+            Assert.IsTrue(fields[Proto2.TestAllTypes.OneofBytesFieldNumber].HasPresence);
+            Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber].HasPresence);
+            Assert.IsFalse(fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].HasPresence);
+
+            fields = Proto2.TestRequired.Descriptor.Fields;
+            Assert.IsTrue(fields[Proto2.TestRequired.AFieldNumber].HasPresence);
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs
index 886937d..15debc1 100644
--- a/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs
+++ b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs
@@ -161,10 +161,10 @@
             MessageParser discardingParser2 = retainingParser2.WithDiscardUnknownFields(true);
 
             // Test parse from byte[]
-            assertFull(retainingParser1.ParseFrom(data));
-            assertFull(retainingParser2.ParseFrom(data));
-            assertEmpty(discardingParser1.ParseFrom(data));
-            assertEmpty(discardingParser2.ParseFrom(data));
+            MessageParsingHelpers.AssertReadingMessage(retainingParser1, data, m => assertFull(m));
+            MessageParsingHelpers.AssertReadingMessage(retainingParser2, data, m => assertFull(m));
+            MessageParsingHelpers.AssertReadingMessage(discardingParser1, data, m => assertEmpty(m));
+            MessageParsingHelpers.AssertReadingMessage(discardingParser2, data, m => assertEmpty(m));
 
             // Test parse from byte[] with offset
             assertFull(retainingParser1.ParseFrom(data, 0, data.Length));
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
index 4a425f7..5b0e5e8 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
@@ -71,18 +71,42 @@
                 Uint64Field = 4
             };
 
-            var bytes = message.ToByteArray();
-            var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
+            MessageParsingHelpers.AssertWritingMessage(message);
 
-            Assert.AreEqual("x", parsed.StringField);
-            Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField);
-            Assert.AreEqual(true, parsed.BoolField);
-            Assert.AreEqual(12.5f, parsed.FloatField);
-            Assert.AreEqual(12.25d, parsed.DoubleField);
-            Assert.AreEqual(1, parsed.Int32Field);
-            Assert.AreEqual(2L, parsed.Int64Field);
-            Assert.AreEqual(3U, parsed.Uint32Field);
-            Assert.AreEqual(4UL, parsed.Uint64Field);
+            MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed =>
+            {
+                Assert.AreEqual("x", parsed.StringField);
+                Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField);
+                Assert.AreEqual(true, parsed.BoolField);
+                Assert.AreEqual(12.5f, parsed.FloatField);
+                Assert.AreEqual(12.25d, parsed.DoubleField);
+                Assert.AreEqual(1, parsed.Int32Field);
+                Assert.AreEqual(2L, parsed.Int64Field);
+                Assert.AreEqual(3U, parsed.Uint32Field);
+                Assert.AreEqual(4UL, parsed.Uint64Field);
+            });
+        }
+
+        [Test]
+        public void NegativeSingleValues()
+        {
+            var message = new TestWellKnownTypes
+            {
+                FloatField = -12.5f,
+                DoubleField = -12.25d,
+                Int32Field = -1,
+                Int64Field = -2
+            };
+
+            MessageParsingHelpers.AssertWritingMessage(message);
+
+            MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed =>
+            {
+                Assert.AreEqual(-12.5f, parsed.FloatField);
+                Assert.AreEqual(-12.25d, parsed.DoubleField);
+                Assert.AreEqual(-1, parsed.Int32Field);
+                Assert.AreEqual(-2L, parsed.Int64Field);
+            });
         }
 
         [Test]
@@ -101,18 +125,20 @@
                 Uint64Field = 0
             };
 
-            var bytes = message.ToByteArray();
-            var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
+            MessageParsingHelpers.AssertWritingMessage(message);
 
-            Assert.AreEqual("", parsed.StringField);
-            Assert.AreEqual(ByteString.Empty, parsed.BytesField);
-            Assert.AreEqual(false, parsed.BoolField);
-            Assert.AreEqual(0f, parsed.FloatField);
-            Assert.AreEqual(0d, parsed.DoubleField);
-            Assert.AreEqual(0, parsed.Int32Field);
-            Assert.AreEqual(0L, parsed.Int64Field);
-            Assert.AreEqual(0U, parsed.Uint32Field);
-            Assert.AreEqual(0UL, parsed.Uint64Field);
+            MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed =>
+            {
+                Assert.AreEqual("", parsed.StringField);
+                Assert.AreEqual(ByteString.Empty, parsed.BytesField);
+                Assert.AreEqual(false, parsed.BoolField);
+                Assert.AreEqual(0f, parsed.FloatField);
+                Assert.AreEqual(0d, parsed.DoubleField);
+                Assert.AreEqual(0, parsed.Int32Field);
+                Assert.AreEqual(0L, parsed.Int64Field);
+                Assert.AreEqual(0U, parsed.Uint32Field);
+                Assert.AreEqual(0UL, parsed.Uint64Field);
+            });
         }
 
         [Test]
@@ -140,12 +166,13 @@
                 Uint32Field = { uint.MaxValue, uint.MinValue, 0U },
                 Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL },
             };
-            var bytes = message.ToByteArray();
-            var parsed = RepeatedWellKnownTypes.Parser.ParseFrom(bytes);
 
-            Assert.AreEqual(message, parsed);
             // Just to test a single value for sanity...
             Assert.AreEqual("Second", message.StringField[1]);
+
+            MessageParsingHelpers.AssertWritingMessage(message);
+
+            MessageParsingHelpers.AssertRoundtrip(RepeatedWellKnownTypes.Parser, message);
         }
 
         [Test]
@@ -170,6 +197,8 @@
             var message = new RepeatedWellKnownTypes { Int32Field = { 5, 0 } };
             var actualBytes = message.ToByteArray();
             Assert.AreEqual(expectedBytes, actualBytes);
+
+            MessageParsingHelpers.AssertWritingMessage(message);
         }
 
         [Test]
@@ -194,12 +223,12 @@
                 Uint64Field = { { 18, ulong.MaxValue }, { 19, ulong.MinValue }, { 20, 0UL } },
             };
 
-            var bytes = message.ToByteArray();
-            var parsed = MapWellKnownTypes.Parser.ParseFrom(bytes);
-
-            Assert.AreEqual(message, parsed);
             // Just to test a single value for sanity...
             Assert.AreEqual("Second", message.StringField[12]);
+
+            MessageParsingHelpers.AssertWritingMessage(message);
+
+            MessageParsingHelpers.AssertRoundtrip(MapWellKnownTypes.Parser, message);
         }
 
         [Test]
@@ -288,10 +317,10 @@
         private void AssertOneofRoundTrip(OneofWellKnownTypes message)
         {
             // Normal roundtrip, but explicitly checking the case...
-            var bytes = message.ToByteArray();
-            var parsed = OneofWellKnownTypes.Parser.ParseFrom(bytes);
-            Assert.AreEqual(message, parsed);
-            Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase);
+            MessageParsingHelpers.AssertRoundtrip(OneofWellKnownTypes.Parser, message, parsed =>
+            {
+                Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase);
+            });
         }
 
         [Test]
@@ -406,8 +435,10 @@
             Assert.AreEqual(8, stream.Length); // tag (1 byte) + length (1 byte) + message (6 bytes)
             stream.Position = 0;
 
-            var message = TestWellKnownTypes.Parser.ParseFrom(stream);
-            Assert.AreEqual(65536, message.Int32Field);
+            MessageParsingHelpers.AssertReadingMessage(
+                TestWellKnownTypes.Parser,
+                stream.ToArray(),
+                message => Assert.AreEqual(65536, message.Int32Field));
         }
 
         [Test]
@@ -431,8 +462,10 @@
             Assert.Less(stream.Length, 8); // tag (1 byte) + length (1 byte) + message
             stream.Position = 0;
 
-            var message = TestWellKnownTypes.Parser.ParseFrom(stream);
-            Assert.AreEqual(6, message.Int32Field);
+            MessageParsingHelpers.AssertReadingMessage(
+                TestWellKnownTypes.Parser,
+                stream.ToArray(),
+                message => Assert.AreEqual(6, message.Int32Field));
         }
 
         [Test]
@@ -456,8 +489,10 @@
             Assert.AreEqual(13, stream.Length); // tag (1 byte) + length (1 byte) + message (11 bytes)
             stream.Position = 0;
 
-            var message = TestWellKnownTypes.Parser.ParseFrom(stream);
-            Assert.AreEqual(0xfffffffffffffL, message.Int64Field);
+            MessageParsingHelpers.AssertReadingMessage(
+                TestWellKnownTypes.Parser,
+                stream.ToArray(),
+                message => Assert.AreEqual(0xfffffffffffffL, message.Int64Field));
         }
 
         [Test]
@@ -481,8 +516,10 @@
             Assert.Less(stream.Length, 12); // tag (1 byte) + length (1 byte) + message
             stream.Position = 0;
 
-            var message = TestWellKnownTypes.Parser.ParseFrom(stream);
-            Assert.AreEqual(6L, message.Int64Field);
+            MessageParsingHelpers.AssertReadingMessage(
+                TestWellKnownTypes.Parser,
+                stream.ToArray(),
+                message => Assert.AreEqual(6L, message.Int64Field));
         }
 
         [Test]
diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb
index 424d969..42ecd3a 100644
--- a/csharp/src/Google.Protobuf.Test/testprotos.pb
+++ b/csharp/src/Google.Protobuf.Test/testprotos.pb
Binary files differ
diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs
index 3eb00e5..063b543 100644
--- a/csharp/src/Google.Protobuf/ByteString.cs
+++ b/csharp/src/Google.Protobuf/ByteString.cs
@@ -34,6 +34,8 @@
 using System.Collections;

 using System.Collections.Generic;

 using System.IO;

+using System.Runtime.InteropServices;

+using System.Security;

 using System.Text;

 #if !NET35

 using System.Threading;

@@ -48,40 +50,36 @@
     /// <summary>

     /// Immutable array of bytes.

     /// </summary>

+    [SecuritySafeCritical]

     public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>

     {

         private static readonly ByteString empty = new ByteString(new byte[0]);

 

-        private readonly byte[] bytes;

+        private readonly ReadOnlyMemory<byte> bytes;

 

         /// <summary>

-        /// Unsafe operations that can cause IO Failure and/or other catastrophic side-effects.

+        /// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.

         /// </summary>

-        internal static class Unsafe

-        {

-            /// <summary>

-            /// Constructs a new ByteString from the given byte array. The array is

-            /// *not* copied, and must not be modified after this constructor is called.

-            /// </summary>

-            internal static ByteString FromBytes(byte[] bytes)

-            {

-                return new ByteString(bytes);

-            }

-        }

-

-        /// <summary>

-        /// Internal use only.  Ensure that the provided array is not mutated and belongs to this instance.

-        /// </summary>

-        internal static ByteString AttachBytes(byte[] bytes)

+        internal static ByteString AttachBytes(ReadOnlyMemory<byte> bytes)

         {

             return new ByteString(bytes);

         }

 

         /// <summary>

-        /// Constructs a new ByteString from the given byte array. The array is

+        /// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.

+        /// This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical

+        /// in .NET Framework.

+        /// </summary>

+        internal static ByteString AttachBytes(byte[] bytes)

+        {

+            return AttachBytes(bytes.AsMemory());

+        }

+

+        /// <summary>

+        /// Constructs a new ByteString from the given memory. The memory is

         /// *not* copied, and must not be modified after this constructor is called.

         /// </summary>

-        private ByteString(byte[] bytes)

+        private ByteString(ReadOnlyMemory<byte> bytes)

         {

             this.bytes = bytes;

         }

@@ -110,13 +108,23 @@
             get { return Length == 0; }

         }

 

-#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY

         /// <summary>

         /// Provides read-only access to the data of this <see cref="ByteString"/>.

         /// No data is copied so this is the most efficient way of accessing.

         /// </summary>

-        public ReadOnlySpan<byte> Span => new ReadOnlySpan<byte>(bytes);

-#endif

+        public ReadOnlySpan<byte> Span

+        {

+            get { return bytes.Span; }

+        }

+

+        /// <summary>

+        /// Provides read-only access to the data of this <see cref="ByteString"/>.

+        /// No data is copied so this is the most efficient way of accessing.

+        /// </summary>

+        public ReadOnlyMemory<byte> Memory

+        {

+            get { return bytes; }

+        }

 

         /// <summary>

         /// Converts this <see cref="ByteString"/> into a byte array.

@@ -125,7 +133,7 @@
         /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>

         public byte[] ToByteArray()

         {

-            return (byte[]) bytes.Clone();

+            return bytes.ToArray();

         }

 

         /// <summary>

@@ -134,7 +142,16 @@
         /// <returns>A base64 representation of this <c>ByteString</c>.</returns>

         public string ToBase64()

         {

-            return Convert.ToBase64String(bytes);

+            if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))

+            {

+                // Fast path. ByteString was created with an array, so pass the underlying array.

+                return Convert.ToBase64String(segment.Array, segment.Offset, segment.Count);

+            }

+            else

+            {

+                // Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String.

+                return Convert.ToBase64String(bytes.ToArray());

+            }

         }

 

         /// <summary>

@@ -160,7 +177,7 @@
             int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;

             var memoryStream = new MemoryStream(capacity);

             stream.CopyTo(memoryStream);

-#if NETSTANDARD1_0 || NETSTANDARD2_0

+#if NETSTANDARD1_1 || NETSTANDARD2_0

             byte[] bytes = memoryStream.ToArray();

 #else

             // Avoid an extra copy if we can.

@@ -178,21 +195,10 @@
         /// <param name="stream">The stream to copy into a ByteString.</param>

         /// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>

         /// <returns>A ByteString with content read from the given stream.</returns>

-        public async static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))

+        public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))

         {

             ProtoPreconditions.CheckNotNull(stream, nameof(stream));

-            int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;

-            var memoryStream = new MemoryStream(capacity);

-            // We have to specify the buffer size here, as there's no overload accepting the cancellation token

-            // alone. But it's documented to use 81920 by default if not specified.

-            await stream.CopyToAsync(memoryStream, 81920, cancellationToken);

-#if NETSTANDARD1_0 || NETSTANDARD2_0

-            byte[] bytes = memoryStream.ToArray();

-#else

-            // Avoid an extra copy if we can.

-            byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();

-#endif

-            return AttachBytes(bytes);

+            return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken);

         }

 #endif

 

@@ -218,7 +224,6 @@
             return new ByteString(portion);

         }

 

-#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY

         /// <summary>

         /// Constructs a <see cref="ByteString" /> from a read only span. The contents

         /// are copied, so further modifications to the span will not

@@ -228,7 +233,6 @@
         {

             return new ByteString(bytes.ToArray());

         }

-#endif

 

         /// <summary>

         /// Creates a new <see cref="ByteString" /> by encoding the specified text with

@@ -248,11 +252,11 @@
         }

 

         /// <summary>

-        /// Retuns the byte at the given index.

+        /// Returns the byte at the given index.

         /// </summary>

         public byte this[int index]

         {

-            get { return bytes[index]; }

+            get { return bytes.Span[index]; }

         }

 

         /// <summary>

@@ -266,7 +270,18 @@
         /// <returns>The result of decoding the binary data with the given decoding.</returns>

         public string ToString(Encoding encoding)

         {

-            return encoding.GetString(bytes, 0, bytes.Length);

+            if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))

+            {

+                // Fast path. ByteString was created with an array.

+                return encoding.GetString(segment.Array, segment.Offset, segment.Count);

+            }

+            else

+            {

+                // Slow path. BytesString is not an array. Convert memory and pass result to GetString.

+                // TODO: Consider using GetString overload that takes a pointer.

+                byte[] array = bytes.ToArray();

+                return encoding.GetString(array, 0, array.Length);

+            }

         }

 

         /// <summary>

@@ -286,9 +301,10 @@
         /// Returns an iterator over the bytes in this <see cref="ByteString"/>.

         /// </summary>

         /// <returns>An iterator over the bytes in this object.</returns>

+        [SecuritySafeCritical]

         public IEnumerator<byte> GetEnumerator()

         {

-            return ((IEnumerable<byte>) bytes).GetEnumerator();

+            return MemoryMarshal.ToEnumerable(bytes).GetEnumerator();

         }

 

         /// <summary>

@@ -306,7 +322,17 @@
         public CodedInputStream CreateCodedInput()

         {

             // We trust CodedInputStream not to reveal the provided byte array or modify it

-            return new CodedInputStream(bytes);

+            if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment) && segment.Count == bytes.Length)

+            {

+                // Fast path. ByteString was created with a complete array.

+                return new CodedInputStream(segment.Array, segment.Offset, segment.Count);

+            }

+            else

+            {

+                // Slow path. BytesString is not an array, or is a slice of an array.

+                // Convert memory and pass result to WriteRawBytes.

+                return new CodedInputStream(bytes.ToArray());

+            }

         }

 

         /// <summary>

@@ -325,18 +351,8 @@
             {

                 return false;

             }

-            if (lhs.bytes.Length != rhs.bytes.Length)

-            {

-                return false;

-            }

-            for (int i = 0; i < lhs.Length; i++)

-            {

-                if (rhs.bytes[i] != lhs.bytes[i])

-                {

-                    return false;

-                }

-            }

-            return true;

+

+            return lhs.bytes.Span.SequenceEqual(rhs.bytes.Span);

         }

 

         /// <summary>

@@ -355,6 +371,7 @@
         /// </summary>

         /// <param name="obj">The object to compare this with.</param>

         /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>

+        [SecuritySafeCritical]

         public override bool Equals(object obj)

         {

             return this == (obj as ByteString);

@@ -365,12 +382,15 @@
         /// will return the same hash code.

         /// </summary>

         /// <returns>A hash code for this object.</returns>

+        [SecuritySafeCritical]

         public override int GetHashCode()

         {

+            ReadOnlySpan<byte> b = bytes.Span;

+

             int ret = 23;

-            foreach (byte b in bytes)

+            for (int i = 0; i < b.Length; i++)

             {

-                ret = (ret * 31) + b;

+                ret = (ret * 31) + b[i];

             }

             return ret;

         }

@@ -386,19 +406,11 @@
         }

 

         /// <summary>

-        /// Used internally by CodedOutputStream to avoid creating a copy for the write

-        /// </summary>

-        internal void WriteRawBytesTo(CodedOutputStream outputStream)

-        {

-            outputStream.WriteRawBytes(bytes, 0, bytes.Length);

-        }

-

-        /// <summary>

         /// Copies the entire byte array to the destination array provided at the offset specified.

         /// </summary>

         public void CopyTo(byte[] array, int position)

         {

-            ByteArray.Copy(bytes, 0, array, position, bytes.Length);

+            bytes.CopyTo(array.AsMemory(position));

         }

 

         /// <summary>

@@ -406,7 +418,17 @@
         /// </summary>

         public void WriteTo(Stream outputStream)

         {

-            outputStream.Write(bytes, 0, bytes.Length);

+            if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))

+            {

+                // Fast path. ByteString was created with an array, so pass the underlying array.

+                outputStream.Write(segment.Array, segment.Offset, segment.Count);

+            }

+            else

+            {

+                // Slow path. BytesString is not an array. Convert memory and pass result to WriteRawBytes.

+                var array = bytes.ToArray();

+                outputStream.Write(array, 0, array.Length);

+            }

         }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/ByteStringAsync.cs b/csharp/src/Google.Protobuf/ByteStringAsync.cs
new file mode 100644
index 0000000..3465cc6
--- /dev/null
+++ b/csharp/src/Google.Protobuf/ByteStringAsync.cs
@@ -0,0 +1,64 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// SecuritySafeCritical attribute can not be placed on types with async methods.
+    /// This class has ByteString's async methods so it can be marked with SecuritySafeCritical.
+    /// </summary>
+    internal static class ByteStringAsync
+    {
+#if !NET35
+        internal static async Task<ByteString> FromStreamAsyncCore(Stream stream, CancellationToken cancellationToken)
+        {
+            int capacity = stream.CanSeek ? checked((int)(stream.Length - stream.Position)) : 0;
+            var memoryStream = new MemoryStream(capacity);
+            // We have to specify the buffer size here, as there's no overload accepting the cancellation token
+            // alone. But it's documented to use 81920 by default if not specified.
+            await stream.CopyToAsync(memoryStream, 81920, cancellationToken);
+#if NETSTANDARD1_1
+            byte[] bytes = memoryStream.ToArray();
+#else
+            // Avoid an extra copy if we can.
+            byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
+#endif
+            return ByteString.AttachBytes(bytes);
+        }
+#endif
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs
index 9976f58..27b23c0 100644
--- a/csharp/src/Google.Protobuf/CodedInputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedInputStream.cs
@@ -34,6 +34,9 @@
 using System;

 using System.Collections.Generic;

 using System.IO;

+using System.Runtime.CompilerServices;

+using System.Runtime.InteropServices;

+using System.Security;

 

 namespace Google.Protobuf

 {

@@ -51,6 +54,7 @@
     /// and <see cref="MapField{TKey, TValue}"/> to serialize such fields.

     /// </para>

     /// </remarks>

+    [SecuritySafeCritical]

     public sealed class CodedInputStream : IDisposable

     {

         /// <summary>

@@ -65,55 +69,21 @@
         private readonly byte[] buffer;

 

         /// <summary>

-        /// The index of the buffer at which we need to refill from the stream (if there is one).

-        /// </summary>

-        private int bufferSize;

-

-        private int bufferSizeAfterLimit = 0;

-        /// <summary>

-        /// The position within the current buffer (i.e. the next byte to read)

-        /// </summary>

-        private int bufferPos = 0;

-

-        /// <summary>

         /// The stream to read further input from, or null if the byte array buffer was provided

         /// directly on construction, with no further data available.

         /// </summary>

         private readonly Stream input;

 

         /// <summary>

-        /// The last tag we read. 0 indicates we've read to the end of the stream

-        /// (or haven't read anything yet).

+        /// The parser state is kept separately so that other parse implementations can reuse the same

+        /// parsing primitives.

         /// </summary>

-        private uint lastTag = 0;

-

-        /// <summary>

-        /// The next tag, used to store the value read by PeekTag.

-        /// </summary>

-        private uint nextTag = 0;

-        private bool hasNextTag = false;

+        private ParserInternalState state;

 

         internal const int DefaultRecursionLimit = 100;

         internal const int DefaultSizeLimit = Int32.MaxValue;

         internal const int BufferSize = 4096;

 

-        /// <summary>

-        /// The total number of bytes read before the current buffer. The

-        /// total bytes read up to the current position can be computed as

-        /// totalBytesRetired + bufferPos.

-        /// </summary>

-        private int totalBytesRetired = 0;

-

-        /// <summary>

-        /// The absolute position of the end of the current message.

-        /// </summary> 

-        private int currentLimit = int.MaxValue;

-

-        private int recursionDepth = 0;

-

-        private readonly int recursionLimit;

-        private readonly int sizeLimit;

-

         #region Construction

         // Note that the checks are performed such that we don't end up checking obviously-valid things

         // like non-null references for arrays we've just created.

@@ -170,11 +140,14 @@
         {

             this.input = input;

             this.buffer = buffer;

-            this.bufferPos = bufferPos;

-            this.bufferSize = bufferSize;

-            this.sizeLimit = DefaultSizeLimit;

-            this.recursionLimit = DefaultRecursionLimit;

+            this.state.bufferPos = bufferPos;

+            this.state.bufferSize = bufferSize;

+            this.state.sizeLimit = DefaultSizeLimit;

+            this.state.recursionLimit = DefaultRecursionLimit;

+            SegmentedBufferHelper.Initialize(this, out this.state.segmentedBufferHelper);

             this.leaveOpen = leaveOpen;

+

+            this.state.currentLimit = int.MaxValue;

         }

 

         /// <summary>

@@ -196,8 +169,8 @@
             {

                 throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive");

             }

-            this.sizeLimit = sizeLimit;

-            this.recursionLimit = recursionLimit;

+            this.state.sizeLimit = sizeLimit;

+            this.state.recursionLimit = recursionLimit;

         }

         #endregion

 

@@ -230,9 +203,9 @@
             {

                 if (input != null)

                 {

-                    return input.Position - ((bufferSize + bufferSizeAfterLimit) - bufferPos);

+                    return input.Position - ((state.bufferSize + state.bufferSizeAfterLimit) - state.bufferPos);

                 }

-                return bufferPos;

+                return state.bufferPos;

             }

         }

 

@@ -240,7 +213,7 @@
         /// Returns the last tag read, or 0 if no tags have been read or we've read beyond

         /// the end of the stream.

         /// </summary>

-        internal uint LastTag { get { return lastTag; } }

+        internal uint LastTag { get { return state.lastTag; } }

 

         /// <summary>

         /// Returns the size limit for this stream.

@@ -253,7 +226,7 @@
         /// <value>

         /// The size limit.

         /// </value>

-        public int SizeLimit { get { return sizeLimit; } }

+        public int SizeLimit { get { return state.sizeLimit; } }

 

         /// <summary>

         /// Returns the recursion limit for this stream. This limit is applied whilst reading messages,

@@ -265,17 +238,31 @@
         /// <value>

         /// The recursion limit for this stream.

         /// </value>

-        public int RecursionLimit { get { return recursionLimit; } }

+        public int RecursionLimit { get { return state.recursionLimit; } }

 

         /// <summary>

         /// Internal-only property; when set to true, unknown fields will be discarded while parsing.

         /// </summary>

-        internal bool DiscardUnknownFields { get; set; }

+        internal bool DiscardUnknownFields

+        {

+            get { return state.DiscardUnknownFields; }

+            set { state.DiscardUnknownFields = value; }

+        }

 

         /// <summary>

         /// Internal-only property; provides extension identifiers to compatible messages while parsing.

         /// </summary>

-        internal ExtensionRegistry ExtensionRegistry { get; set; }

+        internal ExtensionRegistry ExtensionRegistry

+        {

+            get { return state.ExtensionRegistry; }

+            set { state.ExtensionRegistry = value; }

+        }

+

+        internal byte[] InternalBuffer => buffer;

+

+        internal Stream InternalInputStream => input;

+

+        internal ref ParserInternalState InternalState => ref state;

 

         /// <summary>

         /// Disposes of this instance, potentially closing any underlying stream.

@@ -302,17 +289,7 @@
         /// tag read was not the one specified</exception>

         internal void CheckReadEndOfStreamTag()

         {

-            if (lastTag != 0)

-            {

-                throw InvalidProtocolBufferException.MoreDataAvailable();

-            }

-        }

-

-        internal void CheckLastTagWas(uint expectedTag)

-        {

-           if (lastTag != expectedTag) {

-                throw InvalidProtocolBufferException.InvalidEndTag();

-           }

+            ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref state);

         }

         #endregion

 

@@ -325,16 +302,8 @@
         /// </summary>

         public uint PeekTag()

         {

-            if (hasNextTag)

-            {

-                return nextTag;

-            }

-

-            uint savedLast = lastTag;

-            nextTag = ReadTag();

-            hasNextTag = true;

-            lastTag = savedLast; // Undo the side effect of ReadTag

-            return nextTag;

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.PeekTag(ref span, ref state);

         }

 

         /// <summary>

@@ -348,54 +317,8 @@
         /// <returns>The next field tag, or 0 for end of stream. (0 is never a valid tag.)</returns>

         public uint ReadTag()

         {

-            if (hasNextTag)

-            {

-                lastTag = nextTag;

-                hasNextTag = false;

-                return lastTag;

-            }

-

-            // Optimize for the incredibly common case of having at least two bytes left in the buffer,

-            // and those two bytes being enough to get the tag. This will be true for fields up to 4095.

-            if (bufferPos + 2 <= bufferSize)

-            {

-                int tmp = buffer[bufferPos++];

-                if (tmp < 128)

-                {

-                    lastTag = (uint)tmp;

-                }

-                else

-                {

-                    int result = tmp & 0x7f;

-                    if ((tmp = buffer[bufferPos++]) < 128)

-                    {

-                        result |= tmp << 7;

-                        lastTag = (uint) result;

-                    }

-                    else

-                    {

-                        // Nope, rewind and go the potentially slow route.

-                        bufferPos -= 2;

-                        lastTag = ReadRawVarint32();

-                    }

-                }

-            }

-            else

-            {

-                if (IsAtEnd)

-                {

-                    lastTag = 0;

-                    return 0;

-                }

-

-                lastTag = ReadRawVarint32();

-            }

-            if (WireFormat.GetTagFieldNumber(lastTag) == 0)

-            {

-                // If we actually read a tag with a field of 0, that's not a valid tag.

-                throw InvalidProtocolBufferException.InvalidTag();

-            }

-            return lastTag;

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseTag(ref span, ref state);

         }

 

         /// <summary>

@@ -413,32 +336,8 @@
         /// <exception cref="InvalidOperationException">The last read operation read to the end of the logical stream</exception>

         public void SkipLastField()

         {

-            if (lastTag == 0)

-            {

-                throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream");

-            }

-            switch (WireFormat.GetTagWireType(lastTag))

-            {

-                case WireFormat.WireType.StartGroup:

-                    SkipGroup(lastTag);

-                    break;

-                case WireFormat.WireType.EndGroup:

-                    throw new InvalidProtocolBufferException(

-                        "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing");

-                case WireFormat.WireType.Fixed32:

-                    ReadFixed32();

-                    break;

-                case WireFormat.WireType.Fixed64:

-                    ReadFixed64();

-                    break;

-                case WireFormat.WireType.LengthDelimited:

-                    var length = ReadLength();

-                    SkipRawBytes(length);

-                    break;

-                case WireFormat.WireType.Varint:

-                    ReadRawVarint32();

-                    break;

-            }

+            var span = new ReadOnlySpan<byte>(buffer);

+            ParsingPrimitivesMessages.SkipLastField(ref span, ref state);

         }

 

         /// <summary>

@@ -446,37 +345,8 @@
         /// </summary>

         internal void SkipGroup(uint startGroupTag)

         {

-            // Note: Currently we expect this to be the way that groups are read. We could put the recursion

-            // depth changes into the ReadTag method instead, potentially...

-            recursionDepth++;

-            if (recursionDepth >= recursionLimit)

-            {

-                throw InvalidProtocolBufferException.RecursionLimitExceeded();

-            }

-            uint tag;

-            while (true)

-            {

-                tag = ReadTag();

-                if (tag == 0)

-                {

-                    throw InvalidProtocolBufferException.TruncatedMessage();

-                }

-                // Can't call SkipLastField for this case- that would throw.

-                if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup)

-                {

-                    break;

-                }

-                // This recursion will allow us to handle nested groups.

-                SkipLastField();

-            }

-            int startField = WireFormat.GetTagFieldNumber(startGroupTag);

-            int endField = WireFormat.GetTagFieldNumber(tag);

-            if (startField != endField)

-            {

-                throw new InvalidProtocolBufferException(

-                    $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}");

-            }

-            recursionDepth--;

+            var span = new ReadOnlySpan<byte>(buffer);

+            ParsingPrimitivesMessages.SkipGroup(ref span, ref state, startGroupTag);

         }

 

         /// <summary>

@@ -484,33 +354,8 @@
         /// </summary>

         public double ReadDouble()

         {

-            if (bufferPos + 8 <= bufferSize)

-            {

-                if (BitConverter.IsLittleEndian)

-                {

-                    var result = BitConverter.ToDouble(buffer, bufferPos);

-                    bufferPos += 8;

-                    return result;

-                }

-                else

-                {

-                    var bytes = new byte[8];

-                    bytes[0] = buffer[bufferPos + 7];

-                    bytes[1] = buffer[bufferPos + 6];

-                    bytes[2] = buffer[bufferPos + 5];

-                    bytes[3] = buffer[bufferPos + 4];

-                    bytes[4] = buffer[bufferPos + 3];

-                    bytes[5] = buffer[bufferPos + 2];

-                    bytes[6] = buffer[bufferPos + 1];

-                    bytes[7] = buffer[bufferPos];

-                    bufferPos += 8;

-                    return BitConverter.ToDouble(bytes, 0);

-                }

-            }

-            else

-            {

-                return BitConverter.Int64BitsToDouble((long)ReadRawLittleEndian64());

-            }

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseDouble(ref span, ref state);

         }

 

         /// <summary>

@@ -518,21 +363,8 @@
         /// </summary>

         public float ReadFloat()

         {

-            if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)

-            {

-                float ret = BitConverter.ToSingle(buffer, bufferPos);

-                bufferPos += 4;

-                return ret;

-            }

-            else

-            {

-                byte[] rawBytes = ReadRawBytes(4);

-                if (!BitConverter.IsLittleEndian)

-                {

-                    ByteArray.Reverse(rawBytes);

-                }

-                return BitConverter.ToSingle(rawBytes, 0);

-            }

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseFloat(ref span, ref state);

         }

 

         /// <summary>

@@ -588,22 +420,8 @@
         /// </summary>

         public string ReadString()

         {

-            int length = ReadLength();

-            // No need to read any data for an empty string.

-            if (length == 0)

-            {

-                return "";

-            }

-            if (length <= bufferSize - bufferPos && length > 0)

-            {

-                // Fast path:  We already have the bytes in a contiguous buffer, so

-                //   just copy directly from it.

-                String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length);

-                bufferPos += length;

-                return result;

-            }

-            // Slow path: Build a byte array first then copy it.

-            return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length);

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ReadString(ref span, ref state);

         }

 

         /// <summary>

@@ -611,22 +429,21 @@
         /// </summary>

         public void ReadMessage(IMessage builder)

         {

-            int length = ReadLength();

-            if (recursionDepth >= recursionLimit)

+            // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalMergeFrom method),

+            // what we're doing here works fine, but could be more efficient.

+            // What happends is that we first initialize a ParseContext from the current coded input stream only to parse the length of the message, at which point

+            // we will need to switch back again to CodedInputStream-based parsing (which involves copying and storing the state) to be able to

+            // invoke the legacy MergeFrom(CodedInputStream) method.

+            // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it).

+            ParseContext.Initialize(buffer.AsSpan(), ref state, out ParseContext ctx);

+            try

             {

-                throw InvalidProtocolBufferException.RecursionLimitExceeded();

+                ParsingPrimitivesMessages.ReadMessage(ref ctx, builder);

             }

-            int oldLimit = PushLimit(length);

-            ++recursionDepth;

-            builder.MergeFrom(this);

-            CheckReadEndOfStreamTag();

-            // Check that we've read exactly as much data as expected.

-            if (!ReachedLimit)

+            finally

             {

-                throw InvalidProtocolBufferException.TruncatedMessage();

+                ctx.CopyStateTo(this);

             }

-            --recursionDepth;

-            PopLimit(oldLimit);

         }

 

         /// <summary>

@@ -634,33 +451,15 @@
         /// </summary>

         public void ReadGroup(IMessage builder)

         {

-            if (recursionDepth >= recursionLimit)

+            ParseContext.Initialize(this, out ParseContext ctx);

+            try

             {

-                throw InvalidProtocolBufferException.RecursionLimitExceeded();

+                ParsingPrimitivesMessages.ReadGroup(ref ctx, builder);

             }

-            ++recursionDepth;

-

-            uint tag = lastTag;

-            int fieldNumber = WireFormat.GetTagFieldNumber(tag);

-

-            builder.MergeFrom(this);

-            CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));

-            --recursionDepth;

-        }

-

-        /// <summary>

-        /// Reads an embedded group unknown field from the stream.

-        /// </summary>

-        internal void ReadGroup(int fieldNumber, UnknownFieldSet set)

-        {

-            if (recursionDepth >= recursionLimit)

+            finally

             {

-                throw InvalidProtocolBufferException.RecursionLimitExceeded();

+                ctx.CopyStateTo(this);

             }

-            ++recursionDepth;

-            set.MergeGroupFrom(this);

-            CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));

-            --recursionDepth;

         }

 

         /// <summary>

@@ -668,20 +467,8 @@
         /// </summary>   

         public ByteString ReadBytes()

         {

-            int length = ReadLength();

-            if (length <= bufferSize - bufferPos && length > 0)

-            {

-                // Fast path:  We already have the bytes in a contiguous buffer, so

-                //   just copy directly from it.

-                ByteString result = ByteString.CopyFrom(buffer, bufferPos, length);

-                bufferPos += length;

-                return result;

-            }

-            else

-            {

-                // Slow path:  Build a byte array and attach it to a new ByteString.

-                return ByteString.AttachBytes(ReadRawBytes(length));

-            }

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ReadBytes(ref span, ref state);

         }

 

         /// <summary>

@@ -722,7 +509,7 @@
         /// </summary>   

         public int ReadSInt32()

         {

-            return DecodeZigZag32(ReadRawVarint32());

+            return ParsingPrimitives.DecodeZigZag32(ReadRawVarint32());

         }

 

         /// <summary>

@@ -730,7 +517,7 @@
         /// </summary>   

         public long ReadSInt64()

         {

-            return DecodeZigZag64(ReadRawVarint64());

+            return ParsingPrimitives.DecodeZigZag64(ReadRawVarint64());

         }

 

         /// <summary>

@@ -742,7 +529,8 @@
         /// </remarks>

         public int ReadLength()

         {

-            return (int) ReadRawVarint32();

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseLength(ref span, ref state);

         }

 

         /// <summary>

@@ -752,265 +540,8 @@
         /// </summary>

         public bool MaybeConsumeTag(uint tag)

         {

-            if (PeekTag() == tag)

-            {

-                hasNextTag = false;

-                return true;

-            }

-            return false;

-        }

-

-        internal static float? ReadFloatWrapperLittleEndian(CodedInputStream input)

-        {

-            // length:1 + tag:1 + value:4 = 6 bytes

-            if (input.bufferPos + 6 <= input.bufferSize)

-            {

-                // The entire wrapper message is already contained in `buffer`.

-                int length = input.buffer[input.bufferPos];

-                if (length == 0)

-                {

-                    input.bufferPos++;

-                    return 0F;

-                }

-                // tag:1 + value:4 = length of 5 bytes

-                // field=1, type=32-bit = tag of 13

-                if (length != 5 || input.buffer[input.bufferPos + 1] != 13)

-                {

-                    return ReadFloatWrapperSlow(input);

-                }

-                var result = BitConverter.ToSingle(input.buffer, input.bufferPos + 2);

-                input.bufferPos += 6;

-                return result;

-            }

-            else

-            {

-                return ReadFloatWrapperSlow(input);

-            }

-        }

-

-        internal static float? ReadFloatWrapperSlow(CodedInputStream input)

-        {

-            int length = input.ReadLength();

-            if (length == 0)

-            {

-                return 0F;

-            }

-            int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;

-            float result = 0F;

-            do

-            {

-                // field=1, type=32-bit = tag of 13

-                if (input.ReadTag() == 13)

-                {

-                    result = input.ReadFloat();

-                }

-                else

-                {

-                    input.SkipLastField();

-                }

-            }

-            while (input.totalBytesRetired + input.bufferPos < finalBufferPos);

-            return result;

-        }

-

-        internal static double? ReadDoubleWrapperLittleEndian(CodedInputStream input)

-        {

-            // length:1 + tag:1 + value:8 = 10 bytes

-            if (input.bufferPos + 10 <= input.bufferSize)

-            {

-                // The entire wrapper message is already contained in `buffer`.

-                int length = input.buffer[input.bufferPos];

-                if (length == 0)

-                {

-                    input.bufferPos++;

-                    return 0D;

-                }

-                // tag:1 + value:8 = length of 9 bytes

-                // field=1, type=64-bit = tag of 9

-                if (length != 9 || input.buffer[input.bufferPos + 1] != 9)

-                {

-                    return ReadDoubleWrapperSlow(input);

-                }

-                var result = BitConverter.ToDouble(input.buffer, input.bufferPos + 2);

-                input.bufferPos += 10;

-                return result;

-            }

-            else

-            {

-                return ReadDoubleWrapperSlow(input);

-            }

-        }

-

-        internal static double? ReadDoubleWrapperSlow(CodedInputStream input)

-        {

-            int length = input.ReadLength();

-            if (length == 0)

-            {

-                return 0D;

-            }

-            int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;

-            double result = 0D;

-            do

-            {

-                // field=1, type=64-bit = tag of 9

-                if (input.ReadTag() == 9)

-                {

-                    result = input.ReadDouble();

-                }

-                else

-                {

-                    input.SkipLastField();

-                }

-            }

-            while (input.totalBytesRetired + input.bufferPos < finalBufferPos);

-            return result;

-        }

-

-        internal static bool? ReadBoolWrapper(CodedInputStream input)

-        {

-            return ReadUInt64Wrapper(input) != 0;

-        }

-

-        internal static uint? ReadUInt32Wrapper(CodedInputStream input)

-        {

-            // length:1 + tag:1 + value:5(varint32-max) = 7 bytes

-            if (input.bufferPos + 7 <= input.bufferSize)

-            {

-                // The entire wrapper message is already contained in `buffer`.

-                int pos0 = input.bufferPos;

-                int length = input.buffer[input.bufferPos++];

-                if (length == 0)

-                {

-                    return 0;

-                }

-                // Length will always fit in a single byte.

-                if (length >= 128)

-                {

-                    input.bufferPos = pos0;

-                    return ReadUInt32WrapperSlow(input);

-                }

-                int finalBufferPos = input.bufferPos + length;

-                // field=1, type=varint = tag of 8

-                if (input.buffer[input.bufferPos++] != 8)

-                {

-                    input.bufferPos = pos0;

-                    return ReadUInt32WrapperSlow(input);

-                }

-                var result = input.ReadUInt32();

-                // Verify this message only contained a single field.

-                if (input.bufferPos != finalBufferPos)

-                {

-                    input.bufferPos = pos0;

-                    return ReadUInt32WrapperSlow(input);

-                }

-                return result;

-            }

-            else

-            {

-                return ReadUInt32WrapperSlow(input);

-            }

-        }

-

-        private static uint? ReadUInt32WrapperSlow(CodedInputStream input)

-        {

-            int length = input.ReadLength();

-            if (length == 0)

-            {

-                return 0;

-            }

-            int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;

-            uint result = 0;

-            do

-            {

-                // field=1, type=varint = tag of 8

-                if (input.ReadTag() == 8)

-                {

-                    result = input.ReadUInt32();

-                }

-                else

-                {

-                    input.SkipLastField();

-                }

-            }

-            while (input.totalBytesRetired + input.bufferPos < finalBufferPos);

-            return result;

-        }

-

-        internal static int? ReadInt32Wrapper(CodedInputStream input)

-        {

-            return (int?)ReadUInt32Wrapper(input);

-        }

-

-        internal static ulong? ReadUInt64Wrapper(CodedInputStream input)

-        {

-            // field=1, type=varint = tag of 8

-            const int expectedTag = 8;

-            // length:1 + tag:1 + value:10(varint64-max) = 12 bytes

-            if (input.bufferPos + 12 <= input.bufferSize)

-            {

-                // The entire wrapper message is already contained in `buffer`.

-                int pos0 = input.bufferPos;

-                int length = input.buffer[input.bufferPos++];

-                if (length == 0)

-                {

-                    return 0L;

-                }

-                // Length will always fit in a single byte.

-                if (length >= 128)

-                {

-                    input.bufferPos = pos0;

-                    return ReadUInt64WrapperSlow(input);

-                }

-                int finalBufferPos = input.bufferPos + length;

-                if (input.buffer[input.bufferPos++] != expectedTag)

-                {

-                    input.bufferPos = pos0;

-                    return ReadUInt64WrapperSlow(input);

-                }

-                var result = input.ReadUInt64();

-                // Verify this message only contained a single field.

-                if (input.bufferPos != finalBufferPos)

-                {

-                    input.bufferPos = pos0;

-                    return ReadUInt64WrapperSlow(input);

-                }

-                return result;

-            }

-            else

-            {

-                return ReadUInt64WrapperSlow(input);

-            }

-        }

-

-        internal static ulong? ReadUInt64WrapperSlow(CodedInputStream input)

-        {

-            // field=1, type=varint = tag of 8

-            const int expectedTag = 8;

-            int length = input.ReadLength();

-            if (length == 0)

-            {

-                return 0L;

-            }

-            int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;

-            ulong result = 0L;

-            do

-            {

-                if (input.ReadTag() == expectedTag)

-                {

-                    result = input.ReadUInt64();

-                }

-                else

-                {

-                    input.SkipLastField();

-                }

-            }

-            while (input.totalBytesRetired + input.bufferPos < finalBufferPos);

-            return result;

-        }

-

-        internal static long? ReadInt64Wrapper(CodedInputStream input)

-        {

-            return (long?)ReadUInt64Wrapper(input);

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.MaybeConsumeTag(ref span, ref state, tag);

         }

 

 #endregion

@@ -1018,58 +549,6 @@
         #region Underlying reading primitives

 

         /// <summary>

-        /// Same code as ReadRawVarint32, but read each byte individually, checking for

-        /// buffer overflow.

-        /// </summary>

-        private uint SlowReadRawVarint32()

-        {

-            int tmp = ReadRawByte();

-            if (tmp < 128)

-            {

-                return (uint) tmp;

-            }

-            int result = tmp & 0x7f;

-            if ((tmp = ReadRawByte()) < 128)

-            {

-                result |= tmp << 7;

-            }

-            else

-            {

-                result |= (tmp & 0x7f) << 7;

-                if ((tmp = ReadRawByte()) < 128)

-                {

-                    result |= tmp << 14;

-                }

-                else

-                {

-                    result |= (tmp & 0x7f) << 14;

-                    if ((tmp = ReadRawByte()) < 128)

-                    {

-                        result |= tmp << 21;

-                    }

-                    else

-                    {

-                        result |= (tmp & 0x7f) << 21;

-                        result |= (tmp = ReadRawByte()) << 28;

-                        if (tmp >= 128)

-                        {

-                            // Discard upper 32 bits.

-                            for (int i = 0; i < 5; i++)

-                            {

-                                if (ReadRawByte() < 128)

-                                {

-                                    return (uint) result;

-                                }

-                            }

-                            throw InvalidProtocolBufferException.MalformedVarint();

-                        }

-                    }

-                }

-            }

-            return (uint) result;

-        }

-

-        /// <summary>

         /// Reads a raw Varint from the stream.  If larger than 32 bits, discard the upper bits.

         /// This method is optimised for the case where we've got lots of data in the buffer.

         /// That means we can check the size just once, then just read directly from the buffer

@@ -1077,58 +556,8 @@
         /// </summary>

         internal uint ReadRawVarint32()

         {

-            if (bufferPos + 5 > bufferSize)

-            {

-                return SlowReadRawVarint32();

-            }

-

-            int tmp = buffer[bufferPos++];

-            if (tmp < 128)

-            {

-                return (uint) tmp;

-            }

-            int result = tmp & 0x7f;

-            if ((tmp = buffer[bufferPos++]) < 128)

-            {

-                result |= tmp << 7;

-            }

-            else

-            {

-                result |= (tmp & 0x7f) << 7;

-                if ((tmp = buffer[bufferPos++]) < 128)

-                {

-                    result |= tmp << 14;

-                }

-                else

-                {

-                    result |= (tmp & 0x7f) << 14;

-                    if ((tmp = buffer[bufferPos++]) < 128)

-                    {

-                        result |= tmp << 21;

-                    }

-                    else

-                    {

-                        result |= (tmp & 0x7f) << 21;

-                        result |= (tmp = buffer[bufferPos++]) << 28;

-                        if (tmp >= 128)

-                        {

-                            // Discard upper 32 bits.

-                            // Note that this has to use ReadRawByte() as we only ensure we've

-                            // got at least 5 bytes at the start of the method. This lets us

-                            // use the fast path in more cases, and we rarely hit this section of code.

-                            for (int i = 0; i < 5; i++)

-                            {

-                                if (ReadRawByte() < 128)

-                                {

-                                    return (uint) result;

-                                }

-                            }

-                            throw InvalidProtocolBufferException.MalformedVarint();

-                        }

-                    }

-                }

-            }

-            return (uint) result;

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseRawVarint32(ref span, ref state);

         }

 

         /// <summary>

@@ -1142,35 +571,7 @@
         /// <returns></returns>

         internal static uint ReadRawVarint32(Stream input)

         {

-            int result = 0;

-            int offset = 0;

-            for (; offset < 32; offset += 7)

-            {

-                int b = input.ReadByte();

-                if (b == -1)

-                {

-                    throw InvalidProtocolBufferException.TruncatedMessage();

-                }

-                result |= (b & 0x7f) << offset;

-                if ((b & 0x80) == 0)

-                {

-                    return (uint) result;

-                }

-            }

-            // Keep reading up to 64 bits.

-            for (; offset < 64; offset += 7)

-            {

-                int b = input.ReadByte();

-                if (b == -1)

-                {

-                    throw InvalidProtocolBufferException.TruncatedMessage();

-                }

-                if ((b & 0x80) == 0)

-                {

-                    return (uint) result;

-                }

-            }

-            throw InvalidProtocolBufferException.MalformedVarint();

+            return ParsingPrimitives.ReadRawVarint32(input);

         }

 

         /// <summary>

@@ -1178,44 +579,8 @@
         /// </summary>

         internal ulong ReadRawVarint64()

         {

-            if (bufferPos + 10 <= bufferSize)

-            {

-                ulong result = buffer[bufferPos++];

-                if (result < 128)

-                {

-                    return result;

-                }

-                result &= 0x7f;

-                int shift = 7;

-                do

-                {

-                    byte b = buffer[bufferPos++];

-                    result |= (ulong)(b & 0x7F) << shift;

-                    if (b < 0x80)

-                    {

-                        return result;

-                    }

-                    shift += 7;

-                }

-                while (shift < 64);

-            }

-            else

-            {

-                int shift = 0;

-                ulong result = 0;

-                do

-                {

-                    byte b = ReadRawByte();

-                    result |= (ulong)(b & 0x7F) << shift;

-                    if (b < 0x80)

-                    {

-                        return result;

-                    }

-                    shift += 7;

-                }

-                while (shift < 64);

-            }

-            throw InvalidProtocolBufferException.MalformedVarint();

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseRawVarint64(ref span, ref state);

         }

 

         /// <summary>

@@ -1223,32 +588,8 @@
         /// </summary>

         internal uint ReadRawLittleEndian32()

         {

-            if (bufferPos + 4 <= bufferSize)

-            {

-                if (BitConverter.IsLittleEndian)

-                {

-                    var result = BitConverter.ToUInt32(buffer, bufferPos);

-                    bufferPos += 4;

-                    return result;

-                }

-                else

-                {

-                    uint b1 = buffer[bufferPos];

-                    uint b2 = buffer[bufferPos + 1];

-                    uint b3 = buffer[bufferPos + 2];

-                    uint b4 = buffer[bufferPos + 3];

-                    bufferPos += 4;

-                    return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);

-                }

-            }

-            else

-            {

-                uint b1 = ReadRawByte();

-                uint b2 = ReadRawByte();

-                uint b3 = ReadRawByte();

-                uint b4 = ReadRawByte();

-                return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);

-            }

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseRawLittleEndian32(ref span, ref state);

         }

 

         /// <summary>

@@ -1256,70 +597,8 @@
         /// </summary>

         internal ulong ReadRawLittleEndian64()

         {

-            if (bufferPos + 8 <= bufferSize)

-            {

-                if (BitConverter.IsLittleEndian)

-                {

-                    var result = BitConverter.ToUInt64(buffer, bufferPos);

-                    bufferPos += 8;

-                    return result;

-                }

-                else

-                {

-                    ulong b1 = buffer[bufferPos];

-                    ulong b2 = buffer[bufferPos + 1];

-                    ulong b3 = buffer[bufferPos + 2];

-                    ulong b4 = buffer[bufferPos + 3];

-                    ulong b5 = buffer[bufferPos + 4];

-                    ulong b6 = buffer[bufferPos + 5];

-                    ulong b7 = buffer[bufferPos + 6];

-                    ulong b8 = buffer[bufferPos + 7];

-                    bufferPos += 8;

-                    return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)

-                           | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);

-                }

-            }

-            else

-            {

-                ulong b1 = ReadRawByte();

-                ulong b2 = ReadRawByte();

-                ulong b3 = ReadRawByte();

-                ulong b4 = ReadRawByte();

-                ulong b5 = ReadRawByte();

-                ulong b6 = ReadRawByte();

-                ulong b7 = ReadRawByte();

-                ulong b8 = ReadRawByte();

-                return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)

-                       | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);

-            }

-        }

-

-        /// <summary>

-        /// Decode a 32-bit value with ZigZag encoding.

-        /// </summary>

-        /// <remarks>

-        /// ZigZag encodes signed integers into values that can be efficiently

-        /// encoded with varint.  (Otherwise, negative values must be 

-        /// sign-extended to 64 bits to be varint encoded, thus always taking

-        /// 10 bytes on the wire.)

-        /// </remarks>

-        internal static int DecodeZigZag32(uint n)

-        {

-            return (int)(n >> 1) ^ -(int)(n & 1);

-        }

-

-        /// <summary>

-        /// Decode a 32-bit value with ZigZag encoding.

-        /// </summary>

-        /// <remarks>

-        /// ZigZag encodes signed integers into values that can be efficiently

-        /// encoded with varint.  (Otherwise, negative values must be 

-        /// sign-extended to 64 bits to be varint encoded, thus always taking

-        /// 10 bytes on the wire.)

-        /// </remarks>

-        internal static long DecodeZigZag64(ulong n)

-        {

-            return (long)(n >> 1) ^ -(long)(n & 1);

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ParseRawLittleEndian64(ref span, ref state);

         }

         #endregion

 

@@ -1333,37 +612,7 @@
         /// <returns>The old limit.</returns>

         internal int PushLimit(int byteLimit)

         {

-            if (byteLimit < 0)

-            {

-                throw InvalidProtocolBufferException.NegativeSize();

-            }

-            byteLimit += totalBytesRetired + bufferPos;

-            int oldLimit = currentLimit;

-            if (byteLimit > oldLimit)

-            {

-                throw InvalidProtocolBufferException.TruncatedMessage();

-            }

-            currentLimit = byteLimit;

-

-            RecomputeBufferSizeAfterLimit();

-

-            return oldLimit;

-        }

-

-        private void RecomputeBufferSizeAfterLimit()

-        {

-            bufferSize += bufferSizeAfterLimit;

-            int bufferEnd = totalBytesRetired + bufferSize;

-            if (bufferEnd > currentLimit)

-            {

-                // Limit is in current buffer.

-                bufferSizeAfterLimit = bufferEnd - currentLimit;

-                bufferSize -= bufferSizeAfterLimit;

-            }

-            else

-            {

-                bufferSizeAfterLimit = 0;

-            }

+            return SegmentedBufferHelper.PushLimit(ref state, byteLimit);

         }

 

         /// <summary>

@@ -1371,8 +620,7 @@
         /// </summary>

         internal void PopLimit(int oldLimit)

         {

-            currentLimit = oldLimit;

-            RecomputeBufferSizeAfterLimit();

+            SegmentedBufferHelper.PopLimit(ref state, oldLimit);

         }

 

         /// <summary>

@@ -1383,12 +631,7 @@
         {

             get

             {

-                if (currentLimit == int.MaxValue)

-                {

-                    return false;

-                }

-                int currentAbsolutePosition = totalBytesRetired + bufferPos;

-                return currentAbsolutePosition >= currentLimit;

+                return SegmentedBufferHelper.IsReachedLimit(ref state);

             }

         }

 

@@ -1399,12 +642,16 @@
         /// </summary>

         public bool IsAtEnd

         {

-            get { return bufferPos == bufferSize && !RefillBuffer(false); }

+            get

+            {

+                var span = new ReadOnlySpan<byte>(buffer);

+                return SegmentedBufferHelper.IsAtEnd(ref span, ref state);

+            }

         }

 

         /// <summary>

         /// Called when buffer is empty to read more bytes from the

-        /// input.  If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that

+        /// input.  If <paramref name="mustSucceed"/> is true, RefillBuffer() guarantees that

         /// either there will be at least one byte in the buffer when it returns

         /// or it will throw an exception.  If <paramref name="mustSucceed"/> is false,

         /// RefillBuffer() returns false if no more bytes were available.

@@ -1413,69 +660,8 @@
         /// <returns></returns>

         private bool RefillBuffer(bool mustSucceed)

         {

-            if (bufferPos < bufferSize)

-            {

-                throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");

-            }

-

-            if (totalBytesRetired + bufferSize == currentLimit)

-            {

-                // Oops, we hit a limit.

-                if (mustSucceed)

-                {

-                    throw InvalidProtocolBufferException.TruncatedMessage();

-                }

-                else

-                {

-                    return false;

-                }

-            }

-

-            totalBytesRetired += bufferSize;

-

-            bufferPos = 0;

-            bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);

-            if (bufferSize < 0)

-            {

-                throw new InvalidOperationException("Stream.Read returned a negative count");

-            }

-            if (bufferSize == 0)

-            {

-                if (mustSucceed)

-                {

-                    throw InvalidProtocolBufferException.TruncatedMessage();

-                }

-                else

-                {

-                    return false;

-                }

-            }

-            else

-            {

-                RecomputeBufferSizeAfterLimit();

-                int totalBytesRead =

-                    totalBytesRetired + bufferSize + bufferSizeAfterLimit;

-                if (totalBytesRead < 0 || totalBytesRead > sizeLimit)

-                {

-                    throw InvalidProtocolBufferException.SizeLimitExceeded();

-                }

-                return true;

-            }

-        }

-

-        /// <summary>

-        /// Read one byte from the input.

-        /// </summary>

-        /// <exception cref="InvalidProtocolBufferException">

-        /// the end of the stream or the current limit was reached

-        /// </exception>

-        internal byte ReadRawByte()

-        {

-            if (bufferPos == bufferSize)

-            {

-                RefillBuffer(true);

-            }

-            return buffer[bufferPos++];

+            var span = new ReadOnlySpan<byte>(buffer);

+            return state.segmentedBufferHelper.RefillBuffer(ref span, ref state, mustSucceed);

         }

 

         /// <summary>

@@ -1486,193 +672,25 @@
         /// </exception>

         internal byte[] ReadRawBytes(int size)

         {

-            if (size < 0)

-            {

-                throw InvalidProtocolBufferException.NegativeSize();

-            }

-

-            if (totalBytesRetired + bufferPos + size > currentLimit)

-            {

-                // Read to the end of the stream (up to the current limit) anyway.

-                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);

-                // Then fail.

-                throw InvalidProtocolBufferException.TruncatedMessage();

-            }

-

-            if (size <= bufferSize - bufferPos)

-            {

-                // We have all the bytes we need already.

-                byte[] bytes = new byte[size];

-                ByteArray.Copy(buffer, bufferPos, bytes, 0, size);

-                bufferPos += size;

-                return bytes;

-            }

-            else if (size < buffer.Length)

-            {

-                // Reading more bytes than are in the buffer, but not an excessive number

-                // of bytes.  We can safely allocate the resulting array ahead of time.

-

-                // First copy what we have.

-                byte[] bytes = new byte[size];

-                int pos = bufferSize - bufferPos;

-                ByteArray.Copy(buffer, bufferPos, bytes, 0, pos);

-                bufferPos = bufferSize;

-

-                // We want to use RefillBuffer() and then copy from the buffer into our

-                // byte array rather than reading directly into our byte array because

-                // the input may be unbuffered.

-                RefillBuffer(true);

-

-                while (size - pos > bufferSize)

-                {

-                    Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize);

-                    pos += bufferSize;

-                    bufferPos = bufferSize;

-                    RefillBuffer(true);

-                }

-

-                ByteArray.Copy(buffer, 0, bytes, pos, size - pos);

-                bufferPos = size - pos;

-

-                return bytes;

-            }

-            else

-            {

-                // The size is very large.  For security reasons, we can't allocate the

-                // entire byte array yet.  The size comes directly from the input, so a

-                // maliciously-crafted message could provide a bogus very large size in

-                // order to trick the app into allocating a lot of memory.  We avoid this

-                // by allocating and reading only a small chunk at a time, so that the

-                // malicious message must actually *be* extremely large to cause

-                // problems.  Meanwhile, we limit the allowed size of a message elsewhere.

-

-                // Remember the buffer markers since we'll have to copy the bytes out of

-                // it later.

-                int originalBufferPos = bufferPos;

-                int originalBufferSize = bufferSize;

-

-                // Mark the current buffer consumed.

-                totalBytesRetired += bufferSize;

-                bufferPos = 0;

-                bufferSize = 0;

-

-                // Read all the rest of the bytes we need.

-                int sizeLeft = size - (originalBufferSize - originalBufferPos);

-                List<byte[]> chunks = new List<byte[]>();

-

-                while (sizeLeft > 0)

-                {

-                    byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)];

-                    int pos = 0;

-                    while (pos < chunk.Length)

-                    {

-                        int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);

-                        if (n <= 0)

-                        {

-                            throw InvalidProtocolBufferException.TruncatedMessage();

-                        }

-                        totalBytesRetired += n;

-                        pos += n;

-                    }

-                    sizeLeft -= chunk.Length;

-                    chunks.Add(chunk);

-                }

-

-                // OK, got everything.  Now concatenate it all into one buffer.

-                byte[] bytes = new byte[size];

-

-                // Start by copying the leftover bytes from this.buffer.

-                int newPos = originalBufferSize - originalBufferPos;

-                ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos);

-

-                // And now all the chunks.

-                foreach (byte[] chunk in chunks)

-                {

-                    Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);

-                    newPos += chunk.Length;

-                }

-

-                // Done.

-                return bytes;

-            }

+            var span = new ReadOnlySpan<byte>(buffer);

+            return ParsingPrimitives.ReadRawBytes(ref span, ref state, size);

         }

 

         /// <summary>

-        /// Reads and discards <paramref name="size"/> bytes.

+        /// Reads a top-level message or a nested message after the limits for this message have been pushed.

+        /// (parser will proceed until the end of the current limit)

+        /// NOTE: this method needs to be public because it's invoked by the generated code - e.g. msg.MergeFrom(CodedInputStream input) method

         /// </summary>

-        /// <exception cref="InvalidProtocolBufferException">the end of the stream

-        /// or the current limit was reached</exception>

-        private void SkipRawBytes(int size)

+        public void ReadRawMessage(IMessage message)

         {

-            if (size < 0)

+            ParseContext.Initialize(this, out ParseContext ctx);

+            try

             {

-                throw InvalidProtocolBufferException.NegativeSize();

+                ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message);

             }

-

-            if (totalBytesRetired + bufferPos + size > currentLimit)

+            finally

             {

-                // Read to the end of the stream anyway.

-                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);

-                // Then fail.

-                throw InvalidProtocolBufferException.TruncatedMessage();

-            }

-

-            if (size <= bufferSize - bufferPos)

-            {

-                // We have all the bytes we need already.

-                bufferPos += size;

-            }

-            else

-            {

-                // Skipping more bytes than are in the buffer.  First skip what we have.

-                int pos = bufferSize - bufferPos;

-

-                // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize)

-                // totalBytesRetired += pos;

-                totalBytesRetired += bufferSize;

-                

-                bufferPos = 0;

-                bufferSize = 0;

-

-                // Then skip directly from the InputStream for the rest.

-                if (pos < size)

-                {

-                    if (input == null)

-                    {

-                        throw InvalidProtocolBufferException.TruncatedMessage();

-                    }

-                    SkipImpl(size - pos);

-                    totalBytesRetired += size - pos;

-                }

-            }

-        }

-

-        /// <summary>

-        /// Abstraction of skipping to cope with streams which can't really skip.

-        /// </summary>

-        private void SkipImpl(int amountToSkip)

-        {

-            if (input.CanSeek)

-            {

-                long previousPosition = input.Position;

-                input.Position += amountToSkip;

-                if (input.Position != previousPosition + amountToSkip)

-                {

-                    throw InvalidProtocolBufferException.TruncatedMessage();

-                }

-            }

-            else

-            {

-                byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)];

-                while (amountToSkip > 0)

-                {

-                    int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip));

-                    if (bytesRead <= 0)

-                    {

-                        throw InvalidProtocolBufferException.TruncatedMessage();

-                    }

-                    amountToSkip -= bytesRead;

-                }

+                ctx.CopyStateTo(this);

             }

         }

 #endregion

diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
index aa79324..cb92354 100644
--- a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
+++ b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
@@ -132,7 +132,7 @@
         /// </summary>

         public static int ComputeStringSize(String value)

         {

-            int byteArraySize = Utf8Encoding.GetByteCount(value);

+            int byteArraySize = WritingPrimitives.Utf8Encoding.GetByteCount(value);

             return ComputeLengthSize(byteArraySize) + byteArraySize;

         }

 

@@ -208,7 +208,7 @@
         /// </summary>

         public static int ComputeSInt32Size(int value)

         {

-            return ComputeRawVarint32Size(EncodeZigZag32(value));

+            return ComputeRawVarint32Size(WritingPrimitives.EncodeZigZag32(value));

         }

 

         /// <summary>

@@ -217,7 +217,7 @@
         /// </summary>

         public static int ComputeSInt64Size(long value)

         {

-            return ComputeRawVarint64Size(EncodeZigZag64(value));

+            return ComputeRawVarint64Size(WritingPrimitives.EncodeZigZag64(value));

         }

 

         /// <summary>

diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs
index 1d76d27..20d88ea 100644
--- a/csharp/src/Google.Protobuf/CodedOutputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs
@@ -33,6 +33,7 @@
 using Google.Protobuf.Collections;

 using System;

 using System.IO;

+using System.Security;

 using System.Text;

 

 namespace Google.Protobuf

@@ -55,11 +56,9 @@
     /// and <c>MapField&lt;TKey, TValue&gt;</c> to serialize such fields.

     /// </para>

     /// </remarks>

+    [SecuritySafeCritical]

     public sealed partial class CodedOutputStream : IDisposable

     {

-        // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)

-        internal static readonly Encoding Utf8Encoding = Encoding.UTF8;

-

         /// <summary>

         /// The buffer size used by CreateInstance(Stream).

         /// </summary>

@@ -67,8 +66,8 @@
 

         private readonly bool leaveOpen;

         private readonly byte[] buffer;

-        private readonly int limit;

-        private int position;

+        private WriterInternalState state;

+

         private readonly Stream output;

 

         #region Construction

@@ -90,8 +89,9 @@
         {

             this.output = null;

             this.buffer = ProtoPreconditions.CheckNotNull(buffer, nameof(buffer));

-            this.position = offset;

-            this.limit = offset + length;

+            this.state.position = offset;

+            this.state.limit = offset + length;

+            WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper);

             leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference

         }

 

@@ -99,8 +99,9 @@
         {

             this.output = ProtoPreconditions.CheckNotNull(output, nameof(output));

             this.buffer = buffer;

-            this.position = 0;

-            this.limit = buffer.Length;

+            this.state.position = 0;

+            this.state.limit = buffer.Length;

+            WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper);

             this.leaveOpen = leaveOpen;

         }

 

@@ -155,9 +156,9 @@
             {

                 if (output != null)

                 {

-                    return output.Position + position;

+                    return output.Position + state.position;

                 }

-                return position;

+                return state.position;

             }

         }

 

@@ -169,7 +170,8 @@
         /// <param name="value">The value to write</param>

         public void WriteDouble(double value)

         {

-            WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteDouble(ref span, ref state, value);

         }

 

         /// <summary>

@@ -178,23 +180,8 @@
         /// <param name="value">The value to write</param>

         public void WriteFloat(float value)

         {

-            byte[] rawBytes = BitConverter.GetBytes(value);

-            if (!BitConverter.IsLittleEndian)

-            {

-                ByteArray.Reverse(rawBytes);

-            }

-

-            if (limit - position >= 4)

-            {

-                buffer[position++] = rawBytes[0];

-                buffer[position++] = rawBytes[1];

-                buffer[position++] = rawBytes[2];

-                buffer[position++] = rawBytes[3];

-            }

-            else

-            {

-                WriteRawBytes(rawBytes, 0, 4);

-            }

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteFloat(ref span, ref state, value);

         }

 

         /// <summary>

@@ -203,7 +190,8 @@
         /// <param name="value">The value to write</param>

         public void WriteUInt64(ulong value)

         {

-            WriteRawVarint64(value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteUInt64(ref span, ref state, value);

         }

 

         /// <summary>

@@ -212,7 +200,8 @@
         /// <param name="value">The value to write</param>

         public void WriteInt64(long value)

         {

-            WriteRawVarint64((ulong) value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteInt64(ref span, ref state, value);

         }

 

         /// <summary>

@@ -221,15 +210,8 @@
         /// <param name="value">The value to write</param>

         public void WriteInt32(int value)

         {

-            if (value >= 0)

-            {

-                WriteRawVarint32((uint) value);

-            }

-            else

-            {

-                // Must sign-extend.

-                WriteRawVarint64((ulong) value);

-            }

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteInt32(ref span, ref state, value);

         }

 

         /// <summary>

@@ -238,7 +220,8 @@
         /// <param name="value">The value to write</param>

         public void WriteFixed64(ulong value)

         {

-            WriteRawLittleEndian64(value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteFixed64(ref span, ref state, value);

         }

 

         /// <summary>

@@ -247,7 +230,8 @@
         /// <param name="value">The value to write</param>

         public void WriteFixed32(uint value)

         {

-            WriteRawLittleEndian32(value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteFixed32(ref span, ref state, value);

         }

 

         /// <summary>

@@ -256,7 +240,8 @@
         /// <param name="value">The value to write</param>

         public void WriteBool(bool value)

         {

-            WriteRawByte(value ? (byte) 1 : (byte) 0);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteBool(ref span, ref state, value);

         }

 

         /// <summary>

@@ -266,30 +251,8 @@
         /// <param name="value">The value to write</param>

         public void WriteString(string value)

         {

-            // Optimise the case where we have enough space to write

-            // the string directly to the buffer, which should be common.

-            int length = Utf8Encoding.GetByteCount(value);

-            WriteLength(length);

-            if (limit - position >= length)

-            {

-                if (length == value.Length) // Must be all ASCII...

-                {

-                    for (int i = 0; i < length; i++)

-                    {

-                        buffer[position + i] = (byte)value[i];

-                    }

-                }

-                else

-                {

-                    Utf8Encoding.GetBytes(value, 0, value.Length, buffer, position);

-                }

-                position += length;

-            }

-            else

-            {

-                byte[] bytes = Utf8Encoding.GetBytes(value);

-                WriteRawBytes(bytes);

-            }

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteString(ref span, ref state, value);

         }

 

         /// <summary>

@@ -299,8 +262,41 @@
         /// <param name="value">The value to write</param>

         public void WriteMessage(IMessage value)

         {

-            WriteLength(value.CalculateSize());

-            value.WriteTo(this);

+            // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method),

+            // what we're doing here works fine, but could be more efficient.

+            // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it).

+            var span = new Span<byte>(buffer);

+            WriteContext.Initialize(ref span, ref state, out WriteContext ctx);

+            try

+            {

+                WritingPrimitivesMessages.WriteMessage(ref ctx, value);

+            }

+            finally

+            {

+                ctx.CopyStateTo(this);

+            }

+        }

+

+        /// <summary>

+        /// Writes a message, without a tag, to the stream.

+        /// Only the message data is written, without a length-delimiter.

+        /// </summary>

+        /// <param name="value">The value to write</param>

+        public void WriteRawMessage(IMessage value)

+        {

+            // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method),

+            // what we're doing here works fine, but could be more efficient.

+            // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it).

+            var span = new Span<byte>(buffer);

+            WriteContext.Initialize(ref span, ref state, out WriteContext ctx);

+            try

+            {

+                WritingPrimitivesMessages.WriteRawMessage(ref ctx, value);

+            }

+            finally

+            {

+                ctx.CopyStateTo(this);

+            }

         }

 

         /// <summary>

@@ -309,7 +305,16 @@
         /// <param name="value">The value to write</param>

         public void WriteGroup(IMessage value)

         {

-            value.WriteTo(this);

+            var span = new Span<byte>(buffer);

+            WriteContext.Initialize(ref span, ref state, out WriteContext ctx);

+            try

+            {

+                WritingPrimitivesMessages.WriteGroup(ref ctx, value);

+            }

+            finally

+            {

+                ctx.CopyStateTo(this);

+            }

         }

 

         /// <summary>

@@ -319,8 +324,8 @@
         /// <param name="value">The value to write</param>

         public void WriteBytes(ByteString value)

         {

-            WriteLength(value.Length);

-            value.WriteRawBytesTo(this);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteBytes(ref span, ref state, value);

         }

 

         /// <summary>

@@ -329,7 +334,8 @@
         /// <param name="value">The value to write</param>

         public void WriteUInt32(uint value)

         {

-            WriteRawVarint32(value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteUInt32(ref span, ref state, value);

         }

 

         /// <summary>

@@ -338,7 +344,8 @@
         /// <param name="value">The value to write</param>

         public void WriteEnum(int value)

         {

-            WriteInt32(value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteEnum(ref span, ref state, value);

         }

 

         /// <summary>

@@ -347,7 +354,8 @@
         /// <param name="value">The value to write.</param>

         public void WriteSFixed32(int value)

         {

-            WriteRawLittleEndian32((uint) value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteSFixed32(ref span, ref state, value);

         }

 

         /// <summary>

@@ -356,7 +364,8 @@
         /// <param name="value">The value to write</param>

         public void WriteSFixed64(long value)

         {

-            WriteRawLittleEndian64((ulong) value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteSFixed64(ref span, ref state, value);

         }

 

         /// <summary>

@@ -365,7 +374,8 @@
         /// <param name="value">The value to write</param>

         public void WriteSInt32(int value)

         {

-            WriteRawVarint32(EncodeZigZag32(value));

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteSInt32(ref span, ref state, value);

         }

 

         /// <summary>

@@ -374,7 +384,8 @@
         /// <param name="value">The value to write</param>

         public void WriteSInt64(long value)

         {

-            WriteRawVarint64(EncodeZigZag64(value));

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteSInt64(ref span, ref state, value);

         }

 

         /// <summary>

@@ -386,7 +397,8 @@
         /// <param name="length">Length value, in bytes.</param>

         public void WriteLength(int length)

         {

-            WriteRawVarint32((uint) length);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteLength(ref span, ref state, length);

         }

 

         #endregion

@@ -399,7 +411,8 @@
         /// <param name="type">The wire format type of the tag to write</param>

         public void WriteTag(int fieldNumber, WireFormat.WireType type)

         {

-            WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteTag(ref span, ref state, fieldNumber, type);

         }

 

         /// <summary>

@@ -408,7 +421,8 @@
         /// <param name="tag">The encoded tag</param>

         public void WriteTag(uint tag)

         {

-            WriteRawVarint32(tag);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteTag(ref span, ref state, tag);

         }

 

         /// <summary>

@@ -417,7 +431,8 @@
         /// <param name="b1">The encoded tag</param>

         public void WriteRawTag(byte b1)

         {

-            WriteRawByte(b1);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawTag(ref span, ref state, b1);

         }

 

         /// <summary>

@@ -427,8 +442,8 @@
         /// <param name="b2">The second byte of the encoded tag</param>

         public void WriteRawTag(byte b1, byte b2)

         {

-            WriteRawByte(b1);

-            WriteRawByte(b2);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2);

         }

 

         /// <summary>

@@ -439,9 +454,8 @@
         /// <param name="b3">The third byte of the encoded tag</param>

         public void WriteRawTag(byte b1, byte b2, byte b3)

         {

-            WriteRawByte(b1);

-            WriteRawByte(b2);

-            WriteRawByte(b3);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3);

         }

 

         /// <summary>

@@ -453,10 +467,8 @@
         /// <param name="b4">The fourth byte of the encoded tag</param>

         public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)

         {

-            WriteRawByte(b1);

-            WriteRawByte(b2);

-            WriteRawByte(b3);

-            WriteRawByte(b4);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4);

         }

 

         /// <summary>

@@ -469,15 +481,13 @@
         /// <param name="b5">The fifth byte of the encoded tag</param>

         public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)

         {

-            WriteRawByte(b1);

-            WriteRawByte(b2);

-            WriteRawByte(b3);

-            WriteRawByte(b4);

-            WriteRawByte(b5);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4, b5);

         }

         #endregion

 

         #region Underlying writing primitives

+        

         /// <summary>

         /// Writes a 32 bit value as a varint. The fast route is taken when

         /// there's enough buffer space left to whizz through without checking

@@ -485,112 +495,26 @@
         /// </summary>

         internal void WriteRawVarint32(uint value)

         {

-            // Optimize for the common case of a single byte value

-            if (value < 128 && position < limit)

-            {

-                buffer[position++] = (byte)value;

-                return;

-            }

-

-            while (value > 127 && position < limit)

-            {

-                buffer[position++] = (byte) ((value & 0x7F) | 0x80);

-                value >>= 7;

-            }

-            while (value > 127)

-            {

-                WriteRawByte((byte) ((value & 0x7F) | 0x80));

-                value >>= 7;

-            }

-            if (position < limit)

-            {

-                buffer[position++] = (byte) value;

-            }

-            else

-            {

-                WriteRawByte((byte) value);

-            }

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawVarint32(ref span, ref state, value);

         }

 

         internal void WriteRawVarint64(ulong value)

         {

-            while (value > 127 && position < limit)

-            {

-                buffer[position++] = (byte) ((value & 0x7F) | 0x80);

-                value >>= 7;

-            }

-            while (value > 127)

-            {

-                WriteRawByte((byte) ((value & 0x7F) | 0x80));

-                value >>= 7;

-            }

-            if (position < limit)

-            {

-                buffer[position++] = (byte) value;

-            }

-            else

-            {

-                WriteRawByte((byte) value);

-            }

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawVarint64(ref span, ref state, value);

         }

 

         internal void WriteRawLittleEndian32(uint value)

         {

-            if (position + 4 > limit)

-            {

-                WriteRawByte((byte) value);

-                WriteRawByte((byte) (value >> 8));

-                WriteRawByte((byte) (value >> 16));

-                WriteRawByte((byte) (value >> 24));

-            }

-            else

-            {

-                buffer[position++] = ((byte) value);

-                buffer[position++] = ((byte) (value >> 8));

-                buffer[position++] = ((byte) (value >> 16));

-                buffer[position++] = ((byte) (value >> 24));

-            }

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawLittleEndian32(ref span, ref state, value);

         }

 

         internal void WriteRawLittleEndian64(ulong value)

         {

-            if (position + 8 > limit)

-            {

-                WriteRawByte((byte) value);

-                WriteRawByte((byte) (value >> 8));

-                WriteRawByte((byte) (value >> 16));

-                WriteRawByte((byte) (value >> 24));

-                WriteRawByte((byte) (value >> 32));

-                WriteRawByte((byte) (value >> 40));

-                WriteRawByte((byte) (value >> 48));

-                WriteRawByte((byte) (value >> 56));

-            }

-            else

-            {

-                buffer[position++] = ((byte) value);

-                buffer[position++] = ((byte) (value >> 8));

-                buffer[position++] = ((byte) (value >> 16));

-                buffer[position++] = ((byte) (value >> 24));

-                buffer[position++] = ((byte) (value >> 32));

-                buffer[position++] = ((byte) (value >> 40));

-                buffer[position++] = ((byte) (value >> 48));

-                buffer[position++] = ((byte) (value >> 56));

-            }

-        }

-

-        internal void WriteRawByte(byte value)

-        {

-            if (position == limit)

-            {

-                RefreshBuffer();

-            }

-

-            buffer[position++] = value;

-        }

-

-        internal void WriteRawByte(uint value)

-        {

-            WriteRawByte((byte) value);

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawLittleEndian64(ref span, ref state, value);

         }

 

         /// <summary>

@@ -606,86 +530,13 @@
         /// </summary>

         internal void WriteRawBytes(byte[] value, int offset, int length)

         {

-            if (limit - position >= length)

-            {

-                ByteArray.Copy(value, offset, buffer, position, length);

-                // We have room in the current buffer.

-                position += length;

-            }

-            else

-            {

-                // Write extends past current buffer.  Fill the rest of this buffer and

-                // flush.

-                int bytesWritten = limit - position;

-                ByteArray.Copy(value, offset, buffer, position, bytesWritten);

-                offset += bytesWritten;

-                length -= bytesWritten;

-                position = limit;

-                RefreshBuffer();

-

-                // Now deal with the rest.

-                // Since we have an output stream, this is our buffer

-                // and buffer offset == 0

-                if (length <= limit)

-                {

-                    // Fits in new buffer.

-                    ByteArray.Copy(value, offset, buffer, 0, length);

-                    position = length;

-                }

-                else

-                {

-                    // Write is very big.  Let's do it all at once.

-                    output.Write(value, offset, length);

-                }

-            }

+            var span = new Span<byte>(buffer);

+            WritingPrimitives.WriteRawBytes(ref span, ref state, value, offset, length);

         }

 

         #endregion

 

         /// <summary>

-        /// Encode a 32-bit value with ZigZag encoding.

-        /// </summary>

-        /// <remarks>

-        /// ZigZag encodes signed integers into values that can be efficiently

-        /// encoded with varint.  (Otherwise, negative values must be 

-        /// sign-extended to 64 bits to be varint encoded, thus always taking

-        /// 10 bytes on the wire.)

-        /// </remarks>

-        internal static uint EncodeZigZag32(int n)

-        {

-            // Note:  the right-shift must be arithmetic

-            return (uint) ((n << 1) ^ (n >> 31));

-        }

-

-        /// <summary>

-        /// Encode a 64-bit value with ZigZag encoding.

-        /// </summary>

-        /// <remarks>

-        /// ZigZag encodes signed integers into values that can be efficiently

-        /// encoded with varint.  (Otherwise, negative values must be 

-        /// sign-extended to 64 bits to be varint encoded, thus always taking

-        /// 10 bytes on the wire.)

-        /// </remarks>

-        internal static ulong EncodeZigZag64(long n)

-        {

-            return (ulong) ((n << 1) ^ (n >> 63));

-        }

-

-        private void RefreshBuffer()

-        {

-            if (output == null)

-            {

-                // We're writing to a single buffer.

-                throw new OutOfSpaceException();

-            }

-

-            // Since we have an output stream, this is our buffer

-            // and buffer offset == 0

-            output.Write(buffer, 0, position);

-            position = 0;

-        }

-

-        /// <summary>

         /// Indicates that a CodedOutputStream wrapping a flat byte array

         /// ran out of space.

         /// </summary>

@@ -726,45 +577,31 @@
         /// </summary>

         public void Flush()

         {

-            if (output != null)

-            {

-                RefreshBuffer();

-            }

+            var span = new Span<byte>(buffer);

+            WriteBufferHelper.Flush(ref span, ref state);

         }

 

         /// <summary>

         /// Verifies that SpaceLeft returns zero. It's common to create a byte array

         /// that is exactly big enough to hold a message, then write to it with

         /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that

-        /// the message was actually as big as expected, which can help bugs.

+        /// the message was actually as big as expected, which can help finding bugs.

         /// </summary>

         public void CheckNoSpaceLeft()

         {

-            if (SpaceLeft != 0)

-            {

-                throw new InvalidOperationException("Did not write as much data as expected.");

-            }

+            WriteBufferHelper.CheckNoSpaceLeft(ref state);

         }

 

         /// <summary>

         /// If writing to a flat array, returns the space left in the array. Otherwise,

         /// throws an InvalidOperationException.

         /// </summary>

-        public int SpaceLeft

-        {

-            get

-            {

-                if (output == null)

-                {

-                    return limit - position;

-                }

-                else

-                {

-                    throw new InvalidOperationException(

-                        "SpaceLeft can only be called on CodedOutputStreams that are " +

-                        "writing to a flat array.");

-                }

-            }

-        }

+        public int SpaceLeft => WriteBufferHelper.GetSpaceLeft(ref state);

+

+        internal byte[] InternalBuffer => buffer;

+

+        internal Stream InternalOutputStream => output;

+

+        internal ref WriterInternalState InternalState => ref state;

     }

 }

diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs
index 1924439..6b7d0f1 100644
--- a/csharp/src/Google.Protobuf/Collections/MapField.cs
+++ b/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -33,10 +33,12 @@
 using Google.Protobuf.Compatibility;

 using Google.Protobuf.Reflection;

 using System;

+using System.Buffers;

 using System.Collections;

 using System.Collections.Generic;

 using System.IO;

 using System.Linq;

+using System.Security;

 

 namespace Google.Protobuf.Collections

 {

@@ -422,13 +424,35 @@
         /// <param name="codec">Codec describing how the key/value pairs are encoded</param>

         public void AddEntriesFrom(CodedInputStream input, Codec codec)

         {

-            var adapter = new Codec.MessageAdapter(codec);

+            ParseContext.Initialize(input, out ParseContext ctx);

+            try

+            {

+                AddEntriesFrom(ref ctx, codec);

+            }

+            finally

+            {

+                ctx.CopyStateTo(input);

+            }

+        }

+

+        /// <summary>

+        /// Adds entries to the map from the given parse context.

+        /// </summary>

+        /// <remarks>

+        /// It is assumed that the input is initially positioned after the tag specified by the codec.

+        /// This method will continue reading entries from the input until the end is reached, or

+        /// a different tag is encountered.

+        /// </remarks>

+        /// <param name="ctx">Input to read from</param>

+        /// <param name="codec">Codec describing how the key/value pairs are encoded</param>

+        [SecuritySafeCritical]

+        public void AddEntriesFrom(ref ParseContext ctx, Codec codec)

+        {

             do

             {

-                adapter.Reset();

-                input.ReadMessage(adapter);

-                this[adapter.Key] = adapter.Value;

-            } while (input.MaybeConsumeTag(codec.MapTag));

+                KeyValuePair<TKey, TValue> entry = ParsingPrimitivesMessages.ReadMapEntry(ref ctx, codec);

+                this[entry.Key] = entry.Value;

+            } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag));

         }

 

         /// <summary>

@@ -439,13 +463,33 @@
         /// <param name="codec">The codec to use for each entry.</param>

         public void WriteTo(CodedOutputStream output, Codec codec)

         {

-            var message = new Codec.MessageAdapter(codec);

+            WriteContext.Initialize(output, out WriteContext ctx);

+            try

+            {

+                WriteTo(ref ctx, codec);

+            }

+            finally

+            {

+                ctx.CopyStateTo(output);

+            }

+        }

+

+        /// <summary>

+        /// Writes the contents of this map to the given write context, using the specified codec

+        /// to encode each entry.

+        /// </summary>

+        /// <param name="ctx">The write context to write to.</param>

+        /// <param name="codec">The codec to use for each entry.</param>

+        [SecuritySafeCritical]

+        public void WriteTo(ref WriteContext ctx, Codec codec)

+        {

             foreach (var entry in list)

             {

-                message.Key = entry.Key;

-                message.Value = entry.Value;

-                output.WriteTag(codec.MapTag);

-                output.WriteMessage(message);

+                ctx.WriteTag(codec.MapTag);

+

+                WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, CalculateEntrySize(codec, entry));

+                codec.KeyCodec.WriteTagAndValue(ref ctx, entry.Key);

+                codec.ValueCodec.WriteTagAndValue(ref ctx, entry.Value);

             }

         }

 

@@ -460,18 +504,22 @@
             {

                 return 0;

             }

-            var message = new Codec.MessageAdapter(codec);

             int size = 0;

             foreach (var entry in list)

             {

-                message.Key = entry.Key;

-                message.Value = entry.Value;

+                int entrySize = CalculateEntrySize(codec, entry);

+

                 size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);

-                size += CodedOutputStream.ComputeMessageSize(message);

+                size += CodedOutputStream.ComputeLengthSize(entrySize) + entrySize;

             }

             return size;

         }

 

+        private static int CalculateEntrySize(Codec codec, KeyValuePair<TKey, TValue> entry)

+        {

+            return codec.KeyCodec.CalculateSizeWithTag(entry.Key) + codec.ValueCodec.CalculateSizeWithTag(entry.Value);

+        }

+

         /// <summary>

         /// Returns a string representation of this repeated field, in the same

         /// way as it would be represented by the default JSON formatter.

@@ -609,76 +657,19 @@
             }

 

             /// <summary>

-            /// The tag used in the enclosing message to indicate map entries.

+            /// The key codec.

             /// </summary>

-            internal uint MapTag { get { return mapTag; } }

+            internal FieldCodec<TKey> KeyCodec => keyCodec;

 

             /// <summary>

-            /// A mutable message class, used for parsing and serializing. This

-            /// delegates the work to a codec, but implements the <see cref="IMessage"/> interface

-            /// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.

-            /// This is nested inside Codec as it's tightly coupled to the associated codec,

-            /// and it's simpler if it has direct access to all its fields.

+            /// The value codec.

             /// </summary>

-            internal class MessageAdapter : IMessage

-            {

-                private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };

+            internal FieldCodec<TValue> ValueCodec => valueCodec;

 

-                private readonly Codec codec;

-                internal TKey Key { get; set; }

-                internal TValue Value { get; set; }

-

-                internal MessageAdapter(Codec codec)

-                {

-                    this.codec = codec;

-                }

-

-                internal void Reset()

-                {

-                    Key = codec.keyCodec.DefaultValue;

-                    Value = codec.valueCodec.DefaultValue;

-                }

-

-                public void MergeFrom(CodedInputStream input)

-                {

-                    uint tag;

-                    while ((tag = input.ReadTag()) != 0)

-                    {

-                        if (tag == codec.keyCodec.Tag)

-                        {

-                            Key = codec.keyCodec.Read(input);

-                        }

-                        else if (tag == codec.valueCodec.Tag)

-                        {

-                            Value = codec.valueCodec.Read(input);

-                        }

-                        else 

-                        {

-                            input.SkipLastField();

-                        }

-                    }

-

-                    // Corner case: a map entry with a key but no value, where the value type is a message.

-                    // Read it as if we'd seen an input stream with no data (i.e. create a "default" message).

-                    if (Value == null)

-                    {

-                        Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));

-                    }

-                }

-

-                public void WriteTo(CodedOutputStream output)

-                {

-                    codec.keyCodec.WriteTagAndValue(output, Key);

-                    codec.valueCodec.WriteTagAndValue(output, Value);

-                }

-

-                public int CalculateSize()

-                {

-                    return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);

-                }

-

-                MessageDescriptor IMessage.Descriptor { get { return null; } }

-            }

+            /// <summary>

+            /// The tag used in the enclosing message to indicate map entries.

+            /// </summary>

+            internal uint MapTag => mapTag;

         }

 

         private class MapView<T> : ICollection<T>, ICollection

diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
index 0e8bb61..19114ca 100644
--- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
+++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -34,6 +34,8 @@
 using System.Collections;

 using System.Collections.Generic;

 using System.IO;

+using System.Security;

+using System.Threading;

 

 namespace Google.Protobuf.Collections

 {

@@ -95,22 +97,63 @@
         /// <param name="codec">The codec to use in order to read each entry.</param>

         public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec)

         {

+            ParseContext.Initialize(input, out ParseContext ctx);

+            try

+            {

+                AddEntriesFrom(ref ctx, codec);

+            }

+            finally

+            {

+                ctx.CopyStateTo(input);

+            }

+        }

+

+        /// <summary>

+        /// Adds the entries from the given parse context, decoding them with the specified codec.

+        /// </summary>

+        /// <param name="ctx">The input to read from.</param>

+        /// <param name="codec">The codec to use in order to read each entry.</param>

+        [SecuritySafeCritical]

+        public void AddEntriesFrom(ref ParseContext ctx, FieldCodec<T> codec)

+        {

             // TODO: Inline some of the Add code, so we can avoid checking the size on every

             // iteration.

-            uint tag = input.LastTag;

+            uint tag = ctx.state.lastTag;

             var reader = codec.ValueReader;

             // Non-nullable value types can be packed or not.

             if (FieldCodec<T>.IsPackedRepeatedField(tag))

             {

-                int length = input.ReadLength();

+                int length = ctx.ReadLength();

                 if (length > 0)

                 {

-                    int oldLimit = input.PushLimit(length);

-                    while (!input.ReachedLimit)

+                    int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length);

+

+                    // If the content is fixed size then we can calculate the length

+                    // of the repeated field and pre-initialize the underlying collection.

+                    //

+                    // Check that the supplied length doesn't exceed the underlying buffer.

+                    // That prevents a malicious length from initializing a very large collection.

+                    if (codec.FixedSize > 0 && length % codec.FixedSize == 0 && ParsingPrimitives.IsDataAvailable(ref ctx.state, length))

                     {

-                        Add(reader(input));

+                        EnsureSize(count + (length / codec.FixedSize));

+

+                        while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state))

+                        {

+                            // Only FieldCodecs with a fixed size can reach here, and they are all known

+                            // types that don't allow the user to specify a custom reader action.

+                            // reader action will never return null.

+                            array[count++] = reader(ref ctx);

+                        }

                     }

-                    input.PopLimit(oldLimit);

+                    else

+                    {

+                        // Content is variable size so add until we reach the limit.

+                        while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state))

+                        {

+                            Add(reader(ref ctx));

+                        }

+                    }

+                    SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);

                 }

                 // Empty packed field. Odd, but valid - just ignore.

             }

@@ -119,8 +162,8 @@
                 // Not packed... (possibly not packable)

                 do

                 {

-                    Add(reader(input));

-                } while (input.MaybeConsumeTag(tag));

+                    Add(reader(ref ctx));

+                } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, tag));

             }

         }

 

@@ -128,7 +171,7 @@
         /// Calculates the size of this collection based on the given codec.

         /// </summary>

         /// <param name="codec">The codec to use when encoding each field.</param>

-        /// <returns>The number of bytes that would be written to a <see cref="CodedOutputStream"/> by <see cref="WriteTo"/>,

+        /// <returns>The number of bytes that would be written to an output by one of the <c>WriteTo</c> methods,

         /// using the same codec.</returns>

         public int CalculateSize(FieldCodec<T> codec)

         {

@@ -187,6 +230,26 @@
         /// <param name="codec">The codec to use when encoding each value.</param>

         public void WriteTo(CodedOutputStream output, FieldCodec<T> codec)

         {

+            WriteContext.Initialize(output, out WriteContext ctx);

+            try

+            {

+                WriteTo(ref ctx, codec);

+            }

+            finally

+            {

+                ctx.CopyStateTo(output);

+            }

+        }

+

+        /// <summary>

+        /// Writes the contents of this collection to the given write context,

+        /// encoding each value using the specified codec.

+        /// </summary>

+        /// <param name="ctx">The write context to write to.</param>

+        /// <param name="codec">The codec to use when encoding each value.</param>

+        [SecuritySafeCritical]

+        public void WriteTo(ref WriteContext ctx, FieldCodec<T> codec)

+        {

             if (count == 0)

             {

                 return;

@@ -196,12 +259,12 @@
             if (codec.PackedRepeatedField)

             {

                 // Packed primitive type

-                uint size = (uint)CalculatePackedDataSize(codec);

-                output.WriteTag(tag);

-                output.WriteRawVarint32(size);

+                int size = CalculatePackedDataSize(codec);

+                ctx.WriteTag(tag);

+                ctx.WriteLength(size);

                 for (int i = 0; i < count; i++)

                 {

-                    writer(output, array[i]);

+                    writer(ref ctx, array[i]);

                 }

             }

             else

@@ -210,11 +273,11 @@
                 // Can't use codec.WriteTagAndValue, as that omits default values.

                 for (int i = 0; i < count; i++)

                 {

-                    output.WriteTag(tag);

-                    writer(output, array[i]);

+                    ctx.WriteTag(tag);

+                    writer(ref ctx, array[i]);

                     if (codec.EndTag != 0)

                     {

-                        output.WriteTag(codec.EndTag);

+                        ctx.WriteTag(codec.EndTag);

                     }

                 }

             }

diff --git a/csharp/src/Google.Protobuf/Extension.cs b/csharp/src/Google.Protobuf/Extension.cs
index a96f8d2..6dd1cea 100644
--- a/csharp/src/Google.Protobuf/Extension.cs
+++ b/csharp/src/Google.Protobuf/Extension.cs
@@ -55,6 +55,8 @@
         /// Gets the field number of this extension
         /// </summary>
         public int FieldNumber { get; }
+
+        internal abstract bool IsRepeated { get; }
     }
 
     /// <summary>
@@ -79,6 +81,8 @@
 
         internal override Type TargetType => typeof(TTarget);
 
+        internal override bool IsRepeated => false;
+
         internal override IExtensionValue CreateValue()
         {
             return new ExtensionValue<TValue>(codec);
@@ -105,6 +109,8 @@
 
         internal override Type TargetType => typeof(TTarget);
 
+        internal override bool IsRepeated => true;
+
         internal override IExtensionValue CreateValue()
         {
             return new RepeatedExtensionValue<TValue>(codec);
diff --git a/csharp/src/Google.Protobuf/ExtensionRegistry.cs b/csharp/src/Google.Protobuf/ExtensionRegistry.cs
index d3d7ebd..e72314b 100644
--- a/csharp/src/Google.Protobuf/ExtensionRegistry.cs
+++ b/csharp/src/Google.Protobuf/ExtensionRegistry.cs
@@ -80,9 +80,9 @@
         /// </summary>
         bool ICollection<Extension>.IsReadOnly => false;
 
-        internal bool ContainsInputField(CodedInputStream stream, Type target, out Extension extension)
+        internal bool ContainsInputField(uint lastTag, Type target, out Extension extension)
         {
-            return extensions.TryGetValue(new ObjectIntPair<Type>(target, WireFormat.GetTagFieldNumber(stream.LastTag)), out extension);
+            return extensions.TryGetValue(new ObjectIntPair<Type>(target, WireFormat.GetTagFieldNumber(lastTag)), out extension);
         }
 
         /// <summary>
diff --git a/csharp/src/Google.Protobuf/ExtensionSet.cs b/csharp/src/Google.Protobuf/ExtensionSet.cs
index d1bbf69..895b9ae 100644
--- a/csharp/src/Google.Protobuf/ExtensionSet.cs
+++ b/csharp/src/Google.Protobuf/ExtensionSet.cs
@@ -34,6 +34,7 @@
 using System;

 using System.Collections.Generic;

 using System.Linq;

+using System.Security;

 

 namespace Google.Protobuf

 {

@@ -183,19 +184,36 @@
         /// </summary>

         public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, CodedInputStream stream) where TTarget : IExtendableMessage<TTarget>

         {

+            ParseContext.Initialize(stream, out ParseContext ctx);

+            try

+            {

+                return TryMergeFieldFrom<TTarget>(ref set, ref ctx);

+            }

+            finally

+            {

+                ctx.CopyStateTo(stream);

+            }

+        }

+

+        /// <summary>

+        /// Tries to merge a field from the coded input, returning true if the field was merged.

+        /// If the set is null or the field was not otherwise merged, this returns false.

+        /// </summary>

+        public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, ref ParseContext ctx) where TTarget : IExtendableMessage<TTarget>

+        {

             Extension extension;

-            int lastFieldNumber = WireFormat.GetTagFieldNumber(stream.LastTag);

-            

+            int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag);

+

             IExtensionValue extensionValue;

             if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue))

             {

-                extensionValue.MergeFrom(stream);

+                extensionValue.MergeFrom(ref ctx);

                 return true;

             }

-            else if (stream.ExtensionRegistry != null && stream.ExtensionRegistry.ContainsInputField(stream, typeof(TTarget), out extension))

+            else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension))

             {

                 IExtensionValue value = extension.CreateValue();

-                value.MergeFrom(stream);

+                value.MergeFrom(ref ctx);

                 set = (set ?? new ExtensionSet<TTarget>());

                 set.ValuesByNumber.Add(extension.FieldNumber, value);

                 return true;

@@ -327,9 +345,27 @@
         /// </summary>

         public void WriteTo(CodedOutputStream stream)

         {

+            

+            WriteContext.Initialize(stream, out WriteContext ctx);

+            try

+            {

+                WriteTo(ref ctx);

+            }

+            finally

+            {

+                ctx.CopyStateTo(stream);

+            }

+        }

+

+        /// <summary>

+        /// Writes the extension values in this set to the write context

+        /// </summary>

+        [SecuritySafeCritical]

+        public void WriteTo(ref WriteContext ctx)

+        {

             foreach (var value in ValuesByNumber.Values)

             {

-                value.WriteTo(stream);

+                value.WriteTo(ref ctx);

             }

         }

 

diff --git a/csharp/src/Google.Protobuf/ExtensionValue.cs b/csharp/src/Google.Protobuf/ExtensionValue.cs
index 6ee737a..5257c4c 100644
--- a/csharp/src/Google.Protobuf/ExtensionValue.cs
+++ b/csharp/src/Google.Protobuf/ExtensionValue.cs
@@ -38,9 +38,10 @@
 {
     internal interface IExtensionValue : IEquatable<IExtensionValue>, IDeepCloneable<IExtensionValue>
     {
-        void MergeFrom(CodedInputStream input);
+        void MergeFrom(ref ParseContext ctx);
+
         void MergeFrom(IExtensionValue value);
-        void WriteTo(CodedOutputStream output);
+        void WriteTo(ref WriteContext ctx);
         int CalculateSize();
         bool IsInitialized();
     }
@@ -58,7 +59,7 @@
 
         public int CalculateSize()
         {
-            return codec.CalculateSizeWithTag(field);
+            return codec.CalculateUnconditionalSizeWithTag(field);
         }
 
         public IExtensionValue Clone()
@@ -91,27 +92,27 @@
             }
         }
 
-        public void MergeFrom(CodedInputStream input)
+        public void MergeFrom(ref ParseContext ctx)
         {
-            codec.ValueMerger(input, ref field);
+            codec.ValueMerger(ref ctx, ref field);
         }
 
         public void MergeFrom(IExtensionValue value)
         {
             if (value is ExtensionValue<T>)
             {
-                var extensionValue = value as ExtensionValue<T>;

+                var extensionValue = value as ExtensionValue<T>;
                 codec.FieldMerger(ref field, extensionValue.field);
             }
         }
 
-        public void WriteTo(CodedOutputStream output)
+        public void WriteTo(ref WriteContext ctx)
         {
-            output.WriteTag(codec.Tag);
-            codec.ValueWriter(output, field);
+            ctx.WriteTag(codec.Tag);
+            codec.ValueWriter(ref ctx, field);
             if (codec.EndTag != 0)
             {
-                output.WriteTag(codec.EndTag);
+                ctx.WriteTag(codec.EndTag);
             }
         }
 
@@ -124,13 +125,13 @@
 
         public bool IsInitialized()
         {
-            if (field is IMessage)

-            {

-                return (field as IMessage).IsInitialized();

+            if (field is IMessage)
+            {
+                return (field as IMessage).IsInitialized();
             }
-            else

-            {

-                return true;

+            else
+            {
+                return true;
             }
         }
     }
@@ -180,9 +181,9 @@
             }
         }
 
-        public void MergeFrom(CodedInputStream input)
+        public void MergeFrom(ref ParseContext ctx)
         {
-            field.AddEntriesFrom(input, codec);
+            field.AddEntriesFrom(ref ctx, codec);
         }
 
         public void MergeFrom(IExtensionValue value)
@@ -193,29 +194,29 @@
             }
         }
 
-        public void WriteTo(CodedOutputStream output)
+        public void WriteTo(ref WriteContext ctx)
         {
-            field.WriteTo(output, codec);
+            field.WriteTo(ref ctx, codec);
         }
 
         public RepeatedField<T> GetValue() => field;
 
         public bool IsInitialized()
         {
-            for (int i = 0; i < field.Count; i++)

-            {

-                var element = field[i];

-                if (element is IMessage)

-                {

-                    if (!(element as IMessage).IsInitialized())

-                    {

-                        return false;

-                    }

-                }

-                else

-                {

-                    break;

-                }

+            for (int i = 0; i < field.Count; i++)
+            {
+                var element = field[i];
+                if (element is IMessage)
+                {
+                    if (!(element as IMessage).IsInitialized())
+                    {
+                        return false;
+                    }
+                }
+                else
+                {
+                    break;
+                }
             }
 
             return true;
diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs
index 1971261..ee6bd6a 100644
--- a/csharp/src/Google.Protobuf/FieldCodec.cs
+++ b/csharp/src/Google.Protobuf/FieldCodec.cs
@@ -35,6 +35,7 @@
 using Google.Protobuf.WellKnownTypes;
 using System;
 using System.Collections.Generic;
+using System.Security;
 
 namespace Google.Protobuf
 {
@@ -218,7 +219,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<string> ForString(uint tag, string defaultValue)
         {
-            return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue);
+            return new FieldCodec<string>((ref ParseContext ctx) => ctx.ReadString(), (ref WriteContext ctx, string value) => ctx.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue);
         }
 
         /// <summary>
@@ -229,7 +230,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<ByteString> ForBytes(uint tag, ByteString defaultValue)
         {
-            return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue);
+            return new FieldCodec<ByteString>((ref ParseContext ctx) => ctx.ReadBytes(), (ref WriteContext ctx, ByteString value) => ctx.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue);
         }
 
         /// <summary>
@@ -240,7 +241,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<bool> ForBool(uint tag, bool defaultValue)
         {
-            return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue);
+            return new FieldCodec<bool>((ref ParseContext ctx) => ctx.ReadBool(), (ref WriteContext ctx, bool value) => ctx.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue);
         }
 
         /// <summary>
@@ -251,7 +252,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<int> ForInt32(uint tag, int defaultValue)
         {
-            return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue);
+            return new FieldCodec<int>((ref ParseContext ctx) => ctx.ReadInt32(), (ref WriteContext output, int value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue);
         }
 
         /// <summary>
@@ -262,7 +263,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<int> ForSInt32(uint tag, int defaultValue)
         {
-            return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue);
+            return new FieldCodec<int>((ref ParseContext ctx) => ctx.ReadSInt32(), (ref WriteContext output, int value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue);
         }
 
         /// <summary>
@@ -273,7 +274,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<uint> ForFixed32(uint tag, uint defaultValue)
         {
-            return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag, defaultValue);
+            return new FieldCodec<uint>((ref ParseContext ctx) => ctx.ReadFixed32(), (ref WriteContext output, uint value) => output.WriteFixed32(value), 4, tag, defaultValue);
         }
 
         /// <summary>
@@ -284,7 +285,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<int> ForSFixed32(uint tag, int defaultValue)
         {
-            return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag, defaultValue);
+            return new FieldCodec<int>((ref ParseContext ctx) => ctx.ReadSFixed32(), (ref WriteContext output, int value) => output.WriteSFixed32(value), 4, tag, defaultValue);
         }
 
         /// <summary>
@@ -295,7 +296,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<uint> ForUInt32(uint tag, uint defaultValue)
         {
-            return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue);
+            return new FieldCodec<uint>((ref ParseContext ctx) => ctx.ReadUInt32(), (ref WriteContext output, uint value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue);
         }
 
         /// <summary>
@@ -306,7 +307,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<long> ForInt64(uint tag, long defaultValue)
         {
-            return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue);
+            return new FieldCodec<long>((ref ParseContext ctx) => ctx.ReadInt64(), (ref WriteContext output, long value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue);
         }
 
         /// <summary>
@@ -317,7 +318,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<long> ForSInt64(uint tag, long defaultValue)
         {
-            return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue);
+            return new FieldCodec<long>((ref ParseContext ctx) => ctx.ReadSInt64(), (ref WriteContext output, long value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue);
         }
 
         /// <summary>
@@ -328,7 +329,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<ulong> ForFixed64(uint tag, ulong defaultValue)
         {
-            return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag, defaultValue);
+            return new FieldCodec<ulong>((ref ParseContext ctx) => ctx.ReadFixed64(), (ref WriteContext output, ulong value) => output.WriteFixed64(value), 8, tag, defaultValue);
         }
 
         /// <summary>
@@ -339,7 +340,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<long> ForSFixed64(uint tag, long defaultValue)
         {
-            return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag, defaultValue);
+            return new FieldCodec<long>((ref ParseContext ctx) => ctx.ReadSFixed64(), (ref WriteContext output, long value) => output.WriteSFixed64(value), 8, tag, defaultValue);
         }
 
         /// <summary>
@@ -350,7 +351,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<ulong> ForUInt64(uint tag, ulong defaultValue)
         {
-            return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue);
+            return new FieldCodec<ulong>((ref ParseContext ctx) => ctx.ReadUInt64(), (ref WriteContext output, ulong value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue);
         }
 
         /// <summary>
@@ -361,7 +362,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<float> ForFloat(uint tag, float defaultValue)
         {
-            return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue);
+            return new FieldCodec<float>((ref ParseContext ctx) => ctx.ReadFloat(), (ref WriteContext output, float value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue);
         }
 
         /// <summary>
@@ -372,7 +373,7 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<double> ForDouble(uint tag, double defaultValue)
         {
-            return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue);
+            return new FieldCodec<double>((ref ParseContext ctx) => ctx.ReadDouble(), (ref WriteContext output, double value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue);
         }
 
         // Enums are tricky. We can probably use expression trees to build these delegates automatically,
@@ -388,9 +389,9 @@
         /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32, T defaultValue)
         {
-            return new FieldCodec<T>(input => fromInt32(
-                input.ReadEnum()),
-                (output, value) => output.WriteEnum(toInt32(value)),
+            return new FieldCodec<T>((ref ParseContext ctx) => fromInt32(
+                ctx.ReadEnum()),
+                (ref WriteContext output, T value) => output.WriteEnum(toInt32(value)),
                 value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag, defaultValue);
         }
 
@@ -403,21 +404,21 @@
         public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : class, IMessage<T>
         {
             return new FieldCodec<T>(
-                input => 
+                (ref ParseContext ctx) => 
                 { 
                     T message = parser.CreateTemplate(); 
-                    input.ReadMessage(message); 
+                    ctx.ReadMessage(message); 
                     return message; 
                 },
-                (output, value) => output.WriteMessage(value),
-                (CodedInputStream i, ref T v) => 
+                (ref WriteContext output, T value) => output.WriteMessage(value),
+                (ref ParseContext ctx, ref T v) => 
                 {
                     if (v == null)
                     {
                         v = parser.CreateTemplate();
                     }
 
-                    i.ReadMessage(v);
+                    ctx.ReadMessage(v);
                 },
                 (ref T v, T v2) =>
                 {
@@ -448,21 +449,21 @@
         public static FieldCodec<T> ForGroup<T>(uint startTag, uint endTag, MessageParser<T> parser) where T : class, IMessage<T>
         {
             return new FieldCodec<T>(
-                input => 
+                (ref ParseContext ctx) => 
                 { 
                     T message = parser.CreateTemplate();
-                    input.ReadGroup(message);
+                    ctx.ReadGroup(message);
                     return message;
                 },
-                (output, value) => output.WriteGroup(value), 
-                (CodedInputStream i, ref T v) => 
+                (ref WriteContext output, T value) => output.WriteGroup(value), 
+                (ref ParseContext ctx, ref T v) => 
                 {
                     if (v == null)
                     {
                         v = parser.CreateTemplate();
                     }
 
-                    i.ReadGroup(v);
+                    ctx.ReadGroup(v);
                 },
                 (ref T v, T v2) =>
                 {
@@ -490,9 +491,9 @@
         {
             var nestedCodec = WrapperCodecs.GetCodec<T>();
             return new FieldCodec<T>(
-                input => WrapperCodecs.Read<T>(input, nestedCodec),
-                (output, value) => WrapperCodecs.Write<T>(output, value, nestedCodec),
-                (CodedInputStream i, ref T v) => v = WrapperCodecs.Read<T>(i, nestedCodec),
+                (ref ParseContext ctx) => WrapperCodecs.Read<T>(ref ctx, nestedCodec),
+                (ref WriteContext output, T value) => WrapperCodecs.Write<T>(ref output, value, nestedCodec),
+                (ref ParseContext ctx, ref T v) => v = WrapperCodecs.Read<T>(ref ctx, nestedCodec),
                 (ref T v, T v2) => { v = v2; return v == null; },
                 value => WrapperCodecs.CalculateSize<T>(value, nestedCodec),
                 tag, 0,
@@ -508,8 +509,8 @@
             var nestedCodec = WrapperCodecs.GetCodec<T>();
             return new FieldCodec<T?>(
                 WrapperCodecs.GetReader<T>(),
-                (output, value) => WrapperCodecs.Write<T>(output, value.Value, nestedCodec),
-                (CodedInputStream i, ref T? v) => v = WrapperCodecs.Read<T>(i, nestedCodec),
+                (ref WriteContext output, T? value) => WrapperCodecs.Write<T>(ref output, value.Value, nestedCodec),
+                (ref ParseContext ctx, ref T? v) => v = WrapperCodecs.Read<T>(ref ctx, nestedCodec),
                 (ref T? v, T? v2) => { if (v2.HasValue) { v = v2; } return v.HasValue; },
                 value => value == null ? 0 : WrapperCodecs.CalculateSize<T>(value.Value, nestedCodec),
                 tag, 0,
@@ -542,17 +543,17 @@
             private static readonly Dictionary<System.Type, object> Readers = new Dictionary<System.Type, object>
             {
                 // TODO: Provide more optimized readers.
-                { typeof(bool), (Func<CodedInputStream, bool?>)CodedInputStream.ReadBoolWrapper },
-                { typeof(int), (Func<CodedInputStream, int?>)CodedInputStream.ReadInt32Wrapper },
-                { typeof(long), (Func<CodedInputStream, long?>)CodedInputStream.ReadInt64Wrapper },
-                { typeof(uint), (Func<CodedInputStream, uint?>)CodedInputStream.ReadUInt32Wrapper },
-                { typeof(ulong), (Func<CodedInputStream, ulong?>)CodedInputStream.ReadUInt64Wrapper },
+                { typeof(bool), (ValueReader<bool?>)ParsingPrimitivesWrappers.ReadBoolWrapper },
+                { typeof(int), (ValueReader<int?>)ParsingPrimitivesWrappers.ReadInt32Wrapper },
+                { typeof(long), (ValueReader<long?>)ParsingPrimitivesWrappers.ReadInt64Wrapper },
+                { typeof(uint), (ValueReader<uint?>)ParsingPrimitivesWrappers.ReadUInt32Wrapper },
+                { typeof(ulong), (ValueReader<ulong?>)ParsingPrimitivesWrappers.ReadUInt64Wrapper },
                 { typeof(float), BitConverter.IsLittleEndian ?
-                    (Func<CodedInputStream, float?>)CodedInputStream.ReadFloatWrapperLittleEndian :
-                    (Func<CodedInputStream, float?>)CodedInputStream.ReadFloatWrapperSlow },
+                    (ValueReader<float?>)ParsingPrimitivesWrappers.ReadFloatWrapperLittleEndian :
+                    (ValueReader<float?>)ParsingPrimitivesWrappers.ReadFloatWrapperSlow },
                 { typeof(double), BitConverter.IsLittleEndian ?
-                    (Func<CodedInputStream, double?>)CodedInputStream.ReadDoubleWrapperLittleEndian :
-                    (Func<CodedInputStream, double?>)CodedInputStream.ReadDoubleWrapperSlow },
+                    (ValueReader<double?>)ParsingPrimitivesWrappers.ReadDoubleWrapperLittleEndian :
+                    (ValueReader<double?>)ParsingPrimitivesWrappers.ReadDoubleWrapperSlow },
                 // `string` and `ByteString` less performance-sensitive. Do not implement for now.
                 { typeof(string), null },
                 { typeof(ByteString), null },
@@ -572,7 +573,7 @@
                 return (FieldCodec<T>) value;
             }
 
-            internal static Func<CodedInputStream, T?> GetReader<T>() where T : struct
+            internal static ValueReader<T?> GetReader<T>() where T : struct
             {
                 object value;
                 if (!Readers.TryGetValue(typeof(T), out value))
@@ -583,41 +584,42 @@
                 {
                     // Return default unoptimized reader for the wrapper type.
                     var nestedCoded = GetCodec<T>();
-                    return input => Read<T>(input, nestedCoded);
+                    return (ref ParseContext ctx) => Read<T>(ref ctx, nestedCoded);
                 }
                 // Return optimized read for the wrapper type.
-                return (Func<CodedInputStream, T?>)value;
+                return (ValueReader<T?>)value;
             }
 
-            internal static T Read<T>(CodedInputStream input, FieldCodec<T> codec)
+            [SecuritySafeCritical]
+            internal static T Read<T>(ref ParseContext ctx, FieldCodec<T> codec)
             {
-                int length = input.ReadLength();
-                int oldLimit = input.PushLimit(length);
+                int length = ctx.ReadLength();
+                int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length);
 
                 uint tag;
                 T value = codec.DefaultValue;
-                while ((tag = input.ReadTag()) != 0)
+                while ((tag = ctx.ReadTag()) != 0)
                 {
                     if (tag == codec.Tag)
                     {
-                        value = codec.Read(input);
+                        value = codec.Read(ref ctx);
                     }
                     else
                     {
-                        input.SkipLastField();
+                        ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state);
                     }
 
                 }
-                input.CheckReadEndOfStreamTag();
-                input.PopLimit(oldLimit);
+                ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state);
+                SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);
 
                 return value;
             }
 
-            internal static void Write<T>(CodedOutputStream output, T value, FieldCodec<T> codec)
+            internal static void Write<T>(ref WriteContext ctx, T value, FieldCodec<T> codec)
             {
-                output.WriteLength(codec.CalculateSizeWithTag(value));
-                codec.WriteTagAndValue(output, value);
+                ctx.WriteLength(codec.CalculateSizeWithTag(value));
+                codec.WriteTagAndValue(ref ctx, value);
             }
 
             internal  static int CalculateSize<T>(T value, FieldCodec<T> codec)
@@ -628,6 +630,9 @@
         }
     }
 
+    internal delegate TValue ValueReader<out TValue>(ref ParseContext ctx);
+    internal delegate void ValueWriter<T>(ref WriteContext ctx, T value);
+
     /// <summary>
     /// <para>
     /// An encode/decode pair for a single field. This effectively encapsulates
@@ -653,7 +658,7 @@
         /// <summary>
         /// Merges an input stream into a value
         /// </summary>
-        internal delegate void InputMerger(CodedInputStream input, ref T value);
+        internal delegate void InputMerger(ref ParseContext ctx, ref T value);
 
         /// <summary>
         /// Merges a value into a reference to another value, returning a boolean if the value was set
@@ -681,7 +686,7 @@
         /// <summary>
         /// Returns a delegate to write a value (unconditionally) to a coded output stream.
         /// </summary>
-        internal Action<CodedOutputStream, T> ValueWriter { get; }
+        internal ValueWriter<T> ValueWriter { get; }
 
         /// <summary>
         /// Returns the size calculator for just a value.
@@ -692,7 +697,7 @@
         /// Returns a delegate to read a value from a coded input stream. It is assumed that
         /// the stream is already positioned on the appropriate tag.
         /// </summary>
-        internal Func<CodedInputStream, T> ValueReader { get; }
+        internal ValueReader<T> ValueReader { get; }
 
         /// <summary>
         /// Returns a delegate to merge a value from a coded input stream.
@@ -739,8 +744,8 @@
         private readonly int tagSize;
 
         internal FieldCodec(
-                Func<CodedInputStream, T> reader,
-                Action<CodedOutputStream, T> writer,
+                ValueReader<T> reader,
+                ValueWriter<T> writer,
                 int fixedSize,
                 uint tag,
                 T defaultValue) : this(reader, writer, _ => fixedSize, tag, defaultValue)
@@ -749,17 +754,17 @@
         }
 
         internal FieldCodec(
-            Func<CodedInputStream, T> reader,
-            Action<CodedOutputStream, T> writer,
+            ValueReader<T> reader,
+            ValueWriter<T> writer,
             Func<T, int> sizeCalculator,
             uint tag,
-            T defaultValue) : this(reader, writer, (CodedInputStream i, ref T v) => v = reader(i), (ref T v, T v2) => { v = v2; return true; }, sizeCalculator, tag, 0, defaultValue)
+            T defaultValue) : this(reader, writer, (ref ParseContext ctx, ref T v) => v = reader(ref ctx), (ref T v, T v2) => { v = v2; return true; }, sizeCalculator, tag, 0, defaultValue)
         {
         }
 
         internal FieldCodec(
-            Func<CodedInputStream, T> reader,
-            Action<CodedOutputStream, T> writer,
+            ValueReader<T> reader,
+            ValueWriter<T> writer,
             InputMerger inputMerger,
             ValuesMerger valuesMerger,
             Func<T, int> sizeCalculator,
@@ -769,8 +774,8 @@
         }
 
         internal FieldCodec(
-            Func<CodedInputStream, T> reader,
-            Action<CodedOutputStream, T> writer,
+            ValueReader<T> reader,
+            ValueWriter<T> writer,
             InputMerger inputMerger,
             ValuesMerger valuesMerger,
             Func<T, int> sizeCalculator,
@@ -799,13 +804,40 @@
         /// </summary>
         public void WriteTagAndValue(CodedOutputStream output, T value)
         {
+            WriteContext.Initialize(output, out WriteContext ctx);
+            try
+            {
+                WriteTagAndValue(ref ctx, value);
+            }
+            finally
+            {
+                ctx.CopyStateTo(output);
+            }
+
+
+            //if (!IsDefault(value))
+            //{
+            //    output.WriteTag(Tag);
+            //    ValueWriter(output, value);
+            //    if (EndTag != 0)
+            //    {
+            //        output.WriteTag(EndTag);
+            //    }
+            //}
+        }
+
+        /// <summary>
+        /// Write a tag and the given value, *if* the value is not the default.
+        /// </summary>
+        public void WriteTagAndValue(ref WriteContext ctx, T value)
+        {
             if (!IsDefault(value))
             {
-                output.WriteTag(Tag);
-                ValueWriter(output, value);
+                ctx.WriteTag(Tag);
+                ValueWriter(ref ctx, value);
                 if (EndTag != 0)
                 {
-                    output.WriteTag(EndTag);
+                    ctx.WriteTag(EndTag);
                 }
             }
         }
@@ -815,7 +847,28 @@
         /// </summary>
         /// <param name="input">The input stream to read from.</param>
         /// <returns>The value read from the stream.</returns>
-        public T Read(CodedInputStream input) => ValueReader(input);
+        public T Read(CodedInputStream input)
+        {
+            ParseContext.Initialize(input, out ParseContext ctx);
+            try
+            {
+                return ValueReader(ref ctx);
+            }
+            finally
+            {
+                ctx.CopyStateTo(input);
+            }
+        }
+
+        /// <summary>
+        /// Reads a value of the codec type from the given <see cref="ParseContext"/>.
+        /// </summary>
+        /// <param name="ctx">The parse context to read from.</param>
+        /// <returns>The value read.</returns>
+        public T Read(ref ParseContext ctx)
+        {
+            return ValueReader(ref ctx);
+        }
 
         /// <summary>
         /// Calculates the size required to write the given value, with a tag,
@@ -823,6 +876,12 @@
         /// </summary>
         public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize;
 
+        /// <summary>
+        /// Calculates the size required to write the given value, with a tag, even
+        /// if the value is the default.
+        /// </summary>
+        internal int CalculateUnconditionalSizeWithTag(T value) => ValueSizeCalculator(value) + tagSize;
+
         private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue);
     }
 }
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
index 53f45fe..41b2b64 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -4,39 +4,47 @@
     <Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
     <Copyright>Copyright 2015, Google Inc.</Copyright>
     <AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
-    <VersionPrefix>3.11.4</VersionPrefix>
-    <LangVersion>6</LangVersion>
+    <VersionPrefix>3.17.3</VersionPrefix>
+    <!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
+    <LangVersion>7.2</LangVersion>
     <Authors>Google Inc.</Authors>
-    <TargetFrameworks>netstandard1.0;netstandard2.0;net45</TargetFrameworks>
+    <TargetFrameworks>netstandard1.1;netstandard2.0;net45;net50</TargetFrameworks>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
-    <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
     <PackageTags>Protocol;Buffers;Binary;Serialization;Format;Google;proto;proto3</PackageTags>
     <PackageReleaseNotes>C# proto3 support</PackageReleaseNotes>
     <PackageProjectUrl>https://github.com/protocolbuffers/protobuf</PackageProjectUrl>
     <PackageLicenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</PackageLicenseUrl>
     <RepositoryType>git</RepositoryType>
     <RepositoryUrl>https://github.com/protocolbuffers/protobuf.git</RepositoryUrl>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
     <!-- Include PDB in the built .nupkg -->
     <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
   </PropertyGroup>
 
-  <PropertyGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'netstandard2.0' ">
-    <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY</DefineConstants>
+  <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
+    <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING</DefineConstants>
   </PropertyGroup>
 
-  <!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
-  <ItemGroup>
-    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0-preview.2"/>
-  </ItemGroup>
-
-  <ItemGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'netstandard2.0' ">
-    <PackageReference Include="System.Memory" Version="4.5.2"/>
-  </ItemGroup>
+  <PropertyGroup Condition=" '$(TargetFramework)' == 'net50' ">
+    <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING;GOOGLE_PROTOBUF_SIMD</DefineConstants>
+  </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0-beta2-18618-05"/>
+    <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0"/>
+    <!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
+    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0"/>
+  </ItemGroup>
+
+  <ItemGroup Condition=" '$(TargetFramework)' == 'net45' OR '$(TargetFramework)' == 'netstandard1.1' ">
+    <PackageReference Include="System.Memory" Version="4.5.3"/>
+  </ItemGroup>
+
+  <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
+    <PackageReference Include="System.Memory" Version="4.5.3"/>
+    <!-- Needed for netcoreapp2.1 to work correctly. .NET is not able to load the assembly without this -->
+    <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2"/>
   </ItemGroup>
 
 </Project>
diff --git a/python/google/protobuf/python_protobuf.h b/csharp/src/Google.Protobuf/IBufferMessage.cs
similarity index 65%
copy from python/google/protobuf/python_protobuf.h
copy to csharp/src/Google.Protobuf/IBufferMessage.cs
index 8db1ffb..05c15db 100644
--- a/python/google/protobuf/python_protobuf.h
+++ b/csharp/src/Google.Protobuf/IBufferMessage.cs
@@ -1,3 +1,4 @@
+#region Copyright notice and license
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
@@ -27,31 +28,26 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
 
-// Author: qrczak@google.com (Marcin Kowalczyk)
-//
-// This module exposes the C proto inside the given Python proto, in
-// case the Python proto is implemented with a C proto.
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Interface for a Protocol Buffers message, supporting
+    /// parsing from <see cref="ParseContext"/> and writing to <see cref="WriteContext"/>.
+    /// </summary>
+    public interface IBufferMessage : IMessage
+    {
+        /// <summary>
+        /// Internal implementation of merging data from given parse context into this message.
+        /// Users should never invoke this method directly.
+        /// </summary>        
+        void InternalMergeFrom(ref ParseContext ctx);
 
-#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
-#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
-
-#include <Python.h>
-
-namespace google {
-namespace protobuf {
-
-class Message;
-
-namespace python {
-
-// Return the pointer to the C proto inside the given Python proto,
-// or NULL when this is not a Python proto implemented with a C proto.
-const Message* GetCProtoInsidePyProto(PyObject* msg);
-Message* MutableCProtoInsidePyProto(PyObject* msg);
-
-}  // namespace python
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
+        /// <summary>
+        /// Internal implementation of writing this message to a given write context.
+        /// Users should never invoke this method directly.
+        /// </summary>        
+        void InternalWriteTo(ref WriteContext ctx);
+    }
+}
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs
index 5aaefe7..4bffd58 100644
--- a/csharp/src/Google.Protobuf/JsonFormatter.cs
+++ b/csharp/src/Google.Protobuf/JsonFormatter.cs
@@ -221,19 +221,12 @@
             foreach (var field in fields.InFieldNumberOrder())
             {
                 var accessor = field.Accessor;
-                if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field)
-                {
-                    continue;
-                }
-                // Omit default values unless we're asked to format them, or they're oneofs (where the default
-                // value is still formatted regardless, because that's how we preserve the oneof case).
-                object value = accessor.GetValue(message);
-                if (field.ContainingOneof == null && !settings.FormatDefaultValues && IsDefaultValue(accessor, value))
+                var value = accessor.GetValue(message);
+                if (!ShouldFormatFieldValue(message, field, value))
                 {
                     continue;
                 }
 
-                // Okay, all tests complete: let's write the field value...
                 if (!first)
                 {
                     writer.Write(PropertySeparator);
@@ -248,6 +241,18 @@
             return !first;
         }
 
+        /// <summary>
+        /// Determines whether or not a field value should be serialized according to the field,
+        /// its value in the message, and the settings of this formatter.
+        /// </summary>
+        private bool ShouldFormatFieldValue(IMessage message, FieldDescriptor field, object value) =>
+            field.HasPresence
+            // Fields that support presence *just* use that
+            ? field.Accessor.HasValue(message)
+            // Otherwise, format if either we've been asked to format default values, or if it's
+            // not a default value anyway.
+            : settings.FormatDefaultValues || !IsDefaultValue(field, value);
+
         // Converted from java/core/src/main/java/com/google/protobuf/Descriptors.java
         internal static string ToJsonName(string name)
         {
@@ -295,19 +300,19 @@
             writer.Write("null");
         }
 
-        private static bool IsDefaultValue(IFieldAccessor accessor, object value)
+        private static bool IsDefaultValue(FieldDescriptor descriptor, object value)
         {
-            if (accessor.Descriptor.IsMap)
+            if (descriptor.IsMap)
             {
                 IDictionary dictionary = (IDictionary) value;
                 return dictionary.Count == 0;
             }
-            if (accessor.Descriptor.IsRepeated)
+            if (descriptor.IsRepeated)
             {
                 IList list = (IList) value;
                 return list.Count == 0;
             }
-            switch (accessor.Descriptor.FieldType)
+            switch (descriptor.FieldType)
             {
                 case FieldType.Bool:
                     return (bool) value == false;
@@ -352,7 +357,7 @@
         /// <param name="value">The value to write. May be null.</param>
         public void WriteValue(TextWriter writer, object value)
         {
-            if (value == null)
+            if (value == null || value is NullValue)
             {
                 WriteNull(writer);
             }
@@ -793,8 +798,10 @@
             }
 
             /// <summary>
-            /// Whether fields whose values are the default for the field type (e.g. 0 for integers)
-            /// should be formatted (true) or omitted (false).
+            /// Whether fields which would otherwise not be included in the formatted data
+            /// should be formatted even when the value is not present, or has the default value.
+            /// This option only affects fields which don't support "presence" (e.g.
+            /// singular non-optional proto3 primitive fields).
             /// </summary>
             public bool FormatDefaultValues { get; }
 
diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs
index 3f88ea3..cb5f5a8 100644
--- a/csharp/src/Google.Protobuf/JsonParser.cs
+++ b/csharp/src/Google.Protobuf/JsonParser.cs
@@ -37,6 +37,7 @@
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
+using System.Linq;
 using System.Text;
 using System.Text.RegularExpressions;
 
@@ -63,6 +64,7 @@
         private static readonly Regex DurationRegex = new Regex(@"^(?<sign>-)?(?<int>[0-9]{1,12})(?<subseconds>\.[0-9]{1,9})?s$", FrameworkPortability.CompiledRegexWhereAvailable);
         private static readonly int[] SubsecondScalingFactors = { 0, 100000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
         private static readonly char[] FieldMaskPathSeparators = new[] { ',' };
+        private static readonly EnumDescriptor NullValueDescriptor = StructReflection.Descriptor.EnumTypes.Single(ed => ed.ClrType == typeof(NullValue));
 
         private static readonly JsonParser defaultInstance = new JsonParser(Settings.Default);
 
@@ -221,10 +223,11 @@
             if (token.Type == JsonToken.TokenType.Null)
             {
                 // Clear the field if we see a null token, unless it's for a singular field of type
-                // google.protobuf.Value.
+                // google.protobuf.Value or google.protobuf.NullValue.
                 // Note: different from Java API, which just ignores it.
                 // TODO: Bring it more in line? Discuss...
-                if (field.IsMap || field.IsRepeated || !IsGoogleProtobufValueField(field))
+                if (field.IsMap || field.IsRepeated ||
+                    !(IsGoogleProtobufValueField(field) || IsGoogleProtobufNullValueField(field)))
                 {
                     field.Accessor.Clear(message);
                     return;
@@ -314,6 +317,12 @@
                 field.MessageType.FullName == Value.Descriptor.FullName;
         }
 
+        private static bool IsGoogleProtobufNullValueField(FieldDescriptor field)
+        {
+            return field.FieldType == FieldType.Enum &&
+                field.EnumType.FullName == NullValueDescriptor.FullName;
+        }
+
         private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer)
         {
             var token = tokenizer.Next();
@@ -325,6 +334,10 @@
                 {
                     return Value.ForNull();
                 }
+                if (IsGoogleProtobufNullValueField(field))
+                {
+                    return NullValue.NullValue;
+                }
                 return null;
             }
 
diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs
index 06e0980..c4b3f82 100644
--- a/csharp/src/Google.Protobuf/MessageExtensions.cs
+++ b/csharp/src/Google.Protobuf/MessageExtensions.cs
@@ -31,9 +31,12 @@
 #endregion
 
 using Google.Protobuf.Reflection;
+using System.Buffers;
 using System.Collections;
+using System;
 using System.IO;
 using System.Linq;
+using System.Security;
 
 namespace Google.Protobuf
 {
@@ -77,6 +80,15 @@
             MergeFrom(message, input, false, null);
 
         /// <summary>
+        /// Merges data from the given span into an existing message.
+        /// </summary>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="span">Span containing the data to merge, which must be protobuf-encoded binary data.</param>
+        [SecuritySafeCritical]
+        public static void MergeFrom(this IMessage message, ReadOnlySpan<byte> span) =>
+            MergeFrom(message, span, false, null);
+
+        /// <summary>
         /// Merges length-delimited data from the given stream into an existing message.
         /// </summary>
         /// <remarks>
@@ -127,7 +139,7 @@
             ProtoPreconditions.CheckNotNull(message, "message");
             ProtoPreconditions.CheckNotNull(output, "output");
             CodedOutputStream codedOutput = new CodedOutputStream(output);
-            codedOutput.WriteRawVarint32((uint)message.CalculateSize());
+            codedOutput.WriteLength(message.CalculateSize());
             message.WriteTo(codedOutput);
             codedOutput.Flush();
         }
@@ -144,6 +156,39 @@
         }
 
         /// <summary>
+        /// Writes the given message data to the given buffer writer in protobuf encoding.
+        /// </summary>
+        /// <param name="message">The message to write to the stream.</param>
+        /// <param name="output">The stream to write to.</param>
+        [SecuritySafeCritical]
+        public static void WriteTo(this IMessage message, IBufferWriter<byte> output)
+        {
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(output, nameof(output));
+
+            WriteContext.Initialize(output, out WriteContext ctx);
+            WritingPrimitivesMessages.WriteRawMessage(ref ctx, message);
+            ctx.Flush();
+        }
+
+        /// <summary>
+        /// Writes the given message data to the given span in protobuf encoding.
+        /// The size of the destination span needs to fit the serialized size
+        /// of the message exactly, otherwise an exception is thrown.
+        /// </summary>
+        /// <param name="message">The message to write to the stream.</param>
+        /// <param name="output">The span to write to. Size must match size of the message exactly.</param>
+        [SecuritySafeCritical]
+        public static void WriteTo(this IMessage message, Span<byte> output)
+        {
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+
+            WriteContext.Initialize(ref output, out WriteContext ctx);
+            WritingPrimitivesMessages.WriteRawMessage(ref ctx, message);
+            ctx.CheckNoSpaceLeft();
+        }
+
+        /// <summary>
         /// Checks if all required fields in a message have values set. For proto3 messages, this returns true
         /// </summary>
         public static bool IsInitialized(this IMessage message)
@@ -248,6 +293,26 @@
             codedInput.CheckReadEndOfStreamTag();
         }
 
+        [SecuritySafeCritical]
+        internal static void MergeFrom(this IMessage message, ReadOnlySequence<byte> data, bool discardUnknownFields, ExtensionRegistry registry)
+        {
+            ParseContext.Initialize(data, out ParseContext ctx);
+            ctx.DiscardUnknownFields = discardUnknownFields;
+            ctx.ExtensionRegistry = registry;
+            ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message);
+            ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state);
+        }
+
+        [SecuritySafeCritical]
+        internal static void MergeFrom(this IMessage message, ReadOnlySpan<byte> data, bool discardUnknownFields, ExtensionRegistry registry)
+        {
+            ParseContext.Initialize(data, out ParseContext ctx);
+            ctx.DiscardUnknownFields = discardUnknownFields;
+            ctx.ExtensionRegistry = registry;
+            ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message);
+            ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state);
+        }
+
         internal static void MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry)
         {
             ProtoPreconditions.CheckNotNull(message, "message");
diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs
index 06d0f10..30a25a8 100644
--- a/csharp/src/Google.Protobuf/MessageParser.cs
+++ b/csharp/src/Google.Protobuf/MessageParser.cs
@@ -31,7 +31,9 @@
 #endregion
 
 using System;
+using System.Buffers;
 using System.IO;
+using System.Security;
 
 namespace Google.Protobuf
 {
@@ -114,6 +116,32 @@
         }
 
         /// <summary>
+        /// Parses a message from the given sequence.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
+        [SecuritySafeCritical]
+        public IMessage ParseFrom(ReadOnlySequence<byte> data)
+        {
+            IMessage message = factory();
+            message.MergeFrom(data, DiscardUnknownFields, Extensions);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given span.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
+        [SecuritySafeCritical]
+        public IMessage ParseFrom(ReadOnlySpan<byte> data)
+        {
+            IMessage message = factory();
+            message.MergeFrom(data, DiscardUnknownFields, Extensions);
+            return message;
+        }
+
+        /// <summary>
         /// Parses a length-delimited message from the given stream.
         /// </summary>
         /// <remarks>
@@ -288,6 +316,32 @@
         }
 
         /// <summary>
+        /// Parses a message from the given sequence.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
+        [SecuritySafeCritical]
+        public new T ParseFrom(ReadOnlySequence<byte> data)
+        {
+            T message = factory();
+            message.MergeFrom(data, DiscardUnknownFields, Extensions);
+            return message;
+        }
+
+        /// <summary>
+        /// Parses a message from the given span.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
+        [SecuritySafeCritical]
+        public new T ParseFrom(ReadOnlySpan<byte> data)
+        {
+            T message = factory();
+            message.MergeFrom(data, DiscardUnknownFields, Extensions);
+            return message;
+        }
+
+        /// <summary>
         /// Parses a length-delimited message from the given stream.
         /// </summary>
         /// <remarks>
diff --git a/csharp/src/Google.Protobuf/ParseContext.cs b/csharp/src/Google.Protobuf/ParseContext.cs
new file mode 100644
index 0000000..7b278b5
--- /dev/null
+++ b/csharp/src/Google.Protobuf/ParseContext.cs
@@ -0,0 +1,348 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// An opaque struct that represents the current parsing state and is passed along
+    /// as the parsing proceeds.
+    /// All the public methods are intended to be invoked only by the generated code,
+    /// users should never invoke them directly.
+    /// </summary>
+    [SecuritySafeCritical]
+    public ref struct ParseContext
+    {
+        internal const int DefaultRecursionLimit = 100;
+        internal const int DefaultSizeLimit = Int32.MaxValue;
+
+        internal ReadOnlySpan<byte> buffer;
+        internal ParserInternalState state;
+
+        /// <summary>
+        /// Initialize a <see cref="ParseContext"/>, building all <see cref="ParserInternalState"/> from defaults and
+        /// the given <paramref name="buffer"/>.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(ReadOnlySpan<byte> buffer, out ParseContext ctx)
+        {
+            ParserInternalState state = default;
+            state.sizeLimit = DefaultSizeLimit;
+            state.recursionLimit = DefaultRecursionLimit;
+            state.currentLimit = int.MaxValue;
+            state.bufferSize = buffer.Length;
+
+            Initialize(buffer, ref state, out ctx);
+        }
+
+        /// <summary>
+        /// Initialize a <see cref="ParseContext"/> using existing <see cref="ParserInternalState"/>, e.g. from <see cref="CodedInputStream"/>.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(ReadOnlySpan<byte> buffer, ref ParserInternalState state, out ParseContext ctx)
+        {
+            ctx.buffer = buffer;
+            ctx.state = state;
+        }
+
+        /// <summary>
+        /// Creates a ParseContext instance from CodedInputStream.
+        /// WARNING: internally this copies the CodedInputStream's state, so after done with the ParseContext,
+        /// the CodedInputStream's state needs to be updated.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(CodedInputStream input, out ParseContext ctx)
+        {
+            ctx.buffer = new ReadOnlySpan<byte>(input.InternalBuffer);
+            // ideally we would use a reference to the original state, but that doesn't seem possible
+            // so we just copy the struct that holds the state. We will need to later store the state back
+            // into CodedInputStream if we want to keep it usable.
+            ctx.state = input.InternalState;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(ReadOnlySequence<byte> input, out ParseContext ctx)
+        {
+            Initialize(input, DefaultRecursionLimit, out ctx);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(ReadOnlySequence<byte> input, int recursionLimit, out ParseContext ctx)
+        {
+            ctx.buffer = default;
+            ctx.state = default;
+            ctx.state.lastTag = 0;
+            ctx.state.recursionDepth = 0;
+            ctx.state.sizeLimit = DefaultSizeLimit;
+            ctx.state.recursionLimit = recursionLimit;
+            ctx.state.currentLimit = int.MaxValue;
+            SegmentedBufferHelper.Initialize(input, out ctx.state.segmentedBufferHelper, out ctx.buffer);
+            ctx.state.bufferPos = 0;
+            ctx.state.bufferSize = ctx.buffer.Length;
+
+            ctx.state.DiscardUnknownFields = false;
+            ctx.state.ExtensionRegistry = null;
+        }
+
+        /// <summary>
+        /// Returns the last tag read, or 0 if no tags have been read or we've read beyond
+        /// the end of the input.
+        /// </summary>
+        internal uint LastTag { get { return state.lastTag; } }
+
+        /// <summary>
+        /// Internal-only property; when set to true, unknown fields will be discarded while parsing.
+        /// </summary>
+        internal bool DiscardUnknownFields {
+            get { return state.DiscardUnknownFields; }
+            set { state.DiscardUnknownFields = value; }
+        }
+
+        /// <summary>
+        /// Internal-only property; provides extension identifiers to compatible messages while parsing.
+        /// </summary>
+        internal ExtensionRegistry ExtensionRegistry
+        {
+            get { return state.ExtensionRegistry; }
+            set { state.ExtensionRegistry = value; }
+        }
+
+        /// <summary>
+        /// Reads a field tag, returning the tag of 0 for "end of input".
+        /// </summary>
+        /// <remarks>
+        /// If this method returns 0, it doesn't necessarily mean the end of all
+        /// the data in this CodedInputReader; it may be the end of the logical input
+        /// for an embedded message, for example.
+        /// </remarks>
+        /// <returns>The next field tag, or 0 for end of input. (0 is never a valid tag.)</returns>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public uint ReadTag()
+        {
+            return ParsingPrimitives.ParseTag(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads a double field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public double ReadDouble()
+        {
+            return ParsingPrimitives.ParseDouble(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads a float field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public float ReadFloat()
+        {
+            return ParsingPrimitives.ParseFloat(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads a uint64 field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public ulong ReadUInt64()
+        {
+            return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads an int64 field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public long ReadInt64()
+        {
+            return (long)ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads an int32 field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int ReadInt32()
+        {
+            return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads a fixed64 field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public ulong ReadFixed64()
+        {
+            return ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads a fixed32 field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public uint ReadFixed32()
+        {
+            return ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads a bool field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool ReadBool()
+        {
+            return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state) != 0;
+        }
+        /// <summary>
+        /// Reads a string field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public string ReadString()
+        {
+            return ParsingPrimitives.ReadString(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads an embedded message field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void ReadMessage(IMessage message)
+        {
+            ParsingPrimitivesMessages.ReadMessage(ref this, message);
+        }
+
+        /// <summary>
+        /// Reads an embedded group field from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void ReadGroup(IMessage message)
+        {
+            ParsingPrimitivesMessages.ReadGroup(ref this, message);
+        }
+
+        /// <summary>
+        /// Reads a bytes field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public ByteString ReadBytes()
+        {
+            return ParsingPrimitives.ReadBytes(ref buffer, ref state);
+        }
+        /// <summary>
+        /// Reads a uint32 field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public uint ReadUInt32()
+        {
+            return ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads an enum field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int ReadEnum()
+        {
+            // Currently just a pass-through, but it's nice to separate it logically from WriteInt32.
+            return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads an sfixed32 field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int ReadSFixed32()
+        {
+            return (int)ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads an sfixed64 field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public long ReadSFixed64()
+        {
+            return (long)ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Reads an sint32 field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int ReadSInt32()
+        {
+            return ParsingPrimitives.DecodeZigZag32(ParsingPrimitives.ParseRawVarint32(ref buffer, ref state));
+        }
+
+        /// <summary>
+        /// Reads an sint64 field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public long ReadSInt64()
+        {
+            return ParsingPrimitives.DecodeZigZag64(ParsingPrimitives.ParseRawVarint64(ref buffer, ref state));
+        }
+
+        /// <summary>
+        /// Reads a length for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This is internally just reading a varint, but this method exists
+        /// to make the calling code clearer.
+        /// </remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int ReadLength()
+        {
+            return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+        }
+
+        internal void CopyStateTo(CodedInputStream input)
+        {
+            input.InternalState = state;
+        }
+
+        internal void LoadStateFrom(CodedInputStream input)
+        {
+            state = input.InternalState;
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/ParserInternalState.cs b/csharp/src/Google.Protobuf/ParserInternalState.cs
new file mode 100644
index 0000000..cb4f471
--- /dev/null
+++ b/csharp/src/Google.Protobuf/ParserInternalState.cs
@@ -0,0 +1,115 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+
+    // warning: this is a mutable struct, so it needs to be only passed as a ref!
+    internal struct ParserInternalState
+    {
+        // NOTE: the Span representing the current buffer is kept separate so that this doesn't have to be a ref struct and so it can
+        // be included in CodedInputStream's internal state
+
+        /// <summary>
+        /// The position within the current buffer (i.e. the next byte to read)
+        /// </summary>
+        internal int bufferPos;
+
+        /// <summary>
+        /// Size of the current buffer
+        /// </summary>
+        internal int bufferSize;
+
+        /// <summary>
+        /// If we are currently inside a length-delimited block, this is the number of
+        /// bytes in the buffer that are still available once we leave the delimited block.
+        /// </summary>
+        internal int bufferSizeAfterLimit;
+
+        /// <summary>
+        /// The absolute position of the end of the current length-delimited block (including totalBytesRetired)
+        /// </summary>
+        internal int currentLimit;
+
+        /// <summary>
+        /// The total number of consumed before the start of the current buffer. The
+        /// total bytes read up to the current position can be computed as
+        /// totalBytesRetired + bufferPos.
+        /// </summary>
+        internal int totalBytesRetired;
+
+        internal int recursionDepth;  // current recursion depth
+
+        internal SegmentedBufferHelper segmentedBufferHelper;
+
+        /// <summary>
+        /// The last tag we read. 0 indicates we've read to the end of the stream
+        /// (or haven't read anything yet).
+        /// </summary>
+        internal uint lastTag;
+
+        /// <summary>
+        /// The next tag, used to store the value read by PeekTag.
+        /// </summary>
+        internal uint nextTag;
+        internal bool hasNextTag;
+
+        // these fields are configuration, they should be readonly
+        internal int sizeLimit;
+        internal int recursionLimit;
+
+        // If non-null, the top level parse method was started with given coded input stream as an argument
+        // which also means we can potentially fallback to calling MergeFrom(CodedInputStream cis) if needed.
+        internal CodedInputStream CodedInputStream => segmentedBufferHelper.CodedInputStream;
+
+        /// <summary>
+        /// Internal-only property; when set to true, unknown fields will be discarded while parsing.
+        /// </summary>
+        internal bool DiscardUnknownFields { get; set; }
+
+        /// <summary>
+        /// Internal-only property; provides extension identifiers to compatible messages while parsing.
+        /// </summary>
+        internal ExtensionRegistry ExtensionRegistry { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs
new file mode 100644
index 0000000..e270ed8
--- /dev/null
+++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs
@@ -0,0 +1,815 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Primitives for parsing protobuf wire format.
+    /// </summary>
+    [SecuritySafeCritical]
+    internal static class ParsingPrimitives
+    {
+        private const int StackallocThreshold = 256;
+
+        /// <summary>
+        /// Reads a length for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This is internally just reading a varint, but this method exists
+        /// to make the calling code clearer.
+        /// </remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static int ParseLength(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            return (int)ParseRawVarint32(ref buffer, ref state);
+        }
+
+        /// <summary>
+        /// Parses the next tag.
+        /// If the end of logical stream was reached, an invalid tag of 0 is returned. 
+        /// </summary>
+        public static uint ParseTag(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            // The "nextTag" logic is there only as an optimization for reading non-packed repeated / map
+            // fields and is strictly speaking not necessary.
+            // TODO(jtattermusch): look into simplifying the ParseTag logic.
+            if (state.hasNextTag)
+            {
+                state.lastTag = state.nextTag;
+                state.hasNextTag = false;
+                return state.lastTag;
+            }
+
+            // Optimize for the incredibly common case of having at least two bytes left in the buffer,
+            // and those two bytes being enough to get the tag. This will be true for fields up to 4095.
+            if (state.bufferPos + 2 <= state.bufferSize)
+            {
+                int tmp = buffer[state.bufferPos++];
+                if (tmp < 128)
+                {
+                    state.lastTag = (uint)tmp;
+                }
+                else
+                {
+                    int result = tmp & 0x7f;
+                    if ((tmp = buffer[state.bufferPos++]) < 128)
+                    {
+                        result |= tmp << 7;
+                        state.lastTag = (uint) result;
+                    }
+                    else
+                    {
+                        // Nope, rewind and go the potentially slow route.
+                        state.bufferPos -= 2;
+                        state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+                    }
+                }
+            }
+            else
+            {
+                if (SegmentedBufferHelper.IsAtEnd(ref buffer, ref state))
+                {
+                    state.lastTag = 0;
+                    return 0;
+                }
+
+                state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+            }
+            if (WireFormat.GetTagFieldNumber(state.lastTag) == 0)
+            {
+                // If we actually read a tag with a field of 0, that's not a valid tag.
+                throw InvalidProtocolBufferException.InvalidTag();
+            }
+            return state.lastTag;
+        }
+
+        /// <summary>
+        /// Peeks at the next tag in the stream. If it matches <paramref name="tag"/>,
+        /// the tag is consumed and the method returns <c>true</c>; otherwise, the
+        /// stream is left in the original position and the method returns <c>false</c>.
+        /// </summary>
+        public static bool MaybeConsumeTag(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, uint tag)
+        {
+            if (PeekTag(ref buffer, ref state) == tag)
+            {
+                state.hasNextTag = false;
+                return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Peeks at the next field tag. This is like calling <see cref="ParseTag"/>, but the
+        /// tag is not consumed. (So a subsequent call to <see cref="ParseTag"/> will return the
+        /// same value.)
+        /// </summary>
+        public static uint PeekTag(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            if (state.hasNextTag)
+            {
+                return state.nextTag;
+            }
+
+            uint savedLast = state.lastTag;
+            state.nextTag = ParseTag(ref buffer, ref state);
+            state.hasNextTag = true;
+            state.lastTag = savedLast; // Undo the side effect of ReadTag
+            return state.nextTag;
+        }
+
+        /// <summary>
+        /// Parses a raw varint.
+        /// </summary>
+        public static ulong ParseRawVarint64(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            if (state.bufferPos + 10 > state.bufferSize)
+            {
+                return ParseRawVarint64SlowPath(ref buffer, ref state);
+            }
+
+            ulong result = buffer[state.bufferPos++];
+            if (result < 128)
+            {
+                return result;
+            }
+            result &= 0x7f;
+            int shift = 7;
+            do
+            {
+                byte b = buffer[state.bufferPos++];
+                result |= (ulong)(b & 0x7F) << shift;
+                if (b < 0x80)
+                {
+                    return result;
+                }
+                shift += 7;
+            }
+            while (shift < 64);
+
+            throw InvalidProtocolBufferException.MalformedVarint();
+        }
+
+        private static ulong ParseRawVarint64SlowPath(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            int shift = 0;
+            ulong result = 0;
+            do
+            {
+                byte b = ReadRawByte(ref buffer, ref state);
+                result |= (ulong)(b & 0x7F) << shift;
+                if (b < 0x80)
+                {
+                    return result;
+                }
+                shift += 7;
+            }
+            while (shift < 64);
+
+            throw InvalidProtocolBufferException.MalformedVarint();
+        }
+
+        /// <summary>
+        /// Parses a raw Varint.  If larger than 32 bits, discard the upper bits.
+        /// This method is optimised for the case where we've got lots of data in the buffer.
+        /// That means we can check the size just once, then just read directly from the buffer
+        /// without constant rechecking of the buffer length.
+        /// </summary>
+        public static uint ParseRawVarint32(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            if (state.bufferPos + 5 > state.bufferSize)
+            {
+                return ParseRawVarint32SlowPath(ref buffer, ref state);
+            }
+
+            int tmp = buffer[state.bufferPos++];
+            if (tmp < 128)
+            {
+                return (uint)tmp;
+            }
+            int result = tmp & 0x7f;
+            if ((tmp = buffer[state.bufferPos++]) < 128)
+            {
+                result |= tmp << 7;
+            }
+            else
+            {
+                result |= (tmp & 0x7f) << 7;
+                if ((tmp = buffer[state.bufferPos++]) < 128)
+                {
+                    result |= tmp << 14;
+                }
+                else
+                {
+                    result |= (tmp & 0x7f) << 14;
+                    if ((tmp = buffer[state.bufferPos++]) < 128)
+                    {
+                        result |= tmp << 21;
+                    }
+                    else
+                    {
+                        result |= (tmp & 0x7f) << 21;
+                        result |= (tmp = buffer[state.bufferPos++]) << 28;
+                        if (tmp >= 128)
+                        {
+                            // Discard upper 32 bits.
+                            // Note that this has to use ReadRawByte() as we only ensure we've
+                            // got at least 5 bytes at the start of the method. This lets us
+                            // use the fast path in more cases, and we rarely hit this section of code.
+                            for (int i = 0; i < 5; i++)
+                            {
+                                if (ReadRawByte(ref buffer, ref state) < 128)
+                                {
+                                    return (uint) result;
+                                }
+                            }
+                            throw InvalidProtocolBufferException.MalformedVarint();
+                        }
+                    }
+                }
+            }
+            return (uint)result;
+        }
+
+        private static uint ParseRawVarint32SlowPath(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            int tmp = ReadRawByte(ref buffer, ref state);
+            if (tmp < 128)
+            {
+                return (uint) tmp;
+            }
+            int result = tmp & 0x7f;
+            if ((tmp = ReadRawByte(ref buffer, ref state)) < 128)
+            {
+                result |= tmp << 7;
+            }
+            else
+            {
+                result |= (tmp & 0x7f) << 7;
+                if ((tmp = ReadRawByte(ref buffer, ref state)) < 128)
+                {
+                    result |= tmp << 14;
+                }
+                else
+                {
+                    result |= (tmp & 0x7f) << 14;
+                    if ((tmp = ReadRawByte(ref buffer, ref state)) < 128)
+                    {
+                        result |= tmp << 21;
+                    }
+                    else
+                    {
+                        result |= (tmp & 0x7f) << 21;
+                        result |= (tmp = ReadRawByte(ref buffer, ref state)) << 28;
+                        if (tmp >= 128)
+                        {
+                            // Discard upper 32 bits.
+                            for (int i = 0; i < 5; i++)
+                            {
+                                if (ReadRawByte(ref buffer, ref state) < 128)
+                                {
+                                    return (uint) result;
+                                }
+                            }
+                            throw InvalidProtocolBufferException.MalformedVarint();
+                        }
+                    }
+                }
+            }
+            return (uint) result;
+        }
+
+        /// <summary>
+        /// Parses a 32-bit little-endian integer.
+        /// </summary>
+        public static uint ParseRawLittleEndian32(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            const int uintLength = sizeof(uint);
+            const int ulongLength = sizeof(ulong);
+            if (state.bufferPos + ulongLength > state.bufferSize)
+            {
+                return ParseRawLittleEndian32SlowPath(ref buffer, ref state);
+            }
+            // ReadUInt32LittleEndian is many times slower than ReadUInt64LittleEndian (at least on some runtimes)
+            // so it's faster better to use ReadUInt64LittleEndian and truncate the result.
+            uint result = (uint) BinaryPrimitives.ReadUInt64LittleEndian(buffer.Slice(state.bufferPos, ulongLength));
+            state.bufferPos += uintLength;
+            return result;
+        }
+
+        private static uint ParseRawLittleEndian32SlowPath(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            uint b1 = ReadRawByte(ref buffer, ref state);
+            uint b2 = ReadRawByte(ref buffer, ref state);
+            uint b3 = ReadRawByte(ref buffer, ref state);
+            uint b4 = ReadRawByte(ref buffer, ref state);
+            return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
+        }
+
+        /// <summary>
+        /// Parses a 64-bit little-endian integer.
+        /// </summary>
+        public static ulong ParseRawLittleEndian64(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            const int length = sizeof(ulong);
+            if (state.bufferPos + length > state.bufferSize)
+            {
+                return ParseRawLittleEndian64SlowPath(ref buffer, ref state);
+            }
+            ulong result = BinaryPrimitives.ReadUInt64LittleEndian(buffer.Slice(state.bufferPos, length));
+            state.bufferPos += length;
+            return result;
+        }
+
+        private static ulong ParseRawLittleEndian64SlowPath(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            ulong b1 = ReadRawByte(ref buffer, ref state);
+            ulong b2 = ReadRawByte(ref buffer, ref state);
+            ulong b3 = ReadRawByte(ref buffer, ref state);
+            ulong b4 = ReadRawByte(ref buffer, ref state);
+            ulong b5 = ReadRawByte(ref buffer, ref state);
+            ulong b6 = ReadRawByte(ref buffer, ref state);
+            ulong b7 = ReadRawByte(ref buffer, ref state);
+            ulong b8 = ReadRawByte(ref buffer, ref state);
+            return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
+                    | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
+        }
+
+        /// <summary>
+        /// Parses a double value.
+        /// </summary>
+        public static double ParseDouble(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            const int length = sizeof(double);
+            if (!BitConverter.IsLittleEndian || state.bufferPos + length > state.bufferSize)
+            {
+                return BitConverter.Int64BitsToDouble((long)ParseRawLittleEndian64(ref buffer, ref state));
+            }
+            // ReadUnaligned uses processor architecture for endianness.
+            double result = Unsafe.ReadUnaligned<double>(ref MemoryMarshal.GetReference(buffer.Slice(state.bufferPos, length)));
+            state.bufferPos += length;
+            return result;
+        }
+
+        /// <summary>
+        /// Parses a float value.
+        /// </summary>
+        public static float ParseFloat(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            const int length = sizeof(float);
+            if (!BitConverter.IsLittleEndian || state.bufferPos + length > state.bufferSize)
+            {
+                return ParseFloatSlow(ref buffer, ref state);
+            }
+            // ReadUnaligned uses processor architecture for endianness.
+            float result = Unsafe.ReadUnaligned<float>(ref MemoryMarshal.GetReference(buffer.Slice(state.bufferPos, length)));
+            state.bufferPos += length;
+            return result;  
+        }
+
+        private static unsafe float ParseFloatSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            const int length = sizeof(float);
+            byte* stackBuffer = stackalloc byte[length];
+            Span<byte> tempSpan = new Span<byte>(stackBuffer, length);
+            for (int i = 0; i < length; i++)
+            {
+                tempSpan[i] = ReadRawByte(ref buffer, ref state);
+            }
+
+            // Content is little endian. Reverse if needed to match endianness of architecture.
+            if (!BitConverter.IsLittleEndian)
+            {
+                tempSpan.Reverse();
+            }
+            return Unsafe.ReadUnaligned<float>(ref MemoryMarshal.GetReference(tempSpan));
+        }
+
+        /// <summary>
+        /// Reads a fixed size of bytes from the input.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">
+        /// the end of the stream or the current limit was reached
+        /// </exception>
+        public static byte[] ReadRawBytes(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, int size)
+        {
+            if (size < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+
+            if (size <= state.bufferSize - state.bufferPos)
+            {
+                // We have all the bytes we need already.
+                byte[] bytes = new byte[size];
+                buffer.Slice(state.bufferPos, size).CopyTo(bytes);
+                state.bufferPos += size;
+                return bytes;
+            }
+
+            return ReadRawBytesSlow(ref buffer, ref state, size);
+        }
+
+        private static byte[] ReadRawBytesSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, int size)
+        {
+            ValidateCurrentLimit(ref buffer, ref state, size);
+
+            if ((!state.segmentedBufferHelper.TotalLength.HasValue && size < buffer.Length) ||
+                IsDataAvailableInSource(ref state, size))
+            {
+                // Reading more bytes than are in the buffer, but not an excessive number
+                // of bytes.  We can safely allocate the resulting array ahead of time.
+
+                byte[] bytes = new byte[size];
+                ReadRawBytesIntoSpan(ref buffer, ref state, size, bytes);
+                return bytes;
+            }
+            else
+            {
+                // The size is very large.  For security reasons, we can't allocate the
+                // entire byte array yet.  The size comes directly from the input, so a
+                // maliciously-crafted message could provide a bogus very large size in
+                // order to trick the app into allocating a lot of memory.  We avoid this
+                // by allocating and reading only a small chunk at a time, so that the
+                // malicious message must actually *be* extremely large to cause
+                // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
+
+                List<byte[]> chunks = new List<byte[]>();
+
+                int pos = state.bufferSize - state.bufferPos;
+                byte[] firstChunk = new byte[pos];
+                buffer.Slice(state.bufferPos, pos).CopyTo(firstChunk);
+                chunks.Add(firstChunk);
+                state.bufferPos = state.bufferSize;
+
+                // Read all the rest of the bytes we need.
+                int sizeLeft = size - pos;
+                while (sizeLeft > 0)
+                {
+                    state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
+                    byte[] chunk = new byte[Math.Min(sizeLeft, state.bufferSize)];
+
+                    buffer.Slice(0, chunk.Length)
+                        .CopyTo(chunk);
+                    state.bufferPos += chunk.Length;
+                    sizeLeft -= chunk.Length;
+                    chunks.Add(chunk);
+                }
+
+                // OK, got everything.  Now concatenate it all into one buffer.
+                byte[] bytes = new byte[size];
+                int newPos = 0;
+                foreach (byte[] chunk in chunks)
+                {
+                    Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);
+                    newPos += chunk.Length;
+                }
+
+                // Done.
+                return bytes;
+            }
+        }
+
+        /// <summary>
+        /// Reads and discards <paramref name="size"/> bytes.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">the end of the stream
+        /// or the current limit was reached</exception>
+        public static void SkipRawBytes(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, int size)
+        {
+            if (size < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+
+            ValidateCurrentLimit(ref buffer, ref state, size);
+
+            if (size <= state.bufferSize - state.bufferPos)
+            {
+                // We have all the bytes we need already.
+                state.bufferPos += size;
+            }
+            else
+            {
+                // Skipping more bytes than are in the buffer.  First skip what we have.
+                int pos = state.bufferSize - state.bufferPos;
+                state.bufferPos = state.bufferSize;
+
+                // TODO: If our segmented buffer is backed by a Stream that is seekable, we could skip the bytes more efficiently
+                // by simply updating stream's Position property. This used to be supported in the past, but the support was dropped
+                // because it would make the segmentedBufferHelper more complex. Support can be reintroduced if needed.
+                state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
+
+                while (size - pos > state.bufferSize)
+                {
+                    pos += state.bufferSize;
+                    state.bufferPos = state.bufferSize;
+                    state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
+                }
+
+                state.bufferPos = size - pos;
+            }
+        }
+
+        /// <summary>
+        /// Reads a string field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static string ReadString(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            int length = ParsingPrimitives.ParseLength(ref buffer, ref state);
+            return ParsingPrimitives.ReadRawString(ref buffer, ref state, length);
+        }
+
+        /// <summary>
+        /// Reads a bytes field value from the input.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ByteString ReadBytes(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            int length = ParsingPrimitives.ParseLength(ref buffer, ref state);
+            return ByteString.AttachBytes(ParsingPrimitives.ReadRawBytes(ref buffer, ref state, length));
+        }
+
+        /// <summary>
+        /// Reads a UTF-8 string from the next "length" bytes.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">
+        /// the end of the stream or the current limit was reached
+        /// </exception>
+        [SecuritySafeCritical]
+        public static string ReadRawString(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, int length)
+        {
+            // No need to read any data for an empty string.
+            if (length == 0)
+            {
+                return string.Empty;
+            }
+
+            if (length < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+
+#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING
+            if (length <= state.bufferSize - state.bufferPos)
+            {
+                // Fast path: all bytes to decode appear in the same span.
+                ReadOnlySpan<byte> data = buffer.Slice(state.bufferPos, length);
+
+                string value;
+                unsafe
+                {
+                    fixed (byte* sourceBytes = &MemoryMarshal.GetReference(data))
+                    {
+                        value = WritingPrimitives.Utf8Encoding.GetString(sourceBytes, length);
+                    }
+                }
+
+                state.bufferPos += length;
+                return value;
+            }
+#endif
+
+            return ReadStringSlow(ref buffer, ref state, length);
+        }
+
+        /// <summary>
+        /// Reads a string assuming that it is spread across multiple spans in a <see cref="ReadOnlySequence{T}"/>.
+        /// </summary>
+        private static string ReadStringSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, int length)
+        {
+            ValidateCurrentLimit(ref buffer, ref state, length);
+
+#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING
+            if (IsDataAvailable(ref state, length))
+            {
+                // Read string data into a temporary buffer, either stackalloc'ed or from ArrayPool
+                // Once all data is read then call Encoding.GetString on buffer and return to pool if needed.
+
+                byte[] byteArray = null;
+                Span<byte> byteSpan = length <= StackallocThreshold ?
+                    stackalloc byte[length] :
+                    (byteArray = ArrayPool<byte>.Shared.Rent(length));
+
+                try
+                {
+                    unsafe
+                    {
+                        fixed (byte* pByteSpan = &MemoryMarshal.GetReference(byteSpan))
+                        {
+                            // Compiler doesn't like that a potentially stackalloc'd Span<byte> is being used
+                            // in a method with a "ref Span<byte> buffer" argument. If the stackalloc'd span was assigned
+                            // to the ref argument then bad things would happen. We'll never do that so it is ok.
+                            // Make compiler happy by passing a new span created from pointer.
+                            var tempSpan = new Span<byte>(pByteSpan, byteSpan.Length);
+                            ReadRawBytesIntoSpan(ref buffer, ref state, length, tempSpan);
+
+                            return WritingPrimitives.Utf8Encoding.GetString(pByteSpan, length);
+                        }
+                    }
+                }
+                finally
+                {
+                    if (byteArray != null)
+                    {
+                        ArrayPool<byte>.Shared.Return(byteArray);
+                    }
+                }
+            }
+#endif
+
+            // Slow path: Build a byte array first then copy it.
+            // This will be called when reading from a Stream because we don't know the length of the stream,
+            // or there is not enough data in the sequence. If there is not enough data then ReadRawBytes will
+            // throw an exception.
+            return WritingPrimitives.Utf8Encoding.GetString(ReadRawBytes(ref buffer, ref state, length), 0, length);
+        }
+
+        /// <summary>
+        /// Validates that the specified size doesn't exceed the current limit. If it does then remaining bytes
+        /// are skipped and an error is thrown.
+        /// </summary>
+        private static void ValidateCurrentLimit(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, int size)
+        {
+            if (state.totalBytesRetired + state.bufferPos + size > state.currentLimit)
+            {
+                // Read to the end of the stream (up to the current limit) anyway.
+                SkipRawBytes(ref buffer, ref state, state.currentLimit - state.totalBytesRetired - state.bufferPos);
+                // Then fail.
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+        }
+
+        [SecuritySafeCritical]
+        private static byte ReadRawByte(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            if (state.bufferPos == state.bufferSize)
+            {
+                state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
+            }
+            return buffer[state.bufferPos++];
+        }
+
+        /// <summary>
+        /// Reads a varint from the input one byte at a time, so that it does not
+        /// read any bytes after the end of the varint. If you simply wrapped the
+        /// stream in a CodedInputStream and used ReadRawVarint32(Stream)
+        /// then you would probably end up reading past the end of the varint since
+        /// CodedInputStream buffers its input.
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static uint ReadRawVarint32(Stream input)
+        {
+            int result = 0;
+            int offset = 0;
+            for (; offset < 32; offset += 7)
+            {
+                int b = input.ReadByte();
+                if (b == -1)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                result |= (b & 0x7f) << offset;
+                if ((b & 0x80) == 0)
+                {
+                    return (uint) result;
+                }
+            }
+            // Keep reading up to 64 bits.
+            for (; offset < 64; offset += 7)
+            {
+                int b = input.ReadByte();
+                if (b == -1)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                if ((b & 0x80) == 0)
+                {
+                    return (uint) result;
+                }
+            }
+            throw InvalidProtocolBufferException.MalformedVarint();
+        }
+
+        /// <summary>
+        /// Decode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 32 bits to be varint encoded, thus always taking
+        /// 5 bytes on the wire.)
+        /// </remarks>
+        public static int DecodeZigZag32(uint n)
+        {
+            return (int)(n >> 1) ^ -(int)(n & 1);
+        }
+
+        /// <summary>
+        /// Decode a 64-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        public static long DecodeZigZag64(ulong n)
+        {
+            return (long)(n >> 1) ^ -(long)(n & 1);
+        }
+
+        /// <summary>
+        /// Checks whether there is known data available of the specified size remaining to parse.
+        /// When parsing from a Stream this can return false because we have no knowledge of the amount
+        /// of data remaining in the stream until it is read.
+        /// </summary>
+        public static bool IsDataAvailable(ref ParserInternalState state, int size)
+        {
+            // Data fits in remaining buffer
+            if (size <= state.bufferSize - state.bufferPos)
+            {
+                return true;
+            }
+
+            return IsDataAvailableInSource(ref state, size);
+        }
+
+        /// <summary>
+        /// Checks whether there is known data available of the specified size remaining to parse
+        /// in the underlying data source.
+        /// When parsing from a Stream this will return false because we have no knowledge of the amount
+        /// of data remaining in the stream until it is read.
+        /// </summary>
+        private static bool IsDataAvailableInSource(ref ParserInternalState state, int size)
+        {
+            // Data fits in remaining source data.
+            // Note that this will never be true when reading from a stream as the total length is unknown.
+            return size <= state.segmentedBufferHelper.TotalLength - state.totalBytesRetired - state.bufferPos;
+        }
+
+        /// <summary>
+        /// Read raw bytes of the specified length into a span. The amount of data available and the current limit should
+        /// be checked before calling this method.
+        /// </summary>
+        private static void ReadRawBytesIntoSpan(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, int length, Span<byte> byteSpan)
+        {
+            int remainingByteLength = length;
+            while (remainingByteLength > 0)
+            {
+                if (state.bufferSize - state.bufferPos == 0)
+                {
+                    state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
+                }
+
+                ReadOnlySpan<byte> unreadSpan = buffer.Slice(state.bufferPos, Math.Min(remainingByteLength, state.bufferSize - state.bufferPos));
+                unreadSpan.CopyTo(byteSpan.Slice(length - remainingByteLength));
+
+                remainingByteLength -= unreadSpan.Length;
+                state.bufferPos += unreadSpan.Length;
+            }
+        }
+    }
+}
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs
new file mode 100644
index 0000000..eabaf96
--- /dev/null
+++ b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs
@@ -0,0 +1,292 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Security;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Reading and skipping messages / groups
+    /// </summary>
+    [SecuritySafeCritical]
+    internal static class ParsingPrimitivesMessages
+    {
+        private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };
+
+        public static void SkipLastField(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            if (state.lastTag == 0)
+            {
+                throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream");
+            }
+            switch (WireFormat.GetTagWireType(state.lastTag))
+            {
+                case WireFormat.WireType.StartGroup:
+                    SkipGroup(ref buffer, ref state, state.lastTag);
+                    break;
+                case WireFormat.WireType.EndGroup:
+                    throw new InvalidProtocolBufferException(
+                        "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing");
+                case WireFormat.WireType.Fixed32:
+                    ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
+                    break;
+                case WireFormat.WireType.Fixed64:
+                    ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state);
+                    break;
+                case WireFormat.WireType.LengthDelimited:
+                    var length = ParsingPrimitives.ParseLength(ref buffer, ref state);
+                    ParsingPrimitives.SkipRawBytes(ref buffer, ref state, length);
+                    break;
+                case WireFormat.WireType.Varint:
+                    ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// Skip a group.
+        /// </summary>
+        public static void SkipGroup(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, uint startGroupTag)
+        {
+            // Note: Currently we expect this to be the way that groups are read. We could put the recursion
+            // depth changes into the ReadTag method instead, potentially...
+            state.recursionDepth++;
+            if (state.recursionDepth >= state.recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            uint tag;
+            while (true)
+            {
+                tag = ParsingPrimitives.ParseTag(ref buffer, ref state);
+                if (tag == 0)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                // Can't call SkipLastField for this case- that would throw.
+                if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup)
+                {
+                    break;
+                }
+                // This recursion will allow us to handle nested groups.
+                SkipLastField(ref buffer, ref state);
+            }
+            int startField = WireFormat.GetTagFieldNumber(startGroupTag);
+            int endField = WireFormat.GetTagFieldNumber(tag);
+            if (startField != endField)
+            {
+                throw new InvalidProtocolBufferException(
+                    $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}");
+            }
+            state.recursionDepth--;
+        }
+
+        public static void ReadMessage(ref ParseContext ctx, IMessage message)
+        {
+            int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state);
+            if (ctx.state.recursionDepth >= ctx.state.recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length);
+            ++ctx.state.recursionDepth;
+
+            ReadRawMessage(ref ctx, message);
+
+            CheckReadEndOfStreamTag(ref ctx.state);
+            // Check that we've read exactly as much data as expected.
+            if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state))
+            {
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+            --ctx.state.recursionDepth;
+            SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);
+        }
+
+        public static KeyValuePair<TKey, TValue> ReadMapEntry<TKey, TValue>(ref ParseContext ctx, MapField<TKey, TValue>.Codec codec)
+        {
+            int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state);
+            if (ctx.state.recursionDepth >= ctx.state.recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length);
+            ++ctx.state.recursionDepth;
+
+            TKey key = codec.KeyCodec.DefaultValue;
+            TValue value = codec.ValueCodec.DefaultValue;
+
+            uint tag;
+            while ((tag = ctx.ReadTag()) != 0)
+            {
+                if (tag == codec.KeyCodec.Tag)
+                {
+                    key = codec.KeyCodec.Read(ref ctx);
+                }
+                else if (tag == codec.ValueCodec.Tag)
+                {
+                    value = codec.ValueCodec.Read(ref ctx);
+                }
+                else
+                {
+                    SkipLastField(ref ctx.buffer, ref ctx.state);
+                }
+            }
+
+            // Corner case: a map entry with a key but no value, where the value type is a message.
+            // Read it as if we'd seen input with no data (i.e. create a "default" message).
+            if (value == null)
+            {
+                if (ctx.state.CodedInputStream != null)
+                {
+                    // the decoded message might not support parsing from ParseContext, so
+                    // we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing.
+                    value = codec.ValueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
+                }
+                else
+                {
+                    ParseContext.Initialize(new ReadOnlySequence<byte>(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx);
+                    value = codec.ValueCodec.Read(ref zeroLengthCtx);
+                }
+            }
+
+            CheckReadEndOfStreamTag(ref ctx.state);
+            // Check that we've read exactly as much data as expected.
+            if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state))
+            {
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+            --ctx.state.recursionDepth;
+            SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);
+
+            return new KeyValuePair<TKey, TValue>(key, value);
+        }
+
+        public static void ReadGroup(ref ParseContext ctx, IMessage message)
+        {
+            if (ctx.state.recursionDepth >= ctx.state.recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            ++ctx.state.recursionDepth;
+            
+            uint tag = ctx.state.lastTag;
+            int fieldNumber = WireFormat.GetTagFieldNumber(tag);
+            ReadRawMessage(ref ctx, message);
+            CheckLastTagWas(ref ctx.state, WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
+
+            --ctx.state.recursionDepth;
+        }
+
+        public static void ReadGroup(ref ParseContext ctx, int fieldNumber, UnknownFieldSet set)
+        {
+            if (ctx.state.recursionDepth >= ctx.state.recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            ++ctx.state.recursionDepth;
+
+            set.MergeGroupFrom(ref ctx);
+            CheckLastTagWas(ref ctx.state, WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
+
+            --ctx.state.recursionDepth;
+        }
+
+        public static void ReadRawMessage(ref ParseContext ctx, IMessage message)
+        {
+            if (message is IBufferMessage bufferMessage)
+            {
+                bufferMessage.InternalMergeFrom(ref ctx);   
+            }
+            else
+            {
+                // If we reached here, it means we've ran into a nested message with older generated code
+                // which doesn't provide the InternalMergeFrom method that takes a ParseContext.
+                // With a slight performance overhead, we can still parse this message just fine,
+                // but we need to find the original CodedInputStream instance that initiated this
+                // parsing process and make sure its internal state is up to date.
+                // Note that this performance overhead is not very high (basically copying contents of a struct)
+                // and it will only be incurred in case the application mixes older and newer generated code.
+                // Regenerating the code from .proto files will remove this overhead because it will
+                // generate the InternalMergeFrom method we need.
+
+                if (ctx.state.CodedInputStream == null)
+                {
+                    // This can only happen when the parsing started without providing a CodedInputStream instance
+                    // (e.g. ParseContext was created directly from a ReadOnlySequence).
+                    // That also means that one of the new parsing APIs was used at the top level
+                    // and in such case it is reasonable to require that all the nested message provide
+                    // up-to-date generated code with ParseContext support (and fail otherwise).
+                    throw new InvalidProtocolBufferException($"Message {message.GetType().Name} doesn't provide the generated method that enables ParseContext-based parsing. You might need to regenerate the generated protobuf code.");
+                }
+
+                ctx.CopyStateTo(ctx.state.CodedInputStream);
+                try
+                {
+                    // fallback parse using the CodedInputStream that started current parsing tree
+                    message.MergeFrom(ctx.state.CodedInputStream);
+                }
+                finally
+                {
+                    ctx.LoadStateFrom(ctx.state.CodedInputStream);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Verifies that the last call to ReadTag() returned tag 0 - in other words,
+        /// we've reached the end of the stream when we expected to.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">The 
+        /// tag read was not the one specified</exception>
+        public static void CheckReadEndOfStreamTag(ref ParserInternalState state)
+        {
+            if (state.lastTag != 0)
+            {
+                throw InvalidProtocolBufferException.MoreDataAvailable();
+            }
+        }
+
+        private static void CheckLastTagWas(ref ParserInternalState state, uint expectedTag)
+        {
+            if (state.lastTag != expectedTag) {
+               throw InvalidProtocolBufferException.InvalidEndTag();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
new file mode 100644
index 0000000..629ec32
--- /dev/null
+++ b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
@@ -0,0 +1,355 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Fast parsing primitives for wrapper types
+    /// </summary>
+    [SecuritySafeCritical]
+    internal static class ParsingPrimitivesWrappers
+    {
+        internal static float? ReadFloatWrapperLittleEndian(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            // length:1 + tag:1 + value:4 = 6 bytes
+            if (state.bufferPos + 6 <= state.bufferSize)
+            {
+                // The entire wrapper message is already contained in `buffer`.
+                int length = buffer[state.bufferPos];
+                if (length == 0)
+                {
+                    state.bufferPos++;
+                    return 0F;
+                }
+                // tag:1 + value:4 = length of 5 bytes
+                // field=1, type=32-bit = tag of 13
+                if (length != 5 || buffer[state.bufferPos + 1] != 13)
+                {
+                    return ReadFloatWrapperSlow(ref buffer, ref state);
+                }
+                state.bufferPos += 2;
+                return ParsingPrimitives.ParseFloat(ref buffer, ref state);
+            }
+            else
+            {
+                return ReadFloatWrapperSlow(ref buffer, ref state);
+            }
+        }
+
+        internal static float? ReadFloatWrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            int length = ParsingPrimitives.ParseLength(ref buffer, ref state);
+            if (length == 0)
+            {
+                return 0F;
+            }
+            int finalBufferPos = state.totalBytesRetired + state.bufferPos + length;
+            float result = 0F;
+            do
+            {
+                // field=1, type=32-bit = tag of 13
+                if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 13)
+                {
+                    result = ParsingPrimitives.ParseFloat(ref buffer, ref state);
+                }
+                else
+                {
+                    ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state);
+                }
+            }
+            while (state.totalBytesRetired + state.bufferPos < finalBufferPos);
+            return result;
+        }
+
+        internal static double? ReadDoubleWrapperLittleEndian(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            // length:1 + tag:1 + value:8 = 10 bytes
+            if (state.bufferPos + 10 <= state.bufferSize)
+            {
+                // The entire wrapper message is already contained in `buffer`.
+                int length = buffer[state.bufferPos];
+                if (length == 0)
+                {
+                    state.bufferPos++;
+                    return 0D;
+                }
+                // tag:1 + value:8 = length of 9 bytes
+                // field=1, type=64-bit = tag of 9
+                if (length != 9 || buffer[state.bufferPos + 1] != 9)
+                {
+                    return ReadDoubleWrapperSlow(ref buffer, ref state);
+                }
+                state.bufferPos += 2;
+                return ParsingPrimitives.ParseDouble(ref buffer, ref state);
+            }
+            else
+            {
+                return ReadDoubleWrapperSlow(ref buffer, ref state);
+            }
+        }
+
+        internal static double? ReadDoubleWrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            int length = ParsingPrimitives.ParseLength(ref buffer, ref state);
+            if (length == 0)
+            {
+                return 0D;
+            }
+            int finalBufferPos = state.totalBytesRetired + state.bufferPos + length;
+            double result = 0D;
+            do
+            {
+                // field=1, type=64-bit = tag of 9
+                if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 9)
+                {
+                    result = ParsingPrimitives.ParseDouble(ref buffer, ref state);
+                }
+                else
+                {
+                    ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state);
+                }
+            }
+            while (state.totalBytesRetired + state.bufferPos < finalBufferPos);
+            return result;
+        }
+
+        internal static bool? ReadBoolWrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            return ReadUInt64Wrapper(ref buffer, ref state) != 0;
+        }
+
+        internal static uint? ReadUInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            // field=1, type=varint = tag of 8
+            const int expectedTag = 8;
+            // length:1 + tag:1 + value:10(varint64-max) = 12 bytes
+            // Value can be 64 bits for negative integers
+            if (state.bufferPos + 12 <= state.bufferSize)
+            {
+                // The entire wrapper message is already contained in `buffer`.
+                int pos0 = state.bufferPos;
+                int length = buffer[state.bufferPos++];
+                if (length == 0)
+                {
+                    return 0;
+                }
+                // Length will always fit in a single byte.
+                if (length >= 128)
+                {
+                    state.bufferPos = pos0;
+                    return ReadUInt32WrapperSlow(ref buffer, ref state);
+                }
+                int finalBufferPos = state.bufferPos + length;
+                if (buffer[state.bufferPos++] != expectedTag)
+                {
+                    state.bufferPos = pos0;
+                    return ReadUInt32WrapperSlow(ref buffer, ref state);
+                }
+                var result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+                // Verify this message only contained a single field.
+                if (state.bufferPos != finalBufferPos)
+                {
+                    state.bufferPos = pos0;
+                    return ReadUInt32WrapperSlow(ref buffer, ref state);
+                }
+                return result;
+            }
+            else
+            {
+                return ReadUInt32WrapperSlow(ref buffer, ref state);
+            }
+        }
+
+        internal static uint? ReadUInt32WrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            int length = ParsingPrimitives.ParseLength(ref buffer, ref state);
+            if (length == 0)
+            {
+                return 0;
+            }
+            int finalBufferPos = state.totalBytesRetired + state.bufferPos + length;
+            uint result = 0;
+            do
+            {
+                // field=1, type=varint = tag of 8
+                if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 8)
+                {
+                    result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
+                }
+                else
+                {
+                    ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state);
+                }
+            }
+            while (state.totalBytesRetired + state.bufferPos < finalBufferPos);
+            return result;
+        }
+
+        internal static int? ReadInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            return (int?)ReadUInt32Wrapper(ref buffer, ref state);
+        }
+
+        internal static ulong? ReadUInt64Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            // field=1, type=varint = tag of 8
+            const int expectedTag = 8;
+            // length:1 + tag:1 + value:10(varint64-max) = 12 bytes
+            if (state.bufferPos + 12 <= state.bufferSize)
+            {
+                // The entire wrapper message is already contained in `buffer`.
+                int pos0 = state.bufferPos;
+                int length = buffer[state.bufferPos++];
+                if (length == 0)
+                {
+                    return 0L;
+                }
+                // Length will always fit in a single byte.
+                if (length >= 128)
+                {
+                    state.bufferPos = pos0;
+                    return ReadUInt64WrapperSlow(ref buffer, ref state);
+                }
+                int finalBufferPos = state.bufferPos + length;
+                if (buffer[state.bufferPos++] != expectedTag)
+                {
+                    state.bufferPos = pos0;
+                    return ReadUInt64WrapperSlow(ref buffer, ref state);
+                }
+                var result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
+                // Verify this message only contained a single field.
+                if (state.bufferPos != finalBufferPos)
+                {
+                    state.bufferPos = pos0;
+                    return ReadUInt64WrapperSlow(ref buffer, ref state);
+                }
+                return result;
+            }
+            else
+            {
+                return ReadUInt64WrapperSlow(ref buffer, ref state);
+            }
+        }
+
+        internal static ulong? ReadUInt64WrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            // field=1, type=varint = tag of 8
+            const int expectedTag = 8;
+            int length = ParsingPrimitives.ParseLength(ref buffer, ref state);
+            if (length == 0)
+            {
+                return 0L;
+            }
+            int finalBufferPos = state.totalBytesRetired + state.bufferPos + length;
+            ulong result = 0L;
+            do
+            {
+                if (ParsingPrimitives.ParseTag(ref buffer, ref state) == expectedTag)
+                {
+                    result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state);
+                }
+                else
+                {
+                    ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state);
+                }
+            }
+            while (state.totalBytesRetired + state.bufferPos < finalBufferPos);
+            return result;
+        }
+
+        internal static long? ReadInt64Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            return (long?)ReadUInt64Wrapper(ref buffer, ref state);
+        }
+
+        internal static float? ReadFloatWrapperLittleEndian(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadFloatWrapperLittleEndian(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static float? ReadFloatWrapperSlow(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadFloatWrapperSlow(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static double? ReadDoubleWrapperLittleEndian(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadDoubleWrapperLittleEndian(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static double? ReadDoubleWrapperSlow(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadDoubleWrapperSlow(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static bool? ReadBoolWrapper(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadBoolWrapper(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static uint? ReadUInt32Wrapper(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadUInt32Wrapper(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static int? ReadInt32Wrapper(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static ulong? ReadUInt64Wrapper(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadUInt64Wrapper(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static ulong? ReadUInt64WrapperSlow(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadUInt64WrapperSlow(ref ctx.buffer, ref ctx.state);
+        }
+
+        internal static long? ReadInt64Wrapper(ref ParseContext ctx)
+        {
+            return ParsingPrimitivesWrappers.ReadInt64Wrapper(ref ctx.buffer, ref ctx.state);
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
index 9b179bd..130bcf0 100644
--- a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
+++ b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
@@ -47,3 +47,10 @@
     "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +

     "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +

     "c5ae9cb6")]

+

+[assembly: InternalsVisibleTo("Google.Protobuf.Benchmarks, PublicKey=" +

+    "002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +

+    "7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +

+    "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +

+    "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +

+    "c5ae9cb6")]

diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
index c9ba632..5cae6ac 100644
--- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
@@ -107,57 +107,57 @@
             "eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
             "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w",
             "dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf",
-            "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECci8gEKDk1lc3NhZ2VPcHRpb25z",
+            "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECcihAIKDk1lc3NhZ2VPcHRpb25z",
             "EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u",
             "b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ",
             "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS",
             "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
-            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAgQCUoECAkQ",
-            "CiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBlGAEgASgOMiMuZ29vZ2xlLnBy",
-            "b3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToGU1RSSU5HEg4KBnBhY2tlZBgC",
-            "IAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29nbGUucHJvdG9idWYuRmllbGRP",
-            "cHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMKBGxhenkYBSABKAg6BWZhbHNl",
-            "EhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhMKBHdlYWsYCiABKAg6BWZh",
-            "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w",
-            "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIi8KBUNUeXBlEgoKBlNUUklO",
-            "RxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElFQ0UQAiI1CgZKU1R5cGUSDQoJ",
-            "SlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAESDQoJSlNfTlVNQkVSEAIqCQjo",
-            "BxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlvbnMSQwoUdW5pbnRlcnByZXRl",
-            "ZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0",
-            "ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51bU9wdGlvbnMSEwoLYWxsb3df",
-            "YWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USQwoUdW5p",
-            "bnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVu",
-            "aW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAUQBiJ9ChBFbnVtVmFs",
-            "dWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASABKAg6BWZhbHNlEkMKFHVuaW50",
-            "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu",
-            "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiewoOU2VydmljZU9wdGlvbnMS",
-            "GQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v",
-            "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP",
-            "cHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9kT3B0aW9ucxIZCgpkZXByZWNh",
-            "dGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90ZW5jeV9sZXZlbBgiIAEoDjIv",
-            "Lmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zLklkZW1wb3RlbmN5TGV2",
-            "ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoUdW5pbnRlcnByZXRlZF9vcHRp",
-            "b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp",
-            "b24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJREVNUE9URU5DWV9VTktOT1dO",
-            "EAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoKSURFTVBPVEVOVBACKgkI6AcQ",
-            "gICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgCIAMoCzIt",
-            "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5hbWVQYXJ0",
-            "EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVfaW50X3Zh",
-            "bHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIUCgxkb3Vi",
-            "bGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMEhcKD2FnZ3Jl",
-            "Z2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1lX3BhcnQYASAC",
-            "KAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUBCg5Tb3VyY2VDb2RlSW5mbxI6",
-            "Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2Rl",
-            "SW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0aBgBIAMoBUICEAES",
-            "EAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21tZW50cxgDIAEoCRIZ",
-            "ChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFkaW5nX2RldGFjaGVk",
-            "X2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0ZWRDb2RlSW5mbxJBCgphbm5v",
-            "dGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZENvZGVJ",
-            "bmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygFQgIQ",
-            "ARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNlbmQY",
-            "BCABKAVCjwEKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2NyaXB0b3JQcm90",
-            "b3NIAVo+Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHJvdG9jLWdlbi1n",
-            "by9kZXNjcmlwdG9yO2Rlc2NyaXB0b3L4AQGiAgNHUEKqAhpHb29nbGUuUHJv",
+            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAQQBUoECAUQ",
+            "BkoECAYQB0oECAgQCUoECAkQCiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBl",
+            "GAEgASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToG",
+            "U1RSSU5HEg4KBnBhY2tlZBgCIAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29n",
+            "bGUucHJvdG9idWYuRmllbGRPcHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMK",
+            "BGxhenkYBSABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNl",
+            "EhMKBHdlYWsYCiABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u",
+            "GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u",
+            "Ii8KBUNUeXBlEgoKBlNUUklORxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElF",
+            "Q0UQAiI1CgZKU1R5cGUSDQoJSlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAES",
+            "DQoJSlNfTlVNQkVSEAIqCQjoBxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlv",
+            "bnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy",
+            "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51",
+            "bU9wdGlvbnMSEwoLYWxsb3dfYWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgD",
+            "IAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQu",
+            "Z29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICA",
+            "AkoECAUQBiJ9ChBFbnVtVmFsdWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASAB",
+            "KAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdv",
+            "b2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi",
+            "ewoOU2VydmljZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2US",
+            "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
+            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9k",
+            "T3B0aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90",
+            "ZW5jeV9sZXZlbBgiIAEoDjIvLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRp",
+            "b25zLklkZW1wb3RlbmN5TGV2ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoU",
+            "dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm",
+            "LlVuaW50ZXJwcmV0ZWRPcHRpb24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJ",
+            "REVNUE9URU5DWV9VTktOT1dOEAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoK",
+            "SURFTVBPVEVOVBACKgkI6AcQgICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRp",
+            "b24SOwoEbmFtZRgCIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJl",
+            "dGVkT3B0aW9uLk5hbWVQYXJ0EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkS",
+            "GgoScG9zaXRpdmVfaW50X3ZhbHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92",
+            "YWx1ZRgFIAEoAxIUCgxkb3VibGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3Zh",
+            "bHVlGAcgASgMEhcKD2FnZ3JlZ2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFy",
+            "dBIRCgluYW1lX3BhcnQYASACKAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUB",
+            "Cg5Tb3VyY2VDb2RlSW5mbxI6Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5w",
+            "cm90b2J1Zi5Tb3VyY2VDb2RlSW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24S",
+            "EAoEcGF0aBgBIAMoBUICEAESEAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGlu",
+            "Z19jb21tZW50cxgDIAEoCRIZChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIh",
+            "ChlsZWFkaW5nX2RldGFjaGVkX2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0",
+            "ZWRDb2RlSW5mbxJBCgphbm5vdGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3Rv",
+            "YnVmLkdlbmVyYXRlZENvZGVJbmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlv",
+            "bhIQCgRwYXRoGAEgAygFQgIQARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgVi",
+            "ZWdpbhgDIAEoBRILCgNlbmQYBCABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1",
+            "ZkIQRGVzY3JpcHRvclByb3Rvc0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90",
+            "b2J1Zi90eXBlcy9kZXNjcmlwdG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJv",
             "dG9idWYuUmVmbGVjdGlvbg=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
@@ -194,23 +194,31 @@
   /// The protocol compiler can output a FileDescriptorSet containing the .proto
   /// files it parses.
   /// </summary>
-  public sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet> {
+  public sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FileDescriptorSet> _parser = new pb::MessageParser<FileDescriptorSet>(() => new FileDescriptorSet());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FileDescriptorSet> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileDescriptorSet() {
       OnConstruction();
     }
@@ -218,12 +226,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileDescriptorSet(FileDescriptorSet other) : this() {
       file_ = other.file_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileDescriptorSet Clone() {
       return new FileDescriptorSet(this);
     }
@@ -234,16 +244,19 @@
         = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Reflection.FileDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto> file_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto> File {
       get { return file_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FileDescriptorSet);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FileDescriptorSet other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -256,6 +269,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= file_.GetHashCode();
@@ -266,19 +280,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       file_.WriteTo(output, _repeated_file_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      file_.WriteTo(ref output, _repeated_file_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += file_.CalculateSize(_repeated_file_codec);
@@ -289,6 +321,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FileDescriptorSet other) {
       if (other == null) {
         return;
@@ -298,7 +331,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -311,30 +348,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            file_.AddEntriesFrom(ref input, _repeated_file_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Describes a complete .proto file.
   /// </summary>
-  public sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto> {
+  public sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FileDescriptorProto> _parser = new pb::MessageParser<FileDescriptorProto>(() => new FileDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FileDescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileDescriptorProto() {
       OnConstruction();
     }
@@ -342,6 +407,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileDescriptorProto(FileDescriptorProto other) : this() {
       name_ = other.name_;
       package_ = other.package_;
@@ -352,13 +418,14 @@
       enumType_ = other.enumType_.Clone();
       service_ = other.service_.Clone();
       extension_ = other.extension_.Clone();
-      options_ = other.HasOptions ? other.options_.Clone() : null;
-      sourceCodeInfo_ = other.HasSourceCodeInfo ? other.sourceCodeInfo_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
+      sourceCodeInfo_ = other.sourceCodeInfo_ != null ? other.sourceCodeInfo_.Clone() : null;
       syntax_ = other.syntax_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileDescriptorProto Clone() {
       return new FileDescriptorProto(this);
     }
@@ -372,6 +439,7 @@
     /// file name, relative to root of source tree
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -380,11 +448,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -398,6 +468,7 @@
     /// e.g. "foo", "foo.bar", etc.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Package {
       get { return package_ ?? PackageDefaultValue; }
       set {
@@ -406,11 +477,13 @@
     }
     /// <summary>Gets whether the "package" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPackage {
       get { return package_ != null; }
     }
     /// <summary>Clears the value of the "package" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPackage() {
       package_ = null;
     }
@@ -424,6 +497,7 @@
     /// Names of files imported by this file.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> Dependency {
       get { return dependency_; }
     }
@@ -437,6 +511,7 @@
     /// Indexes of the public imported files in the dependency list above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> PublicDependency {
       get { return publicDependency_; }
     }
@@ -451,6 +526,7 @@
     /// For Google-internal migration only. Do not use.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<int> WeakDependency {
       get { return weakDependency_; }
     }
@@ -464,6 +540,7 @@
     /// All top-level definitions in this file.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto> MessageType {
       get { return messageType_; }
     }
@@ -474,6 +551,7 @@
         = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> EnumType {
       get { return enumType_; }
     }
@@ -484,6 +562,7 @@
         = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.ServiceDescriptorProto> service_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.ServiceDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.ServiceDescriptorProto> Service {
       get { return service_; }
     }
@@ -494,6 +573,7 @@
         = pb::FieldCodec.ForMessage(58, global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> Extension {
       get { return extension_; }
     }
@@ -502,22 +582,13 @@
     public const int OptionsFieldNumber = 8;
     private global::Google.Protobuf.Reflection.FileOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.FileOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     /// <summary>Field number for the "source_code_info" field.</summary>
     public const int SourceCodeInfoFieldNumber = 9;
@@ -529,22 +600,13 @@
     /// development tools.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.SourceCodeInfo SourceCodeInfo {
       get { return sourceCodeInfo_; }
       set {
         sourceCodeInfo_ = value;
       }
     }
-    /// <summary>Gets whether the source_code_info field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasSourceCodeInfo {
-      get { return sourceCodeInfo_ != null; }
-    }
-    /// <summary>Clears the value of the source_code_info field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearSourceCodeInfo() {
-      sourceCodeInfo_ = null;
-    }
 
     /// <summary>Field number for the "syntax" field.</summary>
     public const int SyntaxFieldNumber = 12;
@@ -556,6 +618,7 @@
     /// The supported values are "proto2" and "proto3".
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Syntax {
       get { return syntax_ ?? SyntaxDefaultValue; }
       set {
@@ -564,21 +627,25 @@
     }
     /// <summary>Gets whether the "syntax" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSyntax {
       get { return syntax_ != null; }
     }
     /// <summary>Clears the value of the "syntax" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSyntax() {
       syntax_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FileDescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FileDescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -602,6 +669,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
@@ -613,8 +681,8 @@
       hash ^= enumType_.GetHashCode();
       hash ^= service_.GetHashCode();
       hash ^= extension_.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
-      if (HasSourceCodeInfo) hash ^= SourceCodeInfo.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
+      if (sourceCodeInfo_ != null) hash ^= SourceCodeInfo.GetHashCode();
       if (HasSyntax) hash ^= Syntax.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -623,12 +691,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -642,11 +715,11 @@
       enumType_.WriteTo(output, _repeated_enumType_codec);
       service_.WriteTo(output, _repeated_service_codec);
       extension_.WriteTo(output, _repeated_extension_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(66);
         output.WriteMessage(Options);
       }
-      if (HasSourceCodeInfo) {
+      if (sourceCodeInfo_ != null) {
         output.WriteRawTag(74);
         output.WriteMessage(SourceCodeInfo);
       }
@@ -659,9 +732,48 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (HasPackage) {
+        output.WriteRawTag(18);
+        output.WriteString(Package);
+      }
+      dependency_.WriteTo(ref output, _repeated_dependency_codec);
+      messageType_.WriteTo(ref output, _repeated_messageType_codec);
+      enumType_.WriteTo(ref output, _repeated_enumType_codec);
+      service_.WriteTo(ref output, _repeated_service_codec);
+      extension_.WriteTo(ref output, _repeated_extension_codec);
+      if (options_ != null) {
+        output.WriteRawTag(66);
+        output.WriteMessage(Options);
+      }
+      if (sourceCodeInfo_ != null) {
+        output.WriteRawTag(74);
+        output.WriteMessage(SourceCodeInfo);
+      }
+      publicDependency_.WriteTo(ref output, _repeated_publicDependency_codec);
+      weakDependency_.WriteTo(ref output, _repeated_weakDependency_codec);
+      if (HasSyntax) {
+        output.WriteRawTag(98);
+        output.WriteString(Syntax);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
@@ -677,10 +789,10 @@
       size += enumType_.CalculateSize(_repeated_enumType_codec);
       size += service_.CalculateSize(_repeated_service_codec);
       size += extension_.CalculateSize(_repeated_extension_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
-      if (HasSourceCodeInfo) {
+      if (sourceCodeInfo_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceCodeInfo);
       }
       if (HasSyntax) {
@@ -693,6 +805,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FileDescriptorProto other) {
       if (other == null) {
         return;
@@ -710,14 +823,14 @@
       enumType_.Add(other.enumType_);
       service_.Add(other.service_);
       extension_.Add(other.extension_);
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.FileOptions();
         }
         Options.MergeFrom(other.Options);
       }
-      if (other.HasSourceCodeInfo) {
-        if (!HasSourceCodeInfo) {
+      if (other.sourceCodeInfo_ != null) {
+        if (sourceCodeInfo_ == null) {
           SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo();
         }
         SourceCodeInfo.MergeFrom(other.SourceCodeInfo);
@@ -729,7 +842,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -765,14 +882,14 @@
             break;
           }
           case 66: {
-            if (!HasOptions) {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.FileOptions();
             }
             input.ReadMessage(Options);
             break;
           }
           case 74: {
-            if (!HasSourceCodeInfo) {
+            if (sourceCodeInfo_ == null) {
               SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo();
             }
             input.ReadMessage(SourceCodeInfo);
@@ -794,30 +911,110 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Package = input.ReadString();
+            break;
+          }
+          case 26: {
+            dependency_.AddEntriesFrom(ref input, _repeated_dependency_codec);
+            break;
+          }
+          case 34: {
+            messageType_.AddEntriesFrom(ref input, _repeated_messageType_codec);
+            break;
+          }
+          case 42: {
+            enumType_.AddEntriesFrom(ref input, _repeated_enumType_codec);
+            break;
+          }
+          case 50: {
+            service_.AddEntriesFrom(ref input, _repeated_service_codec);
+            break;
+          }
+          case 58: {
+            extension_.AddEntriesFrom(ref input, _repeated_extension_codec);
+            break;
+          }
+          case 66: {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.FileOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+          case 74: {
+            if (sourceCodeInfo_ == null) {
+              SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo();
+            }
+            input.ReadMessage(SourceCodeInfo);
+            break;
+          }
+          case 82:
+          case 80: {
+            publicDependency_.AddEntriesFrom(ref input, _repeated_publicDependency_codec);
+            break;
+          }
+          case 90:
+          case 88: {
+            weakDependency_.AddEntriesFrom(ref input, _repeated_weakDependency_codec);
+            break;
+          }
+          case 98: {
+            Syntax = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Describes a message type.
   /// </summary>
-  public sealed partial class DescriptorProto : pb::IMessage<DescriptorProto> {
+  public sealed partial class DescriptorProto : pb::IMessage<DescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<DescriptorProto> _parser = new pb::MessageParser<DescriptorProto>(() => new DescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<DescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DescriptorProto() {
       OnConstruction();
     }
@@ -825,6 +1022,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DescriptorProto(DescriptorProto other) : this() {
       name_ = other.name_;
       field_ = other.field_.Clone();
@@ -833,13 +1031,14 @@
       enumType_ = other.enumType_.Clone();
       extensionRange_ = other.extensionRange_.Clone();
       oneofDecl_ = other.oneofDecl_.Clone();
-      options_ = other.HasOptions ? other.options_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
       reservedRange_ = other.reservedRange_.Clone();
       reservedName_ = other.reservedName_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DescriptorProto Clone() {
       return new DescriptorProto(this);
     }
@@ -850,6 +1049,7 @@
 
     private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -858,11 +1058,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -873,6 +1075,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> field_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> Field {
       get { return field_; }
     }
@@ -883,6 +1086,7 @@
         = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> extension_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.FieldDescriptorProto> Extension {
       get { return extension_; }
     }
@@ -893,6 +1097,7 @@
         = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.Reflection.DescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto> nestedType_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto> NestedType {
       get { return nestedType_; }
     }
@@ -903,6 +1108,7 @@
         = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> enumType_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto> EnumType {
       get { return enumType_; }
     }
@@ -913,6 +1119,7 @@
         = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange> extensionRange_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange> ExtensionRange {
       get { return extensionRange_; }
     }
@@ -923,6 +1130,7 @@
         = pb::FieldCodec.ForMessage(66, global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.OneofDescriptorProto> oneofDecl_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.OneofDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.OneofDescriptorProto> OneofDecl {
       get { return oneofDecl_; }
     }
@@ -931,22 +1139,13 @@
     public const int OptionsFieldNumber = 7;
     private global::Google.Protobuf.Reflection.MessageOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.MessageOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     /// <summary>Field number for the "reserved_range" field.</summary>
     public const int ReservedRangeFieldNumber = 9;
@@ -954,6 +1153,7 @@
         = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange> reservedRange_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange> ReservedRange {
       get { return reservedRange_; }
     }
@@ -968,16 +1168,19 @@
     /// A given name may only be reserved once.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> ReservedName {
       get { return reservedName_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as DescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(DescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -999,6 +1202,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
@@ -1008,7 +1212,7 @@
       hash ^= enumType_.GetHashCode();
       hash ^= extensionRange_.GetHashCode();
       hash ^= oneofDecl_.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
       hash ^= reservedRange_.GetHashCode();
       hash ^= reservedName_.GetHashCode();
       if (_unknownFields != null) {
@@ -1018,12 +1222,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -1033,7 +1242,7 @@
       enumType_.WriteTo(output, _repeated_enumType_codec);
       extensionRange_.WriteTo(output, _repeated_extensionRange_codec);
       extension_.WriteTo(output, _repeated_extension_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(58);
         output.WriteMessage(Options);
       }
@@ -1043,9 +1252,37 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      field_.WriteTo(ref output, _repeated_field_codec);
+      nestedType_.WriteTo(ref output, _repeated_nestedType_codec);
+      enumType_.WriteTo(ref output, _repeated_enumType_codec);
+      extensionRange_.WriteTo(ref output, _repeated_extensionRange_codec);
+      extension_.WriteTo(ref output, _repeated_extension_codec);
+      if (options_ != null) {
+        output.WriteRawTag(58);
+        output.WriteMessage(Options);
+      }
+      oneofDecl_.WriteTo(ref output, _repeated_oneofDecl_codec);
+      reservedRange_.WriteTo(ref output, _repeated_reservedRange_codec);
+      reservedName_.WriteTo(ref output, _repeated_reservedName_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
@@ -1057,7 +1294,7 @@
       size += enumType_.CalculateSize(_repeated_enumType_codec);
       size += extensionRange_.CalculateSize(_repeated_extensionRange_codec);
       size += oneofDecl_.CalculateSize(_repeated_oneofDecl_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
@@ -1069,6 +1306,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(DescriptorProto other) {
       if (other == null) {
         return;
@@ -1082,8 +1320,8 @@
       enumType_.Add(other.enumType_);
       extensionRange_.Add(other.extensionRange_);
       oneofDecl_.Add(other.oneofDecl_);
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.MessageOptions();
         }
         Options.MergeFrom(other.Options);
@@ -1094,7 +1332,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1126,7 +1368,7 @@
             break;
           }
           case 58: {
-            if (!HasOptions) {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.MessageOptions();
             }
             input.ReadMessage(Options);
@@ -1146,30 +1388,98 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            field_.AddEntriesFrom(ref input, _repeated_field_codec);
+            break;
+          }
+          case 26: {
+            nestedType_.AddEntriesFrom(ref input, _repeated_nestedType_codec);
+            break;
+          }
+          case 34: {
+            enumType_.AddEntriesFrom(ref input, _repeated_enumType_codec);
+            break;
+          }
+          case 42: {
+            extensionRange_.AddEntriesFrom(ref input, _repeated_extensionRange_codec);
+            break;
+          }
+          case 50: {
+            extension_.AddEntriesFrom(ref input, _repeated_extension_codec);
+            break;
+          }
+          case 58: {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.MessageOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+          case 66: {
+            oneofDecl_.AddEntriesFrom(ref input, _repeated_oneofDecl_codec);
+            break;
+          }
+          case 74: {
+            reservedRange_.AddEntriesFrom(ref input, _repeated_reservedRange_codec);
+            break;
+          }
+          case 82: {
+            reservedName_.AddEntriesFrom(ref input, _repeated_reservedName_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the DescriptorProto message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class ExtensionRange : pb::IMessage<ExtensionRange> {
+      public sealed partial class ExtensionRange : pb::IMessage<ExtensionRange>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<ExtensionRange> _parser = new pb::MessageParser<ExtensionRange>(() => new ExtensionRange());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<ExtensionRange> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.DescriptorProto.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ExtensionRange() {
           OnConstruction();
         }
@@ -1177,15 +1487,17 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ExtensionRange(ExtensionRange other) : this() {
           _hasBits0 = other._hasBits0;
           start_ = other.start_;
           end_ = other.end_;
-          options_ = other.HasOptions ? other.options_.Clone() : null;
+          options_ = other.options_ != null ? other.options_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ExtensionRange Clone() {
           return new ExtensionRange(this);
         }
@@ -1199,6 +1511,7 @@
         /// Inclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Start {
           get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } }
           set {
@@ -1208,11 +1521,13 @@
         }
         /// <summary>Gets whether the "start" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasStart {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "start" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearStart() {
           _hasBits0 &= ~1;
         }
@@ -1226,6 +1541,7 @@
         /// Exclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int End {
           get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
@@ -1235,11 +1551,13 @@
         }
         /// <summary>Gets whether the "end" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasEnd {
           get { return (_hasBits0 & 2) != 0; }
         }
         /// <summary>Clears the value of the "end" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearEnd() {
           _hasBits0 &= ~2;
         }
@@ -1248,29 +1566,22 @@
         public const int OptionsFieldNumber = 3;
         private global::Google.Protobuf.Reflection.ExtensionRangeOptions options_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public global::Google.Protobuf.Reflection.ExtensionRangeOptions Options {
           get { return options_; }
           set {
             options_ = value;
           }
         }
-        /// <summary>Gets whether the options field is set</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public bool HasOptions {
-          get { return options_ != null; }
-        }
-        /// <summary>Clears the value of the options field</summary>
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public void ClearOptions() {
-          options_ = null;
-        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as ExtensionRange);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(ExtensionRange other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -1285,11 +1596,12 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasStart) hash ^= Start.GetHashCode();
           if (HasEnd) hash ^= End.GetHashCode();
-          if (HasOptions) hash ^= Options.GetHashCode();
+          if (options_ != null) hash ^= Options.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -1297,12 +1609,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasStart) {
             output.WriteRawTag(8);
             output.WriteInt32(Start);
@@ -1311,16 +1628,40 @@
             output.WriteRawTag(16);
             output.WriteInt32(End);
           }
-          if (HasOptions) {
+          if (options_ != null) {
             output.WriteRawTag(26);
             output.WriteMessage(Options);
           }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasStart) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Start);
+          }
+          if (HasEnd) {
+            output.WriteRawTag(16);
+            output.WriteInt32(End);
+          }
+          if (options_ != null) {
+            output.WriteRawTag(26);
+            output.WriteMessage(Options);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasStart) {
@@ -1329,7 +1670,7 @@
           if (HasEnd) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
           }
-          if (HasOptions) {
+          if (options_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
           }
           if (_unknownFields != null) {
@@ -1339,6 +1680,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(ExtensionRange other) {
           if (other == null) {
             return;
@@ -1349,8 +1691,8 @@
           if (other.HasEnd) {
             End = other.End;
           }
-          if (other.HasOptions) {
-            if (!HasOptions) {
+          if (other.options_ != null) {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
             }
             Options.MergeFrom(other.Options);
@@ -1359,7 +1701,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -1375,7 +1721,37 @@
                 break;
               }
               case 26: {
-                if (!HasOptions) {
+                if (options_ == null) {
+                  Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
+                }
+                input.ReadMessage(Options);
+                break;
+              }
+            }
+          }
+        #endif
+        }
+
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Start = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                End = input.ReadInt32();
+                break;
+              }
+              case 26: {
+                if (options_ == null) {
                   Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
                 }
                 input.ReadMessage(Options);
@@ -1384,6 +1760,7 @@
             }
           }
         }
+        #endif
 
       }
 
@@ -1392,24 +1769,32 @@
       /// fields or extension ranges in the same message. Reserved ranges may
       /// not overlap.
       /// </summary>
-      public sealed partial class ReservedRange : pb::IMessage<ReservedRange> {
+      public sealed partial class ReservedRange : pb::IMessage<ReservedRange>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<ReservedRange> _parser = new pb::MessageParser<ReservedRange>(() => new ReservedRange());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<ReservedRange> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.DescriptorProto.Descriptor.NestedTypes[1]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ReservedRange() {
           OnConstruction();
         }
@@ -1417,6 +1802,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ReservedRange(ReservedRange other) : this() {
           _hasBits0 = other._hasBits0;
           start_ = other.start_;
@@ -1425,6 +1811,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public ReservedRange Clone() {
           return new ReservedRange(this);
         }
@@ -1438,6 +1825,7 @@
         /// Inclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Start {
           get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } }
           set {
@@ -1447,11 +1835,13 @@
         }
         /// <summary>Gets whether the "start" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasStart {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "start" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearStart() {
           _hasBits0 &= ~1;
         }
@@ -1465,6 +1855,7 @@
         /// Exclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int End {
           get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
@@ -1474,21 +1865,25 @@
         }
         /// <summary>Gets whether the "end" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasEnd {
           get { return (_hasBits0 & 2) != 0; }
         }
         /// <summary>Clears the value of the "end" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearEnd() {
           _hasBits0 &= ~2;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as ReservedRange);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(ReservedRange other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -1502,6 +1897,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasStart) hash ^= Start.GetHashCode();
@@ -1513,12 +1909,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasStart) {
             output.WriteRawTag(8);
             output.WriteInt32(Start);
@@ -1530,9 +1931,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasStart) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Start);
+          }
+          if (HasEnd) {
+            output.WriteRawTag(16);
+            output.WriteInt32(End);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasStart) {
@@ -1548,6 +1969,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(ReservedRange other) {
           if (other == null) {
             return;
@@ -1562,7 +1984,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -1579,8 +2005,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Start = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                End = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -1588,25 +2038,33 @@
 
   }
 
-  public sealed partial class ExtensionRangeOptions : pb::IExtendableMessage<ExtensionRangeOptions> {
+  public sealed partial class ExtensionRangeOptions : pb::IExtendableMessage<ExtensionRangeOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ExtensionRangeOptions> _parser = new pb::MessageParser<ExtensionRangeOptions>(() => new ExtensionRangeOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<ExtensionRangeOptions> _extensions;
     private pb::ExtensionSet<ExtensionRangeOptions> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ExtensionRangeOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ExtensionRangeOptions() {
       OnConstruction();
     }
@@ -1614,6 +2072,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ExtensionRangeOptions(ExtensionRangeOptions other) : this() {
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -1621,6 +2080,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ExtensionRangeOptions Clone() {
       return new ExtensionRangeOptions(this);
     }
@@ -1634,16 +2094,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ExtensionRangeOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ExtensionRangeOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1659,6 +2122,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= uninterpretedOption_.GetHashCode();
@@ -1672,12 +2136,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
       if (_extensions != null) {
         _extensions.WriteTo(output);
@@ -1685,9 +2154,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -1701,6 +2186,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ExtensionRangeOptions other) {
       if (other == null) {
         return;
@@ -1711,7 +2197,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1726,8 +2216,30 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<ExtensionRangeOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -1755,24 +2267,32 @@
   /// <summary>
   /// Describes a field within a message.
   /// </summary>
-  public sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto> {
+  public sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FieldDescriptorProto> _parser = new pb::MessageParser<FieldDescriptorProto>(() => new FieldDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FieldDescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldDescriptorProto() {
       OnConstruction();
     }
@@ -1780,6 +2300,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldDescriptorProto(FieldDescriptorProto other) : this() {
       _hasBits0 = other._hasBits0;
       name_ = other.name_;
@@ -1791,12 +2312,13 @@
       defaultValue_ = other.defaultValue_;
       oneofIndex_ = other.oneofIndex_;
       jsonName_ = other.jsonName_;
-      options_ = other.HasOptions ? other.options_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
       proto3Optional_ = other.proto3Optional_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldDescriptorProto Clone() {
       return new FieldDescriptorProto(this);
     }
@@ -1807,6 +2329,7 @@
 
     private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -1815,11 +2338,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -1830,6 +2355,7 @@
 
     private int number_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Number {
       get { if ((_hasBits0 & 1) != 0) { return number_; } else { return NumberDefaultValue; } }
       set {
@@ -1839,11 +2365,13 @@
     }
     /// <summary>Gets whether the "number" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNumber {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "number" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNumber() {
       _hasBits0 &= ~1;
     }
@@ -1854,6 +2382,7 @@
 
     private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label Label {
       get { if ((_hasBits0 & 2) != 0) { return label_; } else { return LabelDefaultValue; } }
       set {
@@ -1863,11 +2392,13 @@
     }
     /// <summary>Gets whether the "label" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasLabel {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "label" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearLabel() {
       _hasBits0 &= ~2;
     }
@@ -1882,6 +2413,7 @@
     /// are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type Type {
       get { if ((_hasBits0 & 4) != 0) { return type_; } else { return TypeDefaultValue; } }
       set {
@@ -1891,11 +2423,13 @@
     }
     /// <summary>Gets whether the "type" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasType {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "type" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearType() {
       _hasBits0 &= ~4;
     }
@@ -1913,6 +2447,7 @@
     /// namespace).
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string TypeName {
       get { return typeName_ ?? TypeNameDefaultValue; }
       set {
@@ -1921,11 +2456,13 @@
     }
     /// <summary>Gets whether the "type_name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasTypeName {
       get { return typeName_ != null; }
     }
     /// <summary>Clears the value of the "type_name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearTypeName() {
       typeName_ = null;
     }
@@ -1940,6 +2477,7 @@
     /// resolved in the same manner as type_name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Extendee {
       get { return extendee_ ?? ExtendeeDefaultValue; }
       set {
@@ -1948,11 +2486,13 @@
     }
     /// <summary>Gets whether the "extendee" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasExtendee {
       get { return extendee_ != null; }
     }
     /// <summary>Clears the value of the "extendee" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearExtendee() {
       extendee_ = null;
     }
@@ -1970,6 +2510,7 @@
     /// TODO(kenton):  Base-64 encode?
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string DefaultValue {
       get { return defaultValue_ ?? DefaultValueDefaultValue; }
       set {
@@ -1978,11 +2519,13 @@
     }
     /// <summary>Gets whether the "default_value" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDefaultValue {
       get { return defaultValue_ != null; }
     }
     /// <summary>Clears the value of the "default_value" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDefaultValue() {
       defaultValue_ = null;
     }
@@ -1997,6 +2540,7 @@
     /// list.  This field is a member of that oneof.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OneofIndex {
       get { if ((_hasBits0 & 8) != 0) { return oneofIndex_; } else { return OneofIndexDefaultValue; } }
       set {
@@ -2006,11 +2550,13 @@
     }
     /// <summary>Gets whether the "oneof_index" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOneofIndex {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "oneof_index" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOneofIndex() {
       _hasBits0 &= ~8;
     }
@@ -2027,6 +2573,7 @@
     /// it to camelCase.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JsonName {
       get { return jsonName_ ?? JsonNameDefaultValue; }
       set {
@@ -2035,11 +2582,13 @@
     }
     /// <summary>Gets whether the "json_name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJsonName {
       get { return jsonName_ != null; }
     }
     /// <summary>Clears the value of the "json_name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJsonName() {
       jsonName_ = null;
     }
@@ -2048,22 +2597,13 @@
     public const int OptionsFieldNumber = 8;
     private global::Google.Protobuf.Reflection.FieldOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.FieldOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     /// <summary>Field number for the "proto3_optional" field.</summary>
     public const int Proto3OptionalFieldNumber = 17;
@@ -2094,6 +2634,7 @@
     /// optional with `LABEL_OPTIONAL`.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Proto3Optional {
       get { if ((_hasBits0 & 16) != 0) { return proto3Optional_; } else { return Proto3OptionalDefaultValue; } }
       set {
@@ -2103,21 +2644,25 @@
     }
     /// <summary>Gets whether the "proto3_optional" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasProto3Optional {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "proto3_optional" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearProto3Optional() {
       _hasBits0 &= ~16;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FieldDescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FieldDescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2140,6 +2685,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
@@ -2151,7 +2697,7 @@
       if (HasDefaultValue) hash ^= DefaultValue.GetHashCode();
       if (HasOneofIndex) hash ^= OneofIndex.GetHashCode();
       if (HasJsonName) hash ^= JsonName.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
       if (HasProto3Optional) hash ^= Proto3Optional.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -2160,12 +2706,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -2194,7 +2745,7 @@
         output.WriteRawTag(58);
         output.WriteString(DefaultValue);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(66);
         output.WriteMessage(Options);
       }
@@ -2213,9 +2764,65 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (HasExtendee) {
+        output.WriteRawTag(18);
+        output.WriteString(Extendee);
+      }
+      if (HasNumber) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Number);
+      }
+      if (HasLabel) {
+        output.WriteRawTag(32);
+        output.WriteEnum((int) Label);
+      }
+      if (HasType) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) Type);
+      }
+      if (HasTypeName) {
+        output.WriteRawTag(50);
+        output.WriteString(TypeName);
+      }
+      if (HasDefaultValue) {
+        output.WriteRawTag(58);
+        output.WriteString(DefaultValue);
+      }
+      if (options_ != null) {
+        output.WriteRawTag(66);
+        output.WriteMessage(Options);
+      }
+      if (HasOneofIndex) {
+        output.WriteRawTag(72);
+        output.WriteInt32(OneofIndex);
+      }
+      if (HasJsonName) {
+        output.WriteRawTag(82);
+        output.WriteString(JsonName);
+      }
+      if (HasProto3Optional) {
+        output.WriteRawTag(136, 1);
+        output.WriteBool(Proto3Optional);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
@@ -2245,7 +2852,7 @@
       if (HasJsonName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (HasProto3Optional) {
@@ -2258,6 +2865,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FieldDescriptorProto other) {
       if (other == null) {
         return;
@@ -2289,8 +2897,8 @@
       if (other.HasJsonName) {
         JsonName = other.JsonName;
       }
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.FieldOptions();
         }
         Options.MergeFrom(other.Options);
@@ -2302,7 +2910,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2338,7 +2950,69 @@
             break;
           }
           case 66: {
-            if (!HasOptions) {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.FieldOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+          case 72: {
+            OneofIndex = input.ReadInt32();
+            break;
+          }
+          case 82: {
+            JsonName = input.ReadString();
+            break;
+          }
+          case 136: {
+            Proto3Optional = input.ReadBool();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Extendee = input.ReadString();
+            break;
+          }
+          case 24: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 32: {
+            Label = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) input.ReadEnum();
+            break;
+          }
+          case 40: {
+            Type = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type) input.ReadEnum();
+            break;
+          }
+          case 50: {
+            TypeName = input.ReadString();
+            break;
+          }
+          case 58: {
+            DefaultValue = input.ReadString();
+            break;
+          }
+          case 66: {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.FieldOptions();
             }
             input.ReadMessage(Options);
@@ -2359,10 +3033,12 @@
         }
       }
     }
+    #endif
 
     #region Nested types
     /// <summary>Container for nested types declared in the FieldDescriptorProto message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum Type {
         /// <summary>
@@ -2432,23 +3108,31 @@
   /// <summary>
   /// Describes a oneof.
   /// </summary>
-  public sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto> {
+  public sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneofDescriptorProto> _parser = new pb::MessageParser<OneofDescriptorProto>(() => new OneofDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneofDescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofDescriptorProto() {
       OnConstruction();
     }
@@ -2456,13 +3140,15 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofDescriptorProto(OneofDescriptorProto other) : this() {
       name_ = other.name_;
-      options_ = other.HasOptions ? other.options_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofDescriptorProto Clone() {
       return new OneofDescriptorProto(this);
     }
@@ -2473,6 +3159,7 @@
 
     private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -2481,11 +3168,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -2494,29 +3183,22 @@
     public const int OptionsFieldNumber = 2;
     private global::Google.Protobuf.Reflection.OneofOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.OneofOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneofDescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneofDescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2530,10 +3212,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -2541,32 +3224,57 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(18);
         output.WriteMessage(Options);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (options_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Options);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (_unknownFields != null) {
@@ -2576,6 +3284,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneofDescriptorProto other) {
       if (other == null) {
         return;
@@ -2583,8 +3292,8 @@
       if (other.HasName) {
         Name = other.Name;
       }
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.OneofOptions();
         }
         Options.MergeFrom(other.Options);
@@ -2593,7 +3302,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2605,7 +3318,33 @@
             break;
           }
           case 18: {
-            if (!HasOptions) {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.OneofOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.OneofOptions();
             }
             input.ReadMessage(Options);
@@ -2614,29 +3353,38 @@
         }
       }
     }
+    #endif
 
   }
 
   /// <summary>
   /// Describes an enum type.
   /// </summary>
-  public sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto> {
+  public sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<EnumDescriptorProto> _parser = new pb::MessageParser<EnumDescriptorProto>(() => new EnumDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<EnumDescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumDescriptorProto() {
       OnConstruction();
     }
@@ -2644,16 +3392,18 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumDescriptorProto(EnumDescriptorProto other) : this() {
       name_ = other.name_;
       value_ = other.value_.Clone();
-      options_ = other.HasOptions ? other.options_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
       reservedRange_ = other.reservedRange_.Clone();
       reservedName_ = other.reservedName_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumDescriptorProto Clone() {
       return new EnumDescriptorProto(this);
     }
@@ -2664,6 +3414,7 @@
 
     private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -2672,11 +3423,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -2687,6 +3440,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumValueDescriptorProto> value_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumValueDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumValueDescriptorProto> Value {
       get { return value_; }
     }
@@ -2695,22 +3449,13 @@
     public const int OptionsFieldNumber = 3;
     private global::Google.Protobuf.Reflection.EnumOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.EnumOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     /// <summary>Field number for the "reserved_range" field.</summary>
     public const int ReservedRangeFieldNumber = 4;
@@ -2723,6 +3468,7 @@
     /// overlap.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange> ReservedRange {
       get { return reservedRange_; }
     }
@@ -2737,16 +3483,19 @@
     /// be reserved once.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> ReservedName {
       get { return reservedName_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as EnumDescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(EnumDescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -2763,11 +3512,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
       hash ^= value_.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
       hash ^= reservedRange_.GetHashCode();
       hash ^= reservedName_.GetHashCode();
       if (_unknownFields != null) {
@@ -2777,18 +3527,23 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
       value_.WriteTo(output, _repeated_value_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(26);
         output.WriteMessage(Options);
       }
@@ -2797,16 +3552,39 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      value_.WriteTo(ref output, _repeated_value_codec);
+      if (options_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Options);
+      }
+      reservedRange_.WriteTo(ref output, _repeated_reservedRange_codec);
+      reservedName_.WriteTo(ref output, _repeated_reservedName_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
       size += value_.CalculateSize(_repeated_value_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
@@ -2818,6 +3596,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(EnumDescriptorProto other) {
       if (other == null) {
         return;
@@ -2826,8 +3605,8 @@
         Name = other.Name;
       }
       value_.Add(other.value_);
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.EnumOptions();
         }
         Options.MergeFrom(other.Options);
@@ -2838,7 +3617,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -2854,7 +3637,7 @@
             break;
           }
           case 26: {
-            if (!HasOptions) {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.EnumOptions();
             }
             input.ReadMessage(Options);
@@ -2870,11 +3653,51 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            value_.AddEntriesFrom(ref input, _repeated_value_codec);
+            break;
+          }
+          case 26: {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.EnumOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+          case 34: {
+            reservedRange_.AddEntriesFrom(ref input, _repeated_reservedRange_codec);
+            break;
+          }
+          case 42: {
+            reservedName_.AddEntriesFrom(ref input, _repeated_reservedName_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the EnumDescriptorProto message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// Range of reserved numeric values. Reserved values may not be used by
@@ -2884,24 +3707,32 @@
       /// is inclusive such that it can appropriately represent the entire int32
       /// domain.
       /// </summary>
-      public sealed partial class EnumReservedRange : pb::IMessage<EnumReservedRange> {
+      public sealed partial class EnumReservedRange : pb::IMessage<EnumReservedRange>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<EnumReservedRange> _parser = new pb::MessageParser<EnumReservedRange>(() => new EnumReservedRange());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<EnumReservedRange> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.EnumDescriptorProto.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public EnumReservedRange() {
           OnConstruction();
         }
@@ -2909,6 +3740,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public EnumReservedRange(EnumReservedRange other) : this() {
           _hasBits0 = other._hasBits0;
           start_ = other.start_;
@@ -2917,6 +3749,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public EnumReservedRange Clone() {
           return new EnumReservedRange(this);
         }
@@ -2930,6 +3763,7 @@
         /// Inclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Start {
           get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } }
           set {
@@ -2939,11 +3773,13 @@
         }
         /// <summary>Gets whether the "start" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasStart {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "start" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearStart() {
           _hasBits0 &= ~1;
         }
@@ -2957,6 +3793,7 @@
         /// Inclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int End {
           get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
@@ -2966,21 +3803,25 @@
         }
         /// <summary>Gets whether the "end" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasEnd {
           get { return (_hasBits0 & 2) != 0; }
         }
         /// <summary>Clears the value of the "end" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearEnd() {
           _hasBits0 &= ~2;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as EnumReservedRange);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(EnumReservedRange other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -2994,6 +3835,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasStart) hash ^= Start.GetHashCode();
@@ -3005,12 +3847,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasStart) {
             output.WriteRawTag(8);
             output.WriteInt32(Start);
@@ -3022,9 +3869,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasStart) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Start);
+          }
+          if (HasEnd) {
+            output.WriteRawTag(16);
+            output.WriteInt32(End);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasStart) {
@@ -3040,6 +3907,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(EnumReservedRange other) {
           if (other == null) {
             return;
@@ -3054,7 +3922,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -3071,8 +3943,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 8: {
+                Start = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                End = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -3083,24 +3979,32 @@
   /// <summary>
   /// Describes a value within an enum.
   /// </summary>
-  public sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto> {
+  public sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<EnumValueDescriptorProto> _parser = new pb::MessageParser<EnumValueDescriptorProto>(() => new EnumValueDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<EnumValueDescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[7]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValueDescriptorProto() {
       OnConstruction();
     }
@@ -3108,15 +4012,17 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValueDescriptorProto(EnumValueDescriptorProto other) : this() {
       _hasBits0 = other._hasBits0;
       name_ = other.name_;
       number_ = other.number_;
-      options_ = other.HasOptions ? other.options_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValueDescriptorProto Clone() {
       return new EnumValueDescriptorProto(this);
     }
@@ -3127,6 +4033,7 @@
 
     private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -3135,11 +4042,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -3150,6 +4059,7 @@
 
     private int number_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Number {
       get { if ((_hasBits0 & 1) != 0) { return number_; } else { return NumberDefaultValue; } }
       set {
@@ -3159,11 +4069,13 @@
     }
     /// <summary>Gets whether the "number" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNumber {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "number" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNumber() {
       _hasBits0 &= ~1;
     }
@@ -3172,29 +4084,22 @@
     public const int OptionsFieldNumber = 3;
     private global::Google.Protobuf.Reflection.EnumValueOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.EnumValueOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as EnumValueDescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(EnumValueDescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3209,11 +4114,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
       if (HasNumber) hash ^= Number.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -3221,12 +4127,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -3235,16 +4146,40 @@
         output.WriteRawTag(16);
         output.WriteInt32(Number);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(26);
         output.WriteMessage(Options);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (HasNumber) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Number);
+      }
+      if (options_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Options);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
@@ -3253,7 +4188,7 @@
       if (HasNumber) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (_unknownFields != null) {
@@ -3263,6 +4198,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(EnumValueDescriptorProto other) {
       if (other == null) {
         return;
@@ -3273,8 +4209,8 @@
       if (other.HasNumber) {
         Number = other.Number;
       }
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.EnumValueOptions();
         }
         Options.MergeFrom(other.Options);
@@ -3283,7 +4219,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3299,7 +4239,37 @@
             break;
           }
           case 26: {
-            if (!HasOptions) {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.EnumValueOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.EnumValueOptions();
             }
             input.ReadMessage(Options);
@@ -3308,29 +4278,38 @@
         }
       }
     }
+    #endif
 
   }
 
   /// <summary>
   /// Describes a service.
   /// </summary>
-  public sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto> {
+  public sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ServiceDescriptorProto> _parser = new pb::MessageParser<ServiceDescriptorProto>(() => new ServiceDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ServiceDescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[8]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ServiceDescriptorProto() {
       OnConstruction();
     }
@@ -3338,14 +4317,16 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ServiceDescriptorProto(ServiceDescriptorProto other) : this() {
       name_ = other.name_;
       method_ = other.method_.Clone();
-      options_ = other.HasOptions ? other.options_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ServiceDescriptorProto Clone() {
       return new ServiceDescriptorProto(this);
     }
@@ -3356,6 +4337,7 @@
 
     private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -3364,11 +4346,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -3379,6 +4363,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.MethodDescriptorProto> method_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.MethodDescriptorProto>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.MethodDescriptorProto> Method {
       get { return method_; }
     }
@@ -3387,29 +4372,22 @@
     public const int OptionsFieldNumber = 3;
     private global::Google.Protobuf.Reflection.ServiceOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.ServiceOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ServiceDescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ServiceDescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3424,11 +4402,12 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
       hash ^= method_.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -3436,34 +4415,60 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
       method_.WriteTo(output, _repeated_method_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(26);
         output.WriteMessage(Options);
       }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      method_.WriteTo(ref output, _repeated_method_codec);
+      if (options_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Options);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
       size += method_.CalculateSize(_repeated_method_codec);
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (_unknownFields != null) {
@@ -3473,6 +4478,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ServiceDescriptorProto other) {
       if (other == null) {
         return;
@@ -3481,8 +4487,8 @@
         Name = other.Name;
       }
       method_.Add(other.method_);
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.ServiceOptions();
         }
         Options.MergeFrom(other.Options);
@@ -3491,7 +4497,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3507,7 +4517,37 @@
             break;
           }
           case 26: {
-            if (!HasOptions) {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.ServiceOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            method_.AddEntriesFrom(ref input, _repeated_method_codec);
+            break;
+          }
+          case 26: {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.ServiceOptions();
             }
             input.ReadMessage(Options);
@@ -3516,30 +4556,39 @@
         }
       }
     }
+    #endif
 
   }
 
   /// <summary>
   /// Describes a method of a service.
   /// </summary>
-  public sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto> {
+  public sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MethodDescriptorProto> _parser = new pb::MessageParser<MethodDescriptorProto>(() => new MethodDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MethodDescriptorProto> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[9]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MethodDescriptorProto() {
       OnConstruction();
     }
@@ -3547,18 +4596,20 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MethodDescriptorProto(MethodDescriptorProto other) : this() {
       _hasBits0 = other._hasBits0;
       name_ = other.name_;
       inputType_ = other.inputType_;
       outputType_ = other.outputType_;
-      options_ = other.HasOptions ? other.options_.Clone() : null;
+      options_ = other.options_ != null ? other.options_.Clone() : null;
       clientStreaming_ = other.clientStreaming_;
       serverStreaming_ = other.serverStreaming_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MethodDescriptorProto Clone() {
       return new MethodDescriptorProto(this);
     }
@@ -3569,6 +4620,7 @@
 
     private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_ ?? NameDefaultValue; }
       set {
@@ -3577,11 +4629,13 @@
     }
     /// <summary>Gets whether the "name" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasName {
       get { return name_ != null; }
     }
     /// <summary>Clears the value of the "name" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearName() {
       name_ = null;
     }
@@ -3596,6 +4650,7 @@
     /// FieldDescriptorProto.type_name, but must refer to a message type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string InputType {
       get { return inputType_ ?? InputTypeDefaultValue; }
       set {
@@ -3604,11 +4659,13 @@
     }
     /// <summary>Gets whether the "input_type" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasInputType {
       get { return inputType_ != null; }
     }
     /// <summary>Clears the value of the "input_type" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearInputType() {
       inputType_ = null;
     }
@@ -3619,6 +4676,7 @@
 
     private string outputType_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string OutputType {
       get { return outputType_ ?? OutputTypeDefaultValue; }
       set {
@@ -3627,11 +4685,13 @@
     }
     /// <summary>Gets whether the "output_type" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOutputType {
       get { return outputType_ != null; }
     }
     /// <summary>Clears the value of the "output_type" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOutputType() {
       outputType_ = null;
     }
@@ -3640,22 +4700,13 @@
     public const int OptionsFieldNumber = 4;
     private global::Google.Protobuf.Reflection.MethodOptions options_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.MethodOptions Options {
       get { return options_; }
       set {
         options_ = value;
       }
     }
-    /// <summary>Gets whether the options field is set</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool HasOptions {
-      get { return options_ != null; }
-    }
-    /// <summary>Clears the value of the options field</summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void ClearOptions() {
-      options_ = null;
-    }
 
     /// <summary>Field number for the "client_streaming" field.</summary>
     public const int ClientStreamingFieldNumber = 5;
@@ -3666,6 +4717,7 @@
     /// Identifies if client streams multiple client messages
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool ClientStreaming {
       get { if ((_hasBits0 & 1) != 0) { return clientStreaming_; } else { return ClientStreamingDefaultValue; } }
       set {
@@ -3675,11 +4727,13 @@
     }
     /// <summary>Gets whether the "client_streaming" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasClientStreaming {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "client_streaming" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearClientStreaming() {
       _hasBits0 &= ~1;
     }
@@ -3693,6 +4747,7 @@
     /// Identifies if server streams multiple server messages
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool ServerStreaming {
       get { if ((_hasBits0 & 2) != 0) { return serverStreaming_; } else { return ServerStreamingDefaultValue; } }
       set {
@@ -3702,21 +4757,25 @@
     }
     /// <summary>Gets whether the "server_streaming" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasServerStreaming {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "server_streaming" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearServerStreaming() {
       _hasBits0 &= ~2;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MethodDescriptorProto);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MethodDescriptorProto other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -3734,12 +4793,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasName) hash ^= Name.GetHashCode();
       if (HasInputType) hash ^= InputType.GetHashCode();
       if (HasOutputType) hash ^= OutputType.GetHashCode();
-      if (HasOptions) hash ^= Options.GetHashCode();
+      if (options_ != null) hash ^= Options.GetHashCode();
       if (HasClientStreaming) hash ^= ClientStreaming.GetHashCode();
       if (HasServerStreaming) hash ^= ServerStreaming.GetHashCode();
       if (_unknownFields != null) {
@@ -3749,12 +4809,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -3767,7 +4832,7 @@
         output.WriteRawTag(26);
         output.WriteString(OutputType);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         output.WriteRawTag(34);
         output.WriteMessage(Options);
       }
@@ -3782,9 +4847,45 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasName) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (HasInputType) {
+        output.WriteRawTag(18);
+        output.WriteString(InputType);
+      }
+      if (HasOutputType) {
+        output.WriteRawTag(26);
+        output.WriteString(OutputType);
+      }
+      if (options_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(Options);
+      }
+      if (HasClientStreaming) {
+        output.WriteRawTag(40);
+        output.WriteBool(ClientStreaming);
+      }
+      if (HasServerStreaming) {
+        output.WriteRawTag(48);
+        output.WriteBool(ServerStreaming);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasName) {
@@ -3796,7 +4897,7 @@
       if (HasOutputType) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(OutputType);
       }
-      if (HasOptions) {
+      if (options_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (HasClientStreaming) {
@@ -3812,6 +4913,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MethodDescriptorProto other) {
       if (other == null) {
         return;
@@ -3825,8 +4927,8 @@
       if (other.HasOutputType) {
         OutputType = other.OutputType;
       }
-      if (other.HasOptions) {
-        if (!HasOptions) {
+      if (other.options_ != null) {
+        if (options_ == null) {
           Options = new global::Google.Protobuf.Reflection.MethodOptions();
         }
         Options.MergeFrom(other.Options);
@@ -3841,7 +4943,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -3861,7 +4967,49 @@
             break;
           }
           case 34: {
-            if (!HasOptions) {
+            if (options_ == null) {
+              Options = new global::Google.Protobuf.Reflection.MethodOptions();
+            }
+            input.ReadMessage(Options);
+            break;
+          }
+          case 40: {
+            ClientStreaming = input.ReadBool();
+            break;
+          }
+          case 48: {
+            ServerStreaming = input.ReadBool();
+            break;
+          }
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            InputType = input.ReadString();
+            break;
+          }
+          case 26: {
+            OutputType = input.ReadString();
+            break;
+          }
+          case 34: {
+            if (options_ == null) {
               Options = new global::Google.Protobuf.Reflection.MethodOptions();
             }
             input.ReadMessage(Options);
@@ -3878,29 +5026,38 @@
         }
       }
     }
+    #endif
 
   }
 
-  public sealed partial class FileOptions : pb::IExtendableMessage<FileOptions> {
+  public sealed partial class FileOptions : pb::IExtendableMessage<FileOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FileOptions> _parser = new pb::MessageParser<FileOptions>(() => new FileOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<FileOptions> _extensions;
     private pb::ExtensionSet<FileOptions> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FileOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[10]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileOptions() {
       OnConstruction();
     }
@@ -3908,6 +5065,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileOptions(FileOptions other) : this() {
       _hasBits0 = other._hasBits0;
       javaPackage_ = other.javaPackage_;
@@ -3936,6 +5094,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FileOptions Clone() {
       return new FileOptions(this);
     }
@@ -3952,6 +5111,7 @@
     /// domain names.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JavaPackage {
       get { return javaPackage_ ?? JavaPackageDefaultValue; }
       set {
@@ -3960,11 +5120,13 @@
     }
     /// <summary>Gets whether the "java_package" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJavaPackage {
       get { return javaPackage_ != null; }
     }
     /// <summary>Clears the value of the "java_package" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJavaPackage() {
       javaPackage_ = null;
     }
@@ -3975,13 +5137,14 @@
 
     private string javaOuterClassname_;
     /// <summary>
-    /// If set, all the classes from the .proto file are wrapped in a single
-    /// outer class with the given name.  This applies to both Proto1
-    /// (equivalent to the old "--one_java_file" option) and Proto2 (where
-    /// a .proto always translates to a single class, but you may want to
-    /// explicitly choose the class name).
+    /// Controls the name of the wrapper Java class generated for the .proto file.
+    /// That class will always contain the .proto file's getDescriptor() method as
+    /// well as any top-level extensions defined in the .proto file.
+    /// If java_multiple_files is disabled, then all the other classes from the
+    /// .proto file will be nested inside the single wrapper outer class.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JavaOuterClassname {
       get { return javaOuterClassname_ ?? JavaOuterClassnameDefaultValue; }
       set {
@@ -3990,11 +5153,13 @@
     }
     /// <summary>Gets whether the "java_outer_classname" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJavaOuterClassname {
       get { return javaOuterClassname_ != null; }
     }
     /// <summary>Clears the value of the "java_outer_classname" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJavaOuterClassname() {
       javaOuterClassname_ = null;
     }
@@ -4005,14 +5170,15 @@
 
     private bool javaMultipleFiles_;
     /// <summary>
-    /// If set true, then the Java code generator will generate a separate .java
+    /// If enabled, then the Java code generator will generate a separate .java
     /// file for each top-level message, enum, and service defined in the .proto
-    /// file.  Thus, these types will *not* be nested inside the outer class
-    /// named by java_outer_classname.  However, the outer class will still be
+    /// file.  Thus, these types will *not* be nested inside the wrapper class
+    /// named by java_outer_classname.  However, the wrapper class will still be
     /// generated to contain the file's getDescriptor() method as well as any
     /// top-level extensions defined in the file.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool JavaMultipleFiles {
       get { if ((_hasBits0 & 2) != 0) { return javaMultipleFiles_; } else { return JavaMultipleFilesDefaultValue; } }
       set {
@@ -4022,11 +5188,13 @@
     }
     /// <summary>Gets whether the "java_multiple_files" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJavaMultipleFiles {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "java_multiple_files" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJavaMultipleFiles() {
       _hasBits0 &= ~2;
     }
@@ -4041,6 +5209,7 @@
     /// </summary>
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool JavaGenerateEqualsAndHash {
       get { if ((_hasBits0 & 32) != 0) { return javaGenerateEqualsAndHash_; } else { return JavaGenerateEqualsAndHashDefaultValue; } }
       set {
@@ -4051,12 +5220,14 @@
     /// <summary>Gets whether the "java_generate_equals_and_hash" field is set</summary>
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJavaGenerateEqualsAndHash {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "java_generate_equals_and_hash" field</summary>
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJavaGenerateEqualsAndHash() {
       _hasBits0 &= ~32;
     }
@@ -4075,6 +5246,7 @@
     /// This option has no effect on when used with the lite runtime.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool JavaStringCheckUtf8 {
       get { if ((_hasBits0 & 128) != 0) { return javaStringCheckUtf8_; } else { return JavaStringCheckUtf8DefaultValue; } }
       set {
@@ -4084,11 +5256,13 @@
     }
     /// <summary>Gets whether the "java_string_check_utf8" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJavaStringCheckUtf8 {
       get { return (_hasBits0 & 128) != 0; }
     }
     /// <summary>Clears the value of the "java_string_check_utf8" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJavaStringCheckUtf8() {
       _hasBits0 &= ~128;
     }
@@ -4099,6 +5273,7 @@
 
     private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode OptimizeFor {
       get { if ((_hasBits0 & 1) != 0) { return optimizeFor_; } else { return OptimizeForDefaultValue; } }
       set {
@@ -4108,11 +5283,13 @@
     }
     /// <summary>Gets whether the "optimize_for" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasOptimizeFor {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "optimize_for" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearOptimizeFor() {
       _hasBits0 &= ~1;
     }
@@ -4130,6 +5307,7 @@
     ///   - Otherwise, the basename of the .proto file, without extension.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string GoPackage {
       get { return goPackage_ ?? GoPackageDefaultValue; }
       set {
@@ -4138,11 +5316,13 @@
     }
     /// <summary>Gets whether the "go_package" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasGoPackage {
       get { return goPackage_ != null; }
     }
     /// <summary>Clears the value of the "go_package" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearGoPackage() {
       goPackage_ = null;
     }
@@ -4165,6 +5345,7 @@
     /// explicitly set them to true.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool CcGenericServices {
       get { if ((_hasBits0 & 4) != 0) { return ccGenericServices_; } else { return CcGenericServicesDefaultValue; } }
       set {
@@ -4174,11 +5355,13 @@
     }
     /// <summary>Gets whether the "cc_generic_services" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasCcGenericServices {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "cc_generic_services" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearCcGenericServices() {
       _hasBits0 &= ~4;
     }
@@ -4189,6 +5372,7 @@
 
     private bool javaGenericServices_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool JavaGenericServices {
       get { if ((_hasBits0 & 8) != 0) { return javaGenericServices_; } else { return JavaGenericServicesDefaultValue; } }
       set {
@@ -4198,11 +5382,13 @@
     }
     /// <summary>Gets whether the "java_generic_services" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJavaGenericServices {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "java_generic_services" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJavaGenericServices() {
       _hasBits0 &= ~8;
     }
@@ -4213,6 +5399,7 @@
 
     private bool pyGenericServices_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool PyGenericServices {
       get { if ((_hasBits0 & 16) != 0) { return pyGenericServices_; } else { return PyGenericServicesDefaultValue; } }
       set {
@@ -4222,11 +5409,13 @@
     }
     /// <summary>Gets whether the "py_generic_services" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPyGenericServices {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "py_generic_services" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPyGenericServices() {
       _hasBits0 &= ~16;
     }
@@ -4237,6 +5426,7 @@
 
     private bool phpGenericServices_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool PhpGenericServices {
       get { if ((_hasBits0 & 512) != 0) { return phpGenericServices_; } else { return PhpGenericServicesDefaultValue; } }
       set {
@@ -4246,11 +5436,13 @@
     }
     /// <summary>Gets whether the "php_generic_services" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPhpGenericServices {
       get { return (_hasBits0 & 512) != 0; }
     }
     /// <summary>Clears the value of the "php_generic_services" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPhpGenericServices() {
       _hasBits0 &= ~512;
     }
@@ -4267,6 +5459,7 @@
     /// least, this is a formalization for deprecating files.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Deprecated {
       get { if ((_hasBits0 & 64) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
@@ -4276,11 +5469,13 @@
     }
     /// <summary>Gets whether the "deprecated" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecated {
       get { return (_hasBits0 & 64) != 0; }
     }
     /// <summary>Clears the value of the "deprecated" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecated() {
       _hasBits0 &= ~64;
     }
@@ -4295,6 +5490,7 @@
     /// only to generated classes for C++.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool CcEnableArenas {
       get { if ((_hasBits0 & 256) != 0) { return ccEnableArenas_; } else { return CcEnableArenasDefaultValue; } }
       set {
@@ -4304,11 +5500,13 @@
     }
     /// <summary>Gets whether the "cc_enable_arenas" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasCcEnableArenas {
       get { return (_hasBits0 & 256) != 0; }
     }
     /// <summary>Clears the value of the "cc_enable_arenas" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearCcEnableArenas() {
       _hasBits0 &= ~256;
     }
@@ -4323,6 +5521,7 @@
     /// generated classes from this .proto. There is no default.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string ObjcClassPrefix {
       get { return objcClassPrefix_ ?? ObjcClassPrefixDefaultValue; }
       set {
@@ -4331,11 +5530,13 @@
     }
     /// <summary>Gets whether the "objc_class_prefix" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasObjcClassPrefix {
       get { return objcClassPrefix_ != null; }
     }
     /// <summary>Clears the value of the "objc_class_prefix" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearObjcClassPrefix() {
       objcClassPrefix_ = null;
     }
@@ -4349,6 +5550,7 @@
     /// Namespace for generated classes; defaults to the package.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string CsharpNamespace {
       get { return csharpNamespace_ ?? CsharpNamespaceDefaultValue; }
       set {
@@ -4357,11 +5559,13 @@
     }
     /// <summary>Gets whether the "csharp_namespace" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasCsharpNamespace {
       get { return csharpNamespace_ != null; }
     }
     /// <summary>Clears the value of the "csharp_namespace" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearCsharpNamespace() {
       csharpNamespace_ = null;
     }
@@ -4378,6 +5582,7 @@
     /// to prefix the types/symbols defined.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string SwiftPrefix {
       get { return swiftPrefix_ ?? SwiftPrefixDefaultValue; }
       set {
@@ -4386,11 +5591,13 @@
     }
     /// <summary>Gets whether the "swift_prefix" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasSwiftPrefix {
       get { return swiftPrefix_ != null; }
     }
     /// <summary>Clears the value of the "swift_prefix" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearSwiftPrefix() {
       swiftPrefix_ = null;
     }
@@ -4405,6 +5612,7 @@
     /// from this .proto. Default is empty.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string PhpClassPrefix {
       get { return phpClassPrefix_ ?? PhpClassPrefixDefaultValue; }
       set {
@@ -4413,11 +5621,13 @@
     }
     /// <summary>Gets whether the "php_class_prefix" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPhpClassPrefix {
       get { return phpClassPrefix_ != null; }
     }
     /// <summary>Clears the value of the "php_class_prefix" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPhpClassPrefix() {
       phpClassPrefix_ = null;
     }
@@ -4433,6 +5643,7 @@
     /// determining the namespace.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string PhpNamespace {
       get { return phpNamespace_ ?? PhpNamespaceDefaultValue; }
       set {
@@ -4441,11 +5652,13 @@
     }
     /// <summary>Gets whether the "php_namespace" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPhpNamespace {
       get { return phpNamespace_ != null; }
     }
     /// <summary>Clears the value of the "php_namespace" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPhpNamespace() {
       phpNamespace_ = null;
     }
@@ -4461,6 +5674,7 @@
     /// used for determining the namespace.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string PhpMetadataNamespace {
       get { return phpMetadataNamespace_ ?? PhpMetadataNamespaceDefaultValue; }
       set {
@@ -4469,11 +5683,13 @@
     }
     /// <summary>Gets whether the "php_metadata_namespace" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPhpMetadataNamespace {
       get { return phpMetadataNamespace_ != null; }
     }
     /// <summary>Clears the value of the "php_metadata_namespace" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPhpMetadataNamespace() {
       phpMetadataNamespace_ = null;
     }
@@ -4489,6 +5705,7 @@
     /// determining the ruby package.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string RubyPackage {
       get { return rubyPackage_ ?? RubyPackageDefaultValue; }
       set {
@@ -4497,11 +5714,13 @@
     }
     /// <summary>Gets whether the "ruby_package" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasRubyPackage {
       get { return rubyPackage_ != null; }
     }
     /// <summary>Clears the value of the "ruby_package" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearRubyPackage() {
       rubyPackage_ = null;
     }
@@ -4516,16 +5735,19 @@
     /// See the documentation for the "Options" section above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FileOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FileOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -4561,6 +5783,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasJavaPackage) hash ^= JavaPackage.GetHashCode();
@@ -4594,12 +5817,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasJavaPackage) {
         output.WriteRawTag(10);
         output.WriteString(JavaPackage);
@@ -4687,9 +5915,105 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasJavaPackage) {
+        output.WriteRawTag(10);
+        output.WriteString(JavaPackage);
+      }
+      if (HasJavaOuterClassname) {
+        output.WriteRawTag(66);
+        output.WriteString(JavaOuterClassname);
+      }
+      if (HasOptimizeFor) {
+        output.WriteRawTag(72);
+        output.WriteEnum((int) OptimizeFor);
+      }
+      if (HasJavaMultipleFiles) {
+        output.WriteRawTag(80);
+        output.WriteBool(JavaMultipleFiles);
+      }
+      if (HasGoPackage) {
+        output.WriteRawTag(90);
+        output.WriteString(GoPackage);
+      }
+      if (HasCcGenericServices) {
+        output.WriteRawTag(128, 1);
+        output.WriteBool(CcGenericServices);
+      }
+      if (HasJavaGenericServices) {
+        output.WriteRawTag(136, 1);
+        output.WriteBool(JavaGenericServices);
+      }
+      if (HasPyGenericServices) {
+        output.WriteRawTag(144, 1);
+        output.WriteBool(PyGenericServices);
+      }
+      if (HasJavaGenerateEqualsAndHash) {
+        output.WriteRawTag(160, 1);
+        output.WriteBool(JavaGenerateEqualsAndHash);
+      }
+      if (HasDeprecated) {
+        output.WriteRawTag(184, 1);
+        output.WriteBool(Deprecated);
+      }
+      if (HasJavaStringCheckUtf8) {
+        output.WriteRawTag(216, 1);
+        output.WriteBool(JavaStringCheckUtf8);
+      }
+      if (HasCcEnableArenas) {
+        output.WriteRawTag(248, 1);
+        output.WriteBool(CcEnableArenas);
+      }
+      if (HasObjcClassPrefix) {
+        output.WriteRawTag(162, 2);
+        output.WriteString(ObjcClassPrefix);
+      }
+      if (HasCsharpNamespace) {
+        output.WriteRawTag(170, 2);
+        output.WriteString(CsharpNamespace);
+      }
+      if (HasSwiftPrefix) {
+        output.WriteRawTag(186, 2);
+        output.WriteString(SwiftPrefix);
+      }
+      if (HasPhpClassPrefix) {
+        output.WriteRawTag(194, 2);
+        output.WriteString(PhpClassPrefix);
+      }
+      if (HasPhpNamespace) {
+        output.WriteRawTag(202, 2);
+        output.WriteString(PhpNamespace);
+      }
+      if (HasPhpGenericServices) {
+        output.WriteRawTag(208, 2);
+        output.WriteBool(PhpGenericServices);
+      }
+      if (HasPhpMetadataNamespace) {
+        output.WriteRawTag(226, 2);
+        output.WriteString(PhpMetadataNamespace);
+      }
+      if (HasRubyPackage) {
+        output.WriteRawTag(234, 2);
+        output.WriteString(RubyPackage);
+      }
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasJavaPackage) {
@@ -4763,6 +6087,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FileOptions other) {
       if (other == null) {
         return;
@@ -4833,7 +6158,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -4928,8 +6257,110 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 10: {
+            JavaPackage = input.ReadString();
+            break;
+          }
+          case 66: {
+            JavaOuterClassname = input.ReadString();
+            break;
+          }
+          case 72: {
+            OptimizeFor = (global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) input.ReadEnum();
+            break;
+          }
+          case 80: {
+            JavaMultipleFiles = input.ReadBool();
+            break;
+          }
+          case 90: {
+            GoPackage = input.ReadString();
+            break;
+          }
+          case 128: {
+            CcGenericServices = input.ReadBool();
+            break;
+          }
+          case 136: {
+            JavaGenericServices = input.ReadBool();
+            break;
+          }
+          case 144: {
+            PyGenericServices = input.ReadBool();
+            break;
+          }
+          case 160: {
+            JavaGenerateEqualsAndHash = input.ReadBool();
+            break;
+          }
+          case 184: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 216: {
+            JavaStringCheckUtf8 = input.ReadBool();
+            break;
+          }
+          case 248: {
+            CcEnableArenas = input.ReadBool();
+            break;
+          }
+          case 290: {
+            ObjcClassPrefix = input.ReadString();
+            break;
+          }
+          case 298: {
+            CsharpNamespace = input.ReadString();
+            break;
+          }
+          case 314: {
+            SwiftPrefix = input.ReadString();
+            break;
+          }
+          case 322: {
+            PhpClassPrefix = input.ReadString();
+            break;
+          }
+          case 330: {
+            PhpNamespace = input.ReadString();
+            break;
+          }
+          case 336: {
+            PhpGenericServices = input.ReadBool();
+            break;
+          }
+          case 354: {
+            PhpMetadataNamespace = input.ReadString();
+            break;
+          }
+          case 362: {
+            RubyPackage = input.ReadString();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<FileOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -4955,6 +6386,7 @@
     #region Nested types
     /// <summary>Container for nested types declared in the FileOptions message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// Generated classes can be optimized for speed or code size.
@@ -4979,26 +6411,34 @@
 
   }
 
-  public sealed partial class MessageOptions : pb::IExtendableMessage<MessageOptions> {
+  public sealed partial class MessageOptions : pb::IExtendableMessage<MessageOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MessageOptions> _parser = new pb::MessageParser<MessageOptions>(() => new MessageOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<MessageOptions> _extensions;
     private pb::ExtensionSet<MessageOptions> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MessageOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[11]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageOptions() {
       OnConstruction();
     }
@@ -5006,6 +6446,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageOptions(MessageOptions other) : this() {
       _hasBits0 = other._hasBits0;
       messageSetWireFormat_ = other.messageSetWireFormat_;
@@ -5018,6 +6459,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MessageOptions Clone() {
       return new MessageOptions(this);
     }
@@ -5048,6 +6490,7 @@
     /// the protocol compiler.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool MessageSetWireFormat {
       get { if ((_hasBits0 & 1) != 0) { return messageSetWireFormat_; } else { return MessageSetWireFormatDefaultValue; } }
       set {
@@ -5057,11 +6500,13 @@
     }
     /// <summary>Gets whether the "message_set_wire_format" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasMessageSetWireFormat {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "message_set_wire_format" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearMessageSetWireFormat() {
       _hasBits0 &= ~1;
     }
@@ -5077,6 +6522,7 @@
     /// from proto1 easier; new code should avoid fields named "descriptor".
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool NoStandardDescriptorAccessor {
       get { if ((_hasBits0 & 2) != 0) { return noStandardDescriptorAccessor_; } else { return NoStandardDescriptorAccessorDefaultValue; } }
       set {
@@ -5086,11 +6532,13 @@
     }
     /// <summary>Gets whether the "no_standard_descriptor_accessor" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNoStandardDescriptorAccessor {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "no_standard_descriptor_accessor" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNoStandardDescriptorAccessor() {
       _hasBits0 &= ~2;
     }
@@ -5107,6 +6555,7 @@
     /// this is a formalization for deprecating messages.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Deprecated {
       get { if ((_hasBits0 & 4) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
@@ -5116,11 +6565,13 @@
     }
     /// <summary>Gets whether the "deprecated" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecated {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "deprecated" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecated() {
       _hasBits0 &= ~4;
     }
@@ -5154,6 +6605,7 @@
     /// parser.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool MapEntry {
       get { if ((_hasBits0 & 8) != 0) { return mapEntry_; } else { return MapEntryDefaultValue; } }
       set {
@@ -5163,11 +6615,13 @@
     }
     /// <summary>Gets whether the "map_entry" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasMapEntry {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "map_entry" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearMapEntry() {
       _hasBits0 &= ~8;
     }
@@ -5181,16 +6635,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MessageOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MessageOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5210,6 +6667,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasMessageSetWireFormat) hash ^= MessageSetWireFormat.GetHashCode();
@@ -5227,12 +6685,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasMessageSetWireFormat) {
         output.WriteRawTag(8);
         output.WriteBool(MessageSetWireFormat);
@@ -5256,9 +6719,41 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasMessageSetWireFormat) {
+        output.WriteRawTag(8);
+        output.WriteBool(MessageSetWireFormat);
+      }
+      if (HasNoStandardDescriptorAccessor) {
+        output.WriteRawTag(16);
+        output.WriteBool(NoStandardDescriptorAccessor);
+      }
+      if (HasDeprecated) {
+        output.WriteRawTag(24);
+        output.WriteBool(Deprecated);
+      }
+      if (HasMapEntry) {
+        output.WriteRawTag(56);
+        output.WriteBool(MapEntry);
+      }
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasMessageSetWireFormat) {
@@ -5284,6 +6779,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MessageOptions other) {
       if (other == null) {
         return;
@@ -5306,7 +6802,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5337,8 +6837,46 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            MessageSetWireFormat = input.ReadBool();
+            break;
+          }
+          case 16: {
+            NoStandardDescriptorAccessor = input.ReadBool();
+            break;
+          }
+          case 24: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 56: {
+            MapEntry = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<MessageOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -5363,26 +6901,34 @@
 
   }
 
-  public sealed partial class FieldOptions : pb::IExtendableMessage<FieldOptions> {
+  public sealed partial class FieldOptions : pb::IExtendableMessage<FieldOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FieldOptions> _parser = new pb::MessageParser<FieldOptions>(() => new FieldOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<FieldOptions> _extensions;
     private pb::ExtensionSet<FieldOptions> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FieldOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[12]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldOptions() {
       OnConstruction();
     }
@@ -5390,6 +6936,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldOptions(FieldOptions other) : this() {
       _hasBits0 = other._hasBits0;
       ctype_ = other.ctype_;
@@ -5404,6 +6951,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldOptions Clone() {
       return new FieldOptions(this);
     }
@@ -5420,6 +6968,7 @@
     /// release -- sorry, we'll try to include it in a future version!
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.FieldOptions.Types.CType Ctype {
       get { if ((_hasBits0 & 1) != 0) { return ctype_; } else { return CtypeDefaultValue; } }
       set {
@@ -5429,11 +6978,13 @@
     }
     /// <summary>Gets whether the "ctype" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasCtype {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "ctype" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearCtype() {
       _hasBits0 &= ~1;
     }
@@ -5451,6 +7002,7 @@
     /// false will avoid using packed encoding.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Packed {
       get { if ((_hasBits0 & 2) != 0) { return packed_; } else { return PackedDefaultValue; } }
       set {
@@ -5460,11 +7012,13 @@
     }
     /// <summary>Gets whether the "packed" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPacked {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "packed" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPacked() {
       _hasBits0 &= ~2;
     }
@@ -5488,6 +7042,7 @@
     /// goog.math.Integer.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.FieldOptions.Types.JSType Jstype {
       get { if ((_hasBits0 & 16) != 0) { return jstype_; } else { return JstypeDefaultValue; } }
       set {
@@ -5497,11 +7052,13 @@
     }
     /// <summary>Gets whether the "jstype" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasJstype {
       get { return (_hasBits0 & 16) != 0; }
     }
     /// <summary>Clears the value of the "jstype" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearJstype() {
       _hasBits0 &= ~16;
     }
@@ -5541,6 +7098,7 @@
     /// been parsed.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Lazy {
       get { if ((_hasBits0 & 8) != 0) { return lazy_; } else { return LazyDefaultValue; } }
       set {
@@ -5550,11 +7108,13 @@
     }
     /// <summary>Gets whether the "lazy" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasLazy {
       get { return (_hasBits0 & 8) != 0; }
     }
     /// <summary>Clears the value of the "lazy" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearLazy() {
       _hasBits0 &= ~8;
     }
@@ -5571,6 +7131,7 @@
     /// is a formalization for deprecating fields.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Deprecated {
       get { if ((_hasBits0 & 4) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
@@ -5580,11 +7141,13 @@
     }
     /// <summary>Gets whether the "deprecated" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecated {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "deprecated" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecated() {
       _hasBits0 &= ~4;
     }
@@ -5598,6 +7161,7 @@
     /// For Google-internal migration only. Do not use.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Weak {
       get { if ((_hasBits0 & 32) != 0) { return weak_; } else { return WeakDefaultValue; } }
       set {
@@ -5607,11 +7171,13 @@
     }
     /// <summary>Gets whether the "weak" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasWeak {
       get { return (_hasBits0 & 32) != 0; }
     }
     /// <summary>Clears the value of the "weak" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearWeak() {
       _hasBits0 &= ~32;
     }
@@ -5625,16 +7191,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FieldOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FieldOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5656,6 +7225,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasCtype) hash ^= Ctype.GetHashCode();
@@ -5675,12 +7245,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasCtype) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Ctype);
@@ -5712,9 +7287,49 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasCtype) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Ctype);
+      }
+      if (HasPacked) {
+        output.WriteRawTag(16);
+        output.WriteBool(Packed);
+      }
+      if (HasDeprecated) {
+        output.WriteRawTag(24);
+        output.WriteBool(Deprecated);
+      }
+      if (HasLazy) {
+        output.WriteRawTag(40);
+        output.WriteBool(Lazy);
+      }
+      if (HasJstype) {
+        output.WriteRawTag(48);
+        output.WriteEnum((int) Jstype);
+      }
+      if (HasWeak) {
+        output.WriteRawTag(80);
+        output.WriteBool(Weak);
+      }
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasCtype) {
@@ -5746,6 +7361,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FieldOptions other) {
       if (other == null) {
         return;
@@ -5774,7 +7390,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -5813,8 +7433,54 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            Ctype = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum();
+            break;
+          }
+          case 16: {
+            Packed = input.ReadBool();
+            break;
+          }
+          case 24: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 40: {
+            Lazy = input.ReadBool();
+            break;
+          }
+          case 48: {
+            Jstype = (global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) input.ReadEnum();
+            break;
+          }
+          case 80: {
+            Weak = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<FieldOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -5840,6 +7506,7 @@
     #region Nested types
     /// <summary>Container for nested types declared in the FieldOptions message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       public enum CType {
         /// <summary>
@@ -5870,25 +7537,33 @@
 
   }
 
-  public sealed partial class OneofOptions : pb::IExtendableMessage<OneofOptions> {
+  public sealed partial class OneofOptions : pb::IExtendableMessage<OneofOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<OneofOptions> _parser = new pb::MessageParser<OneofOptions>(() => new OneofOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<OneofOptions> _extensions;
     private pb::ExtensionSet<OneofOptions> _Extensions { get { return _extensions; } }
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<OneofOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[13]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofOptions() {
       OnConstruction();
     }
@@ -5896,6 +7571,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofOptions(OneofOptions other) : this() {
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -5903,6 +7579,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public OneofOptions Clone() {
       return new OneofOptions(this);
     }
@@ -5916,16 +7593,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as OneofOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(OneofOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -5941,6 +7621,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= uninterpretedOption_.GetHashCode();
@@ -5954,12 +7635,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
       if (_extensions != null) {
         _extensions.WriteTo(output);
@@ -5967,9 +7653,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -5983,6 +7685,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(OneofOptions other) {
       if (other == null) {
         return;
@@ -5993,7 +7696,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6008,8 +7715,30 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<OneofOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -6034,26 +7763,34 @@
 
   }
 
-  public sealed partial class EnumOptions : pb::IExtendableMessage<EnumOptions> {
+  public sealed partial class EnumOptions : pb::IExtendableMessage<EnumOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<EnumOptions> _parser = new pb::MessageParser<EnumOptions>(() => new EnumOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<EnumOptions> _extensions;
     private pb::ExtensionSet<EnumOptions> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<EnumOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[14]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumOptions() {
       OnConstruction();
     }
@@ -6061,6 +7798,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumOptions(EnumOptions other) : this() {
       _hasBits0 = other._hasBits0;
       allowAlias_ = other.allowAlias_;
@@ -6071,6 +7809,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumOptions Clone() {
       return new EnumOptions(this);
     }
@@ -6085,6 +7824,7 @@
     /// value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool AllowAlias {
       get { if ((_hasBits0 & 1) != 0) { return allowAlias_; } else { return AllowAliasDefaultValue; } }
       set {
@@ -6094,11 +7834,13 @@
     }
     /// <summary>Gets whether the "allow_alias" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasAllowAlias {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "allow_alias" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearAllowAlias() {
       _hasBits0 &= ~1;
     }
@@ -6115,6 +7857,7 @@
     /// is a formalization for deprecating enums.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Deprecated {
       get { if ((_hasBits0 & 2) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
@@ -6124,11 +7867,13 @@
     }
     /// <summary>Gets whether the "deprecated" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecated {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "deprecated" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecated() {
       _hasBits0 &= ~2;
     }
@@ -6142,16 +7887,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as EnumOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(EnumOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6169,6 +7917,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasAllowAlias) hash ^= AllowAlias.GetHashCode();
@@ -6184,12 +7933,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasAllowAlias) {
         output.WriteRawTag(16);
         output.WriteBool(AllowAlias);
@@ -6205,9 +7959,33 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasAllowAlias) {
+        output.WriteRawTag(16);
+        output.WriteBool(AllowAlias);
+      }
+      if (HasDeprecated) {
+        output.WriteRawTag(24);
+        output.WriteBool(Deprecated);
+      }
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasAllowAlias) {
@@ -6227,6 +8005,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(EnumOptions other) {
       if (other == null) {
         return;
@@ -6243,7 +8022,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6266,8 +8049,38 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 16: {
+            AllowAlias = input.ReadBool();
+            break;
+          }
+          case 24: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<EnumOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -6292,26 +8105,34 @@
 
   }
 
-  public sealed partial class EnumValueOptions : pb::IExtendableMessage<EnumValueOptions> {
+  public sealed partial class EnumValueOptions : pb::IExtendableMessage<EnumValueOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<EnumValueOptions> _parser = new pb::MessageParser<EnumValueOptions>(() => new EnumValueOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<EnumValueOptions> _extensions;
     private pb::ExtensionSet<EnumValueOptions> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<EnumValueOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[15]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValueOptions() {
       OnConstruction();
     }
@@ -6319,6 +8140,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValueOptions(EnumValueOptions other) : this() {
       _hasBits0 = other._hasBits0;
       deprecated_ = other.deprecated_;
@@ -6328,6 +8150,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValueOptions Clone() {
       return new EnumValueOptions(this);
     }
@@ -6344,6 +8167,7 @@
     /// this is a formalization for deprecating enum values.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Deprecated {
       get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
@@ -6353,11 +8177,13 @@
     }
     /// <summary>Gets whether the "deprecated" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecated {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "deprecated" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecated() {
       _hasBits0 &= ~1;
     }
@@ -6371,16 +8197,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as EnumValueOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(EnumValueOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6397,6 +8226,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasDeprecated) hash ^= Deprecated.GetHashCode();
@@ -6411,12 +8241,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasDeprecated) {
         output.WriteRawTag(8);
         output.WriteBool(Deprecated);
@@ -6428,9 +8263,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasDeprecated) {
+        output.WriteRawTag(8);
+        output.WriteBool(Deprecated);
+      }
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasDeprecated) {
@@ -6447,6 +8302,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(EnumValueOptions other) {
       if (other == null) {
         return;
@@ -6460,7 +8316,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6479,8 +8339,34 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<EnumValueOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -6505,26 +8391,34 @@
 
   }
 
-  public sealed partial class ServiceOptions : pb::IExtendableMessage<ServiceOptions> {
+  public sealed partial class ServiceOptions : pb::IExtendableMessage<ServiceOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ServiceOptions> _parser = new pb::MessageParser<ServiceOptions>(() => new ServiceOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<ServiceOptions> _extensions;
     private pb::ExtensionSet<ServiceOptions> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ServiceOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[16]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ServiceOptions() {
       OnConstruction();
     }
@@ -6532,6 +8426,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ServiceOptions(ServiceOptions other) : this() {
       _hasBits0 = other._hasBits0;
       deprecated_ = other.deprecated_;
@@ -6541,6 +8436,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ServiceOptions Clone() {
       return new ServiceOptions(this);
     }
@@ -6557,6 +8453,7 @@
     /// this is a formalization for deprecating services.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Deprecated {
       get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
@@ -6566,11 +8463,13 @@
     }
     /// <summary>Gets whether the "deprecated" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecated {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "deprecated" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecated() {
       _hasBits0 &= ~1;
     }
@@ -6584,16 +8483,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ServiceOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ServiceOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6610,6 +8512,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasDeprecated) hash ^= Deprecated.GetHashCode();
@@ -6624,12 +8527,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasDeprecated) {
         output.WriteRawTag(136, 2);
         output.WriteBool(Deprecated);
@@ -6641,9 +8549,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasDeprecated) {
+        output.WriteRawTag(136, 2);
+        output.WriteBool(Deprecated);
+      }
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasDeprecated) {
@@ -6660,6 +8588,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ServiceOptions other) {
       if (other == null) {
         return;
@@ -6673,7 +8602,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6692,8 +8625,34 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 264: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<ServiceOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -6718,26 +8677,34 @@
 
   }
 
-  public sealed partial class MethodOptions : pb::IExtendableMessage<MethodOptions> {
+  public sealed partial class MethodOptions : pb::IExtendableMessage<MethodOptions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<MethodOptions> _parser = new pb::MessageParser<MethodOptions>(() => new MethodOptions());
     private pb::UnknownFieldSet _unknownFields;
     internal pb::ExtensionSet<MethodOptions> _extensions;
     private pb::ExtensionSet<MethodOptions> _Extensions { get { return _extensions; } }
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<MethodOptions> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[17]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MethodOptions() {
       OnConstruction();
     }
@@ -6745,6 +8712,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MethodOptions(MethodOptions other) : this() {
       _hasBits0 = other._hasBits0;
       deprecated_ = other.deprecated_;
@@ -6755,6 +8723,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public MethodOptions Clone() {
       return new MethodOptions(this);
     }
@@ -6771,6 +8740,7 @@
     /// this is a formalization for deprecating methods.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Deprecated {
       get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
@@ -6780,11 +8750,13 @@
     }
     /// <summary>Gets whether the "deprecated" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDeprecated {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "deprecated" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDeprecated() {
       _hasBits0 &= ~1;
     }
@@ -6795,6 +8767,7 @@
 
     private global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel idempotencyLevel_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel IdempotencyLevel {
       get { if ((_hasBits0 & 2) != 0) { return idempotencyLevel_; } else { return IdempotencyLevelDefaultValue; } }
       set {
@@ -6804,11 +8777,13 @@
     }
     /// <summary>Gets whether the "idempotency_level" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasIdempotencyLevel {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "idempotency_level" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearIdempotencyLevel() {
       _hasBits0 &= ~2;
     }
@@ -6822,16 +8797,19 @@
     /// The parser stores options it doesn't recognize here. See above.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
       get { return uninterpretedOption_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as MethodOptions);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(MethodOptions other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -6849,6 +8827,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (HasDeprecated) hash ^= Deprecated.GetHashCode();
@@ -6864,12 +8843,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (HasDeprecated) {
         output.WriteRawTag(136, 2);
         output.WriteBool(Deprecated);
@@ -6885,9 +8869,33 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (HasDeprecated) {
+        output.WriteRawTag(136, 2);
+        output.WriteBool(Deprecated);
+      }
+      if (HasIdempotencyLevel) {
+        output.WriteRawTag(144, 2);
+        output.WriteEnum((int) IdempotencyLevel);
+      }
+      uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec);
+      if (_extensions != null) {
+        _extensions.WriteTo(ref output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (HasDeprecated) {
@@ -6907,6 +8915,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(MethodOptions other) {
       if (other == null) {
         return;
@@ -6923,7 +8932,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -6946,8 +8959,38 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 264: {
+            Deprecated = input.ReadBool();
+            break;
+          }
+          case 272: {
+            IdempotencyLevel = (global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) input.ReadEnum();
+            break;
+          }
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     public TValue GetExtension<TValue>(pb::Extension<MethodOptions, TValue> extension) {
       return pb::ExtensionSet.Get(ref _extensions, extension);
     }
@@ -6973,6 +9016,7 @@
     #region Nested types
     /// <summary>Container for nested types declared in the MethodOptions message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
@@ -7004,24 +9048,32 @@
   /// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
   /// in them.
   /// </summary>
-  public sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption> {
+  public sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<UninterpretedOption> _parser = new pb::MessageParser<UninterpretedOption>(() => new UninterpretedOption());
     private pb::UnknownFieldSet _unknownFields;
     private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<UninterpretedOption> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[18]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UninterpretedOption() {
       OnConstruction();
     }
@@ -7029,6 +9081,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UninterpretedOption(UninterpretedOption other) : this() {
       _hasBits0 = other._hasBits0;
       name_ = other.name_.Clone();
@@ -7042,6 +9095,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UninterpretedOption Clone() {
       return new UninterpretedOption(this);
     }
@@ -7052,6 +9106,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart> name_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart> Name {
       get { return name_; }
     }
@@ -7066,6 +9121,7 @@
     /// identified it as during parsing. Exactly one of these should be set.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string IdentifierValue {
       get { return identifierValue_ ?? IdentifierValueDefaultValue; }
       set {
@@ -7074,11 +9130,13 @@
     }
     /// <summary>Gets whether the "identifier_value" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasIdentifierValue {
       get { return identifierValue_ != null; }
     }
     /// <summary>Clears the value of the "identifier_value" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearIdentifierValue() {
       identifierValue_ = null;
     }
@@ -7089,6 +9147,7 @@
 
     private ulong positiveIntValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong PositiveIntValue {
       get { if ((_hasBits0 & 1) != 0) { return positiveIntValue_; } else { return PositiveIntValueDefaultValue; } }
       set {
@@ -7098,11 +9157,13 @@
     }
     /// <summary>Gets whether the "positive_int_value" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasPositiveIntValue {
       get { return (_hasBits0 & 1) != 0; }
     }
     /// <summary>Clears the value of the "positive_int_value" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearPositiveIntValue() {
       _hasBits0 &= ~1;
     }
@@ -7113,6 +9174,7 @@
 
     private long negativeIntValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long NegativeIntValue {
       get { if ((_hasBits0 & 2) != 0) { return negativeIntValue_; } else { return NegativeIntValueDefaultValue; } }
       set {
@@ -7122,11 +9184,13 @@
     }
     /// <summary>Gets whether the "negative_int_value" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasNegativeIntValue {
       get { return (_hasBits0 & 2) != 0; }
     }
     /// <summary>Clears the value of the "negative_int_value" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearNegativeIntValue() {
       _hasBits0 &= ~2;
     }
@@ -7137,6 +9201,7 @@
 
     private double doubleValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double DoubleValue {
       get { if ((_hasBits0 & 4) != 0) { return doubleValue_; } else { return DoubleValueDefaultValue; } }
       set {
@@ -7146,11 +9211,13 @@
     }
     /// <summary>Gets whether the "double_value" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasDoubleValue {
       get { return (_hasBits0 & 4) != 0; }
     }
     /// <summary>Clears the value of the "double_value" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearDoubleValue() {
       _hasBits0 &= ~4;
     }
@@ -7161,6 +9228,7 @@
 
     private pb::ByteString stringValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString StringValue {
       get { return stringValue_ ?? StringValueDefaultValue; }
       set {
@@ -7169,11 +9237,13 @@
     }
     /// <summary>Gets whether the "string_value" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasStringValue {
       get { return stringValue_ != null; }
     }
     /// <summary>Clears the value of the "string_value" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearStringValue() {
       stringValue_ = null;
     }
@@ -7184,6 +9254,7 @@
 
     private string aggregateValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string AggregateValue {
       get { return aggregateValue_ ?? AggregateValueDefaultValue; }
       set {
@@ -7192,21 +9263,25 @@
     }
     /// <summary>Gets whether the "aggregate_value" field is set</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool HasAggregateValue {
       get { return aggregateValue_ != null; }
     }
     /// <summary>Clears the value of the "aggregate_value" field</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearAggregateValue() {
       aggregateValue_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as UninterpretedOption);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(UninterpretedOption other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7225,6 +9300,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= name_.GetHashCode();
@@ -7241,12 +9317,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       name_.WriteTo(output, _repeated_name_codec);
       if (HasIdentifierValue) {
         output.WriteRawTag(26);
@@ -7275,9 +9356,46 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      name_.WriteTo(ref output, _repeated_name_codec);
+      if (HasIdentifierValue) {
+        output.WriteRawTag(26);
+        output.WriteString(IdentifierValue);
+      }
+      if (HasPositiveIntValue) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(PositiveIntValue);
+      }
+      if (HasNegativeIntValue) {
+        output.WriteRawTag(40);
+        output.WriteInt64(NegativeIntValue);
+      }
+      if (HasDoubleValue) {
+        output.WriteRawTag(49);
+        output.WriteDouble(DoubleValue);
+      }
+      if (HasStringValue) {
+        output.WriteRawTag(58);
+        output.WriteBytes(StringValue);
+      }
+      if (HasAggregateValue) {
+        output.WriteRawTag(66);
+        output.WriteString(AggregateValue);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += name_.CalculateSize(_repeated_name_codec);
@@ -7306,6 +9424,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(UninterpretedOption other) {
       if (other == null) {
         return;
@@ -7333,7 +9452,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7370,11 +9493,56 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 18: {
+            name_.AddEntriesFrom(ref input, _repeated_name_codec);
+            break;
+          }
+          case 26: {
+            IdentifierValue = input.ReadString();
+            break;
+          }
+          case 32: {
+            PositiveIntValue = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            NegativeIntValue = input.ReadInt64();
+            break;
+          }
+          case 49: {
+            DoubleValue = input.ReadDouble();
+            break;
+          }
+          case 58: {
+            StringValue = input.ReadBytes();
+            break;
+          }
+          case 66: {
+            AggregateValue = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the UninterpretedOption message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// The name of the uninterpreted option.  Each string represents a segment in
@@ -7383,24 +9551,32 @@
       /// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
       /// "foo.(bar.baz).qux".
       /// </summary>
-      public sealed partial class NamePart : pb::IMessage<NamePart> {
+      public sealed partial class NamePart : pb::IMessage<NamePart>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<NamePart> _parser = new pb::MessageParser<NamePart>(() => new NamePart());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<NamePart> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.UninterpretedOption.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NamePart() {
           OnConstruction();
         }
@@ -7408,6 +9584,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NamePart(NamePart other) : this() {
           _hasBits0 = other._hasBits0;
           namePart_ = other.namePart_;
@@ -7416,6 +9593,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public NamePart Clone() {
           return new NamePart(this);
         }
@@ -7426,6 +9604,7 @@
 
         private string namePart_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string NamePart_ {
           get { return namePart_ ?? NamePart_DefaultValue; }
           set {
@@ -7434,11 +9613,13 @@
         }
         /// <summary>Gets whether the "name_part" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasNamePart_ {
           get { return namePart_ != null; }
         }
         /// <summary>Clears the value of the "name_part" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearNamePart_() {
           namePart_ = null;
         }
@@ -7449,6 +9630,7 @@
 
         private bool isExtension_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool IsExtension {
           get { if ((_hasBits0 & 1) != 0) { return isExtension_; } else { return IsExtensionDefaultValue; } }
           set {
@@ -7458,21 +9640,25 @@
         }
         /// <summary>Gets whether the "is_extension" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasIsExtension {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "is_extension" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearIsExtension() {
           _hasBits0 &= ~1;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as NamePart);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(NamePart other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -7486,6 +9672,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           if (HasNamePart_) hash ^= NamePart_.GetHashCode();
@@ -7497,12 +9684,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           if (HasNamePart_) {
             output.WriteRawTag(10);
             output.WriteString(NamePart_);
@@ -7514,9 +9706,29 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          if (HasNamePart_) {
+            output.WriteRawTag(10);
+            output.WriteString(NamePart_);
+          }
+          if (HasIsExtension) {
+            output.WriteRawTag(16);
+            output.WriteBool(IsExtension);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           if (HasNamePart_) {
@@ -7532,6 +9744,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(NamePart other) {
           if (other == null) {
             return;
@@ -7546,7 +9759,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -7563,8 +9780,32 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10: {
+                NamePart_ = input.ReadString();
+                break;
+              }
+              case 16: {
+                IsExtension = input.ReadBool();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -7576,23 +9817,31 @@
   /// Encapsulates information about the original source file from which a
   /// FileDescriptorProto was generated.
   /// </summary>
-  public sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo> {
+  public sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<SourceCodeInfo> _parser = new pb::MessageParser<SourceCodeInfo>(() => new SourceCodeInfo());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<SourceCodeInfo> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[19]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SourceCodeInfo() {
       OnConstruction();
     }
@@ -7600,12 +9849,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SourceCodeInfo(SourceCodeInfo other) : this() {
       location_ = other.location_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SourceCodeInfo Clone() {
       return new SourceCodeInfo(this);
     }
@@ -7661,16 +9912,19 @@
     ///   be recorded in the future.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location> Location {
       get { return location_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as SourceCodeInfo);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(SourceCodeInfo other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -7683,6 +9937,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= location_.GetHashCode();
@@ -7693,19 +9948,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       location_.WriteTo(output, _repeated_location_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      location_.WriteTo(ref output, _repeated_location_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += location_.CalculateSize(_repeated_location_codec);
@@ -7716,6 +9989,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(SourceCodeInfo other) {
       if (other == null) {
         return;
@@ -7725,7 +9999,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -7738,29 +10016,58 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            location_.AddEntriesFrom(ref input, _repeated_location_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the SourceCodeInfo message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class Location : pb::IMessage<Location> {
+      public sealed partial class Location : pb::IMessage<Location>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<Location> _parser = new pb::MessageParser<Location>(() => new Location());
         private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<Location> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.SourceCodeInfo.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Location() {
           OnConstruction();
         }
@@ -7768,6 +10075,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Location(Location other) : this() {
           path_ = other.path_.Clone();
           span_ = other.span_.Clone();
@@ -7778,6 +10086,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Location Clone() {
           return new Location(this);
         }
@@ -7813,6 +10122,7 @@
         /// of the label to the terminating semicolon).
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<int> Path {
           get { return path_; }
         }
@@ -7830,6 +10140,7 @@
         /// 1 to each before displaying to a user.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<int> Span {
           get { return span_; }
         }
@@ -7889,6 +10200,7 @@
         ///   // ignored detached comments.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string LeadingComments {
           get { return leadingComments_ ?? LeadingCommentsDefaultValue; }
           set {
@@ -7897,11 +10209,13 @@
         }
         /// <summary>Gets whether the "leading_comments" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasLeadingComments {
           get { return leadingComments_ != null; }
         }
         /// <summary>Clears the value of the "leading_comments" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearLeadingComments() {
           leadingComments_ = null;
         }
@@ -7912,6 +10226,7 @@
 
         private string trailingComments_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string TrailingComments {
           get { return trailingComments_ ?? TrailingCommentsDefaultValue; }
           set {
@@ -7920,11 +10235,13 @@
         }
         /// <summary>Gets whether the "trailing_comments" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasTrailingComments {
           get { return trailingComments_ != null; }
         }
         /// <summary>Clears the value of the "trailing_comments" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearTrailingComments() {
           trailingComments_ = null;
         }
@@ -7935,16 +10252,19 @@
             = pb::FieldCodec.ForString(50);
         private readonly pbc::RepeatedField<string> leadingDetachedComments_ = new pbc::RepeatedField<string>();
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<string> LeadingDetachedComments {
           get { return leadingDetachedComments_; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as Location);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(Location other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -7961,6 +10281,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           hash ^= path_.GetHashCode();
@@ -7975,12 +10296,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           path_.WriteTo(output, _repeated_path_codec);
           span_.WriteTo(output, _repeated_span_codec);
           if (HasLeadingComments) {
@@ -7995,9 +10321,32 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          path_.WriteTo(ref output, _repeated_path_codec);
+          span_.WriteTo(ref output, _repeated_span_codec);
+          if (HasLeadingComments) {
+            output.WriteRawTag(26);
+            output.WriteString(LeadingComments);
+          }
+          if (HasTrailingComments) {
+            output.WriteRawTag(34);
+            output.WriteString(TrailingComments);
+          }
+          leadingDetachedComments_.WriteTo(ref output, _repeated_leadingDetachedComments_codec);
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           size += path_.CalculateSize(_repeated_path_codec);
@@ -8016,6 +10365,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(Location other) {
           if (other == null) {
             return;
@@ -8033,7 +10383,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -8064,8 +10418,46 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10:
+              case 8: {
+                path_.AddEntriesFrom(ref input, _repeated_path_codec);
+                break;
+              }
+              case 18:
+              case 16: {
+                span_.AddEntriesFrom(ref input, _repeated_span_codec);
+                break;
+              }
+              case 26: {
+                LeadingComments = input.ReadString();
+                break;
+              }
+              case 34: {
+                TrailingComments = input.ReadString();
+                break;
+              }
+              case 50: {
+                leadingDetachedComments_.AddEntriesFrom(ref input, _repeated_leadingDetachedComments_codec);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
@@ -8078,23 +10470,31 @@
   /// file. A GeneratedCodeInfo message is associated with only one generated
   /// source file, but may contain references to different source .proto files.
   /// </summary>
-  public sealed partial class GeneratedCodeInfo : pb::IMessage<GeneratedCodeInfo> {
+  public sealed partial class GeneratedCodeInfo : pb::IMessage<GeneratedCodeInfo>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<GeneratedCodeInfo> _parser = new pb::MessageParser<GeneratedCodeInfo>(() => new GeneratedCodeInfo());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<GeneratedCodeInfo> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[20]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GeneratedCodeInfo() {
       OnConstruction();
     }
@@ -8102,12 +10502,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GeneratedCodeInfo(GeneratedCodeInfo other) : this() {
       annotation_ = other.annotation_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public GeneratedCodeInfo Clone() {
       return new GeneratedCodeInfo(this);
     }
@@ -8122,16 +10524,19 @@
     /// of its generating .proto file.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation> Annotation {
       get { return annotation_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as GeneratedCodeInfo);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(GeneratedCodeInfo other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -8144,6 +10549,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= annotation_.GetHashCode();
@@ -8154,19 +10560,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       annotation_.WriteTo(output, _repeated_annotation_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      annotation_.WriteTo(ref output, _repeated_annotation_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += annotation_.CalculateSize(_repeated_annotation_codec);
@@ -8177,6 +10601,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(GeneratedCodeInfo other) {
       if (other == null) {
         return;
@@ -8186,7 +10611,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -8199,30 +10628,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            annotation_.AddEntriesFrom(ref input, _repeated_annotation_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the GeneratedCodeInfo message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
-      public sealed partial class Annotation : pb::IMessage<Annotation> {
+      public sealed partial class Annotation : pb::IMessage<Annotation>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
         private static readonly pb::MessageParser<Annotation> _parser = new pb::MessageParser<Annotation>(() => new Annotation());
         private pb::UnknownFieldSet _unknownFields;
         private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pb::MessageParser<Annotation> Parser { get { return _parser; } }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public static pbr::MessageDescriptor Descriptor {
           get { return global::Google.Protobuf.Reflection.GeneratedCodeInfo.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         pbr::MessageDescriptor pb::IMessage.Descriptor {
           get { return Descriptor; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Annotation() {
           OnConstruction();
         }
@@ -8230,6 +10688,7 @@
         partial void OnConstruction();
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Annotation(Annotation other) : this() {
           _hasBits0 = other._hasBits0;
           path_ = other.path_.Clone();
@@ -8240,6 +10699,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public Annotation Clone() {
           return new Annotation(this);
         }
@@ -8254,6 +10714,7 @@
         /// is formatted the same as SourceCodeInfo.Location.path.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public pbc::RepeatedField<int> Path {
           get { return path_; }
         }
@@ -8267,6 +10728,7 @@
         /// Identifies the filesystem path to the original source .proto.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public string SourceFile {
           get { return sourceFile_ ?? SourceFileDefaultValue; }
           set {
@@ -8275,11 +10737,13 @@
         }
         /// <summary>Gets whether the "source_file" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasSourceFile {
           get { return sourceFile_ != null; }
         }
         /// <summary>Clears the value of the "source_file" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearSourceFile() {
           sourceFile_ = null;
         }
@@ -8294,6 +10758,7 @@
         /// that relates to the identified object.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int Begin {
           get { if ((_hasBits0 & 1) != 0) { return begin_; } else { return BeginDefaultValue; } }
           set {
@@ -8303,11 +10768,13 @@
         }
         /// <summary>Gets whether the "begin" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasBegin {
           get { return (_hasBits0 & 1) != 0; }
         }
         /// <summary>Clears the value of the "begin" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearBegin() {
           _hasBits0 &= ~1;
         }
@@ -8323,6 +10790,7 @@
         /// the last relevant byte (so the length of the text = end - begin).
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int End {
           get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
@@ -8332,21 +10800,25 @@
         }
         /// <summary>Gets whether the "end" field is set</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool HasEnd {
           get { return (_hasBits0 & 2) != 0; }
         }
         /// <summary>Clears the value of the "end" field</summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void ClearEnd() {
           _hasBits0 &= ~2;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
           return Equals(other as Annotation);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public bool Equals(Annotation other) {
           if (ReferenceEquals(other, null)) {
             return false;
@@ -8362,6 +10834,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override int GetHashCode() {
           int hash = 1;
           hash ^= path_.GetHashCode();
@@ -8375,12 +10848,17 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override string ToString() {
           return pb::JsonFormatter.ToDiagnosticString(this);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void WriteTo(pb::CodedOutputStream output) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          output.WriteRawMessage(this);
+        #else
           path_.WriteTo(output, _repeated_path_codec);
           if (HasSourceFile) {
             output.WriteRawTag(18);
@@ -8397,9 +10875,34 @@
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+          path_.WriteTo(ref output, _repeated_path_codec);
+          if (HasSourceFile) {
+            output.WriteRawTag(18);
+            output.WriteString(SourceFile);
+          }
+          if (HasBegin) {
+            output.WriteRawTag(24);
+            output.WriteInt32(Begin);
+          }
+          if (HasEnd) {
+            output.WriteRawTag(32);
+            output.WriteInt32(End);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(ref output);
+          }
+        }
+        #endif
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public int CalculateSize() {
           int size = 0;
           size += path_.CalculateSize(_repeated_path_codec);
@@ -8419,6 +10922,7 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(Annotation other) {
           if (other == null) {
             return;
@@ -8437,7 +10941,11 @@
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public void MergeFrom(pb::CodedInputStream input) {
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          input.ReadRawMessage(this);
+        #else
           uint tag;
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
@@ -8463,8 +10971,41 @@
               }
             }
           }
+        #endif
         }
 
+        #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+                break;
+              case 10:
+              case 8: {
+                path_.AddEntriesFrom(ref input, _repeated_path_codec);
+                break;
+              }
+              case 18: {
+                SourceFile = input.ReadString();
+                break;
+              }
+              case 24: {
+                Begin = input.ReadInt32();
+                break;
+              }
+              case 32: {
+                End = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
       }
 
     }
diff --git a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
index 264a88a..f7e8b5b 100644
--- a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
@@ -128,12 +128,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this enum.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>EnumOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public EnumOptions GetOptions() => Proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value enum option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<EnumOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -143,6 +152,7 @@
         /// <summary>
         /// Gets a repeated value enum option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<EnumOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();
diff --git a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
index 3933820..05097bd 100644
--- a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
@@ -73,12 +73,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this enum value.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>EnumValueOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public EnumValueOptions GetOptions() => Proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value enum value option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<EnumValueOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -88,6 +97,7 @@
         /// <summary>
         /// Gets a repeated value enum value option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<EnumValueOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();
diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
index ddd671a..7324e3d 100644
--- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
@@ -59,11 +59,32 @@
         public OneofDescriptor ContainingOneof { get; }
 
         /// <summary>
+        /// Returns the oneof containing this field if it's a "real" oneof, or <c>null</c> if either this
+        /// field is not part of a oneof, or the oneof is synthetic.
+        /// </summary>
+        public OneofDescriptor RealContainingOneof => ContainingOneof?.IsSynthetic == false ? ContainingOneof : null;
+
+        /// <summary>
         /// The effective JSON name for this field. This is usually the lower-camel-cased form of the field name,
         /// but can be overridden using the <c>json_name</c> option in the .proto file.
         /// </summary>
         public string JsonName { get; }
 
+        /// <summary>
+        /// Indicates whether this field supports presence, either implicitly (e.g. due to it being a message
+        /// type field) or explicitly via Has/Clear members. If this returns true, it is safe to call
+        /// <see cref="IFieldAccessor.Clear(IMessage)"/> and <see cref="IFieldAccessor.HasValue(IMessage)"/>
+        /// on this field's accessor with a suitable message.
+        /// </summary>
+        public bool HasPresence =>
+            Extension != null ? !Extension.IsRepeated
+            : IsRepeated ? false
+            : IsMap ? false
+            : FieldType == FieldType.Message ? true
+            // This covers "real oneof members" and "proto3 optional fields"
+            : ContainingOneof != null ? true
+            : File.Syntax == Syntax.Proto2;
+
         internal FieldDescriptorProto Proto { get; }
 
         /// <summary>
@@ -298,12 +319,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this field.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>FieldOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public FieldOptions GetOptions() => Proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value field option for this descriptor
         /// </summary>
+         [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<FieldOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -313,6 +343,7 @@
         /// <summary>
         /// Gets a repeated value field option for this descriptor
         /// </summary>
+         [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<FieldOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();
@@ -388,7 +419,7 @@
 
             File.DescriptorPool.AddFieldByNumber(this);
 
-            if (ContainingType != null && ContainingType.Proto.HasOptions && ContainingType.Proto.Options.MessageSetWireFormat)
+            if (ContainingType != null && ContainingType.Proto.Options != null && ContainingType.Proto.Options.MessageSetWireFormat)
             {
                 throw new DescriptorValidationException(this, "MessageSet format is not supported.");
             }
diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
index 56c0caa..724bb3a 100644
--- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
@@ -481,18 +481,21 @@
         /// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
         /// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
         /// with the order in which protoc provides descriptors to plugins.</param>
+        /// <param name="registry">The extension registry to use when parsing, or null if no extensions are required.</param>
         /// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
-        public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData)
+        public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData, ExtensionRegistry registry)
         {
             ProtoPreconditions.CheckNotNull(descriptorData, nameof(descriptorData));
 
+            var parser = FileDescriptorProto.Parser.WithExtensionRegistry(registry);
+
             // TODO: See if we can build a single DescriptorPool instead of building lots of them.
             // This will all behave correctly, but it's less efficient than we'd like.
             var descriptors = new List<FileDescriptor>();
             var descriptorsByName = new Dictionary<string, FileDescriptor>();
             foreach (var data in descriptorData)
             {
-                var proto = FileDescriptorProto.Parser.ParseFrom(data);
+                var proto = parser.ParseFrom(data);
                 var dependencies = new List<FileDescriptor>();
                 foreach (var dependencyName in proto.Dependency)
                 {
@@ -519,6 +522,18 @@
         }
 
         /// <summary>
+        /// Converts the given descriptor binary data into FileDescriptor objects.
+        /// Note: reflection using the returned FileDescriptors is not currently supported.
+        /// </summary>
+        /// <param name="descriptorData">The binary file descriptor proto data. Must not be null, and any
+        /// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
+        /// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
+        /// with the order in which protoc provides descriptors to plugins.</param>
+        /// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
+        public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData) =>
+            BuildFromByteStrings(descriptorData, null);
+
+        /// <summary>
         /// Returns a <see cref="System.String" /> that represents this instance.
         /// </summary>
         /// <returns>
@@ -547,12 +562,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this file.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>FileOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public FileOptions GetOptions() => Proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value file option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<FileOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -562,6 +586,7 @@
         /// <summary>
         /// Gets a repeated value file option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<FileOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();
diff --git a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
index b48c4f9..d73427b 100644
--- a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
@@ -59,7 +59,8 @@
         object GetValue(IMessage message);
 
         /// <summary>
-        /// Indicates whether the field in the specified message is set. For proto3 fields, this throws an <see cref="InvalidOperationException"/>
+        /// Indicates whether the field in the specified message is set.
+        /// For proto3 fields that aren't explicitly optional, this throws an <see cref="InvalidOperationException"/>
         /// </summary>
         bool HasValue(IMessage message);
 
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
index eda1965..7b5ab2f 100644
--- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -80,6 +80,20 @@
                 (oneof, index) =>
                 new OneofDescriptor(oneof, file, this, index, generatedCodeInfo?.OneofNames[index]));
 
+            int syntheticOneofCount = 0;
+            foreach (var oneof in Oneofs)
+            {
+                if (oneof.IsSynthetic)
+                {
+                    syntheticOneofCount++;
+                }
+                else if (syntheticOneofCount != 0)
+                {
+                    throw new ArgumentException("All synthetic oneofs should come after real oneofs");
+                }
+            }
+            RealOneofCount = Oneofs.Count - syntheticOneofCount;
+
             NestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(
                 proto.NestedType,
                 (type, index) =>
@@ -234,10 +248,20 @@
 
         /// <value>
         /// An unmodifiable list of the "oneof" field collections in this message type.
+        /// All "real" oneofs (where <see cref="OneofDescriptor.IsSynthetic"/> returns false)
+        /// come before synthetic ones.
         /// </value>
         public IList<OneofDescriptor> Oneofs { get; }
 
         /// <summary>
+        /// The number of real "oneof" descriptors in this message type. Every element in <see cref="Oneofs"/>
+        /// with an index less than this will have a <see cref="OneofDescriptor.IsSynthetic"/> property value
+        /// of <c>false</c>; every element with an index greater than or equal to this will have a
+        /// <see cref="OneofDescriptor.IsSynthetic"/> property value of <c>true</c>.
+        /// </summary>
+        public int RealOneofCount { get; }
+
+        /// <summary>
         /// Finds a field by field name.
         /// </summary>
         /// <param name="name">The unqualified name of the field (e.g. "foo").</param>
@@ -263,12 +287,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this message.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>MessageOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public MessageOptions GetOptions() => Proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value message option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<MessageOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -278,6 +311,7 @@
         /// <summary>
         /// Gets a repeated value message option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public Collections.RepeatedField<T> GetOption<T>(RepeatedExtension<MessageOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();
diff --git a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
index 92250ba..8e15037 100644
--- a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
@@ -73,12 +73,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this method.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>MethodOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public MethodOptions GetOptions() => Proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value method option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<MethodOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -88,6 +97,7 @@
         /// <summary>
         /// Gets a repeated value method option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<MethodOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();
diff --git a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
index f4bf628..7523426 100644
--- a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
@@ -43,19 +43,31 @@
     {
         private readonly Func<IMessage, int> caseDelegate;
         private readonly Action<IMessage> clearDelegate;
-        private OneofDescriptor descriptor;
 
-        internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor)
+        private OneofAccessor(OneofDescriptor descriptor, Func<IMessage, int> caseDelegate, Action<IMessage> clearDelegate)
         {
-            if (!caseProperty.CanRead)
-            {
-                throw new ArgumentException("Cannot read from property");
-            }
-            this.descriptor = descriptor;
-            caseDelegate = ReflectionUtil.CreateFuncIMessageInt32(caseProperty.GetGetMethod());
+            Descriptor = descriptor;
+            this.caseDelegate = caseDelegate;
+            this.clearDelegate = clearDelegate;
+        }
 
-            this.descriptor = descriptor;
-            clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
+        internal static OneofAccessor ForRegularOneof(
+            OneofDescriptor descriptor,
+            PropertyInfo caseProperty,
+            MethodInfo clearMethod) =>
+            new OneofAccessor(
+                descriptor,
+                ReflectionUtil.CreateFuncIMessageInt32(caseProperty.GetGetMethod()),
+                ReflectionUtil.CreateActionIMessage(clearMethod));
+
+        internal static OneofAccessor ForSyntheticOneof(OneofDescriptor descriptor)
+        {
+            // Note: descriptor.Fields will be null when this method is called, because we haven't
+            // cross-linked yet. But by the time the delegates are called by user code, all will be
+            // well. (That's why we capture the descriptor itself rather than a field.)
+            return new OneofAccessor(descriptor,
+                message => descriptor.Fields[0].Accessor.HasValue(message) ? descriptor.Fields[0].FieldNumber : 0,
+                message => descriptor.Fields[0].Accessor.Clear(message));
         }
 
         /// <summary>
@@ -64,15 +76,12 @@
         /// <value>
         /// The descriptor of the oneof.
         /// </value>
-        public OneofDescriptor Descriptor { get { return descriptor; } }
+        public OneofDescriptor Descriptor { get; }
 
         /// <summary>
         /// Clears the oneof in the specified message.
         /// </summary>
-        public void Clear(IMessage message)
-        {
-            clearDelegate(message);
-        }
+        public void Clear(IMessage message) => clearDelegate(message);
 
         /// <summary>
         /// Indicates which field in the oneof is set for specified message
@@ -80,11 +89,9 @@
         public FieldDescriptor GetCaseFieldDescriptor(IMessage message)
         {
             int fieldNumber = caseDelegate(message);
-            if (fieldNumber > 0)
-            {
-                return descriptor.ContainingType.FindFieldByNumber(fieldNumber);
-            }
-            return null;
+            return fieldNumber > 0
+                ? Descriptor.ContainingType.FindFieldByNumber(fieldNumber)
+                : null;
         }
     }
 }
diff --git a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
index 1e30b92..b41d520 100644
--- a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
@@ -33,6 +33,7 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Linq;
 using Google.Protobuf.Collections;
 using Google.Protobuf.Compatibility;
 
@@ -54,8 +55,13 @@
         {
             this.proto = proto;
             containingType = parent;
-
             file.DescriptorPool.AddSymbol(this);
+
+            // It's useful to determine whether or not this is a synthetic oneof before cross-linking. That means
+            // diving into the proto directly rather than using FieldDescriptor, but that's okay.
+            var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.HasOneofIndex && fieldProto.OneofIndex == index);
+            IsSynthetic = firstFieldInOneof?.Proto3Optional ?? false;
+
             accessor = CreateAccessor(clrName);
         }
 
@@ -84,6 +90,12 @@
         public IList<FieldDescriptor> Fields { get { return fields; } }
 
         /// <summary>
+        /// Returns <c>true</c> if this oneof is a synthetic oneof containing a proto3 optional field;
+        /// <c>false</c> otherwise.
+        /// </summary>
+        public bool IsSynthetic { get; }
+
+        /// <summary>
         /// Gets an accessor for reflective access to the values associated with the oneof
         /// in a particular message.
         /// </summary>
@@ -105,12 +117,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this oneof.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions method.")]
         public CustomOptions CustomOptions => new CustomOptions(proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>OneofOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public OneofOptions GetOptions() => proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value oneof option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<OneofOptions, T> extension)
         {
             var value = proto.Options.GetExtension(extension);
@@ -120,6 +141,7 @@
         /// <summary>
         /// Gets a repeated value oneof option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<OneofOptions, T> extension)
         {
             return proto.Options.GetExtension(extension).Clone();
@@ -146,18 +168,28 @@
             {
                 return null;
             }
-            var caseProperty = containingType.ClrType.GetProperty(clrName + "Case");
-            if (caseProperty == null)
+            if (IsSynthetic)
             {
-                throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}");
+                return OneofAccessor.ForSyntheticOneof(this);
             }
-            var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName);
-            if (clearMethod == null)
+            else
             {
-                throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}");
+                var caseProperty = containingType.ClrType.GetProperty(clrName + "Case");
+                if (caseProperty == null)
+                {
+                    throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}");
+                }
+                if (!caseProperty.CanRead)
+                {
+                    throw new ArgumentException($"Cannot read from property {clrName}Case in {containingType.ClrType}");
+                }
+                var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName);
+                if (clearMethod == null)
+                {
+                    throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}");
+                }
+                return OneofAccessor.ForRegularOneof(this, caseProperty, clearMethod);
             }
-
-            return new OneofAccessor(caseProperty, clearMethod, this);
         }
     }
 }
diff --git a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
index 21417ec..dab348b 100644
--- a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
@@ -94,12 +94,21 @@
         /// <summary>
         /// The (possibly empty) set of custom options for this service.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
         /// <summary>
+        /// The <c>ServiceOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public ServiceOptions GetOptions() => Proto.Options?.Clone();
+
+        /// <summary>
         /// Gets a single value service option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<ServiceOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -109,6 +118,7 @@
         /// <summary>
         /// Gets a repeated value service option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<ServiceOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();
diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
index de10226..07d84d7 100644
--- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
@@ -57,49 +57,68 @@
                 throw new ArgumentException("Not all required properties/methods available");
             }
             setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
-            if (descriptor.File.Syntax == Syntax.Proto3)
+
+            // Note: this looks worrying in that we access the containing oneof, which isn't valid until cross-linking
+            // is complete... but field accessors aren't created until after cross-linking.
+            // The oneof itself won't be cross-linked yet, but that's okay: the oneof accessor is created
+            // earlier.
+
+            // Message fields always support presence, via null checks.
+            if (descriptor.FieldType == FieldType.Message)
             {
-                hasDelegate = message => {
-                  throw new InvalidOperationException("HasValue is not implemented for proto3 fields");
+                hasDelegate = message => GetValue(message) != null;
+                clearDelegate = message => SetValue(message, null);
+            }
+            // Oneof fields always support presence, via case checks.
+            // Note that clearing the field is a no-op unless that specific field is the current "case".
+            else if (descriptor.RealContainingOneof != null)
+            {
+                var oneofAccessor = descriptor.RealContainingOneof.Accessor;
+                hasDelegate = message => oneofAccessor.GetCaseFieldDescriptor(message) == descriptor;
+                clearDelegate = message =>
+                {
+                    // Clear on a field only affects the oneof itself if the current case is the field we're accessing.
+                    if (oneofAccessor.GetCaseFieldDescriptor(message) == descriptor)
+                    {
+                        oneofAccessor.Clear(message);
+                    }
                 };
+            }
+            // Primitive fields always support presence in proto2, and support presence in proto3 for optional fields.
+            else if (descriptor.File.Syntax == Syntax.Proto2 || descriptor.Proto.Proto3Optional)
+            {
+                MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
+                if (hasMethod == null)
+                {
+                    throw new ArgumentException("Not all required properties/methods are available");
+                }
+                hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
+                MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
+                if (clearMethod == null)
+                {
+                    throw new ArgumentException("Not all required properties/methods are available");
+                }
+                clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
+            }
+            // What's left?
+            // Primitive proto3 fields without the optional keyword, which aren't in oneofs.
+            else
+            {
+                hasDelegate = message => { throw new InvalidOperationException("Presence is not implemented for this field"); };
+
+                // While presence isn't supported, clearing still is; it's just setting to a default value.
                 var clrType = property.PropertyType;
 
-                // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
                 object defaultValue =
-                    descriptor.FieldType == FieldType.Message ? null
-                    : clrType == typeof(string) ? ""
+                    clrType == typeof(string) ? ""
                     : clrType == typeof(ByteString) ? ByteString.Empty
                     : Activator.CreateInstance(clrType);
                 clearDelegate = message => SetValue(message, defaultValue);
             }
-            else
-            {
-                MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
-                if (hasMethod == null) {
-                  throw new ArgumentException("Not all required properties/methods are available");
-                }
-                hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
-                MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
-                if (clearMethod == null) {
-                  throw new ArgumentException("Not all required properties/methods are available");
-                }
-                clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
-            }
         }
 
-        public override void Clear(IMessage message)
-        {
-            clearDelegate(message);
-        }
-
-        public override bool HasValue(IMessage message)
-        {
-            return hasDelegate(message);
-        }
-
-        public override void SetValue(IMessage message, object value)
-        {
-            setValueDelegate(message, value);
-        }
+        public override void Clear(IMessage message) => clearDelegate(message);
+        public override bool HasValue(IMessage message) => hasDelegate(message);
+        public override void SetValue(IMessage message, object value) => setValueDelegate(message, value);
     }
 }
diff --git a/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs b/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs
new file mode 100644
index 0000000..b5441d3
--- /dev/null
+++ b/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs
@@ -0,0 +1,296 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Abstraction for reading from a stream / read only sequence.
+    /// Parsing from the buffer is a loop of reading from current buffer / refreshing the buffer once done.
+    /// </summary>
+    [SecuritySafeCritical]
+    internal struct SegmentedBufferHelper
+    {
+        private int? totalLength;
+        private ReadOnlySequence<byte>.Enumerator readOnlySequenceEnumerator;
+        private CodedInputStream codedInputStream;
+
+        /// <summary>
+        /// Initialize an instance with a coded input stream.
+        /// This approach is faster than using a constructor because the instance to initialize is passed by reference
+        /// and we can write directly into it without copying.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Initialize(CodedInputStream codedInputStream, out SegmentedBufferHelper instance)
+        {
+            instance.totalLength = codedInputStream.InternalInputStream == null ? (int?)codedInputStream.InternalBuffer.Length : null;
+            instance.readOnlySequenceEnumerator = default;
+            instance.codedInputStream = codedInputStream;
+        }
+
+        /// <summary>
+        /// Initialize an instance with a read only sequence.
+        /// This approach is faster than using a constructor because the instance to initialize is passed by reference
+        /// and we can write directly into it without copying.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Initialize(ReadOnlySequence<byte> sequence, out SegmentedBufferHelper instance, out ReadOnlySpan<byte> firstSpan)
+        {
+            instance.codedInputStream = null;
+            if (sequence.IsSingleSegment)
+            {
+                firstSpan = sequence.First.Span;
+                instance.totalLength = firstSpan.Length;
+                instance.readOnlySequenceEnumerator = default;
+            }
+            else
+            {
+                instance.readOnlySequenceEnumerator = sequence.GetEnumerator();
+                instance.totalLength = (int) sequence.Length;
+
+                // set firstSpan to the first segment
+                instance.readOnlySequenceEnumerator.MoveNext();
+                firstSpan = instance.readOnlySequenceEnumerator.Current.Span;
+            }
+        }
+        
+        public bool RefillBuffer(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, bool mustSucceed)
+        {
+            if (codedInputStream != null)
+            {
+                return RefillFromCodedInputStream(ref buffer, ref state, mustSucceed);
+            }
+            else
+            {
+                return RefillFromReadOnlySequence(ref buffer, ref state, mustSucceed);
+            }
+        }
+
+        public int? TotalLength => totalLength;
+
+        public CodedInputStream CodedInputStream => codedInputStream;
+
+        /// <summary>
+        /// Sets currentLimit to (current position) + byteLimit. This is called
+        /// when descending into a length-delimited embedded message. The previous
+        /// limit is returned.
+        /// </summary>
+        /// <returns>The old limit.</returns>
+        public static int PushLimit(ref ParserInternalState state, int byteLimit)
+        {
+            if (byteLimit < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+            byteLimit += state.totalBytesRetired + state.bufferPos;
+            int oldLimit = state.currentLimit;
+            if (byteLimit > oldLimit)
+            {
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+            state.currentLimit = byteLimit;
+
+            RecomputeBufferSizeAfterLimit(ref state);
+
+            return oldLimit;
+        }
+
+        /// <summary>
+        /// Discards the current limit, returning the previous limit.
+        /// </summary>
+        public static void PopLimit(ref ParserInternalState state, int oldLimit)
+        {
+            state.currentLimit = oldLimit;
+            RecomputeBufferSizeAfterLimit(ref state);
+        }
+
+        /// <summary>
+        /// Returns whether or not all the data before the limit has been read.
+        /// </summary>
+        /// <returns></returns>
+        public static bool IsReachedLimit(ref ParserInternalState state)
+        {
+            if (state.currentLimit == int.MaxValue)
+            {
+                return false;
+            }
+            int currentAbsolutePosition = state.totalBytesRetired + state.bufferPos;
+            return currentAbsolutePosition >= state.currentLimit;
+        }
+
+        /// <summary>
+        /// Returns true if the stream has reached the end of the input. This is the
+        /// case if either the end of the underlying input source has been reached or
+        /// the stream has reached a limit created using PushLimit.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsAtEnd(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
+        {
+            return state.bufferPos == state.bufferSize && !state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, false);
+        }
+
+        private bool RefillFromReadOnlySequence(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, bool mustSucceed)
+        {
+            CheckCurrentBufferIsEmpty(ref state);
+
+            if (state.totalBytesRetired + state.bufferSize == state.currentLimit)
+            {
+                // Oops, we hit a limit.
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+
+            state.totalBytesRetired += state.bufferSize;
+
+            state.bufferPos = 0;
+            state.bufferSize = 0;
+            while (readOnlySequenceEnumerator.MoveNext())
+            {
+                buffer = readOnlySequenceEnumerator.Current.Span;
+                state.bufferSize = buffer.Length;
+                if (buffer.Length != 0)
+                {
+                    break;
+                }
+            }
+
+            if (state.bufferSize == 0)
+            {
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                RecomputeBufferSizeAfterLimit(ref state);
+                int totalBytesRead =
+                    state.totalBytesRetired + state.bufferSize + state.bufferSizeAfterLimit;
+                if (totalBytesRead < 0 || totalBytesRead > state.sizeLimit)
+                {
+                    throw InvalidProtocolBufferException.SizeLimitExceeded();
+                }
+                return true;
+            }
+        }
+
+        private bool RefillFromCodedInputStream(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state, bool mustSucceed)
+        {
+            CheckCurrentBufferIsEmpty(ref state);
+
+            if (state.totalBytesRetired + state.bufferSize == state.currentLimit)
+            {
+                // Oops, we hit a limit.
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+
+            Stream input = codedInputStream.InternalInputStream;
+
+            state.totalBytesRetired += state.bufferSize;
+
+            state.bufferPos = 0;
+            state.bufferSize = (input == null) ? 0 : input.Read(codedInputStream.InternalBuffer, 0, buffer.Length);
+            if (state.bufferSize < 0)
+            {
+                throw new InvalidOperationException("Stream.Read returned a negative count");
+            }
+            if (state.bufferSize == 0)
+            {
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                RecomputeBufferSizeAfterLimit(ref state);
+                int totalBytesRead =
+                    state.totalBytesRetired + state.bufferSize + state.bufferSizeAfterLimit;
+                if (totalBytesRead < 0 || totalBytesRead > state.sizeLimit)
+                {
+                    throw InvalidProtocolBufferException.SizeLimitExceeded();
+                }
+                return true;
+            }
+        }
+
+        private static void RecomputeBufferSizeAfterLimit(ref ParserInternalState state)
+        {
+            state.bufferSize += state.bufferSizeAfterLimit;
+            int bufferEnd = state.totalBytesRetired + state.bufferSize;
+            if (bufferEnd > state.currentLimit)
+            {
+                // Limit is in current buffer.
+                state.bufferSizeAfterLimit = bufferEnd - state.currentLimit;
+                state.bufferSize -= state.bufferSizeAfterLimit;
+            }
+            else
+            {
+                state.bufferSizeAfterLimit = 0;
+            }
+        }
+
+        private static void CheckCurrentBufferIsEmpty(ref ParserInternalState state)
+        {
+            if (state.bufferPos < state.bufferSize)
+            {
+                throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/UnknownField.cs b/csharp/src/Google.Protobuf/UnknownField.cs
index e3ce0e8..4793a64 100644
--- a/csharp/src/Google.Protobuf/UnknownField.cs
+++ b/csharp/src/Google.Protobuf/UnknownField.cs
@@ -101,8 +101,8 @@
         /// <paramref name="output"/>
         /// </summary>
         /// <param name="fieldNumber">The unknown field number.</param>
-        /// <param name="output">The CodedOutputStream to write to.</param>
-        internal void WriteTo(int fieldNumber, CodedOutputStream output)
+        /// <param name="output">The write context to write to.</param>
+        internal void WriteTo(int fieldNumber, ref WriteContext output)
         {
             if (varintList != null)
             {
@@ -141,7 +141,7 @@
                 foreach (UnknownFieldSet value in groupList)
                 {
                     output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
-                    value.WriteTo(output);
+                    value.WriteTo(ref output);
                     output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
                 }
             }
@@ -209,13 +209,13 @@
         /// <summary>
         /// Returns a new list containing all of the given specified values from
         /// both the <paramref name="current"/> and <paramref name="extras"/> lists.
-        /// If <paramref name="current" /> is null and <paramref name="extras"/> is empty,
+        /// If <paramref name="current" /> is null and <paramref name="extras"/> is null or empty,
         /// null is returned. Otherwise, either a new list is created (if <paramref name="current" />
         /// is null) or the elements of <paramref name="extras"/> are added to <paramref name="current" />.
         /// </summary>
         private static List<T> AddAll<T>(List<T> current, IList<T> extras)
         {
-            if (extras.Count == 0)
+            if (extras == null || extras.Count == 0)
             {
                 return current;
             }
diff --git a/csharp/src/Google.Protobuf/UnknownFieldSet.cs b/csharp/src/Google.Protobuf/UnknownFieldSet.cs
index 7a2b6a0..9888dd1 100644
--- a/csharp/src/Google.Protobuf/UnknownFieldSet.cs
+++ b/csharp/src/Google.Protobuf/UnknownFieldSet.cs
@@ -33,6 +33,7 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Security;
 using Google.Protobuf.Reflection;
 
 namespace Google.Protobuf
@@ -71,9 +72,26 @@
         /// </summary>
         public void WriteTo(CodedOutputStream output)
         {
+            WriteContext.Initialize(output, out WriteContext ctx);
+            try
+            {
+                WriteTo(ref ctx);
+            }
+            finally
+            {
+                ctx.CopyStateTo(output);
+            }
+        }
+
+        /// <summary>
+        /// Serializes the set and writes it to <paramref name="ctx"/>.
+        /// </summary>
+        [SecuritySafeCritical]
+        public void WriteTo(ref WriteContext ctx)
+        {
             foreach (KeyValuePair<int, UnknownField> entry in fields)
             {
-                entry.Value.WriteTo(entry.Key, output);
+                entry.Value.WriteTo(entry.Key, ref ctx);
             }
         }
 
@@ -176,47 +194,47 @@
             fields[number] = field;
             return this;
         }
-
+        
         /// <summary>
-        /// Parse a single field from <paramref name="input"/> and merge it
+        /// Parse a single field from <paramref name="ctx"/> and merge it
         /// into this set.
         /// </summary>
-        /// <param name="input">The coded input stream containing the field</param>
+        /// <param name="ctx">The parse context from which to read the field</param>
         /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
-        private bool MergeFieldFrom(CodedInputStream input)
+        private bool MergeFieldFrom(ref ParseContext ctx)
         {
-            uint tag = input.LastTag;
+            uint tag = ctx.LastTag;
             int number = WireFormat.GetTagFieldNumber(tag);
             switch (WireFormat.GetTagWireType(tag))
             {
                 case WireFormat.WireType.Varint:
                     {
-                        ulong uint64 = input.ReadUInt64();
+                        ulong uint64 = ctx.ReadUInt64();
                         GetOrAddField(number).AddVarint(uint64);
                         return true;
                     }
                 case WireFormat.WireType.Fixed32:
                     {
-                        uint uint32 = input.ReadFixed32();
+                        uint uint32 = ctx.ReadFixed32();
                         GetOrAddField(number).AddFixed32(uint32);
                         return true;
                     }
                 case WireFormat.WireType.Fixed64:
                     {
-                        ulong uint64 = input.ReadFixed64();
+                        ulong uint64 = ctx.ReadFixed64();
                         GetOrAddField(number).AddFixed64(uint64);
                         return true;
                     }
                 case WireFormat.WireType.LengthDelimited:
                     {
-                        ByteString bytes = input.ReadBytes();
+                        ByteString bytes = ctx.ReadBytes();
                         GetOrAddField(number).AddLengthDelimited(bytes);
                         return true;
                     }
                 case WireFormat.WireType.StartGroup:
                     {
                         UnknownFieldSet set = new UnknownFieldSet();
-                        input.ReadGroup(number, set);
+                        ParsingPrimitivesMessages.ReadGroup(ref ctx, number, set);
                         GetOrAddField(number).AddGroup(set);
                         return true;
                     }
@@ -229,16 +247,16 @@
             }
         }
 
-        internal void MergeGroupFrom(CodedInputStream input)
+        internal void MergeGroupFrom(ref ParseContext ctx)
         {
             while (true)
             {
-                uint tag = input.ReadTag();
+                uint tag = ctx.ReadTag();
                 if (tag == 0)
                 {
                     break;
                 }
-                if (!MergeFieldFrom(input))
+                if (!MergeFieldFrom(ref ctx))
                 {
                     break;
                 }
@@ -257,21 +275,45 @@
         public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields,
                                                      CodedInputStream input)
         {
-            if (input.DiscardUnknownFields)
+            ParseContext.Initialize(input, out ParseContext ctx);
+            try
             {
-                input.SkipLastField();
+                return MergeFieldFrom(unknownFields, ref ctx);
+            }
+            finally
+            {
+                ctx.CopyStateTo(input);
+            }
+        }
+
+        /// <summary>
+        /// Create a new UnknownFieldSet if unknownFields is null.
+        /// Parse a single field from <paramref name="ctx"/> and merge it
+        /// into unknownFields. If <paramref name="ctx"/> is configured to discard unknown fields,
+        /// <paramref name="unknownFields"/> will be returned as-is and the field will be skipped.
+        /// </summary>
+        /// <param name="unknownFields">The UnknownFieldSet which need to be merged</param>
+        /// <param name="ctx">The parse context from which to read the field</param>
+        /// <returns>The merged UnknownFieldSet</returns>
+        [SecuritySafeCritical]
+        public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields,
+                                                     ref ParseContext ctx)
+        {
+            if (ctx.DiscardUnknownFields)
+            {
+                ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state);
                 return unknownFields;
             }
             if (unknownFields == null)
             {
                 unknownFields = new UnknownFieldSet();
             }
-            if (!unknownFields.MergeFieldFrom(input))

-            {

-                throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen

+            if (!unknownFields.MergeFieldFrom(ref ctx))
+            {
+                throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen
             }
             return unknownFields;
-        }

+        }
 
         /// <summary>
         /// Merges the fields from <paramref name="other"/> into this set.
diff --git a/csharp/src/Google.Protobuf/UnsafeByteOperations.cs b/csharp/src/Google.Protobuf/UnsafeByteOperations.cs
new file mode 100644
index 0000000..865ea06
--- /dev/null
+++ b/csharp/src/Google.Protobuf/UnsafeByteOperations.cs
@@ -0,0 +1,81 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Security;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Provides a number of unsafe byte operations to be used by advanced applications with high performance
+    /// requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose
+    /// the backing buffer of a <see cref="ByteString"/> to the application.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// The methods in this class should only be called if it is guaranteed that the buffer backing the
+    /// <see cref="ByteString"/> will never change! Mutation of a <see cref="ByteString"/> can lead to unexpected
+    /// and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution!
+    /// </para>
+    /// <para>
+    /// This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In
+    /// particular, if the bytes value changes out from under a Protocol Buffer:
+    /// </para>
+    /// <list type="bullet">
+    /// <item>
+    /// <description>serialization may throw</description>
+    /// </item>
+    /// <item>
+    /// <description>serialization may succeed but the wrong bytes may be written out</description>
+    /// </item>
+    /// <item>
+    /// <description>objects that are normally immutable (such as ByteString) are no longer immutable</description>
+    /// </item>
+    /// <item>
+    /// <description>hashCode may be incorrect</description>
+    /// </item>
+    /// </list>
+    /// </remarks>
+    [SecuritySafeCritical]
+    public static class UnsafeByteOperations
+    {
+        /// <summary>
+        /// Constructs a new <see cref="ByteString" /> from the given bytes. The bytes are not copied,
+        /// and must not be modified while the <see cref="ByteString" /> is in use.
+        /// This API is experimental and subject to change.
+        /// </summary>
+        public static ByteString UnsafeWrap(ReadOnlyMemory<byte> bytes)
+        {
+            return ByteString.AttachBytes(bytes);
+        }
+    }
+}
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
index 09e0e29..7b5019a 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
@@ -25,10 +25,10 @@
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
             "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi",
-            "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQm8KE2Nv",
-            "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaJWdpdGh1Yi5jb20vZ29s",
-            "YW5nL3Byb3RvYnVmL3B0eXBlcy9hbnmiAgNHUEKqAh5Hb29nbGUuUHJvdG9i",
-            "dWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
+            "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQnYKE2Nv",
+            "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaLGdvb2dsZS5nb2xhbmcu",
+            "b3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2FueXBiogIDR1BCqgIeR29vZ2xl",
+            "LlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -78,10 +78,13 @@
   ///  Example 4: Pack and unpack a message in Go
   ///
   ///      foo := &amp;pb.Foo{...}
-  ///      any, err := ptypes.MarshalAny(foo)
+  ///      any, err := anypb.New(foo)
+  ///      if err != nil {
+  ///        ...
+  ///      }
   ///      ...
   ///      foo := &amp;pb.Foo{}
-  ///      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+  ///      if err := any.UnmarshalTo(foo); err != nil {
   ///        ...
   ///      }
   ///
@@ -119,23 +122,31 @@
   ///       "value": "1.212s"
   ///     }
   /// </summary>
-  public sealed partial class Any : pb::IMessage<Any> {
+  public sealed partial class Any : pb::IMessage<Any>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Any> _parser = new pb::MessageParser<Any>(() => new Any());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Any> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Any() {
       OnConstruction();
     }
@@ -143,6 +154,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Any(Any other) : this() {
       typeUrl_ = other.typeUrl_;
       value_ = other.value_;
@@ -150,6 +162,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Any Clone() {
       return new Any(this);
     }
@@ -187,6 +200,7 @@
     /// used with implementation specific semantics.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string TypeUrl {
       get { return typeUrl_; }
       set {
@@ -201,6 +215,7 @@
     /// Must be a valid serialized protocol buffer of the above specified type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString Value {
       get { return value_; }
       set {
@@ -209,11 +224,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Any);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Any other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -227,6 +244,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode();
@@ -238,12 +256,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (TypeUrl.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(TypeUrl);
@@ -255,9 +278,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (TypeUrl.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(TypeUrl);
+      }
+      if (Value.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteBytes(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (TypeUrl.Length != 0) {
@@ -273,6 +316,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Any other) {
       if (other == null) {
         return;
@@ -287,7 +331,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -304,8 +352,32 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            TypeUrl = input.ReadString();
+            break;
+          }
+          case 18: {
+            Value = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
index 06a9905..58a658e 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
@@ -37,10 +37,10 @@
             "ChFyZXNwb25zZV90eXBlX3VybBgEIAEoCRIaChJyZXNwb25zZV9zdHJlYW1p",
             "bmcYBSABKAgSKAoHb3B0aW9ucxgGIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5P",
             "cHRpb24SJwoGc3ludGF4GAcgASgOMhcuZ29vZ2xlLnByb3RvYnVmLlN5bnRh",
-            "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCdQoTY29t",
-            "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAVorZ29vZ2xlLmdvbGFuZy5v",
-            "cmcvZ2VucHJvdG8vcHJvdG9idWYvYXBpO2FwaaICA0dQQqoCHkdvb2dsZS5Q",
-            "cm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z"));
+            "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCdgoTY29t",
+            "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAVosZ29vZ2xlLmdvbGFuZy5v",
+            "cmcvcHJvdG9idWYvdHlwZXMva25vd24vYXBpcGKiAgNHUEKqAh5Hb29nbGUu",
+            "UHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -64,23 +64,31 @@
   /// this message itself. See https://cloud.google.com/apis/design/glossary for
   /// detailed terminology.
   /// </summary>
-  public sealed partial class Api : pb::IMessage<Api> {
+  public sealed partial class Api : pb::IMessage<Api>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Api> _parser = new pb::MessageParser<Api>(() => new Api());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Api> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Api() {
       OnConstruction();
     }
@@ -88,6 +96,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Api(Api other) : this() {
       name_ = other.name_;
       methods_ = other.methods_.Clone();
@@ -100,6 +109,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Api Clone() {
       return new Api(this);
     }
@@ -112,6 +122,7 @@
     /// followed by the interface's simple name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -128,6 +139,7 @@
     /// The methods of this interface, in unspecified order.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Method> Methods {
       get { return methods_; }
     }
@@ -141,6 +153,7 @@
     /// Any metadata attached to the interface.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
       get { return options_; }
     }
@@ -170,6 +183,7 @@
     /// experimental, non-GA interfaces.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Version {
       get { return version_; }
       set {
@@ -185,6 +199,7 @@
     /// message.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
       get { return sourceContext_; }
       set {
@@ -201,6 +216,7 @@
     /// Included interfaces. See [Mixin][].
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin> Mixins {
       get { return mixins_; }
     }
@@ -212,6 +228,7 @@
     /// The source syntax of the service.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
       get { return syntax_; }
       set {
@@ -220,11 +237,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Api);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Api other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -243,6 +262,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -259,12 +279,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -287,9 +312,40 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      methods_.WriteTo(ref output, _repeated_methods_codec);
+      options_.WriteTo(ref output, _repeated_options_codec);
+      if (Version.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(Version);
+      }
+      if (sourceContext_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(SourceContext);
+      }
+      mixins_.WriteTo(ref output, _repeated_mixins_codec);
+      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) {
+        output.WriteRawTag(56);
+        output.WriteEnum((int) Syntax);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -314,6 +370,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Api other) {
       if (other == null) {
         return;
@@ -340,7 +397,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -380,30 +441,85 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            methods_.AddEntriesFrom(ref input, _repeated_methods_codec);
+            break;
+          }
+          case 26: {
+            options_.AddEntriesFrom(ref input, _repeated_options_codec);
+            break;
+          }
+          case 34: {
+            Version = input.ReadString();
+            break;
+          }
+          case 42: {
+            if (sourceContext_ == null) {
+              SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(SourceContext);
+            break;
+          }
+          case 50: {
+            mixins_.AddEntriesFrom(ref input, _repeated_mixins_codec);
+            break;
+          }
+          case 56: {
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Method represents a method of an API interface.
   /// </summary>
-  public sealed partial class Method : pb::IMessage<Method> {
+  public sealed partial class Method : pb::IMessage<Method>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Method> _parser = new pb::MessageParser<Method>(() => new Method());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Method> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Method() {
       OnConstruction();
     }
@@ -411,6 +527,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Method(Method other) : this() {
       name_ = other.name_;
       requestTypeUrl_ = other.requestTypeUrl_;
@@ -423,6 +540,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Method Clone() {
       return new Method(this);
     }
@@ -434,6 +552,7 @@
     /// The simple name of this method.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -448,6 +567,7 @@
     /// A URL of the input message type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string RequestTypeUrl {
       get { return requestTypeUrl_; }
       set {
@@ -462,6 +582,7 @@
     /// If true, the request is streamed.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool RequestStreaming {
       get { return requestStreaming_; }
       set {
@@ -476,6 +597,7 @@
     /// The URL of the output message type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string ResponseTypeUrl {
       get { return responseTypeUrl_; }
       set {
@@ -490,6 +612,7 @@
     /// If true, the response is streamed.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool ResponseStreaming {
       get { return responseStreaming_; }
       set {
@@ -506,6 +629,7 @@
     /// Any metadata attached to the method.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
       get { return options_; }
     }
@@ -517,6 +641,7 @@
     /// The source syntax of this method.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
       get { return syntax_; }
       set {
@@ -525,11 +650,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Method);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Method other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -548,6 +675,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -564,12 +692,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -598,9 +731,46 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (RequestTypeUrl.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(RequestTypeUrl);
+      }
+      if (RequestStreaming != false) {
+        output.WriteRawTag(24);
+        output.WriteBool(RequestStreaming);
+      }
+      if (ResponseTypeUrl.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(ResponseTypeUrl);
+      }
+      if (ResponseStreaming != false) {
+        output.WriteRawTag(40);
+        output.WriteBool(ResponseStreaming);
+      }
+      options_.WriteTo(ref output, _repeated_options_codec);
+      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) {
+        output.WriteRawTag(56);
+        output.WriteEnum((int) Syntax);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -629,6 +799,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Method other) {
       if (other == null) {
         return;
@@ -656,7 +827,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -693,8 +868,52 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            RequestTypeUrl = input.ReadString();
+            break;
+          }
+          case 24: {
+            RequestStreaming = input.ReadBool();
+            break;
+          }
+          case 34: {
+            ResponseTypeUrl = input.ReadString();
+            break;
+          }
+          case 40: {
+            ResponseStreaming = input.ReadBool();
+            break;
+          }
+          case 50: {
+            options_.AddEntriesFrom(ref input, _repeated_options_codec);
+            break;
+          }
+          case 56: {
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -745,7 +964,7 @@
   /// The mixin construct implies that all methods in `AccessControl` are
   /// also declared with same name and request/response types in
   /// `Storage`. A documentation generator or annotation processor will
-  /// see the effective `Storage.GetAcl` method after inherting
+  /// see the effective `Storage.GetAcl` method after inheriting
   /// documentation and annotations as follows:
   ///
   ///     service Storage {
@@ -777,23 +996,31 @@
   ///       ...
   ///     }
   /// </summary>
-  public sealed partial class Mixin : pb::IMessage<Mixin> {
+  public sealed partial class Mixin : pb::IMessage<Mixin>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Mixin> _parser = new pb::MessageParser<Mixin>(() => new Mixin());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Mixin> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Mixin() {
       OnConstruction();
     }
@@ -801,6 +1028,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Mixin(Mixin other) : this() {
       name_ = other.name_;
       root_ = other.root_;
@@ -808,6 +1036,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Mixin Clone() {
       return new Mixin(this);
     }
@@ -819,6 +1048,7 @@
     /// The fully qualified name of the interface which is included.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -834,6 +1064,7 @@
     /// are rooted.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Root {
       get { return root_; }
       set {
@@ -842,11 +1073,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Mixin);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Mixin other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -860,6 +1093,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -871,12 +1105,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -888,9 +1127,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Root.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(Root);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -906,6 +1165,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Mixin other) {
       if (other == null) {
         return;
@@ -920,7 +1180,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -937,8 +1201,32 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            Root = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
index f0078c4..b46f4d2 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
@@ -26,10 +26,10 @@
           string.Concat(
             "Ch5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8SD2dvb2dsZS5wcm90",
             "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg",
-            "ASgFQnwKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAVoq",
-            "Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL2R1cmF0aW9u+AEB",
-            "ogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90",
-            "bzM="));
+            "ASgFQoMBChNjb20uZ29vZ2xlLnByb3RvYnVmQg1EdXJhdGlvblByb3RvUAFa",
+            "MWdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2R1cmF0",
+            "aW9ucGL4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw",
+            "ZXNiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -100,23 +100,31 @@
   /// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
   /// microsecond should be expressed in JSON format as "3.000001s".
   /// </summary>
-  public sealed partial class Duration : pb::IMessage<Duration> {
+  public sealed partial class Duration : pb::IMessage<Duration>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Duration> _parser = new pb::MessageParser<Duration>(() => new Duration());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Duration> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Duration() {
       OnConstruction();
     }
@@ -124,6 +132,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Duration(Duration other) : this() {
       seconds_ = other.seconds_;
       nanos_ = other.nanos_;
@@ -131,6 +140,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Duration Clone() {
       return new Duration(this);
     }
@@ -144,6 +154,7 @@
     /// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Seconds {
       get { return seconds_; }
       set {
@@ -163,6 +174,7 @@
     /// to +999,999,999 inclusive.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Nanos {
       get { return nanos_; }
       set {
@@ -171,11 +183,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Duration);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Duration other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -189,6 +203,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
@@ -200,12 +215,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Seconds != 0L) {
         output.WriteRawTag(8);
         output.WriteInt64(Seconds);
@@ -217,9 +237,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Seconds != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Seconds);
+      }
+      if (Nanos != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Nanos);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Seconds != 0L) {
@@ -235,6 +275,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Duration other) {
       if (other == null) {
         return;
@@ -249,7 +290,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -266,8 +311,32 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Seconds = input.ReadInt64();
+            break;
+          }
+          case 16: {
+            Nanos = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
index fa435cd..073b59e 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
@@ -25,10 +25,10 @@
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
             "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1",
-            "ZiIHCgVFbXB0eUJ2ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv",
-            "UAFaJ2dpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy9lbXB0efgB",
-            "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv",
-            "dG8z"));
+            "ZiIHCgVFbXB0eUJ9ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv",
+            "UAFaLmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2Vt",
+            "cHR5cGL4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw",
+            "ZXNiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -50,23 +50,31 @@
   ///
   /// The JSON representation for `Empty` is empty JSON object `{}`.
   /// </summary>
-  public sealed partial class Empty : pb::IMessage<Empty> {
+  public sealed partial class Empty : pb::IMessage<Empty>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Empty> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Empty() {
       OnConstruction();
     }
@@ -74,21 +82,25 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Empty(Empty other) : this() {
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Empty Clone() {
       return new Empty(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Empty);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Empty other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -100,6 +112,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (_unknownFields != null) {
@@ -109,18 +122,35 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (_unknownFields != null) {
@@ -130,6 +160,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Empty other) {
       if (other == null) {
         return;
@@ -138,7 +169,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -147,8 +182,24 @@
             break;
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
index 00e1e9f..e90c3d5 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
@@ -25,11 +25,10 @@
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
             "CiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxIPZ29vZ2xlLnBy",
-            "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUKMAQoTY29tLmdv",
-            "b2dsZS5wcm90b2J1ZkIORmllbGRNYXNrUHJvdG9QAVo5Z29vZ2xlLmdvbGFu",
-            "Zy5vcmcvZ2VucHJvdG8vcHJvdG9idWYvZmllbGRfbWFzaztmaWVsZF9tYXNr",
-            "+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZw",
-            "cm90bzM="));
+            "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUKFAQoTY29tLmdv",
+            "b2dsZS5wcm90b2J1ZkIORmllbGRNYXNrUHJvdG9QAVoyZ29vZ2xlLmdvbGFu",
+            "Zy5vcmcvcHJvdG9idWYvdHlwZXMva25vd24vZmllbGRtYXNrcGL4AQGiAgNH",
+            "UEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -240,23 +239,31 @@
   /// request should verify the included field paths, and return an
   /// `INVALID_ARGUMENT` error if any path is unmappable.
   /// </summary>
-  public sealed partial class FieldMask : pb::IMessage<FieldMask> {
+  public sealed partial class FieldMask : pb::IMessage<FieldMask>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FieldMask> _parser = new pb::MessageParser<FieldMask>(() => new FieldMask());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FieldMask> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldMask() {
       OnConstruction();
     }
@@ -264,12 +271,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldMask(FieldMask other) : this() {
       paths_ = other.paths_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FieldMask Clone() {
       return new FieldMask(this);
     }
@@ -283,16 +292,19 @@
     /// The set of field mask paths.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> Paths {
       get { return paths_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FieldMask);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FieldMask other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -305,6 +317,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= paths_.GetHashCode();
@@ -315,19 +328,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       paths_.WriteTo(output, _repeated_paths_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      paths_.WriteTo(ref output, _repeated_paths_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += paths_.CalculateSize(_repeated_paths_codec);
@@ -338,6 +369,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FieldMask other) {
       if (other == null) {
         return;
@@ -347,7 +379,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -360,8 +396,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            paths_.AddEntriesFrom(ref input, _repeated_paths_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
index d707619..58c23ce 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
@@ -26,10 +26,10 @@
           string.Concat(
             "CiRnb29nbGUvcHJvdG9idWYvc291cmNlX2NvbnRleHQucHJvdG8SD2dvb2ds",
             "ZS5wcm90b2J1ZiIiCg1Tb3VyY2VDb250ZXh0EhEKCWZpbGVfbmFtZRgBIAEo",
-            "CUKVAQoTY29tLmdvb2dsZS5wcm90b2J1ZkISU291cmNlQ29udGV4dFByb3Rv",
-            "UAFaQWdvb2dsZS5nb2xhbmcub3JnL2dlbnByb3RvL3Byb3RvYnVmL3NvdXJj",
-            "ZV9jb250ZXh0O3NvdXJjZV9jb250ZXh0ogIDR1BCqgIeR29vZ2xlLlByb3Rv",
-            "YnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM="));
+            "CUKKAQoTY29tLmdvb2dsZS5wcm90b2J1ZkISU291cmNlQ29udGV4dFByb3Rv",
+            "UAFaNmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3Nv",
+            "dXJjZWNvbnRleHRwYqICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25v",
+            "d25UeXBlc2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -44,23 +44,31 @@
   /// `SourceContext` represents information about the source of a
   /// protobuf element, like the file in which it is defined.
   /// </summary>
-  public sealed partial class SourceContext : pb::IMessage<SourceContext> {
+  public sealed partial class SourceContext : pb::IMessage<SourceContext>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<SourceContext> _parser = new pb::MessageParser<SourceContext>(() => new SourceContext());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<SourceContext> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SourceContext() {
       OnConstruction();
     }
@@ -68,12 +76,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SourceContext(SourceContext other) : this() {
       fileName_ = other.fileName_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public SourceContext Clone() {
       return new SourceContext(this);
     }
@@ -86,6 +96,7 @@
     /// protobuf element.  For example: `"google/protobuf/source_context.proto"`.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string FileName {
       get { return fileName_; }
       set {
@@ -94,11 +105,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as SourceContext);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(SourceContext other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -111,6 +124,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (FileName.Length != 0) hash ^= FileName.GetHashCode();
@@ -121,12 +135,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (FileName.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(FileName);
@@ -134,9 +153,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (FileName.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(FileName);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (FileName.Length != 0) {
@@ -149,6 +184,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(SourceContext other) {
       if (other == null) {
         return;
@@ -160,7 +196,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -173,8 +213,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            FileName = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
index b1dbe23..b32b76c 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
@@ -35,10 +35,10 @@
             "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW",
             "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW",
             "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W",
-            "QUxVRRAAQoEBChNjb20uZ29vZ2xlLnByb3RvYnVmQgtTdHJ1Y3RQcm90b1AB",
-            "WjFnaXRodWIuY29tL2dvbGFuZy9wcm90b2J1Zi9wdHlwZXMvc3RydWN0O3N0",
-            "cnVjdHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5",
-            "cGVzYgZwcm90bzM="));
+            "QUxVRRAAQn8KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAFa",
+            "L2dvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3N0cnVj",
+            "dHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVz",
+            "YgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, null, new pbr::GeneratedClrTypeInfo[] {
@@ -77,23 +77,31 @@
   ///
   /// The JSON representation for `Struct` is JSON object.
   /// </summary>
-  public sealed partial class Struct : pb::IMessage<Struct> {
+  public sealed partial class Struct : pb::IMessage<Struct>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Struct> _parser = new pb::MessageParser<Struct>(() => new Struct());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Struct> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Struct() {
       OnConstruction();
     }
@@ -101,12 +109,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Struct(Struct other) : this() {
       fields_ = other.fields_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Struct Clone() {
       return new Struct(this);
     }
@@ -120,16 +130,19 @@
     /// Unordered map of dynamically typed values.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value> Fields {
       get { return fields_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Struct);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Struct other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -142,6 +155,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Fields.GetHashCode();
@@ -152,19 +166,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       fields_.WriteTo(output, _map_fields_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      fields_.WriteTo(ref output, _map_fields_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += fields_.CalculateSize(_map_fields_codec);
@@ -175,6 +207,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Struct other) {
       if (other == null) {
         return;
@@ -184,7 +217,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -197,8 +234,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            fields_.AddEntriesFrom(ref input, _map_fields_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -209,23 +266,31 @@
   ///
   /// The JSON representation for `Value` is JSON value.
   /// </summary>
-  public sealed partial class Value : pb::IMessage<Value> {
+  public sealed partial class Value : pb::IMessage<Value>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Value> _parser = new pb::MessageParser<Value>(() => new Value());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Value> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Value() {
       OnConstruction();
     }
@@ -233,6 +298,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Value(Value other) : this() {
       switch (other.KindCase) {
         case KindOneofCase.NullValue:
@@ -259,6 +325,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Value Clone() {
       return new Value(this);
     }
@@ -269,6 +336,7 @@
     /// Represents a null value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.NullValue NullValue {
       get { return kindCase_ == KindOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) kind_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; }
       set {
@@ -283,6 +351,7 @@
     /// Represents a double value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double NumberValue {
       get { return kindCase_ == KindOneofCase.NumberValue ? (double) kind_ : 0D; }
       set {
@@ -297,6 +366,7 @@
     /// Represents a string value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string StringValue {
       get { return kindCase_ == KindOneofCase.StringValue ? (string) kind_ : ""; }
       set {
@@ -311,6 +381,7 @@
     /// Represents a boolean value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool BoolValue {
       get { return kindCase_ == KindOneofCase.BoolValue ? (bool) kind_ : false; }
       set {
@@ -325,6 +396,7 @@
     /// Represents a structured value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Struct StructValue {
       get { return kindCase_ == KindOneofCase.StructValue ? (global::Google.Protobuf.WellKnownTypes.Struct) kind_ : null; }
       set {
@@ -339,6 +411,7 @@
     /// Represents a repeated `Value`.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.ListValue ListValue {
       get { return kindCase_ == KindOneofCase.ListValue ? (global::Google.Protobuf.WellKnownTypes.ListValue) kind_ : null; }
       set {
@@ -360,22 +433,26 @@
     }
     private KindOneofCase kindCase_ = KindOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public KindOneofCase KindCase {
       get { return kindCase_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void ClearKind() {
       kindCase_ = KindOneofCase.None;
       kind_ = null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Value);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Value other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -394,6 +471,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (kindCase_ == KindOneofCase.NullValue) hash ^= NullValue.GetHashCode();
@@ -410,12 +488,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (kindCase_ == KindOneofCase.NullValue) {
         output.WriteRawTag(8);
         output.WriteEnum((int) NullValue);
@@ -443,9 +526,45 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (kindCase_ == KindOneofCase.NullValue) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) NullValue);
+      }
+      if (kindCase_ == KindOneofCase.NumberValue) {
+        output.WriteRawTag(17);
+        output.WriteDouble(NumberValue);
+      }
+      if (kindCase_ == KindOneofCase.StringValue) {
+        output.WriteRawTag(26);
+        output.WriteString(StringValue);
+      }
+      if (kindCase_ == KindOneofCase.BoolValue) {
+        output.WriteRawTag(32);
+        output.WriteBool(BoolValue);
+      }
+      if (kindCase_ == KindOneofCase.StructValue) {
+        output.WriteRawTag(42);
+        output.WriteMessage(StructValue);
+      }
+      if (kindCase_ == KindOneofCase.ListValue) {
+        output.WriteRawTag(50);
+        output.WriteMessage(ListValue);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (kindCase_ == KindOneofCase.NullValue) {
@@ -473,6 +592,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Value other) {
       if (other == null) {
         return;
@@ -508,7 +628,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -552,8 +676,59 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            kind_ = input.ReadEnum();
+            kindCase_ = KindOneofCase.NullValue;
+            break;
+          }
+          case 17: {
+            NumberValue = input.ReadDouble();
+            break;
+          }
+          case 26: {
+            StringValue = input.ReadString();
+            break;
+          }
+          case 32: {
+            BoolValue = input.ReadBool();
+            break;
+          }
+          case 42: {
+            global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct();
+            if (kindCase_ == KindOneofCase.StructValue) {
+              subBuilder.MergeFrom(StructValue);
+            }
+            input.ReadMessage(subBuilder);
+            StructValue = subBuilder;
+            break;
+          }
+          case 50: {
+            global::Google.Protobuf.WellKnownTypes.ListValue subBuilder = new global::Google.Protobuf.WellKnownTypes.ListValue();
+            if (kindCase_ == KindOneofCase.ListValue) {
+              subBuilder.MergeFrom(ListValue);
+            }
+            input.ReadMessage(subBuilder);
+            ListValue = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -561,23 +736,31 @@
   ///
   /// The JSON representation for `ListValue` is JSON array.
   /// </summary>
-  public sealed partial class ListValue : pb::IMessage<ListValue> {
+  public sealed partial class ListValue : pb::IMessage<ListValue>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<ListValue> _parser = new pb::MessageParser<ListValue>(() => new ListValue());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<ListValue> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ListValue() {
       OnConstruction();
     }
@@ -585,12 +768,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ListValue(ListValue other) : this() {
       values_ = other.values_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ListValue Clone() {
       return new ListValue(this);
     }
@@ -604,16 +789,19 @@
     /// Repeated field of dynamically typed values.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> Values {
       get { return values_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as ListValue);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(ListValue other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -626,6 +814,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= values_.GetHashCode();
@@ -636,19 +825,37 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       values_.WriteTo(output, _repeated_values_codec);
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      values_.WriteTo(ref output, _repeated_values_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       size += values_.CalculateSize(_repeated_values_codec);
@@ -659,6 +866,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(ListValue other) {
       if (other == null) {
         return;
@@ -668,7 +876,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -681,8 +893,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            values_.AddEntriesFrom(ref input, _repeated_values_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
index 12f4812..e981dc2 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
@@ -26,10 +26,10 @@
           string.Concat(
             "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv",
             "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY",
-            "AiABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q",
-            "AVorZ2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL3RpbWVzdGFt",
-            "cPgBAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG",
-            "cHJvdG8z"));
+            "AiABKAVChQEKE2NvbS5nb29nbGUucHJvdG9idWZCDlRpbWVzdGFtcFByb3Rv",
+            "UAFaMmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3Rp",
+            "bWVzdGFtcHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93",
+            "blR5cGVzYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -91,7 +91,15 @@
   ///     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
   ///         .setNanos((int) ((millis % 1000) * 1000000)).build();
   ///
-  /// Example 5: Compute Timestamp from current time in Python.
+  /// Example 5: Compute Timestamp from Java `Instant.now()`.
+  ///
+  ///     Instant now = Instant.now();
+  ///
+  ///     Timestamp timestamp =
+  ///         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
+  ///             .setNanos(now.getNano()).build();
+  ///
+  /// Example 6: Compute Timestamp from current time in Python.
   ///
   ///     timestamp = Timestamp()
   ///     timestamp.GetCurrentTime()
@@ -123,23 +131,31 @@
   /// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
   /// ) to obtain a formatter capable of generating timestamps in this format.
   /// </summary>
-  public sealed partial class Timestamp : pb::IMessage<Timestamp> {
+  public sealed partial class Timestamp : pb::IMessage<Timestamp>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Timestamp> _parser = new pb::MessageParser<Timestamp>(() => new Timestamp());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Timestamp> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Timestamp() {
       OnConstruction();
     }
@@ -147,6 +163,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Timestamp(Timestamp other) : this() {
       seconds_ = other.seconds_;
       nanos_ = other.nanos_;
@@ -154,6 +171,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Timestamp Clone() {
       return new Timestamp(this);
     }
@@ -167,6 +185,7 @@
     /// 9999-12-31T23:59:59Z inclusive.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Seconds {
       get { return seconds_; }
       set {
@@ -184,6 +203,7 @@
     /// inclusive.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Nanos {
       get { return nanos_; }
       set {
@@ -192,11 +212,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Timestamp);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Timestamp other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -210,6 +232,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
@@ -221,12 +244,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Seconds != 0L) {
         output.WriteRawTag(8);
         output.WriteInt64(Seconds);
@@ -238,9 +266,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Seconds != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Seconds);
+      }
+      if (Nanos != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Nanos);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Seconds != 0L) {
@@ -256,6 +304,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Timestamp other) {
       if (other == null) {
         return;
@@ -270,7 +319,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -287,8 +340,32 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Seconds = input.ReadInt64();
+            break;
+          }
+          case 16: {
+            Nanos = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
index bfd4b8e..120f31a 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
@@ -56,10 +56,10 @@
             "ASgFEigKB29wdGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9u",
             "IjsKBk9wdGlvbhIMCgRuYW1lGAEgASgJEiMKBXZhbHVlGAIgASgLMhQuZ29v",
             "Z2xlLnByb3RvYnVmLkFueSouCgZTeW50YXgSEQoNU1lOVEFYX1BST1RPMhAA",
-            "EhEKDVNZTlRBWF9QUk9UTzMQAUJ9ChNjb20uZ29vZ2xlLnByb3RvYnVmQglU",
-            "eXBlUHJvdG9QAVovZ29vZ2xlLmdvbGFuZy5vcmcvZ2VucHJvdG8vcHJvdG9i",
-            "dWYvcHR5cGU7cHR5cGX4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2Vs",
-            "bEtub3duVHlwZXNiBnByb3RvMw=="));
+            "EhEKDVNZTlRBWF9QUk9UTzMQAUJ7ChNjb20uZ29vZ2xlLnByb3RvYnVmQglU",
+            "eXBlUHJvdG9QAVotZ29vZ2xlLmdvbGFuZy5vcmcvcHJvdG9idWYvdHlwZXMv",
+            "a25vd24vdHlwZXBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxL",
+            "bm93blR5cGVzYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, null, new pbr::GeneratedClrTypeInfo[] {
@@ -94,23 +94,31 @@
   /// <summary>
   /// A protocol buffer message type.
   /// </summary>
-  public sealed partial class Type : pb::IMessage<Type> {
+  public sealed partial class Type : pb::IMessage<Type>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Type> _parser = new pb::MessageParser<Type>(() => new Type());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Type> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Type() {
       OnConstruction();
     }
@@ -118,6 +126,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Type(Type other) : this() {
       name_ = other.name_;
       fields_ = other.fields_.Clone();
@@ -129,6 +138,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Type Clone() {
       return new Type(this);
     }
@@ -140,6 +150,7 @@
     /// The fully qualified message name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -156,6 +167,7 @@
     /// The list of fields.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Field> Fields {
       get { return fields_; }
     }
@@ -169,6 +181,7 @@
     /// The list of types appearing in `oneof` definitions in this type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<string> Oneofs {
       get { return oneofs_; }
     }
@@ -182,6 +195,7 @@
     /// The protocol buffer options.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
       get { return options_; }
     }
@@ -193,6 +207,7 @@
     /// The source context.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
       get { return sourceContext_; }
       set {
@@ -207,6 +222,7 @@
     /// The source syntax.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
       get { return syntax_; }
       set {
@@ -215,11 +231,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Type);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Type other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -237,6 +255,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -252,12 +271,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -276,9 +300,36 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      fields_.WriteTo(ref output, _repeated_fields_codec);
+      oneofs_.WriteTo(ref output, _repeated_oneofs_codec);
+      options_.WriteTo(ref output, _repeated_options_codec);
+      if (sourceContext_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(SourceContext);
+      }
+      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) {
+        output.WriteRawTag(48);
+        output.WriteEnum((int) Syntax);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -300,6 +351,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Type other) {
       if (other == null) {
         return;
@@ -323,7 +375,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -359,30 +415,81 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            fields_.AddEntriesFrom(ref input, _repeated_fields_codec);
+            break;
+          }
+          case 26: {
+            oneofs_.AddEntriesFrom(ref input, _repeated_oneofs_codec);
+            break;
+          }
+          case 34: {
+            options_.AddEntriesFrom(ref input, _repeated_options_codec);
+            break;
+          }
+          case 42: {
+            if (sourceContext_ == null) {
+              SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(SourceContext);
+            break;
+          }
+          case 48: {
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// A single field of a message type.
   /// </summary>
-  public sealed partial class Field : pb::IMessage<Field> {
+  public sealed partial class Field : pb::IMessage<Field>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Field> _parser = new pb::MessageParser<Field>(() => new Field());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Field> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Field() {
       OnConstruction();
     }
@@ -390,6 +497,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Field(Field other) : this() {
       kind_ = other.kind_;
       cardinality_ = other.cardinality_;
@@ -405,6 +513,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Field Clone() {
       return new Field(this);
     }
@@ -416,6 +525,7 @@
     /// The field type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Field.Types.Kind Kind {
       get { return kind_; }
       set {
@@ -430,6 +540,7 @@
     /// The field cardinality.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality Cardinality {
       get { return cardinality_; }
       set {
@@ -444,6 +555,7 @@
     /// The field number.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Number {
       get { return number_; }
       set {
@@ -458,6 +570,7 @@
     /// The field name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -473,6 +586,7 @@
     /// types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string TypeUrl {
       get { return typeUrl_; }
       set {
@@ -488,6 +602,7 @@
     /// types. The first type has index 1; zero means the type is not in the list.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int OneofIndex {
       get { return oneofIndex_; }
       set {
@@ -502,6 +617,7 @@
     /// Whether to use alternative packed wire representation.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Packed {
       get { return packed_; }
       set {
@@ -518,6 +634,7 @@
     /// The protocol buffer options.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
       get { return options_; }
     }
@@ -529,6 +646,7 @@
     /// The field JSON name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string JsonName {
       get { return jsonName_; }
       set {
@@ -543,6 +661,7 @@
     /// The string value of the default value of this field. Proto2 syntax only.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string DefaultValue {
       get { return defaultValue_; }
       set {
@@ -551,11 +670,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Field);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Field other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -577,6 +698,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) hash ^= Kind.GetHashCode();
@@ -596,12 +718,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Kind);
@@ -642,9 +769,58 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Kind);
+      }
+      if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown) {
+        output.WriteRawTag(16);
+        output.WriteEnum((int) Cardinality);
+      }
+      if (Number != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Number);
+      }
+      if (Name.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(Name);
+      }
+      if (TypeUrl.Length != 0) {
+        output.WriteRawTag(50);
+        output.WriteString(TypeUrl);
+      }
+      if (OneofIndex != 0) {
+        output.WriteRawTag(56);
+        output.WriteInt32(OneofIndex);
+      }
+      if (Packed != false) {
+        output.WriteRawTag(64);
+        output.WriteBool(Packed);
+      }
+      options_.WriteTo(ref output, _repeated_options_codec);
+      if (JsonName.Length != 0) {
+        output.WriteRawTag(82);
+        output.WriteString(JsonName);
+      }
+      if (DefaultValue.Length != 0) {
+        output.WriteRawTag(90);
+        output.WriteString(DefaultValue);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) {
@@ -682,6 +858,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Field other) {
       if (other == null) {
         return;
@@ -718,7 +895,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -767,11 +948,68 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Kind = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
+            break;
+          }
+          case 16: {
+            Cardinality = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum();
+            break;
+          }
+          case 24: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 34: {
+            Name = input.ReadString();
+            break;
+          }
+          case 50: {
+            TypeUrl = input.ReadString();
+            break;
+          }
+          case 56: {
+            OneofIndex = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            Packed = input.ReadBool();
+            break;
+          }
+          case 74: {
+            options_.AddEntriesFrom(ref input, _repeated_options_codec);
+            break;
+          }
+          case 82: {
+            JsonName = input.ReadString();
+            break;
+          }
+          case 90: {
+            DefaultValue = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
     #region Nested types
     /// <summary>Container for nested types declared in the Field message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static partial class Types {
       /// <summary>
       /// Basic field types.
@@ -885,23 +1123,31 @@
   /// <summary>
   /// Enum type definition.
   /// </summary>
-  public sealed partial class Enum : pb::IMessage<Enum> {
+  public sealed partial class Enum : pb::IMessage<Enum>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Enum> _parser = new pb::MessageParser<Enum>(() => new Enum());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Enum> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Enum() {
       OnConstruction();
     }
@@ -909,6 +1155,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Enum(Enum other) : this() {
       name_ = other.name_;
       enumvalue_ = other.enumvalue_.Clone();
@@ -919,6 +1166,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Enum Clone() {
       return new Enum(this);
     }
@@ -930,6 +1178,7 @@
     /// Enum type name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -946,6 +1195,7 @@
     /// Enum value definitions.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.EnumValue> Enumvalue {
       get { return enumvalue_; }
     }
@@ -959,6 +1209,7 @@
     /// Protocol buffer options.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
       get { return options_; }
     }
@@ -970,6 +1221,7 @@
     /// The source context.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContext {
       get { return sourceContext_; }
       set {
@@ -984,6 +1236,7 @@
     /// The source syntax.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
       get { return syntax_; }
       set {
@@ -992,11 +1245,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Enum);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Enum other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1013,6 +1268,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -1027,12 +1283,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -1050,9 +1311,35 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      enumvalue_.WriteTo(ref output, _repeated_enumvalue_codec);
+      options_.WriteTo(ref output, _repeated_options_codec);
+      if (sourceContext_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(SourceContext);
+      }
+      if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) Syntax);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -1073,6 +1360,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Enum other) {
       if (other == null) {
         return;
@@ -1095,7 +1383,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1127,30 +1419,77 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            enumvalue_.AddEntriesFrom(ref input, _repeated_enumvalue_codec);
+            break;
+          }
+          case 26: {
+            options_.AddEntriesFrom(ref input, _repeated_options_codec);
+            break;
+          }
+          case 34: {
+            if (sourceContext_ == null) {
+              SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(SourceContext);
+            break;
+          }
+          case 40: {
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// Enum value definition.
   /// </summary>
-  public sealed partial class EnumValue : pb::IMessage<EnumValue> {
+  public sealed partial class EnumValue : pb::IMessage<EnumValue>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<EnumValue> _parser = new pb::MessageParser<EnumValue>(() => new EnumValue());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<EnumValue> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValue() {
       OnConstruction();
     }
@@ -1158,6 +1497,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValue(EnumValue other) : this() {
       name_ = other.name_;
       number_ = other.number_;
@@ -1166,6 +1506,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public EnumValue Clone() {
       return new EnumValue(this);
     }
@@ -1177,6 +1518,7 @@
     /// Enum value name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -1191,6 +1533,7 @@
     /// Enum value number.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Number {
       get { return number_; }
       set {
@@ -1207,16 +1550,19 @@
     /// Protocol buffer options.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
       get { return options_; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as EnumValue);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(EnumValue other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1231,6 +1577,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -1243,12 +1590,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -1261,9 +1613,30 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Number != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Number);
+      }
+      options_.WriteTo(ref output, _repeated_options_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -1280,6 +1653,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(EnumValue other) {
       if (other == null) {
         return;
@@ -1295,7 +1669,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1316,31 +1694,67 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            Number = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            options_.AddEntriesFrom(ref input, _repeated_options_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
   /// A protocol buffer option, which can be attached to a message, field,
   /// enumeration, etc.
   /// </summary>
-  public sealed partial class Option : pb::IMessage<Option> {
+  public sealed partial class Option : pb::IMessage<Option>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Option> _parser = new pb::MessageParser<Option>(() => new Option());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Option> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Option() {
       OnConstruction();
     }
@@ -1348,6 +1762,7 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Option(Option other) : this() {
       name_ = other.name_;
       value_ = other.value_ != null ? other.value_.Clone() : null;
@@ -1355,6 +1770,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Option Clone() {
       return new Option(this);
     }
@@ -1369,6 +1785,7 @@
     /// `"google.api.http"`.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Name {
       get { return name_; }
       set {
@@ -1386,6 +1803,7 @@
     /// value using the google.protobuf.Int32Value type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public global::Google.Protobuf.WellKnownTypes.Any Value {
       get { return value_; }
       set {
@@ -1394,11 +1812,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Option);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Option other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1412,6 +1832,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
@@ -1423,12 +1844,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Name.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Name);
@@ -1440,9 +1866,29 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (value_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Name.Length != 0) {
@@ -1458,6 +1904,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Option other) {
       if (other == null) {
         return;
@@ -1475,7 +1922,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1495,8 +1946,35 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 18: {
+            if (value_ == null) {
+              Value = new global::Google.Protobuf.WellKnownTypes.Any();
+            }
+            input.ReadMessage(Value);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
index 556af3c..29c04b3 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
@@ -30,10 +30,11 @@
             "KAMiHAoLVUludDY0VmFsdWUSDQoFdmFsdWUYASABKAQiGwoKSW50MzJWYWx1",
             "ZRINCgV2YWx1ZRgBIAEoBSIcCgtVSW50MzJWYWx1ZRINCgV2YWx1ZRgBIAEo",
             "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS",
-            "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJ8",
-            "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAFaKmdpdGh1",
-            "Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy93cmFwcGVyc/gBAaICA0dQ",
-            "QqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z"));
+            "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEKD",
+            "AQoTY29tLmdvb2dsZS5wcm90b2J1ZkINV3JhcHBlcnNQcm90b1ABWjFnb29n",
+            "bGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9rbm93bi93cmFwcGVyc3Bi",
+            "+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZw",
+            "cm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -57,23 +58,31 @@
   ///
   /// The JSON representation for `DoubleValue` is JSON number.
   /// </summary>
-  public sealed partial class DoubleValue : pb::IMessage<DoubleValue> {
+  public sealed partial class DoubleValue : pb::IMessage<DoubleValue>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<DoubleValue> _parser = new pb::MessageParser<DoubleValue>(() => new DoubleValue());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<DoubleValue> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[0]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DoubleValue() {
       OnConstruction();
     }
@@ -81,12 +90,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DoubleValue(DoubleValue other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public DoubleValue Clone() {
       return new DoubleValue(this);
     }
@@ -98,6 +109,7 @@
     /// The double value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public double Value {
       get { return value_; }
       set {
@@ -106,11 +118,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as DoubleValue);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(DoubleValue other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -123,6 +137,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Value);
@@ -133,12 +148,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != 0D) {
         output.WriteRawTag(9);
         output.WriteDouble(Value);
@@ -146,9 +166,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != 0D) {
@@ -161,6 +197,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(DoubleValue other) {
       if (other == null) {
         return;
@@ -172,7 +209,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -185,8 +226,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 9: {
+            Value = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -194,23 +255,31 @@
   ///
   /// The JSON representation for `FloatValue` is JSON number.
   /// </summary>
-  public sealed partial class FloatValue : pb::IMessage<FloatValue> {
+  public sealed partial class FloatValue : pb::IMessage<FloatValue>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<FloatValue> _parser = new pb::MessageParser<FloatValue>(() => new FloatValue());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<FloatValue> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[1]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FloatValue() {
       OnConstruction();
     }
@@ -218,12 +287,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FloatValue(FloatValue other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public FloatValue Clone() {
       return new FloatValue(this);
     }
@@ -235,6 +306,7 @@
     /// The float value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public float Value {
       get { return value_; }
       set {
@@ -243,11 +315,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as FloatValue);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(FloatValue other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -260,6 +334,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(Value);
@@ -270,12 +345,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != 0F) {
         output.WriteRawTag(13);
         output.WriteFloat(Value);
@@ -283,9 +363,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != 0F) {
+        output.WriteRawTag(13);
+        output.WriteFloat(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != 0F) {
@@ -298,6 +394,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(FloatValue other) {
       if (other == null) {
         return;
@@ -309,7 +406,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -322,8 +423,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 13: {
+            Value = input.ReadFloat();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -331,23 +452,31 @@
   ///
   /// The JSON representation for `Int64Value` is JSON string.
   /// </summary>
-  public sealed partial class Int64Value : pb::IMessage<Int64Value> {
+  public sealed partial class Int64Value : pb::IMessage<Int64Value>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Int64Value> _parser = new pb::MessageParser<Int64Value>(() => new Int64Value());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Int64Value> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[2]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Value() {
       OnConstruction();
     }
@@ -355,12 +484,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Value(Int64Value other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int64Value Clone() {
       return new Int64Value(this);
     }
@@ -372,6 +503,7 @@
     /// The int64 value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public long Value {
       get { return value_; }
       set {
@@ -380,11 +512,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Int64Value);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Int64Value other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -397,6 +531,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0L) hash ^= Value.GetHashCode();
@@ -407,12 +542,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != 0L) {
         output.WriteRawTag(8);
         output.WriteInt64(Value);
@@ -420,9 +560,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != 0L) {
@@ -435,6 +591,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Int64Value other) {
       if (other == null) {
         return;
@@ -446,7 +603,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -459,8 +620,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Value = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -468,23 +649,31 @@
   ///
   /// The JSON representation for `UInt64Value` is JSON string.
   /// </summary>
-  public sealed partial class UInt64Value : pb::IMessage<UInt64Value> {
+  public sealed partial class UInt64Value : pb::IMessage<UInt64Value>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<UInt64Value> _parser = new pb::MessageParser<UInt64Value>(() => new UInt64Value());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<UInt64Value> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[3]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UInt64Value() {
       OnConstruction();
     }
@@ -492,12 +681,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UInt64Value(UInt64Value other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UInt64Value Clone() {
       return new UInt64Value(this);
     }
@@ -509,6 +700,7 @@
     /// The uint64 value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public ulong Value {
       get { return value_; }
       set {
@@ -517,11 +709,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as UInt64Value);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(UInt64Value other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -534,6 +728,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0UL) hash ^= Value.GetHashCode();
@@ -544,12 +739,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != 0UL) {
         output.WriteRawTag(8);
         output.WriteUInt64(Value);
@@ -557,9 +757,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != 0UL) {
+        output.WriteRawTag(8);
+        output.WriteUInt64(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != 0UL) {
@@ -572,6 +788,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(UInt64Value other) {
       if (other == null) {
         return;
@@ -583,7 +800,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -596,8 +817,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Value = input.ReadUInt64();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -605,23 +846,31 @@
   ///
   /// The JSON representation for `Int32Value` is JSON number.
   /// </summary>
-  public sealed partial class Int32Value : pb::IMessage<Int32Value> {
+  public sealed partial class Int32Value : pb::IMessage<Int32Value>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<Int32Value> _parser = new pb::MessageParser<Int32Value>(() => new Int32Value());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<Int32Value> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Value() {
       OnConstruction();
     }
@@ -629,12 +878,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Value(Int32Value other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public Int32Value Clone() {
       return new Int32Value(this);
     }
@@ -646,6 +897,7 @@
     /// The int32 value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int Value {
       get { return value_; }
       set {
@@ -654,11 +906,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as Int32Value);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(Int32Value other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -671,6 +925,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0) hash ^= Value.GetHashCode();
@@ -681,12 +936,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != 0) {
         output.WriteRawTag(8);
         output.WriteInt32(Value);
@@ -694,9 +954,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != 0) {
@@ -709,6 +985,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(Int32Value other) {
       if (other == null) {
         return;
@@ -720,7 +997,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -733,8 +1014,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Value = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -742,23 +1043,31 @@
   ///
   /// The JSON representation for `UInt32Value` is JSON number.
   /// </summary>
-  public sealed partial class UInt32Value : pb::IMessage<UInt32Value> {
+  public sealed partial class UInt32Value : pb::IMessage<UInt32Value>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<UInt32Value> _parser = new pb::MessageParser<UInt32Value>(() => new UInt32Value());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<UInt32Value> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UInt32Value() {
       OnConstruction();
     }
@@ -766,12 +1075,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UInt32Value(UInt32Value other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public UInt32Value Clone() {
       return new UInt32Value(this);
     }
@@ -783,6 +1094,7 @@
     /// The uint32 value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public uint Value {
       get { return value_; }
       set {
@@ -791,11 +1103,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as UInt32Value);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(UInt32Value other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -808,6 +1122,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0) hash ^= Value.GetHashCode();
@@ -818,12 +1133,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != 0) {
         output.WriteRawTag(8);
         output.WriteUInt32(Value);
@@ -831,9 +1151,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != 0) {
+        output.WriteRawTag(8);
+        output.WriteUInt32(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != 0) {
@@ -846,6 +1182,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(UInt32Value other) {
       if (other == null) {
         return;
@@ -857,7 +1194,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -870,8 +1211,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Value = input.ReadUInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -879,23 +1240,31 @@
   ///
   /// The JSON representation for `BoolValue` is JSON `true` and `false`.
   /// </summary>
-  public sealed partial class BoolValue : pb::IMessage<BoolValue> {
+  public sealed partial class BoolValue : pb::IMessage<BoolValue>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolValue() {
       OnConstruction();
     }
@@ -903,12 +1272,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolValue(BoolValue other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BoolValue Clone() {
       return new BoolValue(this);
     }
@@ -920,6 +1291,7 @@
     /// The bool value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Value {
       get { return value_; }
       set {
@@ -928,11 +1300,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BoolValue);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BoolValue other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -945,6 +1319,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != false) hash ^= Value.GetHashCode();
@@ -955,12 +1330,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value != false) {
         output.WriteRawTag(8);
         output.WriteBool(Value);
@@ -968,9 +1348,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value != false) {
@@ -983,6 +1379,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BoolValue other) {
       if (other == null) {
         return;
@@ -994,7 +1391,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1007,8 +1408,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 8: {
+            Value = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -1016,23 +1437,31 @@
   ///
   /// The JSON representation for `StringValue` is JSON string.
   /// </summary>
-  public sealed partial class StringValue : pb::IMessage<StringValue> {
+  public sealed partial class StringValue : pb::IMessage<StringValue>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<StringValue> _parser = new pb::MessageParser<StringValue>(() => new StringValue());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<StringValue> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[7]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public StringValue() {
       OnConstruction();
     }
@@ -1040,12 +1469,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public StringValue(StringValue other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public StringValue Clone() {
       return new StringValue(this);
     }
@@ -1057,6 +1488,7 @@
     /// The string value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public string Value {
       get { return value_; }
       set {
@@ -1065,11 +1497,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as StringValue);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(StringValue other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1082,6 +1516,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value.Length != 0) hash ^= Value.GetHashCode();
@@ -1092,12 +1527,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value.Length != 0) {
         output.WriteRawTag(10);
         output.WriteString(Value);
@@ -1105,9 +1545,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value.Length != 0) {
@@ -1120,6 +1576,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(StringValue other) {
       if (other == null) {
         return;
@@ -1131,7 +1588,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1144,8 +1605,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Value = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   /// <summary>
@@ -1153,23 +1634,31 @@
   ///
   /// The JSON representation for `BytesValue` is JSON string.
   /// </summary>
-  public sealed partial class BytesValue : pb::IMessage<BytesValue> {
+  public sealed partial class BytesValue : pb::IMessage<BytesValue>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
     private static readonly pb::MessageParser<BytesValue> _parser = new pb::MessageParser<BytesValue>(() => new BytesValue());
     private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pb::MessageParser<BytesValue> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public static pbr::MessageDescriptor Descriptor {
       get { return global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor.MessageTypes[8]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     pbr::MessageDescriptor pb::IMessage.Descriptor {
       get { return Descriptor; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BytesValue() {
       OnConstruction();
     }
@@ -1177,12 +1666,14 @@
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BytesValue(BytesValue other) : this() {
       value_ = other.value_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public BytesValue Clone() {
       return new BytesValue(this);
     }
@@ -1194,6 +1685,7 @@
     /// The bytes value.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public pb::ByteString Value {
       get { return value_; }
       set {
@@ -1202,11 +1694,13 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
       return Equals(other as BytesValue);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public bool Equals(BytesValue other) {
       if (ReferenceEquals(other, null)) {
         return false;
@@ -1219,6 +1713,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override int GetHashCode() {
       int hash = 1;
       if (Value.Length != 0) hash ^= Value.GetHashCode();
@@ -1229,12 +1724,17 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override string ToString() {
       return pb::JsonFormatter.ToDiagnosticString(this);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
       if (Value.Length != 0) {
         output.WriteRawTag(10);
         output.WriteBytes(Value);
@@ -1242,9 +1742,25 @@
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (Value.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Value);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public int CalculateSize() {
       int size = 0;
       if (Value.Length != 0) {
@@ -1257,6 +1773,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(BytesValue other) {
       if (other == null) {
         return;
@@ -1268,7 +1785,11 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
       uint tag;
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
@@ -1281,8 +1802,28 @@
           }
         }
       }
+    #endif
     }
 
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+          case 10: {
+            Value = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
   }
 
   #endregion
diff --git a/csharp/src/Google.Protobuf/WriteBufferHelper.cs b/csharp/src/Google.Protobuf/WriteBufferHelper.cs
new file mode 100644
index 0000000..f2a59bc
--- /dev/null
+++ b/csharp/src/Google.Protobuf/WriteBufferHelper.cs
@@ -0,0 +1,166 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Abstraction for writing to a steam / IBufferWriter
+    /// </summary>
+    [SecuritySafeCritical]
+    internal struct WriteBufferHelper
+    {
+        private IBufferWriter<byte> bufferWriter;
+        private CodedOutputStream codedOutputStream;
+
+        public CodedOutputStream CodedOutputStream => codedOutputStream;
+
+        /// <summary>
+        /// Initialize an instance with a coded output stream.
+        /// This approach is faster than using a constructor because the instance to initialize is passed by reference
+        /// and we can write directly into it without copying.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Initialize(CodedOutputStream codedOutputStream, out WriteBufferHelper instance)
+        {
+            instance.bufferWriter = null;
+            instance.codedOutputStream = codedOutputStream;
+        }
+
+        /// <summary>
+        /// Initialize an instance with a buffer writer.
+        /// This approach is faster than using a constructor because the instance to initialize is passed by reference
+        /// and we can write directly into it without copying.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Initialize(IBufferWriter<byte> bufferWriter, out WriteBufferHelper instance, out Span<byte> buffer)
+        {
+            instance.bufferWriter = bufferWriter;
+            instance.codedOutputStream = null;
+            buffer = default;  // TODO: initialize the initial buffer so that the first write is not via slowpath.
+        }
+
+        /// <summary>
+        /// Initialize an instance with a buffer represented by a single span (i.e. buffer cannot be refreshed)
+        /// This approach is faster than using a constructor because the instance to initialize is passed by reference
+        /// and we can write directly into it without copying.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void InitializeNonRefreshable(out WriteBufferHelper instance)
+        {
+            instance.bufferWriter = null;
+            instance.codedOutputStream = null;
+        }
+
+        /// <summary>
+        /// Verifies that SpaceLeft returns zero.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void CheckNoSpaceLeft(ref WriterInternalState state)
+        {
+            if (GetSpaceLeft(ref state) != 0)
+            {
+                throw new InvalidOperationException("Did not write as much data as expected.");
+            }
+        }
+
+        /// <summary>
+        /// If writing to a flat array, returns the space left in the array. Otherwise,
+        /// throws an InvalidOperationException.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static int GetSpaceLeft(ref WriterInternalState state)
+        {
+            if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream == null && state.writeBufferHelper.bufferWriter == null)
+            {
+                return state.limit - state.position;
+            }
+            else
+            {
+                throw new InvalidOperationException(
+                    "SpaceLeft can only be called on CodedOutputStreams that are " +
+                        "writing to a flat array or when writing to a single span.");
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public static void RefreshBuffer(ref Span<byte> buffer, ref WriterInternalState state)
+        {
+            if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream != null)
+            {
+                // because we're using coded output stream, we know that "buffer" and codedOutputStream.InternalBuffer are identical.
+                state.writeBufferHelper.codedOutputStream.InternalOutputStream.Write(state.writeBufferHelper.codedOutputStream.InternalBuffer, 0, state.position);
+                // reset position, limit stays the same because we are reusing the codedOutputStream's internal buffer.
+                state.position = 0;
+            }
+            else if (state.writeBufferHelper.bufferWriter != null)
+            {
+                // commit the bytes and get a new buffer to write to.
+                state.writeBufferHelper.bufferWriter.Advance(state.position);
+                state.position = 0;
+                buffer = state.writeBufferHelper.bufferWriter.GetSpan();
+                state.limit = buffer.Length;
+            }
+            else
+            {
+                // We're writing to a single buffer.
+                throw new CodedOutputStream.OutOfSpaceException();
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Flush(ref Span<byte> buffer, ref WriterInternalState state)
+        {
+            if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream != null)
+            {
+                // because we're using coded output stream, we know that "buffer" and codedOutputStream.InternalBuffer are identical.
+                state.writeBufferHelper.codedOutputStream.InternalOutputStream.Write(state.writeBufferHelper.codedOutputStream.InternalBuffer, 0, state.position);
+                state.position = 0;
+            }
+            else if (state.writeBufferHelper.bufferWriter != null)
+            {
+                // calling Advance invalidates the current buffer and we must not continue writing to it,
+                // so we set the current buffer to point to an empty Span. If any subsequent writes happen,
+                // the first subsequent write will trigger refresing of the buffer.
+                state.writeBufferHelper.bufferWriter.Advance(state.position);
+                state.position = 0;
+                state.limit = 0;
+                buffer = default;  // invalidate the current buffer
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/WriteContext.cs b/csharp/src/Google.Protobuf/WriteContext.cs
new file mode 100644
index 0000000..e822e1d
--- /dev/null
+++ b/csharp/src/Google.Protobuf/WriteContext.cs
@@ -0,0 +1,371 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// An opaque struct that represents the current serialization state and is passed along
+    /// as the serialization proceeds.
+    /// All the public methods are intended to be invoked only by the generated code,
+    /// users should never invoke them directly.
+    /// </summary>
+    [SecuritySafeCritical]
+    public ref struct WriteContext
+    {
+        internal Span<byte> buffer;
+        internal WriterInternalState state;
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(ref Span<byte> buffer, ref WriterInternalState state, out WriteContext ctx)
+        {
+            ctx.buffer = buffer;
+            ctx.state = state;
+        }
+
+        /// <summary>
+        /// Creates a WriteContext instance from CodedOutputStream.
+        /// WARNING: internally this copies the CodedOutputStream's state, so after done with the WriteContext,
+        /// the CodedOutputStream's state needs to be updated.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(CodedOutputStream output, out WriteContext ctx)
+        {
+            ctx.buffer = new Span<byte>(output.InternalBuffer);
+            // ideally we would use a reference to the original state, but that doesn't seem possible
+            // so we just copy the struct that holds the state. We will need to later store the state back
+            // into CodedOutputStream if we want to keep it usable.
+            ctx.state = output.InternalState;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(IBufferWriter<byte> output, out WriteContext ctx)
+        {
+            ctx.buffer = default;
+            ctx.state = default;
+            WriteBufferHelper.Initialize(output, out ctx.state.writeBufferHelper, out ctx.buffer);
+            ctx.state.limit = ctx.buffer.Length;
+            ctx.state.position = 0;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void Initialize(ref Span<byte> buffer, out WriteContext ctx)
+        {
+            ctx.buffer = buffer;
+            ctx.state = default;
+            ctx.state.limit = ctx.buffer.Length;
+            ctx.state.position = 0;
+            WriteBufferHelper.InitializeNonRefreshable(out ctx.state.writeBufferHelper);
+        }
+
+        /// <summary>
+        /// Writes a double field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteDouble(double value)
+        {
+            WritingPrimitives.WriteDouble(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a float field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFloat(float value)
+        {
+            WritingPrimitives.WriteFloat(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a uint64 field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteUInt64(ulong value)
+        {
+            WritingPrimitives.WriteUInt64(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an int64 field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteInt64(long value)
+        {
+            WritingPrimitives.WriteInt64(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an int32 field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteInt32(int value)
+        {
+            WritingPrimitives.WriteInt32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a fixed64 field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFixed64(ulong value)
+        {
+            WritingPrimitives.WriteFixed64(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a fixed32 field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFixed32(uint value)
+        {
+            WritingPrimitives.WriteFixed32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a bool field value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteBool(bool value)
+        {
+            WritingPrimitives.WriteBool(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a string field value, without a tag.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteString(string value)
+        {
+            WritingPrimitives.WriteString(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a message, without a tag.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteMessage(IMessage value)
+        {
+            WritingPrimitivesMessages.WriteMessage(ref this, value);
+        }
+
+        /// <summary>
+        /// Writes a group, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteGroup(IMessage value)
+        {
+            WritingPrimitivesMessages.WriteGroup(ref this, value);
+        }
+
+        /// <summary>
+        /// Write a byte string, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteBytes(ByteString value)
+        {
+            WritingPrimitives.WriteBytes(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a uint32 value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteUInt32(uint value)
+        {
+            WritingPrimitives.WriteUInt32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an enum value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteEnum(int value)
+        {
+            WritingPrimitives.WriteEnum(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed32 value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
+        public void WriteSFixed32(int value)
+        {
+            WritingPrimitives.WriteSFixed32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed64 value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSFixed64(long value)
+        {
+            WritingPrimitives.WriteSFixed64(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an sint32 value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSInt32(int value)
+        {
+            WritingPrimitives.WriteSInt32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an sint64 value, without a tag.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSInt64(long value)
+        {
+            WritingPrimitives.WriteSInt64(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a length (in bytes) for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This method simply writes a rawint, but exists for clarity in calling code.
+        /// </remarks>
+        /// <param name="length">Length value, in bytes.</param>
+        public void WriteLength(int length)
+        {
+            WritingPrimitives.WriteLength(ref buffer, ref state, length);
+        }
+
+        /// <summary>
+        /// Encodes and writes a tag.
+        /// </summary>
+        /// <param name="fieldNumber">The number of the field to write the tag for</param>
+        /// <param name="type">The wire format type of the tag to write</param>
+        public void WriteTag(int fieldNumber, WireFormat.WireType type)
+        {
+            WritingPrimitives.WriteTag(ref buffer, ref state, fieldNumber, type);
+        }
+
+        /// <summary>
+        /// Writes an already-encoded tag.
+        /// </summary>
+        /// <param name="tag">The encoded tag</param>
+        public void WriteTag(uint tag)
+        {
+            WritingPrimitives.WriteTag(ref buffer, ref state, tag);
+        }
+
+        /// <summary>
+        /// Writes the given single-byte tag.
+        /// </summary>
+        /// <param name="b1">The encoded tag</param>
+        public void WriteRawTag(byte b1)
+        {
+            WritingPrimitives.WriteRawTag(ref buffer, ref state, b1);
+        }
+
+        /// <summary>
+        /// Writes the given two-byte tag.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2)
+        {
+            WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2);
+        }
+
+        /// <summary>
+        /// Writes the given three-byte tag.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3)
+        {
+            WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3);
+        }
+
+        /// <summary>
+        /// Writes the given four-byte tag.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        /// <param name="b4">The fourth byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
+        {
+            WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4);
+        }
+
+        /// <summary>
+        /// Writes the given five-byte tag.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        /// <param name="b4">The fourth byte of the encoded tag</param>
+        /// <param name="b5">The fifth byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
+        {
+            WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4, b5);
+        }
+
+        internal void Flush()
+        {
+            WriteBufferHelper.Flush(ref buffer, ref state);
+        }
+
+        internal void CheckNoSpaceLeft()
+        {
+            WriteBufferHelper.CheckNoSpaceLeft(ref state);
+        }
+
+        internal void CopyStateTo(CodedOutputStream output)
+        {
+            output.InternalState = state;
+        }
+
+        internal void LoadStateFrom(CodedOutputStream output)
+        {
+            state = output.InternalState;
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/WriterInternalState.cs b/csharp/src/Google.Protobuf/WriterInternalState.cs
new file mode 100644
index 0000000..a779305
--- /dev/null
+++ b/csharp/src/Google.Protobuf/WriterInternalState.cs
@@ -0,0 +1,62 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+    
+    // warning: this is a mutable struct, so it needs to be only passed as a ref!
+    internal struct WriterInternalState
+    {
+        // NOTE: the Span representing the current buffer is kept separate so that this doesn't have to be a ref struct and so it can
+        // be included in CodedOutputStream's internal state
+
+        internal int limit;  // the size of the current buffer
+        internal int position;  // position in the current buffer
+
+        internal WriteBufferHelper writeBufferHelper;
+
+        // If non-null, the top level parse method was started with given coded output stream as an argument
+        // which also means we can potentially fallback to calling WriteTo(CodedOutputStream cos) if needed.
+        internal CodedOutputStream CodedOutputStream => writeBufferHelper.CodedOutputStream;
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/WritingPrimitives.cs b/csharp/src/Google.Protobuf/WritingPrimitives.cs
new file mode 100644
index 0000000..8beefc5
--- /dev/null
+++ b/csharp/src/Google.Protobuf/WritingPrimitives.cs
@@ -0,0 +1,757 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Buffers.Binary;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+#if GOOGLE_PROTOBUF_SIMD
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+using System.Runtime.Intrinsics.X86;
+#endif
+using System.Security;
+using System.Text;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Primitives for encoding protobuf wire format.
+    /// </summary>
+    [SecuritySafeCritical]
+    internal static class WritingPrimitives
+    {
+#if NET5_0
+        internal static Encoding Utf8Encoding => Encoding.UTF8; // allows JIT to devirtualize
+#else
+        internal static readonly Encoding Utf8Encoding = Encoding.UTF8; // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
+#endif
+
+        #region Writing of values (not including tags)
+
+        /// <summary>
+        /// Writes a double field value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteDouble(ref Span<byte> buffer, ref WriterInternalState state, double value)
+        {
+            WriteRawLittleEndian64(ref buffer, ref state, (ulong)BitConverter.DoubleToInt64Bits(value));
+        }
+
+        /// <summary>
+        /// Writes a float field value, without a tag, to the stream.
+        /// </summary>
+        public static unsafe void WriteFloat(ref Span<byte> buffer, ref WriterInternalState state, float value)
+        {
+            const int length = sizeof(float);
+            if (buffer.Length - state.position >= length)
+            {
+                // if there's enough space in the buffer, write the float directly into the buffer
+                var floatSpan = buffer.Slice(state.position, length);
+                Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value);
+
+                if (!BitConverter.IsLittleEndian)
+                {
+                    floatSpan.Reverse();
+                }
+                state.position += length;
+            }
+            else
+            {
+                WriteFloatSlowPath(ref buffer, ref state, value);
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static unsafe void WriteFloatSlowPath(ref Span<byte> buffer, ref WriterInternalState state, float value)
+        {
+            const int length = sizeof(float);
+
+            // TODO(jtattermusch): deduplicate the code. Populating the span is the same as for the fastpath.
+            Span<byte> floatSpan = stackalloc byte[length];
+            Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value);
+            if (!BitConverter.IsLittleEndian)
+            {
+                floatSpan.Reverse();
+            }
+
+            WriteRawByte(ref buffer, ref state, floatSpan[0]);
+            WriteRawByte(ref buffer, ref state, floatSpan[1]);
+            WriteRawByte(ref buffer, ref state, floatSpan[2]);
+            WriteRawByte(ref buffer, ref state, floatSpan[3]);
+        }
+
+        /// <summary>
+        /// Writes a uint64 field value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteUInt64(ref Span<byte> buffer, ref WriterInternalState state, ulong value)
+        {
+            WriteRawVarint64(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an int64 field value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteInt64(ref Span<byte> buffer, ref WriterInternalState state, long value)
+        {
+            WriteRawVarint64(ref buffer, ref state, (ulong)value);
+        }
+
+        /// <summary>
+        /// Writes an int32 field value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteInt32(ref Span<byte> buffer, ref WriterInternalState state, int value)
+        {
+            if (value >= 0)
+            {
+                WriteRawVarint32(ref buffer, ref state, (uint)value);
+            }
+            else
+            {
+                // Must sign-extend.
+                WriteRawVarint64(ref buffer, ref state, (ulong)value);
+            }
+        }
+
+        /// <summary>
+        /// Writes a fixed64 field value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteFixed64(ref Span<byte> buffer, ref WriterInternalState state, ulong value)
+        {
+            WriteRawLittleEndian64(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a fixed32 field value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteFixed32(ref Span<byte> buffer, ref WriterInternalState state, uint value)
+        {
+            WriteRawLittleEndian32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes a bool field value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteBool(ref Span<byte> buffer, ref WriterInternalState state, bool value)
+        {
+            WriteRawByte(ref buffer, ref state, value ? (byte)1 : (byte)0);
+        }
+
+        /// <summary>
+        /// Writes a string field value, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        public static void WriteString(ref Span<byte> buffer, ref WriterInternalState state, string value)
+        {
+            const int MaxBytesPerChar = 3;
+            const int MaxSmallStringLength = 128 / MaxBytesPerChar;
+
+            // The string is small enough that the length will always be a 1 byte varint.
+            // Also there is enough space to write length + bytes to buffer.
+            // Write string directly to the buffer, and then write length.
+            // This saves calling GetByteCount on the string. We get the string length from GetBytes.
+            if (value.Length <= MaxSmallStringLength && buffer.Length - state.position - 1 >= value.Length * MaxBytesPerChar)
+            {
+                int indexOfLengthDelimiter = state.position++;
+                buffer[indexOfLengthDelimiter] = (byte)WriteStringToBuffer(buffer, ref state, value);
+                return;
+            }
+
+            int length = Utf8Encoding.GetByteCount(value);
+            WriteLength(ref buffer, ref state, length);
+
+            // Optimise the case where we have enough space to write
+            // the string directly to the buffer, which should be common.
+            if (buffer.Length - state.position >= length)
+            {
+                if (length == value.Length) // Must be all ASCII...
+                {
+                    WriteAsciiStringToBuffer(buffer, ref state, value, length);
+                }
+                else
+                {
+                    WriteStringToBuffer(buffer, ref state, value);
+                }
+            }
+            else
+            {
+                // Opportunity for future optimization:
+                // Large strings that don't fit into the current buffer segment
+                // can probably be optimized by using Utf8Encoding.GetEncoder()
+                // but more benchmarks would need to be added as evidence.
+                byte[] bytes = Utf8Encoding.GetBytes(value);
+                WriteRawBytes(ref buffer, ref state, bytes);
+            }
+        }
+
+        // Calling this method with non-ASCII content will break.
+        // Content must be verified to be all ASCII before using this method.
+        private static void WriteAsciiStringToBuffer(Span<byte> buffer, ref WriterInternalState state, string value, int length)
+        {
+            ref char sourceChars = ref MemoryMarshal.GetReference(value.AsSpan());
+            ref byte destinationBytes = ref MemoryMarshal.GetReference(buffer.Slice(state.position));
+
+            int currentIndex = 0;
+            // If 64bit, process 4 chars at a time.
+            // The logic inside this check will be elided by JIT in 32bit programs.
+            if (IntPtr.Size == 8)
+            {
+                // Need at least 4 chars available to use this optimization. 
+                if (length >= 4)
+                {
+                    ref byte sourceBytes = ref Unsafe.As<char, byte>(ref sourceChars);
+
+                    // Process 4 chars at a time until there are less than 4 remaining.
+                    // We already know all characters are ASCII so there is no need to validate the source.
+                    int lastIndexWhereCanReadFourChars = value.Length - 4;
+                    do
+                    {
+                        NarrowFourUtf16CharsToAsciiAndWriteToBuffer(
+                            ref Unsafe.AddByteOffset(ref destinationBytes, (IntPtr)currentIndex),
+                            Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref sourceBytes, (IntPtr)(currentIndex * 2))));
+
+                    } while ((currentIndex += 4) <= lastIndexWhereCanReadFourChars);
+                }
+            }
+
+            // Process any remaining, 1 char at a time.
+            // Avoid bounds checking with ref + Unsafe
+            for (; currentIndex < length; currentIndex++)
+            {
+                Unsafe.AddByteOffset(ref destinationBytes, (IntPtr)currentIndex) = (byte)Unsafe.AddByteOffset(ref sourceChars, (IntPtr)(currentIndex * 2));
+            }
+
+            state.position += length;
+        }
+
+        // Copied with permission from https://github.com/dotnet/runtime/blob/1cdafd27e4afd2c916af5df949c13f8b373c4335/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs#L1119-L1171
+        //
+        /// <summary>
+        /// Given a QWORD which represents a buffer of 4 ASCII chars in machine-endian order,
+        /// narrows each WORD to a BYTE, then writes the 4-byte result to the output buffer
+        /// also in machine-endian order.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static void NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref byte outputBuffer, ulong value)
+        {
+#if GOOGLE_PROTOBUF_SIMD
+            if (Sse2.X64.IsSupported)
+            {
+                // Narrows a vector of words [ w0 w1 w2 w3 ] to a vector of bytes
+                // [ b0 b1 b2 b3 b0 b1 b2 b3 ], then writes 4 bytes (32 bits) to the destination.
+
+                Vector128<short> vecWide = Sse2.X64.ConvertScalarToVector128UInt64(value).AsInt16();
+                Vector128<uint> vecNarrow = Sse2.PackUnsignedSaturate(vecWide, vecWide).AsUInt32();
+                Unsafe.WriteUnaligned<uint>(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow));
+            }
+            else if (AdvSimd.IsSupported)
+            {
+                // Narrows a vector of words [ w0 w1 w2 w3 ] to a vector of bytes
+                // [ b0 b1 b2 b3 * * * * ], then writes 4 bytes (32 bits) to the destination.
+
+                Vector128<short> vecWide = Vector128.CreateScalarUnsafe(value).AsInt16();
+                Vector64<byte> lower = AdvSimd.ExtractNarrowingSaturateUnsignedLower(vecWide);
+                Unsafe.WriteUnaligned<uint>(ref outputBuffer, lower.AsUInt32().ToScalar());
+            }
+            else
+#endif
+            {
+                // Fallback to non-SIMD approach when SIMD is not available.
+                // This could happen either because the APIs are not available, or hardware doesn't support it.
+                // Processing 4 chars at a time in this fallback is still faster than casting one char at a time.
+                if (BitConverter.IsLittleEndian)
+                {
+                    outputBuffer = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 1) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 2) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 3) = (byte)value;
+                }
+                else
+                {
+                    Unsafe.Add(ref outputBuffer, 3) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 2) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 1) = (byte)value;
+                    value >>= 16;
+                    outputBuffer = (byte)value;
+                }
+            }
+        }
+
+        private static int WriteStringToBuffer(Span<byte> buffer, ref WriterInternalState state, string value)
+        {
+#if NETSTANDARD1_1
+            // slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available
+            byte[] bytes = Utf8Encoding.GetBytes(value);
+            WriteRawBytes(ref buffer, ref state, bytes);
+            return bytes.Length;
+#else
+            ReadOnlySpan<char> source = value.AsSpan();
+            int bytesUsed;
+            unsafe
+            {
+                fixed (char* sourceChars = &MemoryMarshal.GetReference(source))
+                fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer))
+                {
+                    bytesUsed = Utf8Encoding.GetBytes(
+                        sourceChars,
+                        source.Length,
+                        destinationBytes + state.position,
+                        buffer.Length - state.position);
+                }
+            }
+            state.position += bytesUsed;
+            return bytesUsed;
+#endif
+        }
+
+        /// <summary>
+        /// Write a byte string, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        public static void WriteBytes(ref Span<byte> buffer, ref WriterInternalState state, ByteString value)
+        {
+            WriteLength(ref buffer, ref state, value.Length);
+            WriteRawBytes(ref buffer, ref state, value.Span);
+        }
+
+        /// <summary>
+        /// Writes a uint32 value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteUInt32(ref Span<byte> buffer, ref WriterInternalState state, uint value)
+        {
+            WriteRawVarint32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an enum value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteEnum(ref Span<byte> buffer, ref WriterInternalState state, int value)
+        {
+            WriteInt32(ref buffer, ref state, value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed32 value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteSFixed32(ref Span<byte> buffer, ref WriterInternalState state, int value)
+        {
+            WriteRawLittleEndian32(ref buffer, ref state, (uint)value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed64 value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteSFixed64(ref Span<byte> buffer, ref WriterInternalState state, long value)
+        {
+            WriteRawLittleEndian64(ref buffer, ref state, (ulong)value);
+        }
+
+        /// <summary>
+        /// Writes an sint32 value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteSInt32(ref Span<byte> buffer, ref WriterInternalState state, int value)
+        {
+            WriteRawVarint32(ref buffer, ref state, EncodeZigZag32(value));
+        }
+
+        /// <summary>
+        /// Writes an sint64 value, without a tag, to the stream.
+        /// </summary>
+        public static void WriteSInt64(ref Span<byte> buffer, ref WriterInternalState state, long value)
+        {
+            WriteRawVarint64(ref buffer, ref state, EncodeZigZag64(value));
+        }
+
+        /// <summary>
+        /// Writes a length (in bytes) for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This method simply writes a rawint, but exists for clarity in calling code.
+        /// </remarks>
+        public static void WriteLength(ref Span<byte> buffer, ref WriterInternalState state, int length)
+        {
+            WriteRawVarint32(ref buffer, ref state, (uint)length);
+        }
+
+        #endregion
+
+        #region Writing primitives
+        /// <summary>
+        /// Writes a 32 bit value as a varint. The fast route is taken when
+        /// there's enough buffer space left to whizz through without checking
+        /// for each byte; otherwise, we resort to calling WriteRawByte each time.
+        /// </summary>
+        public static void WriteRawVarint32(ref Span<byte> buffer, ref WriterInternalState state, uint value)
+        {
+            // Optimize for the common case of a single byte value
+            if (value < 128 && state.position < buffer.Length)
+            {
+                buffer[state.position++] = (byte)value;
+                return;
+            }
+
+            // Fast path when capacity is available
+            while (state.position < buffer.Length)
+            {
+                if (value > 127)
+                {
+                    buffer[state.position++] = (byte)((value & 0x7F) | 0x80);
+                    value >>= 7;
+                }
+                else
+                {
+                    buffer[state.position++] = (byte)value;
+                    return;
+                }
+            }
+
+            while (value > 127)
+            {
+                WriteRawByte(ref buffer, ref state, (byte)((value & 0x7F) | 0x80));
+                value >>= 7;
+            }
+
+            WriteRawByte(ref buffer, ref state, (byte)value);
+        }
+
+        public static void WriteRawVarint64(ref Span<byte> buffer, ref WriterInternalState state, ulong value)
+        {
+            // Optimize for the common case of a single byte value
+            if (value < 128 && state.position < buffer.Length)
+            {
+                buffer[state.position++] = (byte)value;
+                return;
+            }
+
+            // Fast path when capacity is available
+            while (state.position < buffer.Length)
+            {
+                if (value > 127)
+                {
+                    buffer[state.position++] = (byte)((value & 0x7F) | 0x80);
+                    value >>= 7;
+                }
+                else
+                {
+                    buffer[state.position++] = (byte)value;
+                    return;
+                }
+            }
+
+            while (value > 127)
+            {
+                WriteRawByte(ref buffer, ref state, (byte)((value & 0x7F) | 0x80));
+                value >>= 7;
+            }
+
+            WriteRawByte(ref buffer, ref state, (byte)value);
+        }
+
+        public static void WriteRawLittleEndian32(ref Span<byte> buffer, ref WriterInternalState state, uint value)
+        {
+            const int length = sizeof(uint);
+            if (state.position + length > buffer.Length)
+            {
+                WriteRawLittleEndian32SlowPath(ref buffer, ref state, value);
+            }
+            else
+            {
+                BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(state.position), value);
+                state.position += length;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void WriteRawLittleEndian32SlowPath(ref Span<byte> buffer, ref WriterInternalState state, uint value)
+        {
+            WriteRawByte(ref buffer, ref state, (byte)value);
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 8));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 16));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 24));
+        }
+
+        public static void WriteRawLittleEndian64(ref Span<byte> buffer, ref WriterInternalState state, ulong value)
+        {
+            const int length = sizeof(ulong);
+            if (state.position + length > buffer.Length)
+            {
+                WriteRawLittleEndian64SlowPath(ref buffer, ref state, value);
+            }
+            else
+            {
+                BinaryPrimitives.WriteUInt64LittleEndian(buffer.Slice(state.position), value);
+                state.position += length;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public static void WriteRawLittleEndian64SlowPath(ref Span<byte> buffer, ref WriterInternalState state, ulong value)
+        {
+            WriteRawByte(ref buffer, ref state, (byte)value);
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 8));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 16));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 24));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 32));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 40));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 48));
+            WriteRawByte(ref buffer, ref state, (byte)(value >> 56));
+        }
+
+        private static void WriteRawByte(ref Span<byte> buffer, ref WriterInternalState state, byte value)
+        {
+            if (state.position == buffer.Length)
+            {
+                WriteBufferHelper.RefreshBuffer(ref buffer, ref state);
+            }
+
+            buffer[state.position++] = value;
+        }
+
+        /// <summary>
+        /// Writes out an array of bytes.
+        /// </summary>
+        public static void WriteRawBytes(ref Span<byte> buffer, ref WriterInternalState state, byte[] value)
+        {
+            WriteRawBytes(ref buffer, ref state, new ReadOnlySpan<byte>(value));
+        }
+
+        /// <summary>
+        /// Writes out part of an array of bytes.
+        /// </summary>
+        public static void WriteRawBytes(ref Span<byte> buffer, ref WriterInternalState state, byte[] value, int offset, int length)
+        {
+            WriteRawBytes(ref buffer, ref state, new ReadOnlySpan<byte>(value, offset, length));
+        }
+
+        /// <summary>
+        /// Writes out part of an array of bytes.
+        /// </summary>
+        public static void WriteRawBytes(ref Span<byte> buffer, ref WriterInternalState state, ReadOnlySpan<byte> value)
+        {
+            if (buffer.Length - state.position >= value.Length)
+            {
+                // We have room in the current buffer.    
+                value.CopyTo(buffer.Slice(state.position, value.Length));
+                state.position += value.Length;
+            }
+            else
+            {
+                // When writing to a CodedOutputStream backed by a Stream, we could avoid
+                // copying the data twice (first copying to the current buffer and
+                // and later writing from the current buffer to the underlying Stream)
+                // in some circumstances by writing the data directly to the underlying Stream.
+                // Current this is not being done to avoid specialcasing the code for
+                // CodedOutputStream vs IBufferWriter<byte>.
+                int bytesWritten = 0;
+                while (buffer.Length - state.position < value.Length - bytesWritten)
+                {
+                    int length = buffer.Length - state.position;
+                    value.Slice(bytesWritten, length).CopyTo(buffer.Slice(state.position, length));
+                    bytesWritten += length;
+                    state.position += length;
+                    WriteBufferHelper.RefreshBuffer(ref buffer, ref state);
+                }
+
+                // copy the remaining data
+                int remainderLength = value.Length - bytesWritten;
+                value.Slice(bytesWritten, remainderLength).CopyTo(buffer.Slice(state.position, remainderLength));
+                state.position += remainderLength;
+            }
+        }
+        #endregion
+
+        #region Raw tag writing
+        /// <summary>
+        /// Encodes and writes a tag.
+        /// </summary>
+        public static void WriteTag(ref Span<byte> buffer, ref WriterInternalState state, int fieldNumber, WireFormat.WireType type)
+        {
+            WriteRawVarint32(ref buffer, ref state, WireFormat.MakeTag(fieldNumber, type));
+        }
+
+        /// <summary>
+        /// Writes an already-encoded tag.
+        /// </summary>
+        public static void WriteTag(ref Span<byte> buffer, ref WriterInternalState state, uint tag)
+        {
+            WriteRawVarint32(ref buffer, ref state, tag);
+        }
+
+        /// <summary>
+        /// Writes the given single-byte tag directly to the stream.
+        /// </summary>
+        public static void WriteRawTag(ref Span<byte> buffer, ref WriterInternalState state, byte b1)
+        {
+            WriteRawByte(ref buffer, ref state, b1);
+        }
+
+        /// <summary>
+        /// Writes the given two-byte tag directly to the stream.
+        /// </summary>
+        public static void WriteRawTag(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2)
+        {
+            if (state.position + 2 > buffer.Length)
+            {
+                WriteRawTagSlowPath(ref buffer, ref state, b1, b2);
+            }
+            else
+            {
+                buffer[state.position++] = b1;
+                buffer[state.position++] = b2;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void WriteRawTagSlowPath(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2)
+        {
+            WriteRawByte(ref buffer, ref state, b1);
+            WriteRawByte(ref buffer, ref state, b2);
+        }
+
+        /// <summary>
+        /// Writes the given three-byte tag directly to the stream.
+        /// </summary>
+        public static void WriteRawTag(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2, byte b3)
+        {
+            if (state.position + 3 > buffer.Length)
+            {
+                WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3);
+            }
+            else
+            {
+                buffer[state.position++] = b1;
+                buffer[state.position++] = b2;
+                buffer[state.position++] = b3;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void WriteRawTagSlowPath(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2, byte b3)
+        {
+            WriteRawByte(ref buffer, ref state, b1);
+            WriteRawByte(ref buffer, ref state, b2);
+            WriteRawByte(ref buffer, ref state, b3);
+        }
+
+        /// <summary>
+        /// Writes the given four-byte tag directly to the stream.
+        /// </summary>
+        public static void WriteRawTag(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4)
+        {
+            if (state.position + 4 > buffer.Length)
+            {
+                WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3, b4);
+            }
+            else
+            {
+                buffer[state.position++] = b1;
+                buffer[state.position++] = b2;
+                buffer[state.position++] = b3;
+                buffer[state.position++] = b4;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+
+        private static void WriteRawTagSlowPath(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4)
+        {
+            WriteRawByte(ref buffer, ref state, b1);
+            WriteRawByte(ref buffer, ref state, b2);
+            WriteRawByte(ref buffer, ref state, b3);
+            WriteRawByte(ref buffer, ref state, b4);
+        }
+
+        /// <summary>
+        /// Writes the given five-byte tag directly to the stream.
+        /// </summary>
+        public static void WriteRawTag(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4, byte b5)
+        {
+            if (state.position + 5 > buffer.Length)
+            {
+                WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3, b4, b5);
+            }
+            else
+            {
+                buffer[state.position++] = b1;
+                buffer[state.position++] = b2;
+                buffer[state.position++] = b3;
+                buffer[state.position++] = b4;
+                buffer[state.position++] = b5;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void WriteRawTagSlowPath(ref Span<byte> buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4, byte b5)
+        {
+            WriteRawByte(ref buffer, ref state, b1);
+            WriteRawByte(ref buffer, ref state, b2);
+            WriteRawByte(ref buffer, ref state, b3);
+            WriteRawByte(ref buffer, ref state, b4);
+            WriteRawByte(ref buffer, ref state, b5);
+        }
+        #endregion
+
+        /// <summary>
+        /// Encode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        public static uint EncodeZigZag32(int n)
+        {
+            // Note:  the right-shift must be arithmetic
+            return (uint)((n << 1) ^ (n >> 31));
+        }
+
+        /// <summary>
+        /// Encode a 64-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        public static ulong EncodeZigZag64(long n)
+        {
+            return (ulong)((n << 1) ^ (n >> 63));
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs
new file mode 100644
index 0000000..cd2d437
--- /dev/null
+++ b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs
@@ -0,0 +1,112 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Security;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Writing messages / groups.
+    /// </summary>
+    [SecuritySafeCritical]
+    internal static class WritingPrimitivesMessages
+    {
+        /// <summary>
+        /// Writes a message, without a tag.
+        /// The data is length-prefixed.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void WriteMessage(ref WriteContext ctx, IMessage value)
+        {
+            WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, value.CalculateSize());
+            WriteRawMessage(ref ctx, value);
+        }
+
+        /// <summary>
+        /// Writes a group, without a tag.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void WriteGroup(ref WriteContext ctx, IMessage value)
+        {
+            WriteRawMessage(ref ctx, value);
+        }
+
+        /// <summary>
+        /// Writes a message, without a tag.
+        /// Message will be written without a length prefix.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void WriteRawMessage(ref WriteContext ctx, IMessage message)
+        {
+            if (message is IBufferMessage bufferMessage)
+            {
+                bufferMessage.InternalWriteTo(ref ctx);
+            }
+            else
+            {
+                // If we reached here, it means we've ran into a nested message with older generated code
+                // which doesn't provide the InternalWriteTo method that takes a WriteContext.
+                // With a slight performance overhead, we can still serialize this message just fine,
+                // but we need to find the original CodedOutputStream instance that initiated this
+                // serialization process and make sure its internal state is up to date.
+                // Note that this performance overhead is not very high (basically copying contents of a struct)
+                // and it will only be incurred in case the application mixes older and newer generated code.
+                // Regenerating the code from .proto files will remove this overhead because it will
+                // generate the InternalWriteTo method we need.
+
+                if (ctx.state.CodedOutputStream == null)
+                {
+                    // This can only happen when the serialization started without providing a CodedOutputStream instance
+                    // (e.g. WriteContext was created directly from a IBufferWriter).
+                    // That also means that one of the new parsing APIs was used at the top level
+                    // and in such case it is reasonable to require that all the nested message provide
+                    // up-to-date generated code with WriteContext support (and fail otherwise).
+                    throw new InvalidProtocolBufferException($"Message {message.GetType().Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code.");
+                }
+
+                ctx.CopyStateTo(ctx.state.CodedOutputStream);
+                try
+                {
+                    // fallback parse using the CodedOutputStream that started current serialization tree
+                    message.WriteTo(ctx.state.CodedOutputStream);
+                }
+                finally
+                {
+                    ctx.LoadStateFrom(ctx.state.CodedOutputStream);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/docs/csharp/proto2.md b/docs/csharp/proto2.md
index 0d9159d..53fc43c 100644
--- a/docs/csharp/proto2.md
+++ b/docs/csharp/proto2.md
@@ -97,7 +97,7 @@
 
 ### Message initialization
 
-Initialization refers to checking the status of required fields in a proto2 message. If a message is uninitialized, not all required fields are set in either the message itself or any of its submessages. In other languages, missing required fields throw errors depending on the merge method used. This could cause unforseen errors at runtime if the incorrect method is used. 
+Initialization refers to checking the status of required fields in a proto2 message. If a message is uninitialized, not all required fields are set in either the message itself or any of its submessages. In other languages, missing required fields throw errors depending on the merge method used. This could cause unforeseen errors at runtime if the incorrect method is used. 
 However, in this implementation, parsers and input streams don't check messages for initialization on their own and throw errors. Instead it's up to you to handle messages with missing required fields in whatever way you see fit.
 Checking message initialization can be done manually via the `IsInitialized` extension method in `MessageExtensions`.
 
diff --git a/docs/field_presence.md b/docs/field_presence.md
new file mode 100644
index 0000000..b208c95
--- /dev/null
+++ b/docs/field_presence.md
@@ -0,0 +1,476 @@
+# Application note: Field presence
+
+This application note explains the various presence tracking disciplines for protobuf fields. It also explains how to enable experimental support for explicit presence tracking for singular proto3 fields with basic types.
+
+## Background
+
+_Field presence_ is the notion of whether a protobuf field has a value. There are two different manifestations of presence for protobufs: _no presence_, where the generated message API stores field values (only), and _explicit presence_, where the API also stores whether or not a field has been set.
+
+Historically, proto2 has mostly followed _explicit presence_, while proto3 exposes only _no presence_ semantics. Singular proto3 fields of basic types (numeric, string, bytes, and enums) which are defined with the `optional` label have _explicit presence_, like proto2 (this is an experimental feature added as of release 3.12, and must be enabled by passing a flag to `protoc`).
+
+### Presence disciplines
+
+_Presence disciplines_ define the semantics for translating between the _API representation_ and the _serialized representation_. The _no presence_ discipline relies upon the field value itself to make decisions at (de)serialization time, while the _explicit presence_ discipline relies upon the explicit tracking state instead.
+
+### Presence in _tag-value stream_ (wire format) serialization
+
+The wire format is a stream of tagged, _self-delimiting_ values. By definition, the wire format represents a sequence of _present_ values. In other words, every value found within a serialization represents a _present_ field; furthermore, the serialization contains no information about not-present values.
+
+The generated API for a proto message includes (de)serialization definitions which translate between API types and a stream of definitionally _present_ (tag, value) pairs. This translation is designed to be forward- and backward-compatibile across changes to the message definition; however, this compatibility introduces some (perhaps surprising) considerations when deserializing wire-formatted messages:
+
+-   When serializing, fields with _no presence_ are not serialized if they contain their default value.
+	-   For numeric types, the default is 0.
+	-   For enums, the default is the zero-valued enumerator.
+	-   For strings, bytes, and repeated fields, the default is the zero-length value.
+	-   For messages, the default is the language-specific null value.
+-   "Empty" length-delimited values (such as empty strings) can be validly represented in serialized values: the field is "present," in the sense that it appears in the wire format. However, if the generated API does not track presence, then these values may not be re-serialized; i.e., the empty field may be "not present" after a serialization round-trip.
+-   When deserializing, duplicate field values may be handled in different ways depending on the field definition.
+	-   Duplicate `repeated` fields are typically appended to the field's API representation. (Note that serializing a _packed_ repeated field produces only one, length-delimited value in the tag stream.)
+	-   Duplicate `optional` field values follow the rule that "the last one wins."
+-   `oneof` fields expose the API-level invariant that only one field is set at a time. However, the wire format may include multiple (tag, value) pairs which notionally belong to the `oneof`. Similar to `optional` fields, the generated API follows the "last one wins" rule.
+-   Out-of-range values are not returned for enum fields in generated proto2 APIs. However, out-of-range values may be stored as _unknown fields_ in the API, even though the wire-format tag was recognized.
+
+### Presence in _named-field mapping_ formats
+
+Protobufs can be represented in human-readable, textual forms. Two notable formats are TextFormat (the output format produced by generated message `DebugString` methods) and JSON. 
+
+These formats have correctness requirements of their own, and are generally stricter than _tagged-value stream_ formats. However, TextFormat more closely mimics the semantics of the wire format, and does, in certain cases, provide similar semantics (for example, appending repeated name-value mappings to a repeated field). In particular, similar to the wire format, TextFormat only includes fields which are present.
+
+JSON is a much stricter format, however, and cannot validly represent some semantics of the wire format or TextFormat.
+
+-   Notably, JSON _elements_ are semantically unordered, and each member must have a unique name. This is different from TextFormat rules for repeated fields.
+-   JSON may include fields that are "not present," unlike the _no presence_ discipline for other formats:
+	-   JSON defines a `null` value, which may be used to represent a _defined but not-present field_.
+	-   Repeated field values may be included in the formatted output, even if they are equal to the default (an empty list).
+-   Because JSON elements are unordered, there is no way to unambiguously interpret the "last one wins" rule.
+    -   In most cases, this is fine: JSON elements must have unique names: repeated field values are not valid JSON, so they do not need to be resolved as they are for TextFormat.
+	-   However, this means that it may not be possible to interpret `oneof` fields unambiguously: if multiple cases are present, they are unordered.
+
+In theory, JSON _can_ represent presence in a semantic-preserving fashion. In practice, however, presence correctness can vary depending upon implementation choices, especially if JSON was chosen as a means to interoperate with clients not using protobufs.
+
+### Presence in proto2 APIs
+
+This table outlines whether presence is tracked for fields in proto2 APIs (both for generated APIs and using dynamic reflection):
+
+Field type                                   | Explicit Presence
+-------------------------------------------- | -----------------
+Singular numeric (integer or floating point) | ✔️
+Singular enum                                | ✔️
+Singular string or bytes                     | ✔️
+Singular message                             | ✔️
+Repeated                                     |
+Oneofs                                       | ✔️
+Maps                                         |
+
+Singular fields (of all types) track presence explicitly in the generated API. The generated message interface includes methods to query presence of fields. For example, the field `foo` has a corresponding `has_foo` method. (The specific name follows the same language-specific naming convention as the field accessors.) These methods are sometimes referred to as "hazzers" within the protobuf implementation.
+
+Similar to singular fields, `oneof` fields explicitly track which one of the members, if any, contains a value. For example, consider this example `oneof`:
+
+```
+oneof foo {
+  int32 a = 1;
+  float b = 2;
+}
+```
+
+Depending on the target language, the generated API would generally include several methods:
+
+-   A hazzer for the oneof: `has_foo`
+-   A _oneof case_ method: `foo`
+-   Hazzers for the members: `has_a`, `has_b`
+-   Getters for the members: `a`, `b`
+
+Repeated fields and maps do not track presence: there is no distinction between an _empty_ and a _not-present_ repeated field.
+
+### Presence in proto3 APIs
+
+This table outlines whether presence is tracked for fields in proto3 APIs (both for generated APIs and using dynamic reflection):
+
+Field type                                   | `optional` | Explicit Presence
+-------------------------------------------- | ---------- | -----------------
+Singular numeric (integer or floating point) | No         |
+Singular enum                                | No         |
+Singular string or bytes                     | No         |
+Singular numeric (integer or floating point) | Yes        | ✔️
+Singular enum                                | Yes        | ✔️
+Singular string or bytes                     | Yes        | ✔️
+Singular message                             | Yes        | ✔️
+Singular message                             | No         | ✔️
+Repeated                                     | N/A        |
+Oneofs                                       | N/A        | ✔️
+Maps                                         | N/A        |
+
+Similar to proto2 APIs, proto3 does not track presence explicitly for repeated fields. Without the `optional` label, proto3 APIs do not track presence for basic types (numeric, string, bytes, and enums), either. (Note that `optional` for proto3 fields is only experimentally available as of release 3.12.) Oneof fields affirmatively expose presence, although the same set of hazzer methods may not generated as in proto2 APIs.
+
+Under the _no presence_ discipline, the default value is synonymous with "not present" for purposes of serialization. To notionally "clear" a field (so it won't be serialized), an API user would set it to the default value.
+
+The default value for enum-typed fields under _no presence_ is the corresponding 0-valued enumerator. Under proto3 syntax rules, all enum types are required to have an enumerator value which maps to 0. By convention, this is an `UNKNOWN` or similarly-named enumerator. If the zero value is notionally outside the domain of valid values for the application, this behavior can be thought of as tantamount to _explicit presence_.
+
+## Semantic differences
+
+The _no presence_ serialization discipline results in visible differences from the _explicit presence_ tracking discipline, when the default value is set. For a singular field with numeric, enum, or string type:
+
+-   _No presence_ discipline:
+	-   Default values are not serialized.
+	-   Default values are _not_ merged-from.
+	-   To "clear" a field, it is set to its default value.
+    -   The default value may mean:
+		-   the field was explicitly set to its default value, which is valid in the application-specific domain of values;
+		-   the field was notionally "cleared" by setting its default; or
+		-   the field was never set.
+-   _Explicit presence_ discipline:
+	-   Explicitly set values are always serialized, including default values.
+	-   Un-set fields are never merged-from.
+	-   Explicitly set fields -- including default values -- _are_ merged-from.
+	-   A generated `has_foo` method indicates whether or not the field `foo` has been set (and not cleared).
+	-   A generated `clear_foo` method must be used to clear (i.e., un-set) the value.
+
+### Considerations for merging
+
+Under the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, similar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message.
+
+The difference in merging behavior has further implications for protocols which rely on partial "patch" updates. If field presence is not tracked, then an update patch alone cannot represent an update to the default value, because only non-default values are merged-from.
+
+Updating to set a default value in this case requires some external mechanism, such as `FieldMask`. However, if presence _is_ tracked, then all explicitly-set values -- even default values -- will be merged into the target.
+
+### Considerations for change-compatibility
+
+Changing a field between _explicit presence_ and _no presence_ is a binary-compatible change for serialized values in wire format. However, the serialized representation of the message may differ, depending on which version of the message definition was used for serialization. Specifically, when a "sender" explicitly sets a field to its default value:
+
+-   The serialized value following _no presence_ discipline does not contain the default value, even though it was explicitly set.
+-   The serialized value following _explicit presence_ discipline contains every "present" field, even if it contains the default value.
+
+This change may or may not be safe, depending on the application's semantics. For example, consider two clients with different versions of a message definition.
+
+Client A uses this definition of the message, which follows the _explicit presence_ serialization discipline for field `foo`:
+
+```
+syntax = "proto3";
+message Msg {
+  optional int32 foo = 1;
+}
+```
+
+Client B uses a definition of the same message, except that it follows the _no presence_ discipline:
+
+```
+syntax = "proto3";
+message Msg {
+  int32 foo = 1;
+}
+```
+
+Now, consider a scenario where client A observes `foo`'s presence as the clients repeatedly exchange the "same" message by deserializing and reserializing:
+
+```
+// Client A:
+Msg m_a;
+m_a.set_foo(1);                  // non-default value
+assert(m_a.has_foo());           // OK
+Send(m_a.SerializeAsString());   // to client B
+
+// Client B:
+Msg m_b;
+m_b.ParseFromString(Receive());  // from client A
+assert(m_b.foo() == 1);          // OK
+Send(m_b.SerializeAsString());   // to client A
+
+// Client A:
+m_a.ParseFromString(Receive());  // from client B
+assert(m_a.foo() == 1);          // OK
+assert(m_a.has_foo());           // OK
+m_a.set_foo(0);                  // default value
+Send(m_a.SerializeAsString());   // to client B
+
+// Client B:
+Msg m_b;
+m_b.ParseFromString(Receive());  // from client A
+assert(m_b.foo() == 0);          // OK
+Send(m_b.SerializeAsString());   // to client A
+
+// Client A:
+m_a.ParseFromString(Receive());  // from client B
+assert(m_a.foo() == 0);          // OK
+assert(m_a.has_foo());           // FAIL
+```
+
+If client A depends on _explicit presence_ for `foo`, then a "round trip" through client B will be lossy from the perspective of client A. In the example, this is not a safe change: client A requires (by `assert`) that the field is present; even without any modifications through the API, that requirement fails in a value- and peer-dependent case.
+
+## How to enable _explicit presence_ in proto3
+
+These are the general steps to use the experimental field tracking support for proto3:
+
+1.  Add an `optional` field to a `.proto` file.
+1.  Run `protoc` (from release 3.12 or later) with an extra flag to recognize `optional` (i.e,. explicit presence) in proto3 files.
+1.  Use the generated "hazzer" methods and "clear" methods in application code, instead of comparing or setting default values.
+
+### `.proto` file changes
+
+This is an example of a proto3 message with fields which follow both _no presence_ and _explicit presence_ semantics:
+
+```
+syntax = "proto3";
+package example;
+
+message MyMessage {
+  // No presence:
+  int32 not_tracked = 1;
+
+  // Explicit presence:
+  optional int32 tracked = 2;
+}
+```
+
+### `protoc` invocation
+
+To enable presence tracking for proto3 messages, pass the `--experimental_allow_proto3_optional` flag to protoc. Without this flag, the `optional` label is an error in files using proto3 syntax. This flag is available in protobuf release 3.12 or later (or at HEAD, if you are reading this application note from Git).
+
+### Using the generated code
+
+The generated code for proto3 fields with _explicit presence_ (the `optional` label) will be the same as it would be in a proto2 file.
+
+This is the definition used in the "no presence" examples below:
+
+```
+syntax = "proto3";
+package example;
+message Msg {  
+  int32 foo = 1;
+}
+```
+
+This is the definition used in the "explicit presence" examples below:
+
+```
+syntax = "proto3";
+package example;
+message Msg {
+  optional int32 foo = 1;
+}
+```
+
+In the examples, a function `GetProto` constructs and returns a message of type `Msg` with unspecified contents.
+
+#### C++ example
+
+No presence:
+
+```
+Msg m = GetProto();
+if (m.foo() != 0) {
+  // "Clear" the field:
+  m.set_foo(0);
+} else {
+  // Default value: field may not have been present.
+  m.set_foo(1);
+}
+```
+
+Explicit presence:
+
+```
+Msg m = GetProto();
+if (m.has_foo()) {
+  // Clear the field:
+  m.clear_foo();
+} else {
+  // Field is not present, so set it.
+  m.set_foo(1);
+}
+```
+
+#### C# example
+
+No presence:
+
+```
+var m = GetProto();
+if (m.Foo != 0) {
+  // "Clear" the field:
+  m.Foo = 0;
+} else {
+  // Default value: field may not have been present.
+  m.Foo = 1;
+}
+```
+
+Explicit presence:
+
+```
+var m = GetProto();
+if (m.HasFoo) {
+  // Clear the field:
+  m.ClearFoo();
+} else {
+  // Field is not present, so set it.
+  m.Foo = 1;
+}
+```
+
+#### Go example
+
+No presence:
+
+```
+m := GetProto()
+if m.Foo != 0 {
+  // "Clear" the field:
+  m.Foo = 0
+} else {
+  // Default value: field may not have been present.
+  m.Foo = 1
+}
+```
+
+Explicit presence:
+
+```
+m := GetProto()
+if m.Foo != nil {
+  // Clear the field:
+  m.Foo = nil
+} else {
+  // Field is not present, so set it.
+  m.Foo = proto.Int32(1)
+}
+```
+
+#### Java example
+
+These examples use a `Builder` to demonstrate clearing. Simply checking presence and getting values from a `Builder` follows the same API as the message type.
+
+No presence:
+
+```
+Msg.Builder m = GetProto().toBuilder();
+if (m.getFoo() != 0) {
+  // "Clear" the field:
+  m.setFoo(0);
+} else {
+  // Default value: field may not have been present.
+  m.setFoo(1);
+}
+```
+
+Explicit presence:
+
+```
+Msg.Builder m = GetProto().toBuilder();
+if (m.hasFoo()) {
+  // Clear the field:
+  m.clearFoo()
+} else {
+  // Field is not present, so set it.
+  m.setFoo(1);
+}
+```
+
+#### Python example
+
+No presence:
+
+```
+m = example.Msg()
+if m.foo != 0:
+  // "Clear" the field:
+  m.foo = 0
+else:
+  // Default value: field may not have been present.
+  m.foo = 1
+```
+
+Explicit presence:
+
+```
+m = example.Msg()
+if m.HasField('foo'):
+  // Clear the field:
+  m.ClearField('foo')
+else:
+  // Field is not present, so set it.
+  m.foo = 1
+```
+
+#### Ruby example
+
+No presence:
+
+```
+m = Msg.new
+if m.foo != 0
+  // "Clear" the field:
+  m.foo = 0
+else
+  // Default value: field may not have been present.
+  m.foo = 1
+end
+```
+
+Explicit presence:
+
+```
+m = Msg.new
+if m.has_foo?
+  // Clear the field:
+  m.clear_foo
+else
+  // Field is not present, so set it.
+  m.foo = 1
+end
+```
+
+#### Javascript example
+
+No presence:
+
+```
+var m = new Msg();
+if (m.getFoo() != 0) {
+  // "Clear" the field:
+  m.setFoo(0);
+} else {
+  // Default value: field may not have been present.
+  m.setFoo(1);
+}
+```
+
+Explicit presence:
+
+```
+var m = new Msg();
+if (m.hasFoo()) {
+  // Clear the field:
+  m.clearFoo()
+} else {
+  // Field is not present, so set it.
+  m.setFoo(1);
+}
+```
+
+#### Objective C example
+
+No presence:
+
+```
+Msg *m = [[Msg alloc] init];
+if (m.foo != 0) {
+  // "Clear" the field:
+  m.foo = 0;
+} else {
+  // Default value: field may not have been present.
+  m.foo = 1;
+}
+```
+
+Explicit presence:
+
+```
+Msg *m = [[Msg alloc] init];
+if (m.hasFoo()) {
+  // Clear the field:
+  [m clearFoo];
+} else {
+  // Field is not present, so set it.
+  [m setFoo:1];
+}
+```
diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md
new file mode 100644
index 0000000..ae8b369
--- /dev/null
+++ b/docs/implementing_proto3_presence.md
@@ -0,0 +1,400 @@
+# How To Implement Field Presence for Proto3
+
+Protobuf release 3.12 adds experimental support for `optional` fields in
+proto3. Proto3 optional fields track presence like in proto2. For background
+information about what presence tracking means, please see
+[docs/field_presence](field_presence.md).
+
+## Document Summary
+
+This document is targeted at developers who own or maintain protobuf code
+generators. All code generators will need to be updated to support proto3
+optional fields. First-party code generators developed by Google are being
+updated already. However third-party code generators will need to be updated
+independently by their authors. This includes:
+
+- implementations of Protocol Buffers for other languages.
+- alternate implementations of Protocol Buffers that target specialized use
+  cases.
+- RPC code generators that create generated APIs for service calls.
+- code generators that implement some utility code on top of protobuf generated
+  classes.
+
+While this document speaks in terms of "code generators", these same principles
+apply to implementations that dynamically generate a protocol buffer API "on the
+fly", directly from a descriptor, in languages that support this kind of usage.
+
+## Background
+
+Presence tracking was added to proto3 in response to user feedback, both from
+inside Google and [from open-source
+users](https://github.com/protocolbuffers/protobuf/issues/1606). The [proto3
+wrapper
+types](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/wrappers.proto)
+were previously the only supported presence mechanism for proto3. Users have
+pointed to both efficiency and usability issues with the wrapper types.
+
+Presence in proto3 uses exactly the same syntax and semantics as in proto2.
+Proto3 Fields marked `optional` will track presence like proto2, while fields
+without any label (known as "singular fields"), will continue to omit presence
+information.  The `optional` keyword was chosen to minimize differences with
+proto2.
+
+Unfortunately, for the current descriptor protos and `Descriptor` API (as of
+3.11.4) it is not possible to use the same representation as proto2. Proto3
+descriptors already use `LABEL_OPTIONAL` for proto3 singular fields, which do
+not track presence. There is a lot of existing code that reflects over proto3
+protos and assumes that `LABEL_OPTIONAL` in proto3 means "no presence." Changing
+the semantics now would be risky, since old software would likely drop proto3
+presence information, which would be a data loss bug.
+
+To minimize this risk we chose a descriptor representation that is semantically
+compatible with existing proto3 reflection. Every proto3 optional field is
+placed into a one-field `oneof`. We call this a "synthetic" oneof, as it was not
+present in the source `.proto` file.
+
+Since oneof fields in proto3 already track presence, existing proto3
+reflection-based algorithms should correctly preserve presence for proto3
+optional fields with no code changes. For example, the JSON and TextFormat
+parsers/serializers in C++ and Java did not require any changes to support
+proto3 presence. This is the major benefit of synthetic oneofs.
+
+This design does leave some cruft in descriptors. Synthetic oneofs are a
+compatibility measure that we can hopefully clean up in the future. For now
+though, it is important to preserve them across different descriptor formats and
+APIs. It is never safe to drop synthetic oneofs from a proto schema. Code
+generators can (and should) skip synthetic oneofs when generating a user-facing
+API or user-facing documentation. But for any schema representation that is
+consumed programmatically, it is important to keep the synthetic oneofs around.
+
+In APIs it can be helpful to offer separate accessors that refer to "real"
+oneofs (see [API Changes](#api-changes) below). This is a convenient way to omit
+synthetic oneofs in code generators.
+
+## Updating a Code Generator
+
+When a user adds an `optional` field to proto3, this is internally rewritten as
+a one-field oneof, for backward-compatibility with reflection-based algorithms:
+
+```protobuf
+syntax = "proto3";
+
+message Foo {
+  // Experimental feature, not generally supported yet!
+  optional int32 foo = 1;
+
+  // Internally rewritten to:
+  // oneof _foo {
+  //   int32 foo = 1 [proto3_optional=true];
+  // }
+  //
+  // We call _foo a "synthetic" oneof, since it was not created by the user.
+}
+```
+
+As a result, the main two goals when updating a code generator are:
+
+1. Give `optional` fields like `foo` normal field presence, as described in
+   [docs/field_presence](field_presence.md) If your implementation already
+   supports proto2, a proto3 `optional` field should use exactly the same API
+   and internal implementation as proto2 `optional`.
+2. Avoid generating any oneof-based accessors for the synthetic oneof. Its only
+   purpose is to make reflection-based algorithms work properly if they are
+   not aware of proto3 presence. The synthetic oneof should not appear anywhere
+   in the generated API.
+
+### Satisfying the Experimental Check
+
+If you try to run `protoc` on a file with proto3 `optional` fields, you will get
+an error because the feature is still experimental:
+
+```
+$ cat test.proto
+syntax = "proto3";
+
+message Foo {
+  // Experimental feature, not generally supported yet!
+  optional int32 a = 1;
+}
+$ protoc --cpp_out=. test.proto
+test.proto: This file contains proto3 optional fields, but --experimental_allow_proto3_optional was not set.
+```
+
+There are two options for getting around this error:
+
+1. Pass `--experimental_allow_proto3_optional` to protoc.
+2. Make your filename (or a directory name) contain the string
+   `test_proto3_optional`. This indicates that the proto file is specifically
+   for testing proto3 optional support, so the check is suppressed.
+
+These options are demonstrated below:
+
+```
+# One option:
+$ ./src/protoc test.proto --cpp_out=. --experimental_allow_proto3_optional
+
+# Another option:
+$ cp test.proto test_proto3_optional.proto
+$ ./src/protoc test_proto3_optional.proto --cpp_out=.
+$
+```
+
+The experimental check will be removed  in a future release, once we are ready
+to make this feature generally available. Ideally this will happen for the 3.13
+release of protobuf, sometime in mid-2020, but there is not a specific date set
+for this yet. Some of the timing will depend on feedback we get from the
+community, so if you have questions or concerns please get in touch via a
+GitHub issue.
+
+### Signaling That Your Code Generator Supports Proto3 Optional
+
+If you now try to invoke your own code generator with the test proto, you will
+run into a different error:
+
+```
+$ ./src/protoc test_proto3_optional.proto --my_codegen_out=.
+test_proto3_optional.proto: is a proto3 file that contains optional fields, but
+code generator --my_codegen_out hasn't been updated to support optional fields in
+proto3. Please ask the owner of this code generator to support proto3 optional.
+```
+
+This check exists to make sure that code generators get a chance to update
+before they are used with proto3 `optional` fields. Without this check an old
+code generator might emit obsolete generated APIs (like accessors for a
+synthetic oneof) and users could start depending on these. That would create
+a legacy migration burden once a code generator actually implements the feature.
+
+To signal that your code generator supports `optional` fields in proto3, you
+need to tell `protoc` what features you support. The method for doing this
+depends on whether you are using the C++
+`google::protobuf::compiler::CodeGenerator`
+framework or not.
+
+If you are using the CodeGenerator framework:
+
+```c++
+class MyCodeGenerator : public google::protobuf::compiler::CodeGenerator {
+  // Add this method.
+  uint64_t GetSupportedFeatures() const override {
+    // Indicate that this code generator supports proto3 optional fields.
+    // (Note: don't release your code generator with this flag set until you
+    // have actually added and tested your proto3 support!)
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+}
+```
+
+If you are generating code using raw `CodeGeneratorRequest` and
+`CodeGeneratorResponse` messages from `plugin.proto`, the change will be very
+similar:
+
+```c++
+void GenerateResponse() {
+  CodeGeneratorResponse response;
+  response.set_supported_features(CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL);
+
+  // Generate code...
+}
+```
+
+Once you have added this, you should now be able to successfully use your code
+generator to generate a file containing proto3 optional fields:
+
+```
+$ ./src/protoc test_proto3_optional.proto --my_codegen_out=.
+```
+
+### Updating Your Code Generator
+
+Now to actually add support for proto3 optional to your code generator. The goal
+is to recognize proto3 optional fields as optional, and suppress any output from
+synthetic oneofs.
+
+If your code generator does not currently support proto2, you will need to
+design an API and implementation for supporting presence in scalar fields.
+Generally this means:
+
+- allocating a bit inside the generated class to represent whether a given field
+  is present or not.
+- exposing a `has_foo()` method for each field to return the value of this bit.
+- make the parser set this bit when a value is parsed from the wire.
+- make the serializer test this bit to decide whether to serialize.
+
+If your code generator already supports proto2, then most of your work is
+already done. All you need to do is make sure that proto3 optional fields have
+exactly the same API and behave in exactly the same way as proto2 optional
+fields.
+
+From experience updating several of Google's code generators, most of the
+updates that are required fall into one of several patterns. Here we will show
+the patterns in terms of the C++ CodeGenerator framework. If you are using
+`CodeGeneratorRequest` and `CodeGeneratorReply` directly, you can translate the
+C++ examples to your own language, referencing the C++ implementation of these
+methods where required.
+
+#### To test whether a field should have presence
+
+Old:
+
+```c++
+bool MessageHasPresence(const google::protobuf::Descriptor* message) {
+  return message->file()->syntax() ==
+         google::protobuf::FileDescriptor::SYNTAX_PROTO2;
+}
+```
+
+New:
+
+```c++
+// Presence is no longer a property of a message, it's a property of individual
+// fields.
+bool FieldHasPresence(const google::protobuf::FieldDescriptor* field) {
+  return field->has_presence();
+  // Note, the above will return true for fields in a oneof.
+  // If you want to filter out oneof fields, write this instead:
+  //   return field->has_presence && !field->real_containing_oneof()
+}
+```
+
+#### To test whether a field is a member of a oneof
+
+Old:
+
+```c++
+bool FieldIsInOneof(const google::protobuf::FieldDescriptor* field) {
+  return field->containing_oneof() != nullptr;
+}
+```
+
+New:
+
+```c++
+bool FieldIsInOneof(const google::protobuf::FieldDescriptor* field) {
+  // real_containing_oneof() returns nullptr for synthetic oneofs.
+  return field->real_containing_oneof() != nullptr;
+}
+```
+
+#### To iterate over all oneofs
+
+Old:
+
+```c++
+bool IterateOverOneofs(const google::protobuf::Descriptor* message) {
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const google::protobuf::OneofDescriptor* oneof = message->oneof(i);
+    // ...
+  }
+}
+```
+
+New:
+
+```c++
+bool IterateOverOneofs(const google::protobuf::Descriptor* message) {
+  // Real oneofs are always first, and real_oneof_decl_count() will return the
+  // total number of oneofs, excluding synthetic oneofs.
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+    const google::protobuf::OneofDescriptor* oneof = message->oneof(i);
+    // ...
+  }
+}
+```
+
+## Updating Reflection
+
+If your implementation offers reflection, there are a few other changes to make:
+
+### API Changes
+
+The API for reflecting over fields and oneofs should make the following changes.
+These match the changes implemented in C++ reflection.
+
+1. Add a `FieldDescriptor::has_presence()` method returning `bool`
+   (adjusted to your language's naming convention).  This should return true
+   for all fields that have explicit presence, as documented in
+   [docs/field_presence](field_presence.md).  In particular, this includes
+   fields in a oneof, proto2 scalar fields, and proto3 `optional` fields.
+   This accessor will allow users to query what fields have presence without
+   thinking about the difference between proto2 and proto3.
+2. As a corollary of (1), please do *not* expose an accessor for the
+   `FieldDescriptorProto.proto3_optional` field. We want to avoid having
+   users implement any proto2/proto3-specific logic. Users should use the
+   `has_presence()` function instead.
+3. You may also wish to add a `FieldDescriptor::has_optional_keyword()` method
+   returning `bool`, which indicates whether the `optional` keyword is present.
+   Message fields will always return `true` for `has_presence()`, so this method
+   can allow a user to know whether the user wrote `optional` or not. It can
+   occasionally be useful to have this information, even though it does not
+   change the presence semantics of the field.
+4. If your reflection API may be used for a code generator, you may wish to
+   implement methods to help users tell the difference between real and
+   synthetic oneofs.  In particular:
+   - `OneofDescriptor::is_synthetic()`: returns true if this is a synthetic
+     oneof.
+   - `FieldDescriptor::real_containing_oneof()`: like `containing_oneof()`,
+     but returns `nullptr` if the oneof is synthetic.
+   - `Descriptor::real_oneof_decl_count()`: like `oneof_decl_count()`, but
+     returns the number of real oneofs only.
+
+### Implementation Changes
+
+Proto3 `optional` fields and synthetic oneofs must work correctly when
+reflected on. Specifically:
+
+1. Reflection for synthetic oneofs should work properly. Even though synthetic
+   oneofs do not really exist in the message, you can still make reflection work
+   as if they did. In particular, you can make a method like
+   `Reflection::HasOneof()` or `Reflection::GetOneofFieldDescriptor()` look at
+   the hasbit to determine if the oneof is present or not.
+2. Reflection for proto3 optional fields should work properly. For example, a
+   method like `Reflection::HasField()` should know to look for the hasbit for a
+   proto3 `optional` field. It should not be fooled by the synthetic oneof into
+   thinking that there is a `case` member for the oneof.
+
+Once you have updated reflection to work properly with proto3 `optional` and
+synthetic oneofs, any code that *uses* your reflection interface should work
+properly with no changes. This is the benefit of using synthetic oneofs.
+
+In particular, if you have a reflection-based implementation of protobuf text
+format or JSON, it should properly support proto3 optional fields without any
+changes to the code. The fields will look like they all belong to a one-field
+oneof, and existing proto3 reflection code should know how to test presence for
+fields in a oneof.
+
+So the best way to test your reflection changes is to try round-tripping a
+message through text format, JSON, or some other reflection-based parser and
+serializer, if you have one.
+
+### Validating Descriptors
+
+If your reflection implementation supports loading descriptors at runtime,
+you must verify that all synthetic oneofs are ordered after all "real" oneofs.
+
+Here is the code that implements this validation step in C++, for inspiration:
+
+```c++
+  // Validation that runs for each message.
+  // Synthetic oneofs must be last.
+  int first_synthetic = -1;
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    if (oneof->is_synthetic()) {
+      if (first_synthetic == -1) {
+        first_synthetic = i;
+      }
+    } else {
+      if (first_synthetic != -1) {
+        AddError(message->full_name(), proto.oneof_decl(i),
+                 DescriptorPool::ErrorCollector::OTHER,
+                 "Synthetic oneofs must be after all other oneofs");
+      }
+    }
+  }
+
+  if (first_synthetic == -1) {
+    message->real_oneof_decl_count_ = message->oneof_decl_count_;
+  } else {
+    message->real_oneof_decl_count_ = first_synthetic;
+  }
+```
diff --git a/docs/jvm_aot.md b/docs/jvm_aot.md
new file mode 100644
index 0000000..4eb682f
--- /dev/null
+++ b/docs/jvm_aot.md
@@ -0,0 +1,18 @@
+# Ahead Of Time (AOT) compilation for the Java Virtual Machine (JVM)"
+
+Ahead Of Time (AOT) compilation build tools such as those provided by [GraalVM's `native-image`](https://www.graalvm.org/reference-manual/native-image/) can require some configuration when using protobuf.
+Protobuf for the JVM uses reflection and some of its target classes are not possible to determine in advance.
+Historically, there were good reasons to use reflection based on APIs that were published effectively requiring them, and this situation is unlikely to change.
+
+[The Lite version of protobuf for the JVM](https://github.com/protocolbuffers/protobuf/blob/master/java/lite.md)
+avoids reflection and may be better suited for use with AOT compilation tooling. This Lite version was originally targeted for use on Android which has similar AOT compilation
+goals as GraalVM's native-image tool.
+
+## GraalVM native-image
+
+This section addresses GraalVM's `native-image` configuration specifically as this AOT compilation tool due to its popularity. The `native-image` tool can be configured
+with respect to: the [Java Native Interface](https://en.wikipedia.org/wiki/Java_Native_Interface) (JNI), http proxying, reflection, and other resources. While these
+considerations can be manually declared as JSON files, we recommend that a JVM application is exercised along with 
+[the assisted configuration agent](https://www.graalvm.org/reference-manual/native-image/BuildConfiguration/#assisted-configuration-of-native-image-builds). The agent
+will generate files that you can then subsequently point at when invoking `native-image`. We recommend that the generated files are retained with a project's source
+code.
diff --git a/docs/options.md b/docs/options.md
index df6b88c..61851f2 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -93,8 +93,8 @@
    * Website: https://github.com/protobuf-c/protobuf-c
    * Extensions: 1019
 
-1. ScalePB
-   * Website: http://trueaccord.github.io/ScalaPB/
+1. ScalaPB
+   * Website: https://scalapb.github.io/
    * Extensions: 1020
 
 1. protoc-gen-bq-schema
@@ -244,3 +244,43 @@
 1. ADLINK EdgeSDK
    * Website: https://www.adlinktech.com/en/Edge-SDK-IoT
    * Extensions: 1086
+
+1. Wire wire_package
+   * Website: https://square.github.io/wire/
+   * Extensions: 1087
+
+1. Confluent Schema Registry
+   * Website: https://github.com/confluentinc/schema-registry
+   * Extensions: 1088
+
+1. ScalaPB Validate
+   * Website: https://scalapb.github.io/docs/validation
+   * Extension: 1089
+
+1. Astounding (Currently Private)
+   * Website: https://github.com/PbPipes/Astounding
+   * Extension: 1090
+
+1. Protoc-gen-psql
+   * Website: https://github.com/Intrinsec/protoc-gen-psql
+   * Extension: 1091-1101
+
+1. Protoc-gen-sanitize
+   * Website: https://github.com/Intrinsec/protoc-gen-sanitize
+   * Extension: 1102-1106
+
+1. Coach Client Connect (planned release in March 2021)
+   * Website: https://www.coachclientconnect.com
+   * Extension: 1107
+
+1. Kratos API Errors
+   * Website: https://go-kratos.dev
+   * Extension: 1108
+
+1. Glitchdot (Currently Private)
+   * Website: https://go.glitchdot.com
+   * Extension: 1109
+
+1. eigr/protocol
+   * Website: https://eigr.io
+   * Extension: 1110-1114
\ No newline at end of file
diff --git a/docs/third_party.md b/docs/third_party.md
index 11a6efb..4075327 100644
--- a/docs/third_party.md
+++ b/docs/third_party.md
@@ -11,6 +11,7 @@
 * Action Script: https://code.google.com/p/protoc-gen-as3/
 * Action Script: https://github.com/matrix3d/JProtoc
 * Action Script: https://github.com/zhongfq/protobuf-as3/
+* Ada: https://github.com/reznikmm/protobuf
 * C: https://github.com/protobuf-c/protobuf-c
 * C: http://koti.kapsi.fi/jpa/nanopb/
 * C: https://github.com/cloudwu/pbc/
@@ -18,6 +19,7 @@
 * C: https://github.com/squidfunk/protobluff
 * C: https://github.com/eerimoq/pbtools
 * C++: https://github.com/google/protobuf (Google-official implementation)
+* C++: https://EmbeddedProto.com
 * C/C++: http://spbc.sf.net/
 * C#: http://code.google.com/p/protobuf-csharp-port
 * C#: https://silentorbit.com/protobuf/
@@ -25,8 +27,8 @@
 * Clojure: http://github.com/ninjudd/clojure-protobuf
 * Clojure: https://github.com/clojusc/protobuf
 * Clojure: https://protojure.github.io
-* Common Lisp: http://github.com/ndantam/s-protobuf
 * Common Lisp: http://github.com/brown/protobuf
+* Common Lisp: http://github.com/qitab/cl-protobuf
 * D: https://github.com/dcarp/protobuf-d
 * D: https://github.com/msoucy/dproto
 * D: https://github.com/opticron/ProtocolBuffer
@@ -35,6 +37,7 @@
 * Delphi: http://fundementals.sourceforge.net/dl.html
 * Elixir: https://github.com/jeremyong/exprotoc
 * Elixir: https://github.com/tony612/protobuf-elixir
+* Elixir: https://github.com/ahamez/protox
 * Elm: https://github.com/tiziano88/elm-protobuf
 * Erlang: https://github.com/tomas-abrahamsson/gpb
 * Erlang: http://piqi.org/
@@ -60,9 +63,13 @@
 * Javascript: https://github.com/dcodeIO/ProtoBuf.js
 * Javascript: http://code.google.com/p/protobuf-for-node/
 * Javascript: http://code.google.com/p/protostuff/
+* Javascript: https://github.com/seishun/node-protoc-plugin (Node.js port of plugin.h)
+* Javascript: https://github.com/seishun/node-protoc-gen-javascript (Node.js port of the Google-official implementation)
+* Javascript: https://github.com/ButterCam/sisyphus-js
 * Julia: https://github.com/tanmaykm/ProtoBuf.jl
 * Kotlin: https://github.com/marcoferrer/kroto-plus
 * Kotlin: https://github.com/Kotlin/kotlinx.serialization
+* Kotlin: https://github.com/ButterCam/sisyphus
 * Lua: http://code.google.com/p/protoc-gen-lua/
 * Lua: http://github.com/indygreg/lua-protobuf
 * Lua: https://github.com/Neopallium/lua-pb
@@ -80,6 +87,7 @@
 * PHP: https://github.com/chobie/php-protocolbuffers
 * PHP: http://drslump.github.com/Protobuf-PHP
 * Prolog: http://www.swi-prolog.org/pldoc/package/protobufs.html
+* Purescript: https://github.com/xc-jp/purescript-protobuf
 * Python: https://github.com/google/protobuf (Google-official implementation)
 * Python: https://github.com/eigenein/protobuf
 * Python: https://github.com/danielgtaylor/python-betterproto
@@ -96,7 +104,7 @@
 * Solidity: https://github.com/celer-network/pb3-gen-sol
 * Swift: https://github.com/alexeyxo/protobuf-swift
 * Swift: https://github.com/apple/swift-protobuf/
-* Typescript: https://github.com/y3llowcake/protoc-gen-ts
+* Typescript: https://github.com/thesayyn/protoc-gen-ts
 * Vala: https://launchpad.net/protobuf-vala
 * Visual Basic: http://code.google.com/p/protobuf-net/
 
@@ -152,7 +160,8 @@
 * [Alternate encodings (JSON, XML, HTML) for Java protobufs](http://code.google.com/p/protobuf-java-format/)
 * [Another JSON encoder/decoder for Java](https://github.com/sijuv/protobuf-codec)
 * [Editor for serialized protobufs](http://code.google.com/p/protobufeditor/)
-* [Intellij IDEA plugin](http://github.com/nnmatveev/idea-plugin-protobuf)
+* [IntelliJ IDEA plugin](http://github.com/jvolkman/intellij-protobuf-editor)
+* [IntelliJ Protobuf Plugin](https://github.com/devkanro/intellij-protobuf-plugin)
 * [TextMate syntax highlighting](http://github.com/michaeledgar/protobuf-tmbundle)
 * [Oracle PL SQL plugin](http://code.google.com/p/protocol-buffer-plsql/)
 * [Eclipse editor for protobuf (from Google)](http://code.google.com/p/protobuf-dt/)
@@ -182,3 +191,9 @@
 * [Protocol Buffer property-based testing utility and example message generator (Python / Hypothesis)](https://github.com/CurataEng/hypothesis-protobuf)
 * [Protolock - CLI utility to prevent backward-incompatible changes to .proto files](https://github.com/nilslice/protolock)
 * [Optional GRPC - GRPC for testable microservices (Python)](https://github.com/mattpaletta/optional-grpc.git)
+* [Protobuf Parser - Yet another Go package which parses a Protocol Buffer file (proto2+proto3)](https://github.com/yoheimuta/go-protoparser)
+* [Protolint - A tool to enforce Protocol Buffer style and conventions.](https://github.com/yoheimuta/protolint)
+    * [vscode-protolint: A protobuf linter for visual studio code](https://github.com/plexsystems/vscode-protolint)
+    * [intellij-protolint: A protobuf linter for JetBrains IDEs](https://github.com/yoheimuta/intellij-protolint)
+    * [vim-protolint: A protobuf linter for Vim](https://github.com/yoheimuta/vim-protolint)
+* [super-linter: Protocol Buffer lint as GitHub Action](https://github.com/github/super-linter)
diff --git a/editors/proto.vim b/editors/proto.vim
index 7f1aeb7..bdc60ce 100644
--- a/editors/proto.vim
+++ b/editors/proto.vim
@@ -69,10 +69,10 @@
 syn match   pbInt     /-\?\<\d\+\>/
 syn match   pbInt     /\<0[xX]\x+\>/
 syn match   pbFloat   /\<-\?\d*\(\.\d*\)\?/
-syn region  pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp
-syn region  pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp
-syn region  pbString  start=/"/ skip=/\\./ end=/"/
-syn region  pbString  start=/'/ skip=/\\./ end=/'/
+syn region  pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp,@Spell
+syn region  pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp,@Spell
+syn region  pbString  start=/"/ skip=/\\./ end=/"/ contains=@Spell
+syn region  pbString  start=/'/ skip=/\\./ end=/'/ contains=@Spell
 
 if version >= 508 || !exists("did_proto_syn_inits")
   if version < 508
diff --git a/editors/protobuf-mode.el b/editors/protobuf-mode.el
index d3bdcde..8102771 100644
--- a/editors/protobuf-mode.el
+++ b/editors/protobuf-mode.el
@@ -1,4 +1,4 @@
-;;; protobuf-mode.el --- major mode for editing protocol buffers.
+;;; protobuf-mode.el --- major mode for editing protocol buffers.  -*- lexical-binding: t; -*-
 
 ;; Author: Alexandre Vassalotti <alexandre@peadrop.com>
 ;; Created: 23-Apr-2009
@@ -216,7 +216,11 @@
   (c-common-init 'protobuf-mode)
   (easy-menu-add protobuf-menu)
   (c-run-mode-hooks 'c-mode-common-hook 'protobuf-mode-hook)
-  (c-update-modeline))
+  (c-update-modeline)
+  (setq imenu-generic-expression
+	    '(("Message" "^[[:space:]]*message[[:space:]]+\\([[:alnum:]]+\\)" 1)
+          ("Enum" "^[[:space:]]*enum[[:space:]]+\\([[:alnum:]]+\\)" 1)
+          ("Service" "^[[:space:]]*service[[:space:]]+\\([[:alnum:]]+\\)" 1))))
 
 (provide 'protobuf-mode)
 
diff --git a/examples/AddPerson.java b/examples/AddPerson.java
index c262ab7..2f6a231 100644
--- a/examples/AddPerson.java
+++ b/examples/AddPerson.java
@@ -1,7 +1,7 @@
 // See README.txt for information and build instructions.
 
-import com.example.tutorial.AddressBookProtos.AddressBook;
-import com.example.tutorial.AddressBookProtos.Person;
+import com.example.tutorial.protos.AddressBook;
+import com.example.tutorial.protos.Person;
 import java.io.BufferedReader;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 3e8e654..1136296 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -8,7 +8,7 @@
 find_package(protobuf CONFIG REQUIRED)
 
 if(protobuf_VERBOSE)
-  message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
+  message(STATUS "Using Protocol Buffers ${protobuf_VERSION}")
 endif()
 
 set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
diff --git a/examples/ListPeople.java b/examples/ListPeople.java
index 580f7ac..ab07b79 100644
--- a/examples/ListPeople.java
+++ b/examples/ListPeople.java
@@ -1,7 +1,7 @@
 // See README.txt for information and build instructions.
 
-import com.example.tutorial.AddressBookProtos.AddressBook;
-import com.example.tutorial.AddressBookProtos.Person;
+import com.example.tutorial.protos.AddressBook;
+import com.example.tutorial.protos.Person;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.PrintStream;
diff --git a/examples/Makefile b/examples/Makefile
index e9f9635..8ed2492 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -16,7 +16,7 @@
 	rm -f javac_middleman AddPerson*.class ListPeople*.class com/example/tutorial/*.class
 	rm -f protoc_middleman addressbook.pb.cc addressbook.pb.h addressbook_pb2.py com/example/tutorial/AddressBookProtos.java
 	rm -f *.pyc
-	rm -f protoc_middleman_go tutorial/*.pb.go add_person_go list_people_go
+	rm -f protoc_middleman_go tutorial/*.pb.go add_person_go list_people_go go.mod go.sum
 	rm -f protoc_middleman_dart dart_tutorial/*.pb*.dart
 	rmdir dart_tutorial 2>/dev/null || true
 	rmdir tutorial 2>/dev/null || true
@@ -51,16 +51,20 @@
 
 list_people_dart: list_people.dart protoc_middleman_dart
 
-add_person_go: add_person.go protoc_middleman_go
+go_mod:
+	go mod init github.com/protocolbuffers/protobuf/examples
+	go mod tidy
+
+add_person_go: add_person.go protoc_middleman_go go_mod
 	go build -o add_person_go add_person.go
 
-add_person_gotest: add_person_test.go add_person_go
+add_person_gotest: add_person_test.go add_person_go go_mod
 	go test add_person.go add_person_test.go
 
-list_people_go: list_people.go protoc_middleman_go
+list_people_go: list_people.go protoc_middleman_go go_mod
 	go build -o list_people_go list_people.go
 
-list_people_gotest: list_people.go list_people_go
+list_people_gotest: list_people.go list_people_go go_mod
 	go test list_people.go list_people_test.go
 
 javac_middleman: AddPerson.java ListPeople.java protoc_middleman
diff --git a/examples/addressbook.proto b/examples/addressbook.proto
index b4b33b4..5bb3577 100644
--- a/examples/addressbook.proto
+++ b/examples/addressbook.proto
@@ -14,7 +14,8 @@
 // [END declaration]
 
 // [START java_declaration]
-option java_package = "com.example.tutorial";
+option java_multiple_files = true;
+option java_package = "com.example.tutorial.protos";
 option java_outer_classname = "AddressBookProtos";
 // [END java_declaration]
 
@@ -22,6 +23,10 @@
 option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
 // [END csharp_declaration]
 
+// [START go_declaration]
+option go_package = "../tutorial";
+// [END go_declaration]
+
 // [START messages]
 message Person {
   string name = 1;
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index e533d05..dc03fee 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -62,7 +62,7 @@
     PROTOC=$BOOTSTRAP_PROTOC
     BOOTSTRAP_PROTOC=""
   else
-    make $@ protoc
+    make -j$(nproc) $@ protoc
     if test $? -ne 0; then
       echo "Failed to build protoc."
       exit 1
diff --git a/global.json b/global.json
index 1c02f07..d29e29a 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,6 @@
 {
   "sdk": {
-    "version": "3.0.100"
+    "version": "5.0.102",
+    "rollForward": "latestMinor"
   }
 }
diff --git a/internal.bzl b/internal.bzl
new file mode 100644
index 0000000..a281418
--- /dev/null
+++ b/internal.bzl
@@ -0,0 +1,29 @@
+# PLEASE DO NOT DEPEND ON THE CONTENTS OF THIS FILE, IT IS UNSTABLE.
+
+def conformance_test(name, testee, failure_list = None, text_format_failure_list = None):
+    args = ["--testee %s" % _strip_bazel(testee)]
+    failure_lists = []
+    if failure_list:
+        args = args + ["--failure_list %s" % _strip_bazel(failure_list)]
+        failure_lists = failure_lists + [failure_list]
+    if text_format_failure_list:
+        args = args + ["--text_format_failure_list %s" % _strip_bazel(text_format_failure_list)]
+        failure_lists = failure_lists + [text_format_failure_list]
+
+    native.sh_test(
+        name = name,
+        srcs = ["//:conformance/conformance_test_runner.sh"],
+        data = [testee] + failure_lists + [
+            "//:conformance_test_runner", 
+        ],
+        args = args,
+        deps = [
+            "@bazel_tools//tools/bash/runfiles",
+        ],
+    )
+
+
+def _strip_bazel(testee):
+    if testee.startswith("//"):
+        testee = testee.replace("//", "com_google_protobuf")
+    return testee.replace(":", "/")
diff --git a/java/BUILD b/java/BUILD
index 779fa9e..e12d472 100644
--- a/java/BUILD
+++ b/java/BUILD
@@ -1,9 +1,16 @@
-config_setting(
-    name = "jdk9",
-    values = {
-        "java_toolchain": "@bazel_tools//tools/jdk:toolchain_jdk9",
-    },
-    visibility = [
-        "//java:__subpackages__",
+test_suite(
+    name = "tests",
+    tests = [
+        "//java/core:tests",
+        "//java/lite:tests",
+        "//java/util:tests",
     ],
 )
+
+filegroup(
+    name = "release",
+    srcs = [
+        "//java/core:release", # contains lite.
+        "//java/util:release",
+    ]
+)
\ No newline at end of file
diff --git a/java/README.md b/java/README.md
index c4e8e20..48c3aec 100644
--- a/java/README.md
+++ b/java/README.md
@@ -23,7 +23,7 @@
 <dependency>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-java</artifactId>
-  <version>3.11.0</version>
+  <version>3.15.3</version>
 </dependency>
 ```
 
@@ -37,7 +37,7 @@
 <dependency>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-java-util</artifactId>
-  <version>3.11.0</version>
+  <version>3.15.3</version>
 </dependency>
 ```
 
@@ -45,9 +45,9 @@
 
 If you are using Gradle, add the following to your `build.gradle` file's dependencies:
 ```
-    compile 'com.google.protobuf:protobuf-java:3.11.0'
+    implementation 'com.google.protobuf:protobuf-java:3.15.3'
 ```
-Again, be sure to check that the version number maches (or is newer than) the version number of protoc that you are using.
+Again, be sure to check that the version number matches (or is newer than) the version number of protoc that you are using.
 
 ### Use Java Protocol Buffers on Android
 
@@ -68,7 +68,7 @@
 
 Most users should follow the instructions above to use protobuf Java runtime.
 If you are contributing code to protobuf or want to use a protobuf version
-that hasn't been officially released yet, you can folllow the instructions
+that hasn't been officially released yet, you can follow the instructions
 below to build protobuf from source code.
 
 ### Build from Source - With Maven
@@ -178,3 +178,8 @@
 web at:
 
   https://developers.google.com/protocol-buffers/
+
+## Kotlin Protocol Buffers
+
+Code to support more idiomatic Kotlin protocol buffers has been added to the
+repository, and Kotlin support will be launched in the next numbered release.
diff --git a/java/bom/pom.xml b/java/bom/pom.xml
index f499bd1..5cf9774 100644
--- a/java/bom/pom.xml
+++ b/java/bom/pom.xml
@@ -4,7 +4,7 @@
 
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-bom</artifactId>
-  <version>3.11.4</version>
+  <version>3.17.3</version>
   <packaging>pom</packaging>
 
   <name>Protocol Buffers [BOM]</name>
diff --git a/java/compatibility_tests/README.md b/java/compatibility_tests/README.md
deleted file mode 100644
index 72c6034..0000000
--- a/java/compatibility_tests/README.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# Protobuf Java Compatibility Tests
-
-This directory contains tests to ensure protobuf library is compatible with
-previously released versions.
-
-## Directory Layout
-
-For each released protobuf version we are testing compatibility with, there
-is a sub-directory with the following layout (take v2.5.0 as an example):
-
-  * v2.5.0
-    * test.sh
-    * pom.xml
-    * protos/ - unittest protos.
-    * more_protos/ - unittest protos that import the ones in "protos".
-    * tests/ - actual Java test classes.
-
-The testing code is extracted from regular protobuf unittests by removing:
-
-  * tests that access package private methods/classes.
-  * tests that are known to be broken by an intended behavior change (e.g., we
-    changed the parsing recursion limit from 64 to 100).
-  * all lite runtime tests.
-
-It's also divided into 3 submodule with tests depending on more_protos and
-more_protos depending on protos. This way we can test scenarios where only part
-of the dependency is upgraded to the new version.
-
-## How to Run The Tests
-
-We use a shell script to drive the test of different scenarios so the test
-will only run on unix-like environments. The script expects a few command
-line tools to be available on PATH: git, mvn, wget, grep, sed, java.
-
-Before running the tests, make sure you have already built the protoc binary
-following [the C++ installation instructions](../../src/README.md). The test
-scripts will use the built binary located at ${protobuf}/src/protoc.
-
-To start a test, simply run the test.sh script in each version directory. For
-example:
-
-    $ v2.5.0/test.sh
-
-For each version, the test script will test:
-
-  * only upgrading protos to the new version
-  * only upgrading more_protos to the new version
-
-and see whether everything builds/runs fine. Both source compatibility and
-binary compatibility will be tested.
diff --git a/java/compatibility_tests/v2.5.0/deps/pom.xml b/java/compatibility_tests/v2.5.0/deps/pom.xml
deleted file mode 100644
index 7ceb960..0000000
--- a/java/compatibility_tests/v2.5.0/deps/pom.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>com.google.protobuf.compatibility</groupId>
-  <artifactId>compatibility-test-deps</artifactId>
-  <version>2.5.0</version>
-
-  <name>Compatibility Test Dependencies</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.4</version>
-    </dependency>
-    <dependency>
-      <groupId>org.easymock</groupId>
-      <artifactId>easymock</artifactId>
-      <version>2.2</version>
-    </dependency>
-    <dependency>
-      <groupId>org.easymock</groupId>
-      <artifactId>easymockclassextension</artifactId>
-      <version>2.2.1</version>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <version>2.6</version>
-        <configuration>
-          <descriptorRefs>
-            <descriptorRef>jar-with-dependencies</descriptorRef>
-          </descriptorRefs>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/java/compatibility_tests/v2.5.0/more_protos/pom.xml b/java/compatibility_tests/v2.5.0/more_protos/pom.xml
deleted file mode 100644
index ff0c413..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/pom.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>com.google.protobuf.compatibility</groupId>
-    <artifactId>compatibility-test-suite</artifactId>
-    <version>2.5.0</version>
-    <relativePath>..</relativePath>
-  </parent>
-
-  <groupId>com.google.protobuf.compatibility</groupId>
-  <artifactId>compatibility-more-protos</artifactId>
-  <version>2.5.0</version>
-
-  <name>More protos for Compatibility test</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.protobuf</groupId>
-      <artifactId>protobuf-java</artifactId>
-      <version>${more_protos.protobuf.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.protobuf.compatibility</groupId>
-      <artifactId>compatibility-protos</artifactId>
-      <version>2.5.0</version>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.3</version>
-        <configuration>
-          <source>1.6</source>
-          <target>1.6</target>
-        </configuration>
-      </plugin>
-      <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>generate-sources</id>
-            <phase>generate-sources</phase>
-            <configuration>
-              <tasks>
-                <mkdir dir="target/generated-sources" />
-                <exec executable="${more_protos.protoc.path}">
-                  <arg value="--java_out=target/generated-sources" />
-                  <arg value="--proto_path=src/proto" />
-                  <arg value="src/proto/google/protobuf/unittest.proto" />
-                  <arg value="src/proto/google/protobuf/unittest_optimize_for.proto" />
-                  <arg value="src/proto/com/google/protobuf/multiple_files_test.proto" />
-                </exec>
-              </tasks>
-              <sourceRoot>target/generated-sources</sourceRoot>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/multiple_files_test.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/multiple_files_test.proto
deleted file mode 100644
index 9a04014..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/multiple_files_test.proto
+++ /dev/null
@@ -1,71 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// A proto file which tests the java_multiple_files option.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option java_generic_services = true;   // auto-added
-
-import "google/protobuf/unittest.proto";
-
-package protobuf_unittest;
-
-option java_multiple_files = true;
-option java_outer_classname = "MultipleFilesTestProto";
-
-message MessageWithNoOuter {
-  message NestedMessage {
-    optional int32 i = 1;
-  }
-  enum NestedEnum {
-    BAZ = 3;
-  }
-  optional NestedMessage nested = 1;
-  repeated TestAllTypes foreign = 2;
-  optional NestedEnum nested_enum = 3;
-  optional EnumWithNoOuter foreign_enum = 4;
-}
-
-enum EnumWithNoOuter {
-  FOO = 1;
-  BAR = 2;
-}
-
-service ServiceWithNoOuter {
-  rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
-}
-
-extend TestAllExtensions {
-  optional int32 extension_with_outer = 1234567;
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_builders_test.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_builders_test.proto
deleted file mode 100644
index abffb9d..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_builders_test.proto
+++ /dev/null
@@ -1,53 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: jonp@google.com (Jon Perlow)
-//
-
-package protobuf_unittest;
-
-option java_multiple_files = true;
-option java_outer_classname = "NestedBuilders";
-
-
-message Vehicle {
-  optional Engine engine = 1;
-  repeated Wheel wheel = 2;
-}
-
-message Engine {
-  optional int32 cylinder = 1;
-  optional int32 liters = 2;
-}
-
-message Wheel {
-  optional int32 radius = 1;
-  optional int32 width = 2;
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension.proto
deleted file mode 100644
index 9fe5d56..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension.proto
+++ /dev/null
@@ -1,45 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with nested extensions. Note that this must be defined in
-// a separate file to properly test the initialization of the outer class.
-
-
-import "com/google/protobuf/non_nested_extension.proto";
-
-package protobuf_unittest;
-
-message MyNestedExtension {
-  extend MessageToBeExtended {
-    optional MessageToBeExtended recursiveExtension = 2;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension_lite.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension_lite.proto
deleted file mode 100644
index 16ee46e..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension_lite.proto
+++ /dev/null
@@ -1,48 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with nested extensions for a MessageLite messages. Note that
-// this must be defined in a separate file to properly test the initialization
-// of the outer class.
-
-
-package protobuf_unittest;
-
-option optimize_for = LITE_RUNTIME;
-
-import "com/google/protobuf/non_nested_extension_lite.proto";
-
-message MyNestedExtensionLite {
-  extend MessageLiteToBeExtended {
-    optional MessageLiteToBeExtended recursiveExtensionLite = 3;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension.proto
deleted file mode 100644
index f61b419..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension.proto
+++ /dev/null
@@ -1,48 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with extensions.
-
-
-package protobuf_unittest;
-
-message MessageToBeExtended {
-  extensions 1 to max;
-}
-
-message MyNonNestedExtension {
-}
-
-extend MessageToBeExtended {
-  optional MyNonNestedExtension nonNestedExtension = 1;
-}
-
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
deleted file mode 100644
index 3c82659..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with extensions for a MessageLite messages.
-
-
-package protobuf_unittest;
-
-option optimize_for = LITE_RUNTIME;
-
-message MessageLiteToBeExtended {
-  extensions 1 to max;
-}
-
-message MyNonNestedExtensionLite {
-}
-
-extend MessageLiteToBeExtended {
-  optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
-}
-
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/test_bad_identifiers.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
deleted file mode 100644
index 6e67d97..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
+++ /dev/null
@@ -1,108 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: jonp@google.com (Jon Perlow)
-
-// This file tests that various identifiers work as field and type names even
-// though the same identifiers are used internally by the java code generator.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option java_generic_services = true;   // auto-added
-
-package io_protocol_tests;
-
-option java_package = "com.google.protobuf";
-option java_outer_classname = "TestBadIdentifiersProto";
-
-message TestMessage {
-}
-
-message Descriptor {
-  option no_standard_descriptor_accessor = true;
-  optional string descriptor = 1;
-  message NestedDescriptor {
-    option no_standard_descriptor_accessor = true;
-    optional string descriptor = 1;
-  }
-  optional NestedDescriptor nested_descriptor = 2;
-}
-
-message Parser {
-  enum ParserEnum {
-    PARSER = 1;
-  }
-  optional ParserEnum parser = 1;
-}
-
-message Deprecated {
-  enum TestEnum {
-    FOO = 1;
-  }
-
-  optional int32 field1 = 1 [deprecated=true];
-  optional TestEnum field2 = 2 [deprecated=true];
-  optional TestMessage field3 = 3 [deprecated=true];
-}
-
-message Override {
-  optional int32 override = 1;
-}
-
-message Object {
-  optional int32 object = 1;
-  optional string string_object = 2;
-}
-
-message String {
-  optional string string = 1;
-}
-
-message Integer {
-  optional int32 integer = 1;
-}
-
-message Long {
-  optional int32 long = 1;
-}
-
-message Float {
-  optional float float = 1;
-}
-
-message Double {
-  optional double double = 1;
-}
-
-service TestConflictingMethodNames {
-  rpc Override(TestMessage) returns (TestMessage);
-}
-
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto
deleted file mode 100644
index 031433e..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto
+++ /dev/null
@@ -1,620 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// The messages in this file describe the definitions found in .proto files.
-// A valid .proto file can be translated directly to a FileDescriptorProto
-// without any other information (e.g. without reading its imports).
-
-
-
-package google.protobuf;
-option java_package = "com.google.protobuf";
-option java_outer_classname = "DescriptorProtos";
-
-// descriptor.proto must be optimized for speed because reflection-based
-// algorithms don't work during bootstrapping.
-option optimize_for = SPEED;
-
-// The protocol compiler can output a FileDescriptorSet containing the .proto
-// files it parses.
-message FileDescriptorSet {
-  repeated FileDescriptorProto file = 1;
-}
-
-// Describes a complete .proto file.
-message FileDescriptorProto {
-  optional string name = 1;       // file name, relative to root of source tree
-  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
-
-  // Names of files imported by this file.
-  repeated string dependency = 3;
-  // Indexes of the public imported files in the dependency list above.
-  repeated int32 public_dependency = 10;
-  // Indexes of the weak imported files in the dependency list.
-  // For Google-internal migration only. Do not use.
-  repeated int32 weak_dependency = 11;
-
-  // All top-level definitions in this file.
-  repeated DescriptorProto message_type = 4;
-  repeated EnumDescriptorProto enum_type = 5;
-  repeated ServiceDescriptorProto service = 6;
-  repeated FieldDescriptorProto extension = 7;
-
-  optional FileOptions options = 8;
-
-  // This field contains optional information about the original source code.
-  // You may safely remove this entire field whithout harming runtime
-  // functionality of the descriptors -- the information is needed only by
-  // development tools.
-  optional SourceCodeInfo source_code_info = 9;
-}
-
-// Describes a message type.
-message DescriptorProto {
-  optional string name = 1;
-
-  repeated FieldDescriptorProto field = 2;
-  repeated FieldDescriptorProto extension = 6;
-
-  repeated DescriptorProto nested_type = 3;
-  repeated EnumDescriptorProto enum_type = 4;
-
-  message ExtensionRange {
-    optional int32 start = 1;
-    optional int32 end = 2;
-  }
-  repeated ExtensionRange extension_range = 5;
-
-  optional MessageOptions options = 7;
-}
-
-// Describes a field within a message.
-message FieldDescriptorProto {
-  enum Type {
-    // 0 is reserved for errors.
-    // Order is weird for historical reasons.
-    TYPE_DOUBLE         = 1;
-    TYPE_FLOAT          = 2;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
-    // negative values are likely.
-    TYPE_INT64          = 3;
-    TYPE_UINT64         = 4;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
-    // negative values are likely.
-    TYPE_INT32          = 5;
-    TYPE_FIXED64        = 6;
-    TYPE_FIXED32        = 7;
-    TYPE_BOOL           = 8;
-    TYPE_STRING         = 9;
-    TYPE_GROUP          = 10;  // Tag-delimited aggregate.
-    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
-
-    // New in version 2.
-    TYPE_BYTES          = 12;
-    TYPE_UINT32         = 13;
-    TYPE_ENUM           = 14;
-    TYPE_SFIXED32       = 15;
-    TYPE_SFIXED64       = 16;
-    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
-    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
-  };
-
-  enum Label {
-    // 0 is reserved for errors
-    LABEL_OPTIONAL      = 1;
-    LABEL_REQUIRED      = 2;
-    LABEL_REPEATED      = 3;
-    // TODO(sanjay): Should we add LABEL_MAP?
-  };
-
-  optional string name = 1;
-  optional int32 number = 3;
-  optional Label label = 4;
-
-  // If type_name is set, this need not be set.  If both this and type_name
-  // are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
-  optional Type type = 5;
-
-  // For message and enum types, this is the name of the type.  If the name
-  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
-  // rules are used to find the type (i.e. first the nested types within this
-  // message are searched, then within the parent, on up to the root
-  // namespace).
-  optional string type_name = 6;
-
-  // For extensions, this is the name of the type being extended.  It is
-  // resolved in the same manner as type_name.
-  optional string extendee = 2;
-
-  // For numeric types, contains the original text representation of the value.
-  // For booleans, "true" or "false".
-  // For strings, contains the default text contents (not escaped in any way).
-  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
-  // TODO(kenton):  Base-64 encode?
-  optional string default_value = 7;
-
-  optional FieldOptions options = 8;
-}
-
-// Describes an enum type.
-message EnumDescriptorProto {
-  optional string name = 1;
-
-  repeated EnumValueDescriptorProto value = 2;
-
-  optional EnumOptions options = 3;
-}
-
-// Describes a value within an enum.
-message EnumValueDescriptorProto {
-  optional string name = 1;
-  optional int32 number = 2;
-
-  optional EnumValueOptions options = 3;
-}
-
-// Describes a service.
-message ServiceDescriptorProto {
-  optional string name = 1;
-  repeated MethodDescriptorProto method = 2;
-
-  optional ServiceOptions options = 3;
-}
-
-// Describes a method of a service.
-message MethodDescriptorProto {
-  optional string name = 1;
-
-  // Input and output type names.  These are resolved in the same way as
-  // FieldDescriptorProto.type_name, but must refer to a message type.
-  optional string input_type = 2;
-  optional string output_type = 3;
-
-  optional MethodOptions options = 4;
-}
-
-
-// ===================================================================
-// Options
-
-// Each of the definitions above may have "options" attached.  These are
-// just annotations which may cause code to be generated slightly differently
-// or may contain hints for code that manipulates protocol messages.
-//
-// Clients may define custom options as extensions of the *Options messages.
-// These extensions may not yet be known at parsing time, so the parser cannot
-// store the values in them.  Instead it stores them in a field in the *Options
-// message called uninterpreted_option. This field must have the same name
-// across all *Options messages. We then use this field to populate the
-// extensions when we build a descriptor, at which point all protos have been
-// parsed and so all extensions are known.
-//
-// Extension numbers for custom options may be chosen as follows:
-// * For options which will only be used within a single application or
-//   organization, or for experimental options, use field numbers 50000
-//   through 99999.  It is up to you to ensure that you do not use the
-//   same number for multiple options.
-// * For options which will be published and used publicly by multiple
-//   independent entities, e-mail protobuf-global-extension-registry@google.com
-//   to reserve extension numbers. Simply provide your project name (e.g.
-//   Object-C plugin) and your project website (if available) -- there's no need
-//   to explain how you intend to use them. Usually you only need one extension
-//   number. You can declare multiple options with only one extension number by
-//   putting them in a sub-message. See the Custom Options section of the docs
-//   for examples:
-//   http://code.google.com/apis/protocolbuffers/docs/proto.html#options
-//   If this turns out to be popular, a web service will be set up
-//   to automatically assign option numbers.
-
-
-message FileOptions {
-
-  // Sets the Java package where classes generated from this .proto will be
-  // placed.  By default, the proto package is used, but this is often
-  // inappropriate because proto packages do not normally start with backwards
-  // domain names.
-  optional string java_package = 1;
-
-
-  // If set, all the classes from the .proto file are wrapped in a single
-  // outer class with the given name.  This applies to both Proto1
-  // (equivalent to the old "--one_java_file" option) and Proto2 (where
-  // a .proto always translates to a single class, but you may want to
-  // explicitly choose the class name).
-  optional string java_outer_classname = 8;
-
-  // If set true, then the Java code generator will generate a separate .java
-  // file for each top-level message, enum, and service defined in the .proto
-  // file.  Thus, these types will *not* be nested inside the outer class
-  // named by java_outer_classname.  However, the outer class will still be
-  // generated to contain the file's getDescriptor() method as well as any
-  // top-level extensions defined in the file.
-  optional bool java_multiple_files = 10 [default=false];
-
-  // If set true, then the Java code generator will generate equals() and
-  // hashCode() methods for all messages defined in the .proto file. This is
-  // purely a speed optimization, as the AbstractMessage base class includes
-  // reflection-based implementations of these methods.
-  optional bool java_generate_equals_and_hash = 20 [default=false];
-
-  // Generated classes can be optimized for speed or code size.
-  enum OptimizeMode {
-    SPEED = 1;        // Generate complete code for parsing, serialization,
-                      // etc.
-    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
-    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
-  }
-  optional OptimizeMode optimize_for = 9 [default=SPEED];
-
-  // Sets the Go package where structs generated from this .proto will be
-  // placed.  There is no default.
-  optional string go_package = 11;
-
-
-
-  // Should generic services be generated in each language?  "Generic" services
-  // are not specific to any particular RPC system.  They are generated by the
-  // main code generators in each language (without additional plugins).
-  // Generic services were the only kind of service generation supported by
-  // early versions of proto2.
-  //
-  // Generic services are now considered deprecated in favor of using plugins
-  // that generate code specific to your particular RPC system.  Therefore,
-  // these default to false.  Old code which depends on generic services should
-  // explicitly set them to true.
-  optional bool cc_generic_services = 16 [default=false];
-  optional bool java_generic_services = 17 [default=false];
-  optional bool py_generic_services = 18 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MessageOptions {
-  // Set true to use the old proto1 MessageSet wire format for extensions.
-  // This is provided for backwards-compatibility with the MessageSet wire
-  // format.  You should not use this for any other reason:  It's less
-  // efficient, has fewer features, and is more complicated.
-  //
-  // The message must be defined exactly as follows:
-  //   message Foo {
-  //     option message_set_wire_format = true;
-  //     extensions 4 to max;
-  //   }
-  // Note that the message cannot have any defined fields; MessageSets only
-  // have extensions.
-  //
-  // All extensions of your type must be singular messages; e.g. they cannot
-  // be int32s, enums, or repeated messages.
-  //
-  // Because this is an option, the above two restrictions are not enforced by
-  // the protocol compiler.
-  optional bool message_set_wire_format = 1 [default=false];
-
-  // Disables the generation of the standard "descriptor()" accessor, which can
-  // conflict with a field of the same name.  This is meant to make migration
-  // from proto1 easier; new code should avoid fields named "descriptor".
-  optional bool no_standard_descriptor_accessor = 2 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message FieldOptions {
-  // The ctype option instructs the C++ code generator to use a different
-  // representation of the field than it normally would.  See the specific
-  // options below.  This option is not yet implemented in the open source
-  // release -- sorry, we'll try to include it in a future version!
-  optional CType ctype = 1 [default = STRING];
-  enum CType {
-    // Default mode.
-    STRING = 0;
-
-    CORD = 1;
-
-    STRING_PIECE = 2;
-  }
-  // The packed option can be enabled for repeated primitive fields to enable
-  // a more efficient representation on the wire. Rather than repeatedly
-  // writing the tag and type for each element, the entire array is encoded as
-  // a single length-delimited blob.
-  optional bool packed = 2;
-
-
-
-  // Should this field be parsed lazily?  Lazy applies only to message-type
-  // fields.  It means that when the outer message is initially parsed, the
-  // inner message's contents will not be parsed but instead stored in encoded
-  // form.  The inner message will actually be parsed when it is first accessed.
-  //
-  // This is only a hint.  Implementations are free to choose whether to use
-  // eager or lazy parsing regardless of the value of this option.  However,
-  // setting this option true suggests that the protocol author believes that
-  // using lazy parsing on this field is worth the additional bookkeeping
-  // overhead typically needed to implement it.
-  //
-  // This option does not affect the public interface of any generated code;
-  // all method signatures remain the same.  Furthermore, thread-safety of the
-  // interface is not affected by this option; const methods remain safe to
-  // call from multiple threads concurrently, while non-const methods continue
-  // to require exclusive access.
-  //
-  //
-  // Note that implementations may choose not to check required fields within
-  // a lazy sub-message.  That is, calling IsInitialized() on the outher message
-  // may return true even if the inner message has missing required fields.
-  // This is necessary because otherwise the inner message would have to be
-  // parsed in order to perform the check, defeating the purpose of lazy
-  // parsing.  An implementation which chooses not to check required fields
-  // must be consistent about it.  That is, for any particular sub-message, the
-  // implementation must either *always* check its required fields, or *never*
-  // check its required fields, regardless of whether or not the message has
-  // been parsed.
-  optional bool lazy = 5 [default=false];
-
-  // Is this field deprecated?
-  // Depending on the target platform, this can emit Deprecated annotations
-  // for accessors, or it will be completely ignored; in the very least, this
-  // is a formalization for deprecating fields.
-  optional bool deprecated = 3 [default=false];
-
-  // EXPERIMENTAL.  DO NOT USE.
-  // For "map" fields, the name of the field in the enclosed type that
-  // is the key for this map.  For example, suppose we have:
-  //   message Item {
-  //     required string name = 1;
-  //     required string value = 2;
-  //   }
-  //   message Config {
-  //     repeated Item items = 1 [experimental_map_key="name"];
-  //   }
-  // In this situation, the map key for Item will be set to "name".
-  // TODO: Fully-implement this, then remove the "experimental_" prefix.
-  optional string experimental_map_key = 9;
-
-  // For Google-internal migration only. Do not use.
-  optional bool weak = 10 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumOptions {
-
-  // Set this option to false to disallow mapping different tag names to a same
-  // value.
-  optional bool allow_alias = 2 [default=true];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumValueOptions {
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message ServiceOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MethodOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-
-// A message representing a option the parser does not recognize. This only
-// appears in options protos created by the compiler::Parser class.
-// DescriptorPool resolves these when building Descriptor objects. Therefore,
-// options protos in descriptor objects (e.g. returned by Descriptor::options(),
-// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
-// in them.
-message UninterpretedOption {
-  // The name of the uninterpreted option.  Each string represents a segment in
-  // a dot-separated name.  is_extension is true iff a segment represents an
-  // extension (denoted with parentheses in options specs in .proto files).
-  // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
-  // "foo.(bar.baz).qux".
-  message NamePart {
-    required string name_part = 1;
-    required bool is_extension = 2;
-  }
-  repeated NamePart name = 2;
-
-  // The value of the uninterpreted option, in whatever type the tokenizer
-  // identified it as during parsing. Exactly one of these should be set.
-  optional string identifier_value = 3;
-  optional uint64 positive_int_value = 4;
-  optional int64 negative_int_value = 5;
-  optional double double_value = 6;
-  optional bytes string_value = 7;
-  optional string aggregate_value = 8;
-}
-
-// ===================================================================
-// Optional source code info
-
-// Encapsulates information about the original source file from which a
-// FileDescriptorProto was generated.
-message SourceCodeInfo {
-  // A Location identifies a piece of source code in a .proto file which
-  // corresponds to a particular definition.  This information is intended
-  // to be useful to IDEs, code indexers, documentation generators, and similar
-  // tools.
-  //
-  // For example, say we have a file like:
-  //   message Foo {
-  //     optional string foo = 1;
-  //   }
-  // Let's look at just the field definition:
-  //   optional string foo = 1;
-  //   ^       ^^     ^^  ^  ^^^
-  //   a       bc     de  f  ghi
-  // We have the following locations:
-  //   span   path               represents
-  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
-  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
-  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
-  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
-  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
-  //
-  // Notes:
-  // - A location may refer to a repeated field itself (i.e. not to any
-  //   particular index within it).  This is used whenever a set of elements are
-  //   logically enclosed in a single code segment.  For example, an entire
-  //   extend block (possibly containing multiple extension definitions) will
-  //   have an outer location whose path refers to the "extensions" repeated
-  //   field without an index.
-  // - Multiple locations may have the same path.  This happens when a single
-  //   logical declaration is spread out across multiple places.  The most
-  //   obvious example is the "extend" block again -- there may be multiple
-  //   extend blocks in the same scope, each of which will have the same path.
-  // - A location's span is not always a subset of its parent's span.  For
-  //   example, the "extendee" of an extension declaration appears at the
-  //   beginning of the "extend" block and is shared by all extensions within
-  //   the block.
-  // - Just because a location's span is a subset of some other location's span
-  //   does not mean that it is a descendent.  For example, a "group" defines
-  //   both a type and a field in a single declaration.  Thus, the locations
-  //   corresponding to the type and field and their components will overlap.
-  // - Code which tries to interpret locations should probably be designed to
-  //   ignore those that it doesn't understand, as more types of locations could
-  //   be recorded in the future.
-  repeated Location location = 1;
-  message Location {
-    // Identifies which part of the FileDescriptorProto was defined at this
-    // location.
-    //
-    // Each element is a field number or an index.  They form a path from
-    // the root FileDescriptorProto to the place where the definition.  For
-    // example, this path:
-    //   [ 4, 3, 2, 7, 1 ]
-    // refers to:
-    //   file.message_type(3)  // 4, 3
-    //       .field(7)         // 2, 7
-    //       .name()           // 1
-    // This is because FileDescriptorProto.message_type has field number 4:
-    //   repeated DescriptorProto message_type = 4;
-    // and DescriptorProto.field has field number 2:
-    //   repeated FieldDescriptorProto field = 2;
-    // and FieldDescriptorProto.name has field number 1:
-    //   optional string name = 1;
-    //
-    // Thus, the above path gives the location of a field name.  If we removed
-    // the last element:
-    //   [ 4, 3, 2, 7 ]
-    // this path refers to the whole field declaration (from the beginning
-    // of the label to the terminating semicolon).
-    repeated int32 path = 1 [packed=true];
-
-    // Always has exactly three or four elements: start line, start column,
-    // end line (optional, otherwise assumed same as start line), end column.
-    // These are packed into a single field for efficiency.  Note that line
-    // and column numbers are zero-based -- typically you will want to add
-    // 1 to each before displaying to a user.
-    repeated int32 span = 2 [packed=true];
-
-    // If this SourceCodeInfo represents a complete declaration, these are any
-    // comments appearing before and after the declaration which appear to be
-    // attached to the declaration.
-    //
-    // A series of line comments appearing on consecutive lines, with no other
-    // tokens appearing on those lines, will be treated as a single comment.
-    //
-    // Only the comment content is provided; comment markers (e.g. //) are
-    // stripped out.  For block comments, leading whitespace and an asterisk
-    // will be stripped from the beginning of each line other than the first.
-    // Newlines are included in the output.
-    //
-    // Examples:
-    //
-    //   optional int32 foo = 1;  // Comment attached to foo.
-    //   // Comment attached to bar.
-    //   optional int32 bar = 2;
-    //
-    //   optional string baz = 3;
-    //   // Comment attached to baz.
-    //   // Another line attached to baz.
-    //
-    //   // Comment attached to qux.
-    //   //
-    //   // Another line attached to qux.
-    //   optional double qux = 4;
-    //
-    //   optional string corge = 5;
-    //   /* Block comment attached
-    //    * to corge.  Leading asterisks
-    //    * will be removed. */
-    //   /* Block comment attached to
-    //    * grault. */
-    //   optional int32 grault = 6;
-    optional string leading_comments = 3;
-    optional string trailing_comments = 4;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest.proto
deleted file mode 100644
index 6eb2d86..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest.proto
+++ /dev/null
@@ -1,719 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file we will use for unit testing.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;     // auto-added
-
-import "google/protobuf/unittest_import.proto";
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do "using namespace unittest = protobuf_unittest".
-package protobuf_unittest;
-
-// Protos optimized for SPEED use a strict superset of the generated code
-// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
-// tests for speed unless explicitly testing code size optimization.
-option optimize_for = SPEED;
-
-option java_outer_classname = "UnittestProto";
-
-// This proto includes every type of field in both singular and repeated
-// forms.
-message TestAllTypes {
-  message NestedMessage {
-    // The field name "b" fails to compile in proto1 because it conflicts with
-    // a local variable named "b" in one of the generated methods.  Doh.
-    // This file needs to compile in proto1 to test backwards-compatibility.
-    optional int32 bb = 1;
-  }
-
-  enum NestedEnum {
-    FOO = 1;
-    BAR = 2;
-    BAZ = 3;
-  }
-
-  // Singular
-  optional    int32 optional_int32    =  1;
-  optional    int64 optional_int64    =  2;
-  optional   uint32 optional_uint32   =  3;
-  optional   uint64 optional_uint64   =  4;
-  optional   sint32 optional_sint32   =  5;
-  optional   sint64 optional_sint64   =  6;
-  optional  fixed32 optional_fixed32  =  7;
-  optional  fixed64 optional_fixed64  =  8;
-  optional sfixed32 optional_sfixed32 =  9;
-  optional sfixed64 optional_sfixed64 = 10;
-  optional    float optional_float    = 11;
-  optional   double optional_double   = 12;
-  optional     bool optional_bool     = 13;
-  optional   string optional_string   = 14;
-  optional    bytes optional_bytes    = 15;
-
-  optional group OptionalGroup = 16 {
-    optional int32 a = 17;
-  }
-
-  optional NestedMessage                        optional_nested_message  = 18;
-  optional ForeignMessage                       optional_foreign_message = 19;
-  optional protobuf_unittest_import.ImportMessage optional_import_message  = 20;
-
-  optional NestedEnum                           optional_nested_enum     = 21;
-  optional ForeignEnum                          optional_foreign_enum    = 22;
-  optional protobuf_unittest_import.ImportEnum    optional_import_enum     = 23;
-
-  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
-  optional string optional_cord = 25 [ctype=CORD];
-
-  // Defined in unittest_import_public.proto
-  optional protobuf_unittest_import.PublicImportMessage
-      optional_public_import_message = 26;
-
-  optional NestedMessage optional_lazy_message = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32    = 31;
-  repeated    int64 repeated_int64    = 32;
-  repeated   uint32 repeated_uint32   = 33;
-  repeated   uint64 repeated_uint64   = 34;
-  repeated   sint32 repeated_sint32   = 35;
-  repeated   sint64 repeated_sint64   = 36;
-  repeated  fixed32 repeated_fixed32  = 37;
-  repeated  fixed64 repeated_fixed64  = 38;
-  repeated sfixed32 repeated_sfixed32 = 39;
-  repeated sfixed64 repeated_sfixed64 = 40;
-  repeated    float repeated_float    = 41;
-  repeated   double repeated_double   = 42;
-  repeated     bool repeated_bool     = 43;
-  repeated   string repeated_string   = 44;
-  repeated    bytes repeated_bytes    = 45;
-
-  repeated group RepeatedGroup = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated NestedMessage                        repeated_nested_message  = 48;
-  repeated ForeignMessage                       repeated_foreign_message = 49;
-  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
-
-  repeated NestedEnum                           repeated_nested_enum     = 51;
-  repeated ForeignEnum                          repeated_foreign_enum    = 52;
-  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
-
-  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord = 55 [ctype=CORD];
-
-  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32    = 61 [default =  41    ];
-  optional    int64 default_int64    = 62 [default =  42    ];
-  optional   uint32 default_uint32   = 63 [default =  43    ];
-  optional   uint64 default_uint64   = 64 [default =  44    ];
-  optional   sint32 default_sint32   = 65 [default = -45    ];
-  optional   sint64 default_sint64   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
-  optional    float default_float    = 71 [default =  51.5  ];
-  optional   double default_double   = 72 [default =  52e3  ];
-  optional     bool default_bool     = 73 [default = true   ];
-  optional   string default_string   = 74 [default = "hello"];
-  optional    bytes default_bytes    = 75 [default = "world"];
-
-  optional NestedEnum  default_nested_enum  = 81 [default = BAR        ];
-  optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
-  optional protobuf_unittest_import.ImportEnum
-      default_import_enum = 83 [default = IMPORT_BAR];
-
-  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
-  optional string default_cord = 85 [ctype=CORD,default="123"];
-}
-
-message TestDeprecatedFields {
-  optional int32 deprecated_int32 = 1 [deprecated=true];
-}
-
-// Define these after TestAllTypes to make sure the compiler can handle
-// that.
-message ForeignMessage {
-  optional int32 c = 1;
-}
-
-enum ForeignEnum {
-  FOREIGN_FOO = 4;
-  FOREIGN_BAR = 5;
-  FOREIGN_BAZ = 6;
-}
-
-message TestAllExtensions {
-  extensions 1 to max;
-}
-
-extend TestAllExtensions {
-  // Singular
-  optional    int32 optional_int32_extension    =  1;
-  optional    int64 optional_int64_extension    =  2;
-  optional   uint32 optional_uint32_extension   =  3;
-  optional   uint64 optional_uint64_extension   =  4;
-  optional   sint32 optional_sint32_extension   =  5;
-  optional   sint64 optional_sint64_extension   =  6;
-  optional  fixed32 optional_fixed32_extension  =  7;
-  optional  fixed64 optional_fixed64_extension  =  8;
-  optional sfixed32 optional_sfixed32_extension =  9;
-  optional sfixed64 optional_sfixed64_extension = 10;
-  optional    float optional_float_extension    = 11;
-  optional   double optional_double_extension   = 12;
-  optional     bool optional_bool_extension     = 13;
-  optional   string optional_string_extension   = 14;
-  optional    bytes optional_bytes_extension    = 15;
-
-  optional group OptionalGroup_extension = 16 {
-    optional int32 a = 17;
-  }
-
-  optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
-  optional ForeignMessage optional_foreign_message_extension = 19;
-  optional protobuf_unittest_import.ImportMessage
-    optional_import_message_extension = 20;
-
-  optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
-  optional ForeignEnum optional_foreign_enum_extension = 22;
-  optional protobuf_unittest_import.ImportEnum
-    optional_import_enum_extension = 23;
-
-  optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
-  optional string optional_cord_extension = 25 [ctype=CORD];
-
-  optional protobuf_unittest_import.PublicImportMessage
-    optional_public_import_message_extension = 26;
-
-  optional TestAllTypes.NestedMessage
-    optional_lazy_message_extension = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32_extension    = 31;
-  repeated    int64 repeated_int64_extension    = 32;
-  repeated   uint32 repeated_uint32_extension   = 33;
-  repeated   uint64 repeated_uint64_extension   = 34;
-  repeated   sint32 repeated_sint32_extension   = 35;
-  repeated   sint64 repeated_sint64_extension   = 36;
-  repeated  fixed32 repeated_fixed32_extension  = 37;
-  repeated  fixed64 repeated_fixed64_extension  = 38;
-  repeated sfixed32 repeated_sfixed32_extension = 39;
-  repeated sfixed64 repeated_sfixed64_extension = 40;
-  repeated    float repeated_float_extension    = 41;
-  repeated   double repeated_double_extension   = 42;
-  repeated     bool repeated_bool_extension     = 43;
-  repeated   string repeated_string_extension   = 44;
-  repeated    bytes repeated_bytes_extension    = 45;
-
-  repeated group RepeatedGroup_extension = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
-  repeated ForeignMessage repeated_foreign_message_extension = 49;
-  repeated protobuf_unittest_import.ImportMessage
-    repeated_import_message_extension = 50;
-
-  repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
-  repeated ForeignEnum repeated_foreign_enum_extension = 52;
-  repeated protobuf_unittest_import.ImportEnum
-    repeated_import_enum_extension = 53;
-
-  repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord_extension = 55 [ctype=CORD];
-
-  repeated TestAllTypes.NestedMessage
-    repeated_lazy_message_extension = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32_extension    = 61 [default =  41    ];
-  optional    int64 default_int64_extension    = 62 [default =  42    ];
-  optional   uint32 default_uint32_extension   = 63 [default =  43    ];
-  optional   uint64 default_uint64_extension   = 64 [default =  44    ];
-  optional   sint32 default_sint32_extension   = 65 [default = -45    ];
-  optional   sint64 default_sint64_extension   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32_extension  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64_extension  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32_extension = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64_extension = 70 [default = -50    ];
-  optional    float default_float_extension    = 71 [default =  51.5  ];
-  optional   double default_double_extension   = 72 [default =  52e3  ];
-  optional     bool default_bool_extension     = 73 [default = true   ];
-  optional   string default_string_extension   = 74 [default = "hello"];
-  optional    bytes default_bytes_extension    = 75 [default = "world"];
-
-  optional TestAllTypes.NestedEnum
-    default_nested_enum_extension = 81 [default = BAR];
-  optional ForeignEnum
-    default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
-  optional protobuf_unittest_import.ImportEnum
-    default_import_enum_extension = 83 [default = IMPORT_BAR];
-
-  optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
-                                                       default="abc"];
-  optional string default_cord_extension = 85 [ctype=CORD, default="123"];
-}
-
-message TestNestedExtension {
-  extend TestAllExtensions {
-    // Check for bug where string extensions declared in tested scope did not
-    // compile.
-    optional string test = 1002 [default="test"];
-  }
-}
-
-// We have separate messages for testing required fields because it's
-// annoying to have to fill in required fields in TestProto in order to
-// do anything with it.  Note that we don't need to test every type of
-// required filed because the code output is basically identical to
-// optional fields for all types.
-message TestRequired {
-  required int32 a = 1;
-  optional int32 dummy2 = 2;
-  required int32 b = 3;
-
-  extend TestAllExtensions {
-    optional TestRequired single = 1000;
-    repeated TestRequired multi  = 1001;
-  }
-
-  // Pad the field count to 32 so that we can test that IsInitialized()
-  // properly checks multiple elements of has_bits_.
-  optional int32 dummy4  =  4;
-  optional int32 dummy5  =  5;
-  optional int32 dummy6  =  6;
-  optional int32 dummy7  =  7;
-  optional int32 dummy8  =  8;
-  optional int32 dummy9  =  9;
-  optional int32 dummy10 = 10;
-  optional int32 dummy11 = 11;
-  optional int32 dummy12 = 12;
-  optional int32 dummy13 = 13;
-  optional int32 dummy14 = 14;
-  optional int32 dummy15 = 15;
-  optional int32 dummy16 = 16;
-  optional int32 dummy17 = 17;
-  optional int32 dummy18 = 18;
-  optional int32 dummy19 = 19;
-  optional int32 dummy20 = 20;
-  optional int32 dummy21 = 21;
-  optional int32 dummy22 = 22;
-  optional int32 dummy23 = 23;
-  optional int32 dummy24 = 24;
-  optional int32 dummy25 = 25;
-  optional int32 dummy26 = 26;
-  optional int32 dummy27 = 27;
-  optional int32 dummy28 = 28;
-  optional int32 dummy29 = 29;
-  optional int32 dummy30 = 30;
-  optional int32 dummy31 = 31;
-  optional int32 dummy32 = 32;
-
-  required int32 c = 33;
-}
-
-message TestRequiredForeign {
-  optional TestRequired optional_message = 1;
-  repeated TestRequired repeated_message = 2;
-  optional int32 dummy = 3;
-}
-
-// Test that we can use NestedMessage from outside TestAllTypes.
-message TestForeignNested {
-  optional TestAllTypes.NestedMessage foreign_nested = 1;
-}
-
-// TestEmptyMessage is used to test unknown field support.
-message TestEmptyMessage {
-}
-
-// Like above, but declare all field numbers as potential extensions.  No
-// actual extensions should ever be defined for this type.
-message TestEmptyMessageWithExtensions {
-  extensions 1 to max;
-}
-
-message TestMultipleExtensionRanges {
-  extensions 42;
-  extensions 4143 to 4243;
-  extensions 65536 to max;
-}
-
-// Test that really large tag numbers don't break anything.
-message TestReallyLargeTagNumber {
-  // The largest possible tag number is 2^28 - 1, since the wire format uses
-  // three bits to communicate wire type.
-  optional int32 a = 1;
-  optional int32 bb = 268435455;
-}
-
-message TestRecursiveMessage {
-  optional TestRecursiveMessage a = 1;
-  optional int32 i = 2;
-}
-
-// Test that mutual recursion works.
-message TestMutualRecursionA {
-  optional TestMutualRecursionB bb = 1;
-}
-
-message TestMutualRecursionB {
-  optional TestMutualRecursionA a = 1;
-  optional int32 optional_int32 = 2;
-}
-
-// Test that groups have disjoint field numbers from their siblings and
-// parents.  This is NOT possible in proto1; only proto2.  When attempting
-// to compile with proto1, this will emit an error; so we only include it
-// in protobuf_unittest_proto.
-message TestDupFieldNumber {                        // NO_PROTO1
-  optional int32 a = 1;                             // NO_PROTO1
-  optional group Foo = 2 { optional int32 a = 1; }  // NO_PROTO1
-  optional group Bar = 3 { optional int32 a = 1; }  // NO_PROTO1
-}                                                   // NO_PROTO1
-
-// Additional messages for testing lazy fields.
-message TestEagerMessage {
-  optional TestAllTypes sub_message = 1 [lazy=false];
-}
-message TestLazyMessage {
-  optional TestAllTypes sub_message = 1 [lazy=true];
-}
-
-// Needed for a Python test.
-message TestNestedMessageHasBits {
-  message NestedMessage {
-    repeated int32 nestedmessage_repeated_int32 = 1;
-    repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
-  }
-  optional NestedMessage optional_nested_message = 1;
-}
-
-
-// Test an enum that has multiple values with the same number.
-enum TestEnumWithDupValue {
-  option allow_alias = true;
-  FOO1 = 1;
-  BAR1 = 2;
-  BAZ = 3;
-  FOO2 = 1;
-  BAR2 = 2;
-}
-
-// Test an enum with large, unordered values.
-enum TestSparseEnum {
-  SPARSE_A = 123;
-  SPARSE_B = 62374;
-  SPARSE_C = 12589234;
-  SPARSE_D = -15;
-  SPARSE_E = -53452;
-  SPARSE_F = 0;
-  SPARSE_G = 2;
-}
-
-// Test message with CamelCase field names.  This violates Protocol Buffer
-// standard style.
-message TestCamelCaseFieldNames {
-  optional int32 PrimitiveField = 1;
-  optional string StringField = 2;
-  optional ForeignEnum EnumField = 3;
-  optional ForeignMessage MessageField = 4;
-  optional string StringPieceField = 5 [ctype=STRING_PIECE];
-  optional string CordField = 6 [ctype=CORD];
-
-  repeated int32 RepeatedPrimitiveField = 7;
-  repeated string RepeatedStringField = 8;
-  repeated ForeignEnum RepeatedEnumField = 9;
-  repeated ForeignMessage RepeatedMessageField = 10;
-  repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
-  repeated string RepeatedCordField = 12 [ctype=CORD];
-}
-
-
-// We list fields out of order, to ensure that we're using field number and not
-// field index to determine serialization order.
-message TestFieldOrderings {
-  optional string my_string = 11;
-  extensions 2 to 10;
-  optional int64 my_int = 1;
-  extensions 12 to 100;
-  optional float my_float = 101;
-}
-
-
-extend TestFieldOrderings {
-  optional string my_extension_string = 50;
-  optional int32 my_extension_int = 5;
-}
-
-
-message TestExtremeDefaultValues {
-  optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
-  optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
-  optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
-  optional  int32 small_int32  = 4 [default = -0x7FFFFFFF];
-  optional  int64 small_int64  = 5 [default = -0x7FFFFFFFFFFFFFFF];
-  optional  int32 really_small_int32 = 21 [default = -0x80000000];
-  optional  int64 really_small_int64 = 22 [default = -0x8000000000000000];
-
-  // The default value here is UTF-8 for "\u1234".  (We could also just type
-  // the UTF-8 text directly into this text file rather than escape it, but
-  // lots of people use editors that would be confused by this.)
-  optional string utf8_string = 6 [default = "\341\210\264"];
-
-  // Tests for single-precision floating-point values.
-  optional float zero_float = 7 [default = 0];
-  optional float one_float = 8 [default = 1];
-  optional float small_float = 9 [default = 1.5];
-  optional float negative_one_float = 10 [default = -1];
-  optional float negative_float = 11 [default = -1.5];
-  // Using exponents
-  optional float large_float = 12 [default = 2E8];
-  optional float small_negative_float = 13 [default = -8e-28];
-
-  // Text for nonfinite floating-point values.
-  optional double inf_double = 14 [default = inf];
-  optional double neg_inf_double = 15 [default = -inf];
-  optional double nan_double = 16 [default = nan];
-  optional float inf_float = 17 [default = inf];
-  optional float neg_inf_float = 18 [default = -inf];
-  optional float nan_float = 19 [default = nan];
-
-  // Tests for C++ trigraphs.
-  // Trigraphs should be escaped in C++ generated files, but they should not be
-  // escaped for other languages.
-  // Note that in .proto file, "\?" is a valid way to escape ? in string
-  // literals.
-  optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
-
-  // String defaults containing the character '\000'
-  optional string string_with_zero       = 23 [default = "hel\000lo"];
-  optional  bytes bytes_with_zero        = 24 [default = "wor\000ld"];
-  optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
-                                               default="ab\000c"];
-  optional string cord_with_zero         = 26 [ctype=CORD,
-                                               default="12\0003"];
-}
-
-message SparseEnumMessage {
-  optional TestSparseEnum sparse_enum = 1;
-}
-
-// Test String and Bytes: string is for valid UTF-8 strings
-message OneString {
-  optional string data = 1;
-}
-
-message MoreString {
-  repeated string data = 1;
-}
-
-message OneBytes {
-  optional bytes data = 1;
-}
-
-message MoreBytes {
-  repeated bytes data = 1;
-}
-
-
-// Test messages for packed fields
-
-message TestPackedTypes {
-  repeated    int32 packed_int32    =  90 [packed = true];
-  repeated    int64 packed_int64    =  91 [packed = true];
-  repeated   uint32 packed_uint32   =  92 [packed = true];
-  repeated   uint64 packed_uint64   =  93 [packed = true];
-  repeated   sint32 packed_sint32   =  94 [packed = true];
-  repeated   sint64 packed_sint64   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
-  repeated    float packed_float    = 100 [packed = true];
-  repeated   double packed_double   = 101 [packed = true];
-  repeated     bool packed_bool     = 102 [packed = true];
-  repeated ForeignEnum packed_enum  = 103 [packed = true];
-}
-
-// A message with the same fields as TestPackedTypes, but without packing. Used
-// to test packed <-> unpacked wire compatibility.
-message TestUnpackedTypes {
-  repeated    int32 unpacked_int32    =  90 [packed = false];
-  repeated    int64 unpacked_int64    =  91 [packed = false];
-  repeated   uint32 unpacked_uint32   =  92 [packed = false];
-  repeated   uint64 unpacked_uint64   =  93 [packed = false];
-  repeated   sint32 unpacked_sint32   =  94 [packed = false];
-  repeated   sint64 unpacked_sint64   =  95 [packed = false];
-  repeated  fixed32 unpacked_fixed32  =  96 [packed = false];
-  repeated  fixed64 unpacked_fixed64  =  97 [packed = false];
-  repeated sfixed32 unpacked_sfixed32 =  98 [packed = false];
-  repeated sfixed64 unpacked_sfixed64 =  99 [packed = false];
-  repeated    float unpacked_float    = 100 [packed = false];
-  repeated   double unpacked_double   = 101 [packed = false];
-  repeated     bool unpacked_bool     = 102 [packed = false];
-  repeated ForeignEnum unpacked_enum  = 103 [packed = false];
-}
-
-message TestPackedExtensions {
-  extensions 1 to max;
-}
-
-extend TestPackedExtensions {
-  repeated    int32 packed_int32_extension    =  90 [packed = true];
-  repeated    int64 packed_int64_extension    =  91 [packed = true];
-  repeated   uint32 packed_uint32_extension   =  92 [packed = true];
-  repeated   uint64 packed_uint64_extension   =  93 [packed = true];
-  repeated   sint32 packed_sint32_extension   =  94 [packed = true];
-  repeated   sint64 packed_sint64_extension   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32_extension  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64_extension  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32_extension =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64_extension =  99 [packed = true];
-  repeated    float packed_float_extension    = 100 [packed = true];
-  repeated   double packed_double_extension   = 101 [packed = true];
-  repeated     bool packed_bool_extension     = 102 [packed = true];
-  repeated ForeignEnum packed_enum_extension  = 103 [packed = true];
-}
-
-// Used by ExtensionSetTest/DynamicExtensions.  The test actually builds
-// a set of extensions to TestAllExtensions dynamically, based on the fields
-// of this message type.
-message TestDynamicExtensions {
-  enum DynamicEnumType {
-    DYNAMIC_FOO = 2200;
-    DYNAMIC_BAR = 2201;
-    DYNAMIC_BAZ = 2202;
-  }
-  message DynamicMessageType {
-    optional int32 dynamic_field = 2100;
-  }
-
-  optional fixed32 scalar_extension = 2000;
-  optional ForeignEnum enum_extension = 2001;
-  optional DynamicEnumType dynamic_enum_extension = 2002;
-
-  optional ForeignMessage message_extension = 2003;
-  optional DynamicMessageType dynamic_message_extension = 2004;
-
-  repeated string repeated_extension = 2005;
-  repeated sint32 packed_extension = 2006 [packed = true];
-}
-
-message TestRepeatedScalarDifferentTagSizes {
-  // Parsing repeated fixed size values used to fail. This message needs to be
-  // used in order to get a tag of the right size; all of the repeated fields
-  // in TestAllTypes didn't trigger the check.
-  repeated fixed32 repeated_fixed32 = 12;
-  // Check for a varint type, just for good measure.
-  repeated int32   repeated_int32   = 13;
-
-  // These have two-byte tags.
-  repeated fixed64 repeated_fixed64 = 2046;
-  repeated int64   repeated_int64   = 2047;
-
-  // Three byte tags.
-  repeated float   repeated_float   = 262142;
-  repeated uint64  repeated_uint64  = 262143;
-}
-
-// Test that if an optional or required message/group field appears multiple
-// times in the input, they need to be merged.
-message TestParsingMerge {
-  // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
-  // except that all fields are repeated. In the tests, we will serialize the
-  // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
-  // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
-  // the corresponding required/optional fields in TestParsingMerge.
-  message RepeatedFieldsGenerator {
-    repeated TestAllTypes field1 = 1;
-    repeated TestAllTypes field2 = 2;
-    repeated TestAllTypes field3 = 3;
-    repeated group Group1 = 10 {
-      optional TestAllTypes field1 = 11;
-    }
-    repeated group Group2 = 20 {
-      optional TestAllTypes field1 = 21;
-    }
-    repeated TestAllTypes ext1 = 1000;
-    repeated TestAllTypes ext2 = 1001;
-  }
-  required TestAllTypes required_all_types = 1;
-  optional TestAllTypes optional_all_types = 2;
-  repeated TestAllTypes repeated_all_types = 3;
-  optional group OptionalGroup = 10 {
-    optional TestAllTypes optional_group_all_types = 11;
-  }
-  repeated group RepeatedGroup = 20 {
-    optional TestAllTypes repeated_group_all_types = 21;
-  }
-  extensions 1000 to max;
-  extend TestParsingMerge {
-    optional TestAllTypes optional_ext = 1000;
-    repeated TestAllTypes repeated_ext = 1001;
-  }
-}
-
-message TestCommentInjectionMessage {
-  // */ <- This should not close the generated doc comment
-  optional string a = 1 [default="*/ <- Neither should this."];
-}
-
-
-// Test that RPC services work.
-message FooRequest  {}
-message FooResponse {}
-
-message FooClientMessage {}
-message FooServerMessage{}
-
-service TestService {
-  rpc Foo(FooRequest) returns (FooResponse);
-  rpc Bar(BarRequest) returns (BarResponse);
-}
-
-
-message BarRequest  {}
-message BarResponse {}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto
deleted file mode 100644
index 2f4e3fd..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto
+++ /dev/null
@@ -1,387 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: benjy@google.com (Benjy Weinberger)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file used to test the "custom options" feature of proto2.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;
-
-// A custom file option (defined below).
-option (file_opt1) = 9876543210;
-
-import "google/protobuf/descriptor.proto";
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-package protobuf_unittest;
-
-
-// Some simple test custom options of various types.
-
-extend google.protobuf.FileOptions {
-  optional uint64 file_opt1 = 7736974;
-}
-
-extend google.protobuf.MessageOptions {
-  optional int32 message_opt1 = 7739036;
-}
-
-extend google.protobuf.FieldOptions {
-  optional fixed64 field_opt1 = 7740936;
-  // This is useful for testing that we correctly register default values for
-  // extension options.
-  optional int32 field_opt2 = 7753913 [default=42];
-}
-
-extend google.protobuf.EnumOptions {
-  optional sfixed32 enum_opt1 = 7753576;
-}
-
-extend google.protobuf.EnumValueOptions {
-  optional int32 enum_value_opt1 = 1560678;
-}
-
-extend google.protobuf.ServiceOptions {
-  optional sint64 service_opt1 = 7887650;
-}
-
-enum MethodOpt1 {
-  METHODOPT1_VAL1 = 1;
-  METHODOPT1_VAL2 = 2;
-}
-
-extend google.protobuf.MethodOptions {
-  optional MethodOpt1 method_opt1 = 7890860;
-}
-
-// A test message with custom options at all possible locations (and also some
-// regular options, to make sure they interact nicely).
-message TestMessageWithCustomOptions {
-  option message_set_wire_format = false;
-
-  option (message_opt1) = -56;
-
-  optional string field1 = 1 [ctype=CORD,
-                              (field_opt1)=8765432109];
-
-  enum AnEnum {
-    option (enum_opt1) = -789;
-
-    ANENUM_VAL1 = 1;
-    ANENUM_VAL2 = 2 [(enum_value_opt1) = 123];
-  }
-}
-
-
-// A test RPC service with custom options at all possible locations (and also
-// some regular options, to make sure they interact nicely).
-message CustomOptionFooRequest {
-}
-
-message CustomOptionFooResponse {
-}
-
-message CustomOptionFooClientMessage {
-}
-
-message CustomOptionFooServerMessage {
-}
-
-service TestServiceWithCustomOptions {
-  option (service_opt1) = -9876543210;
-
-  rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) {
-    option (method_opt1) = METHODOPT1_VAL2;
-  }
-}
-
-
-
-// Options of every possible field type, so we can test them all exhaustively.
-
-message DummyMessageContainingEnum {
-  enum TestEnumType {
-    TEST_OPTION_ENUM_TYPE1 = 22;
-    TEST_OPTION_ENUM_TYPE2 = -23;
-  }
-}
-
-message DummyMessageInvalidAsOptionType {
-}
-
-extend google.protobuf.MessageOptions {
-  optional         bool     bool_opt = 7706090;
-  optional        int32    int32_opt = 7705709;
-  optional        int64    int64_opt = 7705542;
-  optional       uint32   uint32_opt = 7704880;
-  optional       uint64   uint64_opt = 7702367;
-  optional       sint32   sint32_opt = 7701568;
-  optional       sint64   sint64_opt = 7700863;
-  optional      fixed32  fixed32_opt = 7700307;
-  optional      fixed64  fixed64_opt = 7700194;
-  optional     sfixed32 sfixed32_opt = 7698645;
-  optional     sfixed64 sfixed64_opt = 7685475;
-  optional        float    float_opt = 7675390;
-  optional       double   double_opt = 7673293;
-  optional       string   string_opt = 7673285;
-  optional        bytes    bytes_opt = 7673238;
-  optional DummyMessageContainingEnum.TestEnumType enum_opt = 7673233;
-  optional DummyMessageInvalidAsOptionType message_type_opt = 7665967;
-}
-
-message CustomOptionMinIntegerValues {
-  option     (bool_opt) = false;
-  option    (int32_opt) = -0x80000000;
-  option    (int64_opt) = -0x8000000000000000;
-  option   (uint32_opt) = 0;
-  option   (uint64_opt) = 0;
-  option   (sint32_opt) = -0x80000000;
-  option   (sint64_opt) = -0x8000000000000000;
-  option  (fixed32_opt) = 0;
-  option  (fixed64_opt) = 0;
-  option (sfixed32_opt) = -0x80000000;
-  option (sfixed64_opt) = -0x8000000000000000;
-}
-
-message CustomOptionMaxIntegerValues {
-  option     (bool_opt) = true;
-  option    (int32_opt) = 0x7FFFFFFF;
-  option    (int64_opt) = 0x7FFFFFFFFFFFFFFF;
-  option   (uint32_opt) = 0xFFFFFFFF;
-  option   (uint64_opt) = 0xFFFFFFFFFFFFFFFF;
-  option   (sint32_opt) = 0x7FFFFFFF;
-  option   (sint64_opt) = 0x7FFFFFFFFFFFFFFF;
-  option  (fixed32_opt) = 0xFFFFFFFF;
-  option  (fixed64_opt) = 0xFFFFFFFFFFFFFFFF;
-  option (sfixed32_opt) = 0x7FFFFFFF;
-  option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF;
-}
-
-message CustomOptionOtherValues {
-  option  (int32_opt) = -100;  // To test sign-extension.
-  option  (float_opt) = 12.3456789;
-  option (double_opt) = 1.234567890123456789;
-  option (string_opt) = "Hello, \"World\"";
-  option  (bytes_opt) = "Hello\0World";
-  option   (enum_opt) = TEST_OPTION_ENUM_TYPE2;
-}
-
-message SettingRealsFromPositiveInts {
-  option  (float_opt) = 12;
-  option (double_opt) = 154;
-}
-
-message SettingRealsFromNegativeInts {
-  option  (float_opt) = -12;
-  option  (double_opt) = -154;
-}
-
-// Options of complex message types, themselves combined and extended in
-// various ways.
-
-message ComplexOptionType1 {
-  optional int32 foo = 1;
-  optional int32 foo2 = 2;
-  optional int32 foo3 = 3;
-
-  extensions 100 to max;
-}
-
-message ComplexOptionType2 {
-  optional ComplexOptionType1 bar = 1;
-  optional int32 baz = 2;
-
-  message ComplexOptionType4 {
-    optional int32 waldo = 1;
-
-    extend google.protobuf.MessageOptions {
-      optional ComplexOptionType4 complex_opt4 = 7633546;
-    }
-  }
-
-  optional ComplexOptionType4 fred = 3;
-
-  extensions 100 to max;
-}
-
-message ComplexOptionType3 {
-  optional int32 qux = 1;
-
-  optional group ComplexOptionType5 = 2 {
-    optional int32 plugh = 3;
-  }
-}
-
-extend ComplexOptionType1 {
-  optional int32 quux = 7663707;
-  optional ComplexOptionType3 corge = 7663442;
-}
-
-extend ComplexOptionType2 {
-  optional int32 grault = 7650927;
-  optional ComplexOptionType1 garply = 7649992;
-}
-
-extend google.protobuf.MessageOptions {
-  optional protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756;
-  optional ComplexOptionType2 complex_opt2 = 7636949;
-  optional ComplexOptionType3 complex_opt3 = 7636463;
-  optional group ComplexOpt6 = 7595468 {
-    optional int32 xyzzy = 7593951;
-  }
-}
-
-// Note that we try various different ways of naming the same extension.
-message VariousComplexOptions {
-  option (.protobuf_unittest.complex_opt1).foo = 42;
-  option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324;
-  option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876;
-  option (complex_opt2).baz = 987;
-  option (complex_opt2).(grault) = 654;
-  option (complex_opt2).bar.foo = 743;
-  option (complex_opt2).bar.(quux) = 1999;
-  option (complex_opt2).bar.(protobuf_unittest.corge).qux = 2008;
-  option (complex_opt2).(garply).foo = 741;
-  option (complex_opt2).(garply).(.protobuf_unittest.quux) = 1998;
-  option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121;
-  option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971;
-  option (complex_opt2).fred.waldo = 321;
-  option (protobuf_unittest.complex_opt3).qux = 9;
-  option (complex_opt3).complexoptiontype5.plugh = 22;
-  option (complexopt6).xyzzy = 24;
-}
-
-// ------------------------------------------------------
-// Definitions for testing aggregate option parsing.
-// See descriptor_unittest.cc.
-
-message AggregateMessageSet {
-  option message_set_wire_format = true;
-  extensions 4 to max;
-}
-
-message AggregateMessageSetElement {
-  extend AggregateMessageSet {
-    optional AggregateMessageSetElement message_set_extension = 15447542;
-  }
-  optional string s = 1;
-}
-
-// A helper type used to test aggregate option parsing
-message Aggregate {
-  optional int32 i = 1;
-  optional string s = 2;
-
-  // A nested object
-  optional Aggregate sub = 3;
-
-  // To test the parsing of extensions inside aggregate values
-  optional google.protobuf.FileOptions file = 4;
-  extend google.protobuf.FileOptions {
-    optional Aggregate nested = 15476903;
-  }
-
-  // An embedded message set
-  optional AggregateMessageSet mset = 5;
-}
-
-// Allow Aggregate to be used as an option at all possible locations
-// in the .proto grammar.
-extend google.protobuf.FileOptions      { optional Aggregate fileopt    = 15478479; }
-extend google.protobuf.MessageOptions   { optional Aggregate msgopt     = 15480088; }
-extend google.protobuf.FieldOptions     { optional Aggregate fieldopt   = 15481374; }
-extend google.protobuf.EnumOptions      { optional Aggregate enumopt    = 15483218; }
-extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
-extend google.protobuf.ServiceOptions   { optional Aggregate serviceopt = 15497145; }
-extend google.protobuf.MethodOptions    { optional Aggregate methodopt  = 15512713; }
-
-// Try using AggregateOption at different points in the proto grammar
-option (fileopt) = {
-  s: 'FileAnnotation'
-  // Also test the handling of comments
-  /* of both types */ i: 100
-
-  sub { s: 'NestedFileAnnotation' }
-
-  // Include a google.protobuf.FileOptions and recursively extend it with
-  // another fileopt.
-  file {
-    [protobuf_unittest.fileopt] {
-      s:'FileExtensionAnnotation'
-    }
-  }
-
-  // A message set inside an option value
-  mset {
-    [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
-      s: 'EmbeddedMessageSetElement'
-    }
-  }
-};
-
-message AggregateMessage {
-  option (msgopt) = { i:101 s:'MessageAnnotation' };
-  optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
-}
-
-service AggregateService {
-  option (serviceopt) = { s:'ServiceAnnotation' };
-  rpc Method (AggregateMessage) returns (AggregateMessage) {
-    option (methodopt) = { s:'MethodAnnotation' };
-  }
-}
-
-enum AggregateEnum {
-  option (enumopt) = { s:'EnumAnnotation' };
-  VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
-}
-
-// Test custom options for nested type.
-message NestedOptionType {
-  message NestedMessage {
-    option (message_opt1) = 1001;
-    optional int32 nested_field = 1 [(field_opt1) = 1002];
-  }
-  enum NestedEnum {
-    option (enum_opt1) = 1003;
-    NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
-  }
-  extend google.protobuf.FileOptions {
-    optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
deleted file mode 100644
index fa17625..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
-
-import "google/protobuf/unittest_optimize_for.proto";
-
-package protobuf_unittest;
-
-// We optimize for speed here, but we are importing a proto that is optimized
-// for code size.
-option optimize_for = SPEED;
-
-message TestEmbedOptimizedForSize {
-  // Test that embedding a message which has optimize_for = CODE_SIZE into
-  // one optimized for speed works.
-  optional TestOptimizedForSize optional_message = 1;
-  repeated TestOptimizedForSize repeated_message = 2;
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_empty.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_empty.proto
deleted file mode 100644
index ab12d1f..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_empty.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// This file intentionally left blank.  (At one point this wouldn't compile
-// correctly.)
-
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
deleted file mode 100644
index bc0b7c1..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
+++ /dev/null
@@ -1,1046 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file that has an extremely large descriptor.  Used to test that
-// descriptors over 64k don't break the string literal length limit in Java.
-
-
-package google.protobuf;
-option java_package = "com.google.protobuf";
-
-// Avoid generating insanely long methods.
-option optimize_for = CODE_SIZE;
-
-message TestEnormousDescriptor {
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1 = 1 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_2 = 2 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_3 = 3 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_4 = 4 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_5 = 5 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_6 = 6 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_7 = 7 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_8 = 8 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_9 = 9 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_10 = 10 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_11 = 11 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_12 = 12 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_13 = 13 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_14 = 14 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_15 = 15 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_16 = 16 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_17 = 17 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_18 = 18 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_19 = 19 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_20 = 20 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_21 = 21 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_22 = 22 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_23 = 23 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_24 = 24 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_25 = 25 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_26 = 26 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_27 = 27 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_28 = 28 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_29 = 29 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_30 = 30 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_31 = 31 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_32 = 32 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_33 = 33 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_34 = 34 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_35 = 35 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_36 = 36 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_37 = 37 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_38 = 38 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_39 = 39 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_40 = 40 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_41 = 41 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_42 = 42 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_43 = 43 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_44 = 44 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_45 = 45 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_46 = 46 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_47 = 47 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_48 = 48 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_49 = 49 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_50 = 50 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_51 = 51 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_52 = 52 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_53 = 53 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_54 = 54 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_55 = 55 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_56 = 56 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_57 = 57 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_58 = 58 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_59 = 59 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_60 = 60 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_61 = 61 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_62 = 62 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_63 = 63 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_64 = 64 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_65 = 65 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_66 = 66 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_67 = 67 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_68 = 68 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_69 = 69 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_70 = 70 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_71 = 71 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_72 = 72 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_73 = 73 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_74 = 74 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_75 = 75 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_76 = 76 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_77 = 77 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_78 = 78 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_79 = 79 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_80 = 80 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_81 = 81 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_82 = 82 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_83 = 83 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_84 = 84 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_85 = 85 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_86 = 86 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_87 = 87 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_88 = 88 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_89 = 89 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_90 = 90 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_91 = 91 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_92 = 92 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_93 = 93 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_94 = 94 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_95 = 95 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_96 = 96 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_97 = 97 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_98 = 98 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_99 = 99 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_100 = 100 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_101 = 101 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_102 = 102 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_103 = 103 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_104 = 104 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_105 = 105 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_106 = 106 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_107 = 107 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_108 = 108 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_109 = 109 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_110 = 110 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_111 = 111 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_112 = 112 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_113 = 113 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_114 = 114 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_115 = 115 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_116 = 116 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_117 = 117 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_118 = 118 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_119 = 119 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_120 = 120 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_121 = 121 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_122 = 122 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_123 = 123 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_124 = 124 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_125 = 125 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_126 = 126 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_127 = 127 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_128 = 128 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_129 = 129 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_130 = 130 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_131 = 131 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_132 = 132 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_133 = 133 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_134 = 134 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_135 = 135 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_136 = 136 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_137 = 137 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_138 = 138 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_139 = 139 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_140 = 140 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_141 = 141 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_142 = 142 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_143 = 143 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_144 = 144 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_145 = 145 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_146 = 146 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_147 = 147 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_148 = 148 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_149 = 149 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_150 = 150 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_151 = 151 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_152 = 152 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_153 = 153 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_154 = 154 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_155 = 155 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_156 = 156 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_157 = 157 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_158 = 158 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_159 = 159 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_160 = 160 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_161 = 161 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_162 = 162 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_163 = 163 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_164 = 164 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_165 = 165 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_166 = 166 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_167 = 167 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_168 = 168 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_169 = 169 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_170 = 170 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_171 = 171 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_172 = 172 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_173 = 173 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_174 = 174 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_175 = 175 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_176 = 176 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_177 = 177 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_178 = 178 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_179 = 179 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_180 = 180 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_181 = 181 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_182 = 182 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_183 = 183 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_184 = 184 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_185 = 185 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_186 = 186 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_187 = 187 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_188 = 188 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_189 = 189 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_190 = 190 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_191 = 191 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_192 = 192 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_193 = 193 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_194 = 194 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_195 = 195 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_196 = 196 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_197 = 197 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_198 = 198 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_199 = 199 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_200 = 200 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_201 = 201 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_202 = 202 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_203 = 203 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_204 = 204 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_205 = 205 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_206 = 206 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_207 = 207 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_208 = 208 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_209 = 209 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_210 = 210 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_211 = 211 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_212 = 212 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_213 = 213 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_214 = 214 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_215 = 215 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_216 = 216 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_217 = 217 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_218 = 218 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_219 = 219 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_220 = 220 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_221 = 221 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_222 = 222 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_223 = 223 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_224 = 224 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_225 = 225 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_226 = 226 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_227 = 227 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_228 = 228 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_229 = 229 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_230 = 230 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_231 = 231 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_232 = 232 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_233 = 233 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_234 = 234 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_235 = 235 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_236 = 236 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_237 = 237 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_238 = 238 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_239 = 239 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_240 = 240 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_241 = 241 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_242 = 242 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_243 = 243 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_244 = 244 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_245 = 245 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_246 = 246 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_247 = 247 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_248 = 248 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_249 = 249 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_250 = 250 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_251 = 251 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_252 = 252 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_253 = 253 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_254 = 254 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_255 = 255 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_256 = 256 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_257 = 257 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_258 = 258 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_259 = 259 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_260 = 260 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_261 = 261 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_262 = 262 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_263 = 263 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_264 = 264 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_265 = 265 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_266 = 266 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_267 = 267 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_268 = 268 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_269 = 269 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_270 = 270 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_271 = 271 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_272 = 272 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_273 = 273 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_274 = 274 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_275 = 275 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_276 = 276 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_277 = 277 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_278 = 278 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_279 = 279 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_280 = 280 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_281 = 281 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_282 = 282 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_283 = 283 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_284 = 284 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_285 = 285 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_286 = 286 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_287 = 287 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_288 = 288 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_289 = 289 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_290 = 290 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_291 = 291 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_292 = 292 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_293 = 293 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_294 = 294 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_295 = 295 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_296 = 296 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_297 = 297 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_298 = 298 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_299 = 299 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_300 = 300 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_301 = 301 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_302 = 302 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_303 = 303 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_304 = 304 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_305 = 305 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_306 = 306 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_307 = 307 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_308 = 308 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_309 = 309 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_310 = 310 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_311 = 311 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_312 = 312 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_313 = 313 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_314 = 314 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_315 = 315 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_316 = 316 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_317 = 317 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_318 = 318 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_319 = 319 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_320 = 320 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_321 = 321 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_322 = 322 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_323 = 323 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_324 = 324 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_325 = 325 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_326 = 326 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_327 = 327 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_328 = 328 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_329 = 329 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_330 = 330 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_331 = 331 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_332 = 332 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_333 = 333 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_334 = 334 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_335 = 335 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_336 = 336 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_337 = 337 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_338 = 338 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_339 = 339 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_340 = 340 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_341 = 341 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_342 = 342 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_343 = 343 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_344 = 344 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_345 = 345 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_346 = 346 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_347 = 347 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_348 = 348 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_349 = 349 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_350 = 350 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_351 = 351 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_352 = 352 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_353 = 353 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_354 = 354 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_355 = 355 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_356 = 356 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_357 = 357 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_358 = 358 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_359 = 359 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_360 = 360 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_361 = 361 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_362 = 362 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_363 = 363 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_364 = 364 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_365 = 365 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_366 = 366 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_367 = 367 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_368 = 368 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_369 = 369 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_370 = 370 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_371 = 371 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_372 = 372 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_373 = 373 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_374 = 374 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_375 = 375 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_376 = 376 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_377 = 377 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_378 = 378 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_379 = 379 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_380 = 380 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_381 = 381 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_382 = 382 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_383 = 383 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_384 = 384 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_385 = 385 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_386 = 386 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_387 = 387 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_388 = 388 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_389 = 389 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_390 = 390 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_391 = 391 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_392 = 392 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_393 = 393 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_394 = 394 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_395 = 395 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_396 = 396 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_397 = 397 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_398 = 398 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_399 = 399 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_400 = 400 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_401 = 401 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_402 = 402 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_403 = 403 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_404 = 404 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_405 = 405 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_406 = 406 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_407 = 407 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_408 = 408 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_409 = 409 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_410 = 410 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_411 = 411 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_412 = 412 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_413 = 413 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_414 = 414 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_415 = 415 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_416 = 416 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_417 = 417 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_418 = 418 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_419 = 419 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_420 = 420 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_421 = 421 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_422 = 422 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_423 = 423 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_424 = 424 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_425 = 425 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_426 = 426 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_427 = 427 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_428 = 428 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_429 = 429 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_430 = 430 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_431 = 431 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_432 = 432 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_433 = 433 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_434 = 434 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_435 = 435 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_436 = 436 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_437 = 437 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_438 = 438 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_439 = 439 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_440 = 440 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_441 = 441 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_442 = 442 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_443 = 443 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_444 = 444 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_445 = 445 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_446 = 446 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_447 = 447 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_448 = 448 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_449 = 449 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_450 = 450 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_451 = 451 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_452 = 452 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_453 = 453 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_454 = 454 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_455 = 455 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_456 = 456 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_457 = 457 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_458 = 458 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_459 = 459 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_460 = 460 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_461 = 461 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_462 = 462 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_463 = 463 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_464 = 464 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_465 = 465 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_466 = 466 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_467 = 467 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_468 = 468 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_469 = 469 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_470 = 470 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_471 = 471 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_472 = 472 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_473 = 473 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_474 = 474 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_475 = 475 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_476 = 476 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_477 = 477 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_478 = 478 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_479 = 479 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_480 = 480 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_481 = 481 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_482 = 482 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_483 = 483 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_484 = 484 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_485 = 485 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_486 = 486 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_487 = 487 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_488 = 488 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_489 = 489 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_490 = 490 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_491 = 491 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_492 = 492 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_493 = 493 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_494 = 494 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_495 = 495 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_496 = 496 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_497 = 497 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_498 = 498 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_499 = 499 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_500 = 500 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_501 = 501 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_502 = 502 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_503 = 503 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_504 = 504 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_505 = 505 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_506 = 506 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_507 = 507 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_508 = 508 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_509 = 509 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_510 = 510 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_511 = 511 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_512 = 512 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_513 = 513 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_514 = 514 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_515 = 515 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_516 = 516 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_517 = 517 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_518 = 518 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_519 = 519 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_520 = 520 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_521 = 521 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_522 = 522 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_523 = 523 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_524 = 524 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_525 = 525 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_526 = 526 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_527 = 527 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_528 = 528 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_529 = 529 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_530 = 530 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_531 = 531 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_532 = 532 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_533 = 533 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_534 = 534 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_535 = 535 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_536 = 536 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_537 = 537 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_538 = 538 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_539 = 539 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_540 = 540 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_541 = 541 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_542 = 542 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_543 = 543 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_544 = 544 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_545 = 545 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_546 = 546 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_547 = 547 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_548 = 548 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_549 = 549 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_550 = 550 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_551 = 551 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_552 = 552 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_553 = 553 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_554 = 554 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_555 = 555 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_556 = 556 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_557 = 557 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_558 = 558 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_559 = 559 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_560 = 560 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_561 = 561 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_562 = 562 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_563 = 563 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_564 = 564 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_565 = 565 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_566 = 566 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_567 = 567 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_568 = 568 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_569 = 569 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_570 = 570 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_571 = 571 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_572 = 572 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_573 = 573 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_574 = 574 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_575 = 575 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_576 = 576 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_577 = 577 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_578 = 578 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_579 = 579 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_580 = 580 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_581 = 581 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_582 = 582 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_583 = 583 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_584 = 584 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_585 = 585 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_586 = 586 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_587 = 587 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_588 = 588 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_589 = 589 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_590 = 590 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_591 = 591 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_592 = 592 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_593 = 593 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_594 = 594 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_595 = 595 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_596 = 596 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_597 = 597 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_598 = 598 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_599 = 599 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_600 = 600 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_601 = 601 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_602 = 602 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_603 = 603 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_604 = 604 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_605 = 605 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_606 = 606 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_607 = 607 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_608 = 608 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_609 = 609 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_610 = 610 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_611 = 611 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_612 = 612 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_613 = 613 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_614 = 614 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_615 = 615 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_616 = 616 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_617 = 617 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_618 = 618 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_619 = 619 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_620 = 620 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_621 = 621 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_622 = 622 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_623 = 623 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_624 = 624 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_625 = 625 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_626 = 626 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_627 = 627 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_628 = 628 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_629 = 629 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_630 = 630 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_631 = 631 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_632 = 632 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_633 = 633 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_634 = 634 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_635 = 635 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_636 = 636 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_637 = 637 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_638 = 638 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_639 = 639 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_640 = 640 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_641 = 641 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_642 = 642 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_643 = 643 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_644 = 644 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_645 = 645 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_646 = 646 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_647 = 647 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_648 = 648 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_649 = 649 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_650 = 650 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_651 = 651 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_652 = 652 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_653 = 653 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_654 = 654 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_655 = 655 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_656 = 656 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_657 = 657 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_658 = 658 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_659 = 659 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_660 = 660 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_661 = 661 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_662 = 662 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_663 = 663 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_664 = 664 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_665 = 665 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_666 = 666 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_667 = 667 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_668 = 668 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_669 = 669 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_670 = 670 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_671 = 671 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_672 = 672 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_673 = 673 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_674 = 674 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_675 = 675 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_676 = 676 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_677 = 677 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_678 = 678 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_679 = 679 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_680 = 680 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_681 = 681 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_682 = 682 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_683 = 683 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_684 = 684 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_685 = 685 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_686 = 686 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_687 = 687 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_688 = 688 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_689 = 689 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_690 = 690 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_691 = 691 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_692 = 692 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_693 = 693 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_694 = 694 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_695 = 695 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_696 = 696 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_697 = 697 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_698 = 698 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_699 = 699 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_700 = 700 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_701 = 701 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_702 = 702 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_703 = 703 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_704 = 704 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_705 = 705 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_706 = 706 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_707 = 707 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_708 = 708 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_709 = 709 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_710 = 710 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_711 = 711 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_712 = 712 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_713 = 713 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_714 = 714 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_715 = 715 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_716 = 716 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_717 = 717 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_718 = 718 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_719 = 719 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_720 = 720 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_721 = 721 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_722 = 722 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_723 = 723 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_724 = 724 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_725 = 725 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_726 = 726 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_727 = 727 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_728 = 728 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_729 = 729 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_730 = 730 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_731 = 731 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_732 = 732 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_733 = 733 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_734 = 734 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_735 = 735 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_736 = 736 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_737 = 737 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_738 = 738 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_739 = 739 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_740 = 740 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_741 = 741 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_742 = 742 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_743 = 743 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_744 = 744 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_745 = 745 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_746 = 746 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_747 = 747 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_748 = 748 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_749 = 749 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_750 = 750 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_751 = 751 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_752 = 752 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_753 = 753 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_754 = 754 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_755 = 755 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_756 = 756 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_757 = 757 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_758 = 758 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_759 = 759 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_760 = 760 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_761 = 761 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_762 = 762 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_763 = 763 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_764 = 764 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_765 = 765 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_766 = 766 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_767 = 767 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_768 = 768 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_769 = 769 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_770 = 770 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_771 = 771 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_772 = 772 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_773 = 773 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_774 = 774 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_775 = 775 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_776 = 776 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_777 = 777 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_778 = 778 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_779 = 779 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_780 = 780 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_781 = 781 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_782 = 782 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_783 = 783 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_784 = 784 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_785 = 785 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_786 = 786 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_787 = 787 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_788 = 788 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_789 = 789 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_790 = 790 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_791 = 791 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_792 = 792 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_793 = 793 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_794 = 794 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_795 = 795 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_796 = 796 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_797 = 797 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_798 = 798 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_799 = 799 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_800 = 800 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_801 = 801 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_802 = 802 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_803 = 803 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_804 = 804 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_805 = 805 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_806 = 806 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_807 = 807 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_808 = 808 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_809 = 809 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_810 = 810 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_811 = 811 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_812 = 812 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_813 = 813 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_814 = 814 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_815 = 815 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_816 = 816 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_817 = 817 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_818 = 818 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_819 = 819 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_820 = 820 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_821 = 821 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_822 = 822 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_823 = 823 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_824 = 824 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_825 = 825 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_826 = 826 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_827 = 827 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_828 = 828 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_829 = 829 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_830 = 830 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_831 = 831 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_832 = 832 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_833 = 833 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_834 = 834 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_835 = 835 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_836 = 836 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_837 = 837 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_838 = 838 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_839 = 839 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_840 = 840 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_841 = 841 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_842 = 842 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_843 = 843 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_844 = 844 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_845 = 845 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_846 = 846 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_847 = 847 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_848 = 848 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_849 = 849 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_850 = 850 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_851 = 851 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_852 = 852 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_853 = 853 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_854 = 854 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_855 = 855 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_856 = 856 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_857 = 857 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_858 = 858 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_859 = 859 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_860 = 860 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_861 = 861 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_862 = 862 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_863 = 863 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_864 = 864 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_865 = 865 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_866 = 866 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_867 = 867 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_868 = 868 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_869 = 869 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_870 = 870 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_871 = 871 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_872 = 872 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_873 = 873 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_874 = 874 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_875 = 875 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_876 = 876 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_877 = 877 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_878 = 878 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_879 = 879 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_880 = 880 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_881 = 881 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_882 = 882 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_883 = 883 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_884 = 884 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_885 = 885 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_886 = 886 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_887 = 887 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_888 = 888 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_889 = 889 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_890 = 890 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_891 = 891 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_892 = 892 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_893 = 893 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_894 = 894 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_895 = 895 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_896 = 896 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_897 = 897 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_898 = 898 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_899 = 899 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_900 = 900 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_901 = 901 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_902 = 902 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_903 = 903 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_904 = 904 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_905 = 905 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_906 = 906 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_907 = 907 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_908 = 908 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_909 = 909 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_910 = 910 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_911 = 911 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_912 = 912 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_913 = 913 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_914 = 914 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_915 = 915 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_916 = 916 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_917 = 917 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_918 = 918 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_919 = 919 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_920 = 920 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_921 = 921 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_922 = 922 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_923 = 923 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_924 = 924 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_925 = 925 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_926 = 926 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_927 = 927 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_928 = 928 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_929 = 929 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_930 = 930 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_931 = 931 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_932 = 932 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_933 = 933 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_934 = 934 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_935 = 935 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_936 = 936 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_937 = 937 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_938 = 938 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_939 = 939 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_940 = 940 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_941 = 941 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_942 = 942 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_943 = 943 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_944 = 944 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_945 = 945 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_946 = 946 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_947 = 947 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_948 = 948 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_949 = 949 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_950 = 950 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_951 = 951 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_952 = 952 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_953 = 953 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_954 = 954 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_955 = 955 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_956 = 956 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_957 = 957 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_958 = 958 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_959 = 959 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_960 = 960 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_961 = 961 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_962 = 962 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_963 = 963 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_964 = 964 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_965 = 965 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_966 = 966 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_967 = 967 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_968 = 968 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_969 = 969 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_970 = 970 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_971 = 971 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_972 = 972 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_973 = 973 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_974 = 974 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_975 = 975 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_976 = 976 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_977 = 977 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_978 = 978 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_979 = 979 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_980 = 980 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_981 = 981 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_982 = 982 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_983 = 983 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_984 = 984 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_985 = 985 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_986 = 986 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_987 = 987 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_988 = 988 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_989 = 989 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_990 = 990 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_991 = 991 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_992 = 992 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_993 = 993 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_994 = 994 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_995 = 995 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_996 = 996 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_997 = 997 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_998 = 998 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_999 = 999 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000 = 1000 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto
deleted file mode 100644
index ec36cca..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto
+++ /dev/null
@@ -1,64 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file which is imported by unittest.proto to test importing.
-
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do
-// "using namespace unittest_import = protobuf_unittest_import".
-package protobuf_unittest_import;
-
-option optimize_for = SPEED;
-
-// Exercise the java_package option.
-option java_package = "com.google.protobuf.test";
-
-// Do not set a java_outer_classname here to verify that Proto2 works without
-// one.
-
-// Test public import
-import public "google/protobuf/unittest_import_public.proto";
-
-message ImportMessage {
-  optional int32 d = 1;
-}
-
-enum ImportEnum {
-  IMPORT_FOO = 7;
-  IMPORT_BAR = 8;
-  IMPORT_BAZ = 9;
-}
-
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_lite.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_lite.proto
deleted file mode 100644
index 81b117f..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_lite.proto
+++ /dev/null
@@ -1,51 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
-
-package protobuf_unittest_import;
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.protobuf";
-
-import public "google/protobuf/unittest_import_public_lite.proto";
-
-message ImportMessageLite {
-  optional int32 d = 1;
-}
-
-enum ImportEnumLite {
-  IMPORT_LITE_FOO = 7;
-  IMPORT_LITE_BAR = 8;
-  IMPORT_LITE_BAZ = 9;
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public.proto
deleted file mode 100644
index ea5d1b1..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public.proto
+++ /dev/null
@@ -1,40 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: liujisi@google.com (Pherl Liu)
-
-
-package protobuf_unittest_import;
-
-option java_package = "com.google.protobuf.test";
-
-message PublicImportMessage {
-  optional int32 e = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public_lite.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public_lite.proto
deleted file mode 100644
index d077563..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public_lite.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: liujisi@google.com (Pherl Liu)
-
-
-package protobuf_unittest_import;
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.protobuf";
-
-message PublicImportMessageLite {
-  optional int32 e = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite.proto
deleted file mode 100644
index a1764aa..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite.proto
+++ /dev/null
@@ -1,360 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// This is like unittest.proto but with optimize_for = LITE_RUNTIME.
-
-package protobuf_unittest;
-
-import "google/protobuf/unittest_import_lite.proto";
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.protobuf";
-
-// Same as TestAllTypes but with the lite runtime.
-message TestAllTypesLite {
-  message NestedMessage {
-    optional int32 bb = 1;
-  }
-
-  enum NestedEnum {
-    FOO = 1;
-    BAR = 2;
-    BAZ = 3;
-  }
-
-  // Singular
-  optional    int32 optional_int32    =  1;
-  optional    int64 optional_int64    =  2;
-  optional   uint32 optional_uint32   =  3;
-  optional   uint64 optional_uint64   =  4;
-  optional   sint32 optional_sint32   =  5;
-  optional   sint64 optional_sint64   =  6;
-  optional  fixed32 optional_fixed32  =  7;
-  optional  fixed64 optional_fixed64  =  8;
-  optional sfixed32 optional_sfixed32 =  9;
-  optional sfixed64 optional_sfixed64 = 10;
-  optional    float optional_float    = 11;
-  optional   double optional_double   = 12;
-  optional     bool optional_bool     = 13;
-  optional   string optional_string   = 14;
-  optional    bytes optional_bytes    = 15;
-
-  optional group OptionalGroup = 16 {
-    optional int32 a = 17;
-  }
-
-  optional NestedMessage      optional_nested_message  = 18;
-  optional ForeignMessageLite optional_foreign_message = 19;
-  optional protobuf_unittest_import.ImportMessageLite
-    optional_import_message = 20;
-
-  optional NestedEnum      optional_nested_enum     = 21;
-  optional ForeignEnumLite optional_foreign_enum    = 22;
-  optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23;
-
-  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
-  optional string optional_cord = 25 [ctype=CORD];
-
-  // Defined in unittest_import_public.proto
-  optional protobuf_unittest_import.PublicImportMessageLite
-      optional_public_import_message = 26;
-
-  optional NestedMessage optional_lazy_message = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32    = 31;
-  repeated    int64 repeated_int64    = 32;
-  repeated   uint32 repeated_uint32   = 33;
-  repeated   uint64 repeated_uint64   = 34;
-  repeated   sint32 repeated_sint32   = 35;
-  repeated   sint64 repeated_sint64   = 36;
-  repeated  fixed32 repeated_fixed32  = 37;
-  repeated  fixed64 repeated_fixed64  = 38;
-  repeated sfixed32 repeated_sfixed32 = 39;
-  repeated sfixed64 repeated_sfixed64 = 40;
-  repeated    float repeated_float    = 41;
-  repeated   double repeated_double   = 42;
-  repeated     bool repeated_bool     = 43;
-  repeated   string repeated_string   = 44;
-  repeated    bytes repeated_bytes    = 45;
-
-  repeated group RepeatedGroup = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated NestedMessage      repeated_nested_message  = 48;
-  repeated ForeignMessageLite repeated_foreign_message = 49;
-  repeated protobuf_unittest_import.ImportMessageLite
-    repeated_import_message = 50;
-
-  repeated NestedEnum      repeated_nested_enum  = 51;
-  repeated ForeignEnumLite repeated_foreign_enum = 52;
-  repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53;
-
-  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord = 55 [ctype=CORD];
-
-  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32    = 61 [default =  41    ];
-  optional    int64 default_int64    = 62 [default =  42    ];
-  optional   uint32 default_uint32   = 63 [default =  43    ];
-  optional   uint64 default_uint64   = 64 [default =  44    ];
-  optional   sint32 default_sint32   = 65 [default = -45    ];
-  optional   sint64 default_sint64   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
-  optional    float default_float    = 71 [default =  51.5  ];
-  optional   double default_double   = 72 [default =  52e3  ];
-  optional     bool default_bool     = 73 [default = true   ];
-  optional   string default_string   = 74 [default = "hello"];
-  optional    bytes default_bytes    = 75 [default = "world"];
-
-  optional NestedEnum default_nested_enum = 81 [default = BAR];
-  optional ForeignEnumLite default_foreign_enum = 82
-      [default = FOREIGN_LITE_BAR];
-  optional protobuf_unittest_import.ImportEnumLite
-      default_import_enum = 83 [default = IMPORT_LITE_BAR];
-
-  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
-  optional string default_cord = 85 [ctype=CORD,default="123"];
-}
-
-message ForeignMessageLite {
-  optional int32 c = 1;
-}
-
-enum ForeignEnumLite {
-  FOREIGN_LITE_FOO = 4;
-  FOREIGN_LITE_BAR = 5;
-  FOREIGN_LITE_BAZ = 6;
-}
-
-message TestPackedTypesLite {
-  repeated    int32 packed_int32    =  90 [packed = true];
-  repeated    int64 packed_int64    =  91 [packed = true];
-  repeated   uint32 packed_uint32   =  92 [packed = true];
-  repeated   uint64 packed_uint64   =  93 [packed = true];
-  repeated   sint32 packed_sint32   =  94 [packed = true];
-  repeated   sint64 packed_sint64   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
-  repeated    float packed_float    = 100 [packed = true];
-  repeated   double packed_double   = 101 [packed = true];
-  repeated     bool packed_bool     = 102 [packed = true];
-  repeated ForeignEnumLite packed_enum  = 103 [packed = true];
-}
-
-message TestAllExtensionsLite {
-  extensions 1 to max;
-}
-
-extend TestAllExtensionsLite {
-  // Singular
-  optional    int32 optional_int32_extension_lite    =  1;
-  optional    int64 optional_int64_extension_lite    =  2;
-  optional   uint32 optional_uint32_extension_lite   =  3;
-  optional   uint64 optional_uint64_extension_lite   =  4;
-  optional   sint32 optional_sint32_extension_lite   =  5;
-  optional   sint64 optional_sint64_extension_lite   =  6;
-  optional  fixed32 optional_fixed32_extension_lite  =  7;
-  optional  fixed64 optional_fixed64_extension_lite  =  8;
-  optional sfixed32 optional_sfixed32_extension_lite =  9;
-  optional sfixed64 optional_sfixed64_extension_lite = 10;
-  optional    float optional_float_extension_lite    = 11;
-  optional   double optional_double_extension_lite   = 12;
-  optional     bool optional_bool_extension_lite     = 13;
-  optional   string optional_string_extension_lite   = 14;
-  optional    bytes optional_bytes_extension_lite    = 15;
-
-  optional group OptionalGroup_extension_lite = 16 {
-    optional int32 a = 17;
-  }
-
-  optional TestAllTypesLite.NestedMessage optional_nested_message_extension_lite
-      = 18;
-  optional ForeignMessageLite optional_foreign_message_extension_lite = 19;
-  optional protobuf_unittest_import.ImportMessageLite
-    optional_import_message_extension_lite = 20;
-
-  optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21;
-  optional ForeignEnumLite optional_foreign_enum_extension_lite = 22;
-  optional protobuf_unittest_import.ImportEnumLite
-    optional_import_enum_extension_lite = 23;
-
-  optional string optional_string_piece_extension_lite = 24
-      [ctype=STRING_PIECE];
-  optional string optional_cord_extension_lite = 25 [ctype=CORD];
-
-  optional protobuf_unittest_import.PublicImportMessageLite
-    optional_public_import_message_extension_lite = 26;
-
-  optional TestAllTypesLite.NestedMessage
-    optional_lazy_message_extension_lite = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32_extension_lite    = 31;
-  repeated    int64 repeated_int64_extension_lite    = 32;
-  repeated   uint32 repeated_uint32_extension_lite   = 33;
-  repeated   uint64 repeated_uint64_extension_lite   = 34;
-  repeated   sint32 repeated_sint32_extension_lite   = 35;
-  repeated   sint64 repeated_sint64_extension_lite   = 36;
-  repeated  fixed32 repeated_fixed32_extension_lite  = 37;
-  repeated  fixed64 repeated_fixed64_extension_lite  = 38;
-  repeated sfixed32 repeated_sfixed32_extension_lite = 39;
-  repeated sfixed64 repeated_sfixed64_extension_lite = 40;
-  repeated    float repeated_float_extension_lite    = 41;
-  repeated   double repeated_double_extension_lite   = 42;
-  repeated     bool repeated_bool_extension_lite     = 43;
-  repeated   string repeated_string_extension_lite   = 44;
-  repeated    bytes repeated_bytes_extension_lite    = 45;
-
-  repeated group RepeatedGroup_extension_lite = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite
-      = 48;
-  repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49;
-  repeated protobuf_unittest_import.ImportMessageLite
-    repeated_import_message_extension_lite = 50;
-
-  repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51;
-  repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52;
-  repeated protobuf_unittest_import.ImportEnumLite
-    repeated_import_enum_extension_lite = 53;
-
-  repeated string repeated_string_piece_extension_lite = 54
-      [ctype=STRING_PIECE];
-  repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
-
-  repeated TestAllTypesLite.NestedMessage
-    repeated_lazy_message_extension_lite = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32_extension_lite    = 61 [default =  41    ];
-  optional    int64 default_int64_extension_lite    = 62 [default =  42    ];
-  optional   uint32 default_uint32_extension_lite   = 63 [default =  43    ];
-  optional   uint64 default_uint64_extension_lite   = 64 [default =  44    ];
-  optional   sint32 default_sint32_extension_lite   = 65 [default = -45    ];
-  optional   sint64 default_sint64_extension_lite   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32_extension_lite  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64_extension_lite  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32_extension_lite = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50    ];
-  optional    float default_float_extension_lite    = 71 [default =  51.5  ];
-  optional   double default_double_extension_lite   = 72 [default =  52e3  ];
-  optional     bool default_bool_extension_lite     = 73 [default = true   ];
-  optional   string default_string_extension_lite   = 74 [default = "hello"];
-  optional    bytes default_bytes_extension_lite    = 75 [default = "world"];
-
-  optional TestAllTypesLite.NestedEnum
-    default_nested_enum_extension_lite = 81 [default = BAR];
-  optional ForeignEnumLite
-    default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR];
-  optional protobuf_unittest_import.ImportEnumLite
-    default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR];
-
-  optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE,
-                                                            default="abc"];
-  optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"];
-}
-
-message TestPackedExtensionsLite {
-  extensions 1 to max;
-}
-
-extend TestPackedExtensionsLite {
-  repeated    int32 packed_int32_extension_lite    =  90 [packed = true];
-  repeated    int64 packed_int64_extension_lite    =  91 [packed = true];
-  repeated   uint32 packed_uint32_extension_lite   =  92 [packed = true];
-  repeated   uint64 packed_uint64_extension_lite   =  93 [packed = true];
-  repeated   sint32 packed_sint32_extension_lite   =  94 [packed = true];
-  repeated   sint64 packed_sint64_extension_lite   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32_extension_lite  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64_extension_lite  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32_extension_lite =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64_extension_lite =  99 [packed = true];
-  repeated    float packed_float_extension_lite    = 100 [packed = true];
-  repeated   double packed_double_extension_lite   = 101 [packed = true];
-  repeated     bool packed_bool_extension_lite     = 102 [packed = true];
-  repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true];
-}
-
-message TestNestedExtensionLite {
-  extend TestAllExtensionsLite {
-    optional int32 nested_extension = 12345;
-  }
-}
-
-// Test that deprecated fields work.  We only verify that they compile (at one
-// point this failed).
-message TestDeprecatedLite {
-  optional int32 deprecated_field = 1 [deprecated = true];
-}
-
-// See the comments of the same type in unittest.proto.
-message TestParsingMergeLite {
-  message RepeatedFieldsGenerator {
-    repeated TestAllTypesLite field1 = 1;
-    repeated TestAllTypesLite field2 = 2;
-    repeated TestAllTypesLite field3 = 3;
-    repeated group Group1 = 10 {
-      optional TestAllTypesLite field1 = 11;
-    }
-    repeated group Group2 = 20 {
-      optional TestAllTypesLite field1 = 21;
-    }
-    repeated TestAllTypesLite ext1 = 1000;
-    repeated TestAllTypesLite ext2 = 1001;
-  }
-  required TestAllTypesLite required_all_types = 1;
-  optional TestAllTypesLite optional_all_types = 2;
-  repeated TestAllTypesLite repeated_all_types = 3;
-  optional group OptionalGroup = 10 {
-    optional TestAllTypesLite optional_group_all_types = 11;
-  }
-  repeated group RepeatedGroup = 20 {
-    optional TestAllTypesLite repeated_group_all_types = 21;
-  }
-  extensions 1000 to max;
-  extend TestParsingMergeLite {
-    optional TestAllTypesLite optional_ext = 1000;
-    repeated TestAllTypesLite repeated_ext = 1001;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
deleted file mode 100644
index d52cb8c..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
+++ /dev/null
@@ -1,43 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// Tests that a "lite" message can import a regular message.
-
-package protobuf_unittest;
-
-import "google/protobuf/unittest.proto";
-
-option optimize_for = LITE_RUNTIME;
-
-message TestLiteImportsNonlite {
-  optional TestAllTypes message = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_mset.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_mset.proto
deleted file mode 100644
index 3497f09..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_mset.proto
+++ /dev/null
@@ -1,72 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// This file contains messages for testing message_set_wire_format.
-
-package protobuf_unittest;
-
-option optimize_for = SPEED;
-
-// A message with message_set_wire_format.
-message TestMessageSet {
-  option message_set_wire_format = true;
-  extensions 4 to max;
-}
-
-message TestMessageSetContainer {
-  optional TestMessageSet message_set = 1;
-}
-
-message TestMessageSetExtension1 {
-  extend TestMessageSet {
-    optional TestMessageSetExtension1 message_set_extension = 1545008;
-  }
-  optional int32 i = 15;
-}
-
-message TestMessageSetExtension2 {
-  extend TestMessageSet {
-    optional TestMessageSetExtension2 message_set_extension = 1547769;
-  }
-  optional string str = 25;
-}
-
-// MessageSet wire format is equivalent to this.
-message RawMessageSet {
-  repeated group Item = 1 {
-    required int32 type_id = 2;
-    required bytes message = 3;
-  }
-}
-
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_no_generic_services.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_no_generic_services.proto
deleted file mode 100644
index cffb412..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_no_generic_services.proto
+++ /dev/null
@@ -1,52 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-
-package google.protobuf.no_generic_services_test;
-
-// *_generic_services are false by default.
-
-message TestMessage {
-  optional int32 a = 1;
-  extensions 1000 to max;
-}
-
-enum TestEnum {
-  FOO = 1;
-}
-
-extend TestMessage {
-  optional int32 test_extension = 1000;
-}
-
-service TestService {
-  rpc Foo(TestMessage) returns(TestMessage);
-}
diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto
deleted file mode 100644
index 658c6a9..0000000
--- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto
+++ /dev/null
@@ -1,61 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file which uses optimize_for = CODE_SIZE.
-
-import "google/protobuf/unittest.proto";
-
-package protobuf_unittest;
-
-option optimize_for = CODE_SIZE;
-
-message TestOptimizedForSize {
-  optional int32 i = 1;
-  optional ForeignMessage msg = 19;
-
-  extensions 1000 to max;
-
-  extend TestOptimizedForSize {
-    optional int32 test_extension = 1234;
-    optional TestRequiredOptimizedForSize test_extension2 = 1235;
-  }
-}
-
-message TestRequiredOptimizedForSize {
-  required int32 x = 1;
-}
-
-message TestOptionalOptimizedForSize {
-  optional TestRequiredOptimizedForSize o = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/pom.xml b/java/compatibility_tests/v2.5.0/pom.xml
deleted file mode 100644
index 83a7563..0000000
--- a/java/compatibility_tests/v2.5.0/pom.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>com.google.protobuf.compatibility</groupId>
-  <artifactId>compatibility-test-suite</artifactId>
-  <version>2.5.0</version>
-  <name>Protocol Buffer Java API compatibility tests</name>
-  <packaging>pom</packaging>
-  <modules>
-    <module>protos</module>
-    <module>more_protos</module>
-    <module>tests</module>
-  </modules>
-  <properties>
-    <protoc.path>protoc</protoc.path>
-    <protobuf.version>2.5.0</protobuf.version>
-
-    <protos.protoc.path>${protoc.path}</protos.protoc.path>
-    <protos.protobuf.version>${protobuf.version}</protos.protobuf.version>
-
-    <more_protos.protoc.path>${protoc.path}</more_protos.protoc.path>
-    <more_protos.protobuf.version>${protobuf.version}</more_protos.protobuf.version>
-
-    <tests.protobuf.version>${protobuf.version}</tests.protobuf.version>
-
-    <protobuf.test.source.path>.</protobuf.test.source.path>
-  </properties>
-</project>
diff --git a/java/compatibility_tests/v2.5.0/protos/pom.xml b/java/compatibility_tests/v2.5.0/protos/pom.xml
deleted file mode 100644
index a22e91e..0000000
--- a/java/compatibility_tests/v2.5.0/protos/pom.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>com.google.protobuf.compatibility</groupId>
-    <artifactId>compatibility-test-suite</artifactId>
-    <version>2.5.0</version>
-    <relativePath>..</relativePath>
-  </parent>
-
-  <groupId>com.google.protobuf.compatibility</groupId>
-  <artifactId>compatibility-protos</artifactId>
-  <version>2.5.0</version>
-
-  <name>Protos for Compatibility test</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.protobuf</groupId>
-      <artifactId>protobuf-java</artifactId>
-      <version>${protos.protobuf.version}</version>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.6.0</version>
-        <configuration>
-          <source>1.6</source>
-          <target>1.6</target>
-        </configuration>
-      </plugin>
-      <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>generate-sources</id>
-            <phase>generate-sources</phase>
-            <configuration>
-              <tasks>
-                <mkdir dir="target/generated-sources" />
-                <exec executable="${protos.protoc.path}">
-                  <arg value="--java_out=target/generated-sources" />
-                  <arg value="--proto_path=src/proto" />
-                  <arg value="src/proto/google/protobuf/unittest_custom_options.proto" />
-                  <arg value="src/proto/google/protobuf/unittest_enormous_descriptor.proto" />
-                  <arg value="src/proto/google/protobuf/unittest_import.proto" />
-                  <arg value="src/proto/google/protobuf/unittest_import_public.proto" />
-                  <arg value="src/proto/google/protobuf/unittest_mset.proto" />
-                  <arg value="src/proto/google/protobuf/unittest_no_generic_services.proto" />
-                  <arg value="src/proto/com/google/protobuf/nested_builders_test.proto" />
-                  <arg value="src/proto/com/google/protobuf/nested_extension.proto" />
-                  <arg value="src/proto/com/google/protobuf/non_nested_extension.proto" />
-                  <arg value="src/proto/com/google/protobuf/test_bad_identifiers.proto" />
-                </exec>
-              </tasks>
-              <sourceRoot>target/generated-sources</sourceRoot>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/multiple_files_test.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/multiple_files_test.proto
deleted file mode 100644
index 9a04014..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/multiple_files_test.proto
+++ /dev/null
@@ -1,71 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// A proto file which tests the java_multiple_files option.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option java_generic_services = true;   // auto-added
-
-import "google/protobuf/unittest.proto";
-
-package protobuf_unittest;
-
-option java_multiple_files = true;
-option java_outer_classname = "MultipleFilesTestProto";
-
-message MessageWithNoOuter {
-  message NestedMessage {
-    optional int32 i = 1;
-  }
-  enum NestedEnum {
-    BAZ = 3;
-  }
-  optional NestedMessage nested = 1;
-  repeated TestAllTypes foreign = 2;
-  optional NestedEnum nested_enum = 3;
-  optional EnumWithNoOuter foreign_enum = 4;
-}
-
-enum EnumWithNoOuter {
-  FOO = 1;
-  BAR = 2;
-}
-
-service ServiceWithNoOuter {
-  rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
-}
-
-extend TestAllExtensions {
-  optional int32 extension_with_outer = 1234567;
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_builders_test.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_builders_test.proto
deleted file mode 100644
index abffb9d..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_builders_test.proto
+++ /dev/null
@@ -1,53 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: jonp@google.com (Jon Perlow)
-//
-
-package protobuf_unittest;
-
-option java_multiple_files = true;
-option java_outer_classname = "NestedBuilders";
-
-
-message Vehicle {
-  optional Engine engine = 1;
-  repeated Wheel wheel = 2;
-}
-
-message Engine {
-  optional int32 cylinder = 1;
-  optional int32 liters = 2;
-}
-
-message Wheel {
-  optional int32 radius = 1;
-  optional int32 width = 2;
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension.proto
deleted file mode 100644
index 9fe5d56..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension.proto
+++ /dev/null
@@ -1,45 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with nested extensions. Note that this must be defined in
-// a separate file to properly test the initialization of the outer class.
-
-
-import "com/google/protobuf/non_nested_extension.proto";
-
-package protobuf_unittest;
-
-message MyNestedExtension {
-  extend MessageToBeExtended {
-    optional MessageToBeExtended recursiveExtension = 2;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension_lite.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension_lite.proto
deleted file mode 100644
index 16ee46e..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension_lite.proto
+++ /dev/null
@@ -1,48 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with nested extensions for a MessageLite messages. Note that
-// this must be defined in a separate file to properly test the initialization
-// of the outer class.
-
-
-package protobuf_unittest;
-
-option optimize_for = LITE_RUNTIME;
-
-import "com/google/protobuf/non_nested_extension_lite.proto";
-
-message MyNestedExtensionLite {
-  extend MessageLiteToBeExtended {
-    optional MessageLiteToBeExtended recursiveExtensionLite = 3;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension.proto
deleted file mode 100644
index f61b419..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension.proto
+++ /dev/null
@@ -1,48 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with extensions.
-
-
-package protobuf_unittest;
-
-message MessageToBeExtended {
-  extensions 1 to max;
-}
-
-message MyNonNestedExtension {
-}
-
-extend MessageToBeExtended {
-  optional MyNonNestedExtension nonNestedExtension = 1;
-}
-
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
deleted file mode 100644
index 3c82659..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-//
-// A proto file with extensions for a MessageLite messages.
-
-
-package protobuf_unittest;
-
-option optimize_for = LITE_RUNTIME;
-
-message MessageLiteToBeExtended {
-  extensions 1 to max;
-}
-
-message MyNonNestedExtensionLite {
-}
-
-extend MessageLiteToBeExtended {
-  optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
-}
-
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/test_bad_identifiers.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
deleted file mode 100644
index 6e67d97..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
+++ /dev/null
@@ -1,108 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: jonp@google.com (Jon Perlow)
-
-// This file tests that various identifiers work as field and type names even
-// though the same identifiers are used internally by the java code generator.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option java_generic_services = true;   // auto-added
-
-package io_protocol_tests;
-
-option java_package = "com.google.protobuf";
-option java_outer_classname = "TestBadIdentifiersProto";
-
-message TestMessage {
-}
-
-message Descriptor {
-  option no_standard_descriptor_accessor = true;
-  optional string descriptor = 1;
-  message NestedDescriptor {
-    option no_standard_descriptor_accessor = true;
-    optional string descriptor = 1;
-  }
-  optional NestedDescriptor nested_descriptor = 2;
-}
-
-message Parser {
-  enum ParserEnum {
-    PARSER = 1;
-  }
-  optional ParserEnum parser = 1;
-}
-
-message Deprecated {
-  enum TestEnum {
-    FOO = 1;
-  }
-
-  optional int32 field1 = 1 [deprecated=true];
-  optional TestEnum field2 = 2 [deprecated=true];
-  optional TestMessage field3 = 3 [deprecated=true];
-}
-
-message Override {
-  optional int32 override = 1;
-}
-
-message Object {
-  optional int32 object = 1;
-  optional string string_object = 2;
-}
-
-message String {
-  optional string string = 1;
-}
-
-message Integer {
-  optional int32 integer = 1;
-}
-
-message Long {
-  optional int32 long = 1;
-}
-
-message Float {
-  optional float float = 1;
-}
-
-message Double {
-  optional double double = 1;
-}
-
-service TestConflictingMethodNames {
-  rpc Override(TestMessage) returns (TestMessage);
-}
-
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto
deleted file mode 100644
index 031433e..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto
+++ /dev/null
@@ -1,620 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// The messages in this file describe the definitions found in .proto files.
-// A valid .proto file can be translated directly to a FileDescriptorProto
-// without any other information (e.g. without reading its imports).
-
-
-
-package google.protobuf;
-option java_package = "com.google.protobuf";
-option java_outer_classname = "DescriptorProtos";
-
-// descriptor.proto must be optimized for speed because reflection-based
-// algorithms don't work during bootstrapping.
-option optimize_for = SPEED;
-
-// The protocol compiler can output a FileDescriptorSet containing the .proto
-// files it parses.
-message FileDescriptorSet {
-  repeated FileDescriptorProto file = 1;
-}
-
-// Describes a complete .proto file.
-message FileDescriptorProto {
-  optional string name = 1;       // file name, relative to root of source tree
-  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
-
-  // Names of files imported by this file.
-  repeated string dependency = 3;
-  // Indexes of the public imported files in the dependency list above.
-  repeated int32 public_dependency = 10;
-  // Indexes of the weak imported files in the dependency list.
-  // For Google-internal migration only. Do not use.
-  repeated int32 weak_dependency = 11;
-
-  // All top-level definitions in this file.
-  repeated DescriptorProto message_type = 4;
-  repeated EnumDescriptorProto enum_type = 5;
-  repeated ServiceDescriptorProto service = 6;
-  repeated FieldDescriptorProto extension = 7;
-
-  optional FileOptions options = 8;
-
-  // This field contains optional information about the original source code.
-  // You may safely remove this entire field whithout harming runtime
-  // functionality of the descriptors -- the information is needed only by
-  // development tools.
-  optional SourceCodeInfo source_code_info = 9;
-}
-
-// Describes a message type.
-message DescriptorProto {
-  optional string name = 1;
-
-  repeated FieldDescriptorProto field = 2;
-  repeated FieldDescriptorProto extension = 6;
-
-  repeated DescriptorProto nested_type = 3;
-  repeated EnumDescriptorProto enum_type = 4;
-
-  message ExtensionRange {
-    optional int32 start = 1;
-    optional int32 end = 2;
-  }
-  repeated ExtensionRange extension_range = 5;
-
-  optional MessageOptions options = 7;
-}
-
-// Describes a field within a message.
-message FieldDescriptorProto {
-  enum Type {
-    // 0 is reserved for errors.
-    // Order is weird for historical reasons.
-    TYPE_DOUBLE         = 1;
-    TYPE_FLOAT          = 2;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
-    // negative values are likely.
-    TYPE_INT64          = 3;
-    TYPE_UINT64         = 4;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
-    // negative values are likely.
-    TYPE_INT32          = 5;
-    TYPE_FIXED64        = 6;
-    TYPE_FIXED32        = 7;
-    TYPE_BOOL           = 8;
-    TYPE_STRING         = 9;
-    TYPE_GROUP          = 10;  // Tag-delimited aggregate.
-    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
-
-    // New in version 2.
-    TYPE_BYTES          = 12;
-    TYPE_UINT32         = 13;
-    TYPE_ENUM           = 14;
-    TYPE_SFIXED32       = 15;
-    TYPE_SFIXED64       = 16;
-    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
-    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
-  };
-
-  enum Label {
-    // 0 is reserved for errors
-    LABEL_OPTIONAL      = 1;
-    LABEL_REQUIRED      = 2;
-    LABEL_REPEATED      = 3;
-    // TODO(sanjay): Should we add LABEL_MAP?
-  };
-
-  optional string name = 1;
-  optional int32 number = 3;
-  optional Label label = 4;
-
-  // If type_name is set, this need not be set.  If both this and type_name
-  // are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
-  optional Type type = 5;
-
-  // For message and enum types, this is the name of the type.  If the name
-  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
-  // rules are used to find the type (i.e. first the nested types within this
-  // message are searched, then within the parent, on up to the root
-  // namespace).
-  optional string type_name = 6;
-
-  // For extensions, this is the name of the type being extended.  It is
-  // resolved in the same manner as type_name.
-  optional string extendee = 2;
-
-  // For numeric types, contains the original text representation of the value.
-  // For booleans, "true" or "false".
-  // For strings, contains the default text contents (not escaped in any way).
-  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
-  // TODO(kenton):  Base-64 encode?
-  optional string default_value = 7;
-
-  optional FieldOptions options = 8;
-}
-
-// Describes an enum type.
-message EnumDescriptorProto {
-  optional string name = 1;
-
-  repeated EnumValueDescriptorProto value = 2;
-
-  optional EnumOptions options = 3;
-}
-
-// Describes a value within an enum.
-message EnumValueDescriptorProto {
-  optional string name = 1;
-  optional int32 number = 2;
-
-  optional EnumValueOptions options = 3;
-}
-
-// Describes a service.
-message ServiceDescriptorProto {
-  optional string name = 1;
-  repeated MethodDescriptorProto method = 2;
-
-  optional ServiceOptions options = 3;
-}
-
-// Describes a method of a service.
-message MethodDescriptorProto {
-  optional string name = 1;
-
-  // Input and output type names.  These are resolved in the same way as
-  // FieldDescriptorProto.type_name, but must refer to a message type.
-  optional string input_type = 2;
-  optional string output_type = 3;
-
-  optional MethodOptions options = 4;
-}
-
-
-// ===================================================================
-// Options
-
-// Each of the definitions above may have "options" attached.  These are
-// just annotations which may cause code to be generated slightly differently
-// or may contain hints for code that manipulates protocol messages.
-//
-// Clients may define custom options as extensions of the *Options messages.
-// These extensions may not yet be known at parsing time, so the parser cannot
-// store the values in them.  Instead it stores them in a field in the *Options
-// message called uninterpreted_option. This field must have the same name
-// across all *Options messages. We then use this field to populate the
-// extensions when we build a descriptor, at which point all protos have been
-// parsed and so all extensions are known.
-//
-// Extension numbers for custom options may be chosen as follows:
-// * For options which will only be used within a single application or
-//   organization, or for experimental options, use field numbers 50000
-//   through 99999.  It is up to you to ensure that you do not use the
-//   same number for multiple options.
-// * For options which will be published and used publicly by multiple
-//   independent entities, e-mail protobuf-global-extension-registry@google.com
-//   to reserve extension numbers. Simply provide your project name (e.g.
-//   Object-C plugin) and your project website (if available) -- there's no need
-//   to explain how you intend to use them. Usually you only need one extension
-//   number. You can declare multiple options with only one extension number by
-//   putting them in a sub-message. See the Custom Options section of the docs
-//   for examples:
-//   http://code.google.com/apis/protocolbuffers/docs/proto.html#options
-//   If this turns out to be popular, a web service will be set up
-//   to automatically assign option numbers.
-
-
-message FileOptions {
-
-  // Sets the Java package where classes generated from this .proto will be
-  // placed.  By default, the proto package is used, but this is often
-  // inappropriate because proto packages do not normally start with backwards
-  // domain names.
-  optional string java_package = 1;
-
-
-  // If set, all the classes from the .proto file are wrapped in a single
-  // outer class with the given name.  This applies to both Proto1
-  // (equivalent to the old "--one_java_file" option) and Proto2 (where
-  // a .proto always translates to a single class, but you may want to
-  // explicitly choose the class name).
-  optional string java_outer_classname = 8;
-
-  // If set true, then the Java code generator will generate a separate .java
-  // file for each top-level message, enum, and service defined in the .proto
-  // file.  Thus, these types will *not* be nested inside the outer class
-  // named by java_outer_classname.  However, the outer class will still be
-  // generated to contain the file's getDescriptor() method as well as any
-  // top-level extensions defined in the file.
-  optional bool java_multiple_files = 10 [default=false];
-
-  // If set true, then the Java code generator will generate equals() and
-  // hashCode() methods for all messages defined in the .proto file. This is
-  // purely a speed optimization, as the AbstractMessage base class includes
-  // reflection-based implementations of these methods.
-  optional bool java_generate_equals_and_hash = 20 [default=false];
-
-  // Generated classes can be optimized for speed or code size.
-  enum OptimizeMode {
-    SPEED = 1;        // Generate complete code for parsing, serialization,
-                      // etc.
-    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
-    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
-  }
-  optional OptimizeMode optimize_for = 9 [default=SPEED];
-
-  // Sets the Go package where structs generated from this .proto will be
-  // placed.  There is no default.
-  optional string go_package = 11;
-
-
-
-  // Should generic services be generated in each language?  "Generic" services
-  // are not specific to any particular RPC system.  They are generated by the
-  // main code generators in each language (without additional plugins).
-  // Generic services were the only kind of service generation supported by
-  // early versions of proto2.
-  //
-  // Generic services are now considered deprecated in favor of using plugins
-  // that generate code specific to your particular RPC system.  Therefore,
-  // these default to false.  Old code which depends on generic services should
-  // explicitly set them to true.
-  optional bool cc_generic_services = 16 [default=false];
-  optional bool java_generic_services = 17 [default=false];
-  optional bool py_generic_services = 18 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MessageOptions {
-  // Set true to use the old proto1 MessageSet wire format for extensions.
-  // This is provided for backwards-compatibility with the MessageSet wire
-  // format.  You should not use this for any other reason:  It's less
-  // efficient, has fewer features, and is more complicated.
-  //
-  // The message must be defined exactly as follows:
-  //   message Foo {
-  //     option message_set_wire_format = true;
-  //     extensions 4 to max;
-  //   }
-  // Note that the message cannot have any defined fields; MessageSets only
-  // have extensions.
-  //
-  // All extensions of your type must be singular messages; e.g. they cannot
-  // be int32s, enums, or repeated messages.
-  //
-  // Because this is an option, the above two restrictions are not enforced by
-  // the protocol compiler.
-  optional bool message_set_wire_format = 1 [default=false];
-
-  // Disables the generation of the standard "descriptor()" accessor, which can
-  // conflict with a field of the same name.  This is meant to make migration
-  // from proto1 easier; new code should avoid fields named "descriptor".
-  optional bool no_standard_descriptor_accessor = 2 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message FieldOptions {
-  // The ctype option instructs the C++ code generator to use a different
-  // representation of the field than it normally would.  See the specific
-  // options below.  This option is not yet implemented in the open source
-  // release -- sorry, we'll try to include it in a future version!
-  optional CType ctype = 1 [default = STRING];
-  enum CType {
-    // Default mode.
-    STRING = 0;
-
-    CORD = 1;
-
-    STRING_PIECE = 2;
-  }
-  // The packed option can be enabled for repeated primitive fields to enable
-  // a more efficient representation on the wire. Rather than repeatedly
-  // writing the tag and type for each element, the entire array is encoded as
-  // a single length-delimited blob.
-  optional bool packed = 2;
-
-
-
-  // Should this field be parsed lazily?  Lazy applies only to message-type
-  // fields.  It means that when the outer message is initially parsed, the
-  // inner message's contents will not be parsed but instead stored in encoded
-  // form.  The inner message will actually be parsed when it is first accessed.
-  //
-  // This is only a hint.  Implementations are free to choose whether to use
-  // eager or lazy parsing regardless of the value of this option.  However,
-  // setting this option true suggests that the protocol author believes that
-  // using lazy parsing on this field is worth the additional bookkeeping
-  // overhead typically needed to implement it.
-  //
-  // This option does not affect the public interface of any generated code;
-  // all method signatures remain the same.  Furthermore, thread-safety of the
-  // interface is not affected by this option; const methods remain safe to
-  // call from multiple threads concurrently, while non-const methods continue
-  // to require exclusive access.
-  //
-  //
-  // Note that implementations may choose not to check required fields within
-  // a lazy sub-message.  That is, calling IsInitialized() on the outher message
-  // may return true even if the inner message has missing required fields.
-  // This is necessary because otherwise the inner message would have to be
-  // parsed in order to perform the check, defeating the purpose of lazy
-  // parsing.  An implementation which chooses not to check required fields
-  // must be consistent about it.  That is, for any particular sub-message, the
-  // implementation must either *always* check its required fields, or *never*
-  // check its required fields, regardless of whether or not the message has
-  // been parsed.
-  optional bool lazy = 5 [default=false];
-
-  // Is this field deprecated?
-  // Depending on the target platform, this can emit Deprecated annotations
-  // for accessors, or it will be completely ignored; in the very least, this
-  // is a formalization for deprecating fields.
-  optional bool deprecated = 3 [default=false];
-
-  // EXPERIMENTAL.  DO NOT USE.
-  // For "map" fields, the name of the field in the enclosed type that
-  // is the key for this map.  For example, suppose we have:
-  //   message Item {
-  //     required string name = 1;
-  //     required string value = 2;
-  //   }
-  //   message Config {
-  //     repeated Item items = 1 [experimental_map_key="name"];
-  //   }
-  // In this situation, the map key for Item will be set to "name".
-  // TODO: Fully-implement this, then remove the "experimental_" prefix.
-  optional string experimental_map_key = 9;
-
-  // For Google-internal migration only. Do not use.
-  optional bool weak = 10 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumOptions {
-
-  // Set this option to false to disallow mapping different tag names to a same
-  // value.
-  optional bool allow_alias = 2 [default=true];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumValueOptions {
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message ServiceOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MethodOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-
-// A message representing a option the parser does not recognize. This only
-// appears in options protos created by the compiler::Parser class.
-// DescriptorPool resolves these when building Descriptor objects. Therefore,
-// options protos in descriptor objects (e.g. returned by Descriptor::options(),
-// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
-// in them.
-message UninterpretedOption {
-  // The name of the uninterpreted option.  Each string represents a segment in
-  // a dot-separated name.  is_extension is true iff a segment represents an
-  // extension (denoted with parentheses in options specs in .proto files).
-  // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
-  // "foo.(bar.baz).qux".
-  message NamePart {
-    required string name_part = 1;
-    required bool is_extension = 2;
-  }
-  repeated NamePart name = 2;
-
-  // The value of the uninterpreted option, in whatever type the tokenizer
-  // identified it as during parsing. Exactly one of these should be set.
-  optional string identifier_value = 3;
-  optional uint64 positive_int_value = 4;
-  optional int64 negative_int_value = 5;
-  optional double double_value = 6;
-  optional bytes string_value = 7;
-  optional string aggregate_value = 8;
-}
-
-// ===================================================================
-// Optional source code info
-
-// Encapsulates information about the original source file from which a
-// FileDescriptorProto was generated.
-message SourceCodeInfo {
-  // A Location identifies a piece of source code in a .proto file which
-  // corresponds to a particular definition.  This information is intended
-  // to be useful to IDEs, code indexers, documentation generators, and similar
-  // tools.
-  //
-  // For example, say we have a file like:
-  //   message Foo {
-  //     optional string foo = 1;
-  //   }
-  // Let's look at just the field definition:
-  //   optional string foo = 1;
-  //   ^       ^^     ^^  ^  ^^^
-  //   a       bc     de  f  ghi
-  // We have the following locations:
-  //   span   path               represents
-  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
-  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
-  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
-  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
-  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
-  //
-  // Notes:
-  // - A location may refer to a repeated field itself (i.e. not to any
-  //   particular index within it).  This is used whenever a set of elements are
-  //   logically enclosed in a single code segment.  For example, an entire
-  //   extend block (possibly containing multiple extension definitions) will
-  //   have an outer location whose path refers to the "extensions" repeated
-  //   field without an index.
-  // - Multiple locations may have the same path.  This happens when a single
-  //   logical declaration is spread out across multiple places.  The most
-  //   obvious example is the "extend" block again -- there may be multiple
-  //   extend blocks in the same scope, each of which will have the same path.
-  // - A location's span is not always a subset of its parent's span.  For
-  //   example, the "extendee" of an extension declaration appears at the
-  //   beginning of the "extend" block and is shared by all extensions within
-  //   the block.
-  // - Just because a location's span is a subset of some other location's span
-  //   does not mean that it is a descendent.  For example, a "group" defines
-  //   both a type and a field in a single declaration.  Thus, the locations
-  //   corresponding to the type and field and their components will overlap.
-  // - Code which tries to interpret locations should probably be designed to
-  //   ignore those that it doesn't understand, as more types of locations could
-  //   be recorded in the future.
-  repeated Location location = 1;
-  message Location {
-    // Identifies which part of the FileDescriptorProto was defined at this
-    // location.
-    //
-    // Each element is a field number or an index.  They form a path from
-    // the root FileDescriptorProto to the place where the definition.  For
-    // example, this path:
-    //   [ 4, 3, 2, 7, 1 ]
-    // refers to:
-    //   file.message_type(3)  // 4, 3
-    //       .field(7)         // 2, 7
-    //       .name()           // 1
-    // This is because FileDescriptorProto.message_type has field number 4:
-    //   repeated DescriptorProto message_type = 4;
-    // and DescriptorProto.field has field number 2:
-    //   repeated FieldDescriptorProto field = 2;
-    // and FieldDescriptorProto.name has field number 1:
-    //   optional string name = 1;
-    //
-    // Thus, the above path gives the location of a field name.  If we removed
-    // the last element:
-    //   [ 4, 3, 2, 7 ]
-    // this path refers to the whole field declaration (from the beginning
-    // of the label to the terminating semicolon).
-    repeated int32 path = 1 [packed=true];
-
-    // Always has exactly three or four elements: start line, start column,
-    // end line (optional, otherwise assumed same as start line), end column.
-    // These are packed into a single field for efficiency.  Note that line
-    // and column numbers are zero-based -- typically you will want to add
-    // 1 to each before displaying to a user.
-    repeated int32 span = 2 [packed=true];
-
-    // If this SourceCodeInfo represents a complete declaration, these are any
-    // comments appearing before and after the declaration which appear to be
-    // attached to the declaration.
-    //
-    // A series of line comments appearing on consecutive lines, with no other
-    // tokens appearing on those lines, will be treated as a single comment.
-    //
-    // Only the comment content is provided; comment markers (e.g. //) are
-    // stripped out.  For block comments, leading whitespace and an asterisk
-    // will be stripped from the beginning of each line other than the first.
-    // Newlines are included in the output.
-    //
-    // Examples:
-    //
-    //   optional int32 foo = 1;  // Comment attached to foo.
-    //   // Comment attached to bar.
-    //   optional int32 bar = 2;
-    //
-    //   optional string baz = 3;
-    //   // Comment attached to baz.
-    //   // Another line attached to baz.
-    //
-    //   // Comment attached to qux.
-    //   //
-    //   // Another line attached to qux.
-    //   optional double qux = 4;
-    //
-    //   optional string corge = 5;
-    //   /* Block comment attached
-    //    * to corge.  Leading asterisks
-    //    * will be removed. */
-    //   /* Block comment attached to
-    //    * grault. */
-    //   optional int32 grault = 6;
-    optional string leading_comments = 3;
-    optional string trailing_comments = 4;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto
deleted file mode 100644
index 6eb2d86..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto
+++ /dev/null
@@ -1,719 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file we will use for unit testing.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;     // auto-added
-
-import "google/protobuf/unittest_import.proto";
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do "using namespace unittest = protobuf_unittest".
-package protobuf_unittest;
-
-// Protos optimized for SPEED use a strict superset of the generated code
-// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
-// tests for speed unless explicitly testing code size optimization.
-option optimize_for = SPEED;
-
-option java_outer_classname = "UnittestProto";
-
-// This proto includes every type of field in both singular and repeated
-// forms.
-message TestAllTypes {
-  message NestedMessage {
-    // The field name "b" fails to compile in proto1 because it conflicts with
-    // a local variable named "b" in one of the generated methods.  Doh.
-    // This file needs to compile in proto1 to test backwards-compatibility.
-    optional int32 bb = 1;
-  }
-
-  enum NestedEnum {
-    FOO = 1;
-    BAR = 2;
-    BAZ = 3;
-  }
-
-  // Singular
-  optional    int32 optional_int32    =  1;
-  optional    int64 optional_int64    =  2;
-  optional   uint32 optional_uint32   =  3;
-  optional   uint64 optional_uint64   =  4;
-  optional   sint32 optional_sint32   =  5;
-  optional   sint64 optional_sint64   =  6;
-  optional  fixed32 optional_fixed32  =  7;
-  optional  fixed64 optional_fixed64  =  8;
-  optional sfixed32 optional_sfixed32 =  9;
-  optional sfixed64 optional_sfixed64 = 10;
-  optional    float optional_float    = 11;
-  optional   double optional_double   = 12;
-  optional     bool optional_bool     = 13;
-  optional   string optional_string   = 14;
-  optional    bytes optional_bytes    = 15;
-
-  optional group OptionalGroup = 16 {
-    optional int32 a = 17;
-  }
-
-  optional NestedMessage                        optional_nested_message  = 18;
-  optional ForeignMessage                       optional_foreign_message = 19;
-  optional protobuf_unittest_import.ImportMessage optional_import_message  = 20;
-
-  optional NestedEnum                           optional_nested_enum     = 21;
-  optional ForeignEnum                          optional_foreign_enum    = 22;
-  optional protobuf_unittest_import.ImportEnum    optional_import_enum     = 23;
-
-  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
-  optional string optional_cord = 25 [ctype=CORD];
-
-  // Defined in unittest_import_public.proto
-  optional protobuf_unittest_import.PublicImportMessage
-      optional_public_import_message = 26;
-
-  optional NestedMessage optional_lazy_message = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32    = 31;
-  repeated    int64 repeated_int64    = 32;
-  repeated   uint32 repeated_uint32   = 33;
-  repeated   uint64 repeated_uint64   = 34;
-  repeated   sint32 repeated_sint32   = 35;
-  repeated   sint64 repeated_sint64   = 36;
-  repeated  fixed32 repeated_fixed32  = 37;
-  repeated  fixed64 repeated_fixed64  = 38;
-  repeated sfixed32 repeated_sfixed32 = 39;
-  repeated sfixed64 repeated_sfixed64 = 40;
-  repeated    float repeated_float    = 41;
-  repeated   double repeated_double   = 42;
-  repeated     bool repeated_bool     = 43;
-  repeated   string repeated_string   = 44;
-  repeated    bytes repeated_bytes    = 45;
-
-  repeated group RepeatedGroup = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated NestedMessage                        repeated_nested_message  = 48;
-  repeated ForeignMessage                       repeated_foreign_message = 49;
-  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
-
-  repeated NestedEnum                           repeated_nested_enum     = 51;
-  repeated ForeignEnum                          repeated_foreign_enum    = 52;
-  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
-
-  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord = 55 [ctype=CORD];
-
-  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32    = 61 [default =  41    ];
-  optional    int64 default_int64    = 62 [default =  42    ];
-  optional   uint32 default_uint32   = 63 [default =  43    ];
-  optional   uint64 default_uint64   = 64 [default =  44    ];
-  optional   sint32 default_sint32   = 65 [default = -45    ];
-  optional   sint64 default_sint64   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
-  optional    float default_float    = 71 [default =  51.5  ];
-  optional   double default_double   = 72 [default =  52e3  ];
-  optional     bool default_bool     = 73 [default = true   ];
-  optional   string default_string   = 74 [default = "hello"];
-  optional    bytes default_bytes    = 75 [default = "world"];
-
-  optional NestedEnum  default_nested_enum  = 81 [default = BAR        ];
-  optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
-  optional protobuf_unittest_import.ImportEnum
-      default_import_enum = 83 [default = IMPORT_BAR];
-
-  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
-  optional string default_cord = 85 [ctype=CORD,default="123"];
-}
-
-message TestDeprecatedFields {
-  optional int32 deprecated_int32 = 1 [deprecated=true];
-}
-
-// Define these after TestAllTypes to make sure the compiler can handle
-// that.
-message ForeignMessage {
-  optional int32 c = 1;
-}
-
-enum ForeignEnum {
-  FOREIGN_FOO = 4;
-  FOREIGN_BAR = 5;
-  FOREIGN_BAZ = 6;
-}
-
-message TestAllExtensions {
-  extensions 1 to max;
-}
-
-extend TestAllExtensions {
-  // Singular
-  optional    int32 optional_int32_extension    =  1;
-  optional    int64 optional_int64_extension    =  2;
-  optional   uint32 optional_uint32_extension   =  3;
-  optional   uint64 optional_uint64_extension   =  4;
-  optional   sint32 optional_sint32_extension   =  5;
-  optional   sint64 optional_sint64_extension   =  6;
-  optional  fixed32 optional_fixed32_extension  =  7;
-  optional  fixed64 optional_fixed64_extension  =  8;
-  optional sfixed32 optional_sfixed32_extension =  9;
-  optional sfixed64 optional_sfixed64_extension = 10;
-  optional    float optional_float_extension    = 11;
-  optional   double optional_double_extension   = 12;
-  optional     bool optional_bool_extension     = 13;
-  optional   string optional_string_extension   = 14;
-  optional    bytes optional_bytes_extension    = 15;
-
-  optional group OptionalGroup_extension = 16 {
-    optional int32 a = 17;
-  }
-
-  optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
-  optional ForeignMessage optional_foreign_message_extension = 19;
-  optional protobuf_unittest_import.ImportMessage
-    optional_import_message_extension = 20;
-
-  optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
-  optional ForeignEnum optional_foreign_enum_extension = 22;
-  optional protobuf_unittest_import.ImportEnum
-    optional_import_enum_extension = 23;
-
-  optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
-  optional string optional_cord_extension = 25 [ctype=CORD];
-
-  optional protobuf_unittest_import.PublicImportMessage
-    optional_public_import_message_extension = 26;
-
-  optional TestAllTypes.NestedMessage
-    optional_lazy_message_extension = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32_extension    = 31;
-  repeated    int64 repeated_int64_extension    = 32;
-  repeated   uint32 repeated_uint32_extension   = 33;
-  repeated   uint64 repeated_uint64_extension   = 34;
-  repeated   sint32 repeated_sint32_extension   = 35;
-  repeated   sint64 repeated_sint64_extension   = 36;
-  repeated  fixed32 repeated_fixed32_extension  = 37;
-  repeated  fixed64 repeated_fixed64_extension  = 38;
-  repeated sfixed32 repeated_sfixed32_extension = 39;
-  repeated sfixed64 repeated_sfixed64_extension = 40;
-  repeated    float repeated_float_extension    = 41;
-  repeated   double repeated_double_extension   = 42;
-  repeated     bool repeated_bool_extension     = 43;
-  repeated   string repeated_string_extension   = 44;
-  repeated    bytes repeated_bytes_extension    = 45;
-
-  repeated group RepeatedGroup_extension = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
-  repeated ForeignMessage repeated_foreign_message_extension = 49;
-  repeated protobuf_unittest_import.ImportMessage
-    repeated_import_message_extension = 50;
-
-  repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
-  repeated ForeignEnum repeated_foreign_enum_extension = 52;
-  repeated protobuf_unittest_import.ImportEnum
-    repeated_import_enum_extension = 53;
-
-  repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord_extension = 55 [ctype=CORD];
-
-  repeated TestAllTypes.NestedMessage
-    repeated_lazy_message_extension = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32_extension    = 61 [default =  41    ];
-  optional    int64 default_int64_extension    = 62 [default =  42    ];
-  optional   uint32 default_uint32_extension   = 63 [default =  43    ];
-  optional   uint64 default_uint64_extension   = 64 [default =  44    ];
-  optional   sint32 default_sint32_extension   = 65 [default = -45    ];
-  optional   sint64 default_sint64_extension   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32_extension  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64_extension  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32_extension = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64_extension = 70 [default = -50    ];
-  optional    float default_float_extension    = 71 [default =  51.5  ];
-  optional   double default_double_extension   = 72 [default =  52e3  ];
-  optional     bool default_bool_extension     = 73 [default = true   ];
-  optional   string default_string_extension   = 74 [default = "hello"];
-  optional    bytes default_bytes_extension    = 75 [default = "world"];
-
-  optional TestAllTypes.NestedEnum
-    default_nested_enum_extension = 81 [default = BAR];
-  optional ForeignEnum
-    default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
-  optional protobuf_unittest_import.ImportEnum
-    default_import_enum_extension = 83 [default = IMPORT_BAR];
-
-  optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
-                                                       default="abc"];
-  optional string default_cord_extension = 85 [ctype=CORD, default="123"];
-}
-
-message TestNestedExtension {
-  extend TestAllExtensions {
-    // Check for bug where string extensions declared in tested scope did not
-    // compile.
-    optional string test = 1002 [default="test"];
-  }
-}
-
-// We have separate messages for testing required fields because it's
-// annoying to have to fill in required fields in TestProto in order to
-// do anything with it.  Note that we don't need to test every type of
-// required filed because the code output is basically identical to
-// optional fields for all types.
-message TestRequired {
-  required int32 a = 1;
-  optional int32 dummy2 = 2;
-  required int32 b = 3;
-
-  extend TestAllExtensions {
-    optional TestRequired single = 1000;
-    repeated TestRequired multi  = 1001;
-  }
-
-  // Pad the field count to 32 so that we can test that IsInitialized()
-  // properly checks multiple elements of has_bits_.
-  optional int32 dummy4  =  4;
-  optional int32 dummy5  =  5;
-  optional int32 dummy6  =  6;
-  optional int32 dummy7  =  7;
-  optional int32 dummy8  =  8;
-  optional int32 dummy9  =  9;
-  optional int32 dummy10 = 10;
-  optional int32 dummy11 = 11;
-  optional int32 dummy12 = 12;
-  optional int32 dummy13 = 13;
-  optional int32 dummy14 = 14;
-  optional int32 dummy15 = 15;
-  optional int32 dummy16 = 16;
-  optional int32 dummy17 = 17;
-  optional int32 dummy18 = 18;
-  optional int32 dummy19 = 19;
-  optional int32 dummy20 = 20;
-  optional int32 dummy21 = 21;
-  optional int32 dummy22 = 22;
-  optional int32 dummy23 = 23;
-  optional int32 dummy24 = 24;
-  optional int32 dummy25 = 25;
-  optional int32 dummy26 = 26;
-  optional int32 dummy27 = 27;
-  optional int32 dummy28 = 28;
-  optional int32 dummy29 = 29;
-  optional int32 dummy30 = 30;
-  optional int32 dummy31 = 31;
-  optional int32 dummy32 = 32;
-
-  required int32 c = 33;
-}
-
-message TestRequiredForeign {
-  optional TestRequired optional_message = 1;
-  repeated TestRequired repeated_message = 2;
-  optional int32 dummy = 3;
-}
-
-// Test that we can use NestedMessage from outside TestAllTypes.
-message TestForeignNested {
-  optional TestAllTypes.NestedMessage foreign_nested = 1;
-}
-
-// TestEmptyMessage is used to test unknown field support.
-message TestEmptyMessage {
-}
-
-// Like above, but declare all field numbers as potential extensions.  No
-// actual extensions should ever be defined for this type.
-message TestEmptyMessageWithExtensions {
-  extensions 1 to max;
-}
-
-message TestMultipleExtensionRanges {
-  extensions 42;
-  extensions 4143 to 4243;
-  extensions 65536 to max;
-}
-
-// Test that really large tag numbers don't break anything.
-message TestReallyLargeTagNumber {
-  // The largest possible tag number is 2^28 - 1, since the wire format uses
-  // three bits to communicate wire type.
-  optional int32 a = 1;
-  optional int32 bb = 268435455;
-}
-
-message TestRecursiveMessage {
-  optional TestRecursiveMessage a = 1;
-  optional int32 i = 2;
-}
-
-// Test that mutual recursion works.
-message TestMutualRecursionA {
-  optional TestMutualRecursionB bb = 1;
-}
-
-message TestMutualRecursionB {
-  optional TestMutualRecursionA a = 1;
-  optional int32 optional_int32 = 2;
-}
-
-// Test that groups have disjoint field numbers from their siblings and
-// parents.  This is NOT possible in proto1; only proto2.  When attempting
-// to compile with proto1, this will emit an error; so we only include it
-// in protobuf_unittest_proto.
-message TestDupFieldNumber {                        // NO_PROTO1
-  optional int32 a = 1;                             // NO_PROTO1
-  optional group Foo = 2 { optional int32 a = 1; }  // NO_PROTO1
-  optional group Bar = 3 { optional int32 a = 1; }  // NO_PROTO1
-}                                                   // NO_PROTO1
-
-// Additional messages for testing lazy fields.
-message TestEagerMessage {
-  optional TestAllTypes sub_message = 1 [lazy=false];
-}
-message TestLazyMessage {
-  optional TestAllTypes sub_message = 1 [lazy=true];
-}
-
-// Needed for a Python test.
-message TestNestedMessageHasBits {
-  message NestedMessage {
-    repeated int32 nestedmessage_repeated_int32 = 1;
-    repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
-  }
-  optional NestedMessage optional_nested_message = 1;
-}
-
-
-// Test an enum that has multiple values with the same number.
-enum TestEnumWithDupValue {
-  option allow_alias = true;
-  FOO1 = 1;
-  BAR1 = 2;
-  BAZ = 3;
-  FOO2 = 1;
-  BAR2 = 2;
-}
-
-// Test an enum with large, unordered values.
-enum TestSparseEnum {
-  SPARSE_A = 123;
-  SPARSE_B = 62374;
-  SPARSE_C = 12589234;
-  SPARSE_D = -15;
-  SPARSE_E = -53452;
-  SPARSE_F = 0;
-  SPARSE_G = 2;
-}
-
-// Test message with CamelCase field names.  This violates Protocol Buffer
-// standard style.
-message TestCamelCaseFieldNames {
-  optional int32 PrimitiveField = 1;
-  optional string StringField = 2;
-  optional ForeignEnum EnumField = 3;
-  optional ForeignMessage MessageField = 4;
-  optional string StringPieceField = 5 [ctype=STRING_PIECE];
-  optional string CordField = 6 [ctype=CORD];
-
-  repeated int32 RepeatedPrimitiveField = 7;
-  repeated string RepeatedStringField = 8;
-  repeated ForeignEnum RepeatedEnumField = 9;
-  repeated ForeignMessage RepeatedMessageField = 10;
-  repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
-  repeated string RepeatedCordField = 12 [ctype=CORD];
-}
-
-
-// We list fields out of order, to ensure that we're using field number and not
-// field index to determine serialization order.
-message TestFieldOrderings {
-  optional string my_string = 11;
-  extensions 2 to 10;
-  optional int64 my_int = 1;
-  extensions 12 to 100;
-  optional float my_float = 101;
-}
-
-
-extend TestFieldOrderings {
-  optional string my_extension_string = 50;
-  optional int32 my_extension_int = 5;
-}
-
-
-message TestExtremeDefaultValues {
-  optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
-  optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
-  optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
-  optional  int32 small_int32  = 4 [default = -0x7FFFFFFF];
-  optional  int64 small_int64  = 5 [default = -0x7FFFFFFFFFFFFFFF];
-  optional  int32 really_small_int32 = 21 [default = -0x80000000];
-  optional  int64 really_small_int64 = 22 [default = -0x8000000000000000];
-
-  // The default value here is UTF-8 for "\u1234".  (We could also just type
-  // the UTF-8 text directly into this text file rather than escape it, but
-  // lots of people use editors that would be confused by this.)
-  optional string utf8_string = 6 [default = "\341\210\264"];
-
-  // Tests for single-precision floating-point values.
-  optional float zero_float = 7 [default = 0];
-  optional float one_float = 8 [default = 1];
-  optional float small_float = 9 [default = 1.5];
-  optional float negative_one_float = 10 [default = -1];
-  optional float negative_float = 11 [default = -1.5];
-  // Using exponents
-  optional float large_float = 12 [default = 2E8];
-  optional float small_negative_float = 13 [default = -8e-28];
-
-  // Text for nonfinite floating-point values.
-  optional double inf_double = 14 [default = inf];
-  optional double neg_inf_double = 15 [default = -inf];
-  optional double nan_double = 16 [default = nan];
-  optional float inf_float = 17 [default = inf];
-  optional float neg_inf_float = 18 [default = -inf];
-  optional float nan_float = 19 [default = nan];
-
-  // Tests for C++ trigraphs.
-  // Trigraphs should be escaped in C++ generated files, but they should not be
-  // escaped for other languages.
-  // Note that in .proto file, "\?" is a valid way to escape ? in string
-  // literals.
-  optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
-
-  // String defaults containing the character '\000'
-  optional string string_with_zero       = 23 [default = "hel\000lo"];
-  optional  bytes bytes_with_zero        = 24 [default = "wor\000ld"];
-  optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
-                                               default="ab\000c"];
-  optional string cord_with_zero         = 26 [ctype=CORD,
-                                               default="12\0003"];
-}
-
-message SparseEnumMessage {
-  optional TestSparseEnum sparse_enum = 1;
-}
-
-// Test String and Bytes: string is for valid UTF-8 strings
-message OneString {
-  optional string data = 1;
-}
-
-message MoreString {
-  repeated string data = 1;
-}
-
-message OneBytes {
-  optional bytes data = 1;
-}
-
-message MoreBytes {
-  repeated bytes data = 1;
-}
-
-
-// Test messages for packed fields
-
-message TestPackedTypes {
-  repeated    int32 packed_int32    =  90 [packed = true];
-  repeated    int64 packed_int64    =  91 [packed = true];
-  repeated   uint32 packed_uint32   =  92 [packed = true];
-  repeated   uint64 packed_uint64   =  93 [packed = true];
-  repeated   sint32 packed_sint32   =  94 [packed = true];
-  repeated   sint64 packed_sint64   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
-  repeated    float packed_float    = 100 [packed = true];
-  repeated   double packed_double   = 101 [packed = true];
-  repeated     bool packed_bool     = 102 [packed = true];
-  repeated ForeignEnum packed_enum  = 103 [packed = true];
-}
-
-// A message with the same fields as TestPackedTypes, but without packing. Used
-// to test packed <-> unpacked wire compatibility.
-message TestUnpackedTypes {
-  repeated    int32 unpacked_int32    =  90 [packed = false];
-  repeated    int64 unpacked_int64    =  91 [packed = false];
-  repeated   uint32 unpacked_uint32   =  92 [packed = false];
-  repeated   uint64 unpacked_uint64   =  93 [packed = false];
-  repeated   sint32 unpacked_sint32   =  94 [packed = false];
-  repeated   sint64 unpacked_sint64   =  95 [packed = false];
-  repeated  fixed32 unpacked_fixed32  =  96 [packed = false];
-  repeated  fixed64 unpacked_fixed64  =  97 [packed = false];
-  repeated sfixed32 unpacked_sfixed32 =  98 [packed = false];
-  repeated sfixed64 unpacked_sfixed64 =  99 [packed = false];
-  repeated    float unpacked_float    = 100 [packed = false];
-  repeated   double unpacked_double   = 101 [packed = false];
-  repeated     bool unpacked_bool     = 102 [packed = false];
-  repeated ForeignEnum unpacked_enum  = 103 [packed = false];
-}
-
-message TestPackedExtensions {
-  extensions 1 to max;
-}
-
-extend TestPackedExtensions {
-  repeated    int32 packed_int32_extension    =  90 [packed = true];
-  repeated    int64 packed_int64_extension    =  91 [packed = true];
-  repeated   uint32 packed_uint32_extension   =  92 [packed = true];
-  repeated   uint64 packed_uint64_extension   =  93 [packed = true];
-  repeated   sint32 packed_sint32_extension   =  94 [packed = true];
-  repeated   sint64 packed_sint64_extension   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32_extension  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64_extension  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32_extension =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64_extension =  99 [packed = true];
-  repeated    float packed_float_extension    = 100 [packed = true];
-  repeated   double packed_double_extension   = 101 [packed = true];
-  repeated     bool packed_bool_extension     = 102 [packed = true];
-  repeated ForeignEnum packed_enum_extension  = 103 [packed = true];
-}
-
-// Used by ExtensionSetTest/DynamicExtensions.  The test actually builds
-// a set of extensions to TestAllExtensions dynamically, based on the fields
-// of this message type.
-message TestDynamicExtensions {
-  enum DynamicEnumType {
-    DYNAMIC_FOO = 2200;
-    DYNAMIC_BAR = 2201;
-    DYNAMIC_BAZ = 2202;
-  }
-  message DynamicMessageType {
-    optional int32 dynamic_field = 2100;
-  }
-
-  optional fixed32 scalar_extension = 2000;
-  optional ForeignEnum enum_extension = 2001;
-  optional DynamicEnumType dynamic_enum_extension = 2002;
-
-  optional ForeignMessage message_extension = 2003;
-  optional DynamicMessageType dynamic_message_extension = 2004;
-
-  repeated string repeated_extension = 2005;
-  repeated sint32 packed_extension = 2006 [packed = true];
-}
-
-message TestRepeatedScalarDifferentTagSizes {
-  // Parsing repeated fixed size values used to fail. This message needs to be
-  // used in order to get a tag of the right size; all of the repeated fields
-  // in TestAllTypes didn't trigger the check.
-  repeated fixed32 repeated_fixed32 = 12;
-  // Check for a varint type, just for good measure.
-  repeated int32   repeated_int32   = 13;
-
-  // These have two-byte tags.
-  repeated fixed64 repeated_fixed64 = 2046;
-  repeated int64   repeated_int64   = 2047;
-
-  // Three byte tags.
-  repeated float   repeated_float   = 262142;
-  repeated uint64  repeated_uint64  = 262143;
-}
-
-// Test that if an optional or required message/group field appears multiple
-// times in the input, they need to be merged.
-message TestParsingMerge {
-  // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
-  // except that all fields are repeated. In the tests, we will serialize the
-  // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
-  // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
-  // the corresponding required/optional fields in TestParsingMerge.
-  message RepeatedFieldsGenerator {
-    repeated TestAllTypes field1 = 1;
-    repeated TestAllTypes field2 = 2;
-    repeated TestAllTypes field3 = 3;
-    repeated group Group1 = 10 {
-      optional TestAllTypes field1 = 11;
-    }
-    repeated group Group2 = 20 {
-      optional TestAllTypes field1 = 21;
-    }
-    repeated TestAllTypes ext1 = 1000;
-    repeated TestAllTypes ext2 = 1001;
-  }
-  required TestAllTypes required_all_types = 1;
-  optional TestAllTypes optional_all_types = 2;
-  repeated TestAllTypes repeated_all_types = 3;
-  optional group OptionalGroup = 10 {
-    optional TestAllTypes optional_group_all_types = 11;
-  }
-  repeated group RepeatedGroup = 20 {
-    optional TestAllTypes repeated_group_all_types = 21;
-  }
-  extensions 1000 to max;
-  extend TestParsingMerge {
-    optional TestAllTypes optional_ext = 1000;
-    repeated TestAllTypes repeated_ext = 1001;
-  }
-}
-
-message TestCommentInjectionMessage {
-  // */ <- This should not close the generated doc comment
-  optional string a = 1 [default="*/ <- Neither should this."];
-}
-
-
-// Test that RPC services work.
-message FooRequest  {}
-message FooResponse {}
-
-message FooClientMessage {}
-message FooServerMessage{}
-
-service TestService {
-  rpc Foo(FooRequest) returns (FooResponse);
-  rpc Bar(BarRequest) returns (BarResponse);
-}
-
-
-message BarRequest  {}
-message BarResponse {}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto
deleted file mode 100644
index 2f4e3fd..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto
+++ /dev/null
@@ -1,387 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: benjy@google.com (Benjy Weinberger)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file used to test the "custom options" feature of proto2.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;
-
-// A custom file option (defined below).
-option (file_opt1) = 9876543210;
-
-import "google/protobuf/descriptor.proto";
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-package protobuf_unittest;
-
-
-// Some simple test custom options of various types.
-
-extend google.protobuf.FileOptions {
-  optional uint64 file_opt1 = 7736974;
-}
-
-extend google.protobuf.MessageOptions {
-  optional int32 message_opt1 = 7739036;
-}
-
-extend google.protobuf.FieldOptions {
-  optional fixed64 field_opt1 = 7740936;
-  // This is useful for testing that we correctly register default values for
-  // extension options.
-  optional int32 field_opt2 = 7753913 [default=42];
-}
-
-extend google.protobuf.EnumOptions {
-  optional sfixed32 enum_opt1 = 7753576;
-}
-
-extend google.protobuf.EnumValueOptions {
-  optional int32 enum_value_opt1 = 1560678;
-}
-
-extend google.protobuf.ServiceOptions {
-  optional sint64 service_opt1 = 7887650;
-}
-
-enum MethodOpt1 {
-  METHODOPT1_VAL1 = 1;
-  METHODOPT1_VAL2 = 2;
-}
-
-extend google.protobuf.MethodOptions {
-  optional MethodOpt1 method_opt1 = 7890860;
-}
-
-// A test message with custom options at all possible locations (and also some
-// regular options, to make sure they interact nicely).
-message TestMessageWithCustomOptions {
-  option message_set_wire_format = false;
-
-  option (message_opt1) = -56;
-
-  optional string field1 = 1 [ctype=CORD,
-                              (field_opt1)=8765432109];
-
-  enum AnEnum {
-    option (enum_opt1) = -789;
-
-    ANENUM_VAL1 = 1;
-    ANENUM_VAL2 = 2 [(enum_value_opt1) = 123];
-  }
-}
-
-
-// A test RPC service with custom options at all possible locations (and also
-// some regular options, to make sure they interact nicely).
-message CustomOptionFooRequest {
-}
-
-message CustomOptionFooResponse {
-}
-
-message CustomOptionFooClientMessage {
-}
-
-message CustomOptionFooServerMessage {
-}
-
-service TestServiceWithCustomOptions {
-  option (service_opt1) = -9876543210;
-
-  rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) {
-    option (method_opt1) = METHODOPT1_VAL2;
-  }
-}
-
-
-
-// Options of every possible field type, so we can test them all exhaustively.
-
-message DummyMessageContainingEnum {
-  enum TestEnumType {
-    TEST_OPTION_ENUM_TYPE1 = 22;
-    TEST_OPTION_ENUM_TYPE2 = -23;
-  }
-}
-
-message DummyMessageInvalidAsOptionType {
-}
-
-extend google.protobuf.MessageOptions {
-  optional         bool     bool_opt = 7706090;
-  optional        int32    int32_opt = 7705709;
-  optional        int64    int64_opt = 7705542;
-  optional       uint32   uint32_opt = 7704880;
-  optional       uint64   uint64_opt = 7702367;
-  optional       sint32   sint32_opt = 7701568;
-  optional       sint64   sint64_opt = 7700863;
-  optional      fixed32  fixed32_opt = 7700307;
-  optional      fixed64  fixed64_opt = 7700194;
-  optional     sfixed32 sfixed32_opt = 7698645;
-  optional     sfixed64 sfixed64_opt = 7685475;
-  optional        float    float_opt = 7675390;
-  optional       double   double_opt = 7673293;
-  optional       string   string_opt = 7673285;
-  optional        bytes    bytes_opt = 7673238;
-  optional DummyMessageContainingEnum.TestEnumType enum_opt = 7673233;
-  optional DummyMessageInvalidAsOptionType message_type_opt = 7665967;
-}
-
-message CustomOptionMinIntegerValues {
-  option     (bool_opt) = false;
-  option    (int32_opt) = -0x80000000;
-  option    (int64_opt) = -0x8000000000000000;
-  option   (uint32_opt) = 0;
-  option   (uint64_opt) = 0;
-  option   (sint32_opt) = -0x80000000;
-  option   (sint64_opt) = -0x8000000000000000;
-  option  (fixed32_opt) = 0;
-  option  (fixed64_opt) = 0;
-  option (sfixed32_opt) = -0x80000000;
-  option (sfixed64_opt) = -0x8000000000000000;
-}
-
-message CustomOptionMaxIntegerValues {
-  option     (bool_opt) = true;
-  option    (int32_opt) = 0x7FFFFFFF;
-  option    (int64_opt) = 0x7FFFFFFFFFFFFFFF;
-  option   (uint32_opt) = 0xFFFFFFFF;
-  option   (uint64_opt) = 0xFFFFFFFFFFFFFFFF;
-  option   (sint32_opt) = 0x7FFFFFFF;
-  option   (sint64_opt) = 0x7FFFFFFFFFFFFFFF;
-  option  (fixed32_opt) = 0xFFFFFFFF;
-  option  (fixed64_opt) = 0xFFFFFFFFFFFFFFFF;
-  option (sfixed32_opt) = 0x7FFFFFFF;
-  option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF;
-}
-
-message CustomOptionOtherValues {
-  option  (int32_opt) = -100;  // To test sign-extension.
-  option  (float_opt) = 12.3456789;
-  option (double_opt) = 1.234567890123456789;
-  option (string_opt) = "Hello, \"World\"";
-  option  (bytes_opt) = "Hello\0World";
-  option   (enum_opt) = TEST_OPTION_ENUM_TYPE2;
-}
-
-message SettingRealsFromPositiveInts {
-  option  (float_opt) = 12;
-  option (double_opt) = 154;
-}
-
-message SettingRealsFromNegativeInts {
-  option  (float_opt) = -12;
-  option  (double_opt) = -154;
-}
-
-// Options of complex message types, themselves combined and extended in
-// various ways.
-
-message ComplexOptionType1 {
-  optional int32 foo = 1;
-  optional int32 foo2 = 2;
-  optional int32 foo3 = 3;
-
-  extensions 100 to max;
-}
-
-message ComplexOptionType2 {
-  optional ComplexOptionType1 bar = 1;
-  optional int32 baz = 2;
-
-  message ComplexOptionType4 {
-    optional int32 waldo = 1;
-
-    extend google.protobuf.MessageOptions {
-      optional ComplexOptionType4 complex_opt4 = 7633546;
-    }
-  }
-
-  optional ComplexOptionType4 fred = 3;
-
-  extensions 100 to max;
-}
-
-message ComplexOptionType3 {
-  optional int32 qux = 1;
-
-  optional group ComplexOptionType5 = 2 {
-    optional int32 plugh = 3;
-  }
-}
-
-extend ComplexOptionType1 {
-  optional int32 quux = 7663707;
-  optional ComplexOptionType3 corge = 7663442;
-}
-
-extend ComplexOptionType2 {
-  optional int32 grault = 7650927;
-  optional ComplexOptionType1 garply = 7649992;
-}
-
-extend google.protobuf.MessageOptions {
-  optional protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756;
-  optional ComplexOptionType2 complex_opt2 = 7636949;
-  optional ComplexOptionType3 complex_opt3 = 7636463;
-  optional group ComplexOpt6 = 7595468 {
-    optional int32 xyzzy = 7593951;
-  }
-}
-
-// Note that we try various different ways of naming the same extension.
-message VariousComplexOptions {
-  option (.protobuf_unittest.complex_opt1).foo = 42;
-  option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324;
-  option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876;
-  option (complex_opt2).baz = 987;
-  option (complex_opt2).(grault) = 654;
-  option (complex_opt2).bar.foo = 743;
-  option (complex_opt2).bar.(quux) = 1999;
-  option (complex_opt2).bar.(protobuf_unittest.corge).qux = 2008;
-  option (complex_opt2).(garply).foo = 741;
-  option (complex_opt2).(garply).(.protobuf_unittest.quux) = 1998;
-  option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121;
-  option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971;
-  option (complex_opt2).fred.waldo = 321;
-  option (protobuf_unittest.complex_opt3).qux = 9;
-  option (complex_opt3).complexoptiontype5.plugh = 22;
-  option (complexopt6).xyzzy = 24;
-}
-
-// ------------------------------------------------------
-// Definitions for testing aggregate option parsing.
-// See descriptor_unittest.cc.
-
-message AggregateMessageSet {
-  option message_set_wire_format = true;
-  extensions 4 to max;
-}
-
-message AggregateMessageSetElement {
-  extend AggregateMessageSet {
-    optional AggregateMessageSetElement message_set_extension = 15447542;
-  }
-  optional string s = 1;
-}
-
-// A helper type used to test aggregate option parsing
-message Aggregate {
-  optional int32 i = 1;
-  optional string s = 2;
-
-  // A nested object
-  optional Aggregate sub = 3;
-
-  // To test the parsing of extensions inside aggregate values
-  optional google.protobuf.FileOptions file = 4;
-  extend google.protobuf.FileOptions {
-    optional Aggregate nested = 15476903;
-  }
-
-  // An embedded message set
-  optional AggregateMessageSet mset = 5;
-}
-
-// Allow Aggregate to be used as an option at all possible locations
-// in the .proto grammar.
-extend google.protobuf.FileOptions      { optional Aggregate fileopt    = 15478479; }
-extend google.protobuf.MessageOptions   { optional Aggregate msgopt     = 15480088; }
-extend google.protobuf.FieldOptions     { optional Aggregate fieldopt   = 15481374; }
-extend google.protobuf.EnumOptions      { optional Aggregate enumopt    = 15483218; }
-extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
-extend google.protobuf.ServiceOptions   { optional Aggregate serviceopt = 15497145; }
-extend google.protobuf.MethodOptions    { optional Aggregate methodopt  = 15512713; }
-
-// Try using AggregateOption at different points in the proto grammar
-option (fileopt) = {
-  s: 'FileAnnotation'
-  // Also test the handling of comments
-  /* of both types */ i: 100
-
-  sub { s: 'NestedFileAnnotation' }
-
-  // Include a google.protobuf.FileOptions and recursively extend it with
-  // another fileopt.
-  file {
-    [protobuf_unittest.fileopt] {
-      s:'FileExtensionAnnotation'
-    }
-  }
-
-  // A message set inside an option value
-  mset {
-    [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
-      s: 'EmbeddedMessageSetElement'
-    }
-  }
-};
-
-message AggregateMessage {
-  option (msgopt) = { i:101 s:'MessageAnnotation' };
-  optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
-}
-
-service AggregateService {
-  option (serviceopt) = { s:'ServiceAnnotation' };
-  rpc Method (AggregateMessage) returns (AggregateMessage) {
-    option (methodopt) = { s:'MethodAnnotation' };
-  }
-}
-
-enum AggregateEnum {
-  option (enumopt) = { s:'EnumAnnotation' };
-  VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
-}
-
-// Test custom options for nested type.
-message NestedOptionType {
-  message NestedMessage {
-    option (message_opt1) = 1001;
-    optional int32 nested_field = 1 [(field_opt1) = 1002];
-  }
-  enum NestedEnum {
-    option (enum_opt1) = 1003;
-    NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
-  }
-  extend google.protobuf.FileOptions {
-    optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
deleted file mode 100644
index fa17625..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
-
-import "google/protobuf/unittest_optimize_for.proto";
-
-package protobuf_unittest;
-
-// We optimize for speed here, but we are importing a proto that is optimized
-// for code size.
-option optimize_for = SPEED;
-
-message TestEmbedOptimizedForSize {
-  // Test that embedding a message which has optimize_for = CODE_SIZE into
-  // one optimized for speed works.
-  optional TestOptimizedForSize optional_message = 1;
-  repeated TestOptimizedForSize repeated_message = 2;
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_empty.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_empty.proto
deleted file mode 100644
index ab12d1f..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_empty.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// This file intentionally left blank.  (At one point this wouldn't compile
-// correctly.)
-
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
deleted file mode 100644
index bc0b7c1..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
+++ /dev/null
@@ -1,1046 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file that has an extremely large descriptor.  Used to test that
-// descriptors over 64k don't break the string literal length limit in Java.
-
-
-package google.protobuf;
-option java_package = "com.google.protobuf";
-
-// Avoid generating insanely long methods.
-option optimize_for = CODE_SIZE;
-
-message TestEnormousDescriptor {
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1 = 1 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_2 = 2 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_3 = 3 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_4 = 4 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_5 = 5 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_6 = 6 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_7 = 7 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_8 = 8 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_9 = 9 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_10 = 10 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_11 = 11 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_12 = 12 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_13 = 13 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_14 = 14 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_15 = 15 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_16 = 16 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_17 = 17 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_18 = 18 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_19 = 19 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_20 = 20 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_21 = 21 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_22 = 22 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_23 = 23 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_24 = 24 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_25 = 25 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_26 = 26 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_27 = 27 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_28 = 28 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_29 = 29 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_30 = 30 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_31 = 31 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_32 = 32 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_33 = 33 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_34 = 34 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_35 = 35 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_36 = 36 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_37 = 37 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_38 = 38 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_39 = 39 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_40 = 40 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_41 = 41 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_42 = 42 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_43 = 43 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_44 = 44 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_45 = 45 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_46 = 46 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_47 = 47 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_48 = 48 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_49 = 49 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_50 = 50 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_51 = 51 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_52 = 52 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_53 = 53 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_54 = 54 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_55 = 55 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_56 = 56 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_57 = 57 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_58 = 58 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_59 = 59 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_60 = 60 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_61 = 61 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_62 = 62 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_63 = 63 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_64 = 64 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_65 = 65 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_66 = 66 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_67 = 67 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_68 = 68 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_69 = 69 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_70 = 70 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_71 = 71 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_72 = 72 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_73 = 73 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_74 = 74 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_75 = 75 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_76 = 76 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_77 = 77 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_78 = 78 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_79 = 79 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_80 = 80 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_81 = 81 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_82 = 82 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_83 = 83 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_84 = 84 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_85 = 85 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_86 = 86 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_87 = 87 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_88 = 88 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_89 = 89 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_90 = 90 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_91 = 91 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_92 = 92 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_93 = 93 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_94 = 94 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_95 = 95 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_96 = 96 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_97 = 97 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_98 = 98 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_99 = 99 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_100 = 100 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_101 = 101 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_102 = 102 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_103 = 103 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_104 = 104 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_105 = 105 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_106 = 106 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_107 = 107 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_108 = 108 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_109 = 109 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_110 = 110 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_111 = 111 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_112 = 112 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_113 = 113 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_114 = 114 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_115 = 115 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_116 = 116 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_117 = 117 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_118 = 118 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_119 = 119 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_120 = 120 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_121 = 121 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_122 = 122 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_123 = 123 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_124 = 124 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_125 = 125 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_126 = 126 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_127 = 127 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_128 = 128 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_129 = 129 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_130 = 130 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_131 = 131 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_132 = 132 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_133 = 133 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_134 = 134 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_135 = 135 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_136 = 136 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_137 = 137 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_138 = 138 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_139 = 139 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_140 = 140 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_141 = 141 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_142 = 142 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_143 = 143 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_144 = 144 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_145 = 145 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_146 = 146 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_147 = 147 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_148 = 148 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_149 = 149 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_150 = 150 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_151 = 151 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_152 = 152 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_153 = 153 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_154 = 154 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_155 = 155 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_156 = 156 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_157 = 157 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_158 = 158 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_159 = 159 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_160 = 160 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_161 = 161 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_162 = 162 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_163 = 163 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_164 = 164 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_165 = 165 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_166 = 166 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_167 = 167 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_168 = 168 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_169 = 169 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_170 = 170 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_171 = 171 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_172 = 172 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_173 = 173 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_174 = 174 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_175 = 175 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_176 = 176 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_177 = 177 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_178 = 178 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_179 = 179 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_180 = 180 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_181 = 181 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_182 = 182 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_183 = 183 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_184 = 184 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_185 = 185 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_186 = 186 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_187 = 187 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_188 = 188 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_189 = 189 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_190 = 190 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_191 = 191 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_192 = 192 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_193 = 193 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_194 = 194 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_195 = 195 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_196 = 196 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_197 = 197 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_198 = 198 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_199 = 199 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_200 = 200 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_201 = 201 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_202 = 202 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_203 = 203 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_204 = 204 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_205 = 205 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_206 = 206 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_207 = 207 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_208 = 208 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_209 = 209 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_210 = 210 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_211 = 211 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_212 = 212 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_213 = 213 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_214 = 214 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_215 = 215 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_216 = 216 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_217 = 217 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_218 = 218 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_219 = 219 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_220 = 220 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_221 = 221 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_222 = 222 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_223 = 223 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_224 = 224 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_225 = 225 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_226 = 226 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_227 = 227 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_228 = 228 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_229 = 229 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_230 = 230 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_231 = 231 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_232 = 232 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_233 = 233 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_234 = 234 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_235 = 235 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_236 = 236 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_237 = 237 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_238 = 238 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_239 = 239 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_240 = 240 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_241 = 241 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_242 = 242 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_243 = 243 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_244 = 244 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_245 = 245 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_246 = 246 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_247 = 247 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_248 = 248 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_249 = 249 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_250 = 250 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_251 = 251 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_252 = 252 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_253 = 253 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_254 = 254 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_255 = 255 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_256 = 256 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_257 = 257 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_258 = 258 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_259 = 259 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_260 = 260 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_261 = 261 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_262 = 262 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_263 = 263 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_264 = 264 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_265 = 265 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_266 = 266 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_267 = 267 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_268 = 268 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_269 = 269 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_270 = 270 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_271 = 271 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_272 = 272 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_273 = 273 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_274 = 274 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_275 = 275 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_276 = 276 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_277 = 277 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_278 = 278 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_279 = 279 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_280 = 280 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_281 = 281 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_282 = 282 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_283 = 283 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_284 = 284 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_285 = 285 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_286 = 286 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_287 = 287 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_288 = 288 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_289 = 289 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_290 = 290 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_291 = 291 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_292 = 292 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_293 = 293 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_294 = 294 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_295 = 295 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_296 = 296 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_297 = 297 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_298 = 298 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_299 = 299 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_300 = 300 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_301 = 301 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_302 = 302 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_303 = 303 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_304 = 304 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_305 = 305 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_306 = 306 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_307 = 307 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_308 = 308 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_309 = 309 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_310 = 310 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_311 = 311 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_312 = 312 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_313 = 313 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_314 = 314 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_315 = 315 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_316 = 316 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_317 = 317 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_318 = 318 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_319 = 319 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_320 = 320 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_321 = 321 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_322 = 322 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_323 = 323 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_324 = 324 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_325 = 325 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_326 = 326 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_327 = 327 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_328 = 328 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_329 = 329 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_330 = 330 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_331 = 331 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_332 = 332 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_333 = 333 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_334 = 334 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_335 = 335 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_336 = 336 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_337 = 337 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_338 = 338 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_339 = 339 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_340 = 340 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_341 = 341 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_342 = 342 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_343 = 343 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_344 = 344 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_345 = 345 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_346 = 346 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_347 = 347 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_348 = 348 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_349 = 349 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_350 = 350 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_351 = 351 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_352 = 352 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_353 = 353 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_354 = 354 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_355 = 355 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_356 = 356 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_357 = 357 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_358 = 358 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_359 = 359 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_360 = 360 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_361 = 361 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_362 = 362 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_363 = 363 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_364 = 364 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_365 = 365 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_366 = 366 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_367 = 367 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_368 = 368 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_369 = 369 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_370 = 370 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_371 = 371 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_372 = 372 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_373 = 373 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_374 = 374 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_375 = 375 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_376 = 376 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_377 = 377 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_378 = 378 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_379 = 379 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_380 = 380 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_381 = 381 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_382 = 382 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_383 = 383 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_384 = 384 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_385 = 385 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_386 = 386 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_387 = 387 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_388 = 388 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_389 = 389 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_390 = 390 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_391 = 391 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_392 = 392 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_393 = 393 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_394 = 394 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_395 = 395 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_396 = 396 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_397 = 397 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_398 = 398 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_399 = 399 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_400 = 400 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_401 = 401 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_402 = 402 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_403 = 403 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_404 = 404 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_405 = 405 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_406 = 406 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_407 = 407 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_408 = 408 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_409 = 409 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_410 = 410 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_411 = 411 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_412 = 412 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_413 = 413 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_414 = 414 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_415 = 415 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_416 = 416 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_417 = 417 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_418 = 418 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_419 = 419 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_420 = 420 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_421 = 421 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_422 = 422 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_423 = 423 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_424 = 424 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_425 = 425 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_426 = 426 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_427 = 427 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_428 = 428 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_429 = 429 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_430 = 430 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_431 = 431 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_432 = 432 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_433 = 433 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_434 = 434 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_435 = 435 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_436 = 436 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_437 = 437 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_438 = 438 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_439 = 439 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_440 = 440 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_441 = 441 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_442 = 442 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_443 = 443 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_444 = 444 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_445 = 445 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_446 = 446 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_447 = 447 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_448 = 448 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_449 = 449 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_450 = 450 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_451 = 451 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_452 = 452 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_453 = 453 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_454 = 454 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_455 = 455 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_456 = 456 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_457 = 457 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_458 = 458 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_459 = 459 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_460 = 460 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_461 = 461 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_462 = 462 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_463 = 463 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_464 = 464 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_465 = 465 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_466 = 466 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_467 = 467 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_468 = 468 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_469 = 469 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_470 = 470 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_471 = 471 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_472 = 472 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_473 = 473 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_474 = 474 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_475 = 475 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_476 = 476 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_477 = 477 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_478 = 478 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_479 = 479 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_480 = 480 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_481 = 481 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_482 = 482 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_483 = 483 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_484 = 484 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_485 = 485 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_486 = 486 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_487 = 487 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_488 = 488 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_489 = 489 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_490 = 490 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_491 = 491 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_492 = 492 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_493 = 493 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_494 = 494 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_495 = 495 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_496 = 496 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_497 = 497 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_498 = 498 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_499 = 499 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_500 = 500 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_501 = 501 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_502 = 502 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_503 = 503 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_504 = 504 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_505 = 505 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_506 = 506 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_507 = 507 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_508 = 508 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_509 = 509 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_510 = 510 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_511 = 511 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_512 = 512 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_513 = 513 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_514 = 514 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_515 = 515 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_516 = 516 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_517 = 517 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_518 = 518 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_519 = 519 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_520 = 520 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_521 = 521 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_522 = 522 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_523 = 523 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_524 = 524 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_525 = 525 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_526 = 526 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_527 = 527 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_528 = 528 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_529 = 529 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_530 = 530 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_531 = 531 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_532 = 532 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_533 = 533 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_534 = 534 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_535 = 535 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_536 = 536 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_537 = 537 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_538 = 538 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_539 = 539 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_540 = 540 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_541 = 541 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_542 = 542 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_543 = 543 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_544 = 544 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_545 = 545 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_546 = 546 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_547 = 547 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_548 = 548 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_549 = 549 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_550 = 550 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_551 = 551 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_552 = 552 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_553 = 553 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_554 = 554 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_555 = 555 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_556 = 556 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_557 = 557 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_558 = 558 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_559 = 559 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_560 = 560 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_561 = 561 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_562 = 562 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_563 = 563 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_564 = 564 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_565 = 565 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_566 = 566 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_567 = 567 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_568 = 568 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_569 = 569 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_570 = 570 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_571 = 571 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_572 = 572 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_573 = 573 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_574 = 574 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_575 = 575 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_576 = 576 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_577 = 577 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_578 = 578 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_579 = 579 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_580 = 580 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_581 = 581 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_582 = 582 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_583 = 583 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_584 = 584 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_585 = 585 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_586 = 586 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_587 = 587 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_588 = 588 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_589 = 589 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_590 = 590 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_591 = 591 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_592 = 592 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_593 = 593 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_594 = 594 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_595 = 595 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_596 = 596 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_597 = 597 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_598 = 598 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_599 = 599 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_600 = 600 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_601 = 601 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_602 = 602 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_603 = 603 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_604 = 604 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_605 = 605 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_606 = 606 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_607 = 607 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_608 = 608 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_609 = 609 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_610 = 610 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_611 = 611 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_612 = 612 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_613 = 613 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_614 = 614 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_615 = 615 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_616 = 616 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_617 = 617 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_618 = 618 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_619 = 619 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_620 = 620 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_621 = 621 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_622 = 622 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_623 = 623 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_624 = 624 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_625 = 625 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_626 = 626 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_627 = 627 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_628 = 628 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_629 = 629 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_630 = 630 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_631 = 631 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_632 = 632 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_633 = 633 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_634 = 634 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_635 = 635 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_636 = 636 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_637 = 637 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_638 = 638 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_639 = 639 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_640 = 640 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_641 = 641 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_642 = 642 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_643 = 643 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_644 = 644 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_645 = 645 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_646 = 646 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_647 = 647 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_648 = 648 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_649 = 649 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_650 = 650 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_651 = 651 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_652 = 652 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_653 = 653 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_654 = 654 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_655 = 655 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_656 = 656 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_657 = 657 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_658 = 658 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_659 = 659 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_660 = 660 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_661 = 661 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_662 = 662 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_663 = 663 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_664 = 664 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_665 = 665 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_666 = 666 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_667 = 667 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_668 = 668 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_669 = 669 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_670 = 670 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_671 = 671 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_672 = 672 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_673 = 673 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_674 = 674 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_675 = 675 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_676 = 676 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_677 = 677 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_678 = 678 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_679 = 679 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_680 = 680 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_681 = 681 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_682 = 682 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_683 = 683 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_684 = 684 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_685 = 685 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_686 = 686 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_687 = 687 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_688 = 688 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_689 = 689 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_690 = 690 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_691 = 691 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_692 = 692 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_693 = 693 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_694 = 694 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_695 = 695 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_696 = 696 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_697 = 697 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_698 = 698 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_699 = 699 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_700 = 700 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_701 = 701 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_702 = 702 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_703 = 703 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_704 = 704 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_705 = 705 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_706 = 706 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_707 = 707 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_708 = 708 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_709 = 709 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_710 = 710 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_711 = 711 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_712 = 712 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_713 = 713 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_714 = 714 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_715 = 715 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_716 = 716 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_717 = 717 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_718 = 718 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_719 = 719 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_720 = 720 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_721 = 721 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_722 = 722 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_723 = 723 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_724 = 724 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_725 = 725 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_726 = 726 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_727 = 727 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_728 = 728 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_729 = 729 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_730 = 730 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_731 = 731 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_732 = 732 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_733 = 733 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_734 = 734 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_735 = 735 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_736 = 736 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_737 = 737 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_738 = 738 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_739 = 739 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_740 = 740 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_741 = 741 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_742 = 742 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_743 = 743 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_744 = 744 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_745 = 745 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_746 = 746 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_747 = 747 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_748 = 748 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_749 = 749 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_750 = 750 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_751 = 751 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_752 = 752 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_753 = 753 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_754 = 754 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_755 = 755 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_756 = 756 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_757 = 757 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_758 = 758 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_759 = 759 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_760 = 760 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_761 = 761 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_762 = 762 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_763 = 763 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_764 = 764 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_765 = 765 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_766 = 766 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_767 = 767 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_768 = 768 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_769 = 769 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_770 = 770 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_771 = 771 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_772 = 772 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_773 = 773 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_774 = 774 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_775 = 775 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_776 = 776 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_777 = 777 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_778 = 778 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_779 = 779 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_780 = 780 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_781 = 781 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_782 = 782 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_783 = 783 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_784 = 784 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_785 = 785 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_786 = 786 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_787 = 787 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_788 = 788 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_789 = 789 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_790 = 790 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_791 = 791 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_792 = 792 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_793 = 793 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_794 = 794 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_795 = 795 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_796 = 796 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_797 = 797 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_798 = 798 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_799 = 799 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_800 = 800 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_801 = 801 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_802 = 802 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_803 = 803 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_804 = 804 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_805 = 805 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_806 = 806 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_807 = 807 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_808 = 808 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_809 = 809 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_810 = 810 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_811 = 811 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_812 = 812 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_813 = 813 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_814 = 814 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_815 = 815 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_816 = 816 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_817 = 817 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_818 = 818 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_819 = 819 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_820 = 820 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_821 = 821 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_822 = 822 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_823 = 823 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_824 = 824 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_825 = 825 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_826 = 826 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_827 = 827 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_828 = 828 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_829 = 829 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_830 = 830 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_831 = 831 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_832 = 832 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_833 = 833 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_834 = 834 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_835 = 835 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_836 = 836 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_837 = 837 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_838 = 838 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_839 = 839 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_840 = 840 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_841 = 841 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_842 = 842 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_843 = 843 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_844 = 844 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_845 = 845 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_846 = 846 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_847 = 847 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_848 = 848 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_849 = 849 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_850 = 850 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_851 = 851 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_852 = 852 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_853 = 853 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_854 = 854 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_855 = 855 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_856 = 856 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_857 = 857 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_858 = 858 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_859 = 859 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_860 = 860 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_861 = 861 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_862 = 862 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_863 = 863 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_864 = 864 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_865 = 865 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_866 = 866 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_867 = 867 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_868 = 868 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_869 = 869 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_870 = 870 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_871 = 871 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_872 = 872 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_873 = 873 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_874 = 874 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_875 = 875 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_876 = 876 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_877 = 877 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_878 = 878 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_879 = 879 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_880 = 880 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_881 = 881 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_882 = 882 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_883 = 883 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_884 = 884 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_885 = 885 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_886 = 886 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_887 = 887 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_888 = 888 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_889 = 889 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_890 = 890 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_891 = 891 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_892 = 892 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_893 = 893 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_894 = 894 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_895 = 895 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_896 = 896 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_897 = 897 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_898 = 898 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_899 = 899 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_900 = 900 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_901 = 901 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_902 = 902 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_903 = 903 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_904 = 904 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_905 = 905 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_906 = 906 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_907 = 907 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_908 = 908 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_909 = 909 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_910 = 910 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_911 = 911 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_912 = 912 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_913 = 913 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_914 = 914 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_915 = 915 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_916 = 916 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_917 = 917 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_918 = 918 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_919 = 919 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_920 = 920 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_921 = 921 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_922 = 922 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_923 = 923 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_924 = 924 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_925 = 925 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_926 = 926 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_927 = 927 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_928 = 928 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_929 = 929 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_930 = 930 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_931 = 931 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_932 = 932 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_933 = 933 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_934 = 934 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_935 = 935 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_936 = 936 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_937 = 937 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_938 = 938 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_939 = 939 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_940 = 940 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_941 = 941 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_942 = 942 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_943 = 943 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_944 = 944 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_945 = 945 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_946 = 946 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_947 = 947 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_948 = 948 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_949 = 949 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_950 = 950 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_951 = 951 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_952 = 952 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_953 = 953 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_954 = 954 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_955 = 955 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_956 = 956 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_957 = 957 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_958 = 958 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_959 = 959 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_960 = 960 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_961 = 961 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_962 = 962 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_963 = 963 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_964 = 964 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_965 = 965 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_966 = 966 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_967 = 967 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_968 = 968 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_969 = 969 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_970 = 970 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_971 = 971 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_972 = 972 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_973 = 973 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_974 = 974 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_975 = 975 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_976 = 976 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_977 = 977 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_978 = 978 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_979 = 979 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_980 = 980 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_981 = 981 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_982 = 982 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_983 = 983 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_984 = 984 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_985 = 985 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_986 = 986 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_987 = 987 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_988 = 988 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_989 = 989 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_990 = 990 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_991 = 991 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_992 = 992 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_993 = 993 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_994 = 994 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_995 = 995 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_996 = 996 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_997 = 997 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_998 = 998 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_999 = 999 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-  optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000 = 1000 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto
deleted file mode 100644
index ec36cca..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto
+++ /dev/null
@@ -1,64 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file which is imported by unittest.proto to test importing.
-
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do
-// "using namespace unittest_import = protobuf_unittest_import".
-package protobuf_unittest_import;
-
-option optimize_for = SPEED;
-
-// Exercise the java_package option.
-option java_package = "com.google.protobuf.test";
-
-// Do not set a java_outer_classname here to verify that Proto2 works without
-// one.
-
-// Test public import
-import public "google/protobuf/unittest_import_public.proto";
-
-message ImportMessage {
-  optional int32 d = 1;
-}
-
-enum ImportEnum {
-  IMPORT_FOO = 7;
-  IMPORT_BAR = 8;
-  IMPORT_BAZ = 9;
-}
-
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_lite.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_lite.proto
deleted file mode 100644
index 81b117f..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_lite.proto
+++ /dev/null
@@ -1,51 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
-
-package protobuf_unittest_import;
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.protobuf";
-
-import public "google/protobuf/unittest_import_public_lite.proto";
-
-message ImportMessageLite {
-  optional int32 d = 1;
-}
-
-enum ImportEnumLite {
-  IMPORT_LITE_FOO = 7;
-  IMPORT_LITE_BAR = 8;
-  IMPORT_LITE_BAZ = 9;
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto
deleted file mode 100644
index ea5d1b1..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto
+++ /dev/null
@@ -1,40 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: liujisi@google.com (Pherl Liu)
-
-
-package protobuf_unittest_import;
-
-option java_package = "com.google.protobuf.test";
-
-message PublicImportMessage {
-  optional int32 e = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public_lite.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public_lite.proto
deleted file mode 100644
index d077563..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public_lite.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: liujisi@google.com (Pherl Liu)
-
-
-package protobuf_unittest_import;
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.protobuf";
-
-message PublicImportMessageLite {
-  optional int32 e = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite.proto
deleted file mode 100644
index a1764aa..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite.proto
+++ /dev/null
@@ -1,360 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// This is like unittest.proto but with optimize_for = LITE_RUNTIME.
-
-package protobuf_unittest;
-
-import "google/protobuf/unittest_import_lite.proto";
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.protobuf";
-
-// Same as TestAllTypes but with the lite runtime.
-message TestAllTypesLite {
-  message NestedMessage {
-    optional int32 bb = 1;
-  }
-
-  enum NestedEnum {
-    FOO = 1;
-    BAR = 2;
-    BAZ = 3;
-  }
-
-  // Singular
-  optional    int32 optional_int32    =  1;
-  optional    int64 optional_int64    =  2;
-  optional   uint32 optional_uint32   =  3;
-  optional   uint64 optional_uint64   =  4;
-  optional   sint32 optional_sint32   =  5;
-  optional   sint64 optional_sint64   =  6;
-  optional  fixed32 optional_fixed32  =  7;
-  optional  fixed64 optional_fixed64  =  8;
-  optional sfixed32 optional_sfixed32 =  9;
-  optional sfixed64 optional_sfixed64 = 10;
-  optional    float optional_float    = 11;
-  optional   double optional_double   = 12;
-  optional     bool optional_bool     = 13;
-  optional   string optional_string   = 14;
-  optional    bytes optional_bytes    = 15;
-
-  optional group OptionalGroup = 16 {
-    optional int32 a = 17;
-  }
-
-  optional NestedMessage      optional_nested_message  = 18;
-  optional ForeignMessageLite optional_foreign_message = 19;
-  optional protobuf_unittest_import.ImportMessageLite
-    optional_import_message = 20;
-
-  optional NestedEnum      optional_nested_enum     = 21;
-  optional ForeignEnumLite optional_foreign_enum    = 22;
-  optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23;
-
-  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
-  optional string optional_cord = 25 [ctype=CORD];
-
-  // Defined in unittest_import_public.proto
-  optional protobuf_unittest_import.PublicImportMessageLite
-      optional_public_import_message = 26;
-
-  optional NestedMessage optional_lazy_message = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32    = 31;
-  repeated    int64 repeated_int64    = 32;
-  repeated   uint32 repeated_uint32   = 33;
-  repeated   uint64 repeated_uint64   = 34;
-  repeated   sint32 repeated_sint32   = 35;
-  repeated   sint64 repeated_sint64   = 36;
-  repeated  fixed32 repeated_fixed32  = 37;
-  repeated  fixed64 repeated_fixed64  = 38;
-  repeated sfixed32 repeated_sfixed32 = 39;
-  repeated sfixed64 repeated_sfixed64 = 40;
-  repeated    float repeated_float    = 41;
-  repeated   double repeated_double   = 42;
-  repeated     bool repeated_bool     = 43;
-  repeated   string repeated_string   = 44;
-  repeated    bytes repeated_bytes    = 45;
-
-  repeated group RepeatedGroup = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated NestedMessage      repeated_nested_message  = 48;
-  repeated ForeignMessageLite repeated_foreign_message = 49;
-  repeated protobuf_unittest_import.ImportMessageLite
-    repeated_import_message = 50;
-
-  repeated NestedEnum      repeated_nested_enum  = 51;
-  repeated ForeignEnumLite repeated_foreign_enum = 52;
-  repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53;
-
-  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord = 55 [ctype=CORD];
-
-  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32    = 61 [default =  41    ];
-  optional    int64 default_int64    = 62 [default =  42    ];
-  optional   uint32 default_uint32   = 63 [default =  43    ];
-  optional   uint64 default_uint64   = 64 [default =  44    ];
-  optional   sint32 default_sint32   = 65 [default = -45    ];
-  optional   sint64 default_sint64   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
-  optional    float default_float    = 71 [default =  51.5  ];
-  optional   double default_double   = 72 [default =  52e3  ];
-  optional     bool default_bool     = 73 [default = true   ];
-  optional   string default_string   = 74 [default = "hello"];
-  optional    bytes default_bytes    = 75 [default = "world"];
-
-  optional NestedEnum default_nested_enum = 81 [default = BAR];
-  optional ForeignEnumLite default_foreign_enum = 82
-      [default = FOREIGN_LITE_BAR];
-  optional protobuf_unittest_import.ImportEnumLite
-      default_import_enum = 83 [default = IMPORT_LITE_BAR];
-
-  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
-  optional string default_cord = 85 [ctype=CORD,default="123"];
-}
-
-message ForeignMessageLite {
-  optional int32 c = 1;
-}
-
-enum ForeignEnumLite {
-  FOREIGN_LITE_FOO = 4;
-  FOREIGN_LITE_BAR = 5;
-  FOREIGN_LITE_BAZ = 6;
-}
-
-message TestPackedTypesLite {
-  repeated    int32 packed_int32    =  90 [packed = true];
-  repeated    int64 packed_int64    =  91 [packed = true];
-  repeated   uint32 packed_uint32   =  92 [packed = true];
-  repeated   uint64 packed_uint64   =  93 [packed = true];
-  repeated   sint32 packed_sint32   =  94 [packed = true];
-  repeated   sint64 packed_sint64   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
-  repeated    float packed_float    = 100 [packed = true];
-  repeated   double packed_double   = 101 [packed = true];
-  repeated     bool packed_bool     = 102 [packed = true];
-  repeated ForeignEnumLite packed_enum  = 103 [packed = true];
-}
-
-message TestAllExtensionsLite {
-  extensions 1 to max;
-}
-
-extend TestAllExtensionsLite {
-  // Singular
-  optional    int32 optional_int32_extension_lite    =  1;
-  optional    int64 optional_int64_extension_lite    =  2;
-  optional   uint32 optional_uint32_extension_lite   =  3;
-  optional   uint64 optional_uint64_extension_lite   =  4;
-  optional   sint32 optional_sint32_extension_lite   =  5;
-  optional   sint64 optional_sint64_extension_lite   =  6;
-  optional  fixed32 optional_fixed32_extension_lite  =  7;
-  optional  fixed64 optional_fixed64_extension_lite  =  8;
-  optional sfixed32 optional_sfixed32_extension_lite =  9;
-  optional sfixed64 optional_sfixed64_extension_lite = 10;
-  optional    float optional_float_extension_lite    = 11;
-  optional   double optional_double_extension_lite   = 12;
-  optional     bool optional_bool_extension_lite     = 13;
-  optional   string optional_string_extension_lite   = 14;
-  optional    bytes optional_bytes_extension_lite    = 15;
-
-  optional group OptionalGroup_extension_lite = 16 {
-    optional int32 a = 17;
-  }
-
-  optional TestAllTypesLite.NestedMessage optional_nested_message_extension_lite
-      = 18;
-  optional ForeignMessageLite optional_foreign_message_extension_lite = 19;
-  optional protobuf_unittest_import.ImportMessageLite
-    optional_import_message_extension_lite = 20;
-
-  optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21;
-  optional ForeignEnumLite optional_foreign_enum_extension_lite = 22;
-  optional protobuf_unittest_import.ImportEnumLite
-    optional_import_enum_extension_lite = 23;
-
-  optional string optional_string_piece_extension_lite = 24
-      [ctype=STRING_PIECE];
-  optional string optional_cord_extension_lite = 25 [ctype=CORD];
-
-  optional protobuf_unittest_import.PublicImportMessageLite
-    optional_public_import_message_extension_lite = 26;
-
-  optional TestAllTypesLite.NestedMessage
-    optional_lazy_message_extension_lite = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32_extension_lite    = 31;
-  repeated    int64 repeated_int64_extension_lite    = 32;
-  repeated   uint32 repeated_uint32_extension_lite   = 33;
-  repeated   uint64 repeated_uint64_extension_lite   = 34;
-  repeated   sint32 repeated_sint32_extension_lite   = 35;
-  repeated   sint64 repeated_sint64_extension_lite   = 36;
-  repeated  fixed32 repeated_fixed32_extension_lite  = 37;
-  repeated  fixed64 repeated_fixed64_extension_lite  = 38;
-  repeated sfixed32 repeated_sfixed32_extension_lite = 39;
-  repeated sfixed64 repeated_sfixed64_extension_lite = 40;
-  repeated    float repeated_float_extension_lite    = 41;
-  repeated   double repeated_double_extension_lite   = 42;
-  repeated     bool repeated_bool_extension_lite     = 43;
-  repeated   string repeated_string_extension_lite   = 44;
-  repeated    bytes repeated_bytes_extension_lite    = 45;
-
-  repeated group RepeatedGroup_extension_lite = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite
-      = 48;
-  repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49;
-  repeated protobuf_unittest_import.ImportMessageLite
-    repeated_import_message_extension_lite = 50;
-
-  repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51;
-  repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52;
-  repeated protobuf_unittest_import.ImportEnumLite
-    repeated_import_enum_extension_lite = 53;
-
-  repeated string repeated_string_piece_extension_lite = 54
-      [ctype=STRING_PIECE];
-  repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
-
-  repeated TestAllTypesLite.NestedMessage
-    repeated_lazy_message_extension_lite = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32_extension_lite    = 61 [default =  41    ];
-  optional    int64 default_int64_extension_lite    = 62 [default =  42    ];
-  optional   uint32 default_uint32_extension_lite   = 63 [default =  43    ];
-  optional   uint64 default_uint64_extension_lite   = 64 [default =  44    ];
-  optional   sint32 default_sint32_extension_lite   = 65 [default = -45    ];
-  optional   sint64 default_sint64_extension_lite   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32_extension_lite  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64_extension_lite  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32_extension_lite = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50    ];
-  optional    float default_float_extension_lite    = 71 [default =  51.5  ];
-  optional   double default_double_extension_lite   = 72 [default =  52e3  ];
-  optional     bool default_bool_extension_lite     = 73 [default = true   ];
-  optional   string default_string_extension_lite   = 74 [default = "hello"];
-  optional    bytes default_bytes_extension_lite    = 75 [default = "world"];
-
-  optional TestAllTypesLite.NestedEnum
-    default_nested_enum_extension_lite = 81 [default = BAR];
-  optional ForeignEnumLite
-    default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR];
-  optional protobuf_unittest_import.ImportEnumLite
-    default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR];
-
-  optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE,
-                                                            default="abc"];
-  optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"];
-}
-
-message TestPackedExtensionsLite {
-  extensions 1 to max;
-}
-
-extend TestPackedExtensionsLite {
-  repeated    int32 packed_int32_extension_lite    =  90 [packed = true];
-  repeated    int64 packed_int64_extension_lite    =  91 [packed = true];
-  repeated   uint32 packed_uint32_extension_lite   =  92 [packed = true];
-  repeated   uint64 packed_uint64_extension_lite   =  93 [packed = true];
-  repeated   sint32 packed_sint32_extension_lite   =  94 [packed = true];
-  repeated   sint64 packed_sint64_extension_lite   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32_extension_lite  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64_extension_lite  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32_extension_lite =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64_extension_lite =  99 [packed = true];
-  repeated    float packed_float_extension_lite    = 100 [packed = true];
-  repeated   double packed_double_extension_lite   = 101 [packed = true];
-  repeated     bool packed_bool_extension_lite     = 102 [packed = true];
-  repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true];
-}
-
-message TestNestedExtensionLite {
-  extend TestAllExtensionsLite {
-    optional int32 nested_extension = 12345;
-  }
-}
-
-// Test that deprecated fields work.  We only verify that they compile (at one
-// point this failed).
-message TestDeprecatedLite {
-  optional int32 deprecated_field = 1 [deprecated = true];
-}
-
-// See the comments of the same type in unittest.proto.
-message TestParsingMergeLite {
-  message RepeatedFieldsGenerator {
-    repeated TestAllTypesLite field1 = 1;
-    repeated TestAllTypesLite field2 = 2;
-    repeated TestAllTypesLite field3 = 3;
-    repeated group Group1 = 10 {
-      optional TestAllTypesLite field1 = 11;
-    }
-    repeated group Group2 = 20 {
-      optional TestAllTypesLite field1 = 21;
-    }
-    repeated TestAllTypesLite ext1 = 1000;
-    repeated TestAllTypesLite ext2 = 1001;
-  }
-  required TestAllTypesLite required_all_types = 1;
-  optional TestAllTypesLite optional_all_types = 2;
-  repeated TestAllTypesLite repeated_all_types = 3;
-  optional group OptionalGroup = 10 {
-    optional TestAllTypesLite optional_group_all_types = 11;
-  }
-  repeated group RepeatedGroup = 20 {
-    optional TestAllTypesLite repeated_group_all_types = 21;
-  }
-  extensions 1000 to max;
-  extend TestParsingMergeLite {
-    optional TestAllTypesLite optional_ext = 1000;
-    repeated TestAllTypesLite repeated_ext = 1001;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
deleted file mode 100644
index d52cb8c..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
+++ /dev/null
@@ -1,43 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// Tests that a "lite" message can import a regular message.
-
-package protobuf_unittest;
-
-import "google/protobuf/unittest.proto";
-
-option optimize_for = LITE_RUNTIME;
-
-message TestLiteImportsNonlite {
-  optional TestAllTypes message = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto
deleted file mode 100644
index 3497f09..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto
+++ /dev/null
@@ -1,72 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// This file contains messages for testing message_set_wire_format.
-
-package protobuf_unittest;
-
-option optimize_for = SPEED;
-
-// A message with message_set_wire_format.
-message TestMessageSet {
-  option message_set_wire_format = true;
-  extensions 4 to max;
-}
-
-message TestMessageSetContainer {
-  optional TestMessageSet message_set = 1;
-}
-
-message TestMessageSetExtension1 {
-  extend TestMessageSet {
-    optional TestMessageSetExtension1 message_set_extension = 1545008;
-  }
-  optional int32 i = 15;
-}
-
-message TestMessageSetExtension2 {
-  extend TestMessageSet {
-    optional TestMessageSetExtension2 message_set_extension = 1547769;
-  }
-  optional string str = 25;
-}
-
-// MessageSet wire format is equivalent to this.
-message RawMessageSet {
-  repeated group Item = 1 {
-    required int32 type_id = 2;
-    required bytes message = 3;
-  }
-}
-
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto
deleted file mode 100644
index cffb412..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto
+++ /dev/null
@@ -1,52 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-
-package google.protobuf.no_generic_services_test;
-
-// *_generic_services are false by default.
-
-message TestMessage {
-  optional int32 a = 1;
-  extensions 1000 to max;
-}
-
-enum TestEnum {
-  FOO = 1;
-}
-
-extend TestMessage {
-  optional int32 test_extension = 1000;
-}
-
-service TestService {
-  rpc Foo(TestMessage) returns(TestMessage);
-}
diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto
deleted file mode 100644
index 658c6a9..0000000
--- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto
+++ /dev/null
@@ -1,61 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file which uses optimize_for = CODE_SIZE.
-
-import "google/protobuf/unittest.proto";
-
-package protobuf_unittest;
-
-option optimize_for = CODE_SIZE;
-
-message TestOptimizedForSize {
-  optional int32 i = 1;
-  optional ForeignMessage msg = 19;
-
-  extensions 1000 to max;
-
-  extend TestOptimizedForSize {
-    optional int32 test_extension = 1234;
-    optional TestRequiredOptimizedForSize test_extension2 = 1235;
-  }
-}
-
-message TestRequiredOptimizedForSize {
-  required int32 x = 1;
-}
-
-message TestOptionalOptimizedForSize {
-  optional TestRequiredOptimizedForSize o = 1;
-}
diff --git a/java/compatibility_tests/v2.5.0/test.sh b/java/compatibility_tests/v2.5.0/test.sh
deleted file mode 100755
index 65ea960..0000000
--- a/java/compatibility_tests/v2.5.0/test.sh
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-# Change to the script's directory.
-cd $(dirname $0)
-
-MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository
-MVN="mvn --batch-mode -e -X -Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY"
-
-# Version of the tests (i.e., the version of protobuf from where we extracted
-# these tests).
-TEST_VERSION=`grep "^  <version>.*</version>" pom.xml | sed "s|  <version>\(.*\)</version>|\1|"`
-
-# The old version of protobuf that we are testing compatibility against. This
-# is usually the same as TEST_VERSION (i.e., we use the tests extracted from
-# that version to test compatibility of the newest runtime against it), but it
-# is also possible to use this same test set to test the compatibility of the
-# latest version against other versions.
-OLD_VERSION=$1
-OLD_VERSION_PROTOC=https://repo1.maven.org/maven2/com/google/protobuf/protoc/$OLD_VERSION/protoc-$OLD_VERSION-linux-x86_64.exe
-
-# Extract the latest protobuf version number.
-VERSION_NUMBER=`grep "^  <version>.*</version>" ../../pom.xml | sed "s|  <version>\(.*\)</version>|\1|"`
-
-echo "Running compatibility tests between current $VERSION_NUMBER and released $OLD_VERSION"
-
-# Check protoc
-[ -f ../../../src/protoc ] || {
-  echo "[ERROR]: Please build protoc first."
-  exit 1
-}
-
-# Build and install protobuf-java-$VERSION_NUMBER.jar
-[ -f ../../core/target/protobuf-java-$VERSION_NUMBER.jar ] || {
-  pushd ../..
-  $MVN install -Dmaven.test.skip=true
-  popd
-}
-
-# Download old version source for the compatibility test
-[ -d protobuf ] || {
-  git clone https://github.com/protocolbuffers/protobuf.git
-  cd protobuf
-  git reset --hard v$TEST_VERSION
-  cd ..
-}
-
-# Download old version protoc compiler (for linux)
-wget $OLD_VERSION_PROTOC -O protoc
-chmod +x protoc
-
-# Test source compatibility. In these tests we recompile everything against
-# the new runtime (including old version generated code).
-
-# Test A.1:
-#   protos: use new version
-#   more_protos: use old version
-$MVN clean test \
-  -Dprotobuf.test.source.path=$(pwd)/protobuf \
-  -Dprotoc.path=$(pwd)/protoc \
-  -Dprotos.protoc.path=$(pwd)/../../../src/protoc \
-  -Dprotobuf.version=$VERSION_NUMBER
-
-# Test A.2:
-#   protos: use old version
-#   more_protos: use new version
-$MVN clean test \
-  -Dprotobuf.test.source.path=$(pwd)/protobuf \
-  -Dprotoc.path=$(pwd)/protoc \
-  -Dmore_protos.protoc.path=$(pwd)/../../../src/protoc \
-  -Dprotobuf.version=$VERSION_NUMBER
-
-# Test binary compatibility. In these tests we run the old version compiled
-# jar against the new runtime directly without recompile.
-
-# Collect all test dependencies in a single jar file (except for protobuf) to
-# make it easier to run binary compatibility test (where we will need to run
-# the jar files directly).
-cd deps
-$MVN assembly:single
-cd ..
-cp -f deps/target/compatibility-test-deps-${TEST_VERSION}-jar-with-dependencies.jar deps.jar
-
-# Build the old version of all 3 artifacts.
-$MVN clean install -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/protoc -Dprotobuf.version=$OLD_VERSION
-cp -f protos/target/compatibility-protos-${TEST_VERSION}.jar protos.jar
-cp -f more_protos/target/compatibility-more-protos-${TEST_VERSION}.jar more_protos.jar
-cp -f tests/target/compatibility-tests-${TEST_VERSION}.jar tests.jar
-
-# Collect the list of tests we need to run.
-TESTS=`find tests -name "*Test.java" | sed "s|/|.|g;s/.java$//g;s/tests.src.main.java.//g"`
-
-# Test B.1: run all the old artifacts against the new runtime. Note that we
-# must run the test in the protobuf source tree because some of the tests need
-# to read golden test data files.
-cd protobuf
-java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos.jar:../more_protos.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS
-cd ..
-
-# Test B.2: update protos.jar only.
-cd protos
-$MVN clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER
-cd ..
-cd protobuf
-java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos/target/compatibility-protos-${TEST_VERSION}.jar:../more_protos.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS
-cd ..
-
-# Test B.3: update more_protos.jar only.
-cd more_protos
-$MVN clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER
-cd ..
-cd protobuf
-java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos.jar:../more_protos/target/compatibility-more-protos-${TEST_VERSION}.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS
-cd ..
diff --git a/java/compatibility_tests/v2.5.0/tests/pom.xml b/java/compatibility_tests/v2.5.0/tests/pom.xml
deleted file mode 100644
index f1ce46e..0000000
--- a/java/compatibility_tests/v2.5.0/tests/pom.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>com.google.protobuf.compatibility</groupId>
-    <artifactId>compatibility-test-suite</artifactId>
-    <version>2.5.0</version>
-    <relativePath>..</relativePath>
-  </parent>
-
-  <groupId>com.google.protobuf.compatibility</groupId>
-  <artifactId>compatibility-tests</artifactId>
-  <version>2.5.0</version>
-
-  <name>Compatibility Tests</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.4</version>
-    </dependency>
-    <dependency>
-      <groupId>org.easymock</groupId>
-      <artifactId>easymock</artifactId>
-      <version>2.2</version>
-    </dependency>
-    <dependency>
-      <groupId>org.easymock</groupId>
-      <artifactId>easymockclassextension</artifactId>
-      <version>2.2.1</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.protobuf</groupId>
-      <artifactId>protobuf-java</artifactId>
-      <version>${tests.protobuf.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.protobuf.compatibility</groupId>
-      <artifactId>compatibility-protos</artifactId>
-      <version>2.5.0</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.protobuf.compatibility</groupId>
-      <artifactId>compatibility-more-protos</artifactId>
-      <version>2.5.0</version>
-    </dependency>
-  </dependencies>
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <configuration>
-          <source>1.6</source>
-          <target>1.6</target>
-        </configuration>
-      </plugin>
-      <plugin>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <testSourceDirectory>${basedir}/src/main/java/</testSourceDirectory>
-          <testClassesDirectory>${project.build.directory}/classes/</testClassesDirectory>
-          <includes>
-            <include>**/*Test.java</include>
-          </includes>
-          <workingDirectory>${protobuf.test.source.path}</workingDirectory>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/AbstractMessageTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/AbstractMessageTest.java
deleted file mode 100644
index 6789550..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/AbstractMessageTest.java
+++ /dev/null
@@ -1,510 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
-import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.ForeignMessage;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestPackedTypes;
-import protobuf_unittest.UnittestProto.TestRequired;
-import protobuf_unittest.UnittestProto.TestRequiredForeign;
-import protobuf_unittest.UnittestProto.TestUnpackedTypes;
-
-import junit.framework.TestCase;
-
-import java.util.Map;
-
-/**
- * Unit test for {@link AbstractMessage}.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class AbstractMessageTest extends TestCase {
-  /**
-   * Extends AbstractMessage and wraps some other message object.  The methods
-   * of the Message interface which aren't explicitly implemented by
-   * AbstractMessage are forwarded to the wrapped object.  This allows us to
-   * test that AbstractMessage's implementations work even if the wrapped
-   * object does not use them.
-   */
-  private static class AbstractMessageWrapper extends AbstractMessage {
-    private final Message wrappedMessage;
-
-    public AbstractMessageWrapper(Message wrappedMessage) {
-      this.wrappedMessage = wrappedMessage;
-    }
-
-    public Descriptors.Descriptor getDescriptorForType() {
-      return wrappedMessage.getDescriptorForType();
-    }
-    public AbstractMessageWrapper getDefaultInstanceForType() {
-      return new AbstractMessageWrapper(
-        wrappedMessage.getDefaultInstanceForType());
-    }
-    public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
-      return wrappedMessage.getAllFields();
-    }
-    public boolean hasField(Descriptors.FieldDescriptor field) {
-      return wrappedMessage.hasField(field);
-    }
-    public Object getField(Descriptors.FieldDescriptor field) {
-      return wrappedMessage.getField(field);
-    }
-    public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
-      return wrappedMessage.getRepeatedFieldCount(field);
-    }
-    public Object getRepeatedField(
-        Descriptors.FieldDescriptor field, int index) {
-      return wrappedMessage.getRepeatedField(field, index);
-    }
-    public UnknownFieldSet getUnknownFields() {
-      return wrappedMessage.getUnknownFields();
-    }
-    public Builder newBuilderForType() {
-      return new Builder(wrappedMessage.newBuilderForType());
-    }
-    public Builder toBuilder() {
-      return new Builder(wrappedMessage.toBuilder());
-    }
-
-    static class Builder extends AbstractMessage.Builder<Builder> {
-      private final Message.Builder wrappedBuilder;
-
-      public Builder(Message.Builder wrappedBuilder) {
-        this.wrappedBuilder = wrappedBuilder;
-      }
-
-      public AbstractMessageWrapper build() {
-        return new AbstractMessageWrapper(wrappedBuilder.build());
-      }
-      public AbstractMessageWrapper buildPartial() {
-        return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
-      }
-      public Builder clone() {
-        return new Builder(wrappedBuilder.clone());
-      }
-      public boolean isInitialized() {
-        return clone().buildPartial().isInitialized();
-      }
-      public Descriptors.Descriptor getDescriptorForType() {
-        return wrappedBuilder.getDescriptorForType();
-      }
-      public AbstractMessageWrapper getDefaultInstanceForType() {
-        return new AbstractMessageWrapper(
-          wrappedBuilder.getDefaultInstanceForType());
-      }
-      public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
-        return wrappedBuilder.getAllFields();
-      }
-      public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
-        return new Builder(wrappedBuilder.newBuilderForField(field));
-      }
-      public boolean hasField(Descriptors.FieldDescriptor field) {
-        return wrappedBuilder.hasField(field);
-      }
-      public Object getField(Descriptors.FieldDescriptor field) {
-        return wrappedBuilder.getField(field);
-      }
-      public Builder setField(Descriptors.FieldDescriptor field, Object value) {
-        wrappedBuilder.setField(field, value);
-        return this;
-      }
-      public Builder clearField(Descriptors.FieldDescriptor field) {
-        wrappedBuilder.clearField(field);
-        return this;
-      }
-      public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
-        return wrappedBuilder.getRepeatedFieldCount(field);
-      }
-      public Object getRepeatedField(
-          Descriptors.FieldDescriptor field, int index) {
-        return wrappedBuilder.getRepeatedField(field, index);
-      }
-      public Builder setRepeatedField(Descriptors.FieldDescriptor field,
-                                      int index, Object value) {
-        wrappedBuilder.setRepeatedField(field, index, value);
-        return this;
-      }
-      public Builder addRepeatedField(
-          Descriptors.FieldDescriptor field, Object value) {
-        wrappedBuilder.addRepeatedField(field, value);
-        return this;
-      }
-      public UnknownFieldSet getUnknownFields() {
-        return wrappedBuilder.getUnknownFields();
-      }
-      public Builder setUnknownFields(UnknownFieldSet unknownFields) {
-        wrappedBuilder.setUnknownFields(unknownFields);
-        return this;
-      }
-      @Override
-      public Message.Builder getFieldBuilder(FieldDescriptor field) {
-        return wrappedBuilder.getFieldBuilder(field);
-      }
-    }
-    public Parser<? extends Message> getParserForType() {
-      return wrappedMessage.getParserForType();
-    }
-  }
-
-  // =================================================================
-
-  TestUtil.ReflectionTester reflectionTester =
-    new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
-
-  TestUtil.ReflectionTester extensionsReflectionTester =
-    new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
-                                  TestUtil.getExtensionRegistry());
-
-  public void testClear() throws Exception {
-    AbstractMessageWrapper message =
-      new AbstractMessageWrapper.Builder(
-          TestAllTypes.newBuilder(TestUtil.getAllSet()))
-        .clear().build();
-    TestUtil.assertClear((TestAllTypes) message.wrappedMessage);
-  }
-
-  public void testCopy() throws Exception {
-    AbstractMessageWrapper message =
-      new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder())
-        .mergeFrom(TestUtil.getAllSet()).build();
-    TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
-  }
-
-  public void testSerializedSize() throws Exception {
-    TestAllTypes message = TestUtil.getAllSet();
-    Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
-
-    assertEquals(message.getSerializedSize(),
-                 abstractMessage.getSerializedSize());
-  }
-
-  public void testSerialization() throws Exception {
-    Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
-
-    TestUtil.assertAllFieldsSet(
-      TestAllTypes.parseFrom(abstractMessage.toByteString()));
-
-    assertEquals(TestUtil.getAllSet().toByteString(),
-                 abstractMessage.toByteString());
-  }
-
-  public void testParsing() throws Exception {
-    AbstractMessageWrapper.Builder builder =
-      new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder());
-    AbstractMessageWrapper message =
-      builder.mergeFrom(TestUtil.getAllSet().toByteString()).build();
-    TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
-  }
-
-  public void testParsingUninitialized() throws Exception {
-    TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
-    builder.getOptionalMessageBuilder().setDummy2(10);
-    ByteString bytes = builder.buildPartial().toByteString();
-    Message.Builder abstractMessageBuilder =
-        new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
-    // mergeFrom() should not throw initialization error.
-    abstractMessageBuilder.mergeFrom(bytes).buildPartial();
-    try {
-      abstractMessageBuilder.mergeFrom(bytes).build();
-      fail();
-    } catch (UninitializedMessageException ex) {
-      // pass
-    }
-
-    // test DynamicMessage directly.
-    Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
-        TestRequiredForeign.getDescriptor());
-    // mergeFrom() should not throw initialization error.
-    dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
-    try {
-      dynamicMessageBuilder.mergeFrom(bytes).build();
-      fail();
-    } catch (UninitializedMessageException ex) {
-      // pass
-    }
-  }
-
-  public void testPackedSerialization() throws Exception {
-    Message abstractMessage =
-        new AbstractMessageWrapper(TestUtil.getPackedSet());
-
-    TestUtil.assertPackedFieldsSet(
-      TestPackedTypes.parseFrom(abstractMessage.toByteString()));
-
-    assertEquals(TestUtil.getPackedSet().toByteString(),
-                 abstractMessage.toByteString());
-  }
-
-  public void testPackedParsing() throws Exception {
-    AbstractMessageWrapper.Builder builder =
-      new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
-    AbstractMessageWrapper message =
-      builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
-    TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
-  }
-
-  public void testUnpackedSerialization() throws Exception {
-    Message abstractMessage =
-      new AbstractMessageWrapper(TestUtil.getUnpackedSet());
-
-    TestUtil.assertUnpackedFieldsSet(
-      TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
-
-    assertEquals(TestUtil.getUnpackedSet().toByteString(),
-                 abstractMessage.toByteString());
-  }
-
-  public void testParsePackedToUnpacked() throws Exception {
-    AbstractMessageWrapper.Builder builder =
-      new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
-    AbstractMessageWrapper message =
-      builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
-    TestUtil.assertUnpackedFieldsSet(
-      (TestUnpackedTypes) message.wrappedMessage);
-  }
-
-  public void testParseUnpackedToPacked() throws Exception {
-    AbstractMessageWrapper.Builder builder =
-      new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
-    AbstractMessageWrapper message =
-      builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
-    TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
-  }
-
-  public void testUnpackedParsing() throws Exception {
-    AbstractMessageWrapper.Builder builder =
-      new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
-    AbstractMessageWrapper message =
-      builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
-    TestUtil.assertUnpackedFieldsSet(
-      (TestUnpackedTypes) message.wrappedMessage);
-  }
-
-  public void testOptimizedForSize() throws Exception {
-    // We're mostly only checking that this class was compiled successfully.
-    TestOptimizedForSize message =
-      TestOptimizedForSize.newBuilder().setI(1).build();
-    message = TestOptimizedForSize.parseFrom(message.toByteString());
-    assertEquals(2, message.getSerializedSize());
-  }
-
-  // -----------------------------------------------------------------
-  // Tests for isInitialized().
-
-  private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
-    TestRequired.getDefaultInstance();
-  private static final TestRequired TEST_REQUIRED_INITIALIZED =
-    TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
-
-  public void testIsInitialized() throws Exception {
-    TestRequired.Builder builder = TestRequired.newBuilder();
-    AbstractMessageWrapper.Builder abstractBuilder =
-      new AbstractMessageWrapper.Builder(builder);
-
-    assertFalse(abstractBuilder.isInitialized());
-    assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
-    builder.setA(1);
-    assertFalse(abstractBuilder.isInitialized());
-    assertEquals("b, c", abstractBuilder.getInitializationErrorString());
-    builder.setB(1);
-    assertFalse(abstractBuilder.isInitialized());
-    assertEquals("c", abstractBuilder.getInitializationErrorString());
-    builder.setC(1);
-    assertTrue(abstractBuilder.isInitialized());
-    assertEquals("", abstractBuilder.getInitializationErrorString());
-  }
-
-  public void testForeignIsInitialized() throws Exception {
-    TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
-    AbstractMessageWrapper.Builder abstractBuilder =
-      new AbstractMessageWrapper.Builder(builder);
-
-    assertTrue(abstractBuilder.isInitialized());
-    assertEquals("", abstractBuilder.getInitializationErrorString());
-
-    builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(abstractBuilder.isInitialized());
-    assertEquals(
-        "optional_message.a, optional_message.b, optional_message.c",
-        abstractBuilder.getInitializationErrorString());
-
-    builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
-    assertTrue(abstractBuilder.isInitialized());
-    assertEquals("", abstractBuilder.getInitializationErrorString());
-
-    builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(abstractBuilder.isInitialized());
-    assertEquals(
-        "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
-        abstractBuilder.getInitializationErrorString());
-
-    builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
-    assertTrue(abstractBuilder.isInitialized());
-    assertEquals("", abstractBuilder.getInitializationErrorString());
-  }
-
-  // -----------------------------------------------------------------
-  // Tests for mergeFrom
-
-  static final TestAllTypes MERGE_SOURCE =
-    TestAllTypes.newBuilder()
-      .setOptionalInt32(1)
-      .setOptionalString("foo")
-      .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
-      .addRepeatedString("bar")
-      .build();
-
-  static final TestAllTypes MERGE_DEST =
-    TestAllTypes.newBuilder()
-      .setOptionalInt64(2)
-      .setOptionalString("baz")
-      .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
-      .addRepeatedString("qux")
-      .build();
-
-  static final String MERGE_RESULT_TEXT =
-      "optional_int32: 1\n" +
-      "optional_int64: 2\n" +
-      "optional_string: \"foo\"\n" +
-      "optional_foreign_message {\n" +
-      "  c: 3\n" +
-      "}\n" +
-      "repeated_string: \"qux\"\n" +
-      "repeated_string: \"bar\"\n";
-
-  public void testMergeFrom() throws Exception {
-    AbstractMessageWrapper result =
-      new AbstractMessageWrapper.Builder(
-        TestAllTypes.newBuilder(MERGE_DEST))
-      .mergeFrom(MERGE_SOURCE).build();
-
-    assertEquals(MERGE_RESULT_TEXT, result.toString());
-  }
-
-  // -----------------------------------------------------------------
-  // Tests for equals and hashCode
-
-  public void testEqualsAndHashCode() throws Exception {
-    TestAllTypes a = TestUtil.getAllSet();
-    TestAllTypes b = TestAllTypes.newBuilder().build();
-    TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build();
-    TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build();
-    TestAllExtensions e = TestUtil.getAllExtensionsSet();
-    TestAllExtensions f = TestAllExtensions.newBuilder(e)
-        .addExtension(UnittestProto.repeatedInt32Extension, 999).build();
-
-    checkEqualsIsConsistent(a);
-    checkEqualsIsConsistent(b);
-    checkEqualsIsConsistent(c);
-    checkEqualsIsConsistent(d);
-    checkEqualsIsConsistent(e);
-    checkEqualsIsConsistent(f);
-
-    checkNotEqual(a, b);
-    checkNotEqual(a, c);
-    checkNotEqual(a, d);
-    checkNotEqual(a, e);
-    checkNotEqual(a, f);
-
-    checkNotEqual(b, c);
-    checkNotEqual(b, d);
-    checkNotEqual(b, e);
-    checkNotEqual(b, f);
-
-    checkNotEqual(c, d);
-    checkNotEqual(c, e);
-    checkNotEqual(c, f);
-
-    checkNotEqual(d, e);
-    checkNotEqual(d, f);
-
-    checkNotEqual(e, f);
-
-    // Deserializing into the TestEmptyMessage such that every field
-    // is an {@link UnknownFieldSet.Field}.
-    UnittestProto.TestEmptyMessage eUnknownFields =
-        UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
-    UnittestProto.TestEmptyMessage fUnknownFields =
-        UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray());
-    checkNotEqual(eUnknownFields, fUnknownFields);
-    checkEqualsIsConsistent(eUnknownFields);
-    checkEqualsIsConsistent(fUnknownFields);
-
-    // Subsequent reconstitutions should be identical
-    UnittestProto.TestEmptyMessage eUnknownFields2 =
-        UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
-    checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
-  }
-
-
-  /**
-   * Asserts that the given proto has symmetric equals and hashCode methods.
-   */
-  private void checkEqualsIsConsistent(Message message) {
-    // Object should be equal to itself.
-    assertEquals(message, message);
-
-    // Object should be equal to a dynamic copy of itself.
-    DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
-    checkEqualsIsConsistent(message, dynamic);
-  }
-
-  /**
-   * Asserts that the given protos are equal and have the same hash code.
-   */
-  private void checkEqualsIsConsistent(Message message1, Message message2) {
-    assertEquals(message1, message2);
-    assertEquals(message2, message1);
-    assertEquals(message2.hashCode(), message1.hashCode());
-  }
-
-  /**
-   * Asserts that the given protos are not equal and have different hash codes.
-   *
-   * @warning It's valid for non-equal objects to have the same hash code, so
-   *   this test is stricter than it needs to be. However, this should happen
-   *   relatively rarely.
-   */
-  private void checkNotEqual(Message m1, Message m2) {
-    String equalsError = String.format("%s should not be equal to %s", m1, m2);
-    assertFalse(equalsError, m1.equals(m2));
-    assertFalse(equalsError, m2.equals(m1));
-
-    assertFalse(
-        String.format("%s should have a different hash code from %s", m1, m2),
-        m1.hashCode() == m2.hashCode());
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/BoundedByteStringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/BoundedByteStringTest.java
deleted file mode 100644
index c838274..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/BoundedByteStringTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import java.io.UnsupportedEncodingException;
-
-/**
- * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString},
- * by inheriting the tests from {@link LiteralByteStringTest}.  The only method which
- * is strange enough that it needs to be overridden here is {@link #testToString()}.
- *
- * @author carlanton@google.com (Carl Haverl)
- */
-public class BoundedByteStringTest extends LiteralByteStringTest {
-
-  @Override
-  protected void setUp() throws Exception {
-    classUnderTest = "BoundedByteString";
-    byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L);
-    int from = 100;
-    int to = sourceBytes.length - 100;
-    stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to);
-    referenceBytes = new byte[to - from];
-    System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
-    expectedHashCode = 727575887;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java
deleted file mode 100644
index 9e334e5..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java
+++ /dev/null
@@ -1,590 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import com.google.protobuf.ByteString.Output;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Random;
-
-/**
- * Test methods with implementations in {@link ByteString}, plus do some top-level "integration"
- * tests.
- *
- * @author carlanton@google.com (Carl Haverl)
- */
-public class ByteStringTest extends TestCase {
-
-  private static final String UTF_16 = "UTF-16";
-
-  static byte[] getTestBytes(int size, long seed) {
-    Random random = new Random(seed);
-    byte[] result = new byte[size];
-    random.nextBytes(result);
-    return result;
-  }
-
-  private byte[] getTestBytes(int size) {
-    return getTestBytes(size, 445566L);
-  }
-
-  private byte[] getTestBytes() {
-    return getTestBytes(1000);
-  }
-
-  // Compare the entire left array with a subset of the right array.
-  private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) {
-    boolean stillEqual = (left.length == length);
-    for (int i = 0; (stillEqual && i < length); ++i) {
-      stillEqual = (left[i] == right[rightOffset + i]);
-    }
-    return stillEqual;
-  }
-
-  // Returns true only if the given two arrays have identical contents.
-  private boolean isArray(byte[] left, byte[] right) {
-    return left.length == right.length && isArrayRange(left, right, 0, left.length);
-  }
-
-  public void testSubstring_BeginIndex() {
-    byte[] bytes = getTestBytes();
-    ByteString substring = ByteString.copyFrom(bytes).substring(500);
-    assertTrue("substring must contain the tail of the string",
-        isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500));
-  }
-
-  public void testCopyFrom_BytesOffsetSize() {
-    byte[] bytes = getTestBytes();
-    ByteString byteString = ByteString.copyFrom(bytes, 500, 200);
-    assertTrue("copyFrom sub-range must contain the expected bytes",
-        isArrayRange(byteString.toByteArray(), bytes, 500, 200));
-  }
-
-  public void testCopyFrom_Bytes() {
-    byte[] bytes = getTestBytes();
-    ByteString byteString = ByteString.copyFrom(bytes);
-    assertTrue("copyFrom must contain the expected bytes",
-        isArray(byteString.toByteArray(), bytes));
-  }
-
-  public void testCopyFrom_ByteBufferSize() {
-    byte[] bytes = getTestBytes();
-    ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
-    byteBuffer.put(bytes);
-    byteBuffer.position(500);
-    ByteString byteString = ByteString.copyFrom(byteBuffer, 200);
-    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
-        isArrayRange(byteString.toByteArray(), bytes, 500, 200));
-  }
-
-  public void testCopyFrom_ByteBuffer() {
-    byte[] bytes = getTestBytes();
-    ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
-    byteBuffer.put(bytes);
-    byteBuffer.position(500);
-    ByteString byteString = ByteString.copyFrom(byteBuffer);
-    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
-        isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500));
-  }
-
-  public void testCopyFrom_StringEncoding() throws UnsupportedEncodingException {
-    String testString = "I love unicode \u1234\u5678 characters";
-    ByteString byteString = ByteString.copyFrom(testString, UTF_16);
-    byte[] testBytes = testString.getBytes(UTF_16);
-    assertTrue("copyFrom string must respect the charset",
-        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
-  }
-
-  public void testCopyFrom_Utf8() throws UnsupportedEncodingException {
-    String testString = "I love unicode \u1234\u5678 characters";
-    ByteString byteString = ByteString.copyFromUtf8(testString);
-    byte[] testBytes = testString.getBytes("UTF-8");
-    assertTrue("copyFromUtf8 string must respect the charset",
-        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
-  }
-
-  public void testCopyFrom_Iterable() {
-    byte[] testBytes = getTestBytes(77777, 113344L);
-    final List<ByteString> pieces = makeConcretePieces(testBytes);
-    // Call copyFrom() on a Collection
-    ByteString byteString = ByteString.copyFrom(pieces);
-    assertTrue("copyFrom a List must contain the expected bytes",
-        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
-    // Call copyFrom on an iteration that's not a collection
-    ByteString byteStringAlt = ByteString.copyFrom(new Iterable<ByteString>() {
-      public Iterator<ByteString> iterator() {
-        return pieces.iterator();
-      }
-    });
-    assertEquals("copyFrom from an Iteration must contain the expected bytes",
-        byteString, byteStringAlt);
-  }
-
-  public void testCopyTo_TargetOffset() {
-    byte[] bytes = getTestBytes();
-    ByteString byteString = ByteString.copyFrom(bytes);
-    byte[] target = new byte[bytes.length + 1000];
-    byteString.copyTo(target, 400);
-    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
-        isArrayRange(bytes, target, 400, bytes.length));
-  }
-
-  public void testReadFrom_emptyStream() throws IOException {
-    ByteString byteString =
-        ByteString.readFrom(new ByteArrayInputStream(new byte[0]));
-    assertSame("reading an empty stream must result in the EMPTY constant "
-        + "byte string", ByteString.EMPTY, byteString);
-  }
-
-  public void testReadFrom_smallStream() throws IOException {
-    assertReadFrom(getTestBytes(10));
-  }
-
-  public void testReadFrom_mutating() throws IOException {
-    byte[] capturedArray = null;
-    EvilInputStream eis = new EvilInputStream();
-    ByteString byteString = ByteString.readFrom(eis);
-
-    capturedArray = eis.capturedArray;
-    byte[] originalValue = byteString.toByteArray();
-    for (int x = 0; x < capturedArray.length; ++x) {
-      capturedArray[x] = (byte) 0;
-    }
-
-    byte[] newValue = byteString.toByteArray();
-    assertTrue("copyFrom byteBuffer must not grant access to underlying array",
-        Arrays.equals(originalValue, newValue));
-  }
-
-  // Tests sizes that are over multi-segment rope threshold.
-  public void testReadFrom_largeStream() throws IOException {
-    assertReadFrom(getTestBytes(0x100));
-    assertReadFrom(getTestBytes(0x101));
-    assertReadFrom(getTestBytes(0x110));
-    assertReadFrom(getTestBytes(0x1000));
-    assertReadFrom(getTestBytes(0x1001));
-    assertReadFrom(getTestBytes(0x1010));
-    assertReadFrom(getTestBytes(0x10000));
-    assertReadFrom(getTestBytes(0x10001));
-    assertReadFrom(getTestBytes(0x10010));
-  }
-
-  // Tests that IOExceptions propagate through ByteString.readFrom().
-  public void testReadFrom_IOExceptions() {
-    try {
-      ByteString.readFrom(new FailStream());
-      fail("readFrom must throw the underlying IOException");
-
-    } catch (IOException e) {
-      assertEquals("readFrom must throw the expected exception",
-                   "synthetic failure", e.getMessage());
-    }
-  }
-
-  // Tests that ByteString.readFrom works with streams that don't
-  // always fill their buffers.
-  public void testReadFrom_reluctantStream() throws IOException {
-    final byte[] data = getTestBytes(0x1000);
-
-    ByteString byteString = ByteString.readFrom(new ReluctantStream(data));
-    assertTrue("readFrom byte stream must contain the expected bytes",
-        isArray(byteString.toByteArray(), data));
-
-    // Same test as above, but with some specific chunk sizes.
-    assertReadFromReluctantStream(data, 100);
-    assertReadFromReluctantStream(data, 248);
-    assertReadFromReluctantStream(data, 249);
-    assertReadFromReluctantStream(data, 250);
-    assertReadFromReluctantStream(data, 251);
-    assertReadFromReluctantStream(data, 0x1000);
-    assertReadFromReluctantStream(data, 0x1001);
-  }
-
-  // Fails unless ByteString.readFrom reads the bytes correctly from a
-  // reluctant stream with the given chunkSize parameter.
-  private void assertReadFromReluctantStream(byte[] bytes, int chunkSize)
-      throws IOException {
-    ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize);
-    assertTrue("readFrom byte stream must contain the expected bytes",
-        isArray(b.toByteArray(), bytes));
-  }
-
-  // Tests that ByteString.readFrom works with streams that implement
-  // available().
-  public void testReadFrom_available() throws IOException {
-    final byte[] data = getTestBytes(0x1001);
-
-    ByteString byteString = ByteString.readFrom(new AvailableStream(data));
-    assertTrue("readFrom byte stream must contain the expected bytes",
-        isArray(byteString.toByteArray(), data));
-  }
-
-  // Fails unless ByteString.readFrom reads the bytes correctly.
-  private void assertReadFrom(byte[] bytes) throws IOException {
-    ByteString byteString =
-        ByteString.readFrom(new ByteArrayInputStream(bytes));
-    assertTrue("readFrom byte stream must contain the expected bytes",
-        isArray(byteString.toByteArray(), bytes));
-  }
-
-  // A stream that fails when read.
-  private static final class FailStream extends InputStream {
-    @Override public int read() throws IOException {
-      throw new IOException("synthetic failure");
-    }
-  }
-
-  // A stream that simulates blocking by only producing 250 characters
-  // per call to read(byte[]).
-  private static class ReluctantStream extends InputStream {
-    protected final byte[] data;
-    protected int pos = 0;
-
-    public ReluctantStream(byte[] data) {
-      this.data = data;
-    }
-
-    @Override public int read() {
-      if (pos == data.length) {
-        return -1;
-      } else {
-        return data[pos++];
-      }
-    }
-
-    @Override public int read(byte[] buf) {
-      return read(buf, 0, buf.length);
-    }
-
-    @Override public int read(byte[] buf, int offset, int size) {
-      if (pos == data.length) {
-        return -1;
-      }
-      int count = Math.min(Math.min(size, data.length - pos), 250);
-      System.arraycopy(data, pos, buf, offset, count);
-      pos += count;
-      return count;
-    }
-  }
-
-  // Same as above, but also implements available().
-  private static final class AvailableStream extends ReluctantStream {
-    public AvailableStream(byte[] data) {
-      super(data);
-    }
-
-    @Override public int available() {
-      return Math.min(250, data.length - pos);
-    }
-  }
-
-  // A stream which exposes the byte array passed into read(byte[], int, int).
-  private static class EvilInputStream extends InputStream {
-    public byte[] capturedArray = null;
-
-    @Override
-    public int read(byte[] buf, int off, int len) {
-      if (capturedArray != null) {
-        return -1;
-      } else {
-        capturedArray = buf;
-        for (int x = 0; x < len; ++x) {
-          buf[x] = (byte) x;
-        }
-        return len;
-      }
-    }
-
-    @Override
-    public int read() {
-      // Purposefully do nothing.
-      return -1;
-    }
-  }
-
-  // A stream which exposes the byte array passed into write(byte[], int, int).
-  private static class EvilOutputStream extends OutputStream {
-    public byte[] capturedArray = null;
-
-    @Override
-    public void write(byte[] buf, int off, int len) {
-      if (capturedArray == null) {
-        capturedArray = buf;
-      }
-    }
-
-    @Override
-    public void write(int ignored) {
-      // Purposefully do nothing.
-    }
-  }
-
-  public void testToStringUtf8() throws UnsupportedEncodingException {
-    String testString = "I love unicode \u1234\u5678 characters";
-    byte[] testBytes = testString.getBytes("UTF-8");
-    ByteString byteString = ByteString.copyFrom(testBytes);
-    assertEquals("copyToStringUtf8 must respect the charset",
-        testString, byteString.toStringUtf8());
-  }
-
-  public void testNewOutput_InitialCapacity() throws IOException {
-    byte[] bytes = getTestBytes();
-    ByteString.Output output = ByteString.newOutput(bytes.length + 100);
-    output.write(bytes);
-    ByteString byteString = output.toByteString();
-    assertTrue(
-        "String built from newOutput(int) must contain the expected bytes",
-        isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
-  }
-
-  // Test newOutput() using a variety of buffer sizes and a variety of (fixed)
-  // write sizes
-  public void testNewOutput_ArrayWrite() throws IOException {
-    byte[] bytes = getTestBytes();
-    int length = bytes.length;
-    int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1,
-                         2 * length, 3 * length};
-    int[] writeSizes = {1, 4, 5, 7, 23, bytes.length};
-
-    for (int bufferSize : bufferSizes) {
-      for (int writeSize : writeSizes) {
-        // Test writing the entire output writeSize bytes at a time.
-        ByteString.Output output = ByteString.newOutput(bufferSize);
-        for (int i = 0; i < length; i += writeSize) {
-          output.write(bytes, i, Math.min(writeSize, length - i));
-        }
-        ByteString byteString = output.toByteString();
-        assertTrue("String built from newOutput() must contain the expected bytes",
-            isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
-      }
-    }
-  }
-
-  // Test newOutput() using a variety of buffer sizes, but writing all the
-  // characters using write(byte);
-  public void testNewOutput_WriteChar() throws IOException {
-    byte[] bytes = getTestBytes();
-    int length = bytes.length;
-    int[] bufferSizes = {0, 1, 128, 256, length / 2,
-                         length - 1, length, length + 1,
-                         2 * length, 3 * length};
-    for (int bufferSize : bufferSizes) {
-      ByteString.Output output = ByteString.newOutput(bufferSize);
-      for (byte byteValue : bytes) {
-        output.write(byteValue);
-      }
-      ByteString byteString = output.toByteString();
-      assertTrue("String built from newOutput() must contain the expected bytes",
-          isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
-    }
-  }
-
-  // Test newOutput() in which we write the bytes using a variety of methods
-  // and sizes, and in which we repeatedly call toByteString() in the middle.
-  public void testNewOutput_Mixed() throws IOException {
-    Random rng = new Random(1);
-    byte[] bytes = getTestBytes();
-    int length = bytes.length;
-    int[] bufferSizes = {0, 1, 128, 256, length / 2,
-                         length - 1, length, length + 1,
-                         2 * length, 3 * length};
-
-    for (int bufferSize : bufferSizes) {
-      // Test writing the entire output using a mixture of write sizes and
-      // methods;
-      ByteString.Output output = ByteString.newOutput(bufferSize);
-      int position = 0;
-      while (position < bytes.length) {
-        if (rng.nextBoolean()) {
-          int count = 1 + rng.nextInt(bytes.length - position);
-          output.write(bytes, position, count);
-          position += count;
-        } else {
-          output.write(bytes[position]);
-          position++;
-        }
-        assertEquals("size() returns the right value", position, output.size());
-        assertTrue("newOutput() substring must have correct bytes",
-            isArrayRange(output.toByteString().toByteArray(),
-                bytes, 0, position));
-      }
-      ByteString byteString = output.toByteString();
-      assertTrue("String built from newOutput() must contain the expected bytes",
-          isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
-    }
-  }
-
-  public void testNewOutputEmpty() throws IOException {
-    // Make sure newOutput() correctly builds empty byte strings
-    ByteString byteString = ByteString.newOutput().toByteString();
-    assertEquals(ByteString.EMPTY, byteString);
-  }
-
-  public void testNewOutput_Mutating() throws IOException {
-    Output os = ByteString.newOutput(5);
-    os.write(new byte[] {1, 2, 3, 4, 5});
-    EvilOutputStream eos = new EvilOutputStream();
-    os.writeTo(eos);
-    byte[] capturedArray = eos.capturedArray;
-    ByteString byteString = os.toByteString();
-    byte[] oldValue = byteString.toByteArray();
-    Arrays.fill(capturedArray, (byte) 0);
-    byte[] newValue = byteString.toByteArray();
-    assertTrue("Output must not provide access to the underlying byte array",
-        Arrays.equals(oldValue, newValue));
-  }
-
-  public void testSubstringParity() {
-    byte[] bigBytes = getTestBytes(2048 * 1024, 113344L);
-    int start = 512 * 1024 - 3333;
-    int end   = 512 * 1024 + 7777;
-    ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end);
-    boolean ok = true;
-    for (int i = start; ok && i < end; ++i) {
-      ok = (bigBytes[i] == concreteSubstring.byteAt(i - start));
-    }
-    assertTrue("Concrete substring didn't capture the right bytes", ok);
-
-    ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start);
-    assertTrue("Substring must be equal to literal string",
-        concreteSubstring.equals(literalString));
-    assertEquals("Substring must have same hashcode as literal string",
-        literalString.hashCode(), concreteSubstring.hashCode());
-  }
-
-  public void testCompositeSubstring() {
-    byte[] referenceBytes = getTestBytes(77748, 113344L);
-
-    List<ByteString> pieces = makeConcretePieces(referenceBytes);
-    ByteString listString = ByteString.copyFrom(pieces);
-
-    int from = 1000;
-    int to = 40000;
-    ByteString compositeSubstring = listString.substring(from, to);
-    byte[] substringBytes = compositeSubstring.toByteArray();
-    boolean stillEqual = true;
-    for (int i = 0; stillEqual && i < to - from; ++i) {
-      stillEqual = referenceBytes[from + i] == substringBytes[i];
-    }
-    assertTrue("Substring must return correct bytes", stillEqual);
-
-    stillEqual = true;
-    for (int i = 0; stillEqual && i < to - from; ++i) {
-      stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i);
-    }
-    assertTrue("Substring must support byteAt() correctly", stillEqual);
-
-    ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from);
-    assertTrue("Composite substring must equal a literal substring over the same bytes",
-        compositeSubstring.equals(literalSubstring));
-    assertTrue("Literal substring must equal a composite substring over the same bytes",
-        literalSubstring.equals(compositeSubstring));
-
-    assertEquals("We must get the same hashcodes for composite and literal substrings",
-        literalSubstring.hashCode(), compositeSubstring.hashCode());
-
-    assertFalse("We can't be equal to a proper substring",
-        compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1)));
-  }
-
-  public void testCopyFromList() {
-    byte[] referenceBytes = getTestBytes(77748, 113344L);
-    ByteString literalString = ByteString.copyFrom(referenceBytes);
-
-    List<ByteString> pieces = makeConcretePieces(referenceBytes);
-    ByteString listString = ByteString.copyFrom(pieces);
-
-    assertTrue("Composite string must be equal to literal string",
-        listString.equals(literalString));
-    assertEquals("Composite string must have same hashcode as literal string",
-        literalString.hashCode(), listString.hashCode());
-  }
-
-  public void testConcat() {
-    byte[] referenceBytes = getTestBytes(77748, 113344L);
-    ByteString literalString = ByteString.copyFrom(referenceBytes);
-
-    List<ByteString> pieces = makeConcretePieces(referenceBytes);
-
-    Iterator<ByteString> iter = pieces.iterator();
-    ByteString concatenatedString = iter.next();
-    while (iter.hasNext()) {
-      concatenatedString = concatenatedString.concat(iter.next());
-    }
-
-    assertTrue("Concatenated string must be equal to literal string",
-        concatenatedString.equals(literalString));
-    assertEquals("Concatenated string must have same hashcode as literal string",
-        literalString.hashCode(), concatenatedString.hashCode());
-  }
-
-  public void testStartsWith() {
-    byte[] bytes = getTestBytes(1000, 1234L);
-    ByteString string = ByteString.copyFrom(bytes);
-    ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
-    ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
-    assertTrue(string.startsWith(ByteString.EMPTY));
-    assertTrue(string.startsWith(string));
-    assertTrue(string.startsWith(prefix));
-    assertFalse(string.startsWith(suffix));
-    assertFalse(prefix.startsWith(suffix));
-    assertFalse(suffix.startsWith(prefix));
-    assertFalse(ByteString.EMPTY.startsWith(prefix));
-    assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY));
-  }
-
-  static List<ByteString> makeConcretePieces(byte[] referenceBytes) {
-    List<ByteString> pieces = new ArrayList<ByteString>();
-    // Starting length should be small enough that we'll do some concatenating by
-    // copying if we just concatenate all these pieces together.
-    for (int start = 0, length = 16; start < referenceBytes.length; start += length) {
-      length = (length << 1) - 1;
-      if (start + length > referenceBytes.length) {
-        length = referenceBytes.length - start;
-      }
-      pieces.add(ByteString.copyFrom(referenceBytes, start, length));
-    }
-    return pieces;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java
deleted file mode 100644
index 7e67898..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java
+++ /dev/null
@@ -1,469 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestRecursiveMessage;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayInputStream;
-import java.io.FilterInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-
-/**
- * Unit test for {@link CodedInputStream}.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class CodedInputStreamTest extends TestCase {
-  /**
-   * Helper to construct a byte array from a bunch of bytes.  The inputs are
-   * actually ints so that I can use hex notation and not get stupid errors
-   * about precision.
-   */
-  private byte[] bytes(int... bytesAsInts) {
-    byte[] bytes = new byte[bytesAsInts.length];
-    for (int i = 0; i < bytesAsInts.length; i++) {
-      bytes[i] = (byte) bytesAsInts[i];
-    }
-    return bytes;
-  }
-
-  /**
-   * An InputStream which limits the number of bytes it reads at a time.
-   * We use this to make sure that CodedInputStream doesn't screw up when
-   * reading in small blocks.
-   */
-  private static final class SmallBlockInputStream extends FilterInputStream {
-    private final int blockSize;
-
-    public SmallBlockInputStream(byte[] data, int blockSize) {
-      this(new ByteArrayInputStream(data), blockSize);
-    }
-
-    public SmallBlockInputStream(InputStream in, int blockSize) {
-      super(in);
-      this.blockSize = blockSize;
-    }
-
-    public int read(byte[] b) throws IOException {
-      return super.read(b, 0, Math.min(b.length, blockSize));
-    }
-
-    public int read(byte[] b, int off, int len) throws IOException {
-      return super.read(b, off, Math.min(len, blockSize));
-    }
-  }
-
-  /**
-   * Parses the given bytes using readRawVarint32() and readRawVarint64() and
-   * checks that the result matches the given value.
-   */
-  private void assertReadVarint(byte[] data, long value) throws Exception {
-    CodedInputStream input = CodedInputStream.newInstance(data);
-    assertEquals((int)value, input.readRawVarint32());
-
-    input = CodedInputStream.newInstance(data);
-    assertEquals(value, input.readRawVarint64());
-    assertTrue(input.isAtEnd());
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      input = CodedInputStream.newInstance(
-        new SmallBlockInputStream(data, blockSize));
-      assertEquals((int)value, input.readRawVarint32());
-
-      input = CodedInputStream.newInstance(
-        new SmallBlockInputStream(data, blockSize));
-      assertEquals(value, input.readRawVarint64());
-      assertTrue(input.isAtEnd());
-    }
-
-    // Try reading direct from an InputStream.  We want to verify that it
-    // doesn't read past the end of the input, so we copy to a new, bigger
-    // array first.
-    byte[] longerData = new byte[data.length + 1];
-    System.arraycopy(data, 0, longerData, 0, data.length);
-    InputStream rawInput = new ByteArrayInputStream(longerData);
-  }
-
-  /**
-   * Parses the given bytes using readRawVarint32() and readRawVarint64() and
-   * expects them to fail with an InvalidProtocolBufferException whose
-   * description matches the given one.
-   */
-  private void assertReadVarintFailure(
-      InvalidProtocolBufferException expected, byte[] data)
-      throws Exception {
-    CodedInputStream input = CodedInputStream.newInstance(data);
-    try {
-      input.readRawVarint32();
-      fail("Should have thrown an exception.");
-    } catch (InvalidProtocolBufferException e) {
-      assertEquals(expected.getMessage(), e.getMessage());
-    }
-
-    input = CodedInputStream.newInstance(data);
-    try {
-      input.readRawVarint64();
-      fail("Should have thrown an exception.");
-    } catch (InvalidProtocolBufferException e) {
-      assertEquals(expected.getMessage(), e.getMessage());
-    }
-  }
-
-  /** Tests readRawVarint32() and readRawVarint64(). */
-  public void testReadVarint() throws Exception {
-    assertReadVarint(bytes(0x00), 0);
-    assertReadVarint(bytes(0x01), 1);
-    assertReadVarint(bytes(0x7f), 127);
-    // 14882
-    assertReadVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
-    // 2961488830
-    assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
-      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-      (0x0bL << 28));
-
-    // 64-bit
-    // 7256456126
-    assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
-      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-      (0x1bL << 28));
-    // 41256202580718336
-    assertReadVarint(
-      bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
-      (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
-      (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
-    // 11964378330978735131
-    assertReadVarint(
-      bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
-      (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
-      (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
-      (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
-  }
-
-  /**
-   * Parses the given bytes using readRawLittleEndian32() and checks
-   * that the result matches the given value.
-   */
-  private void assertReadLittleEndian32(byte[] data, int value)
-                                        throws Exception {
-    CodedInputStream input = CodedInputStream.newInstance(data);
-    assertEquals(value, input.readRawLittleEndian32());
-    assertTrue(input.isAtEnd());
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      input = CodedInputStream.newInstance(
-        new SmallBlockInputStream(data, blockSize));
-      assertEquals(value, input.readRawLittleEndian32());
-      assertTrue(input.isAtEnd());
-    }
-  }
-
-  /**
-   * Parses the given bytes using readRawLittleEndian64() and checks
-   * that the result matches the given value.
-   */
-  private void assertReadLittleEndian64(byte[] data, long value)
-                                        throws Exception {
-    CodedInputStream input = CodedInputStream.newInstance(data);
-    assertEquals(value, input.readRawLittleEndian64());
-    assertTrue(input.isAtEnd());
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      input = CodedInputStream.newInstance(
-        new SmallBlockInputStream(data, blockSize));
-      assertEquals(value, input.readRawLittleEndian64());
-      assertTrue(input.isAtEnd());
-    }
-  }
-
-  /** Tests readRawLittleEndian32() and readRawLittleEndian64(). */
-  public void testReadLittleEndian() throws Exception {
-    assertReadLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
-    assertReadLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
-
-    assertReadLittleEndian64(
-      bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
-      0x123456789abcdef0L);
-    assertReadLittleEndian64(
-      bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
-      0x9abcdef012345678L);
-  }
-
-  /** Test decodeZigZag32() and decodeZigZag64(). */
-  public void testDecodeZigZag() throws Exception {
-    assertEquals( 0, CodedInputStream.decodeZigZag32(0));
-    assertEquals(-1, CodedInputStream.decodeZigZag32(1));
-    assertEquals( 1, CodedInputStream.decodeZigZag32(2));
-    assertEquals(-2, CodedInputStream.decodeZigZag32(3));
-    assertEquals(0x3FFFFFFF, CodedInputStream.decodeZigZag32(0x7FFFFFFE));
-    assertEquals(0xC0000000, CodedInputStream.decodeZigZag32(0x7FFFFFFF));
-    assertEquals(0x7FFFFFFF, CodedInputStream.decodeZigZag32(0xFFFFFFFE));
-    assertEquals(0x80000000, CodedInputStream.decodeZigZag32(0xFFFFFFFF));
-
-    assertEquals( 0, CodedInputStream.decodeZigZag64(0));
-    assertEquals(-1, CodedInputStream.decodeZigZag64(1));
-    assertEquals( 1, CodedInputStream.decodeZigZag64(2));
-    assertEquals(-2, CodedInputStream.decodeZigZag64(3));
-    assertEquals(0x000000003FFFFFFFL,
-                 CodedInputStream.decodeZigZag64(0x000000007FFFFFFEL));
-    assertEquals(0xFFFFFFFFC0000000L,
-                 CodedInputStream.decodeZigZag64(0x000000007FFFFFFFL));
-    assertEquals(0x000000007FFFFFFFL,
-                 CodedInputStream.decodeZigZag64(0x00000000FFFFFFFEL));
-    assertEquals(0xFFFFFFFF80000000L,
-                 CodedInputStream.decodeZigZag64(0x00000000FFFFFFFFL));
-    assertEquals(0x7FFFFFFFFFFFFFFFL,
-                 CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFEL));
-    assertEquals(0x8000000000000000L,
-                 CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFFL));
-  }
-
-  /** Tests reading and parsing a whole message with every field type. */
-  public void testReadWholeMessage() throws Exception {
-    TestAllTypes message = TestUtil.getAllSet();
-
-    byte[] rawBytes = message.toByteArray();
-    assertEquals(rawBytes.length, message.getSerializedSize());
-
-    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
-    TestUtil.assertAllFieldsSet(message2);
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
-      message2 = TestAllTypes.parseFrom(
-        new SmallBlockInputStream(rawBytes, blockSize));
-      TestUtil.assertAllFieldsSet(message2);
-    }
-  }
-
-  /** Tests skipField(). */
-  public void testSkipWholeMessage() throws Exception {
-    TestAllTypes message = TestUtil.getAllSet();
-    byte[] rawBytes = message.toByteArray();
-
-    // Create two parallel inputs.  Parse one as unknown fields while using
-    // skipField() to skip each field on the other.  Expect the same tags.
-    CodedInputStream input1 = CodedInputStream.newInstance(rawBytes);
-    CodedInputStream input2 = CodedInputStream.newInstance(rawBytes);
-    UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder();
-
-    while (true) {
-      int tag = input1.readTag();
-      assertEquals(tag, input2.readTag());
-      if (tag == 0) {
-        break;
-      }
-      unknownFields.mergeFieldFrom(tag, input1);
-      input2.skipField(tag);
-    }
-  }
-
-  /**
-   * Test that a bug in skipRawBytes() has been fixed:  if the skip skips
-   * exactly up to a limit, this should not break things.
-   */
-  public void testSkipRawBytesBug() throws Exception {
-    byte[] rawBytes = new byte[] { 1, 2 };
-    CodedInputStream input = CodedInputStream.newInstance(rawBytes);
-
-    int limit = input.pushLimit(1);
-    input.skipRawBytes(1);
-    input.popLimit(limit);
-    assertEquals(2, input.readRawByte());
-  }
-
-  /**
-   * Test that a bug in skipRawBytes() has been fixed:  if the skip skips
-   * past the end of a buffer with a limit that has been set past the end of
-   * that buffer, this should not break things.
-   */
-  public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
-    byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
-    CodedInputStream input = CodedInputStream.newInstance(
-        new SmallBlockInputStream(rawBytes, 3));
-
-    int limit = input.pushLimit(4);
-    // In order to expose the bug we need to read at least one byte to prime the
-    // buffer inside the CodedInputStream.
-    assertEquals(1, input.readRawByte());
-    // Skip to the end of the limit.
-    input.skipRawBytes(3);
-    assertTrue(input.isAtEnd());
-    input.popLimit(limit);
-    assertEquals(5, input.readRawByte());
-  }
-
-  public void testReadHugeBlob() throws Exception {
-    // Allocate and initialize a 1MB blob.
-    byte[] blob = new byte[1 << 20];
-    for (int i = 0; i < blob.length; i++) {
-      blob[i] = (byte)i;
-    }
-
-    // Make a message containing it.
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    builder.setOptionalBytes(ByteString.copyFrom(blob));
-    TestAllTypes message = builder.build();
-
-    // Serialize and parse it.  Make sure to parse from an InputStream, not
-    // directly from a ByteString, so that CodedInputStream uses buffered
-    // reading.
-    TestAllTypes message2 =
-      TestAllTypes.parseFrom(message.toByteString().newInput());
-
-    assertEquals(message.getOptionalBytes(), message2.getOptionalBytes());
-
-    // Make sure all the other fields were parsed correctly.
-    TestAllTypes message3 = TestAllTypes.newBuilder(message2)
-      .setOptionalBytes(TestUtil.getAllSet().getOptionalBytes())
-      .build();
-    TestUtil.assertAllFieldsSet(message3);
-  }
-
-  public int makeTag(int number, int tag) {
-    return (number << 3) + tag;
-  }
-
-  public void testReadMaliciouslyLargeBlob() throws Exception {
-    ByteString.Output rawOutput = ByteString.newOutput();
-    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-
-    int tag = makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
-    output.writeRawVarint32(tag);
-    output.writeRawVarint32(0x7FFFFFFF);
-    output.writeRawBytes(new byte[32]);  // Pad with a few random bytes.
-    output.flush();
-
-    CodedInputStream input = rawOutput.toByteString().newCodedInput();
-    assertEquals(tag, input.readTag());
-
-    try {
-      input.readBytes();
-      fail("Should have thrown an exception!");
-    } catch (InvalidProtocolBufferException e) {
-      // success.
-    }
-  }
-
-  private TestRecursiveMessage makeRecursiveMessage(int depth) {
-    if (depth == 0) {
-      return TestRecursiveMessage.newBuilder().setI(5).build();
-    } else {
-      return TestRecursiveMessage.newBuilder()
-        .setA(makeRecursiveMessage(depth - 1)).build();
-    }
-  }
-
-  private void assertMessageDepth(TestRecursiveMessage message, int depth) {
-    if (depth == 0) {
-      assertFalse(message.hasA());
-      assertEquals(5, message.getI());
-    } else {
-      assertTrue(message.hasA());
-      assertMessageDepth(message.getA(), depth - 1);
-    }
-  }
-
-  public void testResetSizeCounter() throws Exception {
-    CodedInputStream input = CodedInputStream.newInstance(
-        new SmallBlockInputStream(new byte[256], 8));
-    input.setSizeLimit(16);
-    input.readRawBytes(16);
-    assertEquals(16, input.getTotalBytesRead());
-
-    try {
-      input.readRawByte();
-      fail("Should have thrown an exception!");
-    } catch (InvalidProtocolBufferException e) {
-      // success.
-    }
-
-    input.resetSizeCounter();
-    assertEquals(0, input.getTotalBytesRead());
-    input.readRawByte();  // No exception thrown.
-    input.resetSizeCounter();
-    assertEquals(0, input.getTotalBytesRead());
-  }
-
-  /**
-   * Tests that if we read an string that contains invalid UTF-8, no exception
-   * is thrown.  Instead, the invalid bytes are replaced with the Unicode
-   * "replacement character" U+FFFD.
-   */
-  public void testReadInvalidUtf8() throws Exception {
-    ByteString.Output rawOutput = ByteString.newOutput();
-    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-
-    int tag = makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
-    output.writeRawVarint32(tag);
-    output.writeRawVarint32(1);
-    output.writeRawBytes(new byte[] { (byte)0x80 });
-    output.flush();
-
-    CodedInputStream input = rawOutput.toByteString().newCodedInput();
-    assertEquals(tag, input.readTag());
-    String text = input.readString();
-    assertEquals(0xfffd, text.charAt(0));
-  }
-
-  public void testReadFromSlice() throws Exception {
-    byte[] bytes = bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
-    CodedInputStream in = CodedInputStream.newInstance(bytes, 3, 5);
-    assertEquals(0, in.getTotalBytesRead());
-    for (int i = 3; i < 8; i++) {
-      assertEquals(i, in.readRawByte());
-      assertEquals(i-2, in.getTotalBytesRead());
-    }
-    // eof
-    assertEquals(0, in.readTag());
-    assertEquals(5, in.getTotalBytesRead());
-  }
-
-  public void testInvalidTag() throws Exception {
-    // Any tag number which corresponds to field number zero is invalid and
-    // should throw InvalidProtocolBufferException.
-    for (int i = 0; i < 8; i++) {
-      try {
-        CodedInputStream.newInstance(bytes(i)).readTag();
-        fail("Should have thrown an exception.");
-      } catch (InvalidProtocolBufferException e) {
-      }
-    }
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedOutputStreamTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedOutputStreamTest.java
deleted file mode 100644
index 354d89d..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedOutputStreamTest.java
+++ /dev/null
@@ -1,318 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto.SparseEnumMessage;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestPackedTypes;
-import protobuf_unittest.UnittestProto.TestSparseEnum;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Unit test for {@link CodedOutputStream}.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class CodedOutputStreamTest extends TestCase {
-  /**
-   * Helper to construct a byte array from a bunch of bytes.  The inputs are
-   * actually ints so that I can use hex notation and not get stupid errors
-   * about precision.
-   */
-  private byte[] bytes(int... bytesAsInts) {
-    byte[] bytes = new byte[bytesAsInts.length];
-    for (int i = 0; i < bytesAsInts.length; i++) {
-      bytes[i] = (byte) bytesAsInts[i];
-    }
-    return bytes;
-  }
-
-  /** Arrays.asList() does not work with arrays of primitives.  :( */
-  private List<Byte> toList(byte[] bytes) {
-    List<Byte> result = new ArrayList<Byte>();
-    for (byte b : bytes) {
-      result.add(b);
-    }
-    return result;
-  }
-
-  private void assertEqualBytes(byte[] a, byte[] b) {
-    assertEquals(toList(a), toList(b));
-  }
-
-  /**
-   * Writes the given value using writeRawVarint32() and writeRawVarint64() and
-   * checks that the result matches the given bytes.
-   */
-  private void assertWriteVarint(byte[] data, long value) throws Exception {
-    // Only do 32-bit write if the value fits in 32 bits.
-    if ((value >>> 32) == 0) {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-      output.writeRawVarint32((int) value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
-
-      // Also try computing size.
-      assertEquals(data.length,
-                   CodedOutputStream.computeRawVarint32Size((int) value));
-    }
-
-    {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-      output.writeRawVarint64(value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
-
-      // Also try computing size.
-      assertEquals(data.length,
-                   CodedOutputStream.computeRawVarint64Size(value));
-    }
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      // Only do 32-bit write if the value fits in 32 bits.
-      if ((value >>> 32) == 0) {
-        ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-        CodedOutputStream output =
-          CodedOutputStream.newInstance(rawOutput, blockSize);
-        output.writeRawVarint32((int) value);
-        output.flush();
-        assertEqualBytes(data, rawOutput.toByteArray());
-      }
-
-      {
-        ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-        CodedOutputStream output =
-          CodedOutputStream.newInstance(rawOutput, blockSize);
-        output.writeRawVarint64(value);
-        output.flush();
-        assertEqualBytes(data, rawOutput.toByteArray());
-      }
-    }
-  }
-
-  /** Tests writeRawVarint32() and writeRawVarint64(). */
-  public void testWriteVarint() throws Exception {
-    assertWriteVarint(bytes(0x00), 0);
-    assertWriteVarint(bytes(0x01), 1);
-    assertWriteVarint(bytes(0x7f), 127);
-    // 14882
-    assertWriteVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
-    // 2961488830
-    assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
-      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-      (0x0bL << 28));
-
-    // 64-bit
-    // 7256456126
-    assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
-      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-      (0x1bL << 28));
-    // 41256202580718336
-    assertWriteVarint(
-      bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
-      (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
-      (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
-    // 11964378330978735131
-    assertWriteVarint(
-      bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
-      (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
-      (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
-      (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
-  }
-
-  /**
-   * Parses the given bytes using writeRawLittleEndian32() and checks
-   * that the result matches the given value.
-   */
-  private void assertWriteLittleEndian32(byte[] data, int value)
-                                         throws Exception {
-    ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-    output.writeRawLittleEndian32(value);
-    output.flush();
-    assertEqualBytes(data, rawOutput.toByteArray());
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      rawOutput = new ByteArrayOutputStream();
-      output = CodedOutputStream.newInstance(rawOutput, blockSize);
-      output.writeRawLittleEndian32(value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
-    }
-  }
-
-  /**
-   * Parses the given bytes using writeRawLittleEndian64() and checks
-   * that the result matches the given value.
-   */
-  private void assertWriteLittleEndian64(byte[] data, long value)
-                                         throws Exception {
-    ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-    output.writeRawLittleEndian64(value);
-    output.flush();
-    assertEqualBytes(data, rawOutput.toByteArray());
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      rawOutput = new ByteArrayOutputStream();
-      output = CodedOutputStream.newInstance(rawOutput, blockSize);
-      output.writeRawLittleEndian64(value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
-    }
-  }
-
-  /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */
-  public void testWriteLittleEndian() throws Exception {
-    assertWriteLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
-    assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
-
-    assertWriteLittleEndian64(
-      bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
-      0x123456789abcdef0L);
-    assertWriteLittleEndian64(
-      bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
-      0x9abcdef012345678L);
-  }
-
-  /** Test encodeZigZag32() and encodeZigZag64(). */
-  public void testEncodeZigZag() throws Exception {
-    assertEquals(0, CodedOutputStream.encodeZigZag32( 0));
-    assertEquals(1, CodedOutputStream.encodeZigZag32(-1));
-    assertEquals(2, CodedOutputStream.encodeZigZag32( 1));
-    assertEquals(3, CodedOutputStream.encodeZigZag32(-2));
-    assertEquals(0x7FFFFFFE, CodedOutputStream.encodeZigZag32(0x3FFFFFFF));
-    assertEquals(0x7FFFFFFF, CodedOutputStream.encodeZigZag32(0xC0000000));
-    assertEquals(0xFFFFFFFE, CodedOutputStream.encodeZigZag32(0x7FFFFFFF));
-    assertEquals(0xFFFFFFFF, CodedOutputStream.encodeZigZag32(0x80000000));
-
-    assertEquals(0, CodedOutputStream.encodeZigZag64( 0));
-    assertEquals(1, CodedOutputStream.encodeZigZag64(-1));
-    assertEquals(2, CodedOutputStream.encodeZigZag64( 1));
-    assertEquals(3, CodedOutputStream.encodeZigZag64(-2));
-    assertEquals(0x000000007FFFFFFEL,
-                 CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL));
-    assertEquals(0x000000007FFFFFFFL,
-                 CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L));
-    assertEquals(0x00000000FFFFFFFEL,
-                 CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL));
-    assertEquals(0x00000000FFFFFFFFL,
-                 CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L));
-    assertEquals(0xFFFFFFFFFFFFFFFEL,
-                 CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL));
-    assertEquals(0xFFFFFFFFFFFFFFFFL,
-                 CodedOutputStream.encodeZigZag64(0x8000000000000000L));
-
-    // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
-    // were chosen semi-randomly via keyboard bashing.
-    assertEquals(0,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0)));
-    assertEquals(1,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1)));
-    assertEquals(-1,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1)));
-    assertEquals(14927,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927)));
-    assertEquals(-3612,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612)));
-
-    assertEquals(0,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0)));
-    assertEquals(1,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1)));
-    assertEquals(-1,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1)));
-    assertEquals(14927,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927)));
-    assertEquals(-3612,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612)));
-
-    assertEquals(856912304801416L,
-      CodedOutputStream.encodeZigZag64(
-        CodedInputStream.decodeZigZag64(
-          856912304801416L)));
-    assertEquals(-75123905439571256L,
-      CodedOutputStream.encodeZigZag64(
-        CodedInputStream.decodeZigZag64(
-          -75123905439571256L)));
-  }
-
-  /** Tests writing a whole message with every field type. */
-  public void testWriteWholeMessage() throws Exception {
-    TestAllTypes message = TestUtil.getAllSet();
-
-    byte[] rawBytes = message.toByteArray();
-    assertEqualBytes(TestUtil.getGoldenMessage().toByteArray(), rawBytes);
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output =
-        CodedOutputStream.newInstance(rawOutput, blockSize);
-      message.writeTo(output);
-      output.flush();
-      assertEqualBytes(rawBytes, rawOutput.toByteArray());
-    }
-  }
-
-  /** Tests writing a whole message with every packed field type. Ensures the
-   * wire format of packed fields is compatible with C++. */
-  public void testWriteWholePackedFieldsMessage() throws Exception {
-    TestPackedTypes message = TestUtil.getPackedSet();
-
-    byte[] rawBytes = message.toByteArray();
-    assertEqualBytes(TestUtil.getGoldenPackedFieldsMessage().toByteArray(),
-                     rawBytes);
-  }
-
-  /** Test writing a message containing a negative enum value. This used to
-   * fail because the size was not properly computed as a sign-extended varint.
-   */
-  public void testWriteMessageWithNegativeEnumValue() throws Exception {
-    SparseEnumMessage message = SparseEnumMessage.newBuilder()
-        .setSparseEnum(TestSparseEnum.SPARSE_E) .build();
-    assertTrue(message.getSparseEnum().getNumber() < 0);
-    byte[] rawBytes = message.toByteArray();
-    SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
-    assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java
deleted file mode 100644
index a7b7706..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto.TestDeprecatedFields;
-
-import junit.framework.TestCase;
-
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Method;
-/**
- * Test field deprecation
- *
- * @author birdo@google.com (Roberto Scaramuzzi)
- */
-public class DeprecatedFieldTest extends TestCase {
-  private String[] deprecatedGetterNames = {
-      "hasDeprecatedInt32",
-      "getDeprecatedInt32"};
-
-  private String[] deprecatedBuilderGetterNames = {
-      "hasDeprecatedInt32",
-      "getDeprecatedInt32",
-      "clearDeprecatedInt32"};
-
-  private String[] deprecatedBuilderSetterNames = {
-      "setDeprecatedInt32"};
-
-  public void testDeprecatedField() throws Exception {
-    Class<?> deprecatedFields = TestDeprecatedFields.class;
-    Class<?> deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class;
-    for (String name : deprecatedGetterNames) {
-      Method method = deprecatedFields.getMethod(name);
-      assertTrue("Method " + name + " should be deprecated",
-          isDeprecated(method));
-    }
-    for (String name : deprecatedBuilderGetterNames) {
-      Method method = deprecatedFieldsBuilder.getMethod(name);
-      assertTrue("Method " + name + " should be deprecated",
-          isDeprecated(method));
-    }
-    for (String name : deprecatedBuilderSetterNames) {
-      Method method = deprecatedFieldsBuilder.getMethod(name, int.class);
-      assertTrue("Method " + name + " should be deprecated",
-          isDeprecated(method));
-    }
-  }
-
-  private boolean isDeprecated(AnnotatedElement annotated) {
-    return annotated.isAnnotationPresent(Deprecated.class);
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java
deleted file mode 100644
index 37e1ca7..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java
+++ /dev/null
@@ -1,649 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import com.google.protobuf.DescriptorProtos.DescriptorProto;
-import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
-import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
-import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
-import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
-import com.google.protobuf.Descriptors.DescriptorValidationException;
-import com.google.protobuf.Descriptors.FileDescriptor;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.Descriptors.EnumDescriptor;
-import com.google.protobuf.Descriptors.EnumValueDescriptor;
-import com.google.protobuf.Descriptors.ServiceDescriptor;
-import com.google.protobuf.Descriptors.MethodDescriptor;
-
-import com.google.protobuf.test.UnittestImport;
-import com.google.protobuf.test.UnittestImport.ImportEnum;
-import com.google.protobuf.test.UnittestImport.ImportMessage;
-import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.ForeignEnum;
-import protobuf_unittest.UnittestProto.ForeignMessage;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
-import protobuf_unittest.UnittestProto.TestRequired;
-import protobuf_unittest.UnittestProto.TestService;
-import protobuf_unittest.UnittestCustomOptions;
-
-
-import junit.framework.TestCase;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Unit test for {@link Descriptors}.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class DescriptorsTest extends TestCase {
-
-  // Regression test for bug where referencing a FieldDescriptor.Type value
-  // before a FieldDescriptorProto.Type value would yield a
-  // ExceptionInInitializerError.
-  @SuppressWarnings("unused")
-  private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
-
-  public void testFieldTypeEnumMapping() throws Exception {
-    assertEquals(FieldDescriptor.Type.values().length,
-        FieldDescriptorProto.Type.values().length);
-    for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
-      FieldDescriptorProto.Type protoType = type.toProto();
-      assertEquals("TYPE_" + type.name(), protoType.name());
-      assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
-    }
-  }
-
-  public void testFileDescriptor() throws Exception {
-    FileDescriptor file = UnittestProto.getDescriptor();
-
-    assertEquals("google/protobuf/unittest.proto", file.getName());
-    assertEquals("protobuf_unittest", file.getPackage());
-
-    assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
-    assertEquals("google/protobuf/unittest.proto",
-                 file.toProto().getName());
-
-    assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
-                 file.getDependencies());
-
-    Descriptor messageType = TestAllTypes.getDescriptor();
-    assertEquals(messageType, file.getMessageTypes().get(0));
-    assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
-    assertNull(file.findMessageTypeByName("NoSuchType"));
-    assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
-    for (int i = 0; i < file.getMessageTypes().size(); i++) {
-      assertEquals(i, file.getMessageTypes().get(i).getIndex());
-    }
-
-    EnumDescriptor enumType = ForeignEnum.getDescriptor();
-    assertEquals(enumType, file.getEnumTypes().get(0));
-    assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
-    assertNull(file.findEnumTypeByName("NoSuchType"));
-    assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
-    assertEquals(Arrays.asList(ImportEnum.getDescriptor()),
-                 UnittestImport.getDescriptor().getEnumTypes());
-    for (int i = 0; i < file.getEnumTypes().size(); i++) {
-      assertEquals(i, file.getEnumTypes().get(i).getIndex());
-    }
-
-    ServiceDescriptor service = TestService.getDescriptor();
-    assertEquals(service, file.getServices().get(0));
-    assertEquals(service, file.findServiceByName("TestService"));
-    assertNull(file.findServiceByName("NoSuchType"));
-    assertNull(file.findServiceByName("protobuf_unittest.TestService"));
-    assertEquals(Collections.emptyList(),
-                 UnittestImport.getDescriptor().getServices());
-    for (int i = 0; i < file.getServices().size(); i++) {
-      assertEquals(i, file.getServices().get(i).getIndex());
-    }
-
-    FieldDescriptor extension =
-      UnittestProto.optionalInt32Extension.getDescriptor();
-    assertEquals(extension, file.getExtensions().get(0));
-    assertEquals(extension,
-                 file.findExtensionByName("optional_int32_extension"));
-    assertNull(file.findExtensionByName("no_such_ext"));
-    assertNull(file.findExtensionByName(
-      "protobuf_unittest.optional_int32_extension"));
-    assertEquals(Collections.emptyList(),
-                 UnittestImport.getDescriptor().getExtensions());
-    for (int i = 0; i < file.getExtensions().size(); i++) {
-      assertEquals(i, file.getExtensions().get(i).getIndex());
-    }
-  }
-
-  public void testDescriptor() throws Exception {
-    Descriptor messageType = TestAllTypes.getDescriptor();
-    Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();
-
-    assertEquals("TestAllTypes", messageType.getName());
-    assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
-    assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
-    assertNull(messageType.getContainingType());
-    assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
-                 messageType.getOptions());
-    assertEquals("TestAllTypes", messageType.toProto().getName());
-
-    assertEquals("NestedMessage", nestedType.getName());
-    assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
-                 nestedType.getFullName());
-    assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
-    assertEquals(messageType, nestedType.getContainingType());
-
-    FieldDescriptor field = messageType.getFields().get(0);
-    assertEquals("optional_int32", field.getName());
-    assertEquals(field, messageType.findFieldByName("optional_int32"));
-    assertNull(messageType.findFieldByName("no_such_field"));
-    assertEquals(field, messageType.findFieldByNumber(1));
-    assertNull(messageType.findFieldByNumber(571283));
-    for (int i = 0; i < messageType.getFields().size(); i++) {
-      assertEquals(i, messageType.getFields().get(i).getIndex());
-    }
-
-    assertEquals(nestedType, messageType.getNestedTypes().get(0));
-    assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
-    assertNull(messageType.findNestedTypeByName("NoSuchType"));
-    for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
-      assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
-    }
-
-    EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
-    assertEquals(enumType, messageType.getEnumTypes().get(0));
-    assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
-    assertNull(messageType.findEnumTypeByName("NoSuchType"));
-    for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
-      assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
-    }
-  }
-
-  public void testFieldDescriptor() throws Exception {
-    Descriptor messageType = TestAllTypes.getDescriptor();
-    FieldDescriptor primitiveField =
-      messageType.findFieldByName("optional_int32");
-    FieldDescriptor enumField =
-      messageType.findFieldByName("optional_nested_enum");
-    FieldDescriptor messageField =
-      messageType.findFieldByName("optional_foreign_message");
-    FieldDescriptor cordField =
-      messageType.findFieldByName("optional_cord");
-    FieldDescriptor extension =
-      UnittestProto.optionalInt32Extension.getDescriptor();
-    FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
-
-    assertEquals("optional_int32", primitiveField.getName());
-    assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
-                 primitiveField.getFullName());
-    assertEquals(1, primitiveField.getNumber());
-    assertEquals(messageType, primitiveField.getContainingType());
-    assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
-    assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
-    assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
-    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
-                 primitiveField.getOptions());
-    assertFalse(primitiveField.isExtension());
-    assertEquals("optional_int32", primitiveField.toProto().getName());
-
-    assertEquals("optional_nested_enum", enumField.getName());
-    assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
-    assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
-    assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
-                 enumField.getEnumType());
-
-    assertEquals("optional_foreign_message", messageField.getName());
-    assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
-    assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
-    assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
-
-    assertEquals("optional_cord", cordField.getName());
-    assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
-    assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
-    assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
-                 cordField.getOptions().getCtype());
-
-    assertEquals("optional_int32_extension", extension.getName());
-    assertEquals("protobuf_unittest.optional_int32_extension",
-                 extension.getFullName());
-    assertEquals(1, extension.getNumber());
-    assertEquals(TestAllExtensions.getDescriptor(),
-                 extension.getContainingType());
-    assertEquals(UnittestProto.getDescriptor(), extension.getFile());
-    assertEquals(FieldDescriptor.Type.INT32, extension.getType());
-    assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
-    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
-                 extension.getOptions());
-    assertTrue(extension.isExtension());
-    assertEquals(null, extension.getExtensionScope());
-    assertEquals("optional_int32_extension", extension.toProto().getName());
-
-    assertEquals("single", nestedExtension.getName());
-    assertEquals("protobuf_unittest.TestRequired.single",
-                 nestedExtension.getFullName());
-    assertEquals(TestRequired.getDescriptor(),
-                 nestedExtension.getExtensionScope());
-  }
-
-  public void testFieldDescriptorLabel() throws Exception {
-    FieldDescriptor requiredField =
-      TestRequired.getDescriptor().findFieldByName("a");
-    FieldDescriptor optionalField =
-      TestAllTypes.getDescriptor().findFieldByName("optional_int32");
-    FieldDescriptor repeatedField =
-      TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
-
-    assertTrue(requiredField.isRequired());
-    assertFalse(requiredField.isRepeated());
-    assertFalse(optionalField.isRequired());
-    assertFalse(optionalField.isRepeated());
-    assertFalse(repeatedField.isRequired());
-    assertTrue(repeatedField.isRepeated());
-  }
-
-  public void testFieldDescriptorDefault() throws Exception {
-    Descriptor d = TestAllTypes.getDescriptor();
-    assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
-    assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
-    assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
-    assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());
-
-    d = TestExtremeDefaultValues.getDescriptor();
-    assertEquals(
-      ByteString.copyFrom(
-        "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes("ISO-8859-1")),
-      d.findFieldByName("escaped_bytes").getDefaultValue());
-    assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
-    assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
-  }
-
-  public void testEnumDescriptor() throws Exception {
-    EnumDescriptor enumType = ForeignEnum.getDescriptor();
-    EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();
-
-    assertEquals("ForeignEnum", enumType.getName());
-    assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
-    assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
-    assertNull(enumType.getContainingType());
-    assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
-                 enumType.getOptions());
-
-    assertEquals("NestedEnum", nestedType.getName());
-    assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
-                 nestedType.getFullName());
-    assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
-    assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
-
-    EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
-    assertEquals(value, enumType.getValues().get(0));
-    assertEquals("FOREIGN_FOO", value.getName());
-    assertEquals(4, value.getNumber());
-    assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
-    assertEquals(value, enumType.findValueByNumber(4));
-    assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
-    for (int i = 0; i < enumType.getValues().size(); i++) {
-      assertEquals(i, enumType.getValues().get(i).getIndex());
-    }
-  }
-
-  public void testServiceDescriptor() throws Exception {
-    ServiceDescriptor service = TestService.getDescriptor();
-
-    assertEquals("TestService", service.getName());
-    assertEquals("protobuf_unittest.TestService", service.getFullName());
-    assertEquals(UnittestProto.getDescriptor(), service.getFile());
-
-    assertEquals(2, service.getMethods().size());
-
-    MethodDescriptor fooMethod = service.getMethods().get(0);
-    assertEquals("Foo", fooMethod.getName());
-    assertEquals(UnittestProto.FooRequest.getDescriptor(),
-                 fooMethod.getInputType());
-    assertEquals(UnittestProto.FooResponse.getDescriptor(),
-                 fooMethod.getOutputType());
-    assertEquals(fooMethod, service.findMethodByName("Foo"));
-
-    MethodDescriptor barMethod = service.getMethods().get(1);
-    assertEquals("Bar", barMethod.getName());
-    assertEquals(UnittestProto.BarRequest.getDescriptor(),
-                 barMethod.getInputType());
-    assertEquals(UnittestProto.BarResponse.getDescriptor(),
-                 barMethod.getOutputType());
-    assertEquals(barMethod, service.findMethodByName("Bar"));
-
-    assertNull(service.findMethodByName("NoSuchMethod"));
-
-    for (int i = 0; i < service.getMethods().size(); i++) {
-      assertEquals(i, service.getMethods().get(i).getIndex());
-    }
-  }
-
-
-  public void testCustomOptions() throws Exception {
-    Descriptor descriptor =
-      UnittestCustomOptions.TestMessageWithCustomOptions.getDescriptor();
-
-    assertTrue(
-      descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
-    assertEquals(Integer.valueOf(-56),
-      descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
-
-    FieldDescriptor field = descriptor.findFieldByName("field1");
-    assertNotNull(field);
-
-    assertTrue(
-      field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
-    assertEquals(Long.valueOf(8765432109L),
-      field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
-
-    EnumDescriptor enumType =
-      UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
-
-    assertTrue(
-      enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
-    assertEquals(Integer.valueOf(-789),
-      enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
-
-    ServiceDescriptor service =
-      UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
-
-    assertTrue(
-      service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
-    assertEquals(Long.valueOf(-9876543210L),
-      service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
-
-    MethodDescriptor method = service.findMethodByName("Foo");
-    assertNotNull(method);
-
-    assertTrue(
-      method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
-    assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
-      method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
-  }
-
-  /**
-   * Test that the FieldDescriptor.Type enum is the same as the
-   * WireFormat.FieldType enum.
-   */
-  public void testFieldTypeTablesMatch() throws Exception {
-    FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
-    WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
-
-    assertEquals(values1.length, values2.length);
-
-    for (int i = 0; i < values1.length; i++) {
-      assertEquals(values1[i].toString(), values2[i].toString());
-    }
-  }
-
-  /**
-   * Test that the FieldDescriptor.JavaType enum is the same as the
-   * WireFormat.JavaType enum.
-   */
-  public void testJavaTypeTablesMatch() throws Exception {
-    FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
-    WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
-
-    assertEquals(values1.length, values2.length);
-
-    for (int i = 0; i < values1.length; i++) {
-      assertEquals(values1[i].toString(), values2[i].toString());
-    }
-  }
-
-  public void testEnormousDescriptor() throws Exception {
-    // The descriptor for this file is larger than 64k, yet it did not cause
-    // a compiler error due to an over-long string literal.
-    assertTrue(
-        UnittestEnormousDescriptor.getDescriptor()
-          .toProto().getSerializedSize() > 65536);
-  }
-
-  /**
-   * Tests that the DescriptorValidationException works as intended.
-   */
-  public void testDescriptorValidatorException() throws Exception {
-    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
-      .setName("foo.proto")
-      .addMessageType(DescriptorProto.newBuilder()
-      .setName("Foo")
-        .addField(FieldDescriptorProto.newBuilder()
-          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-          .setType(FieldDescriptorProto.Type.TYPE_INT32)
-          .setName("foo")
-          .setNumber(1)
-          .setDefaultValue("invalid")
-          .build())
-        .build())
-      .build();
-    try {
-      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
-          new FileDescriptor[0]);
-      fail("DescriptorValidationException expected");
-    } catch (DescriptorValidationException e) {
-      // Expected; check that the error message contains some useful hints
-      assertTrue(e.getMessage().indexOf("foo") != -1);
-      assertTrue(e.getMessage().indexOf("Foo") != -1);
-      assertTrue(e.getMessage().indexOf("invalid") != -1);
-      assertTrue(e.getCause() instanceof NumberFormatException);
-      assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
-    }
-  }
-
-  /**
-   * Tests the translate/crosslink for an example where a message field's name
-   * and type name are the same.
-   */
-  public void testDescriptorComplexCrosslink() throws Exception {
-    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
-      .setName("foo.proto")
-      .addMessageType(DescriptorProto.newBuilder()
-        .setName("Foo")
-        .addField(FieldDescriptorProto.newBuilder()
-          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-          .setType(FieldDescriptorProto.Type.TYPE_INT32)
-          .setName("foo")
-          .setNumber(1)
-          .build())
-        .build())
-      .addMessageType(DescriptorProto.newBuilder()
-        .setName("Bar")
-        .addField(FieldDescriptorProto.newBuilder()
-          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-          .setTypeName("Foo")
-          .setName("Foo")
-          .setNumber(1)
-          .build())
-        .build())
-      .build();
-    // translate and crosslink
-    FileDescriptor file =
-      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
-          new FileDescriptor[0]);
-    // verify resulting descriptors
-    assertNotNull(file);
-    List<Descriptor> msglist = file.getMessageTypes();
-    assertNotNull(msglist);
-    assertTrue(msglist.size() == 2);
-    boolean barFound = false;
-    for (Descriptor desc : msglist) {
-      if (desc.getName().equals("Bar")) {
-        barFound = true;
-        assertNotNull(desc.getFields());
-        List<FieldDescriptor> fieldlist = desc.getFields();
-        assertNotNull(fieldlist);
-        assertTrue(fieldlist.size() == 1);
-        assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
-        assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
-      }
-    }
-    assertTrue(barFound);
-  }
-
-  public void testInvalidPublicDependency() throws Exception {
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto") .build();
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("boo.proto")
-        .addDependency("foo.proto")
-        .addPublicDependency(1)  // Error, should be 0.
-        .build();
-    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
-        new FileDescriptor[0]);
-    try {
-      Descriptors.FileDescriptor.buildFrom(barProto,
-          new FileDescriptor[] {fooFile});
-      fail("DescriptorValidationException expected");
-    } catch (DescriptorValidationException e) {
-      assertTrue(
-          e.getMessage().indexOf("Invalid public dependency index.") != -1);
-    }
-  }
-
-  public void testHiddenDependency() throws Exception {
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("bar.proto")
-        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
-        .build();
-    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
-        .setName("forward.proto")
-        .addDependency("bar.proto")
-        .build();
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addDependency("forward.proto")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("Foo")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-                .setTypeName("Bar")
-                .setName("bar")
-                .setNumber(1)))
-        .build();
-    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
-        barProto, new FileDescriptor[0]);
-    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
-        forwardProto, new FileDescriptor[] {barFile});
-
-    try {
-      Descriptors.FileDescriptor.buildFrom(
-          fooProto, new FileDescriptor[] {forwardFile});
-      fail("DescriptorValidationException expected");
-    } catch (DescriptorValidationException e) {
-      assertTrue(e.getMessage().indexOf("Bar") != -1);
-      assertTrue(e.getMessage().indexOf("is not defined") != -1);
-    }
-  }
-
-  public void testPublicDependency() throws Exception {
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("bar.proto")
-        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
-        .build();
-    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
-        .setName("forward.proto")
-        .addDependency("bar.proto")
-        .addPublicDependency(0)
-        .build();
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addDependency("forward.proto")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("Foo")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-                .setTypeName("Bar")
-                .setName("bar")
-                .setNumber(1)))
-        .build();
-    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
-        barProto, new FileDescriptor[0]);
-    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
-        forwardProto, new FileDescriptor[]{barFile});
-    Descriptors.FileDescriptor.buildFrom(
-        fooProto, new FileDescriptor[] {forwardFile});
-  }
-
-  /**
-   * Tests the translate/crosslink for an example with a more complex namespace
-   * referencing.
-   */
-  public void testComplexNamespacePublicDependency() throws Exception {
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("bar.proto")
-        .setPackage("a.b.c.d.bar.shared")
-        .addEnumType(EnumDescriptorProto.newBuilder()
-            .setName("MyEnum")
-            .addValue(EnumValueDescriptorProto.newBuilder()
-                .setName("BLAH")
-                .setNumber(1)))
-        .build();
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addDependency("bar.proto")
-        .setPackage("a.b.c.d.foo.shared")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("MyMessage")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
-                .setTypeName("bar.shared.MyEnum")
-                .setName("MyField")
-                .setNumber(1)))
-        .build();
-    // translate and crosslink
-    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
-        fooProto, new FileDescriptor[0]);
-    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
-        barProto, new FileDescriptor[]{fooFile});
-    // verify resulting descriptors
-    assertNotNull(barFile);
-    List<Descriptor> msglist = barFile.getMessageTypes();
-    assertNotNull(msglist);
-    assertTrue(msglist.size() == 1);
-    Descriptor desc = msglist.get(0);
-    if (desc.getName().equals("MyMessage")) {
-      assertNotNull(desc.getFields());
-      List<FieldDescriptor> fieldlist = desc.getFields();
-      assertNotNull(fieldlist);
-      assertTrue(fieldlist.size() == 1);
-      FieldDescriptor field = fieldlist.get(0);
-      assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
-      assertTrue(field.getEnumType().getName().equals("MyEnum"));
-      assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
-      assertTrue(field.getEnumType().getFile().getPackage().equals(
-          "a.b.c.d.bar.shared"));
-    }
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DynamicMessageTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DynamicMessageTest.java
deleted file mode 100644
index 0023067..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DynamicMessageTest.java
+++ /dev/null
@@ -1,265 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestEmptyMessage;
-import protobuf_unittest.UnittestProto.TestPackedTypes;
-
-import junit.framework.TestCase;
-import java.util.Arrays;
-
-/**
- * Unit test for {@link DynamicMessage}.  See also {@link MessageTest}, which
- * tests some {@link DynamicMessage} functionality.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class DynamicMessageTest extends TestCase {
-  TestUtil.ReflectionTester reflectionTester =
-    new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
-
-  TestUtil.ReflectionTester extensionsReflectionTester =
-    new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
-                                  TestUtil.getExtensionRegistry());
-  TestUtil.ReflectionTester packedReflectionTester =
-    new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
-
-  public void testDynamicMessageAccessors() throws Exception {
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    reflectionTester.setAllFieldsViaReflection(builder);
-    Message message = builder.build();
-    reflectionTester.assertAllFieldsSetViaReflection(message);
-  }
-
-  public void testSettersAfterBuild() throws Exception {
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    Message firstMessage = builder.build();
-    // double build()
-    builder.build();
-    // clear() after build()
-    builder.clear();
-    // setters after build()
-    reflectionTester.setAllFieldsViaReflection(builder);
-    Message message = builder.build();
-    reflectionTester.assertAllFieldsSetViaReflection(message);
-    // repeated setters after build()
-    reflectionTester.modifyRepeatedFieldsViaReflection(builder);
-    message = builder.build();
-    reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
-    // firstMessage shouldn't have been modified.
-    reflectionTester.assertClearViaReflection(firstMessage);
-  }
-
-  public void testUnknownFields() throws Exception {
-    Message.Builder builder =
-        DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
-    builder.setUnknownFields(UnknownFieldSet.newBuilder()
-        .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
-        .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
-        .build());
-    Message message = builder.build();
-    assertEquals(2, message.getUnknownFields().asMap().size());
-    // clone() with unknown fields
-    Message.Builder newBuilder = builder.clone();
-    assertEquals(2, newBuilder.getUnknownFields().asMap().size());
-    // clear() with unknown fields
-    newBuilder.clear();
-    assertTrue(newBuilder.getUnknownFields().asMap().isEmpty());
-    // serialize/parse with unknown fields
-    newBuilder.mergeFrom(message.toByteString());
-    assertEquals(2, newBuilder.getUnknownFields().asMap().size());
-  }
-
-  public void testDynamicMessageSettersRejectNull() throws Exception {
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    reflectionTester.assertReflectionSettersRejectNull(builder);
-  }
-
-  public void testDynamicMessageExtensionAccessors() throws Exception {
-    // We don't need to extensively test DynamicMessage's handling of
-    // extensions because, frankly, it doesn't do anything special with them.
-    // It treats them just like any other fields.
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
-    extensionsReflectionTester.setAllFieldsViaReflection(builder);
-    Message message = builder.build();
-    extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
-  }
-
-  public void testDynamicMessageExtensionSettersRejectNull() throws Exception {
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
-    extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
-  }
-
-  public void testDynamicMessageRepeatedSetters() throws Exception {
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    reflectionTester.setAllFieldsViaReflection(builder);
-    reflectionTester.modifyRepeatedFieldsViaReflection(builder);
-    Message message = builder.build();
-    reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
-  }
-
-  public void testDynamicMessageRepeatedSettersRejectNull() throws Exception {
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
-  }
-
-  public void testDynamicMessageDefaults() throws Exception {
-    reflectionTester.assertClearViaReflection(
-      DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor()));
-    reflectionTester.assertClearViaReflection(
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build());
-  }
-
-  public void testDynamicMessageSerializedSize() throws Exception {
-    TestAllTypes message = TestUtil.getAllSet();
-
-    Message.Builder dynamicBuilder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    reflectionTester.setAllFieldsViaReflection(dynamicBuilder);
-    Message dynamicMessage = dynamicBuilder.build();
-
-    assertEquals(message.getSerializedSize(),
-                 dynamicMessage.getSerializedSize());
-  }
-
-  public void testDynamicMessageSerialization() throws Exception {
-    Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    reflectionTester.setAllFieldsViaReflection(builder);
-    Message message = builder.build();
-
-    ByteString rawBytes = message.toByteString();
-    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
-
-    TestUtil.assertAllFieldsSet(message2);
-
-    // In fact, the serialized forms should be exactly the same, byte-for-byte.
-    assertEquals(TestUtil.getAllSet().toByteString(), rawBytes);
-  }
-
-  public void testDynamicMessageParsing() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    TestAllTypes message = builder.build();
-
-    ByteString rawBytes = message.toByteString();
-
-    Message message2 =
-      DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
-    reflectionTester.assertAllFieldsSetViaReflection(message2);
-
-    // Test Parser interface.
-    Message message3 = message2.getParserForType().parseFrom(rawBytes);
-    reflectionTester.assertAllFieldsSetViaReflection(message3);
-  }
-
-  public void testDynamicMessageExtensionParsing() throws Exception {
-    ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
-    Message message = DynamicMessage.parseFrom(
-        TestAllExtensions.getDescriptor(), rawBytes,
-        TestUtil.getExtensionRegistry());
-    extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
-
-    // Test Parser interface.
-    Message message2 = message.getParserForType().parseFrom(
-        rawBytes, TestUtil.getExtensionRegistry());
-    extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
-  }
-
-  public void testDynamicMessagePackedSerialization() throws Exception {
-    Message.Builder builder =
-        DynamicMessage.newBuilder(TestPackedTypes.getDescriptor());
-    packedReflectionTester.setPackedFieldsViaReflection(builder);
-    Message message = builder.build();
-
-    ByteString rawBytes = message.toByteString();
-    TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
-
-    TestUtil.assertPackedFieldsSet(message2);
-
-    // In fact, the serialized forms should be exactly the same, byte-for-byte.
-    assertEquals(TestUtil.getPackedSet().toByteString(), rawBytes);
-  }
-
-  public void testDynamicMessagePackedParsing() throws Exception {
-    TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
-    TestUtil.setPackedFields(builder);
-    TestPackedTypes message = builder.build();
-
-    ByteString rawBytes = message.toByteString();
-
-    Message message2 =
-      DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
-    packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
-
-    // Test Parser interface.
-    Message message3 = message2.getParserForType().parseFrom(rawBytes);
-    packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
-  }
-
-  public void testDynamicMessageCopy() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    TestAllTypes message = builder.build();
-
-    DynamicMessage copy = DynamicMessage.newBuilder(message).build();
-    reflectionTester.assertAllFieldsSetViaReflection(copy);
-  }
-
-  public void testToBuilder() throws Exception {
-    DynamicMessage.Builder builder =
-        DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    reflectionTester.setAllFieldsViaReflection(builder);
-    int unknownFieldNum = 9;
-    long unknownFieldVal = 90;
-    builder.setUnknownFields(UnknownFieldSet.newBuilder()
-        .addField(unknownFieldNum,
-            UnknownFieldSet.Field.newBuilder()
-                .addVarint(unknownFieldVal).build())
-        .build());
-    DynamicMessage message = builder.build();
-
-    DynamicMessage derived = message.toBuilder().build();
-    reflectionTester.assertAllFieldsSetViaReflection(derived);
-    assertEquals(Arrays.asList(unknownFieldVal),
-        derived.getUnknownFields().getField(unknownFieldNum).getVarintList());
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ForceFieldBuildersPreRun.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ForceFieldBuildersPreRun.java
deleted file mode 100644
index 6a39500..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ForceFieldBuildersPreRun.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-/**
- * A prerun for a test suite that allows running the full protocol buffer
- * tests in a mode that disables the optimization for not using
- * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are
- * requested. This allows us to run all the tests through both code paths
- * and ensures that both code paths produce identical results.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class ForceFieldBuildersPreRun implements Runnable {
-
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
-  public void run() {
-    // GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java
deleted file mode 100644
index 1e7d41e..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java
+++ /dev/null
@@ -1,961 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.test.UnittestImport;
-import protobuf_unittest.EnumWithNoOuter;
-import protobuf_unittest.MessageWithNoOuter;
-import protobuf_unittest.MultipleFilesTestProto;
-import protobuf_unittest.NestedExtension.MyNestedExtension;
-import protobuf_unittest.NonNestedExtension;
-import protobuf_unittest.NonNestedExtension.MessageToBeExtended;
-import protobuf_unittest.NonNestedExtension.MyNonNestedExtension;
-import protobuf_unittest.ServiceWithNoOuter;
-import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
-import protobuf_unittest.UnittestOptimizeFor.TestOptionalOptimizedForSize;
-import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
-import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.ForeignEnum;
-import protobuf_unittest.UnittestProto.ForeignMessage;
-import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
-import protobuf_unittest.UnittestProto.TestPackedTypes;
-import protobuf_unittest.UnittestProto.TestUnpackedTypes;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Unit test for generated messages and generated code.  See also
- * {@link MessageTest}, which tests some generated message functionality.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class GeneratedMessageTest extends TestCase {
-  TestUtil.ReflectionTester reflectionTester =
-    new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
-
-  public void testDefaultInstance() throws Exception {
-    assertSame(TestAllTypes.getDefaultInstance(),
-               TestAllTypes.getDefaultInstance().getDefaultInstanceForType());
-    assertSame(TestAllTypes.getDefaultInstance(),
-               TestAllTypes.newBuilder().getDefaultInstanceForType());
-  }
-
-  public void testMessageOrBuilder() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    TestAllTypes message = builder.build();
-    TestUtil.assertAllFieldsSet(message);
-  }
-
-  public void testUsingBuilderMultipleTimes() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    // primitive field scalar and repeated
-    builder.setOptionalSfixed64(100);
-    builder.addRepeatedInt32(100);
-    // enum field scalar and repeated
-    builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
-    builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
-    // proto field scalar and repeated
-    builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(1));
-    builder.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(1));
-
-    TestAllTypes value1 = builder.build();
-
-    assertEquals(100, value1.getOptionalSfixed64());
-    assertEquals(100, value1.getRepeatedInt32(0));
-    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
-        value1.getOptionalImportEnum());
-    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
-        value1.getRepeatedImportEnum(0));
-    assertEquals(1, value1.getOptionalForeignMessage().getC());
-    assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
-
-    // Make sure that builder didn't update previously created values
-    builder.setOptionalSfixed64(200);
-    builder.setRepeatedInt32(0, 200);
-    builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_FOO);
-    builder.setRepeatedImportEnum(0, UnittestImport.ImportEnum.IMPORT_FOO);
-    builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(2));
-    builder.setRepeatedForeignMessage(0, ForeignMessage.newBuilder().setC(2));
-
-    TestAllTypes value2 = builder.build();
-
-    // Make sure value1 didn't change.
-    assertEquals(100, value1.getOptionalSfixed64());
-    assertEquals(100, value1.getRepeatedInt32(0));
-    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
-        value1.getOptionalImportEnum());
-    assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
-        value1.getRepeatedImportEnum(0));
-    assertEquals(1, value1.getOptionalForeignMessage().getC());
-    assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
-
-    // Make sure value2 is correct
-    assertEquals(200, value2.getOptionalSfixed64());
-    assertEquals(200, value2.getRepeatedInt32(0));
-    assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
-        value2.getOptionalImportEnum());
-    assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
-        value2.getRepeatedImportEnum(0));
-    assertEquals(2, value2.getOptionalForeignMessage().getC());
-    assertEquals(2, value2.getRepeatedForeignMessage(0).getC());
-  }
-
-  public void testRepeatedArraysAreImmutable() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    builder.addRepeatedInt32(100);
-    builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
-    builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
-    assertIsUnmodifiable(builder.getRepeatedInt32List());
-    assertIsUnmodifiable(builder.getRepeatedImportEnumList());
-    assertIsUnmodifiable(builder.getRepeatedForeignMessageList());
-    assertIsUnmodifiable(builder.getRepeatedFloatList());
-
-
-    TestAllTypes value = builder.build();
-    assertIsUnmodifiable(value.getRepeatedInt32List());
-    assertIsUnmodifiable(value.getRepeatedImportEnumList());
-    assertIsUnmodifiable(value.getRepeatedForeignMessageList());
-    assertIsUnmodifiable(value.getRepeatedFloatList());
-  }
-
-  public void testParsedMessagesAreImmutable() throws Exception {
-    TestAllTypes value = TestAllTypes.PARSER.parseFrom(
-        TestUtil.getAllSet().toByteString());
-    assertIsUnmodifiable(value.getRepeatedInt32List());
-    assertIsUnmodifiable(value.getRepeatedInt64List());
-    assertIsUnmodifiable(value.getRepeatedUint32List());
-    assertIsUnmodifiable(value.getRepeatedUint64List());
-    assertIsUnmodifiable(value.getRepeatedSint32List());
-    assertIsUnmodifiable(value.getRepeatedSint64List());
-    assertIsUnmodifiable(value.getRepeatedFixed32List());
-    assertIsUnmodifiable(value.getRepeatedFixed64List());
-    assertIsUnmodifiable(value.getRepeatedSfixed32List());
-    assertIsUnmodifiable(value.getRepeatedSfixed64List());
-    assertIsUnmodifiable(value.getRepeatedFloatList());
-    assertIsUnmodifiable(value.getRepeatedDoubleList());
-    assertIsUnmodifiable(value.getRepeatedBoolList());
-    assertIsUnmodifiable(value.getRepeatedStringList());
-    assertIsUnmodifiable(value.getRepeatedBytesList());
-    assertIsUnmodifiable(value.getRepeatedGroupList());
-    assertIsUnmodifiable(value.getRepeatedNestedMessageList());
-    assertIsUnmodifiable(value.getRepeatedForeignMessageList());
-    assertIsUnmodifiable(value.getRepeatedImportMessageList());
-    assertIsUnmodifiable(value.getRepeatedNestedEnumList());
-    assertIsUnmodifiable(value.getRepeatedForeignEnumList());
-    assertIsUnmodifiable(value.getRepeatedImportEnumList());
-  }
-
-  private void assertIsUnmodifiable(List<?> list) {
-    if (list == Collections.emptyList()) {
-      // OKAY -- Need to check this b/c EmptyList allows you to call clear.
-    } else {
-      try {
-        list.clear();
-        fail("List wasn't immutable");
-      } catch (UnsupportedOperationException e) {
-        // good
-      }
-    }
-  }
-
-  public void testSettersRejectNull() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    try {
-      builder.setOptionalString(null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.setOptionalBytes(null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.setOptionalNestedMessage(
-          (TestAllTypes.NestedMessage.Builder) null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.setOptionalNestedEnum(null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.addRepeatedString(null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.addRepeatedBytes(null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.addRepeatedNestedMessage(
-          (TestAllTypes.NestedMessage.Builder) null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.addRepeatedNestedEnum(null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-  }
-
-  public void testRepeatedSetters() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    TestUtil.modifyRepeatedFields(builder);
-    TestAllTypes message = builder.build();
-    TestUtil.assertRepeatedFieldsModified(message);
-  }
-
-  public void testRepeatedSettersRejectNull() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-
-    builder.addRepeatedString("one");
-    builder.addRepeatedString("two");
-    try {
-      builder.setRepeatedString(1, null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-
-    builder.addRepeatedBytes(TestUtil.toBytes("one"));
-    builder.addRepeatedBytes(TestUtil.toBytes("two"));
-    try {
-      builder.setRepeatedBytes(1, null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-
-    builder.addRepeatedNestedMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
-    builder.addRepeatedNestedMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(456).build());
-    try {
-      builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.setRepeatedNestedMessage(
-          1, (TestAllTypes.NestedMessage.Builder) null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-
-    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.FOO);
-    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
-    try {
-      builder.setRepeatedNestedEnum(1, null);
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-  }
-
-  public void testRepeatedAppend() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-
-    builder.addAllRepeatedInt32(Arrays.asList(1, 2, 3, 4));
-    builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ));
-
-    ForeignMessage foreignMessage =
-        ForeignMessage.newBuilder().setC(12).build();
-    builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage));
-
-    TestAllTypes message = builder.build();
-    assertEquals(message.getRepeatedInt32List(), Arrays.asList(1, 2, 3, 4));
-    assertEquals(message.getRepeatedForeignEnumList(),
-        Arrays.asList(ForeignEnum.FOREIGN_BAZ));
-    assertEquals(1, message.getRepeatedForeignMessageCount());
-    assertEquals(12, message.getRepeatedForeignMessage(0).getC());
-  }
-
-  public void testRepeatedAppendRejectsNull() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-
-    ForeignMessage foreignMessage =
-        ForeignMessage.newBuilder().setC(12).build();
-    try {
-      builder.addAllRepeatedForeignMessage(
-          Arrays.asList(foreignMessage, (ForeignMessage) null));
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-
-    try {
-      builder.addAllRepeatedForeignEnum(
-          Arrays.asList(ForeignEnum.FOREIGN_BAZ, null));
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-
-    try {
-      builder.addAllRepeatedString(Arrays.asList("one", null));
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-
-    try {
-      builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null));
-      fail("Exception was not thrown");
-    } catch (NullPointerException e) {
-      // We expect this exception.
-    }
-  }
-
-  public void testSettingForeignMessageUsingBuilder() throws Exception {
-    TestAllTypes message = TestAllTypes.newBuilder()
-        // Pass builder for foreign message instance.
-        .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123))
-        .build();
-    TestAllTypes expectedMessage = TestAllTypes.newBuilder()
-        // Create expected version passing foreign message instance explicitly.
-        .setOptionalForeignMessage(
-            ForeignMessage.newBuilder().setC(123).build())
-        .build();
-    // TODO(ngd): Upgrade to using real #equals method once implemented
-    assertEquals(expectedMessage.toString(), message.toString());
-  }
-
-  public void testSettingRepeatedForeignMessageUsingBuilder() throws Exception {
-    TestAllTypes message = TestAllTypes.newBuilder()
-        // Pass builder for foreign message instance.
-        .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456))
-        .build();
-    TestAllTypes expectedMessage = TestAllTypes.newBuilder()
-        // Create expected version passing foreign message instance explicitly.
-        .addRepeatedForeignMessage(
-            ForeignMessage.newBuilder().setC(456).build())
-        .build();
-    assertEquals(expectedMessage.toString(), message.toString());
-  }
-
-  public void testDefaults() throws Exception {
-    TestUtil.assertClear(TestAllTypes.getDefaultInstance());
-    TestUtil.assertClear(TestAllTypes.newBuilder().build());
-
-    TestExtremeDefaultValues message =
-        TestExtremeDefaultValues.getDefaultInstance();
-    assertEquals("\u1234", message.getUtf8String());
-    assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble());
-    assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble());
-    assertTrue(Double.isNaN(message.getNanDouble()));
-    assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
-    assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
-    assertTrue(Float.isNaN(message.getNanFloat()));
-    assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph());
-  }
-
-  public void testClear() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.assertClear(builder);
-    TestUtil.setAllFields(builder);
-    builder.clear();
-    TestUtil.assertClear(builder);
-  }
-
-  public void testReflectionGetters() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    reflectionTester.assertAllFieldsSetViaReflection(builder);
-
-    TestAllTypes message = builder.build();
-    reflectionTester.assertAllFieldsSetViaReflection(message);
-  }
-
-  public void testReflectionSetters() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    reflectionTester.setAllFieldsViaReflection(builder);
-    TestUtil.assertAllFieldsSet(builder);
-
-    TestAllTypes message = builder.build();
-    TestUtil.assertAllFieldsSet(message);
-  }
-
-  public void testReflectionSettersRejectNull() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    reflectionTester.assertReflectionSettersRejectNull(builder);
-  }
-
-  public void testReflectionRepeatedSetters() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    reflectionTester.setAllFieldsViaReflection(builder);
-    reflectionTester.modifyRepeatedFieldsViaReflection(builder);
-    TestUtil.assertRepeatedFieldsModified(builder);
-
-    TestAllTypes message = builder.build();
-    TestUtil.assertRepeatedFieldsModified(message);
-  }
-
-  public void testReflectionRepeatedSettersRejectNull() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
-  }
-
-  public void testReflectionDefaults() throws Exception {
-    reflectionTester.assertClearViaReflection(
-      TestAllTypes.getDefaultInstance());
-    reflectionTester.assertClearViaReflection(
-      TestAllTypes.newBuilder().build());
-  }
-
-  public void testEnumInterface() throws Exception {
-    assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum()
-        instanceof ProtocolMessageEnum);
-  }
-
-  public void testEnumMap() throws Exception {
-    Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
-
-    for (ForeignEnum value : ForeignEnum.values()) {
-      assertEquals(value, map.findValueByNumber(value.getNumber()));
-    }
-
-    assertTrue(map.findValueByNumber(12345) == null);
-  }
-
-  public void testParsePackedToUnpacked() throws Exception {
-    TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
-    TestUnpackedTypes message =
-      builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
-    TestUtil.assertUnpackedFieldsSet(message);
-  }
-
-  public void testParseUnpackedToPacked() throws Exception {
-    TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
-    TestPackedTypes message =
-      builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
-    TestUtil.assertPackedFieldsSet(message);
-  }
-
-  // =================================================================
-  // Extensions.
-
-  TestUtil.ReflectionTester extensionsReflectionTester =
-    new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
-                                  TestUtil.getExtensionRegistry());
-
-  public void testExtensionMessageOrBuilder() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    TestUtil.setAllExtensions(builder);
-    TestAllExtensions message = builder.build();
-    TestUtil.assertAllExtensionsSet(message);
-  }
-
-  public void testExtensionRepeatedSetters() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    TestUtil.setAllExtensions(builder);
-    TestUtil.modifyRepeatedExtensions(builder);
-    TestAllExtensions message = builder.build();
-    TestUtil.assertRepeatedExtensionsModified(message);
-  }
-
-  public void testExtensionDefaults() throws Exception {
-    TestUtil.assertExtensionsClear(TestAllExtensions.getDefaultInstance());
-    TestUtil.assertExtensionsClear(TestAllExtensions.newBuilder().build());
-  }
-
-  public void testExtensionReflectionGetters() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    TestUtil.setAllExtensions(builder);
-    extensionsReflectionTester.assertAllFieldsSetViaReflection(builder);
-
-    TestAllExtensions message = builder.build();
-    extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
-  }
-
-  public void testExtensionReflectionSetters() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    extensionsReflectionTester.setAllFieldsViaReflection(builder);
-    TestUtil.assertAllExtensionsSet(builder);
-
-    TestAllExtensions message = builder.build();
-    TestUtil.assertAllExtensionsSet(message);
-  }
-
-  public void testExtensionReflectionSettersRejectNull() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
-  }
-
-  public void testExtensionReflectionRepeatedSetters() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    extensionsReflectionTester.setAllFieldsViaReflection(builder);
-    extensionsReflectionTester.modifyRepeatedFieldsViaReflection(builder);
-    TestUtil.assertRepeatedExtensionsModified(builder);
-
-    TestAllExtensions message = builder.build();
-    TestUtil.assertRepeatedExtensionsModified(message);
-  }
-
-  public void testExtensionReflectionRepeatedSettersRejectNull()
-      throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull(
-        builder);
-  }
-
-  public void testExtensionReflectionDefaults() throws Exception {
-    extensionsReflectionTester.assertClearViaReflection(
-      TestAllExtensions.getDefaultInstance());
-    extensionsReflectionTester.assertClearViaReflection(
-      TestAllExtensions.newBuilder().build());
-  }
-
-  public void testClearExtension() throws Exception {
-    // clearExtension() is not actually used in TestUtil, so try it manually.
-    assertFalse(
-      TestAllExtensions.newBuilder()
-        .setExtension(UnittestProto.optionalInt32Extension, 1)
-        .clearExtension(UnittestProto.optionalInt32Extension)
-        .hasExtension(UnittestProto.optionalInt32Extension));
-    assertEquals(0,
-      TestAllExtensions.newBuilder()
-        .addExtension(UnittestProto.repeatedInt32Extension, 1)
-        .clearExtension(UnittestProto.repeatedInt32Extension)
-        .getExtensionCount(UnittestProto.repeatedInt32Extension));
-  }
-
-  public void testExtensionCopy() throws Exception {
-    TestAllExtensions original = TestUtil.getAllExtensionsSet();
-    TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
-    TestUtil.assertAllExtensionsSet(copy);
-  }
-
-  public void testExtensionMergeFrom() throws Exception {
-    TestAllExtensions original =
-      TestAllExtensions.newBuilder()
-        .setExtension(UnittestProto.optionalInt32Extension, 1).build();
-    TestAllExtensions merged =
-        TestAllExtensions.newBuilder().mergeFrom(original).build();
-    assertTrue(merged.hasExtension(UnittestProto.optionalInt32Extension));
-    assertEquals(
-        1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
-  }
-
-  // =================================================================
-  // multiple_files_test
-
-  public void testMultipleFilesOption() throws Exception {
-    // We mostly just want to check that things compile.
-    MessageWithNoOuter message =
-      MessageWithNoOuter.newBuilder()
-        .setNested(MessageWithNoOuter.NestedMessage.newBuilder().setI(1))
-        .addForeign(TestAllTypes.newBuilder().setOptionalInt32(1))
-        .setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ)
-        .setForeignEnum(EnumWithNoOuter.BAR)
-        .build();
-    assertEquals(message, MessageWithNoOuter.parseFrom(message.toByteString()));
-
-    assertEquals(MultipleFilesTestProto.getDescriptor(),
-                 MessageWithNoOuter.getDescriptor().getFile());
-
-    Descriptors.FieldDescriptor field =
-      MessageWithNoOuter.getDescriptor().findFieldByName("foreign_enum");
-    assertEquals(EnumWithNoOuter.BAR.getValueDescriptor(),
-                 message.getField(field));
-
-    assertEquals(MultipleFilesTestProto.getDescriptor(),
-                 ServiceWithNoOuter.getDescriptor().getFile());
-
-    assertFalse(
-      TestAllExtensions.getDefaultInstance().hasExtension(
-        MultipleFilesTestProto.extensionWithOuter));
-  }
-
-  public void testOptionalFieldWithRequiredSubfieldsOptimizedForSize()
-    throws Exception {
-    TestOptionalOptimizedForSize message =
-        TestOptionalOptimizedForSize.getDefaultInstance();
-    assertTrue(message.isInitialized());
-
-    message = TestOptionalOptimizedForSize.newBuilder().setO(
-        TestRequiredOptimizedForSize.newBuilder().buildPartial()
-        ).buildPartial();
-    assertFalse(message.isInitialized());
-
-    message = TestOptionalOptimizedForSize.newBuilder().setO(
-        TestRequiredOptimizedForSize.newBuilder().setX(5).buildPartial()
-        ).buildPartial();
-    assertTrue(message.isInitialized());
-  }
-
-  public void testUninitializedExtensionInOptimizedForSize()
-      throws Exception {
-    TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
-    builder.setExtension(TestOptimizedForSize.testExtension2,
-        TestRequiredOptimizedForSize.newBuilder().buildPartial());
-    assertFalse(builder.isInitialized());
-    assertFalse(builder.buildPartial().isInitialized());
-
-    builder = TestOptimizedForSize.newBuilder();
-    builder.setExtension(TestOptimizedForSize.testExtension2,
-        TestRequiredOptimizedForSize.newBuilder().setX(10).buildPartial());
-    assertTrue(builder.isInitialized());
-    assertTrue(builder.buildPartial().isInitialized());
-  }
-
-  public void testToBuilder() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    TestAllTypes message = builder.build();
-    TestUtil.assertAllFieldsSet(message);
-    TestUtil.assertAllFieldsSet(message.toBuilder().build());
-  }
-
-  public void testFieldConstantValues() throws Exception {
-    assertEquals(TestAllTypes.NestedMessage.BB_FIELD_NUMBER, 1);
-    assertEquals(TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER, 1);
-    assertEquals(TestAllTypes.OPTIONALGROUP_FIELD_NUMBER, 16);
-    assertEquals(TestAllTypes.OPTIONAL_NESTED_MESSAGE_FIELD_NUMBER, 18);
-    assertEquals(TestAllTypes.OPTIONAL_NESTED_ENUM_FIELD_NUMBER, 21);
-    assertEquals(TestAllTypes.REPEATED_INT32_FIELD_NUMBER, 31);
-    assertEquals(TestAllTypes.REPEATEDGROUP_FIELD_NUMBER, 46);
-    assertEquals(TestAllTypes.REPEATED_NESTED_MESSAGE_FIELD_NUMBER, 48);
-    assertEquals(TestAllTypes.REPEATED_NESTED_ENUM_FIELD_NUMBER, 51);
-  }
-
-  public void testExtensionConstantValues() throws Exception {
-    assertEquals(UnittestProto.TestRequired.SINGLE_FIELD_NUMBER, 1000);
-    assertEquals(UnittestProto.TestRequired.MULTI_FIELD_NUMBER, 1001);
-    assertEquals(UnittestProto.OPTIONAL_INT32_EXTENSION_FIELD_NUMBER, 1);
-    assertEquals(UnittestProto.OPTIONALGROUP_EXTENSION_FIELD_NUMBER, 16);
-    assertEquals(
-      UnittestProto.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18);
-    assertEquals(UnittestProto.OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 21);
-    assertEquals(UnittestProto.REPEATED_INT32_EXTENSION_FIELD_NUMBER, 31);
-    assertEquals(UnittestProto.REPEATEDGROUP_EXTENSION_FIELD_NUMBER, 46);
-    assertEquals(
-      UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48);
-    assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51);
-  }
-
-  public void testRecursiveMessageDefaultInstance() throws Exception {
-    UnittestProto.TestRecursiveMessage message =
-        UnittestProto.TestRecursiveMessage.getDefaultInstance();
-    assertTrue(message != null);
-    assertTrue(message.getA() != null);
-    assertTrue(message.getA() == message);
-  }
-
-  public void testSerialize() throws Exception {
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestUtil.setAllFields(builder);
-    TestAllTypes expected = builder.build();
-    ObjectOutputStream out = new ObjectOutputStream(baos);
-    try {
-      out.writeObject(expected);
-    } finally {
-      out.close();
-    }
-    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-    ObjectInputStream in = new ObjectInputStream(bais);
-    TestAllTypes actual = (TestAllTypes) in.readObject();
-    assertEquals(expected, actual);
-  }
-
-  public void testSerializePartial() throws Exception {
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestAllTypes expected = builder.buildPartial();
-    ObjectOutputStream out = new ObjectOutputStream(baos);
-    try {
-      out.writeObject(expected);
-    } finally {
-      out.close();
-    }
-    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-    ObjectInputStream in = new ObjectInputStream(bais);
-    TestAllTypes actual = (TestAllTypes) in.readObject();
-    assertEquals(expected, actual);
-  }
-
-  public void testEnumValues() {
-     assertEquals(
-         TestAllTypes.NestedEnum.BAR.getNumber(),
-         TestAllTypes.NestedEnum.BAR_VALUE);
-    assertEquals(
-        TestAllTypes.NestedEnum.BAZ.getNumber(),
-        TestAllTypes.NestedEnum.BAZ_VALUE);
-    assertEquals(
-        TestAllTypes.NestedEnum.FOO.getNumber(),
-        TestAllTypes.NestedEnum.FOO_VALUE);
-  }
-
-  public void testNonNestedExtensionInitialization() {
-    assertTrue(NonNestedExtension.nonNestedExtension
-               .getMessageDefaultInstance() instanceof MyNonNestedExtension);
-    assertEquals("nonNestedExtension",
-                 NonNestedExtension.nonNestedExtension.getDescriptor().getName());
-  }
-
-  public void testNestedExtensionInitialization() {
-    assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance()
-               instanceof MessageToBeExtended);
-    assertEquals("recursiveExtension",
-                 MyNestedExtension.recursiveExtension.getDescriptor().getName());
-  }
-
-
-  public void testBaseMessageOrBuilder() {
-    // Mostly just makes sure the base interface exists and has some methods.
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestAllTypes message = builder.buildPartial();
-    TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder;
-    TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message;
-
-    assertEquals(
-        messageAsInterface.getDefaultBool(),
-        messageAsInterface.getDefaultBool());
-    assertEquals(
-        messageAsInterface.getOptionalDouble(),
-        messageAsInterface.getOptionalDouble());
-  }
-
-  public void testMessageOrBuilderGetters() {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-
-    // single fields
-    assertSame(ForeignMessage.getDefaultInstance(),
-        builder.getOptionalForeignMessageOrBuilder());
-    ForeignMessage.Builder subBuilder =
-        builder.getOptionalForeignMessageBuilder();
-    assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder());
-
-    // repeated fields
-    ForeignMessage m0 = ForeignMessage.newBuilder().buildPartial();
-    ForeignMessage m1 = ForeignMessage.newBuilder().buildPartial();
-    ForeignMessage m2 = ForeignMessage.newBuilder().buildPartial();
-    builder.addRepeatedForeignMessage(m0);
-    builder.addRepeatedForeignMessage(m1);
-    builder.addRepeatedForeignMessage(m2);
-    assertSame(m0, builder.getRepeatedForeignMessageOrBuilder(0));
-    assertSame(m1, builder.getRepeatedForeignMessageOrBuilder(1));
-    assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
-    ForeignMessage.Builder b0 = builder.getRepeatedForeignMessageBuilder(0);
-    ForeignMessage.Builder b1 = builder.getRepeatedForeignMessageBuilder(1);
-    assertSame(b0, builder.getRepeatedForeignMessageOrBuilder(0));
-    assertSame(b1, builder.getRepeatedForeignMessageOrBuilder(1));
-    assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
-
-    List<? extends ForeignMessageOrBuilder> messageOrBuilderList =
-        builder.getRepeatedForeignMessageOrBuilderList();
-    assertSame(b0, messageOrBuilderList.get(0));
-    assertSame(b1, messageOrBuilderList.get(1));
-    assertSame(m2, messageOrBuilderList.get(2));
-  }
-
-  public void testGetFieldBuilder() {
-    Descriptor descriptor = TestAllTypes.getDescriptor();
-
-    FieldDescriptor fieldDescriptor =
-        descriptor.findFieldByName("optional_nested_message");
-    FieldDescriptor foreignFieldDescriptor =
-        descriptor.findFieldByName("optional_foreign_message");
-    FieldDescriptor importFieldDescriptor =
-        descriptor.findFieldByName("optional_import_message");
-
-    // Mutate the message with new field builder
-    // Mutate nested message
-    TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
-    Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
-        .mergeFrom((Message) builder1.getField(fieldDescriptor));
-    FieldDescriptor subFieldDescriptor1 =
-        fieldBuilder1.getDescriptorForType().findFieldByName("bb");
-    fieldBuilder1.setField(subFieldDescriptor1, 1);
-    builder1.setField(fieldDescriptor, fieldBuilder1.build());
-
-    // Mutate foreign message
-    Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
-        foreignFieldDescriptor)
-        .mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
-    FieldDescriptor subForeignFieldDescriptor1 =
-        foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
-    foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
-    builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
-
-    // Mutate import message
-    Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
-        importFieldDescriptor)
-        .mergeFrom((Message) builder1.getField(importFieldDescriptor));
-    FieldDescriptor subImportFieldDescriptor1 =
-        importFieldBuilder1.getDescriptorForType().findFieldByName("d");
-    importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
-    builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
-
-    Message newMessage1 = builder1.build();
-
-    // Mutate the message with existing field builder
-    // Mutate nested message
-    TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
-    Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
-    FieldDescriptor subFieldDescriptor2 =
-        fieldBuilder2.getDescriptorForType().findFieldByName("bb");
-    fieldBuilder2.setField(subFieldDescriptor2, 1);
-    builder2.setField(fieldDescriptor, fieldBuilder2.build());
-
-    // Mutate foreign message
-    Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
-        foreignFieldDescriptor)
-        .mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
-    FieldDescriptor subForeignFieldDescriptor2 =
-        foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
-    foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
-    builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
-
-    // Mutate import message
-    Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
-        importFieldDescriptor)
-        .mergeFrom((Message) builder2.getField(importFieldDescriptor));
-    FieldDescriptor subImportFieldDescriptor2 =
-        importFieldBuilder2.getDescriptorForType().findFieldByName("d");
-    importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
-    builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
-
-    Message newMessage2 = builder2.build();
-
-    // These two messages should be equal.
-    assertEquals(newMessage1, newMessage2);
-  }
-
-  public void testGetFieldBuilderWithInitializedValue() {
-    Descriptor descriptor = TestAllTypes.getDescriptor();
-    FieldDescriptor fieldDescriptor =
-        descriptor.findFieldByName("optional_nested_message");
-
-    // Before setting field, builder is initialized by default value.
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    NestedMessage.Builder fieldBuilder =
-        (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
-    assertEquals(0, fieldBuilder.getBb());
-
-    // Setting field value with new field builder instance.
-    builder = TestAllTypes.newBuilder();
-    NestedMessage.Builder newFieldBuilder =
-        builder.getOptionalNestedMessageBuilder();
-    newFieldBuilder.setBb(2);
-    // Then get the field builder instance by getFieldBuilder().
-    fieldBuilder =
-        (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
-    // It should contain new value.
-    assertEquals(2, fieldBuilder.getBb());
-    // These two builder should be equal.
-    assertSame(fieldBuilder, newFieldBuilder);
-  }
-
-  public void testGetFieldBuilderNotSupportedException() {
-    Descriptor descriptor = TestAllTypes.getDescriptor();
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    try {
-      builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"));
-      fail("Exception was not thrown");
-    } catch (UnsupportedOperationException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.getFieldBuilder(
-          descriptor.findFieldByName("optional_nested_enum"));
-      fail("Exception was not thrown");
-    } catch (UnsupportedOperationException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"));
-      fail("Exception was not thrown");
-    } catch (UnsupportedOperationException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.getFieldBuilder(
-          descriptor.findFieldByName("repeated_nested_enum"));
-      fail("Exception was not thrown");
-    } catch (UnsupportedOperationException e) {
-      // We expect this exception.
-    }
-    try {
-      builder.getFieldBuilder(
-          descriptor.findFieldByName("repeated_nested_message"));
-      fail("Exception was not thrown");
-    } catch (UnsupportedOperationException e) {
-      // We expect this exception.
-    }
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringArrayListTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringArrayListTest.java
deleted file mode 100644
index 9bc94ee..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringArrayListTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import junit.framework.TestCase;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for {@link LazyStringArrayList}.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class LazyStringArrayListTest extends TestCase {
-
-  private static String STRING_A = "A";
-  private static String STRING_B = "B";
-  private static String STRING_C = "C";
-
-  private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
-  private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
-  private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
-
-  public void testJustStrings() {
-    LazyStringArrayList list = new LazyStringArrayList();
-    list.add(STRING_A);
-    list.add(STRING_B);
-    list.add(STRING_C);
-
-    assertEquals(3, list.size());
-    assertSame(STRING_A, list.get(0));
-    assertSame(STRING_B, list.get(1));
-    assertSame(STRING_C, list.get(2));
-
-    list.set(1, STRING_C);
-    assertSame(STRING_C, list.get(1));
-
-    list.remove(1);
-    assertSame(STRING_A, list.get(0));
-    assertSame(STRING_C, list.get(1));
-  }
-
-  public void testJustByteString() {
-    LazyStringArrayList list = new LazyStringArrayList();
-    list.add(BYTE_STRING_A);
-    list.add(BYTE_STRING_B);
-    list.add(BYTE_STRING_C);
-
-    assertEquals(3, list.size());
-    assertSame(BYTE_STRING_A, list.getByteString(0));
-    assertSame(BYTE_STRING_B, list.getByteString(1));
-    assertSame(BYTE_STRING_C, list.getByteString(2));
-
-    list.remove(1);
-    assertSame(BYTE_STRING_A, list.getByteString(0));
-    assertSame(BYTE_STRING_C, list.getByteString(1));
-  }
-
-  public void testConversionBackAndForth() {
-    LazyStringArrayList list = new LazyStringArrayList();
-    list.add(STRING_A);
-    list.add(BYTE_STRING_B);
-    list.add(BYTE_STRING_C);
-
-    // String a should be the same because it was originally a string
-    assertSame(STRING_A, list.get(0));
-
-    // String b and c should be different because the string has to be computed
-    // from the ByteString
-    String bPrime = list.get(1);
-    assertNotSame(STRING_B, bPrime);
-    assertEquals(STRING_B, bPrime);
-    String cPrime = list.get(2);
-    assertNotSame(STRING_C, cPrime);
-    assertEquals(STRING_C, cPrime);
-
-    // String c and c should stay the same once cached.
-    assertSame(bPrime, list.get(1));
-    assertSame(cPrime, list.get(2));
-
-    // ByteString needs to be computed from string for both a and b
-    ByteString aPrimeByteString = list.getByteString(0);
-    assertEquals(BYTE_STRING_A, aPrimeByteString);
-    ByteString bPrimeByteString = list.getByteString(1);
-    assertNotSame(BYTE_STRING_B, bPrimeByteString);
-    assertEquals(BYTE_STRING_B, list.getByteString(1));
-
-    // Once cached, ByteString should stay cached.
-    assertSame(aPrimeByteString, list.getByteString(0));
-    assertSame(bPrimeByteString, list.getByteString(1));
-  }
-
-  public void testCopyConstructorCopiesByReference() {
-    LazyStringArrayList list1 = new LazyStringArrayList();
-    list1.add(STRING_A);
-    list1.add(BYTE_STRING_B);
-    list1.add(BYTE_STRING_C);
-
-    LazyStringArrayList list2 = new LazyStringArrayList(list1);
-    assertEquals(3, list2.size());
-    assertSame(STRING_A, list2.get(0));
-    assertSame(BYTE_STRING_B, list2.getByteString(1));
-    assertSame(BYTE_STRING_C, list2.getByteString(2));
-  }
-
-  public void testListCopyConstructor() {
-    List<String> list1 = new ArrayList<String>();
-    list1.add(STRING_A);
-    list1.add(STRING_B);
-    list1.add(STRING_C);
-
-    LazyStringArrayList list2 = new LazyStringArrayList(list1);
-    assertEquals(3, list2.size());
-    assertSame(STRING_A, list2.get(0));
-    assertSame(STRING_B, list2.get(1));
-    assertSame(STRING_C, list2.get(2));
-  }
-
-  public void testAddAllCopiesByReferenceIfPossible() {
-    LazyStringArrayList list1 = new LazyStringArrayList();
-    list1.add(STRING_A);
-    list1.add(BYTE_STRING_B);
-    list1.add(BYTE_STRING_C);
-
-    LazyStringArrayList list2 = new LazyStringArrayList();
-    list2.addAll(list1);
-
-    assertEquals(3, list2.size());
-    assertSame(STRING_A, list2.get(0));
-    assertSame(BYTE_STRING_B, list2.getByteString(1));
-    assertSame(BYTE_STRING_C, list2.getByteString(2));
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringEndToEndTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringEndToEndTest.java
deleted file mode 100644
index e21e038..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringEndToEndTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-
-import protobuf_unittest.UnittestProto;
-
-import junit.framework.TestCase;
-
-import java.io.IOException;
-
-/**
- * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to
- * strings works correctly.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class LazyStringEndToEndTest extends TestCase {
-
-  private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 =
-      ByteString.copyFrom(new byte[] {
-          114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
-          0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
-
-  private ByteString encodedTestAllTypes;
-
-  @Override
-  protected void setUp() throws Exception {
-    super.setUp();
-    this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder()
-        .setOptionalString("foo")
-        .addRepeatedString("bar")
-        .addRepeatedString("baz")
-        .build()
-        .toByteString();
-  }
-
-  /**
-   * Tests that an invalid UTF8 string will roundtrip through a parse
-   * and serialization.
-   */
-  public void testParseAndSerialize() throws InvalidProtocolBufferException {
-    UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
-        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
-    ByteString bytes = tV2.toByteString();
-    assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
-
-    tV2.getOptionalString();
-    bytes = tV2.toByteString();
-    assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
-  }
-
-  public void testParseAndWrite() throws IOException {
-    UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
-        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
-    byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()];
-    CodedOutputStream outputStream = CodedOutputStream.newInstance(sink);
-    tV2.writeTo(outputStream);
-    outputStream.flush();
-    assertEquals(
-        TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
-        ByteString.copyFrom(sink));
-  }
-
-  public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
-    UnittestProto.TestAllTypes proto =
-        UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes);
-    ByteString optional = proto.getOptionalStringBytes();
-    assertSame(optional, proto.getOptionalStringBytes());
-    assertSame(optional, proto.toBuilder().getOptionalStringBytes());
-
-    ByteString repeated0 = proto.getRepeatedStringBytes(0);
-    ByteString repeated1 = proto.getRepeatedStringBytes(1);
-    assertSame(repeated0, proto.getRepeatedStringBytes(0));
-    assertSame(repeated1, proto.getRepeatedStringBytes(1));
-    assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0));
-    assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1));
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java
deleted file mode 100644
index d2ce563..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java
+++ /dev/null
@@ -1,344 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-/**
- * Test {@link LiteralByteString} by setting up a reference string in {@link #setUp()}.
- * This class is designed to be extended for testing extensions of {@link LiteralByteString}
- * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}.
- *
- * @author carlanton@google.com (Carl Haverl)
- */
-public class LiteralByteStringTest extends TestCase {
-  protected static final String UTF_8 = "UTF-8";
-
-  protected String classUnderTest;
-  protected byte[] referenceBytes;
-  protected ByteString stringUnderTest;
-  protected int expectedHashCode;
-
-  @Override
-  protected void setUp() throws Exception {
-    classUnderTest = "LiteralByteString";
-    referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
-    stringUnderTest = ByteString.copyFrom(referenceBytes);
-    expectedHashCode = 331161852;
-  }
-
-  protected String getActualClassName(Object object) {
-    String actualClassName = object.getClass().getName();
-    actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
-    return actualClassName;
-  }
-
-  public void testByteAt() {
-    boolean stillEqual = true;
-    for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
-      stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
-    }
-    assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
-  }
-
-  public void testByteIterator() {
-    boolean stillEqual = true;
-    ByteString.ByteIterator iter = stringUnderTest.iterator();
-    for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
-      stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
-    }
-    assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
-    assertFalse(classUnderTest + " must have exhausted the iterator", iter.hasNext());
-
-    try {
-      iter.nextByte();
-      fail("Should have thrown an exception.");
-    } catch (NoSuchElementException e) {
-      // This is success
-    }
-  }
-
-  public void testByteIterable() {
-    boolean stillEqual = true;
-    int j = 0;
-    for (byte quantum : stringUnderTest) {
-      stillEqual = (referenceBytes[j] == quantum);
-      ++j;
-    }
-    assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
-    assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
-  }
-
-  public void testSize() {
-    assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
-        stringUnderTest.size());
-  }
-
-  public void testCopyTo_ByteArrayOffsetLength() {
-    int destinationOffset = 50;
-    int length = 100;
-    byte[] destination = new byte[destinationOffset + length];
-    int sourceOffset = 213;
-    stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
-    boolean stillEqual = true;
-    for (int i = 0; stillEqual && i < length; ++i) {
-      stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
-    }
-    assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
-  }
-
-  public void testCopyTo_ByteArrayOffsetLengthErrors() {
-    int destinationOffset = 50;
-    int length = 100;
-    byte[] destination = new byte[destinationOffset + length];
-
-    try {
-      // Copy one too many bytes
-      stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
-          destinationOffset, length);
-      fail("Should have thrown an exception when copying too many bytes of a "
-          + classUnderTest);
-    } catch (IndexOutOfBoundsException expected) {
-      // This is success
-    }
-
-    try {
-      // Copy with illegal negative sourceOffset
-      stringUnderTest.copyTo(destination, -1, destinationOffset, length);
-      fail("Should have thrown an exception when given a negative sourceOffset in "
-          + classUnderTest);
-    } catch (IndexOutOfBoundsException expected) {
-      // This is success
-    }
-
-    try {
-      // Copy with illegal negative destinationOffset
-      stringUnderTest.copyTo(destination, 0, -1, length);
-      fail("Should have thrown an exception when given a negative destinationOffset in "
-          + classUnderTest);
-    } catch (IndexOutOfBoundsException expected) {
-      // This is success
-    }
-
-    try {
-      // Copy with illegal negative size
-      stringUnderTest.copyTo(destination, 0, 0, -1);
-      fail("Should have thrown an exception when given a negative size in "
-          + classUnderTest);
-    } catch (IndexOutOfBoundsException expected) {
-      // This is success
-    }
-
-    try {
-      // Copy with illegal too-large sourceOffset
-      stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
-      fail("Should have thrown an exception when the destinationOffset is too large in "
-          + classUnderTest);
-    } catch (IndexOutOfBoundsException expected) {
-      // This is success
-    }
-
-    try {
-      // Copy with illegal too-large destinationOffset
-      stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
-      fail("Should have thrown an exception when the destinationOffset is too large in "
-          + classUnderTest);
-    } catch (IndexOutOfBoundsException expected) {
-      // This is success
-    }
-  }
-
-  public void testCopyTo_ByteBuffer() {
-    ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
-    stringUnderTest.copyTo(myBuffer);
-    assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
-        Arrays.equals(referenceBytes, myBuffer.array()));
-  }
-
-  public void testAsReadOnlyByteBuffer() {
-    ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
-    byte[] roundTripBytes = new byte[referenceBytes.length];
-    assertTrue(byteBuffer.remaining() == referenceBytes.length);
-    assertTrue(byteBuffer.isReadOnly());
-    byteBuffer.get(roundTripBytes);
-    assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
-        Arrays.equals(referenceBytes, roundTripBytes));
-  }
-
-  public void testAsReadOnlyByteBufferList() {
-    List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
-    int bytesSeen = 0;
-    byte[] roundTripBytes = new byte[referenceBytes.length];
-    for (ByteBuffer byteBuffer : byteBuffers) {
-      int thisLength = byteBuffer.remaining();
-      assertTrue(byteBuffer.isReadOnly());
-      assertTrue(bytesSeen + thisLength <= referenceBytes.length);
-      byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
-      bytesSeen += thisLength;
-    }
-    assertTrue(bytesSeen == referenceBytes.length);
-    assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
-        Arrays.equals(referenceBytes, roundTripBytes));
-  }
-
-  public void testToByteArray() {
-    byte[] roundTripBytes = stringUnderTest.toByteArray();
-    assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
-        Arrays.equals(referenceBytes, roundTripBytes));
-  }
-
-  public void testWriteTo() throws IOException {
-    ByteArrayOutputStream bos = new ByteArrayOutputStream();
-    stringUnderTest.writeTo(bos);
-    byte[] roundTripBytes = bos.toByteArray();
-    assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
-        Arrays.equals(referenceBytes, roundTripBytes));
-  }
-
-  public void testWriteTo_mutating() throws IOException {
-    OutputStream os = new OutputStream() {
-      @Override
-      public void write(byte[] b, int off, int len) {
-        for (int x = 0; x < len; ++x) {
-          b[off + x] = (byte) 0;
-        }
-      }
-
-      @Override
-      public void write(int b) {
-        // Purposefully left blank.
-      }
-    };
-
-    stringUnderTest.writeTo(os);
-    byte[] newBytes = stringUnderTest.toByteArray();
-    assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
-        Arrays.equals(referenceBytes, newBytes));
-  }
-
-  public void testNewOutput() throws IOException {
-    ByteArrayOutputStream bos = new ByteArrayOutputStream();
-    ByteString.Output output = ByteString.newOutput();
-    stringUnderTest.writeTo(output);
-    assertEquals("Output Size returns correct result",
-        output.size(), stringUnderTest.size());
-    output.writeTo(bos);
-    assertTrue("Output.writeTo() must give back the same bytes",
-        Arrays.equals(referenceBytes, bos.toByteArray()));
-
-    // write the output stream to itself! This should cause it to double
-    output.writeTo(output);
-    assertEquals("Writing an output stream to itself is successful",
-        stringUnderTest.concat(stringUnderTest), output.toByteString());
-
-    output.reset();
-    assertEquals("Output.reset() resets the output", 0, output.size());
-    assertEquals("Output.reset() resets the output",
-        ByteString.EMPTY, output.toByteString());
-
-  }
-
-  public void testHashCode() {
-    int hash = stringUnderTest.hashCode();
-    assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
-  }
-
-  public void testNewInput() throws IOException {
-    InputStream input = stringUnderTest.newInput();
-    assertEquals("InputStream.available() returns correct value",
-        stringUnderTest.size(), input.available());
-    boolean stillEqual = true;
-    for (byte referenceByte : referenceBytes) {
-      int expectedInt = (referenceByte & 0xFF);
-      stillEqual = (expectedInt == input.read());
-    }
-    assertEquals("InputStream.available() returns correct value",
-        0, input.available());
-    assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
-    assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
-  }
-
-  public void testNewInput_skip() throws IOException {
-    InputStream input = stringUnderTest.newInput();
-    int stringSize = stringUnderTest.size();
-    int nearEndIndex = stringSize * 2 / 3;
-    long skipped1 = input.skip(nearEndIndex);
-    assertEquals("InputStream.skip()", skipped1, nearEndIndex);
-    assertEquals("InputStream.available()",
-        stringSize - skipped1, input.available());
-    assertTrue("InputStream.mark() is available", input.markSupported());
-    input.mark(0);
-    assertEquals("InputStream.skip(), read()",
-        stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
-    assertEquals("InputStream.available()",
-                 stringSize - skipped1 - 1, input.available());
-    long skipped2 = input.skip(stringSize);
-    assertEquals("InputStream.skip() incomplete",
-        skipped2, stringSize - skipped1 - 1);
-    assertEquals("InputStream.skip(), no more input", 0, input.available());
-    assertEquals("InputStream.skip(), no more input", -1, input.read());
-    input.reset();
-    assertEquals("InputStream.reset() succeeded",
-                 stringSize - skipped1, input.available());
-    assertEquals("InputStream.reset(), read()",
-        stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
-  }
-
-  public void testNewCodedInput() throws IOException {
-    CodedInputStream cis = stringUnderTest.newCodedInput();
-    byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
-    assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
-        Arrays.equals(referenceBytes, roundTripBytes));
-    assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
-  }
-
-  /**
-   * Make sure we keep things simple when concatenating with empty. See also
-   * {@link ByteStringTest#testConcat_empty()}.
-   */
-  public void testConcat_empty() {
-    assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
-        stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
-    assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
-        ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java
deleted file mode 100644
index 629cabc..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java
+++ /dev/null
@@ -1,354 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestRequired;
-import protobuf_unittest.UnittestProto.TestRequiredForeign;
-import protobuf_unittest.UnittestProto.ForeignMessage;
-
-import junit.framework.TestCase;
-
-import java.util.List;
-
-/**
- * Misc. unit tests for message operations that apply to both generated
- * and dynamic messages.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class MessageTest extends TestCase {
-  // =================================================================
-  // Message-merging tests.
-
-  static final TestAllTypes MERGE_SOURCE =
-    TestAllTypes.newBuilder()
-      .setOptionalInt32(1)
-      .setOptionalString("foo")
-      .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
-      .addRepeatedString("bar")
-      .build();
-
-  static final TestAllTypes MERGE_DEST =
-    TestAllTypes.newBuilder()
-      .setOptionalInt64(2)
-      .setOptionalString("baz")
-      .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
-      .addRepeatedString("qux")
-      .build();
-
-  static final String MERGE_RESULT_TEXT =
-      "optional_int32: 1\n" +
-      "optional_int64: 2\n" +
-      "optional_string: \"foo\"\n" +
-      "optional_foreign_message {\n" +
-      "  c: 3\n" +
-      "}\n" +
-      "repeated_string: \"qux\"\n" +
-      "repeated_string: \"bar\"\n";
-
-  public void testMergeFrom() throws Exception {
-    TestAllTypes result =
-      TestAllTypes.newBuilder(MERGE_DEST)
-        .mergeFrom(MERGE_SOURCE).build();
-
-    assertEquals(MERGE_RESULT_TEXT, result.toString());
-  }
-
-  /**
-   * Test merging a DynamicMessage into a GeneratedMessage.  As long as they
-   * have the same descriptor, this should work, but it is an entirely different
-   * code path.
-   */
-  public void testMergeFromDynamic() throws Exception {
-    TestAllTypes result =
-      TestAllTypes.newBuilder(MERGE_DEST)
-        .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
-        .build();
-
-    assertEquals(MERGE_RESULT_TEXT, result.toString());
-  }
-
-  /** Test merging two DynamicMessages. */
-  public void testDynamicMergeFrom() throws Exception {
-    DynamicMessage result =
-      DynamicMessage.newBuilder(MERGE_DEST)
-        .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
-        .build();
-
-    assertEquals(MERGE_RESULT_TEXT, result.toString());
-  }
-
-  // =================================================================
-  // Required-field-related tests.
-
-  private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
-    TestRequired.getDefaultInstance();
-  private static final TestRequired TEST_REQUIRED_INITIALIZED =
-    TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
-
-  public void testRequired() throws Exception {
-    TestRequired.Builder builder = TestRequired.newBuilder();
-
-    assertFalse(builder.isInitialized());
-    builder.setA(1);
-    assertFalse(builder.isInitialized());
-    builder.setB(1);
-    assertFalse(builder.isInitialized());
-    builder.setC(1);
-    assertTrue(builder.isInitialized());
-  }
-
-  public void testRequiredForeign() throws Exception {
-    TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
-
-    assertTrue(builder.isInitialized());
-
-    builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(builder.isInitialized());
-
-    builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
-    assertTrue(builder.isInitialized());
-
-    builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(builder.isInitialized());
-
-    builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
-    assertTrue(builder.isInitialized());
-  }
-
-  public void testRequiredExtension() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-
-    assertTrue(builder.isInitialized());
-
-    builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(builder.isInitialized());
-
-    builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED);
-    assertTrue(builder.isInitialized());
-
-    builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(builder.isInitialized());
-
-    builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED);
-    assertTrue(builder.isInitialized());
-  }
-
-  public void testRequiredDynamic() throws Exception {
-    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
-    DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
-
-    assertFalse(builder.isInitialized());
-    builder.setField(descriptor.findFieldByName("a"), 1);
-    assertFalse(builder.isInitialized());
-    builder.setField(descriptor.findFieldByName("b"), 1);
-    assertFalse(builder.isInitialized());
-    builder.setField(descriptor.findFieldByName("c"), 1);
-    assertTrue(builder.isInitialized());
-  }
-
-  public void testRequiredDynamicForeign() throws Exception {
-    Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor();
-    DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
-
-    assertTrue(builder.isInitialized());
-
-    builder.setField(descriptor.findFieldByName("optional_message"),
-                     TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(builder.isInitialized());
-
-    builder.setField(descriptor.findFieldByName("optional_message"),
-                     TEST_REQUIRED_INITIALIZED);
-    assertTrue(builder.isInitialized());
-
-    builder.addRepeatedField(descriptor.findFieldByName("repeated_message"),
-                             TEST_REQUIRED_UNINITIALIZED);
-    assertFalse(builder.isInitialized());
-
-    builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0,
-                             TEST_REQUIRED_INITIALIZED);
-    assertTrue(builder.isInitialized());
-  }
-
-  public void testUninitializedException() throws Exception {
-    try {
-      TestRequired.newBuilder().build();
-      fail("Should have thrown an exception.");
-    } catch (UninitializedMessageException e) {
-      assertEquals("Message missing required fields: a, b, c", e.getMessage());
-    }
-  }
-
-  public void testBuildPartial() throws Exception {
-    // We're mostly testing that no exception is thrown.
-    TestRequired message = TestRequired.newBuilder().buildPartial();
-    assertFalse(message.isInitialized());
-  }
-
-  public void testNestedUninitializedException() throws Exception {
-    try {
-      TestRequiredForeign.newBuilder()
-        .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
-        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
-        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
-        .build();
-      fail("Should have thrown an exception.");
-    } catch (UninitializedMessageException e) {
-      assertEquals(
-        "Message missing required fields: " +
-        "optional_message.a, " +
-        "optional_message.b, " +
-        "optional_message.c, " +
-        "repeated_message[0].a, " +
-        "repeated_message[0].b, " +
-        "repeated_message[0].c, " +
-        "repeated_message[1].a, " +
-        "repeated_message[1].b, " +
-        "repeated_message[1].c",
-        e.getMessage());
-    }
-  }
-
-  public void testBuildNestedPartial() throws Exception {
-    // We're mostly testing that no exception is thrown.
-    TestRequiredForeign message =
-      TestRequiredForeign.newBuilder()
-        .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
-        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
-        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
-        .buildPartial();
-    assertFalse(message.isInitialized());
-  }
-
-  public void testParseUnititialized() throws Exception {
-    try {
-      TestRequired.parseFrom(ByteString.EMPTY);
-      fail("Should have thrown an exception.");
-    } catch (InvalidProtocolBufferException e) {
-      assertEquals("Message missing required fields: a, b, c", e.getMessage());
-    }
-  }
-
-  public void testParseNestedUnititialized() throws Exception {
-    ByteString data =
-      TestRequiredForeign.newBuilder()
-        .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
-        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
-        .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
-        .buildPartial().toByteString();
-
-    try {
-      TestRequiredForeign.parseFrom(data);
-      fail("Should have thrown an exception.");
-    } catch (InvalidProtocolBufferException e) {
-      assertEquals(
-        "Message missing required fields: " +
-        "optional_message.a, " +
-        "optional_message.b, " +
-        "optional_message.c, " +
-        "repeated_message[0].a, " +
-        "repeated_message[0].b, " +
-        "repeated_message[0].c, " +
-        "repeated_message[1].a, " +
-        "repeated_message[1].b, " +
-        "repeated_message[1].c",
-        e.getMessage());
-    }
-  }
-
-  public void testDynamicUninitializedException() throws Exception {
-    try {
-      DynamicMessage.newBuilder(TestRequired.getDescriptor()).build();
-      fail("Should have thrown an exception.");
-    } catch (UninitializedMessageException e) {
-      assertEquals("Message missing required fields: a, b, c", e.getMessage());
-    }
-  }
-
-  public void testDynamicBuildPartial() throws Exception {
-    // We're mostly testing that no exception is thrown.
-    DynamicMessage message =
-      DynamicMessage.newBuilder(TestRequired.getDescriptor())
-        .buildPartial();
-    assertFalse(message.isInitialized());
-  }
-
-  public void testDynamicParseUnititialized() throws Exception {
-    try {
-      Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
-      DynamicMessage.parseFrom(descriptor, ByteString.EMPTY);
-      fail("Should have thrown an exception.");
-    } catch (InvalidProtocolBufferException e) {
-      assertEquals("Message missing required fields: a, b, c", e.getMessage());
-    }
-  }
-
-  /** Test reading unset repeated message from DynamicMessage. */
-  public void testDynamicRepeatedMessageNull() throws Exception {
-    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
-    DynamicMessage result =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
-        .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
-        .build();
-
-    assertTrue(result.getField(result.getDescriptorForType()
-        .findFieldByName("repeated_foreign_message")) instanceof List<?>);
-    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
-        .findFieldByName("repeated_foreign_message")), 0);
-  }
-
-  /** Test reading repeated message from DynamicMessage. */
-  public void testDynamicRepeatedMessageNotNull() throws Exception {
-
-    TestAllTypes REPEATED_NESTED =
-      TestAllTypes.newBuilder()
-        .setOptionalInt32(1)
-        .setOptionalString("foo")
-        .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
-        .addRepeatedString("bar")
-        .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
-        .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
-        .build();
-    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
-    DynamicMessage result =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
-        .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
-        .build();
-
-    assertTrue(result.getField(result.getDescriptorForType()
-        .findFieldByName("repeated_foreign_message")) instanceof List<?>);
-    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
-        .findFieldByName("repeated_foreign_message")), 2);
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/NestedBuildersTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/NestedBuildersTest.java
deleted file mode 100644
index 68d70be..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/NestedBuildersTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.Vehicle;
-import protobuf_unittest.Wheel;
-
-import junit.framework.TestCase;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * Test cases that exercise end-to-end use cases involving
- * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class NestedBuildersTest extends TestCase {
-
-  public void testMessagesAndBuilders() {
-    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(4)
-        .setWidth(1);
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(4)
-        .setWidth(2);
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(4)
-        .setWidth(3);
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(4)
-        .setWidth(4);
-    vehicleBuilder.getEngineBuilder()
-        .setLiters(10);
-
-    Vehicle vehicle = vehicleBuilder.build();
-    assertEquals(4, vehicle.getWheelCount());
-    for (int i = 0; i < 4; i++) {
-      Wheel wheel = vehicle.getWheel(i);
-      assertEquals(4, wheel.getRadius());
-      assertEquals(i + 1, wheel.getWidth());
-    }
-    assertEquals(10, vehicle.getEngine().getLiters());
-
-    for (int i = 0; i < 4; i++) {
-      vehicleBuilder.getWheelBuilder(i)
-          .setRadius(5)
-          .setWidth(i + 10);
-    }
-    vehicleBuilder.getEngineBuilder().setLiters(20);
-
-    vehicle = vehicleBuilder.build();
-    for (int i = 0; i < 4; i++) {
-      Wheel wheel = vehicle.getWheel(i);
-      assertEquals(5, wheel.getRadius());
-      assertEquals(i + 10, wheel.getWidth());
-    }
-    assertEquals(20, vehicle.getEngine().getLiters());
-    assertTrue(vehicle.hasEngine());
-  }
-
-  public void testMessagesAreCached() {
-    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(1)
-        .setWidth(2);
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(3)
-        .setWidth(4);
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(5)
-        .setWidth(6);
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(7)
-        .setWidth(8);
-
-    // Make sure messages are cached.
-    List<Wheel> wheels = new ArrayList<Wheel>(vehicleBuilder.getWheelList());
-    for (int i = 0; i < wheels.size(); i++) {
-      assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
-    }
-
-    // Now get builders and check they didn't change.
-    for (int i = 0; i < wheels.size(); i++) {
-      vehicleBuilder.getWheel(i);
-    }
-    for (int i = 0; i < wheels.size(); i++) {
-      assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
-    }
-
-    // Change just one
-    vehicleBuilder.getWheelBuilder(3)
-        .setRadius(20).setWidth(20);
-
-    // Now get wheels and check that only that one changed
-    for (int i = 0; i < wheels.size(); i++) {
-      if (i < 3) {
-        assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
-      } else {
-        assertNotSame(wheels.get(i), vehicleBuilder.getWheel(i));
-      }
-    }
-  }
-
-  public void testRemove_WithNestedBuilders() {
-    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(1)
-        .setWidth(1);
-    vehicleBuilder.addWheelBuilder()
-        .setRadius(2)
-        .setWidth(2);
-    vehicleBuilder.removeWheel(0);
-
-    assertEquals(1, vehicleBuilder.getWheelCount());
-    assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
-  }
-
-  public void testRemove_WithNestedMessages() {
-    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
-    vehicleBuilder.addWheel(Wheel.newBuilder()
-        .setRadius(1)
-        .setWidth(1));
-    vehicleBuilder.addWheel(Wheel.newBuilder()
-        .setRadius(2)
-        .setWidth(2));
-    vehicleBuilder.removeWheel(0);
-
-    assertEquals(1, vehicleBuilder.getWheelCount());
-    assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
-  }
-
-  public void testMerge() {
-    Vehicle vehicle1 = Vehicle.newBuilder()
-        .addWheel(Wheel.newBuilder().setRadius(1).build())
-        .addWheel(Wheel.newBuilder().setRadius(2).build())
-        .build();
-
-    Vehicle vehicle2 = Vehicle.newBuilder()
-        .mergeFrom(vehicle1)
-        .build();
-    // List should be the same -- no allocation
-    assertSame(vehicle1.getWheelList(), vehicle2.getWheelList());
-
-    Vehicle vehicle3 = vehicle1.toBuilder().build();
-    assertSame(vehicle1.getWheelList(), vehicle3.getWheelList());
-  }
-
-  public void testGettingBuilderMarksFieldAsHaving() {
-    Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
-    vehicleBuilder.getEngineBuilder();
-    Vehicle vehicle = vehicleBuilder.buildPartial();
-    assertTrue(vehicle.hasEngine());
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ParserTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ParserTest.java
deleted file mode 100644
index b35af68..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ParserTest.java
+++ /dev/null
@@ -1,278 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
-import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
-import protobuf_unittest.UnittestOptimizeFor;
-import protobuf_unittest.UnittestProto.ForeignMessage;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestEmptyMessage;
-import protobuf_unittest.UnittestProto.TestRequired;
-import protobuf_unittest.UnittestProto.TestParsingMerge;
-import protobuf_unittest.UnittestProto;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Unit test for {@link Parser}.
- *
- * @author liujisi@google.com (Pherl Liu)
- */
-public class ParserTest extends TestCase {
-  public void testGeneratedMessageParserSingleton() throws Exception {
-    for (int i = 0; i < 10; i++) {
-      assertEquals(TestAllTypes.PARSER,
-                   TestUtil.getAllSet().getParserForType());
-    }
-  }
-
-  private void assertRoundTripEquals(MessageLite message,
-                                     ExtensionRegistryLite registry)
-      throws Exception {
-    final byte[] data = message.toByteArray();
-    final int offset = 20;
-    final int length = data.length;
-    final int padding = 30;
-    Parser<? extends MessageLite> parser = message.getParserForType();
-    assertMessageEquals(message, parser.parseFrom(data, registry));
-    assertMessageEquals(message, parser.parseFrom(
-        generatePaddingArray(data, offset, padding),
-        offset, length, registry));
-    assertMessageEquals(message, parser.parseFrom(
-        message.toByteString(), registry));
-    assertMessageEquals(message, parser.parseFrom(
-        new ByteArrayInputStream(data), registry));
-    assertMessageEquals(message, parser.parseFrom(
-        CodedInputStream.newInstance(data), registry));
-  }
-
-  private void assertRoundTripEquals(MessageLite message) throws Exception {
-    final byte[] data = message.toByteArray();
-    final int offset = 20;
-    final int length = data.length;
-    final int padding = 30;
-    Parser<? extends MessageLite> parser = message.getParserForType();
-    assertMessageEquals(message, parser.parseFrom(data));
-    assertMessageEquals(message, parser.parseFrom(
-        generatePaddingArray(data, offset, padding),
-        offset, length));
-    assertMessageEquals(message, parser.parseFrom(message.toByteString()));
-    assertMessageEquals(message, parser.parseFrom(
-        new ByteArrayInputStream(data)));
-    assertMessageEquals(message, parser.parseFrom(
-        CodedInputStream.newInstance(data)));
-  }
-
-  private void assertMessageEquals(MessageLite expected, MessageLite actual)
-      throws Exception {
-    if (expected instanceof Message) {
-      assertEquals(expected, actual);
-    } else {
-      assertEquals(expected.toByteString(), actual.toByteString());
-    }
-  }
-
-  private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
-    byte[] result = new byte[offset + data.length + padding];
-    System.arraycopy(data, 0, result, offset, data.length);
-    return result;
-  }
-
-  public void testNormalMessage() throws Exception {
-    assertRoundTripEquals(TestUtil.getAllSet());
-  }
-
-  public void testParsePartial() throws Exception {
-    Parser<TestRequired> parser = TestRequired.PARSER;
-    final String errorString =
-        "Should throw exceptions when the parsed message isn't initialized.";
-
-    // TestRequired.b and TestRequired.c are not set.
-    TestRequired partialMessage = TestRequired.newBuilder()
-        .setA(1).buildPartial();
-
-    // parsePartialFrom should pass.
-    byte[] data = partialMessage.toByteArray();
-    assertEquals(partialMessage, parser.parsePartialFrom(data));
-    assertEquals(partialMessage, parser.parsePartialFrom(
-        partialMessage.toByteString()));
-    assertEquals(partialMessage, parser.parsePartialFrom(
-        new ByteArrayInputStream(data)));
-    assertEquals(partialMessage, parser.parsePartialFrom(
-        CodedInputStream.newInstance(data)));
-
-    // parseFrom(ByteArray)
-    try {
-      parser.parseFrom(partialMessage.toByteArray());
-      fail(errorString);
-    } catch (InvalidProtocolBufferException e) {
-      // pass.
-    }
-
-    // parseFrom(ByteString)
-    try {
-      parser.parseFrom(partialMessage.toByteString());
-      fail(errorString);
-    } catch (InvalidProtocolBufferException e) {
-      // pass.
-    }
-
-    // parseFrom(InputStream)
-    try {
-      parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
-      fail(errorString);
-    } catch (IOException e) {
-      // pass.
-    }
-
-    // parseFrom(CodedInputStream)
-    try {
-      parser.parseFrom(CodedInputStream.newInstance(
-          partialMessage.toByteArray()));
-      fail(errorString);
-    } catch (IOException e) {
-      // pass.
-    }
-  }
-
-  public void testParseDelimitedTo() throws Exception {
-    // Write normal Message.
-    TestAllTypes normalMessage = TestUtil.getAllSet();
-    ByteArrayOutputStream output = new ByteArrayOutputStream();
-    normalMessage.writeDelimitedTo(output);
-
-    InputStream input = new ByteArrayInputStream(output.toByteArray());
-    assertMessageEquals(
-        normalMessage,
-        normalMessage.getParserForType().parseDelimitedFrom(input));
-  }
-
-  public void testParseUnknownFields() throws Exception {
-    // All fields will be treated as unknown fields in emptyMessage.
-    TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom(
-        TestUtil.getAllSet().toByteString());
-    assertEquals(
-        TestUtil.getAllSet().toByteString(),
-        emptyMessage.toByteString());
-  }
-
-  public void testOptimizeForSize() throws Exception {
-    TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
-    builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
-    builder.setExtension(TestOptimizedForSize.testExtension, 56);
-    builder.setExtension(TestOptimizedForSize.testExtension2,
-        TestRequiredOptimizedForSize.newBuilder().setX(78).build());
-
-    TestOptimizedForSize message = builder.build();
-    ExtensionRegistry registry = ExtensionRegistry.newInstance();
-    UnittestOptimizeFor.registerAllExtensions(registry);
-
-    assertRoundTripEquals(message, registry);
-  }
-
-  /** Helper method for {@link #testParsingMerge()}.*/
-  private void assertMessageMerged(TestAllTypes allTypes)
-      throws Exception {
-    assertEquals(3, allTypes.getOptionalInt32());
-    assertEquals(2, allTypes.getOptionalInt64());
-    assertEquals("hello", allTypes.getOptionalString());
-  }
-
-  public void testParsingMerge() throws Exception {
-    // Build messages.
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TestAllTypes msg1 = builder.setOptionalInt32(1).build();
-    builder.clear();
-    TestAllTypes msg2 = builder.setOptionalInt64(2).build();
-    builder.clear();
-    TestAllTypes msg3 = builder.setOptionalInt32(3)
-        .setOptionalString("hello").build();
-
-    // Build groups.
-    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
-        .setField1(msg1).build();
-    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
-        .setField1(msg2).build();
-    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
-        .setField1(msg3).build();
-    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
-        .setField1(msg1).build();
-    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
-        .setField1(msg2).build();
-    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
-        .setField1(msg3).build();
-
-    // Assign and serialize RepeatedFieldsGenerator.
-    ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
-        .addField1(msg1).addField1(msg2).addField1(msg3)
-        .addField2(msg1).addField2(msg2).addField2(msg3)
-        .addField3(msg1).addField3(msg2).addField3(msg3)
-        .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
-        .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
-        .addExt1(msg1).addExt1(msg2).addExt1(msg3)
-        .addExt2(msg1).addExt2(msg2).addExt2(msg3)
-        .build().toByteString();
-
-    // Parse TestParsingMerge.
-    ExtensionRegistry registry = ExtensionRegistry.newInstance();
-    UnittestProto.registerAllExtensions(registry);
-    TestParsingMerge parsingMerge =
-        TestParsingMerge.PARSER.parseFrom(data, registry);
-
-    // Required and optional fields should be merged.
-    assertMessageMerged(parsingMerge.getRequiredAllTypes());
-    assertMessageMerged(parsingMerge.getOptionalAllTypes());
-    assertMessageMerged(
-        parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
-    assertMessageMerged(parsingMerge.getExtension(
-        TestParsingMerge.optionalExt));
-
-    // Repeated fields should not be merged.
-    assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
-    assertEquals(3, parsingMerge.getRepeatedGroupCount());
-    assertEquals(3, parsingMerge.getExtensionCount(
-        TestParsingMerge.repeatedExt));
-  }
-
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java
deleted file mode 100644
index c122385..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Iterator;
-
-/**
- * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from
- * {@link LiteralByteStringTest}.  Only a couple of methods are overridden.
- *
- * @author carlanton@google.com (Carl Haverl)
- */
-public class RopeByteStringSubstringTest extends LiteralByteStringTest {
-
-  @Override
-  protected void setUp() throws Exception {
-    classUnderTest = "RopeByteString";
-    byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
-    Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator();
-    ByteString sourceString = iter.next();
-    while (iter.hasNext()) {
-      sourceString = sourceString.concat(iter.next());
-    }
-
-    int from = 1130;
-    int to = sourceBytes.length - 5555;
-    stringUnderTest = sourceString.substring(from, to);
-    referenceBytes = new byte[to - from];
-    System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
-    expectedHashCode = -1259260680;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java
deleted file mode 100644
index 19098de..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
-import java.util.Iterator;
-
-/**
- * This class tests {@link RopeByteString} by inheriting the tests from
- * {@link LiteralByteStringTest}.  Only a couple of methods are overridden.
- *
- * <p>A full test of the result of {@link RopeByteString#substring(int, int)} is found in the
- * separate class {@link RopeByteStringSubstringTest}.
- *
- * @author carlanton@google.com (Carl Haverl)
- */
-public class RopeByteStringTest extends LiteralByteStringTest {
-
-  @Override
-  protected void setUp() throws Exception {
-    classUnderTest = "RopeByteString";
-    referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
-    Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator();
-    stringUnderTest = iter.next();
-    while (iter.hasNext()) {
-      stringUnderTest = stringUnderTest.concat(iter.next());
-    }
-    expectedHashCode = -1214197238;
-  }
-
-  public void testBalance() {
-    int numberOfPieces = 10000;
-    int pieceSize = 64;
-    byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L);
-
-    // Build up a big ByteString from smaller pieces to force a rebalance
-    ByteString concatenated = ByteString.EMPTY;
-    for (int i = 0; i < numberOfPieces; ++i) {
-      concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize));
-    }
-
-    assertEquals(classUnderTest + " from string must have the expected type",
-        classUnderTest, getActualClassName(concatenated));
-    assertTrue(classUnderTest + " underlying bytes must match after balancing",
-        Arrays.equals(testBytes, concatenated.toByteArray()));
-    ByteString testString = ByteString.copyFrom(testBytes);
-    assertTrue(classUnderTest + " balanced string must equal flat string",
-        concatenated.equals(testString));
-    assertTrue(classUnderTest + " flat string must equal balanced string",
-        testString.equals(concatenated));
-    assertEquals(classUnderTest + " balanced string must have same hash code as flat string",
-        testString.hashCode(), concatenated.hashCode());
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ServiceTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ServiceTest.java
deleted file mode 100644
index 4c7f751..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ServiceTest.java
+++ /dev/null
@@ -1,321 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import com.google.protobuf.Descriptors.FileDescriptor;
-import com.google.protobuf.Descriptors.MethodDescriptor;
-import google.protobuf.no_generic_services_test.UnittestNoGenericServices;
-import protobuf_unittest.MessageWithNoOuter;
-import protobuf_unittest.ServiceWithNoOuter;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestService;
-import protobuf_unittest.UnittestProto.FooRequest;
-import protobuf_unittest.UnittestProto.FooResponse;
-import protobuf_unittest.UnittestProto.BarRequest;
-import protobuf_unittest.UnittestProto.BarResponse;
-
-import org.easymock.classextension.EasyMock;
-import org.easymock.classextension.IMocksControl;
-import org.easymock.IArgumentMatcher;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import junit.framework.TestCase;
-
-/**
- * Tests services and stubs.
- *
- * @author kenton@google.com Kenton Varda
- */
-public class ServiceTest extends TestCase {
-  private IMocksControl control;
-  private RpcController mockController;
-
-  private final Descriptors.MethodDescriptor fooDescriptor =
-    TestService.getDescriptor().getMethods().get(0);
-  private final Descriptors.MethodDescriptor barDescriptor =
-    TestService.getDescriptor().getMethods().get(1);
-
-  @Override
-  protected void setUp() throws Exception {
-    super.setUp();
-    control = EasyMock.createStrictControl();
-    mockController = control.createMock(RpcController.class);
-  }
-
-  // =================================================================
-
-  /** Tests Service.callMethod(). */
-  public void testCallMethod() throws Exception {
-    FooRequest fooRequest = FooRequest.newBuilder().build();
-    BarRequest barRequest = BarRequest.newBuilder().build();
-    MockCallback<Message> fooCallback = new MockCallback<Message>();
-    MockCallback<Message> barCallback = new MockCallback<Message>();
-    TestService mockService = control.createMock(TestService.class);
-
-    mockService.foo(EasyMock.same(mockController), EasyMock.same(fooRequest),
-                    this.<FooResponse>wrapsCallback(fooCallback));
-    mockService.bar(EasyMock.same(mockController), EasyMock.same(barRequest),
-                    this.<BarResponse>wrapsCallback(barCallback));
-    control.replay();
-
-    mockService.callMethod(fooDescriptor, mockController,
-                           fooRequest, fooCallback);
-    mockService.callMethod(barDescriptor, mockController,
-                           barRequest, barCallback);
-    control.verify();
-  }
-
-  /** Tests Service.get{Request,Response}Prototype(). */
-  public void testGetPrototype() throws Exception {
-    TestService mockService = control.createMock(TestService.class);
-
-    assertSame(mockService.getRequestPrototype(fooDescriptor),
-               FooRequest.getDefaultInstance());
-    assertSame(mockService.getResponsePrototype(fooDescriptor),
-               FooResponse.getDefaultInstance());
-    assertSame(mockService.getRequestPrototype(barDescriptor),
-               BarRequest.getDefaultInstance());
-    assertSame(mockService.getResponsePrototype(barDescriptor),
-               BarResponse.getDefaultInstance());
-  }
-
-  /** Tests generated stubs. */
-  public void testStub() throws Exception {
-    FooRequest fooRequest = FooRequest.newBuilder().build();
-    BarRequest barRequest = BarRequest.newBuilder().build();
-    MockCallback<FooResponse> fooCallback = new MockCallback<FooResponse>();
-    MockCallback<BarResponse> barCallback = new MockCallback<BarResponse>();
-    RpcChannel mockChannel = control.createMock(RpcChannel.class);
-    TestService stub = TestService.newStub(mockChannel);
-
-    mockChannel.callMethod(
-      EasyMock.same(fooDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(fooRequest),
-      EasyMock.same(FooResponse.getDefaultInstance()),
-      this.<Message>wrapsCallback(fooCallback));
-    mockChannel.callMethod(
-      EasyMock.same(barDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(barRequest),
-      EasyMock.same(BarResponse.getDefaultInstance()),
-      this.<Message>wrapsCallback(barCallback));
-    control.replay();
-
-    stub.foo(mockController, fooRequest, fooCallback);
-    stub.bar(mockController, barRequest, barCallback);
-    control.verify();
-  }
-
-  /** Tests generated blocking stubs. */
-  public void testBlockingStub() throws Exception {
-    FooRequest fooRequest = FooRequest.newBuilder().build();
-    BarRequest barRequest = BarRequest.newBuilder().build();
-    BlockingRpcChannel mockChannel =
-        control.createMock(BlockingRpcChannel.class);
-    TestService.BlockingInterface stub =
-        TestService.newBlockingStub(mockChannel);
-
-    FooResponse fooResponse = FooResponse.newBuilder().build();
-    BarResponse barResponse = BarResponse.newBuilder().build();
-
-    EasyMock.expect(mockChannel.callBlockingMethod(
-      EasyMock.same(fooDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(fooRequest),
-      EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse);
-    EasyMock.expect(mockChannel.callBlockingMethod(
-      EasyMock.same(barDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(barRequest),
-      EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse);
-    control.replay();
-
-    assertSame(fooResponse, stub.foo(mockController, fooRequest));
-    assertSame(barResponse, stub.bar(mockController, barRequest));
-    control.verify();
-  }
-
-  public void testNewReflectiveService() {
-    ServiceWithNoOuter.Interface impl =
-        control.createMock(ServiceWithNoOuter.Interface.class);
-    RpcController controller = control.createMock(RpcController.class);
-    Service service = ServiceWithNoOuter.newReflectiveService(impl);
-
-    MethodDescriptor fooMethod =
-        ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
-    MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
-    RpcCallback<Message> callback = new RpcCallback<Message>() {
-      public void run(Message parameter) {
-        // No reason this should be run.
-        fail();
-      }
-    };
-    RpcCallback<TestAllTypes> specializedCallback =
-        RpcUtil.specializeCallback(callback);
-
-    impl.foo(EasyMock.same(controller), EasyMock.same(request),
-        EasyMock.same(specializedCallback));
-    EasyMock.expectLastCall();
-
-    control.replay();
-
-    service.callMethod(fooMethod, controller, request, callback);
-
-    control.verify();
-  }
-
-  public void testNewReflectiveBlockingService() throws ServiceException {
-    ServiceWithNoOuter.BlockingInterface impl =
-        control.createMock(ServiceWithNoOuter.BlockingInterface.class);
-    RpcController controller = control.createMock(RpcController.class);
-    BlockingService service =
-        ServiceWithNoOuter.newReflectiveBlockingService(impl);
-
-    MethodDescriptor fooMethod =
-        ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
-    MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
-
-    TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
-    EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request)))
-        .andReturn(expectedResponse);
-
-    control.replay();
-
-    Message response =
-        service.callBlockingMethod(fooMethod, controller, request);
-    assertEquals(expectedResponse, response);
-
-    control.verify();
-  }
-
-  public void testNoGenericServices() throws Exception {
-    // Non-services should be usable.
-    UnittestNoGenericServices.TestMessage message =
-      UnittestNoGenericServices.TestMessage.newBuilder()
-        .setA(123)
-        .setExtension(UnittestNoGenericServices.testExtension, 456)
-        .build();
-    assertEquals(123, message.getA());
-    assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
-
-    // Build a list of the class names nested in UnittestNoGenericServices.
-    String outerName = "google.protobuf.no_generic_services_test." +
-                       "UnittestNoGenericServices";
-    Class<?> outerClass = Class.forName(outerName);
-
-    Set<String> innerClassNames = new HashSet<String>();
-    for (Class<?> innerClass : outerClass.getClasses()) {
-      String fullName = innerClass.getName();
-      // Figure out the unqualified name of the inner class.
-      // Note:  Surprisingly, the full name of an inner class will be separated
-      //   from the outer class name by a '$' rather than a '.'.  This is not
-      //   mentioned in the documentation for java.lang.Class.  I don't want to
-      //   make assumptions, so I'm just going to accept any character as the
-      //   separator.
-      assertTrue(fullName.startsWith(outerName));
-
-      if (!Service.class.isAssignableFrom(innerClass) &&
-          !Message.class.isAssignableFrom(innerClass) &&
-          !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
-        // Ignore any classes not generated by the base code generator.
-        continue;
-      }
-
-      innerClassNames.add(fullName.substring(outerName.length() + 1));
-    }
-
-    // No service class should have been generated.
-    assertTrue(innerClassNames.contains("TestMessage"));
-    assertTrue(innerClassNames.contains("TestEnum"));
-    assertFalse(innerClassNames.contains("TestService"));
-
-    // But descriptors are there.
-    FileDescriptor file = UnittestNoGenericServices.getDescriptor();
-    assertEquals(1, file.getServices().size());
-    assertEquals("TestService", file.getServices().get(0).getName());
-    assertEquals(1, file.getServices().get(0).getMethods().size());
-    assertEquals("Foo",
-        file.getServices().get(0).getMethods().get(0).getName());
-  }
-
-  // =================================================================
-
-  /**
-   * wrapsCallback() is an EasyMock argument predicate.  wrapsCallback(c)
-   * matches a callback if calling that callback causes c to be called.
-   * In other words, c wraps the given callback.
-   */
-  private <Type extends Message> RpcCallback<Type> wrapsCallback(
-      MockCallback<?> callback) {
-    EasyMock.reportMatcher(new WrapsCallback(callback));
-    return null;
-  }
-
-  /** The parameter to wrapsCallback() must be a MockCallback. */
-  private static class MockCallback<Type extends Message>
-      implements RpcCallback<Type> {
-    private boolean called = false;
-
-    public boolean isCalled() { return called; }
-
-    public void reset() { called = false; }
-    public void run(Type message) { called = true; }
-  }
-
-  /** Implementation of the wrapsCallback() argument matcher. */
-  private static class WrapsCallback implements IArgumentMatcher {
-    private MockCallback<?> callback;
-
-    public WrapsCallback(MockCallback<?> callback) {
-      this.callback = callback;
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean matches(Object actual) {
-      if (!(actual instanceof RpcCallback)) {
-        return false;
-      }
-      RpcCallback actualCallback = (RpcCallback)actual;
-
-      callback.reset();
-      actualCallback.run(null);
-      return callback.isCalled();
-    }
-
-    public void appendTo(StringBuffer buffer) {
-      buffer.append("wrapsCallback(mockCallback)");
-    }
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestBadIdentifiers.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestBadIdentifiers.java
deleted file mode 100644
index 5086732..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestBadIdentifiers.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import junit.framework.TestCase;
-
-/**
- * Tests that proto2 api generation doesn't cause compile errors when
- * compiling protocol buffers that have names that would otherwise conflict
- * if not fully qualified (like @Deprecated and @Override).
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class TestBadIdentifiers extends TestCase {
-
-  public void testCompilation() {
-    // If this compiles, it means the generation was correct.
-    TestBadIdentifiersProto.Deprecated.newBuilder();
-    TestBadIdentifiersProto.Override.newBuilder();
-  }
-
-  public void testGetDescriptor() {
-    Descriptors.FileDescriptor fileDescriptor =
-        TestBadIdentifiersProto.getDescriptor();
-    String descriptorField = TestBadIdentifiersProto.Descriptor
-        .getDefaultInstance().getDescriptor();
-    Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
-        .getDefaultInstance().getDescriptorForType();
-    String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
-        .NestedDescriptor.getDefaultInstance().getDescriptor();
-    Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
-        .Descriptor.NestedDescriptor.getDefaultInstance()
-        .getDescriptorForType();
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestUtil.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestUtil.java
deleted file mode 100644
index a923483..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestUtil.java
+++ /dev/null
@@ -1,3068 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto;
-
-// The static imports are to avoid 100+ char lines.  The following is roughly equivalent to
-// import static protobuf_unittest.UnittestProto.*;
-import static protobuf_unittest.UnittestProto.defaultInt32Extension;
-import static protobuf_unittest.UnittestProto.defaultInt64Extension;
-import static protobuf_unittest.UnittestProto.defaultUint32Extension;
-import static protobuf_unittest.UnittestProto.defaultUint64Extension;
-import static protobuf_unittest.UnittestProto.defaultSint32Extension;
-import static protobuf_unittest.UnittestProto.defaultSint64Extension;
-import static protobuf_unittest.UnittestProto.defaultFixed32Extension;
-import static protobuf_unittest.UnittestProto.defaultFixed64Extension;
-import static protobuf_unittest.UnittestProto.defaultSfixed32Extension;
-import static protobuf_unittest.UnittestProto.defaultSfixed64Extension;
-import static protobuf_unittest.UnittestProto.defaultFloatExtension;
-import static protobuf_unittest.UnittestProto.defaultDoubleExtension;
-import static protobuf_unittest.UnittestProto.defaultBoolExtension;
-import static protobuf_unittest.UnittestProto.defaultStringExtension;
-import static protobuf_unittest.UnittestProto.defaultBytesExtension;
-import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension;
-import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension;
-import static protobuf_unittest.UnittestProto.defaultImportEnumExtension;
-import static protobuf_unittest.UnittestProto.defaultStringPieceExtension;
-import static protobuf_unittest.UnittestProto.defaultCordExtension;
-
-import static protobuf_unittest.UnittestProto.optionalInt32Extension;
-import static protobuf_unittest.UnittestProto.optionalInt64Extension;
-import static protobuf_unittest.UnittestProto.optionalUint32Extension;
-import static protobuf_unittest.UnittestProto.optionalUint64Extension;
-import static protobuf_unittest.UnittestProto.optionalSint32Extension;
-import static protobuf_unittest.UnittestProto.optionalSint64Extension;
-import static protobuf_unittest.UnittestProto.optionalFixed32Extension;
-import static protobuf_unittest.UnittestProto.optionalFixed64Extension;
-import static protobuf_unittest.UnittestProto.optionalSfixed32Extension;
-import static protobuf_unittest.UnittestProto.optionalSfixed64Extension;
-import static protobuf_unittest.UnittestProto.optionalFloatExtension;
-import static protobuf_unittest.UnittestProto.optionalDoubleExtension;
-import static protobuf_unittest.UnittestProto.optionalBoolExtension;
-import static protobuf_unittest.UnittestProto.optionalStringExtension;
-import static protobuf_unittest.UnittestProto.optionalBytesExtension;
-import static protobuf_unittest.UnittestProto.optionalGroupExtension;
-import static protobuf_unittest.UnittestProto.optionalCordExtension;
-import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
-import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
-import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
-import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
-import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
-import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
-import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension;
-import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension;
-import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
-
-import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
-import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
-import static protobuf_unittest.UnittestProto.repeatedUint32Extension;
-import static protobuf_unittest.UnittestProto.repeatedUint64Extension;
-import static protobuf_unittest.UnittestProto.repeatedSint32Extension;
-import static protobuf_unittest.UnittestProto.repeatedSint64Extension;
-import static protobuf_unittest.UnittestProto.repeatedFixed32Extension;
-import static protobuf_unittest.UnittestProto.repeatedFixed64Extension;
-import static protobuf_unittest.UnittestProto.repeatedSfixed32Extension;
-import static protobuf_unittest.UnittestProto.repeatedSfixed64Extension;
-import static protobuf_unittest.UnittestProto.repeatedFloatExtension;
-import static protobuf_unittest.UnittestProto.repeatedDoubleExtension;
-import static protobuf_unittest.UnittestProto.repeatedBoolExtension;
-import static protobuf_unittest.UnittestProto.repeatedStringExtension;
-import static protobuf_unittest.UnittestProto.repeatedBytesExtension;
-import static protobuf_unittest.UnittestProto.repeatedGroupExtension;
-import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
-import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
-import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
-import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension;
-import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
-import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
-import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
-import static protobuf_unittest.UnittestProto.repeatedStringPieceExtension;
-import static protobuf_unittest.UnittestProto.repeatedCordExtension;
-
-import static protobuf_unittest.UnittestProto.OptionalGroup_extension;
-import static protobuf_unittest.UnittestProto.RepeatedGroup_extension;
-
-import static protobuf_unittest.UnittestProto.packedInt32Extension;
-import static protobuf_unittest.UnittestProto.packedInt64Extension;
-import static protobuf_unittest.UnittestProto.packedUint32Extension;
-import static protobuf_unittest.UnittestProto.packedUint64Extension;
-import static protobuf_unittest.UnittestProto.packedSint32Extension;
-import static protobuf_unittest.UnittestProto.packedSint64Extension;
-import static protobuf_unittest.UnittestProto.packedFixed32Extension;
-import static protobuf_unittest.UnittestProto.packedFixed64Extension;
-import static protobuf_unittest.UnittestProto.packedSfixed32Extension;
-import static protobuf_unittest.UnittestProto.packedSfixed64Extension;
-import static protobuf_unittest.UnittestProto.packedFloatExtension;
-import static protobuf_unittest.UnittestProto.packedDoubleExtension;
-import static protobuf_unittest.UnittestProto.packedBoolExtension;
-import static protobuf_unittest.UnittestProto.packedEnumExtension;
-
-
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-import protobuf_unittest.UnittestProto.TestPackedExtensions;
-import protobuf_unittest.UnittestProto.TestPackedTypes;
-import protobuf_unittest.UnittestProto.TestUnpackedTypes;
-import protobuf_unittest.UnittestProto.ForeignMessage;
-import protobuf_unittest.UnittestProto.ForeignEnum;
-import com.google.protobuf.test.UnittestImport.ImportEnum;
-import com.google.protobuf.test.UnittestImport.ImportMessage;
-import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
-
-import junit.framework.Assert;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-
-/**
- * Contains methods for setting all fields of {@code TestAllTypes} to
- * some values as well as checking that all the fields are set to those values.
- * These are useful for testing various protocol message features, e.g.
- * set all fields of a message, serialize it, parse it, and check that all
- * fields are set.
- *
- * <p>This code is not to be used outside of {@code com.google.protobuf} and
- * subpackages.
- *
- * @author kenton@google.com Kenton Varda
- */
-public final class TestUtil {
-  private TestUtil() {}
-
-  /** Helper to convert a String to ByteString. */
-  static ByteString toBytes(String str) {
-    try {
-      return ByteString.copyFrom(str.getBytes("UTF-8"));
-    } catch(java.io.UnsupportedEncodingException e) {
-      throw new RuntimeException("UTF-8 not supported.", e);
-    }
-  }
-
-  /**
-   * Get a {@code TestAllTypes} with all fields set as they would be by
-   * {@link #setAllFields(TestAllTypes.Builder)}.
-   */
-  public static TestAllTypes getAllSet() {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    setAllFields(builder);
-    return builder.build();
-  }
-
-  /**
-   * Get a {@code TestAllTypes.Builder} with all fields set as they would be by
-   * {@link #setAllFields(TestAllTypes.Builder)}.
-   */
-  public static TestAllTypes.Builder getAllSetBuilder() {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    setAllFields(builder);
-    return builder;
-  }
-
-  /**
-   * Get a {@code TestAllExtensions} with all fields set as they would be by
-   * {@link #setAllExtensions(TestAllExtensions.Builder)}.
-   */
-  public static TestAllExtensions getAllExtensionsSet() {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    setAllExtensions(builder);
-    return builder.build();
-  }
-
-  public static TestPackedTypes getPackedSet() {
-    TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
-    setPackedFields(builder);
-    return builder.build();
-  }
-
-  public static TestUnpackedTypes getUnpackedSet() {
-    TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
-    setUnpackedFields(builder);
-    return builder.build();
-  }
-
-  public static TestPackedExtensions getPackedExtensionsSet() {
-    TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
-    setPackedExtensions(builder);
-    return builder.build();
-  }
-
-  /**
-   * Set every field of {@code message} to the values expected by
-   * {@code assertAllFieldsSet()}.
-   */
-  public static void setAllFields(TestAllTypes.Builder message) {
-    message.setOptionalInt32   (101);
-    message.setOptionalInt64   (102);
-    message.setOptionalUint32  (103);
-    message.setOptionalUint64  (104);
-    message.setOptionalSint32  (105);
-    message.setOptionalSint64  (106);
-    message.setOptionalFixed32 (107);
-    message.setOptionalFixed64 (108);
-    message.setOptionalSfixed32(109);
-    message.setOptionalSfixed64(110);
-    message.setOptionalFloat   (111);
-    message.setOptionalDouble  (112);
-    message.setOptionalBool    (true);
-    message.setOptionalString  ("115");
-    message.setOptionalBytes   (toBytes("116"));
-
-    message.setOptionalGroup(
-      TestAllTypes.OptionalGroup.newBuilder().setA(117).build());
-    message.setOptionalNestedMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
-    message.setOptionalForeignMessage(
-      ForeignMessage.newBuilder().setC(119).build());
-    message.setOptionalImportMessage(
-      ImportMessage.newBuilder().setD(120).build());
-    message.setOptionalPublicImportMessage(
-      PublicImportMessage.newBuilder().setE(126).build());
-    message.setOptionalLazyMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
-
-    message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
-    message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
-    message.setOptionalImportEnum (ImportEnum.IMPORT_BAZ);
-
-    message.setOptionalStringPiece("124");
-    message.setOptionalCord("125");
-
-    // -----------------------------------------------------------------
-
-    message.addRepeatedInt32   (201);
-    message.addRepeatedInt64   (202);
-    message.addRepeatedUint32  (203);
-    message.addRepeatedUint64  (204);
-    message.addRepeatedSint32  (205);
-    message.addRepeatedSint64  (206);
-    message.addRepeatedFixed32 (207);
-    message.addRepeatedFixed64 (208);
-    message.addRepeatedSfixed32(209);
-    message.addRepeatedSfixed64(210);
-    message.addRepeatedFloat   (211);
-    message.addRepeatedDouble  (212);
-    message.addRepeatedBool    (true);
-    message.addRepeatedString  ("215");
-    message.addRepeatedBytes   (toBytes("216"));
-
-    message.addRepeatedGroup(
-      TestAllTypes.RepeatedGroup.newBuilder().setA(217).build());
-    message.addRepeatedNestedMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
-    message.addRepeatedForeignMessage(
-      ForeignMessage.newBuilder().setC(219).build());
-    message.addRepeatedImportMessage(
-      ImportMessage.newBuilder().setD(220).build());
-    message.addRepeatedLazyMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
-
-    message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR);
-    message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
-    message.addRepeatedImportEnum (ImportEnum.IMPORT_BAR);
-
-    message.addRepeatedStringPiece("224");
-    message.addRepeatedCord("225");
-
-    // Add a second one of each field.
-    message.addRepeatedInt32   (301);
-    message.addRepeatedInt64   (302);
-    message.addRepeatedUint32  (303);
-    message.addRepeatedUint64  (304);
-    message.addRepeatedSint32  (305);
-    message.addRepeatedSint64  (306);
-    message.addRepeatedFixed32 (307);
-    message.addRepeatedFixed64 (308);
-    message.addRepeatedSfixed32(309);
-    message.addRepeatedSfixed64(310);
-    message.addRepeatedFloat   (311);
-    message.addRepeatedDouble  (312);
-    message.addRepeatedBool    (false);
-    message.addRepeatedString  ("315");
-    message.addRepeatedBytes   (toBytes("316"));
-
-    message.addRepeatedGroup(
-      TestAllTypes.RepeatedGroup.newBuilder().setA(317).build());
-    message.addRepeatedNestedMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
-    message.addRepeatedForeignMessage(
-      ForeignMessage.newBuilder().setC(319).build());
-    message.addRepeatedImportMessage(
-      ImportMessage.newBuilder().setD(320).build());
-    message.addRepeatedLazyMessage(
-      TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
-
-    message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ);
-    message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ);
-    message.addRepeatedImportEnum (ImportEnum.IMPORT_BAZ);
-
-    message.addRepeatedStringPiece("324");
-    message.addRepeatedCord("325");
-
-    // -----------------------------------------------------------------
-
-    message.setDefaultInt32   (401);
-    message.setDefaultInt64   (402);
-    message.setDefaultUint32  (403);
-    message.setDefaultUint64  (404);
-    message.setDefaultSint32  (405);
-    message.setDefaultSint64  (406);
-    message.setDefaultFixed32 (407);
-    message.setDefaultFixed64 (408);
-    message.setDefaultSfixed32(409);
-    message.setDefaultSfixed64(410);
-    message.setDefaultFloat   (411);
-    message.setDefaultDouble  (412);
-    message.setDefaultBool    (false);
-    message.setDefaultString  ("415");
-    message.setDefaultBytes   (toBytes("416"));
-
-    message.setDefaultNestedEnum (TestAllTypes.NestedEnum.FOO);
-    message.setDefaultForeignEnum(ForeignEnum.FOREIGN_FOO);
-    message.setDefaultImportEnum (ImportEnum.IMPORT_FOO);
-
-    message.setDefaultStringPiece("424");
-    message.setDefaultCord("425");
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Modify the repeated fields of {@code message} to contain the values
-   * expected by {@code assertRepeatedFieldsModified()}.
-   */
-  public static void modifyRepeatedFields(TestAllTypes.Builder message) {
-    message.setRepeatedInt32   (1, 501);
-    message.setRepeatedInt64   (1, 502);
-    message.setRepeatedUint32  (1, 503);
-    message.setRepeatedUint64  (1, 504);
-    message.setRepeatedSint32  (1, 505);
-    message.setRepeatedSint64  (1, 506);
-    message.setRepeatedFixed32 (1, 507);
-    message.setRepeatedFixed64 (1, 508);
-    message.setRepeatedSfixed32(1, 509);
-    message.setRepeatedSfixed64(1, 510);
-    message.setRepeatedFloat   (1, 511);
-    message.setRepeatedDouble  (1, 512);
-    message.setRepeatedBool    (1, true);
-    message.setRepeatedString  (1, "515");
-    message.setRepeatedBytes   (1, toBytes("516"));
-
-    message.setRepeatedGroup(1,
-      TestAllTypes.RepeatedGroup.newBuilder().setA(517).build());
-    message.setRepeatedNestedMessage(1,
-      TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
-    message.setRepeatedForeignMessage(1,
-      ForeignMessage.newBuilder().setC(519).build());
-    message.setRepeatedImportMessage(1,
-      ImportMessage.newBuilder().setD(520).build());
-    message.setRepeatedLazyMessage(1,
-      TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
-
-    message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO);
-    message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO);
-    message.setRepeatedImportEnum (1, ImportEnum.IMPORT_FOO);
-
-    message.setRepeatedStringPiece(1, "524");
-    message.setRepeatedCord(1, "525");
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all fields of
-   * {@code message} are set to the values assigned by {@code setAllFields}.
-   */
-  public static void assertAllFieldsSet(TestAllTypesOrBuilder message) {
-    Assert.assertTrue(message.hasOptionalInt32   ());
-    Assert.assertTrue(message.hasOptionalInt64   ());
-    Assert.assertTrue(message.hasOptionalUint32  ());
-    Assert.assertTrue(message.hasOptionalUint64  ());
-    Assert.assertTrue(message.hasOptionalSint32  ());
-    Assert.assertTrue(message.hasOptionalSint64  ());
-    Assert.assertTrue(message.hasOptionalFixed32 ());
-    Assert.assertTrue(message.hasOptionalFixed64 ());
-    Assert.assertTrue(message.hasOptionalSfixed32());
-    Assert.assertTrue(message.hasOptionalSfixed64());
-    Assert.assertTrue(message.hasOptionalFloat   ());
-    Assert.assertTrue(message.hasOptionalDouble  ());
-    Assert.assertTrue(message.hasOptionalBool    ());
-    Assert.assertTrue(message.hasOptionalString  ());
-    Assert.assertTrue(message.hasOptionalBytes   ());
-
-    Assert.assertTrue(message.hasOptionalGroup         ());
-    Assert.assertTrue(message.hasOptionalNestedMessage ());
-    Assert.assertTrue(message.hasOptionalForeignMessage());
-    Assert.assertTrue(message.hasOptionalImportMessage ());
-
-    Assert.assertTrue(message.getOptionalGroup         ().hasA());
-    Assert.assertTrue(message.getOptionalNestedMessage ().hasBb());
-    Assert.assertTrue(message.getOptionalForeignMessage().hasC());
-    Assert.assertTrue(message.getOptionalImportMessage ().hasD());
-
-    Assert.assertTrue(message.hasOptionalNestedEnum ());
-    Assert.assertTrue(message.hasOptionalForeignEnum());
-    Assert.assertTrue(message.hasOptionalImportEnum ());
-
-    Assert.assertTrue(message.hasOptionalStringPiece());
-    Assert.assertTrue(message.hasOptionalCord());
-
-    Assert.assertEquals(101  , message.getOptionalInt32   ());
-    Assert.assertEquals(102  , message.getOptionalInt64   ());
-    Assert.assertEquals(103  , message.getOptionalUint32  ());
-    Assert.assertEquals(104  , message.getOptionalUint64  ());
-    Assert.assertEquals(105  , message.getOptionalSint32  ());
-    Assert.assertEquals(106  , message.getOptionalSint64  ());
-    Assert.assertEquals(107  , message.getOptionalFixed32 ());
-    Assert.assertEquals(108  , message.getOptionalFixed64 ());
-    Assert.assertEquals(109  , message.getOptionalSfixed32());
-    Assert.assertEquals(110  , message.getOptionalSfixed64());
-    Assert.assertEquals(111  , message.getOptionalFloat   (), 0.0);
-    Assert.assertEquals(112  , message.getOptionalDouble  (), 0.0);
-    Assert.assertEquals(true , message.getOptionalBool    ());
-    Assert.assertEquals("115", message.getOptionalString  ());
-    Assert.assertEquals(toBytes("116"), message.getOptionalBytes());
-
-    Assert.assertEquals(117, message.getOptionalGroup              ().getA());
-    Assert.assertEquals(118, message.getOptionalNestedMessage      ().getBb());
-    Assert.assertEquals(119, message.getOptionalForeignMessage     ().getC());
-    Assert.assertEquals(120, message.getOptionalImportMessage      ().getD());
-    Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE());
-    Assert.assertEquals(127, message.getOptionalLazyMessage        ().getBb());
-
-    Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
-    Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getOptionalImportEnum());
-
-    Assert.assertEquals("124", message.getOptionalStringPiece());
-    Assert.assertEquals("125", message.getOptionalCord());
-
-    // -----------------------------------------------------------------
-
-    Assert.assertEquals(2, message.getRepeatedInt32Count   ());
-    Assert.assertEquals(2, message.getRepeatedInt64Count   ());
-    Assert.assertEquals(2, message.getRepeatedUint32Count  ());
-    Assert.assertEquals(2, message.getRepeatedUint64Count  ());
-    Assert.assertEquals(2, message.getRepeatedSint32Count  ());
-    Assert.assertEquals(2, message.getRepeatedSint64Count  ());
-    Assert.assertEquals(2, message.getRepeatedFixed32Count ());
-    Assert.assertEquals(2, message.getRepeatedFixed64Count ());
-    Assert.assertEquals(2, message.getRepeatedSfixed32Count());
-    Assert.assertEquals(2, message.getRepeatedSfixed64Count());
-    Assert.assertEquals(2, message.getRepeatedFloatCount   ());
-    Assert.assertEquals(2, message.getRepeatedDoubleCount  ());
-    Assert.assertEquals(2, message.getRepeatedBoolCount    ());
-    Assert.assertEquals(2, message.getRepeatedStringCount  ());
-    Assert.assertEquals(2, message.getRepeatedBytesCount   ());
-
-    Assert.assertEquals(2, message.getRepeatedGroupCount         ());
-    Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
-    Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
-    Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
-    Assert.assertEquals(2, message.getRepeatedLazyMessageCount   ());
-    Assert.assertEquals(2, message.getRepeatedNestedEnumCount    ());
-    Assert.assertEquals(2, message.getRepeatedForeignEnumCount   ());
-    Assert.assertEquals(2, message.getRepeatedImportEnumCount    ());
-
-    Assert.assertEquals(2, message.getRepeatedStringPieceCount());
-    Assert.assertEquals(2, message.getRepeatedCordCount());
-
-    Assert.assertEquals(201  , message.getRepeatedInt32   (0));
-    Assert.assertEquals(202  , message.getRepeatedInt64   (0));
-    Assert.assertEquals(203  , message.getRepeatedUint32  (0));
-    Assert.assertEquals(204  , message.getRepeatedUint64  (0));
-    Assert.assertEquals(205  , message.getRepeatedSint32  (0));
-    Assert.assertEquals(206  , message.getRepeatedSint64  (0));
-    Assert.assertEquals(207  , message.getRepeatedFixed32 (0));
-    Assert.assertEquals(208  , message.getRepeatedFixed64 (0));
-    Assert.assertEquals(209  , message.getRepeatedSfixed32(0));
-    Assert.assertEquals(210  , message.getRepeatedSfixed64(0));
-    Assert.assertEquals(211  , message.getRepeatedFloat   (0), 0.0);
-    Assert.assertEquals(212  , message.getRepeatedDouble  (0), 0.0);
-    Assert.assertEquals(true , message.getRepeatedBool    (0));
-    Assert.assertEquals("215", message.getRepeatedString  (0));
-    Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
-
-    Assert.assertEquals(217, message.getRepeatedGroup         (0).getA());
-    Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
-    Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
-    Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
-    Assert.assertEquals(227, message.getRepeatedLazyMessage   (0).getBb());
-
-    Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
-    Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
-
-    Assert.assertEquals("224", message.getRepeatedStringPiece(0));
-    Assert.assertEquals("225", message.getRepeatedCord(0));
-
-    Assert.assertEquals(301  , message.getRepeatedInt32   (1));
-    Assert.assertEquals(302  , message.getRepeatedInt64   (1));
-    Assert.assertEquals(303  , message.getRepeatedUint32  (1));
-    Assert.assertEquals(304  , message.getRepeatedUint64  (1));
-    Assert.assertEquals(305  , message.getRepeatedSint32  (1));
-    Assert.assertEquals(306  , message.getRepeatedSint64  (1));
-    Assert.assertEquals(307  , message.getRepeatedFixed32 (1));
-    Assert.assertEquals(308  , message.getRepeatedFixed64 (1));
-    Assert.assertEquals(309  , message.getRepeatedSfixed32(1));
-    Assert.assertEquals(310  , message.getRepeatedSfixed64(1));
-    Assert.assertEquals(311  , message.getRepeatedFloat   (1), 0.0);
-    Assert.assertEquals(312  , message.getRepeatedDouble  (1), 0.0);
-    Assert.assertEquals(false, message.getRepeatedBool    (1));
-    Assert.assertEquals("315", message.getRepeatedString  (1));
-    Assert.assertEquals(toBytes("316"), message.getRepeatedBytes(1));
-
-    Assert.assertEquals(317, message.getRepeatedGroup         (1).getA());
-    Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb());
-    Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC());
-    Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD());
-    Assert.assertEquals(327, message.getRepeatedLazyMessage   (1).getBb());
-
-    Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1));
-    Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getRepeatedImportEnum(1));
-
-    Assert.assertEquals("324", message.getRepeatedStringPiece(1));
-    Assert.assertEquals("325", message.getRepeatedCord(1));
-
-    // -----------------------------------------------------------------
-
-    Assert.assertTrue(message.hasDefaultInt32   ());
-    Assert.assertTrue(message.hasDefaultInt64   ());
-    Assert.assertTrue(message.hasDefaultUint32  ());
-    Assert.assertTrue(message.hasDefaultUint64  ());
-    Assert.assertTrue(message.hasDefaultSint32  ());
-    Assert.assertTrue(message.hasDefaultSint64  ());
-    Assert.assertTrue(message.hasDefaultFixed32 ());
-    Assert.assertTrue(message.hasDefaultFixed64 ());
-    Assert.assertTrue(message.hasDefaultSfixed32());
-    Assert.assertTrue(message.hasDefaultSfixed64());
-    Assert.assertTrue(message.hasDefaultFloat   ());
-    Assert.assertTrue(message.hasDefaultDouble  ());
-    Assert.assertTrue(message.hasDefaultBool    ());
-    Assert.assertTrue(message.hasDefaultString  ());
-    Assert.assertTrue(message.hasDefaultBytes   ());
-
-    Assert.assertTrue(message.hasDefaultNestedEnum ());
-    Assert.assertTrue(message.hasDefaultForeignEnum());
-    Assert.assertTrue(message.hasDefaultImportEnum ());
-
-    Assert.assertTrue(message.hasDefaultStringPiece());
-    Assert.assertTrue(message.hasDefaultCord());
-
-    Assert.assertEquals(401  , message.getDefaultInt32   ());
-    Assert.assertEquals(402  , message.getDefaultInt64   ());
-    Assert.assertEquals(403  , message.getDefaultUint32  ());
-    Assert.assertEquals(404  , message.getDefaultUint64  ());
-    Assert.assertEquals(405  , message.getDefaultSint32  ());
-    Assert.assertEquals(406  , message.getDefaultSint64  ());
-    Assert.assertEquals(407  , message.getDefaultFixed32 ());
-    Assert.assertEquals(408  , message.getDefaultFixed64 ());
-    Assert.assertEquals(409  , message.getDefaultSfixed32());
-    Assert.assertEquals(410  , message.getDefaultSfixed64());
-    Assert.assertEquals(411  , message.getDefaultFloat   (), 0.0);
-    Assert.assertEquals(412  , message.getDefaultDouble  (), 0.0);
-    Assert.assertEquals(false, message.getDefaultBool    ());
-    Assert.assertEquals("415", message.getDefaultString  ());
-    Assert.assertEquals(toBytes("416"), message.getDefaultBytes());
-
-    Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum ());
-    Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getDefaultForeignEnum());
-    Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getDefaultImportEnum());
-
-    Assert.assertEquals("424", message.getDefaultStringPiece());
-    Assert.assertEquals("425", message.getDefaultCord());
-  }
-
-  // -------------------------------------------------------------------
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all fields of
-   * {@code message} are cleared, and that getting the fields returns their
-   * default values.
-   */
-  public static void assertClear(TestAllTypesOrBuilder message) {
-    // hasBlah() should initially be false for all optional fields.
-    Assert.assertFalse(message.hasOptionalInt32   ());
-    Assert.assertFalse(message.hasOptionalInt64   ());
-    Assert.assertFalse(message.hasOptionalUint32  ());
-    Assert.assertFalse(message.hasOptionalUint64  ());
-    Assert.assertFalse(message.hasOptionalSint32  ());
-    Assert.assertFalse(message.hasOptionalSint64  ());
-    Assert.assertFalse(message.hasOptionalFixed32 ());
-    Assert.assertFalse(message.hasOptionalFixed64 ());
-    Assert.assertFalse(message.hasOptionalSfixed32());
-    Assert.assertFalse(message.hasOptionalSfixed64());
-    Assert.assertFalse(message.hasOptionalFloat   ());
-    Assert.assertFalse(message.hasOptionalDouble  ());
-    Assert.assertFalse(message.hasOptionalBool    ());
-    Assert.assertFalse(message.hasOptionalString  ());
-    Assert.assertFalse(message.hasOptionalBytes   ());
-
-    Assert.assertFalse(message.hasOptionalGroup         ());
-    Assert.assertFalse(message.hasOptionalNestedMessage ());
-    Assert.assertFalse(message.hasOptionalForeignMessage());
-    Assert.assertFalse(message.hasOptionalImportMessage ());
-
-    Assert.assertFalse(message.hasOptionalNestedEnum ());
-    Assert.assertFalse(message.hasOptionalForeignEnum());
-    Assert.assertFalse(message.hasOptionalImportEnum ());
-
-    Assert.assertFalse(message.hasOptionalStringPiece());
-    Assert.assertFalse(message.hasOptionalCord());
-
-    // Optional fields without defaults are set to zero or something like it.
-    Assert.assertEquals(0    , message.getOptionalInt32   ());
-    Assert.assertEquals(0    , message.getOptionalInt64   ());
-    Assert.assertEquals(0    , message.getOptionalUint32  ());
-    Assert.assertEquals(0    , message.getOptionalUint64  ());
-    Assert.assertEquals(0    , message.getOptionalSint32  ());
-    Assert.assertEquals(0    , message.getOptionalSint64  ());
-    Assert.assertEquals(0    , message.getOptionalFixed32 ());
-    Assert.assertEquals(0    , message.getOptionalFixed64 ());
-    Assert.assertEquals(0    , message.getOptionalSfixed32());
-    Assert.assertEquals(0    , message.getOptionalSfixed64());
-    Assert.assertEquals(0    , message.getOptionalFloat   (), 0.0);
-    Assert.assertEquals(0    , message.getOptionalDouble  (), 0.0);
-    Assert.assertEquals(false, message.getOptionalBool    ());
-    Assert.assertEquals(""   , message.getOptionalString  ());
-    Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes());
-
-    // Embedded messages should also be clear.
-    Assert.assertFalse(message.getOptionalGroup              ().hasA());
-    Assert.assertFalse(message.getOptionalNestedMessage      ().hasBb());
-    Assert.assertFalse(message.getOptionalForeignMessage     ().hasC());
-    Assert.assertFalse(message.getOptionalImportMessage      ().hasD());
-    Assert.assertFalse(message.getOptionalPublicImportMessage().hasE());
-    Assert.assertFalse(message.getOptionalLazyMessage        ().hasBb());
-
-    Assert.assertEquals(0, message.getOptionalGroup              ().getA());
-    Assert.assertEquals(0, message.getOptionalNestedMessage      ().getBb());
-    Assert.assertEquals(0, message.getOptionalForeignMessage     ().getC());
-    Assert.assertEquals(0, message.getOptionalImportMessage      ().getD());
-    Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE());
-    Assert.assertEquals(0, message.getOptionalLazyMessage        ().getBb());
-
-    // Enums without defaults are set to the first value in the enum.
-    Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ());
-    Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getOptionalForeignEnum());
-    Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getOptionalImportEnum());
-
-    Assert.assertEquals("", message.getOptionalStringPiece());
-    Assert.assertEquals("", message.getOptionalCord());
-
-    // Repeated fields are empty.
-    Assert.assertEquals(0, message.getRepeatedInt32Count   ());
-    Assert.assertEquals(0, message.getRepeatedInt64Count   ());
-    Assert.assertEquals(0, message.getRepeatedUint32Count  ());
-    Assert.assertEquals(0, message.getRepeatedUint64Count  ());
-    Assert.assertEquals(0, message.getRepeatedSint32Count  ());
-    Assert.assertEquals(0, message.getRepeatedSint64Count  ());
-    Assert.assertEquals(0, message.getRepeatedFixed32Count ());
-    Assert.assertEquals(0, message.getRepeatedFixed64Count ());
-    Assert.assertEquals(0, message.getRepeatedSfixed32Count());
-    Assert.assertEquals(0, message.getRepeatedSfixed64Count());
-    Assert.assertEquals(0, message.getRepeatedFloatCount   ());
-    Assert.assertEquals(0, message.getRepeatedDoubleCount  ());
-    Assert.assertEquals(0, message.getRepeatedBoolCount    ());
-    Assert.assertEquals(0, message.getRepeatedStringCount  ());
-    Assert.assertEquals(0, message.getRepeatedBytesCount   ());
-
-    Assert.assertEquals(0, message.getRepeatedGroupCount         ());
-    Assert.assertEquals(0, message.getRepeatedNestedMessageCount ());
-    Assert.assertEquals(0, message.getRepeatedForeignMessageCount());
-    Assert.assertEquals(0, message.getRepeatedImportMessageCount ());
-    Assert.assertEquals(0, message.getRepeatedLazyMessageCount   ());
-    Assert.assertEquals(0, message.getRepeatedNestedEnumCount    ());
-    Assert.assertEquals(0, message.getRepeatedForeignEnumCount   ());
-    Assert.assertEquals(0, message.getRepeatedImportEnumCount    ());
-
-    Assert.assertEquals(0, message.getRepeatedStringPieceCount());
-    Assert.assertEquals(0, message.getRepeatedCordCount());
-
-    // hasBlah() should also be false for all default fields.
-    Assert.assertFalse(message.hasDefaultInt32   ());
-    Assert.assertFalse(message.hasDefaultInt64   ());
-    Assert.assertFalse(message.hasDefaultUint32  ());
-    Assert.assertFalse(message.hasDefaultUint64  ());
-    Assert.assertFalse(message.hasDefaultSint32  ());
-    Assert.assertFalse(message.hasDefaultSint64  ());
-    Assert.assertFalse(message.hasDefaultFixed32 ());
-    Assert.assertFalse(message.hasDefaultFixed64 ());
-    Assert.assertFalse(message.hasDefaultSfixed32());
-    Assert.assertFalse(message.hasDefaultSfixed64());
-    Assert.assertFalse(message.hasDefaultFloat   ());
-    Assert.assertFalse(message.hasDefaultDouble  ());
-    Assert.assertFalse(message.hasDefaultBool    ());
-    Assert.assertFalse(message.hasDefaultString  ());
-    Assert.assertFalse(message.hasDefaultBytes   ());
-
-    Assert.assertFalse(message.hasDefaultNestedEnum ());
-    Assert.assertFalse(message.hasDefaultForeignEnum());
-    Assert.assertFalse(message.hasDefaultImportEnum ());
-
-    Assert.assertFalse(message.hasDefaultStringPiece());
-    Assert.assertFalse(message.hasDefaultCord());
-
-    // Fields with defaults have their default values (duh).
-    Assert.assertEquals( 41    , message.getDefaultInt32   ());
-    Assert.assertEquals( 42    , message.getDefaultInt64   ());
-    Assert.assertEquals( 43    , message.getDefaultUint32  ());
-    Assert.assertEquals( 44    , message.getDefaultUint64  ());
-    Assert.assertEquals(-45    , message.getDefaultSint32  ());
-    Assert.assertEquals( 46    , message.getDefaultSint64  ());
-    Assert.assertEquals( 47    , message.getDefaultFixed32 ());
-    Assert.assertEquals( 48    , message.getDefaultFixed64 ());
-    Assert.assertEquals( 49    , message.getDefaultSfixed32());
-    Assert.assertEquals(-50    , message.getDefaultSfixed64());
-    Assert.assertEquals( 51.5  , message.getDefaultFloat   (), 0.0);
-    Assert.assertEquals( 52e3  , message.getDefaultDouble  (), 0.0);
-    Assert.assertEquals(true   , message.getDefaultBool    ());
-    Assert.assertEquals("hello", message.getDefaultString  ());
-    Assert.assertEquals(toBytes("world"), message.getDefaultBytes());
-
-    Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum ());
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getDefaultForeignEnum());
-    Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getDefaultImportEnum());
-
-    Assert.assertEquals("abc", message.getDefaultStringPiece());
-    Assert.assertEquals("123", message.getDefaultCord());
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all fields of
-   * {@code message} are set to the values assigned by {@code setAllFields}
-   * followed by {@code modifyRepeatedFields}.
-   */
-  public static void assertRepeatedFieldsModified(
-      TestAllTypesOrBuilder message) {
-    // ModifyRepeatedFields only sets the second repeated element of each
-    // field.  In addition to verifying this, we also verify that the first
-    // element and size were *not* modified.
-    Assert.assertEquals(2, message.getRepeatedInt32Count   ());
-    Assert.assertEquals(2, message.getRepeatedInt64Count   ());
-    Assert.assertEquals(2, message.getRepeatedUint32Count  ());
-    Assert.assertEquals(2, message.getRepeatedUint64Count  ());
-    Assert.assertEquals(2, message.getRepeatedSint32Count  ());
-    Assert.assertEquals(2, message.getRepeatedSint64Count  ());
-    Assert.assertEquals(2, message.getRepeatedFixed32Count ());
-    Assert.assertEquals(2, message.getRepeatedFixed64Count ());
-    Assert.assertEquals(2, message.getRepeatedSfixed32Count());
-    Assert.assertEquals(2, message.getRepeatedSfixed64Count());
-    Assert.assertEquals(2, message.getRepeatedFloatCount   ());
-    Assert.assertEquals(2, message.getRepeatedDoubleCount  ());
-    Assert.assertEquals(2, message.getRepeatedBoolCount    ());
-    Assert.assertEquals(2, message.getRepeatedStringCount  ());
-    Assert.assertEquals(2, message.getRepeatedBytesCount   ());
-
-    Assert.assertEquals(2, message.getRepeatedGroupCount         ());
-    Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
-    Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
-    Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
-    Assert.assertEquals(2, message.getRepeatedLazyMessageCount   ());
-    Assert.assertEquals(2, message.getRepeatedNestedEnumCount    ());
-    Assert.assertEquals(2, message.getRepeatedForeignEnumCount   ());
-    Assert.assertEquals(2, message.getRepeatedImportEnumCount    ());
-
-    Assert.assertEquals(2, message.getRepeatedStringPieceCount());
-    Assert.assertEquals(2, message.getRepeatedCordCount());
-
-    Assert.assertEquals(201  , message.getRepeatedInt32   (0));
-    Assert.assertEquals(202L , message.getRepeatedInt64   (0));
-    Assert.assertEquals(203  , message.getRepeatedUint32  (0));
-    Assert.assertEquals(204L , message.getRepeatedUint64  (0));
-    Assert.assertEquals(205  , message.getRepeatedSint32  (0));
-    Assert.assertEquals(206L , message.getRepeatedSint64  (0));
-    Assert.assertEquals(207  , message.getRepeatedFixed32 (0));
-    Assert.assertEquals(208L , message.getRepeatedFixed64 (0));
-    Assert.assertEquals(209  , message.getRepeatedSfixed32(0));
-    Assert.assertEquals(210L , message.getRepeatedSfixed64(0));
-    Assert.assertEquals(211F , message.getRepeatedFloat   (0));
-    Assert.assertEquals(212D , message.getRepeatedDouble  (0));
-    Assert.assertEquals(true , message.getRepeatedBool    (0));
-    Assert.assertEquals("215", message.getRepeatedString  (0));
-    Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
-
-    Assert.assertEquals(217, message.getRepeatedGroup         (0).getA());
-    Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
-    Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
-    Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
-    Assert.assertEquals(227, message.getRepeatedLazyMessage   (0).getBb());
-
-    Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
-    Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
-
-    Assert.assertEquals("224", message.getRepeatedStringPiece(0));
-    Assert.assertEquals("225", message.getRepeatedCord(0));
-
-    // Actually verify the second (modified) elements now.
-    Assert.assertEquals(501  , message.getRepeatedInt32   (1));
-    Assert.assertEquals(502L , message.getRepeatedInt64   (1));
-    Assert.assertEquals(503  , message.getRepeatedUint32  (1));
-    Assert.assertEquals(504L , message.getRepeatedUint64  (1));
-    Assert.assertEquals(505  , message.getRepeatedSint32  (1));
-    Assert.assertEquals(506L , message.getRepeatedSint64  (1));
-    Assert.assertEquals(507  , message.getRepeatedFixed32 (1));
-    Assert.assertEquals(508L , message.getRepeatedFixed64 (1));
-    Assert.assertEquals(509  , message.getRepeatedSfixed32(1));
-    Assert.assertEquals(510L , message.getRepeatedSfixed64(1));
-    Assert.assertEquals(511F , message.getRepeatedFloat   (1));
-    Assert.assertEquals(512D , message.getRepeatedDouble  (1));
-    Assert.assertEquals(true , message.getRepeatedBool    (1));
-    Assert.assertEquals("515", message.getRepeatedString  (1));
-    Assert.assertEquals(toBytes("516"), message.getRepeatedBytes(1));
-
-    Assert.assertEquals(517, message.getRepeatedGroup         (1).getA());
-    Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb());
-    Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC());
-    Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD());
-    Assert.assertEquals(527, message.getRepeatedLazyMessage   (1).getBb());
-
-    Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1));
-    Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1));
-    Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getRepeatedImportEnum(1));
-
-    Assert.assertEquals("524", message.getRepeatedStringPiece(1));
-    Assert.assertEquals("525", message.getRepeatedCord(1));
-  }
-
-  /**
-   * Set every field of {@code message} to a unique value.
-   */
-  public static void setPackedFields(TestPackedTypes.Builder message) {
-    message.addPackedInt32   (601);
-    message.addPackedInt64   (602);
-    message.addPackedUint32  (603);
-    message.addPackedUint64  (604);
-    message.addPackedSint32  (605);
-    message.addPackedSint64  (606);
-    message.addPackedFixed32 (607);
-    message.addPackedFixed64 (608);
-    message.addPackedSfixed32(609);
-    message.addPackedSfixed64(610);
-    message.addPackedFloat   (611);
-    message.addPackedDouble  (612);
-    message.addPackedBool    (true);
-    message.addPackedEnum    (ForeignEnum.FOREIGN_BAR);
-    // Add a second one of each field.
-    message.addPackedInt32   (701);
-    message.addPackedInt64   (702);
-    message.addPackedUint32  (703);
-    message.addPackedUint64  (704);
-    message.addPackedSint32  (705);
-    message.addPackedSint64  (706);
-    message.addPackedFixed32 (707);
-    message.addPackedFixed64 (708);
-    message.addPackedSfixed32(709);
-    message.addPackedSfixed64(710);
-    message.addPackedFloat   (711);
-    message.addPackedDouble  (712);
-    message.addPackedBool    (false);
-    message.addPackedEnum    (ForeignEnum.FOREIGN_BAZ);
-  }
-
-  /**
-   * Set every field of {@code message} to a unique value. Must correspond with
-   * the values applied by {@code setPackedFields}.
-   */
-  public static void setUnpackedFields(TestUnpackedTypes.Builder message) {
-    message.addUnpackedInt32   (601);
-    message.addUnpackedInt64   (602);
-    message.addUnpackedUint32  (603);
-    message.addUnpackedUint64  (604);
-    message.addUnpackedSint32  (605);
-    message.addUnpackedSint64  (606);
-    message.addUnpackedFixed32 (607);
-    message.addUnpackedFixed64 (608);
-    message.addUnpackedSfixed32(609);
-    message.addUnpackedSfixed64(610);
-    message.addUnpackedFloat   (611);
-    message.addUnpackedDouble  (612);
-    message.addUnpackedBool    (true);
-    message.addUnpackedEnum    (ForeignEnum.FOREIGN_BAR);
-    // Add a second one of each field.
-    message.addUnpackedInt32   (701);
-    message.addUnpackedInt64   (702);
-    message.addUnpackedUint32  (703);
-    message.addUnpackedUint64  (704);
-    message.addUnpackedSint32  (705);
-    message.addUnpackedSint64  (706);
-    message.addUnpackedFixed32 (707);
-    message.addUnpackedFixed64 (708);
-    message.addUnpackedSfixed32(709);
-    message.addUnpackedSfixed64(710);
-    message.addUnpackedFloat   (711);
-    message.addUnpackedDouble  (712);
-    message.addUnpackedBool    (false);
-    message.addUnpackedEnum    (ForeignEnum.FOREIGN_BAZ);
-  }
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all fields of
-   * {@code message} are set to the values assigned by {@code setPackedFields}.
-   */
-  public static void assertPackedFieldsSet(TestPackedTypes message) {
-    Assert.assertEquals(2, message.getPackedInt32Count   ());
-    Assert.assertEquals(2, message.getPackedInt64Count   ());
-    Assert.assertEquals(2, message.getPackedUint32Count  ());
-    Assert.assertEquals(2, message.getPackedUint64Count  ());
-    Assert.assertEquals(2, message.getPackedSint32Count  ());
-    Assert.assertEquals(2, message.getPackedSint64Count  ());
-    Assert.assertEquals(2, message.getPackedFixed32Count ());
-    Assert.assertEquals(2, message.getPackedFixed64Count ());
-    Assert.assertEquals(2, message.getPackedSfixed32Count());
-    Assert.assertEquals(2, message.getPackedSfixed64Count());
-    Assert.assertEquals(2, message.getPackedFloatCount   ());
-    Assert.assertEquals(2, message.getPackedDoubleCount  ());
-    Assert.assertEquals(2, message.getPackedBoolCount    ());
-    Assert.assertEquals(2, message.getPackedEnumCount   ());
-    Assert.assertEquals(601  , message.getPackedInt32   (0));
-    Assert.assertEquals(602  , message.getPackedInt64   (0));
-    Assert.assertEquals(603  , message.getPackedUint32  (0));
-    Assert.assertEquals(604  , message.getPackedUint64  (0));
-    Assert.assertEquals(605  , message.getPackedSint32  (0));
-    Assert.assertEquals(606  , message.getPackedSint64  (0));
-    Assert.assertEquals(607  , message.getPackedFixed32 (0));
-    Assert.assertEquals(608  , message.getPackedFixed64 (0));
-    Assert.assertEquals(609  , message.getPackedSfixed32(0));
-    Assert.assertEquals(610  , message.getPackedSfixed64(0));
-    Assert.assertEquals(611  , message.getPackedFloat   (0), 0.0);
-    Assert.assertEquals(612  , message.getPackedDouble  (0), 0.0);
-    Assert.assertEquals(true , message.getPackedBool    (0));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
-    Assert.assertEquals(701  , message.getPackedInt32   (1));
-    Assert.assertEquals(702  , message.getPackedInt64   (1));
-    Assert.assertEquals(703  , message.getPackedUint32  (1));
-    Assert.assertEquals(704  , message.getPackedUint64  (1));
-    Assert.assertEquals(705  , message.getPackedSint32  (1));
-    Assert.assertEquals(706  , message.getPackedSint64  (1));
-    Assert.assertEquals(707  , message.getPackedFixed32 (1));
-    Assert.assertEquals(708  , message.getPackedFixed64 (1));
-    Assert.assertEquals(709  , message.getPackedSfixed32(1));
-    Assert.assertEquals(710  , message.getPackedSfixed64(1));
-    Assert.assertEquals(711  , message.getPackedFloat   (1), 0.0);
-    Assert.assertEquals(712  , message.getPackedDouble  (1), 0.0);
-    Assert.assertEquals(false, message.getPackedBool    (1));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
-  }
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all fields of
-   * {@code message} are set to the values assigned by {@code setUnpackedFields}.
-   */
-  public static void assertUnpackedFieldsSet(TestUnpackedTypes message) {
-    Assert.assertEquals(2, message.getUnpackedInt32Count   ());
-    Assert.assertEquals(2, message.getUnpackedInt64Count   ());
-    Assert.assertEquals(2, message.getUnpackedUint32Count  ());
-    Assert.assertEquals(2, message.getUnpackedUint64Count  ());
-    Assert.assertEquals(2, message.getUnpackedSint32Count  ());
-    Assert.assertEquals(2, message.getUnpackedSint64Count  ());
-    Assert.assertEquals(2, message.getUnpackedFixed32Count ());
-    Assert.assertEquals(2, message.getUnpackedFixed64Count ());
-    Assert.assertEquals(2, message.getUnpackedSfixed32Count());
-    Assert.assertEquals(2, message.getUnpackedSfixed64Count());
-    Assert.assertEquals(2, message.getUnpackedFloatCount   ());
-    Assert.assertEquals(2, message.getUnpackedDoubleCount  ());
-    Assert.assertEquals(2, message.getUnpackedBoolCount    ());
-    Assert.assertEquals(2, message.getUnpackedEnumCount   ());
-    Assert.assertEquals(601  , message.getUnpackedInt32   (0));
-    Assert.assertEquals(602  , message.getUnpackedInt64   (0));
-    Assert.assertEquals(603  , message.getUnpackedUint32  (0));
-    Assert.assertEquals(604  , message.getUnpackedUint64  (0));
-    Assert.assertEquals(605  , message.getUnpackedSint32  (0));
-    Assert.assertEquals(606  , message.getUnpackedSint64  (0));
-    Assert.assertEquals(607  , message.getUnpackedFixed32 (0));
-    Assert.assertEquals(608  , message.getUnpackedFixed64 (0));
-    Assert.assertEquals(609  , message.getUnpackedSfixed32(0));
-    Assert.assertEquals(610  , message.getUnpackedSfixed64(0));
-    Assert.assertEquals(611  , message.getUnpackedFloat   (0), 0.0);
-    Assert.assertEquals(612  , message.getUnpackedDouble  (0), 0.0);
-    Assert.assertEquals(true , message.getUnpackedBool    (0));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0));
-    Assert.assertEquals(701  , message.getUnpackedInt32   (1));
-    Assert.assertEquals(702  , message.getUnpackedInt64   (1));
-    Assert.assertEquals(703  , message.getUnpackedUint32  (1));
-    Assert.assertEquals(704  , message.getUnpackedUint64  (1));
-    Assert.assertEquals(705  , message.getUnpackedSint32  (1));
-    Assert.assertEquals(706  , message.getUnpackedSint64  (1));
-    Assert.assertEquals(707  , message.getUnpackedFixed32 (1));
-    Assert.assertEquals(708  , message.getUnpackedFixed64 (1));
-    Assert.assertEquals(709  , message.getUnpackedSfixed32(1));
-    Assert.assertEquals(710  , message.getUnpackedSfixed64(1));
-    Assert.assertEquals(711  , message.getUnpackedFloat   (1), 0.0);
-    Assert.assertEquals(712  , message.getUnpackedDouble  (1), 0.0);
-    Assert.assertEquals(false, message.getUnpackedBool    (1));
-    Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1));
-  }
-
-  // ===================================================================
-  // Like above, but for extensions
-
-  // Java gets confused with things like assertEquals(int, Integer):  it can't
-  // decide whether to call assertEquals(int, int) or assertEquals(Object,
-  // Object).  So we define these methods to help it.
-  private static void assertEqualsExactType(int a, int b) {
-    Assert.assertEquals(a, b);
-  }
-  private static void assertEqualsExactType(long a, long b) {
-    Assert.assertEquals(a, b);
-  }
-  private static void assertEqualsExactType(float a, float b) {
-    Assert.assertEquals(a, b, 0.0);
-  }
-  private static void assertEqualsExactType(double a, double b) {
-    Assert.assertEquals(a, b, 0.0);
-  }
-  private static void assertEqualsExactType(boolean a, boolean b) {
-    Assert.assertEquals(a, b);
-  }
-  private static void assertEqualsExactType(String a, String b) {
-    Assert.assertEquals(a, b);
-  }
-  private static void assertEqualsExactType(ByteString a, ByteString b) {
-    Assert.assertEquals(a, b);
-  }
-  private static void assertEqualsExactType(TestAllTypes.NestedEnum a,
-                                            TestAllTypes.NestedEnum b) {
-    Assert.assertEquals(a, b);
-  }
-  private static void assertEqualsExactType(ForeignEnum a, ForeignEnum b) {
-    Assert.assertEquals(a, b);
-  }
-  private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
-    Assert.assertEquals(a, b);
-  }
-  /**
-   * Get an unmodifiable {@link ExtensionRegistry} containing all the
-   * extensions of {@code TestAllExtensions}.
-   */
-  public static ExtensionRegistry getExtensionRegistry() {
-    ExtensionRegistry registry = ExtensionRegistry.newInstance();
-    registerAllExtensions(registry);
-    return registry.getUnmodifiable();
-  }
-
-
-  /**
-   * Register all of {@code TestAllExtensions}'s extensions with the
-   * given {@link ExtensionRegistry}.
-   */
-  public static void registerAllExtensions(ExtensionRegistry registry) {
-    UnittestProto.registerAllExtensions(registry);
-  }
-
-
-  /**
-   * Set every field of {@code message} to the values expected by
-   * {@code assertAllExtensionsSet()}.
-   */
-  public static void setAllExtensions(TestAllExtensions.Builder message) {
-    message.setExtension(optionalInt32Extension   , 101);
-    message.setExtension(optionalInt64Extension   , 102L);
-    message.setExtension(optionalUint32Extension  , 103);
-    message.setExtension(optionalUint64Extension  , 104L);
-    message.setExtension(optionalSint32Extension  , 105);
-    message.setExtension(optionalSint64Extension  , 106L);
-    message.setExtension(optionalFixed32Extension , 107);
-    message.setExtension(optionalFixed64Extension , 108L);
-    message.setExtension(optionalSfixed32Extension, 109);
-    message.setExtension(optionalSfixed64Extension, 110L);
-    message.setExtension(optionalFloatExtension   , 111F);
-    message.setExtension(optionalDoubleExtension  , 112D);
-    message.setExtension(optionalBoolExtension    , true);
-    message.setExtension(optionalStringExtension  , "115");
-    message.setExtension(optionalBytesExtension   , toBytes("116"));
-
-    message.setExtension(optionalGroupExtension,
-      OptionalGroup_extension.newBuilder().setA(117).build());
-    message.setExtension(optionalNestedMessageExtension,
-      TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
-    message.setExtension(optionalForeignMessageExtension,
-      ForeignMessage.newBuilder().setC(119).build());
-    message.setExtension(optionalImportMessageExtension,
-      ImportMessage.newBuilder().setD(120).build());
-    message.setExtension(optionalPublicImportMessageExtension,
-      PublicImportMessage.newBuilder().setE(126).build());
-    message.setExtension(optionalLazyMessageExtension,
-      TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
-
-    message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
-    message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
-    message.setExtension(optionalImportEnumExtension, ImportEnum.IMPORT_BAZ);
-
-    message.setExtension(optionalStringPieceExtension, "124");
-    message.setExtension(optionalCordExtension, "125");
-
-    // -----------------------------------------------------------------
-
-    message.addExtension(repeatedInt32Extension   , 201);
-    message.addExtension(repeatedInt64Extension   , 202L);
-    message.addExtension(repeatedUint32Extension  , 203);
-    message.addExtension(repeatedUint64Extension  , 204L);
-    message.addExtension(repeatedSint32Extension  , 205);
-    message.addExtension(repeatedSint64Extension  , 206L);
-    message.addExtension(repeatedFixed32Extension , 207);
-    message.addExtension(repeatedFixed64Extension , 208L);
-    message.addExtension(repeatedSfixed32Extension, 209);
-    message.addExtension(repeatedSfixed64Extension, 210L);
-    message.addExtension(repeatedFloatExtension   , 211F);
-    message.addExtension(repeatedDoubleExtension  , 212D);
-    message.addExtension(repeatedBoolExtension    , true);
-    message.addExtension(repeatedStringExtension  , "215");
-    message.addExtension(repeatedBytesExtension   , toBytes("216"));
-
-    message.addExtension(repeatedGroupExtension,
-      RepeatedGroup_extension.newBuilder().setA(217).build());
-    message.addExtension(repeatedNestedMessageExtension,
-      TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
-    message.addExtension(repeatedForeignMessageExtension,
-      ForeignMessage.newBuilder().setC(219).build());
-    message.addExtension(repeatedImportMessageExtension,
-      ImportMessage.newBuilder().setD(220).build());
-    message.addExtension(repeatedLazyMessageExtension,
-      TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
-
-    message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
-    message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
-    message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAR);
-
-    message.addExtension(repeatedStringPieceExtension, "224");
-    message.addExtension(repeatedCordExtension, "225");
-
-    // Add a second one of each field.
-    message.addExtension(repeatedInt32Extension   , 301);
-    message.addExtension(repeatedInt64Extension   , 302L);
-    message.addExtension(repeatedUint32Extension  , 303);
-    message.addExtension(repeatedUint64Extension  , 304L);
-    message.addExtension(repeatedSint32Extension  , 305);
-    message.addExtension(repeatedSint64Extension  , 306L);
-    message.addExtension(repeatedFixed32Extension , 307);
-    message.addExtension(repeatedFixed64Extension , 308L);
-    message.addExtension(repeatedSfixed32Extension, 309);
-    message.addExtension(repeatedSfixed64Extension, 310L);
-    message.addExtension(repeatedFloatExtension   , 311F);
-    message.addExtension(repeatedDoubleExtension  , 312D);
-    message.addExtension(repeatedBoolExtension    , false);
-    message.addExtension(repeatedStringExtension  , "315");
-    message.addExtension(repeatedBytesExtension   , toBytes("316"));
-
-    message.addExtension(repeatedGroupExtension,
-      RepeatedGroup_extension.newBuilder().setA(317).build());
-    message.addExtension(repeatedNestedMessageExtension,
-      TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
-    message.addExtension(repeatedForeignMessageExtension,
-      ForeignMessage.newBuilder().setC(319).build());
-    message.addExtension(repeatedImportMessageExtension,
-      ImportMessage.newBuilder().setD(320).build());
-    message.addExtension(repeatedLazyMessageExtension,
-      TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
-
-    message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
-    message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
-    message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAZ);
-
-    message.addExtension(repeatedStringPieceExtension, "324");
-    message.addExtension(repeatedCordExtension, "325");
-
-    // -----------------------------------------------------------------
-
-    message.setExtension(defaultInt32Extension   , 401);
-    message.setExtension(defaultInt64Extension   , 402L);
-    message.setExtension(defaultUint32Extension  , 403);
-    message.setExtension(defaultUint64Extension  , 404L);
-    message.setExtension(defaultSint32Extension  , 405);
-    message.setExtension(defaultSint64Extension  , 406L);
-    message.setExtension(defaultFixed32Extension , 407);
-    message.setExtension(defaultFixed64Extension , 408L);
-    message.setExtension(defaultSfixed32Extension, 409);
-    message.setExtension(defaultSfixed64Extension, 410L);
-    message.setExtension(defaultFloatExtension   , 411F);
-    message.setExtension(defaultDoubleExtension  , 412D);
-    message.setExtension(defaultBoolExtension    , false);
-    message.setExtension(defaultStringExtension  , "415");
-    message.setExtension(defaultBytesExtension   , toBytes("416"));
-
-    message.setExtension(defaultNestedEnumExtension, TestAllTypes.NestedEnum.FOO);
-    message.setExtension(defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO);
-    message.setExtension(defaultImportEnumExtension, ImportEnum.IMPORT_FOO);
-
-    message.setExtension(defaultStringPieceExtension, "424");
-    message.setExtension(defaultCordExtension, "425");
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Modify the repeated extensions of {@code message} to contain the values
-   * expected by {@code assertRepeatedExtensionsModified()}.
-   */
-  public static void modifyRepeatedExtensions(
-      TestAllExtensions.Builder message) {
-    message.setExtension(repeatedInt32Extension   , 1, 501);
-    message.setExtension(repeatedInt64Extension   , 1, 502L);
-    message.setExtension(repeatedUint32Extension  , 1, 503);
-    message.setExtension(repeatedUint64Extension  , 1, 504L);
-    message.setExtension(repeatedSint32Extension  , 1, 505);
-    message.setExtension(repeatedSint64Extension  , 1, 506L);
-    message.setExtension(repeatedFixed32Extension , 1, 507);
-    message.setExtension(repeatedFixed64Extension , 1, 508L);
-    message.setExtension(repeatedSfixed32Extension, 1, 509);
-    message.setExtension(repeatedSfixed64Extension, 1, 510L);
-    message.setExtension(repeatedFloatExtension   , 1, 511F);
-    message.setExtension(repeatedDoubleExtension  , 1, 512D);
-    message.setExtension(repeatedBoolExtension    , 1, true);
-    message.setExtension(repeatedStringExtension  , 1, "515");
-    message.setExtension(repeatedBytesExtension   , 1, toBytes("516"));
-
-    message.setExtension(repeatedGroupExtension, 1,
-      RepeatedGroup_extension.newBuilder().setA(517).build());
-    message.setExtension(repeatedNestedMessageExtension, 1,
-      TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
-    message.setExtension(repeatedForeignMessageExtension, 1,
-      ForeignMessage.newBuilder().setC(519).build());
-    message.setExtension(repeatedImportMessageExtension, 1,
-      ImportMessage.newBuilder().setD(520).build());
-    message.setExtension(repeatedLazyMessageExtension, 1,
-      TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
-
-    message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
-    message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
-    message.setExtension(repeatedImportEnumExtension , 1, ImportEnum.IMPORT_FOO);
-
-    message.setExtension(repeatedStringPieceExtension, 1, "524");
-    message.setExtension(repeatedCordExtension, 1, "525");
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all extensions of
-   * {@code message} are set to the values assigned by {@code setAllExtensions}.
-   */
-  public static void assertAllExtensionsSet(
-      TestAllExtensionsOrBuilder message) {
-    Assert.assertTrue(message.hasExtension(optionalInt32Extension   ));
-    Assert.assertTrue(message.hasExtension(optionalInt64Extension   ));
-    Assert.assertTrue(message.hasExtension(optionalUint32Extension  ));
-    Assert.assertTrue(message.hasExtension(optionalUint64Extension  ));
-    Assert.assertTrue(message.hasExtension(optionalSint32Extension  ));
-    Assert.assertTrue(message.hasExtension(optionalSint64Extension  ));
-    Assert.assertTrue(message.hasExtension(optionalFixed32Extension ));
-    Assert.assertTrue(message.hasExtension(optionalFixed64Extension ));
-    Assert.assertTrue(message.hasExtension(optionalSfixed32Extension));
-    Assert.assertTrue(message.hasExtension(optionalSfixed64Extension));
-    Assert.assertTrue(message.hasExtension(optionalFloatExtension   ));
-    Assert.assertTrue(message.hasExtension(optionalDoubleExtension  ));
-    Assert.assertTrue(message.hasExtension(optionalBoolExtension    ));
-    Assert.assertTrue(message.hasExtension(optionalStringExtension  ));
-    Assert.assertTrue(message.hasExtension(optionalBytesExtension   ));
-
-    Assert.assertTrue(message.hasExtension(optionalGroupExtension         ));
-    Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension ));
-    Assert.assertTrue(message.hasExtension(optionalForeignMessageExtension));
-    Assert.assertTrue(message.hasExtension(optionalImportMessageExtension ));
-
-    Assert.assertTrue(message.getExtension(optionalGroupExtension         ).hasA());
-    Assert.assertTrue(message.getExtension(optionalNestedMessageExtension ).hasBb());
-    Assert.assertTrue(message.getExtension(optionalForeignMessageExtension).hasC());
-    Assert.assertTrue(message.getExtension(optionalImportMessageExtension ).hasD());
-
-    Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension ));
-    Assert.assertTrue(message.hasExtension(optionalForeignEnumExtension));
-    Assert.assertTrue(message.hasExtension(optionalImportEnumExtension ));
-
-    Assert.assertTrue(message.hasExtension(optionalStringPieceExtension));
-    Assert.assertTrue(message.hasExtension(optionalCordExtension));
-
-    assertEqualsExactType(101  , message.getExtension(optionalInt32Extension   ));
-    assertEqualsExactType(102L , message.getExtension(optionalInt64Extension   ));
-    assertEqualsExactType(103  , message.getExtension(optionalUint32Extension  ));
-    assertEqualsExactType(104L , message.getExtension(optionalUint64Extension  ));
-    assertEqualsExactType(105  , message.getExtension(optionalSint32Extension  ));
-    assertEqualsExactType(106L , message.getExtension(optionalSint64Extension  ));
-    assertEqualsExactType(107  , message.getExtension(optionalFixed32Extension ));
-    assertEqualsExactType(108L , message.getExtension(optionalFixed64Extension ));
-    assertEqualsExactType(109  , message.getExtension(optionalSfixed32Extension));
-    assertEqualsExactType(110L , message.getExtension(optionalSfixed64Extension));
-    assertEqualsExactType(111F , message.getExtension(optionalFloatExtension   ));
-    assertEqualsExactType(112D , message.getExtension(optionalDoubleExtension  ));
-    assertEqualsExactType(true , message.getExtension(optionalBoolExtension    ));
-    assertEqualsExactType("115", message.getExtension(optionalStringExtension  ));
-    assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
-
-    assertEqualsExactType(117, message.getExtension(optionalGroupExtension              ).getA());
-    assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension      ).getBb());
-    assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension     ).getC());
-    assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension      ).getD());
-    assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE());
-    assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension        ).getBb());
-
-    assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
-      message.getExtension(optionalNestedEnumExtension));
-    assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
-      message.getExtension(optionalForeignEnumExtension));
-    assertEqualsExactType(ImportEnum.IMPORT_BAZ,
-      message.getExtension(optionalImportEnumExtension));
-
-    assertEqualsExactType("124", message.getExtension(optionalStringPieceExtension));
-    assertEqualsExactType("125", message.getExtension(optionalCordExtension));
-
-    // -----------------------------------------------------------------
-
-    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension    ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension   ));
-
-    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension         ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension    ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension    ));
-
-    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
-
-    assertEqualsExactType(201  , message.getExtension(repeatedInt32Extension   , 0));
-    assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension   , 0));
-    assertEqualsExactType(203  , message.getExtension(repeatedUint32Extension  , 0));
-    assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension  , 0));
-    assertEqualsExactType(205  , message.getExtension(repeatedSint32Extension  , 0));
-    assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension  , 0));
-    assertEqualsExactType(207  , message.getExtension(repeatedFixed32Extension , 0));
-    assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
-    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32Extension, 0));
-    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
-    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension   , 0));
-    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension  , 0));
-    assertEqualsExactType(true , message.getExtension(repeatedBoolExtension    , 0));
-    assertEqualsExactType("215", message.getExtension(repeatedStringExtension  , 0));
-    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
-
-    assertEqualsExactType(217, message.getExtension(repeatedGroupExtension         , 0).getA());
-    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
-    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
-    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
-    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension   , 0).getBb());
-
-    assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
-      message.getExtension(repeatedNestedEnumExtension, 0));
-    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
-      message.getExtension(repeatedForeignEnumExtension, 0));
-    assertEqualsExactType(ImportEnum.IMPORT_BAR,
-      message.getExtension(repeatedImportEnumExtension, 0));
-
-    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
-    assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
-
-    assertEqualsExactType(301  , message.getExtension(repeatedInt32Extension   , 1));
-    assertEqualsExactType(302L , message.getExtension(repeatedInt64Extension   , 1));
-    assertEqualsExactType(303  , message.getExtension(repeatedUint32Extension  , 1));
-    assertEqualsExactType(304L , message.getExtension(repeatedUint64Extension  , 1));
-    assertEqualsExactType(305  , message.getExtension(repeatedSint32Extension  , 1));
-    assertEqualsExactType(306L , message.getExtension(repeatedSint64Extension  , 1));
-    assertEqualsExactType(307  , message.getExtension(repeatedFixed32Extension , 1));
-    assertEqualsExactType(308L , message.getExtension(repeatedFixed64Extension , 1));
-    assertEqualsExactType(309  , message.getExtension(repeatedSfixed32Extension, 1));
-    assertEqualsExactType(310L , message.getExtension(repeatedSfixed64Extension, 1));
-    assertEqualsExactType(311F , message.getExtension(repeatedFloatExtension   , 1));
-    assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtension  , 1));
-    assertEqualsExactType(false, message.getExtension(repeatedBoolExtension    , 1));
-    assertEqualsExactType("315", message.getExtension(repeatedStringExtension  , 1));
-    assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtension, 1));
-
-    assertEqualsExactType(317, message.getExtension(repeatedGroupExtension         , 1).getA());
-    assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
-    assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
-    assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
-    assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension   , 1).getBb());
-
-    assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
-      message.getExtension(repeatedNestedEnumExtension, 1));
-    assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
-      message.getExtension(repeatedForeignEnumExtension, 1));
-    assertEqualsExactType(ImportEnum.IMPORT_BAZ,
-      message.getExtension(repeatedImportEnumExtension, 1));
-
-    assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtension, 1));
-    assertEqualsExactType("325", message.getExtension(repeatedCordExtension, 1));
-
-    // -----------------------------------------------------------------
-
-    Assert.assertTrue(message.hasExtension(defaultInt32Extension   ));
-    Assert.assertTrue(message.hasExtension(defaultInt64Extension   ));
-    Assert.assertTrue(message.hasExtension(defaultUint32Extension  ));
-    Assert.assertTrue(message.hasExtension(defaultUint64Extension  ));
-    Assert.assertTrue(message.hasExtension(defaultSint32Extension  ));
-    Assert.assertTrue(message.hasExtension(defaultSint64Extension  ));
-    Assert.assertTrue(message.hasExtension(defaultFixed32Extension ));
-    Assert.assertTrue(message.hasExtension(defaultFixed64Extension ));
-    Assert.assertTrue(message.hasExtension(defaultSfixed32Extension));
-    Assert.assertTrue(message.hasExtension(defaultSfixed64Extension));
-    Assert.assertTrue(message.hasExtension(defaultFloatExtension   ));
-    Assert.assertTrue(message.hasExtension(defaultDoubleExtension  ));
-    Assert.assertTrue(message.hasExtension(defaultBoolExtension    ));
-    Assert.assertTrue(message.hasExtension(defaultStringExtension  ));
-    Assert.assertTrue(message.hasExtension(defaultBytesExtension   ));
-
-    Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension ));
-    Assert.assertTrue(message.hasExtension(defaultForeignEnumExtension));
-    Assert.assertTrue(message.hasExtension(defaultImportEnumExtension ));
-
-    Assert.assertTrue(message.hasExtension(defaultStringPieceExtension));
-    Assert.assertTrue(message.hasExtension(defaultCordExtension));
-
-    assertEqualsExactType(401  , message.getExtension(defaultInt32Extension   ));
-    assertEqualsExactType(402L , message.getExtension(defaultInt64Extension   ));
-    assertEqualsExactType(403  , message.getExtension(defaultUint32Extension  ));
-    assertEqualsExactType(404L , message.getExtension(defaultUint64Extension  ));
-    assertEqualsExactType(405  , message.getExtension(defaultSint32Extension  ));
-    assertEqualsExactType(406L , message.getExtension(defaultSint64Extension  ));
-    assertEqualsExactType(407  , message.getExtension(defaultFixed32Extension ));
-    assertEqualsExactType(408L , message.getExtension(defaultFixed64Extension ));
-    assertEqualsExactType(409  , message.getExtension(defaultSfixed32Extension));
-    assertEqualsExactType(410L , message.getExtension(defaultSfixed64Extension));
-    assertEqualsExactType(411F , message.getExtension(defaultFloatExtension   ));
-    assertEqualsExactType(412D , message.getExtension(defaultDoubleExtension  ));
-    assertEqualsExactType(false, message.getExtension(defaultBoolExtension    ));
-    assertEqualsExactType("415", message.getExtension(defaultStringExtension  ));
-    assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtension));
-
-    assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
-      message.getExtension(defaultNestedEnumExtension ));
-    assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
-      message.getExtension(defaultForeignEnumExtension));
-    assertEqualsExactType(ImportEnum.IMPORT_FOO,
-      message.getExtension(defaultImportEnumExtension));
-
-    assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension));
-    assertEqualsExactType("425", message.getExtension(defaultCordExtension));
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all extensions of
-   * {@code message} are cleared, and that getting the extensions returns their
-   * default values.
-   */
-  public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) {
-    // hasBlah() should initially be false for all optional fields.
-    Assert.assertFalse(message.hasExtension(optionalInt32Extension   ));
-    Assert.assertFalse(message.hasExtension(optionalInt64Extension   ));
-    Assert.assertFalse(message.hasExtension(optionalUint32Extension  ));
-    Assert.assertFalse(message.hasExtension(optionalUint64Extension  ));
-    Assert.assertFalse(message.hasExtension(optionalSint32Extension  ));
-    Assert.assertFalse(message.hasExtension(optionalSint64Extension  ));
-    Assert.assertFalse(message.hasExtension(optionalFixed32Extension ));
-    Assert.assertFalse(message.hasExtension(optionalFixed64Extension ));
-    Assert.assertFalse(message.hasExtension(optionalSfixed32Extension));
-    Assert.assertFalse(message.hasExtension(optionalSfixed64Extension));
-    Assert.assertFalse(message.hasExtension(optionalFloatExtension   ));
-    Assert.assertFalse(message.hasExtension(optionalDoubleExtension  ));
-    Assert.assertFalse(message.hasExtension(optionalBoolExtension    ));
-    Assert.assertFalse(message.hasExtension(optionalStringExtension  ));
-    Assert.assertFalse(message.hasExtension(optionalBytesExtension   ));
-
-    Assert.assertFalse(message.hasExtension(optionalGroupExtension         ));
-    Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension ));
-    Assert.assertFalse(message.hasExtension(optionalForeignMessageExtension));
-    Assert.assertFalse(message.hasExtension(optionalImportMessageExtension ));
-
-    Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension ));
-    Assert.assertFalse(message.hasExtension(optionalForeignEnumExtension));
-    Assert.assertFalse(message.hasExtension(optionalImportEnumExtension ));
-
-    Assert.assertFalse(message.hasExtension(optionalStringPieceExtension));
-    Assert.assertFalse(message.hasExtension(optionalCordExtension));
-
-    // Optional fields without defaults are set to zero or something like it.
-    assertEqualsExactType(0    , message.getExtension(optionalInt32Extension   ));
-    assertEqualsExactType(0L   , message.getExtension(optionalInt64Extension   ));
-    assertEqualsExactType(0    , message.getExtension(optionalUint32Extension  ));
-    assertEqualsExactType(0L   , message.getExtension(optionalUint64Extension  ));
-    assertEqualsExactType(0    , message.getExtension(optionalSint32Extension  ));
-    assertEqualsExactType(0L   , message.getExtension(optionalSint64Extension  ));
-    assertEqualsExactType(0    , message.getExtension(optionalFixed32Extension ));
-    assertEqualsExactType(0L   , message.getExtension(optionalFixed64Extension ));
-    assertEqualsExactType(0    , message.getExtension(optionalSfixed32Extension));
-    assertEqualsExactType(0L   , message.getExtension(optionalSfixed64Extension));
-    assertEqualsExactType(0F   , message.getExtension(optionalFloatExtension   ));
-    assertEqualsExactType(0D   , message.getExtension(optionalDoubleExtension  ));
-    assertEqualsExactType(false, message.getExtension(optionalBoolExtension    ));
-    assertEqualsExactType(""   , message.getExtension(optionalStringExtension  ));
-    assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtension));
-
-    // Embedded messages should also be clear.
-    Assert.assertFalse(message.getExtension(optionalGroupExtension         ).hasA());
-    Assert.assertFalse(message.getExtension(optionalNestedMessageExtension ).hasBb());
-    Assert.assertFalse(message.getExtension(optionalForeignMessageExtension).hasC());
-    Assert.assertFalse(message.getExtension(optionalImportMessageExtension ).hasD());
-
-    assertEqualsExactType(0, message.getExtension(optionalGroupExtension         ).getA());
-    assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension ).getBb());
-    assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtension).getC());
-    assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension ).getD());
-
-    // Enums without defaults are set to the first value in the enum.
-    assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
-      message.getExtension(optionalNestedEnumExtension ));
-    assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
-      message.getExtension(optionalForeignEnumExtension));
-    assertEqualsExactType(ImportEnum.IMPORT_FOO,
-      message.getExtension(optionalImportEnumExtension));
-
-    assertEqualsExactType("", message.getExtension(optionalStringPieceExtension));
-    assertEqualsExactType("", message.getExtension(optionalCordExtension));
-
-    // Repeated fields are empty.
-    Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension   ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension   ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension  ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension  ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension  ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension  ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32Extension));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64Extension));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension   ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension  ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension    ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension  ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension   ));
-
-    Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension         ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension   ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension    ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension   ));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension    ));
-
-    Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtension));
-    Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtension));
-
-    // Repeated fields are empty via getExtension().size().
-    Assert.assertEquals(0, message.getExtension(repeatedInt32Extension   ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedInt64Extension   ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedUint32Extension  ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedUint64Extension  ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedSint32Extension  ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedSint64Extension  ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedFixed32Extension ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedFixed64Extension ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedSfixed32Extension).size());
-    Assert.assertEquals(0, message.getExtension(repeatedSfixed64Extension).size());
-    Assert.assertEquals(0, message.getExtension(repeatedFloatExtension   ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedDoubleExtension  ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedBoolExtension    ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedStringExtension  ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedBytesExtension   ).size());
-
-    Assert.assertEquals(0, message.getExtension(repeatedGroupExtension         ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size());
-    Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension   ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension    ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension   ).size());
-    Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension    ).size());
-
-    Assert.assertEquals(0, message.getExtension(repeatedStringPieceExtension).size());
-    Assert.assertEquals(0, message.getExtension(repeatedCordExtension).size());
-
-    // hasBlah() should also be false for all default fields.
-    Assert.assertFalse(message.hasExtension(defaultInt32Extension   ));
-    Assert.assertFalse(message.hasExtension(defaultInt64Extension   ));
-    Assert.assertFalse(message.hasExtension(defaultUint32Extension  ));
-    Assert.assertFalse(message.hasExtension(defaultUint64Extension  ));
-    Assert.assertFalse(message.hasExtension(defaultSint32Extension  ));
-    Assert.assertFalse(message.hasExtension(defaultSint64Extension  ));
-    Assert.assertFalse(message.hasExtension(defaultFixed32Extension ));
-    Assert.assertFalse(message.hasExtension(defaultFixed64Extension ));
-    Assert.assertFalse(message.hasExtension(defaultSfixed32Extension));
-    Assert.assertFalse(message.hasExtension(defaultSfixed64Extension));
-    Assert.assertFalse(message.hasExtension(defaultFloatExtension   ));
-    Assert.assertFalse(message.hasExtension(defaultDoubleExtension  ));
-    Assert.assertFalse(message.hasExtension(defaultBoolExtension    ));
-    Assert.assertFalse(message.hasExtension(defaultStringExtension  ));
-    Assert.assertFalse(message.hasExtension(defaultBytesExtension   ));
-
-    Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension ));
-    Assert.assertFalse(message.hasExtension(defaultForeignEnumExtension));
-    Assert.assertFalse(message.hasExtension(defaultImportEnumExtension ));
-
-    Assert.assertFalse(message.hasExtension(defaultStringPieceExtension));
-    Assert.assertFalse(message.hasExtension(defaultCordExtension));
-
-    // Fields with defaults have their default values (duh).
-    assertEqualsExactType( 41    , message.getExtension(defaultInt32Extension   ));
-    assertEqualsExactType( 42L   , message.getExtension(defaultInt64Extension   ));
-    assertEqualsExactType( 43    , message.getExtension(defaultUint32Extension  ));
-    assertEqualsExactType( 44L   , message.getExtension(defaultUint64Extension  ));
-    assertEqualsExactType(-45    , message.getExtension(defaultSint32Extension  ));
-    assertEqualsExactType( 46L   , message.getExtension(defaultSint64Extension  ));
-    assertEqualsExactType( 47    , message.getExtension(defaultFixed32Extension ));
-    assertEqualsExactType( 48L   , message.getExtension(defaultFixed64Extension ));
-    assertEqualsExactType( 49    , message.getExtension(defaultSfixed32Extension));
-    assertEqualsExactType(-50L   , message.getExtension(defaultSfixed64Extension));
-    assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtension   ));
-    assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtension  ));
-    assertEqualsExactType(true   , message.getExtension(defaultBoolExtension    ));
-    assertEqualsExactType("hello", message.getExtension(defaultStringExtension  ));
-    assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtension));
-
-    assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
-      message.getExtension(defaultNestedEnumExtension ));
-    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
-      message.getExtension(defaultForeignEnumExtension));
-    assertEqualsExactType(ImportEnum.IMPORT_BAR,
-      message.getExtension(defaultImportEnumExtension));
-
-    assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension));
-    assertEqualsExactType("123", message.getExtension(defaultCordExtension));
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Assert (using {@code junit.framework.Assert}} that all extensions of
-   * {@code message} are set to the values assigned by {@code setAllExtensions}
-   * followed by {@code modifyRepeatedExtensions}.
-   */
-  public static void assertRepeatedExtensionsModified(
-      TestAllExtensionsOrBuilder message) {
-    // ModifyRepeatedFields only sets the second repeated element of each
-    // field.  In addition to verifying this, we also verify that the first
-    // element and size were *not* modified.
-    Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension    ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension  ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension   ));
-
-    Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension         ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension    ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension   ));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension    ));
-
-    Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
-    Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
-
-    assertEqualsExactType(201  , message.getExtension(repeatedInt32Extension   , 0));
-    assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension   , 0));
-    assertEqualsExactType(203  , message.getExtension(repeatedUint32Extension  , 0));
-    assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension  , 0));
-    assertEqualsExactType(205  , message.getExtension(repeatedSint32Extension  , 0));
-    assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension  , 0));
-    assertEqualsExactType(207  , message.getExtension(repeatedFixed32Extension , 0));
-    assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
-    assertEqualsExactType(209  , message.getExtension(repeatedSfixed32Extension, 0));
-    assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
-    assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension   , 0));
-    assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension  , 0));
-    assertEqualsExactType(true , message.getExtension(repeatedBoolExtension    , 0));
-    assertEqualsExactType("215", message.getExtension(repeatedStringExtension  , 0));
-    assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
-
-    assertEqualsExactType(217, message.getExtension(repeatedGroupExtension         , 0).getA());
-    assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
-    assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
-    assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
-    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension   , 0).getBb());
-
-    assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
-      message.getExtension(repeatedNestedEnumExtension, 0));
-    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
-      message.getExtension(repeatedForeignEnumExtension, 0));
-    assertEqualsExactType(ImportEnum.IMPORT_BAR,
-      message.getExtension(repeatedImportEnumExtension, 0));
-
-    assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
-    assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
-
-    // Actually verify the second (modified) elements now.
-    assertEqualsExactType(501  , message.getExtension(repeatedInt32Extension   , 1));
-    assertEqualsExactType(502L , message.getExtension(repeatedInt64Extension   , 1));
-    assertEqualsExactType(503  , message.getExtension(repeatedUint32Extension  , 1));
-    assertEqualsExactType(504L , message.getExtension(repeatedUint64Extension  , 1));
-    assertEqualsExactType(505  , message.getExtension(repeatedSint32Extension  , 1));
-    assertEqualsExactType(506L , message.getExtension(repeatedSint64Extension  , 1));
-    assertEqualsExactType(507  , message.getExtension(repeatedFixed32Extension , 1));
-    assertEqualsExactType(508L , message.getExtension(repeatedFixed64Extension , 1));
-    assertEqualsExactType(509  , message.getExtension(repeatedSfixed32Extension, 1));
-    assertEqualsExactType(510L , message.getExtension(repeatedSfixed64Extension, 1));
-    assertEqualsExactType(511F , message.getExtension(repeatedFloatExtension   , 1));
-    assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtension  , 1));
-    assertEqualsExactType(true , message.getExtension(repeatedBoolExtension    , 1));
-    assertEqualsExactType("515", message.getExtension(repeatedStringExtension  , 1));
-    assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtension, 1));
-
-    assertEqualsExactType(517, message.getExtension(repeatedGroupExtension         , 1).getA());
-    assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
-    assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
-    assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
-    assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension   , 1).getBb());
-
-    assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
-      message.getExtension(repeatedNestedEnumExtension, 1));
-    assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
-      message.getExtension(repeatedForeignEnumExtension, 1));
-    assertEqualsExactType(ImportEnum.IMPORT_FOO,
-      message.getExtension(repeatedImportEnumExtension, 1));
-
-    assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtension, 1));
-    assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
-  }
-
-  public static void setPackedExtensions(TestPackedExtensions.Builder message) {
-    message.addExtension(packedInt32Extension   , 601);
-    message.addExtension(packedInt64Extension   , 602L);
-    message.addExtension(packedUint32Extension  , 603);
-    message.addExtension(packedUint64Extension  , 604L);
-    message.addExtension(packedSint32Extension  , 605);
-    message.addExtension(packedSint64Extension  , 606L);
-    message.addExtension(packedFixed32Extension , 607);
-    message.addExtension(packedFixed64Extension , 608L);
-    message.addExtension(packedSfixed32Extension, 609);
-    message.addExtension(packedSfixed64Extension, 610L);
-    message.addExtension(packedFloatExtension   , 611F);
-    message.addExtension(packedDoubleExtension  , 612D);
-    message.addExtension(packedBoolExtension    , true);
-    message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAR);
-    // Add a second one of each field.
-    message.addExtension(packedInt32Extension   , 701);
-    message.addExtension(packedInt64Extension   , 702L);
-    message.addExtension(packedUint32Extension  , 703);
-    message.addExtension(packedUint64Extension  , 704L);
-    message.addExtension(packedSint32Extension  , 705);
-    message.addExtension(packedSint64Extension  , 706L);
-    message.addExtension(packedFixed32Extension , 707);
-    message.addExtension(packedFixed64Extension , 708L);
-    message.addExtension(packedSfixed32Extension, 709);
-    message.addExtension(packedSfixed64Extension, 710L);
-    message.addExtension(packedFloatExtension   , 711F);
-    message.addExtension(packedDoubleExtension  , 712D);
-    message.addExtension(packedBoolExtension    , false);
-    message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAZ);
-  }
-
-  public static void assertPackedExtensionsSet(TestPackedExtensions message) {
-    Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension   ));
-    Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension   ));
-    Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension  ));
-    Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension ));
-    Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension ));
-    Assert.assertEquals(2, message.getExtensionCount(packedSfixed32Extension));
-    Assert.assertEquals(2, message.getExtensionCount(packedSfixed64Extension));
-    Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension   ));
-    Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension  ));
-    Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension    ));
-    Assert.assertEquals(2, message.getExtensionCount(packedEnumExtension));
-    assertEqualsExactType(601  , message.getExtension(packedInt32Extension   , 0));
-    assertEqualsExactType(602L , message.getExtension(packedInt64Extension   , 0));
-    assertEqualsExactType(603  , message.getExtension(packedUint32Extension  , 0));
-    assertEqualsExactType(604L , message.getExtension(packedUint64Extension  , 0));
-    assertEqualsExactType(605  , message.getExtension(packedSint32Extension  , 0));
-    assertEqualsExactType(606L , message.getExtension(packedSint64Extension  , 0));
-    assertEqualsExactType(607  , message.getExtension(packedFixed32Extension , 0));
-    assertEqualsExactType(608L , message.getExtension(packedFixed64Extension , 0));
-    assertEqualsExactType(609  , message.getExtension(packedSfixed32Extension, 0));
-    assertEqualsExactType(610L , message.getExtension(packedSfixed64Extension, 0));
-    assertEqualsExactType(611F , message.getExtension(packedFloatExtension   , 0));
-    assertEqualsExactType(612D , message.getExtension(packedDoubleExtension  , 0));
-    assertEqualsExactType(true , message.getExtension(packedBoolExtension    , 0));
-    assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
-                          message.getExtension(packedEnumExtension, 0));
-    assertEqualsExactType(701  , message.getExtension(packedInt32Extension   , 1));
-    assertEqualsExactType(702L , message.getExtension(packedInt64Extension   , 1));
-    assertEqualsExactType(703  , message.getExtension(packedUint32Extension  , 1));
-    assertEqualsExactType(704L , message.getExtension(packedUint64Extension  , 1));
-    assertEqualsExactType(705  , message.getExtension(packedSint32Extension  , 1));
-    assertEqualsExactType(706L , message.getExtension(packedSint64Extension  , 1));
-    assertEqualsExactType(707  , message.getExtension(packedFixed32Extension , 1));
-    assertEqualsExactType(708L , message.getExtension(packedFixed64Extension , 1));
-    assertEqualsExactType(709  , message.getExtension(packedSfixed32Extension, 1));
-    assertEqualsExactType(710L , message.getExtension(packedSfixed64Extension, 1));
-    assertEqualsExactType(711F , message.getExtension(packedFloatExtension   , 1));
-    assertEqualsExactType(712D , message.getExtension(packedDoubleExtension  , 1));
-    assertEqualsExactType(false, message.getExtension(packedBoolExtension    , 1));
-    assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
-                          message.getExtension(packedEnumExtension, 1));
-  }
-
-  // =================================================================
-
-  /**
-   * Performs the same things that the methods of {@code TestUtil} do, but
-   * via the reflection interface.  This is its own class because it needs
-   * to know what descriptor to use.
-   */
-  public static class ReflectionTester {
-    private final Descriptors.Descriptor baseDescriptor;
-    private final ExtensionRegistry extensionRegistry;
-
-    private final Descriptors.FileDescriptor file;
-    private final Descriptors.FileDescriptor importFile;
-    private final Descriptors.FileDescriptor publicImportFile;
-
-    private final Descriptors.Descriptor optionalGroup;
-    private final Descriptors.Descriptor repeatedGroup;
-    private final Descriptors.Descriptor nestedMessage;
-    private final Descriptors.Descriptor foreignMessage;
-    private final Descriptors.Descriptor importMessage;
-    private final Descriptors.Descriptor publicImportMessage;
-
-    private final Descriptors.FieldDescriptor groupA;
-    private final Descriptors.FieldDescriptor repeatedGroupA;
-    private final Descriptors.FieldDescriptor nestedB;
-    private final Descriptors.FieldDescriptor foreignC;
-    private final Descriptors.FieldDescriptor importD;
-    private final Descriptors.FieldDescriptor importE;
-
-    private final Descriptors.EnumDescriptor nestedEnum;
-    private final Descriptors.EnumDescriptor foreignEnum;
-    private final Descriptors.EnumDescriptor importEnum;
-
-    private final Descriptors.EnumValueDescriptor nestedFoo;
-    private final Descriptors.EnumValueDescriptor nestedBar;
-    private final Descriptors.EnumValueDescriptor nestedBaz;
-    private final Descriptors.EnumValueDescriptor foreignFoo;
-    private final Descriptors.EnumValueDescriptor foreignBar;
-    private final Descriptors.EnumValueDescriptor foreignBaz;
-    private final Descriptors.EnumValueDescriptor importFoo;
-    private final Descriptors.EnumValueDescriptor importBar;
-    private final Descriptors.EnumValueDescriptor importBaz;
-
-    /**
-     * Construct a {@code ReflectionTester} that will expect messages using
-     * the given descriptor.
-     *
-     * Normally {@code baseDescriptor} should be a descriptor for the type
-     * {@code TestAllTypes}, defined in
-     * {@code google/protobuf/unittest.proto}.  However, if
-     * {@code extensionRegistry} is non-null, then {@code baseDescriptor} should
-     * be for {@code TestAllExtensions} instead, and instead of reading and
-     * writing normal fields, the tester will read and write extensions.
-     * All of {@code TestAllExtensions}' extensions must be registered in the
-     * registry.
-     */
-    public ReflectionTester(Descriptors.Descriptor baseDescriptor,
-                            ExtensionRegistry extensionRegistry) {
-      this.baseDescriptor = baseDescriptor;
-      this.extensionRegistry = extensionRegistry;
-
-      this.file = baseDescriptor.getFile();
-      Assert.assertEquals(1, file.getDependencies().size());
-      this.importFile = file.getDependencies().get(0);
-      this.publicImportFile = importFile.getDependencies().get(0);
-
-      Descriptors.Descriptor testAllTypes;
-      if (baseDescriptor.getName() == "TestAllTypes") {
-        testAllTypes = baseDescriptor;
-      } else {
-        testAllTypes = file.findMessageTypeByName("TestAllTypes");
-        Assert.assertNotNull(testAllTypes);
-      }
-
-      if (extensionRegistry == null) {
-        // Use testAllTypes, rather than baseDescriptor, to allow
-        // initialization using TestPackedTypes descriptors. These objects
-        // won't be used by the methods for packed fields.
-        this.optionalGroup =
-          testAllTypes.findNestedTypeByName("OptionalGroup");
-        this.repeatedGroup =
-          testAllTypes.findNestedTypeByName("RepeatedGroup");
-      } else {
-        this.optionalGroup =
-          file.findMessageTypeByName("OptionalGroup_extension");
-        this.repeatedGroup =
-          file.findMessageTypeByName("RepeatedGroup_extension");
-      }
-      this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage");
-      this.foreignMessage = file.findMessageTypeByName("ForeignMessage");
-      this.importMessage = importFile.findMessageTypeByName("ImportMessage");
-      this.publicImportMessage = publicImportFile.findMessageTypeByName(
-          "PublicImportMessage");
-
-      this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum");
-      this.foreignEnum = file.findEnumTypeByName("ForeignEnum");
-      this.importEnum = importFile.findEnumTypeByName("ImportEnum");
-
-      Assert.assertNotNull(optionalGroup );
-      Assert.assertNotNull(repeatedGroup );
-      Assert.assertNotNull(nestedMessage );
-      Assert.assertNotNull(foreignMessage);
-      Assert.assertNotNull(importMessage );
-      Assert.assertNotNull(nestedEnum    );
-      Assert.assertNotNull(foreignEnum   );
-      Assert.assertNotNull(importEnum    );
-
-      this.nestedB  = nestedMessage .findFieldByName("bb");
-      this.foreignC = foreignMessage.findFieldByName("c");
-      this.importD  = importMessage .findFieldByName("d");
-      this.importE  = publicImportMessage.findFieldByName("e");
-      this.nestedFoo = nestedEnum.findValueByName("FOO");
-      this.nestedBar = nestedEnum.findValueByName("BAR");
-      this.nestedBaz = nestedEnum.findValueByName("BAZ");
-      this.foreignFoo = foreignEnum.findValueByName("FOREIGN_FOO");
-      this.foreignBar = foreignEnum.findValueByName("FOREIGN_BAR");
-      this.foreignBaz = foreignEnum.findValueByName("FOREIGN_BAZ");
-      this.importFoo = importEnum.findValueByName("IMPORT_FOO");
-      this.importBar = importEnum.findValueByName("IMPORT_BAR");
-      this.importBaz = importEnum.findValueByName("IMPORT_BAZ");
-
-      this.groupA = optionalGroup.findFieldByName("a");
-      this.repeatedGroupA = repeatedGroup.findFieldByName("a");
-
-      Assert.assertNotNull(groupA        );
-      Assert.assertNotNull(repeatedGroupA);
-      Assert.assertNotNull(nestedB       );
-      Assert.assertNotNull(foreignC      );
-      Assert.assertNotNull(importD       );
-      Assert.assertNotNull(importE       );
-      Assert.assertNotNull(nestedFoo     );
-      Assert.assertNotNull(nestedBar     );
-      Assert.assertNotNull(nestedBaz     );
-      Assert.assertNotNull(foreignFoo    );
-      Assert.assertNotNull(foreignBar    );
-      Assert.assertNotNull(foreignBaz    );
-      Assert.assertNotNull(importFoo     );
-      Assert.assertNotNull(importBar     );
-      Assert.assertNotNull(importBaz     );
-    }
-
-    /**
-     * Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
-     */
-    private Descriptors.FieldDescriptor f(String name) {
-      Descriptors.FieldDescriptor result;
-      if (extensionRegistry == null) {
-        result = baseDescriptor.findFieldByName(name);
-      } else {
-        result = file.findExtensionByName(name + "_extension");
-      }
-      Assert.assertNotNull(result);
-      return result;
-    }
-
-    /**
-     * Calls {@code parent.newBuilderForField()} or uses the
-     * {@code ExtensionRegistry} to find an appropriate builder, depending
-     * on what type is being tested.
-     */
-    private Message.Builder newBuilderForField(
-        Message.Builder parent, Descriptors.FieldDescriptor field) {
-      if (extensionRegistry == null) {
-        return parent.newBuilderForField(field);
-      } else {
-        ExtensionRegistry.ExtensionInfo extension =
-          extensionRegistry.findExtensionByNumber(field.getContainingType(),
-                                                  field.getNumber());
-        Assert.assertNotNull(extension);
-        Assert.assertNotNull(extension.defaultInstance);
-        return extension.defaultInstance.newBuilderForType();
-      }
-    }
-
-    // -------------------------------------------------------------------
-
-    /**
-     * Set every field of {@code message} to the values expected by
-     * {@code assertAllFieldsSet()}, using the {@link Message.Builder}
-     * reflection interface.
-     */
-    void setAllFieldsViaReflection(Message.Builder message) {
-      message.setField(f("optional_int32"   ), 101 );
-      message.setField(f("optional_int64"   ), 102L);
-      message.setField(f("optional_uint32"  ), 103 );
-      message.setField(f("optional_uint64"  ), 104L);
-      message.setField(f("optional_sint32"  ), 105 );
-      message.setField(f("optional_sint64"  ), 106L);
-      message.setField(f("optional_fixed32" ), 107 );
-      message.setField(f("optional_fixed64" ), 108L);
-      message.setField(f("optional_sfixed32"), 109 );
-      message.setField(f("optional_sfixed64"), 110L);
-      message.setField(f("optional_float"   ), 111F);
-      message.setField(f("optional_double"  ), 112D);
-      message.setField(f("optional_bool"    ), true);
-      message.setField(f("optional_string"  ), "115");
-      message.setField(f("optional_bytes"   ), toBytes("116"));
-
-      message.setField(f("optionalgroup"),
-        newBuilderForField(message, f("optionalgroup"))
-               .setField(groupA, 117).build());
-      message.setField(f("optional_nested_message"),
-        newBuilderForField(message, f("optional_nested_message"))
-               .setField(nestedB, 118).build());
-      message.setField(f("optional_foreign_message"),
-        newBuilderForField(message, f("optional_foreign_message"))
-               .setField(foreignC, 119).build());
-      message.setField(f("optional_import_message"),
-        newBuilderForField(message, f("optional_import_message"))
-               .setField(importD, 120).build());
-      message.setField(f("optional_public_import_message"),
-        newBuilderForField(message, f("optional_public_import_message"))
-               .setField(importE, 126).build());
-      message.setField(f("optional_lazy_message"),
-        newBuilderForField(message, f("optional_lazy_message"))
-               .setField(nestedB, 127).build());
-
-      message.setField(f("optional_nested_enum" ),  nestedBaz);
-      message.setField(f("optional_foreign_enum"), foreignBaz);
-      message.setField(f("optional_import_enum" ),  importBaz);
-
-      message.setField(f("optional_string_piece" ), "124");
-      message.setField(f("optional_cord" ), "125");
-
-      // -----------------------------------------------------------------
-
-      message.addRepeatedField(f("repeated_int32"   ), 201 );
-      message.addRepeatedField(f("repeated_int64"   ), 202L);
-      message.addRepeatedField(f("repeated_uint32"  ), 203 );
-      message.addRepeatedField(f("repeated_uint64"  ), 204L);
-      message.addRepeatedField(f("repeated_sint32"  ), 205 );
-      message.addRepeatedField(f("repeated_sint64"  ), 206L);
-      message.addRepeatedField(f("repeated_fixed32" ), 207 );
-      message.addRepeatedField(f("repeated_fixed64" ), 208L);
-      message.addRepeatedField(f("repeated_sfixed32"), 209 );
-      message.addRepeatedField(f("repeated_sfixed64"), 210L);
-      message.addRepeatedField(f("repeated_float"   ), 211F);
-      message.addRepeatedField(f("repeated_double"  ), 212D);
-      message.addRepeatedField(f("repeated_bool"    ), true);
-      message.addRepeatedField(f("repeated_string"  ), "215");
-      message.addRepeatedField(f("repeated_bytes"   ), toBytes("216"));
-
-      message.addRepeatedField(f("repeatedgroup"),
-        newBuilderForField(message, f("repeatedgroup"))
-               .setField(repeatedGroupA, 217).build());
-      message.addRepeatedField(f("repeated_nested_message"),
-        newBuilderForField(message, f("repeated_nested_message"))
-               .setField(nestedB, 218).build());
-      message.addRepeatedField(f("repeated_foreign_message"),
-        newBuilderForField(message, f("repeated_foreign_message"))
-               .setField(foreignC, 219).build());
-      message.addRepeatedField(f("repeated_import_message"),
-        newBuilderForField(message, f("repeated_import_message"))
-               .setField(importD, 220).build());
-      message.addRepeatedField(f("repeated_lazy_message"),
-        newBuilderForField(message, f("repeated_lazy_message"))
-               .setField(nestedB, 227).build());
-
-      message.addRepeatedField(f("repeated_nested_enum" ),  nestedBar);
-      message.addRepeatedField(f("repeated_foreign_enum"), foreignBar);
-      message.addRepeatedField(f("repeated_import_enum" ),  importBar);
-
-      message.addRepeatedField(f("repeated_string_piece" ), "224");
-      message.addRepeatedField(f("repeated_cord" ), "225");
-
-      // Add a second one of each field.
-      message.addRepeatedField(f("repeated_int32"   ), 301 );
-      message.addRepeatedField(f("repeated_int64"   ), 302L);
-      message.addRepeatedField(f("repeated_uint32"  ), 303 );
-      message.addRepeatedField(f("repeated_uint64"  ), 304L);
-      message.addRepeatedField(f("repeated_sint32"  ), 305 );
-      message.addRepeatedField(f("repeated_sint64"  ), 306L);
-      message.addRepeatedField(f("repeated_fixed32" ), 307 );
-      message.addRepeatedField(f("repeated_fixed64" ), 308L);
-      message.addRepeatedField(f("repeated_sfixed32"), 309 );
-      message.addRepeatedField(f("repeated_sfixed64"), 310L);
-      message.addRepeatedField(f("repeated_float"   ), 311F);
-      message.addRepeatedField(f("repeated_double"  ), 312D);
-      message.addRepeatedField(f("repeated_bool"    ), false);
-      message.addRepeatedField(f("repeated_string"  ), "315");
-      message.addRepeatedField(f("repeated_bytes"   ), toBytes("316"));
-
-      message.addRepeatedField(f("repeatedgroup"),
-        newBuilderForField(message, f("repeatedgroup"))
-               .setField(repeatedGroupA, 317).build());
-      message.addRepeatedField(f("repeated_nested_message"),
-        newBuilderForField(message, f("repeated_nested_message"))
-               .setField(nestedB, 318).build());
-      message.addRepeatedField(f("repeated_foreign_message"),
-        newBuilderForField(message, f("repeated_foreign_message"))
-               .setField(foreignC, 319).build());
-      message.addRepeatedField(f("repeated_import_message"),
-        newBuilderForField(message, f("repeated_import_message"))
-               .setField(importD, 320).build());
-      message.addRepeatedField(f("repeated_lazy_message"),
-        newBuilderForField(message, f("repeated_lazy_message"))
-               .setField(nestedB, 327).build());
-
-      message.addRepeatedField(f("repeated_nested_enum" ),  nestedBaz);
-      message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz);
-      message.addRepeatedField(f("repeated_import_enum" ),  importBaz);
-
-      message.addRepeatedField(f("repeated_string_piece" ), "324");
-      message.addRepeatedField(f("repeated_cord" ), "325");
-
-      // -----------------------------------------------------------------
-
-      message.setField(f("default_int32"   ), 401 );
-      message.setField(f("default_int64"   ), 402L);
-      message.setField(f("default_uint32"  ), 403 );
-      message.setField(f("default_uint64"  ), 404L);
-      message.setField(f("default_sint32"  ), 405 );
-      message.setField(f("default_sint64"  ), 406L);
-      message.setField(f("default_fixed32" ), 407 );
-      message.setField(f("default_fixed64" ), 408L);
-      message.setField(f("default_sfixed32"), 409 );
-      message.setField(f("default_sfixed64"), 410L);
-      message.setField(f("default_float"   ), 411F);
-      message.setField(f("default_double"  ), 412D);
-      message.setField(f("default_bool"    ), false);
-      message.setField(f("default_string"  ), "415");
-      message.setField(f("default_bytes"   ), toBytes("416"));
-
-      message.setField(f("default_nested_enum" ),  nestedFoo);
-      message.setField(f("default_foreign_enum"), foreignFoo);
-      message.setField(f("default_import_enum" ),  importFoo);
-
-      message.setField(f("default_string_piece" ), "424");
-      message.setField(f("default_cord" ), "425");
-    }
-
-    // -------------------------------------------------------------------
-
-    /**
-     * Modify the repeated fields of {@code message} to contain the values
-     * expected by {@code assertRepeatedFieldsModified()}, using the
-     * {@link Message.Builder} reflection interface.
-     */
-    void modifyRepeatedFieldsViaReflection(Message.Builder message) {
-      message.setRepeatedField(f("repeated_int32"   ), 1, 501 );
-      message.setRepeatedField(f("repeated_int64"   ), 1, 502L);
-      message.setRepeatedField(f("repeated_uint32"  ), 1, 503 );
-      message.setRepeatedField(f("repeated_uint64"  ), 1, 504L);
-      message.setRepeatedField(f("repeated_sint32"  ), 1, 505 );
-      message.setRepeatedField(f("repeated_sint64"  ), 1, 506L);
-      message.setRepeatedField(f("repeated_fixed32" ), 1, 507 );
-      message.setRepeatedField(f("repeated_fixed64" ), 1, 508L);
-      message.setRepeatedField(f("repeated_sfixed32"), 1, 509 );
-      message.setRepeatedField(f("repeated_sfixed64"), 1, 510L);
-      message.setRepeatedField(f("repeated_float"   ), 1, 511F);
-      message.setRepeatedField(f("repeated_double"  ), 1, 512D);
-      message.setRepeatedField(f("repeated_bool"    ), 1, true);
-      message.setRepeatedField(f("repeated_string"  ), 1, "515");
-      message.setRepeatedField(f("repeated_bytes"   ), 1, toBytes("516"));
-
-      message.setRepeatedField(f("repeatedgroup"), 1,
-        newBuilderForField(message, f("repeatedgroup"))
-               .setField(repeatedGroupA, 517).build());
-      message.setRepeatedField(f("repeated_nested_message"), 1,
-        newBuilderForField(message, f("repeated_nested_message"))
-               .setField(nestedB, 518).build());
-      message.setRepeatedField(f("repeated_foreign_message"), 1,
-        newBuilderForField(message, f("repeated_foreign_message"))
-               .setField(foreignC, 519).build());
-      message.setRepeatedField(f("repeated_import_message"), 1,
-        newBuilderForField(message, f("repeated_import_message"))
-               .setField(importD, 520).build());
-      message.setRepeatedField(f("repeated_lazy_message"), 1,
-        newBuilderForField(message, f("repeated_lazy_message"))
-               .setField(nestedB, 527).build());
-
-      message.setRepeatedField(f("repeated_nested_enum" ), 1,  nestedFoo);
-      message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo);
-      message.setRepeatedField(f("repeated_import_enum" ), 1,  importFoo);
-
-      message.setRepeatedField(f("repeated_string_piece"), 1, "524");
-      message.setRepeatedField(f("repeated_cord"), 1, "525");
-    }
-
-    // -------------------------------------------------------------------
-
-    /**
-     * Assert (using {@code junit.framework.Assert}} that all fields of
-     * {@code message} are set to the values assigned by {@code setAllFields},
-     * using the {@link Message} reflection interface.
-     */
-    public void assertAllFieldsSetViaReflection(MessageOrBuilder message) {
-      Assert.assertTrue(message.hasField(f("optional_int32"   )));
-      Assert.assertTrue(message.hasField(f("optional_int64"   )));
-      Assert.assertTrue(message.hasField(f("optional_uint32"  )));
-      Assert.assertTrue(message.hasField(f("optional_uint64"  )));
-      Assert.assertTrue(message.hasField(f("optional_sint32"  )));
-      Assert.assertTrue(message.hasField(f("optional_sint64"  )));
-      Assert.assertTrue(message.hasField(f("optional_fixed32" )));
-      Assert.assertTrue(message.hasField(f("optional_fixed64" )));
-      Assert.assertTrue(message.hasField(f("optional_sfixed32")));
-      Assert.assertTrue(message.hasField(f("optional_sfixed64")));
-      Assert.assertTrue(message.hasField(f("optional_float"   )));
-      Assert.assertTrue(message.hasField(f("optional_double"  )));
-      Assert.assertTrue(message.hasField(f("optional_bool"    )));
-      Assert.assertTrue(message.hasField(f("optional_string"  )));
-      Assert.assertTrue(message.hasField(f("optional_bytes"   )));
-
-      Assert.assertTrue(message.hasField(f("optionalgroup"           )));
-      Assert.assertTrue(message.hasField(f("optional_nested_message" )));
-      Assert.assertTrue(message.hasField(f("optional_foreign_message")));
-      Assert.assertTrue(message.hasField(f("optional_import_message" )));
-
-      Assert.assertTrue(
-        ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
-      Assert.assertTrue(
-        ((Message)message.getField(f("optional_nested_message")))
-                         .hasField(nestedB));
-      Assert.assertTrue(
-        ((Message)message.getField(f("optional_foreign_message")))
-                         .hasField(foreignC));
-      Assert.assertTrue(
-        ((Message)message.getField(f("optional_import_message")))
-                         .hasField(importD));
-
-      Assert.assertTrue(message.hasField(f("optional_nested_enum" )));
-      Assert.assertTrue(message.hasField(f("optional_foreign_enum")));
-      Assert.assertTrue(message.hasField(f("optional_import_enum" )));
-
-      Assert.assertTrue(message.hasField(f("optional_string_piece")));
-      Assert.assertTrue(message.hasField(f("optional_cord")));
-
-      Assert.assertEquals(101  , message.getField(f("optional_int32"   )));
-      Assert.assertEquals(102L , message.getField(f("optional_int64"   )));
-      Assert.assertEquals(103  , message.getField(f("optional_uint32"  )));
-      Assert.assertEquals(104L , message.getField(f("optional_uint64"  )));
-      Assert.assertEquals(105  , message.getField(f("optional_sint32"  )));
-      Assert.assertEquals(106L , message.getField(f("optional_sint64"  )));
-      Assert.assertEquals(107  , message.getField(f("optional_fixed32" )));
-      Assert.assertEquals(108L , message.getField(f("optional_fixed64" )));
-      Assert.assertEquals(109  , message.getField(f("optional_sfixed32")));
-      Assert.assertEquals(110L , message.getField(f("optional_sfixed64")));
-      Assert.assertEquals(111F , message.getField(f("optional_float"   )));
-      Assert.assertEquals(112D , message.getField(f("optional_double"  )));
-      Assert.assertEquals(true , message.getField(f("optional_bool"    )));
-      Assert.assertEquals("115", message.getField(f("optional_string"  )));
-      Assert.assertEquals(toBytes("116"), message.getField(f("optional_bytes")));
-
-      Assert.assertEquals(117,
-        ((Message)message.getField(f("optionalgroup"))).getField(groupA));
-      Assert.assertEquals(118,
-        ((Message)message.getField(f("optional_nested_message")))
-                         .getField(nestedB));
-      Assert.assertEquals(119,
-        ((Message)message.getField(f("optional_foreign_message")))
-                         .getField(foreignC));
-      Assert.assertEquals(120,
-        ((Message)message.getField(f("optional_import_message")))
-                         .getField(importD));
-      Assert.assertEquals(126,
-        ((Message)message.getField(f("optional_public_import_message")))
-                         .getField(importE));
-      Assert.assertEquals(127,
-        ((Message)message.getField(f("optional_lazy_message")))
-                         .getField(nestedB));
-
-      Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" )));
-      Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum")));
-      Assert.assertEquals( importBaz, message.getField(f("optional_import_enum" )));
-
-      Assert.assertEquals("124", message.getField(f("optional_string_piece")));
-      Assert.assertEquals("125", message.getField(f("optional_cord")));
-
-      // -----------------------------------------------------------------
-
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool"    )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes"   )));
-
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup"           )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
-
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
-
-      Assert.assertEquals(201  , message.getRepeatedField(f("repeated_int32"   ), 0));
-      Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64"   ), 0));
-      Assert.assertEquals(203  , message.getRepeatedField(f("repeated_uint32"  ), 0));
-      Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64"  ), 0));
-      Assert.assertEquals(205  , message.getRepeatedField(f("repeated_sint32"  ), 0));
-      Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64"  ), 0));
-      Assert.assertEquals(207  , message.getRepeatedField(f("repeated_fixed32" ), 0));
-      Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
-      Assert.assertEquals(209  , message.getRepeatedField(f("repeated_sfixed32"), 0));
-      Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
-      Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float"   ), 0));
-      Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double"  ), 0));
-      Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool"    ), 0));
-      Assert.assertEquals("215", message.getRepeatedField(f("repeated_string"  ), 0));
-      Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
-
-      Assert.assertEquals(217,
-        ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
-                         .getField(repeatedGroupA));
-      Assert.assertEquals(218,
-        ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
-                         .getField(nestedB));
-      Assert.assertEquals(219,
-        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
-                         .getField(foreignC));
-      Assert.assertEquals(220,
-        ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
-                         .getField(importD));
-      Assert.assertEquals(227,
-        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
-                         .getField(nestedB));
-
-      Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
-      Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
-      Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
-
-      Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
-      Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
-
-      Assert.assertEquals(301  , message.getRepeatedField(f("repeated_int32"   ), 1));
-      Assert.assertEquals(302L , message.getRepeatedField(f("repeated_int64"   ), 1));
-      Assert.assertEquals(303  , message.getRepeatedField(f("repeated_uint32"  ), 1));
-      Assert.assertEquals(304L , message.getRepeatedField(f("repeated_uint64"  ), 1));
-      Assert.assertEquals(305  , message.getRepeatedField(f("repeated_sint32"  ), 1));
-      Assert.assertEquals(306L , message.getRepeatedField(f("repeated_sint64"  ), 1));
-      Assert.assertEquals(307  , message.getRepeatedField(f("repeated_fixed32" ), 1));
-      Assert.assertEquals(308L , message.getRepeatedField(f("repeated_fixed64" ), 1));
-      Assert.assertEquals(309  , message.getRepeatedField(f("repeated_sfixed32"), 1));
-      Assert.assertEquals(310L , message.getRepeatedField(f("repeated_sfixed64"), 1));
-      Assert.assertEquals(311F , message.getRepeatedField(f("repeated_float"   ), 1));
-      Assert.assertEquals(312D , message.getRepeatedField(f("repeated_double"  ), 1));
-      Assert.assertEquals(false, message.getRepeatedField(f("repeated_bool"    ), 1));
-      Assert.assertEquals("315", message.getRepeatedField(f("repeated_string"  ), 1));
-      Assert.assertEquals(toBytes("316"), message.getRepeatedField(f("repeated_bytes"), 1));
-
-      Assert.assertEquals(317,
-        ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
-                         .getField(repeatedGroupA));
-      Assert.assertEquals(318,
-        ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
-                         .getField(nestedB));
-      Assert.assertEquals(319,
-        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
-                         .getField(foreignC));
-      Assert.assertEquals(320,
-        ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
-                         .getField(importD));
-      Assert.assertEquals(327,
-        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
-                         .getField(nestedB));
-
-      Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1));
-      Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1));
-      Assert.assertEquals( importBaz, message.getRepeatedField(f("repeated_import_enum" ),1));
-
-      Assert.assertEquals("324", message.getRepeatedField(f("repeated_string_piece"), 1));
-      Assert.assertEquals("325", message.getRepeatedField(f("repeated_cord"), 1));
-
-      // -----------------------------------------------------------------
-
-      Assert.assertTrue(message.hasField(f("default_int32"   )));
-      Assert.assertTrue(message.hasField(f("default_int64"   )));
-      Assert.assertTrue(message.hasField(f("default_uint32"  )));
-      Assert.assertTrue(message.hasField(f("default_uint64"  )));
-      Assert.assertTrue(message.hasField(f("default_sint32"  )));
-      Assert.assertTrue(message.hasField(f("default_sint64"  )));
-      Assert.assertTrue(message.hasField(f("default_fixed32" )));
-      Assert.assertTrue(message.hasField(f("default_fixed64" )));
-      Assert.assertTrue(message.hasField(f("default_sfixed32")));
-      Assert.assertTrue(message.hasField(f("default_sfixed64")));
-      Assert.assertTrue(message.hasField(f("default_float"   )));
-      Assert.assertTrue(message.hasField(f("default_double"  )));
-      Assert.assertTrue(message.hasField(f("default_bool"    )));
-      Assert.assertTrue(message.hasField(f("default_string"  )));
-      Assert.assertTrue(message.hasField(f("default_bytes"   )));
-
-      Assert.assertTrue(message.hasField(f("default_nested_enum" )));
-      Assert.assertTrue(message.hasField(f("default_foreign_enum")));
-      Assert.assertTrue(message.hasField(f("default_import_enum" )));
-
-      Assert.assertTrue(message.hasField(f("default_string_piece")));
-      Assert.assertTrue(message.hasField(f("default_cord")));
-
-      Assert.assertEquals(401  , message.getField(f("default_int32"   )));
-      Assert.assertEquals(402L , message.getField(f("default_int64"   )));
-      Assert.assertEquals(403  , message.getField(f("default_uint32"  )));
-      Assert.assertEquals(404L , message.getField(f("default_uint64"  )));
-      Assert.assertEquals(405  , message.getField(f("default_sint32"  )));
-      Assert.assertEquals(406L , message.getField(f("default_sint64"  )));
-      Assert.assertEquals(407  , message.getField(f("default_fixed32" )));
-      Assert.assertEquals(408L , message.getField(f("default_fixed64" )));
-      Assert.assertEquals(409  , message.getField(f("default_sfixed32")));
-      Assert.assertEquals(410L , message.getField(f("default_sfixed64")));
-      Assert.assertEquals(411F , message.getField(f("default_float"   )));
-      Assert.assertEquals(412D , message.getField(f("default_double"  )));
-      Assert.assertEquals(false, message.getField(f("default_bool"    )));
-      Assert.assertEquals("415", message.getField(f("default_string"  )));
-      Assert.assertEquals(toBytes("416"), message.getField(f("default_bytes")));
-
-      Assert.assertEquals( nestedFoo, message.getField(f("default_nested_enum" )));
-      Assert.assertEquals(foreignFoo, message.getField(f("default_foreign_enum")));
-      Assert.assertEquals( importFoo, message.getField(f("default_import_enum" )));
-
-      Assert.assertEquals("424", message.getField(f("default_string_piece")));
-      Assert.assertEquals("425", message.getField(f("default_cord")));
-    }
-
-    // -------------------------------------------------------------------
-
-    /**
-     * Assert (using {@code junit.framework.Assert}} that all fields of
-     * {@code message} are cleared, and that getting the fields returns their
-     * default values, using the {@link Message} reflection interface.
-     */
-    public void assertClearViaReflection(MessageOrBuilder message) {
-      // has_blah() should initially be false for all optional fields.
-      Assert.assertFalse(message.hasField(f("optional_int32"   )));
-      Assert.assertFalse(message.hasField(f("optional_int64"   )));
-      Assert.assertFalse(message.hasField(f("optional_uint32"  )));
-      Assert.assertFalse(message.hasField(f("optional_uint64"  )));
-      Assert.assertFalse(message.hasField(f("optional_sint32"  )));
-      Assert.assertFalse(message.hasField(f("optional_sint64"  )));
-      Assert.assertFalse(message.hasField(f("optional_fixed32" )));
-      Assert.assertFalse(message.hasField(f("optional_fixed64" )));
-      Assert.assertFalse(message.hasField(f("optional_sfixed32")));
-      Assert.assertFalse(message.hasField(f("optional_sfixed64")));
-      Assert.assertFalse(message.hasField(f("optional_float"   )));
-      Assert.assertFalse(message.hasField(f("optional_double"  )));
-      Assert.assertFalse(message.hasField(f("optional_bool"    )));
-      Assert.assertFalse(message.hasField(f("optional_string"  )));
-      Assert.assertFalse(message.hasField(f("optional_bytes"   )));
-
-      Assert.assertFalse(message.hasField(f("optionalgroup"           )));
-      Assert.assertFalse(message.hasField(f("optional_nested_message" )));
-      Assert.assertFalse(message.hasField(f("optional_foreign_message")));
-      Assert.assertFalse(message.hasField(f("optional_import_message" )));
-
-      Assert.assertFalse(message.hasField(f("optional_nested_enum" )));
-      Assert.assertFalse(message.hasField(f("optional_foreign_enum")));
-      Assert.assertFalse(message.hasField(f("optional_import_enum" )));
-
-      Assert.assertFalse(message.hasField(f("optional_string_piece")));
-      Assert.assertFalse(message.hasField(f("optional_cord")));
-
-      // Optional fields without defaults are set to zero or something like it.
-      Assert.assertEquals(0    , message.getField(f("optional_int32"   )));
-      Assert.assertEquals(0L   , message.getField(f("optional_int64"   )));
-      Assert.assertEquals(0    , message.getField(f("optional_uint32"  )));
-      Assert.assertEquals(0L   , message.getField(f("optional_uint64"  )));
-      Assert.assertEquals(0    , message.getField(f("optional_sint32"  )));
-      Assert.assertEquals(0L   , message.getField(f("optional_sint64"  )));
-      Assert.assertEquals(0    , message.getField(f("optional_fixed32" )));
-      Assert.assertEquals(0L   , message.getField(f("optional_fixed64" )));
-      Assert.assertEquals(0    , message.getField(f("optional_sfixed32")));
-      Assert.assertEquals(0L   , message.getField(f("optional_sfixed64")));
-      Assert.assertEquals(0F   , message.getField(f("optional_float"   )));
-      Assert.assertEquals(0D   , message.getField(f("optional_double"  )));
-      Assert.assertEquals(false, message.getField(f("optional_bool"    )));
-      Assert.assertEquals(""   , message.getField(f("optional_string"  )));
-      Assert.assertEquals(ByteString.EMPTY, message.getField(f("optional_bytes")));
-
-      // Embedded messages should also be clear.
-      Assert.assertFalse(
-        ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
-      Assert.assertFalse(
-        ((Message)message.getField(f("optional_nested_message")))
-                         .hasField(nestedB));
-      Assert.assertFalse(
-        ((Message)message.getField(f("optional_foreign_message")))
-                         .hasField(foreignC));
-      Assert.assertFalse(
-        ((Message)message.getField(f("optional_import_message")))
-                         .hasField(importD));
-      Assert.assertFalse(
-        ((Message)message.getField(f("optional_public_import_message")))
-                         .hasField(importE));
-      Assert.assertFalse(
-        ((Message)message.getField(f("optional_lazy_message")))
-                         .hasField(nestedB));
-
-      Assert.assertEquals(0,
-        ((Message)message.getField(f("optionalgroup"))).getField(groupA));
-      Assert.assertEquals(0,
-        ((Message)message.getField(f("optional_nested_message")))
-                         .getField(nestedB));
-      Assert.assertEquals(0,
-        ((Message)message.getField(f("optional_foreign_message")))
-                         .getField(foreignC));
-      Assert.assertEquals(0,
-        ((Message)message.getField(f("optional_import_message")))
-                         .getField(importD));
-      Assert.assertEquals(0,
-        ((Message)message.getField(f("optional_public_import_message")))
-                         .getField(importE));
-      Assert.assertEquals(0,
-        ((Message)message.getField(f("optional_lazy_message")))
-                         .getField(nestedB));
-
-      // Enums without defaults are set to the first value in the enum.
-      Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" )));
-      Assert.assertEquals(foreignFoo, message.getField(f("optional_foreign_enum")));
-      Assert.assertEquals( importFoo, message.getField(f("optional_import_enum" )));
-
-      Assert.assertEquals("", message.getField(f("optional_string_piece")));
-      Assert.assertEquals("", message.getField(f("optional_cord")));
-
-      // Repeated fields are empty.
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int32"   )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int64"   )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint32"  )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint64"  )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint32"  )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint64"  )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed32" )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed64" )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed32")));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed64")));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_float"   )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_double"  )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bool"    )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string"  )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bytes"   )));
-
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeatedgroup"           )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message")));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message"   )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
-
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string_piece")));
-      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_cord")));
-
-      // has_blah() should also be false for all default fields.
-      Assert.assertFalse(message.hasField(f("default_int32"   )));
-      Assert.assertFalse(message.hasField(f("default_int64"   )));
-      Assert.assertFalse(message.hasField(f("default_uint32"  )));
-      Assert.assertFalse(message.hasField(f("default_uint64"  )));
-      Assert.assertFalse(message.hasField(f("default_sint32"  )));
-      Assert.assertFalse(message.hasField(f("default_sint64"  )));
-      Assert.assertFalse(message.hasField(f("default_fixed32" )));
-      Assert.assertFalse(message.hasField(f("default_fixed64" )));
-      Assert.assertFalse(message.hasField(f("default_sfixed32")));
-      Assert.assertFalse(message.hasField(f("default_sfixed64")));
-      Assert.assertFalse(message.hasField(f("default_float"   )));
-      Assert.assertFalse(message.hasField(f("default_double"  )));
-      Assert.assertFalse(message.hasField(f("default_bool"    )));
-      Assert.assertFalse(message.hasField(f("default_string"  )));
-      Assert.assertFalse(message.hasField(f("default_bytes"   )));
-
-      Assert.assertFalse(message.hasField(f("default_nested_enum" )));
-      Assert.assertFalse(message.hasField(f("default_foreign_enum")));
-      Assert.assertFalse(message.hasField(f("default_import_enum" )));
-
-      Assert.assertFalse(message.hasField(f("default_string_piece" )));
-      Assert.assertFalse(message.hasField(f("default_cord" )));
-
-      // Fields with defaults have their default values (duh).
-      Assert.assertEquals( 41    , message.getField(f("default_int32"   )));
-      Assert.assertEquals( 42L   , message.getField(f("default_int64"   )));
-      Assert.assertEquals( 43    , message.getField(f("default_uint32"  )));
-      Assert.assertEquals( 44L   , message.getField(f("default_uint64"  )));
-      Assert.assertEquals(-45    , message.getField(f("default_sint32"  )));
-      Assert.assertEquals( 46L   , message.getField(f("default_sint64"  )));
-      Assert.assertEquals( 47    , message.getField(f("default_fixed32" )));
-      Assert.assertEquals( 48L   , message.getField(f("default_fixed64" )));
-      Assert.assertEquals( 49    , message.getField(f("default_sfixed32")));
-      Assert.assertEquals(-50L   , message.getField(f("default_sfixed64")));
-      Assert.assertEquals( 51.5F , message.getField(f("default_float"   )));
-      Assert.assertEquals( 52e3D , message.getField(f("default_double"  )));
-      Assert.assertEquals(true   , message.getField(f("default_bool"    )));
-      Assert.assertEquals("hello", message.getField(f("default_string"  )));
-      Assert.assertEquals(toBytes("world"), message.getField(f("default_bytes")));
-
-      Assert.assertEquals( nestedBar, message.getField(f("default_nested_enum" )));
-      Assert.assertEquals(foreignBar, message.getField(f("default_foreign_enum")));
-      Assert.assertEquals( importBar, message.getField(f("default_import_enum" )));
-
-      Assert.assertEquals("abc", message.getField(f("default_string_piece")));
-      Assert.assertEquals("123", message.getField(f("default_cord")));
-    }
-
-
-    // ---------------------------------------------------------------
-
-    public void assertRepeatedFieldsModifiedViaReflection(
-        MessageOrBuilder message) {
-      // ModifyRepeatedFields only sets the second repeated element of each
-      // field.  In addition to verifying this, we also verify that the first
-      // element and size were *not* modified.
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool"    )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes"   )));
-
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup"           )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
-
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
-
-      Assert.assertEquals(201  , message.getRepeatedField(f("repeated_int32"   ), 0));
-      Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64"   ), 0));
-      Assert.assertEquals(203  , message.getRepeatedField(f("repeated_uint32"  ), 0));
-      Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64"  ), 0));
-      Assert.assertEquals(205  , message.getRepeatedField(f("repeated_sint32"  ), 0));
-      Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64"  ), 0));
-      Assert.assertEquals(207  , message.getRepeatedField(f("repeated_fixed32" ), 0));
-      Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
-      Assert.assertEquals(209  , message.getRepeatedField(f("repeated_sfixed32"), 0));
-      Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
-      Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float"   ), 0));
-      Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double"  ), 0));
-      Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool"    ), 0));
-      Assert.assertEquals("215", message.getRepeatedField(f("repeated_string"  ), 0));
-      Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
-
-      Assert.assertEquals(217,
-        ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
-                         .getField(repeatedGroupA));
-      Assert.assertEquals(218,
-        ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
-                         .getField(nestedB));
-      Assert.assertEquals(219,
-        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
-                         .getField(foreignC));
-      Assert.assertEquals(220,
-        ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
-                         .getField(importD));
-      Assert.assertEquals(227,
-        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
-                         .getField(nestedB));
-
-      Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
-      Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
-      Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
-
-      Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
-      Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
-
-      Assert.assertEquals(501  , message.getRepeatedField(f("repeated_int32"   ), 1));
-      Assert.assertEquals(502L , message.getRepeatedField(f("repeated_int64"   ), 1));
-      Assert.assertEquals(503  , message.getRepeatedField(f("repeated_uint32"  ), 1));
-      Assert.assertEquals(504L , message.getRepeatedField(f("repeated_uint64"  ), 1));
-      Assert.assertEquals(505  , message.getRepeatedField(f("repeated_sint32"  ), 1));
-      Assert.assertEquals(506L , message.getRepeatedField(f("repeated_sint64"  ), 1));
-      Assert.assertEquals(507  , message.getRepeatedField(f("repeated_fixed32" ), 1));
-      Assert.assertEquals(508L , message.getRepeatedField(f("repeated_fixed64" ), 1));
-      Assert.assertEquals(509  , message.getRepeatedField(f("repeated_sfixed32"), 1));
-      Assert.assertEquals(510L , message.getRepeatedField(f("repeated_sfixed64"), 1));
-      Assert.assertEquals(511F , message.getRepeatedField(f("repeated_float"   ), 1));
-      Assert.assertEquals(512D , message.getRepeatedField(f("repeated_double"  ), 1));
-      Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool"    ), 1));
-      Assert.assertEquals("515", message.getRepeatedField(f("repeated_string"  ), 1));
-      Assert.assertEquals(toBytes("516"), message.getRepeatedField(f("repeated_bytes"), 1));
-
-      Assert.assertEquals(517,
-        ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
-                         .getField(repeatedGroupA));
-      Assert.assertEquals(518,
-        ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
-                         .getField(nestedB));
-      Assert.assertEquals(519,
-        ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
-                         .getField(foreignC));
-      Assert.assertEquals(520,
-        ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
-                         .getField(importD));
-      Assert.assertEquals(527,
-        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
-                         .getField(nestedB));
-
-      Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1));
-      Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1));
-      Assert.assertEquals( importFoo, message.getRepeatedField(f("repeated_import_enum" ),1));
-
-      Assert.assertEquals("524", message.getRepeatedField(f("repeated_string_piece"), 1));
-      Assert.assertEquals("525", message.getRepeatedField(f("repeated_cord"), 1));
-    }
-
-    public void setPackedFieldsViaReflection(Message.Builder message) {
-      message.addRepeatedField(f("packed_int32"   ), 601 );
-      message.addRepeatedField(f("packed_int64"   ), 602L);
-      message.addRepeatedField(f("packed_uint32"  ), 603 );
-      message.addRepeatedField(f("packed_uint64"  ), 604L);
-      message.addRepeatedField(f("packed_sint32"  ), 605 );
-      message.addRepeatedField(f("packed_sint64"  ), 606L);
-      message.addRepeatedField(f("packed_fixed32" ), 607 );
-      message.addRepeatedField(f("packed_fixed64" ), 608L);
-      message.addRepeatedField(f("packed_sfixed32"), 609 );
-      message.addRepeatedField(f("packed_sfixed64"), 610L);
-      message.addRepeatedField(f("packed_float"   ), 611F);
-      message.addRepeatedField(f("packed_double"  ), 612D);
-      message.addRepeatedField(f("packed_bool"    ), true);
-      message.addRepeatedField(f("packed_enum" ),  foreignBar);
-      // Add a second one of each field.
-      message.addRepeatedField(f("packed_int32"   ), 701 );
-      message.addRepeatedField(f("packed_int64"   ), 702L);
-      message.addRepeatedField(f("packed_uint32"  ), 703 );
-      message.addRepeatedField(f("packed_uint64"  ), 704L);
-      message.addRepeatedField(f("packed_sint32"  ), 705 );
-      message.addRepeatedField(f("packed_sint64"  ), 706L);
-      message.addRepeatedField(f("packed_fixed32" ), 707 );
-      message.addRepeatedField(f("packed_fixed64" ), 708L);
-      message.addRepeatedField(f("packed_sfixed32"), 709 );
-      message.addRepeatedField(f("packed_sfixed64"), 710L);
-      message.addRepeatedField(f("packed_float"   ), 711F);
-      message.addRepeatedField(f("packed_double"  ), 712D);
-      message.addRepeatedField(f("packed_bool"    ), false);
-      message.addRepeatedField(f("packed_enum" ),  foreignBaz);
-    }
-
-    public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) {
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64" )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed32")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed64")));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float"   )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double"  )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool"    )));
-      Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum"   )));
-      Assert.assertEquals(601  , message.getRepeatedField(f("packed_int32"   ), 0));
-      Assert.assertEquals(602L , message.getRepeatedField(f("packed_int64"   ), 0));
-      Assert.assertEquals(603  , message.getRepeatedField(f("packed_uint32"  ), 0));
-      Assert.assertEquals(604L , message.getRepeatedField(f("packed_uint64"  ), 0));
-      Assert.assertEquals(605  , message.getRepeatedField(f("packed_sint32"  ), 0));
-      Assert.assertEquals(606L , message.getRepeatedField(f("packed_sint64"  ), 0));
-      Assert.assertEquals(607  , message.getRepeatedField(f("packed_fixed32" ), 0));
-      Assert.assertEquals(608L , message.getRepeatedField(f("packed_fixed64" ), 0));
-      Assert.assertEquals(609  , message.getRepeatedField(f("packed_sfixed32"), 0));
-      Assert.assertEquals(610L , message.getRepeatedField(f("packed_sfixed64"), 0));
-      Assert.assertEquals(611F , message.getRepeatedField(f("packed_float"   ), 0));
-      Assert.assertEquals(612D , message.getRepeatedField(f("packed_double"  ), 0));
-      Assert.assertEquals(true , message.getRepeatedField(f("packed_bool"    ), 0));
-      Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum" ),0));
-      Assert.assertEquals(701  , message.getRepeatedField(f("packed_int32"   ), 1));
-      Assert.assertEquals(702L , message.getRepeatedField(f("packed_int64"   ), 1));
-      Assert.assertEquals(703  , message.getRepeatedField(f("packed_uint32"  ), 1));
-      Assert.assertEquals(704L , message.getRepeatedField(f("packed_uint64"  ), 1));
-      Assert.assertEquals(705  , message.getRepeatedField(f("packed_sint32"  ), 1));
-      Assert.assertEquals(706L , message.getRepeatedField(f("packed_sint64"  ), 1));
-      Assert.assertEquals(707  , message.getRepeatedField(f("packed_fixed32" ), 1));
-      Assert.assertEquals(708L , message.getRepeatedField(f("packed_fixed64" ), 1));
-      Assert.assertEquals(709  , message.getRepeatedField(f("packed_sfixed32"), 1));
-      Assert.assertEquals(710L , message.getRepeatedField(f("packed_sfixed64"), 1));
-      Assert.assertEquals(711F , message.getRepeatedField(f("packed_float"   ), 1));
-      Assert.assertEquals(712D , message.getRepeatedField(f("packed_double"  ), 1));
-      Assert.assertEquals(false, message.getRepeatedField(f("packed_bool"    ), 1));
-      Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum" ),1));
-    }
-
-    /**
-     * Verifies that the reflection setters for the given.Builder object throw a
-     * NullPointerException if they are passed a null value.  Uses Assert to throw an
-     * appropriate assertion failure, if the condition is not verified.
-     */
-    public void assertReflectionSettersRejectNull(Message.Builder builder)
-        throws Exception {
-      try {
-        builder.setField(f("optional_string"), null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-      try {
-        builder.setField(f("optional_bytes"), null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-      try {
-        builder.setField(f("optional_nested_enum"), null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-      try {
-        builder.setField(f("optional_nested_message"),
-                         (TestAllTypes.NestedMessage) null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-      try {
-        builder.setField(f("optional_nested_message"),
-                         (TestAllTypes.NestedMessage.Builder) null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-
-      try {
-        builder.addRepeatedField(f("repeated_string"), null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-      try {
-        builder.addRepeatedField(f("repeated_bytes"), null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-      try {
-        builder.addRepeatedField(f("repeated_nested_enum"), null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-      try {
-        builder.addRepeatedField(f("repeated_nested_message"), null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-    }
-
-    /**
-     * Verifies that the reflection repeated setters for the given Builder object throw a
-     * NullPointerException if they are passed a null value.  Uses Assert to throw an appropriate
-     * assertion failure, if the condition is not verified.
-     */
-    public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder)
-        throws Exception {
-      builder.addRepeatedField(f("repeated_string"), "one");
-      try {
-        builder.setRepeatedField(f("repeated_string"), 0, null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-
-      builder.addRepeatedField(f("repeated_bytes"), toBytes("one"));
-      try {
-        builder.setRepeatedField(f("repeated_bytes"), 0, null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-
-      builder.addRepeatedField(f("repeated_nested_enum"), nestedBaz);
-      try {
-        builder.setRepeatedField(f("repeated_nested_enum"), 0, null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-
-      builder.addRepeatedField(
-          f("repeated_nested_message"),
-          TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
-      try {
-        builder.setRepeatedField(f("repeated_nested_message"), 0, null);
-        Assert.fail("Exception was not thrown");
-      } catch (NullPointerException e) {
-        // We expect this exception.
-      }
-    }
-  }
-
-  /**
-   * @param filePath The path relative to
-   * {@link #getTestDataDir}.
-   */
-  public static String readTextFromFile(String filePath) {
-    return readBytesFromFile(filePath).toStringUtf8();
-  }
-
-  private static File getTestDataDir() {
-    // Search each parent directory looking for "src/google/protobuf".
-    File ancestor = new File(".");
-    try {
-      ancestor = ancestor.getCanonicalFile();
-    } catch (IOException e) {
-      throw new RuntimeException(
-        "Couldn't get canonical name of working directory.", e);
-    }
-    while (ancestor != null && ancestor.exists()) {
-      if (new File(ancestor, "src/google/protobuf").exists()) {
-        return new File(ancestor, "src/google/protobuf/testdata");
-      }
-      ancestor = ancestor.getParentFile();
-    }
-
-    throw new RuntimeException(
-      "Could not find golden files.  This test must be run from within the " +
-      "protobuf source package so that it can read test data files from the " +
-      "C++ source tree: " + new File(".").getAbsolutePath());
-  }
-
-  /**
-   * @param filename The path relative to
-   * {@link #getTestDataDir}.
-   */
-  public static ByteString readBytesFromFile(String filename) {
-    File fullPath = new File(getTestDataDir(), filename);
-    try {
-      RandomAccessFile file = new RandomAccessFile(fullPath, "r");
-      byte[] content = new byte[(int) file.length()];
-      file.readFully(content);
-      return ByteString.copyFrom(content);
-    } catch (IOException e) {
-      // Throw a RuntimeException here so that we can call this function from
-      // static initializers.
-      throw new IllegalArgumentException(
-        "Couldn't read file: " + fullPath.getPath(), e);
-    }
-  }
-
-  /**
-   * Get the bytes of the "golden message".  This is a serialized TestAllTypes
-   * with all fields set as they would be by
-   * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
-   * on disk rather than generated dynamically.  The file is actually generated
-   * by C++ code, so testing against it verifies compatibility with C++.
-   */
-  public static ByteString getGoldenMessage() {
-    if (goldenMessage == null) {
-      goldenMessage = readBytesFromFile("golden_message");
-    }
-    return goldenMessage;
-  }
-  private static ByteString goldenMessage = null;
-
-  /**
-   * Get the bytes of the "golden packed fields message".  This is a serialized
-   * TestPackedTypes with all fields set as they would be by
-   * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
-   * file on disk rather than generated dynamically.  The file is actually
-   * generated by C++ code, so testing against it verifies compatibility with
-   * C++.
-   */
-  public static ByteString getGoldenPackedFieldsMessage() {
-    if (goldenPackedFieldsMessage == null) {
-      goldenPackedFieldsMessage =
-          readBytesFromFile("golden_packed_fields_message");
-    }
-    return goldenPackedFieldsMessage;
-  }
-  private static ByteString goldenPackedFieldsMessage = null;
-
-  public static abstract class HackMessage extends GeneratedMessage {
-    public interface MyInterface extends BuilderParent {
-    }
-  }
-  /**
-   * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing.
-   *
-   * @author jonp@google.com (Jon Perlow)
-   */
-  public static class MockBuilderParent
-      implements HackMessage.MyInterface {
-
-    private int invalidations;
-
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public void markDirty() {
-      invalidations++;
-    }
-
-    public int getInvalidationCount() {
-      return invalidations;
-    }
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TextFormatTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TextFormatTest.java
deleted file mode 100644
index edcc890..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TextFormatTest.java
+++ /dev/null
@@ -1,536 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import protobuf_unittest.UnittestMset.TestMessageSet;
-import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
-import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
-import protobuf_unittest.UnittestProto.OneString;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
-import protobuf_unittest.UnittestProto.TestEmptyMessage;
-
-import junit.framework.TestCase;
-
-import java.io.StringReader;
-
-/**
- * Test case for {@link TextFormat}.
- *
- * TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc.
- *
- * @author wenboz@google.com (Wenbo Zhu)
- */
-public class TextFormatTest extends TestCase {
-
-  // A basic string with different escapable characters for testing.
-  private final static String kEscapeTestString =
-      "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
-          + "slashes \\";
-
-  // A representation of the above string with all the characters escaped.
-  private final static String kEscapeTestStringEscaped =
-      "\\\"A string with \\' characters \\n and \\r newlines "
-          + "and \\t tabs and \\001 slashes \\\\";
-
-  private static String allFieldsSetText = TestUtil.readTextFromFile(
-    "text_format_unittest_data.txt");
-  private static String allExtensionsSetText = TestUtil.readTextFromFile(
-    "text_format_unittest_extensions_data.txt");
-
-  private static String exoticText =
-    "repeated_int32: -1\n" +
-    "repeated_int32: -2147483648\n" +
-    "repeated_int64: -1\n" +
-    "repeated_int64: -9223372036854775808\n" +
-    "repeated_uint32: 4294967295\n" +
-    "repeated_uint32: 2147483648\n" +
-    "repeated_uint64: 18446744073709551615\n" +
-    "repeated_uint64: 9223372036854775808\n" +
-    "repeated_double: 123.0\n" +
-    "repeated_double: 123.5\n" +
-    "repeated_double: 0.125\n" +
-    "repeated_double: .125\n" +
-    "repeated_double: -.125\n" +
-    "repeated_double: 1.23E17\n" +
-    "repeated_double: 1.23E+17\n" +
-    "repeated_double: -1.23e-17\n" +
-    "repeated_double: .23e+17\n" +
-    "repeated_double: -.23E17\n" +
-    "repeated_double: 1.235E22\n" +
-    "repeated_double: 1.235E-18\n" +
-    "repeated_double: 123.456789\n" +
-    "repeated_double: Infinity\n" +
-    "repeated_double: -Infinity\n" +
-    "repeated_double: NaN\n" +
-    "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
-      "\\341\\210\\264\"\n" +
-    "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
-
-  private static String canonicalExoticText =
-      exoticText.replace(": .", ": 0.").replace(": -.", ": -0.")   // short-form double
-      .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16");
-
-  private String messageSetText =
-    "[protobuf_unittest.TestMessageSetExtension1] {\n" +
-    "  i: 123\n" +
-    "}\n" +
-    "[protobuf_unittest.TestMessageSetExtension2] {\n" +
-    "  str: \"foo\"\n" +
-    "}\n";
-
-  /** Print TestAllTypes and compare with golden file. */
-  public void testPrintMessage() throws Exception {
-    String javaText = TextFormat.printToString(TestUtil.getAllSet());
-
-    // Java likes to add a trailing ".0" to floats and doubles.  C printf
-    // (with %g format) does not.  Our golden files are used for both
-    // C++ and Java TextFormat classes, so we need to conform.
-    javaText = javaText.replace(".0\n", "\n");
-
-    assertEquals(allFieldsSetText, javaText);
-  }
-
-  /** Print TestAllTypes as Builder and compare with golden file. */
-  public void testPrintMessageBuilder() throws Exception {
-    String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
-
-    // Java likes to add a trailing ".0" to floats and doubles.  C printf
-    // (with %g format) does not.  Our golden files are used for both
-    // C++ and Java TextFormat classes, so we need to conform.
-    javaText = javaText.replace(".0\n", "\n");
-
-    assertEquals(allFieldsSetText, javaText);
-  }
-
-  /** Print TestAllExtensions and compare with golden file. */
-  public void testPrintExtensions() throws Exception {
-    String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
-
-    // Java likes to add a trailing ".0" to floats and doubles.  C printf
-    // (with %g format) does not.  Our golden files are used for both
-    // C++ and Java TextFormat classes, so we need to conform.
-    javaText = javaText.replace(".0\n", "\n");
-
-    assertEquals(allExtensionsSetText, javaText);
-  }
-
-  // Creates an example unknown field set.
-  private UnknownFieldSet makeUnknownFieldSet() {
-    return UnknownFieldSet.newBuilder()
-        .addField(5,
-            UnknownFieldSet.Field.newBuilder()
-            .addVarint(1)
-            .addFixed32(2)
-            .addFixed64(3)
-            .addLengthDelimited(ByteString.copyFromUtf8("4"))
-            .addGroup(
-                UnknownFieldSet.newBuilder()
-                .addField(10,
-                    UnknownFieldSet.Field.newBuilder()
-                    .addVarint(5)
-                    .build())
-                .build())
-            .build())
-        .addField(8,
-            UnknownFieldSet.Field.newBuilder()
-            .addVarint(1)
-            .addVarint(2)
-            .addVarint(3)
-            .build())
-        .addField(15,
-            UnknownFieldSet.Field.newBuilder()
-            .addVarint(0xABCDEF1234567890L)
-            .addFixed32(0xABCD1234)
-            .addFixed64(0xABCDEF1234567890L)
-            .build())
-        .build();
-  }
-
-  public void testPrintUnknownFields() throws Exception {
-    // Test printing of unknown fields in a message.
-
-    TestEmptyMessage message =
-      TestEmptyMessage.newBuilder()
-        .setUnknownFields(makeUnknownFieldSet())
-        .build();
-
-    assertEquals(
-      "5: 1\n" +
-      "5: 0x00000002\n" +
-      "5: 0x0000000000000003\n" +
-      "5: \"4\"\n" +
-      "5 {\n" +
-      "  10: 5\n" +
-      "}\n" +
-      "8: 1\n" +
-      "8: 2\n" +
-      "8: 3\n" +
-      "15: 12379813812177893520\n" +
-      "15: 0xabcd1234\n" +
-      "15: 0xabcdef1234567890\n",
-      TextFormat.printToString(message));
-  }
-
-  public void testPrintField() throws Exception {
-    final FieldDescriptor dataField =
-      OneString.getDescriptor().findFieldByName("data");
-    assertEquals(
-      "data: \"test data\"\n",
-      TextFormat.printFieldToString(dataField, "test data"));
-
-    final FieldDescriptor optionalField =
-      TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
-    final Object value = NestedMessage.newBuilder().setBb(42).build();
-
-    assertEquals(
-      "optional_nested_message {\n  bb: 42\n}\n",
-      TextFormat.printFieldToString(optionalField, value));
-  }
-
-  /**
-   * Helper to construct a ByteString from a String containing only 8-bit
-   * characters.  The characters are converted directly to bytes, *not*
-   * encoded using UTF-8.
-   */
-  private ByteString bytes(String str) throws Exception {
-    return ByteString.copyFrom(str.getBytes("ISO-8859-1"));
-  }
-
-  /**
-   * Helper to construct a ByteString from a bunch of bytes.  The inputs are
-   * actually ints so that I can use hex notation and not get stupid errors
-   * about precision.
-   */
-  private ByteString bytes(int... bytesAsInts) {
-    byte[] bytes = new byte[bytesAsInts.length];
-    for (int i = 0; i < bytesAsInts.length; i++) {
-      bytes[i] = (byte) bytesAsInts[i];
-    }
-    return ByteString.copyFrom(bytes);
-  }
-
-  public void testPrintExotic() throws Exception {
-    Message message = TestAllTypes.newBuilder()
-      // Signed vs. unsigned numbers.
-      .addRepeatedInt32 (-1)
-      .addRepeatedUint32(-1)
-      .addRepeatedInt64 (-1)
-      .addRepeatedUint64(-1)
-
-      .addRepeatedInt32 (1  << 31)
-      .addRepeatedUint32(1  << 31)
-      .addRepeatedInt64 (1l << 63)
-      .addRepeatedUint64(1l << 63)
-
-      // Floats of various precisions and exponents.
-      .addRepeatedDouble(123)
-      .addRepeatedDouble(123.5)
-      .addRepeatedDouble(0.125)
-      .addRepeatedDouble(.125)
-      .addRepeatedDouble(-.125)
-      .addRepeatedDouble(123e15)
-      .addRepeatedDouble(123e15)
-      .addRepeatedDouble(-1.23e-17)
-      .addRepeatedDouble(.23e17)
-      .addRepeatedDouble(-23e15)
-      .addRepeatedDouble(123.5e20)
-      .addRepeatedDouble(123.5e-20)
-      .addRepeatedDouble(123.456789)
-      .addRepeatedDouble(Double.POSITIVE_INFINITY)
-      .addRepeatedDouble(Double.NEGATIVE_INFINITY)
-      .addRepeatedDouble(Double.NaN)
-
-      // Strings and bytes that needing escaping.
-      .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234")
-      .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
-      .build();
-
-    assertEquals(canonicalExoticText, message.toString());
-  }
-
-  public void testPrintMessageSet() throws Exception {
-    TestMessageSet messageSet =
-      TestMessageSet.newBuilder()
-        .setExtension(
-          TestMessageSetExtension1.messageSetExtension,
-          TestMessageSetExtension1.newBuilder().setI(123).build())
-        .setExtension(
-          TestMessageSetExtension2.messageSetExtension,
-          TestMessageSetExtension2.newBuilder().setStr("foo").build())
-        .build();
-
-    assertEquals(messageSetText, messageSet.toString());
-  }
-
-  // =================================================================
-
-  public void testParse() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge(allFieldsSetText, builder);
-    TestUtil.assertAllFieldsSet(builder.build());
-  }
-
-  public void testParseReader() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge(new StringReader(allFieldsSetText), builder);
-    TestUtil.assertAllFieldsSet(builder.build());
-  }
-
-  public void testParseExtensions() throws Exception {
-    TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
-    TextFormat.merge(allExtensionsSetText,
-                     TestUtil.getExtensionRegistry(),
-                     builder);
-    TestUtil.assertAllExtensionsSet(builder.build());
-  }
-
-  public void testParseCompatibility() throws Exception {
-    String original = "repeated_float: inf\n" +
-                      "repeated_float: -inf\n" +
-                      "repeated_float: nan\n" +
-                      "repeated_float: inff\n" +
-                      "repeated_float: -inff\n" +
-                      "repeated_float: nanf\n" +
-                      "repeated_float: 1.0f\n" +
-                      "repeated_float: infinityf\n" +
-                      "repeated_float: -Infinityf\n" +
-                      "repeated_double: infinity\n" +
-                      "repeated_double: -infinity\n" +
-                      "repeated_double: nan\n";
-    String canonical =  "repeated_float: Infinity\n" +
-                        "repeated_float: -Infinity\n" +
-                        "repeated_float: NaN\n" +
-                        "repeated_float: Infinity\n" +
-                        "repeated_float: -Infinity\n" +
-                        "repeated_float: NaN\n" +
-                        "repeated_float: 1.0\n" +
-                        "repeated_float: Infinity\n" +
-                        "repeated_float: -Infinity\n" +
-                        "repeated_double: Infinity\n" +
-                        "repeated_double: -Infinity\n" +
-                        "repeated_double: NaN\n";
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge(original, builder);
-    assertEquals(canonical, builder.build().toString());
-  }
-
-  public void testParseExotic() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge(exoticText, builder);
-
-    // Too lazy to check things individually.  Don't try to debug this
-    // if testPrintExotic() is failing.
-    assertEquals(canonicalExoticText, builder.build().toString());
-  }
-
-  public void testParseMessageSet() throws Exception {
-    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
-    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
-    extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
-
-    TestMessageSet.Builder builder = TestMessageSet.newBuilder();
-    TextFormat.merge(messageSetText, extensionRegistry, builder);
-    TestMessageSet messageSet = builder.build();
-
-    assertTrue(messageSet.hasExtension(
-      TestMessageSetExtension1.messageSetExtension));
-    assertEquals(123, messageSet.getExtension(
-      TestMessageSetExtension1.messageSetExtension).getI());
-    assertTrue(messageSet.hasExtension(
-      TestMessageSetExtension2.messageSetExtension));
-    assertEquals("foo", messageSet.getExtension(
-      TestMessageSetExtension2.messageSetExtension).getStr());
-  }
-
-  public void testParseNumericEnum() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge("optional_nested_enum: 2", builder);
-    assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum());
-  }
-
-  public void testParseAngleBrackets() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge("OptionalGroup: < a: 1 >", builder);
-    assertTrue(builder.hasOptionalGroup());
-    assertEquals(1, builder.getOptionalGroup().getA());
-  }
-
-  public void testParseComment() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge(
-      "# this is a comment\n" +
-      "optional_int32: 1  # another comment\n" +
-      "optional_int64: 2\n" +
-      "# EOF comment", builder);
-    assertEquals(1, builder.getOptionalInt32());
-    assertEquals(2, builder.getOptionalInt64());
-  }
-
-  // =================================================================
-
-  public void testParseString() throws Exception {
-    final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge("optional_string: \"" + zh + "\"", builder);
-    assertEquals(zh, builder.getOptionalString());
-  }
-
-  public void testParseLongString() throws Exception {
-    String longText =
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890" +
-      "123456789012345678901234567890123456789012345678901234567890";
-
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge("optional_string: \"" + longText + "\"", builder);
-    assertEquals(longText, builder.getOptionalString());
-  }
-
-  public void testParseBoolean() throws Exception {
-    String goodText =
-        "repeated_bool: t  repeated_bool : 0\n" +
-        "repeated_bool :f repeated_bool:1";
-    String goodTextCanonical =
-        "repeated_bool: true\n" +
-        "repeated_bool: false\n" +
-        "repeated_bool: false\n" +
-        "repeated_bool: true\n";
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge(goodText, builder);
-    assertEquals(goodTextCanonical, builder.build().toString());
-
-    try {
-      TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
-      TextFormat.merge("optional_bool:2", badBuilder);
-      fail("Should have thrown an exception.");
-    } catch (TextFormat.ParseException e) {
-      // success
-    }
-    try {
-      TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
-      TextFormat.merge("optional_bool: foo", badBuilder);
-      fail("Should have thrown an exception.");
-    } catch (TextFormat.ParseException e) {
-      // success
-    }
-  }
-
-  public void testParseAdjacentStringLiterals() throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder);
-    assertEquals("foocorgegrault", builder.getOptionalString());
-  }
-
-  public void testPrintFieldValue() throws Exception {
-    assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string");
-    assertPrintFieldValue("123.0",  123f, "repeated_float");
-    assertPrintFieldValue("123.0",  123d, "repeated_double");
-    assertPrintFieldValue("123",  123, "repeated_int32");
-    assertPrintFieldValue("123",  123L, "repeated_int64");
-    assertPrintFieldValue("true",  true, "repeated_bool");
-    assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32");
-    assertPrintFieldValue("18446744073709551615",  0xFFFFFFFFFFFFFFFFL,
-        "repeated_uint64");
-    assertPrintFieldValue("\"\\001\\002\\003\"",
-        ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes");
-  }
-
-  private void assertPrintFieldValue(String expect, Object value,
-      String fieldName) throws Exception {
-    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
-    StringBuilder sb = new StringBuilder();
-    TextFormat.printFieldValue(
-        TestAllTypes.getDescriptor().findFieldByName(fieldName),
-        value, sb);
-    assertEquals(expect, sb.toString());
-  }
-
-  public void testShortDebugString() {
-    assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1"
-        + " repeated_uint32: 2",
-        TextFormat.shortDebugString(TestAllTypes.newBuilder()
-            .addRepeatedInt32(1)
-            .addRepeatedUint32(2)
-            .setOptionalNestedMessage(
-                NestedMessage.newBuilder().setBb(42).build())
-            .build()));
-  }
-
-  public void testShortDebugString_unknown() {
-    assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
-        + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
-        + " 0xabcdef1234567890",
-        TextFormat.shortDebugString(makeUnknownFieldSet()));
-  }
-
-  public void testPrintToUnicodeString() {
-    assertEquals(
-        "optional_string: \"abc\u3042efg\"\n" +
-        "optional_bytes: \"\\343\\201\\202\"\n" +
-        "repeated_string: \"\u3093XYZ\"\n",
-        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
-            .setOptionalString("abc\u3042efg")
-            .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
-            .addRepeatedString("\u3093XYZ")
-            .build()));
-  }
-
-  public void testPrintToUnicodeString_unknown() {
-    assertEquals(
-        "1: \"\\343\\201\\202\"\n",
-        TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
-            .addField(1,
-                UnknownFieldSet.Field.newBuilder()
-                .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
-            .build()));
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnknownFieldSetTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnknownFieldSetTest.java
deleted file mode 100644
index b9bfb69..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnknownFieldSetTest.java
+++ /dev/null
@@ -1,438 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestEmptyMessage;
-import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions;
-
-import junit.framework.TestCase;
-
-import java.util.Arrays;
-import java.util.Map;
-
-/**
- * Tests related to unknown field handling.
- *
- * @author kenton@google.com (Kenton Varda)
- */
-public class UnknownFieldSetTest extends TestCase {
-  public void setUp() throws Exception {
-    descriptor = TestAllTypes.getDescriptor();
-    allFields = TestUtil.getAllSet();
-    allFieldsData = allFields.toByteString();
-    emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
-    unknownFields = emptyMessage.getUnknownFields();
-  }
-
-  UnknownFieldSet.Field getField(String name) {
-    Descriptors.FieldDescriptor field = descriptor.findFieldByName(name);
-    assertNotNull(field);
-    return unknownFields.getField(field.getNumber());
-  }
-
-  // Constructs a protocol buffer which contains fields with all the same
-  // numbers as allFieldsData except that each field is some other wire
-  // type.
-  ByteString getBizarroData() throws Exception {
-    UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.newBuilder();
-
-    UnknownFieldSet.Field varintField =
-      UnknownFieldSet.Field.newBuilder().addVarint(1).build();
-    UnknownFieldSet.Field fixed32Field =
-      UnknownFieldSet.Field.newBuilder().addFixed32(1).build();
-
-    for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
-         unknownFields.asMap().entrySet()) {
-      if (entry.getValue().getVarintList().isEmpty()) {
-        // Original field is not a varint, so use a varint.
-        bizarroFields.addField(entry.getKey(), varintField);
-      } else {
-        // Original field *is* a varint, so use something else.
-        bizarroFields.addField(entry.getKey(), fixed32Field);
-      }
-    }
-
-    return bizarroFields.build().toByteString();
-  }
-
-  Descriptors.Descriptor descriptor;
-  TestAllTypes allFields;
-  ByteString allFieldsData;
-
-  // An empty message that has been parsed from allFieldsData.  So, it has
-  // unknown fields of every type.
-  TestEmptyMessage emptyMessage;
-  UnknownFieldSet unknownFields;
-
-  // =================================================================
-
-  public void testVarint() throws Exception {
-    UnknownFieldSet.Field field = getField("optional_int32");
-    assertEquals(1, field.getVarintList().size());
-    assertEquals(allFields.getOptionalInt32(),
-                 (long) field.getVarintList().get(0));
-  }
-
-  public void testFixed32() throws Exception {
-    UnknownFieldSet.Field field = getField("optional_fixed32");
-    assertEquals(1, field.getFixed32List().size());
-    assertEquals(allFields.getOptionalFixed32(),
-                 (int) field.getFixed32List().get(0));
-  }
-
-  public void testFixed64() throws Exception {
-    UnknownFieldSet.Field field = getField("optional_fixed64");
-    assertEquals(1, field.getFixed64List().size());
-    assertEquals(allFields.getOptionalFixed64(),
-                 (long) field.getFixed64List().get(0));
-  }
-
-  public void testLengthDelimited() throws Exception {
-    UnknownFieldSet.Field field = getField("optional_bytes");
-    assertEquals(1, field.getLengthDelimitedList().size());
-    assertEquals(allFields.getOptionalBytes(),
-                 field.getLengthDelimitedList().get(0));
-  }
-
-  public void testGroup() throws Exception {
-    Descriptors.FieldDescriptor nestedFieldDescriptor =
-      TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a");
-    assertNotNull(nestedFieldDescriptor);
-
-    UnknownFieldSet.Field field = getField("optionalgroup");
-    assertEquals(1, field.getGroupList().size());
-
-    UnknownFieldSet group = field.getGroupList().get(0);
-    assertEquals(1, group.asMap().size());
-    assertTrue(group.hasField(nestedFieldDescriptor.getNumber()));
-
-    UnknownFieldSet.Field nestedField =
-      group.getField(nestedFieldDescriptor.getNumber());
-    assertEquals(1, nestedField.getVarintList().size());
-    assertEquals(allFields.getOptionalGroup().getA(),
-                 (long) nestedField.getVarintList().get(0));
-  }
-
-  public void testSerialize() throws Exception {
-    // Check that serializing the UnknownFieldSet produces the original data
-    // again.
-    ByteString data = emptyMessage.toByteString();
-    assertEquals(allFieldsData, data);
-  }
-
-  public void testCopyFrom() throws Exception {
-    TestEmptyMessage message =
-      TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build();
-
-    assertEquals(emptyMessage.toString(), message.toString());
-  }
-
-  public void testMergeFrom() throws Exception {
-    TestEmptyMessage source =
-      TestEmptyMessage.newBuilder()
-        .setUnknownFields(
-          UnknownFieldSet.newBuilder()
-            .addField(2,
-              UnknownFieldSet.Field.newBuilder()
-                .addVarint(2).build())
-            .addField(3,
-              UnknownFieldSet.Field.newBuilder()
-                .addVarint(4).build())
-            .build())
-        .build();
-    TestEmptyMessage destination =
-      TestEmptyMessage.newBuilder()
-        .setUnknownFields(
-          UnknownFieldSet.newBuilder()
-            .addField(1,
-              UnknownFieldSet.Field.newBuilder()
-                .addVarint(1).build())
-            .addField(3,
-              UnknownFieldSet.Field.newBuilder()
-                .addVarint(3).build())
-            .build())
-        .mergeFrom(source)
-        .build();
-
-    assertEquals(
-      "1: 1\n" +
-      "2: 2\n" +
-      "3: 3\n" +
-      "3: 4\n",
-      destination.toString());
-  }
-
-  public void testClear() throws Exception {
-    UnknownFieldSet fields =
-      UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build();
-    assertTrue(fields.asMap().isEmpty());
-  }
-
-  public void testClearMessage() throws Exception {
-    TestEmptyMessage message =
-      TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build();
-    assertEquals(0, message.getSerializedSize());
-  }
-
-  public void testParseKnownAndUnknown() throws Exception {
-    // Test mixing known and unknown fields when parsing.
-
-    UnknownFieldSet fields =
-      UnknownFieldSet.newBuilder(unknownFields)
-        .addField(123456,
-          UnknownFieldSet.Field.newBuilder().addVarint(654321).build())
-        .build();
-
-    ByteString data = fields.toByteString();
-    TestAllTypes destination = TestAllTypes.parseFrom(data);
-
-    TestUtil.assertAllFieldsSet(destination);
-    assertEquals(1, destination.getUnknownFields().asMap().size());
-
-    UnknownFieldSet.Field field =
-      destination.getUnknownFields().getField(123456);
-    assertEquals(1, field.getVarintList().size());
-    assertEquals(654321, (long) field.getVarintList().get(0));
-  }
-
-  public void testWrongTypeTreatedAsUnknown() throws Exception {
-    // Test that fields of the wrong wire type are treated like unknown fields
-    // when parsing.
-
-    ByteString bizarroData = getBizarroData();
-    TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
-    TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
-
-    // All fields should have been interpreted as unknown, so the debug strings
-    // should be the same.
-    assertEquals(emptyMessage.toString(), allTypesMessage.toString());
-  }
-
-  public void testUnknownExtensions() throws Exception {
-    // Make sure fields are properly parsed to the UnknownFieldSet even when
-    // they are declared as extension numbers.
-
-    TestEmptyMessageWithExtensions message =
-      TestEmptyMessageWithExtensions.parseFrom(allFieldsData);
-
-    assertEquals(unknownFields.asMap().size(),
-                 message.getUnknownFields().asMap().size());
-    assertEquals(allFieldsData, message.toByteString());
-  }
-
-  public void testWrongExtensionTypeTreatedAsUnknown() throws Exception {
-    // Test that fields of the wrong wire type are treated like unknown fields
-    // when parsing extensions.
-
-    ByteString bizarroData = getBizarroData();
-    TestAllExtensions allExtensionsMessage =
-      TestAllExtensions.parseFrom(bizarroData);
-    TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
-
-    // All fields should have been interpreted as unknown, so the debug strings
-    // should be the same.
-    assertEquals(emptyMessage.toString(),
-                 allExtensionsMessage.toString());
-  }
-
-  public void testParseUnknownEnumValue() throws Exception {
-    Descriptors.FieldDescriptor singularField =
-      TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
-    Descriptors.FieldDescriptor repeatedField =
-      TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
-    assertNotNull(singularField);
-    assertNotNull(repeatedField);
-
-    ByteString data =
-      UnknownFieldSet.newBuilder()
-        .addField(singularField.getNumber(),
-          UnknownFieldSet.Field.newBuilder()
-            .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
-            .addVarint(5)   // not valid
-            .build())
-        .addField(repeatedField.getNumber(),
-          UnknownFieldSet.Field.newBuilder()
-            .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
-            .addVarint(4)   // not valid
-            .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
-            .addVarint(6)   // not valid
-            .build())
-        .build()
-        .toByteString();
-
-    {
-      TestAllTypes message = TestAllTypes.parseFrom(data);
-      assertEquals(TestAllTypes.NestedEnum.BAR,
-                   message.getOptionalNestedEnum());
-      assertEquals(
-        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
-        message.getRepeatedNestedEnumList());
-      assertEquals(Arrays.asList(5L),
-                   message.getUnknownFields()
-                          .getField(singularField.getNumber())
-                          .getVarintList());
-      assertEquals(Arrays.asList(4L, 6L),
-                   message.getUnknownFields()
-                          .getField(repeatedField.getNumber())
-                          .getVarintList());
-    }
-
-    {
-      TestAllExtensions message =
-        TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
-      assertEquals(TestAllTypes.NestedEnum.BAR,
-        message.getExtension(UnittestProto.optionalNestedEnumExtension));
-      assertEquals(
-        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
-        message.getExtension(UnittestProto.repeatedNestedEnumExtension));
-      assertEquals(Arrays.asList(5L),
-                   message.getUnknownFields()
-                          .getField(singularField.getNumber())
-                          .getVarintList());
-      assertEquals(Arrays.asList(4L, 6L),
-                   message.getUnknownFields()
-                          .getField(repeatedField.getNumber())
-                          .getVarintList());
-    }
-  }
-
-  public void testLargeVarint() throws Exception {
-    ByteString data =
-      UnknownFieldSet.newBuilder()
-        .addField(1,
-          UnknownFieldSet.Field.newBuilder()
-            .addVarint(0x7FFFFFFFFFFFFFFFL)
-            .build())
-        .build()
-        .toByteString();
-    UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data);
-    UnknownFieldSet.Field field = parsed.getField(1);
-    assertEquals(1, field.getVarintList().size());
-    assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0));
-  }
-
-  public void testEqualsAndHashCode() {
-    UnknownFieldSet.Field fixed32Field =
-        UnknownFieldSet.Field.newBuilder()
-            .addFixed32(1)
-            .build();
-    UnknownFieldSet.Field fixed64Field =
-        UnknownFieldSet.Field.newBuilder()
-            .addFixed64(1)
-            .build();
-    UnknownFieldSet.Field varIntField =
-        UnknownFieldSet.Field.newBuilder()
-            .addVarint(1)
-            .build();
-    UnknownFieldSet.Field lengthDelimitedField =
-        UnknownFieldSet.Field.newBuilder()
-            .addLengthDelimited(ByteString.EMPTY)
-            .build();
-    UnknownFieldSet.Field groupField =
-        UnknownFieldSet.Field.newBuilder()
-            .addGroup(unknownFields)
-            .build();
-
-    UnknownFieldSet a =
-        UnknownFieldSet.newBuilder()
-            .addField(1, fixed32Field)
-            .build();
-    UnknownFieldSet b =
-        UnknownFieldSet.newBuilder()
-            .addField(1, fixed64Field)
-            .build();
-    UnknownFieldSet c =
-        UnknownFieldSet.newBuilder()
-            .addField(1, varIntField)
-            .build();
-    UnknownFieldSet d =
-        UnknownFieldSet.newBuilder()
-            .addField(1, lengthDelimitedField)
-            .build();
-    UnknownFieldSet e =
-        UnknownFieldSet.newBuilder()
-            .addField(1, groupField)
-            .build();
-
-    checkEqualsIsConsistent(a);
-    checkEqualsIsConsistent(b);
-    checkEqualsIsConsistent(c);
-    checkEqualsIsConsistent(d);
-    checkEqualsIsConsistent(e);
-
-    checkNotEqual(a, b);
-    checkNotEqual(a, c);
-    checkNotEqual(a, d);
-    checkNotEqual(a, e);
-    checkNotEqual(b, c);
-    checkNotEqual(b, d);
-    checkNotEqual(b, e);
-    checkNotEqual(c, d);
-    checkNotEqual(c, e);
-    checkNotEqual(d, e);
-  }
-
-  /**
-   * Asserts that the given field sets are not equal and have different
-   * hash codes.
-   *
-   * @warning It's valid for non-equal objects to have the same hash code, so
-   *   this test is stricter than it needs to be. However, this should happen
-   *   relatively rarely.
-   */
-  private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
-    String equalsError = String.format("%s should not be equal to %s", s1, s2);
-    assertFalse(equalsError, s1.equals(s2));
-    assertFalse(equalsError, s2.equals(s1));
-
-    assertFalse(
-        String.format("%s should have a different hash code from %s", s1, s2),
-        s1.hashCode() == s2.hashCode());
-  }
-
-  /**
-   * Asserts that the given field sets are equal and have identical hash codes.
-   */
-  private void checkEqualsIsConsistent(UnknownFieldSet set) {
-    // Object should be equal to itself.
-    assertEquals(set, set);
-
-    // Object should be equal to a copy of itself.
-    UnknownFieldSet copy = UnknownFieldSet.newBuilder(set).build();
-    assertEquals(set, copy);
-    assertEquals(copy, set);
-    assertEquals(set.hashCode(), copy.hashCode());
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnmodifiableLazyStringListTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnmodifiableLazyStringListTest.java
deleted file mode 100644
index cb75d74..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnmodifiableLazyStringListTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import junit.framework.TestCase;
-
-import java.util.Iterator;
-import java.util.ListIterator;
-
-/**
- * Tests for {@link UnmodifiableLazyStringList}.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class UnmodifiableLazyStringListTest extends TestCase {
-
-  private static String STRING_A = "A";
-  private static String STRING_B = "B";
-  private static String STRING_C = "C";
-
-  private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
-  private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
-  private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
-
-  public void testReadOnlyMethods() {
-    LazyStringArrayList rawList = createSampleList();
-    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
-    assertEquals(3, list.size());
-    assertSame(STRING_A, list.get(0));
-    assertSame(STRING_B, list.get(1));
-    assertSame(STRING_C, list.get(2));
-    assertEquals(BYTE_STRING_A, list.getByteString(0));
-    assertEquals(BYTE_STRING_B, list.getByteString(1));
-    assertEquals(BYTE_STRING_C, list.getByteString(2));
-  }
-
-  public void testModifyMethods() {
-    LazyStringArrayList rawList = createSampleList();
-    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
-
-    try {
-      list.remove(0);
-      fail();
-    } catch (UnsupportedOperationException e) {
-      // expected
-    }
-    assertEquals(3, list.size());
-
-    try {
-      list.add(STRING_B);
-      fail();
-    } catch (UnsupportedOperationException e) {
-      // expected
-    }
-    assertEquals(3, list.size());
-
-    try {
-      list.set(1, STRING_B);
-      fail();
-    } catch (UnsupportedOperationException e) {
-      // expected
-    }
-  }
-
-  public void testIterator() {
-    LazyStringArrayList rawList = createSampleList();
-    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
-
-    Iterator<String> iter = list.iterator();
-    int count = 0;
-    while (iter.hasNext()) {
-      iter.next();
-      count++;
-      try {
-        iter.remove();
-        fail();
-      } catch (UnsupportedOperationException e) {
-        // expected
-      }
-    }
-    assertEquals(3, count);
-
-  }
-
-  public void testListIterator() {
-    LazyStringArrayList rawList = createSampleList();
-    UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
-
-    ListIterator<String> iter = list.listIterator();
-    int count = 0;
-    while (iter.hasNext()) {
-      iter.next();
-      count++;
-      try {
-        iter.remove();
-        fail();
-      } catch (UnsupportedOperationException e) {
-        // expected
-      }
-      try {
-        iter.set("bar");
-        fail();
-      } catch (UnsupportedOperationException e) {
-        // expected
-      }
-      try {
-        iter.add("bar");
-        fail();
-      } catch (UnsupportedOperationException e) {
-        // expected
-      }
-    }
-    assertEquals(3, count);
-
-  }
-
-  private LazyStringArrayList createSampleList() {
-    LazyStringArrayList rawList = new LazyStringArrayList();
-    rawList.add(STRING_A);
-    rawList.add(STRING_B);
-    rawList.add(STRING_C);
-    return rawList;
-  }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/WireFormatTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/WireFormatTest.java
deleted file mode 100644
index 7452872..0000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/WireFormatTest.java
+++ /dev/null
@@ -1,465 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.util.List;
-
-import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.TestAllExtensions;
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestFieldOrderings;
-import protobuf_unittest.UnittestProto.TestPackedExtensions;
-import protobuf_unittest.UnittestProto.TestPackedTypes;
-import protobuf_unittest.UnittestMset.TestMessageSet;
-import protobuf_unittest.UnittestMset.RawMessageSet;
-import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
-import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
-
-/**
- * Tests related to parsing and serialization.
- *
- * @author kenton@google.com (Kenton Varda)
- */
-public class WireFormatTest extends TestCase {
-  public void testSerialization() throws Exception {
-    TestAllTypes message = TestUtil.getAllSet();
-
-    ByteString rawBytes = message.toByteString();
-    assertEquals(rawBytes.size(), message.getSerializedSize());
-
-    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
-
-    TestUtil.assertAllFieldsSet(message2);
-  }
-
-  public void testSerializationPacked() throws Exception {
-    TestPackedTypes message = TestUtil.getPackedSet();
-
-    ByteString rawBytes = message.toByteString();
-    assertEquals(rawBytes.size(), message.getSerializedSize());
-
-    TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
-
-    TestUtil.assertPackedFieldsSet(message2);
-  }
-
-  public void testSerializeExtensions() throws Exception {
-    // TestAllTypes and TestAllExtensions should have compatible wire formats,
-    // so if we serialize a TestAllExtensions then parse it as TestAllTypes
-    // it should work.
-
-    TestAllExtensions message = TestUtil.getAllExtensionsSet();
-    ByteString rawBytes = message.toByteString();
-    assertEquals(rawBytes.size(), message.getSerializedSize());
-
-    TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
-
-    TestUtil.assertAllFieldsSet(message2);
-  }
-
-  public void testSerializePackedExtensions() throws Exception {
-    // TestPackedTypes and TestPackedExtensions should have compatible wire
-    // formats; check that they serialize to the same string.
-    TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
-    ByteString rawBytes = message.toByteString();
-
-    TestPackedTypes message2 = TestUtil.getPackedSet();
-    ByteString rawBytes2 = message2.toByteString();
-
-    assertEquals(rawBytes, rawBytes2);
-  }
-
-  public void testSerializationPackedWithoutGetSerializedSize()
-      throws Exception {
-    // Write directly to an OutputStream, without invoking getSerializedSize()
-    // This used to be a bug where the size of a packed field was incorrect,
-    // since getSerializedSize() was never invoked.
-    TestPackedTypes message = TestUtil.getPackedSet();
-
-    // Directly construct a CodedOutputStream around the actual OutputStream,
-    // in case writeTo(OutputStream output) invokes getSerializedSize();
-    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-    CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
-
-    message.writeTo(codedOutput);
-
-    codedOutput.flush();
-
-    TestPackedTypes message2 = TestPackedTypes.parseFrom(
-        outputStream.toByteArray());
-
-    TestUtil.assertPackedFieldsSet(message2);
-  }
-
-  public void testParseExtensions() throws Exception {
-    // TestAllTypes and TestAllExtensions should have compatible wire formats,
-    // so if we serialize a TestAllTypes then parse it as TestAllExtensions
-    // it should work.
-
-    TestAllTypes message = TestUtil.getAllSet();
-    ByteString rawBytes = message.toByteString();
-
-    ExtensionRegistry registry = TestUtil.getExtensionRegistry();
-
-    TestAllExtensions message2 =
-      TestAllExtensions.parseFrom(rawBytes, registry);
-
-    TestUtil.assertAllExtensionsSet(message2);
-  }
-
-  public void testParsePackedExtensions() throws Exception {
-    // Ensure that packed extensions can be properly parsed.
-    TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
-    ByteString rawBytes = message.toByteString();
-
-    ExtensionRegistry registry = TestUtil.getExtensionRegistry();
-
-    TestPackedExtensions message2 =
-        TestPackedExtensions.parseFrom(rawBytes, registry);
-
-    TestUtil.assertPackedExtensionsSet(message2);
-  }
-
-  public void testExtensionsSerializedSize() throws Exception {
-    assertEquals(TestUtil.getAllSet().getSerializedSize(),
-                 TestUtil.getAllExtensionsSet().getSerializedSize());
-  }
-
-  public void testSerializeDelimited() throws Exception {
-    ByteArrayOutputStream output = new ByteArrayOutputStream();
-    TestUtil.getAllSet().writeDelimitedTo(output);
-    output.write(12);
-    TestUtil.getPackedSet().writeDelimitedTo(output);
-    output.write(34);
-
-    ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
-
-    TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
-    assertEquals(12, input.read());
-    TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
-    assertEquals(34, input.read());
-    assertEquals(-1, input.read());
-
-    // We're at EOF, so parsing again should return null.
-    assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
-  }
-
-  private void assertFieldsInOrder(ByteString data) throws Exception {
-    CodedInputStream input = data.newCodedInput();
-    int previousTag = 0;
-
-    while (true) {
-      int tag = input.readTag();
-      if (tag == 0) {
-        break;
-      }
-
-      assertTrue(tag > previousTag);
-      previousTag = tag;
-      input.skipField(tag);
-    }
-  }
-
-  public void testInterleavedFieldsAndExtensions() throws Exception {
-    // Tests that fields are written in order even when extension ranges
-    // are interleaved with field numbers.
-    ByteString data =
-      TestFieldOrderings.newBuilder()
-        .setMyInt(1)
-        .setMyString("foo")
-        .setMyFloat(1.0F)
-        .setExtension(UnittestProto.myExtensionInt, 23)
-        .setExtension(UnittestProto.myExtensionString, "bar")
-        .build().toByteString();
-    assertFieldsInOrder(data);
-
-    Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
-    ByteString dynamic_data =
-      DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
-        .setField(descriptor.findFieldByName("my_int"), 1L)
-        .setField(descriptor.findFieldByName("my_string"), "foo")
-        .setField(descriptor.findFieldByName("my_float"), 1.0F)
-        .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
-        .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
-        .build().toByteString();
-    assertFieldsInOrder(dynamic_data);
-  }
-
-  private ExtensionRegistry getTestFieldOrderingsRegistry() {
-    ExtensionRegistry result = ExtensionRegistry.newInstance();
-    result.add(UnittestProto.myExtensionInt);
-    result.add(UnittestProto.myExtensionString);
-    return result;
-  }
-
-  public void testParseMultipleExtensionRanges() throws Exception {
-    // Make sure we can parse a message that contains multiple extensions
-    // ranges.
-    TestFieldOrderings source =
-      TestFieldOrderings.newBuilder()
-        .setMyInt(1)
-        .setMyString("foo")
-        .setMyFloat(1.0F)
-        .setExtension(UnittestProto.myExtensionInt, 23)
-        .setExtension(UnittestProto.myExtensionString, "bar")
-        .build();
-    TestFieldOrderings dest =
-      TestFieldOrderings.parseFrom(source.toByteString(),
-                                   getTestFieldOrderingsRegistry());
-    assertEquals(source, dest);
-  }
-
-  public void testParseMultipleExtensionRangesDynamic() throws Exception {
-    // Same as above except with DynamicMessage.
-    Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
-    DynamicMessage source =
-      DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
-        .setField(descriptor.findFieldByName("my_int"), 1L)
-        .setField(descriptor.findFieldByName("my_string"), "foo")
-        .setField(descriptor.findFieldByName("my_float"), 1.0F)
-        .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
-        .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
-        .build();
-    DynamicMessage dest =
-      DynamicMessage.parseFrom(descriptor, source.toByteString(),
-                               getTestFieldOrderingsRegistry());
-    assertEquals(source, dest);
-  }
-
-  private static final int UNKNOWN_TYPE_ID = 1550055;
-  private static final int TYPE_ID_1 =
-    TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
-  private static final int TYPE_ID_2 =
-    TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
-
-  public void testSerializeMessageSetEagerly() throws Exception {
-    testSerializeMessageSetWithFlag(true);
-  }
-
-  public void testSerializeMessageSetNotEagerly() throws Exception {
-    testSerializeMessageSetWithFlag(false);
-  }
-
-  private void testSerializeMessageSetWithFlag(boolean eagerParsing)
-      throws Exception {
-    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
-    // Set up a TestMessageSet with two known messages and an unknown one.
-    TestMessageSet messageSet =
-      TestMessageSet.newBuilder()
-        .setExtension(
-          TestMessageSetExtension1.messageSetExtension,
-          TestMessageSetExtension1.newBuilder().setI(123).build())
-        .setExtension(
-          TestMessageSetExtension2.messageSetExtension,
-          TestMessageSetExtension2.newBuilder().setStr("foo").build())
-        .setUnknownFields(
-          UnknownFieldSet.newBuilder()
-            .addField(UNKNOWN_TYPE_ID,
-              UnknownFieldSet.Field.newBuilder()
-                .addLengthDelimited(ByteString.copyFromUtf8("bar"))
-                .build())
-            .build())
-        .build();
-
-    ByteString data = messageSet.toByteString();
-
-    // Parse back using RawMessageSet and check the contents.
-    RawMessageSet raw = RawMessageSet.parseFrom(data);
-
-    assertTrue(raw.getUnknownFields().asMap().isEmpty());
-
-    assertEquals(3, raw.getItemCount());
-    assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
-    assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
-    assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
-
-    TestMessageSetExtension1 message1 =
-      TestMessageSetExtension1.parseFrom(
-        raw.getItem(0).getMessage().toByteArray());
-    assertEquals(123, message1.getI());
-
-    TestMessageSetExtension2 message2 =
-      TestMessageSetExtension2.parseFrom(
-        raw.getItem(1).getMessage().toByteArray());
-    assertEquals("foo", message2.getStr());
-
-    assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
-  }
-
-  public void testParseMessageSetEagerly() throws Exception {
-    testParseMessageSetWithFlag(true);
-  }
-
-  public void testParseMessageSetNotEagerly()throws Exception {
-    testParseMessageSetWithFlag(false);
-  }
-
-  private void testParseMessageSetWithFlag(boolean eagerParsing)
-      throws Exception {
-    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
-    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
-    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
-    extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
-
-    // Set up a RawMessageSet with two known messages and an unknown one.
-    RawMessageSet raw =
-      RawMessageSet.newBuilder()
-        .addItem(
-          RawMessageSet.Item.newBuilder()
-            .setTypeId(TYPE_ID_1)
-            .setMessage(
-              TestMessageSetExtension1.newBuilder()
-                .setI(123)
-                .build().toByteString())
-            .build())
-        .addItem(
-          RawMessageSet.Item.newBuilder()
-            .setTypeId(TYPE_ID_2)
-            .setMessage(
-              TestMessageSetExtension2.newBuilder()
-                .setStr("foo")
-                .build().toByteString())
-            .build())
-        .addItem(
-          RawMessageSet.Item.newBuilder()
-            .setTypeId(UNKNOWN_TYPE_ID)
-            .setMessage(ByteString.copyFromUtf8("bar"))
-            .build())
-        .build();
-
-    ByteString data = raw.toByteString();
-
-    // Parse as a TestMessageSet and check the contents.
-    TestMessageSet messageSet =
-      TestMessageSet.parseFrom(data, extensionRegistry);
-
-    assertEquals(123, messageSet.getExtension(
-      TestMessageSetExtension1.messageSetExtension).getI());
-    assertEquals("foo", messageSet.getExtension(
-      TestMessageSetExtension2.messageSetExtension).getStr());
-
-    // Check for unknown field with type LENGTH_DELIMITED,
-    //   number UNKNOWN_TYPE_ID, and contents "bar".
-    UnknownFieldSet unknownFields = messageSet.getUnknownFields();
-    assertEquals(1, unknownFields.asMap().size());
-    assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
-
-    UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
-    assertEquals(1, field.getLengthDelimitedList().size());
-    assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
-  }
-
-  public void testParseMessageSetExtensionEagerly() throws Exception {
-    testParseMessageSetExtensionWithFlag(true);
-  }
-
-  public void testParseMessageSetExtensionNotEagerly() throws Exception {
-    testParseMessageSetExtensionWithFlag(false);
-  }
-
-  private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
-      throws Exception {
-    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
-    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
-    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
-
-    // Set up a RawMessageSet with a known messages.
-    int TYPE_ID_1 =
-        TestMessageSetExtension1
-            .getDescriptor().getExtensions().get(0).getNumber();
-    RawMessageSet raw =
-      RawMessageSet.newBuilder()
-        .addItem(
-          RawMessageSet.Item.newBuilder()
-            .setTypeId(TYPE_ID_1)
-            .setMessage(
-              TestMessageSetExtension1.newBuilder()
-                .setI(123)
-                .build().toByteString())
-            .build())
-        .build();
-
-    ByteString data = raw.toByteString();
-
-    // Parse as a TestMessageSet and check the contents.
-    TestMessageSet messageSet =
-        TestMessageSet.parseFrom(data, extensionRegistry);
-    assertEquals(123, messageSet.getExtension(
-        TestMessageSetExtension1.messageSetExtension).getI());
-  }
-
-  public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
-    testMergeLazyMessageSetExtensionWithFlag(true);
-  }
-
-  public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
-    testMergeLazyMessageSetExtensionWithFlag(false);
-  }
-
-  private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
-      throws Exception {
-    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
-    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
-    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
-
-    // Set up a RawMessageSet with a known messages.
-    int TYPE_ID_1 =
-        TestMessageSetExtension1
-            .getDescriptor().getExtensions().get(0).getNumber();
-    RawMessageSet raw =
-      RawMessageSet.newBuilder()
-        .addItem(
-          RawMessageSet.Item.newBuilder()
-            .setTypeId(TYPE_ID_1)
-            .setMessage(
-              TestMessageSetExtension1.newBuilder()
-                .setI(123)
-                .build().toByteString())
-            .build())
-        .build();
-
-    ByteString data = raw.toByteString();
-
-    // Parse as a TestMessageSet and store value into lazy field
-    TestMessageSet messageSet =
-        TestMessageSet.parseFrom(data, extensionRegistry);
-    // Merge lazy field check the contents.
-    messageSet =
-        messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
-    assertEquals(123, messageSet.getExtension(
-        TestMessageSetExtension1.messageSetExtension).getI());
-  }
-}
diff --git a/java/core/BUILD b/java/core/BUILD
index 5f4a7ab..6fa1084 100644
--- a/java/core/BUILD
+++ b/java/core/BUILD
@@ -1,5 +1,10 @@
-load("@rules_java//java:defs.bzl", "java_library")
-load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain")
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+load("@rules_java//java:defs.bzl", "java_library", "java_proto_library", "java_lite_proto_library")
+load("@rules_jvm_external//:defs.bzl", "java_export")
+load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library")
+load("//:internal.bzl", "conformance_test")
+load("//:protobuf_version.bzl", "PROTOBUF_VERSION")
+load("//java/internal:testing.bzl", "junit_tests")
 
 LITE_SRCS = [
     # Keep in sync with `//java/lite:pom.xml`.
@@ -85,32 +90,38 @@
     "src/main/java/com/google/protobuf/UnknownFieldSetLite.java",
     "src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java",
     "src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java",
+    "src/main/java/com/google/protobuf/UnsafeByteOperations.java",
     "src/main/java/com/google/protobuf/UnsafeUtil.java",
     "src/main/java/com/google/protobuf/Utf8.java",
     "src/main/java/com/google/protobuf/WireFormat.java",
     "src/main/java/com/google/protobuf/Writer.java",
 ]
 
-javacopts = select({
-    "//java:jdk9": ["--add-modules=jdk.unsupported"],
-    "//conditions:default": [
-        "-source 7",
-        "-target 7",
-    ],
-})
-
 # Should be used as `//java/lite`.
-java_library(
+java_export(
     name = "lite",
-    srcs = LITE_SRCS,
-    javacopts = javacopts,
+    maven_coordinates = "com.google.protobuf:protobuf-javalite:%s" % PROTOBUF_VERSION,
+    pom_template = "//java/lite:pom_template.xml",
+    srcs = LITE_SRCS + [
+        "//:gen_well_known_protos_javalite"
+    ],
     visibility = [
         "//java/lite:__pkg__",
     ],
+    resources = [
+        "//:lite_well_known_protos",
+    ],
 )
 
 java_library(
+    name = "lite_runtime_only",
+    srcs = LITE_SRCS,
+)
+
+java_export(
     name = "core",
+    maven_coordinates = "com.google.protobuf:protobuf-java:%s" % PROTOBUF_VERSION,
+    pom_template = "pom_template.xml",
     srcs = glob(
         [
             "src/main/java/com/google/protobuf/*.java",
@@ -119,14 +130,31 @@
     ) + [
         "//:gen_well_known_protos_java",
     ],
-    javacopts = javacopts,
     visibility = ["//visibility:public"],
     exports = [
-        "//java/lite",
+        ":lite_runtime_only",
     ],
     deps = [
-        "//java/lite",
+        ":lite_runtime_only",
     ],
+    resources = [
+        "//:well_known_protos",
+    ],
+)
+
+filegroup(
+    name = "release",
+    visibility = ["//java:__pkg__"],
+    srcs = [
+        ":core-pom",
+        ":core-maven-source",
+        ":core-docs",
+        ":core-project",
+        ":lite-pom",
+        ":lite-maven-source",
+        ":lite-docs",
+        ":lite-project",
+    ]
 )
 
 proto_lang_toolchain(
@@ -135,3 +163,192 @@
     runtime = ":core",
     visibility = ["//visibility:public"],
 )
+
+proto_library(
+    name = "java_test_protos",
+    srcs = glob(["src/test/proto/**/*.proto"]),
+    strip_import_prefix = "src/test/proto",
+    deps = [
+        "//:any_proto",
+        "//:descriptor_proto",
+        "//:generic_test_protos",
+        "//:wrappers_proto",
+    ],
+)
+
+java_proto_library(
+    name = "generic_test_protos_java_proto",
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    deps = ["//:generic_test_protos"],
+)
+
+java_proto_library(
+    name = "java_test_protos_java_proto",
+    deps = [":java_test_protos"],
+)
+
+java_library(
+    name = "test_util",
+    srcs = [
+        "src/test/java/com/google/protobuf/TestUtil.java",
+        "src/test/java/com/google/protobuf/TestUtilLite.java"
+    ],
+    deps = [
+        ":core",
+        ":generic_test_protos_java_proto",
+        ":java_test_protos_java_proto",
+        "//external:guava",
+        "//external:junit",
+    ],
+)
+
+test_suite(
+    name = "tests",
+    tests = [
+        "core_build_test",
+        "conformance_test",
+        "core_tests",
+    ],
+)
+
+build_test(
+    name = "core_build_test",
+    targets = [
+        ":core",
+    ],
+)
+
+conformance_test(
+    name = "conformance_test",
+    testee = "//:conformance_java",
+    failure_list = "//:conformance/failure_list_java.txt",
+    text_format_failure_list = "//:conformance/text_format_failure_list_java.txt",
+)
+
+junit_tests(
+    name = "core_tests",
+    srcs = glob(["src/test/java/**/*.java"], exclude = [
+        "src/test/java/com/google/protobuf/TestUtil.java",
+        "src/test/java/com/google/protobuf/TestUtilLite.java",
+    ]),
+    data = ["//:testdata"],
+    size = "large",
+    deps = [
+        ":core",
+        ":generic_test_protos_java_proto",
+        ":java_test_protos_java_proto",
+        ":test_util",
+        "//external:easymock",
+        "//external:easymock_classextension",
+        "//external:junit",
+        "//external:truth",
+    ]
+)
+
+java_lite_proto_library(
+    name = "generic_test_protos_java_proto_lite",
+    visibility = [
+        "//java/lite:__pkg__",
+    ],
+    deps = ["//:generic_test_protos"],
+)
+
+java_lite_proto_library(
+    name = "java_test_protos_java_proto_lite",
+    visibility = [
+        "//java/lite:__pkg__",
+    ],
+    deps = [":java_test_protos"],
+)
+
+genrule(
+    name = "rewrite_javalite_test_util",
+    srcs = [
+        "//java/lite:lite.awk",
+        "src/test/java/com/google/protobuf/TestUtil.java"
+    ],
+    outs = ["TestUtil.java"],
+    cmd = "awk -f $(location //java/lite:lite.awk) $(location src/test/java/com/google/protobuf/TestUtil.java) > $@"
+)
+
+java_library(
+    name = "test_util_lite",
+    srcs = [
+        ":rewrite_javalite_test_util",
+        "src/test/java/com/google/protobuf/TestUtilLite.java"
+    ],
+    visibility = [
+        "//java/lite:__pkg__",
+    ],
+    deps = [
+        ":generic_test_protos_java_proto_lite",
+        ":java_test_protos_java_proto_lite",
+        ":lite_runtime_only",
+        "//external:guava",
+        "//external:junit",
+    ],
+)
+
+LITE_TEST_EXCLUSIONS = [
+    # Keep in sync with //java/lite:pom.xml id=copy-test-source-files execution.
+    "src/test/java/com/google/protobuf/AbstractMessageTest.java",
+    "src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java",
+    "src/test/java/com/google/protobuf/AnyTest.java",
+    "src/test/java/com/google/protobuf/CodedInputStreamTest.java",
+    "src/test/java/com/google/protobuf/DeprecatedFieldTest.java",
+    "src/test/java/com/google/protobuf/DescriptorsTest.java",
+    "src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java",
+    "src/test/java/com/google/protobuf/DynamicMessageTest.java",
+    "src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java",
+    "src/test/java/com/google/protobuf/FieldPresenceTest.java",
+    "src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java",
+    "src/test/java/com/google/protobuf/GeneratedMessageTest.java",
+    "src/test/java/com/google/protobuf/LazyFieldTest.java",
+    "src/test/java/com/google/protobuf/LazyStringEndToEndTest.java",
+    "src/test/java/com/google/protobuf/MapForProto2Test.java",
+    "src/test/java/com/google/protobuf/MapTest.java",
+    "src/test/java/com/google/protobuf/MessageTest.java",
+    "src/test/java/com/google/protobuf/NestedBuildersTest.java",
+    "src/test/java/com/google/protobuf/PackedFieldTest.java",
+    "src/test/java/com/google/protobuf/ParserTest.java",
+    "src/test/java/com/google/protobuf/ParseExceptionsTest.java",
+    "src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java",
+    "src/test/java/com/google/protobuf/Proto2SchemaTest.java",
+    "src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java",
+    "src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java",
+    "src/test/java/com/google/protobuf/ServiceTest.java",
+    "src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java",
+    "src/test/java/com/google/protobuf/TestBadIdentifiers.java",
+    "src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java",
+    "src/test/java/com/google/protobuf/TextFormatParseLocationTest.java",
+    "src/test/java/com/google/protobuf/TextFormatTest.java",
+    "src/test/java/com/google/protobuf/TestUtil.java",
+    "src/test/java/com/google/protobuf/TestUtilLite.java",
+    "src/test/java/com/google/protobuf/TypeRegistryTest.java",
+    "src/test/java/com/google/protobuf/UnknownEnumValueTest.java",
+    "src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java",
+    "src/test/java/com/google/protobuf/UnknownFieldSetTest.java",
+    "src/test/java/com/google/protobuf/WellKnownTypesTest.java",
+    "src/test/java/com/google/protobuf/WireFormatTest.java",
+]
+
+junit_tests(
+    name = "lite_tests",
+    srcs = glob(["src/test/java/**/*.java"], exclude = LITE_TEST_EXCLUSIONS),
+    data = ["//:testdata"],
+    test_prefix = "Lite",
+    size = "large",
+    deps = [
+        ":lite",
+        ":generic_test_protos_java_proto_lite",
+        ":java_test_protos_java_proto_lite",
+        ":test_util_lite",
+        "//external:easymock",
+        "//external:easymock_classextension",
+        "//external:junit",
+        "//external:truth",
+    ]
+)
+
diff --git a/java/core/generate-test-sources-build.xml b/java/core/generate-test-sources-build.xml
index 92c0b1c..71a88d0 100644
--- a/java/core/generate-test-sources-build.xml
+++ b/java/core/generate-test-sources-build.xml
@@ -17,6 +17,7 @@
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3_optional.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/cached_field_size_test.proto"/>
diff --git a/java/core/pom.xml b/java/core/pom.xml
index 79a1e71..468ab48 100644
--- a/java/core/pom.xml
+++ b/java/core/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.11.4</version>
+    <version>3.17.3</version>
   </parent>
 
   <artifactId>protobuf-java</artifactId>
diff --git a/java/core/pom_template.xml b/java/core/pom_template.xml
new file mode 100644
index 0000000..2c61281
--- /dev/null
+++ b/java/core/pom_template.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>{groupId}</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>{version}</version>
+  </parent>
+
+  <artifactId>{artifactId}</artifactId>
+  <packaging>{type}</packaging>
+
+  <name>Protocol Buffers [Core]</name>
+  <description>
+    Core Protocol Buffers library. Protocol Buffers are a way of encoding structured data in an
+    efficient yet extensible format.
+  </description>
+</project>
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
index 3220f64..e792d7d 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
@@ -142,7 +142,12 @@
   @Override
   public boolean remove(Object o) {
     ensureIsMutable();
-    return super.remove(o);
+    int index = indexOf(o);
+    if (index == -1) {
+      return false;
+    }
+    remove(index);
+    return true;
   }
 
   @Override
diff --git a/java/core/src/main/java/com/google/protobuf/Android.java b/java/core/src/main/java/com/google/protobuf/Android.java
index cad5478..5a7ce9e 100644
--- a/java/core/src/main/java/com/google/protobuf/Android.java
+++ b/java/core/src/main/java/com/google/protobuf/Android.java
@@ -31,14 +31,21 @@
 package com.google.protobuf;
 
 final class Android {
+  private Android() {
+  }
+
+  // Set to true in lite_proguard_android.pgcfg.
+  @SuppressWarnings("ConstantField")
+  private static boolean ASSUME_ANDROID;
 
   private static final Class<?> MEMORY_CLASS = getClassForName("libcore.io.Memory");
+
   private static final boolean IS_ROBOLECTRIC =
-      getClassForName("org.robolectric.Robolectric") != null;
+      !ASSUME_ANDROID && getClassForName("org.robolectric.Robolectric") != null;
 
   /** Returns {@code true} if running on an Android device. */
   static boolean isOnAndroidDevice() {
-    return MEMORY_CLASS != null && !IS_ROBOLECTRIC;
+    return ASSUME_ANDROID || (MEMORY_CLASS != null && !IS_ROBOLECTRIC);
   }
 
   /** Returns the memory class or {@code null} if not on Android device. */
diff --git a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
index 1e33c5a..1217e11 100644
--- a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
+++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
@@ -39,7 +39,7 @@
  * Helper functions to decode protobuf wire format from a byte array.
  *
  * <p>Note that these functions don't do boundary check on the byte array but instead rely on Java
- * VM to check it. That means parsing rountines utilizing these functions must catch
+ * VM to check it. That means parsing routines utilizing these functions must catch
  * IndexOutOfBoundsException and convert it to protobuf's InvalidProtocolBufferException when
  * crossing protobuf public API boundaries.
  */
@@ -51,7 +51,7 @@
    * multiple values and let the function set the return value in this Registers instance instead.
    *
    * <p>TODO(xiaofeng): This could be merged into CodedInputStream or CodedInputStreamReader which
-   * is already being passed through all the parsing rountines.
+   * is already being passed through all the parsing routines.
    */
   static final class Registers {
     public int int1;
diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
index f023baa..451fce1 100644
--- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -268,20 +268,6 @@
   }
 
   @Override
-  public boolean remove(Object o) {
-    ensureIsMutable();
-    for (int i = 0; i < size; i++) {
-      if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i - 1);
-        size--;
-        modCount++;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
   public Boolean remove(int index) {
     ensureIsMutable();
     ensureIndexInRange(index);
diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java
index 17b7c98..74c9a71 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -1043,8 +1043,10 @@
     }
 
     /**
-     * Creates a byte string. Its size is the current size of this output stream and its output has
-     * been copied to it.
+     * Creates a byte string with the size and contents of this output stream. This does not create
+     * a new copy of the underlying bytes. If the stream size grows dynamically, the runtime is
+     * O(log n) in respect to the number of bytes written to the {@link Output}. If the stream size
+     * stays within the initial capacity, the runtime is O(1).
      *
      * @return the current contents of this output stream, as a byte string.
      */
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
index e20a885..1060c5a 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -41,6 +41,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -872,6 +873,9 @@
       builder.mergeFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
     }
 
@@ -888,6 +892,9 @@
       T result = parser.parsePartialFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
       return result;
     }
@@ -1184,6 +1191,9 @@
         throw InvalidProtocolBufferException.negativeSize();
       }
       byteLimit += getTotalBytesRead();
+      if (byteLimit < 0) {
+        throw InvalidProtocolBufferException.parseFailure();
+      }
       final int oldLimit = currentLimit;
       if (byteLimit > oldLimit) {
         throw InvalidProtocolBufferException.truncatedMessage();
@@ -1591,6 +1601,9 @@
       builder.mergeFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
     }
 
@@ -1607,6 +1620,9 @@
       T result = parser.parsePartialFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
       return result;
     }
@@ -2009,14 +2025,14 @@
       int prevPos = buffer.position();
       int prevLimit = buffer.limit();
       try {
-        buffer.position(bufferPos(begin));
-        buffer.limit(bufferPos(end));
+        ((Buffer) buffer).position(bufferPos(begin));
+        ((Buffer) buffer).limit(bufferPos(end));
         return buffer.slice();
       } catch (IllegalArgumentException e) {
         throw InvalidProtocolBufferException.truncatedMessage();
       } finally {
-        buffer.position(prevPos);
-        buffer.limit(prevLimit);
+        ((Buffer) buffer).position(prevPos);
+        ((Buffer) buffer).limit(prevLimit);
       }
     }
   }
@@ -2054,6 +2070,44 @@
       totalBytesRetired = 0;
     }
 
+    /*
+     * The following wrapper methods exist so that InvalidProtocolBufferExceptions thrown by the
+     * InputStream can be differentiated from ones thrown by CodedInputStream itself. Each call to
+     * an InputStream method that can throw IOException must be wrapped like this. We do this
+     * because we sometimes need to modify IPBE instances after they are thrown far away from where
+     * they are thrown (ex. to add unfinished messages) and we use this signal elsewhere in the
+     * exception catch chain to know when to perform these operations directly or to wrap the
+     * exception in their own IPBE so the extra information can be communicated without trampling
+     * downstream information.
+     */
+    private static int read(InputStream input, byte[] data, int offset, int length)
+        throws IOException {
+      try {
+        return input.read(data, offset, length);
+      } catch (InvalidProtocolBufferException e) {
+        e.setThrownFromInputStream();
+        throw e;
+      }
+    }
+
+    private static long skip(InputStream input, long length) throws IOException {
+      try {
+        return input.skip(length);
+      } catch (InvalidProtocolBufferException e) {
+        e.setThrownFromInputStream();
+        throw e;
+      }
+    }
+
+    private static int available(InputStream input) throws IOException {
+      try {
+        return input.available();
+      } catch (InvalidProtocolBufferException e) {
+        e.setThrownFromInputStream();
+        throw e;
+      }
+    }
+
     @Override
     public int readTag() throws IOException {
       if (isAtEnd()) {
@@ -2350,6 +2404,9 @@
       builder.mergeFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
     }
 
@@ -2366,6 +2423,9 @@
       T result = parser.parsePartialFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
       return result;
     }
@@ -2782,7 +2842,8 @@
 
       // Here we should refill the buffer as many bytes as possible.
       int bytesRead =
-          input.read(
+          read(
+              input,
               buffer,
               bufferSize,
               Math.min(
@@ -2904,7 +2965,7 @@
       // Determine the number of bytes we need to read from the input stream.
       int sizeLeft = size - bufferedBytes;
       // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
-      if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= input.available()) {
+      if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= available(input)) {
         // Either the bytes we need are known to be available, or the required buffer is
         // within an allowed threshold - go ahead and allocate the buffer now.
         final byte[] bytes = new byte[size];
@@ -2918,7 +2979,7 @@
         // Fill the remaining bytes from the input stream.
         int tempPos = bufferedBytes;
         while (tempPos < bytes.length) {
-          int n = input.read(bytes, tempPos, size - tempPos);
+          int n = read(input, bytes, tempPos, size - tempPos);
           if (n == -1) {
             throw InvalidProtocolBufferException.truncatedMessage();
           }
@@ -3046,7 +3107,7 @@
         try {
           while (totalSkipped < size) {
             int toSkip = size - totalSkipped;
-            long skipped = input.skip(toSkip);
+            long skipped = skip(input, toSkip);
             if (skipped < 0 || skipped > toSkip) {
               throw new IllegalStateException(
                   input.getClass()
@@ -3446,6 +3507,9 @@
       builder.mergeFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
     }
 
@@ -3462,6 +3526,9 @@
       T result = parser.parsePartialFrom(this, extensionRegistry);
       checkLastTagWas(0);
       --recursionDepth;
+      if (getBytesUntilLimit() != 0) {
+        throw InvalidProtocolBufferException.truncatedMessage();
+      }
       popLimit(oldLimit);
       return result;
     }
@@ -3483,9 +3550,25 @@
           return ByteString.wrap(bytes);
         }
       } else if (size > 0 && size <= remaining()) {
-        byte[] temp = new byte[size];
-        readRawBytesTo(temp, 0, size);
-        return ByteString.wrap(temp);
+        if (immutable && enableAliasing) {
+          ArrayList<ByteString> byteStrings = new ArrayList<>();
+          int l = size;
+          while (l > 0) {
+            if (currentRemaining() == 0) {
+              getNextByteBuffer();
+            }
+            int bytesToCopy = Math.min(l, (int) currentRemaining());
+            int idx = (int) (currentByteBufferPos - currentAddress);
+            byteStrings.add(ByteString.wrap(slice(idx, idx + bytesToCopy)));
+            l -= bytesToCopy;
+            currentByteBufferPos += bytesToCopy;
+          }
+          return ByteString.copyFrom(byteStrings);
+        } else {
+          byte[] temp = new byte[size];
+          readRawBytesTo(temp, 0, size);
+          return ByteString.wrap(temp);
+        }
       }
 
       if (size == 0) {
@@ -3910,14 +3993,14 @@
       int prevPos = currentByteBuffer.position();
       int prevLimit = currentByteBuffer.limit();
       try {
-        currentByteBuffer.position(begin);
-        currentByteBuffer.limit(end);
+        ((Buffer) currentByteBuffer).position(begin);
+        ((Buffer) currentByteBuffer).limit(end);
         return currentByteBuffer.slice();
       } catch (IllegalArgumentException e) {
         throw InvalidProtocolBufferException.truncatedMessage();
       } finally {
-        currentByteBuffer.position(prevPos);
-        currentByteBuffer.limit(prevLimit);
+        ((Buffer) currentByteBuffer).position(prevPos);
+        ((Buffer) currentByteBuffer).limit(prevLimit);
       }
     }
   }
diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java
index 960ff5d..e56a18e 100644
--- a/java/core/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -190,7 +190,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof Descriptor && result.getFile() == this) {
+      if (result instanceof Descriptor && result.getFile() == this) {
         return (Descriptor) result;
       } else {
         return null;
@@ -214,7 +214,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof EnumDescriptor && result.getFile() == this) {
+      if (result instanceof EnumDescriptor && result.getFile() == this) {
         return (EnumDescriptor) result;
       } else {
         return null;
@@ -238,7 +238,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof ServiceDescriptor && result.getFile() == this) {
+      if (result instanceof ServiceDescriptor && result.getFile() == this) {
         return (ServiceDescriptor) result;
       } else {
         return null;
@@ -260,7 +260,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof FieldDescriptor && result.getFile() == this) {
+      if (result instanceof FieldDescriptor && result.getFile() == this) {
         return (FieldDescriptor) result;
       } else {
         return null;
@@ -338,7 +338,7 @@
         final Class<?> descriptorOuterClass,
         final String[] dependencyClassNames,
         final String[] dependencyFileNames) {
-      List<FileDescriptor> descriptors = new ArrayList<FileDescriptor>();
+      List<FileDescriptor> descriptors = new ArrayList<>();
       for (int i = 0; i < dependencyClassNames.length; i++) {
         try {
           Class<?> clazz = descriptorOuterClass.getClassLoader().loadClass(dependencyClassNames[i]);
@@ -507,11 +507,11 @@
       this.pool = pool;
       this.proto = proto;
       this.dependencies = dependencies.clone();
-      HashMap<String, FileDescriptor> nameToFileMap = new HashMap<String, FileDescriptor>();
+      HashMap<String, FileDescriptor> nameToFileMap = new HashMap<>();
       for (FileDescriptor file : dependencies) {
         nameToFileMap.put(file.getName(), file);
       }
-      List<FileDescriptor> publicDependencies = new ArrayList<FileDescriptor>();
+      List<FileDescriptor> publicDependencies = new ArrayList<>();
       for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
         int index = proto.getPublicDependency(i);
         if (index < 0 || index >= proto.getDependencyCount()) {
@@ -702,6 +702,11 @@
       return Collections.unmodifiableList(Arrays.asList(oneofs));
     }
 
+    /** Get a list of this message type's real oneofs. */
+    public List<OneofDescriptor> getRealOneofs() {
+      return Collections.unmodifiableList(Arrays.asList(oneofs).subList(0, realOneofCount));
+    }
+
     /** Get a list of this message type's extensions. */
     public List<FieldDescriptor> getExtensions() {
       return Collections.unmodifiableList(Arrays.asList(extensions));
@@ -719,12 +724,12 @@
 
     /** Determines if the given field number is an extension. */
     public boolean isExtensionNumber(final int number) {
-      for (final DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) {
-        if (range.getStart() <= number && number < range.getEnd()) {
-          return true;
-        }
+      int index = Arrays.binarySearch(extensionRangeLowerBounds, number);
+      if (index < 0) {
+        index = ~index - 1;
       }
-      return false;
+      // extensionRangeLowerBounds[index] is the biggest value <= number
+      return index >= 0 && number < extensionRangeUpperBounds[index];
     }
 
     /** Determines if the given field number is reserved. */
@@ -753,18 +758,21 @@
      * y" ranges declared on it.
      */
     public boolean isExtendable() {
-      return proto.getExtensionRangeList().size() != 0;
+      return !proto.getExtensionRangeList().isEmpty();
     }
 
     /**
      * Finds a field by name.
      *
-     * @param name The unqualified name of the field (e.g. "foo").
+     * @param name The unqualified name of the field (e.g. "foo"). For protocol buffer messages that
+     *     follow <a
+     *     href=https://developers.google.com/protocol-buffers/docs/style#message_and_field_names>Google's
+     *     guidance on naming</a> this will be a snake case string, such as <pre>song_name</pre>.
      * @return The field's descriptor, or {@code null} if not found.
      */
     public FieldDescriptor findFieldByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof FieldDescriptor) {
+      if (result instanceof FieldDescriptor) {
         return (FieldDescriptor) result;
       } else {
         return null;
@@ -789,7 +797,7 @@
      */
     public Descriptor findNestedTypeByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof Descriptor) {
+      if (result instanceof Descriptor) {
         return (Descriptor) result;
       } else {
         return null;
@@ -804,7 +812,7 @@
      */
     public EnumDescriptor findEnumTypeByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof EnumDescriptor) {
+      if (result instanceof EnumDescriptor) {
         return (EnumDescriptor) result;
       } else {
         return null;
@@ -821,6 +829,10 @@
     private final FieldDescriptor[] fields;
     private final FieldDescriptor[] extensions;
     private final OneofDescriptor[] oneofs;
+    private final int realOneofCount;
+
+    private final int[] extensionRangeLowerBounds;
+    private final int[] extensionRangeUpperBounds;
 
     // Used to create a placeholder when the type cannot be found.
     Descriptor(final String fullname) throws DescriptorValidationException {
@@ -846,9 +858,13 @@
       this.fields = new FieldDescriptor[0];
       this.extensions = new FieldDescriptor[0];
       this.oneofs = new OneofDescriptor[0];
+      this.realOneofCount = 0;
 
       // Create a placeholder FileDescriptor to hold this message.
       this.file = new FileDescriptor(packageName, this);
+
+      extensionRangeLowerBounds = new int[] {1};
+      extensionRangeUpperBounds = new int[] {536870912};
     }
 
     private Descriptor(
@@ -899,7 +915,33 @@
         }
       }
 
+      int syntheticOneofCount = 0;
+      for (OneofDescriptor oneof : this.oneofs) {
+        if (oneof.isSynthetic()) {
+          syntheticOneofCount++;
+        } else {
+          if (syntheticOneofCount > 0) {
+            throw new DescriptorValidationException(this, "Synthetic oneofs must come last.");
+          }
+        }
+      }
+      this.realOneofCount = this.oneofs.length - syntheticOneofCount;
+
       file.pool.addSymbol(this);
+
+      // NOTE: The defined extension ranges are guaranteed to be disjoint.
+      extensionRangeLowerBounds = new int[proto.getExtensionRangeCount()];
+      extensionRangeUpperBounds = new int[proto.getExtensionRangeCount()];
+      int i = 0;
+      for (final DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) {
+        extensionRangeLowerBounds[i] = range.getStart();
+        extensionRangeUpperBounds[i] = range.getEnd();
+        i++;
+      }
+      // Since the ranges are disjoint, sorting these independently must still produce the correct
+      // order.
+      Arrays.sort(extensionRangeLowerBounds);
+      Arrays.sort(extensionRangeUpperBounds);
     }
 
     /** Look up and cross-link all field types, etc. */
@@ -1065,7 +1107,7 @@
 
     /**
      * Does this field have the {@code [packed = true]} option or is this field packable in proto3
-     * and not explicitly setted to unpacked?
+     * and not explicitly set to unpacked?
      */
     @Override
     public boolean isPacked() {
@@ -1125,6 +1167,11 @@
       return containingOneof;
     }
 
+    /** Get the field's containing oneof, only if non-synthetic. */
+    public OneofDescriptor getRealContainingOneof() {
+      return containingOneof != null && !containingOneof.isSynthetic() ? containingOneof : null;
+    }
+
     /**
      * Returns true if this field was syntactically written with "optional" in the .proto file.
      * Excludes singular proto3 fields that do not have a label.
@@ -1135,22 +1182,23 @@
     }
 
     /**
-     * Returns true if this is a non-oneof field that tracks presence.
+     * Returns true if this field tracks presence, ie. does the field distinguish between "unset"
+     * and "present with default value."
      *
-     * <p>This includes all "required" and "optional" fields in the .proto file, but excludes oneof
-     * fields and singular proto3 fields without "optional".
+     * <p>This includes required, optional, and oneof fields. It excludes maps, repeated fields, and
+     * singular proto3 fields without "optional".
      *
-     * <p>In implementations that use hasbits, this method will probably indicate whether this field
-     * uses a hasbit.
+     * <p>For fields where hasPresence() == true, the return value of msg.hasField() is semantically
+     * meaningful.
      */
-    boolean isSingularWithPresence() {
+    boolean hasPresence() {
       if (isRepeated()) {
         return false;
       }
-      if (getContainingOneof() != null && !getContainingOneof().isSynthetic()) {
-        return false;
-      }
-      return getType() == Type.MESSAGE || isProto3Optional || file.getSyntax() == Syntax.PROTO2;
+      return getType() == Type.MESSAGE
+          || getType() == Type.GROUP
+          || getContainingOneof() != null
+          || file.getSyntax() == Syntax.PROTO2;
     }
 
     /**
@@ -1673,7 +1721,7 @@
      */
     public EnumValueDescriptor findValueByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof EnumValueDescriptor) {
+      if (result instanceof EnumValueDescriptor) {
         return (EnumValueDescriptor) result;
       } else {
         return null;
@@ -1757,7 +1805,7 @@
     private final Descriptor containingType;
     private EnumValueDescriptor[] values;
     private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
-        new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
+        new WeakHashMap<>();
 
     private EnumDescriptor(
         final EnumDescriptorProto proto,
@@ -1963,7 +2011,7 @@
      */
     public MethodDescriptor findMethodByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof MethodDescriptor) {
+      if (result instanceof MethodDescriptor) {
         return (MethodDescriptor) result;
       } else {
         return null;
@@ -2237,12 +2285,12 @@
     }
 
     DescriptorPool(final FileDescriptor[] dependencies, boolean allowUnknownDependencies) {
-      this.dependencies = new HashSet<FileDescriptor>();
+      this.dependencies = new HashSet<>();
       this.allowUnknownDependencies = allowUnknownDependencies;
 
-      for (int i = 0; i < dependencies.length; i++) {
-        this.dependencies.add(dependencies[i]);
-        importPublicDependencies(dependencies[i]);
+      for (Descriptors.FileDescriptor dependency : dependencies) {
+        this.dependencies.add(dependency);
+        importPublicDependencies(dependency);
       }
 
       for (final FileDescriptor dependency : this.dependencies) {
@@ -2269,12 +2317,9 @@
     private final Set<FileDescriptor> dependencies;
     private boolean allowUnknownDependencies;
 
-    private final Map<String, GenericDescriptor> descriptorsByName =
-        new HashMap<String, GenericDescriptor>();
-    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
-        new HashMap<DescriptorIntPair, FieldDescriptor>();
-    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
-        new HashMap<DescriptorIntPair, EnumValueDescriptor>();
+    private final Map<String, GenericDescriptor> descriptorsByName = new HashMap<>();
+    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber = new HashMap<>();
+    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = new HashMap<>();
 
     /** Find a generic descriptor by fully-qualified name. */
     GenericDescriptor findSymbol(final String fullName) {
diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
index 12824ab..4085653 100644
--- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -268,20 +268,6 @@
   }
 
   @Override
-  public boolean remove(Object o) {
-    ensureIsMutable();
-    for (int i = 0; i < size; i++) {
-      if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i - 1);
-        size--;
-        modCount++;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
   public Double remove(int index) {
     ensureIsMutable();
     ensureIndexInRange(index);
diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
index 63dda6b..8beebba 100644
--- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -328,20 +328,6 @@
       this.fields = FieldSet.newFieldSet();
       this.unknownFields = UnknownFieldSet.getDefaultInstance();
       this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()];
-      // A MapEntry has all of its fields present at all times.
-      if (type.getOptions().getMapEntry()) {
-        populateMapEntry();
-      }
-    }
-
-    private void populateMapEntry() {
-      for (FieldDescriptor field : type.getFields()) {
-        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-          fields.setField(field, getDefaultInstance(field.getMessageType()));
-        } else {
-          fields.setField(field, field.getDefaultValue());
-        }
-      }
     }
 
     // ---------------------------------------------------------------
@@ -354,10 +340,6 @@
       } else {
         fields.clear();
       }
-      // A MapEntry has all of its fields present at all times.
-      if (type.getOptions().getMapEntry()) {
-        populateMapEntry();
-      }
       unknownFields = UnknownFieldSet.getDefaultInstance();
       return this;
     }
@@ -423,6 +405,19 @@
 
     @Override
     public DynamicMessage buildPartial() {
+      // Set default values for all fields in a MapEntry.
+      if (type.getOptions().getMapEntry()) {
+        for (FieldDescriptor field : type.getFields()) {
+          if (field.isOptional() && !fields.hasField(field)) {
+            if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+              fields.setField(field, getDefaultInstance(field.getMessageType()));
+            } else {
+              fields.setField(field, field.getDefaultValue());
+            }
+          }
+        }
+      }
+
       fields.makeImmutable();
       DynamicMessage result =
           new DynamicMessage(
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
index 241fcbd..0a63fad 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
@@ -46,7 +46,6 @@
   @Nullable */
   static final Class<?> EXTENSION_REGISTRY_CLASS = reflectExtensionRegistry();
 
-  /* @Nullable */
   static Class<?> reflectExtensionRegistry() {
     try {
       return Class.forName(FULL_REGISTRY_CLASS_NAME);
@@ -77,7 +76,6 @@
         && EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass());
   }
 
-  /* @Nullable */
   private static final ExtensionRegistryLite invokeSubclassFactory(String methodName) {
     if (EXTENSION_REGISTRY_CLASS == null) {
       return null;
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
index 0c4b20e..caa58e1 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -84,10 +84,8 @@
   static final String EXTENSION_CLASS_NAME = "com.google.protobuf.Extension";
 
   private static class ExtensionClassHolder {
-    /* @Nullable */
     static final Class<?> INSTANCE = resolveExtensionClass();
 
-    /* @Nullable */
     static Class<?> resolveExtensionClass() {
       try {
         return Class.forName(EXTENSION_CLASS_NAME);
diff --git a/java/core/src/main/java/com/google/protobuf/FieldSet.java b/java/core/src/main/java/com/google/protobuf/FieldSet.java
index d52aede..f64b50a 100644
--- a/java/core/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java
@@ -119,7 +119,6 @@
   }
 
   /** Make this FieldSet immutable from this point forward. */
-  @SuppressWarnings("unchecked")
   public void makeImmutable() {
     if (isImmutable) {
       return;
@@ -283,14 +282,14 @@
 
       // Wrap the contents in a new list so that the caller cannot change
       // the list's contents after setting it.
-      final List newList = new ArrayList();
+      final List newList = new ArrayList<>();
       newList.addAll((List) value);
       for (final Object element : newList) {
-        verifyType(descriptor.getLiteType(), element);
+        verifyType(descriptor, element);
       }
       value = newList;
     } else {
-      verifyType(descriptor.getLiteType(), value);
+      verifyType(descriptor, value);
     }
 
     if (value instanceof LazyField) {
@@ -354,7 +353,7 @@
       throw new IndexOutOfBoundsException();
     }
 
-    verifyType(descriptor.getLiteType(), value);
+    verifyType(descriptor, value);
     ((List<Object>) list).set(index, value);
   }
 
@@ -369,7 +368,7 @@
           "addRepeatedField() can only be called on repeated fields.");
     }
 
-    verifyType(descriptor.getLiteType(), value);
+    verifyType(descriptor, value);
 
     final Object existingValue = getField(descriptor);
     List<Object> list;
@@ -390,8 +389,8 @@
    *
    * @throws IllegalArgumentException The value is not of the right type.
    */
-  private void verifyType(final WireFormat.FieldType type, final Object value) {
-    if (!isValidType(type, value)) {
+  private void verifyType(final T descriptor, final Object value) {
+    if (!isValidType(descriptor.getLiteType(), value)) {
       // TODO(kenton):  When chaining calls to setField(), it can be hard to
       //   tell from the stack trace which exact call failed, since the whole
       //   chain is considered one line of code.  It would be nice to print
@@ -400,10 +399,16 @@
       //   isn't a big deal, though, since it would only really apply when using
       //   reflection and generally people don't chain reflection setters.
       throw new IllegalArgumentException(
-          "Wrong object type used with protocol message reflection.");
+          String.format(
+              "Wrong object type used with protocol message reflection.\n"
+              + "Field number: %d, field java type: %s, value type: %s\n",
+              descriptor.getNumber(),
+              descriptor.getLiteType().getJavaType(),
+              value.getClass().getName()));
     }
   }
 
+
   private static boolean isValidType(final WireFormat.FieldType type, final Object value) {
     checkNotNull(value);
     switch (type.getJavaType()) {
@@ -1081,12 +1086,12 @@
         final List newList = new ArrayList();
         newList.addAll((List) value);
         for (final Object element : newList) {
-          verifyType(descriptor.getLiteType(), element);
+          verifyType(descriptor, element);
           hasNestedBuilders = hasNestedBuilders || element instanceof MessageLite.Builder;
         }
         value = newList;
       } else {
-        verifyType(descriptor.getLiteType(), value);
+        verifyType(descriptor, value);
       }
 
       if (value instanceof LazyField) {
@@ -1172,7 +1177,7 @@
         throw new IndexOutOfBoundsException();
       }
 
-      verifyType(descriptor.getLiteType(), value);
+      verifyType(descriptor, value);
       ((List<Object>) list).set(index, value);
     }
 
@@ -1190,7 +1195,7 @@
 
       hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder;
 
-      verifyType(descriptor.getLiteType(), value);
+      verifyType(descriptor, value);
 
       final Object existingValue = getField(descriptor);
       List<Object> list;
@@ -1211,15 +1216,20 @@
      *
      * @throws IllegalArgumentException The value is not of the right type.
      */
-    private static void verifyType(final WireFormat.FieldType type, final Object value) {
-      if (!FieldSet.isValidType(type, value)) {
+    private void verifyType(final T descriptor, final Object value) {
+      if (!FieldSet.isValidType(descriptor.getLiteType(), value)) {
         // Builder can accept Message.Builder values even though FieldSet will reject.
-        if (type.getJavaType() == WireFormat.JavaType.MESSAGE
+        if (descriptor.getLiteType().getJavaType() == WireFormat.JavaType.MESSAGE
             && value instanceof MessageLite.Builder) {
           return;
         }
         throw new IllegalArgumentException(
-            "Wrong object type used with protocol message reflection.");
+            String.format(
+                "Wrong object type used with protocol message reflection.\n"
+                + "Field number: %d, field java type: %s, value type: %s\n",
+                descriptor.getNumber(),
+                descriptor.getLiteType().getJavaType(),
+                value.getClass().getName()));
       }
     }
 
diff --git a/java/core/src/main/java/com/google/protobuf/FieldType.java b/java/core/src/main/java/com/google/protobuf/FieldType.java
index 1b8f9e5..7232753 100644
--- a/java/core/src/main/java/com/google/protobuf/FieldType.java
+++ b/java/core/src/main/java/com/google/protobuf/FieldType.java
@@ -204,7 +204,6 @@
    *
    * @return the {@link FieldType} or {@code null} if not found.
    */
-  /* @Nullable */
   public static FieldType forId(int id) {
     if (id < 0 || id >= VALUES.length) {
       return null;
@@ -228,7 +227,6 @@
    *
    * @return the generic super class/interface, or {@code null} if not found.
    */
-  /* @Nullable */
   private static Type getGenericSuperList(Class<?> clazz) {
     // First look at interfaces.
     Type[] genericInterfaces = clazz.getGenericInterfaces();
diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
index 9589816..e6feba8 100644
--- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -267,20 +267,6 @@
   }
 
   @Override
-  public boolean remove(Object o) {
-    ensureIsMutable();
-    for (int i = 0; i < size; i++) {
-      if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i - 1);
-        size--;
-        modCount++;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
   public Float remove(int index) {
     ensureIsMutable();
     ensureIndexInRange(index);
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 8456713..7db8f32 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -223,7 +223,7 @@
 
   /**
    * A method that implements different types of operations described in {@link MethodToInvoke}.
-   * Theses different kinds of operations are required to implement message-level operations for
+   * These different kinds of operations are required to implement message-level operations for
    * builders in the runtime. This method bundles those operations to reduce the generated methods
    * count.
    *
@@ -234,7 +234,7 @@
    *       It doesn't use or modify any memoized value.
    *   <li>{@code GET_MEMOIZED_IS_INITIALIZED} returns the memoized {@code isInitialized} byte
    *       value.
-   *   <li>{@code SET_MEMOIZED_IS_INITIALIZED} sets the memoized {@code isInitilaized} byte value to
+   *   <li>{@code SET_MEMOIZED_IS_INITIALIZED} sets the memoized {@code isInitialized} byte value to
    *       1 if the first parameter is not null, or to 0 if the first parameter is null.
    *   <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance.
    * </ul>
@@ -266,12 +266,14 @@
     memoizedSerializedSize = size;
   }
 
+  @Override
   public void writeTo(CodedOutputStream output) throws IOException {
     Protobuf.getInstance()
         .schemaFor(this)
         .writeTo(this, CodedOutputStreamWriter.forCodedOutput(output));
   }
 
+  @Override
   public int getSerializedSize() {
     if (memoizedSerializedSize == -1) {
       memoizedSerializedSize = Protobuf.getInstance().schemaFor(this).getSerializedSize(this);
@@ -461,7 +463,7 @@
         throws IOException {
       copyOnWrite();
       try {
-        // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
+        // TODO(yilunchong): Try to make input with type CodedInputStream.ArrayDecoder use
         // fast path.
         Protobuf.getInstance().schemaFor(instance).mergeFrom(
             instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
@@ -1535,11 +1537,16 @@
       Schema<T> schema = Protobuf.getInstance().schemaFor(result);
       schema.mergeFrom(result, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
       schema.makeImmutable(result);
+    } catch (InvalidProtocolBufferException e) {
+      if (e.getThrownFromInputStream()) {
+        e = new InvalidProtocolBufferException(e);
+      }
+      throw e.setUnfinishedMessage(result);
     } catch (IOException e) {
       if (e.getCause() instanceof InvalidProtocolBufferException) {
         throw (InvalidProtocolBufferException) e.getCause();
       }
-      throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
+      throw new InvalidProtocolBufferException(e).setUnfinishedMessage(result);
     } catch (RuntimeException e) {
       if (e.getCause() instanceof InvalidProtocolBufferException) {
         throw (InvalidProtocolBufferException) e.getCause();
@@ -1563,11 +1570,16 @@
       if (result.memoizedHashCode != 0) {
         throw new RuntimeException();
       }
+    } catch (InvalidProtocolBufferException e) {
+      if (e.getThrownFromInputStream()) {
+        e = new InvalidProtocolBufferException(e);
+      }
+      throw e.setUnfinishedMessage(result);
     } catch (IOException e) {
       if (e.getCause() instanceof InvalidProtocolBufferException) {
         throw (InvalidProtocolBufferException) e.getCause();
       }
-      throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
+      throw new InvalidProtocolBufferException(e).setUnfinishedMessage(result);
     } catch (IndexOutOfBoundsException e) {
       throw InvalidProtocolBufferException.truncatedMessage().setUnfinishedMessage(result);
     }
@@ -1725,8 +1737,13 @@
         return null;
       }
       size = CodedInputStream.readRawVarint32(firstByte, input);
+    } catch (InvalidProtocolBufferException e) {
+      if (e.getThrownFromInputStream()) {
+        e = new InvalidProtocolBufferException(e);
+      }
+      throw e;
     } catch (IOException e) {
-      throw new InvalidProtocolBufferException(e.getMessage());
+      throw new InvalidProtocolBufferException(e);
     }
     InputStream limitedInput = new LimitedInputStream(input, size);
     CodedInputStream codedInput = CodedInputStream.newInstance(limitedInput);
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
index 86f88a0..f54b123 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -3068,6 +3068,14 @@
     return (Extension<MessageType, T>) extension;
   }
 
+  protected static boolean isStringEmpty(final Object value) {
+    if (value instanceof String) {
+      return ((String) value).isEmpty();
+    } else {
+      return ((ByteString) value).isEmpty();
+    }
+  }
+
   protected static int computeStringSize(final int fieldNumber, final Object value) {
     if (value instanceof String) {
       return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
index e9c3b1a..9daeebe 100644
--- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
@@ -267,20 +267,6 @@
   }
 
   @Override
-  public boolean remove(Object o) {
-    ensureIsMutable();
-    for (int i = 0; i < size; i++) {
-      if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i - 1);
-        size--;
-        modCount++;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
   public Integer remove(int index) {
     ensureIsMutable();
     ensureIndexInRange(index);
diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java
index 0826351..90643b8 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -30,7 +30,6 @@
 
 package com.google.protobuf;
 
-import java.io.IOException;
 import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 22f31bb..4b43033 100644
--- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -41,6 +41,7 @@
 public class InvalidProtocolBufferException extends IOException {
   private static final long serialVersionUID = -1616151763072450476L;
   private MessageLite unfinishedMessage = null;
+  private boolean wasThrownFromInputStream;
 
   public InvalidProtocolBufferException(final String description) {
     super(description);
@@ -72,6 +73,28 @@
     return unfinishedMessage;
   }
 
+  /** Set by CodedInputStream */
+  void setThrownFromInputStream() {
+    /* This write can be racy if the same exception is stored and then thrown by multiple custom
+     * InputStreams on different threads. But since it only ever moves from false->true, there's no
+     * problem. A thread checking this condition after catching this exception from a delegate
+     * stream of CodedInputStream is guaranteed to always observe true, because a write on the same
+     * thread set the value when the exception left the delegate. A thread checking the same
+     * condition with an exception created by CodedInputStream is guaranteed to always see false,
+     * because the exception has not been exposed to any code that could publish it to other threads
+     * and cause a write.
+     */
+    wasThrownFromInputStream = true;
+  }
+
+  /**
+   * Allows code catching IOException from CodedInputStream to tell whether this instance was thrown
+   * by a delegate InputStream, rather than directly by a parse failure.
+   */
+  boolean getThrownFromInputStream() {
+    return wasThrownFromInputStream;
+  }
+
   /**
    * Unwraps the underlying {@link IOException} if this exception was caused by an I/O problem.
    * Otherwise, returns {@code this}.
diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
index 04f4475..bda43a4 100644
--- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
@@ -267,20 +267,6 @@
   }
 
   @Override
-  public boolean remove(Object o) {
-    ensureIsMutable();
-    for (int i = 0; i < size; i++) {
-      if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i - 1);
-        size--;
-        modCount++;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
   public Long remove(int index) {
     ensureIsMutable();
     ensureIndexInRange(index);
diff --git a/java/core/src/main/java/com/google/protobuf/MapEntryLite.java b/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
index ca2a3c2..81bf4c2 100644
--- a/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
+++ b/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
@@ -192,7 +192,7 @@
   }
 
   /**
-   * Parses an entry off of the input into the map. This helper avoids allocaton of a {@link
+   * Parses an entry off of the input into the map. This helper avoids allocation of a {@link
    * MapEntryLite} by parsing directly into the provided {@link MapFieldLite}.
    */
   public void parseInto(
diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
index 139e55a..33c8e91 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
@@ -1402,8 +1402,10 @@
     if (!isOneofPresent(other, number, pos)) {
       return;
     }
-
-    Object mine = UnsafeUtil.getObject(message, offset);
+    Object mine = null;
+    if (isOneofPresent(message, number, pos)) {
+      mine = UnsafeUtil.getObject(message, offset);
+    }
     Object theirs = UnsafeUtil.getObject(other, offset);
     if (mine != null && theirs != null) {
       Object merged = Internal.mergeMessage(mine, theirs);
@@ -2570,7 +2572,7 @@
 
       int presenceMaskAndOffset = 0;
       int presenceMask = 0;
-      if (!proto3 && fieldType <= 17) {
+      if (fieldType <= 17) {
         presenceMaskAndOffset = buffer[pos + 2];
         final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
         if (presenceFieldOffset != currentPresenceFieldOffset) {
diff --git a/java/core/src/main/java/com/google/protobuf/NioByteString.java b/java/core/src/main/java/com/google/protobuf/NioByteString.java
index 64c46be..1e594ff 100644
--- a/java/core/src/main/java/com/google/protobuf/NioByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/NioByteString.java
@@ -37,6 +37,7 @@
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.OutputStream;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.InvalidMarkException;
@@ -109,7 +110,7 @@
   protected void copyToInternal(
       byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
     ByteBuffer slice = buffer.slice();
-    slice.position(sourceOffset);
+    ((Buffer) slice).position(sourceOffset);
     slice.get(target, targetOffset, numberToCopy);
   }
 
@@ -285,8 +286,8 @@
     }
 
     ByteBuffer slice = buffer.slice();
-    slice.position(beginIndex - buffer.position());
-    slice.limit(endIndex - buffer.position());
+    ((Buffer) slice).position(beginIndex - buffer.position());
+    ((Buffer) slice).limit(endIndex - buffer.position());
     return slice;
   }
 }
diff --git a/java/core/src/main/java/com/google/protobuf/Protobuf.java b/java/core/src/main/java/com/google/protobuf/Protobuf.java
index adaa7fa..0affac5 100644
--- a/java/core/src/main/java/com/google/protobuf/Protobuf.java
+++ b/java/core/src/main/java/com/google/protobuf/Protobuf.java
@@ -76,11 +76,8 @@
     schemaFor(message).makeImmutable(message);
   }
 
-  /**
-   * Checks if all required fields are set. TODO(xiaofeng): Make this package private when the tests
-   * are moved to protobuf package.
-   */
-  public <T> boolean isInitialized(T message) {
+  /** Checks if all required fields are set. */
+  <T> boolean isInitialized(T message) {
     return schemaFor(message).isInitialized(message);
   }
 
diff --git a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
index 72f56ed..d66f5c4 100644
--- a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
+++ b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
@@ -80,14 +80,15 @@
    *   <li>[1]: field type with extra bits:
    *       <ul>
    *         <li>v & 0xFF = field type as defined in the FieldType class
-   *         <li>v & 0x100 = is required?
-   *         <li>v & 0x200 = is checkUtf8?
-   *         <li>v & 0x400 = needs isInitialized check?
-   *         <li>v & 0x800 = is map field with proto2 enum value?
+   *         <li>v & 0x0100 = is required?
+   *         <li>v & 0x0200 = is checkUtf8?
+   *         <li>v & 0x0400 = needs isInitialized check?
+   *         <li>v & 0x0800 = is map field with proto2 enum value?
+   *         <li>v & 0x1000 = supports presence checking?
    *       </ul>
    * </ul>
    *
-   * If the file is proto2 and this is a singular field:
+   * If the (singular) field supports presence checking:
    *
    * <ul>
    *   <li>[2]: hasbits offset
@@ -180,8 +181,32 @@
     this.defaultInstance = defaultInstance;
     this.info = info;
     this.objects = objects;
-    int position = 0;
-    int value = (int) info.charAt(position++);
+    int value;
+    try {
+      value = (int) info.charAt(0);
+    } catch (StringIndexOutOfBoundsException e) {
+      // This is a fix for issues
+      // that error out on a subset of phones on charAt(0) with an index out of bounds exception.
+      char[] infoChars = info.toCharArray();
+      info = new String(infoChars);
+      try {
+        value = (int) info.charAt(0);
+      } catch (StringIndexOutOfBoundsException e2) {
+        try {
+          char[] infoChars2 = new char[info.length()];
+          info.getChars(0, info.length(), infoChars2, 0);
+          info = new String(infoChars2);
+          value = (int) info.charAt(0);
+        } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e3) {
+          throw new IllegalStateException(
+              String.format(
+                  "Failed parsing '%s' with charArray.length of %d", info, infoChars.length),
+              e3);
+        }
+      }
+    }
+    int position = 1;
+
     if (value < 0xD800) {
       flags = value;
     } else {
diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
index 54d4180..f584164 100644
--- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
@@ -603,7 +603,12 @@
 
   @Override
   public CodedInputStream newCodedInput() {
-    return CodedInputStream.newInstance(new RopeInputStream());
+    // Passing along direct references to internal ByteBuffers can support more efficient parsing
+    // via aliasing in CodedInputStream for users who wish to use it.
+    //
+    // Otherwise we force data copies, both in copying as an input stream and in buffering in the
+    // CodedInputSteam.
+    return CodedInputStream.newInstance(asReadOnlyByteBufferList(), /* bufferIsImmutable= */ true);
   }
 
   @Override
@@ -845,7 +850,10 @@
         throw new IndexOutOfBoundsException();
       }
       int bytesRead = readSkipInternal(b, offset, length);
-      if (bytesRead == 0) {
+      if (bytesRead == 0 && (length > 0 || availableInternal() == 0)) {
+        // Modeling ByteArrayInputStream.read(byte[], int, int) behavior noted above:
+        // It's ok to read 0 bytes on purpose (length == 0) from a stream that isn't at EOF.
+        // It's not ok to try to read bytes (even 0 bytes) from a stream that is at EOF.
         return -1;
       } else {
         return bytesRead;
@@ -905,8 +913,7 @@
 
     @Override
     public int available() throws IOException {
-      int bytesRead = currentPieceOffsetInRope + currentPieceIndex;
-      return RopeByteString.this.size() - bytesRead;
+      return availableInternal();
     }
 
     @Override
@@ -955,5 +962,11 @@
         }
       }
     }
+
+    /** Computes the number of bytes still available to read. */
+    private int availableInternal() {
+      int bytesRead = currentPieceOffsetInRope + currentPieceIndex;
+      return RopeByteString.this.size() - bytesRead;
+    }
   }
 }
diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java
index 673343d..e781df3 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -30,6 +30,8 @@
 
 package com.google.protobuf;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.EnumDescriptor;
 import com.google.protobuf.Descriptors.EnumValueDescriptor;
@@ -59,6 +61,7 @@
 
   private static final Logger logger = Logger.getLogger(TextFormat.class.getName());
 
+
   /**
    * Outputs a textual representation of the Protocol Message supplied into the parameter output.
    * (This representation is the new version of the classic "ProtocolPrinter" output from the
@@ -490,27 +493,11 @@
         }
         switch (fieldType) {
           case BOOLEAN:
-            boolean aBoolean = (boolean) getKey();
-            boolean bBoolean = (boolean) b.getKey();
-            if (aBoolean == bBoolean) {
-              return 0;
-            } else if (aBoolean) {
-              return 1;
-            } else {
-              return -1;
-            }
+            return Boolean.compare((boolean) getKey(), (boolean) b.getKey());
           case LONG:
-            long aLong = (long) getKey();
-            long bLong = (long) b.getKey();
-            if (aLong < bLong) {
-              return -1;
-            } else if (aLong > bLong) {
-              return 1;
-            } else {
-              return 0;
-            }
+            return Long.compare((long) getKey(), (long) b.getKey());
           case INT:
-            return (int) getKey() - (int) b.getKey();
+            return Integer.compare((int) getKey(), (int) b.getKey());
           case STRING:
             String aString = (String) getKey();
             String bString = (String) b.getKey();
@@ -741,9 +728,9 @@
           // Groups must be serialized with their original capitalization.
           generator.print(field.getMessageType().getName());
         } else {
-          generator.print(field.getName());
+            generator.print(field.getName());
+          }
         }
-      }
 
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         generator.print(" {");
@@ -1677,7 +1664,7 @@
         throws IOException {
       // Read the entire input to a String then parse that.
 
-      // If StreamTokenizer were not quite so crippled, or if there were a kind
+      // If StreamTokenizer was not so limited, or if there were a kind
       // of Reader that could read in chunks that match some particular regex,
       // or if we wanted to write a custom Reader to tokenize our stream, then
       // we would not have to read to one big String.  Alas, none of these is
@@ -1825,16 +1812,16 @@
         extension = target.findExtensionByName(extensionRegistry, name.toString());
 
         if (extension == null) {
-          String message =
-              (tokenizer.getPreviousLine() + 1)
-                  + ":"
-                  + (tokenizer.getPreviousColumn() + 1)
-                  + ":\t"
-                  + type.getFullName()
-                  + ".["
-                  + name
-                  + "]";
-          unknownFields.add(new UnknownField(message, UnknownField.Type.EXTENSION));
+            String message =
+                (tokenizer.getPreviousLine() + 1)
+                    + ":"
+                    + (tokenizer.getPreviousColumn() + 1)
+                    + ":\t"
+                    + type.getFullName()
+                    + ".["
+                    + name
+                    + "]";
+            unknownFields.add(new UnknownField(message, UnknownField.Type.EXTENSION));
         } else {
           if (extension.descriptor.getContainingType() != type) {
             throw tokenizer.parseExceptionPreviousToken(
@@ -2391,6 +2378,73 @@
                 result[pos++] = (byte) code;
                 break;
 
+              case 'u':
+                // Unicode escape
+                ++i;
+                if (i + 3 < input.size()
+                    && isHex(input.byteAt(i))
+                    && isHex(input.byteAt(i + 1))
+                    && isHex(input.byteAt(i + 2))
+                    && isHex(input.byteAt(i + 3))) {
+                  char ch =
+                      (char)
+                          (digitValue(input.byteAt(i)) << 12
+                              | digitValue(input.byteAt(i + 1)) << 8
+                              | digitValue(input.byteAt(i + 2)) << 4
+                              | digitValue(input.byteAt(i + 3)));
+                  if (Character.isSurrogate(ch)) {
+                    throw new InvalidEscapeSequenceException(
+                        "Invalid escape sequence: '\\u' refers to a surrogate");
+                  }
+                  byte[] chUtf8 = Character.toString(ch).getBytes(UTF_8);
+                  System.arraycopy(chUtf8, 0, result, pos, chUtf8.length);
+                  pos += chUtf8.length;
+                  i += 3;
+                } else {
+                  throw new InvalidEscapeSequenceException(
+                      "Invalid escape sequence: '\\u' with too few hex chars");
+                }
+                break;
+
+              case 'U':
+                // Unicode escape
+                ++i;
+                if (i + 7 >= input.size()) {
+                  throw new InvalidEscapeSequenceException(
+                      "Invalid escape sequence: '\\U' with too few hex chars");
+                }
+                int codepoint = 0;
+                for (int offset = i; offset < i + 8; offset++) {
+                  byte b = input.byteAt(offset);
+                  if (!isHex(b)) {
+                    throw new InvalidEscapeSequenceException(
+                        "Invalid escape sequence: '\\U' with too few hex chars");
+                  }
+                  codepoint = (codepoint << 4) | digitValue(b);
+                }
+                if (!Character.isValidCodePoint(codepoint)) {
+                  throw new InvalidEscapeSequenceException(
+                      "Invalid escape sequence: '\\U"
+                          + input.substring(i, i + 8).toStringUtf8()
+                          + "' is not a valid code point value");
+                }
+                Character.UnicodeBlock unicodeBlock = Character.UnicodeBlock.of(codepoint);
+                if (unicodeBlock.equals(Character.UnicodeBlock.LOW_SURROGATES)
+                    || unicodeBlock.equals(Character.UnicodeBlock.HIGH_SURROGATES)
+                    || unicodeBlock.equals(Character.UnicodeBlock.HIGH_PRIVATE_USE_SURROGATES)) {
+                  throw new InvalidEscapeSequenceException(
+                      "Invalid escape sequence: '\\U"
+                          + input.substring(i, i + 8).toStringUtf8()
+                          + "' refers to a surrogate code unit");
+                }
+                int[] codepoints = new int[1];
+                codepoints[0] = codepoint;
+                byte[] chUtf8 = new String(codepoints, 0, 1).getBytes(UTF_8);
+                System.arraycopy(chUtf8, 0, result, pos, chUtf8.length);
+                pos += chUtf8.length;
+                i += 7;
+                break;
+
               default:
                 throw new InvalidEscapeSequenceException(
                     "Invalid escape sequence: '\\" + (char) c + '\'');
diff --git a/java/core/src/main/java/com/google/protobuf/TypeRegistry.java b/java/core/src/main/java/com/google/protobuf/TypeRegistry.java
index 47d798b..422ff1f 100644
--- a/java/core/src/main/java/com/google/protobuf/TypeRegistry.java
+++ b/java/core/src/main/java/com/google/protobuf/TypeRegistry.java
@@ -70,7 +70,6 @@
   /**
    * Find a type by its typeUrl. Returns null if it cannot be found in this {@link TypeRegistry}.
    */
-  /* @Nullable */
   public final Descriptor getDescriptorForTypeUrl(String typeUrl)
       throws InvalidProtocolBufferException {
     return find(getTypeName(typeUrl));
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
index b435327..dd459f0 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -41,7 +41,6 @@
 
 /** Utility class for working with unsafe operations. */
 final class UnsafeUtil {
-  private static final Logger logger = Logger.getLogger(UnsafeUtil.class.getName());
   private static final sun.misc.Unsafe UNSAFE = getUnsafe();
   private static final Class<?> MEMORY_CLASS = Android.getMemoryClass();
   private static final boolean IS_ANDROID_64 = determineAndroidSupportByAddressSize(long.class);
@@ -333,78 +332,21 @@
     return new JvmMemoryAccessor(UNSAFE);
   }
 
-  /** Indicates whether or not unsafe array operations are supported on this platform. */
   private static boolean supportsUnsafeArrayOperations() {
-    if (UNSAFE == null) {
+    if (MEMORY_ACCESSOR == null) {
       return false;
     }
-    try {
-      Class<?> clazz = UNSAFE.getClass();
-      clazz.getMethod("objectFieldOffset", Field.class);
-      clazz.getMethod("arrayBaseOffset", Class.class);
-      clazz.getMethod("arrayIndexScale", Class.class);
-      clazz.getMethod("getInt", Object.class, long.class);
-      clazz.getMethod("putInt", Object.class, long.class, int.class);
-      clazz.getMethod("getLong", Object.class, long.class);
-      clazz.getMethod("putLong", Object.class, long.class, long.class);
-      clazz.getMethod("getObject", Object.class, long.class);
-      clazz.getMethod("putObject", Object.class, long.class, Object.class);
-      if (Android.isOnAndroidDevice()) {
-        return true;
-      }
-      clazz.getMethod("getByte", Object.class, long.class);
-      clazz.getMethod("putByte", Object.class, long.class, byte.class);
-      clazz.getMethod("getBoolean", Object.class, long.class);
-      clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
-      clazz.getMethod("getFloat", Object.class, long.class);
-      clazz.getMethod("putFloat", Object.class, long.class, float.class);
-      clazz.getMethod("getDouble", Object.class, long.class);
-      clazz.getMethod("putDouble", Object.class, long.class, double.class);
-
-      return true;
-    } catch (Throwable e) {
-      logger.log(
-          Level.WARNING,
-          "platform method missing - proto runtime falling back to safer methods: " + e);
-    }
-    return false;
+    return MEMORY_ACCESSOR.supportsUnsafeArrayOperations();
   }
 
   private static boolean supportsUnsafeByteBufferOperations() {
-    if (UNSAFE == null) {
+    if (MEMORY_ACCESSOR == null) {
       return false;
     }
-    try {
-      Class<?> clazz = UNSAFE.getClass();
-      // Methods for getting direct buffer address.
-      clazz.getMethod("objectFieldOffset", Field.class);
-      clazz.getMethod("getLong", Object.class, long.class);
-
-      if (bufferAddressField() == null) {
-        return false;
-      }
-
-      if (Android.isOnAndroidDevice()) {
-        return true;
-      }
-      clazz.getMethod("getByte", long.class);
-      clazz.getMethod("putByte", long.class, byte.class);
-      clazz.getMethod("getInt", long.class);
-      clazz.getMethod("putInt", long.class, int.class);
-      clazz.getMethod("getLong", long.class);
-      clazz.getMethod("putLong", long.class, long.class);
-      clazz.getMethod("copyMemory", long.class, long.class, long.class);
-      clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
-      return true;
-    } catch (Throwable e) {
-      logger.log(
-          Level.WARNING,
-          "platform method missing - proto runtime falling back to safer methods: " + e);
-    }
-    return false;
+    return MEMORY_ACCESSOR.supportsUnsafeByteBufferOperations();
   }
 
-  private static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
+  static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
     if (!Android.isOnAndroidDevice()) {
       return false;
     }
@@ -546,6 +488,43 @@
       return unsafe.objectFieldOffset(field);
     }
 
+    public final int arrayBaseOffset(Class<?> clazz) {
+      return unsafe.arrayBaseOffset(clazz);
+    }
+
+    public final int arrayIndexScale(Class<?> clazz) {
+      return unsafe.arrayIndexScale(clazz);
+    }
+
+    public abstract Object getStaticObject(Field field);
+
+    // Relative Address Operations ---------------------------------------------
+
+    // Indicates whether the following relative address operations are supported
+    // by this memory accessor.
+    public boolean supportsUnsafeArrayOperations() {
+      if (unsafe == null) {
+        return false;
+      }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("objectFieldOffset", Field.class);
+        clazz.getMethod("arrayBaseOffset", Class.class);
+        clazz.getMethod("arrayIndexScale", Class.class);
+        clazz.getMethod("getInt", Object.class, long.class);
+        clazz.getMethod("putInt", Object.class, long.class, int.class);
+        clazz.getMethod("getLong", Object.class, long.class);
+        clazz.getMethod("putLong", Object.class, long.class, long.class);
+        clazz.getMethod("getObject", Object.class, long.class);
+        clazz.getMethod("putObject", Object.class, long.class, Object.class);
+
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
+    }
+
     public abstract byte getByte(Object target, long offset);
 
     public abstract void putByte(Object target, long offset, byte value);
@@ -586,12 +565,29 @@
       unsafe.putObject(target, offset, value);
     }
 
-    public final int arrayBaseOffset(Class<?> clazz) {
-      return unsafe.arrayBaseOffset(clazz);
-    }
+    // Absolute Address Operations --------------------------------------------
 
-    public final int arrayIndexScale(Class<?> clazz) {
-      return unsafe.arrayIndexScale(clazz);
+    // Indicates whether the following absolute address operations are
+    // supported by this memory accessor.
+    public boolean supportsUnsafeByteBufferOperations() {
+      if (unsafe == null) {
+        return false;
+      }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        // Methods for getting direct buffer address.
+        clazz.getMethod("objectFieldOffset", Field.class);
+        clazz.getMethod("getLong", Object.class, long.class);
+
+        if (bufferAddressField() == null) {
+          return false;
+        }
+
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
     }
 
     public abstract byte getByte(long address);
@@ -606,8 +602,6 @@
 
     public abstract void putLong(long address, long value);
 
-    public abstract Object getStaticObject(Field field);
-
     public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length);
 
     public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length);
@@ -620,33 +614,32 @@
     }
 
     @Override
-    public byte getByte(long address) {
-      return unsafe.getByte(address);
+    public Object getStaticObject(Field field) {
+      return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
     }
 
     @Override
-    public void putByte(long address, byte value) {
-      unsafe.putByte(address, value);
-    }
+    public boolean supportsUnsafeArrayOperations() {
+      if (!super.supportsUnsafeArrayOperations()) {
+        return false;
+      }
 
-    @Override
-    public int getInt(long address) {
-      return unsafe.getInt(address);
-    }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("getByte", Object.class, long.class);
+        clazz.getMethod("putByte", Object.class, long.class, byte.class);
+        clazz.getMethod("getBoolean", Object.class, long.class);
+        clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
+        clazz.getMethod("getFloat", Object.class, long.class);
+        clazz.getMethod("putFloat", Object.class, long.class, float.class);
+        clazz.getMethod("getDouble", Object.class, long.class);
+        clazz.getMethod("putDouble", Object.class, long.class, double.class);
 
-    @Override
-    public void putInt(long address, int value) {
-      unsafe.putInt(address, value);
-    }
-
-    @Override
-    public long getLong(long address) {
-      return unsafe.getLong(address);
-    }
-
-    @Override
-    public void putLong(long address, long value) {
-      unsafe.putLong(address, value);
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
     }
 
     @Override
@@ -690,6 +683,60 @@
     }
 
     @Override
+    public boolean supportsUnsafeByteBufferOperations() {
+      if (!super.supportsUnsafeByteBufferOperations()) {
+        return false;
+      }
+
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("getByte", long.class);
+        clazz.getMethod("putByte", long.class, byte.class);
+        clazz.getMethod("getInt", long.class);
+        clazz.getMethod("putInt", long.class, int.class);
+        clazz.getMethod("getLong", long.class);
+        clazz.getMethod("putLong", long.class, long.class);
+        clazz.getMethod("copyMemory", long.class, long.class, long.class);
+        clazz.getMethod(
+            "copyMemory", Object.class, long.class, Object.class, long.class, long.class);
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
+    }
+
+    @Override
+    public byte getByte(long address) {
+      return unsafe.getByte(address);
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      unsafe.putByte(address, value);
+    }
+
+    @Override
+    public int getInt(long address) {
+      return unsafe.getInt(address);
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      unsafe.putInt(address, value);
+    }
+
+    @Override
+    public long getLong(long address) {
+      return unsafe.getLong(address);
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      unsafe.putLong(address, value);
+    }
+
+    @Override
     public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
       unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length);
     }
@@ -698,11 +745,6 @@
     public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
       unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length);
     }
-
-    @Override
-    public Object getStaticObject(Field field) {
-      return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
-    }
   }
 
   private static final class Android64MemoryAccessor extends MemoryAccessor {
@@ -712,33 +754,12 @@
     }
 
     @Override
-    public byte getByte(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putByte(long address, byte value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getInt(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putInt(long address, int value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public long getLong(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putLong(long address, long value) {
-      throw new UnsupportedOperationException();
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
     }
 
     @Override
@@ -798,6 +819,41 @@
     }
 
     @Override
+    public boolean supportsUnsafeByteBufferOperations() {
+      return false;
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
       throw new UnsupportedOperationException();
     }
@@ -806,15 +862,6 @@
     public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
       throw new UnsupportedOperationException();
     }
-
-    @Override
-    public Object getStaticObject(Field field) {
-      try {
-        return field.get(null);
-      } catch (IllegalAccessException e) {
-        return null;
-      }
-    }
   }
 
   private static final class Android32MemoryAccessor extends MemoryAccessor {
@@ -832,33 +879,12 @@
     }
 
     @Override
-    public byte getByte(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putByte(long address, byte value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getInt(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putInt(long address, int value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public long getLong(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putLong(long address, long value) {
-      throw new UnsupportedOperationException();
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
     }
 
     @Override
@@ -918,6 +944,41 @@
     }
 
     @Override
+    public boolean supportsUnsafeByteBufferOperations() {
+      return false;
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
       throw new UnsupportedOperationException();
     }
@@ -926,15 +987,6 @@
     public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
       throw new UnsupportedOperationException();
     }
-
-    @Override
-    public Object getStaticObject(Field field) {
-      try {
-        return field.get(null);
-      } catch (IllegalAccessException e) {
-        return null;
-      }
-    }
   }
 
   private static byte getByteBigEndian(Object target, long offset) {
@@ -974,4 +1026,11 @@
   private static void putBooleanLittleEndian(Object target, long offset, boolean value) {
     putByteLittleEndian(target, offset, (byte) (value ? 1 : 0));
   }
+
+  private static void logMissingMethod(Throwable e) {
+    Logger.getLogger(UnsafeUtil.class.getName())
+        .log(
+            Level.WARNING,
+            "platform method missing - proto runtime falling back to safer methods: " + e);
+  }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
index cc979ac..4bc8d10 100644
--- a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -283,7 +283,7 @@
     Message.Builder abstractMessageBuilder =
         new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
     // mergeFrom() should not throw initialization error.
-    abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+    Message unused1 = abstractMessageBuilder.mergeFrom(bytes).buildPartial();
     try {
       abstractMessageBuilder.mergeFrom(bytes).build();
       fail();
@@ -295,7 +295,7 @@
     Message.Builder dynamicMessageBuilder =
         DynamicMessage.newBuilder(TestRequiredForeign.getDescriptor());
     // mergeFrom() should not throw initialization error.
-    dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+    Message unused2 = dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
     try {
       dynamicMessageBuilder.mergeFrom(bytes).build();
       fail();
diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index 532052c..10d156e 100644
--- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -1142,6 +1142,39 @@
     }
   }
 
+  public void testIterableByteBufferInputStreamReadBytesWithAlias() throws Exception {
+    ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
+    CodedOutputStream output = CodedOutputStream.newInstance(byteArrayStream);
+    // A bytes field large enough that won't fit into the default block buffer.
+    // 4.5 is to test the case where the total size of input is not aligned with DEFAULT_BLOCK_SIZE.
+    final int bytesLength = DEFAULT_BLOCK_SIZE * 4 + (DEFAULT_BLOCK_SIZE / 2);
+    byte[] bytes = new byte[bytesLength];
+    for (int i = 0; i < bytesLength; i++) {
+      bytes[i] = (byte) (i % 256);
+    }
+    output.writeByteArrayNoTag(bytes);
+    output.flush();
+
+    // Input data is split into multiple ByteBuffers so that a single bytes spans across them.
+    // CodedInputStream with aliasing will decode it as a consequent rope by wrapping ByteBuffers.
+    byte[] data = byteArrayStream.toByteArray();
+    ArrayList<ByteBuffer> input = new ArrayList<>();
+    for (int i = 0; i < data.length; i += DEFAULT_BLOCK_SIZE) {
+      int rl = Math.min(DEFAULT_BLOCK_SIZE, data.length - i);
+      ByteBuffer rb = ByteBuffer.allocateDirect(rl);
+      rb.put(data, i, rl);
+      rb.flip();
+      input.add(rb);
+    }
+    final CodedInputStream inputStream = CodedInputStream.newInstance(input, true);
+    inputStream.enableAliasing(true);
+
+    ByteString result = inputStream.readBytes();
+    for (int i = 0; i < bytesLength; i++) {
+      assertEquals((byte) (i % 256), result.byteAt(i));
+    }
+  }
+
   public void testCompatibleTypes() throws Exception {
     long data = 0x100000000L;
     Int64Message message = Int64Message.newBuilder().setData(data).build();
@@ -1196,7 +1229,7 @@
       // Expected
     }
   }
-  
+
   public void testMaliciousInputStream() throws Exception {
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream);
@@ -1210,17 +1243,17 @@
         return super.read(b, off, len);
       }
     };
-    
+
     // test ByteString
-    
+
     CodedInputStream codedInputStream = CodedInputStream.newInstance(inputStream, 1);
     ByteString byteString = codedInputStream.readBytes();
     assertEquals(0x0, byteString.byteAt(0));
     maliciousCapture.get(1)[0] = 0x9;
     assertEquals(0x0, byteString.byteAt(0));
-    
+
     // test ByteBuffer
-    
+
     inputStream.reset();
     maliciousCapture.clear();
     codedInputStream = CodedInputStream.newInstance(inputStream, 1);
@@ -1228,10 +1261,10 @@
     assertEquals(0x0, byteBuffer.get(0));
     maliciousCapture.get(1)[0] = 0x9;
     assertEquals(0x0, byteBuffer.get(0));
-    
+
 
     // test byte[]
-    
+
     inputStream.reset();
     maliciousCapture.clear();
     codedInputStream = CodedInputStream.newInstance(inputStream, 1);
@@ -1241,7 +1274,7 @@
     assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
 
     // test rawBytes
-    
+
     inputStream.reset();
     maliciousCapture.clear();
     codedInputStream = CodedInputStream.newInstance(inputStream, 1);
@@ -1251,4 +1284,33 @@
     maliciousCapture.get(1)[0] = 0x9;
     assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
   }
+
+  public void testInvalidInputYieldsInvalidProtocolBufferException_readTag() throws Exception {
+    byte[] input = new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x77};
+    CodedInputStream inputStream = CodedInputStream.newInstance(input);
+    try {
+      inputStream.readTag();
+      int size = inputStream.readRawVarint32();
+      inputStream.pushLimit(size);
+      inputStream.readTag();
+      fail();
+    } catch (InvalidProtocolBufferException ex) {
+      // Expected.
+    }
+  }
+
+  public void testInvalidInputYieldsInvalidProtocolBufferException_readBytes() throws Exception {
+    byte[] input =
+        new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x67, 0x1a, 0x1a};
+    CodedInputStream inputStream = CodedInputStream.newInstance(input);
+    try {
+      inputStream.readTag();
+      int size = inputStream.readRawVarint32();
+      inputStream.pushLimit(size);
+      inputStream.readBytes();
+      fail();
+    } catch (InvalidProtocolBufferException ex) {
+      // Expected.
+    }
+  }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
index 74d42c6..b98b332 100644
--- a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -804,4 +804,8 @@
             .build();
     assertEquals(8, msg.getExtension(NestedExtension.MyNestedExtension.default_).intValue());
   }
+
+  public void testDefaultDescriptorExtensionRange() throws Exception {
+    assertTrue(new Descriptor("default").isExtensionNumber(1));
+  }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
index fe37ea8..cd40ffa 100644
--- a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -69,7 +69,7 @@
     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
     Message firstMessage = builder.build();
     // double build()
-    builder.build();
+    Message unused = builder.build();
     // clear() after build()
     builder.clear();
     // setters after build()
diff --git a/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
index c6aed07..70466ba 100644
--- a/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
+++ b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
@@ -41,6 +41,7 @@
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
+import org.junit.Ignore;
 
 /**
  * Tests for {@link ExtensionRegistryFactory} and the {@link ExtensionRegistry} instances it
@@ -52,7 +53,13 @@
  *
  * <p>The test mechanism employed here is based on the pattern in {@code
  * com.google.common.util.concurrent.AbstractFutureFallbackAtomicHelperTest}
+ *
+ * <p> This test is temporarily disabled due to what appears to be a subtle change to class loading
+ * behavior in Java 11. That seems to have broken the way the test uses a custom ClassLoader to
+ * exercise Lite functionality.
  */
+@SuppressWarnings("JUnit4ClassUsedInJUnit3")
+@Ignore
 public class ExtensionRegistryFactoryTest extends TestCase {
 
   // A classloader which blacklists some non-Lite classes.
diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
index 53ec6fe..7266729 100644
--- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
+++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -38,6 +38,7 @@
 import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
 import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly;
 import com.google.protobuf.FieldPresenceTestProto.TestRepeatedFieldsOnly;
+import com.google.protobuf.testing.proto.TestProto3Optional;
 import protobuf_unittest.UnittestProto;
 import junit.framework.TestCase;
 
@@ -65,6 +66,11 @@
     assertFalse(hasMethod(classWithoutFieldPresence, "has" + camelName));
   }
 
+  private static void assertHasMethodExisting(Class<?> clazz, String camelName) {
+    assertTrue(hasMethod(clazz, "get" + camelName));
+    assertTrue(hasMethod(clazz, "has" + camelName));
+  }
+
   public void testHasMethod() {
     // Optional non-message fields don't have a hasFoo() method generated.
     assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OptionalInt32");
@@ -86,21 +92,125 @@
     assertFalse(TestAllTypes.getDefaultInstance().hasOptionalNestedMessage());
     assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
 
-    // oneof fields don't have hasFoo() methods for non-message types.
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofUint32");
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofString");
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofBytes");
+    // oneof fields support hasFoo() methods for non-message types.
+    assertHasMethodExisting(TestAllTypes.class, "OneofUint32");
+    assertHasMethodExisting(TestAllTypes.class, "OneofString");
+    assertHasMethodExisting(TestAllTypes.class, "OneofBytes");
     assertFalse(TestAllTypes.getDefaultInstance().hasOneofNestedMessage());
     assertFalse(TestAllTypes.newBuilder().hasOneofNestedMessage());
 
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofUint32");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofString");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofBytes");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofUint32");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofString");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofBytes");
   }
 
+  public void testHasMethodForProto3Optional() throws Exception {
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalInt32());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalInt64());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalUint32());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalUint64());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalSint32());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalSint64());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFixed32());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFixed64());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFloat());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalDouble());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalBool());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalString());
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalBytes());
+
+    TestProto3Optional.Builder builder = TestProto3Optional.newBuilder().setOptionalInt32(0);
+    assertTrue(builder.hasOptionalInt32());
+    assertTrue(builder.build().hasOptionalInt32());
+
+    TestProto3Optional.Builder otherBuilder = TestProto3Optional.newBuilder().setOptionalInt32(1);
+    otherBuilder.mergeFrom(builder.build());
+    assertTrue(otherBuilder.hasOptionalInt32());
+    assertEquals(0, otherBuilder.getOptionalInt32());
+
+    TestProto3Optional.Builder builder3 =
+        TestProto3Optional.newBuilder().setOptionalNestedEnumValue(5);
+    assertTrue(builder3.hasOptionalNestedEnum());
+
+    TestProto3Optional.Builder builder4 =
+        TestProto3Optional.newBuilder().setOptionalNestedEnum(TestProto3Optional.NestedEnum.FOO);
+    assertTrue(builder4.hasOptionalNestedEnum());
+
+    TestProto3Optional proto = TestProto3Optional.parseFrom(builder.build().toByteArray());
+    assertTrue(proto.hasOptionalInt32());
+    assertTrue(proto.toBuilder().hasOptionalInt32());
+  }
+
+  private static void assertProto3OptionalReflection(String name) throws Exception {
+    FieldDescriptor fieldDescriptor = TestProto3Optional.getDescriptor().findFieldByName(name);
+    OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+    assertNotNull(fieldDescriptor.getContainingOneof());
+    assertTrue(fieldDescriptor.hasOptionalKeyword());
+    assertTrue(fieldDescriptor.hasPresence());
+
+    assertFalse(TestProto3Optional.getDefaultInstance().hasOneof(oneofDescriptor));
+    assertNull(TestProto3Optional.getDefaultInstance().getOneofFieldDescriptor(oneofDescriptor));
+
+    TestProto3Optional.Builder builder = TestProto3Optional.newBuilder();
+    builder.setField(fieldDescriptor, fieldDescriptor.getDefaultValue());
+    assertTrue(builder.hasField(fieldDescriptor));
+    assertEquals(fieldDescriptor.getDefaultValue(), builder.getField(fieldDescriptor));
+    assertTrue(builder.build().hasField(fieldDescriptor));
+    assertEquals(fieldDescriptor.getDefaultValue(), builder.build().getField(fieldDescriptor));
+    assertTrue(builder.hasOneof(oneofDescriptor));
+    assertEquals(fieldDescriptor, builder.getOneofFieldDescriptor(oneofDescriptor));
+    assertTrue(builder.build().hasOneof(oneofDescriptor));
+    assertEquals(fieldDescriptor, builder.build().getOneofFieldDescriptor(oneofDescriptor));
+
+    TestProto3Optional.Builder otherBuilder = TestProto3Optional.newBuilder();
+    otherBuilder.mergeFrom(builder.build());
+    assertTrue(otherBuilder.hasField(fieldDescriptor));
+    assertEquals(fieldDescriptor.getDefaultValue(), otherBuilder.getField(fieldDescriptor));
+
+    TestProto3Optional proto = TestProto3Optional.parseFrom(builder.build().toByteArray());
+    assertTrue(proto.hasField(fieldDescriptor));
+    assertTrue(proto.toBuilder().hasField(fieldDescriptor));
+
+    DynamicMessage.Builder dynamicBuilder =
+        DynamicMessage.newBuilder(TestProto3Optional.getDescriptor());
+    dynamicBuilder.setField(fieldDescriptor, fieldDescriptor.getDefaultValue());
+    assertTrue(dynamicBuilder.hasField(fieldDescriptor));
+    assertEquals(fieldDescriptor.getDefaultValue(), dynamicBuilder.getField(fieldDescriptor));
+    assertTrue(dynamicBuilder.build().hasField(fieldDescriptor));
+    assertEquals(
+        fieldDescriptor.getDefaultValue(), dynamicBuilder.build().getField(fieldDescriptor));
+    assertTrue(dynamicBuilder.hasOneof(oneofDescriptor));
+    assertEquals(fieldDescriptor, dynamicBuilder.getOneofFieldDescriptor(oneofDescriptor));
+    assertTrue(dynamicBuilder.build().hasOneof(oneofDescriptor));
+    assertEquals(fieldDescriptor, dynamicBuilder.build().getOneofFieldDescriptor(oneofDescriptor));
+
+    DynamicMessage.Builder otherDynamicBuilder =
+        DynamicMessage.newBuilder(TestProto3Optional.getDescriptor());
+    otherDynamicBuilder.mergeFrom(dynamicBuilder.build());
+    assertTrue(otherDynamicBuilder.hasField(fieldDescriptor));
+    assertEquals(fieldDescriptor.getDefaultValue(), otherDynamicBuilder.getField(fieldDescriptor));
+
+    DynamicMessage dynamicProto =
+        DynamicMessage.parseFrom(TestProto3Optional.getDescriptor(), builder.build().toByteArray());
+    assertTrue(dynamicProto.hasField(fieldDescriptor));
+    assertTrue(dynamicProto.toBuilder().hasField(fieldDescriptor));
+  }
+
+  public void testProto3Optional_reflection() throws Exception {
+    assertProto3OptionalReflection("optional_int32");
+    assertProto3OptionalReflection("optional_int64");
+    assertProto3OptionalReflection("optional_uint32");
+    assertProto3OptionalReflection("optional_uint64");
+    assertProto3OptionalReflection("optional_sint32");
+    assertProto3OptionalReflection("optional_sint64");
+    assertProto3OptionalReflection("optional_fixed32");
+    assertProto3OptionalReflection("optional_fixed64");
+    assertProto3OptionalReflection("optional_float");
+    assertProto3OptionalReflection("optional_double");
+    assertProto3OptionalReflection("optional_bool");
+    assertProto3OptionalReflection("optional_string");
+    assertProto3OptionalReflection("optional_bytes");
+  }
 
   public void testOneofEquals() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 9261a36..840e13e 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -76,6 +76,7 @@
  *
  * @author kenton@google.com Kenton Varda
  */
+@SuppressWarnings({"ProtoBuilderReturnValueIgnored", "ReturnValueIgnored"})
 public class GeneratedMessageTest extends TestCase {
   TestUtil.ReflectionTester reflectionTester =
       new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
diff --git a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
index 9f64b6b..4177a47 100644
--- a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -514,6 +514,20 @@
     assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
   }
 
+  public void testNewInput_readZeroBytes() throws IOException {
+    InputStream input = stringUnderTest.newInput();
+    assertEquals(
+        classUnderTest + " InputStream.read() returns 0 when told to read 0 bytes and not at EOF",
+        0,
+        input.read(new byte[0]));
+
+    input.skip(input.available());
+    assertEquals(
+        classUnderTest + " InputStream.read() returns -1 when told to read 0 bytes at EOF",
+        -1,
+        input.read(new byte[0]));
+  }
+
   public void testNewInput_skip() throws IOException {
     InputStream input = stringUnderTest.newInput();
     int stringSize = stringUnderTest.size();
diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
index adca1d5..4de09cd 100644
--- a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -77,44 +77,44 @@
 
   private void copyMapValues(TestMap source, TestMap.Builder destination) {
     destination
-        .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
-        .putAllInt32ToStringField(source.getInt32ToStringField())
-        .putAllInt32ToBytesField(source.getInt32ToBytesField())
-        .putAllInt32ToEnumField(source.getInt32ToEnumField())
-        .putAllInt32ToMessageField(source.getInt32ToMessageField())
-        .putAllStringToInt32Field(source.getStringToInt32Field());
+        .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap())
+        .putAllInt32ToStringField(source.getInt32ToStringFieldMap())
+        .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap())
+        .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap())
+        .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap())
+        .putAllStringToInt32Field(source.getStringToInt32FieldMap());
   }
 
   private void assertMapValuesSet(TestMap message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("11", message.getInt32ToStringField().get(1));
-    assertEquals("22", message.getInt32ToStringField().get(2));
-    assertEquals("33", message.getInt32ToStringField().get(3));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("11", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("22", message.getInt32ToStringFieldMap().get(2));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(11, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(22, message.getStringToInt32Field().get("2").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
   }
 
   private void updateMapValues(TestMap.Builder builder) {
@@ -152,49 +152,49 @@
   }
 
   private void assertMapValuesUpdated(TestMap message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
-    assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
+    assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("111", message.getInt32ToStringField().get(1));
-    assertEquals("33", message.getInt32ToStringField().get(3));
-    assertEquals("44", message.getInt32ToStringField().get(4));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("111", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
+    assertEquals("44", message.getInt32ToStringFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
-    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
+    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
-    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
+    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
-    assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
+    assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(111, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
-    assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
+    assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue());
   }
 
   private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
-    assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
-    assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
   }
 
@@ -206,13 +206,13 @@
     TestMap.Builder builder = TestMap.newBuilder();
     TestMap message = builder.build();
     builder.putInt32ToInt32Field(1, 2);
-    assertTrue(message.getInt32ToInt32Field().isEmpty());
+    assertTrue(message.getInt32ToInt32FieldMap().isEmpty());
     message = builder.build();
-    assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
-    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap());
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap());
     builder.putInt32ToInt32Field(2, 3);
-    assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
-    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap());
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap());
   }
 
   public void testGetMapIsImmutable() {
@@ -226,13 +226,13 @@
   }
 
   private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
-    assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
-    assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
-    assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
-    assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
+    assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
+    assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
+    assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
+    assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
     assertImmutable(
-        testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
-    assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
+        testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
+    assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
   }
 
   private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
@@ -254,30 +254,31 @@
 
   public void testMutableMapLifecycle() {
     TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2);
-    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
-    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32FieldMap());
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap());
     builder.putInt32ToInt32Field(2, 3);
-    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap());
 
     builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR);
-    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
-    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumFieldMap());
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumFieldMap());
     builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO);
     assertEquals(
-        newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField());
+        newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+        builder.getInt32ToEnumFieldMap());
 
     builder.putInt32ToStringField(1, "1");
-    assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
-    assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+    assertEquals(newMap(1, "1"), builder.build().getInt32ToStringFieldMap());
+    assertEquals(newMap(1, "1"), builder.getInt32ToStringFieldMap());
     builder.putInt32ToStringField(2, "2");
-    assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringField());
+    assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringFieldMap());
 
     builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance());
     assertEquals(
         newMap(1, TestMap.MessageValue.getDefaultInstance()),
-        builder.build().getInt32ToMessageField());
+        builder.build().getInt32ToMessageFieldMap());
     assertEquals(
-        newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField());
+        newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageFieldMap());
     builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance());
     assertEquals(
         newMap(
@@ -285,7 +286,7 @@
             TestMap.MessageValue.getDefaultInstance(),
             2,
             TestMap.MessageValue.getDefaultInstance()),
-        builder.getInt32ToMessageField());
+        builder.getInt32ToMessageFieldMap());
   }
 
   public void testGettersAndSetters() throws Exception {
@@ -415,7 +416,7 @@
     } catch (InvalidProtocolBufferException expected) {
       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
       map = (TestMap) expected.getUnfinishedMessage();
-      assertTrue(map.getInt32ToMessageField().isEmpty());
+      assertTrue(map.getInt32ToMessageFieldMap().isEmpty());
     }
 
     map =
@@ -476,14 +477,14 @@
     TestMap message = TestMap.parseFrom(data);
     // Entries with unknown enum values will be stored into UnknownFieldSet so
     // there is only one entry in the map.
-    assertEquals(1, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+    assertEquals(1, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
     // Serializing and parsing should preserve the unknown entry.
     data = message.toByteString();
     TestUnknownEnumValue messageWithUnknownEnums = TestUnknownEnumValue.parseFrom(data);
-    assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
-    assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+    assertEquals(2, messageWithUnknownEnums.getInt32ToInt32FieldMap().size());
+    assertEquals(1, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(2).intValue());
   }
 
   public void testIterationOrder() throws Exception {
@@ -493,7 +494,7 @@
 
     assertEquals(
         Arrays.asList("1", "2", "3"),
-        new ArrayList<String>(message.getStringToInt32Field().keySet()));
+        new ArrayList<String>(message.getStringToInt32FieldMap().keySet()));
   }
 
   private static <K, V> Map<K, V> newMap(K key1, V value1) {
@@ -513,10 +514,10 @@
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap());
-    assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap());
-    assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap());
-    assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap());
+    assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap());
+    assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap());
+    assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
+    assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap());
   }
 
   public void testContains() {
diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
index bb70632..25c5625 100644
--- a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -119,44 +119,44 @@
 
   private void copyMapValues(TestMap source, TestMap.Builder destination) {
     destination
-        .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
-        .putAllInt32ToStringField(source.getInt32ToStringField())
-        .putAllInt32ToBytesField(source.getInt32ToBytesField())
-        .putAllInt32ToEnumField(source.getInt32ToEnumField())
-        .putAllInt32ToMessageField(source.getInt32ToMessageField())
-        .putAllStringToInt32Field(source.getStringToInt32Field());
+        .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap())
+        .putAllInt32ToStringField(source.getInt32ToStringFieldMap())
+        .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap())
+        .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap())
+        .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap())
+        .putAllStringToInt32Field(source.getStringToInt32FieldMap());
   }
 
   private void assertMapValuesSet(TestMapOrBuilder message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("11", message.getInt32ToStringField().get(1));
-    assertEquals("22", message.getInt32ToStringField().get(2));
-    assertEquals("33", message.getInt32ToStringField().get(3));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("11", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("22", message.getInt32ToStringFieldMap().get(2));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(11, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(22, message.getStringToInt32Field().get("2").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
   }
 
   private void updateMapValuesUsingMutableMap(TestMap.Builder builder) {
@@ -236,49 +236,49 @@
   }
 
   private void assertMapValuesUpdated(TestMap message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
-    assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
+    assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("111", message.getInt32ToStringField().get(1));
-    assertEquals("33", message.getInt32ToStringField().get(3));
-    assertEquals("44", message.getInt32ToStringField().get(4));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("111", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
+    assertEquals("44", message.getInt32ToStringFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
-    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
+    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
-    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
+    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
-    assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
+    assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(111, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
-    assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
+    assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue());
   }
 
   private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
-    assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
-    assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
   }
 
@@ -293,13 +293,13 @@
   }
 
   private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
-    assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
-    assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
-    assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
-    assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
+    assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
+    assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
+    assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
+    assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
     assertImmutable(
-        testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
-    assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
+        testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
+    assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
   }
 
   private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
@@ -563,7 +563,7 @@
     } catch (InvalidProtocolBufferException expected) {
       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
       map = (TestMap) expected.getUnfinishedMessage();
-      assertTrue(map.getInt32ToMessageField().isEmpty());
+      assertTrue(map.getInt32ToMessageFieldMap().isEmpty());
     }
 
     map =
@@ -698,8 +698,8 @@
     builder.clearField(f("int32_to_int32_field"));
     builder.clearField(f("int32_to_message_field"));
     message = builder.build();
-    assertEquals(0, message.getInt32ToInt32Field().size());
-    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getInt32ToInt32FieldMap().size());
+    assertEquals(0, message.getInt32ToMessageFieldMap().size());
 
     // Test setField()
     setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44));
@@ -710,10 +710,10 @@
             111, MessageValue.newBuilder().setValue(222).build(),
             333, MessageValue.newBuilder().setValue(444).build()));
     message = builder.build();
-    assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
-    assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
-    assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
-    assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+    assertEquals(22, message.getInt32ToInt32FieldMap().get(11).intValue());
+    assertEquals(44, message.getInt32ToInt32FieldMap().get(33).intValue());
+    assertEquals(222, message.getInt32ToMessageFieldMap().get(111).getValue());
+    assertEquals(444, message.getInt32ToMessageFieldMap().get(333).getValue());
 
     // Test addRepeatedField
     builder.addRepeatedField(
@@ -726,8 +726,8 @@
             555,
             MessageValue.newBuilder().setValue(666).build()));
     message = builder.build();
-    assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
-    assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+    assertEquals(66, message.getInt32ToInt32FieldMap().get(55).intValue());
+    assertEquals(666, message.getInt32ToMessageFieldMap().get(555).getValue());
 
     // Test addRepeatedField (overriding existing values)
     builder.addRepeatedField(
@@ -740,8 +740,8 @@
             555,
             MessageValue.newBuilder().setValue(555).build()));
     message = builder.build();
-    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
-    assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+    assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue());
+    assertEquals(555, message.getInt32ToMessageFieldMap().get(555).getValue());
 
     // Test setRepeatedField
     for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
@@ -755,9 +755,9 @@
       builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
     }
     message = builder.build();
-    assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
-    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+    assertEquals(11, message.getInt32ToInt32FieldMap().get(22).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(44).intValue());
+    assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue());
   }
 
   // See additional coverage in TextFormatTest.java.
@@ -844,16 +844,16 @@
     TestMap message = TestMap.parseFrom(data);
     // Entries with unknown enum values will be stored into UnknownFieldSet so
     // there is only one entry in the map.
-    assertEquals(1, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+    assertEquals(1, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
     // UnknownFieldSet should not be empty.
     assertFalse(message.getUnknownFields().asMap().isEmpty());
     // Serializing and parsing should preserve the unknown entry.
     data = message.toByteString();
     TestUnknownEnumValue messageWithUnknownEnums = TestUnknownEnumValue.parseFrom(data);
-    assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
-    assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+    assertEquals(2, messageWithUnknownEnums.getInt32ToInt32FieldMap().size());
+    assertEquals(1, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(2).intValue());
   }
 
   public void testRequiredMessage() throws Exception {
@@ -874,8 +874,8 @@
     ByteString data = builder.build().toByteString();
 
     TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
-    assertEquals(2, message.getRecursiveMapField().get(1).getValue());
-    assertEquals(4, message.getRecursiveMapField().get(3).getValue());
+    assertEquals(2, message.getRecursiveMapFieldMap().get(1).getValue());
+    assertEquals(4, message.getRecursiveMapFieldMap().get(3).getValue());
   }
 
   public void testIterationOrder() throws Exception {
@@ -885,7 +885,7 @@
 
     assertEquals(
         Arrays.asList("1", "2", "3"),
-        new ArrayList<String>(message.getStringToInt32Field().keySet()));
+        new ArrayList<String>(message.getStringToInt32FieldMap().keySet()));
   }
 
   public void testContains() {
@@ -1163,8 +1163,8 @@
   }
 
   public void testReservedWordsFieldNames() {
-    ReservedAsMapField.newBuilder().build();
-    ReservedAsMapFieldWithEnumValue.newBuilder().build();
+    ReservedAsMapField unused1 = ReservedAsMapField.newBuilder().build();
+    ReservedAsMapFieldWithEnumValue unused2 = ReservedAsMapFieldWithEnumValue.newBuilder().build();
   }
 
   public void testGetMap() {
@@ -1172,9 +1172,9 @@
     setMapValuesUsingAccessors(builder);
     assertMapValuesSet(builder);
     TestMap message = builder.build();
-    assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap());
-    assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap());
-    assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap());
-    assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap());
+    assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap());
+    assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap());
+    assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
+    assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap());
   }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java
index d18fd13..33282ad 100644
--- a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java
@@ -84,44 +84,44 @@
 
   private void copyMapValues(TestMap source, TestMap.Builder destination) {
     destination
-        .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
-        .putAllInt32ToStringField(source.getInt32ToStringField())
-        .putAllInt32ToBytesField(source.getInt32ToBytesField())
-        .putAllInt32ToEnumField(source.getInt32ToEnumField())
-        .putAllInt32ToMessageField(source.getInt32ToMessageField())
-        .putAllStringToInt32Field(source.getStringToInt32Field());
+        .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap())
+        .putAllInt32ToStringField(source.getInt32ToStringFieldMap())
+        .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap())
+        .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap())
+        .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap())
+        .putAllStringToInt32Field(source.getStringToInt32FieldMap());
   }
 
   private void assertMapValuesSet(TestMap message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("11", message.getInt32ToStringField().get(1));
-    assertEquals("22", message.getInt32ToStringField().get(2));
-    assertEquals("33", message.getInt32ToStringField().get(3));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("11", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("22", message.getInt32ToStringFieldMap().get(2));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(11, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(22, message.getStringToInt32Field().get("2").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
   }
 
   private void updateMapValues(TestMap.Builder builder) {
@@ -159,49 +159,49 @@
   }
 
   private void assertMapValuesUpdated(TestMap message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
-    assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
+    assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("111", message.getInt32ToStringField().get(1));
-    assertEquals("33", message.getInt32ToStringField().get(3));
-    assertEquals("44", message.getInt32ToStringField().get(4));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("111", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
+    assertEquals("44", message.getInt32ToStringFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
-    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
+    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
-    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
+    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
-    assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
+    assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(111, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
-    assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
+    assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue());
   }
 
   private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
-    assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
-    assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
   }
 
@@ -213,12 +213,12 @@
     TestMap.Builder builder = TestMap.newBuilder();
     TestMap message = builder.build();
     builder.putInt32ToInt32Field(1, 2);
-    assertTrue(message.getInt32ToInt32Field().isEmpty());
-    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    assertTrue(message.getInt32ToInt32FieldMap().isEmpty());
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap());
     message = builder.build();
     builder.putInt32ToInt32Field(2, 3);
-    assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
-    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap());
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap());
   }
 
   public void testGetMapIsImmutable() {
@@ -232,13 +232,13 @@
   }
 
   private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
-    assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
-    assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
-    assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
-    assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
+    assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
+    assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
+    assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
+    assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
     assertImmutable(
-        testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
-    assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
+        testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
+    assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
   }
 
   private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
@@ -266,30 +266,31 @@
 
   public void testMutableMapLifecycle() {
     TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2);
-    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
-    assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2), builder.build().getInt32ToInt32FieldMap());
+    assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap());
     builder.putInt32ToInt32Field(2, 3);
-    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+    assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap());
 
     builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR);
-    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
-    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumFieldMap());
+    assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumFieldMap());
     builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO);
     assertEquals(
-        newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField());
+        newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+        builder.getInt32ToEnumFieldMap());
 
     builder.putInt32ToStringField(1, "1");
-    assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
-    assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+    assertEquals(newMap(1, "1"), builder.build().getInt32ToStringFieldMap());
+    assertEquals(newMap(1, "1"), builder.getInt32ToStringFieldMap());
     builder.putInt32ToStringField(2, "2");
-    assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringField());
+    assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringFieldMap());
 
     builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance());
     assertEquals(
         newMap(1, TestMap.MessageValue.getDefaultInstance()),
-        builder.build().getInt32ToMessageField());
+        builder.build().getInt32ToMessageFieldMap());
     assertEquals(
-        newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField());
+        newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageFieldMap());
     builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance());
     assertEquals(
         newMap(
@@ -297,7 +298,7 @@
             TestMap.MessageValue.getDefaultInstance(),
             2,
             TestMap.MessageValue.getDefaultInstance()),
-        builder.getInt32ToMessageField());
+        builder.getInt32ToMessageFieldMap());
   }
 
   public void testGettersAndSetters() throws Exception {
@@ -342,12 +343,12 @@
     TestMap source = sourceBuilder.build();
 
     TestMap.Builder destinationBuilder = TestMap.newBuilder();
-    destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue());
+    destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap());
     TestMap destination = destinationBuilder.build();
 
-    assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
-    assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
-    assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue());
+    assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue());
+    assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue());
     assertEquals(3, destination.getInt32ToEnumFieldCount());
   }
 
@@ -459,7 +460,7 @@
     } catch (InvalidProtocolBufferException expected) {
       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
       map = (TestMap) expected.getUnfinishedMessage();
-      assertTrue(map.getInt32ToMessageField().isEmpty());
+      assertTrue(map.getInt32ToMessageFieldMap().isEmpty());
     }
 
     map =
@@ -524,24 +525,24 @@
             .putInt32ToEnumFieldValue(2, 1000); // unknown value.
     TestMap message = builder.build();
 
-    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(0));
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2));
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2));
 
     builder.putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value.
     message = builder.build();
-    assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2));
+    assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2));
 
     // Unknown enum values should be preserved after:
     //   1. Serialization and parsing.
     //   2. toBuild().
     //   3. mergeFrom().
     message = TestMap.parseFrom(message.toByteString());
-    assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue());
     builder = message.toBuilder();
-    assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
     builder = TestMap.newBuilder().mergeFrom(message);
-    assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
 
     // hashCode()/equals() should take unknown enum values into account.
     builder.putAllInt32ToEnumFieldValue(newMap(2, 1001));
@@ -550,7 +551,7 @@
     assertFalse(message.equals(message2));
     // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
     // should be the same.
-    assertEquals(message2.getInt32ToEnumField(), message.getInt32ToEnumField());
+    assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
   }
 
   public void testIterationOrder() throws Exception {
@@ -559,18 +560,18 @@
     TestMap message = builder.build();
 
     assertEquals(
-        Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32Field().keySet()));
+        Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet()));
   }
 
   public void testGetMap() {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap());
-    assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap());
-    assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap());
-    assertEquals(message.getInt32ToEnumFieldValue(), message.getInt32ToEnumFieldValueMap());
-    assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap());
+    assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap());
+    assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap());
+    assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
+    assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap());
+    assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap());
   }
 
   public void testContains() {
diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java
index 9f1ebae..c3b1fa3 100644
--- a/java/core/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MapTest.java
@@ -122,44 +122,44 @@
 
   private void copyMapValues(TestMap source, TestMap.Builder destination) {
     destination
-        .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
-        .putAllInt32ToStringField(source.getInt32ToStringField())
-        .putAllInt32ToBytesField(source.getInt32ToBytesField())
-        .putAllInt32ToEnumField(source.getInt32ToEnumField())
-        .putAllInt32ToMessageField(source.getInt32ToMessageField())
-        .putAllStringToInt32Field(source.getStringToInt32Field());
+        .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap())
+        .putAllInt32ToStringField(source.getInt32ToStringFieldMap())
+        .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap())
+        .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap())
+        .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap())
+        .putAllStringToInt32Field(source.getStringToInt32FieldMap());
   }
 
   private void assertMapValuesSet(TestMap message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("11", message.getInt32ToStringField().get(1));
-    assertEquals("22", message.getInt32ToStringField().get(2));
-    assertEquals("33", message.getInt32ToStringField().get(3));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("11", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("22", message.getInt32ToStringFieldMap().get(2));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(11, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(22, message.getStringToInt32Field().get("2").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
   }
 
   private void updateMapValuesUsingMutableMap(TestMap.Builder builder) {
@@ -239,49 +239,49 @@
   }
 
   private void assertMapValuesUpdated(TestMap message) {
-    assertEquals(3, message.getInt32ToInt32Field().size());
-    assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
-    assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+    assertEquals(3, message.getInt32ToInt32FieldMap().size());
+    assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
+    assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue());
 
-    assertEquals(3, message.getInt32ToStringField().size());
-    assertEquals("111", message.getInt32ToStringField().get(1));
-    assertEquals("33", message.getInt32ToStringField().get(3));
-    assertEquals("44", message.getInt32ToStringField().get(4));
+    assertEquals(3, message.getInt32ToStringFieldMap().size());
+    assertEquals("111", message.getInt32ToStringFieldMap().get(1));
+    assertEquals("33", message.getInt32ToStringFieldMap().get(3));
+    assertEquals("44", message.getInt32ToStringFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToBytesField().size());
-    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
-    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
-    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+    assertEquals(3, message.getInt32ToBytesFieldMap().size());
+    assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1));
+    assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
+    assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToEnumField().size());
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
-    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+    assertEquals(3, message.getInt32ToEnumFieldMap().size());
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
+    assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4));
 
-    assertEquals(3, message.getInt32ToMessageField().size());
-    assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
-    assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
-    assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+    assertEquals(3, message.getInt32ToMessageFieldMap().size());
+    assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue());
+    assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
+    assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue());
 
-    assertEquals(3, message.getStringToInt32Field().size());
-    assertEquals(111, message.getStringToInt32Field().get("1").intValue());
-    assertEquals(33, message.getStringToInt32Field().get("3").intValue());
-    assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+    assertEquals(3, message.getStringToInt32FieldMap().size());
+    assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue());
+    assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
+    assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue());
   }
 
   private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
-    assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
-    assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
+    assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
     assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
-    assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
+    assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
     assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
   }
 
@@ -296,13 +296,13 @@
   }
 
   private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
-    assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
-    assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
-    assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
-    assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
+    assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
+    assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
+    assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
+    assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
     assertImmutable(
-        testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
-    assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
+        testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
+    assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
   }
 
   private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
@@ -468,11 +468,13 @@
             .build();
 
     TestMap destination =
-        TestMap.newBuilder().putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue()).build();
+        TestMap.newBuilder()
+            .putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap())
+            .build();
 
-    assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
-    assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
-    assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue());
+    assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue());
+    assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue());
     assertEquals(3, destination.getInt32ToEnumFieldCount());
   }
 
@@ -583,7 +585,7 @@
     } catch (InvalidProtocolBufferException expected) {
       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
       map = (TestMap) expected.getUnfinishedMessage();
-      assertTrue(map.getInt32ToMessageField().isEmpty());
+      assertTrue(map.getInt32ToMessageFieldMap().isEmpty());
     }
 
     map =
@@ -644,14 +646,14 @@
     TestOnChangeEventPropagation.Builder parent = TestOnChangeEventPropagation.newBuilder();
     parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2);
     TestOnChangeEventPropagation message = parent.build();
-    assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+    assertEquals(2, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
 
     // Make a change using nested builder.
     parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3);
 
     // Should be able to observe the change.
     message = parent.build();
-    assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+    assertEquals(3, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
 
     // Make another change using mergeFrom()
     TestMap other = TestMap.newBuilder().putInt32ToInt32Field(1, 4).build();
@@ -659,14 +661,14 @@
 
     // Should be able to observe the change.
     message = parent.build();
-    assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+    assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
 
     // Make yet another change by clearing the nested builder.
     parent.getOptionalMessageBuilder().clear();
 
     // Should be able to observe the change.
     message = parent.build();
-    assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+    assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size());
   }
 
   public void testNestedBuilderOnChangeEventPropagationReflection() {
@@ -683,7 +685,7 @@
 
     // Should be able to observe the change.
     TestOnChangeEventPropagation message = parentBuilder.build();
-    assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
+    assertEquals(1, message.getOptionalMessage().getInt32ToInt32FieldMap().size());
 
     // Change the entry value.
     entryBuilder.putInt32ToInt32Field(1, 4);
@@ -692,7 +694,7 @@
 
     // Should be able to observe the change.
     message = parentBuilder.build();
-    assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+    assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
 
     // Clear the nested builder.
     testMapBuilder = parentBuilder.getOptionalMessageBuilder();
@@ -700,7 +702,7 @@
 
     // Should be able to observe the change.
     message = parentBuilder.build();
-    assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+    assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size());
   }
 
   // The following methods are used to test reflection API.
@@ -789,8 +791,8 @@
     builder.clearField(f("int32_to_int32_field"));
     builder.clearField(f("int32_to_message_field"));
     message = builder.build();
-    assertEquals(0, message.getInt32ToInt32Field().size());
-    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getInt32ToInt32FieldMap().size());
+    assertEquals(0, message.getInt32ToMessageFieldMap().size());
 
     // Test setField()
     setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44));
@@ -801,10 +803,10 @@
             111, MessageValue.newBuilder().setValue(222).build(),
             333, MessageValue.newBuilder().setValue(444).build()));
     message = builder.build();
-    assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
-    assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
-    assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
-    assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+    assertEquals(22, message.getInt32ToInt32FieldMap().get(11).intValue());
+    assertEquals(44, message.getInt32ToInt32FieldMap().get(33).intValue());
+    assertEquals(222, message.getInt32ToMessageFieldMap().get(111).getValue());
+    assertEquals(444, message.getInt32ToMessageFieldMap().get(333).getValue());
 
     // Test addRepeatedField
     builder.addRepeatedField(
@@ -817,8 +819,8 @@
             555,
             MessageValue.newBuilder().setValue(666).build()));
     message = builder.build();
-    assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
-    assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+    assertEquals(66, message.getInt32ToInt32FieldMap().get(55).intValue());
+    assertEquals(666, message.getInt32ToMessageFieldMap().get(555).getValue());
 
     // Test addRepeatedField (overriding existing values)
     builder.addRepeatedField(
@@ -831,8 +833,8 @@
             555,
             MessageValue.newBuilder().setValue(555).build()));
     message = builder.build();
-    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
-    assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+    assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue());
+    assertEquals(555, message.getInt32ToMessageFieldMap().get(555).getValue());
 
     // Test setRepeatedField
     for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
@@ -846,9 +848,9 @@
       builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
     }
     message = builder.build();
-    assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
-    assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
-    assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+    assertEquals(11, message.getInt32ToInt32FieldMap().get(22).intValue());
+    assertEquals(33, message.getInt32ToInt32FieldMap().get(44).intValue());
+    assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue());
   }
 
   // See additional coverage in TextFormatTest.java.
@@ -937,21 +939,21 @@
                     2, 1000)); // unknown value.
     TestMap message = builder.build();
 
-    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(0));
-    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
-    assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2));
-    assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0));
+    assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
+    assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2));
+    assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue());
 
     // Unknown enum values should be preserved after:
     //   1. Serialization and parsing.
     //   2. toBuild().
     //   3. mergeFrom().
     message = TestMap.parseFrom(message.toByteString());
-    assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue());
     builder = message.toBuilder();
-    assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
     builder = TestMap.newBuilder().mergeFrom(message);
-    assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+    assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
 
     // hashCode()/equals() should take unknown enum values into account.
     builder.putAllInt32ToEnumFieldValue(newMap(2, 1001));
@@ -960,7 +962,7 @@
     assertFalse(message.equals(message2));
     // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
     // should be the same.
-    assertEquals(message2.getInt32ToEnumField(), message.getInt32ToEnumField());
+    assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
   }
 
   public void testUnknownEnumValuesInReflectionApi() throws Exception {
@@ -991,7 +993,7 @@
 
     // Verify that enum values have been successfully updated.
     TestMap message = builder.build();
-    for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValue().entrySet()) {
+    for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValueMap().entrySet()) {
       assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
     }
   }
@@ -1002,18 +1004,18 @@
     TestMap message = builder.build();
 
     assertEquals(
-        Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32Field().keySet()));
+        Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet()));
   }
 
   public void testGetMap() {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValuesUsingAccessors(builder);
     TestMap message = builder.build();
-    assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap());
-    assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap());
-    assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap());
-    assertEquals(message.getInt32ToEnumFieldValue(), message.getInt32ToEnumFieldValueMap());
-    assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap());
+    assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap());
+    assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap());
+    assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
+    assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap());
+    assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap());
   }
 
   public void testContains() {
@@ -1292,8 +1294,8 @@
   }
 
   public void testReservedWordsFieldNames() {
-    ReservedAsMapField.newBuilder().build();
-    ReservedAsMapFieldWithEnumValue.newBuilder().build();
+    ReservedAsMapField unused1 = ReservedAsMapField.newBuilder().build();
+    ReservedAsMapFieldWithEnumValue unused2 = ReservedAsMapFieldWithEnumValue.newBuilder().build();
   }
 
   public void testDeterministicSerialziation() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
index 66e406a..3c0c629 100644
--- a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
+++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
@@ -139,12 +139,12 @@
     // the content of the generated buildMessageInfo() method here.
     java.lang.String info =
         "\u0000@\u0001\u0000\u0001D@\u0000\u001f\u0000\u0001\u0000\u0002\u0001\u0003\u0002"
-            + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b"
-            + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014"
-            + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b"
-            + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f  !!\"\"##$$%%&&\'\'(())**++,,--"
-            + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000"
-            + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000";
+        + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b"
+        + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014"
+        + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b"
+        + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f  !!\"\"##$$%%&&\'\'(())**++,,--"
+        + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000"
+        + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000";
     return new RawMessageInfo(Proto3MessageLite.getDefaultInstance(), info, objects);
   }
 
diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
index 3d82c5f..08a23ba 100644
--- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -43,8 +43,10 @@
 
   public void testCompilation() {
     // If this compiles, it means the generation was correct.
-    TestBadIdentifiersProto.Deprecated.newBuilder();
-    TestBadIdentifiersProto.Override.newBuilder();
+    TestBadIdentifiersProto.Deprecated unused1 =
+        TestBadIdentifiersProto.Deprecated.newBuilder().build();
+    TestBadIdentifiersProto.Override unused2 =
+        TestBadIdentifiersProto.Override.getDefaultInstance();
   }
 
   public void testGetDescriptor() {
diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
index 798d7ca..523e23a 100644
--- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
@@ -45,8 +45,10 @@
 
   public void testCompilation() {
     // If this compiles, it means the generation was correct.
-    TestBadIdentifiersProto.Deprecated.newBuilder();
-    TestBadIdentifiersProto.Override.newBuilder();
+    TestBadIdentifiersProto.Deprecated.Builder builder1 =
+        TestBadIdentifiersProto.Deprecated.newBuilder();
+    TestBadIdentifiersProto.Override.Builder builder2 =
+        TestBadIdentifiersProto.Override.newBuilder();
   }
 
   public void testConflictingFieldNames() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/TestUtil.java b/java/core/src/test/java/com/google/protobuf/TestUtil.java
index 22c0be2..6c1021f 100644
--- a/java/core/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java
@@ -260,8 +260,8 @@
       TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
 
   /** Helper to convert a String to ByteString. */
-  static ByteString toBytes(String str) {
-    return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+  public static ByteString toBytes(String str) {
+    return ByteString.copyFromUtf8(str);
   }
 
   // BEGIN FULL-RUNTIME
@@ -3758,7 +3758,7 @@
 
   /** @param filePath The path relative to {@link #getTestDataDir}. */
   public static String readTextFromFile(String filePath) {
-    return readBytesFromFile(filePath).toStringUtf8();
+    return readBytesFromFile(filePath).toStringUtf8().replace(System.getProperty("line.separator"), "\n");
   }
 
   private static File getTestDataDir() {
@@ -3770,8 +3770,18 @@
     } catch (IOException e) {
       throw new RuntimeException("Couldn't get canonical name of working directory.", e);
     }
+    
+    String srcRootCheck = "src/google/protobuf";
+
+    // If we're running w/ Bazel on Windows, we're not in a sandbox, so we
+    // we must change our source root check condition to find the true test data dir.
+    String testBinaryName = System.getenv("TEST_BINARY");
+    if (testBinaryName != null && testBinaryName.endsWith(".exe")) {
+      srcRootCheck = srcRootCheck + "/descriptor.cc";
+    }
     while (ancestor != null && ancestor.exists()) {
-      if (new File(ancestor, "src/google/protobuf").exists()) {
+      // Identify the true source root.
+      if (new File(ancestor, srcRootCheck).exists()) {
         return new File(ancestor, "src/google/protobuf/testdata");
       }
       ancestor = ancestor.getParentFile();
diff --git a/java/core/src/test/java/com/google/protobuf/TestUtilLite.java b/java/core/src/test/java/com/google/protobuf/TestUtilLite.java
index 31565fc..993dd9d 100644
--- a/java/core/src/test/java/com/google/protobuf/TestUtilLite.java
+++ b/java/core/src/test/java/com/google/protobuf/TestUtilLite.java
@@ -142,8 +142,8 @@
   private TestUtilLite() {}
 
   /** Helper to convert a String to ByteString. */
-  static ByteString toBytes(String str) {
-    return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+  public static ByteString toBytes(String str) {
+    return ByteString.copyFromUtf8(str);
   }
 
   /**
diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
index 50ba016..a919f3b 100644
--- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -30,6 +30,7 @@
 
 package com.google.protobuf;
 
+import static com.google.common.truth.Truth.assertThat;
 import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED;
 import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED;
 
@@ -40,6 +41,8 @@
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.Descriptors.FileDescriptor;
 import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
+import com.google.protobuf.testing.proto.TestProto3Optional;
+import com.google.protobuf.testing.proto.TestProto3Optional.NestedEnum;
 import any_test.AnyTestProto.TestAny;
 import map_test.MapTestProto.TestMap;
 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
@@ -319,6 +322,24 @@
     assertEquals(canonicalExoticText, message.toString());
   }
 
+  public void testRoundtripProto3Optional() throws Exception {
+    Message message =
+        TestProto3Optional.newBuilder()
+            .setOptionalInt32(1)
+            .setOptionalInt64(2)
+            .setOptionalNestedEnum(NestedEnum.BAZ)
+            .build();
+    TestProto3Optional.Builder message2 = TestProto3Optional.newBuilder();
+    TextFormat.merge(message.toString(), message2);
+
+    assertTrue(message2.hasOptionalInt32());
+    assertTrue(message2.hasOptionalInt64());
+    assertTrue(message2.hasOptionalNestedEnum());
+    assertEquals(1, message2.getOptionalInt32());
+    assertEquals(2, message2.getOptionalInt64());
+    assertEquals(NestedEnum.BAZ, message2.getOptionalNestedEnum());
+  }
+
   public void testPrintMessageSet() throws Exception {
     TestMessageSet messageSet =
         TestMessageSet.newBuilder()
@@ -846,6 +867,12 @@
     assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\341\\210\\264"));
     assertEquals("\u1234", TextFormat.unescapeText("\\xe1\\x88\\xb4"));
     assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\xe1\\x88\\xb4"));
+    assertEquals("\u1234", TextFormat.unescapeText("\\u1234"));
+    assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\u1234"));
+    assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\U00001234"));
+    assertEquals(
+        new String(new int[] {0x10437}, 0, 1), TextFormat.unescapeText("\\xf0\\x90\\x90\\xb7"));
+    assertEquals(bytes(0xf0, 0x90, 0x90, 0xb7), TextFormat.unescapeBytes("\\U00010437"));
 
     // Handling of strings with unescaped Unicode characters > 255.
     final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
@@ -873,6 +900,87 @@
     } catch (TextFormat.InvalidEscapeSequenceException e) {
       // success
     }
+
+    try {
+      TextFormat.unescapeText("\\u");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\u' with too few hex chars");
+    }
+
+    try {
+      TextFormat.unescapeText("\\ud800");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate");
+    }
+
+    try {
+      TextFormat.unescapeText("\\ud800\\u1234");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate");
+    }
+
+    try {
+      TextFormat.unescapeText("\\udc00");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate");
+    }
+
+    try {
+      TextFormat.unescapeText("\\ud801\\udc37");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate");
+    }
+
+    try {
+      TextFormat.unescapeText("\\U1234");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars");
+    }
+
+    try {
+      TextFormat.unescapeText("\\U1234no more hex");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars");
+    }
+
+    try {
+      TextFormat.unescapeText("\\U00110000");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\U00110000' is not a valid code point value");
+    }
+
+    try {
+      TextFormat.unescapeText("\\U0000d801\\U00000dc37");
+      fail("Should have thrown an exception.");
+    } catch (TextFormat.InvalidEscapeSequenceException e) {
+      assertThat(e)
+          .hasMessageThat()
+          .isEqualTo("Invalid escape sequence: '\\U0000d801' refers to a surrogate code unit");
+    }
   }
 
   public void testParseInteger() throws Exception {
@@ -1384,6 +1492,27 @@
     }
   }
 
+  public void testMapDuplicateKeys() throws Exception {
+    String input =
+        "int32_to_int32_field: {\n"
+            + "  key: 1\n"
+            + "  value: 1\n"
+            + "}\n"
+            + "int32_to_int32_field: {\n"
+            + "  key: -2147483647\n"
+            + "  value: 5\n"
+            + "}\n"
+            + "int32_to_int32_field: {\n"
+            + "  key: 1\n"
+            + "  value: -1\n"
+            + "}\n";
+    TestMap msg = TextFormat.parse(input, TestMap.class);
+    int i1 = msg.getInt32ToInt32FieldMap().get(1);
+    TestMap msg2 = TextFormat.parse(msg.toString(), TestMap.class);
+    int i2 = msg2.getInt32ToInt32FieldMap().get(1);
+    assertEquals(i1, i2);
+  }
+
   public void testMapShortForm() throws Exception {
     String text =
         "string_to_int32_field [{ key: 'x' value: 10 }, { key: 'y' value: 20 }]\n"
@@ -1392,10 +1521,10 @@
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertEquals(2, message.getStringToInt32Field().size());
-    assertEquals(2, message.getInt32ToMessageField().size());
-    assertEquals(10, message.getStringToInt32Field().get("x").intValue());
-    assertEquals(200, message.getInt32ToMessageField().get(2).getValue());
+    assertEquals(2, message.getStringToInt32FieldMap().size());
+    assertEquals(2, message.getInt32ToMessageFieldMap().size());
+    assertEquals(10, message.getStringToInt32FieldMap().get("x").intValue());
+    assertEquals(200, message.getInt32ToMessageFieldMap().get(2).getValue());
   }
 
   public void testMapShortFormEmpty() throws Exception {
@@ -1403,8 +1532,8 @@
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertEquals(0, message.getStringToInt32Field().size());
-    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getStringToInt32FieldMap().size());
+    assertEquals(0, message.getInt32ToMessageFieldMap().size());
   }
 
   public void testMapShortFormTrailingComma() throws Exception {
@@ -1429,18 +1558,30 @@
       TestMap.Builder builder = TestMap.newBuilder();
       defaultParser.merge(text, builder);
       TestMap map = builder.build();
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
 
     {
       // With overwrite forbidden, same behavior.
       // TODO(b/29122459): Expect parse exception here.
       TestMap.Builder builder = TestMap.newBuilder();
-      defaultParser.merge(text, builder);
+      parserWithOverwriteForbidden.merge(text, builder);
       TestMap map = builder.build();
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
+    }
+
+    {
+      // With overwrite forbidden and a dynamic message, same behavior.
+      // TODO(b/29122459): Expect parse exception here.
+      Message.Builder builder = DynamicMessage.newBuilder(TestMap.getDescriptor());
+      parserWithOverwriteForbidden.merge(text, builder);
+      TestMap map =
+          TestMap.parseFrom(
+              builder.build().toByteString(), ExtensionRegistryLite.getEmptyRegistry());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
   }
 
diff --git a/java/internal/BUILD b/java/internal/BUILD
new file mode 100644
index 0000000..4f542ec
--- /dev/null
+++ b/java/internal/BUILD
@@ -0,0 +1 @@
+package(default_visibility = ["//java:__subpackages__"])
\ No newline at end of file
diff --git a/java/internal/testing.bzl b/java/internal/testing.bzl
new file mode 100644
index 0000000..76e1e45
--- /dev/null
+++ b/java/internal/testing.bzl
@@ -0,0 +1,72 @@
+"""
+Generates a side-car JUnit suite test runner class for each
+input src.
+"""
+_template = """import org.junit.runners.Suite;
+import org.junit.runner.RunWith;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({%s})
+public class %s {}
+"""
+
+def _as_classname(fname, pkg):
+    path_name = [x.path for x in fname.files.to_list()][0]
+    file_name = path_name.split("/")[-1]
+    return ".".join([pkg, file_name.split(".")[0]]) + ".class"
+
+def _gen_suite_impl(ctx):
+    classes = ",".join(
+        [_as_classname(x, ctx.attr.package_name) for x in ctx.attr.srcs],
+    )
+    ctx.actions.write(output = ctx.outputs.out, content = _template % (
+        classes,
+        ctx.attr.outname,
+    ))
+
+_gen_suite = rule(
+    attrs = {
+        "srcs": attr.label_list(allow_files = True),
+        "package_name": attr.string(),
+        "outname": attr.string(),
+    },
+    outputs = {"out": "%{name}.java"},
+    implementation = _gen_suite_impl,
+)
+
+def junit_tests(name, srcs, data = [], deps = [], package_name = "com.google.protobuf", test_prefix = None, **kwargs):
+    testlib_name = "%s_lib" % name
+    native.java_library(
+        name = testlib_name,
+        srcs = srcs,
+        deps = deps,
+        resources = data,
+        data = data,
+    )
+    test_names = []
+    prefix = name.replace("-", "_") + "TestSuite"
+    for src in srcs:
+        test_name = src.rsplit("/", 1)[1].split(".")[0]
+        if not test_name.endswith("Test") or test_name.startswith("Abstract"):
+            continue
+        if test_prefix:
+            test_name = "%s%s" % (test_prefix, test_name)  
+        test_names = test_names + [test_name]
+        suite_name = prefix + '_' + test_name
+        _gen_suite(
+            name = suite_name,
+            srcs = [src],
+            package_name = package_name,
+            outname = suite_name,
+        )
+        native.java_test(
+            name = test_name,
+            test_class = suite_name,
+            srcs = [src] + [":" + suite_name],
+            deps = deps + [":%s" % testlib_name],
+            **kwargs
+        )
+    native.test_suite(
+        name = name,
+        tests = test_names,
+    )
diff --git a/java/kotlin-lite/generate-sources-build.xml b/java/kotlin-lite/generate-sources-build.xml
new file mode 100644
index 0000000..ab9cfea
--- /dev/null
+++ b/java/kotlin-lite/generate-sources-build.xml
@@ -0,0 +1,19 @@
+<project name="generate-sources">
+    <echo message="Running protoc ..."/>
+    <mkdir dir="${generated.sources.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--kotlin_out=lite:${generated.sources.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
+    </exec>
+</project>
+
diff --git a/java/kotlin-lite/generate-test-sources-build.xml b/java/kotlin-lite/generate-test-sources-build.xml
new file mode 100644
index 0000000..c5f60b8
--- /dev/null
+++ b/java/kotlin-lite/generate-test-sources-build.xml
@@ -0,0 +1,34 @@
+<project name="generate-test-sources">
+    <mkdir dir="${generated.testsources.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=lite:${generated.testsources.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="--proto_path=${protobuf.basedir}/java/kotlin/${test.proto.dir}"/>
+        <arg value="--experimental_allow_proto3_optional"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/map_lite_unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
+        <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
+        <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
+        <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/example_extensible_message.proto"/>
+        <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
+    </exec>
+    <exec executable="${protoc}">
+      <arg value="--kotlin_out=lite:${generated.testsources.dir}"/>
+      <arg value="--proto_path=${protobuf.source.dir}"/>
+      <arg value="--proto_path=${protobuf.basedir}/java/kotlin/${test.proto.dir}"/>
+      <arg value="--experimental_allow_proto3_optional"/>
+      <arg value="${protobuf.source.dir}/google/protobuf/map_lite_unittest.proto"/>
+      <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+      <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
+      <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
+      <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
+      <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/example_extensible_message.proto"/>
+      <arg value="${protobuf.basedir}/java/kotlin/${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
+    </exec>
+</project>
diff --git a/java/kotlin-lite/lite.awk b/java/kotlin-lite/lite.awk
new file mode 100644
index 0000000..b22d965
--- /dev/null
+++ b/java/kotlin-lite/lite.awk
@@ -0,0 +1,25 @@
+# Remove code enclosed by "BEGIN FULL-RUNTIME" and "END FULL-RUNTIME" to
+# create the lite-only version of a test file.
+
+BEGIN {
+  in_full_runtime = 0;
+}
+
+/BEGIN FULL-RUNTIME/ {
+  in_full_runtime = 1;
+  next;
+}
+
+/END FULL-RUNTIME/ {
+  in_full_runtime = 0;
+  next;
+}
+
+in_full_runtime {
+  # Skip full runtime code path.
+  next;
+}
+
+{
+  print;
+}
diff --git a/java/kotlin-lite/pom.xml b/java/kotlin-lite/pom.xml
new file mode 100644
index 0000000..6d04939
--- /dev/null
+++ b/java/kotlin-lite/pom.xml
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.protobuf</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>3.17.3</version>
+  </parent>
+
+  <artifactId>protobuf-kotlin-lite</artifactId>
+
+  <name>Protocol Buffers [Lite]</name>
+  <description>
+    Lite version of Protocol Buffers library. This version is optimized for code size, but does
+    not guarantee API/ABI stability.
+  </description>
+
+  <properties>
+    <kotlin.version>1.5.0</kotlin.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>protobuf-javalite</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava-testlib</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.truth</groupId>
+      <artifactId>truth</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlin</groupId>
+      <artifactId>kotlin-stdlib</artifactId>
+      <version>${kotlin.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlin</groupId>
+      <artifactId>kotlin-test</artifactId>
+      <version>${kotlin.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <testResources>
+      <testResource>
+        <directory>${protobuf.source.dir}</directory>
+        <includes>
+          <include>google/protobuf/testdata/golden_message_oneof_implemented</include>
+          <include>google/protobuf/testdata/golden_packed_fields_message</include>
+        </includes>
+      </testResource>
+    </testResources>
+
+    <plugins>
+      <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>3.1.0</version>
+        <executions>
+          <execution>
+            <id>copy-kotlin-source-files</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${generated.sources.dir}/com/google/protobuf</outputDirectory>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../kotlin/src/main/kotlin/com/google/protobuf</directory>
+                  <includes>
+                    <include>DslList.kt</include>
+                    <include>DslMap.kt</include>
+                    <include>DslProxy.kt</include>
+                    <include>ExtendableMessageLiteExtensions.kt</include>
+                    <include>ExtensionList.kt</include>
+                    <include>OnlyForUseByGeneratedProtoCode.kt</include>
+                    <include>ProtoDslMarker.kt</include>
+                    <include>UnmodifiableCollections.kt</include>
+                  </includes>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>copy-test-source-files</id>
+            <phase>generate-test-sources</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${generated.testsources.dir}/com/google/protobuf</outputDirectory>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../core/src/test/java/com/google/protobuf</directory>
+                  <includes>
+                    <include>TestUtilLite.java</include>
+                  </includes>
+                </resource>
+                <resource>
+                  <directory>${basedir}/../kotlin/src/test/kotlin/com/google/protobuf</directory>
+                  <excludes>
+                    <exclude>ExtendableMessageExtensionsTest.kt</exclude>
+                    <exclude>Proto2Test.kt</exclude>
+                    <exclude>ProtoUtil.java</exclude>
+                  </excludes>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- Use Antrun plugin to generate sources with protoc -->
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <!-- Generate core protos -->
+          <execution>
+            <id>generate-sources</id>
+            <phase>generate-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+
+          <!-- Generate the test protos -->
+          <execution>
+            <id>generate-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-test-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+
+          <execution>
+            <id>process-lite-sources</id>
+            <phase>generate-test-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="process-lite-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-generated-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.sources.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+
+          <execution>
+            <id>add-generated-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <goals>
+              <goal>add-test-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.testsources.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.jetbrains.kotlin</groupId>
+        <artifactId>kotlin-maven-plugin</artifactId>
+        <version>${kotlin.version}</version>
+        <extensions>true</extensions>
+        <executions>
+          <execution>
+            <id>compile</id>
+            <goals> <goal>compile</goal> </goals>
+            <configuration>
+              <sourceDirs>
+                <sourceDir>${generated.sources.dir}</sourceDir>
+                <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
+              </sourceDirs>
+            </configuration>
+          </execution>
+          <execution>
+            <id>test-compile</id>
+            <goals> <goal>test-compile</goal> </goals>
+            <configuration>
+              <sourceDirs>
+                <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
+                <sourceDir>${generated.testsources.dir}</sourceDir>
+              </sourceDirs>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/java/kotlin-lite/process-lite-sources-build.xml b/java/kotlin-lite/process-lite-sources-build.xml
new file mode 100644
index 0000000..d49cf3a
--- /dev/null
+++ b/java/kotlin-lite/process-lite-sources-build.xml
@@ -0,0 +1,7 @@
+<project name="process-lite-sources">
+    <exec executable="awk" output="${generated.testsources.dir}/com/google/protobuf/TestUtil.java">
+      <arg value="-f" />
+      <arg value="${basedir}/lite.awk" />
+      <arg value="${basedir}/../core/src/test/java/com/google/protobuf/TestUtil.java" />
+    </exec>
+</project>
diff --git a/java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt
new file mode 100644
index 0000000..53291b4
--- /dev/null
+++ b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt
@@ -0,0 +1,90 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.kotlin.test.ExampleExtensibleMessage
+import com.google.protobuf.kotlin.test.ExampleExtensibleMessageOuterClass as TestProto
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ExtendableMessageLiteExtensionsTest {
+  @Test
+  fun setOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+    builder[TestProto.int32Extension] = 5
+    assertThat(builder.build().getExtension(TestProto.int32Extension)).isEqualTo(5)
+  }
+
+  @Test
+  fun getOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+    assertThat(builder[TestProto.int32Extension]).isEqualTo(6)
+  }
+
+  @Test
+  fun getOnMessage() {
+    val message = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+      .build()
+    assertThat(message[TestProto.int32Extension]).isEqualTo(6)
+  }
+
+  @Test
+  fun containsPositiveOnMessage() {
+    val message = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+      .build()
+    assertThat(TestProto.int32Extension in message).isTrue()
+  }
+
+  @Test
+  fun containsPositiveOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+    assertThat(TestProto.int32Extension in builder).isTrue()
+  }
+
+  @Test
+  fun containsNegativeOnMessage() {
+    val message = ExampleExtensibleMessage.newBuilder().build()
+    assertThat(TestProto.int32Extension in message).isFalse()
+  }
+
+  @Test
+  fun containsNegativeOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+    assertThat(TestProto.int32Extension in builder).isFalse()
+  }
+}
diff --git a/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt
new file mode 100644
index 0000000..76d4847
--- /dev/null
+++ b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt
@@ -0,0 +1,1018 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.TestAllTypesLiteKt
+import com.google.protobuf.TestAllTypesLiteKt.nestedMessage
+import com.google.protobuf.TestUtilLite
+import com.google.protobuf.TestUtilLite.toBytes
+import com.google.protobuf.UnittestImportLite.ImportEnumLite
+import com.google.protobuf.UnittestImportLite.ImportMessageLite
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite
+import com.google.protobuf.UnittestLite
+import com.google.protobuf.UnittestLite.ForeignEnumLite
+import com.google.protobuf.UnittestLite.TestAllTypesLite
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum
+import com.google.protobuf.UnittestLite.TestEmptyMessageLite
+import com.google.protobuf.UnittestLite.TestEmptyMessageWithExtensionsLite
+import com.google.protobuf.copy
+import com.google.protobuf.foreignMessageLite
+import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.EvilNamesProto2
+import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.HardKeywordsAllTypesProto2
+import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.Interface
+import com.google.protobuf.kotlin.generator.HardKeywordsAllTypesProto2Kt
+import com.google.protobuf.kotlin.generator.evilNamesProto2
+import com.google.protobuf.kotlin.generator.hardKeywordsAllTypesProto2
+import com.google.protobuf.kotlin.generator.interface_
+import com.google.protobuf.optionalGroupExtensionLite
+import com.google.protobuf.repeatedGroupExtensionLite
+import com.google.protobuf.testAllExtensionsLite
+import com.google.protobuf.testAllTypesLite
+import com.google.protobuf.testEmptyMessageLite
+import com.google.protobuf.testEmptyMessageWithExtensionsLite
+import protobuf_unittest.MapLiteUnittest.MapEnumLite
+import protobuf_unittest.MapLiteUnittest.TestMapLite
+import protobuf_unittest.testMapLite
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class Proto2LiteTest {
+  @Test
+  fun testSetters() {
+    assertThat(
+      testAllTypesLite {
+        optionalInt32 = 101
+        optionalInt64 = 102
+        optionalUint32 = 103
+        optionalUint64 = 104
+        optionalSint32 = 105
+        optionalSint64 = 106
+        optionalFixed32 = 107
+        optionalFixed64 = 108
+        optionalSfixed32 = 109
+        optionalSfixed64 = 110
+        optionalFloat = 111.0f
+        optionalDouble = 112.0
+        optionalBool = true
+        optionalString = "115"
+        optionalBytes = toBytes("116")
+        optionalGroup =
+          TestAllTypesLiteKt.optionalGroup { a = 117 }
+        optionalNestedMessage = nestedMessage { bb = 118 }
+        optionalForeignMessage =
+          foreignMessageLite { c = 119 }
+        optionalImportMessage =
+          ImportMessageLite.newBuilder().setD(120).build()
+        optionalPublicImportMessage =
+          PublicImportMessageLite.newBuilder().setE(126).build()
+        optionalLazyMessage = nestedMessage { bb = 127 }
+        optionalNestedEnum = NestedEnum.BAZ
+        optionalForeignEnum = ForeignEnumLite.FOREIGN_LITE_BAZ
+        optionalImportEnum = ImportEnumLite.IMPORT_LITE_BAZ
+        optionalStringPiece = "124"
+        optionalCord = "125"
+        repeatedInt32.add(201)
+        repeatedInt64.add(202)
+        repeatedUint32.add(203)
+        repeatedUint64.add(204)
+        repeatedSint32.add(205)
+        repeatedSint64.add(206)
+        repeatedFixed32.add(207)
+        repeatedFixed64.add(208)
+        repeatedSfixed32.add(209)
+        repeatedSfixed64.add(210)
+        repeatedFloat.add(211f)
+        repeatedDouble.add(212.0)
+        repeatedBool.add(true)
+        repeatedString.add("215")
+        repeatedBytes.add(toBytes("216"))
+        repeatedGroup.add(TestAllTypesLiteKt.repeatedGroup { a = 217 })
+        repeatedNestedMessage.add(nestedMessage { bb = 218 })
+        repeatedForeignMessage.add(
+          foreignMessageLite { c = 219 }
+        )
+        repeatedImportMessage.add(
+          ImportMessageLite.newBuilder().setD(220).build()
+        )
+        repeatedLazyMessage.add(nestedMessage { bb = 227 })
+        repeatedNestedEnum.add(NestedEnum.BAR)
+        repeatedForeignEnum.add(ForeignEnumLite.FOREIGN_LITE_BAR)
+        repeatedImportEnum.add(ImportEnumLite.IMPORT_LITE_BAR)
+        repeatedStringPiece.add("224")
+        repeatedCord.add("225")
+        repeatedInt32 += 301
+        repeatedInt64 += 302
+        repeatedUint32 += 303
+        repeatedUint64 += 304
+        repeatedSint32 += 305
+        repeatedSint64 += 306
+        repeatedFixed32 += 307
+        repeatedFixed64 += 308
+        repeatedSfixed32 += 309
+        repeatedSfixed64 += 310
+        repeatedFloat += 311f
+        repeatedDouble += 312.0
+        repeatedBool += false
+        repeatedString += "315"
+        repeatedBytes += toBytes("316")
+        repeatedGroup += TestAllTypesLiteKt.repeatedGroup { a = 317 }
+        repeatedNestedMessage += nestedMessage { bb = 318 }
+        repeatedForeignMessage +=
+          foreignMessageLite { c = 319 }
+        repeatedImportMessage +=
+          ImportMessageLite.newBuilder().setD(320).build()
+        repeatedLazyMessage +=
+          TestAllTypesLiteKt.nestedMessage { bb = 327 }
+        repeatedNestedEnum += NestedEnum.BAZ
+        repeatedForeignEnum += ForeignEnumLite.FOREIGN_LITE_BAZ
+        repeatedImportEnum += ImportEnumLite.IMPORT_LITE_BAZ
+        repeatedStringPiece += "324"
+        repeatedCord += "325"
+        defaultInt32 = 401
+        defaultInt64 = 402
+        defaultUint32 = 403
+        defaultUint64 = 404
+        defaultSint32 = 405
+        defaultSint64 = 406
+        defaultFixed32 = 407
+        defaultFixed64 = 408
+        defaultSfixed32 = 409
+        defaultSfixed64 = 410
+        defaultFloat = 411f
+        defaultDouble = 412.0
+        defaultBool = false
+        defaultString = "415"
+        defaultBytes = toBytes("416")
+        defaultNestedEnum = NestedEnum.FOO
+        defaultForeignEnum = ForeignEnumLite.FOREIGN_LITE_FOO
+        defaultImportEnum = ImportEnumLite.IMPORT_LITE_FOO
+        defaultStringPiece = "424"
+        defaultCord = "425"
+        oneofUint32 = 601
+        oneofNestedMessage =
+          TestAllTypesLiteKt.nestedMessage { bb = 602 }
+        oneofString = "603"
+        oneofBytes = toBytes("604")
+      }
+    ).isEqualTo(
+      TestUtilLite.getAllLiteSetBuilder().build()
+    )
+  }
+
+  @Test
+  fun testGetters() {
+    testAllTypesLite {
+      optionalInt32 = 101
+      assertThat(optionalInt32).isEqualTo(101)
+      optionalString = "115"
+      assertThat(optionalString).isEqualTo("115")
+      optionalGroup = TestAllTypesLiteKt.optionalGroup { a = 117 }
+      assertThat(optionalGroup).isEqualTo(TestAllTypesLiteKt.optionalGroup { a = 117 })
+      optionalNestedMessage = TestAllTypesLiteKt.nestedMessage { bb = 118 }
+      assertThat(optionalNestedMessage).isEqualTo(TestAllTypesLiteKt.nestedMessage { bb = 118 })
+      optionalNestedEnum = NestedEnum.BAZ
+      assertThat(optionalNestedEnum).isEqualTo(NestedEnum.BAZ)
+      defaultInt32 = 401
+      assertThat(defaultInt32).isEqualTo(401)
+      oneofUint32 = 601
+      assertThat(oneofUint32).isEqualTo(601)
+    }
+  }
+
+  @Test
+  fun testDefaultGetters() {
+    testAllTypesLite {
+      assertThat(defaultInt32).isEqualTo(41)
+      assertThat(defaultString).isEqualTo("hello")
+      assertThat(defaultNestedEnum).isEqualTo(NestedEnum.BAR)
+      assertThat(defaultStringPiece).isEqualTo("abc")
+    }
+  }
+
+  @Test
+  fun testRepeatedGettersAndSetters() {
+    testAllTypesLite {
+      repeatedInt32.addAll(listOf(1, 2))
+      assertThat(repeatedInt32).isEqualTo(listOf(1, 2))
+      repeatedInt32 += listOf(3, 4)
+      assertThat(repeatedInt32).isEqualTo(listOf(1, 2, 3, 4))
+      repeatedInt32[0] = 5
+      assertThat(repeatedInt32).isEqualTo(listOf(5, 2, 3, 4))
+
+      repeatedString.addAll(listOf("1", "2"))
+      assertThat(repeatedString).isEqualTo(listOf("1", "2"))
+      repeatedString += listOf("3", "4")
+      assertThat(repeatedString).isEqualTo(listOf("1", "2", "3", "4"))
+      repeatedString[0] = "5"
+      assertThat(repeatedString).isEqualTo(listOf("5", "2", "3", "4"))
+
+      repeatedGroup.addAll(
+        listOf(
+          TestAllTypesLiteKt.repeatedGroup { a = 1 },
+          TestAllTypesLiteKt.repeatedGroup { a = 2 }
+        )
+      )
+      assertThat(repeatedGroup).isEqualTo(
+        listOf(
+          TestAllTypesLiteKt.repeatedGroup { a = 1 },
+          TestAllTypesLiteKt.repeatedGroup { a = 2 }
+        )
+      )
+      repeatedGroup +=
+        listOf(
+          TestAllTypesLiteKt.repeatedGroup { a = 3 },
+          TestAllTypesLiteKt.repeatedGroup { a = 4 }
+        )
+      assertThat(repeatedGroup).isEqualTo(
+        listOf(
+          TestAllTypesLiteKt.repeatedGroup { a = 1 },
+          TestAllTypesLiteKt.repeatedGroup { a = 2 },
+          TestAllTypesLiteKt.repeatedGroup { a = 3 },
+          TestAllTypesLiteKt.repeatedGroup { a = 4 }
+        )
+      )
+      repeatedGroup[0] = TestAllTypesLiteKt.repeatedGroup { a = 5 }
+      assertThat(repeatedGroup).isEqualTo(
+        listOf(
+          TestAllTypesLiteKt.repeatedGroup { a = 5 },
+          TestAllTypesLiteKt.repeatedGroup { a = 2 },
+          TestAllTypesLiteKt.repeatedGroup { a = 3 },
+          TestAllTypesLiteKt.repeatedGroup { a = 4 }
+        )
+      )
+
+      repeatedNestedMessage.addAll(listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 }))
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 }
+        )
+      )
+      repeatedNestedMessage += listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+      repeatedNestedMessage[0] = nestedMessage { bb = 5 }
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 5 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+
+      repeatedNestedEnum.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      assertThat(repeatedNestedEnum).isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      repeatedNestedEnum += listOf(NestedEnum.BAZ, NestedEnum.FOO)
+      assertThat(repeatedNestedEnum).isEqualTo(
+        listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+      repeatedNestedEnum[0] = NestedEnum.BAR
+      assertThat(repeatedNestedEnum).isEqualTo(
+        listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+    }
+  }
+
+  @Test
+  fun testHazzers() {
+    testAllTypesLite {
+      optionalInt32 = 101
+      assertThat(hasOptionalInt32()).isTrue()
+      assertThat(hasOptionalString()).isFalse()
+      optionalGroup = TestAllTypesLiteKt.optionalGroup { a = 117 }
+      assertThat(hasOptionalGroup()).isTrue()
+      assertThat(hasOptionalNestedMessage()).isFalse()
+      optionalNestedEnum = NestedEnum.BAZ
+      assertThat(hasOptionalNestedEnum()).isTrue()
+      assertThat(hasDefaultInt32()).isFalse()
+      oneofUint32 = 601
+      assertThat(hasOneofUint32()).isTrue()
+    }
+
+    testAllTypesLite {
+      assertThat(hasOptionalInt32()).isFalse()
+      optionalString = "115"
+      assertThat(hasOptionalString()).isTrue()
+      assertThat(hasOptionalGroup()).isFalse()
+      optionalNestedMessage = TestAllTypesLiteKt.nestedMessage { bb = 118 }
+      assertThat(hasOptionalNestedMessage()).isTrue()
+      assertThat(hasOptionalNestedEnum()).isFalse()
+      defaultInt32 = 401
+      assertThat(hasDefaultInt32()).isTrue()
+      assertThat(hasOneofUint32()).isFalse()
+    }
+  }
+
+  @Test
+  fun testClears() {
+    testAllTypesLite {
+      optionalInt32 = 101
+      clearOptionalInt32()
+      assertThat(hasOptionalInt32()).isFalse()
+
+      optionalString = "115"
+      clearOptionalString()
+      assertThat(hasOptionalString()).isFalse()
+
+      optionalGroup = TestAllTypesLiteKt.optionalGroup { a = 117 }
+      clearOptionalGroup()
+      assertThat(hasOptionalGroup()).isFalse()
+
+      optionalNestedMessage = TestAllTypesLiteKt.nestedMessage { bb = 118 }
+      clearOptionalNestedMessage()
+      assertThat(hasOptionalNestedMessage()).isFalse()
+
+      optionalNestedEnum = NestedEnum.BAZ
+      clearOptionalNestedEnum()
+      assertThat(hasOptionalNestedEnum()).isFalse()
+
+      defaultInt32 = 401
+      clearDefaultInt32()
+      assertThat(hasDefaultInt32()).isFalse()
+
+      oneofUint32 = 601
+      clearOneofUint32()
+      assertThat(hasOneofUint32()).isFalse()
+    }
+  }
+
+  @Test
+  fun testCopy() {
+    val message = testAllTypesLite {
+      optionalInt32 = 101
+      optionalString = "115"
+    }
+    val modifiedMessage = message.copy {
+      optionalInt32 = 201
+    }
+
+    assertThat(message).isEqualTo(
+      TestAllTypesLite.newBuilder()
+        .setOptionalInt32(101)
+        .setOptionalString("115")
+        .build()
+    )
+    assertThat(modifiedMessage).isEqualTo(
+      TestAllTypesLite.newBuilder()
+        .setOptionalInt32(201)
+        .setOptionalString("115")
+        .build()
+    )
+  }
+
+  @Test
+  fun testOneof() {
+    val message = testAllTypesLite {
+      oneofString = "foo"
+      assertThat(oneofFieldCase)
+        .isEqualTo(TestAllTypesLite.OneofFieldCase.ONEOF_STRING)
+      assertThat(oneofString).isEqualTo("foo")
+      clearOneofField()
+      assertThat(hasOneofUint32()).isFalse()
+      assertThat(oneofFieldCase)
+        .isEqualTo(TestAllTypesLite.OneofFieldCase.ONEOFFIELD_NOT_SET)
+      oneofUint32 = 5
+    }
+
+    assertThat(message.getOneofFieldCase())
+      .isEqualTo(TestAllTypesLite.OneofFieldCase.ONEOF_UINT32)
+    assertThat(message.getOneofUint32()).isEqualTo(5)
+  }
+
+  @Test
+  fun testExtensionsSet() {
+    assertThat(
+      testAllExtensionsLite {
+        this[UnittestLite.optionalInt32ExtensionLite] = 101
+        this[UnittestLite.optionalInt64ExtensionLite] = 102L
+        this[UnittestLite.optionalUint32ExtensionLite] = 103
+        this[UnittestLite.optionalUint64ExtensionLite] = 104L
+        this[UnittestLite.optionalSint32ExtensionLite] = 105
+        this[UnittestLite.optionalSint64ExtensionLite] = 106L
+        this[UnittestLite.optionalFixed32ExtensionLite] = 107
+        this[UnittestLite.optionalFixed64ExtensionLite] = 108L
+        this[UnittestLite.optionalSfixed32ExtensionLite] = 109
+        this[UnittestLite.optionalSfixed64ExtensionLite] = 110L
+        this[UnittestLite.optionalFloatExtensionLite] = 111F
+        this[UnittestLite.optionalDoubleExtensionLite] = 112.0
+        this[UnittestLite.optionalBoolExtensionLite] = true
+        this[UnittestLite.optionalStringExtensionLite] = "115"
+        this[UnittestLite.optionalBytesExtensionLite] = toBytes("116")
+        this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
+        this[UnittestLite.optionalNestedMessageExtensionLite] =
+          TestAllTypesLiteKt.nestedMessage { bb = 118 }
+        this[UnittestLite.optionalForeignMessageExtensionLite] = foreignMessageLite { c = 119 }
+        this[UnittestLite.optionalImportMessageExtensionLite] =
+          ImportMessageLite.newBuilder().setD(120).build()
+        this[UnittestLite.optionalPublicImportMessageExtensionLite] =
+          PublicImportMessageLite.newBuilder().setE(126).build()
+        this[UnittestLite.optionalLazyMessageExtensionLite] =
+          TestAllTypesLiteKt.nestedMessage { bb = 127 }
+        this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
+        this[UnittestLite.optionalForeignEnumExtensionLite] = ForeignEnumLite.FOREIGN_LITE_BAZ
+        this[UnittestLite.optionalImportEnumExtensionLite] = ImportEnumLite.IMPORT_LITE_BAZ
+        this[UnittestLite.optionalStringPieceExtensionLite] = "124"
+        this[UnittestLite.optionalCordExtensionLite] = "125"
+        this[UnittestLite.repeatedInt32ExtensionLite].add(201)
+        this[UnittestLite.repeatedInt64ExtensionLite].add(202L)
+        this[UnittestLite.repeatedUint32ExtensionLite].add(203)
+        this[UnittestLite.repeatedUint64ExtensionLite].add(204L)
+        this[UnittestLite.repeatedSint32ExtensionLite].add(205)
+        this[UnittestLite.repeatedSint64ExtensionLite].add(206L)
+        this[UnittestLite.repeatedFixed32ExtensionLite].add(207)
+        this[UnittestLite.repeatedFixed64ExtensionLite].add(208L)
+        this[UnittestLite.repeatedSfixed32ExtensionLite].add(209)
+        this[UnittestLite.repeatedSfixed64ExtensionLite].add(210L)
+        this[UnittestLite.repeatedFloatExtensionLite].add(211F)
+        this[UnittestLite.repeatedDoubleExtensionLite].add(212.0)
+        this[UnittestLite.repeatedBoolExtensionLite].add(true)
+        this[UnittestLite.repeatedStringExtensionLite].add("215")
+        this[UnittestLite.repeatedBytesExtensionLite].add(toBytes("216"))
+        this[UnittestLite.repeatedGroupExtensionLite].add(repeatedGroupExtensionLite { a = 217 })
+        this[UnittestLite.repeatedNestedMessageExtensionLite].add(
+          TestAllTypesLiteKt.nestedMessage { bb = 218 }
+        )
+        this[UnittestLite.repeatedForeignMessageExtensionLite].add(foreignMessageLite { c = 219 })
+        this[UnittestLite.repeatedImportMessageExtensionLite].add(
+          ImportMessageLite.newBuilder().setD(220).build()
+        )
+        this[UnittestLite.repeatedLazyMessageExtensionLite].add(
+          TestAllTypesLiteKt.nestedMessage { bb = 227 }
+        )
+        this[UnittestLite.repeatedNestedEnumExtensionLite].add(NestedEnum.BAR)
+        this[UnittestLite.repeatedForeignEnumExtensionLite].add(ForeignEnumLite.FOREIGN_LITE_BAR)
+        this[UnittestLite.repeatedImportEnumExtensionLite].add(ImportEnumLite.IMPORT_LITE_BAR)
+        this[UnittestLite.repeatedStringPieceExtensionLite].add("224")
+        this[UnittestLite.repeatedCordExtensionLite].add("225")
+        this[UnittestLite.repeatedInt32ExtensionLite] += 301
+        this[UnittestLite.repeatedInt64ExtensionLite] += 302L
+        this[UnittestLite.repeatedUint32ExtensionLite] += 303
+        this[UnittestLite.repeatedUint64ExtensionLite] += 304L
+        this[UnittestLite.repeatedSint32ExtensionLite] += 305
+        this[UnittestLite.repeatedSint64ExtensionLite] += 306L
+        this[UnittestLite.repeatedFixed32ExtensionLite] += 307
+        this[UnittestLite.repeatedFixed64ExtensionLite] += 308L
+        this[UnittestLite.repeatedSfixed32ExtensionLite] += 309
+        this[UnittestLite.repeatedSfixed64ExtensionLite] += 310L
+        this[UnittestLite.repeatedFloatExtensionLite] += 311F
+        this[UnittestLite.repeatedDoubleExtensionLite] += 312.0
+        this[UnittestLite.repeatedBoolExtensionLite] += false
+        this[UnittestLite.repeatedStringExtensionLite] += "315"
+        this[UnittestLite.repeatedBytesExtensionLite] += toBytes("316")
+        this[UnittestLite.repeatedGroupExtensionLite] += repeatedGroupExtensionLite { a = 317 }
+        this[UnittestLite.repeatedNestedMessageExtensionLite] +=
+          TestAllTypesLiteKt.nestedMessage { bb = 318 }
+        this[UnittestLite.repeatedForeignMessageExtensionLite] += foreignMessageLite { c = 319 }
+        this[UnittestLite.repeatedImportMessageExtensionLite] +=
+          ImportMessageLite.newBuilder().setD(320).build()
+        this[UnittestLite.repeatedLazyMessageExtensionLite] +=
+          TestAllTypesLiteKt.nestedMessage { bb = 327 }
+        this[UnittestLite.repeatedNestedEnumExtensionLite] += NestedEnum.BAZ
+        this[UnittestLite.repeatedForeignEnumExtensionLite] += ForeignEnumLite.FOREIGN_LITE_BAZ
+        this[UnittestLite.repeatedImportEnumExtensionLite] += ImportEnumLite.IMPORT_LITE_BAZ
+        this[UnittestLite.repeatedStringPieceExtensionLite] += "324"
+        this[UnittestLite.repeatedCordExtensionLite] += "325"
+        this[UnittestLite.defaultInt32ExtensionLite] = 401
+        this[UnittestLite.defaultInt64ExtensionLite] = 402L
+        this[UnittestLite.defaultUint32ExtensionLite] = 403
+        this[UnittestLite.defaultUint64ExtensionLite] = 404L
+        this[UnittestLite.defaultSint32ExtensionLite] = 405
+        this[UnittestLite.defaultSint64ExtensionLite] = 406L
+        this[UnittestLite.defaultFixed32ExtensionLite] = 407
+        this[UnittestLite.defaultFixed64ExtensionLite] = 408L
+        this[UnittestLite.defaultSfixed32ExtensionLite] = 409
+        this[UnittestLite.defaultSfixed64ExtensionLite] = 410L
+        this[UnittestLite.defaultFloatExtensionLite] = 411F
+        this[UnittestLite.defaultDoubleExtensionLite] = 412.0
+        this[UnittestLite.defaultBoolExtensionLite] = false
+        this[UnittestLite.defaultStringExtensionLite] = "415"
+        this[UnittestLite.defaultBytesExtensionLite] = toBytes("416")
+        this[UnittestLite.defaultNestedEnumExtensionLite] = NestedEnum.FOO
+        this[UnittestLite.defaultForeignEnumExtensionLite] = ForeignEnumLite.FOREIGN_LITE_FOO
+        this[UnittestLite.defaultImportEnumExtensionLite] = ImportEnumLite.IMPORT_LITE_FOO
+        this[UnittestLite.defaultStringPieceExtensionLite] = "424"
+        this[UnittestLite.defaultCordExtensionLite] = "425"
+        this[UnittestLite.oneofUint32ExtensionLite] = 601
+        this[UnittestLite.oneofNestedMessageExtensionLite] =
+          TestAllTypesLiteKt.nestedMessage { bb = 602 }
+        this[UnittestLite.oneofStringExtensionLite] = "603"
+        this[UnittestLite.oneofBytesExtensionLite] = toBytes("604")
+      }
+    ).isEqualTo(
+      TestUtilLite.getAllLiteExtensionsSet()
+    )
+  }
+
+  @Test
+  fun testExtensionGetters() {
+    testAllExtensionsLite {
+      this[UnittestLite.optionalInt32ExtensionLite] = 101
+      assertThat(this[UnittestLite.optionalInt32ExtensionLite]).isEqualTo(101)
+      this[UnittestLite.optionalStringExtensionLite] = "115"
+      assertThat(this[UnittestLite.optionalStringExtensionLite]).isEqualTo("115")
+      this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
+      assertThat(this[UnittestLite.optionalGroupExtensionLite])
+        .isEqualTo(optionalGroupExtensionLite { a = 117 })
+      this[UnittestLite.optionalNestedMessageExtensionLite] =
+        TestAllTypesLiteKt.nestedMessage { bb = 118 }
+      assertThat(this[UnittestLite.optionalNestedMessageExtensionLite])
+        .isEqualTo(TestAllTypesLiteKt.nestedMessage { bb = 118 })
+      this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
+      assertThat(this[UnittestLite.optionalNestedEnumExtensionLite]).isEqualTo(NestedEnum.BAZ)
+      this[UnittestLite.defaultInt32ExtensionLite] = 401
+      assertThat(this[UnittestLite.defaultInt32ExtensionLite]).isEqualTo(401)
+      this[UnittestLite.oneofUint32ExtensionLite] = 601
+      assertThat(this[UnittestLite.oneofUint32ExtensionLite]).isEqualTo(601)
+    }
+  }
+
+  @Test
+  fun testRepeatedExtensionGettersAndSetters() {
+    testAllExtensionsLite {
+      this[UnittestLite.repeatedInt32ExtensionLite].addAll(listOf(1, 2))
+      assertThat(this[UnittestLite.repeatedInt32ExtensionLite]).isEqualTo(listOf(1, 2))
+      this[UnittestLite.repeatedInt32ExtensionLite] += listOf(3, 4)
+      assertThat(this[UnittestLite.repeatedInt32ExtensionLite]).isEqualTo(listOf(1, 2, 3, 4))
+      this[UnittestLite.repeatedInt32ExtensionLite][0] = 5
+      assertThat(this[UnittestLite.repeatedInt32ExtensionLite]).isEqualTo(listOf(5, 2, 3, 4))
+
+      this[UnittestLite.repeatedStringExtensionLite].addAll(listOf("1", "2"))
+      assertThat(this[UnittestLite.repeatedStringExtensionLite]).isEqualTo(listOf("1", "2"))
+      this[UnittestLite.repeatedStringExtensionLite] += listOf("3", "4")
+      assertThat(this[UnittestLite.repeatedStringExtensionLite])
+        .isEqualTo(listOf("1", "2", "3", "4"))
+      this[UnittestLite.repeatedStringExtensionLite][0] = "5"
+      assertThat(this[UnittestLite.repeatedStringExtensionLite])
+        .isEqualTo(listOf("5", "2", "3", "4"))
+
+      this[UnittestLite.repeatedGroupExtensionLite].addAll(
+        listOf(
+          repeatedGroupExtensionLite { a = 1 },
+          repeatedGroupExtensionLite { a = 2 }
+        )
+      )
+      assertThat(this[UnittestLite.repeatedGroupExtensionLite]).isEqualTo(
+        listOf(
+          repeatedGroupExtensionLite { a = 1 },
+          repeatedGroupExtensionLite { a = 2 }
+        )
+      )
+      this[UnittestLite.repeatedGroupExtensionLite] +=
+        listOf(
+          repeatedGroupExtensionLite { a = 3 },
+          repeatedGroupExtensionLite { a = 4 }
+        )
+      assertThat(this[UnittestLite.repeatedGroupExtensionLite]).isEqualTo(
+        listOf(
+          repeatedGroupExtensionLite { a = 1 },
+          repeatedGroupExtensionLite { a = 2 },
+          repeatedGroupExtensionLite { a = 3 },
+          repeatedGroupExtensionLite { a = 4 }
+        )
+      )
+      this[UnittestLite.repeatedGroupExtensionLite][0] = repeatedGroupExtensionLite { a = 5 }
+      assertThat(this[UnittestLite.repeatedGroupExtensionLite]).isEqualTo(
+        listOf(
+          repeatedGroupExtensionLite { a = 5 },
+          repeatedGroupExtensionLite { a = 2 },
+          repeatedGroupExtensionLite { a = 3 },
+          repeatedGroupExtensionLite { a = 4 }
+        )
+      )
+
+      this[UnittestLite.repeatedNestedMessageExtensionLite].addAll(
+        listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
+      )
+      assertThat(this[UnittestLite.repeatedNestedMessageExtensionLite]).isEqualTo(
+        listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
+      )
+      this[UnittestLite.repeatedNestedMessageExtensionLite] +=
+        listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
+      assertThat(this[UnittestLite.repeatedNestedMessageExtensionLite]).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+      this[UnittestLite.repeatedNestedMessageExtensionLite][0] = nestedMessage { bb = 5 }
+      assertThat(this[UnittestLite.repeatedNestedMessageExtensionLite]).isEqualTo(
+        listOf(
+          nestedMessage { bb = 5 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+
+      this[UnittestLite.repeatedNestedEnumExtensionLite]
+        .addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      assertThat(this[UnittestLite.repeatedNestedEnumExtensionLite])
+        .isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      this[UnittestLite.repeatedNestedEnumExtensionLite] += listOf(NestedEnum.BAZ, NestedEnum.FOO)
+      assertThat(this[UnittestLite.repeatedNestedEnumExtensionLite]).isEqualTo(
+        listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+      this[UnittestLite.repeatedNestedEnumExtensionLite][0] = NestedEnum.BAR
+      assertThat(this[UnittestLite.repeatedNestedEnumExtensionLite]).isEqualTo(
+        listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+    }
+  }
+
+  @Test
+  fun testExtensionContains() {
+    testAllExtensionsLite {
+      this[UnittestLite.optionalInt32ExtensionLite] = 101
+      assertThat(contains(UnittestLite.optionalInt32ExtensionLite)).isTrue()
+      assertThat(contains(UnittestLite.optionalStringExtensionLite)).isFalse()
+      this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
+      assertThat(contains(UnittestLite.optionalGroupExtensionLite)).isTrue()
+      assertThat(contains(UnittestLite.optionalNestedMessageExtensionLite)).isFalse()
+      this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
+      assertThat(contains(UnittestLite.optionalNestedEnumExtensionLite)).isTrue()
+      assertThat(contains(UnittestLite.defaultInt32ExtensionLite)).isFalse()
+      this[UnittestLite.oneofUint32ExtensionLite] = 601
+      assertThat(contains(UnittestLite.oneofUint32ExtensionLite)).isTrue()
+    }
+
+    testAllExtensionsLite {
+      assertThat(contains(UnittestLite.optionalInt32ExtensionLite)).isFalse()
+      this[UnittestLite.optionalStringExtensionLite] = "115"
+      assertThat(contains(UnittestLite.optionalStringExtensionLite)).isTrue()
+      assertThat(contains(UnittestLite.optionalGroupExtensionLite)).isFalse()
+      this[UnittestLite.optionalNestedMessageExtensionLite] =
+        TestAllTypesLiteKt.nestedMessage { bb = 118 }
+      assertThat(contains(UnittestLite.optionalNestedMessageExtensionLite)).isTrue()
+      assertThat(contains(UnittestLite.optionalNestedEnumExtensionLite)).isFalse()
+      this[UnittestLite.defaultInt32ExtensionLite] = 401
+      assertThat(contains(UnittestLite.defaultInt32ExtensionLite)).isTrue()
+      assertThat(contains(UnittestLite.oneofUint32ExtensionLite)).isFalse()
+    }
+  }
+
+  @Test
+  fun testExtensionClears() {
+    testAllExtensionsLite {
+      this[UnittestLite.optionalInt32ExtensionLite] = 101
+      clear(UnittestLite.optionalInt32ExtensionLite)
+      assertThat(contains(UnittestLite.optionalInt32ExtensionLite)).isFalse()
+
+      this[UnittestLite.optionalStringExtensionLite] = "115"
+      clear(UnittestLite.optionalStringExtensionLite)
+      assertThat(contains(UnittestLite.optionalStringExtensionLite)).isFalse()
+
+      this[UnittestLite.optionalGroupExtensionLite] = optionalGroupExtensionLite { a = 117 }
+      clear(UnittestLite.optionalGroupExtensionLite)
+      assertThat(contains(UnittestLite.optionalGroupExtensionLite)).isFalse()
+
+      this[UnittestLite.optionalNestedMessageExtensionLite] =
+        TestAllTypesLiteKt.nestedMessage { bb = 118 }
+      clear(UnittestLite.optionalNestedMessageExtensionLite)
+      assertThat(contains(UnittestLite.optionalNestedMessageExtensionLite)).isFalse()
+
+      this[UnittestLite.optionalNestedEnumExtensionLite] = NestedEnum.BAZ
+      clear(UnittestLite.optionalNestedEnumExtensionLite)
+      assertThat(contains(UnittestLite.optionalNestedEnumExtensionLite)).isFalse()
+
+      this[UnittestLite.defaultInt32ExtensionLite] = 401
+      clear(UnittestLite.defaultInt32ExtensionLite)
+      assertThat(contains(UnittestLite.defaultInt32ExtensionLite)).isFalse()
+
+      this[UnittestLite.oneofUint32ExtensionLite] = 601
+      clear(UnittestLite.oneofUint32ExtensionLite)
+      assertThat(contains(UnittestLite.oneofUint32ExtensionLite)).isFalse()
+    }
+  }
+
+  @Test
+  fun testEmptyMessages() {
+    assertThat(
+      testEmptyMessageLite {}
+    ).isEqualTo(
+      TestEmptyMessageLite.newBuilder().build()
+    )
+
+    assertThat(
+      testEmptyMessageWithExtensionsLite {}
+    ).isEqualTo(
+      TestEmptyMessageWithExtensionsLite.newBuilder().build()
+    )
+  }
+
+  @Test
+  fun testMapSetters() {
+    assertThat(
+      testMapLite {
+        mapInt32Int32[1] = 2
+        mapInt64Int64[1L] = 2L
+        mapUint32Uint32[1] = 2
+        mapUint64Uint64[1L] = 2L
+        mapSint32Sint32[1] = 2
+        mapSint64Sint64[1L] = 2L
+        mapFixed32Fixed32[1] = 2
+        mapFixed64Fixed64[1L] = 2L
+        mapSfixed32Sfixed32[1] = 2
+        mapSfixed64Sfixed64[1L] = 2L
+        mapInt32Float[1] = 2F
+        mapInt32Double[1] = 2.0
+        mapBoolBool[true] = true
+        mapStringString["1"] = "2"
+        mapInt32Bytes[1] = toBytes("2")
+        mapInt32Enum[1] = MapEnumLite.MAP_ENUM_FOO_LITE
+        mapInt32ForeignMessage[1] = foreignMessageLite { c = 1 }
+      }
+    ).isEqualTo(
+      TestMapLite.newBuilder()
+        .putMapInt32Int32(1, 2)
+        .putMapInt64Int64(1L, 2L)
+        .putMapUint32Uint32(1, 2)
+        .putMapUint64Uint64(1L, 2L)
+        .putMapSint32Sint32(1, 2)
+        .putMapSint64Sint64(1L, 2L)
+        .putMapFixed32Fixed32(1, 2)
+        .putMapFixed64Fixed64(1L, 2L)
+        .putMapSfixed32Sfixed32(1, 2)
+        .putMapSfixed64Sfixed64(1L, 2L)
+        .putMapInt32Float(1, 2F)
+        .putMapInt32Double(1, 2.0)
+        .putMapBoolBool(true, true)
+        .putMapStringString("1", "2")
+        .putMapInt32Bytes(1, toBytes("2"))
+        .putMapInt32Enum(1, MapEnumLite.MAP_ENUM_FOO_LITE)
+        .putMapInt32ForeignMessage(1, foreignMessageLite { c = 1 })
+        .build()
+    )
+  }
+
+  @Test
+  fun testMapGettersAndSetters() {
+    testMapLite {
+      mapInt32Int32.put(1, 2)
+      assertThat(mapInt32Int32).isEqualTo(mapOf(1 to 2))
+      mapInt32Int32[3] = 4
+      assertThat(mapInt32Int32).isEqualTo(mapOf(1 to 2, 3 to 4))
+      mapInt32Int32.putAll(mapOf(5 to 6, 7 to 8))
+      assertThat(mapInt32Int32).isEqualTo(mapOf(1 to 2, 3 to 4, 5 to 6, 7 to 8))
+
+      mapStringString.put("1", "2")
+      assertThat(mapStringString).isEqualTo(mapOf("1" to "2"))
+      mapStringString["3"] = "4"
+      assertThat(mapStringString).isEqualTo(mapOf("1" to "2", "3" to "4"))
+      mapStringString.putAll(mapOf("5" to "6", "7" to "8"))
+      assertThat(mapStringString).isEqualTo(mapOf("1" to "2", "3" to "4", "5" to "6", "7" to "8"))
+
+      mapInt32Enum.put(1, MapEnumLite.MAP_ENUM_FOO_LITE)
+      assertThat(mapInt32Enum).isEqualTo(mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE))
+      mapInt32Enum[2] = MapEnumLite.MAP_ENUM_BAR_LITE
+      assertThat(mapInt32Enum).isEqualTo(
+        mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE, 2 to MapEnumLite.MAP_ENUM_BAR_LITE)
+      )
+      mapInt32Enum.putAll(
+        mapOf(3 to MapEnumLite.MAP_ENUM_BAZ_LITE, 4 to MapEnumLite.MAP_ENUM_FOO_LITE)
+      )
+      assertThat(mapInt32Enum).isEqualTo(
+        mapOf(
+          1 to MapEnumLite.MAP_ENUM_FOO_LITE,
+          2 to MapEnumLite.MAP_ENUM_BAR_LITE,
+          3 to MapEnumLite.MAP_ENUM_BAZ_LITE,
+          4 to MapEnumLite.MAP_ENUM_FOO_LITE
+        )
+      )
+
+      mapInt32ForeignMessage.put(1, foreignMessageLite { c = 1 })
+      assertThat(mapInt32ForeignMessage).isEqualTo(mapOf(1 to foreignMessageLite { c = 1 }))
+      mapInt32ForeignMessage[2] = foreignMessageLite { c = 2 }
+      assertThat(mapInt32ForeignMessage).isEqualTo(
+        mapOf(1 to foreignMessageLite { c = 1 }, 2 to foreignMessageLite { c = 2 })
+      )
+      mapInt32ForeignMessage.putAll(
+        mapOf(3 to foreignMessageLite { c = 3 }, 4 to foreignMessageLite { c = 4 })
+      )
+      assertThat(mapInt32ForeignMessage).isEqualTo(
+        mapOf(
+          1 to foreignMessageLite { c = 1 },
+          2 to foreignMessageLite { c = 2 },
+          3 to foreignMessageLite { c = 3 },
+          4 to foreignMessageLite { c = 4 }
+        )
+      )
+    }
+  }
+
+  @Test
+  fun testMapRemove() {
+    testMapLite {
+      mapInt32Int32.putAll(mapOf(1 to 2, 3 to 4))
+      mapInt32Int32.remove(1)
+      assertThat(mapInt32Int32).isEqualTo(mapOf(3 to 4))
+
+      mapStringString.putAll(mapOf("1" to "2", "3" to "4"))
+      mapStringString.remove("1")
+      assertThat(mapStringString).isEqualTo(mapOf("3" to "4"))
+
+      mapInt32Enum.putAll(
+        mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE, 2 to MapEnumLite.MAP_ENUM_BAR_LITE)
+      )
+      mapInt32Enum.remove(1)
+      assertThat(mapInt32Enum).isEqualTo(mapOf(2 to MapEnumLite.MAP_ENUM_BAR_LITE))
+
+      mapInt32ForeignMessage.putAll(
+        mapOf(1 to foreignMessageLite { c = 1 }, 2 to foreignMessageLite { c = 2 })
+      )
+      mapInt32ForeignMessage.remove(1)
+      assertThat(mapInt32ForeignMessage).isEqualTo(mapOf(2 to foreignMessageLite { c = 2 }))
+    }
+  }
+
+  @Test
+  fun testMapClear() {
+    testMapLite {
+      mapInt32Int32.putAll(mapOf(1 to 2, 3 to 4))
+      mapInt32Int32.clear()
+      assertThat(mapInt32Int32.isEmpty()).isTrue()
+
+      mapStringString.putAll(mapOf("1" to "2", "3" to "4"))
+      mapStringString.clear()
+      assertThat(mapStringString.isEmpty()).isTrue()
+
+      mapInt32Enum.putAll(
+        mapOf(1 to MapEnumLite.MAP_ENUM_FOO_LITE, 2 to MapEnumLite.MAP_ENUM_BAR_LITE)
+      )
+      mapInt32Enum.clear()
+      assertThat(mapInt32Enum.isEmpty()).isTrue()
+
+      mapInt32ForeignMessage.putAll(
+        mapOf(1 to foreignMessageLite { c = 1 }, 2 to foreignMessageLite { c = 2 })
+      )
+      mapInt32ForeignMessage.clear()
+      assertThat(mapInt32ForeignMessage.isEmpty()).isTrue()
+    }
+  }
+
+  @Test
+  fun testEvilNames() {
+    assertThat(
+      evilNamesProto2 {
+        initialized = true
+        hasFoo = true
+        bar = "foo"
+        isInitialized = true
+        fooBar = "foo"
+        aLLCAPS += "foo"
+        aLLCAPSMAP[1] = true
+        hasUnderbarPrecedingNumeric1Foo = true
+        hasUnderbarPrecedingNumeric42Bar = true
+        hasUnderbarPrecedingNumeric123Foo42BarBaz = true
+        extension += "foo"
+        class_ += 1
+        int = 1.0
+        long = true
+        boolean = 1L
+        sealed = "foo"
+        interface_ = 1F
+        in_ = 1
+        object_ = "foo"
+        cachedSize_ = "foo"
+        serializedSize_ = true
+        by = "foo"
+      }
+    ).isEqualTo(
+      EvilNamesProto2.newBuilder()
+        .setInitialized(true)
+        .setHasFoo(true)
+        .setBar("foo")
+        .setIsInitialized(true)
+        .setFooBar("foo")
+        .addALLCAPS("foo")
+        .putALLCAPSMAP(1, true)
+        .setHasUnderbarPrecedingNumeric1Foo(true)
+        .setHasUnderbarPrecedingNumeric42Bar(true)
+        .setHasUnderbarPrecedingNumeric123Foo42BarBaz(true)
+        .addExtension("foo")
+        .addClass_(1)
+        .setInt(1.0)
+        .setLong(true)
+        .setBoolean(1L)
+        .setSealed("foo")
+        .setInterface(1F)
+        .setIn(1)
+        .setObject("foo")
+        .setCachedSize_("foo")
+        .setSerializedSize_(true)
+        .setBy("foo")
+        .build()
+    )
+
+    assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build())
+  }
+
+  @Test
+  fun testHardKeywordGettersAndSetters() {
+    hardKeywordsAllTypesProto2 {
+      as_ = 1
+      assertThat(as_).isEqualTo(1)
+
+      in_ = "foo"
+      assertThat(in_).isEqualTo("foo")
+
+      break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
+      assertThat(break_).isEqualTo(HardKeywordsAllTypesProto2.NestedEnum.FOO)
+
+      do_ = HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      assertThat(do_).isEqualTo(HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 })
+
+      continue_[1] = 1
+      assertThat(continue_[1]).isEqualTo(1)
+
+      else_ += 1
+      assertThat(else_).isEqualTo(listOf(1))
+
+      for_ += "foo"
+      assertThat(for_).isEqualTo(listOf("foo"))
+
+      fun_ += HardKeywordsAllTypesProto2.NestedEnum.FOO
+      assertThat(fun_).isEqualTo(listOf(HardKeywordsAllTypesProto2.NestedEnum.FOO))
+
+      if_ += HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      assertThat(if_).isEqualTo(listOf(HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }))
+    }
+  }
+
+  @Test
+  fun testHardKeywordHazzers() {
+    hardKeywordsAllTypesProto2 {
+      as_ = 1
+      assertThat(hasAs_()).isTrue()
+
+      in_ = "foo"
+      assertThat(hasIn_()).isTrue()
+
+      break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
+      assertThat(hasBreak_()).isTrue()
+
+      do_ = HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      assertThat(hasDo_()).isTrue()
+    }
+  }
+
+  @Test
+  fun testHardKeywordClears() {
+    hardKeywordsAllTypesProto2 {
+      as_ = 1
+      clearAs_()
+      assertThat(hasAs_()).isFalse()
+
+      in_ = "foo"
+      clearIn_()
+      assertThat(hasIn_()).isFalse()
+
+      break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
+      clearBreak_()
+      assertThat(hasBreak_()).isFalse()
+
+      do_ = HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      clearDo_()
+      assertThat(hasDo_()).isFalse()
+    }
+  }
+}
diff --git a/java/kotlin/generate-sources-build.xml b/java/kotlin/generate-sources-build.xml
new file mode 100644
index 0000000..6963f37
--- /dev/null
+++ b/java/kotlin/generate-sources-build.xml
@@ -0,0 +1,20 @@
+<project name="generate-sources">
+    <echo message="Running protoc ..."/>
+    <mkdir dir="${generated.sources.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--kotlin_out=${generated.sources.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/>
+    </exec>
+</project>
diff --git a/java/kotlin/generate-test-sources-build.xml b/java/kotlin/generate-test-sources-build.xml
new file mode 100644
index 0000000..dca1a05
--- /dev/null
+++ b/java/kotlin/generate-test-sources-build.xml
@@ -0,0 +1,34 @@
+<project name="generate-test-sources">
+    <mkdir dir="${generated.testsources.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=${generated.testsources.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="--proto_path=${test.proto.dir}"/>
+        <arg value="--experimental_allow_proto3_optional"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/map_proto2_unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/example_extensible_message.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
+    </exec>
+    <exec executable="${protoc}">
+      <arg value="--kotlin_out=${generated.testsources.dir}"/>
+      <arg value="--proto_path=${protobuf.source.dir}"/>
+      <arg value="--proto_path=${test.proto.dir}"/>
+      <arg value="--experimental_allow_proto3_optional"/>
+      <arg value="${protobuf.source.dir}/google/protobuf/map_proto2_unittest.proto"/>
+      <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+      <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
+      <arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto2.proto"/>
+      <arg value="${test.proto.dir}/com/google/protobuf/evil_names_proto3.proto"/>
+      <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_proto3.proto"/>
+    </exec>
+
+</project>
diff --git a/java/kotlin/pom.xml b/java/kotlin/pom.xml
new file mode 100644
index 0000000..756611c
--- /dev/null
+++ b/java/kotlin/pom.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.protobuf</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>3.17.3</version>
+  </parent>
+
+  <artifactId>protobuf-kotlin</artifactId>
+
+  <name>Protocol Buffers [Core]</name>
+  <description>
+    Core Protocol Buffers library. Protocol Buffers are a way of encoding structured data in an
+    efficient yet extensible format.
+  </description>
+
+  <properties>
+    <kotlin.version>1.5.0</kotlin.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>protobuf-java</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava-testlib</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.truth</groupId>
+      <artifactId>truth</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlin</groupId>
+      <artifactId>kotlin-stdlib</artifactId>
+      <version>${kotlin.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlin</groupId>
+      <artifactId>kotlin-test</artifactId>
+      <version>${kotlin.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <testResources>
+      <testResource>
+        <directory>${protobuf.source.dir}</directory>
+        <includes>
+          <include>google/protobuf/testdata/golden_message_oneof_implemented</include>
+          <include>google/protobuf/testdata/golden_packed_fields_message</include>
+        </includes>
+      </testResource>
+    </testResources>
+
+    <plugins>
+      <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>3.1.0</version>
+        <executions>
+          <execution>
+            <id>copy-test-source-files</id>
+            <phase>generate-test-sources</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${generated.testsources.dir}/com/google/protobuf</outputDirectory>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../core/src/test/java/com/google/protobuf</directory>
+                  <includes>
+                    <include>TestUtil.java</include>
+                    <include>TestUtilLite.java</include>
+                  </includes>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- Use Antrun plugin to generate sources with protoc -->
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <!-- Generate core protos -->
+          <execution>
+            <id>generate-sources</id>
+            <phase>generate-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+
+          <!-- Generate the test protos -->
+          <execution>
+            <id>generate-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <configuration>
+              <target>
+                <ant antfile="generate-test-sources-build.xml"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <!-- Add the generated sources to the build -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-generated-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.sources.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>add-generated-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <goals>
+              <goal>add-test-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.testsources.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.jetbrains.kotlin</groupId>
+        <artifactId>kotlin-maven-plugin</artifactId>
+        <version>${kotlin.version}</version>
+        <extensions>true</extensions>
+        <executions>
+          <execution>
+            <id>compile</id>
+            <goals> <goal>compile</goal> </goals>
+            <configuration>
+              <sourceDirs>
+                <sourceDir>${generated.sources.dir}</sourceDir>
+                <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
+              </sourceDirs>
+            </configuration>
+          </execution>
+          <execution>
+            <id>test-compile</id>
+            <goals> <goal>test-compile</goal> </goals>
+            <configuration>
+              <sourceDirs>
+                <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
+                <sourceDir>${generated.testsources.dir}</sourceDir>
+              </sourceDirs>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt
new file mode 100644
index 0000000..9f7f75b
--- /dev/null
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt
@@ -0,0 +1,59 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+/**
+ * A simple wrapper around a [List] with an extra generic parameter that can be used to disambiguate
+ * extension methods.
+ *
+ * <p>This class is used by Kotlin protocol buffer extensions, and its constructor is public only
+ * because generated message code is in a different compilation unit.  Others should not use this
+ * class directly in any way.
+ */
+@Suppress("unused") // the unused type parameter
+class DslList<E, P : DslProxy> @OnlyForUseByGeneratedProtoCode constructor(
+  private val delegate: List<E>
+) : List<E> by delegate {
+  override fun iterator(): Iterator<E> = UnmodifiableIterator(delegate.iterator())
+
+  override fun listIterator(): ListIterator<E> = UnmodifiableListIterator(delegate.listIterator())
+
+  override fun listIterator(index: Int): ListIterator<E> =
+    UnmodifiableListIterator(delegate.listIterator(index))
+
+  override fun equals(other: Any?): Boolean = delegate == other
+
+  override fun hashCode(): Int = delegate.hashCode()
+
+  override fun toString(): String = delegate.toString()
+}
+
+// TODO(lowasser): investigate making this an inline class
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt
new file mode 100644
index 0000000..d35195e
--- /dev/null
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt
@@ -0,0 +1,62 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+/**
+ * A simple wrapper around a [Map] with an extra generic parameter that can be used to disambiguate
+ * extension methods.
+ *
+ * <p>This class is used by Kotlin protocol buffer extensions, and its constructor is public only
+ * because generated message code is in a different compilation unit.  Others should not use this
+ * class directly in any way.
+ */
+@Suppress("unused") // the unused type parameter
+class DslMap<K, V, P : DslProxy> @OnlyForUseByGeneratedProtoCode constructor(
+  private val delegate: Map<K, V>
+) : Map<K, V> by delegate {
+  // We allocate the wrappers on calls to get, not with lazy {...}, because lazy allocates
+  // a few objects up front, and any kind of query operation on this object should be rare.
+
+  override val entries: Set<Map.Entry<K, V>>
+    get() = UnmodifiableMapEntries(delegate.entries)
+  override val keys: Set<K>
+    get() = UnmodifiableSet(delegate.keys)
+  override val values: Collection<V>
+    get() = UnmodifiableCollection(delegate.values)
+
+  override fun equals(other: Any?): Boolean = delegate == other
+
+  override fun hashCode(): Int = delegate.hashCode()
+
+  override fun toString(): String = delegate.toString()
+}
+
+// TODO(lowasser): investigate making this an inline class
diff --git a/src/google/protobuf/unittest_no_arena_import.proto b/java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt
similarity index 79%
copy from src/google/protobuf/unittest_no_arena_import.proto
copy to java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt
index 6f3f04f..c9b2dd4 100644
--- a/src/google/protobuf/unittest_no_arena_import.proto
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt
@@ -28,12 +28,15 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+package com.google.protobuf.kotlin
 
-package proto2_arena_unittest;
-
-option cc_enable_arenas = false;
-
-message ImportNoArenaNestedMessage {
-  optional int32 d = 1;
+/**
+ * A type meaningful only for its existence, never intended to be instantiated.  For example,
+ * a `DslList<Int, FooProxy>` can be given different extension methods than a
+ * `DslList<Int, BarProxy>`.
+ */
+abstract class DslProxy @OnlyForUseByGeneratedProtoCode protected constructor() {
+  init {
+    throw UnsupportedOperationException("A DslProxy should never be instantiated")
+  }
 }
diff --git a/python/google/protobuf/internal/python_protobuf.cc b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt
similarity index 63%
copy from python/google/protobuf/internal/python_protobuf.cc
copy to java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt
index e823bf2..4f64843 100644
--- a/python/google/protobuf/internal/python_protobuf.cc
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt
@@ -28,32 +28,29 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: qrczak@google.com (Marcin Kowalczyk)
+package com.google.protobuf.kotlin
 
-#include <google/protobuf/python/python_protobuf.h>
+import com.google.protobuf.ExtensionLite
+import com.google.protobuf.GeneratedMessageV3
 
-namespace google {
-namespace protobuf {
-namespace python {
-
-static const Message* GetCProtoInsidePyProtoStub(PyObject* msg) { return NULL; }
-static Message* MutableCProtoInsidePyProtoStub(PyObject* msg) { return NULL; }
-
-// This is initialized with a default, stub implementation.
-// If python-google.protobuf.cc is loaded, the function pointer is overridden
-// with a full implementation.
-const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg) =
-    GetCProtoInsidePyProtoStub;
-Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg) =
-    MutableCProtoInsidePyProtoStub;
-
-const Message* GetCProtoInsidePyProto(PyObject* msg) {
-  return GetCProtoInsidePyProtoPtr(msg);
-}
-Message* MutableCProtoInsidePyProto(PyObject* msg) {
-  return MutableCProtoInsidePyProtoPtr(msg);
+/** Sets the current value of the proto extension in this builder.*/
+operator fun <
+  M : GeneratedMessageV3.ExtendableMessage<M>,
+  B : GeneratedMessageV3.ExtendableBuilder<M, B>,
+  T : Any
+  > B.set(extension: ExtensionLite<M, T>, value: T) {
+  setExtension(extension, value)
 }
 
-}  // namespace python
-}  // namespace protobuf
-}  // namespace google
+/** Gets the current value of the proto extension. */
+operator fun <
+  M : GeneratedMessageV3.ExtendableMessage<M>,
+  MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder<M>,
+  T : Any
+  > MorBT.get(extension: ExtensionLite<M, T>): T = getExtension(extension)
+
+/** Returns true if the specified extension is set on this builder. */
+operator fun <
+  M : GeneratedMessageV3.ExtendableMessage<M>,
+  MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder<M>
+  > MorBT.contains(extension: ExtensionLite<M, *>): Boolean = hasExtension(extension)
diff --git a/python/google/protobuf/internal/python_protobuf.cc b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt
similarity index 63%
rename from python/google/protobuf/internal/python_protobuf.cc
rename to java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt
index e823bf2..6c208b2 100644
--- a/python/google/protobuf/internal/python_protobuf.cc
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt
@@ -28,32 +28,31 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: qrczak@google.com (Marcin Kowalczyk)
+package com.google.protobuf.kotlin
 
-#include <google/protobuf/python/python_protobuf.h>
+import com.google.protobuf.ExtensionLite
+import com.google.protobuf.GeneratedMessageLite
 
-namespace google {
-namespace protobuf {
-namespace python {
+/** Gets the value of the proto extension. */
+operator fun <
+  M : GeneratedMessageLite.ExtendableMessage<M, *>,
+  MOrBT : GeneratedMessageLite.ExtendableMessageOrBuilder<M, *>,
+  T : Any
+  > MOrBT.get(extension: ExtensionLite<M, T>): T = getExtension(extension)
 
-static const Message* GetCProtoInsidePyProtoStub(PyObject* msg) { return NULL; }
-static Message* MutableCProtoInsidePyProtoStub(PyObject* msg) { return NULL; }
-
-// This is initialized with a default, stub implementation.
-// If python-google.protobuf.cc is loaded, the function pointer is overridden
-// with a full implementation.
-const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg) =
-    GetCProtoInsidePyProtoStub;
-Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg) =
-    MutableCProtoInsidePyProtoStub;
-
-const Message* GetCProtoInsidePyProto(PyObject* msg) {
-  return GetCProtoInsidePyProtoPtr(msg);
-}
-Message* MutableCProtoInsidePyProto(PyObject* msg) {
-  return MutableCProtoInsidePyProtoPtr(msg);
+/** Sets the current value of the proto extension in this builder. */
+operator fun <
+  M : GeneratedMessageLite.ExtendableMessage<M, B>,
+  B : GeneratedMessageLite.ExtendableBuilder<M, B>,
+  T : Any
+  > B.set(extension: ExtensionLite<M, T>, value: T) {
+  setExtension(extension, value)
 }
 
-}  // namespace python
-}  // namespace protobuf
-}  // namespace google
+/** Returns true if the specified extension is set. */
+operator fun <
+  M : GeneratedMessageLite.ExtendableMessage<M, *>,
+  MorBT : GeneratedMessageLite.ExtendableMessageOrBuilder<M, *>
+  > MorBT.contains(
+  extension: ExtensionLite<M, *>
+): Boolean = hasExtension(extension)
diff --git a/python/google/protobuf/internal/python_protobuf.cc b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtensionList.kt
similarity index 61%
copy from python/google/protobuf/internal/python_protobuf.cc
copy to java/kotlin/src/main/kotlin/com/google/protobuf/ExtensionList.kt
index e823bf2..d8982eb 100644
--- a/python/google/protobuf/internal/python_protobuf.cc
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtensionList.kt
@@ -28,32 +28,30 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: qrczak@google.com (Marcin Kowalczyk)
+package com.google.protobuf.kotlin
 
-#include <google/protobuf/python/python_protobuf.h>
+import com.google.protobuf.ExtensionLite
+import com.google.protobuf.MessageLite
 
-namespace google {
-namespace protobuf {
-namespace python {
+/**
+ * Implementation for ExtensionList and ExtensionListLite.  Like [DslList], represents an
+ * unmodifiable view of a repeated proto field -- in this case, an extension field -- but
+ * supports querying the extension.
+ */
+class ExtensionList<E, M : MessageLite> @OnlyForUseByGeneratedProtoCode constructor(
+  val extension: ExtensionLite<M, List<E>>,
+  private val delegate: List<E>
+) : List<E> by delegate {
+  override fun iterator(): Iterator<E> = UnmodifiableIterator(delegate.iterator())
 
-static const Message* GetCProtoInsidePyProtoStub(PyObject* msg) { return NULL; }
-static Message* MutableCProtoInsidePyProtoStub(PyObject* msg) { return NULL; }
+  override fun listIterator(): ListIterator<E> = UnmodifiableListIterator(delegate.listIterator())
 
-// This is initialized with a default, stub implementation.
-// If python-google.protobuf.cc is loaded, the function pointer is overridden
-// with a full implementation.
-const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg) =
-    GetCProtoInsidePyProtoStub;
-Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg) =
-    MutableCProtoInsidePyProtoStub;
+  override fun listIterator(index: Int): ListIterator<E> =
+    UnmodifiableListIterator(delegate.listIterator(index))
 
-const Message* GetCProtoInsidePyProto(PyObject* msg) {
-  return GetCProtoInsidePyProtoPtr(msg);
+  override fun equals(other: Any?): Boolean = delegate == other
+
+  override fun hashCode(): Int = delegate.hashCode()
+
+  override fun toString(): String = delegate.toString()
 }
-Message* MutableCProtoInsidePyProto(PyObject* msg) {
-  return MutableCProtoInsidePyProtoPtr(msg);
-}
-
-}  // namespace python
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/unittest_no_arena_import.proto b/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt
similarity index 70%
copy from src/google/protobuf/unittest_no_arena_import.proto
copy to java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt
index 6f3f04f..c8ed63d 100644
--- a/src/google/protobuf/unittest_no_arena_import.proto
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt
@@ -28,12 +28,21 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+package com.google.protobuf.kotlin
 
-package proto2_arena_unittest;
-
-option cc_enable_arenas = false;
-
-message ImportNoArenaNestedMessage {
-  optional int32 d = 1;
-}
+/**
+ * Opt-in annotation to make it difficult to accidentally use APIs only intended for use by proto
+ * generated code.  See https://kotlinlang.org/docs/reference/opt-in-requirements.html for details
+ * on how this API works.
+ */
+@RequiresOptIn(
+  message =
+    """
+    This API is only intended for use by generated protobuf code, the code generator, and their own
+    tests.  If this does not describe your code, you should not be using this API.
+  """,
+  level = RequiresOptIn.Level.ERROR
+)
+@Retention(AnnotationRetention.BINARY)
+@Target(AnnotationTarget.CONSTRUCTOR, AnnotationTarget.ANNOTATION_CLASS)
+annotation class OnlyForUseByGeneratedProtoCode
diff --git a/src/google/protobuf/unittest_no_arena_import.proto b/java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt
similarity index 85%
copy from src/google/protobuf/unittest_no_arena_import.proto
copy to java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt
index 6f3f04f..e922624 100644
--- a/src/google/protobuf/unittest_no_arena_import.proto
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt
@@ -28,12 +28,13 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+package com.google.protobuf.kotlin
 
-package proto2_arena_unittest;
-
-option cc_enable_arenas = false;
-
-message ImportNoArenaNestedMessage {
-  optional int32 d = 1;
-}
+/**
+ * Indicates an API that is part of a DSL to generate protocol buffer messages.
+ */
+@DslMarker
+@Target(AnnotationTarget.CLASS)
+@Retention(AnnotationRetention.BINARY)
+@OnlyForUseByGeneratedProtoCode
+annotation class ProtoDslMarker
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt
new file mode 100644
index 0000000..cf45e89
--- /dev/null
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt
@@ -0,0 +1,69 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+/** Wraps an [Iterator] and makes it unmodifiable even from Java. */
+internal class UnmodifiableIterator<E>(delegate: Iterator<E>) : Iterator<E> by delegate
+
+/** Wraps a [ListIterator] and makes it unmodifiable even from Java. */
+internal class UnmodifiableListIterator<E>(
+  delegate: ListIterator<E>
+) : ListIterator<E> by delegate
+
+/** Wraps a [Collection] and makes it unmodifiable even from Java. */
+internal open class UnmodifiableCollection<E>(
+  private val delegate: Collection<E>
+) : Collection<E> by delegate {
+  override fun iterator(): Iterator<E> = UnmodifiableIterator(delegate.iterator())
+}
+
+/** Wraps a [Set] and makes it unmodifiable even from Java. */
+internal class UnmodifiableSet<E>(
+  delegate: Collection<E>
+) : UnmodifiableCollection<E>(delegate), Set<E>
+
+/** Wraps a [Map.Entry] and makes it unmodifiable even from Java. */
+internal class UnmodifiableMapEntry<K, V>(delegate: Map.Entry<K, V>) : Map.Entry<K, V> by delegate
+
+/** Wraps a [Set] of map entries and makes it unmodifiable even from Java. */
+internal class UnmodifiableMapEntries<K, V>(
+  private val delegate: Set<Map.Entry<K, V>>
+) : UnmodifiableCollection<Map.Entry<K, V>>(delegate), Set<Map.Entry<K, V>> {
+
+  // Is this overkill? Probably.
+
+  override fun iterator(): Iterator<Map.Entry<K, V>> {
+    val itr = delegate.iterator()
+    return object : Iterator<Map.Entry<K, V>> by itr {
+      override fun next(): Map.Entry<K, V> = UnmodifiableMapEntry(itr.next())
+    }
+  }
+}
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt
new file mode 100644
index 0000000..a5f0c49
--- /dev/null
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt
@@ -0,0 +1,128 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.testing.EqualsTester
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Tests for [DslList]. */
+@RunWith(JUnit4::class)
+@OptIn(OnlyForUseByGeneratedProtoCode::class)
+class DslListTest {
+  class DummyProxy private constructor() : DslProxy()
+
+  @Test
+  fun matchesList() {
+    assertThat(DslList<Int, DummyProxy>(listOf(1, 2, 3))).containsExactly(1, 2, 3).inOrder()
+  }
+
+  @Test
+  fun reflectsChangesInList() {
+    val mutableList = mutableListOf(1, 2, 3)
+    val dslList = DslList<Int, DummyProxy>(mutableList)
+    mutableList.add(4)
+    assertThat(dslList).containsExactly(1, 2, 3, 4).inOrder()
+  }
+
+  @Test
+  fun dslListIsNotMutable() {
+    val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
+    assertThat(dslList is MutableList<*>).isFalse()
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslListIsNotEvenSecretlyMutable() {
+    val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
+    val dslListAsJavaUtil = dslList as java.util.List<Int>
+    assertFailsWith<UnsupportedOperationException> {
+      dslListAsJavaUtil.add(4)
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslList_IteratorIsNotEvenSecretlyMutable() {
+    val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
+    val iterator = dslList.iterator() as java.util.Iterator<Int>
+    iterator.next()
+
+    assertFailsWith<UnsupportedOperationException> {
+      iterator.remove()
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslList_ListIteratorIsNotEvenSecretlyMutable() {
+    val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
+    val iterator = dslList.listIterator() as java.util.ListIterator<Int>
+    iterator.next()
+
+    assertFailsWith<UnsupportedOperationException> {
+      iterator.remove()
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslList_ListIteratorIndexIsNotEvenSecretlyMutable() {
+    val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
+    val iterator = dslList.listIterator(1) as java.util.ListIterator<Int>
+    iterator.next()
+
+    assertFailsWith<UnsupportedOperationException> {
+      iterator.remove()
+    }
+  }
+
+  @Test
+  fun expectedToString() {
+    assertThat(DslList<Int, DummyProxy>(listOf(1, 2)).toString()).isEqualTo("[1, 2]")
+  }
+
+  @Test
+  fun equality() {
+    EqualsTester()
+      .addEqualityGroup(DslList<Int, DummyProxy>(listOf(1, 2)), listOf(1, 2))
+      .addEqualityGroup(DslList<Int, DummyProxy>(listOf(2, 2)), listOf(2, 2))
+      .addEqualityGroup(
+        DslList<Int, DummyProxy>(emptyList()),
+        DslList<String, DummyProxy>(emptyList()),
+        emptyList<Int>()
+      )
+      .testEquals()
+  }
+}
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt
new file mode 100644
index 0000000..e7f7a19
--- /dev/null
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt
@@ -0,0 +1,194 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.testing.EqualsTester
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+@OptIn(OnlyForUseByGeneratedProtoCode::class)
+class DslMapTest {
+  class DummyProxy private constructor() : DslProxy()
+
+  @Test
+  fun matchesMap() {
+    assertThat(DslMap<Int, Int, DummyProxy>(mapOf(1 to -1, 2 to -2)))
+      .containsExactly(1, -1, 2, -2)
+  }
+
+  @Test
+  fun reflectsChangesInMap() {
+    val mutableMap = mutableMapOf(1 to -1, 2 to -2)
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMap)
+    mutableMap[3] = -3
+    assertThat(dslMap).containsExactly(1, -1, 2, -2, 3, -3).inOrder()
+  }
+
+  @Test
+  fun dslMapIsNotMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    assertThat(dslMap is MutableMap<*, *>).isFalse()
+  }
+
+  @Test
+  fun dslMapKeysAreNotMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    assertThat(dslMap.keys is MutableSet<*>).isFalse()
+  }
+
+  @Test
+  fun dslMapValuesAreNotMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    assertThat(dslMap.values is MutableSet<*>).isFalse()
+  }
+
+  @Test
+  fun dslMapEntriesAreNotMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    assertThat(dslMap.entries is MutableSet<*>).isFalse()
+  }
+
+  @Test
+  fun dslMapEntryObjectsAreNotMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    assertThat(dslMap.entries.single() is MutableMap.MutableEntry<*, *>).isFalse()
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapIsNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapAsJavaUtilMap = dslMap as java.util.Map<Int, Int>
+    assertFailsWith<UnsupportedOperationException> {
+      dslMapAsJavaUtilMap.put(2, -2)
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapKeysAreNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapKeysAsJavaUtilSet = dslMap.keys as java.util.Set<Int>
+    assertFailsWith<UnsupportedOperationException> {
+      dslMapKeysAsJavaUtilSet.remove(1)
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapKeysIteratorIsNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapKeysAsJavaUtilSet = dslMap.keys as java.util.Set<Int>
+    val itr = dslMapKeysAsJavaUtilSet.iterator()
+    itr.next()
+    assertFailsWith<UnsupportedOperationException> {
+      itr.remove()
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapValuesAreNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapValuesAsJavaUtilCollection = dslMap.values as java.util.Collection<Int>
+    assertFailsWith<UnsupportedOperationException> {
+      dslMapValuesAsJavaUtilCollection.remove(1)
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapValuesIteratorIsNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapValuesAsJavaUtilCollection = dslMap.values as java.util.Collection<Int>
+    val itr = dslMapValuesAsJavaUtilCollection.iterator()
+    itr.next()
+    assertFailsWith<UnsupportedOperationException> {
+      itr.remove()
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapEntriesAreNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapEntriesAsJavaUtilSet = dslMap.entries as java.util.Set<Map.Entry<Int, Int>>
+    val entry = dslMap.entries.single()
+    assertFailsWith<UnsupportedOperationException> {
+      dslMapEntriesAsJavaUtilSet.remove(entry)
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapEntriesIteratorIsNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapEntriesAsJavaUtilSet = dslMap.entries as java.util.Set<Map.Entry<Int, Int>>
+    val itr = dslMapEntriesAsJavaUtilSet.iterator()
+    itr.next()
+    assertFailsWith<UnsupportedOperationException> {
+      itr.remove()
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun dslMapEntryObjectsAreNotEvenSecretlyMutable() {
+    val dslMap = DslMap<Int, Int, DummyProxy>(mutableMapOf(1 to -1))
+    val dslMapEntryAsJavaUtilMapEntry = dslMap.entries.single() as java.util.Map.Entry<Int, Int>
+    assertFailsWith<UnsupportedOperationException> {
+      dslMapEntryAsJavaUtilMapEntry.value = 2
+    }
+  }
+
+  @Test
+  fun expectedToString() {
+    assertThat(DslMap<Int, Int, DummyProxy>(mapOf(1 to 2, 2 to 3)).toString())
+      .isEqualTo("{1=2, 2=3}")
+  }
+
+  @Test
+  fun equality() {
+    EqualsTester()
+      .addEqualityGroup(DslMap<Int, Int, DummyProxy>(mapOf(1 to 2, 2 to 3)), mapOf(1 to 2, 2 to 3))
+      .addEqualityGroup(DslMap<Int, Int, DummyProxy>(mapOf(1 to 3, 2 to 3)), mapOf(1 to 3, 2 to 3))
+      .addEqualityGroup(
+        DslMap<Int, Int, DummyProxy>(emptyMap()),
+        DslMap<String, String, DummyProxy>(emptyMap()),
+        emptyMap<Int, Int>()
+      )
+      .testEquals()
+  }
+}
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt
new file mode 100644
index 0000000..623bc58
--- /dev/null
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt
@@ -0,0 +1,90 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.kotlin.test.ExampleExtensibleMessage
+import com.google.protobuf.kotlin.test.ExampleExtensibleMessageOuterClass as TestProto
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ExtendableMessageExtensionsTest {
+  @Test
+  fun setOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+    builder[TestProto.int32Extension] = 5
+    assertThat(builder.build().getExtension(TestProto.int32Extension)).isEqualTo(5)
+  }
+
+  @Test
+  fun getOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+    assertThat(builder[TestProto.int32Extension]).isEqualTo(6)
+  }
+
+  @Test
+  fun getOnMessage() {
+    val message = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+      .build()
+    assertThat(message[TestProto.int32Extension]).isEqualTo(6)
+  }
+
+  @Test
+  fun containsPositiveOnMessage() {
+    val message = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+      .build()
+    assertThat(TestProto.int32Extension in message).isTrue()
+  }
+
+  @Test
+  fun containsPositiveOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+      .setExtension(TestProto.int32Extension, 6)
+    assertThat(TestProto.int32Extension in builder).isTrue()
+  }
+
+  @Test
+  fun containsNegativeOnMessage() {
+    val message = ExampleExtensibleMessage.newBuilder().build()
+    assertThat(TestProto.int32Extension in message).isFalse()
+  }
+
+  @Test
+  fun containsNegativeOnBuilder() {
+    val builder = ExampleExtensibleMessage.newBuilder()
+    assertThat(TestProto.int32Extension in builder).isFalse()
+  }
+}
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt
new file mode 100644
index 0000000..239f27a
--- /dev/null
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt
@@ -0,0 +1,155 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.testing.EqualsTester
+import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.kotlin.test.ExampleExtensibleMessage
+import com.google.protobuf.kotlin.test.ExampleExtensibleMessageOuterClass as TestProto
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Tests for [DslList]. */
+@RunWith(JUnit4::class)
+@OptIn(OnlyForUseByGeneratedProtoCode::class)
+class ExtensionListTest {
+  class DummyProxy private constructor() : DslProxy()
+
+  @Test
+  fun matchesList() {
+    assertThat(
+      ExtensionList<Int, ExampleExtensibleMessage>(
+        TestProto.repeatedExtension, listOf(1, 2, 3)
+      )
+    ).containsExactly(1, 2, 3).inOrder()
+  }
+
+  @Test
+  fun reflectsChangesInList() {
+    val mutableList = mutableListOf(1, 2, 3)
+    val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
+      TestProto.repeatedExtension, mutableList
+    )
+    mutableList.add(4)
+    assertThat(extensionList).containsExactly(1, 2, 3, 4).inOrder()
+  }
+
+  @Test
+  fun extensionListIsNotMutable() {
+    val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
+      TestProto.repeatedExtension, mutableListOf(1, 2, 3)
+    )
+    assertThat(extensionList is MutableList<*>).isFalse()
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun extensionListIsNotEvenSecretlyMutable() {
+    val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
+      TestProto.repeatedExtension, mutableListOf(1, 2, 3)
+    )
+    val extensionListAsJavaUtil = extensionList as java.util.List<Int>
+    assertFailsWith<UnsupportedOperationException> {
+      extensionListAsJavaUtil.add(4)
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun extensionList_IteratorIsNotEvenSecretlyMutable() {
+    val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
+      TestProto.repeatedExtension, mutableListOf(1, 2, 3)
+    )
+    val iterator = extensionList.iterator() as java.util.Iterator<Int>
+    iterator.next()
+
+    assertFailsWith<UnsupportedOperationException> {
+      iterator.remove()
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun extensionList_ListIteratorIsNotEvenSecretlyMutable() {
+    val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
+      TestProto.repeatedExtension, mutableListOf(1, 2, 3)
+    )
+    val iterator = extensionList.listIterator() as java.util.ListIterator<Int>
+    iterator.next()
+
+    assertFailsWith<UnsupportedOperationException> {
+      iterator.remove()
+    }
+  }
+
+  @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
+  @Test
+  fun extensionList_ListIteratorIndexIsNotEvenSecretlyMutable() {
+    val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
+      TestProto.repeatedExtension, mutableListOf(1, 2, 3)
+    )
+    val iterator = extensionList.listIterator(1) as java.util.ListIterator<Int>
+    iterator.next()
+
+    assertFailsWith<UnsupportedOperationException> {
+      iterator.remove()
+    }
+  }
+
+  @Test
+  fun expectedToString() {
+    assertThat(
+      ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(1, 2))
+        .toString()
+    ).isEqualTo("[1, 2]")
+  }
+
+  @Test
+  fun equality() {
+    EqualsTester()
+      .addEqualityGroup(
+        ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(1, 2)),
+        ExtensionList<Int, ExampleExtensibleMessage>(TestProto.differentExtension, listOf(1, 2)),
+        listOf(1, 2)
+      )
+      .addEqualityGroup(
+        ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(2, 2)),
+        listOf(2, 2)
+      )
+      .addEqualityGroup(
+        ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, emptyList()),
+        emptyList<Int>()
+      )
+      .testEquals()
+  }
+}
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
new file mode 100644
index 0000000..65f0324
--- /dev/null
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
@@ -0,0 +1,1010 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.TestUtil
+import com.google.protobuf.TestUtil.toBytes
+import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.EvilNamesProto2
+import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.HardKeywordsAllTypesProto2
+import com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.Interface
+import com.google.protobuf.kotlin.generator.HardKeywordsAllTypesProto2Kt
+import com.google.protobuf.kotlin.generator.evilNamesProto2
+import com.google.protobuf.kotlin.generator.hardKeywordsAllTypesProto2
+import com.google.protobuf.kotlin.generator.interface_
+import com.google.protobuf.test.UnittestImport.ImportEnum
+import com.google.protobuf.test.UnittestImport.ImportMessage
+import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage
+import protobuf_unittest.MapProto2Unittest.Proto2MapEnum
+import protobuf_unittest.MapProto2Unittest.TestEnumMap
+import protobuf_unittest.MapProto2Unittest.TestIntIntMap
+import protobuf_unittest.MapProto2Unittest.TestMaps
+import protobuf_unittest.TestAllTypesKt
+import protobuf_unittest.TestAllTypesKt.nestedMessage
+import protobuf_unittest.UnittestProto
+import protobuf_unittest.UnittestProto.ForeignEnum
+import protobuf_unittest.UnittestProto.TestAllTypes
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedEnum
+import protobuf_unittest.UnittestProto.TestEmptyMessage
+import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions
+import protobuf_unittest.copy
+import protobuf_unittest.foreignMessage
+import protobuf_unittest.optionalGroupExtension
+import protobuf_unittest.repeatedGroupExtension
+import protobuf_unittest.testAllExtensions
+import protobuf_unittest.testAllTypes
+import protobuf_unittest.testEmptyMessage
+import protobuf_unittest.testEmptyMessageWithExtensions
+import protobuf_unittest.testEnumMap
+import protobuf_unittest.testIntIntMap
+import protobuf_unittest.testMaps
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class Proto2Test {
+  @Test
+  fun testSetters() {
+    assertThat(
+      testAllTypes {
+        optionalInt32 = 101
+        optionalInt64 = 102
+        optionalUint32 = 103
+        optionalUint64 = 104
+        optionalSint32 = 105
+        optionalSint64 = 106
+        optionalFixed32 = 107
+        optionalFixed64 = 108
+        optionalSfixed32 = 109
+        optionalSfixed64 = 110
+        optionalFloat = 111.0f
+        optionalDouble = 112.0
+        optionalBool = true
+        optionalString = "115"
+        optionalBytes = toBytes("116")
+        optionalGroup =
+          TestAllTypesKt.optionalGroup { a = 117 }
+        optionalNestedMessage = nestedMessage { bb = 118 }
+        optionalForeignMessage = foreignMessage { c = 119 }
+        optionalImportMessage =
+          ImportMessage.newBuilder().setD(120).build()
+        optionalPublicImportMessage =
+          PublicImportMessage.newBuilder().setE(126).build()
+        optionalLazyMessage = nestedMessage { bb = 127 }
+        optionalNestedEnum = NestedEnum.BAZ
+        optionalForeignEnum = ForeignEnum.FOREIGN_BAZ
+        optionalImportEnum = ImportEnum.IMPORT_BAZ
+        optionalStringPiece = "124"
+        optionalCord = "125"
+        repeatedInt32.add(201)
+        repeatedInt64.add(202)
+        repeatedUint32.add(203)
+        repeatedUint64.add(204)
+        repeatedSint32.add(205)
+        repeatedSint64.add(206)
+        repeatedFixed32.add(207)
+        repeatedFixed64.add(208)
+        repeatedSfixed32.add(209)
+        repeatedSfixed64.add(210)
+        repeatedFloat.add(211f)
+        repeatedDouble.add(212.0)
+        repeatedBool.add(true)
+        repeatedString.add("215")
+        repeatedBytes.add(toBytes("216"))
+        repeatedGroup.add(TestAllTypesKt.repeatedGroup { a = 217 })
+        repeatedNestedMessage.add(nestedMessage { bb = 218 })
+        repeatedForeignMessage.add(foreignMessage { c = 219 })
+        repeatedImportMessage.add(
+          ImportMessage.newBuilder().setD(220).build()
+        )
+        repeatedLazyMessage.add(nestedMessage { bb = 227 })
+        repeatedNestedEnum.add(NestedEnum.BAR)
+        repeatedForeignEnum.add(ForeignEnum.FOREIGN_BAR)
+        repeatedImportEnum.add(ImportEnum.IMPORT_BAR)
+        repeatedStringPiece.add("224")
+        repeatedCord.add("225")
+        repeatedInt32 += 301
+        repeatedInt64 += 302
+        repeatedUint32 += 303
+        repeatedUint64 += 304
+        repeatedSint32 += 305
+        repeatedSint64 += 306
+        repeatedFixed32 += 307
+        repeatedFixed64 += 308
+        repeatedSfixed32 += 309
+        repeatedSfixed64 += 310
+        repeatedFloat += 311f
+        repeatedDouble += 312.0
+        repeatedBool += false
+        repeatedString += "315"
+        repeatedBytes += toBytes("316")
+        repeatedGroup += TestAllTypesKt.repeatedGroup { a = 317 }
+        repeatedNestedMessage += nestedMessage { bb = 318 }
+        repeatedForeignMessage += foreignMessage { c = 319 }
+        repeatedImportMessage +=
+          ImportMessage.newBuilder().setD(320).build()
+        repeatedLazyMessage +=
+          TestAllTypesKt.nestedMessage { bb = 327 }
+        repeatedNestedEnum += NestedEnum.BAZ
+        repeatedForeignEnum += ForeignEnum.FOREIGN_BAZ
+        repeatedImportEnum += ImportEnum.IMPORT_BAZ
+        repeatedStringPiece += "324"
+        repeatedCord += "325"
+        defaultInt32 = 401
+        defaultInt64 = 402
+        defaultUint32 = 403
+        defaultUint64 = 404
+        defaultSint32 = 405
+        defaultSint64 = 406
+        defaultFixed32 = 407
+        defaultFixed64 = 408
+        defaultSfixed32 = 409
+        defaultSfixed64 = 410
+        defaultFloat = 411f
+        defaultDouble = 412.0
+        defaultBool = false
+        defaultString = "415"
+        defaultBytes = toBytes("416")
+        defaultNestedEnum = NestedEnum.FOO
+        defaultForeignEnum = ForeignEnum.FOREIGN_FOO
+        defaultImportEnum = ImportEnum.IMPORT_FOO
+        defaultStringPiece = "424"
+        defaultCord = "425"
+        oneofUint32 = 601
+        oneofNestedMessage =
+          TestAllTypesKt.nestedMessage { bb = 602 }
+        oneofString = "603"
+        oneofBytes = toBytes("604")
+      }
+    ).isEqualTo(
+      TestUtil.getAllSetBuilder().build()
+    )
+  }
+
+  @Test
+  fun testGetters() {
+    testAllTypes {
+      optionalInt32 = 101
+      assertThat(optionalInt32).isEqualTo(101)
+      optionalString = "115"
+      assertThat(optionalString).isEqualTo("115")
+      optionalGroup = TestAllTypesKt.optionalGroup { a = 117 }
+      assertThat(optionalGroup).isEqualTo(TestAllTypesKt.optionalGroup { a = 117 })
+      optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
+      assertThat(optionalNestedMessage).isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
+      optionalNestedEnum = NestedEnum.BAZ
+      assertThat(optionalNestedEnum).isEqualTo(NestedEnum.BAZ)
+      defaultInt32 = 401
+      assertThat(defaultInt32).isEqualTo(401)
+      oneofUint32 = 601
+      assertThat(oneofUint32).isEqualTo(601)
+    }
+  }
+
+  @Test
+  fun testDefaultGetters() {
+    testAllTypes {
+      assertThat(defaultInt32).isEqualTo(41)
+      assertThat(defaultString).isEqualTo("hello")
+      assertThat(defaultNestedEnum).isEqualTo(NestedEnum.BAR)
+      assertThat(defaultStringPiece).isEqualTo("abc")
+    }
+  }
+
+  @Test
+  fun testRepeatedGettersAndSetters() {
+    testAllTypes {
+      repeatedInt32.addAll(listOf(1, 2))
+      assertThat(repeatedInt32).isEqualTo(listOf(1, 2))
+      repeatedInt32 += listOf(3, 4)
+      assertThat(repeatedInt32).isEqualTo(listOf(1, 2, 3, 4))
+      repeatedInt32[0] = 5
+      assertThat(repeatedInt32).isEqualTo(listOf(5, 2, 3, 4))
+
+      repeatedString.addAll(listOf("1", "2"))
+      assertThat(repeatedString).isEqualTo(listOf("1", "2"))
+      repeatedString += listOf("3", "4")
+      assertThat(repeatedString).isEqualTo(listOf("1", "2", "3", "4"))
+      repeatedString[0] = "5"
+      assertThat(repeatedString).isEqualTo(listOf("5", "2", "3", "4"))
+
+      repeatedGroup.addAll(
+        listOf(
+          TestAllTypesKt.repeatedGroup { a = 1 },
+          TestAllTypesKt.repeatedGroup { a = 2 }
+        )
+      )
+      assertThat(repeatedGroup).isEqualTo(
+        listOf(
+          TestAllTypesKt.repeatedGroup { a = 1 },
+          TestAllTypesKt.repeatedGroup { a = 2 }
+        )
+      )
+      repeatedGroup +=
+        listOf(
+          TestAllTypesKt.repeatedGroup { a = 3 },
+          TestAllTypesKt.repeatedGroup { a = 4 }
+        )
+      assertThat(repeatedGroup).isEqualTo(
+        listOf(
+          TestAllTypesKt.repeatedGroup { a = 1 },
+          TestAllTypesKt.repeatedGroup { a = 2 },
+          TestAllTypesKt.repeatedGroup { a = 3 },
+          TestAllTypesKt.repeatedGroup { a = 4 }
+        )
+      )
+      repeatedGroup[0] = TestAllTypesKt.repeatedGroup { a = 5 }
+      assertThat(repeatedGroup).isEqualTo(
+        listOf(
+          TestAllTypesKt.repeatedGroup { a = 5 },
+          TestAllTypesKt.repeatedGroup { a = 2 },
+          TestAllTypesKt.repeatedGroup { a = 3 },
+          TestAllTypesKt.repeatedGroup { a = 4 }
+        )
+      )
+
+      repeatedNestedMessage.addAll(listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 }))
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 }
+        )
+      )
+      repeatedNestedMessage += listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+      repeatedNestedMessage[0] = nestedMessage { bb = 5 }
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 5 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+
+      repeatedNestedEnum.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      assertThat(repeatedNestedEnum).isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      repeatedNestedEnum += listOf(NestedEnum.BAZ, NestedEnum.FOO)
+      assertThat(repeatedNestedEnum).isEqualTo(
+        listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+      repeatedNestedEnum[0] = NestedEnum.BAR
+      assertThat(repeatedNestedEnum).isEqualTo(
+        listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+    }
+  }
+
+  @Test
+  fun testHazzers() {
+    testAllTypes {
+      optionalInt32 = 101
+      assertThat(hasOptionalInt32()).isTrue()
+      assertThat(hasOptionalString()).isFalse()
+      optionalGroup = TestAllTypesKt.optionalGroup { a = 117 }
+      assertThat(hasOptionalGroup()).isTrue()
+      assertThat(hasOptionalNestedMessage()).isFalse()
+      optionalNestedEnum = NestedEnum.BAZ
+      assertThat(hasOptionalNestedEnum()).isTrue()
+      assertThat(hasDefaultInt32()).isFalse()
+      oneofUint32 = 601
+      assertThat(hasOneofUint32()).isTrue()
+    }
+
+    testAllTypes {
+      assertThat(hasOptionalInt32()).isFalse()
+      optionalString = "115"
+      assertThat(hasOptionalString()).isTrue()
+      assertThat(hasOptionalGroup()).isFalse()
+      optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
+      assertThat(hasOptionalNestedMessage()).isTrue()
+      assertThat(hasOptionalNestedEnum()).isFalse()
+      defaultInt32 = 401
+      assertThat(hasDefaultInt32()).isTrue()
+      assertThat(hasOneofUint32()).isFalse()
+    }
+  }
+
+  @Test
+  fun testClears() {
+    testAllTypes {
+      optionalInt32 = 101
+      clearOptionalInt32()
+      assertThat(hasOptionalInt32()).isFalse()
+
+      optionalString = "115"
+      clearOptionalString()
+      assertThat(hasOptionalString()).isFalse()
+
+      optionalGroup = TestAllTypesKt.optionalGroup { a = 117 }
+      clearOptionalGroup()
+      assertThat(hasOptionalGroup()).isFalse()
+
+      optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
+      clearOptionalNestedMessage()
+      assertThat(hasOptionalNestedMessage()).isFalse()
+
+      optionalNestedEnum = NestedEnum.BAZ
+      clearOptionalNestedEnum()
+      assertThat(hasOptionalNestedEnum()).isFalse()
+
+      defaultInt32 = 401
+      clearDefaultInt32()
+      assertThat(hasDefaultInt32()).isFalse()
+
+      oneofUint32 = 601
+      clearOneofUint32()
+      assertThat(hasOneofUint32()).isFalse()
+    }
+  }
+
+  @Test
+  fun testCopy() {
+    val message = testAllTypes {
+      optionalInt32 = 101
+      optionalString = "115"
+    }
+    val modifiedMessage = message.copy {
+      optionalInt32 = 201
+    }
+
+    assertThat(message).isEqualTo(
+      TestAllTypes.newBuilder()
+        .setOptionalInt32(101)
+        .setOptionalString("115")
+        .build()
+    )
+    assertThat(modifiedMessage).isEqualTo(
+      TestAllTypes.newBuilder()
+        .setOptionalInt32(201)
+        .setOptionalString("115")
+        .build()
+    )
+  }
+
+  @Test
+  fun testOneof() {
+    val message = testAllTypes {
+      oneofString = "foo"
+      assertThat(oneofFieldCase)
+        .isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_STRING)
+      assertThat(oneofString).isEqualTo("foo")
+      clearOneofField()
+      assertThat(hasOneofUint32()).isFalse()
+      assertThat(oneofFieldCase)
+        .isEqualTo(TestAllTypes.OneofFieldCase.ONEOFFIELD_NOT_SET)
+      oneofUint32 = 5
+    }
+
+    assertThat(message.getOneofFieldCase())
+      .isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_UINT32)
+    assertThat(message.getOneofUint32()).isEqualTo(5)
+  }
+
+  @Test
+  fun testExtensionsSet() {
+    assertThat(
+      testAllExtensions {
+        this[UnittestProto.optionalInt32Extension] = 101
+        this[UnittestProto.optionalInt64Extension] = 102L
+        this[UnittestProto.optionalUint32Extension] = 103
+        this[UnittestProto.optionalUint64Extension] = 104L
+        this[UnittestProto.optionalSint32Extension] = 105
+        this[UnittestProto.optionalSint64Extension] = 106L
+        this[UnittestProto.optionalFixed32Extension] = 107
+        this[UnittestProto.optionalFixed64Extension] = 108L
+        this[UnittestProto.optionalSfixed32Extension] = 109
+        this[UnittestProto.optionalSfixed64Extension] = 110L
+        this[UnittestProto.optionalFloatExtension] = 111F
+        this[UnittestProto.optionalDoubleExtension] = 112.0
+        this[UnittestProto.optionalBoolExtension] = true
+        this[UnittestProto.optionalStringExtension] = "115"
+        this[UnittestProto.optionalBytesExtension] = toBytes("116")
+        this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
+        this[UnittestProto.optionalNestedMessageExtension] =
+          TestAllTypesKt.nestedMessage { bb = 118 }
+        this[UnittestProto.optionalForeignMessageExtension] = foreignMessage { c = 119 }
+        this[UnittestProto.optionalImportMessageExtension] =
+          ImportMessage.newBuilder().setD(120).build()
+        this[UnittestProto.optionalPublicImportMessageExtension] =
+          PublicImportMessage.newBuilder().setE(126).build()
+        this[UnittestProto.optionalLazyMessageExtension] = TestAllTypesKt.nestedMessage { bb = 127 }
+        this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
+        this[UnittestProto.optionalForeignEnumExtension] = ForeignEnum.FOREIGN_BAZ
+        this[UnittestProto.optionalImportEnumExtension] = ImportEnum.IMPORT_BAZ
+        this[UnittestProto.optionalStringPieceExtension] = "124"
+        this[UnittestProto.optionalCordExtension] = "125"
+        this[UnittestProto.repeatedInt32Extension].add(201)
+        this[UnittestProto.repeatedInt64Extension].add(202L)
+        this[UnittestProto.repeatedUint32Extension].add(203)
+        this[UnittestProto.repeatedUint64Extension].add(204L)
+        this[UnittestProto.repeatedSint32Extension].add(205)
+        this[UnittestProto.repeatedSint64Extension].add(206L)
+        this[UnittestProto.repeatedFixed32Extension].add(207)
+        this[UnittestProto.repeatedFixed64Extension].add(208L)
+        this[UnittestProto.repeatedSfixed32Extension].add(209)
+        this[UnittestProto.repeatedSfixed64Extension].add(210L)
+        this[UnittestProto.repeatedFloatExtension].add(211F)
+        this[UnittestProto.repeatedDoubleExtension].add(212.0)
+        this[UnittestProto.repeatedBoolExtension].add(true)
+        this[UnittestProto.repeatedStringExtension].add("215")
+        this[UnittestProto.repeatedBytesExtension].add(toBytes("216"))
+        this[UnittestProto.repeatedGroupExtension].add(repeatedGroupExtension { a = 217 })
+        this[UnittestProto.repeatedNestedMessageExtension]
+          .add(TestAllTypesKt.nestedMessage { bb = 218 })
+        this[UnittestProto.repeatedForeignMessageExtension].add(foreignMessage { c = 219 })
+        this[UnittestProto.repeatedImportMessageExtension]
+          .add(ImportMessage.newBuilder().setD(220).build())
+        this[UnittestProto.repeatedLazyMessageExtension]
+          .add(TestAllTypesKt.nestedMessage { bb = 227 })
+        this[UnittestProto.repeatedNestedEnumExtension].add(NestedEnum.BAR)
+        this[UnittestProto.repeatedForeignEnumExtension].add(ForeignEnum.FOREIGN_BAR)
+        this[UnittestProto.repeatedImportEnumExtension].add(ImportEnum.IMPORT_BAR)
+        this[UnittestProto.repeatedStringPieceExtension].add("224")
+        this[UnittestProto.repeatedCordExtension].add("225")
+        this[UnittestProto.repeatedInt32Extension] += 301
+        this[UnittestProto.repeatedInt64Extension] += 302L
+        this[UnittestProto.repeatedUint32Extension] += 303
+        this[UnittestProto.repeatedUint64Extension] += 304L
+        this[UnittestProto.repeatedSint32Extension] += 305
+        this[UnittestProto.repeatedSint64Extension] += 306L
+        this[UnittestProto.repeatedFixed32Extension] += 307
+        this[UnittestProto.repeatedFixed64Extension] += 308L
+        this[UnittestProto.repeatedSfixed32Extension] += 309
+        this[UnittestProto.repeatedSfixed64Extension] += 310L
+        this[UnittestProto.repeatedFloatExtension] += 311F
+        this[UnittestProto.repeatedDoubleExtension] += 312.0
+        this[UnittestProto.repeatedBoolExtension] += false
+        this[UnittestProto.repeatedStringExtension] += "315"
+        this[UnittestProto.repeatedBytesExtension] += toBytes("316")
+        this[UnittestProto.repeatedGroupExtension] += repeatedGroupExtension { a = 317 }
+        this[UnittestProto.repeatedNestedMessageExtension] +=
+	  TestAllTypesKt.nestedMessage { bb = 318 }
+        this[UnittestProto.repeatedForeignMessageExtension] += foreignMessage { c = 319 }
+        this[UnittestProto.repeatedImportMessageExtension] +=
+          ImportMessage.newBuilder().setD(320).build()
+        this[UnittestProto.repeatedLazyMessageExtension] +=
+	  TestAllTypesKt.nestedMessage { bb = 327 }
+        this[UnittestProto.repeatedNestedEnumExtension] += NestedEnum.BAZ
+        this[UnittestProto.repeatedForeignEnumExtension] += ForeignEnum.FOREIGN_BAZ
+        this[UnittestProto.repeatedImportEnumExtension] += ImportEnum.IMPORT_BAZ
+        this[UnittestProto.repeatedStringPieceExtension] += "324"
+        this[UnittestProto.repeatedCordExtension] += "325"
+        this[UnittestProto.defaultInt32Extension] = 401
+        this[UnittestProto.defaultInt64Extension] = 402L
+        this[UnittestProto.defaultUint32Extension] = 403
+        this[UnittestProto.defaultUint64Extension] = 404L
+        this[UnittestProto.defaultSint32Extension] = 405
+        this[UnittestProto.defaultSint64Extension] = 406L
+        this[UnittestProto.defaultFixed32Extension] = 407
+        this[UnittestProto.defaultFixed64Extension] = 408L
+        this[UnittestProto.defaultSfixed32Extension] = 409
+        this[UnittestProto.defaultSfixed64Extension] = 410L
+        this[UnittestProto.defaultFloatExtension] = 411F
+        this[UnittestProto.defaultDoubleExtension] = 412.0
+        this[UnittestProto.defaultBoolExtension] = false
+        this[UnittestProto.defaultStringExtension] = "415"
+        this[UnittestProto.defaultBytesExtension] = toBytes("416")
+        this[UnittestProto.defaultNestedEnumExtension] = NestedEnum.FOO
+        this[UnittestProto.defaultForeignEnumExtension] = ForeignEnum.FOREIGN_FOO
+        this[UnittestProto.defaultImportEnumExtension] = ImportEnum.IMPORT_FOO
+        this[UnittestProto.defaultStringPieceExtension] = "424"
+        this[UnittestProto.defaultCordExtension] = "425"
+        this[UnittestProto.oneofUint32Extension] = 601
+        this[UnittestProto.oneofNestedMessageExtension] = TestAllTypesKt.nestedMessage { bb = 602 }
+        this[UnittestProto.oneofStringExtension] = "603"
+        this[UnittestProto.oneofBytesExtension] = toBytes("604")
+      }
+    ).isEqualTo(
+      TestUtil.getAllExtensionsSet()
+    )
+  }
+
+  @Test
+  fun testExtensionGetters() {
+    testAllExtensions {
+      this[UnittestProto.optionalInt32Extension] = 101
+      assertThat(this[UnittestProto.optionalInt32Extension]).isEqualTo(101)
+      this[UnittestProto.optionalStringExtension] = "115"
+      assertThat(this[UnittestProto.optionalStringExtension]).isEqualTo("115")
+      this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
+      assertThat(this[UnittestProto.optionalGroupExtension])
+        .isEqualTo(optionalGroupExtension { a = 117 })
+      this[UnittestProto.optionalNestedMessageExtension] =
+        TestAllTypesKt.nestedMessage { bb = 118 }
+      assertThat(this[UnittestProto.optionalNestedMessageExtension])
+        .isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
+      this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
+      assertThat(this[UnittestProto.optionalNestedEnumExtension]).isEqualTo(NestedEnum.BAZ)
+      this[UnittestProto.defaultInt32Extension] = 401
+      assertThat(this[UnittestProto.defaultInt32Extension]).isEqualTo(401)
+      this[UnittestProto.oneofUint32Extension] = 601
+      assertThat(this[UnittestProto.oneofUint32Extension]).isEqualTo(601)
+    }
+  }
+
+  @Test
+  fun testRepeatedExtensionGettersAndSetters() {
+    testAllExtensions {
+      this[UnittestProto.repeatedInt32Extension].addAll(listOf(1, 2))
+      assertThat(this[UnittestProto.repeatedInt32Extension]).isEqualTo(listOf(1, 2))
+      this[UnittestProto.repeatedInt32Extension] += listOf(3, 4)
+      assertThat(this[UnittestProto.repeatedInt32Extension]).isEqualTo(listOf(1, 2, 3, 4))
+      this[UnittestProto.repeatedInt32Extension][0] = 5
+      assertThat(this[UnittestProto.repeatedInt32Extension]).isEqualTo(listOf(5, 2, 3, 4))
+
+      this[UnittestProto.repeatedStringExtension].addAll(listOf("1", "2"))
+      assertThat(this[UnittestProto.repeatedStringExtension]).isEqualTo(listOf("1", "2"))
+      this[UnittestProto.repeatedStringExtension] += listOf("3", "4")
+      assertThat(this[UnittestProto.repeatedStringExtension]).isEqualTo(listOf("1", "2", "3", "4"))
+      this[UnittestProto.repeatedStringExtension][0] = "5"
+      assertThat(this[UnittestProto.repeatedStringExtension]).isEqualTo(listOf("5", "2", "3", "4"))
+
+      this[UnittestProto.repeatedGroupExtension].addAll(
+        listOf(
+          repeatedGroupExtension { a = 1 },
+          repeatedGroupExtension { a = 2 }
+        )
+      )
+      assertThat(this[UnittestProto.repeatedGroupExtension]).isEqualTo(
+        listOf(
+          repeatedGroupExtension { a = 1 },
+          repeatedGroupExtension { a = 2 }
+        )
+      )
+      this[UnittestProto.repeatedGroupExtension] +=
+        listOf(
+          repeatedGroupExtension { a = 3 },
+          repeatedGroupExtension { a = 4 }
+        )
+      assertThat(this[UnittestProto.repeatedGroupExtension]).isEqualTo(
+        listOf(
+          repeatedGroupExtension { a = 1 },
+          repeatedGroupExtension { a = 2 },
+          repeatedGroupExtension { a = 3 },
+          repeatedGroupExtension { a = 4 }
+        )
+      )
+      this[UnittestProto.repeatedGroupExtension][0] = repeatedGroupExtension { a = 5 }
+      assertThat(this[UnittestProto.repeatedGroupExtension]).isEqualTo(
+        listOf(
+          repeatedGroupExtension { a = 5 },
+          repeatedGroupExtension { a = 2 },
+          repeatedGroupExtension { a = 3 },
+          repeatedGroupExtension { a = 4 }
+        )
+      )
+
+      this[UnittestProto.repeatedNestedMessageExtension].addAll(
+        listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
+      )
+      assertThat(this[UnittestProto.repeatedNestedMessageExtension]).isEqualTo(
+        listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 })
+      )
+      this[UnittestProto.repeatedNestedMessageExtension] +=
+        listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
+      assertThat(this[UnittestProto.repeatedNestedMessageExtension]).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+      this[UnittestProto.repeatedNestedMessageExtension][0] = nestedMessage { bb = 5 }
+      assertThat(this[UnittestProto.repeatedNestedMessageExtension]).isEqualTo(
+        listOf(
+          nestedMessage { bb = 5 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+
+      this[UnittestProto.repeatedNestedEnumExtension]
+        .addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      assertThat(this[UnittestProto.repeatedNestedEnumExtension])
+        .isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      this[UnittestProto.repeatedNestedEnumExtension] += listOf(NestedEnum.BAZ, NestedEnum.FOO)
+      assertThat(this[UnittestProto.repeatedNestedEnumExtension]).isEqualTo(
+        listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+    }
+  }
+
+  @Test
+  fun testExtensionContains() {
+    testAllExtensions {
+      this[UnittestProto.optionalInt32Extension] = 101
+      assertThat(contains(UnittestProto.optionalInt32Extension)).isTrue()
+      assertThat(contains(UnittestProto.optionalStringExtension)).isFalse()
+      this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
+      assertThat(contains(UnittestProto.optionalGroupExtension)).isTrue()
+      assertThat(contains(UnittestProto.optionalNestedMessageExtension)).isFalse()
+      this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
+      assertThat(contains(UnittestProto.optionalNestedEnumExtension)).isTrue()
+      assertThat(contains(UnittestProto.defaultInt32Extension)).isFalse()
+      this[UnittestProto.oneofUint32Extension] = 601
+      assertThat(contains(UnittestProto.optionalInt32Extension)).isTrue()
+    }
+
+    testAllExtensions {
+      assertThat(contains(UnittestProto.optionalInt32Extension)).isFalse()
+      this[UnittestProto.optionalStringExtension] = "115"
+      assertThat(contains(UnittestProto.optionalStringExtension)).isTrue()
+      assertThat(contains(UnittestProto.optionalGroupExtension)).isFalse()
+      this[UnittestProto.optionalNestedMessageExtension] =
+        TestAllTypesKt.nestedMessage { bb = 118 }
+      assertThat(contains(UnittestProto.optionalNestedMessageExtension)).isTrue()
+      assertThat(contains(UnittestProto.optionalNestedEnumExtension)).isFalse()
+      this[UnittestProto.defaultInt32Extension] = 401
+      assertThat(contains(UnittestProto.defaultInt32Extension)).isTrue()
+      assertThat(contains(UnittestProto.oneofUint32Extension)).isFalse()
+    }
+  }
+
+  @Test
+  fun testExtensionClears() {
+    testAllExtensions {
+      this[UnittestProto.optionalInt32Extension] = 101
+      clear(UnittestProto.optionalInt32Extension)
+      assertThat(contains(UnittestProto.optionalInt32Extension)).isFalse()
+
+      this[UnittestProto.optionalStringExtension] = "115"
+      clear(UnittestProto.optionalStringExtension)
+      assertThat(contains(UnittestProto.optionalStringExtension)).isFalse()
+
+      this[UnittestProto.optionalGroupExtension] = optionalGroupExtension { a = 117 }
+      clear(UnittestProto.optionalGroupExtension)
+      assertThat(contains(UnittestProto.optionalGroupExtension)).isFalse()
+
+      this[UnittestProto.optionalNestedMessageExtension] =
+        TestAllTypesKt.nestedMessage { bb = 118 }
+      clear(UnittestProto.optionalNestedMessageExtension)
+      assertThat(contains(UnittestProto.optionalNestedMessageExtension)).isFalse()
+
+      this[UnittestProto.optionalNestedEnumExtension] = NestedEnum.BAZ
+      clear(UnittestProto.optionalNestedEnumExtension)
+      assertThat(contains(UnittestProto.optionalNestedEnumExtension)).isFalse()
+
+      this[UnittestProto.defaultInt32Extension] = 401
+      clear(UnittestProto.defaultInt32Extension)
+      assertThat(contains(UnittestProto.oneofUint32Extension)).isFalse()
+    }
+  }
+
+  @Test
+  fun testEmptyMessages() {
+    assertThat(
+      testEmptyMessage {}
+    ).isEqualTo(
+      TestEmptyMessage.newBuilder().build()
+    )
+
+    assertThat(
+      testEmptyMessageWithExtensions {}
+    ).isEqualTo(
+      TestEmptyMessageWithExtensions.newBuilder().build()
+    )
+  }
+
+  @Test
+  fun testMapSetters() {
+    val intMap = testIntIntMap { m[1] = 2 }
+    assertThat(intMap).isEqualTo(
+      TestIntIntMap.newBuilder().putM(1, 2).build()
+    )
+
+    assertThat(
+      testMaps {
+        mInt32[1] = intMap
+        mInt64[1L] = intMap
+        mUint32[1] = intMap
+        mUint64[1L] = intMap
+        mSint32[1] = intMap
+        mSint64[1L] = intMap
+        mFixed32[1] = intMap
+        mFixed64[1L] = intMap
+        mSfixed32[1] = intMap
+        mSfixed64[1] = intMap
+        mBool[true] = intMap
+        mString["1"] = intMap
+      }
+    ).isEqualTo(
+      TestMaps.newBuilder()
+        .putMInt32(1, intMap)
+        .putMInt64(1L, intMap)
+        .putMUint32(1, intMap)
+        .putMUint64(1L, intMap)
+        .putMSint32(1, intMap)
+        .putMSint64(1L, intMap)
+        .putMFixed32(1, intMap)
+        .putMFixed64(1L, intMap)
+        .putMSfixed32(1, intMap)
+        .putMSfixed64(1L, intMap)
+        .putMBool(true, intMap)
+        .putMString("1", intMap)
+        .build()
+    )
+
+    assertThat(
+      testEnumMap {
+        knownMapField[1] = Proto2MapEnum.PROTO2_MAP_ENUM_FOO
+      }
+    ).isEqualTo(
+      TestEnumMap.newBuilder()
+        .putKnownMapField(1, Proto2MapEnum.PROTO2_MAP_ENUM_FOO)
+        .build()
+    )
+  }
+
+  @Test
+  fun testMapGettersAndSetters() {
+    val intMap =
+      testIntIntMap {
+        m.put(1, 2)
+        assertThat(m).isEqualTo(mapOf(1 to 2))
+        m[3] = 4
+        assertThat(m).isEqualTo(mapOf(1 to 2, 3 to 4))
+        m.putAll(mapOf(5 to 6, 7 to 8))
+        assertThat(m).isEqualTo(mapOf(1 to 2, 3 to 4, 5 to 6, 7 to 8))
+      }
+
+    testMaps {
+      mInt32.put(1, intMap)
+      assertThat(mInt32).isEqualTo(mapOf(1 to intMap))
+      mInt32[2] = intMap
+      assertThat(mInt32).isEqualTo(mapOf(1 to intMap, 2 to intMap))
+      mInt32.putAll(mapOf(3 to intMap, 4 to intMap))
+      assertThat(mInt32).isEqualTo(mapOf(1 to intMap, 2 to intMap, 3 to intMap, 4 to intMap))
+
+      mString.put("1", intMap)
+      assertThat(mString).isEqualTo(mapOf("1" to intMap))
+      mString["2"] = intMap
+      assertThat(mString).isEqualTo(mapOf("1" to intMap, "2" to intMap))
+      mString.putAll(mapOf("3" to intMap, "4" to intMap))
+      assertThat(mString).isEqualTo(
+        mapOf("1" to intMap, "2" to intMap, "3" to intMap, "4" to intMap)
+      )
+    }
+
+    testEnumMap {
+      knownMapField.put(1, Proto2MapEnum.PROTO2_MAP_ENUM_FOO)
+      assertThat(knownMapField).isEqualTo(mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO))
+      knownMapField[2] = Proto2MapEnum.PROTO2_MAP_ENUM_BAR
+      assertThat(knownMapField).isEqualTo(
+        mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, 2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR)
+      )
+      knownMapField.putAll(
+        mapOf(3 to Proto2MapEnum.PROTO2_MAP_ENUM_BAZ, 4 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO)
+      )
+      assertThat(knownMapField).isEqualTo(
+        mapOf(
+          1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO,
+          2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR,
+          3 to Proto2MapEnum.PROTO2_MAP_ENUM_BAZ,
+          4 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO
+        )
+      )
+    }
+  }
+
+  @Test
+  fun testMapRemove() {
+    val intMap =
+      testIntIntMap {
+        m.putAll(mapOf(1 to 2, 3 to 4))
+        m.remove(1)
+        assertThat(m).isEqualTo(mapOf(3 to 4))
+      }
+
+    testMaps {
+      mInt32.putAll(mapOf(1 to intMap, 2 to intMap))
+      mInt32.remove(1)
+      assertThat(mInt32).isEqualTo(mapOf(2 to intMap))
+
+      mString.putAll(mapOf("1" to intMap, "2" to intMap))
+      mString.remove("1")
+      assertThat(mString).isEqualTo(mapOf("2" to intMap))
+    }
+
+    testEnumMap {
+      knownMapField.putAll(
+        mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, 2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR)
+      )
+      knownMapField.remove(1)
+      assertThat(knownMapField).isEqualTo(mapOf(2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR))
+    }
+  }
+
+  @Test
+  fun testMapClear() {
+    val intMap =
+      testIntIntMap {
+        m.putAll(mapOf(1 to 2, 3 to 4))
+        m.clear()
+        assertThat(m.isEmpty()).isTrue()
+      }
+
+    testMaps {
+      mInt32.putAll(mapOf(1 to intMap, 2 to intMap))
+      mInt32.clear()
+      assertThat(mInt32.isEmpty()).isTrue()
+
+      mString.putAll(mapOf("1" to intMap, "2" to intMap))
+      mString.clear()
+      assertThat(mString.isEmpty()).isTrue()
+    }
+
+    testEnumMap {
+      knownMapField.putAll(
+        mapOf(1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, 2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR)
+      )
+      knownMapField.clear()
+      assertThat(knownMapField.isEmpty()).isTrue()
+    }
+  }
+
+  @Test
+  fun testEvilNames() {
+    assertThat(
+      evilNamesProto2 {
+        initialized = true
+        hasFoo = true
+        bar = "foo"
+        isInitialized = true
+        fooBar = "foo"
+        aLLCAPS += "foo"
+        aLLCAPSMAP[1] = true
+        hasUnderbarPrecedingNumeric1Foo = true
+        hasUnderbarPrecedingNumeric42Bar = true
+        hasUnderbarPrecedingNumeric123Foo42BarBaz = true
+        extension += "foo"
+        class_ += 1
+        int = 1.0
+        long = true
+        boolean = 1L
+        sealed = "foo"
+        interface_ = 1F
+        in_ = 1
+        object_ = "foo"
+        cachedSize_ = "foo"
+        serializedSize_ = true
+        by = "foo"
+      }
+    ).isEqualTo(
+      EvilNamesProto2.newBuilder()
+        .setInitialized(true)
+        .setHasFoo(true)
+        .setBar("foo")
+        .setIsInitialized(true)
+        .setFooBar("foo")
+        .addALLCAPS("foo")
+        .putALLCAPSMAP(1, true)
+        .setHasUnderbarPrecedingNumeric1Foo(true)
+        .setHasUnderbarPrecedingNumeric42Bar(true)
+        .setHasUnderbarPrecedingNumeric123Foo42BarBaz(true)
+        .addExtension("foo")
+        .addClass_(1)
+        .setInt(1.0)
+        .setLong(true)
+        .setBoolean(1L)
+        .setSealed("foo")
+        .setInterface(1F)
+        .setIn(1)
+        .setObject("foo")
+        .setCachedSize_("foo")
+        .setSerializedSize_(true)
+        .setBy("foo")
+        .build()
+    )
+
+    assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build())
+  }
+
+  @Test
+  fun testHardKeywordGettersAndSetters() {
+    hardKeywordsAllTypesProto2 {
+      as_ = 1
+      assertThat(as_).isEqualTo(1)
+
+      in_ = "foo"
+      assertThat(in_).isEqualTo("foo")
+
+      break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
+      assertThat(break_).isEqualTo(HardKeywordsAllTypesProto2.NestedEnum.FOO)
+
+      do_ = HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      assertThat(do_).isEqualTo(HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 })
+
+      continue_[1] = 1
+      assertThat(continue_[1]).isEqualTo(1)
+
+      else_ += 1
+      assertThat(else_).isEqualTo(listOf(1))
+
+      for_ += "foo"
+      assertThat(for_).isEqualTo(listOf("foo"))
+
+      fun_ += HardKeywordsAllTypesProto2.NestedEnum.FOO
+      assertThat(fun_).isEqualTo(listOf(HardKeywordsAllTypesProto2.NestedEnum.FOO))
+
+      if_ += HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      assertThat(if_).isEqualTo(listOf(HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }))
+    }
+  }
+
+  @Test
+  fun testHardKeywordHazzers() {
+    hardKeywordsAllTypesProto2 {
+      as_ = 1
+      assertThat(hasAs_()).isTrue()
+
+      in_ = "foo"
+      assertThat(hasIn_()).isTrue()
+
+      break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
+      assertThat(hasBreak_()).isTrue()
+
+      do_ = HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      assertThat(hasDo_()).isTrue()
+    }
+  }
+
+  @Test
+  fun testHardKeywordClears() {
+    hardKeywordsAllTypesProto2 {
+      as_ = 1
+      clearAs_()
+      assertThat(hasAs_()).isFalse()
+
+      in_ = "foo"
+      clearIn_()
+      assertThat(hasIn_()).isFalse()
+
+      break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
+      clearBreak_()
+      assertThat(hasBreak_()).isFalse()
+
+      do_ = HardKeywordsAllTypesProto2Kt.nestedMessage { while_ = 1 }
+      clearDo_()
+      assertThat(hasDo_()).isFalse()
+    }
+  }
+}
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt
new file mode 100644
index 0000000..7b394da
--- /dev/null
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt
@@ -0,0 +1,365 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.kotlin
+
+import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.kotlin.generator.EvilNamesProto3OuterClass.Class
+import com.google.protobuf.kotlin.generator.EvilNamesProto3OuterClass.EvilNamesProto3
+import com.google.protobuf.kotlin.generator.EvilNamesProto3OuterClass.HardKeywordsAllTypesProto3
+import com.google.protobuf.kotlin.generator.HardKeywordsAllTypesProto3Kt
+import com.google.protobuf.kotlin.generator.class_
+import com.google.protobuf.kotlin.generator.evilNamesProto3
+import com.google.protobuf.kotlin.generator.hardKeywordsAllTypesProto3
+import proto3_unittest.TestAllTypesKt
+import proto3_unittest.TestAllTypesKt.nestedMessage
+import proto3_unittest.UnittestProto3.TestAllTypes
+import proto3_unittest.UnittestProto3.TestAllTypes.NestedEnum
+import proto3_unittest.UnittestProto3.TestEmptyMessage
+import proto3_unittest.copy
+import proto3_unittest.testAllTypes
+import proto3_unittest.testEmptyMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class Proto3Test {
+  @Test
+  fun testGettersAndSetters() {
+    testAllTypes {
+      optionalInt32 = 101
+      assertThat(optionalInt32).isEqualTo(101)
+      optionalString = "115"
+      assertThat(optionalString).isEqualTo("115")
+      optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
+      assertThat(optionalNestedMessage).isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
+      optionalNestedEnum = NestedEnum.BAZ
+      assertThat(optionalNestedEnum).isEqualTo(NestedEnum.BAZ)
+      oneofUint32 = 601
+      assertThat(oneofUint32).isEqualTo(601)
+    }
+  }
+
+  @Test
+  fun testRepeatedGettersAndSetters() {
+    testAllTypes {
+      repeatedInt32.addAll(listOf(1, 2))
+      assertThat(repeatedInt32).isEqualTo(listOf(1, 2))
+      repeatedInt32 += listOf(3, 4)
+      assertThat(repeatedInt32).isEqualTo(listOf(1, 2, 3, 4))
+      repeatedInt32[0] = 5
+      assertThat(repeatedInt32).isEqualTo(listOf(5, 2, 3, 4))
+
+      repeatedString.addAll(listOf("1", "2"))
+      assertThat(repeatedString).isEqualTo(listOf("1", "2"))
+      repeatedString += listOf("3", "4")
+      assertThat(repeatedString).isEqualTo(listOf("1", "2", "3", "4"))
+      repeatedString[0] = "5"
+      assertThat(repeatedString).isEqualTo(listOf("5", "2", "3", "4"))
+
+      repeatedNestedMessage.addAll(listOf(nestedMessage { bb = 1 }, nestedMessage { bb = 2 }))
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 }
+        )
+      )
+      repeatedNestedMessage += listOf(nestedMessage { bb = 3 }, nestedMessage { bb = 4 })
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 1 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+      repeatedNestedMessage[0] = nestedMessage { bb = 5 }
+      assertThat(repeatedNestedMessage).isEqualTo(
+        listOf(
+          nestedMessage { bb = 5 },
+          nestedMessage { bb = 2 },
+          nestedMessage { bb = 3 },
+          nestedMessage { bb = 4 }
+        )
+      )
+
+      repeatedNestedEnum.addAll(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      assertThat(repeatedNestedEnum).isEqualTo(listOf(NestedEnum.FOO, NestedEnum.BAR))
+      repeatedNestedEnum += listOf(NestedEnum.BAZ, NestedEnum.FOO)
+      assertThat(repeatedNestedEnum).isEqualTo(
+        listOf(NestedEnum.FOO, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+      repeatedNestedEnum[0] = NestedEnum.BAR
+      assertThat(repeatedNestedEnum).isEqualTo(
+        listOf(NestedEnum.BAR, NestedEnum.BAR, NestedEnum.BAZ, NestedEnum.FOO)
+      )
+    }
+  }
+
+  @Test
+  fun testClears() {
+    assertThat(
+      testAllTypes {
+        optionalInt32 = 101
+        clearOptionalInt32()
+
+        optionalString = "115"
+        clearOptionalString()
+
+        optionalNestedMessage = TestAllTypesKt.nestedMessage { bb = 118 }
+        clearOptionalNestedMessage()
+
+        optionalNestedEnum = NestedEnum.BAZ
+        clearOptionalNestedEnum()
+
+        oneofUint32 = 601
+        clearOneofUint32()
+      }
+    ).isEqualTo(
+      TestAllTypes.newBuilder().build()
+    )
+  }
+
+  @Test
+  fun testCopy() {
+    val message = testAllTypes {
+      optionalInt32 = 101
+      optionalString = "115"
+    }
+    val modifiedMessage = message.copy {
+      optionalInt32 = 201
+    }
+
+    assertThat(message).isEqualTo(
+      TestAllTypes.newBuilder()
+        .setOptionalInt32(101)
+        .setOptionalString("115")
+        .build()
+    )
+    assertThat(modifiedMessage).isEqualTo(
+      TestAllTypes.newBuilder()
+        .setOptionalInt32(201)
+        .setOptionalString("115")
+        .build()
+    )
+  }
+
+  @Test
+  fun testOneof() {
+    val message = testAllTypes {
+      oneofString = "foo"
+      assertThat(oneofFieldCase)
+        .isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_STRING)
+      assertThat(oneofString).isEqualTo("foo")
+      clearOneofField()
+      assertThat(oneofFieldCase)
+        .isEqualTo(TestAllTypes.OneofFieldCase.ONEOFFIELD_NOT_SET)
+      oneofUint32 = 5
+    }
+
+    assertThat(message.getOneofFieldCase())
+      .isEqualTo(TestAllTypes.OneofFieldCase.ONEOF_UINT32)
+    assertThat(message.getOneofUint32()).isEqualTo(5)
+  }
+
+  @Test
+  fun testEmptyMessages() {
+    assertThat(
+      testEmptyMessage {}
+    ).isEqualTo(
+      TestEmptyMessage.newBuilder().build()
+    )
+  }
+
+  @Test
+  fun testEvilNames() {
+    assertThat(
+      evilNamesProto3 {
+        initialized = true
+        hasFoo = true
+        bar = "foo"
+        isInitialized = true
+        fooBar = "foo"
+        aLLCAPS += "foo"
+        aLLCAPSMAP[1] = true
+        hasUnderbarPrecedingNumeric1Foo = true
+        hasUnderbarPrecedingNumeric42Bar = true
+        hasUnderbarPrecedingNumeric123Foo42BarBaz = true
+        extension += "foo"
+        class_ = "foo"
+        int = 1.0
+        long = true
+        boolean = 1L
+        sealed = "foo"
+        interface_ = 1F
+        in_ = 1
+        object_ = "foo"
+        cachedSize_ = "foo"
+        serializedSize_ = true
+        value = "foo"
+        index = 1L
+        values += "foo"
+        newValues += "foo"
+        builder = true
+        k[1] = 1
+        v["foo"] = "foo"
+        key["foo"] = 1
+        map[1] = "foo"
+        pairs["foo"] = 1
+        LeadingUnderscore = "foo"
+        option = 1
+      }
+    ).isEqualTo(
+      EvilNamesProto3.newBuilder()
+        .setInitialized(true)
+        .setHasFoo(true)
+        .setBar("foo")
+        .setIsInitialized(true)
+        .setFooBar("foo")
+        .addALLCAPS("foo")
+        .putALLCAPSMAP(1, true)
+        .setHasUnderbarPrecedingNumeric1Foo(true)
+        .setHasUnderbarPrecedingNumeric42Bar(true)
+        .setHasUnderbarPrecedingNumeric123Foo42BarBaz(true)
+        .addExtension("foo")
+        .setClass_("foo")
+        .setInt(1.0)
+        .setLong(true)
+        .setBoolean(1L)
+        .setSealed("foo")
+        .setInterface(1F)
+        .setIn(1)
+        .setObject("foo")
+        .setCachedSize_("foo")
+        .setSerializedSize_(true)
+        .setValue("foo")
+        .setIndex(1L)
+        .addValues("foo")
+        .addNewValues("foo")
+        .setBuilder(true)
+        .putK(1, 1)
+        .putV("foo", "foo")
+        .putKey("foo", 1)
+        .putMap(1, "foo")
+        .putPairs("foo", 1)
+        .setLeadingUnderscore("foo")
+        .setOption(1)
+        .build()
+    )
+
+    assertThat(class_ {}).isEqualTo(Class.newBuilder().build())
+  }
+
+  @Test
+  fun testHardKeywordGettersAndSetters() {
+    hardKeywordsAllTypesProto3 {
+      as_ = 1
+      assertThat(as_).isEqualTo(1)
+
+      in_ = "foo"
+      assertThat(in_).isEqualTo("foo")
+
+      break_ = HardKeywordsAllTypesProto3.NestedEnum.FOO
+      assertThat(break_).isEqualTo(HardKeywordsAllTypesProto3.NestedEnum.FOO)
+
+      do_ = HardKeywordsAllTypesProto3Kt.nestedMessage { while_ = 1 }
+      assertThat(do_).isEqualTo(HardKeywordsAllTypesProto3Kt.nestedMessage { while_ = 1 })
+
+      continue_[1] = 1
+      assertThat(continue_[1]).isEqualTo(1)
+
+      else_ += 1
+      assertThat(else_).isEqualTo(listOf(1))
+
+      for_ += "foo"
+      assertThat(for_).isEqualTo(listOf("foo"))
+
+      fun_ += HardKeywordsAllTypesProto3.NestedEnum.FOO
+      assertThat(fun_).isEqualTo(listOf(HardKeywordsAllTypesProto3.NestedEnum.FOO))
+
+      if_ += HardKeywordsAllTypesProto3Kt.nestedMessage { while_ = 1 }
+      assertThat(if_).isEqualTo(listOf(HardKeywordsAllTypesProto3Kt.nestedMessage { while_ = 1 }))
+    }
+  }
+
+  @Test
+  fun testHardKeywordHazzers() {
+    hardKeywordsAllTypesProto3 {
+      as_ = 1
+      assertThat(hasAs_()).isTrue()
+
+      in_ = "foo"
+      assertThat(hasIn_()).isTrue()
+
+      break_ = HardKeywordsAllTypesProto3.NestedEnum.FOO
+      assertThat(hasBreak_()).isTrue()
+
+      do_ = HardKeywordsAllTypesProto3Kt.nestedMessage { while_ = 1 }
+      assertThat(hasDo_()).isTrue()
+    }
+  }
+
+  @Test
+  fun testHardKeywordClears() {
+    hardKeywordsAllTypesProto3 {
+      as_ = 1
+      clearAs_()
+      assertThat(hasAs_()).isFalse()
+
+      in_ = "foo"
+      clearIn_()
+      assertThat(hasIn_()).isFalse()
+
+      break_ = HardKeywordsAllTypesProto3.NestedEnum.FOO
+      clearBreak_()
+      assertThat(hasBreak_()).isFalse()
+
+      do_ = HardKeywordsAllTypesProto3Kt.nestedMessage { while_ = 1 }
+      clearDo_()
+      assertThat(hasDo_()).isFalse()
+    }
+  }
+
+  @Test
+  fun testMultipleFiles() {
+    assertThat(
+      com.google.protobuf.kotlin.generator.multipleFilesMessageA {}
+    ).isEqualTo(
+      com.google.protobuf.kotlin.generator.MultipleFilesMessageA.newBuilder().build()
+    )
+
+    assertThat(
+      com.google.protobuf.kotlin.generator.multipleFilesMessageB {}
+    ).isEqualTo(
+      com.google.protobuf.kotlin.generator.MultipleFilesMessageB.newBuilder().build()
+    )
+  }
+}
diff --git a/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto
new file mode 100644
index 0000000..3735baf
--- /dev/null
+++ b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// LINT: LEGACY_NAMES
+syntax = "proto2";
+
+package protobuf.kotlin.generator;
+
+option java_package = "com.google.protobuf.kotlin.generator";
+
+message EvilNamesProto2 {
+  optional bool initialized = 1;
+  optional bool has_foo = 2;
+  optional string Bar = 3;
+  optional bool is_initialized = 4;
+
+  oneof camelCase {
+    string fooBar = 5;
+  }
+
+  repeated string ALL_CAPS = 7;
+  map<int32, bool> ALL_CAPS_MAP = 8;
+
+  optional bool has_underbar_preceding_numeric_1foo = 9;
+  optional bool has_underbar_preceding_numeric_42bar = 13;
+  optional bool has_underbar_preceding_numeric_123foo42bar_baz = 14;
+
+  extensions 100 to max;
+
+  repeated string extension = 12;
+  repeated int32 class = 15;
+  optional double int = 16;
+  optional bool long = 17;
+  optional int64 boolean = 18;
+  optional string sealed = 19;
+  optional float interface = 20;
+  optional int32 in = 21;
+  optional string object = 22;
+  optional string cached_size = 23;
+  optional bool serialized_size = 24;
+  optional string by = 25;
+}
+
+message HardKeywordsAllTypesProto2 {
+  message NestedMessage {
+    optional int32 while = 1;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+  }
+
+  optional int32 as = 1;
+  optional string in = 2;
+  optional NestedEnum break = 3;
+  map<int32, int32> continue = 4;
+  optional NestedMessage do = 5;
+
+  repeated int32 else = 6;
+  repeated string for = 7;
+  repeated NestedEnum fun = 8;
+  repeated NestedMessage if = 9;
+}
+
+message Interface {}
diff --git a/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto
new file mode 100644
index 0000000..f6b06d3
--- /dev/null
+++ b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto
@@ -0,0 +1,107 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// LINT: LEGACY_NAMES
+syntax = "proto3";
+
+package protobuf.kotlin.generator;
+
+option java_package = "com.google.protobuf.kotlin.generator";
+
+message EvilNamesProto3 {
+  bool initialized = 1;
+  bool has_foo = 2;
+  string Bar = 3;
+  bool is_initialized = 4;
+
+  oneof camelCase {
+    string fooBar = 5;
+  }
+
+  repeated string ALL_CAPS = 7;
+  map<int32, bool> ALL_CAPS_MAP = 8;
+
+  bool has_underbar_preceding_numeric_1foo = 9;
+  bool has_underbar_preceding_numeric_42bar = 10;
+  bool has_underbar_preceding_numeric_123foo42bar_baz = 11;
+
+  repeated string extension = 12;
+
+  string class = 13;
+  double int = 14;
+  bool long = 15;
+  int64 boolean = 16;
+  string sealed = 17;
+  float interface = 18;
+  int32 in = 19;
+  string object = 20;
+  string cached_size = 21;
+  bool serialized_size = 22;
+  string value = 23;
+  int64 index = 24;
+  repeated string values = 25;
+  repeated string new_values = 26;
+  bool builder = 27;
+  map<int32, int32> k = 28;
+  map<string, string> v = 29;
+  map<string, int32> key = 30;
+  map<int32, string> map = 31;
+  map<string, int32> pairs = 32;
+
+  string _leading_underscore = 33;
+  oneof _leading_underscore_oneof {
+    int32 option = 34;
+  }
+}
+
+message HardKeywordsAllTypesProto3 {
+  message NestedMessage {
+    optional int32 while = 1;
+  }
+
+  enum NestedEnum {
+    ZERO = 0;
+    FOO = 1;
+    BAR = 2;
+  }
+
+  optional int32 as = 1;
+  optional string in = 2;
+  optional NestedEnum break = 3;
+  map<int32, int32> continue = 4;
+  optional NestedMessage do = 5;
+
+  repeated int32 else = 6;
+  repeated string for = 7;
+  repeated NestedEnum fun = 8;
+  repeated NestedMessage if = 9;
+}
+
+message Class {}
diff --git a/src/google/protobuf/unittest_no_arena_import.proto b/java/kotlin/src/test/proto/com/google/protobuf/example_extensible_message.proto
similarity index 82%
copy from src/google/protobuf/unittest_no_arena_import.proto
copy to java/kotlin/src/test/proto/com/google/protobuf/example_extensible_message.proto
index 6f3f04f..b82c82b 100644
--- a/src/google/protobuf/unittest_no_arena_import.proto
+++ b/java/kotlin/src/test/proto/com/google/protobuf/example_extensible_message.proto
@@ -30,10 +30,17 @@
 
 syntax = "proto2";
 
-package proto2_arena_unittest;
+package protobuf.kotlin.test;
 
-option cc_enable_arenas = false;
+option java_package = "com.google.protobuf.kotlin.test";
+option java_multiple_files = true;
 
-message ImportNoArenaNestedMessage {
-  optional int32 d = 1;
+message ExampleExtensibleMessage {
+  extensions 10 to 20;
+}
+
+extend ExampleExtensibleMessage {
+  repeated int32 repeated_extension = 10;
+  repeated int32 different_extension = 11;
+  optional int32 int32_extension = 12;
 }
diff --git a/src/google/protobuf/unittest_no_arena_import.proto b/java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto
similarity index 86%
copy from src/google/protobuf/unittest_no_arena_import.proto
copy to java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto
index 6f3f04f..61141c5 100644
--- a/src/google/protobuf/unittest_no_arena_import.proto
+++ b/java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto
@@ -28,12 +28,15 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+syntax = "proto3";
 
-package proto2_arena_unittest;
+package protobuf.kotlin.generator;
 
-option cc_enable_arenas = false;
+option java_package = "com.google.protobuf.kotlin.generator";
+option java_multiple_files = true;
 
-message ImportNoArenaNestedMessage {
-  optional int32 d = 1;
-}
+enum NestedEnum { FOO = 0; }
+
+message MultipleFilesMessageA {}
+
+message MultipleFilesMessageB {}
diff --git a/java/lite.md b/java/lite.md
index 5cbfbb1..f248ff6 100644
--- a/java/lite.md
+++ b/java/lite.md
@@ -34,6 +34,22 @@
 </dependency>
 ```
 
+## R8 rule to make production app builds work
+
+The Lite runtime internally uses reflection to avoid generating hashCode/equals/(de)serialization methods. 
+R8 by default obfuscates the field names, which makes the reflection fail causing exceptions of the form 
+`java.lang.RuntimeException: Field {NAME}_ for {CLASS} not found. Known fields are [ {FIELDS} ]` in MessageSchema.java.
+
+There are open issues for this on the [protobuf Github project](https://github.com/protocolbuffers/protobuf/issues/6463) and [R8](https://issuetracker.google.com/issues/144631039).
+
+Until the issues is resolved you need to add the following line to your `proguard-rules.pro` file inside your project:
+
+```
+-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }
+```
+
+## Older versions
+
 For the older version of Java Lite (v3.0.0), please refer to:
 
     https://github.com/protocolbuffers/protobuf/blob/javalite/java/lite.md
diff --git a/java/lite/BUILD b/java/lite/BUILD
index 22840ec..35a1368 100644
--- a/java/lite/BUILD
+++ b/java/lite/BUILD
@@ -1,4 +1,10 @@
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
 load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain")
+load("//:internal.bzl", "conformance_test")
+load("//java/internal:testing.bzl", "junit_tests")
+
+exports_files(["lite.awk"], visibility = ["//java/core:__pkg__"])
+exports_files(["pom_template.xml"], visibility = ["//java/core:__pkg__"])
 
 alias(
     name = "lite",
@@ -12,3 +18,40 @@
     runtime = ":lite",
     visibility = ["//visibility:public"],
 )
+
+test_suite(
+    name = "tests",
+    tests = [
+        "lite_build_test",
+        "conformance_test",
+        "lite_tests",
+        "//java/core:lite_tests",
+    ],
+)
+
+build_test(
+    name = "lite_build_test",
+    targets = [
+        ":lite",
+    ],
+)
+
+conformance_test(
+    name = "conformance_test",
+    testee = "//:conformance_java_lite",
+    failure_list = "//:conformance/failure_list_java_lite.txt",
+    text_format_failure_list = "//:conformance/text_format_failure_list_java_lite.txt",
+)
+
+junit_tests(
+    name = "lite_tests",
+    srcs = glob(["src/test/**/*.java"]),
+    size = "small",
+    deps = [
+        ":lite",
+        "//external:junit",
+        "//java/core:generic_test_protos_java_proto_lite",
+        "//java/core:java_test_protos_java_proto_lite",
+        "//java/core:test_util_lite",
+    ],
+)
diff --git a/java/lite/generate-test-sources-build.xml b/java/lite/generate-test-sources-build.xml
index 1c1a18c..65e62ce 100644
--- a/java/lite/generate-test-sources-build.xml
+++ b/java/lite/generate-test-sources-build.xml
@@ -4,6 +4,7 @@
         <arg value="--java_out=lite:${generated.testsources.dir}"/>
         <arg value="--proto_path=${protobuf.source.dir}"/>
         <arg value="--proto_path=${protobuf.basedir}/java/core/${test.proto.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
@@ -15,6 +16,7 @@
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3_optional.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
         <arg value="${protobuf.basedir}/java/core/${test.proto.dir}/com/google/protobuf/any_test.proto"/>
         <arg value="${protobuf.basedir}/java/core/${test.proto.dir}/com/google/protobuf/cached_field_size_test.proto"/>
diff --git a/java/lite/pom.xml b/java/lite/pom.xml
index 9c7d6ef..1c09a3c 100644
--- a/java/lite/pom.xml
+++ b/java/lite/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.11.4</version>
+    <version>3.17.3</version>
   </parent>
 
   <artifactId>protobuf-javalite</artifactId>
@@ -52,6 +52,7 @@
         <includes>
           <include>google/protobuf/any.proto</include>
           <include>google/protobuf/api.proto</include>
+          <include>google/protobuf/duration.proto</include>
           <include>google/protobuf/empty.proto</include>
           <include>google/protobuf/field_mask.proto</include>
           <include>google/protobuf/source_context.proto</include>
@@ -172,6 +173,7 @@
                     <include>UnknownFieldSetLite.java</include>
                     <include>UnknownFieldSetLiteSchema.java</include>
                     <include>UnmodifiableLazyStringList.java</include>
+                    <include>UnsafeByteOperations.java</include>
                     <include>UnsafeUtil.java</include>
                     <include>Utf8.java</include>
                     <include>WireFormat.java</include>
@@ -197,6 +199,7 @@
                   and exclude only the full runtime exclusive tests so we don't accidentally miss
                   any test. -->
                   <excludes>
+                    <!-- Keep in sync with //java/core:lite_tests BUILD rule. -->
                     <exclude>AbstractMessageTest.java</exclude>
                     <exclude>AbstractProto2SchemaTest.java</exclude>
                     <exclude>AnyTest.java</exclude>
diff --git a/java/lite/pom_template.xml b/java/lite/pom_template.xml
new file mode 100644
index 0000000..6d705fd
--- /dev/null
+++ b/java/lite/pom_template.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>{groupId}</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>{version}</version>
+  </parent>
+
+  <artifactId>{artifactId}</artifactId>
+  <packaging>{type}</packaging>
+
+  <name>Protocol Buffers [Lite]</name>
+  <description>
+    Lite version of Protocol Buffers library. This version is optimized for code size, but does
+    not guarantee API/ABI stability.
+  </description>
+
+</project>
diff --git a/java/lite/proguard.pgcfg b/java/lite/proguard.pgcfg
index 4bb31e5..54c798c 100644
--- a/java/lite/proguard.pgcfg
+++ b/java/lite/proguard.pgcfg
@@ -1,3 +1,8 @@
+
+# Skip runtime check for isOnAndroidDevice().
+# One line to make it easy to remove with sed.
+-assumevalues class com.google.protobuf.Android { static boolean ASSUME_ANDROID return true; }
+
 -keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
   <fields>;
 }
diff --git a/java/lite/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
index 3e39bc7..f2ce461 100644
--- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
@@ -38,10 +38,12 @@
 import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
 import com.google.protobuf.UnittestLite.ForeignEnumLite;
 import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.RecursiveMessage;
 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 import com.google.protobuf.UnittestLite.TestAllTypesLite;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage2;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
@@ -60,6 +62,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
@@ -1354,6 +1357,45 @@
     assertEquals(message.getSerializedSize() * 2, result.getSerializedSize());
   }
 
+  public void testMergeFrom_differentFieldsSetWithinOneField() throws Exception {
+    TestAllTypesLite result =
+        TestAllTypesLite.newBuilder()
+            .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2))
+            .mergeFrom(
+                TestAllTypesLite.newBuilder()
+                    .setOneofNestedMessage2(NestedMessage2.newBuilder().setDd(3))
+                    .build())
+            .build();
+
+    assertToStringEquals("oneof_nested_message2 {\n  dd: 3\n}", result);
+  }
+
+  public void testMergeFrom_differentFieldsOfSameTypeSetWithinOneField() throws Exception {
+    TestAllTypesLite result =
+        TestAllTypesLite.newBuilder()
+            .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2))
+            .mergeFrom(
+                TestAllTypesLite.newBuilder()
+                    .setOneofLazyNestedMessage(NestedMessage.newBuilder().setCc(3))
+                    .build())
+            .build();
+
+    assertToStringEquals("oneof_lazy_nested_message {\n  cc: 3\n}", result);
+  }
+
+  public void testMergeFrom_sameFieldSetWithinOneofField() throws Exception {
+    TestAllTypesLite result =
+        TestAllTypesLite.newBuilder()
+            .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2))
+            .mergeFrom(
+                TestAllTypesLite.newBuilder()
+                    .setOneofNestedMessage(NestedMessage.newBuilder().setCc(4))
+                    .build())
+            .build();
+
+    assertToStringEquals("oneof_nested_message {\n  bb: 2\n  cc: 4\n}", result);
+  }
+
   public void testToStringDefaultInstance() throws Exception {
     assertToStringEquals("", TestAllTypesLite.getDefaultInstance());
   }
@@ -1598,6 +1640,160 @@
     }
   }
 
+  public void testParseFromStream_IOExceptionNotLost() throws Exception {
+    final IOException readException = new IOException();
+    try {
+      TestAllTypesLite.parseFrom(
+          CodedInputStream.newInstance(
+              new InputStream() {
+                @Override
+                public int read() throws IOException {
+                  throw readException;
+                }
+              }));
+      fail();
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception == readException) {
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+    }
+  }
+
+  public void testParseDelimitedFromStream_IOExceptionNotLost() throws Exception {
+    final IOException readException = new IOException();
+    try {
+      TestAllTypesLite.parseDelimitedFrom(
+          new InputStream() {
+            @Override
+            public int read() throws IOException {
+              throw readException;
+            }
+          });
+      fail();
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception == readException) {
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+    }
+  }
+
+  public void testParseFromArray_manyNestedMessagesError() throws Exception {
+    RecursiveMessage.Builder recursiveMessage =
+        RecursiveMessage.newBuilder().setPayload(ByteString.copyFrom(new byte[1]));
+    for (int i = 0; i < 20; i++) {
+      recursiveMessage = RecursiveMessage.newBuilder().setRecurse(recursiveMessage.build());
+    }
+    byte[] result = recursiveMessage.build().toByteArray();
+    result[
+            result.length
+                - CodedOutputStream.computeTagSize(RecursiveMessage.PAYLOAD_FIELD_NUMBER)
+                - CodedOutputStream.computeLengthDelimitedFieldSize(1)] =
+        0; // Set invalid tag
+    try {
+      RecursiveMessage.parseFrom(result);
+      fail("Result was: " + Arrays.toString(result));
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      int exceptionCount = 0;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception instanceof InvalidProtocolBufferException) {
+          exceptionCount++;
+        }
+        for (StackTraceElement element : exception.getStackTrace()) {
+          if (InvalidProtocolBufferException.class.getName().equals(element.getClassName())
+              && "invalidTag".equals(element.getMethodName())) {
+            found = true;
+          } else if (Android.isOnAndroidDevice()
+              && "decodeUnknownField".equals(element.getMethodName())) {
+            // Android is missing the first element of the stack trace - b/181147885
+            found = true;
+          }
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+      if (exceptionCount > 1) {
+        throw new AssertionError(exceptionCount + " nested parsing exceptions", expected);
+      }
+    }
+  }
+
+  public void testParseFromStream_manyNestedMessagesError() throws Exception {
+    RecursiveMessage.Builder recursiveMessage =
+        RecursiveMessage.newBuilder().setPayload(ByteString.copyFrom(new byte[1]));
+    for (int i = 0; i < 20; i++) {
+      recursiveMessage = RecursiveMessage.newBuilder().setRecurse(recursiveMessage.build());
+    }
+    byte[] result = recursiveMessage.build().toByteArray();
+    result[
+            result.length
+                - CodedOutputStream.computeTagSize(RecursiveMessage.PAYLOAD_FIELD_NUMBER)
+                - CodedOutputStream.computeLengthDelimitedFieldSize(1)] =
+        0; // Set invalid tag
+    try {
+      RecursiveMessage.parseFrom(CodedInputStream.newInstance(new ByteArrayInputStream(result)));
+      fail("Result was: " + Arrays.toString(result));
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      int exceptionCount = 0;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception instanceof InvalidProtocolBufferException) {
+          exceptionCount++;
+        }
+        for (StackTraceElement element : exception.getStackTrace()) {
+          if (InvalidProtocolBufferException.class.getName().equals(element.getClassName())
+              && "invalidTag".equals(element.getMethodName())) {
+            found = true;
+          } else if (Android.isOnAndroidDevice() && "readTag".equals(element.getMethodName())) {
+            // Android is missing the first element of the stack trace - b/181147885
+            found = true;
+          }
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+      if (exceptionCount > 1) {
+        throw new AssertionError(exceptionCount + " nested parsing exceptions", expected);
+      }
+    }
+  }
+
+  public void testParseFromStream_sneakyNestedException() throws Exception {
+    final InvalidProtocolBufferException sketchy =
+        new InvalidProtocolBufferException("Created in a sketchy way!")
+            .setUnfinishedMessage(TestAllTypesLite.getDefaultInstance());
+    try {
+      RecursiveMessage.parseFrom(
+          CodedInputStream.newInstance(
+              new InputStream() {
+                @Override
+                public int read() throws IOException {
+                  throw sketchy;
+                }
+              }));
+      fail();
+    } catch (InvalidProtocolBufferException expected) {
+      assertNotSame(expected, sketchy);
+    }
+    assertEquals(sketchy.getUnfinishedMessage(), TestAllTypesLite.getDefaultInstance());
+  }
+
   public void testMergeFrom_sanity() throws Exception {
     TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
     byte[] bytes = one.toByteArray();
@@ -2210,24 +2406,26 @@
   }
 
   public void testAddAllIteratesOnce() {
-    TestAllTypesLite.newBuilder()
-        .addAllRepeatedBool(new OneTimeIterableList<>(false))
-        .addAllRepeatedInt32(new OneTimeIterableList<>(0))
-        .addAllRepeatedInt64(new OneTimeIterableList<>(0L))
-        .addAllRepeatedFloat(new OneTimeIterableList<>(0f))
-        .addAllRepeatedDouble(new OneTimeIterableList<>(0d))
-        .addAllRepeatedBytes(new OneTimeIterableList<>(ByteString.EMPTY))
-        .addAllRepeatedString(new OneTimeIterableList<>(""))
-        .addAllRepeatedNestedMessage(new OneTimeIterableList<>(NestedMessage.getDefaultInstance()))
-        .addAllRepeatedBool(new OneTimeIterable<>(false))
-        .addAllRepeatedInt32(new OneTimeIterable<>(0))
-        .addAllRepeatedInt64(new OneTimeIterable<>(0L))
-        .addAllRepeatedFloat(new OneTimeIterable<>(0f))
-        .addAllRepeatedDouble(new OneTimeIterable<>(0d))
-        .addAllRepeatedBytes(new OneTimeIterable<>(ByteString.EMPTY))
-        .addAllRepeatedString(new OneTimeIterable<>(""))
-        .addAllRepeatedNestedMessage(new OneTimeIterable<>(NestedMessage.getDefaultInstance()))
-        .build();
+    TestAllTypesLite unused =
+        TestAllTypesLite.newBuilder()
+            .addAllRepeatedBool(new OneTimeIterableList<>(false))
+            .addAllRepeatedInt32(new OneTimeIterableList<>(0))
+            .addAllRepeatedInt64(new OneTimeIterableList<>(0L))
+            .addAllRepeatedFloat(new OneTimeIterableList<>(0f))
+            .addAllRepeatedDouble(new OneTimeIterableList<>(0d))
+            .addAllRepeatedBytes(new OneTimeIterableList<>(ByteString.EMPTY))
+            .addAllRepeatedString(new OneTimeIterableList<>(""))
+            .addAllRepeatedNestedMessage(
+                new OneTimeIterableList<>(NestedMessage.getDefaultInstance()))
+            .addAllRepeatedBool(new OneTimeIterable<>(false))
+            .addAllRepeatedInt32(new OneTimeIterable<>(0))
+            .addAllRepeatedInt64(new OneTimeIterable<>(0L))
+            .addAllRepeatedFloat(new OneTimeIterable<>(0f))
+            .addAllRepeatedDouble(new OneTimeIterable<>(0d))
+            .addAllRepeatedBytes(new OneTimeIterable<>(ByteString.EMPTY))
+            .addAllRepeatedString(new OneTimeIterable<>(""))
+            .addAllRepeatedNestedMessage(new OneTimeIterable<>(NestedMessage.getDefaultInstance()))
+            .build();
   }
 
   public void testAddAllIteratesOnce_throwsOnNull() {
diff --git a/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java
index 57e933f..a17dda5 100644
--- a/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java
+++ b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java
@@ -174,8 +174,9 @@
           "fieldRequiredSint6487_",
           "fieldRequiredGroup88_",
         };
-    // To update this after a proto change, run protoc on proto2_message_lite.proto and copy over
-    // the content of the generated buildMessageInfo() method here.
+    // To update this after a proto change, run blaze build on proto2_message_lite.proto and copy
+    // over the String info from the proto2_message_lite_proto-lite-src.jar file in the
+    // blaze-genfiles directory.
     java.lang.String info =
         "\u0001U\u0001\u0002\u0001XU\u0000 \u0015\u0001\u1000\u0000\u0002\u1001\u0001\u0003"
             + "\u1002\u0002\u0004\u1003\u0003\u0005\u1004\u0004\u0006\u1005\u0005\u0007\u1006\u0006\b\u1007\u0007"
diff --git a/java/pom.xml b/java/pom.xml
index d1928ec..f008094 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -4,7 +4,7 @@
 
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-parent</artifactId>
-  <version>3.11.4</version>
+  <version>3.17.3</version>
   <packaging>pom</packaging>
 
   <name>Protocol Buffers [Parent]</name>
@@ -75,7 +75,7 @@
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
-        <version>4.13</version>
+        <version>4.13.2</version>
         <scope>test</scope>
       </dependency>
       <dependency>
@@ -93,18 +93,18 @@
       <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
-        <version>29.0-android</version>
+        <version>30.1.1-android</version>
       </dependency>
       <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava-testlib</artifactId>
-        <version>29.0-android</version>
+        <version>30.1.1-android</version>
         <scope>test</scope>
       </dependency>
       <dependency>
         <groupId>com.google.truth</groupId>
         <artifactId>truth</artifactId>
-        <version>1.0.1</version>
+        <version>1.1.2</version>
         <scope>test</scope>
       </dependency>
     </dependencies>
@@ -228,6 +228,19 @@
               <autoReleaseAfterClose>false</autoReleaseAfterClose>
             </configuration>
           </plugin>
+          <plugin>
+            <groupId>org.jetbrains.dokka</groupId>
+            <artifactId>dokka-maven-plugin</artifactId>
+            <version>1.4.32</version>
+            <executions>
+              <execution>
+                <phase>prepare-package</phase>
+                <goals>
+                  <goal>javadocJar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
         </plugins>
       </build>
     </profile>
@@ -238,6 +251,8 @@
     <module>lite</module>
     <module>core</module>
     <module>util</module>
+    <module>kotlin</module>
+    <module>kotlin-lite</module>
   </modules>
 
 </project>
diff --git a/java/util/BUILD b/java/util/BUILD
index cfdb28e..b839575 100644
--- a/java/util/BUILD
+++ b/java/util/BUILD
@@ -1,20 +1,65 @@
-load("@rules_java//java:defs.bzl", "java_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_jvm_external//:defs.bzl", "java_export")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("//:protobuf_version.bzl", "PROTOBUF_VERSION")
+load("//java/internal:testing.bzl", "junit_tests")
 
-java_library(
+java_export(
     name = "util",
+    maven_coordinates = "com.google.protobuf:protobuf-java-util:%s" % PROTOBUF_VERSION,
+    pom_template = "pom_template.xml",
     srcs = glob([
         "src/main/java/com/google/protobuf/util/*.java",
     ]),
-    javacopts = [
-        "-source 7",
-        "-target 7",
-    ],
     visibility = ["//visibility:public"],
     deps = [
         "//external:error_prone_annotations",
         "//external:gson",
         "//external:guava",
         "//java/core",
-        "//java/lite",
+    ],
+)
+
+filegroup(
+    name = "release",
+    visibility = ["//java:__pkg__"],
+    srcs = [
+        ":util-pom",
+        ":util-maven-source",
+        ":util-docs",
+        ":util-project",
+    ]
+)
+
+proto_library(
+    name = "test_protos",
+    srcs = glob(["src/test/proto/**/*.proto"]),
+    deps = [
+        "//:any_proto",
+        "//:duration_proto",
+        "//:field_mask_proto",
+        "//:struct_proto",
+        "//:timestamp_proto",
+        "//:wrappers_proto",
+    ],
+)
+
+java_proto_library(
+    name = "test_protos_java_proto",
+    deps = [":test_protos"],
+)
+
+junit_tests(
+    name = "tests",
+    srcs = glob(["src/test/java/**/*.java"]),
+    package_name = "com.google.protobuf.util",
+    deps = [
+        ":test_protos_java_proto",
+        ":util",
+        "//external:guava",
+        "//external:junit",
+        "//external:truth",
+        "//java/core",
+        "//java/core:generic_test_protos_java_proto",
     ],
 )
diff --git a/java/util/pom.xml b/java/util/pom.xml
index 58d05d2..2ea6116 100644
--- a/java/util/pom.xml
+++ b/java/util/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.11.4</version>
+    <version>3.17.3</version>
   </parent>
 
   <artifactId>protobuf-java-util</artifactId>
@@ -25,7 +25,7 @@
     <dependency>
       <groupId>com.google.errorprone</groupId>
       <artifactId>error_prone_annotations</artifactId>
-      <version>2.3.4</version>
+      <version>2.5.1</version>
     </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>
diff --git a/java/util/pom_template.xml b/java/util/pom_template.xml
new file mode 100644
index 0000000..b20e62a
--- /dev/null
+++ b/java/util/pom_template.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>{groupId}</groupId>
+    <artifactId>protobuf-parent</artifactId>
+    <version>{version}</version>
+  </parent>
+
+  <artifactId>{artifactId}</artifactId>
+  <packaging>{type}</packaging>
+
+  <name>Protocol Buffers [Util]</name>
+  <description>Utilities for Protocol Buffers</description>
+
+  {dependencies}
+
+</project>
diff --git a/java/util/src/main/java/com/google/protobuf/util/Durations.java b/java/util/src/main/java/com/google/protobuf/util/Durations.java
index 1edc8f0..fd13771 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Durations.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Durations.java
@@ -44,6 +44,7 @@
 
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.protobuf.Duration;
+import java.io.Serializable;
 import java.text.ParseException;
 import java.util.Comparator;
 
@@ -72,23 +73,25 @@
 
   private Durations() {}
 
-  private static final Comparator<Duration> COMPARATOR =
-      new Comparator<Duration>() {
-        @Override
-        public int compare(Duration d1, Duration d2) {
-          checkValid(d1);
-          checkValid(d2);
-          int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
-          return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
-        }
-      };
+  private static enum DurationComparator implements Comparator<Duration>, Serializable {
+    INSTANCE;
+
+    @Override
+    public int compare(Duration d1, Duration d2) {
+      checkValid(d1);
+      checkValid(d2);
+      int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
+      return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
+    }
+  }
 
   /**
    * Returns a {@link Comparator} for {@link Duration}s which sorts in increasing chronological
-   * order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}).
+   * order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}). The returned
+   * comparator is serializable.
    */
   public static Comparator<Duration> comparator() {
-    return COMPARATOR;
+    return DurationComparator.INSTANCE;
   }
 
   /**
@@ -99,7 +102,7 @@
    *     and a value greater than {@code 0} if {@code x > y}
    */
   public static int compare(Duration x, Duration y) {
-    return COMPARATOR.compare(x, y);
+    return DurationComparator.INSTANCE.compare(x, y);
   }
 
   /**
@@ -146,6 +149,12 @@
     return (duration.getSeconds() == 0) ? duration.getNanos() < 0 : duration.getSeconds() < 0;
   }
 
+  /** Returns whether the given {@link Duration} is positive or not. */
+  public static boolean isPositive(Duration duration) {
+    checkValid(duration);
+    return !isNegative(duration) && !duration.equals(ZERO);
+  }
+
   /**
    * Ensures that the given {@link Duration} is not negative.
    *
@@ -154,7 +163,6 @@
    */
   @CanIgnoreReturnValue
   public static Duration checkNotNegative(Duration duration) {
-    checkValid(duration);
     checkArgument(!isNegative(duration), "duration (%s) must not be negative", toString(duration));
     return duration;
   }
@@ -167,11 +175,7 @@
    */
   @CanIgnoreReturnValue
   public static Duration checkPositive(Duration duration) {
-    checkValid(duration);
-    checkArgument(
-        !isNegative(duration) && !duration.equals(ZERO),
-        "duration (%s) must be positive",
-        toString(duration));
+    checkArgument(isPositive(duration), "duration (%s) must be positive", toString(duration));
     return duration;
   }
 
diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
index d07731d..352376e 100644
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
@@ -30,6 +30,7 @@
 
 package com.google.protobuf.util;
 
+import com.google.common.base.Splitter;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
@@ -66,7 +67,7 @@
   private static final String FIELD_PATH_SEPARATOR_REGEX = "\\.";
 
   private static final class Node {
-    final SortedMap<String, Node> children = new TreeMap<String, Node>();
+    final SortedMap<String, Node> children = new TreeMap<>();
   }
 
   private final Node root = new Node();
@@ -97,6 +98,7 @@
    * to add is a sub-path of an existing leaf node, nothing will be changed in the tree.
    */
   @CanIgnoreReturnValue
+  @SuppressWarnings("StringSplitter")
   FieldMaskTree addFieldPath(String path) {
     String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
     if (parts.length == 0) {
@@ -135,21 +137,78 @@
   }
 
   /**
+   * Removes {@code path} from the tree.
+   *
+   * <ul>
+   *   When removing a field path from the tree:
+   *   <li>All sub-paths will be removed. That is, after removing "foo.bar" from the tree,
+   *       "foo.bar.baz" will be removed.
+   *   <li>If all children of a node has been removed, the node itself will be removed as well.
+   *       That is, if "foo" only has one child "bar" and "foo.bar" only has one child "baz",
+   *       removing "foo.bar.barz" would remove both "foo" and "foo.bar".
+   *       If "foo" has both "bar" and "qux" as children, removing "foo.bar" would leave the path
+   *       "foo.qux" intact.
+   *   <li>If the field path to remove is a non-exist sub-path, nothing will be changed.
+   * </ul>
+   */
+  @CanIgnoreReturnValue
+  FieldMaskTree removeFieldPath(String path) {
+    List<String> parts = Splitter.onPattern(FIELD_PATH_SEPARATOR_REGEX).splitToList(path);
+    if (parts.isEmpty()) {
+      return this;
+    }
+    removeFieldPath(root, parts, 0);
+    return this;
+  }
+
+  /**
+   * Removes {@code parts} from {@code node} recursively.
+   *
+   * @return a boolean value indicating whether current {@code node} should be removed.
+   */
+  @CanIgnoreReturnValue
+  private static boolean removeFieldPath(Node node, List<String> parts, int index) {
+    String key = parts.get(index);
+
+    // Base case 1: path not match.
+    if (!node.children.containsKey(key)) {
+      return false;
+    }
+    // Base case 2: last element in parts.
+    if (index == parts.size() - 1) {
+      node.children.remove(key);
+      return node.children.isEmpty();
+    }
+    // Recursive remove sub-path.
+    if (removeFieldPath(node.children.get(key), parts, index + 1)) {
+      node.children.remove(key);
+    }
+    return node.children.isEmpty();
+  }
+
+  /** Removes all field paths in {@code mask} from this tree. */
+  @CanIgnoreReturnValue
+  FieldMaskTree removeFromFieldMask(FieldMask mask) {
+    for (String path : mask.getPathsList()) {
+      removeFieldPath(path);
+    }
+    return this;
+  }
+
+  /**
    * Converts this tree to a FieldMask.
    */
   FieldMask toFieldMask() {
     if (root.children.isEmpty()) {
       return FieldMask.getDefaultInstance();
     }
-    List<String> paths = new ArrayList<String>();
+    List<String> paths = new ArrayList<>();
     getFieldPaths(root, "", paths);
     return FieldMask.newBuilder().addAllPaths(paths).build();
   }
 
-  /**
-   * Gathers all field paths in a sub-tree.
-   */
-  private void getFieldPaths(Node node, String path, List<String> paths) {
+  /** Gathers all field paths in a sub-tree. */
+  private static void getFieldPaths(Node node, String path, List<String> paths) {
     if (node.children.isEmpty()) {
       paths.add(path);
       return;
@@ -186,7 +245,7 @@
     }
     // We found a matching node for the path. All leaf children of this matching
     // node is in the intersection.
-    List<String> paths = new ArrayList<String>();
+    List<String> paths = new ArrayList<>();
     getFieldPaths(node, path, paths);
     for (String value : paths) {
       output.addFieldPath(value);
@@ -206,10 +265,8 @@
     merge(root, "", source, destination, options);
   }
 
-  /**
-   * Merges all fields specified by a sub-tree from {@code source} to {@code destination}.
-   */
-  private void merge(
+  /** Merges all fields specified by a sub-tree from {@code source} to {@code destination}. */
+  private static void merge(
       Node node,
       String path,
       Message source,
diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
index 312d30f..c32d10a 100644
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -277,6 +277,22 @@
   }
 
   /**
+   * Subtracts {@code secondMask} and {@code otherMasks} from {@code firstMask}.
+   *
+   * <p>This method disregards proto structure. That is, if {@code firstMask} is "foo" and {@code
+   * secondMask} is "foo.bar", the response will always be "foo" without considering the internal
+   * proto structure of message "foo".
+   */
+  public static FieldMask subtract(
+      FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) {
+    FieldMaskTree maskTree = new FieldMaskTree(firstMask).removeFromFieldMask(secondMask);
+    for (FieldMask mask : otherMasks) {
+      maskTree.removeFromFieldMask(mask);
+    }
+    return maskTree.toFieldMask();
+  }
+
+  /**
    * Calculates the intersection of two FieldMasks.
    */
   public static FieldMask intersection(FieldMask mask1, FieldMask mask2) {
diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
index 6798143..2383da6 100644
--- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
+++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -328,14 +328,13 @@
     /**
      * Create a new {@link Printer} that will sort the map keys in the JSON output.
      *
-     * Use of this modifier is discouraged, the generated JSON messages are equivalent
-     * with and without this option set, but there are some corner caseuse cases that
-     * demand a stable output, while order of map keys is otherwise arbitrary.
+     * <p>Use of this modifier is discouraged, the generated JSON messages are equivalent with and
+     * without this option set, but there are some corner use cases that demand a stable output,
+     * while order of map keys is otherwise arbitrary.
      *
-     * The generated order is not well-defined and should not be depended on, but
-     * it's stable.
+     * <p>The generated order is not well-defined and should not be depended on, but it's stable.
      *
-     * This new Printer clones all other configurations from the current {@link Printer}.
+     * <p>This new Printer clones all other configurations from the current {@link Printer}.
      */
     public Printer sortingMapKeys() {
       return new Printer(
@@ -526,7 +525,6 @@
       return types.get(name);
     }
 
-    /* @Nullable */
     Descriptor getDescriptorForTypeUrl(String typeUrl) throws InvalidProtocolBufferException {
       return find(getTypeName(typeUrl));
     }
@@ -1297,7 +1295,6 @@
   private static class ParserImpl {
     private final com.google.protobuf.TypeRegistry registry;
     private final TypeRegistry oldRegistry;
-    private final JsonParser jsonParser;
     private final boolean ignoringUnknownFields;
     private final int recursionLimit;
     private int currentDepth;
@@ -1310,7 +1307,6 @@
       this.registry = registry;
       this.oldRegistry = oldRegistry;
       this.ignoringUnknownFields = ignoreUnknownFields;
-      this.jsonParser = new JsonParser();
       this.recursionLimit = recursionLimit;
       this.currentDepth = 0;
     }
@@ -1319,7 +1315,7 @@
       try {
         JsonReader reader = new JsonReader(json);
         reader.setLenient(false);
-        merge(jsonParser.parse(reader), builder);
+        merge(JsonParser.parseReader(reader), builder);
       } catch (InvalidProtocolBufferException e) {
         throw e;
       } catch (JsonIOException e) {
@@ -1339,7 +1335,7 @@
       try {
         JsonReader reader = new JsonReader(new StringReader(json));
         reader.setLenient(false);
-        merge(jsonParser.parse(reader), builder);
+        merge(JsonParser.parseReader(reader), builder);
       } catch (InvalidProtocolBufferException e) {
         throw e;
       } catch (Exception e) {
diff --git a/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java b/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
deleted file mode 100644
index 4ffb410..0000000
--- a/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
+++ /dev/null
@@ -1,401 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.util;
-
-import com.google.protobuf.Duration;
-import com.google.protobuf.Timestamp;
-
-import java.math.BigInteger;
-import java.text.ParseException;
-
-/**
- * Utilities to help create/manipulate Timestamp/Duration
- *
- * @deprecated Use {@link Durations} and {@link Timestamps} instead.
- */
-@Deprecated
-public final class TimeUtil {
-  // Timestamp for "0001-01-01T00:00:00Z"
-  public static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
-
-  // Timestamp for "9999-12-31T23:59:59Z"
-  public static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
-  public static final long DURATION_SECONDS_MIN = -315576000000L;
-  public static final long DURATION_SECONDS_MAX = 315576000000L;
-
-  private static final long NANOS_PER_SECOND = 1000000000;
-
-  private TimeUtil() {}
-
-  /**
-   * Convert Timestamp to RFC 3339 date string format. The output will always
-   * be Z-normalized and uses 3, 6 or 9 fractional digits as required to
-   * represent the exact value. Note that Timestamp can only represent time
-   * from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
-   * https://www.ietf.org/rfc/rfc3339.txt
-   *
-   * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
-   *
-   * @return The string representation of the given timestamp.
-   * @throws IllegalArgumentException if the given timestamp is not in the
-   *         valid range.
-   * @deprecated Use {@link Timestamps#toString} instead.
-   */
-  @Deprecated
-  public static String toString(Timestamp timestamp) {
-    return Timestamps.toString(timestamp);
-  }
-
-  /**
-   * Parse from RFC 3339 date string to Timestamp. This method accepts all
-   * outputs of {@link #toString(Timestamp)} and it also accepts any fractional
-   * digits (or none) and any offset as long as they fit into nano-seconds
-   * precision.
-   *
-   * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
-   *
-   * @return A Timestamp parsed from the string.
-   * @throws ParseException if parsing fails.
-   * @deprecated Use {@link Timestamps#parse} instead.
-   */
-  @Deprecated
-  public static Timestamp parseTimestamp(String value) throws ParseException {
-    return Timestamps.parse(value);
-  }
-
-  /**
-   * Convert Duration to string format. The string format will contains 3, 6,
-   * or 9 fractional digits depending on the precision required to represent
-   * the exact Duration value. For example: "1s", "1.010s", "1.000000100s",
-   * "-3.100s" The range that can be represented by Duration is from
-   * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
-   *
-   * @return The string representation of the given duration.
-   * @throws IllegalArgumentException if the given duration is not in the valid
-   *         range.
-   * @deprecated Use {@link Durations#toString} instead.
-   */
-  @Deprecated
-  public static String toString(Duration duration) {
-    return Durations.toString(duration);
-  }
-
-  /**
-   * Parse from a string to produce a duration.
-   *
-   * @return A Duration parsed from the string.
-   * @throws ParseException if parsing fails.
-   * @deprecated Use {@link Durations#parse} instead.
-   */
-  @Deprecated
-  public static Duration parseDuration(String value) throws ParseException {
-    return Durations.parse(value);
-  }
-
-  /**
-   * Create a Timestamp from the number of milliseconds elapsed from the epoch.
-   *
-   * @deprecated Use {@link Timestamps#fromMillis} instead.
-   */
-  @Deprecated
-  public static Timestamp createTimestampFromMillis(long milliseconds) {
-    return Timestamps.fromMillis(milliseconds);
-  }
-
-  /**
-   * Create a Duration from the number of milliseconds.
-   *
-   * @deprecated Use {@link Durations#fromMillis} instead.
-   */
-  @Deprecated
-  public static Duration createDurationFromMillis(long milliseconds) {
-    return Durations.fromMillis(milliseconds);
-  }
-
-  /**
-   * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
-   *
-   * <p>The result will be rounded down to the nearest millisecond. E.g., if the
-   * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
-   * to -1 millisecond.
-   *
-   * @deprecated Use {@link Timestamps#toMillis} instead.
-   */
-  @Deprecated
-  public static long toMillis(Timestamp timestamp) {
-    return Timestamps.toMillis(timestamp);
-  }
-
-  /**
-   * Convert a Duration to the number of milliseconds.The result will be
-   * rounded towards 0 to the nearest millisecond. E.g., if the duration
-   * represents -1 nanosecond, it will be rounded to 0.
-   *
-   * @deprecated Use {@link Durations#toMillis} instead.
-   */
-  @Deprecated
-  public static long toMillis(Duration duration) {
-    return Durations.toMillis(duration);
-  }
-
-  /**
-   * Create a Timestamp from the number of microseconds elapsed from the epoch.
-   *
-   * @deprecated Use {@link Timestamps#fromMicros} instead.
-   */
-  @Deprecated
-  public static Timestamp createTimestampFromMicros(long microseconds) {
-    return Timestamps.fromMicros(microseconds);
-  }
-
-  /**
-   * Create a Duration from the number of microseconds.
-   *
-   * @deprecated Use {@link Durations#fromMicros} instead.
-   */
-  @Deprecated
-  public static Duration createDurationFromMicros(long microseconds) {
-    return Durations.fromMicros(microseconds);
-  }
-
-  /**
-   * Convert a Timestamp to the number of microseconds elapsed from the epoch.
-   *
-   * <p>The result will be rounded down to the nearest microsecond. E.g., if the
-   * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
-   * to -1 millisecond.
-   *
-   * @deprecated Use {@link Timestamps#toMicros} instead.
-   */
-  @Deprecated
-  public static long toMicros(Timestamp timestamp) {
-    return Timestamps.toMicros(timestamp);
-  }
-
-  /**
-   * Convert a Duration to the number of microseconds.The result will be
-   * rounded towards 0 to the nearest microseconds. E.g., if the duration
-   * represents -1 nanosecond, it will be rounded to 0.
-   *
-   * @deprecated Use {@link Durations#toMicros} instead.
-   */
-  @Deprecated
-  public static long toMicros(Duration duration) {
-    return Durations.toMicros(duration);
-  }
-
-  /**
-   * Create a Timestamp from the number of nanoseconds elapsed from the epoch.
-   *
-   * @deprecated Use {@link Timestamps#fromNanos} instead.
-   */
-  @Deprecated
-  public static Timestamp createTimestampFromNanos(long nanoseconds) {
-    return Timestamps.fromNanos(nanoseconds);
-  }
-
-  /**
-   * Create a Duration from the number of nanoseconds.
-   *
-   * @deprecated Use {@link Durations#fromNanos} instead.
-   */
-  @Deprecated
-  public static Duration createDurationFromNanos(long nanoseconds) {
-    return Durations.fromNanos(nanoseconds);
-  }
-
-  /**
-   * Convert a Timestamp to the number of nanoseconds elapsed from the epoch.
-   *
-   * @deprecated Use {@link Timestamps#toNanos} instead.
-   */
-  @Deprecated
-  public static long toNanos(Timestamp timestamp) {
-    return Timestamps.toNanos(timestamp);
-  }
-
-  /**
-   * Convert a Duration to the number of nanoseconds.
-   *
-   * @deprecated Use {@link Durations#toNanos} instead.
-   */
-  @Deprecated
-  public static long toNanos(Duration duration) {
-    return Durations.toNanos(duration);
-  }
-
-  /**
-   * Get the current time.
-   *
-   * @deprecated Use {@code Timestamps.fromMillis(System.currentTimeMillis())} instead.
-   */
-  @Deprecated
-  public static Timestamp getCurrentTime() {
-    return Timestamps.fromMillis(System.currentTimeMillis());
-  }
-
-  /**
-   * Get the epoch.
-   *
-   * @deprecated Use {@code Timestamps.fromMillis(0)} instead.
-   */
-  @Deprecated
-  public static Timestamp getEpoch() {
-    return Timestamp.getDefaultInstance();
-  }
-
-  /**
-   * Calculate the difference between two timestamps.
-   *
-   * @deprecated Use {@link Timestamps#between} instead.
-   */
-  @Deprecated
-  public static Duration distance(Timestamp from, Timestamp to) {
-    return Timestamps.between(from, to);
-  }
-
-  /**
-   * Add a duration to a timestamp.
-   *
-   * @deprecated Use {@link Timestamps#add} instead.
-   */
-  @Deprecated
-  public static Timestamp add(Timestamp start, Duration length) {
-    return Timestamps.add(start, length);
-  }
-
-  /**
-   * Subtract a duration from a timestamp.
-   *
-   * @deprecated Use {@link Timestamps#subtract} instead.
-   */
-  @Deprecated
-  public static Timestamp subtract(Timestamp start, Duration length) {
-    return Timestamps.subtract(start, length);
-  }
-
-  /**
-   * Add two durations.
-   *
-   * @deprecated Use {@link Durations#add} instead.
-   */
-  @Deprecated
-  public static Duration add(Duration d1, Duration d2) {
-    return Durations.add(d1, d2);
-  }
-
-  /**
-   * Subtract a duration from another.
-   *
-   * @deprecated Use {@link Durations#subtract} instead.
-   */
-  @Deprecated
-  public static Duration subtract(Duration d1, Duration d2) {
-    return Durations.subtract(d1, d2);
-  }
-
-  // Multiplications and divisions.
-
-  // TODO(kak): Delete this.
-  @SuppressWarnings("DurationSecondsToDouble")
-  public static Duration multiply(Duration duration, double times) {
-    double result = duration.getSeconds() * times + duration.getNanos() * times / 1000000000.0;
-    if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) {
-      throw new IllegalArgumentException("Result is out of valid range.");
-    }
-    long seconds = (long) result;
-    int nanos = (int) ((result - seconds) * 1000000000);
-    return normalizedDuration(seconds, nanos);
-  }
-
-  // TODO(kak): Delete this.
-  public static Duration divide(Duration duration, double value) {
-    return multiply(duration, 1.0 / value);
-  }
-
-  // TODO(kak): Delete this.
-  public static Duration multiply(Duration duration, long times) {
-    return createDurationFromBigInteger(toBigInteger(duration).multiply(toBigInteger(times)));
-  }
-
-  // TODO(kak): Delete this.
-  public static Duration divide(Duration duration, long times) {
-    return createDurationFromBigInteger(toBigInteger(duration).divide(toBigInteger(times)));
-  }
-
-  // TODO(kak): Delete this.
-  public static long divide(Duration d1, Duration d2) {
-    return toBigInteger(d1).divide(toBigInteger(d2)).longValue();
-  }
-
-  // TODO(kak): Delete this.
-  public static Duration remainder(Duration d1, Duration d2) {
-    return createDurationFromBigInteger(toBigInteger(d1).remainder(toBigInteger(d2)));
-  }
-
-  private static final BigInteger NANOS_PER_SECOND_BIG_INTEGER =
-      new BigInteger(String.valueOf(NANOS_PER_SECOND));
-
-  private static BigInteger toBigInteger(Duration duration) {
-    return toBigInteger(duration.getSeconds())
-        .multiply(NANOS_PER_SECOND_BIG_INTEGER)
-        .add(toBigInteger(duration.getNanos()));
-  }
-
-  private static BigInteger toBigInteger(long value) {
-    return new BigInteger(String.valueOf(value));
-  }
-
-  private static Duration createDurationFromBigInteger(BigInteger value) {
-    long seconds = value.divide(new BigInteger(String.valueOf(NANOS_PER_SECOND))).longValue();
-    int nanos = value.remainder(new BigInteger(String.valueOf(NANOS_PER_SECOND))).intValue();
-    return normalizedDuration(seconds, nanos);
-  }
-
-  private static Duration normalizedDuration(long seconds, int nanos) {
-    if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
-      seconds += nanos / NANOS_PER_SECOND;
-      nanos %= NANOS_PER_SECOND;
-    }
-    if (seconds > 0 && nanos < 0) {
-      nanos += NANOS_PER_SECOND;
-      seconds -= 1;
-    }
-    if (seconds < 0 && nanos > 0) {
-      nanos -= NANOS_PER_SECOND;
-      seconds += 1;
-    }
-    if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
-      throw new IllegalArgumentException("Duration is out of valid range.");
-    }
-    return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
-  }
-}
diff --git a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
index 0c19ad5..fe9b9a5 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
@@ -39,6 +39,7 @@
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.protobuf.Duration;
 import com.google.protobuf.Timestamp;
+import java.io.Serializable;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Comparator;
@@ -92,7 +93,7 @@
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
     GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
     // We use Proleptic Gregorian Calendar (i.e., Gregorian calendar extends
-    // backwards to year one) for timestamp formating.
+    // backwards to year one) for timestamp formatting.
     calendar.setGregorianChange(new Date(Long.MIN_VALUE));
     sdf.setCalendar(calendar);
     return sdf;
@@ -100,24 +101,25 @@
 
   private Timestamps() {}
 
-  private static final Comparator<Timestamp> COMPARATOR =
-      new Comparator<Timestamp>() {
-        @Override
-        public int compare(Timestamp t1, Timestamp t2) {
-          checkValid(t1);
-          checkValid(t2);
-          int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds());
-          return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos());
-        }
-      };
+  private static enum TimestampComparator implements Comparator<Timestamp>, Serializable {
+    INSTANCE;
+
+    @Override
+    public int compare(Timestamp t1, Timestamp t2) {
+      checkValid(t1);
+      checkValid(t2);
+      int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds());
+      return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos());
+    }
+  }
 
   /**
    * Returns a {@link Comparator} for {@link Timestamp Timestamps} which sorts in increasing
    * chronological order. Nulls and invalid {@link Timestamp Timestamps} are not allowed (see
-   * {@link #isValid}).
+   * {@link #isValid}). The returned comparator is serializable.
    */
   public static Comparator<Timestamp> comparator() {
-    return COMPARATOR;
+    return TimestampComparator.INSTANCE;
   }
 
   /**
@@ -128,7 +130,7 @@
    *     and a value greater than {@code 0} if {@code x > y}
    */
   public static int compare(Timestamp x, Timestamp y) {
-    return COMPARATOR.compare(x, y);
+    return TimestampComparator.INSTANCE.compare(x, y);
   }
 
   /**
diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
index baae224..c829722 100644
--- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
@@ -30,6 +30,8 @@
 
 package com.google.protobuf.util;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import com.google.protobuf.DynamicMessage;
 import com.google.protobuf.Message;
 import com.google.protobuf.UninitializedMessageException;
@@ -43,9 +45,9 @@
 public class FieldMaskTreeTest extends TestCase {
   public void testAddFieldPath() throws Exception {
     FieldMaskTree tree = new FieldMaskTree();
-    assertEquals("", tree.toString());
+    assertThat(tree.toString()).isEmpty();
     tree.addFieldPath("");
-    assertEquals("", tree.toString());
+    assertThat(tree.toString()).isEmpty();
     // New branch.
     tree.addFieldPath("foo");
     assertEquals("foo", tree.toString());
@@ -73,15 +75,57 @@
     assertEquals("bar,foo", tree.toString());
   }
 
+  public void testRemoveFieldPath() throws Exception {
+    String initialTreeString = "bar.baz,bar.quz.bar,foo";
+    FieldMaskTree tree;
+
+    // Empty path.
+    tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString));
+    tree.removeFieldPath("");
+    assertEquals(initialTreeString, tree.toString());
+
+    // Non-exist sub-path of an existing leaf.
+    tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString));
+    tree.removeFieldPath("foo.bar");
+    assertEquals(initialTreeString, tree.toString());
+
+    // Non-exist path.
+    tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString));
+    tree.removeFieldPath("bar.foo");
+    assertEquals(initialTreeString, tree.toString());
+
+    // Match an existing leaf node -> remove leaf node.
+    tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString));
+    tree.removeFieldPath("foo");
+    assertEquals("bar.baz,bar.quz.bar", tree.toString());
+
+    // Match sub-path of an existing leaf node -> recursive removal.
+    tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString));
+    tree.removeFieldPath("bar.quz.bar");
+    assertEquals("bar.baz,foo", tree.toString());
+
+    // Match a non-leaf node -> remove all children.
+    tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString));
+    tree.removeFieldPath("bar");
+    assertEquals("foo", tree.toString());
+  }
+
+  public void testRemoveFromFieldMask() throws Exception {
+    FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
+    assertEquals("bar.baz,bar.quz,foo", tree.toString());
+    tree.removeFromFieldMask(FieldMaskUtil.fromString("foo.bar,bar"));
+    assertEquals("foo", tree.toString());
+  }
+
   public void testIntersectFieldPath() throws Exception {
     FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
     FieldMaskTree result = new FieldMaskTree();
     // Empty path.
     tree.intersectFieldPath("", result);
-    assertEquals("", result.toString());
+    assertThat(result.toString()).isEmpty();
     // Non-exist path.
     tree.intersectFieldPath("quz", result);
-    assertEquals("", result.toString());
+    assertThat(result.toString()).isEmpty();
     // Sub-path of an existing leaf.
     tree.intersectFieldPath("foo.bar", result);
     assertEquals("foo.bar", result.toString());
diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
index 78b470e..28e43a7 100644
--- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
@@ -224,6 +224,24 @@
     assertEquals("bar,foo", FieldMaskUtil.toString(result));
   }
 
+  public void testSubstract() throws Exception {
+    // Only test a simple case here and expect
+    // {@link FieldMaskTreeTest#testRemoveFieldPath} to cover all scenarios.
+    FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
+    FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
+    FieldMask result = FieldMaskUtil.subtract(mask1, mask2);
+    assertEquals("foo", FieldMaskUtil.toString(result));
+  }
+
+  public void testSubstract_usingVarArgs() throws Exception {
+    FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz.bar");
+    FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.baz.quz");
+    FieldMask mask3 = FieldMaskUtil.fromString("bar.quz");
+    FieldMask mask4 = FieldMaskUtil.fromString("foo,bar.baz");
+    FieldMask result = FieldMaskUtil.subtract(mask1, mask2, mask3, mask4);
+    assertThat(FieldMaskUtil.toString(result)).isEmpty();
+  }
+
   public void testIntersection() throws Exception {
     // Only test a simple case here and expect
     // {@link FieldMaskTreeTest#testIntersectFieldPath} to cover all scenarios.
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
index f9358e5..6133bb4 100644
--- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -722,8 +722,8 @@
     mergeFromJson(
         "{\n" + "  int32ToInt32Map: {1: 2},\n" + "  stringToInt32Map: {hello: 3}\n" + "}", builder);
     TestMap message = builder.build();
-    assertEquals(2, message.getInt32ToInt32Map().get(1).intValue());
-    assertEquals(3, message.getStringToInt32Map().get("hello").intValue());
+    assertEquals(2, message.getInt32ToInt32MapMap().get(1).intValue());
+    assertEquals(3, message.getStringToInt32MapMap().get("hello").intValue());
   }
 
   public void testWrappers() throws Exception {
@@ -1697,6 +1697,7 @@
   public void testJsonException() throws Exception {
     InputStream throwingInputStream =
         new InputStream() {
+          @Override
           public int read() throws IOException {
             throw new IOException("12345");
           }
diff --git a/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java b/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
deleted file mode 100644
index 5af83d8..0000000
--- a/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
+++ /dev/null
@@ -1,498 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.util;
-
-import com.google.protobuf.Duration;
-import com.google.protobuf.Timestamp;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.List;
-import junit.framework.TestCase;
-import org.junit.Assert;
-
-/** Unit tests for {@link TimeUtil}. */
-public class TimeUtilTest extends TestCase {
-  public void testTimestampStringFormat() throws Exception {
-    Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
-    Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
-    assertEquals(TimeUtil.TIMESTAMP_SECONDS_MIN, start.getSeconds());
-    assertEquals(0, start.getNanos());
-    assertEquals(TimeUtil.TIMESTAMP_SECONDS_MAX, end.getSeconds());
-    assertEquals(999999999, end.getNanos());
-    assertEquals("0001-01-01T00:00:00Z", TimeUtil.toString(start));
-    assertEquals("9999-12-31T23:59:59.999999999Z", TimeUtil.toString(end));
-
-    Timestamp value = TimeUtil.parseTimestamp("1970-01-01T00:00:00Z");
-    assertEquals(0, value.getSeconds());
-    assertEquals(0, value.getNanos());
-
-    // Test negative timestamps.
-    value = TimeUtil.parseTimestamp("1969-12-31T23:59:59.999Z");
-    assertEquals(-1, value.getSeconds());
-    // Nano part is in the range of [0, 999999999] for Timestamp.
-    assertEquals(999000000, value.getNanos());
-
-    // Test that 3, 6, or 9 digits are used for the fractional part.
-    value = Timestamp.newBuilder().setNanos(10).build();
-    assertEquals("1970-01-01T00:00:00.000000010Z", TimeUtil.toString(value));
-    value = Timestamp.newBuilder().setNanos(10000).build();
-    assertEquals("1970-01-01T00:00:00.000010Z", TimeUtil.toString(value));
-    value = Timestamp.newBuilder().setNanos(10000000).build();
-    assertEquals("1970-01-01T00:00:00.010Z", TimeUtil.toString(value));
-
-    // Test that parsing accepts timezone offsets.
-    value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010+08:00");
-    assertEquals("1969-12-31T16:00:00.010Z", TimeUtil.toString(value));
-    value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010-08:00");
-    assertEquals("1970-01-01T08:00:00.010Z", TimeUtil.toString(value));
-  }
-
-  private volatile boolean stopParsingThreads = false;
-  private volatile String errorMessage = "";
-
-  private class ParseTimestampThread extends Thread {
-    private final String[] strings;
-    private final Timestamp[] values;
-
-    public ParseTimestampThread(String[] strings, Timestamp[] values) {
-      this.strings = strings;
-      this.values = values;
-    }
-
-    @Override
-    public void run() {
-      int index = 0;
-      while (!stopParsingThreads) {
-        Timestamp result;
-        try {
-          result = TimeUtil.parseTimestamp(strings[index]);
-        } catch (ParseException e) {
-          errorMessage = "Failed to parse timestamp: " + strings[index];
-          break;
-        }
-        if (result.getSeconds() != values[index].getSeconds()
-            || result.getNanos() != values[index].getNanos()) {
-          errorMessage =
-              "Actual result: " + result.toString() + ", expected: " + values[index].toString();
-          break;
-        }
-        index = (index + 1) % strings.length;
-      }
-    }
-  }
-
-  public void testTimestampConcurrentParsing() throws Exception {
-    String[] timestampStrings =
-        new String[] {
-          "0001-01-01T00:00:00Z",
-          "9999-12-31T23:59:59.999999999Z",
-          "1970-01-01T00:00:00Z",
-          "1969-12-31T23:59:59.999Z",
-        };
-    Timestamp[] timestampValues = new Timestamp[timestampStrings.length];
-    for (int i = 0; i < timestampStrings.length; i++) {
-      timestampValues[i] = TimeUtil.parseTimestamp(timestampStrings[i]);
-    }
-
-    final int THREAD_COUNT = 16;
-    final int RUNNING_TIME = 5000; // in milliseconds.
-    final List<Thread> threads = new ArrayList<Thread>();
-
-    stopParsingThreads = false;
-    errorMessage = "";
-    for (int i = 0; i < THREAD_COUNT; i++) {
-      Thread thread = new ParseTimestampThread(timestampStrings, timestampValues);
-      thread.start();
-      threads.add(thread);
-    }
-    Thread.sleep(RUNNING_TIME);
-    stopParsingThreads = true;
-    for (Thread thread : threads) {
-      thread.join();
-    }
-    Assert.assertEquals("", errorMessage);
-  }
-
-  public void testTimetampInvalidFormat() throws Exception {
-    try {
-      // Value too small.
-      Timestamp value =
-          Timestamp.newBuilder().setSeconds(TimeUtil.TIMESTAMP_SECONDS_MIN - 1).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Value too large.
-      Timestamp value =
-          Timestamp.newBuilder().setSeconds(TimeUtil.TIMESTAMP_SECONDS_MAX + 1).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid nanos value.
-      Timestamp value = Timestamp.newBuilder().setNanos(-1).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid nanos value.
-      Timestamp value = Timestamp.newBuilder().setNanos(1000000000).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Value to small.
-      TimeUtil.parseTimestamp("0000-01-01T00:00:00Z");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Value to large.
-      TimeUtil.parseTimestamp("10000-01-01T00:00:00Z");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Missing 'T'.
-      TimeUtil.parseTimestamp("1970-01-01 00:00:00Z");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Missing 'Z'.
-      TimeUtil.parseTimestamp("1970-01-01T00:00:00");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid offset.
-      TimeUtil.parseTimestamp("1970-01-01T00:00:00+0000");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Trailing text.
-      TimeUtil.parseTimestamp("1970-01-01T00:00:00Z0");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid nanosecond value.
-      TimeUtil.parseTimestamp("1970-01-01T00:00:00.ABCZ");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-  }
-
-  public void testDurationStringFormat() throws Exception {
-    Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
-    Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
-    Duration duration = TimeUtil.distance(start, end);
-    assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
-    duration = TimeUtil.distance(end, start);
-    assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
-
-    // Generated output should contain 3, 6, or 9 fractional digits.
-    duration = Duration.newBuilder().setSeconds(1).build();
-    assertEquals("1s", TimeUtil.toString(duration));
-    duration = Duration.newBuilder().setNanos(10000000).build();
-    assertEquals("0.010s", TimeUtil.toString(duration));
-    duration = Duration.newBuilder().setNanos(10000).build();
-    assertEquals("0.000010s", TimeUtil.toString(duration));
-    duration = Duration.newBuilder().setNanos(10).build();
-    assertEquals("0.000000010s", TimeUtil.toString(duration));
-
-    // Parsing accepts an fractional digits as long as they fit into nano
-    // precision.
-    duration = TimeUtil.parseDuration("0.1s");
-    assertEquals(100000000, duration.getNanos());
-    duration = TimeUtil.parseDuration("0.0001s");
-    assertEquals(100000, duration.getNanos());
-    duration = TimeUtil.parseDuration("0.0000001s");
-    assertEquals(100, duration.getNanos());
-
-    // Duration must support range from -315,576,000,000s to +315576000000s
-    // which includes negative values.
-    duration = TimeUtil.parseDuration("315576000000.999999999s");
-    assertEquals(315576000000L, duration.getSeconds());
-    assertEquals(999999999, duration.getNanos());
-    duration = TimeUtil.parseDuration("-315576000000.999999999s");
-    assertEquals(-315576000000L, duration.getSeconds());
-    assertEquals(-999999999, duration.getNanos());
-  }
-
-  public void testDurationInvalidFormat() throws Exception {
-    try {
-      // Value too small.
-      Duration value = Duration.newBuilder().setSeconds(TimeUtil.DURATION_SECONDS_MIN - 1).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Value too large.
-      Duration value = Duration.newBuilder().setSeconds(TimeUtil.DURATION_SECONDS_MAX + 1).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid nanos value.
-      Duration value = Duration.newBuilder().setSeconds(1).setNanos(-1).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid nanos value.
-      Duration value = Duration.newBuilder().setSeconds(-1).setNanos(1).build();
-      TimeUtil.toString(value);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    try {
-      // Value too small.
-      TimeUtil.parseDuration("-315576000001s");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Value too large.
-      TimeUtil.parseDuration("315576000001s");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Empty.
-      TimeUtil.parseDuration("");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Missing "s".
-      TimeUtil.parseDuration("0");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid trailing data.
-      TimeUtil.parseDuration("0s0");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-
-    try {
-      // Invalid prefix.
-      TimeUtil.parseDuration("--1s");
-      Assert.fail("Exception is expected.");
-    } catch (ParseException e) {
-      // Expected.
-    }
-  }
-
-  public void testTimestampConversion() throws Exception {
-    Timestamp timestamp = TimeUtil.parseTimestamp("1970-01-01T00:00:01.111111111Z");
-    assertEquals(1111111111, TimeUtil.toNanos(timestamp));
-    assertEquals(1111111, TimeUtil.toMicros(timestamp));
-    assertEquals(1111, TimeUtil.toMillis(timestamp));
-    timestamp = TimeUtil.createTimestampFromNanos(1111111111);
-    assertEquals("1970-01-01T00:00:01.111111111Z", TimeUtil.toString(timestamp));
-    timestamp = TimeUtil.createTimestampFromMicros(1111111);
-    assertEquals("1970-01-01T00:00:01.111111Z", TimeUtil.toString(timestamp));
-    timestamp = TimeUtil.createTimestampFromMillis(1111);
-    assertEquals("1970-01-01T00:00:01.111Z", TimeUtil.toString(timestamp));
-
-    timestamp = TimeUtil.parseTimestamp("1969-12-31T23:59:59.111111111Z");
-    assertEquals(-888888889, TimeUtil.toNanos(timestamp));
-    assertEquals(-888889, TimeUtil.toMicros(timestamp));
-    assertEquals(-889, TimeUtil.toMillis(timestamp));
-    timestamp = TimeUtil.createTimestampFromNanos(-888888889);
-    assertEquals("1969-12-31T23:59:59.111111111Z", TimeUtil.toString(timestamp));
-    timestamp = TimeUtil.createTimestampFromMicros(-888889);
-    assertEquals("1969-12-31T23:59:59.111111Z", TimeUtil.toString(timestamp));
-    timestamp = TimeUtil.createTimestampFromMillis(-889);
-    assertEquals("1969-12-31T23:59:59.111Z", TimeUtil.toString(timestamp));
-  }
-
-  public void testDurationConversion() throws Exception {
-    Duration duration = TimeUtil.parseDuration("1.111111111s");
-    assertEquals(1111111111, TimeUtil.toNanos(duration));
-    assertEquals(1111111, TimeUtil.toMicros(duration));
-    assertEquals(1111, TimeUtil.toMillis(duration));
-    duration = TimeUtil.createDurationFromNanos(1111111111);
-    assertEquals("1.111111111s", TimeUtil.toString(duration));
-    duration = TimeUtil.createDurationFromMicros(1111111);
-    assertEquals("1.111111s", TimeUtil.toString(duration));
-    duration = TimeUtil.createDurationFromMillis(1111);
-    assertEquals("1.111s", TimeUtil.toString(duration));
-
-    duration = TimeUtil.parseDuration("-1.111111111s");
-    assertEquals(-1111111111, TimeUtil.toNanos(duration));
-    assertEquals(-1111111, TimeUtil.toMicros(duration));
-    assertEquals(-1111, TimeUtil.toMillis(duration));
-    duration = TimeUtil.createDurationFromNanos(-1111111111);
-    assertEquals("-1.111111111s", TimeUtil.toString(duration));
-    duration = TimeUtil.createDurationFromMicros(-1111111);
-    assertEquals("-1.111111s", TimeUtil.toString(duration));
-    duration = TimeUtil.createDurationFromMillis(-1111);
-    assertEquals("-1.111s", TimeUtil.toString(duration));
-  }
-
-  public void testTimeOperations() throws Exception {
-    Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
-    Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
-
-    Duration duration = TimeUtil.distance(start, end);
-    assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
-    Timestamp value = TimeUtil.add(start, duration);
-    assertEquals(end, value);
-    value = TimeUtil.subtract(end, duration);
-    assertEquals(start, value);
-
-    duration = TimeUtil.distance(end, start);
-    assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
-    value = TimeUtil.add(end, duration);
-    assertEquals(start, value);
-    value = TimeUtil.subtract(start, duration);
-    assertEquals(end, value);
-
-    // Result is larger than Long.MAX_VALUE.
-    try {
-      duration = TimeUtil.parseDuration("315537897599.999999999s");
-      duration = TimeUtil.multiply(duration, 315537897599.999999999);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    // Result is lesser than Long.MIN_VALUE.
-    try {
-      duration = TimeUtil.parseDuration("315537897599.999999999s");
-      duration = TimeUtil.multiply(duration, -315537897599.999999999);
-      Assert.fail("Exception is expected.");
-    } catch (IllegalArgumentException e) {
-      // Expected.
-    }
-
-    duration = TimeUtil.parseDuration("-1.125s");
-    duration = TimeUtil.divide(duration, 2.0);
-    assertEquals("-0.562500s", TimeUtil.toString(duration));
-    duration = TimeUtil.multiply(duration, 2.0);
-    assertEquals("-1.125s", TimeUtil.toString(duration));
-
-    duration = TimeUtil.add(duration, duration);
-    assertEquals("-2.250s", TimeUtil.toString(duration));
-
-    duration = TimeUtil.subtract(duration, TimeUtil.parseDuration("-1s"));
-    assertEquals("-1.250s", TimeUtil.toString(duration));
-
-    // Multiplications (with results larger than Long.MAX_VALUE in nanoseconds).
-    duration = TimeUtil.parseDuration("0.999999999s");
-    assertEquals(
-        "315575999684.424s", TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
-    duration = TimeUtil.parseDuration("-0.999999999s");
-    assertEquals(
-        "-315575999684.424s", TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
-    assertEquals(
-        "315575999684.424s", TimeUtil.toString(TimeUtil.multiply(duration, -315576000000L)));
-
-    // Divisions (with values larger than Long.MAX_VALUE in nanoseconds).
-    Duration d1 = TimeUtil.parseDuration("315576000000s");
-    Duration d2 = TimeUtil.subtract(d1, TimeUtil.createDurationFromNanos(1));
-    assertEquals(1, TimeUtil.divide(d1, d2));
-    assertEquals(0, TimeUtil.divide(d2, d1));
-    assertEquals("0.000000001s", TimeUtil.toString(TimeUtil.remainder(d1, d2)));
-    assertEquals("315575999999.999999999s", TimeUtil.toString(TimeUtil.remainder(d2, d1)));
-
-    // Divisions involving negative values.
-    //
-    // (-5) / 2 = -2, remainder = -1
-    d1 = TimeUtil.parseDuration("-5s");
-    d2 = TimeUtil.parseDuration("2s");
-    assertEquals(-2, TimeUtil.divide(d1, d2));
-    assertEquals(-2, TimeUtil.divide(d1, 2).getSeconds());
-    assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
-    // (-5) / (-2) = 2, remainder = -1
-    d1 = TimeUtil.parseDuration("-5s");
-    d2 = TimeUtil.parseDuration("-2s");
-    assertEquals(2, TimeUtil.divide(d1, d2));
-    assertEquals(2, TimeUtil.divide(d1, -2).getSeconds());
-    assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
-    // 5 / (-2) = -2, remainder = 1
-    d1 = TimeUtil.parseDuration("5s");
-    d2 = TimeUtil.parseDuration("-2s");
-    assertEquals(-2, TimeUtil.divide(d1, d2));
-    assertEquals(-2, TimeUtil.divide(d1, -2).getSeconds());
-    assertEquals(1, TimeUtil.remainder(d1, d2).getSeconds());
-  }
-}
diff --git a/js/README.md b/js/README.md
index 3635028..0dd0801 100644
--- a/js/README.md
+++ b/js/README.md
@@ -39,9 +39,8 @@
 follow the instructions in [the top-level
 README](https://github.com/protocolbuffers/protobuf/blob/master/src/README.md).
 
-Once you have `protoc` compiled, you can run the tests by typing:
+Once you have `protoc` compiled, you can run the tests provided along with our project to examine whether it can run successfully. In order to do this, you should download the Protocol Buffer source code from the release page with the link above. Then extract the source code and navigate to the folder named `js` containing a `package.json` file and a series of test files. In this folder, you can run the commands below to run the tests automatically.
 
-    $ cd js
     $ npm install
     $ npm test
 
@@ -95,11 +94,8 @@
 
     var message = proto.my.package.MyMessage();
 
-If unfamiliar with Closure or it's compiler, consider reviewing Closure documentation
-https://developers.google.com/closure/library/docs/tutorial
-https://developers.google.com/closure/library/docs/closurebuilder
-https://developers.google.com/closure/library/docs/depswriter
-At a high level, closurebuilder.py can walk dependencies, and compile your code, and all dependencies for Protobuf into a single .js file.  Using depsbuilder.py to generate a dependency file can also be considered for non-production dev environments.
+If unfamiliar with Closure or its compiler, consider reviewing
+[Closure documentation](https://developers.google.com/closure/library).
 
 CommonJS imports
 ----------------
diff --git a/js/binary/constants.js b/js/binary/constants.js
index f8b13a8..d2e62e5 100644
--- a/js/binary/constants.js
+++ b/js/binary/constants.js
@@ -31,6 +31,7 @@
 /**
  * @fileoverview This file contains constants and typedefs used by
  * jspb.BinaryReader and BinaryWriter.
+ * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
  *
  * @author aappleby@google.com (Austin Appleby)
  */
diff --git a/js/binary/decoder.js b/js/binary/decoder.js
index 257c283..fb40ec9 100644
--- a/js/binary/decoder.js
+++ b/js/binary/decoder.js
@@ -40,6 +40,7 @@
  * intact, you _must_ read them using one of the Hash64 methods, which return
  * an 8-character string.
  *
+ * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
  * @author aappleby@google.com (Austin Appleby)
  */
 
diff --git a/js/binary/decoder_test.js b/js/binary/decoder_test.js
index 9900e65..0fddc4b 100644
--- a/js/binary/decoder_test.js
+++ b/js/binary/decoder_test.js
@@ -315,6 +315,9 @@
         // 64-bit extremes, not in dev guide.
         {original: '9223372036854775807', zigzag: '18446744073709551614'},
         {original: '-9223372036854775808', zigzag: '18446744073709551615'},
+        // None of the above catch: bitsLow < 0 && bitsHigh > 0 && bitsHigh <
+        // 0x1FFFFF. The following used to be broken.
+        {original: '72000000000', zigzag: '144000000000'},
       ];
       var encoder = new jspb.BinaryEncoder();
       testCases.forEach(function(c) {
diff --git a/js/binary/reader.js b/js/binary/reader.js
index 2af1a4a..31bbfda 100644
--- a/js/binary/reader.js
+++ b/js/binary/reader.js
@@ -41,6 +41,7 @@
  * using the typed jspb code generator, but if you bypass that you'll need
  * to keep things in sync by hand.
  *
+ * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
  * @author aappleby@google.com (Austin Appleby)
  */
 
@@ -207,6 +208,15 @@
 
 
 /**
+ * @return {boolean} Whether the current wire type is a delimited field. Used to
+ * conditionally parse packed repeated fields.
+ */
+jspb.BinaryReader.prototype.isDelimited = function() {
+  return this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED;
+};
+
+
+/**
  * @return {boolean} Whether the current wire type is an end-group tag. Used as
  * an exit condition in decoder loops in generated code.
  */
diff --git a/js/binary/reader_test.js b/js/binary/reader_test.js
index daa0ab6..7e46828 100644
--- a/js/binary/reader_test.js
+++ b/js/binary/reader_test.js
@@ -46,7 +46,8 @@
 goog.require('jspb.BinaryDecoder');
 goog.require('jspb.BinaryReader');
 goog.require('jspb.BinaryWriter');
-
+goog.require('jspb.utils');
+goog.requireType('jspb.BinaryMessage');
 
 
 describe('binaryReaderTest', function() {
@@ -55,7 +56,7 @@
    */
   it('testInstanceCaches', /** @suppress {visibility} */ function() {
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
     writer.writeMessage(1, dummyMessage, goog.nullFunction);
     writer.writeMessage(2, dummyMessage, goog.nullFunction);
 
@@ -135,7 +136,7 @@
     // Calling readMessage on a non-delimited field should trigger an
     // assertion.
     var reader = jspb.BinaryReader.alloc([8, 1]);
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
     reader.nextField();
     assertThrows(function() {
       reader.readMessage(dummyMessage, goog.nullFunction);
@@ -144,47 +145,91 @@
     // Reading past the end of the stream should trigger an assertion.
     reader = jspb.BinaryReader.alloc([9, 1]);
     reader.nextField();
-    assertThrows(function() {reader.readFixed64()});
+    assertThrows(function() {
+      reader.readFixed64()
+    });
 
     // Reading past the end of a submessage should trigger an assertion.
     reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
     reader.nextField();
     reader.readMessage(dummyMessage, function() {
       reader.nextField();
-      assertThrows(function() {reader.readFixed32()});
+      assertThrows(function() {
+        reader.readFixed32()
+      });
     });
 
     // Skipping an invalid field should trigger an assertion.
     reader = jspb.BinaryReader.alloc([12, 1]);
     reader.nextWireType_ = 1000;
-    assertThrows(function() {reader.skipField()});
+    assertThrows(function() {
+      reader.skipField()
+    });
 
     // Reading fields with the wrong wire type should assert.
     reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
     reader.nextField();
-    assertThrows(function() {reader.readInt32()});
-    assertThrows(function() {reader.readInt32String()});
-    assertThrows(function() {reader.readInt64()});
-    assertThrows(function() {reader.readInt64String()});
-    assertThrows(function() {reader.readUint32()});
-    assertThrows(function() {reader.readUint32String()});
-    assertThrows(function() {reader.readUint64()});
-    assertThrows(function() {reader.readUint64String()});
-    assertThrows(function() {reader.readSint32()});
-    assertThrows(function() {reader.readBool()});
-    assertThrows(function() {reader.readEnum()});
+    assertThrows(function() {
+      reader.readInt32()
+    });
+    assertThrows(function() {
+      reader.readInt32String()
+    });
+    assertThrows(function() {
+      reader.readInt64()
+    });
+    assertThrows(function() {
+      reader.readInt64String()
+    });
+    assertThrows(function() {
+      reader.readUint32()
+    });
+    assertThrows(function() {
+      reader.readUint32String()
+    });
+    assertThrows(function() {
+      reader.readUint64()
+    });
+    assertThrows(function() {
+      reader.readUint64String()
+    });
+    assertThrows(function() {
+      reader.readSint32()
+    });
+    assertThrows(function() {
+      reader.readBool()
+    });
+    assertThrows(function() {
+      reader.readEnum()
+    });
 
     reader = jspb.BinaryReader.alloc([8, 1]);
     reader.nextField();
-    assertThrows(function() {reader.readFixed32()});
-    assertThrows(function() {reader.readFixed64()});
-    assertThrows(function() {reader.readSfixed32()});
-    assertThrows(function() {reader.readSfixed64()});
-    assertThrows(function() {reader.readFloat()});
-    assertThrows(function() {reader.readDouble()});
+    assertThrows(function() {
+      reader.readFixed32()
+    });
+    assertThrows(function() {
+      reader.readFixed64()
+    });
+    assertThrows(function() {
+      reader.readSfixed32()
+    });
+    assertThrows(function() {
+      reader.readSfixed64()
+    });
+    assertThrows(function() {
+      reader.readFloat()
+    });
+    assertThrows(function() {
+      reader.readDouble()
+    });
 
-    assertThrows(function() {reader.readString()});
-    assertThrows(function() {reader.readBytes()});
+    assertThrows(function() {
+      reader.readString()
+    });
+    assertThrows(function() {
+      reader.readBytes()
+    });
   });
 
 
@@ -198,8 +243,8 @@
    * @private
    * @suppress {missingProperties}
    */
-  var doTestUnsignedField_ = function(readField,
-      writeField, epsilon, upperLimit, filter) {
+  var doTestUnsignedField_ = function(
+      readField, writeField, epsilon, upperLimit, filter) {
     assertNotNull(readField);
     assertNotNull(writeField);
 
@@ -250,8 +295,8 @@
    * @private
    * @suppress {missingProperties}
    */
-  var doTestSignedField_ = function(readField,
-      writeField, epsilon, lowerLimit, upperLimit, filter) {
+  var doTestSignedField_ = function(
+      readField, writeField, epsilon, lowerLimit, upperLimit, filter) {
     var writer = new jspb.BinaryWriter();
 
     // Encode zero and limits.
@@ -267,20 +312,14 @@
     for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
       var val = filter(cursor);
       writeField.call(writer, 6, val);
-      inputValues.push({
-        fieldNumber: 6,
-        value: val
-      });
+      inputValues.push({fieldNumber: 6, value: val});
     }
 
     // Encode positive values.
     for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
       var val = filter(cursor);
       writeField.call(writer, 7, val);
-      inputValues.push({
-        fieldNumber: 7,
-        value: val
-      });
+      inputValues.push({fieldNumber: 7, value: val});
     }
 
     var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
@@ -327,33 +366,34 @@
     assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readUint32,
-        jspb.BinaryWriter.prototype.writeUint32,
-        1, Math.pow(2, 32) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1,
+        Math.round);
 
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readUint64,
-        jspb.BinaryWriter.prototype.writeUint64,
-        1, Math.pow(2, 64) - 1025, Math.round);
+        jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025,
+        Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readInt32,
-        jspb.BinaryWriter.prototype.writeInt32,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readInt64,
-        jspb.BinaryWriter.prototype.writeInt64,
-        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+        jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63),
+        Math.pow(2, 63) - 513, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readEnum,
-        jspb.BinaryWriter.prototype.writeEnum,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readBool,
-        jspb.BinaryWriter.prototype.writeBool,
-        1, 1, function(x) { return !!x; });
+        jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) {
+          return !!x;
+        });
   });
 
 
@@ -387,24 +427,22 @@
     // uint32 and sint32 take no more than 5 bytes
     // 08 - field prefix (type = 0 means varint)
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readUint32,
-      12, '08 8C 80 80 80 00');
+        jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00');
 
     // 11 stands for -6 in zigzag encoding
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readSint32,
-      -6, '08 8B 80 80 80 00');
+        jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00');
 
     // uint64 and sint64 take no more than 10 bytes
     // 08 - field prefix (type = 0 means varint)
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readUint64,
-      12, '08 8C 80 80 80 80 80 80 80 80 00');
+        jspb.BinaryReader.prototype.readUint64, 12,
+        '08 8C 80 80 80 80 80 80 80 80 00');
 
     // 11 stands for -6 in zigzag encoding
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readSint64,
-      -6, '08 8B 80 80 80 80 80 80 80 80 00');
+        jspb.BinaryReader.prototype.readSint64, -6,
+        '08 8B 80 80 80 80 80 80 80 80 00');
   });
 
   /**
@@ -440,27 +478,15 @@
     var writer = new jspb.BinaryWriter();
 
     var testSignedData = [
-      '2730538252207801776',
-      '-2688470994844604560',
-      '3398529779486536359',
-      '3568577411627971000',
-      '272477188847484900',
-      '-6649058714086158188',
-      '-7695254765712060806',
-      '-4525541438037104029',
-      '-4993706538836508568',
+      '2730538252207801776', '-2688470994844604560', '3398529779486536359',
+      '3568577411627971000', '272477188847484900', '-6649058714086158188',
+      '-7695254765712060806', '-4525541438037104029', '-4993706538836508568',
       '4990160321893729138'
     ];
     var testUnsignedData = [
-      '7822732630241694882',
-      '6753602971916687352',
-      '2399935075244442116',
-      '8724292567325338867',
-      '16948784802625696584',
-      '4136275908516066934',
-      '3575388346793700364',
-      '5167142028379259461',
-      '1557573948689737699',
+      '7822732630241694882', '6753602971916687352', '2399935075244442116',
+      '8724292567325338867', '16948784802625696584', '4136275908516066934',
+      '3575388346793700364', '5167142028379259461', '1557573948689737699',
       '17100725280812548567'
     ];
 
@@ -488,13 +514,13 @@
   it('testZigzagFields', function() {
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSint32,
-        jspb.BinaryWriter.prototype.writeSint32,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSint64,
-        jspb.BinaryWriter.prototype.writeSint64,
-        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+        jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63),
+        Math.pow(2, 63) - 513, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSintHash64,
@@ -509,23 +535,23 @@
   it('testFixedFields', function() {
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readFixed32,
-        jspb.BinaryWriter.prototype.writeFixed32,
-        1, Math.pow(2, 32) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1,
+        Math.round);
 
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readFixed64,
-        jspb.BinaryWriter.prototype.writeFixed64,
-        1, Math.pow(2, 64) - 1025, Math.round);
+        jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025,
+        Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSfixed32,
-        jspb.BinaryWriter.prototype.writeSfixed32,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSfixed64,
-        jspb.BinaryWriter.prototype.writeSfixed64,
-        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+        jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63),
+        Math.pow(2, 63) - 513, Math.round);
   });
 
 
@@ -536,18 +562,17 @@
     doTestSignedField_(
         jspb.BinaryReader.prototype.readFloat,
         jspb.BinaryWriter.prototype.writeFloat,
-        jspb.BinaryConstants.FLOAT32_MIN,
-        -jspb.BinaryConstants.FLOAT32_MAX,
-        jspb.BinaryConstants.FLOAT32_MAX,
-        truncate);
+        jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX,
+        jspb.BinaryConstants.FLOAT32_MAX, truncate);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readDouble,
         jspb.BinaryWriter.prototype.writeDouble,
         jspb.BinaryConstants.FLOAT64_EPS * 10,
-        -jspb.BinaryConstants.FLOAT64_MIN,
-        jspb.BinaryConstants.FLOAT64_MIN,
-        function(x) { return x; });
+        -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN,
+        function(x) {
+          return x;
+        });
   });
 
 
@@ -614,7 +639,7 @@
    */
   it('testNesting', function() {
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     writer.writeInt32(1, 100);
 
@@ -707,7 +732,7 @@
 
     // Write a group with a nested group inside.
     writer.writeInt32(5, sentinel);
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
     writer.writeGroup(5, dummyMessage, function() {
       // Previously the skipGroup implementation was wrong, which only consume
       // the decoder by nextField. This case is for making the previous
@@ -726,7 +751,7 @@
         writer.writeInt64(84, 42);
         writer.writeInt64(84, 44);
         writer.writeBytes(
-          43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]);
+            43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]);
       });
     });
 
@@ -875,7 +900,7 @@
     var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
     var blob = [1, 2, 3, 4, 5];
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     writer.writeMessage(1, dummyMessage, function() {
       writer.writeMessage(1, dummyMessage, function() {
@@ -908,7 +933,7 @@
    */
   it('testReadCallbacks', function() {
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     // Add an int, a submessage, and another int.
     writer.writeInt32(1, 100);
diff --git a/js/binary/utils.js b/js/binary/utils.js
index 0d55a4a..4d74331 100644
--- a/js/binary/utils.js
+++ b/js/binary/utils.js
@@ -32,6 +32,7 @@
  * @fileoverview This file contains helper code used by jspb.BinaryReader
  * and BinaryWriter.
  *
+ * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
  * @author aappleby@google.com (Austin Appleby)
  */
 
@@ -258,7 +259,7 @@
   // Compute the least significant exponent needed to represent the magnitude of
   // the value by repeadly dividing/multiplying by 2 until the magnitude
   // crosses 2. While tempting to use log math to find the exponent, at the
-  // bounadaries of precision, the result can be off by one.
+  // boundaries of precision, the result can be off by one.
   var maxDoubleExponent = 1023;
   var minDoubleExponent = -1022;
   var x = value;
@@ -510,7 +511,7 @@
   // Skip the expensive conversion if the number is small enough to use the
   // built-in conversions.
   if (bitsHigh <= 0x1FFFFF) {
-    return '' + (jspb.BinaryConstants.TWO_TO_32 * bitsHigh + bitsLow);
+    return '' + jspb.utils.joinUint64(bitsLow, bitsHigh);
   }
 
   // What this code is doing is essentially converting the input number from
diff --git a/js/binary/writer.js b/js/binary/writer.js
index ab9a815..1e2beee 100644
--- a/js/binary/writer.js
+++ b/js/binary/writer.js
@@ -52,6 +52,7 @@
  * Major caveat 3 - This class uses typed arrays and must not be used on older
  * browsers that do not support them.
  *
+ * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
  * @author aappleby@google.com (Austin Appleby)
  */
 
diff --git a/js/binary/writer_test.js b/js/binary/writer_test.js
index fca1ba4..6c5f36e 100644
--- a/js/binary/writer_test.js
+++ b/js/binary/writer_test.js
@@ -44,7 +44,8 @@
 goog.require('jspb.BinaryReader');
 goog.require('jspb.BinaryWriter');
 goog.require('jspb.utils');
-
+goog.require('goog.crypt.base64');
+goog.requireType('jspb.BinaryMessage');
 
 /**
  * @param {function()} func This function should throw an error when run.
@@ -61,7 +62,7 @@
   it('testWriteErrors', function() {
     // Submessages with invalid field indices should assert.
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     assertFails(function() {
       writer.writeMessage(-1, dummyMessage, goog.nullFunction);
@@ -69,40 +70,82 @@
 
     // Writing invalid field indices should assert.
     writer = new jspb.BinaryWriter();
-    assertFails(function() {writer.writeUint64(-1, 1);});
+    assertFails(function() {
+      writer.writeUint64(-1, 1);
+    });
 
     // Writing out-of-range field values should assert.
     writer = new jspb.BinaryWriter();
 
-    assertFails(function() {writer.writeInt32(1, -Infinity);});
-    assertFails(function() {writer.writeInt32(1, Infinity);});
+    assertFails(function() {
+      writer.writeInt32(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeInt32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeInt64(1, -Infinity);});
-    assertFails(function() {writer.writeInt64(1, Infinity);});
+    assertFails(function() {
+      writer.writeInt64(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeInt64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeUint32(1, -1);});
-    assertFails(function() {writer.writeUint32(1, Infinity);});
+    assertFails(function() {
+      writer.writeUint32(1, -1);
+    });
+    assertFails(function() {
+      writer.writeUint32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeUint64(1, -1);});
-    assertFails(function() {writer.writeUint64(1, Infinity);});
+    assertFails(function() {
+      writer.writeUint64(1, -1);
+    });
+    assertFails(function() {
+      writer.writeUint64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSint32(1, -Infinity);});
-    assertFails(function() {writer.writeSint32(1, Infinity);});
+    assertFails(function() {
+      writer.writeSint32(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSint32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSint64(1, -Infinity);});
-    assertFails(function() {writer.writeSint64(1, Infinity);});
+    assertFails(function() {
+      writer.writeSint64(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSint64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeFixed32(1, -1);});
-    assertFails(function() {writer.writeFixed32(1, Infinity);});
+    assertFails(function() {
+      writer.writeFixed32(1, -1);
+    });
+    assertFails(function() {
+      writer.writeFixed32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeFixed64(1, -1);});
-    assertFails(function() {writer.writeFixed64(1, Infinity);});
+    assertFails(function() {
+      writer.writeFixed64(1, -1);
+    });
+    assertFails(function() {
+      writer.writeFixed64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSfixed32(1, -Infinity);});
-    assertFails(function() {writer.writeSfixed32(1, Infinity);});
+    assertFails(function() {
+      writer.writeSfixed32(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSfixed32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSfixed64(1, -Infinity);});
-    assertFails(function() {writer.writeSfixed64(1, Infinity);});
+    assertFails(function() {
+      writer.writeSfixed64(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSfixed64(1, Infinity);
+    });
   });
 
 
diff --git a/js/commonjs/export.js b/js/commonjs/export.js
index a93ee92..a9932e9 100644
--- a/js/commonjs/export.js
+++ b/js/commonjs/export.js
@@ -5,8 +5,6 @@
  * the google-protobuf.js file that we build at distribution time.
  */
 
-// Include a dummy provide statement so that closurebuilder.py does not skip over this
-// file.
 goog.provide('jspb.Export');
 
 goog.require('goog.object');
diff --git a/js/commonjs/export_asserts.js b/js/commonjs/export_asserts.js
index ad9446c..fa6e795 100644
--- a/js/commonjs/export_asserts.js
+++ b/js/commonjs/export_asserts.js
@@ -6,8 +6,6 @@
  * closure_asserts_commonjs.js that is only used at testing time.
  */
 
-// Include a dummy provide statement so that closurebuilder.py does not skip over this
-// file.
 goog.provide('jspb.ExportAsserts');
 
 goog.require('goog.testing.asserts');
diff --git a/js/commonjs/export_testdeps.js b/js/commonjs/export_testdeps.js
index 96d3f34..51d868e 100644
--- a/js/commonjs/export_testdeps.js
+++ b/js/commonjs/export_testdeps.js
@@ -7,8 +7,6 @@
  * export_asserts.js.
  */
 
-// Include a dummy provide statement so that closurebuilder.py does not skip over this
-// file.
 goog.provide('jspb.ExportTestDeps');
 
 goog.require('goog.crypt.base64');
diff --git a/js/commonjs/rewrite_tests_for_commonjs.js b/js/commonjs/rewrite_tests_for_commonjs.js
index b6d90d2..82eef18 100644
--- a/js/commonjs/rewrite_tests_for_commonjs.js
+++ b/js/commonjs/rewrite_tests_for_commonjs.js
@@ -80,6 +80,8 @@
   if (isRequire) {
     if (module) {  // Skip goog.require() lines before the first directive.
       var fullSym = isRequire[1];
+      // Skip lines importing from jspb.*, these are handled by the header above.
+      if (fullSym.match(/^jspb\./)) return;
       var sym = tryStripPrefix(fullSym, pkg);
       console.log("googleProtobuf.exportSymbol('" + fullSym + "', " + module + sym + ', global);');
     }
diff --git a/js/compatibility_tests/v3.0.0/test.sh b/js/compatibility_tests/v3.0.0/test.sh
index 9d58f30..5b92ed1 100755
--- a/js/compatibility_tests/v3.0.0/test.sh
+++ b/js/compatibility_tests/v3.0.0/test.sh
@@ -53,8 +53,20 @@
 done
 cp commonjs/{jasmine.json,import_test.js} commonjs_out/
 mkdir -p commonjs_out/test_node_modules
-../../node_modules/google-closure-library/closure/bin/calcdeps.py -i commonjs/export_asserts.js -p . -p ../../node_modules/google-closure-library/closure -o compiled --compiler_jar ../../node_modules/google-closure-compiler/compiler.jar > commonjs_out/test_node_modules/closure_asserts_commonjs.js
-../../node_modules/google-closure-library/closure/bin/calcdeps.py -i commonjs/export_testdeps.js -p ../.. -p ../../node_modules/google-closure-library/closure -o compiled --compiler_jar ../../node_modules/google-closure-compiler/compiler.jar > commonjs_out/test_node_modules/testdeps_commonjs.js
+../../node_modules/.bin/google-closure-compiler \
+  --entry_point=commonjs/export_asserts.js \
+  --js=commonjs/export_asserts.js \
+  --js=../../node_modules/google-closure-library/closure/goog/**.js \
+  --js=../../node_modules/google-closure-library/third_party/closure/goog/**.js \
+  > commonjs_out/test_node_modules/closure_asserts_commonjs.js
+../../node_modules/.bin/google-closure-compiler \
+  --entry_point=commonjs/export_testdeps.js \
+  --js=commonjs/export_testdeps.js \
+  --js=../../binary/*.js \
+  --js=!../../binary/*_test.js \
+  --js=../../node_modules/google-closure-library/closure/goog/**.js \
+  --js=../../node_modules/google-closure-library/third_party/closure/goog/**.js \
+  > commonjs_out/test_node_modules/testdeps_commonjs.js
 cp ../../google-protobuf.js commonjs_out/test_node_modules
 cp -r ../../commonjs_out/node_modules commonjs_out
 
diff --git a/js/compatibility_tests/v3.1.0/binary/decoder_test.js b/js/compatibility_tests/v3.1.0/binary/decoder_test.js
index 71a3725..01100fd 100644
--- a/js/compatibility_tests/v3.1.0/binary/decoder_test.js
+++ b/js/compatibility_tests/v3.1.0/binary/decoder_test.js
@@ -224,7 +224,6 @@
 
   /**
    * Verifies that misuse of the decoder class triggers assertions.
-   * @suppress {checkTypes|visibility}
    */
   it('testDecodeErrors', function() {
     // Reading a value past the end of the stream should trigger an assertion.
diff --git a/js/compatibility_tests/v3.1.0/binary/reader_test.js b/js/compatibility_tests/v3.1.0/binary/reader_test.js
index 9571138..d0062de 100644
--- a/js/compatibility_tests/v3.1.0/binary/reader_test.js
+++ b/js/compatibility_tests/v3.1.0/binary/reader_test.js
@@ -46,7 +46,7 @@
 goog.require('jspb.BinaryDecoder');
 goog.require('jspb.BinaryReader');
 goog.require('jspb.BinaryWriter');
-
+goog.requireType('jspb.BinaryMessage');
 
 
 describe('binaryReaderTest', function() {
@@ -55,7 +55,7 @@
    */
   it('testInstanceCaches', /** @suppress {visibility} */ function() {
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
     writer.writeMessage(1, dummyMessage, goog.nullFunction);
     writer.writeMessage(2, dummyMessage, goog.nullFunction);
 
@@ -135,7 +135,7 @@
     // Calling readMessage on a non-delimited field should trigger an
     // assertion.
     var reader = jspb.BinaryReader.alloc([8, 1]);
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
     reader.nextField();
     assertThrows(function() {
       reader.readMessage(dummyMessage, goog.nullFunction);
@@ -144,47 +144,91 @@
     // Reading past the end of the stream should trigger an assertion.
     reader = jspb.BinaryReader.alloc([9, 1]);
     reader.nextField();
-    assertThrows(function() {reader.readFixed64()});
+    assertThrows(function() {
+      reader.readFixed64()
+    });
 
     // Reading past the end of a submessage should trigger an assertion.
     reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
     reader.nextField();
     reader.readMessage(dummyMessage, function() {
       reader.nextField();
-      assertThrows(function() {reader.readFixed32()});
+      assertThrows(function() {
+        reader.readFixed32()
+      });
     });
 
     // Skipping an invalid field should trigger an assertion.
     reader = jspb.BinaryReader.alloc([12, 1]);
     reader.nextWireType_ = 1000;
-    assertThrows(function() {reader.skipField()});
+    assertThrows(function() {
+      reader.skipField()
+    });
 
     // Reading fields with the wrong wire type should assert.
     reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
     reader.nextField();
-    assertThrows(function() {reader.readInt32()});
-    assertThrows(function() {reader.readInt32String()});
-    assertThrows(function() {reader.readInt64()});
-    assertThrows(function() {reader.readInt64String()});
-    assertThrows(function() {reader.readUint32()});
-    assertThrows(function() {reader.readUint32String()});
-    assertThrows(function() {reader.readUint64()});
-    assertThrows(function() {reader.readUint64String()});
-    assertThrows(function() {reader.readSint32()});
-    assertThrows(function() {reader.readBool()});
-    assertThrows(function() {reader.readEnum()});
+    assertThrows(function() {
+      reader.readInt32()
+    });
+    assertThrows(function() {
+      reader.readInt32String()
+    });
+    assertThrows(function() {
+      reader.readInt64()
+    });
+    assertThrows(function() {
+      reader.readInt64String()
+    });
+    assertThrows(function() {
+      reader.readUint32()
+    });
+    assertThrows(function() {
+      reader.readUint32String()
+    });
+    assertThrows(function() {
+      reader.readUint64()
+    });
+    assertThrows(function() {
+      reader.readUint64String()
+    });
+    assertThrows(function() {
+      reader.readSint32()
+    });
+    assertThrows(function() {
+      reader.readBool()
+    });
+    assertThrows(function() {
+      reader.readEnum()
+    });
 
     reader = jspb.BinaryReader.alloc([8, 1]);
     reader.nextField();
-    assertThrows(function() {reader.readFixed32()});
-    assertThrows(function() {reader.readFixed64()});
-    assertThrows(function() {reader.readSfixed32()});
-    assertThrows(function() {reader.readSfixed64()});
-    assertThrows(function() {reader.readFloat()});
-    assertThrows(function() {reader.readDouble()});
+    assertThrows(function() {
+      reader.readFixed32()
+    });
+    assertThrows(function() {
+      reader.readFixed64()
+    });
+    assertThrows(function() {
+      reader.readSfixed32()
+    });
+    assertThrows(function() {
+      reader.readSfixed64()
+    });
+    assertThrows(function() {
+      reader.readFloat()
+    });
+    assertThrows(function() {
+      reader.readDouble()
+    });
 
-    assertThrows(function() {reader.readString()});
-    assertThrows(function() {reader.readBytes()});
+    assertThrows(function() {
+      reader.readString()
+    });
+    assertThrows(function() {
+      reader.readBytes()
+    });
   });
 
 
@@ -198,8 +242,8 @@
    * @private
    * @suppress {missingProperties}
    */
-  var doTestUnsignedField_ = function(readField,
-      writeField, epsilon, upperLimit, filter) {
+  var doTestUnsignedField_ = function(
+      readField, writeField, epsilon, upperLimit, filter) {
     assertNotNull(readField);
     assertNotNull(writeField);
 
@@ -250,8 +294,8 @@
    * @private
    * @suppress {missingProperties}
    */
-  var doTestSignedField_ = function(readField,
-      writeField, epsilon, lowerLimit, upperLimit, filter) {
+  var doTestSignedField_ = function(
+      readField, writeField, epsilon, lowerLimit, upperLimit, filter) {
     var writer = new jspb.BinaryWriter();
 
     // Encode zero and limits.
@@ -267,20 +311,14 @@
     for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
       var val = filter(cursor);
       writeField.call(writer, 6, val);
-      inputValues.push({
-        fieldNumber: 6,
-        value: val
-      });
+      inputValues.push({fieldNumber: 6, value: val});
     }
 
     // Encode positive values.
     for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
       var val = filter(cursor);
       writeField.call(writer, 7, val);
-      inputValues.push({
-        fieldNumber: 7,
-        value: val
-      });
+      inputValues.push({fieldNumber: 7, value: val});
     }
 
     var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
@@ -327,33 +365,34 @@
     assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readUint32,
-        jspb.BinaryWriter.prototype.writeUint32,
-        1, Math.pow(2, 32) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1,
+        Math.round);
 
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readUint64,
-        jspb.BinaryWriter.prototype.writeUint64,
-        1, Math.pow(2, 64) - 1025, Math.round);
+        jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025,
+        Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readInt32,
-        jspb.BinaryWriter.prototype.writeInt32,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readInt64,
-        jspb.BinaryWriter.prototype.writeInt64,
-        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+        jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63),
+        Math.pow(2, 63) - 513, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readEnum,
-        jspb.BinaryWriter.prototype.writeEnum,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readBool,
-        jspb.BinaryWriter.prototype.writeBool,
-        1, 1, function(x) { return !!x; });
+        jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) {
+          return !!x;
+        });
   });
 
 
@@ -387,24 +426,22 @@
     // uint32 and sint32 take no more than 5 bytes
     // 08 - field prefix (type = 0 means varint)
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readUint32,
-      12, '08 8C 80 80 80 00');
+        jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00');
 
     // 11 stands for -6 in zigzag encoding
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readSint32,
-      -6, '08 8B 80 80 80 00');
+        jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00');
 
     // uint64 and sint64 take no more than 10 bytes
     // 08 - field prefix (type = 0 means varint)
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readUint64,
-      12, '08 8C 80 80 80 80 80 80 80 80 00');
+        jspb.BinaryReader.prototype.readUint64, 12,
+        '08 8C 80 80 80 80 80 80 80 80 00');
 
     // 11 stands for -6 in zigzag encoding
     doTestHexStringVarint_(
-      jspb.BinaryReader.prototype.readSint64,
-      -6, '08 8B 80 80 80 80 80 80 80 80 00');
+        jspb.BinaryReader.prototype.readSint64, -6,
+        '08 8B 80 80 80 80 80 80 80 80 00');
   });
 
 
@@ -415,27 +452,15 @@
     var writer = new jspb.BinaryWriter();
 
     var testSignedData = [
-      '2730538252207801776',
-      '-2688470994844604560',
-      '3398529779486536359',
-      '3568577411627971000',
-      '272477188847484900',
-      '-6649058714086158188',
-      '-7695254765712060806',
-      '-4525541438037104029',
-      '-4993706538836508568',
+      '2730538252207801776', '-2688470994844604560', '3398529779486536359',
+      '3568577411627971000', '272477188847484900', '-6649058714086158188',
+      '-7695254765712060806', '-4525541438037104029', '-4993706538836508568',
       '4990160321893729138'
     ];
     var testUnsignedData = [
-      '7822732630241694882',
-      '6753602971916687352',
-      '2399935075244442116',
-      '8724292567325338867',
-      '16948784802625696584',
-      '4136275908516066934',
-      '3575388346793700364',
-      '5167142028379259461',
-      '1557573948689737699',
+      '7822732630241694882', '6753602971916687352', '2399935075244442116',
+      '8724292567325338867', '16948784802625696584', '4136275908516066934',
+      '3575388346793700364', '5167142028379259461', '1557573948689737699',
       '17100725280812548567'
     ];
 
@@ -463,13 +488,13 @@
   it('testZigzagFields', function() {
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSint32,
-        jspb.BinaryWriter.prototype.writeSint32,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSint64,
-        jspb.BinaryWriter.prototype.writeSint64,
-        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+        jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63),
+        Math.pow(2, 63) - 513, Math.round);
   });
 
 
@@ -479,23 +504,23 @@
   it('testFixedFields', function() {
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readFixed32,
-        jspb.BinaryWriter.prototype.writeFixed32,
-        1, Math.pow(2, 32) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1,
+        Math.round);
 
     doTestUnsignedField_(
         jspb.BinaryReader.prototype.readFixed64,
-        jspb.BinaryWriter.prototype.writeFixed64,
-        1, Math.pow(2, 64) - 1025, Math.round);
+        jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025,
+        Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSfixed32,
-        jspb.BinaryWriter.prototype.writeSfixed32,
-        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+        jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31),
+        Math.pow(2, 31) - 1, Math.round);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readSfixed64,
-        jspb.BinaryWriter.prototype.writeSfixed64,
-        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+        jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63),
+        Math.pow(2, 63) - 513, Math.round);
   });
 
 
@@ -506,18 +531,17 @@
     doTestSignedField_(
         jspb.BinaryReader.prototype.readFloat,
         jspb.BinaryWriter.prototype.writeFloat,
-        jspb.BinaryConstants.FLOAT32_MIN,
-        -jspb.BinaryConstants.FLOAT32_MAX,
-        jspb.BinaryConstants.FLOAT32_MAX,
-        truncate);
+        jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX,
+        jspb.BinaryConstants.FLOAT32_MAX, truncate);
 
     doTestSignedField_(
         jspb.BinaryReader.prototype.readDouble,
         jspb.BinaryWriter.prototype.writeDouble,
         jspb.BinaryConstants.FLOAT64_EPS * 10,
-        -jspb.BinaryConstants.FLOAT64_MIN,
-        jspb.BinaryConstants.FLOAT64_MIN,
-        function(x) { return x; });
+        -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN,
+        function(x) {
+          return x;
+        });
   });
 
 
@@ -584,7 +608,7 @@
    */
   it('testNesting', function() {
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     writer.writeInt32(1, 100);
 
@@ -677,7 +701,7 @@
 
     // Write a group with a nested group inside.
     writer.writeInt32(5, sentinel);
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
     writer.writeGroup(5, dummyMessage, function() {
       writer.writeInt64(42, 42);
       writer.writeGroup(6, dummyMessage, function() {
@@ -830,7 +854,7 @@
     var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
     var blob = [1, 2, 3, 4, 5];
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     writer.writeMessage(1, dummyMessage, function() {
       writer.writeMessage(1, dummyMessage, function() {
@@ -863,7 +887,7 @@
    */
   it('testReadCallbacks', function() {
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     // Add an int, a submessage, and another int.
     writer.writeInt32(1, 100);
diff --git a/js/compatibility_tests/v3.1.0/binary/writer_test.js b/js/compatibility_tests/v3.1.0/binary/writer_test.js
index d5dadb4..55bc6be 100644
--- a/js/compatibility_tests/v3.1.0/binary/writer_test.js
+++ b/js/compatibility_tests/v3.1.0/binary/writer_test.js
@@ -41,14 +41,14 @@
 goog.require('goog.crypt');
 goog.require('goog.testing.asserts');
 goog.require('jspb.BinaryWriter');
-
+goog.requireType('jspb.BinaryMessage');
 
 /**
  * @param {function()} func This function should throw an error when run.
  */
 function assertFails(func) {
   var e = assertThrows(func);
-  //assertNotNull(e.toString().match(/Error/));
+  // assertNotNull(e.toString().match(/Error/));
 }
 
 
@@ -59,7 +59,7 @@
   it('testWriteErrors', function() {
     // Submessages with invalid field indices should assert.
     var writer = new jspb.BinaryWriter();
-    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
 
     assertFails(function() {
       writer.writeMessage(-1, dummyMessage, goog.nullFunction);
@@ -67,40 +67,82 @@
 
     // Writing invalid field indices should assert.
     writer = new jspb.BinaryWriter();
-    assertFails(function() {writer.writeUint64(-1, 1);});
+    assertFails(function() {
+      writer.writeUint64(-1, 1);
+    });
 
     // Writing out-of-range field values should assert.
     writer = new jspb.BinaryWriter();
 
-    assertFails(function() {writer.writeInt32(1, -Infinity);});
-    assertFails(function() {writer.writeInt32(1, Infinity);});
+    assertFails(function() {
+      writer.writeInt32(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeInt32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeInt64(1, -Infinity);});
-    assertFails(function() {writer.writeInt64(1, Infinity);});
+    assertFails(function() {
+      writer.writeInt64(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeInt64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeUint32(1, -1);});
-    assertFails(function() {writer.writeUint32(1, Infinity);});
+    assertFails(function() {
+      writer.writeUint32(1, -1);
+    });
+    assertFails(function() {
+      writer.writeUint32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeUint64(1, -1);});
-    assertFails(function() {writer.writeUint64(1, Infinity);});
+    assertFails(function() {
+      writer.writeUint64(1, -1);
+    });
+    assertFails(function() {
+      writer.writeUint64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSint32(1, -Infinity);});
-    assertFails(function() {writer.writeSint32(1, Infinity);});
+    assertFails(function() {
+      writer.writeSint32(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSint32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSint64(1, -Infinity);});
-    assertFails(function() {writer.writeSint64(1, Infinity);});
+    assertFails(function() {
+      writer.writeSint64(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSint64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeFixed32(1, -1);});
-    assertFails(function() {writer.writeFixed32(1, Infinity);});
+    assertFails(function() {
+      writer.writeFixed32(1, -1);
+    });
+    assertFails(function() {
+      writer.writeFixed32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeFixed64(1, -1);});
-    assertFails(function() {writer.writeFixed64(1, Infinity);});
+    assertFails(function() {
+      writer.writeFixed64(1, -1);
+    });
+    assertFails(function() {
+      writer.writeFixed64(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSfixed32(1, -Infinity);});
-    assertFails(function() {writer.writeSfixed32(1, Infinity);});
+    assertFails(function() {
+      writer.writeSfixed32(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSfixed32(1, Infinity);
+    });
 
-    assertFails(function() {writer.writeSfixed64(1, -Infinity);});
-    assertFails(function() {writer.writeSfixed64(1, Infinity);});
+    assertFails(function() {
+      writer.writeSfixed64(1, -Infinity);
+    });
+    assertFails(function() {
+      writer.writeSfixed64(1, Infinity);
+    });
   });
 
 
diff --git a/js/compatibility_tests/v3.1.0/maps_test.js b/js/compatibility_tests/v3.1.0/maps_test.js
index 0d442f4..452dfe5 100644
--- a/js/compatibility_tests/v3.1.0/maps_test.js
+++ b/js/compatibility_tests/v3.1.0/maps_test.js
@@ -40,6 +40,8 @@
 goog.require('proto.jspb.test.MapValueMessageNoBinary');
 goog.require('proto.jspb.test.TestMapFieldsNoBinary');
 
+goog.requireType('jspb.Map');
+
 /**
  * Helper: check that the given map has exactly this set of (sorted) entries.
  * @param {!jspb.Map} map
@@ -98,7 +100,9 @@
     msg.getMapStringMsgMap().get('k').setFoo(42);
     msg.getMapStringMsgMap().get('l').setFoo(84);
     msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
-    msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd');
+    msg.getMapInt64StringMap()
+        .set(0x123456789abc, 'c')
+        .set(0xcba987654321, 'd');
     msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
   };
 
@@ -107,42 +111,24 @@
    * @param {?} msg
    */
   var checkMapFields = function(msg) {
-    checkMapEquals(msg.getMapStringStringMap(), [
-          ['asdf', 'jkl;'],
-          ['key 2', 'hello world']
-    ]);
-    checkMapEquals(msg.getMapStringInt32Map(), [
-          ['a', 1],
-          ['b', -2]
-    ]);
-    checkMapEquals(msg.getMapStringInt64Map(), [
-          ['c', 0x100000000],
-          ['d', 0x200000000]
-    ]);
-    checkMapEquals(msg.getMapStringBoolMap(), [
-          ['e', true],
-          ['f', false]
-    ]);
-    checkMapEquals(msg.getMapStringDoubleMap(), [
-          ['g', 3.14159],
-          ['h', 2.71828]
-    ]);
+    checkMapEquals(
+        msg.getMapStringStringMap(),
+        [['asdf', 'jkl;'], ['key 2', 'hello world']]);
+    checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]);
+    checkMapEquals(
+        msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]);
+    checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]);
+    checkMapEquals(
+        msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]);
     checkMapEquals(msg.getMapStringEnumMap(), [
-          ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
-          ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
+      ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
+      ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
     ]);
-    checkMapEquals(msg.getMapInt32StringMap(), [
-          [-1, 'a'],
-          [42, 'b']
-    ]);
-    checkMapEquals(msg.getMapInt64StringMap(), [
-          [0x123456789abc, 'c'],
-          [0xcba987654321, 'd']
-    ]);
-    checkMapEquals(msg.getMapBoolStringMap(), [
-          [false, 'e'],
-          [true, 'f']
-    ]);
+    checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]);
+    checkMapEquals(
+        msg.getMapInt64StringMap(),
+        [[0x123456789abc, 'c'], [0xcba987654321, 'd']]);
+    checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]);
 
     assertEquals(msg.getMapStringMsgMap().getLength(), 2);
     assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
@@ -187,10 +173,7 @@
     assertElementsEquals(it.next().value, ['asdf', 'hello world']);
     assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
     assertEquals(it.next().done, true);
-    checkMapEquals(m, [
-        ['asdf', 'hello world'],
-        ['jkl;', 'key 2']
-    ]);
+    checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]);
     m.del('jkl;');
     assertEquals(m.has('jkl;'), false);
     assertEquals(m.get('jkl;'), undefined);
@@ -242,11 +225,11 @@
       msg.getMapStringStringMap().set('A', 'a');
       var serialized = msg.serializeBinary();
       var expectedSerialized = [
-          0x0a, 0x6, // field 1 (map_string_string), delimited, length 6
-          0x0a, 0x1, // field 1 in submessage (key), delimited, length 1
-          0x41,      // ASCII 'A'
-          0x12, 0x1, // field 2 in submessage (value), delimited, length 1
-          0x61       // ASCII 'a'
+        0x0a, 0x6,  // field 1 (map_string_string), delimited, length 6
+        0x0a, 0x1,  // field 1 in submessage (key), delimited, length 1
+        0x41,       // ASCII 'A'
+        0x12, 0x1,  // field 2 in submessage (value), delimited, length 1
+        0x61        // ASCII 'a'
       ];
       assertEquals(serialized.length, expectedSerialized.length);
       for (var i = 0; i < serialized.length; i++) {
@@ -267,11 +250,7 @@
    */
   it('testLazyMapSync' + suffix, function() {
     // Start with a JSPB array containing a few map entries.
-    var entries = [
-        ['a', 'entry 1'],
-        ['c', 'entry 2'],
-        ['b', 'entry 3']
-    ];
+    var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']];
     var msg = new msgInfo.constructor([entries]);
     assertEquals(entries.length, 3);
     assertEquals(entries[0][0], 'a');
@@ -279,9 +258,9 @@
     assertEquals(entries[2][0], 'b');
     msg.getMapStringStringMap().del('a');
     assertEquals(entries.length, 3);  // not yet sync'd
-    msg.toArray();                // force a sync
+    msg.toArray();                    // force a sync
     assertEquals(entries.length, 2);
-    assertEquals(entries[0][0], 'b'); // now in sorted order
+    assertEquals(entries[0][0], 'b');  // now in sorted order
     assertEquals(entries[1][0], 'c');
 
     var a = msg.toArray();
@@ -290,12 +269,16 @@
 }
 
 describe('mapsTest', function() {
-  makeTests({
-    constructor: proto.jspb.test.TestMapFields,
-    deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
-  }, proto.jspb.test.MapValueMessage, "_Binary");
-  makeTests({
-    constructor: proto.jspb.test.TestMapFieldsNoBinary,
-    deserializeBinary: null
-  }, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary");
+  makeTests(
+      {
+        constructor: proto.jspb.test.TestMapFields,
+        deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
+      },
+      proto.jspb.test.MapValueMessage, '_Binary');
+  makeTests(
+      {
+        constructor: proto.jspb.test.TestMapFieldsNoBinary,
+        deserializeBinary: null
+      },
+      proto.jspb.test.MapValueMessageNoBinary, '_NoBinary');
 });
diff --git a/js/compatibility_tests/v3.1.0/message_test.js b/js/compatibility_tests/v3.1.0/message_test.js
index 80a1c52..9830a02 100644
--- a/js/compatibility_tests/v3.1.0/message_test.js
+++ b/js/compatibility_tests/v3.1.0/message_test.js
@@ -67,7 +67,6 @@
 goog.require('proto.jspb.test.Simple2');
 goog.require('proto.jspb.test.SpecialCases');
 goog.require('proto.jspb.test.TestClone');
-goog.require('proto.jspb.test.TestEndsWithBytes');
 goog.require('proto.jspb.test.TestGroup');
 goog.require('proto.jspb.test.TestGroup1');
 goog.require('proto.jspb.test.TestMessageWithOneof');
@@ -77,7 +76,7 @@
 // CommonJS-LoadFromFile: test2_pb proto.jspb.test
 goog.require('proto.jspb.test.ExtensionMessage');
 goog.require('proto.jspb.test.TestExtensionsMessage');
-
+goog.require('proto.jspb.test.simple1');
 
 
 
@@ -102,59 +101,59 @@
   });
 
   it('testComplexConversion', function() {
-    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, true];
-    var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, true];
+    var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true];
+    var data2 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true];
     var foo = new proto.jspb.test.Complex(data1);
     var bar = new proto.jspb.test.Complex(data2);
     var result = foo.toObject();
-    assertObjectEquals({
-      aString: 'a',
-      anOutOfOrderBool: true,
-      aNestedMessage: {
-        anInt: 11
-      },
-      aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
-      aRepeatedStringList: ['s1', 's2']
-    }, result);
+    assertObjectEquals(
+        {
+          aString: 'a',
+          anOutOfOrderBool: true,
+          aNestedMessage: {anInt: 11},
+          aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
+          aRepeatedStringList: ['s1', 's2']
+        },
+        result);
 
     // Now test with the jspb instances included.
     result = foo.toObject(true /* opt_includeInstance */);
-    assertObjectEquals({
-      aString: 'a',
-      anOutOfOrderBool: true,
-      aNestedMessage: {
-        anInt: 11,
-        $jspbMessageInstance: foo.getANestedMessage()
-      },
-      aRepeatedMessageList: [
-        {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
-        {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
-      ],
-      aRepeatedStringList: ['s1', 's2'],
-      $jspbMessageInstance: foo
-    }, result);
-
+    assertObjectEquals(
+        {
+          aString: 'a',
+          anOutOfOrderBool: true,
+          aNestedMessage:
+              {anInt: 11, $jspbMessageInstance: foo.getANestedMessage()},
+          aRepeatedMessageList: [
+            {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
+            {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
+          ],
+          aRepeatedStringList: ['s1', 's2'],
+          $jspbMessageInstance: foo
+        },
+        result);
   });
 
   it('testMissingFields', function() {
     var foo = new proto.jspb.test.Complex([
-        undefined, undefined, undefined, [],
-        undefined, undefined, undefined, undefined]);
+      undefined, undefined, undefined, [], undefined, undefined, undefined,
+      undefined
+    ]);
     var bar = new proto.jspb.test.Complex([
-        undefined, undefined, undefined, [],
-        undefined, undefined, undefined, undefined]);
+      undefined, undefined, undefined, [], undefined, undefined, undefined,
+      undefined
+    ]);
     var result = foo.toObject();
-    assertObjectEquals({
-      aString: undefined,
-      anOutOfOrderBool: undefined,
-      aNestedMessage: {
-        anInt: undefined
-      },
-      // Note: JsPb converts undefined repeated fields to empty arrays.
-      aRepeatedMessageList: [],
-      aRepeatedStringList: []
-    }, result);
-
+    assertObjectEquals(
+        {
+          aString: undefined,
+          anOutOfOrderBool: undefined,
+          aNestedMessage: {anInt: undefined},
+          // Note: JsPb converts undefined repeated fields to empty arrays.
+          aRepeatedMessageList: [],
+          aRepeatedStringList: []
+        },
+        result);
   });
 
   it('testNestedComplexMessage', function() {
@@ -167,20 +166,21 @@
   it('testSpecialCases', function() {
     // Note: Some property names are reserved in JavaScript.
     // These names are converted to the Js property named pb_<reserved_name>.
-    var special =
-        new proto.jspb.test.SpecialCases(['normal', 'default', 'function',
-        'var']);
+    var special = new proto.jspb.test.SpecialCases(
+        ['normal', 'default', 'function', 'var']);
     var result = special.toObject();
-    assertObjectEquals({
-      normal: 'normal',
-      pb_default: 'default',
-      pb_function: 'function',
-      pb_var: 'var'
-    }, result);
+    assertObjectEquals(
+        {
+          normal: 'normal',
+          pb_default: 'default',
+          pb_function: 'function',
+          pb_var: 'var'
+        },
+        result);
   });
 
   it('testDefaultValues', function() {
-    var defaultString = "default<>\'\"abc";
+    var defaultString = 'default<>\'"abc';
     var response = new proto.jspb.test.DefaultValues();
 
     // Test toObject
@@ -244,8 +244,10 @@
 
     // Test that clearing the values reverts them to the default state.
     response = makeDefault(['blah', false, 111, 77]);
-    response.clearStringField(); response.clearBoolField();
-    response.clearIntField(); response.clearEnumField();
+    response.clearStringField();
+    response.clearBoolField();
+    response.clearIntField();
+    response.clearEnumField();
     assertEquals(defaultString, response.getStringField());
     assertEquals(true, response.getBoolField());
     assertEquals(11, response.getIntField());
@@ -257,8 +259,10 @@
 
     // Test that setFoo(null) clears the values.
     response = makeDefault(['blah', false, 111, 77]);
-    response.setStringField(null); response.setBoolField(null);
-    response.setIntField(undefined); response.setEnumField(undefined);
+    response.setStringField(null);
+    response.setBoolField(null);
+    response.setIntField(undefined);
+    response.setEnumField(undefined);
     assertEquals(defaultString, response.getStringField());
     assertEquals(true, response.getBoolField());
     assertEquals(11, response.getIntField());
@@ -288,15 +292,15 @@
     // but we actually get a sparse array instead. We could use something
     // like [1,undefined,2] to avoid this, except that this is still
     // sparse on IE. No comment...
-    var expected = [,,, [], []];
+    var expected = [, , , [], []];
     expected[0] = expected[1] = expected[2] = undefined;
     assertObjectEquals(expected, foo.toArray());
   });
 
   it('testDifferenceRawObject', /** @suppress {visibility} */ function() {
     var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]);
-    var p2 = new proto.jspb.test.HasExtensions(['hi', 'what',
-                                               {1000: 'unique'}]);
+    var p2 =
+        new proto.jspb.test.HasExtensions(['hi', 'what', {1000: 'unique'}]);
     var diff = /** @type {proto.jspb.test.HasExtensions} */
         (jspb.Message.difference(p1, p2));
     assertEquals('', diff.getStr1());
@@ -310,13 +314,13 @@
     assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi'])));
     assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye'])));
     var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]);
-    assertTrue(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['hi', ['hello']])));
-    assertTrue(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['hi', ['hello', undefined,
-                                            undefined, undefined]])));
-    assertFalse(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['no', ['hello']])));
+    assertTrue(jspb.Message.equals(
+        s1b, new proto.jspb.test.Simple1(['hi', ['hello']])));
+    assertTrue(jspb.Message.equals(s1b, new proto.jspb.test.Simple1([
+      'hi', ['hello', undefined, undefined, undefined]
+    ])));
+    assertFalse(jspb.Message.equals(
+        s1b, new proto.jspb.test.Simple1(['no', ['hello']])));
     // Test with messages of different types
     var s2 = new proto.jspb.test.Simple2(['hi']);
     assertFalse(jspb.Message.equals(s1, s2));
@@ -324,18 +328,18 @@
 
   it('testEquals_softComparison', function() {
     var s1 = new proto.jspb.test.Simple1(['hi', [], null]);
-    assertTrue(jspb.Message.equals(s1,
-        new proto.jspb.test.Simple1(['hi', []])));
+    assertTrue(
+        jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi', []])));
 
     var s1b = new proto.jspb.test.Simple1(['hi', [], true]);
-    assertTrue(jspb.Message.equals(s1b,
-        new proto.jspb.test.Simple1(['hi', [], 1])));
+    assertTrue(
+        jspb.Message.equals(s1b, new proto.jspb.test.Simple1(['hi', [], 1])));
   });
 
   it('testEqualsComplex', function() {
-    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
-    var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1];
-    var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1];
+    var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1];
+    var data2 = ['a', , , [, 11], [[, 22], [, 34]], , ['s1', 's2'], , 1];
+    var data3 = ['a', , , [, 11], [[, 22]], , ['s1', 's2'], , 1];
     var data4 = ['hi'];
     var c1a = new proto.jspb.test.Complex(data1);
     var c1b = new proto.jspb.test.Complex(data1);
@@ -352,42 +356,34 @@
   it('testEqualsExtensionsConstructed', function() {
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions([]),
-        new proto.jspb.test.HasExtensions([{}])
-    ));
+        new proto.jspb.test.HasExtensions([{}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])));
     assertFalse(jspb.Message.equals(
         new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
-        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
         new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}])));
     assertTrue(jspb.Message.equals(
-        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]),
-        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
-    ));
+        new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])));
   });
 
   it('testEqualsExtensionsUnconstructed', function() {
     assertTrue(jspb.Message.compareFields([], [{}]));
-    assertTrue(jspb.Message.compareFields([,,, {}], []));
-    assertTrue(jspb.Message.compareFields([,,, {}], [,, {}]));
+    assertTrue(jspb.Message.compareFields([, , , {}], []));
+    assertTrue(jspb.Message.compareFields([, , , {}], [, , {}]));
     assertTrue(jspb.Message.compareFields(
         ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
     assertFalse(jspb.Message.compareFields(
@@ -395,25 +391,25 @@
     assertTrue(jspb.Message.compareFields(
         [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}]));
+        [{100: [{200: 'a'}]}], [, , , {100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+        [, , , {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}]));
+        ['hi', {100: [{200: 'a'}]}], ['hi', , , {100: [{200: 'a'}]}]));
     assertTrue(jspb.Message.compareFields(
-        ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+        ['hi', , , {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
   });
 
   it('testToMap', function() {
     var p1 = new proto.jspb.test.Simple1(['k', ['v']]);
     var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]);
-    var soymap = jspb.Message.toMap([p1, p2],
-        proto.jspb.test.Simple1.prototype.getAString,
+    var soymap = jspb.Message.toMap(
+        [p1, p2], proto.jspb.test.Simple1.prototype.getAString,
         proto.jspb.test.Simple1.prototype.toObject);
     assertEquals('k', soymap['k'].aString);
     assertArrayEquals(['v'], soymap['k'].aRepeatedStringList);
-    var protomap = jspb.Message.toMap([p1, p2],
-        proto.jspb.test.Simple1.prototype.getAString);
+    var protomap = jspb.Message.toMap(
+        [p1, p2], proto.jspb.test.Simple1.prototype.getAString);
     assertEquals('k', protomap['k'].getAString());
     assertArrayEquals(['v'], protomap['k'].getARepeatedStringList());
   });
@@ -434,8 +430,12 @@
     extension.setExt('e1');
     original.setExtension(proto.jspb.test.IsExtension.extField, extension);
     var clone = original.clone();
-    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
-      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+    assertArrayEquals(
+        [
+          'v1', , ['x1', ['y1', 'z1']], ,
+          [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, ,
+          {100: [, 'e1']}
+        ],
         clone.toArray());
     clone.setStr('v2');
     var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]);
@@ -452,11 +452,19 @@
     var newExtension = new proto.jspb.test.CloneExtension();
     newExtension.setExt('e2');
     clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension);
-    assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],,
-      [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }],
+    assertArrayEquals(
+        [
+          'v2', , ['a1', ['b1', 'c1']], ,
+          [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2, ,
+          {100: [, 'e2']}
+        ],
         clone.toArray());
-    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
-      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+    assertArrayEquals(
+        [
+          'v1', , ['x1', ['y1', 'z1']], ,
+          [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, ,
+          {100: [, 'e1']}
+        ],
         original.toArray());
   });
 
@@ -488,11 +496,12 @@
     jspb.Message.copyInto(original, dest);
     assertArrayEquals(original.toArray(), dest.toArray());
     assertEquals('x1', dest.getSimple1().getAString());
-    assertEquals('e1',
+    assertEquals(
+        'e1',
         dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt());
     dest.getSimple1().setAString('new value');
-    assertNotEquals(dest.getSimple1().getAString(),
-        original.getSimple1().getAString());
+    assertNotEquals(
+        dest.getSimple1().getAString(), original.getSimple1().getAString());
     if (supportsUint8Array) {
       dest.getBytesField()[0] = 7;
       assertObjectEquals(bytes1, original.getBytesField());
@@ -502,12 +511,12 @@
       assertObjectEquals(bytes1, original.getBytesField());
       assertObjectEquals('789', dest.getBytesField());
     }
-    dest.getExtension(proto.jspb.test.CloneExtension.extField).
-        setExt('new value');
+    dest.getExtension(proto.jspb.test.CloneExtension.extField)
+        .setExt('new value');
     assertNotEquals(
         dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(),
-        original.getExtension(
-            proto.jspb.test.CloneExtension.extField).getExt());
+        original.getExtension(proto.jspb.test.CloneExtension.extField)
+            .getExt());
   });
 
   it('testCopyInto_notSameType', function() {
@@ -525,26 +534,32 @@
     var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
     var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
     extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
-    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
-                            extension2);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.simple, extension2);
     extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
-    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
-        ['a', 'b']);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']);
     var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
     var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]);
     extendable.setExtension(
-        proto.jspb.test.IndirectExtension.repeatedSimpleList,
-        [s1, s2]);
-    assertObjectEquals(extension1,
+        proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]);
+    assertObjectEquals(
+        extension1,
         extendable.getExtension(proto.jspb.test.IsExtension.extField));
-    assertObjectEquals(extension2,
+    assertObjectEquals(
+        extension2,
         extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
-    assertObjectEquals('xyzzy',
+    assertObjectEquals(
+        'xyzzy',
         extendable.getExtension(proto.jspb.test.IndirectExtension.str));
-    assertObjectEquals(['a', 'b'], extendable.getExtension(
-        proto.jspb.test.IndirectExtension.repeatedStrList));
-    assertObjectEquals([s1, s2], extendable.getExtension(
-        proto.jspb.test.IndirectExtension.repeatedSimpleList));
+    assertObjectEquals(
+        ['a', 'b'],
+        extendable.getExtension(
+            proto.jspb.test.IndirectExtension.repeatedStrList));
+    assertObjectEquals(
+        [s1, s2],
+        extendable.getExtension(
+            proto.jspb.test.IndirectExtension.repeatedSimpleList));
     // Not supported yet, but it should work...
     extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null);
     assertNull(
@@ -563,18 +578,18 @@
     var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
     var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
     extendable.setExtension(proto.jspb.test.simple1, extension);
-    assertObjectEquals(extension,
-        extendable.getExtension(proto.jspb.test.simple1));
+    assertObjectEquals(
+        extension, extendable.getExtension(proto.jspb.test.simple1));
 
     // From _lib mode.
     extension = new proto.jspb.test.ExtensionMessage(['s1']);
     extendable = new proto.jspb.test.TestExtensionsMessage([16]);
     extendable.setExtension(proto.jspb.test.floatingMsgField, extension);
     extendable.setExtension(proto.jspb.test.floatingStrField, 's2');
-    assertObjectEquals(extension,
-        extendable.getExtension(proto.jspb.test.floatingMsgField));
-    assertObjectEquals('s2',
-        extendable.getExtension(proto.jspb.test.floatingStrField));
+    assertObjectEquals(
+        extension, extendable.getExtension(proto.jspb.test.floatingMsgField));
+    assertObjectEquals(
+        's2', extendable.getExtension(proto.jspb.test.floatingStrField));
     assertNotUndefined(proto.jspb.exttest.floatingMsgField);
     assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo);
     assertNotUndefined(proto.jspb.exttest.beta.floatingStrField);
@@ -585,60 +600,72 @@
     var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]);
     var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
     extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
-    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
-                            extension2);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.simple, extension2);
     extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
-    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
-        ['a', 'b']);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']);
     var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]);
     var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]);
     extendable.setExtension(
-        proto.jspb.test.IndirectExtension.repeatedSimpleList,
-        [s1, s2]);
-    assertObjectEquals({
-      str1: 'v1', str2: 'v2', str3: 'v3',
-      extField: { ext1: 'ext1field' },
-      simple: {
-        aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true
-      },
-      str: 'xyzzy',
-      repeatedStrList: ['a', 'b'],
-      repeatedSimpleList: [
-        { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
-        { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
-      ]
-    }, extendable.toObject());
+        proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]);
+    assertObjectEquals(
+        {
+          str1: 'v1',
+          str2: 'v2',
+          str3: 'v3',
+          extField: {ext1: 'ext1field'},
+          simple: {
+            aString: 'str',
+            aRepeatedStringList: ['s1', 's2'],
+            aBoolean: true
+          },
+          str: 'xyzzy',
+          repeatedStrList: ['a', 'b'],
+          repeatedSimpleList: [
+            {aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
+            {aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
+          ]
+        },
+        extendable.toObject());
 
     // Now, with instances included.
-    assertObjectEquals({
-      str1: 'v1', str2: 'v2', str3: 'v3',
-      extField: {
-        ext1: 'ext1field',
-        $jspbMessageInstance:
-            extendable.getExtension(proto.jspb.test.IsExtension.extField)
-      },
-      simple: {
-        aString: 'str',
-        aRepeatedStringList: ['s1', 's2'],
-        aBoolean: true,
-        $jspbMessageInstance:
-            extendable.getExtension(proto.jspb.test.IndirectExtension.simple)
-      },
-      str: 'xyzzy',
-      repeatedStrList: ['a', 'b'],
-      repeatedSimpleList: [{
-        aString: 'foo',
-        aRepeatedStringList: ['s1', 's2'],
-        aBoolean: true,
-        $jspbMessageInstance: s1
-      }, {
-        aString: 'bar',
-        aRepeatedStringList: ['t1', 't2'],
-        aBoolean: false,
-        $jspbMessageInstance: s2
-      }],
-      $jspbMessageInstance: extendable
-    }, extendable.toObject(true /* opt_includeInstance */));
+    assertObjectEquals(
+        {
+          str1: 'v1',
+          str2: 'v2',
+          str3: 'v3',
+          extField: {
+            ext1: 'ext1field',
+            $jspbMessageInstance:
+                extendable.getExtension(proto.jspb.test.IsExtension.extField)
+          },
+          simple: {
+            aString: 'str',
+            aRepeatedStringList: ['s1', 's2'],
+            aBoolean: true,
+            $jspbMessageInstance: extendable.getExtension(
+                proto.jspb.test.IndirectExtension.simple)
+          },
+          str: 'xyzzy',
+          repeatedStrList: ['a', 'b'],
+          repeatedSimpleList: [
+            {
+              aString: 'foo',
+              aRepeatedStringList: ['s1', 's2'],
+              aBoolean: true,
+              $jspbMessageInstance: s1
+            },
+            {
+              aString: 'bar',
+              aRepeatedStringList: ['t1', 't2'],
+              aBoolean: false,
+              $jspbMessageInstance: s2
+            }
+          ],
+          $jspbMessageInstance: extendable
+        },
+        extendable.toObject(true /* opt_includeInstance */));
   });
 
   it('testInitialization_emptyArray', function() {
@@ -690,8 +717,7 @@
     var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']);
     data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage);
     var obj = data.toObject();
-    assertNotNull(
-        data.getExtension(proto.jspb.test.IsExtension.extField));
+    assertNotNull(data.getExtension(proto.jspb.test.IsExtension.extField));
     assertEquals('is_extension', obj.extField.ext1);
   });
 
@@ -708,16 +734,18 @@
     var groups = group.getRepeatedGroupList();
     assertEquals('g1', groups[0].getId());
     assertObjectEquals([true, false], groups[0].getSomeBoolList());
-    assertObjectEquals({id: 'g1', someBoolList: [true, false]},
-        groups[0].toObject());
-    assertObjectEquals({
-      repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
-      requiredGroup: {id: undefined},
-      optionalGroup: undefined,
-      requiredSimple: {aRepeatedStringList: [], aString: undefined},
-      optionalSimple: undefined,
-      id: undefined
-    }, group.toObject());
+    assertObjectEquals(
+        {id: 'g1', someBoolList: [true, false]}, groups[0].toObject());
+    assertObjectEquals(
+        {
+          repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
+          requiredGroup: {id: undefined},
+          optionalGroup: undefined,
+          requiredSimple: {aRepeatedStringList: [], aString: undefined},
+          optionalSimple: undefined,
+          id: undefined
+        },
+        group.toObject());
     var group1 = new proto.jspb.test.TestGroup1();
     group1.setGroup(someGroup);
     assertEquals(someGroup, group1.getGroup());
@@ -734,25 +762,26 @@
     message.setExtension$(11);
     message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12);
     assertEquals(11, message.getExtension$());
-    assertEquals(12, message.getExtension(
-        proto.jspb.test.TestReservedNamesExtension.foo));
+    assertEquals(
+        12,
+        message.getExtension(proto.jspb.test.TestReservedNamesExtension.foo));
     assertObjectEquals({extension: 11, foo: 12}, message.toObject());
   });
 
   it('testInitializeMessageWithUnsetOneof', function() {
     var message = new proto.jspb.test.TestMessageWithOneof([]);
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
-            PARTIAL_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase
+            .PARTIAL_ONEOF_NOT_SET,
         message.getPartialOneofCase());
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
-            RECURSIVE_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase
+            .RECURSIVE_ONEOF_NOT_SET,
         message.getRecursiveOneofCase());
   });
 
   it('testInitializeMessageWithSingleValueSetInOneof', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']);
+    var message = new proto.jspb.test.TestMessageWithOneof([, , 'x']);
 
     assertEquals('x', message.getPone());
     assertEquals('', message.getPthree());
@@ -762,7 +791,7 @@
   });
 
   it('testKeepsLastWireValueSetInUnion_multipleValues', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']);
+    var message = new proto.jspb.test.TestMessageWithOneof([, , 'x', , 'y']);
 
     assertEquals('', message.getPone());
     assertEquals('y', message.getPthree());
@@ -819,8 +848,8 @@
   it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
     var message = new proto.jspb.test.TestMessageWithOneof;
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
-            PARTIAL_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase
+            .PARTIAL_ONEOF_NOT_SET,
         message.getPartialOneofCase());
 
     message.setPone('hi');
@@ -830,8 +859,8 @@
 
     message.clearPone();
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
-            PARTIAL_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase
+            .PARTIAL_ONEOF_NOT_SET,
         message.getPartialOneofCase());
   });
 
@@ -934,39 +963,39 @@
   });
 
   it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField',
-      function() {
-        var message;
+     function() {
+       var message;
 
-        message =
-            new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567));
-        assertEquals(567, message.getBone());
-        assertEquals(1234, message.getBtwo());
-        assertEquals(
-            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
-            message.getDefaultOneofBCase());
+       message =
+           new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567));
+       assertEquals(567, message.getBone());
+       assertEquals(1234, message.getBtwo());
+       assertEquals(
+           proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
+           message.getDefaultOneofBCase());
 
-        message =
-            new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
-        assertEquals(0, message.getBone());
-        assertEquals(890, message.getBtwo());
-        assertEquals(
-            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
-            message.getDefaultOneofBCase());
+       message =
+           new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
+       assertEquals(0, message.getBone());
+       assertEquals(890, message.getBtwo());
+       assertEquals(
+           proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+           message.getDefaultOneofBCase());
 
-        message = new proto.jspb.test.TestMessageWithOneof(
-            new Array(11).concat(567, 890));
-        assertEquals(0, message.getBone());
-        assertEquals(890, message.getBtwo());
-        assertEquals(
-            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
-            message.getDefaultOneofBCase());
-      });
+       message = new proto.jspb.test.TestMessageWithOneof(
+           new Array(11).concat(567, 890));
+       assertEquals(0, message.getBone());
+       assertEquals(890, message.getBtwo());
+       assertEquals(
+           proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+           message.getDefaultOneofBCase());
+     });
 
   it('testOneofContainingAnotherMessage', function() {
     var message = new proto.jspb.test.TestMessageWithOneof;
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
-            RECURSIVE_ONEOF_NOT_SET,
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase
+            .RECURSIVE_ONEOF_NOT_SET,
         message.getRecursiveOneofCase());
 
     var other = new proto.jspb.test.TestMessageWithOneof;
@@ -987,25 +1016,25 @@
 
   it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray',
      function() {
-    var message = new proto.jspb.test.TestMessageWithOneof;
-    message.setPone('x');
-    assertEquals('x', message.getPone());
-    assertEquals('', message.getPthree());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
-        message.getPartialOneofCase());
+       var message = new proto.jspb.test.TestMessageWithOneof;
+       message.setPone('x');
+       assertEquals('x', message.getPone());
+       assertEquals('', message.getPthree());
+       assertEquals(
+           proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+           message.getPartialOneofCase());
 
-    var array = message.toArray();
-    assertEquals('x', array[2]);
-    assertUndefined(array[4]);
-    array[4] = 'y';
+       var array = message.toArray();
+       assertEquals('x', array[2]);
+       assertUndefined(array[4]);
+       array[4] = 'y';
 
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
-        message.getPartialOneofCase());
-    assertUndefined(array[2]);
-    assertEquals('y', array[4]);
-  });
+       assertEquals(
+           proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
+           message.getPartialOneofCase());
+       assertUndefined(array[2]);
+       assertEquals('y', array[4]);
+     });
 
   it('testFloatingPointFieldsSupportNan', function() {
     var assertNan = function(x) {
@@ -1015,8 +1044,7 @@
     };
 
     var message = new proto.jspb.test.FloatingPointFields([
-      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN',
-      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
     ]);
     assertNan(message.getOptionalFloatField());
     assertNan(message.getRequiredFloatField());
@@ -1029,5 +1057,4 @@
     assertNan(message.getRepeatedDoubleFieldList()[1]);
     assertNan(message.getDefaultDoubleField());
   });
-
 });
diff --git a/js/experimental/runtime/internal/checks.js b/js/experimental/runtime/internal/checks.js
index 369c6af..3d1af54 100644
--- a/js/experimental/runtime/internal/checks.js
+++ b/js/experimental/runtime/internal/checks.js
@@ -2,7 +2,7 @@
  * @fileoverview Proto internal runtime checks.
  *
  * Checks are grouped into different severity, see:
- * http://g3doc/javascript/protobuf/README.md#configurable-check-support-in-protocol-buffers
+ * http://g3doc/third_party/protobuf/javascript/README.md#configurable-check-support-in-protocol-buffers
  *
  * Checks are also grouped into different sections:
  *   - CHECK_BOUNDS:
@@ -23,7 +23,7 @@
 
 //
 // See
-// http://g3doc/javascript/protobuf/README.md#configurable-check-support-in-protocol-buffers
+// http://g3doc/third_party/protobuf/javascript/README.md#configurable-check-support-in-protocol-buffers
 //
 /** @define{string} */
 const CHECK_LEVEL_DEFINE = goog.define('protobuf.defines.CHECK_LEVEL', '');
diff --git a/js/experimental/runtime/kernel/conformance/conformance_testee.js b/js/experimental/runtime/kernel/conformance/conformance_testee.js
old mode 100644
new mode 100755
diff --git a/js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js b/js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js
old mode 100644
new mode 100755
diff --git a/js/experimental/runtime/kernel/indexer.js b/js/experimental/runtime/kernel/indexer.js
index d4dea13..205a34e 100644
--- a/js/experimental/runtime/kernel/indexer.js
+++ b/js/experimental/runtime/kernel/indexer.js
@@ -8,7 +8,8 @@
 const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
 const WireType = goog.require('protobuf.binary.WireType');
 const {Field} = goog.require('protobuf.binary.field');
-const {checkCriticalElementIndex, checkCriticalState} = goog.require('protobuf.internal.checks');
+const {checkCriticalState} = goog.require('protobuf.internal.checks');
+const {skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag');
 
 /**
  * Appends a new entry in the index array for the given field number.
@@ -27,26 +28,6 @@
 }
 
 /**
- * Returns wire type stored in a tag.
- * Protos store the wire type as the first 3 bit of a tag.
- * @param {number} tag
- * @return {!WireType}
- */
-function tagToWireType(tag) {
-  return /** @type {!WireType} */ (tag & 0x07);
-}
-
-/**
- * Returns the field number stored in a tag.
- * Protos store the field number in the upper 29 bits of a 32 bit number.
- * @param {number} tag
- * @return {number}
- */
-function tagToFieldNumber(tag) {
-  return tag >>> 3;
-}
-
-/**
  * Creates an index of field locations in a given binary protobuf.
  * @param {!BufferDecoder} bufferDecoder
  * @param {number|undefined} pivot
@@ -62,83 +43,13 @@
     const wireType = tagToWireType(tag);
     const fieldNumber = tagToFieldNumber(tag);
     checkCriticalState(fieldNumber > 0, `Invalid field number ${fieldNumber}`);
-
     addIndexEntry(storage, fieldNumber, wireType, bufferDecoder.cursor());
-
-    checkCriticalState(
-        !skipField_(bufferDecoder, wireType, fieldNumber),
-        'Found unmatched stop group.');
+    skipField(bufferDecoder, wireType, fieldNumber);
   }
   return storage;
 }
 
-/**
- * Skips over fields until the next field of the message.
- * @param {!BufferDecoder} bufferDecoder
- * @param {!WireType} wireType
- * @param {number} fieldNumber
- * @return {boolean} Whether the field we skipped over was a stop group.
- * @private
- */
-function skipField_(bufferDecoder, wireType, fieldNumber) {
-  switch (wireType) {
-    case WireType.VARINT:
-      checkCriticalElementIndex(
-          bufferDecoder.cursor(), bufferDecoder.endIndex());
-      bufferDecoder.skipVarint();
-      return false;
-    case WireType.FIXED64:
-      bufferDecoder.skip(8);
-      return false;
-    case WireType.DELIMITED:
-      checkCriticalElementIndex(
-          bufferDecoder.cursor(), bufferDecoder.endIndex());
-      const length = bufferDecoder.getUnsignedVarint32();
-      bufferDecoder.skip(length);
-      return false;
-    case WireType.START_GROUP:
-      checkCriticalState(
-          skipGroup_(bufferDecoder, fieldNumber), 'No end group found.');
-      return false;
-    case WireType.END_GROUP:
-      // Signal that we found a stop group to the caller
-      return true;
-    case WireType.FIXED32:
-      bufferDecoder.skip(4);
-      return false;
-    default:
-      throw new Error(`Invalid wire type: ${wireType}`);
-  }
-}
-
-/**
- * Skips over fields until it finds the end of a given group.
- * @param {!BufferDecoder} bufferDecoder
- * @param {number} groupFieldNumber
- * @return {boolean} Returns true if an end was found.
- * @private
- */
-function skipGroup_(bufferDecoder, groupFieldNumber) {
-  // On a start group we need to keep skipping fields until we find a
-  // corresponding stop group
-  // Note: Since we are calling skipField from here nested groups will be
-  // handled by recursion of this method and thus we will not see a nested
-  // STOP GROUP here unless there is something wrong with the input data.
-  while (bufferDecoder.hasNext()) {
-    const tag = bufferDecoder.getUnsignedVarint32();
-    const wireType = tagToWireType(tag);
-    const fieldNumber = tagToFieldNumber(tag);
-
-    if (skipField_(bufferDecoder, wireType, fieldNumber)) {
-      checkCriticalState(
-          groupFieldNumber === fieldNumber,
-          `Expected stop group for fieldnumber ${groupFieldNumber} not found.`);
-      return true;
-    }
-  }
-  return false;
-}
-
 exports = {
   buildIndex,
+  tagToWireType,
 };
diff --git a/js/experimental/runtime/kernel/indexer_test.js b/js/experimental/runtime/kernel/indexer_test.js
index 101e442..ffb8807 100644
--- a/js/experimental/runtime/kernel/indexer_test.js
+++ b/js/experimental/runtime/kernel/indexer_test.js
@@ -72,12 +72,12 @@
 
   it('fail for invalid wire type (6)', () => {
     expect(() => buildIndex(createBufferDecoder(0x0E, 0x01), PIVOT))
-        .toThrowError('Invalid wire type: 6');
+        .toThrowError('Unexpected wire type: 6');
   });
 
   it('fail for invalid wire type (7)', () => {
     expect(() => buildIndex(createBufferDecoder(0x0F, 0x01), PIVOT))
-        .toThrowError('Invalid wire type: 7');
+        .toThrowError('Unexpected wire type: 7');
   });
 
   it('index varint', () => {
@@ -269,33 +269,8 @@
 
   it('fail on unmatched stop group', () => {
     const data = createBufferDecoder(0x0C, 0x01);
-    if (CHECK_CRITICAL_STATE) {
-      expect(() => buildIndex(data, PIVOT))
-          .toThrowError('Found unmatched stop group.');
-    } else {
-      // Note in unchecked mode we produce invalid output for invalid inputs.
-      // This test just documents our behavior in those cases.
-      // These values might change at any point and are not considered
-      // what the implementation should be doing here.
-      const storage = buildIndex(data, PIVOT);
-
-      expect(getStorageSize(storage)).toBe(1);
-      const entryArray = storage.get(1).getIndexArray();
-      expect(entryArray).not.toBeUndefined();
-      expect(entryArray.length).toBe(1);
-      const entry = entryArray[0];
-
-      expect(Field.getWireType(entry)).toBe(WireType.END_GROUP);
-      expect(Field.getStartIndex(entry)).toBe(1);
-
-      const entryArray2 = storage.get(0).getIndexArray();
-      expect(entryArray2).not.toBeUndefined();
-      expect(entryArray2.length).toBe(1);
-      const entry2 = entryArray2[0];
-
-      expect(Field.getWireType(entry2)).toBe(WireType.FIXED64);
-      expect(Field.getStartIndex(entry2)).toBe(2);
-    }
+    expect(() => buildIndex(data, PIVOT))
+        .toThrowError('Unexpected wire type: 4');
   });
 
   it('fail for groups without matching stop group', () => {
diff --git a/js/experimental/runtime/kernel/kernel.js b/js/experimental/runtime/kernel/kernel.js
index 2a2b2d8..bb26083 100644
--- a/js/experimental/runtime/kernel/kernel.js
+++ b/js/experimental/runtime/kernel/kernel.js
@@ -26,6 +26,7 @@
 const {CHECK_TYPE, checkCriticalElementIndex, checkCriticalState, checkCriticalType, checkCriticalTypeBool, checkCriticalTypeBoolArray, checkCriticalTypeByteString, checkCriticalTypeByteStringArray, checkCriticalTypeDouble, checkCriticalTypeDoubleArray, checkCriticalTypeFloat, checkCriticalTypeFloatIterable, checkCriticalTypeMessageArray, checkCriticalTypeSignedInt32, checkCriticalTypeSignedInt32Array, checkCriticalTypeSignedInt64, checkCriticalTypeSignedInt64Array, checkCriticalTypeString, checkCriticalTypeStringArray, checkCriticalTypeUnsignedInt32, checkCriticalTypeUnsignedInt32Array, checkDefAndNotNull, checkElementIndex, checkFieldNumber, checkFunctionExists, checkState, checkTypeDouble, checkTypeFloat, checkTypeSignedInt32, checkTypeSignedInt64, checkTypeUnsignedInt32} = goog.require('protobuf.internal.checks');
 const {Field, IndexEntry} = goog.require('protobuf.binary.field');
 const {buildIndex} = goog.require('protobuf.binary.indexer');
+const {createTag, get32BitVarintLength, getTagLength} = goog.require('protobuf.binary.tag');
 
 
 /**
@@ -140,6 +141,28 @@
 }
 
 /**
+ * Converts all entries of the index array to the template type using the given
+ * read function and return an Array containing those converted values. This is
+ * used to implement parsing repeated non-primitive fields.
+ * @param {!Array<!IndexEntry>} indexArray
+ * @param {!BufferDecoder} bufferDecoder
+ * @param {number} fieldNumber
+ * @param {function(!Kernel):T} instanceCreator
+ * @param {number=} pivot
+ * @return {!Array<T>}
+ * @template T
+ */
+function readRepeatedGroup(
+    indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot) {
+  const result = new Array(indexArray.length);
+  for (let i = 0; i < indexArray.length; i++) {
+    result[i] = doReadGroup(
+        bufferDecoder, indexArray[i], fieldNumber, instanceCreator, pivot);
+  }
+  return result;
+}
+
+/**
  * Creates a new bytes array to contain all data of a submessage.
  * When there are multiple entries, merge them together.
  * @param {!Array<!IndexEntry>} indexArray
@@ -194,6 +217,51 @@
 }
 
 /**
+ * Merges all index entries of the index array using the given read function.
+ * This is used to implement parsing singular group fields.
+ * @param {!Array<!IndexEntry>} indexArray
+ * @param {!BufferDecoder} bufferDecoder
+ * @param {number} fieldNumber
+ * @param {function(!Kernel):T} instanceCreator
+ * @param {number=} pivot
+ * @return {T}
+ * @template T
+ */
+function readGroup(
+    indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot) {
+  checkInstanceCreator(instanceCreator);
+  checkState(indexArray.length > 0);
+  return doReadGroup(
+      bufferDecoder, indexArray[indexArray.length - 1], fieldNumber,
+      instanceCreator, pivot);
+}
+
+/**
+ * Merges all index entries of the index array using the given read function.
+ * This is used to implement parsing singular message fields.
+ * @param {!BufferDecoder} bufferDecoder
+ * @param {!IndexEntry} indexEntry
+ * @param {number} fieldNumber
+ * @param {function(!Kernel):T} instanceCreator
+ * @param {number=} pivot
+ * @return {T}
+ * @template T
+ */
+function doReadGroup(
+    bufferDecoder, indexEntry, fieldNumber, instanceCreator, pivot) {
+  validateWireType(indexEntry, WireType.START_GROUP);
+  const fieldStartIndex = Field.getStartIndex(indexEntry);
+  const tag = createTag(WireType.START_GROUP, fieldNumber);
+  const groupTagLength = get32BitVarintLength(tag);
+  const groupLength = getTagLength(
+      bufferDecoder, fieldStartIndex, WireType.START_GROUP, fieldNumber);
+  const accessorBuffer = bufferDecoder.subBufferDecoder(
+      fieldStartIndex, groupLength - groupTagLength);
+  const kernel = Kernel.fromBufferDecoder_(accessorBuffer, pivot);
+  return instanceCreator(kernel);
+}
+
+/**
  * @param {!Writer} writer
  * @param {number} fieldNumber
  * @param {?InternalMessage} value
@@ -204,6 +272,18 @@
 }
 
 /**
+ * @param {!Writer} writer
+ * @param {number} fieldNumber
+ * @param {?InternalMessage} value
+ */
+function writeGroup(writer, fieldNumber, value) {
+  const kernel = checkDefAndNotNull(value).internalGetKernel();
+  writer.writeStartGroup(fieldNumber);
+  kernel.serializeToWriter(writer);
+  writer.writeEndGroup(fieldNumber);
+}
+
+/**
  * Writes the array of Messages into the writer for the given field number.
  * @param {!Writer} writer
  * @param {number} fieldNumber
@@ -216,6 +296,18 @@
 }
 
 /**
+ * Writes the array of Messages into the writer for the given field number.
+ * @param {!Writer} writer
+ * @param {number} fieldNumber
+ * @param {!Array<!InternalMessage>} values
+ */
+function writeRepeatedGroup(writer, fieldNumber, values) {
+  for (const value of values) {
+    writeGroup(writer, fieldNumber, value);
+  }
+}
+
+/**
  * Array.from has a weird type definition in google3/javascript/externs/es6.js
  * and wants the mapping function accept strings.
  * @const {function((string|number)): number}
@@ -406,7 +498,8 @@
           writer.writeTag(fieldNumber, Field.getWireType(indexEntry));
           writer.writeBufferDecoder(
               checkDefAndNotNull(this.bufferDecoder_),
-              Field.getStartIndex(indexEntry), Field.getWireType(indexEntry));
+              Field.getStartIndex(indexEntry), Field.getWireType(indexEntry),
+              fieldNumber);
         }
       }
     });
@@ -692,6 +785,28 @@
 
   /**
    * Returns data as a mutable proto Message for the given field number.
+   * If no value has been set, return null.
+   * If hasFieldNumber(fieldNumber) == false before calling, it remains false.
+   *
+   * This method should not be used along with getMessage, since calling
+   * getMessageOrNull after getMessage will not register the encoder.
+   *
+   * @param {number} fieldNumber
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {?T}
+   * @template T
+   */
+  getGroupOrNull(fieldNumber, instanceCreator, pivot = undefined) {
+    return this.getFieldWithDefault_(
+        fieldNumber, null,
+        (indexArray, bytes) =>
+            readGroup(indexArray, bytes, fieldNumber, instanceCreator, pivot),
+        writeGroup);
+  }
+
+  /**
+   * Returns data as a mutable proto Message for the given field number.
    * If no value has been set previously, creates and attaches an instance.
    * Postcondition: hasFieldNumber(fieldNumber) == true.
    *
@@ -715,6 +830,30 @@
   }
 
   /**
+   * Returns data as a mutable proto Message for the given field number.
+   * If no value has been set previously, creates and attaches an instance.
+   * Postcondition: hasFieldNumber(fieldNumber) == true.
+   *
+   * This method should not be used along with getMessage, since calling
+   * getMessageAttach after getMessage will not register the encoder.
+   *
+   * @param {number} fieldNumber
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {T}
+   * @template T
+   */
+  getGroupAttach(fieldNumber, instanceCreator, pivot = undefined) {
+    checkInstanceCreator(instanceCreator);
+    let instance = this.getGroupOrNull(fieldNumber, instanceCreator, pivot);
+    if (!instance) {
+      instance = instanceCreator(Kernel.createEmpty());
+      this.setField_(fieldNumber, instance, writeGroup);
+    }
+    return instance;
+  }
+
+  /**
    * Returns data as a proto Message for the given field number.
    * If no value has been set, return a default instance.
    * This default instance is guaranteed to be the same instance, unless this
@@ -745,6 +884,36 @@
   }
 
   /**
+   * Returns data as a proto Message for the given field number.
+   * If no value has been set, return a default instance.
+   * This default instance is guaranteed to be the same instance, unless this
+   * field is cleared.
+   * Does not register the encoder, so changes made to the returned
+   * sub-message will not be included when serializing the parent message.
+   * Use getMessageAttach() if the resulting sub-message should be mutable.
+   *
+   * This method should not be used along with getMessageOrNull or
+   * getMessageAttach, since these methods register the encoder.
+   *
+   * @param {number} fieldNumber
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {T}
+   * @template T
+   */
+  getGroup(fieldNumber, instanceCreator, pivot = undefined) {
+    checkInstanceCreator(instanceCreator);
+    const message = this.getFieldWithDefault_(
+        fieldNumber, null,
+        (indexArray, bytes) =>
+            readGroup(indexArray, bytes, fieldNumber, instanceCreator, pivot));
+    // Returns an empty message as the default value if the field doesn't exist.
+    // We don't pass the default value to getFieldWithDefault_ to reduce object
+    // allocation.
+    return message === null ? instanceCreator(Kernel.createEmpty()) : message;
+  }
+
+  /**
    * Returns the accessor for the given singular message, or returns null if
    * it hasn't been set.
    * @param {number} fieldNumber
@@ -1614,6 +1783,71 @@
         .length;
   }
 
+  /**
+   * Returns an Array instance containing boolean values for the given field
+   * number.
+   * @param {number} fieldNumber
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number|undefined} pivot
+   * @return {!Array<T>}
+   * @template T
+   * @private
+   */
+  getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot) {
+    return this.getFieldWithDefault_(
+        fieldNumber, [],
+        (indexArray, bufferDecoder) => readRepeatedGroup(
+            indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot),
+        writeRepeatedGroup);
+  }
+
+  /**
+   * Returns the element at index for the given field number as a group.
+   * @param {number} fieldNumber
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number} index
+   * @param {number=} pivot
+   * @return {T}
+   * @template T
+   */
+  getRepeatedGroupElement(
+      fieldNumber, instanceCreator, index, pivot = undefined) {
+    const array =
+        this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot);
+    checkCriticalElementIndex(index, array.length);
+    return array[index];
+  }
+
+  /**
+   * Returns an Iterable instance containing group values for the given field
+   * number.
+   * @param {number} fieldNumber
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {!Iterable<T>}
+   * @template T
+   */
+  getRepeatedGroupIterable(fieldNumber, instanceCreator, pivot = undefined) {
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedMessageArray_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(
+        this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot));
+  }
+
+  /**
+   * Returns the size of the repeated field.
+   * @param {number} fieldNumber
+   * @param {function(!Kernel):T} instanceCreator
+   * @return {number}
+   * @param {number=} pivot
+   * @template T
+   */
+  getRepeatedGroupSize(fieldNumber, instanceCreator, pivot = undefined) {
+    return this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot)
+        .length;
+  }
+
   /***************************************************************************
    *                        OPTIONAL SETTER METHODS
    ***************************************************************************/
@@ -1802,6 +2036,20 @@
   }
 
   /**
+   * Sets a proto Group to the field with the given field number.
+   * Instead of working with the Kernel inside of the message directly, we
+   * need the message instance to keep its reference equality for subsequent
+   * gettings.
+   * @param {number} fieldNumber
+   * @param {!InternalMessage} value
+   */
+  setGroup(fieldNumber, value) {
+    checkCriticalType(
+        value !== null, 'Given value is not a message instance: null');
+    this.setField_(fieldNumber, value, writeGroup);
+  }
+
+  /**
    * Sets a proto Message to the field with the given field number.
    * Instead of working with the Kernel inside of the message directly, we
    * need the message instance to keep its reference equality for subsequent
@@ -3806,6 +4054,69 @@
     this.addRepeatedMessageIterable(
         fieldNumber, [value], instanceCreator, pivot);
   }
+
+  // Groups
+  /**
+   * Sets all message values into the field for the given field number.
+   * @param {number} fieldNumber
+   * @param {!Iterable<!InternalMessage>} values
+   */
+  setRepeatedGroupIterable(fieldNumber, values) {
+    const /** !Array<!InternalMessage> */ array = Array.from(values);
+    checkCriticalTypeMessageArray(array);
+    this.setField_(fieldNumber, array, writeRepeatedGroup);
+  }
+
+  /**
+   * Adds all message values into the field for the given field number.
+   * @param {number} fieldNumber
+   * @param {!Iterable<!InternalMessage>} values
+   * @param {function(!Kernel):!InternalMessage} instanceCreator
+   * @param {number=} pivot
+   */
+  addRepeatedGroupIterable(
+      fieldNumber, values, instanceCreator, pivot = undefined) {
+    const array = [
+      ...this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot),
+      ...values,
+    ];
+    checkCriticalTypeMessageArray(array);
+    // Needs to set it back with the new array.
+    this.setField_(fieldNumber, array, writeRepeatedGroup);
+  }
+
+  /**
+   * Sets a single message value into the field for the given field number at
+   * the given index.
+   * @param {number} fieldNumber
+   * @param {!InternalMessage} value
+   * @param {function(!Kernel):!InternalMessage} instanceCreator
+   * @param {number} index
+   * @param {number=} pivot
+   * @throws {!Error} if index is out of range when check mode is critical
+   */
+  setRepeatedGroupElement(
+      fieldNumber, value, instanceCreator, index, pivot = undefined) {
+    checkInstanceCreator(instanceCreator);
+    checkCriticalType(
+        value !== null, 'Given value is not a message instance: null');
+    const array =
+        this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot);
+    checkCriticalElementIndex(index, array.length);
+    array[index] = value;
+  }
+
+  /**
+   * Adds a single message value into the field for the given field number.
+   * @param {number} fieldNumber
+   * @param {!InternalMessage} value
+   * @param {function(!Kernel):!InternalMessage} instanceCreator
+   * @param {number=} pivot
+   */
+  addRepeatedGroupElement(
+      fieldNumber, value, instanceCreator, pivot = undefined) {
+    this.addRepeatedGroupIterable(fieldNumber, [value], instanceCreator, pivot);
+  }
 }
 
 exports = Kernel;
diff --git a/js/experimental/runtime/kernel/kernel_repeated_test.js b/js/experimental/runtime/kernel/kernel_repeated_test.js
index 7741c35..6a798b6 100644
--- a/js/experimental/runtime/kernel/kernel_repeated_test.js
+++ b/js/experimental/runtime/kernel/kernel_repeated_test.js
@@ -7425,3 +7425,383 @@
     }
   });
 });
+
+describe('Kernel for repeated groups does', () => {
+  it('return empty array for the empty input', () => {
+    const accessor = Kernel.createEmpty();
+    expectEqualToArray(
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator), []);
+  });
+
+  it('ensure not the same instance returned for the empty input', () => {
+    const accessor = Kernel.createEmpty();
+    const list1 =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+    const list2 =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+    expect(list1).not.toBe(list2);
+  });
+
+  it('return size for the empty input', () => {
+    const accessor = Kernel.createEmpty();
+    expect(accessor.getRepeatedGroupSize(1, TestMessage.instanceCreator))
+        .toEqual(0);
+  });
+
+  it('return values from the input', () => {
+    const bytes1 = createArrayBuffer(0x08, 0x01);
+    const bytes2 = createArrayBuffer(0x08, 0x02);
+    const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1));
+    const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2));
+
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    expectEqualToMessageArray(
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator),
+        [msg1, msg2]);
+  });
+
+  it('ensure not the same array instance returned', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const list1 =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+    const list2 =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+    expect(list1).not.toBe(list2);
+  });
+
+  it('ensure the same array element returned for get iterable', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const list1 =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+    const list2 = accessor.getRepeatedGroupIterable(
+        1, TestMessage.instanceCreator, /* pivot= */ 0);
+    const array1 = Array.from(list1);
+    const array2 = Array.from(list2);
+    for (let i = 0; i < array1.length; i++) {
+      expect(array1[i]).toBe(array2[i]);
+    }
+  });
+
+  it('return accessors from the input', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const [accessor1, accessor2] =
+        [...accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator)];
+    expect(accessor1.getInt32WithDefault(1)).toEqual(1);
+    expect(accessor2.getInt32WithDefault(1)).toEqual(2);
+  });
+
+  it('return accessors from the input when pivot is set', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const [accessor1, accessor2] = [...accessor.getRepeatedGroupIterable(
+        1, TestMessage.instanceCreator, /* pivot= */ 0)];
+    expect(accessor1.getInt32WithDefault(1)).toEqual(1);
+    expect(accessor2.getInt32WithDefault(1)).toEqual(2);
+  });
+
+  it('return the repeated field element from the input', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const msg1 = accessor.getRepeatedGroupElement(
+        /* fieldNumber= */ 1, TestMessage.instanceCreator,
+        /* index= */ 0);
+    const msg2 = accessor.getRepeatedGroupElement(
+        /* fieldNumber= */ 1, TestMessage.instanceCreator,
+        /* index= */ 1, /* pivot= */ 0);
+    expect(msg1.getInt32WithDefault(
+               /* fieldNumber= */ 1, /* default= */ 0))
+        .toEqual(1);
+    expect(msg2.getInt32WithDefault(
+               /* fieldNumber= */ 1, /* default= */ 0))
+        .toEqual(2);
+  });
+
+  it('ensure the same array element returned', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const msg1 = accessor.getRepeatedGroupElement(
+        /* fieldNumber= */ 1, TestMessage.instanceCreator,
+        /* index= */ 0);
+    const msg2 = accessor.getRepeatedGroupElement(
+        /* fieldNumber= */ 1, TestMessage.instanceCreator,
+        /* index= */ 0);
+    expect(msg1).toBe(msg2);
+  });
+
+  it('return the size from the input', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    expect(accessor.getRepeatedGroupSize(1, TestMessage.instanceCreator))
+        .toEqual(2);
+  });
+
+  it('encode repeated message from the input', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    expect(accessor.serialize()).toEqual(bytes);
+  });
+
+  it('add a single value', () => {
+    const accessor = Kernel.createEmpty();
+    const bytes1 = createArrayBuffer(0x08, 0x01);
+    const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1));
+    const bytes2 = createArrayBuffer(0x08, 0x02);
+    const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2));
+
+    accessor.addRepeatedGroupElement(1, msg1, TestMessage.instanceCreator);
+    accessor.addRepeatedGroupElement(1, msg2, TestMessage.instanceCreator);
+    const result =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+
+    expect(Array.from(result)).toEqual([msg1, msg2]);
+  });
+
+  it('add values', () => {
+    const accessor = Kernel.createEmpty();
+    const bytes1 = createArrayBuffer(0x08, 0x01);
+    const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1));
+    const bytes2 = createArrayBuffer(0x08, 0x02);
+    const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2));
+
+    accessor.addRepeatedGroupIterable(1, [msg1], TestMessage.instanceCreator);
+    accessor.addRepeatedGroupIterable(1, [msg2], TestMessage.instanceCreator);
+    const result =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+
+    expect(Array.from(result)).toEqual([msg1, msg2]);
+  });
+
+  it('set a single value', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const subbytes = createArrayBuffer(0x08, 0x01);
+    const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes));
+
+    accessor.setRepeatedGroupElement(
+        /* fieldNumber= */ 1, submsg, TestMessage.instanceCreator,
+        /* index= */ 0);
+    const result =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+
+    expect(Array.from(result)).toEqual([submsg]);
+  });
+
+  it('write submessage changes made via getRepeatedGroupElement', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x05, 0x0C);
+    const expected = createArrayBuffer(0x0B, 0x08, 0x00, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const submsg = accessor.getRepeatedGroupElement(
+        /* fieldNumber= */ 1, TestMessage.instanceCreator,
+        /* index= */ 0);
+    expect(submsg.getInt32WithDefault(1, 0)).toEqual(5);
+    submsg.setInt32(1, 0);
+
+    expect(accessor.serialize()).toEqual(expected);
+  });
+
+  it('set values', () => {
+    const accessor = Kernel.createEmpty();
+    const subbytes = createArrayBuffer(0x08, 0x01);
+    const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes));
+
+    accessor.setRepeatedGroupIterable(1, [submsg]);
+    const result =
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+
+    expect(Array.from(result)).toEqual([submsg]);
+  });
+
+  it('encode for adding single value', () => {
+    const accessor = Kernel.createEmpty();
+    const bytes1 = createArrayBuffer(0x08, 0x01);
+    const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1));
+    const bytes2 = createArrayBuffer(0x08, 0x00);
+    const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2));
+    const expected =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x00, 0x0C);
+
+    accessor.addRepeatedGroupElement(1, msg1, TestMessage.instanceCreator);
+    accessor.addRepeatedGroupElement(1, msg2, TestMessage.instanceCreator);
+    const result = accessor.serialize();
+
+    expect(result).toEqual(expected);
+  });
+
+  it('encode for adding values', () => {
+    const accessor = Kernel.createEmpty();
+    const bytes1 = createArrayBuffer(0x08, 0x01);
+    const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1));
+    const bytes2 = createArrayBuffer(0x08, 0x00);
+    const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2));
+    const expected =
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x00, 0x0C);
+
+    accessor.addRepeatedGroupIterable(
+        1, [msg1, msg2], TestMessage.instanceCreator);
+    const result = accessor.serialize();
+
+    expect(result).toEqual(expected);
+  });
+
+  it('encode for setting single value', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x00, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const subbytes = createArrayBuffer(0x08, 0x01);
+    const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes));
+    const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+
+    accessor.setRepeatedGroupElement(
+        /* fieldNumber= */ 1, submsg, TestMessage.instanceCreator,
+        /* index= */ 0);
+    const result = accessor.serialize();
+
+    expect(result).toEqual(expected);
+  });
+
+  it('encode for setting values', () => {
+    const accessor = Kernel.createEmpty();
+    const subbytes = createArrayBuffer(0x08, 0x01);
+    const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes));
+    const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+
+    accessor.setRepeatedGroupIterable(1, [submsg]);
+    const result = accessor.serialize();
+
+    expect(result).toEqual(expected);
+  });
+
+  it('fail when getting groups value with other wire types', () => {
+    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
+        0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
+
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => {
+        accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+      }).toThrow();
+    }
+  });
+
+  it('fail when adding group values with wrong type value', () => {
+    const accessor = Kernel.createEmpty();
+    const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null));
+    if (CHECK_CRITICAL_STATE) {
+      expect(
+          () => accessor.addRepeatedGroupIterable(
+              1, [fakeValue], TestMessage.instanceCreator))
+          .toThrowError('Given value is not a message instance: null');
+    } else {
+      // Note in unchecked mode we produce invalid output for invalid inputs.
+      // This test just documents our behavior in those cases.
+      // These values might change at any point and are not considered
+      // what the implementation should be doing here.
+      accessor.addRepeatedGroupIterable(
+          1, [fakeValue], TestMessage.instanceCreator);
+      const list =
+          accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+      expect(Array.from(list)).toEqual([null]);
+    }
+  });
+
+  it('fail when adding single group value with wrong type value', () => {
+    const accessor = Kernel.createEmpty();
+    const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null));
+    if (CHECK_CRITICAL_STATE) {
+      expect(
+          () => accessor.addRepeatedGroupElement(
+              1, fakeValue, TestMessage.instanceCreator))
+          .toThrowError('Given value is not a message instance: null');
+    } else {
+      // Note in unchecked mode we produce invalid output for invalid inputs.
+      // This test just documents our behavior in those cases.
+      // These values might change at any point and are not considered
+      // what the implementation should be doing here.
+      accessor.addRepeatedGroupElement(
+          1, fakeValue, TestMessage.instanceCreator);
+      const list =
+          accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+      expect(Array.from(list)).toEqual([null]);
+    }
+  });
+
+  it('fail when setting message values with wrong type value', () => {
+    const accessor = Kernel.createEmpty();
+    const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null));
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => accessor.setRepeatedGroupIterable(1, [fakeValue]))
+          .toThrowError('Given value is not a message instance: null');
+    } else {
+      // Note in unchecked mode we produce invalid output for invalid inputs.
+      // This test just documents our behavior in those cases.
+      // These values might change at any point and are not considered
+      // what the implementation should be doing here.
+      accessor.setRepeatedGroupIterable(1, [fakeValue]);
+      const list =
+          accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+      expect(Array.from(list)).toEqual([null]);
+    }
+  });
+
+  it('fail when setting single value with wrong type value', () => {
+    const accessor =
+        Kernel.fromArrayBuffer(createArrayBuffer(0x0B, 0x08, 0x00, 0x0C));
+    const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null));
+    if (CHECK_CRITICAL_STATE) {
+      expect(
+          () => accessor.setRepeatedGroupElement(
+              /* fieldNumber= */ 1, fakeValue, TestMessage.instanceCreator,
+              /* index= */ 0))
+          .toThrowError('Given value is not a message instance: null');
+    } else {
+      // Note in unchecked mode we produce invalid output for invalid inputs.
+      // This test just documents our behavior in those cases.
+      // These values might change at any point and are not considered
+      // what the implementation should be doing here.
+      accessor.setRepeatedGroupElement(
+          /* fieldNumber= */ 1, fakeValue, TestMessage.instanceCreator,
+          /* index= */ 0);
+      const list =
+          accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator);
+      expect(Array.from(list).length).toEqual(1);
+    }
+  });
+
+  it('fail when setting single value with out-of-bound index', () => {
+    const accessor =
+        Kernel.fromArrayBuffer(createArrayBuffer(0x0B, 0x08, 0x00, 0x0C));
+    const msg1 =
+        accessor.getRepeatedGroupElement(1, TestMessage.instanceCreator, 0);
+    const bytes2 = createArrayBuffer(0x08, 0x01);
+    const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2));
+    if (CHECK_CRITICAL_STATE) {
+      expect(
+          () => accessor.setRepeatedGroupElement(
+              /* fieldNumber= */ 1, msg2, TestMessage.instanceCreator,
+              /* index= */ 1))
+          .toThrowError('Index out of bounds: index: 1 size: 1');
+    } else {
+      // Note in unchecked mode we produce invalid output for invalid inputs.
+      // This test just documents our behavior in those cases.
+      // These values might change at any point and are not considered
+      // what the implementation should be doing here.
+      accessor.setRepeatedGroupElement(
+          /* fieldNumber= */ 1, msg2, TestMessage.instanceCreator,
+          /* index= */ 1);
+      expectEqualToArray(
+          accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator),
+          [msg1, msg2]);
+    }
+  });
+});
diff --git a/js/experimental/runtime/kernel/kernel_test.js b/js/experimental/runtime/kernel/kernel_test.js
index 61cdeec..eba7c4a 100644
--- a/js/experimental/runtime/kernel/kernel_test.js
+++ b/js/experimental/runtime/kernel/kernel_test.js
@@ -699,7 +699,7 @@
     expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString);
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(
         createArrayBuffer(0x0A, 0x01, 0x00, 0x0A, 0x01, 0x01));
     expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString);
@@ -801,7 +801,7 @@
     expect(accessor.getFixed32WithDefault(1)).toEqual(1);
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
         0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00));
     expect(accessor.getFixed32WithDefault(1)).toEqual(2);
@@ -909,7 +909,7 @@
     expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1));
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
         0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
@@ -1008,7 +1008,7 @@
     expect(accessor.getFloatWithDefault(1)).toEqual(1);
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
         0x0D, 0x00, 0x00, 0x80, 0x3F, 0x0D, 0x00, 0x00, 0x80, 0xBF));
     expect(accessor.getFloatWithDefault(1)).toEqual(-1);
@@ -1110,7 +1110,7 @@
     expect(accessor.getInt32WithDefault(1)).toEqual(1);
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor =
         Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
     expect(accessor.getInt32WithDefault(1)).toEqual(2);
@@ -1207,7 +1207,7 @@
     expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1));
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor =
         Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
     expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(2));
@@ -1306,7 +1306,7 @@
     expect(accessor.getSfixed32WithDefault(1)).toEqual(1);
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
         0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00));
     expect(accessor.getSfixed32WithDefault(1)).toEqual(2);
@@ -1404,7 +1404,7 @@
     expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1));
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
         0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
@@ -1502,7 +1502,7 @@
     expect(accessor.getSint32WithDefault(1)).toEqual(1);
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor =
         Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x03, 0x08, 0x02));
     expect(accessor.getSint32WithDefault(1)).toEqual(1);
@@ -1599,7 +1599,7 @@
     expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1));
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor =
         Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
     expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1));
@@ -1698,7 +1698,7 @@
     expect(accessor.getStringWithDefault(1)).toEqual('a');
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(
         createArrayBuffer(0x0A, 0x01, 0x60, 0x0A, 0x01, 0x61));
     expect(accessor.getStringWithDefault(1)).toEqual('a');
@@ -1789,7 +1789,7 @@
     expect(accessor.getUint32WithDefault(1)).toEqual(1);
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor =
         Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
     expect(accessor.getUint32WithDefault(1)).toEqual(2);
@@ -1896,7 +1896,7 @@
     expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1));
   });
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor =
         Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
     expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(2));
@@ -1996,7 +1996,7 @@
   });
 
 
-  it('decodes value from wire with multple values being present', () => {
+  it('decodes value from wire with multiple values being present', () => {
     const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x09, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF));
@@ -2075,3 +2075,255 @@
     }
   });
 });
+
+describe('Kernel for singular group does', () => {
+  it('return group from the input', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    expect(msg.getBoolWithDefault(1, false)).toBe(true);
+  });
+
+  it('return group from the input when pivot is set', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator, 0);
+    expect(msg.getBoolWithDefault(1, false)).toBe(true);
+  });
+
+  it('encode group from the input', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    expect(accessor.serialize()).toEqual(bytes);
+  });
+
+  it('encode group from the input after read', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    expect(accessor.serialize()).toEqual(bytes);
+  });
+
+  it('return last group from multiple inputs', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    expect(msg.getBoolWithDefault(1, false)).toBe(true);
+  });
+
+  it('removes duplicated group when serializing', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    expect(accessor.serialize())
+        .toEqual(createArrayBuffer(0x0B, 0x08, 0x01, 0x0C));
+  });
+
+  it('encode group from multiple inputs', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    expect(accessor.serialize()).toEqual(bytes);
+  });
+
+  it('encode group after read', () => {
+    const bytes =
+        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
+    const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    expect(accessor.serialize()).toEqual(expected);
+  });
+
+  it('return group from setter', () => {
+    const bytes = createArrayBuffer(0x08, 0x01);
+    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
+    const subaccessor = Kernel.fromArrayBuffer(bytes);
+    const submsg1 = new TestMessage(subaccessor);
+    accessor.setGroup(1, submsg1);
+    const submsg2 = accessor.getGroup(1, TestMessage.instanceCreator);
+    expect(submsg1).toBe(submsg2);
+  });
+
+  it('encode group from setter', () => {
+    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
+    const subaccessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
+    const submsg = new TestMessage(subaccessor);
+    accessor.setGroup(1, submsg);
+    const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
+    expect(accessor.serialize()).toEqual(expected);
+  });
+
+  it('leave hasFieldNumber unchanged after getGroupOrNull', () => {
+    const accessor = Kernel.createEmpty();
+    expect(accessor.hasFieldNumber(1)).toBe(false);
+    expect(accessor.getGroupOrNull(1, TestMessage.instanceCreator)).toBe(null);
+    expect(accessor.hasFieldNumber(1)).toBe(false);
+  });
+
+  it('serialize changes to subgroups made with getGroupsOrNull', () => {
+    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
+    const mutableSubMessage =
+        accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    mutableSubMessage.setInt32(1, 10);
+    const intTenBytes = createArrayBuffer(0x0B, 0x08, 0x0A, 0x0C);
+    expect(accessor.serialize()).toEqual(intTenBytes);
+  });
+
+  it('serialize additions to subgroups made with getGroupOrNull', () => {
+    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
+    const mutableSubMessage =
+        accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    mutableSubMessage.setInt32(2, 3);
+    // Sub group contains the original field, plus the new one.
+    expect(accessor.serialize())
+        .toEqual(createArrayBuffer(0x0B, 0x08, 0x02, 0x10, 0x03, 0x0C));
+  });
+
+  it('fail with getGroupOrNull if immutable group exist in cache', () => {
+    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
+
+    const readOnly = accessor.getGroup(1, TestMessage.instanceCreator);
+    if (CHECK_TYPE) {
+      expect(() => accessor.getGroupOrNull(1, TestMessage.instanceCreator))
+          .toThrow();
+    } else {
+      const mutableSubGropu =
+          accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+      // The instance returned by getGroupOrNull is the exact same instance.
+      expect(mutableSubGropu).toBe(readOnly);
+
+      // Serializing the subgroup does not write the changes
+      mutableSubGropu.setInt32(1, 0);
+      expect(accessor.serialize()).toEqual(intTwoBytes);
+    }
+  });
+
+  it('change hasFieldNumber after getGroupAttach', () => {
+    const accessor = Kernel.createEmpty();
+    expect(accessor.hasFieldNumber(1)).toBe(false);
+    expect(accessor.getGroupAttach(1, TestMessage.instanceCreator))
+        .not.toBe(null);
+    expect(accessor.hasFieldNumber(1)).toBe(true);
+  });
+
+  it('change hasFieldNumber after getGroupAttach when pivot is set', () => {
+    const accessor = Kernel.createEmpty();
+    expect(accessor.hasFieldNumber(1)).toBe(false);
+    expect(
+        accessor.getGroupAttach(1, TestMessage.instanceCreator, /* pivot= */ 1))
+        .not.toBe(null);
+    expect(accessor.hasFieldNumber(1)).toBe(true);
+  });
+
+  it('serialize subgroups made with getGroupAttach', () => {
+    const accessor = Kernel.createEmpty();
+    const mutableSubGroup =
+        accessor.getGroupAttach(1, TestMessage.instanceCreator);
+    mutableSubGroup.setInt32(1, 10);
+    const intTenBytes = createArrayBuffer(0x0B, 0x08, 0x0A, 0x0C);
+    expect(accessor.serialize()).toEqual(intTenBytes);
+  });
+
+  it('serialize additions to subgroups using getMessageAttach', () => {
+    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
+    const mutableSubGroup =
+        accessor.getGroupAttach(1, TestMessage.instanceCreator);
+    mutableSubGroup.setInt32(2, 3);
+    // Sub message contains the original field, plus the new one.
+    expect(accessor.serialize())
+        .toEqual(createArrayBuffer(0x0B, 0x08, 0x02, 0x10, 0x03, 0x0C));
+  });
+
+  it('fail with getGroupAttach if immutable message exist in cache', () => {
+    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
+
+    const readOnly = accessor.getGroup(1, TestMessage.instanceCreator);
+    if (CHECK_TYPE) {
+      expect(() => accessor.getGroupAttach(1, TestMessage.instanceCreator))
+          .toThrow();
+    } else {
+      const mutableSubGroup =
+          accessor.getGroupAttach(1, TestMessage.instanceCreator);
+      // The instance returned by getMessageOrNull is the exact same instance.
+      expect(mutableSubGroup).toBe(readOnly);
+
+      // Serializing the submessage does not write the changes
+      mutableSubGroup.setInt32(1, 0);
+      expect(accessor.serialize()).toEqual(intTwoBytes);
+    }
+  });
+
+  it('read default group return empty group with getGroup', () => {
+    const bytes = new ArrayBuffer(0);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    expect(accessor.getGroup(1, TestMessage.instanceCreator)).toBeTruthy();
+    expect(accessor.getGroup(1, TestMessage.instanceCreator).serialize())
+        .toEqual(bytes);
+  });
+
+  it('read default group return null with getGroupOrNull', () => {
+    const bytes = new ArrayBuffer(0);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    expect(accessor.getGroupOrNull(1, TestMessage.instanceCreator)).toBe(null);
+  });
+
+  it('read group preserve reference equality', () => {
+    const bytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const msg1 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    const msg2 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    const msg3 = accessor.getGroupAttach(1, TestMessage.instanceCreator);
+    expect(msg1).toBe(msg2);
+    expect(msg1).toBe(msg3);
+  });
+
+  it('fail when getting group with null instance constructor', () => {
+    const accessor =
+        Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x08, 0x01));
+    const nullMessage = /** @type {function(!Kernel):!TestMessage} */
+        (/** @type {*} */ (null));
+    expect(() => accessor.getGroupOrNull(1, nullMessage)).toThrow();
+  });
+
+  it('fail when setting group value with null value', () => {
+    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
+    const fakeMessage = /** @type {!TestMessage} */ (/** @type {*} */ (null));
+    if (CHECK_CRITICAL_TYPE) {
+      expect(() => accessor.setGroup(1, fakeMessage))
+          .toThrowError('Given value is not a message instance: null');
+    } else {
+      // Note in unchecked mode we produce invalid output for invalid inputs.
+      // This test just documents our behavior in those cases.
+      // These values might change at any point and are not considered
+      // what the implementation should be doing here.
+      accessor.setMessage(1, fakeMessage);
+      expect(accessor.getGroupOrNull(
+                 /* fieldNumber= */ 1, TestMessage.instanceCreator))
+          .toBeNull();
+    }
+  });
+
+  it('reads group in a longer buffer', () => {
+    const bytes = createArrayBuffer(
+        0x12, 0x20,  // 32 length delimited
+        0x00,        // random values for padding start
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00,  // random values for padding end
+        0x0B,  // Group tag
+        0x08, 0x02, 0x0C);
+    const accessor = Kernel.fromArrayBuffer(bytes);
+    const msg1 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    const msg2 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
+    expect(msg1).toBe(msg2);
+  });
+});
diff --git a/js/experimental/runtime/kernel/message_set.js b/js/experimental/runtime/kernel/message_set.js
new file mode 100644
index 0000000..d66bace
--- /dev/null
+++ b/js/experimental/runtime/kernel/message_set.js
@@ -0,0 +1,285 @@
+/*
+##########################################################
+#                                                        #
+#  __          __     _____  _   _ _____ _   _  _____    #
+#  \ \        / /\   |  __ \| \ | |_   _| \ | |/ ____|   #
+#   \ \  /\  / /  \  | |__) |  \| | | | |  \| | |  __    #
+#    \ \/  \/ / /\ \ |  _  /| . ` | | | | . ` | | |_ |   #
+#     \  /\  / ____ \| | \ \| |\  |_| |_| |\  | |__| |   #
+#      \/  \/_/    \_\_|  \_\_| \_|_____|_| \_|\_____|   #
+#                                                        #
+#                                                        #
+##########################################################
+# Do not use this class in your code. This class purely  #
+# exists to make proto code generation easier.           #
+##########################################################
+*/
+goog.module('protobuf.runtime.MessageSet');
+
+const InternalMessage = goog.require('protobuf.binary.InternalMessage');
+const Kernel = goog.require('protobuf.runtime.Kernel');
+
+// These are the tags for the old MessageSet format, which was defined as:
+//   message MessageSet {
+//     repeated group Item = 1 {
+//       required uint32 type_id = 2;
+//       optional bytes message = 3;
+//     }
+//   }
+/** @const {number} */
+const MSET_GROUP_FIELD_NUMBER = 1;
+/** @const {number} */
+const MSET_TYPE_ID_FIELD_NUMBER = 2;
+/** @const {number} */
+const MSET_MESSAGE_FIELD_NUMBER = 3;
+
+/**
+ * @param {!Kernel} kernel
+ * @return {!Map<number, !Item>}
+ */
+function createItemMap(kernel) {
+  const itemMap = new Map();
+  let totalCount = 0;
+  for (const item of kernel.getRepeatedGroupIterable(
+           MSET_GROUP_FIELD_NUMBER, Item.fromKernel)) {
+    itemMap.set(item.getTypeId(), item);
+    totalCount++;
+  }
+
+  // Normalize the entries.
+  if (totalCount > itemMap.size) {
+    writeItemMap(kernel, itemMap);
+  }
+  return itemMap;
+}
+
+/**
+ * @param {!Kernel} kernel
+ * @param {!Map<number, !Item>} itemMap
+ */
+function writeItemMap(kernel, itemMap) {
+  kernel.setRepeatedGroupIterable(MSET_GROUP_FIELD_NUMBER, itemMap.values());
+}
+
+/**
+ * @implements {InternalMessage}
+ * @final
+ */
+class MessageSet {
+  /**
+   * @param {!Kernel} kernel
+   * @return {!MessageSet}
+   */
+  static fromKernel(kernel) {
+    const itemMap = createItemMap(kernel);
+    return new MessageSet(kernel, itemMap);
+  }
+
+  /**
+   * @return {!MessageSet}
+   */
+  static createEmpty() {
+    return MessageSet.fromKernel(Kernel.createEmpty());
+  }
+
+  /**
+   * @param {!Kernel} kernel
+   * @param {!Map<number, !Item>} itemMap
+   * @private
+   */
+  constructor(kernel, itemMap) {
+    /** @const {!Kernel} @private */
+    this.kernel_ = kernel;
+    /** @const {!Map<number, !Item>} @private */
+    this.itemMap_ = itemMap;
+  }
+
+
+
+  // code helpers for code gen
+
+  /**
+   * @param {number} typeId
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {?T}
+   * @template T
+   */
+  getMessageOrNull(typeId, instanceCreator, pivot) {
+    const item = this.itemMap_.get(typeId);
+    return item ? item.getMessageOrNull(instanceCreator, pivot) : null;
+  }
+
+  /**
+   * @param {number} typeId
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {T}
+   * @template T
+   */
+  getMessageAttach(typeId, instanceCreator, pivot) {
+    let item = this.itemMap_.get(typeId);
+    if (item) {
+      return item.getMessageAttach(instanceCreator, pivot);
+    }
+    const message = instanceCreator(Kernel.createEmpty());
+    this.setMessage(typeId, message);
+    return message;
+  }
+
+  /**
+   * @param {number} typeId
+   * @param {number=} pivot
+   * @return {?Kernel}
+   */
+  getMessageAccessorOrNull(typeId, pivot) {
+    const item = this.itemMap_.get(typeId);
+    return item ? item.getMessageAccessorOrNull(pivot) : null;
+  }
+
+
+  /**
+   * @param {number} typeId
+   */
+  clearMessage(typeId) {
+    if (this.itemMap_.delete(typeId)) {
+      writeItemMap(this.kernel_, this.itemMap_);
+    }
+  }
+
+  /**
+   * @param {number} typeId
+   * @return {boolean}
+   */
+  hasMessage(typeId) {
+    return this.itemMap_.has(typeId);
+  }
+
+  /**
+   * @param {number} typeId
+   * @param {!InternalMessage} value
+   */
+  setMessage(typeId, value) {
+    const item = this.itemMap_.get(typeId);
+    if (item) {
+      item.setMessage(value);
+    } else {
+      this.itemMap_.set(typeId, Item.create(typeId, value));
+      writeItemMap(this.kernel_, this.itemMap_);
+    }
+  }
+
+  /**
+   * @return {!Kernel}
+   * @override
+   */
+  internalGetKernel() {
+    return this.kernel_;
+  }
+}
+
+/**
+ * @implements {InternalMessage}
+ * @final
+ */
+class Item {
+  /**
+   * @param {number} typeId
+   * @param {!InternalMessage} message
+   * @return {!Item}
+   */
+  static create(typeId, message) {
+    const messageSet = Item.fromKernel(Kernel.createEmpty());
+    messageSet.setTypeId_(typeId);
+    messageSet.setMessage(message);
+    return messageSet;
+  }
+
+
+  /**
+   * @param {!Kernel} kernel
+   * @return {!Item}
+   */
+  static fromKernel(kernel) {
+    return new Item(kernel);
+  }
+
+  /**
+   * @param {!Kernel} kernel
+   * @private
+   */
+  constructor(kernel) {
+    /** @const {!Kernel} @private */
+    this.kernel_ = kernel;
+  }
+
+  /**
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {T}
+   * @template T
+   */
+  getMessage(instanceCreator, pivot) {
+    return this.kernel_.getMessage(
+        MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
+  }
+
+  /**
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {?T}
+   * @template T
+   */
+  getMessageOrNull(instanceCreator, pivot) {
+    return this.kernel_.getMessageOrNull(
+        MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
+  }
+
+  /**
+   * @param {function(!Kernel):T} instanceCreator
+   * @param {number=} pivot
+   * @return {T}
+   * @template T
+   */
+  getMessageAttach(instanceCreator, pivot) {
+    return this.kernel_.getMessageAttach(
+        MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
+  }
+
+  /**
+   * @param {number=} pivot
+   * @return {?Kernel}
+   */
+  getMessageAccessorOrNull(pivot) {
+    return this.kernel_.getMessageAccessorOrNull(
+        MSET_MESSAGE_FIELD_NUMBER, pivot);
+  }
+
+  /** @param {!InternalMessage} value */
+  setMessage(value) {
+    this.kernel_.setMessage(MSET_MESSAGE_FIELD_NUMBER, value);
+  }
+
+  /** @return {number} */
+  getTypeId() {
+    return this.kernel_.getUint32WithDefault(MSET_TYPE_ID_FIELD_NUMBER);
+  }
+
+  /**
+   * @param {number} value
+   * @private
+   */
+  setTypeId_(value) {
+    this.kernel_.setUint32(MSET_TYPE_ID_FIELD_NUMBER, value);
+  }
+
+  /**
+   * @return {!Kernel}
+   * @override
+   */
+  internalGetKernel() {
+    return this.kernel_;
+  }
+}
+
+exports = MessageSet;
diff --git a/js/experimental/runtime/kernel/message_set_test.js b/js/experimental/runtime/kernel/message_set_test.js
new file mode 100644
index 0000000..35e5935
--- /dev/null
+++ b/js/experimental/runtime/kernel/message_set_test.js
@@ -0,0 +1,262 @@
+/**
+ * @fileoverview Tests for message_set.js.
+ */
+goog.module('protobuf.runtime.MessageSetTest');
+
+goog.setTestOnly();
+
+const Kernel = goog.require('protobuf.runtime.Kernel');
+const MessageSet = goog.require('protobuf.runtime.MessageSet');
+const TestMessage = goog.require('protobuf.testing.binary.TestMessage');
+
+/**
+ * @param {...number} bytes
+ * @return {!ArrayBuffer}
+ */
+function createArrayBuffer(...bytes) {
+  return new Uint8Array(bytes).buffer;
+}
+
+describe('MessageSet does', () => {
+  it('returns no messages for empty set', () => {
+    const messageSet = MessageSet.createEmpty();
+    expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator))
+        .toBeNull();
+  });
+
+  it('returns no kernel for empty set', () => {
+    const messageSet = MessageSet.createEmpty();
+    expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull();
+  });
+
+  it('returns message that has been set', () => {
+    const messageSet = MessageSet.createEmpty();
+    const message = TestMessage.createEmpty();
+    messageSet.setMessage(12345, message);
+    expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator))
+        .toBe(message);
+  });
+
+  it('returns null for cleared message', () => {
+    const messageSet = MessageSet.createEmpty();
+    const message = TestMessage.createEmpty();
+    messageSet.setMessage(12345, message);
+    messageSet.clearMessage(12345);
+    expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull();
+  });
+
+  it('returns false for not present message', () => {
+    const messageSet = MessageSet.createEmpty();
+    expect(messageSet.hasMessage(12345)).toBe(false);
+  });
+
+  it('returns true for present message', () => {
+    const messageSet = MessageSet.createEmpty();
+    const message = TestMessage.createEmpty();
+    messageSet.setMessage(12345, message);
+    expect(messageSet.hasMessage(12345)).toBe(true);
+  });
+
+  it('returns false for cleared message', () => {
+    const messageSet = MessageSet.createEmpty();
+    const message = TestMessage.createEmpty();
+    messageSet.setMessage(12345, message);
+    messageSet.clearMessage(12345);
+    expect(messageSet.hasMessage(12345)).toBe(false);
+  });
+
+  it('returns false for cleared message without it being present', () => {
+    const messageSet = MessageSet.createEmpty();
+    messageSet.clearMessage(12345);
+    expect(messageSet.hasMessage(12345)).toBe(false);
+  });
+
+  const createMessageSet = () => {
+    const messageSet = MessageSet.createEmpty();
+    const message = TestMessage.createEmpty();
+    message.setInt32(1, 2);
+    messageSet.setMessage(12345, message);
+
+
+    const parsedKernel =
+        Kernel.fromArrayBuffer(messageSet.internalGetKernel().serialize());
+    return MessageSet.fromKernel(parsedKernel);
+  };
+
+  it('pass through pivot for getMessageOrNull', () => {
+    const messageSet = createMessageSet();
+    const message =
+        messageSet.getMessageOrNull(12345, TestMessage.instanceCreator, 2);
+    expect(message.internalGetKernel().getPivot()).toBe(2);
+  });
+
+  it('pass through pivot for getMessageAttach', () => {
+    const messageSet = createMessageSet();
+    const message =
+        messageSet.getMessageAttach(12345, TestMessage.instanceCreator, 2);
+    expect(message.internalGetKernel().getPivot()).toBe(2);
+  });
+
+  it('pass through pivot for getMessageAccessorOrNull', () => {
+    const messageSet = createMessageSet();
+    const kernel = messageSet.getMessageAccessorOrNull(12345, 2);
+    expect(kernel.getPivot()).toBe(2);
+  });
+
+  it('pick the last value in the stream', () => {
+    const arrayBuffer = createArrayBuffer(
+        0x52,  // Tag (field:10, length delimited)
+        0x14,  // Length of 20 bytes
+        0x0B,  // Start group fieldnumber 1
+        0x10,  // Tag (field 2, varint)
+        0xB9,  // 12345
+        0x60,  // 12345
+        0x1A,  // Tag (field 3, length delimited)
+        0x03,  // length 3
+        0xA0,  // Tag (fieldnumber 20, varint)
+        0x01,  // Tag (fieldnumber 20, varint)
+        0x1E,  // 30
+        0x0C,  // Stop Group field number 1
+        // second group
+        0x0B,  // Start group fieldnumber 1
+        0x10,  // Tag (field 2, varint)
+        0xB9,  // 12345
+        0x60,  // 12345
+        0x1A,  // Tag (field 3, length delimited)
+        0x03,  // length 3
+        0xA0,  // Tag (fieldnumber 20, varint)
+        0x01,  // Tag (fieldnumber 20, varint)
+        0x01,  // 1
+        0x0C   // Stop Group field number 1
+    );
+
+    const outerMessage = Kernel.fromArrayBuffer(arrayBuffer);
+
+    const messageSet = outerMessage.getMessage(10, MessageSet.fromKernel);
+
+    const message =
+        messageSet.getMessageOrNull(12345, TestMessage.instanceCreator);
+    expect(message.getInt32WithDefault(20)).toBe(1);
+  });
+
+  it('removes duplicates when read', () => {
+    const arrayBuffer = createArrayBuffer(
+        0x52,  // Tag (field:10, length delimited)
+        0x14,  // Length of 20 bytes
+        0x0B,  // Start group fieldnumber 1
+        0x10,  // Tag (field 2, varint)
+        0xB9,  // 12345
+        0x60,  // 12345
+        0x1A,  // Tag (field 3, length delimited)
+        0x03,  // length 3
+        0xA0,  // Tag (fieldnumber 20, varint)
+        0x01,  // Tag (fieldnumber 20, varint)
+        0x1E,  // 30
+        0x0C,  // Stop Group field number 1
+        // second group
+        0x0B,  // Start group fieldnumber 1
+        0x10,  // Tag (field 2, varint)
+        0xB9,  // 12345
+        0x60,  // 12345
+        0x1A,  // Tag (field 3, length delimited)
+        0x03,  // length 3
+        0xA0,  // Tag (fieldnumber 20, varint)
+        0x01,  // Tag (fieldnumber 20, varint)
+        0x01,  // 1
+        0x0C   // Stop Group field number 1
+    );
+
+
+    const outerMessage = Kernel.fromArrayBuffer(arrayBuffer);
+    outerMessage.getMessageAttach(10, MessageSet.fromKernel);
+
+    expect(outerMessage.serialize())
+        .toEqual(createArrayBuffer(
+            0x52,  // Tag (field:10, length delimited)
+            0x0A,  // Length of 10 bytes
+            0x0B,  // Start group fieldnumber 1
+            0x10,  // Tag (field 2, varint)
+            0xB9,  // 12345
+            0x60,  // 12345
+            0x1A,  // Tag (field 3, length delimited)
+            0x03,  // length 3
+            0xA0,  // Tag (fieldnumber 20, varint)
+            0x01,  // Tag (fieldnumber 20, varint)
+            0x01,  // 1
+            0x0C   // Stop Group field number 1
+            ));
+  });
+
+  it('allow for large typeIds', () => {
+    const messageSet = MessageSet.createEmpty();
+    const message = TestMessage.createEmpty();
+    messageSet.setMessage(0xFFFFFFFE >>> 0, message);
+    expect(messageSet.hasMessage(0xFFFFFFFE >>> 0)).toBe(true);
+  });
+});
+
+describe('Optional MessageSet does', () => {
+  // message Bar {
+  //  optional MessageSet mset = 10;
+  //}
+  //
+  // message Foo {
+  //  extend proto2.bridge.MessageSet {
+  //    optional Foo message_set_extension = 12345;
+  //  }
+  //  optional int32 f20 = 20;
+  //}
+
+  it('encode as a field', () => {
+    const fooMessage = Kernel.createEmpty();
+    fooMessage.setInt32(20, 30);
+
+    const messageSet = MessageSet.createEmpty();
+    messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage));
+
+    const barMessage = Kernel.createEmpty();
+    barMessage.setMessage(10, messageSet);
+
+    expect(barMessage.serialize())
+        .toEqual(createArrayBuffer(
+            0x52,  // Tag (field:10, length delimited)
+            0x0A,  // Length of 10 bytes
+            0x0B,  // Start group fieldnumber 1
+            0x10,  // Tag (field 2, varint)
+            0xB9,  // 12345
+            0x60,  // 12345
+            0x1A,  // Tag (field 3, length delimited)
+            0x03,  // length 3
+            0xA0,  // Tag (fieldnumber 20, varint)
+            0x01,  // Tag (fieldnumber 20, varint)
+            0x1E,  // 30
+            0x0C   // Stop Group field number 1
+            ));
+  });
+
+  it('deserializes', () => {
+    const fooMessage = Kernel.createEmpty();
+    fooMessage.setInt32(20, 30);
+
+    const messageSet = MessageSet.createEmpty();
+    messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage));
+
+
+    const barMessage = Kernel.createEmpty();
+    barMessage.setMessage(10, messageSet);
+
+    const arrayBuffer = barMessage.serialize();
+
+    const barMessageParsed = Kernel.fromArrayBuffer(arrayBuffer);
+    expect(barMessageParsed.hasFieldNumber(10)).toBe(true);
+
+    const messageSetParsed =
+        barMessageParsed.getMessage(10, MessageSet.fromKernel);
+
+    const fooMessageParsed =
+        messageSetParsed.getMessageOrNull(12345, TestMessage.instanceCreator)
+            .internalGetKernel();
+
+    expect(fooMessageParsed.getInt32WithDefault(20)).toBe(30);
+  });
+});
diff --git a/js/experimental/runtime/kernel/tag.js b/js/experimental/runtime/kernel/tag.js
new file mode 100644
index 0000000..b288df3
--- /dev/null
+++ b/js/experimental/runtime/kernel/tag.js
@@ -0,0 +1,144 @@
+goog.module('protobuf.binary.tag');
+
+const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
+const WireType = goog.require('protobuf.binary.WireType');
+const {checkCriticalElementIndex, checkCriticalState} = goog.require('protobuf.internal.checks');
+
+/**
+ * Returns wire type stored in a tag.
+ * Protos store the wire type as the first 3 bit of a tag.
+ * @param {number} tag
+ * @return {!WireType}
+ */
+function tagToWireType(tag) {
+  return /** @type {!WireType} */ (tag & 0x07);
+}
+
+/**
+ * Returns the field number stored in a tag.
+ * Protos store the field number in the upper 29 bits of a 32 bit number.
+ * @param {number} tag
+ * @return {number}
+ */
+function tagToFieldNumber(tag) {
+  return tag >>> 3;
+}
+
+/**
+ * Combines wireType and fieldNumber into a tag.
+ * @param {!WireType} wireType
+ * @param {number} fieldNumber
+ * @return {number}
+ */
+function createTag(wireType, fieldNumber) {
+  return (fieldNumber << 3 | wireType) >>> 0;
+}
+
+/**
+ * Returns the length, in bytes, of the field in the tag stream, less the tag
+ * itself.
+ * Note: This moves the cursor in the bufferDecoder.
+ * @param {!BufferDecoder} bufferDecoder
+ * @param {number} start
+ * @param {!WireType} wireType
+ * @param {number} fieldNumber
+ * @return {number}
+ * @private
+ */
+function getTagLength(bufferDecoder, start, wireType, fieldNumber) {
+  bufferDecoder.setCursor(start);
+  skipField(bufferDecoder, wireType, fieldNumber);
+  return bufferDecoder.cursor() - start;
+}
+
+/**
+ * @param {number} value
+ * @return {number}
+ */
+function get32BitVarintLength(value) {
+  if (value < 0) {
+    return 5;
+  }
+  let size = 1;
+  while (value >= 128) {
+    size++;
+    value >>>= 7;
+  }
+  return size;
+}
+
+/**
+ * Skips over a field.
+ * Note: If the field is a start group the entire group will be skipped, placing
+ * the cursor onto the next field.
+ * @param {!BufferDecoder} bufferDecoder
+ * @param {!WireType} wireType
+ * @param {number} fieldNumber
+ */
+function skipField(bufferDecoder, wireType, fieldNumber) {
+  switch (wireType) {
+    case WireType.VARINT:
+      checkCriticalElementIndex(
+          bufferDecoder.cursor(), bufferDecoder.endIndex());
+      bufferDecoder.skipVarint();
+      return;
+    case WireType.FIXED64:
+      bufferDecoder.skip(8);
+      return;
+    case WireType.DELIMITED:
+      checkCriticalElementIndex(
+          bufferDecoder.cursor(), bufferDecoder.endIndex());
+      const length = bufferDecoder.getUnsignedVarint32();
+      bufferDecoder.skip(length);
+      return;
+    case WireType.START_GROUP:
+      const foundGroup = skipGroup_(bufferDecoder, fieldNumber);
+      checkCriticalState(foundGroup, 'No end group found.');
+      return;
+    case WireType.FIXED32:
+      bufferDecoder.skip(4);
+      return;
+    default:
+      throw new Error(`Unexpected wire type: ${wireType}`);
+  }
+}
+
+/**
+ * Skips over fields until it finds the end of a given group consuming the stop
+ * group tag.
+ * @param {!BufferDecoder} bufferDecoder
+ * @param {number} groupFieldNumber
+ * @return {boolean} Whether the end group tag was found.
+ * @private
+ */
+function skipGroup_(bufferDecoder, groupFieldNumber) {
+  // On a start group we need to keep skipping fields until we find a
+  // corresponding stop group
+  // Note: Since we are calling skipField from here nested groups will be
+  // handled by recursion of this method and thus we will not see a nested
+  // STOP GROUP here unless there is something wrong with the input data.
+  while (bufferDecoder.hasNext()) {
+    const tag = bufferDecoder.getUnsignedVarint32();
+    const wireType = tagToWireType(tag);
+    const fieldNumber = tagToFieldNumber(tag);
+
+    if (wireType === WireType.END_GROUP) {
+      checkCriticalState(
+          groupFieldNumber === fieldNumber,
+          `Expected stop group for fieldnumber ${groupFieldNumber} not found.`);
+      return true;
+    } else {
+      skipField(bufferDecoder, wireType, fieldNumber);
+    }
+  }
+  return false;
+}
+
+exports = {
+  createTag,
+  get32BitVarintLength,
+  getTagLength,
+  skipField,
+  tagToWireType,
+  tagToFieldNumber,
+};
diff --git a/js/experimental/runtime/kernel/tag_test.js b/js/experimental/runtime/kernel/tag_test.js
new file mode 100644
index 0000000..35137bb
--- /dev/null
+++ b/js/experimental/runtime/kernel/tag_test.js
@@ -0,0 +1,221 @@
+/**
+ * @fileoverview Tests for tag.js.
+ */
+goog.module('protobuf.binary.TagTests');
+
+const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
+const WireType = goog.require('protobuf.binary.WireType');
+const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
+const {createTag, get32BitVarintLength, skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag');
+
+
+goog.setTestOnly();
+
+/**
+ * @param {...number} bytes
+ * @return {!ArrayBuffer}
+ */
+function createArrayBuffer(...bytes) {
+  return new Uint8Array(bytes).buffer;
+}
+
+describe('skipField', () => {
+  it('skips varints', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
+    skipField(bufferDecoder, WireType.VARINT, 1);
+    expect(bufferDecoder.cursor()).toBe(2);
+  });
+
+  it('throws for out of bounds varints', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
+    bufferDecoder.setCursor(2);
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => skipField(bufferDecoder, WireType.VARINT, 1)).toThrowError();
+    }
+  });
+
+  it('skips fixed64', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
+    skipField(bufferDecoder, WireType.FIXED64, 1);
+    expect(bufferDecoder.cursor()).toBe(8);
+  });
+
+  it('throws for fixed64 if length is too short', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => skipField(bufferDecoder, WireType.FIXED64, 1))
+          .toThrowError();
+    }
+  });
+
+  it('skips fixed32', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0x80, 0x00, 0x00, 0x00));
+    skipField(bufferDecoder, WireType.FIXED32, 1);
+    expect(bufferDecoder.cursor()).toBe(4);
+  });
+
+  it('throws for fixed32 if length is too short', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => skipField(bufferDecoder, WireType.FIXED32, 1))
+          .toThrowError();
+    }
+  });
+
+
+  it('skips length delimited', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0x03, 0x00, 0x00, 0x00));
+    skipField(bufferDecoder, WireType.DELIMITED, 1);
+    expect(bufferDecoder.cursor()).toBe(4);
+  });
+
+  it('throws for length delimited if length is too short', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x03, 0x00, 0x00));
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => skipField(bufferDecoder, WireType.DELIMITED, 1))
+          .toThrowError();
+    }
+  });
+
+  it('skips groups', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0x0B, 0x08, 0x01, 0x0C));
+    bufferDecoder.setCursor(1);
+    skipField(bufferDecoder, WireType.START_GROUP, 1);
+    expect(bufferDecoder.cursor()).toBe(4);
+  });
+
+  it('skips group in group', () => {
+    const buffer = createArrayBuffer(
+        0x0B,        // start outer
+        0x10, 0x01,  // field: 2, value: 1
+        0x0B,        // start inner group
+        0x10, 0x01,  // payload inner group
+        0x0C,        // stop inner group
+        0x0C         // end outer
+    );
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(buffer);
+    bufferDecoder.setCursor(1);
+    skipField(bufferDecoder, WireType.START_GROUP, 1);
+    expect(bufferDecoder.cursor()).toBe(8);
+  });
+
+  it('throws for group if length is too short', () => {
+    // no closing group
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0B, 0x00, 0x00));
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => skipField(bufferDecoder, WireType.START_GROUP, 1))
+          .toThrowError();
+    }
+  });
+});
+
+
+describe('tagToWireType', () => {
+  it('decodes numbers ', () => {
+    // simple numbers
+    expect(tagToWireType(0x00)).toBe(WireType.VARINT);
+    expect(tagToWireType(0x01)).toBe(WireType.FIXED64);
+    expect(tagToWireType(0x02)).toBe(WireType.DELIMITED);
+    expect(tagToWireType(0x03)).toBe(WireType.START_GROUP);
+    expect(tagToWireType(0x04)).toBe(WireType.END_GROUP);
+    expect(tagToWireType(0x05)).toBe(WireType.FIXED32);
+
+    // upper bits should not matter
+    expect(tagToWireType(0x08)).toBe(WireType.VARINT);
+    expect(tagToWireType(0x09)).toBe(WireType.FIXED64);
+    expect(tagToWireType(0x0A)).toBe(WireType.DELIMITED);
+    expect(tagToWireType(0x0B)).toBe(WireType.START_GROUP);
+    expect(tagToWireType(0x0C)).toBe(WireType.END_GROUP);
+    expect(tagToWireType(0x0D)).toBe(WireType.FIXED32);
+
+    // upper bits should not matter
+    expect(tagToWireType(0xF8)).toBe(WireType.VARINT);
+    expect(tagToWireType(0xF9)).toBe(WireType.FIXED64);
+    expect(tagToWireType(0xFA)).toBe(WireType.DELIMITED);
+    expect(tagToWireType(0xFB)).toBe(WireType.START_GROUP);
+    expect(tagToWireType(0xFC)).toBe(WireType.END_GROUP);
+    expect(tagToWireType(0xFD)).toBe(WireType.FIXED32);
+
+    // negative numbers work
+    expect(tagToWireType(-8)).toBe(WireType.VARINT);
+    expect(tagToWireType(-7)).toBe(WireType.FIXED64);
+    expect(tagToWireType(-6)).toBe(WireType.DELIMITED);
+    expect(tagToWireType(-5)).toBe(WireType.START_GROUP);
+    expect(tagToWireType(-4)).toBe(WireType.END_GROUP);
+    expect(tagToWireType(-3)).toBe(WireType.FIXED32);
+  });
+});
+
+describe('tagToFieldNumber', () => {
+  it('returns fieldNumber', () => {
+    expect(tagToFieldNumber(0x08)).toBe(1);
+    expect(tagToFieldNumber(0x09)).toBe(1);
+    expect(tagToFieldNumber(0x10)).toBe(2);
+    expect(tagToFieldNumber(0x12)).toBe(2);
+  });
+});
+
+describe('createTag', () => {
+  it('combines fieldNumber and wireType', () => {
+    expect(createTag(WireType.VARINT, 1)).toBe(0x08);
+    expect(createTag(WireType.FIXED64, 1)).toBe(0x09);
+    expect(createTag(WireType.DELIMITED, 1)).toBe(0x0A);
+    expect(createTag(WireType.START_GROUP, 1)).toBe(0x0B);
+    expect(createTag(WireType.END_GROUP, 1)).toBe(0x0C);
+    expect(createTag(WireType.FIXED32, 1)).toBe(0x0D);
+
+    expect(createTag(WireType.VARINT, 2)).toBe(0x10);
+    expect(createTag(WireType.FIXED64, 2)).toBe(0x11);
+    expect(createTag(WireType.DELIMITED, 2)).toBe(0x12);
+    expect(createTag(WireType.START_GROUP, 2)).toBe(0x13);
+    expect(createTag(WireType.END_GROUP, 2)).toBe(0x14);
+    expect(createTag(WireType.FIXED32, 2)).toBe(0x15);
+
+    expect(createTag(WireType.VARINT, 0x1FFFFFFF)).toBe(0xFFFFFFF8 >>> 0);
+    expect(createTag(WireType.FIXED64, 0x1FFFFFFF)).toBe(0xFFFFFFF9 >>> 0);
+    expect(createTag(WireType.DELIMITED, 0x1FFFFFFF)).toBe(0xFFFFFFFA >>> 0);
+    expect(createTag(WireType.START_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFB >>> 0);
+    expect(createTag(WireType.END_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFC >>> 0);
+    expect(createTag(WireType.FIXED32, 0x1FFFFFFF)).toBe(0xFFFFFFFD >>> 0);
+  });
+});
+
+describe('get32BitVarintLength', () => {
+  it('length of tag', () => {
+    expect(get32BitVarintLength(0)).toBe(1);
+    expect(get32BitVarintLength(1)).toBe(1);
+    expect(get32BitVarintLength(1)).toBe(1);
+
+    expect(get32BitVarintLength(Math.pow(2, 7) - 1)).toBe(1);
+    expect(get32BitVarintLength(Math.pow(2, 7))).toBe(2);
+
+    expect(get32BitVarintLength(Math.pow(2, 14) - 1)).toBe(2);
+    expect(get32BitVarintLength(Math.pow(2, 14))).toBe(3);
+
+    expect(get32BitVarintLength(Math.pow(2, 21) - 1)).toBe(3);
+    expect(get32BitVarintLength(Math.pow(2, 21))).toBe(4);
+
+    expect(get32BitVarintLength(Math.pow(2, 28) - 1)).toBe(4);
+    expect(get32BitVarintLength(Math.pow(2, 28))).toBe(5);
+
+    expect(get32BitVarintLength(Math.pow(2, 31) - 1)).toBe(5);
+
+    expect(get32BitVarintLength(-1)).toBe(5);
+    expect(get32BitVarintLength(-Math.pow(2, 31))).toBe(5);
+
+    expect(get32BitVarintLength(createTag(WireType.VARINT, 0x1fffffff)))
+        .toBe(5);
+    expect(get32BitVarintLength(createTag(WireType.FIXED32, 0x1fffffff)))
+        .toBe(5);
+  });
+});
diff --git a/js/experimental/runtime/kernel/writer.js b/js/experimental/runtime/kernel/writer.js
index 8af7a06..5b8b79b 100644
--- a/js/experimental/runtime/kernel/writer.js
+++ b/js/experimental/runtime/kernel/writer.js
@@ -10,6 +10,7 @@
 const WireType = goog.require('protobuf.binary.WireType');
 const {POLYFILL_TEXT_ENCODING, checkFieldNumber, checkTypeUnsignedInt32, checkWireType} = goog.require('protobuf.internal.checks');
 const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays');
+const {createTag, getTagLength} = goog.require('protobuf.binary.tag');
 const {encode} = goog.require('protobuf.binary.textencoding');
 
 /**
@@ -92,8 +93,8 @@
   writeTag(fieldNumber, wireType) {
     checkFieldNumber(fieldNumber);
     checkWireType(wireType);
-    const tag = fieldNumber << 3 | wireType;
-    this.writeUnsignedVarint32_(tag >>> 0);
+    const tag = createTag(wireType, fieldNumber);
+    this.writeUnsignedVarint32_(tag);
   }
 
   /**
@@ -300,6 +301,22 @@
   }
 
   /**
+   * Writes a sfixed64 value field to the buffer.
+   * @param {number} fieldNumber
+   */
+  writeStartGroup(fieldNumber) {
+    this.writeTag(fieldNumber, WireType.START_GROUP);
+  }
+
+  /**
+   * Writes a sfixed64 value field to the buffer.
+   * @param {number} fieldNumber
+   */
+  writeEndGroup(fieldNumber) {
+    this.writeTag(fieldNumber, WireType.END_GROUP);
+  }
+
+  /**
    * Writes a uint32 value field to the buffer as a varint without tag.
    * @param {number} value
    * @private
@@ -430,68 +447,18 @@
    * @param {!BufferDecoder} bufferDecoder
    * @param {number} start
    * @param {!WireType} wireType
+   * @param {number} fieldNumber
    * @package
    */
-  writeBufferDecoder(bufferDecoder, start, wireType) {
+  writeBufferDecoder(bufferDecoder, start, wireType, fieldNumber) {
     this.closeAndStartNewBuffer_();
-    const dataLength = this.getLength_(bufferDecoder, start, wireType);
+    const dataLength =
+        getTagLength(bufferDecoder, start, wireType, fieldNumber);
     this.blocks_.push(
         bufferDecoder.subBufferDecoder(start, dataLength).asUint8Array());
   }
 
   /**
-   * Returns the length of the data to serialize. Returns -1 when a STOP GROUP
-   * is found.
-   * @param {!BufferDecoder} bufferDecoder
-   * @param {number} start
-   * @param {!WireType} wireType
-   * @return {number}
-   * @private
-   */
-  getLength_(bufferDecoder, start, wireType) {
-    switch (wireType) {
-      case WireType.VARINT:
-        bufferDecoder.setCursor(start);
-        bufferDecoder.skipVarint();
-        return bufferDecoder.cursor() - start;
-      case WireType.FIXED64:
-        return 8;
-      case WireType.DELIMITED:
-        const dataLength = bufferDecoder.getUnsignedVarint32At(start);
-        return dataLength + bufferDecoder.cursor() - start;
-      case WireType.START_GROUP:
-        return this.getGroupLength_(bufferDecoder, start);
-      case WireType.FIXED32:
-        return 4;
-      default:
-        throw new Error(`Invalid wire type: ${wireType}`);
-    }
-  }
-
-  /**
-   * Skips over fields until it finds the end of a given group.
-   * @param {!BufferDecoder} bufferDecoder
-   * @param {number} start
-   * @return {number}
-   * @private
-   */
-  getGroupLength_(bufferDecoder, start) {
-    // On a start group we need to keep skipping fields until we find a
-    // corresponding stop group
-    let cursor = start;
-    while (cursor < bufferDecoder.endIndex()) {
-      const tag = bufferDecoder.getUnsignedVarint32At(cursor);
-      const wireType = /** @type {!WireType} */ (tag & 0x07);
-      if (wireType === WireType.END_GROUP) {
-        return bufferDecoder.cursor() - start;
-      }
-      cursor = bufferDecoder.cursor() +
-          this.getLength_(bufferDecoder, bufferDecoder.cursor(), wireType);
-    }
-    throw new Error('No end group found');
-  }
-
-  /**
    * Write the whole bytes as a length delimited field.
    * @param {number} fieldNumber
    * @param {!ArrayBuffer} arrayBuffer
diff --git a/js/experimental/runtime/kernel/writer_test.js b/js/experimental/runtime/kernel/writer_test.js
index 331ab2b..019ae1e 100644
--- a/js/experimental/runtime/kernel/writer_test.js
+++ b/js/experimental/runtime/kernel/writer_test.js
@@ -148,7 +148,7 @@
     const expected = createArrayBuffer(
         0x08, /* varint start= */ 0xFF, /* varint end= */ 0x01, 0x08, 0x01);
     writer.writeBufferDecoder(
-        BufferDecoder.fromArrayBuffer(expected), 1, WireType.VARINT);
+        BufferDecoder.fromArrayBuffer(expected), 1, WireType.VARINT, 1);
     const result = writer.getAndResetResultBuffer();
     expect(result).toEqual(arrayBufferSlice(expected, 1, 3));
   });
@@ -159,7 +159,7 @@
         0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
         /* fixed64 end= */ 0x08, 0x08, 0x01);
     writer.writeBufferDecoder(
-        BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED64);
+        BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED64, 1);
     const result = writer.getAndResetResultBuffer();
     expect(result).toEqual(arrayBufferSlice(expected, 1, 9));
   });
@@ -170,7 +170,7 @@
         0xA, /* length= */ 0x03, /* data start= */ 0x01, 0x02,
         /* data end= */ 0x03, 0x08, 0x01);
     writer.writeBufferDecoder(
-        BufferDecoder.fromArrayBuffer(expected), 1, WireType.DELIMITED);
+        BufferDecoder.fromArrayBuffer(expected), 1, WireType.DELIMITED, 1);
     const result = writer.getAndResetResultBuffer();
     expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
   });
@@ -181,7 +181,7 @@
         0xB, /* group start= */ 0x08, 0x01, /* nested group start= */ 0x0B,
         /* nested group end= */ 0x0C, /* group end= */ 0x0C, 0x08, 0x01);
     writer.writeBufferDecoder(
-        BufferDecoder.fromArrayBuffer(expected), 1, WireType.START_GROUP);
+        BufferDecoder.fromArrayBuffer(expected), 1, WireType.START_GROUP, 1);
     const result = writer.getAndResetResultBuffer();
     expect(result).toEqual(arrayBufferSlice(expected, 1, 6));
   });
@@ -192,7 +192,7 @@
         0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, /* fixed64 end= */ 0x04,
         0x08, 0x01);
     writer.writeBufferDecoder(
-        BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED32);
+        BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED32, 1);
     const result = writer.getAndResetResultBuffer();
     expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
   });
@@ -203,7 +203,7 @@
     const subBuffer = arrayBufferSlice(buffer, 0, 2);
     expect(
         () => writer.writeBufferDecoder(
-            BufferDecoder.fromArrayBuffer(subBuffer), 0, WireType.DELIMITED))
+            BufferDecoder.fromArrayBuffer(subBuffer), 0, WireType.DELIMITED, 1))
         .toThrow();
   });
 });
diff --git a/js/experimental/runtime/testing/binary/test_message.js b/js/experimental/runtime/testing/binary/test_message.js
index a7aa8a1..cfd264b 100644
--- a/js/experimental/runtime/testing/binary/test_message.js
+++ b/js/experimental/runtime/testing/binary/test_message.js
@@ -14,6 +14,13 @@
  */
 class TestMessage {
   /**
+   * @return {!TestMessage}
+   */
+  static createEmpty() {
+    return TestMessage.instanceCreator(Kernel.createEmpty());
+  }
+
+  /**
    * @param {!Kernel} kernel
    * @return {!TestMessage}
    */
@@ -31,7 +38,6 @@
 
   /**
    * @override
-   * @package
    * @return {!Kernel}
    */
   internalGetKernel() {
@@ -1760,4 +1766,4 @@
   }
 }
 
-exports = TestMessage;
\ No newline at end of file
+exports = TestMessage;
diff --git a/js/gulpfile.js b/js/gulpfile.js
index a81c011..dea5f41 100644
--- a/js/gulpfile.js
+++ b/js/gulpfile.js
@@ -71,13 +71,16 @@
   });
 });
 
-gulp.task('genproto_group2_closure', function (cb) {
-  exec(protoc + ' --js_out=library=testproto_libs2,binary:.  -I ../src -I . -I commonjs ' + group2Protos.join(' '),
-       function (err, stdout, stderr) {
-    console.log(stdout);
-    console.log(stderr);
-    cb(err);
-  });
+gulp.task('genproto_group2_closure', function(cb) {
+  exec(
+      protoc +
+          ' --experimental_allow_proto3_optional --js_out=library=testproto_libs2,binary:.  -I ../src -I . -I commonjs ' +
+          group2Protos.join(' '),
+      function(err, stdout, stderr) {
+        console.log(stdout);
+        console.log(stderr);
+        cb(err);
+      });
 });
 
 gulp.task('genproto_well_known_types_commonjs', function (cb) {
@@ -98,13 +101,16 @@
   });
 });
 
-gulp.task('genproto_group2_commonjs', function (cb) {
-  exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' + group2Protos.join(' '),
-       function (err, stdout, stderr) {
-    console.log(stdout);
-    console.log(stderr);
-    cb(err);
-  });
+gulp.task('genproto_group2_commonjs', function(cb) {
+  exec(
+      'mkdir -p commonjs_out && ' + protoc +
+          ' --experimental_allow_proto3_optional --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' +
+          group2Protos.join(' '),
+      function(err, stdout, stderr) {
+        console.log(stdout);
+        console.log(stderr);
+        cb(err);
+      });
 });
 
 gulp.task('genproto_commonjs_wellknowntypes', function (cb) {
@@ -134,21 +140,31 @@
 });
 
 
-function getClosureBuilderCommand(exportsFile, outputFile) {
-  return './node_modules/google-closure-library/closure/bin/build/closurebuilder.py ' +
-  '--root node_modules ' +
-  '-o compiled ' +
-  '--compiler_jar node_modules/google-closure-compiler-java/compiler.jar ' +
-  '-i ' + exportsFile + ' ' +
-  'map.js message.js binary/arith.js binary/constants.js binary/decoder.js ' +
-  'binary/encoder.js binary/reader.js binary/utils.js binary/writer.js ' +
-  exportsFile  + ' > ' + outputFile;
+function getClosureCompilerCommand(exportsFile, outputFile) {
+  const closureLib = 'node_modules/google-closure-library';
+  return [
+    'node_modules/.bin/google-closure-compiler',
+    `--js=${closureLib}/closure/goog/**.js`,
+    `--js=${closureLib}/third_party/closure/goog/**.js`,
+    '--js=map.js',
+    '--js=message.js',
+    '--js=binary/arith.js',
+    '--js=binary/constants.js',
+    '--js=binary/decoder.js',
+    '--js=binary/encoder.js',
+    '--js=binary/reader.js',
+    '--js=binary/utils.js',
+    '--js=binary/writer.js',
+    `--js=${exportsFile}`,
+    `--entry_point=${exportsFile}`,
+    `> ${outputFile}`
+  ].join(' ');
 }
 
 gulp.task('dist', gulp.series(['genproto_wellknowntypes'], function(cb) {
   // TODO(haberman): minify this more aggressively.
   // Will require proper externs/exports.
-  exec(getClosureBuilderCommand('commonjs/export.js', 'google-protobuf.js'),
+  exec(getClosureCompilerCommand('commonjs/export.js', 'google-protobuf.js'),
        function (err, stdout, stderr) {
     console.log(stdout);
     console.log(stderr);
@@ -158,7 +174,7 @@
 
 gulp.task('commonjs_asserts', function (cb) {
   exec('mkdir -p commonjs_out/test_node_modules && ' +
-       getClosureBuilderCommand(
+       getClosureCompilerCommand(
            'commonjs/export_asserts.js',
            'commonjs_out/test_node_modules/closure_asserts_commonjs.js'),
        function (err, stdout, stderr) {
@@ -170,7 +186,7 @@
 
 gulp.task('commonjs_testdeps', function (cb) {
   exec('mkdir -p commonjs_out/test_node_modules && ' +
-       getClosureBuilderCommand(
+       getClosureCompilerCommand(
            'commonjs/export_testdeps.js',
            'commonjs_out/test_node_modules/testdeps_commonjs.js'),
        function (err, stdout, stderr) {
@@ -223,7 +239,7 @@
         ],
         function(cb) {
           exec(
-              './node_modules/google-closure-library/closure/bin/build/depswriter.py binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js',
+              './node_modules/.bin/closure-make-deps --closure-path=. --file=node_modules/google-closure-library/closure/goog/deps.js binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js',
               function(err, stdout, stderr) {
                 console.log(stdout);
                 console.log(stderr);
diff --git a/js/map.js b/js/map.js
index 589a293..61f0f3b 100644
--- a/js/map.js
+++ b/js/map.js
@@ -1,3 +1,4 @@
+
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
@@ -28,6 +29,10 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+/**
+ * @fileoverview
+ * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
+ */
 goog.provide('jspb.Map');
 
 goog.require('goog.asserts');
diff --git a/js/maps_test.js b/js/maps_test.js
index 1cbff7b..68ed683 100644
--- a/js/maps_test.js
+++ b/js/maps_test.js
@@ -53,6 +53,8 @@
 goog.require('proto.jspb.test.MapValueMessageNoBinary');
 goog.require('proto.jspb.test.TestMapFieldsNoBinary');
 
+goog.requireType('jspb.Map');
+
 /**
  * Helper: check that the given map has exactly this set of (sorted) entries.
  * @param {!jspb.Map} map
@@ -116,7 +118,9 @@
     msg.getMapStringMsgMap().get('k').setFoo(42);
     msg.getMapStringMsgMap().get('l').setFoo(84);
     msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
-    msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd');
+    msg.getMapInt64StringMap()
+        .set(0x123456789abc, 'c')
+        .set(0xcba987654321, 'd');
     msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
   };
 
@@ -125,42 +129,24 @@
    * @param {?} msg
    */
   var checkMapFields = function(msg) {
-    checkMapEquals(msg.getMapStringStringMap(), [
-          ['asdf', 'jkl;'],
-          ['key 2', 'hello world']
-    ]);
-    checkMapEquals(msg.getMapStringInt32Map(), [
-          ['a', 1],
-          ['b', -2]
-    ]);
-    checkMapEquals(msg.getMapStringInt64Map(), [
-          ['c', 0x100000000],
-          ['d', 0x200000000]
-    ]);
-    checkMapEquals(msg.getMapStringBoolMap(), [
-          ['e', true],
-          ['f', false]
-    ]);
-    checkMapEquals(msg.getMapStringDoubleMap(), [
-          ['g', 3.14159],
-          ['h', 2.71828]
-    ]);
+    checkMapEquals(
+        msg.getMapStringStringMap(),
+        [['asdf', 'jkl;'], ['key 2', 'hello world']]);
+    checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]);
+    checkMapEquals(
+        msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]);
+    checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]);
+    checkMapEquals(
+        msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]);
     checkMapEquals(msg.getMapStringEnumMap(), [
-          ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
-          ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
+      ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
+      ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
     ]);
-    checkMapEquals(msg.getMapInt32StringMap(), [
-          [-1, 'a'],
-          [42, 'b']
-    ]);
-    checkMapEquals(msg.getMapInt64StringMap(), [
-          [0x123456789abc, 'c'],
-          [0xcba987654321, 'd']
-    ]);
-    checkMapEquals(msg.getMapBoolStringMap(), [
-          [false, 'e'],
-          [true, 'f']
-    ]);
+    checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]);
+    checkMapEquals(
+        msg.getMapInt64StringMap(),
+        [[0x123456789abc, 'c'], [0xcba987654321, 'd']]);
+    checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]);
 
     assertEquals(msg.getMapStringMsgMap().getLength(), 2);
     assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
@@ -205,10 +191,7 @@
     assertElementsEquals(it.next().value, ['asdf', 'hello world']);
     assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
     assertEquals(it.next().done, true);
-    checkMapEquals(m, [
-        ['asdf', 'hello world'],
-        ['jkl;', 'key 2']
-    ]);
+    checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]);
     m.del('jkl;');
     assertEquals(m.has('jkl;'), false);
     assertEquals(m.get('jkl;'), undefined);
@@ -260,11 +243,11 @@
       msg.getMapStringStringMap().set('A', 'a');
       var serialized = msg.serializeBinary();
       var expectedSerialized = [
-          0x0a, 0x6, // field 1 (map_string_string), delimited, length 6
-          0x0a, 0x1, // field 1 in submessage (key), delimited, length 1
-          0x41,      // ASCII 'A'
-          0x12, 0x1, // field 2 in submessage (value), delimited, length 1
-          0x61       // ASCII 'a'
+        0x0a, 0x6,  // field 1 (map_string_string), delimited, length 6
+        0x0a, 0x1,  // field 1 in submessage (key), delimited, length 1
+        0x41,       // ASCII 'A'
+        0x12, 0x1,  // field 2 in submessage (value), delimited, length 1
+        0x61        // ASCII 'a'
       ];
       assertEquals(serialized.length, expectedSerialized.length);
       for (var i = 0; i < serialized.length; i++) {
@@ -284,34 +267,27 @@
      * binary format.
      */
     it('testMapDeserializationForUndefinedKeys', function() {
-      var testMessageOptionalKeys = new proto.jspb.test.TestMapFieldsOptionalKeys();
-      var mapEntryStringKey = new proto.jspb.test.MapEntryOptionalKeysStringKey();
-      mapEntryStringKey.setValue("a");
+      var testMessageOptionalKeys =
+          new proto.jspb.test.TestMapFieldsOptionalKeys();
+      var mapEntryStringKey =
+          new proto.jspb.test.MapEntryOptionalKeysStringKey();
+      mapEntryStringKey.setValue('a');
       testMessageOptionalKeys.setMapStringString(mapEntryStringKey);
       var mapEntryInt32Key = new proto.jspb.test.MapEntryOptionalKeysInt32Key();
-      mapEntryInt32Key.setValue("b");
+      mapEntryInt32Key.setValue('b');
       testMessageOptionalKeys.setMapInt32String(mapEntryInt32Key);
       var mapEntryInt64Key = new proto.jspb.test.MapEntryOptionalKeysInt64Key();
-      mapEntryInt64Key.setValue("c");
+      mapEntryInt64Key.setValue('c');
       testMessageOptionalKeys.setMapInt64String(mapEntryInt64Key);
       var mapEntryBoolKey = new proto.jspb.test.MapEntryOptionalKeysBoolKey();
-      mapEntryBoolKey.setValue("d");
+      mapEntryBoolKey.setValue('d');
       testMessageOptionalKeys.setMapBoolString(mapEntryBoolKey);
-      var deserializedMessage = msgInfo.deserializeBinary(
-        testMessageOptionalKeys.serializeBinary()
-       );
-      checkMapEquals(deserializedMessage.getMapStringStringMap(), [
-        ['', 'a']
-      ]);
-      checkMapEquals(deserializedMessage.getMapInt32StringMap(), [
-        [0, 'b']
-      ]);
-      checkMapEquals(deserializedMessage.getMapInt64StringMap(), [
-        [0, 'c']
-      ]);
-      checkMapEquals(deserializedMessage.getMapBoolStringMap(), [
-        [false, 'd']
-      ]);
+      var deserializedMessage =
+          msgInfo.deserializeBinary(testMessageOptionalKeys.serializeBinary());
+      checkMapEquals(deserializedMessage.getMapStringStringMap(), [['', 'a']]);
+      checkMapEquals(deserializedMessage.getMapInt32StringMap(), [[0, 'b']]);
+      checkMapEquals(deserializedMessage.getMapInt64StringMap(), [[0, 'c']]);
+      checkMapEquals(deserializedMessage.getMapBoolStringMap(), [[false, 'd']]);
     });
 
     /**
@@ -323,56 +299,41 @@
           new proto.jspb.test.TestMapFieldsOptionalValues();
       var mapEntryStringValue =
           new proto.jspb.test.MapEntryOptionalValuesStringValue();
-      mapEntryStringValue.setKey("a");
+      mapEntryStringValue.setKey('a');
       testMessageOptionalValues.setMapStringString(mapEntryStringValue);
       var mapEntryInt32Value =
           new proto.jspb.test.MapEntryOptionalValuesInt32Value();
-      mapEntryInt32Value.setKey("b");
+      mapEntryInt32Value.setKey('b');
       testMessageOptionalValues.setMapStringInt32(mapEntryInt32Value);
       var mapEntryInt64Value =
           new proto.jspb.test.MapEntryOptionalValuesInt64Value();
-      mapEntryInt64Value.setKey("c");
+      mapEntryInt64Value.setKey('c');
       testMessageOptionalValues.setMapStringInt64(mapEntryInt64Value);
       var mapEntryBoolValue =
           new proto.jspb.test.MapEntryOptionalValuesBoolValue();
-      mapEntryBoolValue.setKey("d");
+      mapEntryBoolValue.setKey('d');
       testMessageOptionalValues.setMapStringBool(mapEntryBoolValue);
       var mapEntryDoubleValue =
           new proto.jspb.test.MapEntryOptionalValuesDoubleValue();
-      mapEntryDoubleValue.setKey("e");
+      mapEntryDoubleValue.setKey('e');
       testMessageOptionalValues.setMapStringDouble(mapEntryDoubleValue);
       var mapEntryEnumValue =
           new proto.jspb.test.MapEntryOptionalValuesEnumValue();
-      mapEntryEnumValue.setKey("f");
+      mapEntryEnumValue.setKey('f');
       testMessageOptionalValues.setMapStringEnum(mapEntryEnumValue);
       var mapEntryMessageValue =
           new proto.jspb.test.MapEntryOptionalValuesMessageValue();
-      mapEntryMessageValue.setKey("g");
+      mapEntryMessageValue.setKey('g');
       testMessageOptionalValues.setMapStringMsg(mapEntryMessageValue);
       var deserializedMessage = msgInfo.deserializeBinary(
-        testMessageOptionalValues.serializeBinary()
-       );
-      checkMapEquals(deserializedMessage.getMapStringStringMap(), [
-        ['a', '']
-      ]);
-      checkMapEquals(deserializedMessage.getMapStringInt32Map(), [
-        ['b', 0]
-      ]);
-      checkMapEquals(deserializedMessage.getMapStringInt64Map(), [
-        ['c', 0]
-      ]);
-      checkMapEquals(deserializedMessage.getMapStringBoolMap(), [
-        ['d', false]
-      ]);
-      checkMapEquals(deserializedMessage.getMapStringDoubleMap(), [
-        ['e', 0.0]
-      ]);
-      checkMapEquals(deserializedMessage.getMapStringEnumMap(), [
-        ['f', 0]
-      ]);
-      checkMapEquals(deserializedMessage.getMapStringMsgMap(), [
-        ['g', []]
-      ]);
+          testMessageOptionalValues.serializeBinary());
+      checkMapEquals(deserializedMessage.getMapStringStringMap(), [['a', '']]);
+      checkMapEquals(deserializedMessage.getMapStringInt32Map(), [['b', 0]]);
+      checkMapEquals(deserializedMessage.getMapStringInt64Map(), [['c', 0]]);
+      checkMapEquals(deserializedMessage.getMapStringBoolMap(), [['d', false]]);
+      checkMapEquals(deserializedMessage.getMapStringDoubleMap(), [['e', 0.0]]);
+      checkMapEquals(deserializedMessage.getMapStringEnumMap(), [['f', 0]]);
+      checkMapEquals(deserializedMessage.getMapStringMsgMap(), [['g', []]]);
     });
   }
 
@@ -382,11 +343,7 @@
    */
   it('testLazyMapSync' + suffix, function() {
     // Start with a JSPB array containing a few map entries.
-    var entries = [
-        ['a', 'entry 1'],
-        ['c', 'entry 2'],
-        ['b', 'entry 3']
-    ];
+    var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']];
     var msg = new msgInfo.constructor([entries]);
     assertEquals(entries.length, 3);
     assertEquals(entries[0][0], 'a');
@@ -394,9 +351,9 @@
     assertEquals(entries[2][0], 'b');
     msg.getMapStringStringMap().del('a');
     assertEquals(entries.length, 3);  // not yet sync'd
-    msg.toArray();                // force a sync
+    msg.toArray();                    // force a sync
     assertEquals(entries.length, 2);
-    assertEquals(entries[0][0], 'b'); // now in sorted order
+    assertEquals(entries[0][0], 'b');  // now in sorted order
     assertEquals(entries[1][0], 'c');
 
     var a = msg.toArray();
diff --git a/js/message.js b/js/message.js
index c1736b3..905329f 100644
--- a/js/message.js
+++ b/js/message.js
@@ -31,6 +31,7 @@
 /**
  * @fileoverview Definition of jspb.Message.
  *
+ * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
  * @author mwr@google.com (Mark Rawling)
  */
 
@@ -417,7 +418,7 @@
  */
 jspb.Message.isArray_ = function(o) {
   return jspb.Message.ASSUME_LOCAL_ARRAYS ? o instanceof Array :
-                                            goog.isArray(o);
+                                            Array.isArray(o);
 };
 
 /**
@@ -1433,7 +1434,7 @@
   if (this.wrappers_) {
     for (var fieldNumber in this.wrappers_) {
       var val = this.wrappers_[fieldNumber];
-      if (goog.isArray(val)) {
+      if (Array.isArray(val)) {
         for (var i = 0; i < val.length; i++) {
           if (val[i]) {
             val[i].toArray();
@@ -1823,7 +1824,7 @@
  */
 jspb.Message.clone_ = function(obj) {
   var o;
-  if (goog.isArray(obj)) {
+  if (Array.isArray(obj)) {
     // Allocate array of correct size.
     var clonedArray = new Array(obj.length);
     // Use array iteration where possible because it is faster than for-in.
diff --git a/js/message_test.js b/js/message_test.js
index 3db8716..2a524de 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -121,6 +121,8 @@
 // CommonJS-LoadFromFile: testlargenumbers_pb proto.jspb.test
 goog.require('proto.jspb.test.MessageWithLargeFieldNumbers');
 
+goog.require('proto.jspb.test.simple1');
+
 describe('Message test suite', function() {
   var stubs = new goog.testing.PropertyReplacer();
 
@@ -185,7 +187,6 @@
           $jspbMessageInstance: foo
         },
         result);
-
   });
 
   it('testMissingFields', function() {
@@ -209,7 +210,6 @@
           aFloatingPointField: undefined,
         },
         result);
-
   });
 
   it('testNestedComplexMessage', function() {
@@ -1108,5 +1108,4 @@
     message.setAInt(42);
     assertEquals(42, message.getAInt());
   });
-
 });
diff --git a/js/package.json b/js/package.json
index 14186be..8121aac 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
 {
   "name": "google-protobuf",
-  "version": "3.11.4",
+  "version": "3.17.3",
   "description": "Protocol Buffers for JavaScript",
   "main": "google-protobuf.js",
   "files": [
@@ -10,6 +10,7 @@
   "devDependencies": {
     "glob": "~7.1.4",
     "google-closure-compiler": "~20190819.0.0",
+    "google-closure-deps": "^20210406.0.0",
     "google-closure-library": "~20190819.0.0",
     "gulp": "~4.0.2",
     "jasmine": "~3.4.0"
diff --git a/js/proto3_test.js b/js/proto3_test.js
index 79acc3c..8de1575 100644
--- a/js/proto3_test.js
+++ b/js/proto3_test.js
@@ -41,7 +41,7 @@
 goog.require('proto.google.protobuf.Timestamp');
 // CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf
 goog.require('proto.google.protobuf.Struct');
-
+goog.require('jspb.Message');
 
 var BYTES = new Uint8Array([1, 2, 8, 9]);
 var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
@@ -70,14 +70,13 @@
 
 
 describe('proto3Test', function() {
-
   /**
    * Test default values don't affect equality test.
    */
   it('testEqualsProto3', function() {
     var msg1 = new proto.jspb.test.TestProto3();
     var msg2 = new proto.jspb.test.TestProto3();
-    msg2.setOptionalString('');
+    msg2.setSingularString('');
 
     assertTrue(jspb.Message.equals(msg1, msg2));
   });
@@ -90,12 +89,12 @@
     var msg = new proto.jspb.test.TestProto3();
 
     // Setting should work normally.
-    msg.setOptionalString('optionalString');
-    assertEquals(msg.getOptionalString(), 'optionalString');
+    msg.setSingularString('optionalString');
+    assertEquals(msg.getSingularString(), 'optionalString');
 
     // Clearing should work too ...
-    msg.setOptionalString('');
-    assertEquals(msg.getOptionalString(), '');
+    msg.setSingularString('');
+    assertEquals(msg.getSingularString(), '');
 
     // ... and shouldn't affect the equality with a brand new message.
     assertTrue(jspb.Message.equals(msg, new proto.jspb.test.TestProto3()));
@@ -107,6 +106,58 @@
   it('testProto3FieldDefaults', function() {
     var msg = new proto.jspb.test.TestProto3();
 
+    assertEquals(msg.getSingularInt32(), 0);
+    assertEquals(msg.getSingularInt64(), 0);
+    assertEquals(msg.getSingularUint32(), 0);
+    assertEquals(msg.getSingularUint64(), 0);
+    assertEquals(msg.getSingularSint32(), 0);
+    assertEquals(msg.getSingularSint64(), 0);
+    assertEquals(msg.getSingularFixed32(), 0);
+    assertEquals(msg.getSingularFixed64(), 0);
+    assertEquals(msg.getSingularSfixed32(), 0);
+    assertEquals(msg.getSingularSfixed64(), 0);
+    assertEquals(msg.getSingularFloat(), 0);
+    assertEquals(msg.getSingularDouble(), 0);
+    assertEquals(msg.getSingularString(), '');
+
+    // TODO(b/26173701): when we change bytes fields default getter to return
+    // Uint8Array, we'll want to switch this assertion to match the u8 case.
+    assertEquals(typeof msg.getSingularBytes(), 'string');
+    assertEquals(msg.getSingularBytes_asU8() instanceof Uint8Array, true);
+    assertEquals(typeof msg.getSingularBytes_asB64(), 'string');
+    assertEquals(msg.getSingularBytes().length, 0);
+    assertEquals(msg.getSingularBytes_asU8().length, 0);
+    assertEquals(msg.getSingularBytes_asB64(), '');
+
+    assertEquals(
+        msg.getSingularForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    assertEquals(msg.getSingularForeignMessage(), undefined);
+    assertEquals(msg.getSingularForeignMessage(), undefined);
+
+    assertEquals(msg.getRepeatedInt32List().length, 0);
+    assertEquals(msg.getRepeatedInt64List().length, 0);
+    assertEquals(msg.getRepeatedUint32List().length, 0);
+    assertEquals(msg.getRepeatedUint64List().length, 0);
+    assertEquals(msg.getRepeatedSint32List().length, 0);
+    assertEquals(msg.getRepeatedSint64List().length, 0);
+    assertEquals(msg.getRepeatedFixed32List().length, 0);
+    assertEquals(msg.getRepeatedFixed64List().length, 0);
+    assertEquals(msg.getRepeatedSfixed32List().length, 0);
+    assertEquals(msg.getRepeatedSfixed64List().length, 0);
+    assertEquals(msg.getRepeatedFloatList().length, 0);
+    assertEquals(msg.getRepeatedDoubleList().length, 0);
+    assertEquals(msg.getRepeatedStringList().length, 0);
+    assertEquals(msg.getRepeatedBytesList().length, 0);
+    assertEquals(msg.getRepeatedForeignEnumList().length, 0);
+    assertEquals(msg.getRepeatedForeignMessageList().length, 0);
+  });
+
+  /**
+   * Test presence for proto3 optional fields.
+   */
+  it('testProto3Optional', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
     assertEquals(msg.getOptionalInt32(), 0);
     assertEquals(msg.getOptionalInt64(), 0);
     assertEquals(msg.getOptionalUint32(), 0);
@@ -130,56 +181,70 @@
     assertEquals(msg.getOptionalBytes_asU8().length, 0);
     assertEquals(msg.getOptionalBytes_asB64(), '');
 
-    assertEquals(msg.getOptionalForeignEnum(),
-                 proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    assertEquals(
+        msg.getOptionalForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO);
     assertEquals(msg.getOptionalForeignMessage(), undefined);
     assertEquals(msg.getOptionalForeignMessage(), undefined);
 
-    assertEquals(msg.getRepeatedInt32List().length, 0);
-    assertEquals(msg.getRepeatedInt64List().length, 0);
-    assertEquals(msg.getRepeatedUint32List().length, 0);
-    assertEquals(msg.getRepeatedUint64List().length, 0);
-    assertEquals(msg.getRepeatedSint32List().length, 0);
-    assertEquals(msg.getRepeatedSint64List().length, 0);
-    assertEquals(msg.getRepeatedFixed32List().length, 0);
-    assertEquals(msg.getRepeatedFixed64List().length, 0);
-    assertEquals(msg.getRepeatedSfixed32List().length, 0);
-    assertEquals(msg.getRepeatedSfixed64List().length, 0);
-    assertEquals(msg.getRepeatedFloatList().length, 0);
-    assertEquals(msg.getRepeatedDoubleList().length, 0);
-    assertEquals(msg.getRepeatedStringList().length, 0);
-    assertEquals(msg.getRepeatedBytesList().length, 0);
-    assertEquals(msg.getRepeatedForeignEnumList().length, 0);
-    assertEquals(msg.getRepeatedForeignMessageList().length, 0);
+    // Serializing an empty proto yields the empty string.
+    assertEquals(msg.serializeBinary().length, 0);
 
+    // Values start as unset, but can be explicitly set even to default values
+    // like 0.
+    assertFalse(msg.hasOptionalInt32());
+    msg.setOptionalInt32(0);
+    assertTrue(msg.hasOptionalInt32());
+
+    assertFalse(msg.hasOptionalInt64());
+    msg.setOptionalInt64(0);
+    assertTrue(msg.hasOptionalInt64());
+
+    assertFalse(msg.hasOptionalString());
+    msg.setOptionalString('');
+    assertTrue(msg.hasOptionalString());
+
+    // Now the proto will have a non-zero size, even though its values are 0.
+    var serialized = msg.serializeBinary();
+    assertNotEquals(serialized.length, 0);
+
+    var msg2 = proto.jspb.test.TestProto3.deserializeBinary(serialized);
+    assertTrue(msg2.hasOptionalInt32());
+    assertTrue(msg2.hasOptionalInt64());
+    assertTrue(msg2.hasOptionalString());
+
+    // We can clear fields to go back to empty.
+    msg2.clearOptionalInt32();
+    assertFalse(msg2.hasOptionalInt32());
+
+    msg2.clearOptionalString();
+    assertFalse(msg2.hasOptionalString());
   });
 
-
   /**
-   * Test that all fields can be set and read via a serialization roundtrip.
+   * Test that all fields can be set ,and read via a serialization roundtrip.
    */
   it('testProto3FieldSetGet', function() {
     var msg = new proto.jspb.test.TestProto3();
 
-    msg.setOptionalInt32(-42);
-    msg.setOptionalInt64(-0x7fffffff00000000);
-    msg.setOptionalUint32(0x80000000);
-    msg.setOptionalUint64(0xf000000000000000);
-    msg.setOptionalSint32(-100);
-    msg.setOptionalSint64(-0x8000000000000000);
-    msg.setOptionalFixed32(1234);
-    msg.setOptionalFixed64(0x1234567800000000);
-    msg.setOptionalSfixed32(-1234);
-    msg.setOptionalSfixed64(-0x1234567800000000);
-    msg.setOptionalFloat(1.5);
-    msg.setOptionalDouble(-1.5);
-    msg.setOptionalBool(true);
-    msg.setOptionalString('hello world');
-    msg.setOptionalBytes(BYTES);
+    msg.setSingularInt32(-42);
+    msg.setSingularInt64(-0x7fffffff00000000);
+    msg.setSingularUint32(0x80000000);
+    msg.setSingularUint64(0xf000000000000000);
+    msg.setSingularSint32(-100);
+    msg.setSingularSint64(-0x8000000000000000);
+    msg.setSingularFixed32(1234);
+    msg.setSingularFixed64(0x1234567800000000);
+    msg.setSingularSfixed32(-1234);
+    msg.setSingularSfixed64(-0x1234567800000000);
+    msg.setSingularFloat(1.5);
+    msg.setSingularDouble(-1.5);
+    msg.setSingularBool(true);
+    msg.setSingularString('hello world');
+    msg.setSingularBytes(BYTES);
     var submsg = new proto.jspb.test.ForeignMessage();
     submsg.setC(16);
-    msg.setOptionalForeignMessage(submsg);
-    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+    msg.setSingularForeignMessage(submsg);
+    msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
 
     msg.setRepeatedInt32List([-42]);
     msg.setRepeatedInt64List([-0x7fffffff00000000]);
@@ -206,24 +271,24 @@
     var serialized = msg.serializeBinary();
     msg = proto.jspb.test.TestProto3.deserializeBinary(serialized);
 
-    assertEquals(msg.getOptionalInt32(), -42);
-    assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000);
-    assertEquals(msg.getOptionalUint32(), 0x80000000);
-    assertEquals(msg.getOptionalUint64(), 0xf000000000000000);
-    assertEquals(msg.getOptionalSint32(), -100);
-    assertEquals(msg.getOptionalSint64(), -0x8000000000000000);
-    assertEquals(msg.getOptionalFixed32(), 1234);
-    assertEquals(msg.getOptionalFixed64(), 0x1234567800000000);
-    assertEquals(msg.getOptionalSfixed32(), -1234);
-    assertEquals(msg.getOptionalSfixed64(), -0x1234567800000000);
-    assertEquals(msg.getOptionalFloat(), 1.5);
-    assertEquals(msg.getOptionalDouble(), -1.5);
-    assertEquals(msg.getOptionalBool(), true);
-    assertEquals(msg.getOptionalString(), 'hello world');
-    assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES));
-    assertEquals(msg.getOptionalForeignMessage().getC(), 16);
-    assertEquals(msg.getOptionalForeignEnum(),
-        proto.jspb.test.Proto3Enum.PROTO3_BAR);
+    assertEquals(msg.getSingularInt32(), -42);
+    assertEquals(msg.getSingularInt64(), -0x7fffffff00000000);
+    assertEquals(msg.getSingularUint32(), 0x80000000);
+    assertEquals(msg.getSingularUint64(), 0xf000000000000000);
+    assertEquals(msg.getSingularSint32(), -100);
+    assertEquals(msg.getSingularSint64(), -0x8000000000000000);
+    assertEquals(msg.getSingularFixed32(), 1234);
+    assertEquals(msg.getSingularFixed64(), 0x1234567800000000);
+    assertEquals(msg.getSingularSfixed32(), -1234);
+    assertEquals(msg.getSingularSfixed64(), -0x1234567800000000);
+    assertEquals(msg.getSingularFloat(), 1.5);
+    assertEquals(msg.getSingularDouble(), -1.5);
+    assertEquals(msg.getSingularBool(), true);
+    assertEquals(msg.getSingularString(), 'hello world');
+    assertEquals(true, bytesCompare(msg.getSingularBytes(), BYTES));
+    assertEquals(msg.getSingularForeignMessage().getC(), 16);
+    assertEquals(
+        msg.getSingularForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_BAR);
 
     assertElementsEquals(msg.getRepeatedInt32List(), [-42]);
     assertElementsEquals(msg.getRepeatedInt64List(), [-0x7fffffff00000000]);
@@ -243,7 +308,8 @@
     assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
     assertEquals(msg.getRepeatedForeignMessageList().length, 1);
     assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000);
-    assertElementsEquals(msg.getRepeatedForeignEnumList(),
+    assertElementsEquals(
+        msg.getRepeatedForeignEnumList(),
         [proto.jspb.test.Proto3Enum.PROTO3_BAR]);
 
     assertEquals(msg.getOneofString(), 'asdf');
@@ -308,7 +374,8 @@
     assertEquals(msg.getOneofUint32(), 0);
     assertEquals(msg.getOneofForeignMessage(), undefined);
     assertEquals(msg.getOneofString(), '');
-    assertEquals(msg.getOneofBytes_asB64(),
+    assertEquals(
+        msg.getOneofBytes_asB64(),
         goog.crypt.base64.encodeString('\u00FF\u00FF'));
 
     assertFalse(msg.hasOneofUint32());
@@ -327,20 +394,20 @@
     // Set each primitive to a non-default value, then back to its default, to
     // ensure that the serialization is actually checking the value and not just
     // whether it has ever been set.
-    msg.setOptionalInt32(42);
-    msg.setOptionalInt32(0);
-    msg.setOptionalDouble(3.14);
-    msg.setOptionalDouble(0.0);
-    msg.setOptionalBool(true);
-    msg.setOptionalBool(false);
-    msg.setOptionalString('hello world');
-    msg.setOptionalString('');
-    msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
-    msg.setOptionalBytes('');
-    msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage());
-    msg.setOptionalForeignMessage(null);
-    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
-    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    msg.setSingularInt32(42);
+    msg.setSingularInt32(0);
+    msg.setSingularDouble(3.14);
+    msg.setSingularDouble(0.0);
+    msg.setSingularBool(true);
+    msg.setSingularBool(false);
+    msg.setSingularString('hello world');
+    msg.setSingularString('');
+    msg.setSingularBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+    msg.setSingularBytes('');
+    msg.setSingularForeignMessage(new proto.jspb.test.ForeignMessage());
+    msg.setSingularForeignMessage(null);
+    msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+    msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
     msg.setOneofUint32(32);
     msg.clearOneofUint32();
 
@@ -355,27 +422,25 @@
   it('testBytesFieldsInterop', function() {
     var msg = new proto.jspb.test.TestProto3();
     // Set as a base64 string and check all the getters work.
-    msg.setOptionalBytes(BYTES_B64);
-    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
-    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
-    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+    msg.setSingularBytes(BYTES_B64);
+    assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getSingularBytes(), BYTES));
 
     // Test binary serialize round trip doesn't break it.
     msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary());
-    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
-    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
-    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+    assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getSingularBytes(), BYTES));
 
     msg = new proto.jspb.test.TestProto3();
     // Set as a Uint8Array and check all the getters work.
-    msg.setOptionalBytes(BYTES);
-    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
-    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
-    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
-
+    msg.setSingularBytes(BYTES);
+    assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getSingularBytes(), BYTES));
   });
 
-
   it('testTimestampWellKnownType', function() {
     var msg = new proto.google.protobuf.Timestamp();
     msg.fromDate(new Date(123456789));
@@ -390,24 +455,24 @@
 
   it('testStructWellKnownType', function() {
     var jsObj = {
-      abc: "def",
+      abc: 'def',
       number: 12345.678,
       nullKey: null,
       boolKey: true,
-      listKey: [1, null, true, false, "abc"],
-      structKey: {foo: "bar", somenum: 123},
-      complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, "zzz"]
+      listKey: [1, null, true, false, 'abc'],
+      structKey: {foo: 'bar', somenum: 123},
+      complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, 'zzz']
     };
 
     var struct = proto.google.protobuf.Struct.fromJavaScript(jsObj);
     var jsObj2 = struct.toJavaScript();
 
-    assertEquals("def", jsObj2.abc);
+    assertEquals('def', jsObj2.abc);
     assertEquals(12345.678, jsObj2.number);
     assertEquals(null, jsObj2.nullKey);
     assertEquals(true, jsObj2.boolKey);
-    assertEquals("abc", jsObj2.listKey[4]);
-    assertEquals("bar", jsObj2.structKey.foo);
+    assertEquals('abc', jsObj2.listKey[4]);
+    assertEquals('bar', jsObj2.structKey.foo);
     assertEquals(4, jsObj2.complicatedKey[0].xyz.abc[1]);
   });
 });
diff --git a/js/proto3_test.proto b/js/proto3_test.proto
index f23e19c..14f104e 100644
--- a/js/proto3_test.proto
+++ b/js/proto3_test.proto
@@ -30,29 +30,48 @@
 
 syntax = "proto3";
 
-import "testbinary.proto";
-
 package jspb.test;
 
-message TestProto3 {
-  int32 optional_int32 = 1;
-  int64 optional_int64 = 2;
-  uint32 optional_uint32 = 3;
-  uint64 optional_uint64 = 4;
-  sint32 optional_sint32 = 5;
-  sint64 optional_sint64 = 6;
-  fixed32 optional_fixed32 = 7;
-  fixed64 optional_fixed64 = 8;
-  sfixed32 optional_sfixed32 = 9;
-  sfixed64 optional_sfixed64 = 10;
-  float optional_float = 11;
-  double optional_double = 12;
-  bool optional_bool = 13;
-  string optional_string = 14;
-  bytes optional_bytes = 15;
+import "testbinary.proto";
 
-  ForeignMessage optional_foreign_message = 19;
-  Proto3Enum optional_foreign_enum = 22;
+message TestProto3 {
+  int32 singular_int32 = 1;
+  int64 singular_int64 = 2;
+  uint32 singular_uint32 = 3;
+  uint64 singular_uint64 = 4;
+  sint32 singular_sint32 = 5;
+  sint64 singular_sint64 = 6;
+  fixed32 singular_fixed32 = 7;
+  fixed64 singular_fixed64 = 8;
+  sfixed32 singular_sfixed32 = 9;
+  sfixed64 singular_sfixed64 = 10;
+  float singular_float = 11;
+  double singular_double = 12;
+  bool singular_bool = 13;
+  string singular_string = 14;
+  bytes singular_bytes = 15;
+
+  ForeignMessage singular_foreign_message = 19;
+  Proto3Enum singular_foreign_enum = 22;
+
+  optional int32 optional_int32 = 121;
+  optional int64 optional_int64 = 122;
+  optional uint32 optional_uint32 = 123;
+  optional uint64 optional_uint64 = 124;
+  optional sint32 optional_sint32 = 125;
+  optional sint64 optional_sint64 = 126;
+  optional fixed32 optional_fixed32 = 127;
+  optional fixed64 optional_fixed64 = 128;
+  optional sfixed32 optional_sfixed32 = 129;
+  optional sfixed64 optional_sfixed64 = 130;
+  optional float optional_float = 131;
+  optional double optional_double = 132;
+  optional bool optional_bool = 133;
+  optional string optional_string = 134;
+  optional bytes optional_bytes = 135;
+
+  optional ForeignMessage optional_foreign_message = 136;
+  optional Proto3Enum optional_foreign_enum = 137;
 
   repeated int32 repeated_int32 = 31;
   repeated int64 repeated_int64 = 32;
@@ -73,7 +92,6 @@
   repeated ForeignMessage repeated_foreign_message = 49;
   repeated Proto3Enum repeated_foreign_enum = 52;
 
-
   oneof oneof_field {
     uint32 oneof_uint32 = 111;
     ForeignMessage oneof_foreign_message = 112;
diff --git a/kokoro/README.md b/kokoro/README.md
index 0791c92..590d7bd 100644
--- a/kokoro/README.md
+++ b/kokoro/README.md
@@ -3,4 +3,10 @@
 ----------------------
 
 The files in this directory serve as plumbing for running Protobuf
-tests under Kokoro, our internal CI.
\ No newline at end of file
+tests under Kokoro, our internal CI.
+
+We have shared this part of our CI configuration in hopes that it is
+helpful to contributors who want to better understand the details of
+our test and release processes. If there are changes, please file an
+issue; unfortunately, we may not be able to accept PRs (but feel free
+to send one if it helps to explain the issue).
diff --git a/kokoro/docs/publish-python.sh b/kokoro/docs/publish-python.sh
index eea1755..457a24f 100755
--- a/kokoro/docs/publish-python.sh
+++ b/kokoro/docs/publish-python.sh
@@ -14,10 +14,10 @@
 sudo add-apt-repository universe
 sudo apt-get update
 sudo apt-get -y install unzip
-wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.2/protoc-3.11.2-linux-x86_64.zip
-unzip protoc-3.11.2-linux-x86_64.zip bin/protoc
+wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.8/protoc-3.15.8-linux-x86_64.zip
+unzip protoc-3.15.8-linux-x86_64.zip bin/protoc
 mv bin/protoc ../src/protoc
-python3.6 -m venv venv
+python3 -m venv venv
 source venv/bin/activate
 python setup.py install
 
@@ -30,13 +30,13 @@
 cd ..
 deactivate
 
-python3.6 -m pip install protobuf==3.11.1 gcp-docuploader
+python3 -m pip install protobuf==3.15.8 gcp-docuploader
 
 # install a json parser
 sudo apt-get -y install jq
 
 # create metadata
-python3.6 -m docuploader create-metadata \
+python3 -m docuploader create-metadata \
   --name=$(jq --raw-output '.name // empty' .repo-metadata.json) \
   --version=$(python3 setup.py --version) \
   --language=$(jq --raw-output '.language // empty' .repo-metadata.json) \
@@ -48,4 +48,4 @@
 cat docs.metadata
 
 # upload docs
-python3.6 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket docs-staging
+python3 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket docs-staging
diff --git a/kokoro/linux/aarch64/cpp_crosscompile_and_run_tests_with_qemu_aarch64.sh b/kokoro/linux/aarch64/cpp_crosscompile_and_run_tests_with_qemu_aarch64.sh
new file mode 100755
index 0000000..425cc90
--- /dev/null
+++ b/kokoro/linux/aarch64/cpp_crosscompile_and_run_tests_with_qemu_aarch64.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Builds protobuf C++ with aarch64 crosscompiler and runs a basic set of tests under an emulator.
+# NOTE: This script is expected to run under the dockcross/linux-arm64 docker image.
+
+set -ex
+
+mkdir -p cmake/crossbuild_aarch64
+cd cmake/crossbuild_aarch64
+
+# the build commands are expected to run under dockcross docker image
+# where the CC, CXX and other toolchain variables already point to the crosscompiler
+cmake ..
+make -j8
+
+# check that the resulting test binary is indeed an aarch64 ELF
+(file ./tests | grep -q "ELF 64-bit LSB executable, ARM aarch64") || (echo "Test binary in not an aarch64 binary"; exit 1)
+
+# run the basic set of C++ tests under QEMU
+# there are other tests we could run (e.g. ./lite-test), but this is sufficient as a smoketest
+qemu-aarch64 ./tests
diff --git a/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_linux_aarch64.sh b/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_linux_aarch64.sh
new file mode 100755
index 0000000..70a0d7c
--- /dev/null
+++ b/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_linux_aarch64.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+set -e
+
+# go to the repo root
+cd $(dirname $0)/../../../..
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# running dockcross image without any arguments generates a wrapper
+# scripts that can be used to run commands under the dockcross image
+# easily.
+# See https://github.com/dockcross/dockcross#usage for details
+docker run $DOCKER_TTY_ARGS --rm dockcross/linux-arm64 >dockcross-linux-arm64.sh
+chmod +x dockcross-linux-arm64.sh
+
+# the wrapper script has CRLF line endings and bash doesn't like that
+# so we change CRLF line endings into LF.
+sed -i 's/\r//g' dockcross-linux-arm64.sh
+
+# The dockcross wrapper script runs arbitrary commands under the selected dockcross
+# image with the following properties which make its use very convenient:
+# * the current working directory is mounted under /work so the container can easily
+#   access the current workspace
+# * the processes in the container run under the same UID and GID as the host process so unlike
+#   vanilla "docker run" invocations, the workspace doesn't get polluted with files
+#   owned by root.
+./dockcross-linux-arm64.sh "$@"
diff --git a/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh b/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh
new file mode 100755
index 0000000..115478b
--- /dev/null
+++ b/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+set -e
+
+# go to the repo root
+cd $(dirname $0)/../../../..
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# running dockcross image without any arguments generates a wrapper
+# scripts that can be used to run commands under the dockcross image
+# easily.
+# See https://github.com/dockcross/dockcross#usage for details
+docker run $DOCKER_TTY_ARGS --rm dockcross/manylinux2014-aarch64 >dockcross-manylinux2014-aarch64.sh
+chmod +x dockcross-manylinux2014-aarch64.sh
+
+# the wrapper script has CRLF line endings and bash doesn't like that
+# so we change CRLF line endings into LF.
+sed -i 's/\r//g' dockcross-manylinux2014-aarch64.sh
+
+# The dockcross wrapper script runs arbitrary commands under the selected dockcross
+# image with the following properties which make its use very convenient:
+# * the current working directory is mounted under /work so the container can easily
+#   access the current workspace
+# * the processes in the container run under the same UID and GID as the host process so unlike
+#   vanilla "docker run" invocations, the workspace doesn't get polluted with files
+#   owned by root.
+./dockcross-manylinux2014-aarch64.sh "$@"
diff --git a/kokoro/linux/aarch64/javascript_build_and_run_tests_with_qemu_aarch64.sh b/kokoro/linux/aarch64/javascript_build_and_run_tests_with_qemu_aarch64.sh
new file mode 100755
index 0000000..c4eb7d8
--- /dev/null
+++ b/kokoro/linux/aarch64/javascript_build_and_run_tests_with_qemu_aarch64.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -ex
+
+# install the same version of node as in /tests.sh
+NODE_VERSION=node-v12.16.3-linux-arm64
+NODE_TGZ="$NODE_VERSION.tar.gz"
+pushd /tmp
+curl -OL https://nodejs.org/dist/v12.16.3/$NODE_TGZ
+tar zxvf $NODE_TGZ
+export PATH=$PATH:`pwd`/$NODE_VERSION/bin
+popd
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+cd js
+npm install
+npm test
diff --git a/kokoro/linux/aarch64/php_build_and_run_tests_with_qemu_aarch64.sh b/kokoro/linux/aarch64/php_build_and_run_tests_with_qemu_aarch64.sh
new file mode 100755
index 0000000..bcb3d9d
--- /dev/null
+++ b/kokoro/linux/aarch64/php_build_and_run_tests_with_qemu_aarch64.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -ex
+
+# Install composer
+curl -sS https://getcomposer.org/installer | php
+mkdir -p "$HOME/bin"
+mv composer.phar "$HOME/bin/composer"
+PATH="$HOME/bin:$PATH"
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+cd php
+
+composer install
+composer test
+composer test_c
diff --git a/kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh b/kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
new file mode 100755
index 0000000..77942a4
--- /dev/null
+++ b/kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+#
+# Builds protobuf C++ with aarch64 crosscompiler.
+
+set -ex
+
+./autogen.sh
+CXXFLAGS="-fPIC -g -O2" ./configure --host=aarch64
+make -j8
diff --git a/kokoro/linux/aarch64/python_crosscompile_aarch64.sh b/kokoro/linux/aarch64/python_crosscompile_aarch64.sh
new file mode 100755
index 0000000..db2e776
--- /dev/null
+++ b/kokoro/linux/aarch64/python_crosscompile_aarch64.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Builds protobuf python including the C++ extension with aarch64 crosscompiler.
+# The outputs of this script are laid out so that we can later test them under an aarch64 emulator.
+# NOTE: This script is expected to run under the dockcross/manylinux2014-aarch64 docker image.
+
+set -ex
+
+PYTHON="/opt/python/cp38-cp38/bin/python"
+
+./autogen.sh
+CXXFLAGS="-fPIC -g -O2" ./configure --host=aarch64
+make -j8
+
+# create a simple shell wrapper that runs crosscompiled protoc under qemu
+echo '#!/bin/bash' >protoc_qemu_wrapper.sh
+echo 'exec qemu-aarch64 "../src/protoc" "$@"' >>protoc_qemu_wrapper.sh
+chmod ugo+x protoc_qemu_wrapper.sh
+
+# PROTOC variable is by build_py step that runs under ./python directory
+export PROTOC=../protoc_qemu_wrapper.sh
+
+pushd python
+
+# NOTE: this step will use protoc_qemu_wrapper.sh to generate protobuf files.
+${PYTHON} setup.py build_py
+
+# when crosscompiling for aarch64, --plat-name needs to be set explicitly
+# to end up with correctly named wheel file
+# the value should be manylinuxABC_ARCH and dockcross docker image
+# conveniently provides the value in the AUDITWHEEL_PLAT env
+plat_name_flag="--plat-name=$AUDITWHEEL_PLAT"
+
+# override the value of EXT_SUFFIX to make sure the crosscompiled .so files in the wheel have the correct filename suffix
+export PROTOCOL_BUFFERS_OVERRIDE_EXT_SUFFIX="$(${PYTHON} -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX").replace("-x86_64-linux-gnu.so", "-aarch64-linux-gnu.so"))')"
+
+# Build the python extension inplace to be able to python unittests later
+${PYTHON} setup.py build_ext --cpp_implementation --compile_static_extension --inplace
+
+# Build the binary wheel (to check it with auditwheel)
+${PYTHON} setup.py bdist_wheel --cpp_implementation --compile_static_extension $plat_name_flag
diff --git a/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh b/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
new file mode 100755
index 0000000..527fc48
--- /dev/null
+++ b/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+set -ex
+
+# go to the repo root
+cd $(dirname $0)/../../..
+cd python
+
+PYTHON="/opt/python/cp38-cp38/bin/python"
+${PYTHON} -m pip install --user six pytest auditwheel
+
+# check that we are really using aarch64 python
+(${PYTHON} -c 'import sysconfig; print(sysconfig.get_platform())' | grep -q "linux-aarch64") || (echo "Wrong python platform, needs to be aarch64 python."; exit 1)
+
+# step 1: run all python unittests
+# we've built the python extension previously with --inplace option
+# so we can just discover all the unittests and run them directly under 
+# the python/ directory.
+LD_LIBRARY_PATH=../src/.libs PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp ${PYTHON} -m pytest google/protobuf
+
+# step 2: run auditwheel show to check that the wheel is manylinux2014 compatible.
+# auditwheel needs to run on wheel's target platform (or under an emulator)
+${PYTHON} -m auditwheel show dist/protobuf-*-manylinux2014_aarch64.whl
+
+# step 3: smoketest that the wheel can be installed and run a smokecheck
+${PYTHON} -m pip install dist/protobuf-*-manylinux2014_aarch64.whl
+# when python cpp extension is on, simply importing a message type will trigger loading the cpp extension
+PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp ${PYTHON} -c 'import google.protobuf.timestamp_pb2; print("Successfully loaded the python cpp extension!")'
diff --git a/kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh b/kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
new file mode 100755
index 0000000..f613202
--- /dev/null
+++ b/kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# Setup and configure qemu userspace emulator on kokoro worker so that we can seamlessly emulate processes running
+# inside docker containers.
+
+set -ex
+
+# show pre-existing qemu registration
+cat /proc/sys/fs/binfmt_misc/qemu-aarch64
+
+# Kokoro ubuntu1604 workers have already qemu-user and qemu-user-static packages installed, but it's and old version that:
+# * prints warning about some syscalls (e.g "qemu: Unsupported syscall: 278")
+# * doesn't register with binfmt_misc with the persistent ("F") flag we need (see below)
+#
+# To overcome the above limitations, we use the https://github.com/multiarch/qemu-user-static
+# docker image to provide a new enough version of qemu-user-static and register it with
+# the desired binfmt_misc flags. The most important flag we need is "F" (set by "--persistent yes"),
+# which allows the qemu-aarch64-static binary to be loaded eagerly at the time of registration with binfmt_misc.
+# That way, we can emulate aarch64 binaries running inside docker containers transparently, without needing the emulator
+# binary to be accessible from the docker image we're emulating.
+# Note that on newer distributions (such as glinux), simply "apt install qemu-user-static" is sufficient
+# to install qemu-user-static with the right flags.
+docker run --rm --privileged multiarch/qemu-user-static:5.2.0-2 --reset --credential yes --persistent yes
+
+# Print current qemu reqistration to make sure everything is setup correctly.
+cat /proc/sys/fs/binfmt_misc/qemu-aarch64
diff --git a/kokoro/linux/aarch64/ruby_build_and_run_tests_with_qemu_aarch64.sh b/kokoro/linux/aarch64/ruby_build_and_run_tests_with_qemu_aarch64.sh
new file mode 100755
index 0000000..dc093bc
--- /dev/null
+++ b/kokoro/linux/aarch64/ruby_build_and_run_tests_with_qemu_aarch64.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -ex
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+gem install bundler
+
+cd ruby
+
+bundle
+rake
+rake clobber_package gem
+
+# run all the tests
+rake test
diff --git a/kokoro/linux/aarch64/test_cpp_aarch64.sh b/kokoro/linux/aarch64/test_cpp_aarch64.sh
new file mode 100755
index 0000000..26f95f3
--- /dev/null
+++ b/kokoro/linux/aarch64/test_cpp_aarch64.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#
+# Crosscompiles protobuf C++ under dockcross docker image and runs the tests under an emulator.
+
+set -e
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+# run the C++ build and test script under dockcross/linux-arm64 image
+kokoro/linux/aarch64/dockcross_helpers/run_dockcross_linux_aarch64.sh kokoro/linux/aarch64/cpp_crosscompile_and_run_tests_with_qemu_aarch64.sh
diff --git a/kokoro/linux/aarch64/test_csharp_aarch64.sh b/kokoro/linux/aarch64/test_csharp_aarch64.sh
new file mode 100755
index 0000000..450bb1e
--- /dev/null
+++ b/kokoro/linux/aarch64/test_csharp_aarch64.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -ex
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# First, build protobuf C# tests under x86_64 docker image
+# Tests are built "dotnet publish" because we want all the dependencies to the copied to the destination directory
+# (we want to avoid references to ~/.nuget that won't be available in the subsequent docker run)
+CSHARP_BUILD_COMMAND="dotnet publish -c Release -f net50 csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj"
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -e "DOTNET_CLI_TELEMETRY_OPTOUT=true" -e "DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work mcr.microsoft.com/dotnet/sdk:5.0.202-buster-slim bash -c "$CSHARP_BUILD_COMMAND"
+
+# Use an actual aarch64 docker image to run protobuf C# tests with an emulator. "dotnet vstest" allows
+# running tests from a pre-built project.
+# * mount the protobuf root as /work to be able to access the crosscompiled files
+# * to avoid running the process inside docker as root (which can pollute the workspace with files owned by root), we force
+#   running under current user's UID and GID. To be able to do that, we need to provide a home directory for the user
+#   otherwise the UID would be homeless under the docker container and pip install wouldn't work. For simplicity,
+#   we just run map the user's home to a throwaway temporary directory
+CSHARP_TEST_COMMAND="dotnet vstest csharp/src/Google.Protobuf.Test/bin/Release/net50/publish/Google.Protobuf.Test.dll"
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -e "DOTNET_CLI_TELEMETRY_OPTOUT=true" -e "DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work mcr.microsoft.com/dotnet/sdk:5.0.202-buster-slim-arm64v8 bash -c "$CSHARP_TEST_COMMAND"
diff --git a/kokoro/linux/aarch64/test_java_aarch64.sh b/kokoro/linux/aarch64/test_java_aarch64.sh
new file mode 100755
index 0000000..72f1c83
--- /dev/null
+++ b/kokoro/linux/aarch64/test_java_aarch64.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -ex
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# crosscompile protoc as we will later need it for the java build.
+# we build it under the dockcross/manylinux2014-aarch64 image so that the resulting protoc binary is compatible
+# with a wide range of linux distros (including any docker images we will use later to build and test java)
+kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
+
+# the command that will be used to build and test java under an emulator
+# * IsValidUtf8Test and DecodeUtf8Test tests are being skipped because that take very long under an emulator.
+TEST_JAVA_COMMAND="mvn --batch-mode -DskipTests install && mvn --batch-mode -Dtest='**/*Test, !**/*IsValidUtf8Test, !**/*DecodeUtf8Test' -DfailIfNoTests=false surefire:test"
+
+# use an actual aarch64 docker image (with a real aarch64 java and maven) to run build & test protobuf java under an emulator
+# * mount the protobuf root as /work to be able to access the crosscompiled files
+# * to avoid running the process inside docker as root (which can pollute the workspace with files owned by root), we force
+#   running under current user's UID and GID. To be able to do that, we need to provide a home directory for the user
+#   otherwise the UID would be homeless under the docker container and pip install wouldn't work. For simplicity,
+#   we just run map the user's home to a throwaway temporary directory
+# * the JAVA_OPTS and MAVEN_CONFIG variables are being set mostly to silence warnings about non-existent home directory
+#   and to avoid polluting the workspace.
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -e "JAVA_OPTS=-Duser.home=/home/fake-user" -e "MAVEN_CONFIG=/home/fake-user/.m2" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work arm64v8/maven:3.8-openjdk-11 bash -c "cd java && $TEST_JAVA_COMMAND"
diff --git a/kokoro/linux/aarch64/test_javascript_aarch64.sh b/kokoro/linux/aarch64/test_javascript_aarch64.sh
new file mode 100755
index 0000000..3156e6e
--- /dev/null
+++ b/kokoro/linux/aarch64/test_javascript_aarch64.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -ex
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# crosscompile protoc as we will later need it for the javascript build.
+# we build it under the dockcross/manylinux2014-aarch64 image so that the resulting protoc binary is compatible
+# with a wide range of linux distros (including any docker images we will use later to build and test javascript)
+kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
+
+# use an actual aarch64 docker image (with a real aarch64 nodejs) to run build & test protobuf javascript under an emulator
+# * mount the protobuf root as /work to be able to access the crosscompiled files
+# * to avoid running the process inside docker as root (which can pollute the workspace with files owned by root), we force
+#   running under current user's UID and GID. To be able to do that, we need to provide a home directory for the user
+#   otherwise the UID would be homeless under the docker container and pip install wouldn't work. For simplicity,
+#   we just run map the user's home to a throwaway temporary directory
+# Note that the docker image used for running the tests is arm64v8/openjdk, not arm64v8/node
+# This is because some of the node tests require java to be available and adding node
+# binary distribution into a java image is easier than vice versa.
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work arm64v8/openjdk:11-jdk-buster kokoro/linux/aarch64/javascript_build_and_run_tests_with_qemu_aarch64.sh
diff --git a/kokoro/linux/aarch64/test_php_aarch64.sh b/kokoro/linux/aarch64/test_php_aarch64.sh
new file mode 100755
index 0000000..b11ef43
--- /dev/null
+++ b/kokoro/linux/aarch64/test_php_aarch64.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+set -ex
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+# there is no php testing docker image readily available, so we build
+# our own. It's a aarch64 image, but that's fine since qemu will
+# automatically be used to run the commands in the dockerfile.
+docker build -t testimage_protobuf_php_arm64v8 kokoro/linux/aarch64/testimage_protobuf_php_arm64v8
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# crosscompile protoc as we will later need it for the php build.
+# we build it under the dockcross/manylinux2014-aarch64 image so that the resulting protoc binary is compatible
+# with a wide range of linux distros (including any docker images we will use later to build and test php)
+kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
+
+# use an actual aarch64 docker image (with a real aarch64 php) to run build & test protobuf php under an emulator
+# * mount the protobuf root as /work to be able to access the crosscompiled files
+# * to avoid running the process inside docker as root (which can pollute the workspace with files owned by root), we force
+#   running under current user's UID and GID. To be able to do that, we need to provide a home directory for the user
+#   otherwise the UID would be homeless under the docker container and pip install wouldn't work. For simplicity,
+#   we just run map the user's home to a throwaway temporary directory
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work testimage_protobuf_php_arm64v8 kokoro/linux/aarch64/php_build_and_run_tests_with_qemu_aarch64.sh
diff --git a/kokoro/linux/aarch64/test_python_aarch64.sh b/kokoro/linux/aarch64/test_python_aarch64.sh
new file mode 100755
index 0000000..1e2d570
--- /dev/null
+++ b/kokoro/linux/aarch64/test_python_aarch64.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+set -e
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# crosscompile python extension and the binary wheel under dockcross/manylinux2014-aarch64 image
+kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh kokoro/linux/aarch64/python_crosscompile_aarch64.sh
+
+# once crosscompilation is done, use an actual aarch64 docker image (with a real aarch64 python) to run all the tests under an emulator
+# * mount the protobuf root as /work to be able to access the crosscompiled files
+# * intentionally use a different image than manylinux2014 so that we don't build and test on the same linux distribution
+#   (manylinux_2_24 is debian-based while manylinux2014 is centos-based)
+# * to avoid running the process inside docker as root (which can pollute the workspace with files owned by root), we force
+#   running under current user's UID and GID. To be able to do that, we need to provide a home directory for the user
+#   otherwise the UID would be homeless under the docker container and pip install wouldn't work. For simplicity,
+#   we just run map the user's home to a throwaway temporary directory
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work quay.io/pypa/manylinux_2_24_aarch64 kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
diff --git a/kokoro/linux/aarch64/test_ruby_aarch64.sh b/kokoro/linux/aarch64/test_ruby_aarch64.sh
new file mode 100755
index 0000000..91ee5f2
--- /dev/null
+++ b/kokoro/linux/aarch64/test_ruby_aarch64.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+set -ex
+
+# go to the repo root
+cd $(dirname $0)/../../..
+
+if [[ -t 0 ]]; then
+  DOCKER_TTY_ARGS="-it"
+else
+  # The input device on kokoro is not a TTY, so -it does not work.
+  DOCKER_TTY_ARGS=
+fi
+
+# crosscompile protoc as we will later need it for the ruby build.
+# we build it under the dockcross/manylinux2014-aarch64 image so that the resulting protoc binary is compatible
+# with a wide range of linux distros (including any docker images we will use later to build and test ruby)
+kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
+
+# use an actual aarch64 docker image (with a real aarch64 ruby) to run build & test protobuf ruby under an emulator
+# * mount the protobuf root as /work to be able to access the crosscompiled files
+# * to avoid running the process inside docker as root (which can pollute the workspace with files owned by root), we force
+#   running under current user's UID and GID. To be able to do that, we need to provide a home directory for the user
+#   otherwise the UID would be homeless under the docker container and pip install wouldn't work. For simplicity,
+#   we just run map the user's home to a throwaway temporary directory
+
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work arm64v8/ruby:2.7.3-buster kokoro/linux/aarch64/ruby_build_and_run_tests_with_qemu_aarch64.sh
\ No newline at end of file
diff --git a/kokoro/linux/aarch64/testimage_protobuf_php_arm64v8/Dockerfile b/kokoro/linux/aarch64/testimage_protobuf_php_arm64v8/Dockerfile
new file mode 100644
index 0000000..eae1bbc
--- /dev/null
+++ b/kokoro/linux/aarch64/testimage_protobuf_php_arm64v8/Dockerfile
@@ -0,0 +1,3 @@
+FROM arm64v8/debian:buster
+
+RUN apt-get update && apt-get install -y php7.3-cli php7.3-dev php7.3-bcmath composer phpunit curl git valgrind && apt-get clean
diff --git a/kokoro/linux/bazel/build.sh b/kokoro/linux/bazel/build.sh
index 9355eba..300e212 100755
--- a/kokoro/linux/bazel/build.sh
+++ b/kokoro/linux/bazel/build.sh
@@ -3,8 +3,8 @@
 # Build file to set up and run tests
 set -ex
 
-# Install the latest Bazel version available
-use_bazel.sh latest
+# Install Bazel 4.0.0.
+use_bazel.sh 4.0.0
 bazel version
 
 # Print bazel testlogs to stdout when tests failed.
@@ -25,7 +25,10 @@
 trap print_test_logs EXIT
 bazel test --copt=-Werror --host_copt=-Werror \
   //:build_files_updated_unittest \
-  //java/... \
+  //java:tests \
+  //:protoc \
+  //:protobuf \
+  //:protobuf_python \
   //:protobuf_test \
   @com_google_protobuf//:cc_proto_blacklist_test
 trap - EXIT
diff --git a/kokoro/linux/benchmark/build.sh b/kokoro/linux/benchmark/build.sh
index e563e79..f078280 100755
--- a/kokoro/linux/benchmark/build.sh
+++ b/kokoro/linux/benchmark/build.sh
@@ -2,25 +2,4 @@
 
 cd $(dirname $0)/../../..
 
-# prepare php environments
-sudo apt-get update && sudo apt-get install -y --force-yes php5
-sudo ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h
-mkdir php_temp
-cd php_temp
-curl -sS https://getcomposer.org/installer | php
-sudo mv composer.phar /usr/local/bin/composer
-git clone https://github.com/php/php-src
-cd php-src && git checkout PHP-7.2.13 && ./buildconf --force
-./configure \
-	--enable-bcmatch \
-	--with-gmp --with-openssl \
-	--with-zlib  \
-	--prefix=/usr/local/php-7.2 && \
-make -j8 && sudo make install && make clean
-wget -O phpunit https://phar.phpunit.de/phpunit-7.phar && \
-	chmod +x phpunit && \
-	sudo cp phpunit /usr/local/php-7.2/bin
-sudo apt-get install -y --force-yes valgrind
-cd ../..
-
 ./tests.sh benchmark
diff --git a/kokoro/linux/benchmark/run.sh b/kokoro/linux/benchmark/run.sh
index 1b1032b..4276d62 100755
--- a/kokoro/linux/benchmark/run.sh
+++ b/kokoro/linux/benchmark/run.sh
@@ -3,37 +3,40 @@
 # Change to repo root
 cd $(dirname $0)/../../..
 
+set -ex
+
 export OUTPUT_DIR=testoutput
-oldpwd=`pwd`
+repo_root="$(pwd)"
 
 # tcmalloc
 if [ ! -f gperftools/.libs/libtcmalloc.so ]; then
   git clone https://github.com/gperftools/gperftools.git
-  cd gperftools
+  pushd gperftools
   ./autogen.sh
   ./configure
   make -j8
-  cd ..
+  popd
 fi
 
 # download datasets for benchmark
-cd benchmarks
-./download_data.sh
+pushd benchmarks
 datasets=$(for file in $(find . -type f -name "dataset.*.pb" -not -path "./tmp/*"); do echo "$(pwd)/$file"; done | xargs)
 echo $datasets
-cd $oldpwd
+popd
 
 # build Python protobuf
 ./autogen.sh
 ./configure CXXFLAGS="-fPIC -O2"
 make -j8
-cd python
+pushd python
 python setup.py build --cpp_implementation
 pip install . --user
-
+popd
 
 # build and run Python benchmark
-cd ../benchmarks
+# We do this before building protobuf C++ since C++ build
+# will rewrite some libraries used by protobuf python.
+pushd benchmarks
 make python-pure-python-benchmark
 make python-cpp-reflection-benchmark
 make -j8 python-cpp-generated-code-benchmark
@@ -42,64 +45,60 @@
 ./python-pure-python-benchmark --json --behavior_prefix="pure-python-benchmark" $datasets  >> tmp/python_result.json
 echo "," >> "tmp/python_result.json"
 echo "benchmarking python cpp reflection..."
-env LD_PRELOAD="$oldpwd/gperftools/.libs/libtcmalloc.so" LD_LIBRARY_PATH="$oldpwd/src/.libs" ./python-cpp-reflection-benchmark --json --behavior_prefix="cpp-reflection-benchmark" $datasets  >> tmp/python_result.json
+env LD_PRELOAD="${repo_root}/gperftools/.libs/libtcmalloc.so" LD_LIBRARY_PATH="${repo_root}/src/.libs" ./python-cpp-reflection-benchmark --json --behavior_prefix="cpp-reflection-benchmark" $datasets  >> tmp/python_result.json
 echo "," >> "tmp/python_result.json"
 echo "benchmarking python cpp generated code..."
-env LD_PRELOAD="$oldpwd/gperftools/.libs/libtcmalloc.so" LD_LIBRARY_PATH="$oldpwd/src/.libs" ./python-cpp-generated-code-benchmark --json --behavior_prefix="cpp-generated-code-benchmark" $datasets >> tmp/python_result.json
+env LD_PRELOAD="${repo_root}/gperftools/.libs/libtcmalloc.so" LD_LIBRARY_PATH="${repo_root}/src/.libs" ./python-cpp-generated-code-benchmark --json --behavior_prefix="cpp-generated-code-benchmark" $datasets >> tmp/python_result.json
 echo "]" >> "tmp/python_result.json"
-cd $oldpwd
+popd
 
 # build CPP protobuf
 ./configure
 make clean && make -j8
 
 # build Java protobuf
-cd java
-mvn package
-cd ..
+pushd java
+mvn package -B -Dmaven.test.skip=true
+popd
 
-# build CPP benchmark
-cd benchmarks
+pushd benchmarks
+
+# build and run C++ benchmark
+# "make clean" deletes the contents of the tmp/ directory, so we move it elsewhere and then restore it once build is done.
+# TODO(jtattermusch): find a less clumsy way of protecting python_result.json contents
 mv tmp/python_result.json . && make clean && make -j8 cpp-benchmark && mv python_result.json tmp
 echo "benchmarking cpp..."
-env LD_PRELOAD="$oldpwd/gperftools/.libs/libtcmalloc.so" ./cpp-benchmark --benchmark_min_time=5.0 --benchmark_out_format=json --benchmark_out="tmp/cpp_result.json" $datasets
-cd $oldpwd
+env LD_PRELOAD="${repo_root}/gperftools/.libs/libtcmalloc.so" ./cpp-benchmark --benchmark_min_time=5.0 --benchmark_out_format=json --benchmark_out="tmp/cpp_result.json" $datasets
 
-# build go protobuf
-export PATH="`pwd`/src:$PATH"
-export GOPATH="$HOME/gocode"
-mkdir -p "$GOPATH/src/github.com/google"
-rm -f "$GOPATH/src/github.com/protocolbuffers/protobuf"
-ln -s "`pwd`" "$GOPATH/src/github.com/protocolbuffers/protobuf"
-export PATH="$GOPATH/bin:$PATH"
-go get github.com/golang/protobuf/protoc-gen-go
+# TODO(jtattermusch): add benchmarks for https://github.com/protocolbuffers/protobuf-go.
+# The original benchmarks for https://github.com/golang/protobuf were removed
+# because:
+# * they were broken and haven't been producing results for a long time
+# * the https://github.com/golang/protobuf implementation has been superseded by
+#   https://github.com/protocolbuffers/protobuf-go
 
-# build go benchmark
-cd benchmarks
-make go-benchmark
-echo "benchmarking go..."
-./go-benchmark $datasets > tmp/go_result.txt
-
-# build java benchmark
+# build and run java benchmark
 make java-benchmark
 echo "benchmarking java..."
 ./java-benchmark -Cresults.file.options.file="tmp/java_result.json" $datasets
 
+# build and run js benchmark
 make js-benchmark
 echo "benchmarking js..."
 ./js-benchmark $datasets  --json_output=$(pwd)/tmp/node_result.json
 
-make -j8 generate_proto3_data
-proto3_datasets=$(for file in $datasets; do echo $(pwd)/tmp/proto3_data/${file#$(pwd)}; done | xargs)
-echo $proto3_datasets
+# TODO(jtattermusch): add php-c-benchmark. Currently its build is broken.
 
-# build php benchmark
-make -j8 php-c-benchmark
-echo "benchmarking php_c..."
-./php-c-benchmark $proto3_datasets --json --behavior_prefix="php_c" > tmp/php_c_result.json
+# persist raw the results in the build job log (for better debuggability)
+cat tmp/cpp_result.json
+cat tmp/java_result.json
+cat tmp/python_result.json
+cat tmp/node_result.json
 
-# upload result to bq
+# print the postprocessed results to the build job log
+# TODO(jtattermusch): re-enable uploading results to bigquery (it is currently broken)
 make python_add_init
-env LD_LIBRARY_PATH="$oldpwd/src/.libs" python -m util.result_uploader -php_c="../tmp/php_c_result.json"  \
-	-cpp="../tmp/cpp_result.json" -java="../tmp/java_result.json" -go="../tmp/go_result.txt" -python="../tmp/python_result.json" -node="../tmp/node_result.json"
-cd $oldpwd
+env LD_LIBRARY_PATH="${repo_root}/src/.libs" python -m util.result_parser \
+	-cpp="../tmp/cpp_result.json" -java="../tmp/java_result.json" -python="../tmp/python_result.json" -node="../tmp/node_result.json"
+popd
+
diff --git a/kokoro/linux/cpp_aarch64/build.sh b/kokoro/linux/cpp_aarch64/build.sh
new file mode 100755
index 0000000..a43ab1c
--- /dev/null
+++ b/kokoro/linux/cpp_aarch64/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "continuous" and "presubmit" jobs.
+
+set -ex
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+kokoro/linux/aarch64/test_cpp_aarch64.sh
diff --git a/kokoro/linux/cpp_aarch64/continuous.cfg b/kokoro/linux/cpp_aarch64/continuous.cfg
new file mode 100644
index 0000000..0f1be4a
--- /dev/null
+++ b/kokoro/linux/cpp_aarch64/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cpp_aarch64/build.sh"
+timeout_mins: 120
diff --git a/kokoro/linux/cpp_aarch64/presubmit.cfg b/kokoro/linux/cpp_aarch64/presubmit.cfg
new file mode 100644
index 0000000..0f1be4a
--- /dev/null
+++ b/kokoro/linux/cpp_aarch64/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cpp_aarch64/build.sh"
+timeout_mins: 120
diff --git a/kokoro/linux/cpp_distcheck/build.sh b/kokoro/linux/cpp_distcheck/build.sh
index 42ac88c..a28843e 100755
--- a/kokoro/linux/cpp_distcheck/build.sh
+++ b/kokoro/linux/cpp_distcheck/build.sh
@@ -16,6 +16,10 @@
 docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \
   bash -l /var/local/protobuf/tests.sh cpp || FAILED="true"
 
+# This directory is owned by root. We need to delete it, because otherwise
+# Kokoro will attempt to rsync it and fail with a permission error.
+rm -rf src/core
+
 if [ "$FAILED" = "true" ]; then
   exit 1
 fi
diff --git a/kokoro/linux/csharp_aarch64/build.sh b/kokoro/linux/csharp_aarch64/build.sh
new file mode 100755
index 0000000..db3fc21
--- /dev/null
+++ b/kokoro/linux/csharp_aarch64/build.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "continuous" and "presubmit" jobs.
+
+set -ex
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
+
+kokoro/linux/aarch64/test_csharp_aarch64.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/csharp_aarch64/continuous.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/csharp_aarch64/continuous.cfg
index e2fc413..df28ef3 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/csharp_aarch64/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/csharp_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/presubmit.cfg b/kokoro/linux/csharp_aarch64/presubmit.cfg
similarity index 74%
copy from kokoro/linux/python/presubmit.cfg
copy to kokoro/linux/csharp_aarch64/presubmit.cfg
index e2fc413..df28ef3 100644
--- a/kokoro/linux/python/presubmit.cfg
+++ b/kokoro/linux/csharp_aarch64/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/csharp_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/dist_install/build.sh b/kokoro/linux/dist_install/build.sh
index 81a0516..c456ee8 100755
--- a/kokoro/linux/dist_install/build.sh
+++ b/kokoro/linux/dist_install/build.sh
@@ -7,8 +7,8 @@
 # Change to repo root
 cd $(dirname $0)/../../..
 
-# Run tests under release docker image.
-export DOCKERFILE_DIR=kokoro/linux/64-bit
+export DOCKERHUB_ORGANIZATION=protobuftesting
+export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/java_stretch
 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
 export OUTPUT_DIR=testoutput
 export TEST_SET="dist_install"
diff --git a/kokoro/linux/dockerfile/test/csharp/Dockerfile b/kokoro/linux/dockerfile/test/csharp/Dockerfile
index 3d54436..37edbfd 100644
--- a/kokoro/linux/dockerfile/test/csharp/Dockerfile
+++ b/kokoro/linux/dockerfile/test/csharp/Dockerfile
@@ -1,4 +1,4 @@
-FROM debian:stretch
+FROM debian:buster
 
 # Install dependencies.  We start with the basic ones require to build protoc
 # and the C++ build
@@ -22,14 +22,18 @@
   wget \
   && apt-get clean
 
+# Update ca-certificates to fix known buster + .NET 5 issue
+# https://github.com/NuGet/Announcements/issues/49
+RUN apt-get update && apt-get install -y ca-certificates && apt-get clean
+
 # dotnet SDK prerequisites
-RUN apt-get update && apt-get install -y libunwind8 libicu57 && apt-get clean
+RUN apt-get update && apt-get install -y libunwind8 libicu63 && apt-get clean
 
 # Install dotnet SDK via install script
 RUN wget -q https://dot.net/v1/dotnet-install.sh && \
     chmod u+x dotnet-install.sh && \
     ./dotnet-install.sh --version 2.1.802 && \
-    ./dotnet-install.sh --version 3.0.100 && \
+    ./dotnet-install.sh --version 5.0.102 && \
     ln -s /root/.dotnet/dotnet /usr/local/bin
 
 RUN wget -q www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe
diff --git a/kokoro/linux/dockerfile/test/java_stretch/Dockerfile b/kokoro/linux/dockerfile/test/java_stretch/Dockerfile
index fc5e82a..3e72046 100644
--- a/kokoro/linux/dockerfile/test/java_stretch/Dockerfile
+++ b/kokoro/linux/dockerfile/test/java_stretch/Dockerfile
@@ -1,6 +1,6 @@
 FROM debian:stretch
 
-# Install dependencies.  We start with the basic ones require to build protoc
+# Install dependencies.  We start with the basic ones required to build protoc
 # and the C++ build
 RUN apt-get update && apt-get install -y \
   autoconf \
@@ -20,12 +20,11 @@
   parallel \
   time \
   wget \
-  && apt-get clean
-
-# Java dependencies
-RUN apt-get install -y \
-  # -- For all Java builds -- \
+  # Java dependencies
   maven \
-  # -- For java_linkage_monitor \
   openjdk-8-jdk \
+  # Python dependencies
+  python-setuptools \
+  python-pip \
+  virtualenv \
   && apt-get clean
diff --git a/kokoro/linux/dockerfile/test/javascript/Dockerfile b/kokoro/linux/dockerfile/test/javascript/Dockerfile
index dff7e7b..184828f 100644
--- a/kokoro/linux/dockerfile/test/javascript/Dockerfile
+++ b/kokoro/linux/dockerfile/test/javascript/Dockerfile
@@ -27,7 +27,11 @@
 
 ##################
 # Javascript dependencies.
-RUN apt-get install -y \
+# We need to set these environment variables so that the Docker build does not
+# have to ask for this information while it is installing the tzdata package.
+RUN DEBIAN_FRONTEND="noninteractive" TZ="America/Los_Angeles" \
+  apt-get install -y \
   # -- For javascript and closure compiler -- \
   npm \
-  default-jre
+  default-jre \
+  python
diff --git a/kokoro/linux/dockerfile/test/php/Dockerfile b/kokoro/linux/dockerfile/test/php/Dockerfile
index a540177..4c9d69d 100644
--- a/kokoro/linux/dockerfile/test/php/Dockerfile
+++ b/kokoro/linux/dockerfile/test/php/Dockerfile
@@ -55,36 +55,6 @@
 # Download php source code
 RUN git clone https://github.com/php/php-src
 
-# php 5.5
-RUN cd php-src \
-  && git checkout PHP-5.5.38 \
-  && ./buildconf --force
-RUN cd php-src \
-  && ./configure \
-  --enable-bcmath \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-5.5 \
-  && make \
-  && make install \
-  && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-5.5-zts \
-  && make \
-  && make install \
-  && make clean
-
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-4.phar \
-  && chmod +x phpunit \
-  && cp phpunit /usr/local/php-5.5/bin \
-  && mv phpunit /usr/local/php-5.5-zts/bin
-
 # php 5.6
 RUN cd php-src \
   && git checkout PHP-5.6.39 \
@@ -92,6 +62,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -99,21 +70,10 @@
   && make \
   && make install \
   && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-5.6-zts \
-  && make \
-  && make install \
-  && make clean
 
 RUN wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \
   && chmod +x phpunit \
-  && cp phpunit /usr/local/php-5.6/bin \
-  && mv phpunit /usr/local/php-5.6-zts/bin
+  && mv phpunit /usr/local/php-5.6/bin
 
 # php 7.0
 RUN cd php-src \
@@ -122,6 +82,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -132,6 +93,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -152,6 +114,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -162,6 +125,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -170,7 +134,7 @@
   && make install \
   && make clean
 
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.phar \
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \
   && chmod +x phpunit \
   && cp phpunit /usr/local/php-7.1/bin \
   && mv phpunit /usr/local/php-7.1-zts/bin
@@ -182,6 +146,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -192,6 +157,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -200,7 +166,7 @@
   && make install \
   && make clean
 
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.phar \
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \
   && chmod +x phpunit \
   && cp phpunit /usr/local/php-7.2/bin \
   && mv phpunit /usr/local/php-7.2-zts/bin
@@ -212,6 +178,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -222,6 +189,7 @@
 RUN cd php-src \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -230,7 +198,7 @@
   && make install \
   && make clean
 
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.phar \
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \
   && chmod +x phpunit \
   && cp phpunit /usr/local/php-7.3/bin \
   && mv phpunit /usr/local/php-7.3-zts/bin
@@ -253,6 +221,8 @@
   && ./buildconf --force \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
+  --disable-mbregex \
   --with-gmp \
   --with-openssl \
   --with-zlib \
@@ -264,6 +234,8 @@
   && ./buildconf --force \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
+  --disable-mbregex \
   --with-gmp \
   --with-openssl \
   --with-zlib \
diff --git a/kokoro/linux/dockerfile/test/php80/Dockerfile b/kokoro/linux/dockerfile/test/php80/Dockerfile
new file mode 100644
index 0000000..8093eae
--- /dev/null
+++ b/kokoro/linux/dockerfile/test/php80/Dockerfile
@@ -0,0 +1,96 @@
+FROM debian:jessie
+
+# Install dependencies.  We start with the basic ones require to build protoc
+# and the C++ build
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  git \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  parallel \
+  time \
+  wget \
+  re2c \
+  sqlite3 \
+  vim \
+  libonig-dev \
+  libsqlite3-dev \
+  && apt-get clean
+
+# Install php dependencies
+RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
+  php5 \
+  libcurl4-openssl-dev \
+  libgmp-dev \
+  libgmp3-dev \
+  libssl-dev \
+  libxml2-dev \
+  unzip \
+  zlib1g-dev \
+  pkg-config \
+  && apt-get clean
+
+# Install other dependencies
+RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h
+RUN wget https://ftp.gnu.org/gnu/bison/bison-3.0.1.tar.gz -O /var/local/bison-3.0.1.tar.gz
+RUN cd /var/local \
+  && tar -zxvf bison-3.0.1.tar.gz \
+  && cd /var/local/bison-3.0.1 \
+  && ./configure \
+  && make \
+  && make install
+
+# Install composer
+RUN curl -sS https://getcomposer.org/installer | php
+RUN mv composer.phar /usr/local/bin/composer
+
+# Download php source code
+RUN git clone https://github.com/php/php-src
+
+# php 8.0
+RUN cd php-src \
+  && git checkout php-8.0.0 \
+  && ./buildconf --force
+RUN cd php-src \
+  && ./configure \
+  --enable-bcmath \
+  --enable-mbstring \
+  --with-gmp \
+  --with-openssl \
+  --with-zlib \
+  --prefix=/usr/local/php-8.0 \
+  && make \
+  && make install \
+  && make clean
+RUN cd php-src \
+  && ./configure \
+  --enable-bcmath \
+  --enable-mbstring \
+  --enable-maintainer-zts \
+  --with-gmp \
+  --with-openssl \
+  --with-zlib \
+  --prefix=/usr/local/php-8.0-zts \
+  && make \
+  && make install \
+  && make clean
+
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-9.phar \
+  && chmod +x phpunit \
+  && cp phpunit /usr/local/php-8.0/bin \
+  && mv phpunit /usr/local/php-8.0-zts/bin
+
+# Install php dependencies
+RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
+  valgrind \
+  && apt-get clean
diff --git a/kokoro/linux/dockerfile/test/php_32bit/Dockerfile b/kokoro/linux/dockerfile/test/php_32bit/Dockerfile
index b40cb70..d657af1 100644
--- a/kokoro/linux/dockerfile/test/php_32bit/Dockerfile
+++ b/kokoro/linux/dockerfile/test/php_32bit/Dockerfile
@@ -53,34 +53,6 @@
 # Download php source code
 RUN git clone https://github.com/php/php-src
 
-# php 5.5
-RUN cd php-src \
-  && git checkout PHP-5.5.38 \
-  && ./buildconf --force
-RUN cd php-src \
-  && ./configure \
-  --enable-bcmath \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-5.5 \
-  && make \
-  && make install \
-  && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-5.5-zts \
-  && make \
-  && make install \
-  && make clean
-
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-4.phar \
-  && chmod +x phpunit \
-  && cp phpunit /usr/local/php-5.5/bin \
-  && mv phpunit /usr/local/php-5.5-zts/bin
-
 # php 5.6
 RUN cd php-src \
   && git checkout PHP-5.6.39 \
@@ -88,43 +60,40 @@
 RUN cd php-src \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-5.6 \
   && make \
   && make install \
   && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-5.6-zts \
-  && make \
-  && make install \
-  && make clean
 
 RUN wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \
   && chmod +x phpunit \
-  && cp phpunit /usr/local/php-5.6/bin \
-  && mv phpunit /usr/local/php-5.6-zts/bin
+  && mv phpunit /usr/local/php-5.6/bin
 
 # php 7.0
-RUN cd php-src \
-  && git checkout PHP-7.0.33 \
-  && ./buildconf --force
-RUN cd php-src \
+RUN wget https://github.com/php/php-src/archive/php-7.0.33.tar.gz -O /var/local/php-7.0.33.tar.gz
+
+RUN cd /var/local \
+  && tar -zxvf php-7.0.33.tar.gz
+
+RUN cd /var/local/php-src-php-7.0.33 \
+  && ./buildconf --force \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.0 \
   && make \
   && make install \
   && make clean
-RUN cd php-src \
+RUN cd /var/local/php-src-php-7.0.33 \
+  && ./buildconf --force \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.0-zts \
@@ -138,21 +107,27 @@
   && mv phpunit /usr/local/php-7.0-zts/bin
 
 # php 7.1
-RUN cd php-src \
-  && git checkout PHP-7.1.25 \
-  && ./buildconf --force
-RUN cd php-src \
+RUN wget https://github.com/php/php-src/archive/php-7.1.25.tar.gz -O /var/local/php-7.1.25.tar.gz
+
+RUN cd /var/local \
+  && tar -zxvf php-7.1.25.tar.gz
+
+RUN cd /var/local/php-src-php-7.1.25 \
+  && ./buildconf --force \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.1 \
   && make \
   && make install \
   && make clean
-RUN cd php-src \
+RUN cd /var/local/php-src-php-7.1.25 \
+  && ./buildconf --force \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.1-zts \
@@ -160,27 +135,33 @@
   && make install \
   && make clean
 
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.phar \
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \
   && chmod +x phpunit \
   && cp phpunit /usr/local/php-7.1/bin \
   && mv phpunit /usr/local/php-7.1-zts/bin
 
 # php 7.2
-RUN cd php-src \
-  && git checkout PHP-7.2.13 \
-  && ./buildconf --force
-RUN cd php-src \
+RUN wget https://github.com/php/php-src/archive/php-7.2.13.tar.gz -O /var/local/php-7.2.13.tar.gz
+
+RUN cd /var/local \
+  && tar -zxvf php-7.2.13.tar.gz
+
+RUN cd /var/local/php-src-php-7.2.13 \
+  && ./buildconf --force \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.2 \
   && make \
   && make install \
   && make clean
-RUN cd php-src \
+RUN cd /var/local/php-src-php-7.2.13 \
+  && ./buildconf --force \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.2-zts \
@@ -188,27 +169,33 @@
   && make install \
   && make clean
 
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.phar \
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \
   && chmod +x phpunit \
   && cp phpunit /usr/local/php-7.2/bin \
   && mv phpunit /usr/local/php-7.2-zts/bin
 
 # php 7.3
-RUN cd php-src \
-  && git checkout PHP-7.3.0 \
-  && ./buildconf --force
-RUN cd php-src \
+RUN wget https://github.com/php/php-src/archive/php-7.3.0.tar.gz -O /var/local/php-7.3.0.tar.gz
+
+RUN cd /var/local \
+  && tar -zxvf php-7.3.0.tar.gz
+
+RUN cd /var/local/php-src-php-7.3.0 \
+  && ./buildconf --force \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.3 \
   && make \
   && make install \
   && make clean
-RUN cd php-src \
+RUN cd /var/local/php-src-php-7.3.0 \
+  && ./buildconf --force \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.3-zts \
@@ -216,7 +203,7 @@
   && make install \
   && make clean
 
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.phar \
+RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \
   && chmod +x phpunit \
   && cp phpunit /usr/local/php-7.3/bin \
   && mv phpunit /usr/local/php-7.3-zts/bin
@@ -239,6 +226,8 @@
   && ./buildconf --force \
   && ./configure \
   --enable-bcmath \
+  --enable-mbstring \
+  --disable-mbregex \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.4 \
@@ -249,6 +238,8 @@
   && ./buildconf --force \
   && ./configure \
   --enable-maintainer-zts \
+  --enable-mbstring \
+  --disable-mbregex \
   --with-openssl \
   --with-zlib \
   --prefix=/usr/local/php-7.4-zts \
diff --git a/kokoro/linux/dockerfile/test/python27/Dockerfile b/kokoro/linux/dockerfile/test/python27/Dockerfile
index e41e49a..6b0eaf7 100644
--- a/kokoro/linux/dockerfile/test/python27/Dockerfile
+++ b/kokoro/linux/dockerfile/test/python27/Dockerfile
@@ -20,4 +20,12 @@
   parallel \
   time \
   wget \
-  && apt-get clean
+  && apt-get clean \
+  && rm -rf /var/lib/apt/lists/*
+
+# Install Python libraries.
+RUN python -m pip install --no-cache-dir --upgrade \
+  pip \
+  setuptools \
+  tox \
+  wheel
diff --git a/kokoro/linux/dockerfile/test/python35/Dockerfile b/kokoro/linux/dockerfile/test/python35/Dockerfile
index 3ea4c9e..50ee184 100644
--- a/kokoro/linux/dockerfile/test/python35/Dockerfile
+++ b/kokoro/linux/dockerfile/test/python35/Dockerfile
@@ -20,4 +20,12 @@
   parallel \
   time \
   wget \
-  && apt-get clean
+  && apt-get clean \
+  && rm -rf /var/lib/apt/lists/*
+
+# Install Python libraries.
+RUN python -m pip install --no-cache-dir --upgrade \
+  pip \
+  setuptools \
+  tox \
+  wheel
diff --git a/kokoro/linux/dockerfile/test/python36/Dockerfile b/kokoro/linux/dockerfile/test/python36/Dockerfile
index 4368460..742503e 100644
--- a/kokoro/linux/dockerfile/test/python36/Dockerfile
+++ b/kokoro/linux/dockerfile/test/python36/Dockerfile
@@ -20,4 +20,12 @@
   parallel \
   time \
   wget \
-  && apt-get clean
+  && apt-get clean \
+  && rm -rf /var/lib/apt/lists/*
+
+# Install Python libraries.
+RUN python -m pip install --no-cache-dir --upgrade \
+  pip \
+  setuptools \
+  tox \
+  wheel
diff --git a/kokoro/linux/dockerfile/test/python37/Dockerfile b/kokoro/linux/dockerfile/test/python37/Dockerfile
index c711eb8..ee108dd 100644
--- a/kokoro/linux/dockerfile/test/python37/Dockerfile
+++ b/kokoro/linux/dockerfile/test/python37/Dockerfile
@@ -20,4 +20,12 @@
   parallel \
   time \
   wget \
-  && apt-get clean
+  && apt-get clean \
+  && rm -rf /var/lib/apt/lists/*
+
+# Install Python libraries.
+RUN python -m pip install --no-cache-dir --upgrade \
+  pip \
+  setuptools \
+  tox \
+  wheel
diff --git a/kokoro/linux/dockerfile/test/python38/Dockerfile b/kokoro/linux/dockerfile/test/python38/Dockerfile
index 48a7be5..56efc9d 100644
--- a/kokoro/linux/dockerfile/test/python38/Dockerfile
+++ b/kokoro/linux/dockerfile/test/python38/Dockerfile
@@ -20,4 +20,12 @@
   parallel \
   time \
   wget \
-  && apt-get clean
+  && apt-get clean \
+  && rm -rf /var/lib/apt/lists/*
+
+# Install Python libraries.
+RUN python -m pip install --no-cache-dir --upgrade \
+  pip \
+  setuptools \
+  tox \
+  wheel
diff --git a/kokoro/linux/dockerfile/test/python39/Dockerfile b/kokoro/linux/dockerfile/test/python39/Dockerfile
new file mode 100644
index 0000000..ee7554d
--- /dev/null
+++ b/kokoro/linux/dockerfile/test/python39/Dockerfile
@@ -0,0 +1,31 @@
+FROM python:3.9-buster
+
+# Install dependencies.  We start with the basic ones require to build protoc
+# and the C++ build
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  git \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  parallel \
+  time \
+  wget \
+  && apt-get clean \
+  && rm -rf /var/lib/apt/lists/*
+
+# Install Python libraries.
+RUN python -m pip install --no-cache-dir --upgrade \
+  pip \
+  setuptools \
+  tox \
+  wheel
diff --git a/kokoro/linux/dockerfile/test/ruby/Dockerfile b/kokoro/linux/dockerfile/test/ruby/Dockerfile
index 41bfede..b73bf84 100644
--- a/kokoro/linux/dockerfile/test/ruby/Dockerfile
+++ b/kokoro/linux/dockerfile/test/ruby/Dockerfile
@@ -26,12 +26,14 @@
 RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys \
     409B6B1796C275462A1703113804BB82D39DC0E3 \
     7D2BAF1CF37B13E2069D6956105BD0E739499BDB
-RUN \curl -sSL https://get.rvm.io | bash -s stable
+RUN \curl -sSL https://get.rvm.io | bash -s master
 
 RUN /bin/bash -l -c "rvm install 2.3.8"
 RUN /bin/bash -l -c "rvm install 2.4.5"
 RUN /bin/bash -l -c "rvm install 2.5.1"
 RUN /bin/bash -l -c "rvm install 2.6.0"
+RUN /bin/bash -l -c "rvm install 2.7.0"
+RUN /bin/bash -l -c "rvm install 3.0.0"
 
 RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
 RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
diff --git a/kokoro/linux/java_aarch64/build.sh b/kokoro/linux/java_aarch64/build.sh
new file mode 100755
index 0000000..ed5ad53
--- /dev/null
+++ b/kokoro/linux/java_aarch64/build.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "continuous" and "presubmit" jobs.
+
+set -ex
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
+
+kokoro/linux/aarch64/test_java_aarch64.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/java_aarch64/continuous.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/java_aarch64/continuous.cfg
index e2fc413..5db46d4 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/java_aarch64/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/java_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/java_aarch64/presubmit.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/java_aarch64/presubmit.cfg
index e2fc413..5db46d4 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/java_aarch64/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/java_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/java_compatibility/build.sh b/kokoro/linux/java_compatibility/build.sh
deleted file mode 100755
index de88454..0000000
--- a/kokoro/linux/java_compatibility/build.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# This is the top-level script we give to Kokoro as the entry point for
-# running the "pull request" project:
-#
-# This script selects a specific Dockerfile (for building a Docker image) and
-# a script to run inside that image.  Then we delegate to the general
-# build_and_run_docker.sh script.
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-export DOCKERFILE_DIR=kokoro/linux/64-bit
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="java_compatibility"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/java_compatibility/continuous.cfg b/kokoro/linux/java_compatibility/continuous.cfg
deleted file mode 100644
index 4897f5c..0000000
--- a/kokoro/linux/java_compatibility/continuous.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_compatibility/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/linux/java_compatibility/presubmit.cfg b/kokoro/linux/java_compatibility/presubmit.cfg
deleted file mode 100644
index 4897f5c..0000000
--- a/kokoro/linux/java_compatibility/presubmit.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_compatibility/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/linux/javascript_aarch64/build.sh b/kokoro/linux/javascript_aarch64/build.sh
new file mode 100755
index 0000000..dd9f8af
--- /dev/null
+++ b/kokoro/linux/javascript_aarch64/build.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "continuous" and "presubmit" jobs.
+
+set -ex
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
+
+kokoro/linux/aarch64/test_javascript_aarch64.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/javascript_aarch64/continuous.cfg
similarity index 72%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/javascript_aarch64/continuous.cfg
index e2fc413..947bc75 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/javascript_aarch64/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/javascript_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/javascript_aarch64/presubmit.cfg
similarity index 72%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/javascript_aarch64/presubmit.cfg
index e2fc413..947bc75 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/javascript_aarch64/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/javascript_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/php80/build.sh b/kokoro/linux/php80/build.sh
new file mode 100755
index 0000000..ba269e5
--- /dev/null
+++ b/kokoro/linux/php80/build.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# This is the entry point for kicking off a Kokoro job. This path is referenced
+# from the .cfg files in this directory.
+
+set -ex
+
+cd $(dirname $0)
+
+# Most of our tests use a debug build of PHP, but we do one build against an opt
+# php just in case that surfaces anything unexpected.
+../test_php.sh gcr.io/protobuf-build/php/linux:8.0.5-14a06550010c0649bf69b6c9b803c1ca609bbb6d
+
+../test_php.sh gcr.io/protobuf-build/php/linux:7.0.33-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d
+../test_php.sh gcr.io/protobuf-build/php/linux:7.3.28-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d
+../test_php.sh gcr.io/protobuf-build/php/linux:7.4.18-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d
+../test_php.sh gcr.io/protobuf-build/php/linux:8.0.5-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d
diff --git a/kokoro/linux/php80/continuous.cfg b/kokoro/linux/php80/continuous.cfg
new file mode 100644
index 0000000..6d67a8c
--- /dev/null
+++ b/kokoro/linux/php80/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/php80/build.sh"
+timeout_mins: 20
diff --git a/kokoro/linux/php80/presubmit.cfg b/kokoro/linux/php80/presubmit.cfg
new file mode 100644
index 0000000..6d67a8c
--- /dev/null
+++ b/kokoro/linux/php80/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/php80/build.sh"
+timeout_mins: 20
diff --git a/kokoro/linux/php_aarch64/build.sh b/kokoro/linux/php_aarch64/build.sh
new file mode 100755
index 0000000..eba8b55
--- /dev/null
+++ b/kokoro/linux/php_aarch64/build.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "continuous" and "presubmit" jobs.
+
+set -ex
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
+
+kokoro/linux/aarch64/test_php_aarch64.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/php_aarch64/continuous.cfg
similarity index 75%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/php_aarch64/continuous.cfg
index e2fc413..ff20682 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/php_aarch64/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/php_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/presubmit.cfg b/kokoro/linux/php_aarch64/presubmit.cfg
similarity index 75%
copy from kokoro/linux/python/presubmit.cfg
copy to kokoro/linux/php_aarch64/presubmit.cfg
index e2fc413..ff20682 100644
--- a/kokoro/linux/python/presubmit.cfg
+++ b/kokoro/linux/php_aarch64/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/php_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/php_all/build.sh b/kokoro/linux/php_all/build.sh
index 23468a7..1ee79ad 100755
--- a/kokoro/linux/php_all/build.sh
+++ b/kokoro/linux/php_all/build.sh
@@ -1,18 +1,20 @@
 #!/bin/bash
 #
-# This is the top-level script we give to Kokoro as the entry point for
-# running the "pull request" project:
-#
-# This script selects a specific Dockerfile (for building a Docker image) and
-# a script to run inside that image.  Then we delegate to the general
-# build_and_run_docker.sh script.
+# This is the entry point for kicking off a Kokoro job. This path is referenced
+# from the .cfg files in this directory.
 
-# Change to repo root
+set -ex
+
+# Change to repo base.
 cd $(dirname $0)/../../..
 
-export DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/php
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="php_all"
-./kokoro/linux/build_and_run_docker.sh
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:8.0.5-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d "composer test_valgrind"
+
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:7.0.33-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d "composer test && composer test_c"
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:7.3.28-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d "composer test && composer test_c"
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:7.4.18-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d "composer test && composer test_c"
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:8.0.5-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d "composer test && composer test_c"
+
+# Most of our tests use a debug build of PHP, but we do one build against an opt
+# php just in case that surfaces anything unexpected.
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:8.0.5-14a06550010c0649bf69b6c9b803c1ca609bbb6d "composer test && composer test_c"
diff --git a/kokoro/linux/python27/continuous.cfg b/kokoro/linux/python27/continuous.cfg
index e2fc413..dd98469 100644
--- a/kokoro/linux/python27/continuous.cfg
+++ b/kokoro/linux/python27/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python27/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python27/presubmit.cfg b/kokoro/linux/python27/presubmit.cfg
index e2fc413..dd98469 100644
--- a/kokoro/linux/python27/presubmit.cfg
+++ b/kokoro/linux/python27/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python27/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python27_cpp/continuous.cfg b/kokoro/linux/python27_cpp/continuous.cfg
index b1b0e55..ace22d0 100644
--- a/kokoro/linux/python27_cpp/continuous.cfg
+++ b/kokoro/linux/python27_cpp/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python27_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python27_cpp/presubmit.cfg b/kokoro/linux/python27_cpp/presubmit.cfg
index b1b0e55..ace22d0 100644
--- a/kokoro/linux/python27_cpp/presubmit.cfg
+++ b/kokoro/linux/python27_cpp/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python27_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python35/continuous.cfg b/kokoro/linux/python35/continuous.cfg
index e2fc413..2b3e12c 100644
--- a/kokoro/linux/python35/continuous.cfg
+++ b/kokoro/linux/python35/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python35/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python35/presubmit.cfg b/kokoro/linux/python35/presubmit.cfg
index e2fc413..2b3e12c 100644
--- a/kokoro/linux/python35/presubmit.cfg
+++ b/kokoro/linux/python35/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python35/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python35_cpp/continuous.cfg b/kokoro/linux/python35_cpp/continuous.cfg
index b1b0e55..ad5cc86 100644
--- a/kokoro/linux/python35_cpp/continuous.cfg
+++ b/kokoro/linux/python35_cpp/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python35_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python35_cpp/presubmit.cfg b/kokoro/linux/python35_cpp/presubmit.cfg
index b1b0e55..ad5cc86 100644
--- a/kokoro/linux/python35_cpp/presubmit.cfg
+++ b/kokoro/linux/python35_cpp/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python35_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python36/continuous.cfg b/kokoro/linux/python36/continuous.cfg
index e2fc413..ee7f488 100644
--- a/kokoro/linux/python36/continuous.cfg
+++ b/kokoro/linux/python36/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python36/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python36/presubmit.cfg b/kokoro/linux/python36/presubmit.cfg
index e2fc413..ee7f488 100644
--- a/kokoro/linux/python36/presubmit.cfg
+++ b/kokoro/linux/python36/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python36/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python36_cpp/continuous.cfg b/kokoro/linux/python36_cpp/continuous.cfg
index b1b0e55..df9e714 100644
--- a/kokoro/linux/python36_cpp/continuous.cfg
+++ b/kokoro/linux/python36_cpp/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python36_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python36_cpp/presubmit.cfg b/kokoro/linux/python36_cpp/presubmit.cfg
index b1b0e55..df9e714 100644
--- a/kokoro/linux/python36_cpp/presubmit.cfg
+++ b/kokoro/linux/python36_cpp/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python36_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python37/continuous.cfg b/kokoro/linux/python37/continuous.cfg
index e2fc413..9fa20c1 100644
--- a/kokoro/linux/python37/continuous.cfg
+++ b/kokoro/linux/python37/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python37/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python37/presubmit.cfg b/kokoro/linux/python37/presubmit.cfg
index e2fc413..9fa20c1 100644
--- a/kokoro/linux/python37/presubmit.cfg
+++ b/kokoro/linux/python37/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python37/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python37_cpp/continuous.cfg b/kokoro/linux/python37_cpp/continuous.cfg
index b1b0e55..49c441f 100644
--- a/kokoro/linux/python37_cpp/continuous.cfg
+++ b/kokoro/linux/python37_cpp/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python37_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python37_cpp/presubmit.cfg b/kokoro/linux/python37_cpp/presubmit.cfg
index b1b0e55..49c441f 100644
--- a/kokoro/linux/python37_cpp/presubmit.cfg
+++ b/kokoro/linux/python37_cpp/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python37_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python38/continuous.cfg b/kokoro/linux/python38/continuous.cfg
index e2fc413..76425d2 100644
--- a/kokoro/linux/python38/continuous.cfg
+++ b/kokoro/linux/python38/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python38/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python38/presubmit.cfg b/kokoro/linux/python38/presubmit.cfg
index e2fc413..76425d2 100644
--- a/kokoro/linux/python38/presubmit.cfg
+++ b/kokoro/linux/python38/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python38/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python38_cpp/continuous.cfg b/kokoro/linux/python38_cpp/continuous.cfg
index b1b0e55..1e8888c 100644
--- a/kokoro/linux/python38_cpp/continuous.cfg
+++ b/kokoro/linux/python38_cpp/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python38_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python38_cpp/presubmit.cfg b/kokoro/linux/python38_cpp/presubmit.cfg
index b1b0e55..1e8888c 100644
--- a/kokoro/linux/python38_cpp/presubmit.cfg
+++ b/kokoro/linux/python38_cpp/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
+build_file: "protobuf/kokoro/linux/python38_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/build.sh b/kokoro/linux/python39/build.sh
similarity index 78%
copy from kokoro/linux/python/build.sh
copy to kokoro/linux/python39/build.sh
index 86964f5..497dc66 100755
--- a/kokoro/linux/python/build.sh
+++ b/kokoro/linux/python39/build.sh
@@ -10,8 +10,9 @@
 # Change to repo root
 cd $(dirname $0)/../../..
 
-export DOCKERFILE_DIR=kokoro/linux/64-bit
+export DOCKERHUB_ORGANIZATION=protobuftesting
+export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python39
 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
 export OUTPUT_DIR=testoutput
-export TEST_SET="python"
+export TEST_SET="python39"
 ./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/python39/continuous.cfg
similarity index 76%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/python39/continuous.cfg
index e2fc413..b03bc90 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/python39/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python39/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/presubmit.cfg b/kokoro/linux/python39/presubmit.cfg
similarity index 76%
rename from kokoro/linux/python/presubmit.cfg
rename to kokoro/linux/python39/presubmit.cfg
index e2fc413..b03bc90 100644
--- a/kokoro/linux/python/presubmit.cfg
+++ b/kokoro/linux/python39/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python39/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/build.sh b/kokoro/linux/python39_cpp/build.sh
similarity index 78%
copy from kokoro/linux/python/build.sh
copy to kokoro/linux/python39_cpp/build.sh
index 86964f5..f45d2ec 100755
--- a/kokoro/linux/python/build.sh
+++ b/kokoro/linux/python39_cpp/build.sh
@@ -10,8 +10,9 @@
 # Change to repo root
 cd $(dirname $0)/../../..
 
-export DOCKERFILE_DIR=kokoro/linux/64-bit
+export DOCKERHUB_ORGANIZATION=protobuftesting
+export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python39
 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
 export OUTPUT_DIR=testoutput
-export TEST_SET="python"
+export TEST_SET="python39_cpp"
 ./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/python39_cpp/continuous.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/python39_cpp/continuous.cfg
index e2fc413..dd84fbe 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/python39_cpp/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python39_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/python39_cpp/presubmit.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/python39_cpp/presubmit.cfg
index e2fc413..dd84fbe 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/python39_cpp/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python39_cpp/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python_aarch64/build.sh b/kokoro/linux/python_aarch64/build.sh
new file mode 100755
index 0000000..2c67396
--- /dev/null
+++ b/kokoro/linux/python_aarch64/build.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "continuous" and "presubmit" jobs.
+
+set -ex
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
+
+kokoro/linux/aarch64/test_python_aarch64.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/python_aarch64/continuous.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/python_aarch64/continuous.cfg
index e2fc413..dee4a47 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/python_aarch64/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/presubmit.cfg b/kokoro/linux/python_aarch64/presubmit.cfg
similarity index 74%
copy from kokoro/linux/python/presubmit.cfg
copy to kokoro/linux/python_aarch64/presubmit.cfg
index e2fc413..dee4a47 100644
--- a/kokoro/linux/python/presubmit.cfg
+++ b/kokoro/linux/python_aarch64/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/python_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/build.sh b/kokoro/linux/ruby27/build.sh
similarity index 79%
rename from kokoro/linux/python/build.sh
rename to kokoro/linux/ruby27/build.sh
index 86964f5..c38ee36 100755
--- a/kokoro/linux/python/build.sh
+++ b/kokoro/linux/ruby27/build.sh
@@ -10,8 +10,9 @@
 # Change to repo root
 cd $(dirname $0)/../../..
 
-export DOCKERFILE_DIR=kokoro/linux/64-bit
+export DOCKERHUB_ORGANIZATION=protobuftesting
+export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby
 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
 export OUTPUT_DIR=testoutput
-export TEST_SET="python"
+export TEST_SET="ruby27"
 ./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/ruby27/continuous.cfg
similarity index 76%
rename from kokoro/linux/python/continuous.cfg
rename to kokoro/linux/ruby27/continuous.cfg
index e2fc413..9cce8c9 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/ruby27/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/ruby27/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/ruby27/presubmit.cfg
similarity index 76%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/ruby27/presubmit.cfg
index e2fc413..9cce8c9 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/ruby27/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/ruby27/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/build.sh b/kokoro/linux/ruby30/build.sh
similarity index 79%
copy from kokoro/linux/python/build.sh
copy to kokoro/linux/ruby30/build.sh
index 86964f5..9e44575 100755
--- a/kokoro/linux/python/build.sh
+++ b/kokoro/linux/ruby30/build.sh
@@ -10,8 +10,9 @@
 # Change to repo root
 cd $(dirname $0)/../../..
 
-export DOCKERFILE_DIR=kokoro/linux/64-bit
+export DOCKERHUB_ORGANIZATION=protobuftesting
+export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby
 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
 export OUTPUT_DIR=testoutput
-export TEST_SET="python"
+export TEST_SET="ruby30"
 ./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/ruby30/continuous.cfg
similarity index 76%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/ruby30/continuous.cfg
index e2fc413..b03a335 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/ruby30/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/ruby30/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/ruby30/presubmit.cfg
similarity index 76%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/ruby30/presubmit.cfg
index e2fc413..b03a335 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/ruby30/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/ruby30/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/ruby_aarch64/build.sh b/kokoro/linux/ruby_aarch64/build.sh
new file mode 100755
index 0000000..6473e0d
--- /dev/null
+++ b/kokoro/linux/ruby_aarch64/build.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "continuous" and "presubmit" jobs.
+
+set -ex
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+kokoro/linux/aarch64/qemu_helpers/prepare_qemu.sh
+
+kokoro/linux/aarch64/test_ruby_aarch64.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/ruby_aarch64/continuous.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/ruby_aarch64/continuous.cfg
index e2fc413..ae82696 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/ruby_aarch64/continuous.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/ruby_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/ruby_aarch64/presubmit.cfg
similarity index 74%
copy from kokoro/linux/python/continuous.cfg
copy to kokoro/linux/ruby_aarch64/presubmit.cfg
index e2fc413..ae82696 100644
--- a/kokoro/linux/python/continuous.cfg
+++ b/kokoro/linux/ruby_aarch64/presubmit.cfg
@@ -1,7 +1,7 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
+build_file: "protobuf/kokoro/linux/ruby_aarch64/build.sh"
 timeout_mins: 120
 
 action {
diff --git a/kokoro/macos/objectivec_cocoapods_integration/build.sh b/kokoro/macos/objectivec_cocoapods_integration/build.sh
index f96d289..8f3c9b4 100755
--- a/kokoro/macos/objectivec_cocoapods_integration/build.sh
+++ b/kokoro/macos/objectivec_cocoapods_integration/build.sh
@@ -6,6 +6,7 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_COCOAPODS=yes
 source kokoro/macos/prepare_build_macos_rc
 
 ./tests.sh objectivec_cocoapods_integration
diff --git a/kokoro/macos/php5.6_mac/presubmit.cfg b/kokoro/macos/php5.6_mac/presubmit.cfg
deleted file mode 100644
index ff345e9..0000000
--- a/kokoro/macos/php5.6_mac/presubmit.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/php5.6_mac/build.sh b/kokoro/macos/php7.3_mac/build.sh
similarity index 89%
rename from kokoro/macos/php5.6_mac/build.sh
rename to kokoro/macos/php7.3_mac/build.sh
index 7487889..2d2f679 100755
--- a/kokoro/macos/php5.6_mac/build.sh
+++ b/kokoro/macos/php7.3_mac/build.sh
@@ -8,4 +8,4 @@
 # Prepare worker environment to run tests
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh php5.6_mac
+./tests.sh php7.3_mac
diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/php7.3_mac/continuous.cfg
similarity index 65%
rename from kokoro/macos/php5.6_mac/continuous.cfg
rename to kokoro/macos/php7.3_mac/continuous.cfg
index ff345e9..9a71745 100644
--- a/kokoro/macos/php5.6_mac/continuous.cfg
+++ b/kokoro/macos/php7.3_mac/continuous.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh"
 timeout_mins: 1440
diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/php7.3_mac/presubmit.cfg
similarity index 65%
copy from kokoro/macos/php5.6_mac/continuous.cfg
copy to kokoro/macos/php7.3_mac/presubmit.cfg
index ff345e9..9a71745 100644
--- a/kokoro/macos/php5.6_mac/continuous.cfg
+++ b/kokoro/macos/php7.3_mac/presubmit.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh"
 timeout_mins: 1440
diff --git a/kokoro/macos/php7.4_mac/build.sh b/kokoro/macos/php7.4_mac/build.sh
deleted file mode 100755
index 98c82d4..0000000
--- a/kokoro/macos/php7.4_mac/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-#
-# Build file to set up and run tests
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-# Prepare worker environment to run tests
-source kokoro/macos/prepare_build_macos_rc
-
-./tests.sh php7.4_mac
diff --git a/kokoro/macos/php7.4_mac/continuous.cfg b/kokoro/macos/php7.4_mac/continuous.cfg
deleted file mode 100644
index 5b2d6fd..0000000
--- a/kokoro/macos/php7.4_mac/continuous.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php7.4_mac/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/php7.4_mac/presubmit.cfg b/kokoro/macos/php7.4_mac/presubmit.cfg
deleted file mode 100644
index 5b2d6fd..0000000
--- a/kokoro/macos/php7.4_mac/presubmit.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php7.4_mac/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/prepare_build_macos_rc b/kokoro/macos/prepare_build_macos_rc
index 2428750..dcd17f3 100755
--- a/kokoro/macos/prepare_build_macos_rc
+++ b/kokoro/macos/prepare_build_macos_rc
@@ -2,6 +2,8 @@
 #
 # This script sets up a Kokoro MacOS worker for running Protobuf tests
 
+set -eux
+
 ##
 # Select Xcode version
 
@@ -18,24 +20,70 @@
 export CXX=g++
 
 ##
-# Install Brew and core softwares
+# Brew: update, then upgrade the installed tools to current version and install
+# some needed ones not in the Kokoro base image. This ensure current versions
+# of CMake, autotools, etc.
 
-ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
-source $HOME/.rvm/scripts/rvm
-brew uninstall node icu4c cmake wget
-brew prune
-brew install gflags gpg gpg2 node openssl pcre ruby cmake wget
-sudo chown -R $(whoami) /usr/local
-brew postinstall node
+# But first...
+#
+# The transitive deps of the installed tools need protobuf, but Kokoro manually
+# installed it outside of brew so it needs to be removed so brew can install the
+# tools (and a newer version of protobuf). g/kokoro-users/7FRvQMUdN40 about why
+# it is a manual install vs. a brew install in the first place.
+sudo rm -rf \
+    /usr/local/include/google/protobuf \
+    /usr/local/bin/protoc
+# Likewise, updating python can have issues because of some existing binaries.
+sudo rm -rf \
+    /usr/local/bin/2to3* \
+    /usr/local/bin/idle3* \
+    /usr/local/bin/pip3 \
+    /usr/local/bin/pydoc3* \
+    /usr/local/bin/python3* \
+    /usr/local/bin/pyvenv*
+
+git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
+git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
+
+# This is needed to fix a conflict between the ilmbase and imath packages,
+# which seem to conflict with each other by both trying to install
+# libImath.dylib.
+brew unlink ilmbase
+
+brew update
+brew upgrade
+
+##
+# Install Ruby
+
+if [[ "${KOKORO_INSTALL_RUBY:-}" == "yes" ]] ; then
+  brew install ruby
+fi
+
+##
+# Install Cocoapods
+
+if [[ "${KOKORO_INSTALL_COCOAPODS:-}" == "yes" ]] ; then
+  # The existing cocoapods was installed via gem, but that doesn't work well
+  # with the overlap in deps with things managed by brew (errors around ruby
+  # versions, etc.); so remove it and install in via brew instead.
+  gem uninstall -a "$(gem list | grep cocoapods | cut -d ' ' -f 1)"
+  brew install cocoapods
+fi
 
 ##
 # Install Tox
 
-sudo pip install tox==2.4.1
+if [[ "${KOKORO_INSTALL_TOX:-}" == "yes" ]] ; then
+  sudo python3 -m pip install --upgrade pip tox
+fi
 
 ##
 # Install RVM
 
-gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
-command curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -
-curl -sSL https://get.rvm.io | bash -s stable --ruby
+if [[ "${KOKORO_INSTALL_RVM:-}" == "yes" ]] ; then
+  curl -sSL https://rvm.io/mpapis.asc | gpg --import -
+  curl -sSL https://rvm.io/pkuczynski.asc | gpg --import -
+
+  curl -sSL https://get.rvm.io | bash -s master --ruby
+fi
diff --git a/kokoro/macos/python/build.sh b/kokoro/macos/python/build.sh
index 6b17b95..388e24b 100755
--- a/kokoro/macos/python/build.sh
+++ b/kokoro/macos/python/build.sh
@@ -6,6 +6,7 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_TOX=yes
 source kokoro/macos/prepare_build_macos_rc
 
 ./tests.sh python
diff --git a/kokoro/macos/python_cpp/build.sh b/kokoro/macos/python_cpp/build.sh
index cb53def..f86dd6f 100755
--- a/kokoro/macos/python_cpp/build.sh
+++ b/kokoro/macos/python_cpp/build.sh
@@ -6,6 +6,7 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_TOX=yes
 source kokoro/macos/prepare_build_macos_rc
 g++ --version
 
diff --git a/kokoro/macos/ruby23/build.sh b/kokoro/macos/ruby23/build.sh
index dc950a2..9317838 100755
--- a/kokoro/macos/ruby23/build.sh
+++ b/kokoro/macos/ruby23/build.sh
@@ -6,6 +6,8 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_RUBY=yes
+KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
 ./tests.sh ruby23
diff --git a/kokoro/macos/ruby24/build.sh b/kokoro/macos/ruby24/build.sh
index 3c3a190..51bb2e6 100755
--- a/kokoro/macos/ruby24/build.sh
+++ b/kokoro/macos/ruby24/build.sh
@@ -6,6 +6,8 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_RUBY=yes
+KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
 ./tests.sh ruby24
diff --git a/kokoro/macos/ruby25/build.sh b/kokoro/macos/ruby25/build.sh
index 38e90aa..ba2d0a4 100755
--- a/kokoro/macos/ruby25/build.sh
+++ b/kokoro/macos/ruby25/build.sh
@@ -6,6 +6,8 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_RUBY=yes
+KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
 ./tests.sh ruby25
diff --git a/kokoro/macos/ruby26/build.sh b/kokoro/macos/ruby26/build.sh
index 6c33ed0..5a4c243 100755
--- a/kokoro/macos/ruby26/build.sh
+++ b/kokoro/macos/ruby26/build.sh
@@ -6,6 +6,8 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_RUBY=yes
+KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
 ./tests.sh ruby26
diff --git a/kokoro/macos/php5.6_mac/build.sh b/kokoro/macos/ruby27/build.sh
similarity index 74%
copy from kokoro/macos/php5.6_mac/build.sh
copy to kokoro/macos/ruby27/build.sh
index 7487889..b1529b9 100755
--- a/kokoro/macos/php5.6_mac/build.sh
+++ b/kokoro/macos/ruby27/build.sh
@@ -6,6 +6,8 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_RUBY=yes
+KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh php5.6_mac
+./tests.sh ruby27
diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/ruby27/continuous.cfg
similarity index 65%
copy from kokoro/macos/php5.6_mac/continuous.cfg
copy to kokoro/macos/ruby27/continuous.cfg
index ff345e9..b10b455 100644
--- a/kokoro/macos/php5.6_mac/continuous.cfg
+++ b/kokoro/macos/ruby27/continuous.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+build_file: "protobuf/kokoro/macos/ruby27/build.sh"
 timeout_mins: 1440
diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/ruby27/presubmit.cfg
similarity index 65%
copy from kokoro/macos/php5.6_mac/continuous.cfg
copy to kokoro/macos/ruby27/presubmit.cfg
index ff345e9..b10b455 100644
--- a/kokoro/macos/php5.6_mac/continuous.cfg
+++ b/kokoro/macos/ruby27/presubmit.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+build_file: "protobuf/kokoro/macos/ruby27/build.sh"
 timeout_mins: 1440
diff --git a/kokoro/macos/php5.6_mac/build.sh b/kokoro/macos/ruby30/build.sh
similarity index 74%
copy from kokoro/macos/php5.6_mac/build.sh
copy to kokoro/macos/ruby30/build.sh
index 7487889..6b9bfb3 100755
--- a/kokoro/macos/php5.6_mac/build.sh
+++ b/kokoro/macos/ruby30/build.sh
@@ -6,6 +6,8 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
+KOKORO_INSTALL_RUBY=yes
+KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh php5.6_mac
+./tests.sh ruby30
diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/ruby30/continuous.cfg
similarity index 65%
copy from kokoro/macos/php5.6_mac/continuous.cfg
copy to kokoro/macos/ruby30/continuous.cfg
index ff345e9..d505117 100644
--- a/kokoro/macos/php5.6_mac/continuous.cfg
+++ b/kokoro/macos/ruby30/continuous.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+build_file: "protobuf/kokoro/macos/ruby30/build.sh"
 timeout_mins: 1440
diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/ruby30/presubmit.cfg
similarity index 65%
copy from kokoro/macos/php5.6_mac/continuous.cfg
copy to kokoro/macos/ruby30/presubmit.cfg
index ff345e9..d505117 100644
--- a/kokoro/macos/php5.6_mac/continuous.cfg
+++ b/kokoro/macos/ruby30/presubmit.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+build_file: "protobuf/kokoro/macos/ruby30/build.sh"
 timeout_mins: 1440
diff --git a/kokoro/release/collect_all_artifacts.sh b/kokoro/release/collect_all_artifacts.sh
index 3b7d7d4..3372a01 100755
--- a/kokoro/release/collect_all_artifacts.sh
+++ b/kokoro/release/collect_all_artifacts.sh
@@ -39,7 +39,7 @@
 mkdir -p protoc/linux_x86
 mkdir -p protoc/linux_x64
 # Because of maven unrelated reasonse the linux protoc binaries have a dummy .exe extension.
-# For the Google.Protobuf.Tools nuget, we don't want that expection, so we just remove it.
+# For the Google.Protobuf.Tools nuget, we don't want that exception, so we just remove it.
 cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_32/protoc.exe protoc/linux_x86/protoc
 cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_64/protoc.exe protoc/linux_x64/protoc
 
@@ -49,8 +49,7 @@
 # Install nuget (will also install  mono)
 # TODO(jtattermusch): use "mono:5.14" docker image instead so we don't have to apt-get install
 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
-sudo apt install apt-transport-https
-echo "deb https://download.mono-project.com/repo/ubuntu stable-trusty main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
+echo "deb https://download.mono-project.com/repo/ubuntu stable-xenial main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
 sudo apt update
 sudo apt-get install -y nuget
 
diff --git a/kokoro/release/csharp/windows/build_nuget.bat b/kokoro/release/csharp/windows/build_nuget.bat
index 0ff8db0..590c391 100644
--- a/kokoro/release/csharp/windows/build_nuget.bat
+++ b/kokoro/release/csharp/windows/build_nuget.bat
@@ -11,4 +11,7 @@
 set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
 set DOTNET_CLI_TELEMETRY_OPTOUT=true
 
+@rem Work around https://github.com/dotnet/core/issues/5881
+dotnet nuget locals all --clear
+
 call build_packages.bat
diff --git a/kokoro/release/protoc/linux/build.sh b/kokoro/release/protoc/linux/build.sh
index efc3ee6..44a95aa 100755
--- a/kokoro/release/protoc/linux/build.sh
+++ b/kokoro/release/protoc/linux/build.sh
@@ -23,7 +23,7 @@
 protoc-artifacts/build-protoc.sh linux ppcle_64 protoc
 
 sudo apt install -y g++-s390x-linux-gnu
-protoc-artifacts/build-protoc.sh linux s390x protoc
+protoc-artifacts/build-protoc.sh linux s390_64 protoc
 
 # Use docker image to build linux artifacts.
 DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
diff --git a/kokoro/release/python/linux/build_artifacts.sh b/kokoro/release/python/linux/build_artifacts.sh
index fd9d5a9..fc9e740 100755
--- a/kokoro/release/python/linux/build_artifacts.sh
+++ b/kokoro/release/python/linux/build_artifacts.sh
@@ -30,10 +30,6 @@
 
 build_artifact_version() {
   MB_PYTHON_VERSION=$1
-
-  # Clean up env
-  rm -rf venv
-  sudo rm -rf $REPO_DIR
   cp -R $STAGE_DIR $REPO_DIR
 
   source multibuild/common_utils.sh
@@ -47,6 +43,20 @@
   build_wheel $REPO_DIR/python $PLAT
 
   mv wheelhouse/* $ARTIFACT_DIR
+
+  # Clean up env
+  rm -rf venv
+  sudo rm -rf $REPO_DIR
+}
+
+build_crosscompiled_aarch64_artifact_version() {
+  # crosscompilation is only supported with the dockcross manylinux2014 image
+  DOCKER_IMAGE=dockcross/manylinux2014-aarch64
+  PLAT=aarch64
+
+  # TODO(jtatermusch): currently when crosscompiling, "auditwheel repair" will be disabled
+  # since auditwheel doesn't work for crosscomiled wheels.
+  build_artifact_version $@
 }
 
 build_artifact_version 2.7
@@ -54,3 +64,8 @@
 build_artifact_version 3.6
 build_artifact_version 3.7
 build_artifact_version 3.8
+build_artifact_version 3.9
+
+build_crosscompiled_aarch64_artifact_version 3.7
+build_crosscompiled_aarch64_artifact_version 3.8
+build_crosscompiled_aarch64_artifact_version 3.9
diff --git a/kokoro/release/python/linux/config.sh b/kokoro/release/python/linux/config.sh
index 7a8f663..e29eb58 100644
--- a/kokoro/release/python/linux/config.sh
+++ b/kokoro/release/python/linux/config.sh
@@ -6,15 +6,38 @@
     # Runs in the root directory of this repository.
     pushd protobuf
 
-    yum install -y devtoolset-2-libatomic-devel
+    if [ "$PLAT" == "aarch64" ]
+    then
+      local configure_host_flag="--host=aarch64"
+    else
+      yum install -y devtoolset-2-libatomic-devel
+    fi
 
-    # Build protoc
+    # Build protoc and libprotobuf
     ./autogen.sh
-    ./configure
-
-    CXXFLAGS="-fPIC -g -O2" ./configure
+    CXXFLAGS="-fPIC -g -O2" ./configure $configure_host_flag
     make -j8
 
+    if [ "$PLAT" == "aarch64" ]
+    then
+      # we are crosscompiling for aarch64 while running on x64
+      # the simplest way for build_py command to be able to generate
+      # the protos is by running the protoc process under
+      # an emulator. That way we don't have to build a x64 version
+      # of protoc. The qemu-arm emulator is already included
+      # in the dockcross docker image.
+      # Running protoc under an emulator is fast as protoc doesn't
+      # really do much.
+
+      # create a simple shell wrapper that runs crosscompiled protoc under qemu
+      echo '#!/bin/bash' >protoc_qemu_wrapper.sh
+      echo 'exec qemu-aarch64 "../src/protoc" "$@"' >>protoc_qemu_wrapper.sh
+      chmod ugo+x protoc_qemu_wrapper.sh
+
+      # PROTOC variable is by build_py step that runs under ./python directory
+      export PROTOC=../protoc_qemu_wrapper.sh
+    fi
+
     # Generate python dependencies.
     pushd python
     python setup.py build_py
@@ -35,7 +58,20 @@
     # Modify build version
     pwd
     ls
-    python setup.py bdist_wheel --cpp_implementation --compile_static_extension
+
+    if [ "$PLAT" == "aarch64" ]
+    then
+      # when crosscompiling for aarch64, --plat-name needs to be set explicitly
+      # to end up with correctly named wheel file
+      # the value should be manylinuxABC_ARCH and dockcross docker image
+      # conveniently provides the value in the AUDITWHEEL_PLAT env
+      local plat_name_flag="--plat-name=$AUDITWHEEL_PLAT"
+
+      # override the value of EXT_SUFFIX to make sure the crosscompiled .so files in the wheel have the correct filename suffix
+      export PROTOCOL_BUFFERS_OVERRIDE_EXT_SUFFIX="$(python -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX").replace("-x86_64-linux-gnu.so", "-aarch64-linux-gnu.so"))')"
+    fi
+
+    python setup.py bdist_wheel --cpp_implementation --compile_static_extension $plat_name_flag
     cp dist/*.whl $abs_wheelhouse
 }
 
@@ -48,3 +84,12 @@
     python --version
     python -c "from google.protobuf.pyext import _message;"
 }
+
+if [ "$PLAT" == "aarch64" ]
+then
+  # when crosscompiling for aarch64, override the default multibuild's repair_wheelhouse logic
+  # since "auditwheel repair" doesn't work for crosscompiled wheels
+  function repair_wheelhouse {
+      echo "Skipping repair_wheelhouse since auditwheel requires build architecture to match wheel architecture."
+  }
+fi
diff --git a/kokoro/release/python/macos/build_artifacts.sh b/kokoro/release/python/macos/build_artifacts.sh
index 15aae39..7801b01 100755
--- a/kokoro/release/python/macos/build_artifacts.sh
+++ b/kokoro/release/python/macos/build_artifacts.sh
@@ -55,6 +55,7 @@
 build_artifact_version 3.6
 build_artifact_version 3.7
 build_artifact_version 3.8
+build_artifact_version 3.9
 
 # python OSX10.9 does not have python 3.5
 export MB_PYTHON_OSX_VER=10.6
diff --git a/kokoro/release/python/macos/config.sh b/kokoro/release/python/macos/config.sh
index 741988a..1b0a302 100644
--- a/kokoro/release/python/macos/config.sh
+++ b/kokoro/release/python/macos/config.sh
@@ -1,6 +1,25 @@
 # Define custom utilities
 # Test for OSX with [ -n "$IS_OSX" ]
 
+function remove_travis_ve_pip {
+    # Removing the system virtualenv or pip can be very problematic for
+    # macOS on Kokoro, so just leave them be.
+    :;
+}
+
+function install_pip {
+    check_python
+    PIP_CMD="sudo $PYTHON_EXE -m pip${pip_args:+ $pip_args}"
+    $PIP_CMD install --upgrade pip
+}
+
+function install_virtualenv {
+    check_python
+    check_pip
+    $PIP_CMD install --upgrade virtualenv
+    VIRTUALENV_CMD="$PYTHON_EXE -m virtualenv"
+}
+
 function pre_build {
     # Any stuff that you need to do before you start building the wheels
     # Runs in the root directory of this repository.
diff --git a/kokoro/release/python/windows/build_artifacts.bat b/kokoro/release/python/windows/build_artifacts.bat
index 70a86a1..2a5b7b6 100644
--- a/kokoro/release/python/windows/build_artifacts.bat
+++ b/kokoro/release/python/windows/build_artifacts.bat
@@ -62,6 +62,8 @@
 SET PYTHON_ARCH=64
 CALL build_single_artifact.bat || goto :error
 
+powershell -File kokoro/release/python/windows/install_python_interpreters.ps1
+
 SET PYTHON=C:\python38_32bit
 SET PYTHON_VERSION=3.8
 SET PYTHON_ARCH=32
@@ -72,6 +74,16 @@
 SET PYTHON_ARCH=64
 CALL build_single_artifact.bat || goto :error
 
+SET PYTHON=C:\python39_32bit
+SET PYTHON_VERSION=3.9
+SET PYTHON_ARCH=32
+CALL build_single_artifact.bat || goto :error
+
+SET PYTHON=C:\python39
+SET PYTHON_VERSION=3.9
+SET PYTHON_ARCH=64
+CALL build_single_artifact.bat || goto :error
+
 goto :EOF
 
 :error
diff --git a/kokoro/release/python/windows/build_single_artifact.bat b/kokoro/release/python/windows/build_single_artifact.bat
index 45843e1..a3cfef9 100644
--- a/kokoro/release/python/windows/build_single_artifact.bat
+++ b/kokoro/release/python/windows/build_single_artifact.bat
@@ -24,10 +24,16 @@
 if %PYTHON%==C:\python38 set generator=Visual Studio 14 Win64
 if %PYTHON%==C:\python38 set vcplatform=x64
 
+if %PYTHON%==C:\python39_32bit set generator=Visual Studio 14
+if %PYTHON%==C:\python39_32bit set vcplatform=Win32
+
+if %PYTHON%==C:\python39 set generator=Visual Studio 14 Win64
+if %PYTHON%==C:\python39 set vcplatform=x64
+
 REM Prepend newly installed Python to the PATH of this build (this cannot be
 REM done from inside the powershell script as it would require to restart
 REM the parent CMD process).
-SET PATH=%PYTHON%;%PYTHON%\Scripts;%OLD_PATH%
+SET PATH=C:\Program Files\CMake\bin;%PYTHON%;%PYTHON%\Scripts;%OLD_PATH%
 python -m pip install -U pip
 pip install wheel
 
diff --git a/kokoro/release/python/windows/install_python_interpreters.ps1 b/kokoro/release/python/windows/install_python_interpreters.ps1
new file mode 100644
index 0000000..b63259a
--- /dev/null
+++ b/kokoro/release/python/windows/install_python_interpreters.ps1
@@ -0,0 +1,97 @@
+#!/usr/bin/env powershell
+# Install Python 3.8 for x64 and x86 in order to build wheels on Windows.
+# Originally from grpc/tools/internal_ci/helper_scripts/install_python_interpreters.ps1
+
+Set-StrictMode -Version 2
+$ErrorActionPreference = 'Stop'
+
+trap {
+    $ErrorActionPreference = "Continue"
+    Write-Error $_
+    exit 1
+}
+
+# Avoid "Could not create SSL/TLS secure channel"
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+function Install-Python {
+    Param(
+        [string]$PythonVersion,
+        [string]$PythonInstaller,
+        [string]$PythonInstallPath,
+        [string]$PythonInstallerHash
+    )
+    $PythonInstallerUrl = "https://www.python.org/ftp/python/$PythonVersion/$PythonInstaller.exe"
+    $PythonInstallerPath = "C:\tools\$PythonInstaller.exe"
+
+    # Downloads installer
+    Write-Host "Downloading the Python installer: $PythonInstallerUrl => $PythonInstallerPath"
+    Invoke-WebRequest -Uri $PythonInstallerUrl -OutFile $PythonInstallerPath
+
+    # Validates checksum
+    $HashFromDownload = Get-FileHash -Path $PythonInstallerPath -Algorithm MD5
+    if ($HashFromDownload.Hash -ne $PythonInstallerHash) {
+        throw "Invalid Python installer: failed checksum!"
+    }
+    Write-Host "Python installer $PythonInstallerPath validated."
+
+    # Installs Python
+    & $PythonInstallerPath /passive InstallAllUsers=1 PrependPath=1 Include_test=0 TargetDir=$PythonInstallPath
+    if (-Not $?) {
+        throw "The Python installation exited with error!"
+    }
+
+    # NOTE(lidiz) Even if the install command finishes in the script, that
+    # doesn't mean the Python installation is finished. If using "ps" to check
+    # for running processes, you might see ongoing installers at this point.
+    # So, we needs this "hack" to reliably validate that the Python binary is
+    # functioning properly.
+
+    # Wait for the installer process
+    Wait-Process -Name $PythonInstaller -Timeout 300
+    Write-Host "Installation process exits normally."
+
+    # Validate Python binary
+    $PythonBinary = "$PythonInstallPath\python.exe"
+    & $PythonBinary -c 'print(42)'
+    Write-Host "Python binary works properly."
+
+    # Installs pip
+    & $PythonBinary -m ensurepip --user
+
+    Write-Host "Python $PythonVersion installed by $PythonInstaller at $PythonInstallPath."
+}
+
+# Python 3.8
+$Python38x86Config = @{
+    PythonVersion = "3.8.0"
+    PythonInstaller = "python-3.8.0"
+    PythonInstallPath = "C:\python38_32bit"
+    PythonInstallerHash = "412a649d36626d33b8ca5593cf18318c"
+}
+Install-Python @Python38x86Config
+
+$Python38x64Config = @{
+    PythonVersion = "3.8.0"
+    PythonInstaller = "python-3.8.0-amd64"
+    PythonInstallPath = "C:\python38"
+    PythonInstallerHash = "29ea87f24c32f5e924b7d63f8a08ee8d"
+}
+Install-Python @Python38x64Config
+
+# Python 3.9
+$Python39x86Config = @{
+    PythonVersion = "3.9.0"
+    PythonInstaller = "python-3.9.0"
+    PythonInstallPath = "C:\python39_32bit"
+    PythonInstallerHash = "4a2812db8ab9f2e522c96c7728cfcccb"
+}
+Install-Python @Python39x86Config
+
+$Python39x64Config = @{
+    PythonVersion = "3.9.0"
+    PythonInstaller = "python-3.9.0-amd64"
+    PythonInstallPath = "C:\python39"
+    PythonInstallerHash = "b61a33dc28f13b561452f3089c87eb63"
+}
+Install-Python @Python39x64Config
diff --git a/kokoro/release/ruby/linux/ruby/ruby_build.sh b/kokoro/release/ruby/linux/ruby/ruby_build.sh
index 95f1dea..f8ae962 100755
--- a/kokoro/release/ruby/linux/ruby/ruby_build.sh
+++ b/kokoro/release/ruby/linux/ruby/ruby_build.sh
@@ -12,7 +12,7 @@
 umask 0022
 pushd ruby
 gem install bundler -v 2.1.4
-bundle install && bundle exec rake gem:native
+bundle update && bundle exec rake gem:native
 ls pkg
 mv pkg/* $ARTIFACT_DIR
 popd
diff --git a/kokoro/release/ruby/macos/ruby/ruby_build.sh b/kokoro/release/ruby/macos/ruby/ruby_build.sh
index 9fc42b1..7f6c18f 100755
--- a/kokoro/release/ruby/macos/ruby/ruby_build.sh
+++ b/kokoro/release/ruby/macos/ruby/ruby_build.sh
@@ -11,7 +11,7 @@
 
 umask 0022
 pushd ruby
-bundle install && bundle exec rake gem:native
+bundle update && bundle exec rake gem:native
 ls pkg
 mv pkg/* $ARTIFACT_DIR
 popd
diff --git a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
index a4bf9e0..046b604 100755
--- a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
+++ b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
@@ -21,13 +21,13 @@
 
 CROSS_RUBY=$(mktemp tmpfile.XXXXXXXX)
 
-curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v1.1.0/tasks/bin/cross-ruby.rake > "$CROSS_RUBY"
+curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/72184e51779b6a3b9b8580b036a052fdc3181ced/tasks/bin/cross-ruby.rake > "$CROSS_RUBY"
 
 # See https://github.com/grpc/grpc/issues/12161 for verconf.h patch details
 patch "$CROSS_RUBY" << EOF
---- cross-ruby.rake	2018-04-10 11:32:16.000000000 -0700
-+++ patched	2018-04-10 11:40:25.000000000 -0700
-@@ -141,8 +141,10 @@
+--- cross-ruby.rake	2020-12-11 11:17:53.000000000 +0900
++++ patched	2020-12-11 11:18:52.000000000 +0900
+@@ -111,10 +111,12 @@
      "--host=#{MINGW_HOST}",
      "--target=#{MINGW_TARGET}",
      "--build=#{RUBY_BUILD}",
@@ -36,10 +36,13 @@
 +    '--disable-shared',
      '--disable-install-doc',
 +    '--without-gmp',
-     '--with-ext='
+     '--with-ext=',
+-    'LDFLAGS=-pipe -s',
++    'LDFLAGS=-pipe',
    ]
 
-@@ -159,6 +161,7 @@
+   # Force Winsock2 for Ruby 1.8, 1.9 defaults to it
+@@ -130,6 +132,7 @@
  # make
  file "#{build_dir}/ruby.exe" => ["#{build_dir}/Makefile"] do |t|
    chdir File.dirname(t.prerequisites.first) do
@@ -55,7 +58,7 @@
 rvm use 2.7.0
 set -x
 ruby --version | grep 'ruby 2.7.0'
-for v in 2.7.0 ; do
+for v in 3.0.0 2.7.0 ; do
   ccache -c
   rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE"
 done
@@ -63,7 +66,7 @@
 rvm use 2.5.0
 set -x
 ruby --version | grep 'ruby 2.5.0'
-for v in 2.6.0 2.5.1 2.4.0 2.3.0 ; do
+for v in 2.6.0 2.5.1 2.4.0 2.3.0; do
   ccache -c
   rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE"
 done
diff --git a/kokoro/windows/csharp/build.bat b/kokoro/windows/csharp/build.bat
index 95224f2..4f1df37 100644
--- a/kokoro/windows/csharp/build.bat
+++ b/kokoro/windows/csharp/build.bat
@@ -11,4 +11,7 @@
 set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
 set DOTNET_CLI_TELEMETRY_OPTOUT=true
 
+@rem Work around https://github.com/dotnet/core/issues/5881
+dotnet nuget locals all --clear
+
 call buildall.bat
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
index d218d1a..1598d07 100644
--- a/m4/ax_pthread.m4
+++ b/m4/ax_pthread.m4
@@ -1,5 +1,5 @@
 # ===========================================================================
-#        http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+#        https://www.gnu.org/software/autoconf-archive/ax_pthread.html
 # ===========================================================================
 #
 # SYNOPSIS
@@ -55,6 +55,7 @@
 #
 #   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
 #   Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
+#   Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
 #
 #   This program is free software: you can redistribute it and/or modify it
 #   under the terms of the GNU General Public License as published by the
@@ -67,7 +68,7 @@
 #   Public License for more details.
 #
 #   You should have received a copy of the GNU General Public License along
-#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
 #
 #   As a special exception, the respective Autoconf Macro's copyright owner
 #   gives unlimited permission to copy, distribute and modify the configure
@@ -82,7 +83,7 @@
 #   modified version of the Autoconf Macro, you may extend this special
 #   exception to the GPL to apply to your modified version as well.
 
-#serial 22
+#serial 27
 
 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
 AC_DEFUN([AX_PTHREAD], [
@@ -100,22 +101,22 @@
 # etcetera environment variables, and if threads linking works using
 # them:
 if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
-	ax_pthread_save_CC="$CC"
-	ax_pthread_save_CFLAGS="$CFLAGS"
-	ax_pthread_save_LIBS="$LIBS"
-	AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
-	CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-	LIBS="$PTHREAD_LIBS $LIBS"
-	AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
-	AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
-	AC_MSG_RESULT([$ax_pthread_ok])
-	if test "x$ax_pthread_ok" = "xno"; then
-		PTHREAD_LIBS=""
-		PTHREAD_CFLAGS=""
-	fi
-	CC="$ax_pthread_save_CC"
-	CFLAGS="$ax_pthread_save_CFLAGS"
-	LIBS="$ax_pthread_save_LIBS"
+        ax_pthread_save_CC="$CC"
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
+        AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
+        AC_MSG_RESULT([$ax_pthread_ok])
+        if test "x$ax_pthread_ok" = "xno"; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        CC="$ax_pthread_save_CC"
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
 fi
 
 # We must check for the threads library under a number of different
@@ -123,10 +124,12 @@
 # (e.g. DEC) have both -lpthread and -lpthreads, where one of the
 # libraries is broken (non-POSIX).
 
-# Create a list of thread flags to try.  Items starting with a "-" are
-# C compiler flags, and other items are library names, except for "none"
-# which indicates that we try without any flags at all, and "pthread-config"
-# which is a program returning the flags for the Pth emulation library.
+# Create a list of thread flags to try. Items with a "," contain both
+# C compiler flags (before ",") and linker flags (after ","). Other items
+# starting with a "-" are C compiler flags, and remaining items are
+# library names, except for "none" which indicates that we try without
+# any flags at all, and "pthread-config" which is a program returning
+# the flags for the Pth emulation library.
 
 ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
 
@@ -152,78 +155,52 @@
 
 case $host_os in
 
-	freebsd*)
+        freebsd*)
 
-	# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
-	# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+        # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+        # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
 
-	ax_pthread_flags="-kthread lthread $ax_pthread_flags"
-	;;
+        ax_pthread_flags="-kthread lthread $ax_pthread_flags"
+        ;;
 
-	hpux*)
+        hpux*)
 
-	# From the cc(1) man page: "[-mt] Sets various -D flags to enable
-	# multi-threading and also sets -lpthread."
+        # From the cc(1) man page: "[-mt] Sets various -D flags to enable
+        # multi-threading and also sets -lpthread."
 
-	ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
-	;;
+        ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
+        ;;
 
-	openedition*)
+        openedition*)
 
-	# IBM z/OS requires a feature-test macro to be defined in order to
-	# enable POSIX threads at all, so give the user a hint if this is
-	# not set. (We don't define these ourselves, as they can affect
-	# other portions of the system API in unpredictable ways.)
+        # IBM z/OS requires a feature-test macro to be defined in order to
+        # enable POSIX threads at all, so give the user a hint if this is
+        # not set. (We don't define these ourselves, as they can affect
+        # other portions of the system API in unpredictable ways.)
 
-	AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
-	    [
-#	     if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
-	     AX_PTHREAD_ZOS_MISSING
-#	     endif
-	    ],
-	    [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
-	;;
+        AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
+            [
+#            if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
+             AX_PTHREAD_ZOS_MISSING
+#            endif
+            ],
+            [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
+        ;;
 
-	solaris*)
+        solaris*)
 
-	# On Solaris (at least, for some versions), libc contains stubbed
-	# (non-functional) versions of the pthreads routines, so link-based
-	# tests will erroneously succeed. (N.B.: The stubs are missing
-	# pthread_cleanup_push, or rather a function called by this macro,
-	# so we could check for that, but who knows whether they'll stub
-	# that too in a future libc.)  So we'll check first for the
-	# standard Solaris way of linking pthreads (-mt -lpthread).
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed. (N.B.: The stubs are missing
+        # pthread_cleanup_push, or rather a function called by this macro,
+        # so we could check for that, but who knows whether they'll stub
+        # that too in a future libc.)  So we'll check first for the
+        # standard Solaris way of linking pthreads (-mt -lpthread).
 
-	ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
-	;;
+        ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
+        ;;
 esac
 
-# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
-
-AS_IF([test "x$GCC" = "xyes"],
-      [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
-
-# The presence of a feature test macro requesting re-entrant function
-# definitions is, on some systems, a strong hint that pthreads support is
-# correctly enabled
-
-case $host_os in
-	darwin* | hpux* | linux* | osf* | solaris*)
-	ax_pthread_check_macro="_REENTRANT"
-	;;
-
-	aix* | freebsd*)
-	ax_pthread_check_macro="_THREAD_SAFE"
-	;;
-
-	*)
-	ax_pthread_check_macro="--"
-	;;
-esac
-AS_IF([test "x$ax_pthread_check_macro" = "x--"],
-      [ax_pthread_check_cond=0],
-      [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
-
 # Are we compiling with Clang?
 
 AC_CACHE_CHECK([whether $CC is Clang],
@@ -231,240 +208,285 @@
     [ax_cv_PTHREAD_CLANG=no
      # Note that Autoconf sets GCC=yes for Clang as well as GCC
      if test "x$GCC" = "xyes"; then
-	AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
-	    [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
-#	     if defined(__clang__) && defined(__llvm__)
-	     AX_PTHREAD_CC_IS_CLANG
-#	     endif
-	    ],
-	    [ax_cv_PTHREAD_CLANG=yes])
+        AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
+            [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+#            if defined(__clang__) && defined(__llvm__)
+             AX_PTHREAD_CC_IS_CLANG
+#            endif
+            ],
+            [ax_cv_PTHREAD_CLANG=yes])
      fi
     ])
 ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
 
-ax_pthread_clang_warning=no
+
+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+
+# Note that for GCC and Clang -pthread generally implies -lpthread,
+# except when -nostdlib is passed.
+# This is problematic using libtool to build C++ shared libraries with pthread:
+# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
+# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
+# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
+# To solve this, first try -pthread together with -lpthread for GCC
+
+AS_IF([test "x$GCC" = "xyes"],
+      [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
+
+# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
+
+AS_IF([test "x$ax_pthread_clang" = "xyes"],
+      [ax_pthread_flags="-pthread,-lpthread -pthread"])
+
+
+# The presence of a feature test macro requesting re-entrant function
+# definitions is, on some systems, a strong hint that pthreads support is
+# correctly enabled
+
+case $host_os in
+        darwin* | hpux* | linux* | osf* | solaris*)
+        ax_pthread_check_macro="_REENTRANT"
+        ;;
+
+        aix*)
+        ax_pthread_check_macro="_THREAD_SAFE"
+        ;;
+
+        *)
+        ax_pthread_check_macro="--"
+        ;;
+esac
+AS_IF([test "x$ax_pthread_check_macro" = "x--"],
+      [ax_pthread_check_cond=0],
+      [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
+
+
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+        case $ax_pthread_try_flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                *,*)
+                PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
+                PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
+                AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
+                PTHREAD_CFLAGS="$ax_pthread_try_flag"
+                ;;
+
+                pthread-config)
+                AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+                AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
+                PTHREAD_LIBS="-l$ax_pthread_try_flag"
+                ;;
+        esac
+
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+#                       if $ax_pthread_check_cond
+#                        error "$ax_pthread_check_macro must be defined"
+#                       endif
+                        static void *some_global = NULL;
+                        static void routine(void *a)
+                          {
+                             /* To avoid any unused-parameter or
+                                unused-but-set-parameter warning.  */
+                             some_global = a;
+                          }
+                        static void *start_routine(void *a) { return a; }],
+                       [pthread_t th; pthread_attr_t attr;
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */])],
+            [ax_pthread_ok=yes],
+            [])
+
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
+
+        AC_MSG_RESULT([$ax_pthread_ok])
+        AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
 
 # Clang needs special handling, because older versions handle the -pthread
 # option in a rather... idiosyncratic way
 
 if test "x$ax_pthread_clang" = "xyes"; then
 
-	# Clang takes -pthread; it has never supported any other flag
+        # Clang takes -pthread; it has never supported any other flag
 
-	# (Note 1: This will need to be revisited if a system that Clang
-	# supports has POSIX threads in a separate library.  This tends not
-	# to be the way of modern systems, but it's conceivable.)
+        # (Note 1: This will need to be revisited if a system that Clang
+        # supports has POSIX threads in a separate library.  This tends not
+        # to be the way of modern systems, but it's conceivable.)
 
-	# (Note 2: On some systems, notably Darwin, -pthread is not needed
-	# to get POSIX threads support; the API is always present and
-	# active.  We could reasonably leave PTHREAD_CFLAGS empty.  But
-	# -pthread does define _REENTRANT, and while the Darwin headers
-	# ignore this macro, third-party headers might not.)
+        # (Note 2: On some systems, notably Darwin, -pthread is not needed
+        # to get POSIX threads support; the API is always present and
+        # active.  We could reasonably leave PTHREAD_CFLAGS empty.  But
+        # -pthread does define _REENTRANT, and while the Darwin headers
+        # ignore this macro, third-party headers might not.)
 
-	PTHREAD_CFLAGS="-pthread"
-	PTHREAD_LIBS=
+        # However, older versions of Clang make a point of warning the user
+        # that, in an invocation where only linking and no compilation is
+        # taking place, the -pthread option has no effect ("argument unused
+        # during compilation").  They expect -pthread to be passed in only
+        # when source code is being compiled.
+        #
+        # Problem is, this is at odds with the way Automake and most other
+        # C build frameworks function, which is that the same flags used in
+        # compilation (CFLAGS) are also used in linking.  Many systems
+        # supported by AX_PTHREAD require exactly this for POSIX threads
+        # support, and in fact it is often not straightforward to specify a
+        # flag that is used only in the compilation phase and not in
+        # linking.  Such a scenario is extremely rare in practice.
+        #
+        # Even though use of the -pthread flag in linking would only print
+        # a warning, this can be a nuisance for well-run software projects
+        # that build with -Werror.  So if the active version of Clang has
+        # this misfeature, we search for an option to squash it.
 
-	ax_pthread_ok=yes
+        AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
+            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
+            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
+             # Create an alternate version of $ac_link that compiles and
+             # links in two steps (.c -> .o, .o -> exe) instead of one
+             # (.c -> exe), because the warning occurs only in the second
+             # step
+             ax_pthread_save_ac_link="$ac_link"
+             ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
+             ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
+             ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
+             ax_pthread_save_CFLAGS="$CFLAGS"
+             for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
+                AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
+                CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
+                ac_link="$ax_pthread_save_ac_link"
+                AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+                    [ac_link="$ax_pthread_2step_ac_link"
+                     AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+                         [break])
+                    ])
+             done
+             ac_link="$ax_pthread_save_ac_link"
+             CFLAGS="$ax_pthread_save_CFLAGS"
+             AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
+             ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
+            ])
 
-	# However, older versions of Clang make a point of warning the user
-	# that, in an invocation where only linking and no compilation is
-	# taking place, the -pthread option has no effect ("argument unused
-	# during compilation").  They expect -pthread to be passed in only
-	# when source code is being compiled.
-	#
-	# Problem is, this is at odds with the way Automake and most other
-	# C build frameworks function, which is that the same flags used in
-	# compilation (CFLAGS) are also used in linking.  Many systems
-	# supported by AX_PTHREAD require exactly this for POSIX threads
-	# support, and in fact it is often not straightforward to specify a
-	# flag that is used only in the compilation phase and not in
-	# linking.  Such a scenario is extremely rare in practice.
-	#
-	# Even though use of the -pthread flag in linking would only print
-	# a warning, this can be a nuisance for well-run software projects
-	# that build with -Werror.  So if the active version of Clang has
-	# this misfeature, we search for an option to squash it.
-
-	AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
-	    [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
-	    [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
-	     # Create an alternate version of $ac_link that compiles and
-	     # links in two steps (.c -> .o, .o -> exe) instead of one
-	     # (.c -> exe), because the warning occurs only in the second
-	     # step
-	     ax_pthread_save_ac_link="$ac_link"
-	     ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
-	     ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
-	     ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
-	     ax_pthread_save_CFLAGS="$CFLAGS"
-	     for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
-		AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
-		CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
-		ac_link="$ax_pthread_save_ac_link"
-		AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
-		    [ac_link="$ax_pthread_2step_ac_link"
-		     AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
-			 [break])
-		    ])
-	     done
-	     ac_link="$ax_pthread_save_ac_link"
-	     CFLAGS="$ax_pthread_save_CFLAGS"
-	     AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
-	     ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
-	    ])
-
-	case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
-		no | unknown) ;;
-		*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
-	esac
+        case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
+                no | unknown) ;;
+                *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
+        esac
 
 fi # $ax_pthread_clang = yes
 
-if test "x$ax_pthread_ok" = "xno"; then
-for ax_pthread_try_flag in $ax_pthread_flags; do
 
-	case $ax_pthread_try_flag in
-		none)
-		AC_MSG_CHECKING([whether pthreads work without any flags])
-		;;
-
-		-mt,pthread)
-		AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
-		PTHREAD_CFLAGS="-mt"
-		PTHREAD_LIBS="-lpthread"
-		;;
-
-		-*)
-		AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
-		PTHREAD_CFLAGS="$ax_pthread_try_flag"
-		;;
-
-		pthread-config)
-		AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
-		AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
-		PTHREAD_CFLAGS="`pthread-config --cflags`"
-		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
-		;;
-
-		*)
-		AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
-		PTHREAD_LIBS="-l$ax_pthread_try_flag"
-		;;
-	esac
-
-	ax_pthread_save_CFLAGS="$CFLAGS"
-	ax_pthread_save_LIBS="$LIBS"
-	CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-	LIBS="$PTHREAD_LIBS $LIBS"
-
-	# Check for various functions.  We must include pthread.h,
-	# since some functions may be macros.  (On the Sequent, we
-	# need a special flag -Kthread to make this header compile.)
-	# We check for pthread_join because it is in -lpthread on IRIX
-	# while pthread_create is in libc.  We check for pthread_attr_init
-	# due to DEC craziness with -lpthreads.  We check for
-	# pthread_cleanup_push because it is one of the few pthread
-	# functions on Solaris that doesn't have a non-functional libc stub.
-	# We try pthread_create on general principles.
-
-	AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
-#			if $ax_pthread_check_cond
-#			 error "$ax_pthread_check_macro must be defined"
-#			endif
-			static void routine(void *a) { a = 0; }
-			static void *start_routine(void *a) { return a; }],
-		       [pthread_t th; pthread_attr_t attr;
-			pthread_create(&th, 0, start_routine, 0);
-			pthread_join(th, 0);
-			pthread_attr_init(&attr);
-			pthread_cleanup_push(routine, 0);
-			pthread_cleanup_pop(0) /* ; */])],
-	    [ax_pthread_ok=yes],
-	    [])
-
-	CFLAGS="$ax_pthread_save_CFLAGS"
-	LIBS="$ax_pthread_save_LIBS"
-
-	AC_MSG_RESULT([$ax_pthread_ok])
-	AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
-
-	PTHREAD_LIBS=""
-	PTHREAD_CFLAGS=""
-done
-fi
 
 # Various other checks:
 if test "x$ax_pthread_ok" = "xyes"; then
-	ax_pthread_save_CFLAGS="$CFLAGS"
-	ax_pthread_save_LIBS="$LIBS"
-	CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-	LIBS="$PTHREAD_LIBS $LIBS"
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
 
-	# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
-	AC_CACHE_CHECK([for joinable pthread attribute],
-	    [ax_cv_PTHREAD_JOINABLE_ATTR],
-	    [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
-	     for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
-		 AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
-						 [int attr = $ax_pthread_attr; return attr /* ; */])],
-				[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
-				[])
-	     done
-	    ])
-	AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
-	       test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
-	       test "x$ax_pthread_joinable_attr_defined" != "xyes"],
-	      [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
-				  [$ax_cv_PTHREAD_JOINABLE_ATTR],
-				  [Define to necessary symbol if this constant
-				   uses a non-standard name on your system.])
-	       ax_pthread_joinable_attr_defined=yes
-	      ])
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+        AC_CACHE_CHECK([for joinable pthread attribute],
+            [ax_cv_PTHREAD_JOINABLE_ATTR],
+            [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
+             for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+                 AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+                                                 [int attr = $ax_pthread_attr; return attr /* ; */])],
+                                [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
+                                [])
+             done
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
+               test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
+               test "x$ax_pthread_joinable_attr_defined" != "xyes"],
+              [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
+                                  [$ax_cv_PTHREAD_JOINABLE_ATTR],
+                                  [Define to necessary symbol if this constant
+                                   uses a non-standard name on your system.])
+               ax_pthread_joinable_attr_defined=yes
+              ])
 
-	AC_CACHE_CHECK([whether more special flags are required for pthreads],
-	    [ax_cv_PTHREAD_SPECIAL_FLAGS],
-	    [ax_cv_PTHREAD_SPECIAL_FLAGS=no
-	     case $host_os in
-	     solaris*)
-	     ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
-	     ;;
-	     esac
-	    ])
-	AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
-	       test "x$ax_pthread_special_flags_added" != "xyes"],
-	      [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
-	       ax_pthread_special_flags_added=yes])
+        AC_CACHE_CHECK([whether more special flags are required for pthreads],
+            [ax_cv_PTHREAD_SPECIAL_FLAGS],
+            [ax_cv_PTHREAD_SPECIAL_FLAGS=no
+             case $host_os in
+             solaris*)
+             ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
+             ;;
+             esac
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
+               test "x$ax_pthread_special_flags_added" != "xyes"],
+              [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
+               ax_pthread_special_flags_added=yes])
 
-	AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
-	    [ax_cv_PTHREAD_PRIO_INHERIT],
-	    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
-					     [[int i = PTHREAD_PRIO_INHERIT;]])],
-			    [ax_cv_PTHREAD_PRIO_INHERIT=yes],
-			    [ax_cv_PTHREAD_PRIO_INHERIT=no])
-	    ])
-	AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
-	       test "x$ax_pthread_prio_inherit_defined" != "xyes"],
-	      [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
-	       ax_pthread_prio_inherit_defined=yes
-	      ])
+        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+            [ax_cv_PTHREAD_PRIO_INHERIT],
+            [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+                                             [[int i = PTHREAD_PRIO_INHERIT;
+                                               return i;]])],
+                            [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+                            [ax_cv_PTHREAD_PRIO_INHERIT=no])
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
+               test "x$ax_pthread_prio_inherit_defined" != "xyes"],
+              [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
+               ax_pthread_prio_inherit_defined=yes
+              ])
 
-	CFLAGS="$ax_pthread_save_CFLAGS"
-	LIBS="$ax_pthread_save_LIBS"
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
 
-	# More AIX lossage: compile with *_r variant
-	if test "x$GCC" != "xyes"; then
-	    case $host_os in
-		aix*)
-		AS_CASE(["x/$CC"],
-		    [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
-		    [#handle absolute path differently from PATH based program lookup
-		     AS_CASE(["x$CC"],
-			 [x/*],
-			 [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
-			 [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
-		;;
-	    esac
-	fi
+        # More AIX lossage: compile with *_r variant
+        if test "x$GCC" != "xyes"; then
+            case $host_os in
+                aix*)
+                AS_CASE(["x/$CC"],
+                    [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+                    [#handle absolute path differently from PATH based program lookup
+                     AS_CASE(["x$CC"],
+                         [x/*],
+                         [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+                         [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+                ;;
+            esac
+        fi
 fi
 
 test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
@@ -475,11 +497,11 @@
 
 # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
 if test "x$ax_pthread_ok" = "xyes"; then
-	ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
-	:
+        ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
+        :
 else
-	ax_pthread_ok=no
-	$2
+        ax_pthread_ok=no
+        $2
 fi
 AC_LANG_POP
 ])dnl AX_PTHREAD
diff --git a/maven_install.json b/maven_install.json
new file mode 100644
index 0000000..f934218
--- /dev/null
+++ b/maven_install.json
@@ -0,0 +1,261 @@
+{
+    "dependency_tree": {
+        "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": 1033791982,
+        "conflict_resolution": {
+            "com.google.errorprone:error_prone_annotations:2.3.2": "com.google.errorprone:error_prone_annotations:2.5.1",
+            "junit:junit:4.12": "junit:junit:4.13.1"
+        },
+        "dependencies": [
+            {
+                "coord": "cglib:cglib-nodep:2.2.2",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/cglib/cglib-nodep/2.2.2/cglib-nodep-2.2.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/cglib/cglib-nodep/2.2.2/cglib-nodep-2.2.2.jar",
+                    "https://repo.maven.apache.org/maven2/cglib/cglib-nodep/2.2.2/cglib-nodep-2.2.2.jar"
+                ],
+                "sha256": "e78c7792e59554ed8a23d18a12e3a0d2f7a244217ecf89621477f63aec074f15",
+                "url": "https://repo1.maven.org/maven2/cglib/cglib-nodep/2.2.2/cglib-nodep-2.2.2.jar"
+            },
+            {
+                "coord": "com.google.auto.value:auto-value-annotations:1.7.4",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/auto/value/auto-value-annotations/1.7.4/auto-value-annotations-1.7.4.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/auto/value/auto-value-annotations/1.7.4/auto-value-annotations-1.7.4.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.7.4/auto-value-annotations-1.7.4.jar"
+                ],
+                "sha256": "fedd59b0b4986c342f6ab2d182f2a4ee9fceb2c7e2d5bdc4dc764c92394a23d3",
+                "url": "https://repo1.maven.org/maven2/com/google/auto/value/auto-value-annotations/1.7.4/auto-value-annotations-1.7.4.jar"
+            },
+            {
+                "coord": "com.google.code.findbugs:jsr305:3.0.2",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar"
+                ],
+                "sha256": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7",
+                "url": "https://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar"
+            },
+            {
+                "coord": "com.google.code.gson:gson:2.8.6",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar"
+                ],
+                "sha256": "c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f",
+                "url": "https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar"
+            },
+            {
+                "coord": "com.google.errorprone:error_prone_annotations:2.5.1",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar"
+                ],
+                "sha256": "ff80626baaf12a09342befd4e84cba9d50662f5fcd7f7a9b3490a6b7cf87e66c",
+                "url": "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar"
+            },
+            {
+                "coord": "com.google.guava:failureaccess:1.0.1",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar"
+                ],
+                "sha256": "a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26",
+                "url": "https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar"
+            },
+            {
+                "coord": "com.google.guava:guava:30.1.1-jre",
+                "dependencies": [
+                    "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+                    "com.google.j2objc:j2objc-annotations:1.3",
+                    "com.google.code.findbugs:jsr305:3.0.2",
+                    "com.google.guava:failureaccess:1.0.1",
+                    "com.google.errorprone:error_prone_annotations:2.5.1",
+                    "org.checkerframework:checker-qual:3.9.1"
+                ],
+                "directDependencies": [
+                    "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+                    "com.google.j2objc:j2objc-annotations:1.3",
+                    "com.google.code.findbugs:jsr305:3.0.2",
+                    "com.google.guava:failureaccess:1.0.1",
+                    "com.google.errorprone:error_prone_annotations:2.5.1",
+                    "org.checkerframework:checker-qual:3.9.1"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar"
+                ],
+                "sha256": "44ce229ce26d880bf3afc362bbfcec34d7e6903d195bbb1db9f3b6e0d9834f06",
+                "url": "https://repo1.maven.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar"
+            },
+            {
+                "coord": "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar"
+                ],
+                "sha256": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99",
+                "url": "https://repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar"
+            },
+            {
+                "coord": "com.google.j2objc:j2objc-annotations:1.3",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar"
+                ],
+                "sha256": "21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b",
+                "url": "https://repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar"
+            },
+            {
+                "coord": "com.google.truth:truth:1.1.2",
+                "dependencies": [
+                    "org.ow2.asm:asm:9.0",
+                    "org.hamcrest:hamcrest-core:1.3",
+                    "com.google.auto.value:auto-value-annotations:1.7.4",
+                    "junit:junit:4.13.1",
+                    "com.google.guava:guava:30.1.1-jre",
+                    "com.google.errorprone:error_prone_annotations:2.5.1",
+                    "org.checkerframework:checker-qual:3.9.1"
+                ],
+                "directDependencies": [
+                    "org.ow2.asm:asm:9.0",
+                    "com.google.auto.value:auto-value-annotations:1.7.4",
+                    "junit:junit:4.13.1",
+                    "com.google.guava:guava:30.1.1-jre",
+                    "com.google.errorprone:error_prone_annotations:2.5.1",
+                    "org.checkerframework:checker-qual:3.9.1"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/truth/truth/1.1.2/truth-1.1.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/truth/truth/1.1.2/truth-1.1.2.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/truth/truth/1.1.2/truth-1.1.2.jar"
+                ],
+                "sha256": "a85e03b8b6ae8780f060cfded9500a3d1b5f52808f99a2ea6da9c683313c7518",
+                "url": "https://repo1.maven.org/maven2/com/google/truth/truth/1.1.2/truth-1.1.2.jar"
+            },
+            {
+                "coord": "junit:junit:4.13.1",
+                "dependencies": [
+                    "org.hamcrest:hamcrest-core:1.3"
+                ],
+                "directDependencies": [
+                    "org.hamcrest:hamcrest-core:1.3"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/junit/junit/4.13.1/junit-4.13.1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/junit/junit/4.13.1/junit-4.13.1.jar",
+                    "https://repo.maven.apache.org/maven2/junit/junit/4.13.1/junit-4.13.1.jar"
+                ],
+                "sha256": "c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122",
+                "url": "https://repo1.maven.org/maven2/junit/junit/4.13.1/junit-4.13.1.jar"
+            },
+            {
+                "coord": "org.checkerframework:checker-qual:3.9.1",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar",
+                    "https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar"
+                ],
+                "sha256": "ab0468b1ba35bb2ae45f61a60dc4960bd887660ab8f05113a662a7e675eae776",
+                "url": "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar"
+            },
+            {
+                "coord": "org.easymock:easymock:3.2",
+                "dependencies": [
+                    "cglib:cglib-nodep:2.2.2",
+                    "org.objenesis:objenesis:1.3"
+                ],
+                "directDependencies": [
+                    "cglib:cglib-nodep:2.2.2",
+                    "org.objenesis:objenesis:1.3"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/org/easymock/easymock/3.2/easymock-3.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/easymock/easymock/3.2/easymock-3.2.jar",
+                    "https://repo.maven.apache.org/maven2/org/easymock/easymock/3.2/easymock-3.2.jar"
+                ],
+                "sha256": "b3dd1cf5019f942d8cc2afad0aa6aef4b21532446fe90a6b68d567e3389763dd",
+                "url": "https://repo1.maven.org/maven2/org/easymock/easymock/3.2/easymock-3.2.jar"
+            },
+            {
+                "coord": "org.easymock:easymockclassextension:3.2",
+                "dependencies": [
+                    "org.easymock:easymock:3.2",
+                    "cglib:cglib-nodep:2.2.2",
+                    "org.objenesis:objenesis:1.3"
+                ],
+                "directDependencies": [
+                    "org.easymock:easymock:3.2"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/org/easymock/easymockclassextension/3.2/easymockclassextension-3.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/easymock/easymockclassextension/3.2/easymockclassextension-3.2.jar",
+                    "https://repo.maven.apache.org/maven2/org/easymock/easymockclassextension/3.2/easymockclassextension-3.2.jar"
+                ],
+                "sha256": "e2aeb3ecec87d859b2f3072985d4b15873558bcf6410f422db0c0c5194c76c87",
+                "url": "https://repo1.maven.org/maven2/org/easymock/easymockclassextension/3.2/easymockclassextension-3.2.jar"
+            },
+            {
+                "coord": "org.hamcrest:hamcrest-core:1.3",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar",
+                    "https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar"
+                ],
+                "sha256": "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9",
+                "url": "https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar"
+            },
+            {
+                "coord": "org.objenesis:objenesis:1.3",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/org/objenesis/objenesis/1.3/objenesis-1.3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/objenesis/objenesis/1.3/objenesis-1.3.jar",
+                    "https://repo.maven.apache.org/maven2/org/objenesis/objenesis/1.3/objenesis-1.3.jar"
+                ],
+                "sha256": "dd4ef3d3091063a4fec578cbb2bbe6c1f921c00091ba2993dcd9afd25ff9444a",
+                "url": "https://repo1.maven.org/maven2/org/objenesis/objenesis/1.3/objenesis-1.3.jar"
+            },
+            {
+                "coord": "org.ow2.asm:asm:9.0",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/org/ow2/asm/asm/9.0/asm-9.0.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/ow2/asm/asm/9.0/asm-9.0.jar",
+                    "https://repo.maven.apache.org/maven2/org/ow2/asm/asm/9.0/asm-9.0.jar"
+                ],
+                "sha256": "0df97574914aee92fd349d0cb4e00f3345d45b2c239e0bb50f0a90ead47888e0",
+                "url": "https://repo1.maven.org/maven2/org/ow2/asm/asm/9.0/asm-9.0.jar"
+            }
+        ],
+        "version": "0.1.0"
+    }
+}
diff --git a/objectivec/BUILD b/objectivec/BUILD
new file mode 100644
index 0000000..9f702ec
--- /dev/null
+++ b/objectivec/BUILD
@@ -0,0 +1,90 @@
+load("@rules_cc//cc:defs.bzl", "objc_library")
+
+objc_library(
+    name = "objectivec",
+    hdrs = [
+        "GPBAny.pbobjc.h",
+        "GPBApi.pbobjc.h",
+        "GPBDuration.pbobjc.h",
+        "GPBEmpty.pbobjc.h",
+        "GPBFieldMask.pbobjc.h",
+        "GPBSourceContext.pbobjc.h",
+        "GPBStruct.pbobjc.h",
+        "GPBTimestamp.pbobjc.h",
+        "GPBType.pbobjc.h",
+        "GPBWrappers.pbobjc.h",
+        "GPBArray.h",
+        "GPBBootstrap.h",
+        "GPBCodedInputStream.h",
+        "GPBCodedOutputStream.h",
+        "GPBDescriptor.h",
+        "GPBDictionary.h",
+        "GPBExtensionInternals.h",
+        "GPBExtensionRegistry.h",
+        "GPBMessage.h",
+        "GPBProtocolBuffers.h",
+        "GPBProtocolBuffers_RuntimeSupport.h",
+        "GPBRootObject.h",
+        "GPBRuntimeTypes.h",
+        "GPBUnknownField.h",
+        "GPBUnknownFieldSet.h",
+        "GPBUtilities.h",
+        "GPBWellKnownTypes.h",
+        "GPBWireFormat.h",
+        "google/protobuf/Any.pbobjc.h",
+        "google/protobuf/Api.pbobjc.h",
+        "google/protobuf/Duration.pbobjc.h",
+        "google/protobuf/Empty.pbobjc.h",
+        "google/protobuf/FieldMask.pbobjc.h",
+        "google/protobuf/SourceContext.pbobjc.h",
+        "google/protobuf/Struct.pbobjc.h",
+        "google/protobuf/Timestamp.pbobjc.h",
+        "google/protobuf/Type.pbobjc.h",
+        "google/protobuf/Wrappers.pbobjc.h",
+        # Package private headers, but exposed because the generated sources
+        # need to use them.
+        "GPBArray_PackagePrivate.h",
+        "GPBCodedInputStream_PackagePrivate.h",
+        "GPBCodedOutputStream_PackagePrivate.h",
+        "GPBDescriptor_PackagePrivate.h",
+        "GPBDictionary_PackagePrivate.h",
+        "GPBMessage_PackagePrivate.h",
+        "GPBRootObject_PackagePrivate.h",
+        "GPBUnknownFieldSet_PackagePrivate.h",
+        "GPBUnknownField_PackagePrivate.h",
+        "GPBUtilities_PackagePrivate.h",
+    ],
+    copts = [
+        "-Wno-vla",
+    ],
+    includes = [
+        ".",
+    ],
+    non_arc_srcs = [
+        "GPBAny.pbobjc.m",
+        "GPBApi.pbobjc.m",
+        "GPBDuration.pbobjc.m",
+        "GPBEmpty.pbobjc.m",
+        "GPBFieldMask.pbobjc.m",
+        "GPBSourceContext.pbobjc.m",
+        "GPBStruct.pbobjc.m",
+        "GPBTimestamp.pbobjc.m",
+        "GPBType.pbobjc.m",
+        "GPBWrappers.pbobjc.m",
+        "GPBArray.m",
+        "GPBCodedInputStream.m",
+        "GPBCodedOutputStream.m",
+        "GPBDescriptor.m",
+        "GPBDictionary.m",
+        "GPBExtensionInternals.m",
+        "GPBExtensionRegistry.m",
+        "GPBMessage.m",
+        "GPBRootObject.m",
+        "GPBUnknownField.m",
+        "GPBUnknownFieldSet.m",
+        "GPBUtilities.m",
+        "GPBWellKnownTypes.m",
+        "GPBWireFormat.m",
+    ],
+    visibility = ["//visibility:public"],
+)
diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh
index dc1d6d2..69c32f9 100755
--- a/objectivec/DevTools/compile_testing_protos.sh
+++ b/objectivec/DevTools/compile_testing_protos.sh
@@ -42,8 +42,6 @@
   src/google/protobuf/unittest_lite.proto
   src/google/protobuf/unittest_mset.proto
   src/google/protobuf/unittest_mset_wire_format.proto
-  src/google/protobuf/unittest_no_arena.proto
-  src/google/protobuf/unittest_no_arena_import.proto
   src/google/protobuf/unittest_no_generic_services.proto
   src/google/protobuf/unittest_optimize_for.proto
   src/google/protobuf/unittest.proto
@@ -97,7 +95,7 @@
 # -----------------------------------------------------------------------------
 RUN_PROTOC=no
 
-# Check to if all the output files exist (incase a new one got added).
+# Check to if all the output files exist (in case a new one got added).
 
 for PROTO_FILE in "${CORE_PROTO_FILES[@]}" "${OBJC_TEST_PROTO_FILES[@]}"; do
   DIR=${PROTO_FILE%/*}
@@ -158,6 +156,7 @@
     --objc_out="${OUTPUT_DIR}/google/protobuf" \
     --proto_path=src/google/protobuf/          \
     --proto_path=src                           \
+    --experimental_allow_proto3_optional       \
     "$@"
 }
 
diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh
index 84ed8e9..9319b55 100755
--- a/objectivec/DevTools/full_mac_build.sh
+++ b/objectivec/DevTools/full_mac_build.sh
@@ -285,11 +285,11 @@
           -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
           -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit
           # 10.x also seems to often fail running destinations in parallel (with
-          # 32bit one include atleast)
+          # 32bit one include at least)
           -disable-concurrent-destination-testing
       )
       ;;
-    11.*)
+    11.* | 12.*)
       # Dropped 32bit as Apple doesn't seem support the simulators either.
       XCODEBUILD_TEST_BASE_IOS+=(
           -destination "platform=iOS Simulator,name=iPhone 8,OS=latest" # 64bit
@@ -352,10 +352,8 @@
       echo "ERROR: Xcode 10.0 or higher is required to build the test suite." 1>&2
       exit 11
       ;;
-    10.* | 11.* )
+    10.* | 11.* | 12.*)
       XCODEBUILD_TEST_BASE_TVOS+=(
-        # Test on the oldest and current.
-        -destination "platform=tvOS Simulator,name=Apple TV,OS=11.0"
         -destination "platform=tvOS Simulator,name=Apple TV 4K,OS=latest"
       )
       ;;
diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py
index dacf7bb..b572cc7 100755
--- a/objectivec/DevTools/pddm.py
+++ b/objectivec/DevTools/pddm.py
@@ -645,7 +645,7 @@
   opts, extra_args = parser.parse_args(args)
 
   if not extra_args:
-    parser.error('Need atleast one file to process')
+    parser.error('Need at least one file to process')
 
   result = 0
   for a_path in extra_args:
diff --git a/objectivec/GPBAny.pbobjc.h b/objectivec/GPBAny.pbobjc.h
index 233cc27..21b7dcf 100644
--- a/objectivec/GPBAny.pbobjc.h
+++ b/objectivec/GPBAny.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
@@ -94,10 +94,13 @@
  *  Example 4: Pack and unpack a message in Go
  *
  *      foo := &pb.Foo{...}
- *      any, err := ptypes.MarshalAny(foo)
+ *      any, err := anypb.New(foo)
+ *      if err != nil {
+ *        ...
+ *      }
  *      ...
  *      foo := &pb.Foo{}
- *      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+ *      if err := any.UnmarshalTo(foo); err != nil {
  *        ...
  *      }
  *
diff --git a/objectivec/GPBAny.pbobjc.m b/objectivec/GPBAny.pbobjc.m
index 06b892e..a5143f1 100644
--- a/objectivec/GPBAny.pbobjc.m
+++ b/objectivec/GPBAny.pbobjc.m
@@ -72,7 +72,7 @@
         .number = GPBAny_FieldNumber_TypeURL,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -81,7 +81,7 @@
         .number = GPBAny_FieldNumber_Value,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBAny__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeBytes,
       },
     };
@@ -92,7 +92,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBAny__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
 #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
     static const char *extraTextFormatInfo =
         "\001\001\004\241!!\000";
diff --git a/objectivec/GPBApi.pbobjc.h b/objectivec/GPBApi.pbobjc.h
index c47a01c..5d55ebf 100644
--- a/objectivec/GPBApi.pbobjc.h
+++ b/objectivec/GPBApi.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
@@ -257,7 +257,7 @@
  * The mixin construct implies that all methods in `AccessControl` are
  * also declared with same name and request/response types in
  * `Storage`. A documentation generator or annotation processor will
- * see the effective `Storage.GetAcl` method after inherting
+ * see the effective `Storage.GetAcl` method after inheriting
  * documentation and annotations as follows:
  *
  *     service Storage {
diff --git a/objectivec/GPBApi.pbobjc.m b/objectivec/GPBApi.pbobjc.m
index bdd35bb..5915ce1 100644
--- a/objectivec/GPBApi.pbobjc.m
+++ b/objectivec/GPBApi.pbobjc.m
@@ -96,7 +96,7 @@
         .number = GPBApi_FieldNumber_Name,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBApi__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -123,7 +123,7 @@
         .number = GPBApi_FieldNumber_Version,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBApi__storage_, version),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -150,7 +150,7 @@
         .number = GPBApi_FieldNumber_Syntax,
         .hasIndex = 3,
         .offset = (uint32_t)offsetof(GPBApi__storage_, syntax),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeEnum,
       },
     };
@@ -161,7 +161,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBApi__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -175,13 +175,13 @@
 int32_t GPBApi_Syntax_RawValue(GPBApi *message) {
   GPBDescriptor *descriptor = [GPBApi descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
-  return GPBGetMessageInt32Field(message, field);
+  return GPBGetMessageRawEnumField(message, field);
 }
 
 void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) {
   GPBDescriptor *descriptor = [GPBApi descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
-  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+  GPBSetMessageRawEnumField(message, field, value);
 }
 
 #pragma mark - GPBMethod
@@ -217,7 +217,7 @@
         .number = GPBMethod_FieldNumber_Name,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBMethod__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -226,7 +226,7 @@
         .number = GPBMethod_FieldNumber_RequestTypeURL,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -235,7 +235,7 @@
         .number = GPBMethod_FieldNumber_RequestStreaming,
         .hasIndex = 2,
         .offset = 3,  // Stored in _has_storage_ to save space.
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeBool,
       },
       {
@@ -244,7 +244,7 @@
         .number = GPBMethod_FieldNumber_ResponseTypeURL,
         .hasIndex = 4,
         .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -253,7 +253,7 @@
         .number = GPBMethod_FieldNumber_ResponseStreaming,
         .hasIndex = 5,
         .offset = 6,  // Stored in _has_storage_ to save space.
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeBool,
       },
       {
@@ -271,7 +271,7 @@
         .number = GPBMethod_FieldNumber_Syntax,
         .hasIndex = 7,
         .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeEnum,
       },
     };
@@ -282,7 +282,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBMethod__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
 #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
     static const char *extraTextFormatInfo =
         "\002\002\007\244\241!!\000\004\010\244\241!!\000";
@@ -301,13 +301,13 @@
 int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) {
   GPBDescriptor *descriptor = [GPBMethod descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
-  return GPBGetMessageInt32Field(message, field);
+  return GPBGetMessageRawEnumField(message, field);
 }
 
 void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) {
   GPBDescriptor *descriptor = [GPBMethod descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
-  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+  GPBSetMessageRawEnumField(message, field, value);
 }
 
 #pragma mark - GPBMixin
@@ -335,7 +335,7 @@
         .number = GPBMixin_FieldNumber_Name,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBMixin__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -344,7 +344,7 @@
         .number = GPBMixin_FieldNumber_Root,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBMixin__storage_, root),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
     };
@@ -355,7 +355,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBMixin__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h
index 198ff9c..ea5986b 100644
--- a/objectivec/GPBBootstrap.h
+++ b/objectivec/GPBBootstrap.h
@@ -132,7 +132,7 @@
 // Current library runtime version.
 // - Gets bumped when the runtime makes changes to the interfaces between the
 //   generated code and runtime (things added/removed, etc).
-#define GOOGLE_PROTOBUF_OBJC_VERSION 30003
+#define GOOGLE_PROTOBUF_OBJC_VERSION 30004
 
 // Minimum runtime version supported for compiling/running against.
 // - Gets changed when support for the older generated code is dropped.
diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h
index 331d444..fd66b0e 100644
--- a/objectivec/GPBDescriptor.h
+++ b/objectivec/GPBDescriptor.h
@@ -182,7 +182,7 @@
 @property(nonatomic, readonly, getter=isOptional) BOOL optional;
 /** Type of field (single, repeated, map). */
 @property(nonatomic, readonly) GPBFieldType fieldType;
-/** Type of the key if the field is a map. The value's type is -fieldType. */
+/** Type of the key if the field is a map. The value's type is -dataType. */
 @property(nonatomic, readonly) GPBDataType mapKeyDataType;
 /** Whether the field is packable. */
 @property(nonatomic, readonly, getter=isPackable) BOOL packable;
diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m
index 130f1b9..c29b955 100644
--- a/objectivec/GPBDescriptor.m
+++ b/objectivec/GPBDescriptor.m
@@ -128,6 +128,8 @@
       (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
   BOOL usesClassRefs =
       (flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0;
+  BOOL proto3OptionalKnown =
+      (flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) != 0;
 
   void *desc;
   for (uint32_t i = 0; i < fieldCount; ++i) {
@@ -146,6 +148,7 @@
         [[GPBFieldDescriptor alloc] initWithFieldDescription:desc
                                              includesDefault:fieldsIncludeDefault
                                                usesClassRefs:usesClassRefs
+                                         proto3OptionalKnown:proto3OptionalKnown
                                                       syntax:syntax];
     [fields addObject:fieldDescriptor];
     [fieldDescriptor release];
@@ -488,6 +491,7 @@
 - (instancetype)initWithFieldDescription:(void *)description
                          includesDefault:(BOOL)includesDefault
                            usesClassRefs:(BOOL)usesClassRefs
+                     proto3OptionalKnown:(BOOL)proto3OptionalKnown
                                   syntax:(GPBFileSyntax)syntax {
   if ((self = [super init])) {
     GPBMessageFieldDescription *coreDesc;
@@ -504,20 +508,34 @@
     BOOL isMessage = GPBDataTypeIsMessage(dataType);
     BOOL isMapOrArray = GPBFieldIsMapOrArray(self);
 
+    // If proto3 optionals weren't known (i.e. generated code from an
+    // older version), compute the flag for the rest of the runtime.
+    if (!proto3OptionalKnown) {
+      // If it was...
+      //  - proto3 syntax
+      //  - not repeated/map
+      //  - not in a oneof (negative has index)
+      //  - not a message (the flag doesn't make sense for messages)
+      BOOL clearOnZero = ((syntax == GPBFileSyntaxProto3) &&
+                          !isMapOrArray &&
+                          (coreDesc->hasIndex >= 0) &&
+                          !isMessage);
+      if (clearOnZero) {
+        coreDesc->flags |= GPBFieldClearHasIvarOnZero;
+      }
+    }
+
     if (isMapOrArray) {
       // map<>/repeated fields get a *Count property (inplace of a has*) to
       // support checking if there are any entries without triggering
       // autocreation.
       hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO);
     } else {
-      // If there is a positive hasIndex, then:
-      //   - All fields types for proto2 messages get has* selectors.
-      //   - Only message fields for proto3 messages get has* selectors.
-      // Note: the positive check is to handle oneOfs, we can't check
-      // containingOneof_ because it isn't set until after initialization.
+      // It is a single field; it gets has/setHas selectors if...
+      //  - not in a oneof (negative has index)
+      //  - not clearing on zero
       if ((coreDesc->hasIndex >= 0) &&
-          (coreDesc->hasIndex != GPBNoHasBit) &&
-          ((syntax != GPBFileSyntaxProto3) || isMessage)) {
+          ((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) {
         hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO);
         setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES);
       }
@@ -567,15 +585,6 @@
   return self;
 }
 
-- (instancetype)initWithFieldDescription:(void *)description
-                         includesDefault:(BOOL)includesDefault
-                                  syntax:(GPBFileSyntax)syntax {
-  return [self initWithFieldDescription:description
-                        includesDefault:includesDefault
-                          usesClassRefs:NO
-                                 syntax:syntax];
-}
-
 - (void)dealloc {
   if (description_->dataType == GPBDataTypeBytes &&
       !(description_->flags & GPBFieldRepeated)) {
diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h
index 09c1202..408f8d4 100644
--- a/objectivec/GPBDescriptor_PackagePrivate.h
+++ b/objectivec/GPBDescriptor_PackagePrivate.h
@@ -45,6 +45,10 @@
   GPBFieldOptional        = 1 << 3,
   GPBFieldHasDefaultValue = 1 << 4,
 
+  // Indicate that the field should "clear" when set to zero value. This is the
+  // proto3 non optional behavior for singular data (ints, data, string, enum)
+  // fields.
+  GPBFieldClearHasIvarOnZero = 1 << 5,
   // Indicates the field needs custom handling for the TextFormat name, if not
   // set, the name can be derived from the ObjC name.
   GPBFieldTextFormatNameCustom = 1 << 6,
@@ -127,14 +131,29 @@
 typedef struct GPBExtensionDescription {
   GPBGenericValue defaultValue;
   const char *singletonName;
+  // Before 3.12, `extendedClass` was just a `const char *`. Thanks to nested
+  // initialization (https://en.cppreference.com/w/c/language/struct_initialization#Nested_initialization)
+  // old generated code with `.extendedClass = GPBStringifySymbol(Something)`
+  // still works; and the current generator can use `extendedClass.clazz`, to
+  // pass a Class reference.
   union {
     const char *name;
     Class clazz;
   } extendedClass;
+  // Before 3.12, this was `const char *messageOrGroupClassName`. In the
+  // initial 3.12 release, we moved the `union messageOrGroupClass`, and failed
+  // to realize that would break existing source code for extensions. So to
+  // keep existing source code working, we added an unnamed union (C11) to
+  // provide both the old field name and the new union. This keeps both older
+  // and newer code working.
+  // Background: https://github.com/protocolbuffers/protobuf/issues/7555
   union {
-    const char *name;
-    Class clazz;
-  } messageOrGroupClass;
+    const char *messageOrGroupClassName;
+    union {
+     const char *name;
+     Class clazz;
+   } messageOrGroupClass;
+  };
   GPBEnumDescriptorFunc enumDescriptorFunc;
   int32_t fieldNumber;
   GPBDataType dataType;
@@ -149,7 +168,13 @@
   // This is used as a stopgap as we move from using class names to class
   // references. The runtime needs to support both until we allow a
   // breaking change in the runtime.
-  GPBDescriptorInitializationFlag_UsesClassRefs        = 1 << 2,
+  GPBDescriptorInitializationFlag_UsesClassRefs     = 1 << 2,
+
+  // This flag is used to indicate that the generated sources already contain
+  // the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed
+  // at startup. This allows older generated code to still work with the
+  // current runtime library.
+  GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3,
 };
 
 @interface GPBDescriptor () {
@@ -225,14 +250,9 @@
 - (instancetype)initWithFieldDescription:(void *)description
                          includesDefault:(BOOL)includesDefault
                            usesClassRefs:(BOOL)usesClassRefs
+                     proto3OptionalKnown:(BOOL)proto3OptionalKnown
                                   syntax:(GPBFileSyntax)syntax;
 
-// Deprecated. Equivalent to calling above with `usesClassRefs = NO`.
-- (instancetype)initWithFieldDescription:(void *)description
-                         includesDefault:(BOOL)includesDefault
-                                  syntax:(GPBFileSyntax)syntax;
-
-
 @end
 
 @interface GPBEnumDescriptor ()
diff --git a/objectivec/GPBDuration.pbobjc.h b/objectivec/GPBDuration.pbobjc.h
index 6ff2709..88527f5 100644
--- a/objectivec/GPBDuration.pbobjc.h
+++ b/objectivec/GPBDuration.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
diff --git a/objectivec/GPBDuration.pbobjc.m b/objectivec/GPBDuration.pbobjc.m
index 465831e..d3cc7e3 100644
--- a/objectivec/GPBDuration.pbobjc.m
+++ b/objectivec/GPBDuration.pbobjc.m
@@ -72,7 +72,7 @@
         .number = GPBDuration_FieldNumber_Seconds,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt64,
       },
       {
@@ -81,7 +81,7 @@
         .number = GPBDuration_FieldNumber_Nanos,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt32,
       },
     };
@@ -92,7 +92,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBDuration__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBEmpty.pbobjc.h b/objectivec/GPBEmpty.pbobjc.h
index 9673400..45600ea 100644
--- a/objectivec/GPBEmpty.pbobjc.h
+++ b/objectivec/GPBEmpty.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
diff --git a/objectivec/GPBEmpty.pbobjc.m b/objectivec/GPBEmpty.pbobjc.m
index 29aa389..df3e398 100644
--- a/objectivec/GPBEmpty.pbobjc.m
+++ b/objectivec/GPBEmpty.pbobjc.m
@@ -68,7 +68,7 @@
                                         fields:NULL
                                     fieldCount:0
                                    storageSize:sizeof(GPBEmpty__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m
index 290c82a..bacec57 100644
--- a/objectivec/GPBExtensionInternals.m
+++ b/objectivec/GPBExtensionInternals.m
@@ -361,8 +361,8 @@
       if (existingValue) {
         message = [existingValue retain];
       } else {
-        GPBDescriptor *decriptor = [extension.msgClass descriptor];
-        message = [[decriptor.messageClass alloc] init];
+        GPBDescriptor *descriptor = [extension.msgClass descriptor];
+        message = [[descriptor.messageClass alloc] init];
       }
 
       if (description->dataType == GPBDataTypeGroup) {
diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m
index b056a52..e3ff7c4 100644
--- a/objectivec/GPBExtensionRegistry.m
+++ b/objectivec/GPBExtensionRegistry.m
@@ -34,18 +34,20 @@
 #import "GPBDescriptor.h"
 
 @implementation GPBExtensionRegistry {
-  NSMutableDictionary *mutableClassMap_;
+  CFMutableDictionaryRef mutableClassMap_;
 }
 
 - (instancetype)init {
   if ((self = [super init])) {
-    mutableClassMap_ = [[NSMutableDictionary alloc] init];
+    // The keys are ObjC classes, so straight up ptr comparisons are fine.
+    mutableClassMap_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
+                                             &kCFTypeDictionaryValueCallBacks);
   }
   return self;
 }
 
 - (void)dealloc {
-  [mutableClassMap_ release];
+  CFRelease(mutableClassMap_);
   [super dealloc];
 }
 
@@ -68,14 +70,13 @@
 
   Class containingMessageClass = extension.containingMessageClass;
   CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-      [mutableClassMap_ objectForKey:containingMessageClass];
+      CFDictionaryGetValue(mutableClassMap_, containingMessageClass);
   if (extensionMap == nil) {
     // Use a custom dictionary here because the keys are numbers and conversion
     // back and forth from NSNumber isn't worth the cost.
     extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
                                              &kCFTypeDictionaryValueCallBacks);
-    [mutableClassMap_ setObject:(id)extensionMap
-                         forKey:(id<NSCopying>)containingMessageClass];
+    CFDictionarySetValue(mutableClassMap_, containingMessageClass, extensionMap);
     CFRelease(extensionMap);
   }
 
@@ -87,7 +88,7 @@
                                        fieldNumber:(NSInteger)fieldNumber {
   Class messageClass = descriptor.messageClass;
   CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-      [mutableClassMap_ objectForKey:messageClass];
+      CFDictionaryGetValue(mutableClassMap_, messageClass);
   ssize_t key = fieldNumber;
   GPBExtensionDescriptor *result =
       (extensionMap
@@ -101,28 +102,28 @@
   CFDictionarySetValue(extensionMap, key, value);
 }
 
+static void CopySubDictionary(const void *key, const void *value, void *context) {
+  CFMutableDictionaryRef mutableClassMap = (CFMutableDictionaryRef)context;
+  Class containingMessageClass = key;
+  CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value;
+
+  CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
+      CFDictionaryGetValue(mutableClassMap, containingMessageClass);
+  if (extensionMap == nil) {
+    extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap);
+    CFDictionarySetValue(mutableClassMap, containingMessageClass, extensionMap);
+    CFRelease(extensionMap);
+  } else {
+    CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap);
+  }
+}
+
 - (void)addExtensions:(GPBExtensionRegistry *)registry {
   if (registry == nil) {
     // In the case where there are no extensions just ignore.
     return;
   }
-  NSMutableDictionary *otherClassMap = registry->mutableClassMap_;
-  [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) {
-#pragma unused(stop)
-    Class containingMessageClass = key;
-    CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value;
-
-    CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-        [mutableClassMap_ objectForKey:containingMessageClass];
-    if (extensionMap == nil) {
-      extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap);
-      [mutableClassMap_ setObject:(id)extensionMap
-                           forKey:(id<NSCopying>)containingMessageClass];
-      CFRelease(extensionMap);
-    } else {
-      CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap);
-    }
-  }];
+  CFDictionaryApplyFunction(registry->mutableClassMap_, CopySubDictionary, mutableClassMap_);
 }
 
 #pragma clang diagnostic pop
diff --git a/objectivec/GPBFieldMask.pbobjc.h b/objectivec/GPBFieldMask.pbobjc.h
index fa52ed0..3028b77 100644
--- a/objectivec/GPBFieldMask.pbobjc.h
+++ b/objectivec/GPBFieldMask.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
diff --git a/objectivec/GPBFieldMask.pbobjc.m b/objectivec/GPBFieldMask.pbobjc.m
index 9f119fc..3605f89 100644
--- a/objectivec/GPBFieldMask.pbobjc.m
+++ b/objectivec/GPBFieldMask.pbobjc.m
@@ -81,7 +81,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBFieldMask__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
index 973c18b..ee94dee 100644
--- a/objectivec/GPBMessage.m
+++ b/objectivec/GPBMessage.m
@@ -71,6 +71,8 @@
  @package
   GPBUnknownFieldSet *unknownFields_;
   NSMutableDictionary *extensionMap_;
+  // Readonly access to autocreatedExtensionMap_ is protected via
+  // readOnlySemaphore_.
   NSMutableDictionary *autocreatedExtensionMap_;
 
   // If the object was autocreated, we remember the creator so that if we get
@@ -79,10 +81,10 @@
   GPBFieldDescriptor *autocreatorField_;
   GPBExtensionDescriptor *autocreatorExtension_;
 
-  // A lock to provide mutual exclusion from internal data that can be modified
-  // by *read* operations such as getters (autocreation of message fields and
-  // message extensions, not setting of values). Used to guarantee thread safety
-  // for concurrent reads on the message.
+  // Message can only be mutated from one thread. But some *readonly* operations
+  // modify internal state because they autocreate things. The
+  // autocreatedExtensionMap_ is one such structure. Access during readonly
+  // operations is protected via this semaphore.
   // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have
   // pointed out that they are vulnerable to live locking on iOS in cases of
   // priority inversion:
@@ -99,15 +101,13 @@
                               GPBMessage *autocreator)
     __attribute__((ns_returns_retained));
 static id GetOrCreateArrayIvarWithField(GPBMessage *self,
-                                        GPBFieldDescriptor *field,
-                                        GPBFileSyntax syntax);
+                                        GPBFieldDescriptor *field);
 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
 static id CreateMapForField(GPBFieldDescriptor *field,
                             GPBMessage *autocreator)
     __attribute__((ns_returns_retained));
 static id GetOrCreateMapIvarWithField(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      GPBFileSyntax syntax);
+                                      GPBFieldDescriptor *field);
 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
 static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
                                               NSZone *zone)
@@ -560,10 +560,10 @@
 
 #if !defined(__clang_analyzer__)
 // These functions are blocked from the analyzer because the analyzer sees the
-// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map,
+// GPBSetRetainedObjectIvarWithFieldPrivate() call as consuming the array/map,
 // so use of the array/map after the call returns is flagged as a use after
 // free.
-// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain
+// But GPBSetRetainedObjectIvarWithFieldPrivate() is "consuming" the retain
 // count be holding onto the object (it is transferring it), the object is
 // still valid after returning from the call.  The other way to avoid this
 // would be to add a -retain/-autorelease, but that would force every
@@ -571,14 +571,13 @@
 // and performance hit.
 
 static id GetOrCreateArrayIvarWithField(GPBMessage *self,
-                                        GPBFieldDescriptor *field,
-                                        GPBFileSyntax syntax) {
+                                        GPBFieldDescriptor *field) {
   id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   if (!array) {
     // No lock needed, this is called from places expecting to mutate
     // so no threading protection is needed.
     array = CreateArrayForField(field, nil);
-    GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax);
+    GPBSetRetainedObjectIvarWithFieldPrivate(self, field, array);
   }
   return array;
 }
@@ -586,30 +585,40 @@
 // This is like GPBGetObjectIvarWithField(), but for arrays, it should
 // only be used to wire the method into the class.
 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
-  id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-  if (!array) {
-    // Check again after getting the lock.
-    GPBPrepareReadOnlySemaphore(self);
-    dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
-    array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-    if (!array) {
-      array = CreateArrayForField(field, self);
-      GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array);
-    }
-    dispatch_semaphore_signal(self->readOnlySemaphore_);
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
+  id array = atomic_load(typePtr);
+  if (array) {
+    return array;
   }
-  return array;
+
+  id expected = nil;
+  id autocreated = CreateArrayForField(field, self);
+  if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
+    // Value was set, return it.
+    return autocreated;
+  }
+
+  // Some other thread set it, release the one created and return what got set.
+  if (GPBFieldDataTypeIsObject(field)) {
+    GPBAutocreatedArray *autoArray = autocreated;
+    autoArray->_autocreator = nil;
+  } else {
+    GPBInt32Array *gpbArray = autocreated;
+    gpbArray->_autocreator = nil;
+  }
+  [autocreated release];
+  return expected;
 }
 
 static id GetOrCreateMapIvarWithField(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      GPBFileSyntax syntax) {
+                                      GPBFieldDescriptor *field) {
   id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   if (!dict) {
     // No lock needed, this is called from places expecting to mutate
     // so no threading protection is needed.
     dict = CreateMapForField(field, nil);
-    GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax);
+    GPBSetRetainedObjectIvarWithFieldPrivate(self, field, dict);
   }
   return dict;
 }
@@ -617,19 +626,31 @@
 // This is like GPBGetObjectIvarWithField(), but for maps, it should
 // only be used to wire the method into the class.
 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
-  id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-  if (!dict) {
-    // Check again after getting the lock.
-    GPBPrepareReadOnlySemaphore(self);
-    dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
-    dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-    if (!dict) {
-      dict = CreateMapForField(field, self);
-      GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict);
-    }
-    dispatch_semaphore_signal(self->readOnlySemaphore_);
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
+  id dict = atomic_load(typePtr);
+  if (dict) {
+    return dict;
   }
-  return dict;
+
+  id expected = nil;
+  id autocreated = CreateMapForField(field, self);
+  if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
+    // Value was set, return it.
+    return autocreated;
+  }
+
+  // Some other thread set it, release the one created and return what got set.
+  if ((field.mapKeyDataType == GPBDataTypeString) &&
+      GPBFieldDataTypeIsObject(field)) {
+    GPBAutocreatedDictionary *autoDict = autocreated;
+    autoDict->_autocreator = nil;
+  } else {
+    GPBInt32Int32Dictionary *gpbDict = autocreated;
+    gpbDict->_autocreator = nil;
+  }
+  [autocreated release];
+  return expected;
 }
 
 #endif  // !defined(__clang_analyzer__)
@@ -668,9 +689,8 @@
     // This will recursively make all parent messages visible until it reaches a
     // super-creator that's visible.
     if (self->autocreatorField_) {
-      GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax;
-      GPBSetObjectIvarWithFieldInternal(self->autocreator_,
-                                        self->autocreatorField_, self, syntax);
+      GPBSetObjectIvarWithFieldPrivate(self->autocreator_,
+                                        self->autocreatorField_, self);
     } else {
       [self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
     }
@@ -936,8 +956,6 @@
   // Copy all the storage...
   memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_);
 
-  GPBFileSyntax syntax = descriptor.file.syntax;
-
   // Loop over the fields doing fixup...
   for (GPBFieldDescriptor *field in descriptor->fields_) {
     if (GPBFieldIsMapOrArray(field)) {
@@ -1005,8 +1023,7 @@
         // We retain here because the memcpy picked up the pointer value and
         // the next call to SetRetainedObject... will release the current value.
         [value retain];
-        GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
-                                                  syntax);
+        GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
       }
     } else if (GPBFieldDataTypeIsMessage(field)) {
       // For object types, if we have a value, copy it.  If we don't,
@@ -1018,8 +1035,7 @@
         // We retain here because the memcpy picked up the pointer value and
         // the next call to SetRetainedObject... will release the current value.
         [value retain];
-        GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
-                                                  syntax);
+        GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
       } else {
         uint8_t *storage = (uint8_t *)message->messageStorage_;
         id *typePtr = (id *)&storage[field->description_->offset];
@@ -1033,8 +1049,7 @@
       // We retain here because the memcpy picked up the pointer value and
       // the next call to SetRetainedObject... will release the current value.
       [value retain];
-      GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
-                                                syntax);
+      GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
     } else {
       // memcpy took care of the rest of the primitive fields if they were set.
     }
@@ -2161,13 +2176,13 @@
 #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                             \
     case GPBDataType##NAME: {                                              \
       TYPE val = GPBCodedInputStreamRead##NAME(&input->state_);            \
-      GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax);  \
+      GPBSet##FUNC_TYPE##IvarWithFieldPrivate(self, field, val);           \
       break;                                                               \
             }
 #define CASE_SINGLE_OBJECT(NAME)                                           \
     case GPBDataType##NAME: {                                              \
       id val = GPBCodedInputStreamReadRetained##NAME(&input->state_);      \
-      GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \
+      GPBSetRetainedObjectIvarWithFieldPrivate(self, field, val);          \
       break;                                                               \
     }
       CASE_SINGLE_POD(Bool, BOOL, Bool)
@@ -2198,7 +2213,7 @@
       } else {
         GPBMessage *message = [[field.msgClass alloc] init];
         [input readMessage:message extensionRegistry:extensionRegistry];
-        GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
+        GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
       }
       break;
     }
@@ -2217,7 +2232,7 @@
         [input readGroup:GPBFieldNumber(field)
                       message:message
             extensionRegistry:extensionRegistry];
-        GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
+        GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
       }
       break;
     }
@@ -2226,7 +2241,7 @@
       int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
       if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
           [field isValidEnumValue:val]) {
-        GPBSetInt32IvarWithFieldInternal(self, field, val, syntax);
+        GPBSetInt32IvarWithFieldPrivate(self, field, val);
       } else {
         GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
         [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
@@ -2240,7 +2255,7 @@
     GPBCodedInputStream *input) {
   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   GPBCodedInputStreamState *state = &input->state_;
-  id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
+  id genericArray = GetOrCreateArrayIvarWithField(self, field);
   int32_t length = GPBCodedInputStreamReadInt32(state);
   size_t limit = GPBCodedInputStreamPushLimit(state, length);
   while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
@@ -2293,7 +2308,7 @@
     GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
     GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
   GPBCodedInputStreamState *state = &input->state_;
-  id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
+  id genericArray = GetOrCreateArrayIvarWithField(self, field);
   switch (GPBGetFieldDataType(field)) {
 #define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
    case GPBDataType##NAME: {                                 \
@@ -2395,7 +2410,7 @@
         } else {  // fieldType == GPBFieldTypeMap
           // GPB*Dictionary or NSDictionary, exact type doesn't matter at this
           // point.
-          id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax);
+          id map = GetOrCreateMapIvarWithField(self, fieldDescriptor);
           [input readMapEntry:map
             extensionRegistry:extensionRegistry
                         field:fieldDescriptor
@@ -2469,7 +2484,6 @@
   GPBBecomeVisibleToAutocreator(self);
 
   GPBDescriptor *descriptor = [[self class] descriptor];
-  GPBFileSyntax syntax = descriptor.file.syntax;
 
   for (GPBFieldDescriptor *field in descriptor->fields_) {
     GPBFieldType fieldType = field.fieldType;
@@ -2483,44 +2497,44 @@
       GPBDataType fieldDataType = GPBGetFieldDataType(field);
       switch (fieldDataType) {
         case GPBDataTypeBool:
-          GPBSetBoolIvarWithFieldInternal(
-              self, field, GPBGetMessageBoolField(other, field), syntax);
+          GPBSetBoolIvarWithFieldPrivate(
+              self, field, GPBGetMessageBoolField(other, field));
           break;
         case GPBDataTypeSFixed32:
         case GPBDataTypeEnum:
         case GPBDataTypeInt32:
         case GPBDataTypeSInt32:
-          GPBSetInt32IvarWithFieldInternal(
-              self, field, GPBGetMessageInt32Field(other, field), syntax);
+          GPBSetInt32IvarWithFieldPrivate(
+              self, field, GPBGetMessageInt32Field(other, field));
           break;
         case GPBDataTypeFixed32:
         case GPBDataTypeUInt32:
-          GPBSetUInt32IvarWithFieldInternal(
-              self, field, GPBGetMessageUInt32Field(other, field), syntax);
+          GPBSetUInt32IvarWithFieldPrivate(
+              self, field, GPBGetMessageUInt32Field(other, field));
           break;
         case GPBDataTypeSFixed64:
         case GPBDataTypeInt64:
         case GPBDataTypeSInt64:
-          GPBSetInt64IvarWithFieldInternal(
-              self, field, GPBGetMessageInt64Field(other, field), syntax);
+          GPBSetInt64IvarWithFieldPrivate(
+              self, field, GPBGetMessageInt64Field(other, field));
           break;
         case GPBDataTypeFixed64:
         case GPBDataTypeUInt64:
-          GPBSetUInt64IvarWithFieldInternal(
-              self, field, GPBGetMessageUInt64Field(other, field), syntax);
+          GPBSetUInt64IvarWithFieldPrivate(
+              self, field, GPBGetMessageUInt64Field(other, field));
           break;
         case GPBDataTypeFloat:
-          GPBSetFloatIvarWithFieldInternal(
-              self, field, GPBGetMessageFloatField(other, field), syntax);
+          GPBSetFloatIvarWithFieldPrivate(
+              self, field, GPBGetMessageFloatField(other, field));
           break;
         case GPBDataTypeDouble:
-          GPBSetDoubleIvarWithFieldInternal(
-              self, field, GPBGetMessageDoubleField(other, field), syntax);
+          GPBSetDoubleIvarWithFieldPrivate(
+              self, field, GPBGetMessageDoubleField(other, field));
           break;
         case GPBDataTypeBytes:
         case GPBDataTypeString: {
           id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
-          GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax);
+          GPBSetObjectIvarWithFieldPrivate(self, field, otherVal);
           break;
         }
         case GPBDataTypeMessage:
@@ -2532,8 +2546,7 @@
             [message mergeFrom:otherVal];
           } else {
             GPBMessage *message = [otherVal copy];
-            GPBSetRetainedObjectIvarWithFieldInternal(self, field, message,
-                                                      syntax);
+            GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
           }
           break;
         }
@@ -2547,17 +2560,17 @@
         GPBDataType fieldDataType = field->description_->dataType;
         if (GPBDataTypeIsObject(fieldDataType)) {
           NSMutableArray *resultArray =
-              GetOrCreateArrayIvarWithField(self, field, syntax);
+              GetOrCreateArrayIvarWithField(self, field);
           [resultArray addObjectsFromArray:otherArray];
         } else if (fieldDataType == GPBDataTypeEnum) {
           GPBEnumArray *resultArray =
-              GetOrCreateArrayIvarWithField(self, field, syntax);
+              GetOrCreateArrayIvarWithField(self, field);
           [resultArray addRawValuesFromArray:otherArray];
         } else {
           // The array type doesn't matter, that all implement
           // -addValuesFromArray:.
           GPBInt32Array *resultArray =
-              GetOrCreateArrayIvarWithField(self, field, syntax);
+              GetOrCreateArrayIvarWithField(self, field);
           [resultArray addValuesFromArray:otherArray];
         }
       }
@@ -2571,19 +2584,19 @@
         if (GPBDataTypeIsObject(keyDataType) &&
             GPBDataTypeIsObject(valueDataType)) {
           NSMutableDictionary *resultDict =
-              GetOrCreateMapIvarWithField(self, field, syntax);
+              GetOrCreateMapIvarWithField(self, field);
           [resultDict addEntriesFromDictionary:otherDict];
         } else if (valueDataType == GPBDataTypeEnum) {
           // The exact type doesn't matter, just need to know it is a
           // GPB*EnumDictionary.
           GPBInt32EnumDictionary *resultDict =
-              GetOrCreateMapIvarWithField(self, field, syntax);
+              GetOrCreateMapIvarWithField(self, field);
           [resultDict addRawEntriesFromDictionary:otherDict];
         } else {
           // The exact type doesn't matter, they all implement
           // -addEntriesFromDictionary:.
           GPBInt32Int32Dictionary *resultDict =
-              GetOrCreateMapIvarWithField(self, field, syntax);
+              GetOrCreateMapIvarWithField(self, field);
           [resultDict addEntriesFromDictionary:otherDict];
         }
       }
@@ -3115,14 +3128,13 @@
 
 // See comment about __unsafe_unretained on ResolveIvarGet.
 static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field,
-                           GPBFileSyntax syntax,
                            ResolveIvarAccessorMethodResult *result) {
   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   switch (fieldDataType) {
 #define CASE_SET(NAME, TYPE, TRUE_NAME)                                       \
     case GPBDataType##NAME: {                                                 \
       result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {  \
-        return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \
+        return GPBSet##TRUE_NAME##IvarWithFieldPrivate(obj, field, value);    \
       });                                                                     \
       result->encodingSelector = @selector(set##NAME:);                       \
       break;                                                                  \
@@ -3130,7 +3142,7 @@
 #define CASE_SET_COPY(NAME)                                                   \
     case GPBDataType##NAME: {                                                 \
       result->impToAdd = imp_implementationWithBlock(^(id obj, id value) {    \
-        return GPBSetRetainedObjectIvarWithFieldInternal(obj, field, [value copy], syntax); \
+        return GPBSetRetainedObjectIvarWithFieldPrivate(obj, field, [value copy]); \
       });                                                                     \
       result->encodingSelector = @selector(set##NAME:);                       \
       break;                                                                  \
@@ -3177,7 +3189,7 @@
         ResolveIvarGet(field, &result);
         break;
       } else if (sel == field->setSel_) {
-        ResolveIvarSet(field, descriptor.file.syntax, &result);
+        ResolveIvarSet(field, &result);
         break;
       } else if (sel == field->hasOrCountSel_) {
         int32_t index = GPBFieldHasIndex(field);
@@ -3227,9 +3239,8 @@
       } else if (sel == field->setSel_) {
         // Local for syntax so the block can directly capture it and not the
         // full lookup.
-        const GPBFileSyntax syntax = descriptor.file.syntax;
         result.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
-          GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+          GPBSetObjectIvarWithFieldPrivate(obj, field, value);
         });
         result.encodingSelector = @selector(setArray:);
         break;
@@ -3267,7 +3278,7 @@
 
 + (BOOL)resolveClassMethod:(SEL)sel {
   // Extensions scoped to a Message and looked up via class methods.
-  if (GPBResolveExtensionClassMethod([self descriptor].messageClass, sel)) {
+  if (GPBResolveExtensionClassMethod(self, sel)) {
     return YES;
   }
   return [super resolveClassMethod:sel];
@@ -3300,7 +3311,7 @@
     // if a sub message in a field has extensions, the issue still exists. A
     // recursive check could be done here (like the work in
     // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to
-    // be expensive and could slow down serialization in DEBUG enought to cause
+    // be expensive and could slow down serialization in DEBUG enough to cause
     // developers other problems.
     NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it"
           @" has %ld extensions; when read back in, those fields will be"
@@ -3334,9 +3345,7 @@
      [self class], field.name];
   }
 #endif
-  GPBDescriptor *descriptor = [[self class] descriptor];
-  GPBFileSyntax syntax = descriptor.file.syntax;
-  return GetOrCreateArrayIvarWithField(self, field, syntax);
+  return GetOrCreateArrayIvarWithField(self, field);
 }
 
 // Only exists for public api, no core code should use this.
@@ -3348,37 +3357,39 @@
      [self class], field.name];
   }
 #endif
-  GPBDescriptor *descriptor = [[self class] descriptor];
-  GPBFileSyntax syntax = descriptor.file.syntax;
-  return GetOrCreateMapIvarWithField(self, field, syntax);
+  return GetOrCreateMapIvarWithField(self, field);
 }
 
 id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
   NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here");
-  if (GPBGetHasIvarField(self, field)) {
-    uint8_t *storage = (uint8_t *)self->messageStorage_;
-    id *typePtr = (id *)&storage[field->description_->offset];
-    return *typePtr;
-  }
-  // Not set...
-
-  // Non messages (string/data), get their default.
   if (!GPBFieldDataTypeIsMessage(field)) {
+    if (GPBGetHasIvarField(self, field)) {
+      uint8_t *storage = (uint8_t *)self->messageStorage_;
+      id *typePtr = (id *)&storage[field->description_->offset];
+      return *typePtr;
+    }
+    // Not set...non messages (string/data), get their default.
     return field.defaultValue.valueMessage;
   }
 
-  GPBPrepareReadOnlySemaphore(self);
-  dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
-  GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
-  if (!result) {
-    // For non repeated messages, create the object, set it and return it.
-    // This object will not initially be visible via GPBGetHasIvar, so
-    // we save its creator so it can become visible if it's mutated later.
-    result = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
-    GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result);
+  uint8_t *storage = (uint8_t *)self->messageStorage_;
+  _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
+  id msg = atomic_load(typePtr);
+  if (msg) {
+    return msg;
   }
-  dispatch_semaphore_signal(self->readOnlySemaphore_);
-  return result;
+
+  id expected = nil;
+  id autocreated = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
+  if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
+    // Value was set, return it.
+    return autocreated;
+  }
+
+  // Some other thread set it, release the one created and return what got set.
+  GPBClearMessageAutocreator(autocreated);
+  [autocreated release];
+  return expected;
 }
 
 #pragma clang diagnostic pop
diff --git a/objectivec/GPBSourceContext.pbobjc.h b/objectivec/GPBSourceContext.pbobjc.h
index 90263b1..7a10336 100644
--- a/objectivec/GPBSourceContext.pbobjc.h
+++ b/objectivec/GPBSourceContext.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
diff --git a/objectivec/GPBSourceContext.pbobjc.m b/objectivec/GPBSourceContext.pbobjc.m
index d37a425..b3e6fa7 100644
--- a/objectivec/GPBSourceContext.pbobjc.m
+++ b/objectivec/GPBSourceContext.pbobjc.m
@@ -70,7 +70,7 @@
         .number = GPBSourceContext_FieldNumber_FileName,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
     };
@@ -81,7 +81,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBSourceContext__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBStruct.pbobjc.h b/objectivec/GPBStruct.pbobjc.h
index b465c3b..e36df3f 100644
--- a/objectivec/GPBStruct.pbobjc.h
+++ b/objectivec/GPBStruct.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
diff --git a/objectivec/GPBStruct.pbobjc.m b/objectivec/GPBStruct.pbobjc.m
index dbdcbe1..554046a 100644
--- a/objectivec/GPBStruct.pbobjc.m
+++ b/objectivec/GPBStruct.pbobjc.m
@@ -126,7 +126,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBStruct__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -226,7 +226,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     static const char *oneofs[] = {
       "kind",
     };
@@ -246,19 +246,19 @@
 int32_t GPBValue_NullValue_RawValue(GPBValue *message) {
   GPBDescriptor *descriptor = [GPBValue descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue];
-  return GPBGetMessageInt32Field(message, field);
+  return GPBGetMessageRawEnumField(message, field);
 }
 
 void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) {
   GPBDescriptor *descriptor = [GPBValue descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue];
-  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+  GPBSetMessageRawEnumField(message, field, value);
 }
 
 void GPBValue_ClearKindOneOfCase(GPBValue *message) {
-  GPBDescriptor *descriptor = [message descriptor];
+  GPBDescriptor *descriptor = [GPBValue descriptor];
   GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0];
-  GPBMaybeClearOneof(message, oneof, -1, 0);
+  GPBClearOneof(message, oneof);
 }
 #pragma mark - GPBListValue
 
@@ -294,7 +294,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBListValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBTimestamp.pbobjc.h b/objectivec/GPBTimestamp.pbobjc.h
index 1118c77..a328afc 100644
--- a/objectivec/GPBTimestamp.pbobjc.h
+++ b/objectivec/GPBTimestamp.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
@@ -107,7 +107,16 @@
  *         .setNanos((int) ((millis % 1000) * 1000000)).build();
  *
  *
- * Example 5: Compute Timestamp from current time in Python.
+ * Example 5: Compute Timestamp from Java `Instant.now()`.
+ *
+ *     Instant now = Instant.now();
+ *
+ *     Timestamp timestamp =
+ *         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
+ *             .setNanos(now.getNano()).build();
+ *
+ *
+ * Example 6: Compute Timestamp from current time in Python.
  *
  *     timestamp = Timestamp()
  *     timestamp.GetCurrentTime()
diff --git a/objectivec/GPBTimestamp.pbobjc.m b/objectivec/GPBTimestamp.pbobjc.m
index 450d131..736a75d 100644
--- a/objectivec/GPBTimestamp.pbobjc.m
+++ b/objectivec/GPBTimestamp.pbobjc.m
@@ -72,7 +72,7 @@
         .number = GPBTimestamp_FieldNumber_Seconds,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt64,
       },
       {
@@ -81,7 +81,7 @@
         .number = GPBTimestamp_FieldNumber_Nanos,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt32,
       },
     };
@@ -92,7 +92,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBTimestamp__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBType.pbobjc.h b/objectivec/GPBType.pbobjc.h
index 4b6cd9c..747e15d 100644
--- a/objectivec/GPBType.pbobjc.h
+++ b/objectivec/GPBType.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
diff --git a/objectivec/GPBType.pbobjc.m b/objectivec/GPBType.pbobjc.m
index 827270a..70dae31 100644
--- a/objectivec/GPBType.pbobjc.m
+++ b/objectivec/GPBType.pbobjc.m
@@ -132,7 +132,7 @@
         .number = GPBType_FieldNumber_Name,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBType__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -177,7 +177,7 @@
         .number = GPBType_FieldNumber_Syntax,
         .hasIndex = 2,
         .offset = (uint32_t)offsetof(GPBType__storage_, syntax),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeEnum,
       },
     };
@@ -188,7 +188,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBType__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -202,13 +202,13 @@
 int32_t GPBType_Syntax_RawValue(GPBType *message) {
   GPBDescriptor *descriptor = [GPBType descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
-  return GPBGetMessageInt32Field(message, field);
+  return GPBGetMessageRawEnumField(message, field);
 }
 
 void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) {
   GPBDescriptor *descriptor = [GPBType descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
-  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+  GPBSetMessageRawEnumField(message, field, value);
 }
 
 #pragma mark - GPBField
@@ -251,7 +251,7 @@
         .number = GPBField_FieldNumber_Kind,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBField__storage_, kind),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeEnum,
       },
       {
@@ -260,7 +260,7 @@
         .number = GPBField_FieldNumber_Cardinality,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBField__storage_, cardinality),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeEnum,
       },
       {
@@ -269,7 +269,7 @@
         .number = GPBField_FieldNumber_Number,
         .hasIndex = 2,
         .offset = (uint32_t)offsetof(GPBField__storage_, number),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt32,
       },
       {
@@ -278,7 +278,7 @@
         .number = GPBField_FieldNumber_Name,
         .hasIndex = 3,
         .offset = (uint32_t)offsetof(GPBField__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -287,7 +287,7 @@
         .number = GPBField_FieldNumber_TypeURL,
         .hasIndex = 4,
         .offset = (uint32_t)offsetof(GPBField__storage_, typeURL),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -296,7 +296,7 @@
         .number = GPBField_FieldNumber_OneofIndex,
         .hasIndex = 5,
         .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt32,
       },
       {
@@ -305,7 +305,7 @@
         .number = GPBField_FieldNumber_Packed,
         .hasIndex = 6,
         .offset = 7,  // Stored in _has_storage_ to save space.
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeBool,
       },
       {
@@ -323,7 +323,7 @@
         .number = GPBField_FieldNumber_JsonName,
         .hasIndex = 8,
         .offset = (uint32_t)offsetof(GPBField__storage_, jsonName),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -332,7 +332,7 @@
         .number = GPBField_FieldNumber_DefaultValue,
         .hasIndex = 9,
         .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
     };
@@ -343,7 +343,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBField__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
 #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
     static const char *extraTextFormatInfo =
         "\001\006\004\241!!\000";
@@ -362,25 +362,25 @@
 int32_t GPBField_Kind_RawValue(GPBField *message) {
   GPBDescriptor *descriptor = [GPBField descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind];
-  return GPBGetMessageInt32Field(message, field);
+  return GPBGetMessageRawEnumField(message, field);
 }
 
 void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) {
   GPBDescriptor *descriptor = [GPBField descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind];
-  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+  GPBSetMessageRawEnumField(message, field, value);
 }
 
 int32_t GPBField_Cardinality_RawValue(GPBField *message) {
   GPBDescriptor *descriptor = [GPBField descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality];
-  return GPBGetMessageInt32Field(message, field);
+  return GPBGetMessageRawEnumField(message, field);
 }
 
 void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) {
   GPBDescriptor *descriptor = [GPBField descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality];
-  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+  GPBSetMessageRawEnumField(message, field, value);
 }
 
 #pragma mark - Enum GPBField_Kind
@@ -528,7 +528,7 @@
         .number = GPBEnum_FieldNumber_Name,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBEnum__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -564,7 +564,7 @@
         .number = GPBEnum_FieldNumber_Syntax,
         .hasIndex = 2,
         .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax),
-        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeEnum,
       },
     };
@@ -575,7 +575,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBEnum__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -589,13 +589,13 @@
 int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) {
   GPBDescriptor *descriptor = [GPBEnum descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
-  return GPBGetMessageInt32Field(message, field);
+  return GPBGetMessageRawEnumField(message, field);
 }
 
 void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) {
   GPBDescriptor *descriptor = [GPBEnum descriptor];
   GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
-  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+  GPBSetMessageRawEnumField(message, field, value);
 }
 
 #pragma mark - GPBEnumValue
@@ -625,7 +625,7 @@
         .number = GPBEnumValue_FieldNumber_Name,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -634,7 +634,7 @@
         .number = GPBEnumValue_FieldNumber_Number,
         .hasIndex = 1,
         .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt32,
       },
       {
@@ -654,7 +654,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBEnumValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -690,7 +690,7 @@
         .number = GPBOption_FieldNumber_Name,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBOption__storage_, name),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
       {
@@ -710,7 +710,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBOption__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h
index ef4f855..75759b2 100644
--- a/objectivec/GPBUtilities.h
+++ b/objectivec/GPBUtilities.h
@@ -34,6 +34,8 @@
 #import "GPBMessage.h"
 #import "GPBRuntimeTypes.h"
 
+@class GPBOneofDescriptor;
+
 CF_EXTERN_C_BEGIN
 
 NS_ASSUME_NONNULL_BEGIN
@@ -92,6 +94,14 @@
  **/
 void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
 
+/**
+ * Clears the given oneof field for the given message.
+ *
+ * @param self  The message for which to clear the field.
+ * @param oneof The oneof to clear.
+ **/
+void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof);
+
 //%PDDM-EXPAND GPB_ACCESSORS()
 // This block of code is generated, do not edit it directly.
 // clang-format off
diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m
index 7a1635f..08dd358 100644
--- a/objectivec/GPBUtilities.m
+++ b/objectivec/GPBUtilities.m
@@ -62,6 +62,12 @@
 // Marked unused because currently only called from asserts/debug.
 static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused));
 
+// Helper for clearing oneofs.
+static void GPBMaybeClearOneofPrivate(GPBMessage *self,
+                                      GPBOneofDescriptor *oneof,
+                                      int32_t oneofHasIndex,
+                                      uint32_t fieldNumberNotToClear);
+
 NSData *GPBEmptyNSData(void) {
   static dispatch_once_t onceToken;
   static NSData *defaultNSData = nil;
@@ -213,7 +219,7 @@
     // Library is too old for headers.
     [NSException raise:NSInternalInconsistencyException
                 format:@"Linked to ProtocolBuffer runtime version %d,"
-                       @" but code compiled needing atleast %d!",
+                       @" but code compiled needing at least %d!",
                        GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion];
   }
   if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
@@ -281,6 +287,16 @@
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO);
 }
 
+void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof) {
+  #if defined(DEBUG) && DEBUG
+    NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
+              @"OneofDescriptor %@ doesn't appear to be for %@ messages.",
+              oneof.name, [self class]);
+  #endif
+  GPBFieldDescriptor *firstField = oneof->fields_[0];
+  GPBMaybeClearOneofPrivate(self, oneof, firstField->description_->hasIndex, 0);
+}
+
 BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
   NSCAssert(self->messageStorage_ != NULL,
             @"%@: All messages should have storage (from init)",
@@ -325,8 +341,10 @@
   }
 }
 
-void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
-                        int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
+static void GPBMaybeClearOneofPrivate(GPBMessage *self,
+                                      GPBOneofDescriptor *oneof,
+                                      int32_t oneofHasIndex,
+                                      uint32_t fieldNumberNotToClear) {
   uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex);
   if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
     // Do nothing/nothing set in the oneof.
@@ -392,18 +410,16 @@
 //%            [self class], field.name,
 //%            TypeToString(GPBGetFieldDataType(field)));
 //%#endif
-//%  GPBFileSyntax syntax = [self descriptor].file.syntax;
-//%  GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax);
+//%  GPBSet##NAME##IvarWithFieldPrivate(self, field, value);
 //%}
 //%
-//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
-//%            NAME$S                     GPBFieldDescriptor *field,
-//%            NAME$S                     TYPE value,
-//%            NAME$S                     GPBFileSyntax syntax) {
+//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self,
+//%            NAME$S                    GPBFieldDescriptor *field,
+//%            NAME$S                    TYPE value) {
 //%  GPBOneofDescriptor *oneof = field->containingOneof_;
 //%  GPBMessageFieldDescription *fieldDesc = field->description_;
 //%  if (oneof) {
-//%    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+//%    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 //%  }
 //%#if defined(DEBUG) && DEBUG
 //%  NSCAssert(self->messageStorage_ != NULL,
@@ -416,11 +432,10 @@
 //%  uint8_t *storage = (uint8_t *)self->messageStorage_;
 //%  TYPE *typePtr = (TYPE *)&storage[fieldDesc->offset];
 //%  *typePtr = value;
-//%  // proto2: any value counts as having been set; proto3, it
-//%  // has to be a non zero value or be in a oneof.
-//%  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-//%                   || (value != (TYPE)0)
-//%                   || (field->containingOneof_ != NULL));
+//%  // If the value is zero, then we only count the field as "set" if the field
+//%  // shouldn't auto clear on zero.
+//%  BOOL hasValue = ((value != (TYPE)0)
+//%                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
 //%  GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
 //%  GPBBecomeVisibleToAutocreator(self);
 //%}
@@ -489,15 +504,6 @@
 // Object types are handled slightly differently, they need to be released
 // and retained.
 
-void GPBSetAutocreatedRetainedObjectIvarWithField(
-    GPBMessage *self, GPBFieldDescriptor *field,
-    id __attribute__((ns_consumed)) value) {
-  uint8_t *storage = (uint8_t *)self->messageStorage_;
-  id *typePtr = (id *)&storage[field->description_->offset];
-  NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once.");
-  *typePtr = value;
-}
-
 void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
                                              GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
@@ -515,16 +521,14 @@
 static void GPBSetObjectIvarWithField(GPBMessage *self,
                                       GPBFieldDescriptor *field, id value) {
   if (self == nil || field == nil) return;
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
-                                            syntax);
+  GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
 }
 
 static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
                                           GPBFieldDescriptor *field, id value);
 
 // GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags
-// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldInternal
+// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldPrivate
 // is marked as consuming the value. Note: For some reason this doesn't happen
 // with the -retain in GPBSetObjectIvarWithField.
 #if !defined(__clang_analyzer__)
@@ -532,22 +536,18 @@
 static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
                                           GPBFieldDescriptor *field, id value) {
   if (self == nil || field == nil) return;
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value copy],
-                                            syntax);
+  GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value copy]);
 }
 #endif  // !defined(__clang_analyzer__)
 
-void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field, id value,
-                                       GPBFileSyntax syntax) {
-  GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
-                                            syntax);
+void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field, id value) {
+  GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
 }
 
-void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
-                                               GPBFieldDescriptor *field,
-                                               id value, GPBFileSyntax syntax) {
+void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
+                                              GPBFieldDescriptor *field,
+                                              id value) {
   NSCAssert(self->messageStorage_ != NULL,
             @"%@: All messages should have storage (from init)",
             [self class]);
@@ -592,28 +592,19 @@
     // oneof.
     GPBOneofDescriptor *oneof = field->containingOneof_;
     if (oneof) {
-      GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+      GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
     }
     // Clear "has" if they are being set to nil.
     BOOL setHasValue = (value != nil);
-    // Under proto3, Bytes & String fields get cleared by resetting them to
-    // their default (empty) values, so if they are set to something of length
-    // zero, they are being cleared.
-    if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
+    // If the field should clear on a "zero" value, then check if the string/data
+    // was zero length, and clear instead.
+    if (((fieldDesc->flags & GPBFieldClearHasIvarOnZero) != 0) &&
         ([value length] == 0)) {
-      // Except, if the field was in a oneof, then it still gets recorded as
-      // having been set so the state of the oneof can be serialized back out.
-      if (!oneof) {
-        setHasValue = NO;
-      }
-      if (setHasValue) {
-        NSCAssert(value != nil, @"Should never be setting has for nil");
-      } else {
-        // The value passed in was retained, it must be released since we
-        // aren't saving anything in the field.
-        [value release];
-        value = nil;
-      }
+      setHasValue = NO;
+      // The value passed in was retained, it must be released since we
+      // aren't saving anything in the field.
+      [value release];
+      value = nil;
     }
     GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, setHasValue);
   }
@@ -695,16 +686,12 @@
               [self class], field.name,
               TypeToString(GPBGetFieldDataType(field)));
   #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  return GPBGetEnumIvarWithFieldInternal(self, field, syntax);
-}
 
-int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
-                                        GPBFieldDescriptor *field,
-                                        GPBFileSyntax syntax) {
   int32_t result = GPBGetMessageInt32Field(self, field);
   // If this is presevering unknown enums, make sure the value is valid before
   // returning it.
+
+  GPBFileSyntax syntax = [self descriptor].file.syntax;
   if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
       ![field isValidEnumValue:result]) {
     result = kGPBUnrecognizedEnumeratorValue;
@@ -725,20 +712,18 @@
               [self class], field.name,
               TypeToString(GPBGetFieldDataType(field)));
   #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+  GPBSetEnumIvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
-                                     GPBFieldDescriptor *field, int32_t value,
-                                     GPBFileSyntax syntax) {
+void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self,
+                                    GPBFieldDescriptor *field, int32_t value) {
   // Don't allow in unknown values.  Proto3 can use the Raw method.
   if (![field isValidEnumValue:value]) {
     [NSException raise:NSInvalidArgumentException
                 format:@"%@.%@: Attempt to set an unknown enum value (%d)",
                        [self class], field.name, value];
   }
-  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+  GPBSetInt32IvarWithFieldPrivate(self, field, value);
 }
 
 // Only exists for public api, no core code should use this.
@@ -751,8 +736,7 @@
 // Only exists for public api, no core code should use this.
 void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
                                int32_t value) {
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+  GPBSetInt32IvarWithFieldPrivate(self, field, value);
 }
 
 BOOL GPBGetMessageBoolField(GPBMessage *self,
@@ -794,18 +778,16 @@
               [self class], field.name,
               TypeToString(GPBGetFieldDataType(field)));
   #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetBoolIvarWithFieldInternal(self, field, value, syntax);
+  GPBSetBoolIvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
-                                     GPBFieldDescriptor *field,
-                                     BOOL value,
-                                     GPBFileSyntax syntax) {
+void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self,
+                                    GPBFieldDescriptor *field,
+                                    BOOL value) {
   GPBMessageFieldDescription *fieldDesc = field->description_;
   GPBOneofDescriptor *oneof = field->containingOneof_;
   if (oneof) {
-    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
   }
 
   // Bools are stored in the has bits to avoid needing explicit space in the
@@ -814,11 +796,10 @@
   // the offset is never negative)
   GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
 
-  // proto2: any value counts as having been set; proto3, it
-  // has to be a non zero value or be in a oneof.
-  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-                   || (value != (BOOL)0)
-                   || (field->containingOneof_ != NULL));
+  // If the value is zero, then we only count the field as "set" if the field
+  // shouldn't auto clear on zero.
+  BOOL hasValue = ((value != (BOOL)0)
+                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
@@ -865,18 +846,16 @@
             [self class], field.name,
             TypeToString(GPBGetFieldDataType(field)));
 #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+  GPBSetInt32IvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      int32_t value,
-                                      GPBFileSyntax syntax) {
+void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     int32_t value) {
   GPBOneofDescriptor *oneof = field->containingOneof_;
   GPBMessageFieldDescription *fieldDesc = field->description_;
   if (oneof) {
-    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
   }
 #if defined(DEBUG) && DEBUG
   NSCAssert(self->messageStorage_ != NULL,
@@ -889,11 +868,10 @@
   uint8_t *storage = (uint8_t *)self->messageStorage_;
   int32_t *typePtr = (int32_t *)&storage[fieldDesc->offset];
   *typePtr = value;
-  // proto2: any value counts as having been set; proto3, it
-  // has to be a non zero value or be in a oneof.
-  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-                   || (value != (int32_t)0)
-                   || (field->containingOneof_ != NULL));
+  // If the value is zero, then we only count the field as "set" if the field
+  // shouldn't auto clear on zero.
+  BOOL hasValue = ((value != (int32_t)0)
+                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
@@ -941,18 +919,16 @@
             [self class], field.name,
             TypeToString(GPBGetFieldDataType(field)));
 #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax);
+  GPBSetUInt32IvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field,
-                                       uint32_t value,
-                                       GPBFileSyntax syntax) {
+void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      uint32_t value) {
   GPBOneofDescriptor *oneof = field->containingOneof_;
   GPBMessageFieldDescription *fieldDesc = field->description_;
   if (oneof) {
-    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
   }
 #if defined(DEBUG) && DEBUG
   NSCAssert(self->messageStorage_ != NULL,
@@ -965,11 +941,10 @@
   uint8_t *storage = (uint8_t *)self->messageStorage_;
   uint32_t *typePtr = (uint32_t *)&storage[fieldDesc->offset];
   *typePtr = value;
-  // proto2: any value counts as having been set; proto3, it
-  // has to be a non zero value or be in a oneof.
-  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-                   || (value != (uint32_t)0)
-                   || (field->containingOneof_ != NULL));
+  // If the value is zero, then we only count the field as "set" if the field
+  // shouldn't auto clear on zero.
+  BOOL hasValue = ((value != (uint32_t)0)
+                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
@@ -1017,18 +992,16 @@
             [self class], field.name,
             TypeToString(GPBGetFieldDataType(field)));
 #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetInt64IvarWithFieldInternal(self, field, value, syntax);
+  GPBSetInt64IvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      int64_t value,
-                                      GPBFileSyntax syntax) {
+void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     int64_t value) {
   GPBOneofDescriptor *oneof = field->containingOneof_;
   GPBMessageFieldDescription *fieldDesc = field->description_;
   if (oneof) {
-    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
   }
 #if defined(DEBUG) && DEBUG
   NSCAssert(self->messageStorage_ != NULL,
@@ -1041,11 +1014,10 @@
   uint8_t *storage = (uint8_t *)self->messageStorage_;
   int64_t *typePtr = (int64_t *)&storage[fieldDesc->offset];
   *typePtr = value;
-  // proto2: any value counts as having been set; proto3, it
-  // has to be a non zero value or be in a oneof.
-  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-                   || (value != (int64_t)0)
-                   || (field->containingOneof_ != NULL));
+  // If the value is zero, then we only count the field as "set" if the field
+  // shouldn't auto clear on zero.
+  BOOL hasValue = ((value != (int64_t)0)
+                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
@@ -1093,18 +1065,16 @@
             [self class], field.name,
             TypeToString(GPBGetFieldDataType(field)));
 #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax);
+  GPBSetUInt64IvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field,
-                                       uint64_t value,
-                                       GPBFileSyntax syntax) {
+void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      uint64_t value) {
   GPBOneofDescriptor *oneof = field->containingOneof_;
   GPBMessageFieldDescription *fieldDesc = field->description_;
   if (oneof) {
-    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
   }
 #if defined(DEBUG) && DEBUG
   NSCAssert(self->messageStorage_ != NULL,
@@ -1117,11 +1087,10 @@
   uint8_t *storage = (uint8_t *)self->messageStorage_;
   uint64_t *typePtr = (uint64_t *)&storage[fieldDesc->offset];
   *typePtr = value;
-  // proto2: any value counts as having been set; proto3, it
-  // has to be a non zero value or be in a oneof.
-  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-                   || (value != (uint64_t)0)
-                   || (field->containingOneof_ != NULL));
+  // If the value is zero, then we only count the field as "set" if the field
+  // shouldn't auto clear on zero.
+  BOOL hasValue = ((value != (uint64_t)0)
+                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
@@ -1169,18 +1138,16 @@
             [self class], field.name,
             TypeToString(GPBGetFieldDataType(field)));
 #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetFloatIvarWithFieldInternal(self, field, value, syntax);
+  GPBSetFloatIvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      float value,
-                                      GPBFileSyntax syntax) {
+void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     float value) {
   GPBOneofDescriptor *oneof = field->containingOneof_;
   GPBMessageFieldDescription *fieldDesc = field->description_;
   if (oneof) {
-    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
   }
 #if defined(DEBUG) && DEBUG
   NSCAssert(self->messageStorage_ != NULL,
@@ -1193,11 +1160,10 @@
   uint8_t *storage = (uint8_t *)self->messageStorage_;
   float *typePtr = (float *)&storage[fieldDesc->offset];
   *typePtr = value;
-  // proto2: any value counts as having been set; proto3, it
-  // has to be a non zero value or be in a oneof.
-  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-                   || (value != (float)0)
-                   || (field->containingOneof_ != NULL));
+  // If the value is zero, then we only count the field as "set" if the field
+  // shouldn't auto clear on zero.
+  BOOL hasValue = ((value != (float)0)
+                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
@@ -1245,18 +1211,16 @@
             [self class], field.name,
             TypeToString(GPBGetFieldDataType(field)));
 #endif
-  GPBFileSyntax syntax = [self descriptor].file.syntax;
-  GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax);
+  GPBSetDoubleIvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field,
-                                       double value,
-                                       GPBFileSyntax syntax) {
+void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      double value) {
   GPBOneofDescriptor *oneof = field->containingOneof_;
   GPBMessageFieldDescription *fieldDesc = field->description_;
   if (oneof) {
-    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
+    GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
   }
 #if defined(DEBUG) && DEBUG
   NSCAssert(self->messageStorage_ != NULL,
@@ -1269,11 +1233,10 @@
   uint8_t *storage = (uint8_t *)self->messageStorage_;
   double *typePtr = (double *)&storage[fieldDesc->offset];
   *typePtr = value;
-  // proto2: any value counts as having been set; proto3, it
-  // has to be a non zero value or be in a oneof.
-  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
-                   || (value != (double)0)
-                   || (field->containingOneof_ != NULL));
+  // If the value is zero, then we only count the field as "set" if the field
+  // shouldn't auto clear on zero.
+  BOOL hasValue = ((value != (double)0)
+                   || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
@@ -2267,8 +2230,36 @@
   return result;
 }
 
+#pragma mark Legacy methods old generated code calls
+
+// Shim from the older generated code into the runtime.
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      int32_t value,
+                                      GPBFileSyntax syntax) {
+#pragma unused(syntax)
+  GPBSetMessageInt32Field(self, field, value);
+}
+
+void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
+                        int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
+#pragma unused(fieldNumberNotToClear)
+  #if defined(DEBUG) && DEBUG
+    NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
+              @"OneofDescriptor %@ doesn't appear to be for %@ messages.",
+              oneof.name, [self class]);
+    GPBFieldDescriptor *firstField = oneof->fields_[0];
+    NSCAssert(firstField->description_->hasIndex == oneofHasIndex,
+              @"Internal error, oneofHasIndex (%d) doesn't match (%d).",
+              firstField->description_->hasIndex, oneofHasIndex);
+  #endif
+  GPBMaybeClearOneofPrivate(self, oneof, oneofHasIndex, 0);
+}
+
 #pragma clang diagnostic pop
 
+#pragma mark Misc Helpers
+
 BOOL GPBClassHasSel(Class aClass, SEL sel) {
   // NOTE: We have to use class_copyMethodList, all other runtime method
   // lookups actually also resolve the method implementation and this
diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h
index 1638a8c..3d3d734 100644
--- a/objectivec/GPBUtilities_PackagePrivate.h
+++ b/objectivec/GPBUtilities_PackagePrivate.h
@@ -207,114 +207,88 @@
   return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number);
 }
 
-void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
-                        int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
-
 #pragma clang diagnostic pop
 
 //%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE)
-//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
-//%            NAME$S                     GPBFieldDescriptor *field,
-//%            NAME$S                     TYPE value,
-//%            NAME$S                     GPBFileSyntax syntax);
+//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self,
+//%            NAME$S                    GPBFieldDescriptor *field,
+//%            NAME$S                    TYPE value);
 //%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL)
 // This block of code is generated, do not edit it directly.
 // clang-format off
 
-void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
-                                     GPBFieldDescriptor *field,
-                                     BOOL value,
-                                     GPBFileSyntax syntax);
+void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self,
+                                    GPBFieldDescriptor *field,
+                                    BOOL value);
 // clang-format on
 //%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t)
 // This block of code is generated, do not edit it directly.
 // clang-format off
 
-void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      int32_t value,
-                                      GPBFileSyntax syntax);
+void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     int32_t value);
 // clang-format on
 //%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t)
 // This block of code is generated, do not edit it directly.
 // clang-format off
 
-void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field,
-                                       uint32_t value,
-                                       GPBFileSyntax syntax);
+void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      uint32_t value);
 // clang-format on
 //%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t)
 // This block of code is generated, do not edit it directly.
 // clang-format off
 
-void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      int64_t value,
-                                      GPBFileSyntax syntax);
+void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     int64_t value);
 // clang-format on
 //%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t)
 // This block of code is generated, do not edit it directly.
 // clang-format off
 
-void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field,
-                                       uint64_t value,
-                                       GPBFileSyntax syntax);
+void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      uint64_t value);
 // clang-format on
 //%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float)
 // This block of code is generated, do not edit it directly.
 // clang-format off
 
-void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
-                                      GPBFieldDescriptor *field,
-                                      float value,
-                                      GPBFileSyntax syntax);
+void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self,
+                                     GPBFieldDescriptor *field,
+                                     float value);
 // clang-format on
 //%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double)
 // This block of code is generated, do not edit it directly.
 // clang-format off
 
-void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field,
-                                       double value,
-                                       GPBFileSyntax syntax);
+void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      double value);
 // clang-format on
-//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t)
-// This block of code is generated, do not edit it directly.
-// clang-format off
+//%PDDM-EXPAND-END (7 expansions)
 
-void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
-                                     GPBFieldDescriptor *field,
-                                     int32_t value,
-                                     GPBFileSyntax syntax);
-// clang-format on
-//%PDDM-EXPAND-END (8 expansions)
-
-int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
-                                        GPBFieldDescriptor *field,
-                                        GPBFileSyntax syntax);
+void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self,
+                                    GPBFieldDescriptor *field,
+                                    int32_t value);
 
 id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
 
-void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
-                                       GPBFieldDescriptor *field, id value,
-                                       GPBFileSyntax syntax);
-void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
-                                               GPBFieldDescriptor *field,
-                                               id __attribute__((ns_consumed))
-                                               value,
-                                               GPBFileSyntax syntax);
+void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self,
+                                      GPBFieldDescriptor *field, id value);
+void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
+                                              GPBFieldDescriptor *field,
+                                              id __attribute__((ns_consumed))
+                                              value);
 
 // GPBGetObjectIvarWithField will automatically create the field (message) if
 // it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil.
 id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
                                          GPBFieldDescriptor *field);
 
-void GPBSetAutocreatedRetainedObjectIvarWithField(
-    GPBMessage *self, GPBFieldDescriptor *field,
-    id __attribute__((ns_consumed)) value);
-
 // Clears and releases the autocreated message ivar, if it's autocreated. If
 // it's not set as autocreated, this method does nothing.
 void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
@@ -326,11 +300,20 @@
 const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel);
 
 // Helper for text format name encoding.
-// decodeData is the data describing the sepecial decodes.
+// decodeData is the data describing the special decodes.
 // key and inputString are the input that needs decoding.
 NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
                                   NSString *inputString);
 
+
+// Shims from the older generated code into the runtime.
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
+                                      GPBFieldDescriptor *field,
+                                      int32_t value,
+                                      GPBFileSyntax syntax);
+void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
+                        int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
+
 // A series of selectors that are used solely to get @encoding values
 // for them by the dynamic protobuf runtime code. See
 // GPBMessageEncodingForSelector for details. GPBRootObject conforms to
diff --git a/objectivec/GPBWrappers.pbobjc.h b/objectivec/GPBWrappers.pbobjc.h
index cc377f2..713bafc 100644
--- a/objectivec/GPBWrappers.pbobjc.h
+++ b/objectivec/GPBWrappers.pbobjc.h
@@ -17,10 +17,10 @@
  #import "GPBRootObject.h"
 #endif
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
 #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
 
diff --git a/objectivec/GPBWrappers.pbobjc.m b/objectivec/GPBWrappers.pbobjc.m
index 5de7a83..32201d4 100644
--- a/objectivec/GPBWrappers.pbobjc.m
+++ b/objectivec/GPBWrappers.pbobjc.m
@@ -70,7 +70,7 @@
         .number = GPBDoubleValue_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeDouble,
       },
     };
@@ -81,7 +81,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBDoubleValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -115,7 +115,7 @@
         .number = GPBFloatValue_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeFloat,
       },
     };
@@ -126,7 +126,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBFloatValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -160,7 +160,7 @@
         .number = GPBInt64Value_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt64,
       },
     };
@@ -171,7 +171,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBInt64Value__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -205,7 +205,7 @@
         .number = GPBUInt64Value_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeUInt64,
       },
     };
@@ -216,7 +216,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBUInt64Value__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -250,7 +250,7 @@
         .number = GPBInt32Value_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeInt32,
       },
     };
@@ -261,7 +261,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBInt32Value__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -295,7 +295,7 @@
         .number = GPBUInt32Value_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeUInt32,
       },
     };
@@ -306,7 +306,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBUInt32Value__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -339,7 +339,7 @@
         .number = GPBBoolValue_FieldNumber_Value,
         .hasIndex = 0,
         .offset = 1,  // Stored in _has_storage_ to save space.
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeBool,
       },
     };
@@ -350,7 +350,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBBoolValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -384,7 +384,7 @@
         .number = GPBStringValue_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBStringValue__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeString,
       },
     };
@@ -395,7 +395,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBStringValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -429,7 +429,7 @@
         .number = GPBBytesValue_FieldNumber_Value,
         .hasIndex = 0,
         .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value),
-        .flags = GPBFieldOptional,
+        .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
         .dataType = GPBDataTypeBytes,
       },
     };
@@ -440,7 +440,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBBytesValue__storage_)
-                                         flags:GPBDescriptorInitializationFlag_UsesClassRefs];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index 12d0ffd..03e0580 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -836,6 +836,7 @@
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				PRODUCT_NAME = ProtocolBuffers;
+				SKIP_INSTALL = YES;
 				TARGETED_DEVICE_FAMILY = "1,2";
 				USER_HEADER_SEARCH_PATHS = "$(SRCROOT)";
 			};
@@ -846,6 +847,7 @@
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				PRODUCT_NAME = ProtocolBuffers;
+				SKIP_INSTALL = YES;
 				TARGETED_DEVICE_FAMILY = "1,2";
 				USER_HEADER_SEARCH_PATHS = "$(SRCROOT)";
 			};
@@ -856,13 +858,11 @@
 			buildSettings = {
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_WEAK = YES;
-				ENABLE_BITCODE = YES;
 				FRAMEWORK_SEARCH_PATHS = (
 					"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
 					"$(inherited)",
 				);
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
@@ -889,13 +889,11 @@
 			buildSettings = {
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_WEAK = YES;
-				ENABLE_BITCODE = YES;
 				FRAMEWORK_SEARCH_PATHS = (
 					"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
 					"$(inherited)",
 				);
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
@@ -972,7 +970,7 @@
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PROFILING_CODE = NO;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				ONLY_ACTIVE_ARCH = YES;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = iphoneos;
@@ -1041,7 +1039,7 @@
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PROFILING_CODE = NO;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
diff --git a/objectivec/README.md b/objectivec/README.md
index 69fe631..485a720 100644
--- a/objectivec/README.md
+++ b/objectivec/README.md
@@ -131,10 +131,16 @@
 
 **objc_class_prefix=\<prefix\>** (no default)
 
-Since Objective C uses a global namespace for all of its classes, there can
-be collisions. This option provides a prefix that will be added to the Enums
-and Objects (for messages) generated from the proto. Convention is to base
-the prefix on the package the proto is in.
+This options allow you to provide a custom prefix for all the symbols generated
+from a proto file (classes (from message), enums, the Root for extension
+support).
+
+If not set, the generation option `use_package_as_prefix` (documented below)
+controls what is used instead. Since Objective C uses a global namespace for all
+of its classes, there can be collisions. `use_package_as_prefix=yes` should
+avoid collisions since proto package are used to scope/name things in other
+languages, but this option can be used to get shorter names instead. Convention
+is to base the explicit prefix on the proto package.
 
 Objective C Generator `protoc` Options
 --------------------------------------
@@ -168,10 +174,34 @@
     Any number of files can be listed for a framework, just separate them with
     commas.
 
-    There can be multiple lines listing the same frameworkName incase it has a
+    There can be multiple lines listing the same frameworkName in case it has a
     lot of proto files included in it; and having multiple lines makes things
     easier to read.
 
+  * `runtime_import_prefix`: The `value` used for this key to be used as a
+    prefix on `#import`s of runtime provided headers in the generated files.
+    When integrating ObjC protos into a build system, this can be used to avoid
+    having to add the runtime directory to the header search path since the
+    generate `#import` will be more complete.
+
+  * `use_package_as_prefix` and `proto_package_prefix_exceptions_path`: The
+    `value` for `use_package_as_prefix` can be `yes` or `no`, and indicates
+    if a prefix should be derived from the proto package for all the symbols
+    for files that don't have the `objc_class_prefix` file option (mentioned
+    above). This helps ensure the symbols are more unique and means there is
+    less chance of ObjC class name collisions.
+
+    To help in migrating code to using this support,
+    `proto_package_prefix_exceptions_path` can be used to provide the path
+    to a file that contains proto package names (one per line, comments allowed
+    if prefixed with `#`). These package won't get the derived prefix, allowing
+    migrations to the behavior one proto package at a time across a code base.
+
+    `use_package_as_prefix` currently defaults to `no` (existing behavior), but
+    in the future (as a breaking change), that is likely to change since it
+    helps prepare folks before they end up using a lot of protos and getting a
+    lot of collisions.
+
 Contributing
 ------------
 
@@ -188,4 +218,4 @@
 The complete documentation for Protocol Buffers is available via the
 web at:
 
-    https://developers.google.com/protocol-buffers/
+https://developers.google.com/protocol-buffers/
diff --git a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework
index 913a289..e0ee905 100644
--- a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework
+++ b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework
@@ -1,5 +1,5 @@
 source 'https://github.com/CocoaPods/Specs.git'
-platform :ios, '8.0'
+platform :ios, '9.0'
 
 install! 'cocoapods', :deterministic_uuids => false
 
diff --git a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static
index e9b3c23..1bb8cb2 100644
--- a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static
+++ b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static
@@ -1,5 +1,5 @@
 source 'https://github.com/CocoaPods/Specs.git'
-platform :ios, '8.0'
+platform :ios, '9.0'
 
 install! 'cocoapods', :deterministic_uuids => false
 
diff --git a/objectivec/Tests/CocoaPods/run_tests.sh b/objectivec/Tests/CocoaPods/run_tests.sh
index 6d3e12b..35bcc18 100755
--- a/objectivec/Tests/CocoaPods/run_tests.sh
+++ b/objectivec/Tests/CocoaPods/run_tests.sh
@@ -90,7 +90,7 @@
   echo "Cleaning up..."
 
   # Generally don't let things fail, and eat common stdout, but let stderr show
-  # incase something does hiccup.
+  # in case something does hiccup.
   xcodebuild -workspace "${TEST_NAME}.xcworkspace" -scheme "${TEST_NAME}" clean > /dev/null || true
   pod deintegrate > /dev/null || true
   # Flush the cache so nothing is left behind.
diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m
index f5aa690..6cd5a1f 100644
--- a/objectivec/Tests/GPBCodedInputStreamTests.m
+++ b/objectivec/Tests/GPBCodedInputStreamTests.m
@@ -422,7 +422,7 @@
 - (void)testBOMWithinStrings {
   // We've seen servers that end up with BOMs within strings (not always at the
   // start, and sometimes in multiple places), make sure they always parse
-  // correctly. (Again, this is inpart incase a custom string class is ever
+  // correctly. (Again, this is inpart in case a custom string class is ever
   // used again.)
   const char* strs[] = {
     "\xEF\xBB\xBF String with BOM",
diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOuputStreamTests.m
index 6c9144f..a9934ac 100644
--- a/objectivec/Tests/GPBCodedOuputStreamTests.m
+++ b/objectivec/Tests/GPBCodedOuputStreamTests.m
@@ -400,7 +400,7 @@
 
 - (void)testWriteStringsWithZeroChar {
   // Unicode allows `\0` as a character, and NSString is a class cluster, so
-  // there are a few different classes that could end up beind a given string.
+  // there are a few different classes that could end up behind a given string.
   // Historically, we've seen differences based on constant strings in code and
   // strings built via the NSString apis. So this round trips them to ensure
   // they are acting as expected.
diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m
index 6fa7202..b1ff544 100644
--- a/objectivec/Tests/GPBDescriptorTests.m
+++ b/objectivec/Tests/GPBDescriptorTests.m
@@ -304,12 +304,6 @@
 - (void)testOneofDescriptor {
   GPBDescriptor *descriptor = [TestOneof2 descriptor];
 
-  // All fields should be listed.
-  XCTAssertEqual(descriptor.fields.count, 17U);
-
-  // There are two oneofs in there.
-  XCTAssertEqual(descriptor.oneofs.count, 2U);
-
   GPBFieldDescriptor *fooStringField =
       [descriptor fieldWithNumber:TestOneof2_FieldNumber_FooString];
   XCTAssertNotNil(fooStringField);
@@ -317,22 +311,24 @@
       [descriptor fieldWithNumber:TestOneof2_FieldNumber_BarString];
   XCTAssertNotNil(barStringField);
 
-  // Check the oneofs to have what is expected.
+  // Check the oneofs to have what is expected but not other onesofs
 
   GPBOneofDescriptor *oneofFoo = [descriptor oneofWithName:@"foo"];
   XCTAssertNotNil(oneofFoo);
-  XCTAssertEqual(oneofFoo.fields.count, 9U);
+  XCTAssertNotNil([oneofFoo fieldWithName:@"fooString"]);
+  XCTAssertNil([oneofFoo fieldWithName:@"barString"]);
 
-  // Pointer comparisons.
+  GPBOneofDescriptor *oneofBar = [descriptor oneofWithName:@"bar"];
+  XCTAssertNotNil(oneofBar);
+  XCTAssertNil([oneofBar fieldWithName:@"fooString"]);
+  XCTAssertNotNil([oneofBar fieldWithName:@"barString"]);
+
+  // Pointer comparisons against lookups from message.
+
   XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString],
                  fooStringField);
   XCTAssertEqual([oneofFoo fieldWithName:@"fooString"], fooStringField);
 
-  GPBOneofDescriptor *oneofBar = [descriptor oneofWithName:@"bar"];
-  XCTAssertNotNil(oneofBar);
-  XCTAssertEqual(oneofBar.fields.count, 6U);
-
-  // Pointer comparisons.
   XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString],
                  barStringField);
   XCTAssertEqual([oneofBar fieldWithName:@"barString"], barStringField);
diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m
index aa5b0db..baad082 100644
--- a/objectivec/Tests/GPBMessageTests+Runtime.m
+++ b/objectivec/Tests/GPBMessageTests+Runtime.m
@@ -270,6 +270,23 @@
                    @"field: %@", name);
   }
 
+  // Single Optional fields
+  //  - has*/setHas* thanks to the optional keyword in proto3, they exist
+  //    for primitive types.
+  //  - has*/setHas* valid for Message.
+
+  for (NSString *name in names) {
+    // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
+    SEL hasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"hasOptional%@", name]);
+    SEL setHasSel = NSSelectorFromString(
+        [NSString stringWithFormat:@"setHasOptional%@:", name]);
+    XCTAssertTrue([Message3Optional instancesRespondToSelector:hasSel], @"field: %@",
+                  name);
+    XCTAssertTrue([Message3Optional instancesRespondToSelector:setHasSel],
+                  @"field: %@", name);
+  }
+
   // map<> fields
   //  - no has*/setHas*
   //  - *Count
@@ -1002,6 +1019,249 @@
 //%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS()
 }
 
+- (void)testProto3SingleOptionalFieldHasBehavior {
+  //
+  // Setting to any value including the default (0) should result in true.
+  //
+
+//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
+//%  {  // optional##FIELD
+//%    Message3Optional *msg = [[Message3Optional alloc] init];
+//%    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
+//%    msg.optional##FIELD = NON_ZERO_VALUE;
+//%    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
+//%    msg.hasOptional##FIELD = NO;
+//%    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
+//%    msg.optional##FIELD = ZERO_VALUE;
+//%    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
+//%    [msg release];
+//%  }
+//%
+//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELDS()
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int32, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int64, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint32, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint64, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint32, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint64, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed32, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed64, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed32, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed64, 1, 0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Float, 1.0f, 0.0f)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Double, 1.0, 0.0)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bool, YES, NO)
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(String, @"foo", @"")
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
+//%  //
+//%  // Test doesn't apply to optionalMessage (no groups in proto3).
+//%  //
+//%
+//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Enum, Message3Optional_Enum_Bar, Message3Optional_Enum_Foo)
+//%PDDM-EXPAND PROTO3_TEST_OPTIONAL_HAS_FIELDS()
+// This block of code is generated, do not edit it directly.
+// clang-format off
+
+  {  // optionalInt32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
+    msg.optionalInt32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
+    msg.hasOptionalInt32 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
+    msg.optionalInt32 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
+    [msg release];
+  }
+
+  {  // optionalInt64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
+    msg.optionalInt64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
+    msg.hasOptionalInt64 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
+    msg.optionalInt64 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
+    [msg release];
+  }
+
+  {  // optionalUint32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
+    msg.optionalUint32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
+    msg.hasOptionalUint32 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
+    msg.optionalUint32 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
+    [msg release];
+  }
+
+  {  // optionalUint64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
+    msg.optionalUint64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
+    msg.hasOptionalUint64 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
+    msg.optionalUint64 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
+    [msg release];
+  }
+
+  {  // optionalSint32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
+    msg.optionalSint32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
+    msg.hasOptionalSint32 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
+    msg.optionalSint32 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
+    [msg release];
+  }
+
+  {  // optionalSint64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
+    msg.optionalSint64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
+    msg.hasOptionalSint64 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
+    msg.optionalSint64 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
+    [msg release];
+  }
+
+  {  // optionalFixed32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
+    msg.optionalFixed32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
+    msg.hasOptionalFixed32 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
+    msg.optionalFixed32 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
+    [msg release];
+  }
+
+  {  // optionalFixed64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
+    msg.optionalFixed64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
+    msg.hasOptionalFixed64 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
+    msg.optionalFixed64 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
+    [msg release];
+  }
+
+  {  // optionalSfixed32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
+    msg.optionalSfixed32 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
+    msg.hasOptionalSfixed32 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
+    msg.optionalSfixed32 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
+    [msg release];
+  }
+
+  {  // optionalSfixed64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
+    msg.optionalSfixed64 = 1;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
+    msg.hasOptionalSfixed64 = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
+    msg.optionalSfixed64 = 0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
+    [msg release];
+  }
+
+  {  // optionalFloat
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
+    msg.optionalFloat = 1.0f;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
+    msg.hasOptionalFloat = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
+    msg.optionalFloat = 0.0f;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
+    [msg release];
+  }
+
+  {  // optionalDouble
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
+    msg.optionalDouble = 1.0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
+    msg.hasOptionalDouble = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
+    msg.optionalDouble = 0.0;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
+    [msg release];
+  }
+
+  {  // optionalBool
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
+    msg.optionalBool = YES;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
+    msg.hasOptionalBool = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
+    msg.optionalBool = NO;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
+    [msg release];
+  }
+
+  {  // optionalString
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
+    msg.optionalString = @"foo";
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
+    msg.hasOptionalString = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
+    msg.optionalString = @"";
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
+    [msg release];
+  }
+
+  {  // optionalBytes
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
+    msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
+    msg.hasOptionalBytes = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
+    msg.optionalBytes = [NSData data];
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
+    [msg release];
+  }
+
+  //
+  // Test doesn't apply to optionalMessage (no groups in proto3).
+  //
+
+  {  // optionalEnum
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
+    msg.optionalEnum = Message3Optional_Enum_Bar;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
+    msg.hasOptionalEnum = NO;
+    XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
+    msg.optionalEnum = Message3Optional_Enum_Foo;
+    XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
+    [msg release];
+  }
+
+// clang-format on
+//%PDDM-EXPAND-END PROTO3_TEST_OPTIONAL_HAS_FIELDS()
+}
+
 - (void)testAccessingProto2UnknownEnumValues {
   Message2 *msg = [[Message2 alloc] init];
 
@@ -2186,7 +2446,7 @@
         msg.oneofBytes = oneofBytesDefault;
         break;
       case Message2_O_OneOfCase_OneofEnum:
-        msg.oneofEnum = Message3_Enum_Baz;
+        msg.oneofEnum = Message2_Enum_Baz;
         break;
       default:
         XCTFail(@"shouldn't happen, loop: %zd, value: %d", i, values[i]);
diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m
index ef6e589..bb63ec3 100644
--- a/objectivec/Tests/GPBMessageTests+Serialization.m
+++ b/objectivec/Tests/GPBMessageTests+Serialization.m
@@ -109,6 +109,317 @@
   [msg release];
 }
 
+- (void)testProto3SerializationHandlingOptionals {
+  //
+  // Proto3 optionals should be just like proto2, zero values also get serialized.
+  //
+
+//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(FIELD, ZERO_VALUE, EXPECTED_LEN)
+//%  {  // optional##FIELD
+//%    Message3Optional *msg = [[Message3Optional alloc] init];
+//%    NSData *data = [msg data];
+//%    XCTAssertEqual([data length], 0U);
+//%    msg.optional##FIELD = ZERO_VALUE;
+//%    data = [msg data];
+//%    XCTAssertEqual(data.length, EXPECTED_LEN);
+//%    NSError *err = nil;
+//%    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+//%    XCTAssertNotNil(msg2);
+//%    XCTAssertNil(err);
+//%    XCTAssertTrue(msg2.hasOptional##FIELD);
+//%    XCTAssertEqualObjects(msg, msg2);
+//%    [msg release];
+//%  }
+//%
+//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS()
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int32, 0, 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int64, 0, 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint32, 0, 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint64, 0, 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint32, 0, 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint64, 0, 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed32, 0, 5)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed64, 0, 9)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed32, 0, 5)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed64, 0, 9)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Float, 0.0f, 5)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Double, 0.0, 9)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bool, NO, 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(String, @"", 2)
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bytes, [NSData data], 2)
+//%  //
+//%  // Test doesn't apply to optionalMessage (no groups in proto3).
+//%  //
+//%
+//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Enum, Message3Optional_Enum_Foo, 3)
+//%PDDM-EXPAND PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS()
+// This block of code is generated, do not edit it directly.
+// clang-format off
+
+  {  // optionalInt32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalInt32 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalInt32);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalInt64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalInt64 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalInt64);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalUint32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalUint32 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalUint32);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalUint64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalUint64 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalUint64);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalSint32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalSint32 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalSint32);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalSint64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalSint64 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalSint64);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalFixed32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalFixed32 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 5);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalFixed32);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalFixed64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalFixed64 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 9);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalFixed64);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalSfixed32
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalSfixed32 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 5);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalSfixed32);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalSfixed64
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalSfixed64 = 0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 9);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalSfixed64);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalFloat
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalFloat = 0.0f;
+    data = [msg data];
+    XCTAssertEqual(data.length, 5);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalFloat);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalDouble
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalDouble = 0.0;
+    data = [msg data];
+    XCTAssertEqual(data.length, 9);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalDouble);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalBool
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalBool = NO;
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalBool);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalString
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalString = @"";
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalString);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  {  // optionalBytes
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalBytes = [NSData data];
+    data = [msg data];
+    XCTAssertEqual(data.length, 2);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalBytes);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+  //
+  // Test doesn't apply to optionalMessage (no groups in proto3).
+  //
+
+  {  // optionalEnum
+    Message3Optional *msg = [[Message3Optional alloc] init];
+    NSData *data = [msg data];
+    XCTAssertEqual([data length], 0U);
+    msg.optionalEnum = Message3Optional_Enum_Foo;
+    data = [msg data];
+    XCTAssertEqual(data.length, 3);
+    NSError *err = nil;
+    Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
+    XCTAssertNotNil(msg2);
+    XCTAssertNil(err);
+    XCTAssertTrue(msg2.hasOptionalEnum);
+    XCTAssertEqualObjects(msg, msg2);
+    [msg release];
+  }
+
+// clang-format on
+//%PDDM-EXPAND-END PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS()
+}
+
 - (void)testProto2UnknownEnumToUnknownField {
   Message3 *orig = [[Message3 alloc] init];
 
@@ -248,7 +559,7 @@
 //%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, String, @"foo", Objects)
 //%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Bytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding], Objects)
 //%GROUP_TEST##SYNTAX()TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Message, subMessage, Objects)
-//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Enum, Message2_Enum_Bar)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Enum, Message##SYNTAX##_Enum_Bar)
 //%GROUP_CLEANUP##SYNTAX()  [subMessage release];
 //%}
 //%
@@ -711,13 +1022,13 @@
 
   {  // oneofEnum
     Message3 *orig = [[Message3 alloc] init];
-    orig.oneofEnum = Message2_Enum_Bar;
+    orig.oneofEnum = Message3_Enum_Bar;
     XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
     NSData *data = [orig data];
     XCTAssertNotNil(data);
     Message3 *msg = [Message3 parseFromData:data error:NULL];
     XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
-    XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+    XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
     [orig release];
   }
 
diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m
index ea224fa..b2c75ba 100644
--- a/objectivec/Tests/GPBMessageTests.m
+++ b/objectivec/Tests/GPBMessageTests.m
@@ -41,6 +41,52 @@
 #import "google/protobuf/Unittest.pbobjc.h"
 #import "google/protobuf/UnittestObjc.pbobjc.h"
 #import "google/protobuf/UnittestObjcOptions.pbobjc.h"
+#import "google/protobuf/UnittestImport.pbobjc.h"
+
+// Helper class to test KVO.
+@interface GPBKVOTestObserver : NSObject {
+  id observee_;
+  NSString *keyPath_;
+}
+
+@property (nonatomic) BOOL didObserve;
+- (id)initWithObservee:(id)observee keyPath:(NSString *)keyPath;
+@end
+
+@implementation GPBKVOTestObserver
+
+@synthesize didObserve;
+
+- (id)initWithObservee:(id)observee keyPath:(NSString *)keyPath {
+  if (self = [super init]) {
+    observee_ = [observee retain];
+    keyPath_ = [keyPath copy];
+    [observee_ addObserver:self forKeyPath:keyPath_ options:0 context:NULL];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [observee_ removeObserver:self forKeyPath:keyPath_];
+  [observee_ release];
+  [keyPath_ release];
+  [super dealloc];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context
+{
+#pragma unused(object)
+#pragma unused(change)
+#pragma unused(context)
+  if ([keyPath isEqualToString:keyPath_]) {
+    self.didObserve = YES;
+  }
+}
+
+@end
 
 @interface MessageTests : GPBTestCase
 @end
@@ -337,6 +383,9 @@
 #endif  // DEBUG
 }
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
 - (void)testCoding {
   GPBMessage *original = [self mergeResult];
   NSData *data =
@@ -372,6 +421,8 @@
   XCTAssertNotEqual(unarchivedObject, original);
 }
 
+#pragma clang diagnostic pop
+
 - (void)testObjectReset {
   // Tests a failure where clearing out defaults values caused an over release.
   TestAllTypes *message = [TestAllTypes message];
@@ -431,6 +482,55 @@
   [self assertAllFieldsKVCMatch:message];
 }
 
+- (void)testKVOBasic {
+  TestAllTypes *message = [TestAllTypes message];
+  GPBKVOTestObserver *observer =
+      [[[GPBKVOTestObserver alloc] initWithObservee:message
+                                            keyPath:@"optionalString"]
+       autorelease];
+  XCTAssertFalse(observer.didObserve);
+  message.defaultString = @"Hello";
+  XCTAssertFalse(observer.didObserve);
+  message.optionalString = @"Hello";
+  XCTAssertTrue(observer.didObserve);
+}
+
+- (void)testKVOAutocreate {
+  TestAllTypes *message = [TestAllTypes message];
+  GPBKVOTestObserver *autocreateObserver =
+      [[[GPBKVOTestObserver alloc] initWithObservee:message
+                                            keyPath:@"optionalImportMessage"]
+       autorelease];
+ GPBKVOTestObserver *innerFieldObserver =
+     [[[GPBKVOTestObserver alloc] initWithObservee:message
+                                           keyPath:@"optionalImportMessage.d"]
+      autorelease];
+  XCTAssertFalse(autocreateObserver.didObserve);
+  XCTAssertFalse(innerFieldObserver.didObserve);
+
+  int a = message.optionalImportMessage.d;
+  XCTAssertEqual(a, 0);
+
+  // Autocreation of fields is not observed by KVO when getting values.
+  XCTAssertFalse(autocreateObserver.didObserve);
+  XCTAssertFalse(innerFieldObserver.didObserve);
+
+  message.optionalImportMessage.d = 2;
+
+  // Autocreation of fields is not observed by KVO.
+  // This is undefined behavior. The library makes no guarantees with regards
+  // to KVO firing if an autocreation occurs as part of a setter.
+  // This test exists just to be aware if the behavior changes.
+  XCTAssertFalse(autocreateObserver.didObserve);
+
+  // Values set inside of an autocreated field are observed.
+  XCTAssertTrue(innerFieldObserver.didObserve);
+
+  // Explicit setting of a message field is observed.
+  message.optionalImportMessage = [ImportMessage message];
+  XCTAssertTrue(autocreateObserver.didObserve);
+}
+
 - (void)testDescription {
   // No real test, just exercise code
   TestAllTypes *message = [TestAllTypes message];
diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m
index 0362bdd..48d75e7 100644
--- a/objectivec/Tests/GPBTestUtilities.m
+++ b/objectivec/Tests/GPBTestUtilities.m
@@ -779,7 +779,7 @@
     [message.repeatedSfixed64Array addValue:210 + i * 100];
     [message.repeatedFloatArray addValue:211 + i * 100];
     [message.repeatedDoubleArray addValue:212 + i * 100];
-    [message.repeatedBoolArray addValue:(i % 2)];
+    [message.repeatedBoolArray addValue:(BOOL)(i % 2)];
     NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
     [message.repeatedStringArray addObject:string];
     [string release];
diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m
index 756bd99..1c6eddf 100644
--- a/objectivec/Tests/GPBUnittestProtos.m
+++ b/objectivec/Tests/GPBUnittestProtos.m
@@ -56,8 +56,6 @@
 #import "google/protobuf/UnittestLite.pbobjc.m"
 #import "google/protobuf/UnittestMset.pbobjc.m"
 #import "google/protobuf/UnittestMsetWireFormat.pbobjc.m"
-#import "google/protobuf/UnittestNoArena.pbobjc.m"
-#import "google/protobuf/UnittestNoArenaImport.pbobjc.m"
 #import "google/protobuf/UnittestNoGenericServices.pbobjc.m"
 #import "google/protobuf/UnittestObjc.pbobjc.m"
 #import "google/protobuf/UnittestObjcStartup.pbobjc.m"
diff --git a/objectivec/Tests/unittest_runtime_proto3.proto b/objectivec/Tests/unittest_runtime_proto3.proto
index ad2e362..c2ee5fb 100644
--- a/objectivec/Tests/unittest_runtime_proto3.proto
+++ b/objectivec/Tests/unittest_runtime_proto3.proto
@@ -119,3 +119,31 @@
   map<int32   , Enum    > map_int32_enum        = 87;
   map<int32   , Message3> map_int32_message     = 88;
 }
+
+message Message3Optional {
+  enum Enum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    EXTRA_3 = 30;
+  }
+
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+  // No 'group' in proto3.
+  optional Message3  optional_message = 18;
+  optional Enum         optional_enum = 19;
+}
diff --git a/php/README.md b/php/README.md
index 16757be..c4292cf 100644
--- a/php/README.md
+++ b/php/README.md
@@ -16,8 +16,8 @@
 
 To use PHP runtime library requires:
 
-- C extension: PHP 5.5, 5.6, or 7.
-- [PHP package](http://php.net/downloads.php): PHP 5.5, 5.6 or 7.
+- C extension: PHP 7.x, 8.0
+- [PHP package](http://php.net/downloads.php): PHP 5.5, 5.6, 7.x, or 8.0.
 
 ## Installation
 
diff --git a/php/REFCOUNTING.md b/php/REFCOUNTING.md
new file mode 100644
index 0000000..26ca717
--- /dev/null
+++ b/php/REFCOUNTING.md
@@ -0,0 +1,112 @@
+
+# Refcounting Tips
+
+One of the trickiest parts of the C extension for PHP is getting the refcounting
+right.  These are some notes about the basics of what you should know,
+especially if you're not super familiar with PHP's C API.
+
+These notes cover the same general material as [the Memory Management chapter of
+the PHP internal's
+book](https://www.phpinternalsbook.com/php7/zvals/memory_management.html), but
+calls out some points that were not immediately clear to me.
+
+##  Zvals
+
+In the PHP C API, the `zval` type is roughly analogous to a variable in PHP, eg:
+
+```php
+    // Think of $a as a "zval".
+    $a = [];
+```
+
+The equivalent PHP C code would be:
+
+```c
+    zval a;
+    ZVAL_NEW_ARR(&a);  // Allocates and assigns a new array.
+```
+
+PHP is reference counted, so each variable -- and thus each zval -- will have a
+reference on whatever it points to (unless its holding a data type that isn't
+refcounted at all, like numbers). Since the zval owns a reference, it must be
+explicitly destroyed in order to release this reference.
+
+```c
+    zval a;
+    ZVAL_NEW_ARR(&a);
+
+    // The destructor for a zval, this must be called or the ref will be leaked.
+    zval_ptr_dtor(&a);
+```
+
+Whenever you see a `zval`, you can assume it owns a ref (or is storing a
+non-refcounted type). If you see a `zval*`, which is also quite common, then
+this is *pointing to* something that owns a ref, but it does not own a ref
+itself.
+
+The [`ZVAL_*` family of
+macros](https://github.com/php/php-src/blob/4030a00e8b6453aff929362bf9b25c193f72c94a/Zend/zend_types.h#L883-L1109)
+initializes a `zval` from a specific value type.  A few examples:
+
+* `ZVAL_NULL(&zv)`: initializes the value to `null`
+* `ZVAL_LONG(&zv, 5)`: initializes a `zend_long` (integer) value
+* `ZVAL_ARR(&zv, arr)`: initializes a `zend_array*` value (refcounted)
+* `ZVAL_OBJ(&zv, obj)`: initializes a `zend_object*` value (refcounted)
+
+Note that all of our custom objects (messages, repeated fields, descriptors,
+etc) are `zend_object*`.
+
+The variants that initialize from a refcounted type do *not* increase the
+refcount. This makes them suitable for initializing from a newly-created object:
+
+```c
+    zval zv;
+    ZVAL_OBJ(&zv, CreateObject());
+```
+
+Once in a while, we want to initialize a `zval` while also increasing the
+reference count. For this we can use `ZVAL_OBJ_COPY()`:
+
+```c
+zend_object *some_global;
+
+void GetGlobal(zval *zv) {
+    // We want to create a new ref to an existing object.
+    ZVAL_OBJ_COPY(zv, some_global);
+}
+```
+
+## Transferring references
+
+A `zval`'s ref must be released at some point. While `zval_ptr_dtor()` is the
+simplest way of releasing a ref, it is not the most common (at least in our code
+base). More often, we are returning the `zval` back to PHP from C.
+
+```c
+    zval zv;
+    InitializeOurZval(&zv);
+    // Returns the value of zv to the caller and donates our ref.
+    RETURN_COPY_VALUE(&zv);
+```
+
+The `RETURN_COPY_VALUE()` macro (standard in PHP 8.x, and polyfilled in earlier
+versions) is the most common way we return a value back to PHP, because it
+donates our `zval`'s refcount to the caller, and thus saves us from needing to
+destroy our `zval` explicitly. This is ideal when we have a full `zval` to
+return.
+
+Once in a while we have a `zval*` to return instead. For example when we parse
+parameters to our function and ask for a `zval`, PHP will give us pointers to
+the existing `zval` structures instead of creating new ones.
+
+```c
+    zval *val;
+    if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) == FAILURE) {
+      return;
+    }
+    // Returns a copy of this zval, adding a ref in the process.
+    RETURN_COPY(val);
+```
+
+When we use `RETURN_COPY`, the refcount is increased; this is perfect for
+returning a `zval*` when we do not own a ref on it.
diff --git a/php/composer.json b/php/composer.json
index b618ea1..f712f0e 100644
--- a/php/composer.json
+++ b/php/composer.json
@@ -6,10 +6,10 @@
   "homepage": "https://developers.google.com/protocol-buffers/",
   "license": "BSD-3-Clause",
   "require": {
-    "php": ">=5.5.0"
+    "php": ">=7.0.0"
   },
   "require-dev": {
-    "phpunit/phpunit": "^5|^4.8.0"
+    "phpunit/phpunit": ">=5.0.0"
   },
   "autoload": {
     "psr-4": {
@@ -19,11 +19,13 @@
   },
   "autoload-dev": {
     "psr-4": {
-      "": "tests/generated"
+      "": "tmp"
     }
   },
   "scripts": {
-    "test": "(cd tests && rm -rf generated && mkdir -p generated && ../../src/protoc --php_out=generated -I../../src -I. proto/empty/echo.proto proto/test.proto proto/test_include.proto proto/test_no_namespace.proto proto/test_prefix.proto proto/test_php_namespace.proto proto/test_empty_php_namespace.proto proto/test_reserved_enum_lower.proto proto/test_reserved_enum_upper.proto proto/test_reserved_enum_value_lower.proto proto/test_reserved_enum_value_upper.proto proto/test_reserved_message_lower.proto proto/test_reserved_message_upper.proto proto/test_service.proto proto/test_service_namespace.proto proto/test_wrapper_type_setters.proto proto/test_descriptors.proto) && (cd ../src && ./protoc --php_out=../php/tests/generated -I../php/tests -I. ../php/tests/proto/test_import_descriptor_proto.proto) && vendor/bin/phpunit",
-    "aggregate_metadata_test": "(cd tests && rm -rf generated && mkdir -p generated && ../../src/protoc --php_out=aggregate_metadata=foo#bar:generated -I../../src -I. proto/test.proto proto/test_include.proto && ../../src/protoc --php_out=generated -I../../src -I. proto/empty/echo.proto proto/test_no_namespace.proto proto/test_empty_php_namespace.proto proto/test_prefix.proto proto/test_php_namespace.proto proto/test_reserved_enum_lower.proto proto/test_reserved_enum_upper.proto proto/test_reserved_enum_value_lower.proto proto/test_reserved_enum_value_upper.proto proto/test_reserved_message_lower.proto proto/test_reserved_message_upper.proto proto/test_service.proto proto/test_service_namespace.proto proto/test_wrapper_type_setters.proto proto/test_descriptors.proto) && (cd ../src && ./protoc --php_out=aggregate_metadata=foo:../php/tests/generated -I../php/tests -I. ../php/tests/proto/test_import_descriptor_proto.proto) && vendor/bin/phpunit"
+    "test_c": "./generate_test_protos.sh && ./tests/compile_extension.sh && php -dextension=ext/google/protobuf/modules/protobuf.so vendor/bin/phpunit --bootstrap tests/force_c_ext.php tests",
+    "test_valgrind": "./generate_test_protos.sh && ./tests/compile_extension.sh && ZEND_DONT_UNLOAD_MODULES=1 USE_ZEND_ALLOC=0 valgrind --leak-check=full --error-exitcode=1 php -dextension=ext/google/protobuf/modules/protobuf.so vendor/bin/phpunit --bootstrap tests/force_c_ext.php tests",
+    "test": "./generate_test_protos.sh && vendor/bin/phpunit tests",
+    "aggregate_metadata_test": "./generate_test_protos.sh --aggregate_metadata && vendor/bin/phpunit tests"
   }
 }
diff --git a/php/ext/google/protobuf/arena.c b/php/ext/google/protobuf/arena.c
new file mode 100644
index 0000000..035dfca
--- /dev/null
+++ b/php/ext/google/protobuf/arena.c
@@ -0,0 +1,95 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <Zend/zend_API.h>
+
+#include "php-upb.h"
+
+// -----------------------------------------------------------------------------
+// Arena
+// -----------------------------------------------------------------------------
+
+typedef struct Arena {
+  zend_object std;
+  upb_arena* arena;
+} Arena;
+
+zend_class_entry *Arena_class_entry;
+static zend_object_handlers Arena_object_handlers;
+
+// PHP Object Handlers /////////////////////////////////////////////////////////
+
+static zend_object* Arena_Create(zend_class_entry *class_type) {
+  Arena *intern = emalloc(sizeof(Arena));
+  zend_object_std_init(&intern->std, class_type);
+  intern->std.handlers = &Arena_object_handlers;
+  intern->arena = upb_arena_new();
+  // Skip object_properties_init(), we don't allow derived classes.
+  return &intern->std;
+}
+
+static void Arena_Free(zend_object* obj) {
+  Arena* intern = (Arena*)obj;
+  upb_arena_free(intern->arena);
+  zend_object_std_dtor(&intern->std);
+}
+
+// C Functions from arena.h ////////////////////////////////////////////////////
+
+void Arena_Init(zval* val) {
+  ZVAL_OBJ(val, Arena_Create(Arena_class_entry));
+}
+
+upb_arena *Arena_Get(zval *val) {
+  Arena *a = (Arena*)Z_OBJ_P(val);
+  return a->arena;
+}
+
+// -----------------------------------------------------------------------------
+// Module init.
+// -----------------------------------------------------------------------------
+
+// No public methods.
+static const zend_function_entry Arena_methods[] = {
+  ZEND_FE_END
+};
+
+void Arena_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Arena", Arena_methods);
+  Arena_class_entry = zend_register_internal_class(&tmp_ce);
+  Arena_class_entry->create_object = Arena_Create;
+  Arena_class_entry->ce_flags |= ZEND_ACC_FINAL;
+
+  memcpy(&Arena_object_handlers, &std_object_handlers,
+         sizeof(zend_object_handlers));
+  Arena_object_handlers.free_obj = Arena_Free;
+}
diff --git a/php/ext/google/protobuf/utf8.h b/php/ext/google/protobuf/arena.h
similarity index 81%
copy from php/ext/google/protobuf/utf8.h
copy to php/ext/google/protobuf/arena.h
index 28b8d87..67e165d 100644
--- a/php/ext/google/protobuf/utf8.h
+++ b/php/ext/google/protobuf/arena.h
@@ -28,9 +28,20 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef GOOGLE_PROTOBUF_UTF8_H_
-#define GOOGLE_PROTOBUF_UTF8_H_
+#ifndef PHP_PROTOBUF_ARENA_H_
+#define PHP_PROTOBUF_ARENA_H_
 
-bool is_structurally_valid_utf8(const char* buf, int len);
+#include <php.h>
 
-#endif  // GOOGLE_PROTOBUF_UTF8_H_
+#include "php-upb.h"
+
+// Registers the PHP Arena class.
+void Arena_ModuleInit();
+
+// Creates and returns a new arena object that wraps a new upb_arena*.
+void Arena_Init(zval *val);
+
+// Gets the underlying upb_arena from this arena object.
+upb_arena *Arena_Get(zval *arena);
+
+#endif  // PHP_PROTOBUF_ARENA_H_
diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c
index 5174f4a..765e902 100644
--- a/php/ext/google/protobuf/array.c
+++ b/php/ext/google/protobuf/array.c
@@ -28,12 +28,437 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <ext/spl/spl_iterators.h>
+#include "array.h"
+
 #include <Zend/zend_API.h>
 #include <Zend/zend_interfaces.h>
 
+#include <ext/spl/spl_iterators.h>
+
+// This is not self-contained: it must be after other Zend includes.
+#include <Zend/zend_exceptions.h>
+
+#include "arena.h"
+#include "convert.h"
+#include "def.h"
+#include "message.h"
+#include "php-upb.h"
 #include "protobuf.h"
 
+static void RepeatedFieldIter_make(zval *val, zval *repeated_field);
+
+// -----------------------------------------------------------------------------
+// RepeatedField
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  zend_object std;
+  zval arena;
+  upb_array *array;
+  TypeInfo type;
+} RepeatedField;
+
+zend_class_entry *RepeatedField_class_entry;
+static zend_object_handlers RepeatedField_object_handlers;
+
+// PHP Object Handlers /////////////////////////////////////////////////////////
+
+/**
+ * RepeatedField_create()
+ *
+ * PHP class entry function to allocate and initialize a new RepeatedField
+ * object.
+ */
+static zend_object* RepeatedField_create(zend_class_entry *class_type) {
+  RepeatedField *intern = emalloc(sizeof(RepeatedField));
+  zend_object_std_init(&intern->std, class_type);
+  intern->std.handlers = &RepeatedField_object_handlers;
+  Arena_Init(&intern->arena);
+  intern->array = NULL;
+  // Skip object_properties_init(), we don't allow derived classes.
+  return &intern->std;
+}
+
+/**
+ * RepeatedField_dtor()
+ *
+ * Object handler to destroy a RepeatedField. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void RepeatedField_destructor(zend_object* obj) {
+  RepeatedField* intern = (RepeatedField*)obj;
+  ObjCache_Delete(intern->array);
+  zval_ptr_dtor(&intern->arena);
+  zend_object_std_dtor(&intern->std);
+}
+
+/**
+ * RepeatedField_compare_objects()
+ *
+ * Object handler for comparing two repeated field objects. Called whenever PHP
+ * code does:
+ *
+ *   $rf1 == $rf2
+ */
+static int RepeatedField_compare_objects(zval *rf1, zval *rf2) {
+  RepeatedField* intern1 = (RepeatedField*)Z_OBJ_P(rf1);
+  RepeatedField* intern2 = (RepeatedField*)Z_OBJ_P(rf2);
+
+  return TypeInfo_Eq(intern1->type, intern2->type) &&
+                 ArrayEq(intern1->array, intern2->array, intern1->type)
+             ? 0
+             : 1;
+}
+
+/**
+ * RepeatedField_clone_obj()
+ *
+ * Object handler for cloning an object in PHP. Called when PHP code does:
+ *
+ *   $rf2 = clone $rf1;
+ */
+static zend_object *RepeatedField_clone_obj(PROTO_VAL *object) {
+  RepeatedField* intern = PROTO_VAL_P(object);
+  upb_arena *arena = Arena_Get(&intern->arena);
+  upb_array *clone = upb_array_new(arena, intern->type.type);
+  size_t n = upb_array_size(intern->array);
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    upb_msgval msgval = upb_array_get(intern->array, i);
+    upb_array_append(clone, msgval, arena);
+  }
+
+  zval ret;
+  RepeatedField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena);
+  return Z_OBJ_P(&ret);
+}
+
+static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) {
+  return NULL;  // We do not have a properties table.
+}
+
+static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object,
+                                             PROTO_STR *member,
+                                             int type, void **cache_slot) {
+  return NULL;  // We don't offer direct references to our properties.
+}
+
+// C Functions from array.h ////////////////////////////////////////////////////
+
+// These are documented in the header file.
+
+void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type,
+                                 zval *arena) {
+  if (!arr) {
+    ZVAL_NULL(val);
+    return;
+  }
+
+  if (!ObjCache_Get(arr, val)) {
+    RepeatedField *intern = emalloc(sizeof(RepeatedField));
+    zend_object_std_init(&intern->std, RepeatedField_class_entry);
+    intern->std.handlers = &RepeatedField_object_handlers;
+    ZVAL_COPY(&intern->arena, arena);
+    intern->array = arr;
+    intern->type = type;
+    // Skip object_properties_init(), we don't allow derived classes.
+    ObjCache_Add(intern->array, &intern->std);
+    ZVAL_OBJ(val, &intern->std);
+  }
+}
+
+upb_array *RepeatedField_GetUpbArray(zval *val, TypeInfo type,
+                                     upb_arena *arena) {
+  if (Z_ISREF_P(val)) {
+    ZVAL_DEREF(val);
+  }
+
+  if (Z_TYPE_P(val) == IS_ARRAY) {
+    // Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]).
+    upb_array *arr = upb_array_new(arena, type.type);
+    HashTable *table = HASH_OF(val);
+    HashPosition pos;
+
+    zend_hash_internal_pointer_reset_ex(table, &pos);
+
+    while (true) {
+      zval *zv = zend_hash_get_current_data_ex(table, &pos);
+      upb_msgval val;
+
+      if (!zv) return arr;
+
+      if (!Convert_PhpToUpbAutoWrap(zv, &val, type, arena)) {
+        return NULL;
+      }
+
+      upb_array_append(arr, val, arena);
+      zend_hash_move_forward_ex(table, &pos);
+    }
+  } else if (Z_TYPE_P(val) == IS_OBJECT &&
+             Z_OBJCE_P(val) == RepeatedField_class_entry) {
+    // Unwrap existing RepeatedField object to get the upb_array* inside.
+    RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val);
+
+    if (!TypeInfo_Eq(intern->type, type)) {
+      php_error_docref(NULL, E_USER_ERROR,
+                       "Wrong type for this repeated field.");
+    }
+
+    upb_arena_fuse(arena, Arena_Get(&intern->arena));
+    return intern->array;
+  } else {
+    php_error_docref(NULL, E_USER_ERROR, "Must be a repeated field");
+    return NULL;
+  }
+}
+
+bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type) {
+  size_t i;
+  size_t n;
+
+  if ((a1 == NULL) != (a2 == NULL)) return false;
+  if (a1 == NULL) return true;
+
+  n = upb_array_size(a1);
+  if (n != upb_array_size(a2)) return false;
+
+  for (i = 0; i < n; i++) {
+    upb_msgval val1 = upb_array_get(a1, i);
+    upb_msgval val2 = upb_array_get(a2, i);
+    if (!ValueEq(val1, val2, type)) return false;
+  }
+
+  return true;
+}
+
+
+// RepeatedField PHP methods ///////////////////////////////////////////////////
+
+/**
+ * RepeatedField::__construct()
+ *
+ * Constructs an instance of RepeatedField.
+ * @param long Type of the stored element.
+ * @param string Message/Enum class.
+ */
+PHP_METHOD(RepeatedField, __construct) {
+  RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  zend_long type;
+  zend_class_entry* klass = NULL;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|C", &type, &klass) != SUCCESS) {
+    return;
+  }
+
+  intern->type.type = pbphp_dtype_to_type(type);
+  intern->type.desc = Descriptor_GetFromClassEntry(klass);
+
+  if (intern->type.type == UPB_TYPE_MESSAGE && klass == NULL) {
+    php_error_docref(NULL, E_USER_ERROR,
+                     "Message/enum type must have concrete class.");
+    return;
+  }
+
+  intern->array = upb_array_new(arena, intern->type.type);
+  ObjCache_Add(intern->array, &intern->std);
+}
+
+/**
+ * RepeatedField::append()
+ *
+ * Append element to the end of the repeated field.
+ * @param object The element to be added.
+ */
+PHP_METHOD(RepeatedField, append) {
+  RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  zval *php_val;
+  upb_msgval msgval;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS ||
+      !Convert_PhpToUpb(php_val, &msgval, intern->type, arena)) {
+    return;
+  }
+
+  upb_array_append(intern->array, msgval, arena);
+}
+
+/**
+ * RepeatedField::offsetExists()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   isset($arr[$idx]);
+ *   empty($arr[$idx]);
+ *
+ * @param long The index to be checked.
+ * @return bool True if the element at the given index exists.
+ */
+PHP_METHOD(RepeatedField, offsetExists) {
+  RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+  zend_long index;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
+    return;
+  }
+
+  RETURN_BOOL(index >= 0 && index < upb_array_size(intern->array));
+}
+
+/**
+ * RepeatedField::offsetGet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   $x = $arr[$idx];
+ *
+ * @param long The index of the element to be fetched.
+ * @return object The stored element at given index.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ */
+PHP_METHOD(RepeatedField, offsetGet) {
+  RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+  zend_long index;
+  upb_msgval msgval;
+  zval ret;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
+    return;
+  }
+
+  if (index < 0 || index >= upb_array_size(intern->array)) {
+    zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
+    return;
+  }
+
+  msgval = upb_array_get(intern->array, index);
+  Convert_UpbToPhp(msgval, &ret, intern->type, &intern->arena);
+  RETURN_COPY_VALUE(&ret);
+}
+
+/**
+ * RepeatedField::offsetSet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   $arr[$idx] = $x;
+ *   $arr []= $x;  // Append
+ *
+ * @param long The index of the element to be assigned.
+ * @param object The element to be assigned.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ * @exception Incorrect type of the element.
+ */
+PHP_METHOD(RepeatedField, offsetSet) {
+  RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  size_t size = upb_array_size(intern->array);
+  zval *offset, *val;
+  int64_t index;
+  upb_msgval msgval;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &offset, &val) != SUCCESS) {
+    return;
+  }
+
+  if (Z_TYPE_P(offset) == IS_NULL) {
+    index = size;
+  } else if (!Convert_PhpToInt64(offset, &index)) {
+    return;
+  }
+
+  if (!Convert_PhpToUpb(val, &msgval, intern->type, arena)) {
+    return;
+  }
+
+  if (index > size) {
+    zend_error(E_USER_ERROR, "Element at index %ld doesn't exist.\n", index);
+  } else if (index == size) {
+    upb_array_append(intern->array, msgval, Arena_Get(&intern->arena));
+  } else {
+    upb_array_set(intern->array, index, msgval);
+  }
+}
+
+/**
+ * RepeatedField::offsetUnset()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   unset($arr[$idx]);
+ *
+ * @param long The index of the element to be removed.
+ * @exception Invalid type for index.
+ * @exception The element to be removed is not at the end of the RepeatedField.
+ */
+PHP_METHOD(RepeatedField, offsetUnset) {
+  RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+  zend_long index;
+  zend_long size = upb_array_size(intern->array);
+
+  // Only the element at the end of the array can be removed.
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) != SUCCESS) {
+    return;
+  }
+
+  if (size == 0 || index != size - 1) {
+    php_error_docref(NULL, E_USER_ERROR, "Cannot remove element at %ld.\n",
+                     index);
+    return;
+  }
+
+  upb_array_resize(intern->array, size - 1, Arena_Get(&intern->arena));
+}
+
+/**
+ * RepeatedField::count()
+ *
+ * Implements the Countable interface. Invoked when PHP code calls:
+ *
+ *   $len = count($arr);
+ * Return the number of stored elements.
+ * This will also be called for: count($arr)
+ * @return long The number of stored elements.
+ */
+PHP_METHOD(RepeatedField, count) {
+  RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+
+  if (zend_parse_parameters_none() == FAILURE) {
+    return;
+  }
+
+  RETURN_LONG(upb_array_size(intern->array));
+}
+
+/**
+ * RepeatedField::getIterator()
+ *
+ * Implements the IteratorAggregate interface. Invoked when PHP code calls:
+ *
+ *   foreach ($arr) {}
+ *
+ * @return object Beginning iterator.
+ */
+PHP_METHOD(RepeatedField, getIterator) {
+  zval ret;
+  RepeatedFieldIter_make(&ret, getThis());
+  RETURN_COPY_VALUE(&ret);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
+  ZEND_ARG_INFO(0, type)
+  ZEND_ARG_INFO(0, class)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 1)
+  ZEND_ARG_INFO(0, newval)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
   ZEND_ARG_INFO(0, index)
 ZEND_END_ARG_INFO()
@@ -43,12 +468,9 @@
   ZEND_ARG_INFO(0, newval)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
-ZEND_END_ARG_INFO()
-
 static zend_function_entry repeated_field_methods[] = {
-  PHP_ME(RepeatedField, __construct,  NULL,              ZEND_ACC_PUBLIC)
-  PHP_ME(RepeatedField, append,       NULL,              ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedField, __construct,  arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedField, append,       arginfo_append,    ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, offsetGet,    arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, offsetSet,    arginfo_offsetSet, ZEND_ACC_PUBLIC)
@@ -58,6 +480,139 @@
   ZEND_FE_END
 };
 
+// -----------------------------------------------------------------------------
+// PHP RepeatedFieldIter
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  zend_object std;
+  zval repeated_field;
+  zend_long position;
+} RepeatedFieldIter;
+
+zend_class_entry *RepeatedFieldIter_class_entry;
+static zend_object_handlers repeated_field_iter_object_handlers;
+
+/**
+ * RepeatedFieldIter_create()
+ *
+ * PHP class entry function to allocate and initialize a new RepeatedFieldIter
+ * object.
+ */
+zend_object* RepeatedFieldIter_create(zend_class_entry *class_type) {
+  RepeatedFieldIter *intern = emalloc(sizeof(RepeatedFieldIter));
+  zend_object_std_init(&intern->std, class_type);
+  intern->std.handlers = &repeated_field_iter_object_handlers;
+  ZVAL_NULL(&intern->repeated_field);
+  intern->position = 0;
+  // Skip object_properties_init(), we don't allow derived classes.
+  return &intern->std;
+}
+
+/**
+ * RepeatedFieldIter_dtor()
+ *
+ * Object handler to destroy a RepeatedFieldIter. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void RepeatedFieldIter_dtor(zend_object* obj) {
+  RepeatedFieldIter* intern = (RepeatedFieldIter*)obj;
+  zval_ptr_dtor(&intern->repeated_field);
+  zend_object_std_dtor(&intern->std);
+}
+
+/**
+ * RepeatedFieldIter_make()
+ *
+ * C function to create a RepeatedFieldIter.
+ */
+static void RepeatedFieldIter_make(zval *val, zval *repeated_field) {
+  RepeatedFieldIter *iter;
+  ZVAL_OBJ(val, RepeatedFieldIter_class_entry->create_object(
+                    RepeatedFieldIter_class_entry));
+  iter = (RepeatedFieldIter*)Z_OBJ_P(val);
+  ZVAL_COPY(&iter->repeated_field, repeated_field);
+}
+
+/*
+ * When a user writes:
+ *
+ *   foreach($arr as $key => $val) {}
+ *
+ * PHP's iterator protocol is:
+ *
+ *   $iter = $arr->getIterator();
+ *   for ($iter->rewind(); $iter->valid(); $iter->next()) {
+ *     $key = $iter->key();
+ *     $val = $iter->current();
+ *   }
+ */
+
+/**
+ * RepeatedFieldIter::rewind()
+ *
+ * Implements the Iterator interface. Sets the iterator to the first element.
+ */
+PHP_METHOD(RepeatedFieldIter, rewind) {
+  RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
+  intern->position = 0;
+}
+
+/**
+ * RepeatedFieldIter::current()
+ *
+ * Implements the Iterator interface. Returns the current value.
+ */
+PHP_METHOD(RepeatedFieldIter, current) {
+  RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
+  RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
+  upb_array *array = field->array;
+  zend_long index = intern->position;
+  upb_msgval msgval;
+  zval ret;
+
+  if (index < 0 || index >= upb_array_size(array)) {
+    zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
+  }
+
+  msgval = upb_array_get(array, index);
+
+  Convert_UpbToPhp(msgval, &ret, field->type, &field->arena);
+  RETURN_COPY_VALUE(&ret);
+}
+
+/**
+ * RepeatedFieldIter::key()
+ *
+ * Implements the Iterator interface. Returns the current key.
+ */
+PHP_METHOD(RepeatedFieldIter, key) {
+  RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
+  RETURN_LONG(intern->position);
+}
+
+/**
+ * RepeatedFieldIter::next()
+ *
+ * Implements the Iterator interface. Advances to the next element.
+ */
+PHP_METHOD(RepeatedFieldIter, next) {
+  RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
+  ++intern->position;
+}
+
+/**
+ * RepeatedFieldIter::valid()
+ *
+ * Implements the Iterator interface. Returns true if this is a valid element.
+ */
+PHP_METHOD(RepeatedFieldIter, valid) {
+  RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
+  RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
+  RETURN_BOOL(intern->position < upb_array_size(field->array));
+}
+
 static zend_function_entry repeated_field_iter_methods[] = {
   PHP_ME(RepeatedFieldIter, rewind,      arginfo_void, ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedFieldIter, current,     arginfo_void, ZEND_ACC_PUBLIC)
@@ -67,491 +622,51 @@
   ZEND_FE_END
 };
 
-// Forward declare static functions.
+// -----------------------------------------------------------------------------
+// Module init.
+// -----------------------------------------------------------------------------
 
-static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
-                                     uint size ZEND_FILE_LINE_DC);
-static void repeated_field_write_dimension(zval *object, zval *offset,
-                                           zval *value TSRMLS_DC);
-static HashTable *repeated_field_get_gc(zval *object, CACHED_VALUE **table,
-                                        int *n TSRMLS_DC);
-#if PHP_MAJOR_VERSION < 7
-static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC);
-static zend_object_value repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
+/**
+ * Array_ModuleInit()
+ *
+ * Called when the C extension is loaded to register all types.
+ */
+void Array_ModuleInit() {
+  zend_class_entry tmp_ce;
+  zend_object_handlers *h;
+
+  // RepeatedField.
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedField",
+                   repeated_field_methods);
+
+  RepeatedField_class_entry = zend_register_internal_class(&tmp_ce);
+  zend_class_implements(RepeatedField_class_entry, 3, spl_ce_ArrayAccess,
+                        zend_ce_aggregate, spl_ce_Countable);
+  RepeatedField_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  RepeatedField_class_entry->create_object = RepeatedField_create;
+
+  h = &RepeatedField_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = RepeatedField_destructor;
+#if PHP_VERSION_ID < 80000
+  h->compare_objects = RepeatedField_compare_objects;
 #else
-static zend_object *repeated_field_create(zend_class_entry *ce TSRMLS_DC);
-static zend_object *repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
+  h->compare = RepeatedField_compare_objects;
 #endif
+  h->clone_obj = RepeatedField_clone_obj;
+  h->get_properties = RepeatedField_GetProperties;
+  h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr;
 
-// -----------------------------------------------------------------------------
-// RepeatedField creation/destruction
-// -----------------------------------------------------------------------------
+  // RepeatedFieldIter
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedFieldIter",
+                   repeated_field_iter_methods);
 
-zend_class_entry* repeated_field_type;
-zend_class_entry* repeated_field_iter_type;
-zend_object_handlers* repeated_field_handlers;
-zend_object_handlers* repeated_field_iter_handlers;
+  RepeatedFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
+  zend_class_implements(RepeatedFieldIter_class_entry, 1, zend_ce_iterator);
+  RepeatedFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  RepeatedFieldIter_class_entry->create_object = RepeatedFieldIter_create;
 
-// Define object free method.
-PHP_PROTO_OBJECT_FREE_START(RepeatedField, repeated_field)
-#if PHP_MAJOR_VERSION < 7
-php_proto_zval_ptr_dtor(intern->array);
-#else
-php_proto_zval_ptr_dtor(&intern->array);
-#endif
-PHP_PROTO_OBJECT_FREE_END
-
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(RepeatedField, repeated_field)
-PHP_PROTO_OBJECT_DTOR_END
-
-// Define object create method.
-PHP_PROTO_OBJECT_CREATE_START(RepeatedField, repeated_field)
-#if PHP_MAJOR_VERSION < 7
-intern->array = NULL;
-#endif
-intern->type = 0;
-intern->msg_ce = NULL;
-PHP_PROTO_OBJECT_CREATE_END(RepeatedField, repeated_field)
-
-// Init class entry.
-PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedField",
-                           RepeatedField, repeated_field)
-zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
-                      zend_ce_aggregate, spl_ce_Countable);
-repeated_field_handlers->write_dimension = repeated_field_write_dimension;
-repeated_field_handlers->get_gc = repeated_field_get_gc;
-PHP_PROTO_INIT_CLASS_END
-
-// Define array element free function.
-#if PHP_MAJOR_VERSION < 7
-static inline void php_proto_array_string_release(void *value) {
-  zval_ptr_dtor(value);
-}
-
-static inline void php_proto_array_object_release(void *value) {
-  zval_ptr_dtor(value);
-}
-static inline void php_proto_array_default_release(void *value) {
-}
-#else
-static inline void php_proto_array_string_release(zval *value) {
-  void* ptr = Z_PTR_P(value);
-  zend_string* object = *(zend_string**)ptr;
-  zend_string_release(object);
-  efree(ptr);
-}
-static inline void php_proto_array_object_release(zval *value) {
-  zval_ptr_dtor(value);
-}
-static void php_proto_array_default_release(zval* value) {
-  void* ptr = Z_PTR_P(value);
-  efree(ptr);
-}
-#endif
-
-static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
-                                     uint size ZEND_FILE_LINE_DC) {
-  PHP_PROTO_ALLOC_ARRAY(array);
-
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      zend_hash_init(Z_ARRVAL_P(array), size, NULL,
-                     php_proto_array_string_release, 0);
-      break;
-    case UPB_TYPE_MESSAGE:
-      zend_hash_init(Z_ARRVAL_P(array), size, NULL,
-                     php_proto_array_object_release, 0);
-      break;
-    default:
-      zend_hash_init(Z_ARRVAL_P(array), size, NULL,
-                     php_proto_array_default_release, 0);
-  }
-  return SUCCESS;
-}
-
-// -----------------------------------------------------------------------------
-// RepeatedField Handlers
-// -----------------------------------------------------------------------------
-
-static void repeated_field_write_dimension(zval *object, zval *offset,
-                                           zval *value TSRMLS_DC) {
-  uint64_t index;
-
-  RepeatedField *intern = UNBOX(RepeatedField, object);
-  HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
-  int size = native_slot_size(intern->type);
-
-  unsigned char memory[NATIVE_SLOT_MAX_SIZE];
-  memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
-
-  if (!native_slot_set_by_array(intern->type, intern->msg_ce, memory,
-                                value TSRMLS_CC)) {
-    return;
-  }
-
-  if (!offset || Z_TYPE_P(offset) == IS_NULL) {
-    index = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array));
-  } else {
-    if (protobuf_convert_to_uint64(offset, &index)) {
-      if (!zend_hash_index_exists(ht, index)) {
-        zend_error(E_USER_ERROR, "Element at %llu doesn't exist.\n",
-                   (long long unsigned int)index);
-        return;
-      }
-    } else {
-      return;
-    }
-  }
-
-  if (intern->type == UPB_TYPE_MESSAGE) {
-    php_proto_zend_hash_index_update_zval(ht, index, *(zval**)memory);
-  } else {
-    php_proto_zend_hash_index_update_mem(ht, index, memory, size, NULL);
-  }
-}
-
-#if PHP_MAJOR_VERSION < 7
-static HashTable *repeated_field_get_gc(zval *object, zval ***table,
-                                        int *n TSRMLS_DC) {
-#else
-static HashTable *repeated_field_get_gc(zval *object, zval **table, int *n) {
-#endif
-  *table = NULL;
-  *n = 0;
-  RepeatedField *intern = UNBOX(RepeatedField, object);
-  return PHP_PROTO_HASH_OF(intern->array);
-}
-
-// -----------------------------------------------------------------------------
-// C RepeatedField Utilities
-// -----------------------------------------------------------------------------
-
-void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) {
-  HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
-  void *value;
-
-  if (intern->type == UPB_TYPE_MESSAGE) {
-    if (php_proto_zend_hash_index_find_zval(ht, index, (void **)&value) ==
-        FAILURE) {
-      zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
-      return NULL;
-    }
-  } else {
-    if (php_proto_zend_hash_index_find_mem(ht, index, (void **)&value) ==
-        FAILURE) {
-      zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
-      return NULL;
-    }
-  }
-
-  return value;
-}
-
-void repeated_field_push_native(RepeatedField *intern, void *value) {
-  HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
-  int size = native_slot_size(intern->type);
-  if (intern->type == UPB_TYPE_MESSAGE) {
-    php_proto_zend_hash_next_index_insert_zval(ht, value);
-  } else {
-    php_proto_zend_hash_next_index_insert_mem(ht, (void **)value, size, NULL);
-  }
-}
-
-void repeated_field_ensure_created(
-    const upb_fielddef *field,
-    CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
-  if (ZVAL_IS_NULL(CACHED_PTR_TO_ZVAL_PTR(repeated_field))) {
-    zval_ptr_dtor(repeated_field);
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(CACHED_PTR_TO_ZVAL_PTR(repeated_field));
-#endif
-    repeated_field_create_with_field(repeated_field_type, field,
-                                     repeated_field PHP_PROTO_TSRMLS_CC);
-  }
-}
-
-void repeated_field_create_with_field(
-    zend_class_entry *ce, const upb_fielddef *field,
-    CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
-  upb_fieldtype_t type = upb_fielddef_type(field);
-  const zend_class_entry *msg_ce = field_type_class(field PHP_PROTO_TSRMLS_CC);
-  repeated_field_create_with_type(ce, type, msg_ce,
-                                  repeated_field PHP_PROTO_TSRMLS_CC);
-}
-
-void repeated_field_create_with_type(
-    zend_class_entry *ce, upb_fieldtype_t type, const zend_class_entry *msg_ce,
-    CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
-  CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(CACHED_PTR_TO_ZVAL_PTR(repeated_field),
-                                   repeated_field_type);
-
-  RepeatedField *intern =
-      UNBOX(RepeatedField, CACHED_TO_ZVAL_PTR(*repeated_field));
-  intern->type = type;
-  intern->msg_ce = msg_ce;
-#if PHP_MAJOR_VERSION < 7
-  MAKE_STD_ZVAL(intern->array);
-  repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
-#else
-  repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
-#endif
-
-  // TODO(teboring): Link class entry for message and enum
-}
-
-
-// -----------------------------------------------------------------------------
-// PHP RepeatedField Methods
-// -----------------------------------------------------------------------------
-
-/**
- * Constructs an instance of RepeatedField.
- * @param long Type of the stored element.
- * @param string Message/Enum class name (message/enum fields only).
- */
-PHP_METHOD(RepeatedField, __construct) {
-  long type;
-  zend_class_entry* klass = NULL;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|C", &type, &klass) ==
-      FAILURE) {
-    return;
-  }
-
-  RepeatedField *intern = UNBOX(RepeatedField, getThis());
-  intern->type = to_fieldtype(type);
-  intern->msg_ce = klass;
-
-#if PHP_MAJOR_VERSION < 7
-  MAKE_STD_ZVAL(intern->array);
-  repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
-#else
-  repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
-#endif
-
-  if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) {
-    zend_error(E_USER_ERROR, "Message type must have concrete class.");
-    return;
-  }
-
-  // TODO(teboring): Consider enum.
-}
-
-/**
- * Append element to the end of the repeated field.
- * @param object The element to be added.
- */
-PHP_METHOD(RepeatedField, append) {
-  zval *value;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) ==
-      FAILURE) {
-    return;
-  }
-  repeated_field_write_dimension(getThis(), NULL, value TSRMLS_CC);
-}
-
-/**
- * Check whether the element at given index exists.
- * @param long The index to be checked.
- * @return bool True if the element at the given index exists.
- */
-PHP_METHOD(RepeatedField, offsetExists) {
-  long index;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
-    return;
-  }
-
-  RepeatedField *intern = UNBOX(RepeatedField, getThis());
-
-  RETURN_BOOL(index >= 0 &&
-              index < zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)));
-}
-
-/**
- * Return the element at the given index.
- * This will also be called for: $ele = $arr[0]
- * @param long The index of the element to be fetched.
- * @return object The stored element at given index.
- * @exception Invalid type for index.
- * @exception Non-existing index.
- */
-PHP_METHOD(RepeatedField, offsetGet) {
-  long index;
-  void *memory;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
-    return;
-  }
-
-  RepeatedField *intern = UNBOX(RepeatedField, getThis());
-  HashTable *table = PHP_PROTO_HASH_OF(intern->array);
-
-  if (intern->type == UPB_TYPE_MESSAGE) {
-    if (php_proto_zend_hash_index_find_zval(table, index, (void **)&memory) ==
-        FAILURE) {
-      zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
-      return;
-    }
-  } else {
-    if (php_proto_zend_hash_index_find_mem(table, index, (void **)&memory) ==
-        FAILURE) {
-      zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
-      return;
-    }
-  }
-  native_slot_get_by_array(intern->type, memory,
-                           ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
-/**
- * Assign the element at the given index.
- * This will also be called for: $arr []= $ele and $arr[0] = ele
- * @param long The index of the element to be assigned.
- * @param object The element to be assigned.
- * @exception Invalid type for index.
- * @exception Non-existing index.
- * @exception Incorrect type of the element.
- */
-PHP_METHOD(RepeatedField, offsetSet) {
-  zval *index, *value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) ==
-      FAILURE) {
-    return;
-  }
-  repeated_field_write_dimension(getThis(), index, value TSRMLS_CC);
-}
-
-/**
- * Remove the element at the given index.
- * This will also be called for: unset($arr)
- * @param long The index of the element to be removed.
- * @exception Invalid type for index.
- * @exception The element to be removed is not at the end of the RepeatedField.
- */
-PHP_METHOD(RepeatedField, offsetUnset) {
-  long index;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
-    return;
-  }
-
-  RepeatedField *intern = UNBOX(RepeatedField, getThis());
-
-  // Only the element at the end of the array can be removed.
-  if (index == -1 ||
-      index != (zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)) - 1)) {
-    zend_error(E_USER_ERROR, "Cannot remove element at %ld.\n", index);
-    return;
-  }
-
-  zend_hash_index_del(PHP_PROTO_HASH_OF(intern->array), index);
-}
-
-/**
- * Return the number of stored elements.
- * This will also be called for: count($arr)
- * @return long The number of stored elements.
- */
-PHP_METHOD(RepeatedField, count) {
-  RepeatedField *intern = UNBOX(RepeatedField, getThis());
-
-  if (zend_parse_parameters_none() == FAILURE) {
-    return;
-  }
-
-  RETURN_LONG(zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)));
-}
-
-/**
- * Return the beginning iterator.
- * This will also be called for: foreach($arr)
- * @return object Beginning iterator.
- */
-PHP_METHOD(RepeatedField, getIterator) {
-  CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value,
-                                   repeated_field_iter_type);
-
-  RepeatedField *intern = UNBOX(RepeatedField, getThis());
-  RepeatedFieldIter *iter = UNBOX(RepeatedFieldIter, return_value);
-  iter->repeated_field = intern;
-  iter->position = 0;
-}
-
-// -----------------------------------------------------------------------------
-// RepeatedFieldIter creation/destruction
-// -----------------------------------------------------------------------------
-
-// Define object free method.
-PHP_PROTO_OBJECT_EMPTY_FREE_START(RepeatedFieldIter, repeated_field_iter)
-PHP_PROTO_OBJECT_FREE_END
-
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(RepeatedFieldIter, repeated_field_iter)
-PHP_PROTO_OBJECT_DTOR_END
-
-// Define object create method.
-PHP_PROTO_OBJECT_CREATE_START(RepeatedFieldIter, repeated_field_iter)
-intern->repeated_field = NULL;
-intern->position = 0;
-PHP_PROTO_OBJECT_CREATE_END(RepeatedFieldIter, repeated_field_iter)
-
-// Init class entry.
-PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedFieldIter",
-                           RepeatedFieldIter, repeated_field_iter)
-zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1, zend_ce_iterator);
-PHP_PROTO_INIT_CLASS_END
-
-// -----------------------------------------------------------------------------
-// PHP RepeatedFieldIter Methods
-// -----------------------------------------------------------------------------
-
-PHP_METHOD(RepeatedFieldIter, rewind) {
-  RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
-  intern->position = 0;
-}
-
-PHP_METHOD(RepeatedFieldIter, current) {
-  RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
-  RepeatedField *repeated_field = intern->repeated_field;
-
-  long index = 0;
-  void *memory;
-
-  HashTable *table = PHP_PROTO_HASH_OF(repeated_field->array);
-
-  if (repeated_field->type == UPB_TYPE_MESSAGE) {
-    if (php_proto_zend_hash_index_find_zval(table, intern->position,
-                                            (void **)&memory) == FAILURE) {
-      zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
-      return;
-    }
-  } else {
-    if (php_proto_zend_hash_index_find_mem(table, intern->position,
-                                           (void **)&memory) == FAILURE) {
-      zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
-      return;
-    }
-  }
-  native_slot_get_by_array(repeated_field->type, memory,
-                           ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
-PHP_METHOD(RepeatedFieldIter, key) {
-  RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
-  RETURN_LONG(intern->position);
-}
-
-PHP_METHOD(RepeatedFieldIter, next) {
-  RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
-  ++intern->position;
-}
-
-PHP_METHOD(RepeatedFieldIter, valid) {
-  RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
-  RETURN_BOOL(zend_hash_num_elements(PHP_PROTO_HASH_OF(
-                  intern->repeated_field->array)) > intern->position);
+  h = &repeated_field_iter_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = RepeatedFieldIter_dtor;
 }
diff --git a/php/ext/google/protobuf/array.h b/php/ext/google/protobuf/array.h
new file mode 100644
index 0000000..031effa
--- /dev/null
+++ b/php/ext/google/protobuf/array.h
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PHP_PROTOBUF_ARRAY_H_
+#define PHP_PROTOBUF_ARRAY_H_
+
+#include <php.h>
+
+#include "def.h"
+#include "php-upb.h"
+
+// Registers PHP classes for RepeatedField.
+void Array_ModuleInit();
+
+// Gets a upb_array* for the PHP object |val|:
+//  * If |val| is a RepeatedField object, we first check its type and verify
+//    that that the elements have the correct type for |type|. If so, we return
+//    the wrapped upb_array*. We also make sure that this array's arena is fused
+//    to |arena|, so the returned upb_array is guaranteed to live as long as
+//    |arena|.
+//  * If |val| is a PHP Array, we attempt to create a new upb_array using
+//    |arena| and add all of the PHP elements to it.
+//
+// If an error occurs, we raise a PHP error and return NULL.
+upb_array *RepeatedField_GetUpbArray(zval *val, TypeInfo type,
+                                     upb_arena *arena);
+
+// Creates a PHP RepeatedField object for the given upb_array* and |type| and
+// returns it in |val|. The PHP object will keep a reference to this |arena| to
+// ensure the underlying array data stays alive.
+//
+// If |arr| is NULL, this will return a PHP null object.
+void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type,
+                                 zval *arena);
+
+// Returns true if the given arrays are equal. Both arrays must be of this
+// |type| and, if the type is |UPB_TYPE_MESSAGE|, must have the same |m|.
+bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type);
+
+#endif  // PHP_PROTOBUF_ARRAY_H_
diff --git a/php/ext/google/protobuf/builtin_descriptors.inc b/php/ext/google/protobuf/builtin_descriptors.inc
deleted file mode 100644
index 1bb5dbf..0000000
--- a/php/ext/google/protobuf/builtin_descriptors.inc
+++ /dev/null
@@ -1,635 +0,0 @@
-unsigned char descriptor_proto[] = {
-  0x0a, 0x9b, 0x3b, 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
-  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73,
-  0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-  0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
-  0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69,
-  0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
-  0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
-  0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-  0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-  0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
-  0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c,
-  0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
-  0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
-  0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
-  0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
-  0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12,
-  0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
-  0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70,
-  0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70,
-  0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
-  0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10,
-  0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
-  0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b,
-  0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18,
-  0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44,
-  0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a,
-  0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70,
-  0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f,
-  0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
-  0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
-  0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61,
-  0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e,
-  0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
-  0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-  0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
-  0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
-  0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70,
-  0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-  0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
-  0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-  0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63,
-  0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52,
-  0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09,
-  0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
-  0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-  0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
-  0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
-  0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65,
-  0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
-  0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-  0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
-  0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
-  0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20,
-  0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-  0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
-  0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
-  0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65,
-  0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74,
-  0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79,
-  0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73,
-  0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
-  0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-  0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05,
-  0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
-  0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
-  0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44,
-  0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
-  0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a,
-  0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06,
-  0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-  0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
-  0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
-  0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74,
-  0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65,
-  0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
-  0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-  0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
-  0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70,
-  0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79,
-  0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67,
-  0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-  0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72,
-  0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08,
-  0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f,
-  0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61,
-  0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
-  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-  0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
-  0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65,
-  0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e,
-  0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e,
-  0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f,
-  0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
-  0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-  0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
-  0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c,
-  0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
-  0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-  0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-  0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
-  0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
-  0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f,
-  0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32,
-  0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
-  0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
-  0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
-  0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
-  0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
-  0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
-  0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28,
-  0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
-  0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e,
-  0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a,
-  0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
-  0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65,
-  0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e,
-  0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
-  0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
-  0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-  0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61,
-  0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07,
-  0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52,
-  0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
-  0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
-  0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
-  0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
-  0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65,
-  0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70,
-  0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
-  0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b,
-  0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
-  0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
-  0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
-  0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
-  0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a,
-  0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98,
-  0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
-  0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-  0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-  0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e,
-  0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
-  0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c,
-  0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b,
-  0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-  0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
-  0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62,
-  0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
-  0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-  0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
-  0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
-  0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65,
-  0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79,
-  0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
-  0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
-  0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18,
-  0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e,
-  0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75,
-  0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
-  0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56,
-  0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f,
-  0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28,
-  0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65,
-  0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61,
-  0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73,
-  0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70,
-  0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32,
-  0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
-  0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
-  0x6f, 0x6e, 0x73, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
-  0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55,
-  0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50,
-  0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a,
-  0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10,
-  0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49,
-  0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
-  0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10,
-  0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44,
-  0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45,
-  0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d,
-  0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10,
-  0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54,
-  0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
-  0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10,
-  0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41,
-  0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
-  0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b,
-  0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10,
-  0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e,
-  0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45,
-  0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12,
-  0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58,
-  0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
-  0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12,
-  0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54,
-  0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65,
-  0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f,
-  0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a,
-  0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49,
-  0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42,
-  0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10,
-  0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
-  0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
-  0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a,
-  0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
-  0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65,
-  0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45,
-  0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
-  0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
-  0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-  0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
-  0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-  0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-  0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73,
-  0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
-  0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
-  0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
-  0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
-  0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72,
-  0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
-  0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-  0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
-  0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
-  0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65,
-  0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
-  0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
-  0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
-  0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
-  0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
-  0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52,
-  0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
-  0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
-  0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
-  0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
-  0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75,
-  0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
-  0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
-  0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-  0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d,
-  0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e,
-  0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
-  0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-  0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
-  0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53,
-  0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
-  0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
-  0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-  0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74,
-  0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
-  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-  0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
-  0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a,
-  0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
-  0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72,
-  0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
-  0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a,
-  0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
-  0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12,
-  0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
-  0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e,
-  0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
-  0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70,
-  0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
-  0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
-  0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38,
-  0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
-  0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-  0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
-  0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
-  0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10,
-  0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
-  0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
-  0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
-  0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30,
-  0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72,
-  0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
-  0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72,
-  0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67,
-  0x22, 0x92, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61,
-  0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
-  0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b,
-  0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f,
-  0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e,
-  0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a,
-  0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73,
-  0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76,
-  0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66,
-  0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
-  0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d,
-  0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73,
-  0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e,
-  0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73,
-  0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20,
-  0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76,
-  0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75,
-  0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a,
-  0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
-  0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38,
-  0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73,
-  0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e,
-  0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53,
-  0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66,
-  0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67,
-  0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-  0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
-  0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d,
-  0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b,
-  0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12,
-  0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
-  0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50,
-  0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63,
-  0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
-  0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a,
-  0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65,
-  0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-  0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65,
-  0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
-  0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
-  0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e,
-  0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
-  0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72,
-  0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18,
-  0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
-  0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53,
-  0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70,
-  0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73,
-  0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28,
-  0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68,
-  0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76,
-  0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
-  0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08,
-  0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
-  0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x10, 0x63,
-  0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65,
-  0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
-  0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62,
-  0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11,
-  0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70,
-  0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
-  0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
-  0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61,
-  0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
-  0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61,
-  0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
-  0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65,
-  0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
-  0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28,
-  0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f,
-  0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09,
-  0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
-  0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f,
-  0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20,
-  0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65,
-  0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70,
-  0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61,
-  0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28,
-  0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
-  0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
-  0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b,
-  0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
-  0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58,
-  0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
-  0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
-  0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-  0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-  0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
-  0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
-  0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
-  0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69,
-  0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05,
-  0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43,
-  0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10,
-  0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49,
-  0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
-  0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02,
-  0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73,
-  0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65,
-  0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
-  0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65,
-  0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65,
-  0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f,
-  0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63,
-  0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
-  0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74,
-  0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
-  0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
-  0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
-  0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
-  0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
-  0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65,
-  0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
-  0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14,
-  0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
-  0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
-  0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-  0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e,
-  0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74,
-  0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
-  0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
-  0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10,
-  0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74,
-  0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e,
-  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-  0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06,
-  0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70,
-  0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18,
-  0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65,
-  0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18,
-  0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-  0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-  0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
-  0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f,
-  0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79,
-  0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05,
-  0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
-  0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70,
-  0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
-  0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65,
-  0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04,
-  0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
-  0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12,
-  0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
-  0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
-  0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
-  0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-  0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
-  0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e,
-  0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79,
-  0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47,
-  0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01,
-  0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50,
-  0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53,
-  0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e,
-  0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
-  0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d,
-  0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10,
-  0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
-  0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e,
-  0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58,
-  0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
-  0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
-  0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-  0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-  0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
-  0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
-  0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
-  0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
-  0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d,
-  0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61,
-  0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02,
-  0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41,
-  0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
-  0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
-  0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
-  0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75,
-  0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
-  0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
-  0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
-  0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
-  0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
-  0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
-  0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
-  0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45,
-  0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69,
-  0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65,
-  0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a,
-  0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72,
-  0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
-  0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
-  0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
-  0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-  0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
-  0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
-  0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
-  0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
-  0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f,
-  0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
-  0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01,
-  0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
-  0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a,
-  0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
-  0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
-  0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-  0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
-  0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
-  0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e,
-  0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80,
-  0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f,
-  0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a,
-  0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21,
-  0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
-  0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
-  0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e,
-  0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01,
-  0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74,
-  0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49,
-  0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65,
-  0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54,
-  0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
-  0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63,
-  0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
-  0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
-  0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
-  0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-  0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
-  0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
-  0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
-  0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
-  0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65,
-  0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13,
-  0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
-  0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a,
-  0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46,
-  0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44,
-  0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09,
-  0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03,
-  0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
-  0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a,
-  0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
-  0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
-  0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65,
-  0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
-  0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04,
-  0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e,
-  0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
-  0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e,
-  0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
-  0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f,
-  0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20,
-  0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76,
-  0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a,
-  0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e,
-  0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
-  0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49,
-  0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64,
-  0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
-  0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c,
-  0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74,
-  0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07,
-  0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
-  0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67,
-  0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
-  0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72,
-  0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a,
-  0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b,
-  0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18,
-  0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50,
-  0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78,
-  0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28,
-  0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
-  0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63,
-  0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a,
-  0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
-  0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-  0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
-  0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
-  0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
-  0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08,
-  0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04,
-  0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
-  0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04,
-  0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
-  0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10,
-  0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
-  0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
-  0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
-  0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c,
-  0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
-  0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69,
-  0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
-  0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f,
-  0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d,
-  0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
-  0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61,
-  0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
-  0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
-  0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d,
-  0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-  0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f,
-  0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-  0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
-  0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
-  0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
-  0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e,
-  0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70,
-  0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10,
-  0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
-  0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02,
-  0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-  0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69,
-  0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67,
-  0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20,
-  0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x8f, 0x01, 0x0a,
-  0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
-  0x6f, 0x73, 0x48, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
-  0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,
-  0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f,
-  0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64,
-  0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x65,
-  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0xf8, 0x01, 0x01, 0xa2,
-  0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67,
-  0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-  0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e
-};
-unsigned int descriptor_proto_len = 7582;
diff --git a/php/ext/google/protobuf/config.m4 b/php/ext/google/protobuf/config.m4
index ab032e4..c09c03a 100644
--- a/php/ext/google/protobuf/config.m4
+++ b/php/ext/google/protobuf/config.m4
@@ -4,7 +4,7 @@
 
   PHP_NEW_EXTENSION(
     protobuf,
-    array.c def.c encode_decode.c map.c message.c protobuf.c storage.c type_check.c upb.c utf8.c,
-    $ext_shared)
+    arena.c array.c convert.c def.c map.c message.c names.c php-upb.c protobuf.c,
+    $ext_shared, , -std=gnu99)
 
 fi
diff --git a/php/ext/google/protobuf/convert.c b/php/ext/google/protobuf/convert.c
new file mode 100644
index 0000000..a1ed2c8
--- /dev/null
+++ b/php/ext/google/protobuf/convert.c
@@ -0,0 +1,517 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "convert.h"
+
+#include <php.h>
+
+// This is not self-contained: it must be after other Zend includes.
+#include <Zend/zend_exceptions.h>
+
+#include "array.h"
+#include "map.h"
+#include "message.h"
+#include "php-upb.h"
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// GPBUtil
+// -----------------------------------------------------------------------------
+
+static zend_class_entry* GPBUtil_class_entry;
+
+// The implementation of type checking for primitive fields is empty. This is
+// because type checking is done when direct assigning message fields (e.g.,
+// foo->a = 1). Functions defined here are place holders in generated code for
+// pure PHP implementation (c extension and pure PHP share the same generated
+// code).
+
+PHP_METHOD(Util, checkInt32) {}
+PHP_METHOD(Util, checkUint32) {}
+PHP_METHOD(Util, checkInt64) {}
+PHP_METHOD(Util, checkUint64) {}
+PHP_METHOD(Util, checkEnum) {}
+PHP_METHOD(Util, checkFloat) {}
+PHP_METHOD(Util, checkDouble) {}
+PHP_METHOD(Util, checkBool) {}
+PHP_METHOD(Util, checkString) {}
+PHP_METHOD(Util, checkBytes) {}
+PHP_METHOD(Util, checkMessage) {}
+
+// The result of checkMapField() is assigned, so we need to return the first
+// param:
+//   $arr = GPBUtil::checkMapField($var,
+//                                 \Google\Protobuf\Internal\GPBType::INT64,
+//                                 \Google\Protobuf\Internal\GPBType::INT32);
+PHP_METHOD(Util, checkMapField) {
+  zval *val, *key_type, *val_type, *klass;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z", &val, &key_type,
+                            &val_type, &klass) == FAILURE) {
+    return;
+  }
+  RETURN_COPY(val);
+}
+
+// The result of checkRepeatedField() is assigned, so we need to return the
+// first param:
+// $arr = GPBUtil::checkRepeatedField(
+//     $var, \Google\Protobuf\Internal\GPBType::STRING);
+PHP_METHOD(Util, checkRepeatedField) {
+  zval *val, *type, *klass;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &val, &type, &klass) ==
+      FAILURE) {
+    return;
+  }
+  RETURN_COPY(val);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkPrimitive, 0, 0, 1)
+  ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkString, 0, 0, 1)
+  ZEND_ARG_INFO(0, value)
+  ZEND_ARG_INFO(0, check_utf8)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMessage, 0, 0, 2)
+  ZEND_ARG_INFO(0, value)
+  ZEND_ARG_INFO(0, class)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMapField, 0, 0, 3)
+  ZEND_ARG_INFO(0, value)
+  ZEND_ARG_INFO(0, key_type)
+  ZEND_ARG_INFO(0, value_type)
+  ZEND_ARG_INFO(0, value_class)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_checkRepeatedField, 0, 0, 2)
+  ZEND_ARG_INFO(0, value)
+  ZEND_ARG_INFO(0, type)
+  ZEND_ARG_INFO(0, class)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry util_methods[] = {
+  PHP_ME(Util, checkInt32,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkUint32, arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkInt64,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkUint64, arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkEnum,   arginfo_checkMessage,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkFloat,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkDouble, arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkBool,   arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkString, arginfo_checkString,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkBytes,  arginfo_checkPrimitive,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkMessage, arginfo_checkMessage,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkMapField, arginfo_checkMapField,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(Util, checkRepeatedField, arginfo_checkRepeatedField,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+// -----------------------------------------------------------------------------
+// Conversion functions used from C
+// -----------------------------------------------------------------------------
+
+upb_fieldtype_t pbphp_dtype_to_type(upb_descriptortype_t type) {
+  switch (type) {
+#define CASE(descriptor_type, type)           \
+  case UPB_DESCRIPTOR_TYPE_##descriptor_type: \
+    return UPB_TYPE_##type;
+
+  CASE(FLOAT,    FLOAT);
+  CASE(DOUBLE,   DOUBLE);
+  CASE(BOOL,     BOOL);
+  CASE(STRING,   STRING);
+  CASE(BYTES,    BYTES);
+  CASE(MESSAGE,  MESSAGE);
+  CASE(GROUP,    MESSAGE);
+  CASE(ENUM,     ENUM);
+  CASE(INT32,    INT32);
+  CASE(INT64,    INT64);
+  CASE(UINT32,   UINT32);
+  CASE(UINT64,   UINT64);
+  CASE(SINT32,   INT32);
+  CASE(SINT64,   INT64);
+  CASE(FIXED32,  UINT32);
+  CASE(FIXED64,  UINT64);
+  CASE(SFIXED32, INT32);
+  CASE(SFIXED64, INT64);
+
+#undef CASE
+
+  }
+
+  zend_error(E_ERROR, "Unknown field type.");
+  return 0;
+}
+
+static bool buftouint64(const char *ptr, const char *end, uint64_t *val) {
+  uint64_t u64 = 0;
+  while (ptr < end) {
+    unsigned ch = (unsigned)(*ptr - '0');
+    if (ch >= 10) break;
+    if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) {
+      return false;
+    }
+    u64 *= 10;
+    u64 += ch;
+    ptr++;
+  }
+
+  if (ptr != end) {
+    // In PHP tradition, we allow truncation: "1.1" -> 1.
+    // But we don't allow 'e', eg. '1.1e2' or any other non-numeric chars.
+    if (*ptr++ != '.') return false;
+
+    for (;ptr < end; ptr++) {
+      if (*ptr < '0' || *ptr > '9') {
+        return false;
+      }
+    }
+  }
+
+  *val = u64;
+  return true;
+}
+
+static bool buftoint64(const char *ptr, const char *end, int64_t *val) {
+  bool neg = false;
+  uint64_t u64;
+
+  if (ptr != end && *ptr == '-') {
+    ptr++;
+    neg = true;
+  }
+
+  if (!buftouint64(ptr, end, &u64) ||
+      u64 > (uint64_t)INT64_MAX + neg) {
+    return false;
+  }
+
+  *val = neg ? -u64 : u64;
+  return true;
+}
+
+static void throw_conversion_exception(const char *to, const zval *zv) {
+  zval tmp;
+  ZVAL_COPY(&tmp, zv);
+  convert_to_string(&tmp);
+
+  zend_throw_exception_ex(NULL, 0, "Cannot convert '%s' to %s",
+                          Z_STRVAL_P(&tmp), to);
+
+  zval_ptr_dtor(&tmp);
+}
+
+bool Convert_PhpToInt64(const zval *php_val, int64_t *i64) {
+  switch (Z_TYPE_P(php_val)) {
+    case IS_LONG:
+      *i64 = Z_LVAL_P(php_val);
+      return true;
+    case IS_DOUBLE: {
+      double dbl = Z_DVAL_P(php_val);
+      if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) {
+        zend_throw_exception_ex(NULL, 0, "Out of range");
+        return false;
+      }
+      *i64 = dbl; /* must be guarded, overflow here is UB */
+      return true;
+    }
+    case IS_STRING: {
+      const char *buf = Z_STRVAL_P(php_val);
+      // PHP would accept scientific notation here, but we're going to be a
+      // little more discerning and only accept pure integers.
+      bool ok = buftoint64(buf, buf + Z_STRLEN_P(php_val), i64);
+      if (!ok) {
+        throw_conversion_exception("integer", php_val);
+      }
+      return ok;
+    }
+    default:
+      throw_conversion_exception("integer", php_val);
+      return false;
+  }
+}
+
+static bool to_double(zval *php_val, double *dbl) {
+  switch (Z_TYPE_P(php_val)) {
+    case IS_LONG:
+      *dbl = Z_LVAL_P(php_val);
+      return true;
+    case IS_DOUBLE:
+      *dbl = Z_DVAL_P(php_val);
+      return true;
+    case IS_STRING: {
+      zend_long lval;
+      switch (is_numeric_string(Z_STRVAL_P(php_val), Z_STRLEN_P(php_val), &lval,
+                                dbl, false)) {
+        case IS_LONG:
+          *dbl = lval;
+          return true;
+        case IS_DOUBLE:
+          return true;
+        default:
+          goto fail;
+      }
+    }
+    default:
+     fail:
+      throw_conversion_exception("double", php_val);
+      return false;
+  }
+}
+
+static bool to_bool(zval* from, bool* to) {
+  switch (Z_TYPE_P(from)) {
+    case IS_TRUE:
+      *to = true;
+      return true;
+    case IS_FALSE:
+      *to = false;
+      return true;
+    case IS_LONG:
+      *to = (Z_LVAL_P(from) != 0);
+      return true;
+    case IS_DOUBLE:
+      *to = (Z_LVAL_P(from) != 0);
+      return true;
+    case IS_STRING:
+      if (Z_STRLEN_P(from) == 0 ||
+          (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) {
+        *to = false;
+      } else {
+        *to = true;
+      }
+      return true;
+    default:
+      throw_conversion_exception("bool", from);
+      return false;
+  }
+}
+
+static bool to_string(zval* from) {
+  if (Z_ISREF_P(from)) {
+    ZVAL_DEREF(from);
+  }
+
+  switch (Z_TYPE_P(from)) {
+    case IS_STRING:
+      return true;
+    case IS_TRUE:
+    case IS_FALSE:
+    case IS_LONG:
+    case IS_DOUBLE: {
+      zval tmp;
+      zend_make_printable_zval(from, &tmp);
+      ZVAL_COPY_VALUE(from, &tmp);
+      return true;
+    }
+    default:
+      throw_conversion_exception("string", from);
+      return false;
+  }
+}
+
+bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type,
+                      upb_arena *arena) {
+  int64_t i64;
+
+  if (Z_ISREF_P(php_val)) {
+    ZVAL_DEREF(php_val);
+  }
+
+  switch (type.type) {
+    case UPB_TYPE_INT64:
+      return Convert_PhpToInt64(php_val, &upb_val->int64_val);
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_ENUM:
+      if (!Convert_PhpToInt64(php_val, &i64)) {
+        return false;
+      }
+      upb_val->int32_val = i64;
+      return true;
+    case UPB_TYPE_UINT64:
+      if (!Convert_PhpToInt64(php_val, &i64)) {
+        return false;
+      }
+      upb_val->uint64_val = i64;
+      return true;
+    case UPB_TYPE_UINT32:
+      if (!Convert_PhpToInt64(php_val, &i64)) {
+        return false;
+      }
+      upb_val->uint32_val = i64;
+      return true;
+    case UPB_TYPE_DOUBLE:
+      return to_double(php_val, &upb_val->double_val);
+    case UPB_TYPE_FLOAT:
+      if (!to_double(php_val, &upb_val->double_val)) return false;
+      upb_val->float_val = upb_val->double_val;
+      return true;
+    case UPB_TYPE_BOOL:
+      return to_bool(php_val, &upb_val->bool_val);
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      char *ptr;
+      size_t size;
+
+      if (!to_string(php_val)) return false;
+
+      size = Z_STRLEN_P(php_val);
+
+      // If arena is NULL we reference the input zval.
+      // The resulting upb_strview will only be value while the zval is alive.
+      if (arena) {
+        ptr = upb_arena_malloc(arena, size);
+        memcpy(ptr, Z_STRVAL_P(php_val), size);
+      } else {
+        ptr = Z_STRVAL_P(php_val);
+      }
+
+      upb_val->str_val = upb_strview_make(ptr, size);
+      return true;
+    }
+    case UPB_TYPE_MESSAGE:
+      PBPHP_ASSERT(type.desc);
+      return Message_GetUpbMessage(php_val, type.desc, arena,
+                                   (upb_msg **)&upb_val->msg_val);
+  }
+
+  return false;
+}
+
+void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type,
+                      zval *arena) {
+  switch (type.type) {
+    case UPB_TYPE_INT64:
+#if SIZEOF_ZEND_LONG == 8
+      ZVAL_LONG(php_val, upb_val.int64_val);
+#else
+      {
+        char buf[20];
+        int size = sprintf(buf, "%lld", upb_val.int64_val);
+        ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0));
+      }
+#endif
+      break;
+    case UPB_TYPE_UINT64:
+#if SIZEOF_ZEND_LONG == 8
+      ZVAL_LONG(php_val, upb_val.uint64_val);
+#else
+      {
+        char buf[20];
+        int size = sprintf(buf, "%lld", (int64_t)upb_val.uint64_val);
+        ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0));
+      }
+#endif
+      break;
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_ENUM:
+      ZVAL_LONG(php_val, upb_val.int32_val);
+      break;
+    case UPB_TYPE_UINT32: {
+      // Sign-extend for consistency between 32/64-bit builds.
+      zend_long val = (int32_t)upb_val.uint32_val;
+      ZVAL_LONG(php_val, val);
+      break;
+    }
+    case UPB_TYPE_DOUBLE:
+      ZVAL_DOUBLE(php_val, upb_val.double_val);
+      break;
+    case UPB_TYPE_FLOAT:
+      ZVAL_DOUBLE(php_val, upb_val.float_val);
+      break;
+    case UPB_TYPE_BOOL:
+      ZVAL_BOOL(php_val, upb_val.bool_val);
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      upb_strview str = upb_val.str_val;
+      ZVAL_NEW_STR(php_val, zend_string_init(str.data, str.size, 0));
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      PBPHP_ASSERT(type.desc);
+      Message_GetPhpWrapper(php_val, type.desc, (upb_msg *)upb_val.msg_val,
+                            arena);
+      break;
+  }
+}
+
+bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type,
+                              upb_arena *arena) {
+  const upb_msgdef *subm = type.desc ? type.desc->msgdef : NULL;
+  if (subm && upb_msgdef_iswrapper(subm) && Z_TYPE_P(val) != IS_OBJECT) {
+    // Assigning a scalar to a wrapper-typed value. We will automatically wrap
+    // the value, so the user doesn't need to create a FooWrapper(['value': X])
+    // message manually.
+    upb_msg *wrapper = upb_msg_new(subm, arena);
+    const upb_fielddef *val_f = upb_msgdef_itof(subm, 1);
+    upb_msgval msgval;
+    if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) return false;
+    upb_msg_set(wrapper, val_f, msgval, arena);
+    upb_val->msg_val = wrapper;
+    return true;
+  } else {
+    // Convert_PhpToUpb doesn't auto-construct messages. This means that we only
+    // allow:
+    //   ['foo_submsg': new Foo(['a' => 1])]
+    // not:
+    //   ['foo_submsg': ['a' => 1]]
+    return Convert_PhpToUpb(val, upb_val, type, arena);
+  }
+}
+
+void Convert_ModuleInit(void) {
+  const char *prefix_name = "TYPE_URL_PREFIX";
+  zend_class_entry class_type;
+
+  INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil",
+                   util_methods);
+  GPBUtil_class_entry = zend_register_internal_class(&class_type);
+
+  zend_declare_class_constant_string(GPBUtil_class_entry, prefix_name,
+                                     strlen(prefix_name),
+                                     "type.googleapis.com/");
+}
diff --git a/php/ext/google/protobuf/convert.h b/php/ext/google/protobuf/convert.h
new file mode 100644
index 0000000..96cfc34
--- /dev/null
+++ b/php/ext/google/protobuf/convert.h
@@ -0,0 +1,73 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PHP_PROTOBUF_CONVERT_H_
+#define PHP_PROTOBUF_CONVERT_H_
+
+#include <php.h>
+
+#include "php-upb.h"
+#include "def.h"
+
+upb_fieldtype_t pbphp_dtype_to_type(upb_descriptortype_t type);
+
+// Converts |php_val| to an int64_t. Returns false if the value cannot be
+// converted.
+bool Convert_PhpToInt64(const zval *php_val, int64_t *i64);
+
+// Converts |php_val| to a upb_msgval according to |type|. If type is
+// UPB_TYPE_MESSAGE, then |desc| must be the Descriptor for this message type.
+// If type is string, message, or bytes, then |arena| will be used to copy
+// string data or fuse this arena to the given message's arena.
+bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type,
+                      upb_arena *arena);
+
+// Similar to Convert_PhpToUpb, but supports automatically wrapping the wrapper
+// types if a primitive is specified:
+//
+//   5 -> Int64Wrapper(value=5)
+//
+// We currently allow this implicit conversion in initializers, but not for
+// assignment.
+bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type,
+                              upb_arena *arena);
+
+// Converts |upb_val| to a PHP zval according to |type|. This may involve
+// creating a PHP wrapper object. Any newly created wrapper object
+// will reference |arena|.
+//
+// The caller owns a reference to the returned value.
+void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type,
+                      zval *arena);
+
+// Registers the GPBUtil class.
+void Convert_ModuleInit(void);
+
+#endif  // PHP_PROTOBUF_CONVERT_H_
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index 5edcb03..88c201f 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -28,246 +28,171 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "def.h"
+
 #include <php.h>
+
+// This is not self-contained: it must be after other Zend includes.
 #include <Zend/zend_exceptions.h>
 
+#include "names.h"
+#include "php-upb.h"
 #include "protobuf.h"
-#include "builtin_descriptors.inc"
 
-// Forward declare.
-static void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC);
-static void descriptor_free_c(Descriptor* object TSRMLS_DC);
-
-static void field_descriptor_init_c_instance(FieldDescriptor* intern TSRMLS_DC);
-static void field_descriptor_free_c(FieldDescriptor* object TSRMLS_DC);
-
-static void enum_descriptor_init_c_instance(EnumDescriptor* intern TSRMLS_DC);
-static void enum_descriptor_free_c(EnumDescriptor* object TSRMLS_DC);
-
-static void enum_value_descriptor_init_c_instance(
-    EnumValueDescriptor *intern TSRMLS_DC);
-static void enum_value_descriptor_free_c(EnumValueDescriptor *object TSRMLS_DC);
-
-static void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC);
-static void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC);
-
-static void internal_descriptor_pool_free_c(
-    InternalDescriptorPool *object TSRMLS_DC);
-static void internal_descriptor_pool_init_c_instance(
-    InternalDescriptorPool *pool TSRMLS_DC);
-
-static void oneof_descriptor_free_c(Oneof* object TSRMLS_DC);
-static void oneof_descriptor_init_c_instance(Oneof* pool TSRMLS_DC);
-
-// -----------------------------------------------------------------------------
-// Common Utilities
-// -----------------------------------------------------------------------------
-
-static void check_upb_status(const upb_status* status, const char* msg) {
+static void CheckUpbStatus(const upb_status* status, const char* msg) {
   if (!upb_ok(status)) {
     zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status));
   }
 }
 
+static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f);
+
+// We use this for objects that should not be created directly from PHP.
+static zend_object *CreateHandler_ReturnNull(zend_class_entry *class_type) {
+  return NULL;  // Nobody should call this.
+}
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getByIndex, 0, 0, 1)
+  ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
 // -----------------------------------------------------------------------------
-// GPBType
+// EnumValueDescriptor
 // -----------------------------------------------------------------------------
 
-zend_class_entry* gpb_type_type;
+typedef struct {
+  zend_object std;
+  const char *name;
+  int32_t number;
+} EnumValueDescriptor;
 
-static zend_function_entry gpb_type_methods[] = {
+zend_class_entry *EnumValueDescriptor_class_entry;
+static zend_object_handlers EnumValueDescriptor_object_handlers;
+
+/*
+ * EnumValueDescriptor_Make()
+ *
+ * Function to create an EnumValueDescriptor object from C.
+ */
+static void EnumValueDescriptor_Make(zval *val, const char *name,
+                                     int32_t number) {
+  EnumValueDescriptor *intern = emalloc(sizeof(EnumValueDescriptor));
+  zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry);
+  intern->std.handlers = &EnumValueDescriptor_object_handlers;
+  intern->name = name;
+  intern->number = number;
+  // Skip object_properties_init(), we don't allow derived classes.
+  ZVAL_OBJ(val, &intern->std);
+}
+
+/*
+ * EnumValueDescriptor::getName()
+ *
+ * Returns the name for this enum value.
+ */
+PHP_METHOD(EnumValueDescriptor, getName) {
+  EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
+  RETURN_STRING(intern->name);
+}
+
+/*
+ * EnumValueDescriptor::getNumber()
+ *
+ * Returns the number for this enum value.
+ */
+PHP_METHOD(EnumValueDescriptor, getNumber) {
+  EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
+  RETURN_LONG(intern->number);
+}
+
+static zend_function_entry EnumValueDescriptor_methods[] = {
+  PHP_ME(EnumValueDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(EnumValueDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
-void gpb_type_init(TSRMLS_D) {
-  zend_class_entry class_type;
-  INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
-                   gpb_type_methods);
-  gpb_type_type = zend_register_internal_class(&class_type TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"),  1 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"),   2 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("INT64"),   3 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("UINT64"),  4 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("INT32"),   5 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("BOOL"),    8 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("STRING"),  9 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("GROUP"),   10 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("BYTES"),   12 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("UINT32"),  13 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("ENUM"),    14 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"),
-                                   15 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"),
-                                   16 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17 TSRMLS_CC);
-  zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18 TSRMLS_CC);
-}
-
-// -----------------------------------------------------------------------------
-// Descriptor
-// -----------------------------------------------------------------------------
-
-static zend_function_entry descriptor_methods[] = {
-  PHP_ME(Descriptor, getClass, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC)
-  ZEND_FE_END
-};
-
-DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor");
-
-static void descriptor_free_c(Descriptor *self TSRMLS_DC) {
-}
-
-static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) {
-  desc->intern = NULL;
-}
-
-PHP_METHOD(Descriptor, getClass) {
-  Descriptor* desc = UNBOX(Descriptor, getThis());
-  DescriptorInternal* intern = desc->intern;
-  register_class(intern, false TSRMLS_CC);
-#if PHP_MAJOR_VERSION < 7
-  const char* classname = intern->klass->name;
-#else
-  const char* classname = ZSTR_VAL(intern->klass->name);
-#endif
-  PHP_PROTO_RETVAL_STRINGL(classname, strlen(classname), 1);
-}
-
-PHP_METHOD(Descriptor, getFullName) {
-  Descriptor* desc = UNBOX(Descriptor, getThis());
-  DescriptorInternal* intern = desc->intern;
-  const char* fullname = upb_msgdef_fullname(intern->msgdef);
-  PHP_PROTO_RETVAL_STRINGL(fullname, strlen(fullname), 1);
-}
-
-PHP_METHOD(Descriptor, getField) {
-  long index;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
-    zend_error(E_USER_ERROR, "Expect integer for index.\n");
-    return;
-  }
-
-  Descriptor* desc = UNBOX(Descriptor, getThis());
-  DescriptorInternal* intern = desc->intern;
-  int field_num = upb_msgdef_numfields(intern->msgdef);
-  if (index < 0 || index >= field_num) {
-    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
-    return;
-  }
-
-  upb_msg_field_iter iter;
-  int i;
-  for(upb_msg_field_begin(&iter, intern->msgdef), i = 0;
-      !upb_msg_field_done(&iter) && i < index;
-      upb_msg_field_next(&iter), i++);
-  const upb_fielddef *field = upb_msg_iter_field(&iter);
-
-  PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field);
-  if (field_hashtable_value == NULL) {
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(field_hashtable_value);
-    ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
-                                        field_descriptor_type TSRMLS_CC));
-    Z_DELREF_P(field_hashtable_value);
-#else
-    field_hashtable_value =
-        field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
-    GC_DELREF(field_hashtable_value);
-#endif
-    FieldDescriptor *field_php =
-        UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
-    field_php->fielddef = field;
-    add_def_obj(field, field_hashtable_value);
-  }
-
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(field_hashtable_value, 1, 0);
-#else
-  GC_ADDREF(field_hashtable_value);
-  RETURN_OBJ(field_hashtable_value);
-#endif
-}
-
-PHP_METHOD(Descriptor, getFieldCount) {
-  Descriptor* desc = UNBOX(Descriptor, getThis());
-  DescriptorInternal* intern = desc->intern;
-  RETURN_LONG(upb_msgdef_numfields(intern->msgdef));
-}
-
-PHP_METHOD(Descriptor, getOneofDecl) {
-  long index;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
-    zend_error(E_USER_ERROR, "Expect integer for index.\n");
-    return;
-  }
-
-  Descriptor* desc = UNBOX(Descriptor, getThis());
-  DescriptorInternal* intern = desc->intern;
-  int field_num = upb_msgdef_numoneofs(intern->msgdef);
-  if (index < 0 || index >= field_num) {
-    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
-    return;
-  }
-
-  upb_msg_oneof_iter iter;
-  int i;
-  for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0;
-      !upb_msg_oneof_done(&iter) && i < index;
-      upb_msg_oneof_next(&iter), i++);
-  const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter);
-
-  ZVAL_OBJ(return_value, oneof_descriptor_type->create_object(
-                             oneof_descriptor_type TSRMLS_CC));
-  Oneof *oneof_php = UNBOX(Oneof, return_value);
-  oneof_php->oneofdef = oneof;
-}
-
-PHP_METHOD(Descriptor, getOneofDeclCount) {
-  Descriptor* desc = UNBOX(Descriptor, getThis());
-  DescriptorInternal* intern = desc->intern;
-  RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));
-}
-
 // -----------------------------------------------------------------------------
 // EnumDescriptor
 // -----------------------------------------------------------------------------
 
-static zend_function_entry enum_descriptor_methods[] = {
-  PHP_ME(EnumDescriptor, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumDescriptor, getValueCount, NULL, ZEND_ACC_PUBLIC)
-  ZEND_FE_END
-};
+typedef struct {
+  zend_object std;
+  const upb_enumdef *enumdef;
+  void *cache_key;
+} EnumDescriptor;
 
-DEFINE_CLASS(EnumDescriptor, enum_descriptor,
-             "Google\\Protobuf\\EnumDescriptor");
+zend_class_entry *EnumDescriptor_class_entry;
+static zend_object_handlers EnumDescriptor_object_handlers;
 
-static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) {
+static void EnumDescriptor_destructor(zend_object* obj) {
+  EnumDescriptor *intern = (EnumDescriptor*)obj;
+  ObjCache_Delete(intern->cache_key);
 }
 
-static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) {
-  self->intern = NULL;
+// Caller owns a ref on the returned zval.
+static void EnumDescriptor_FromClassEntry(zval *val, zend_class_entry *ce) {
+  // To differentiate enums from classes, we pointer-tag the class entry.
+  void* key = (void*)((uintptr_t)ce | 1);
+  PBPHP_ASSERT(key != ce);
+
+  if (ce == NULL) {
+    ZVAL_NULL(val);
+    return;
+  }
+
+  if (!ObjCache_Get(key, val)) {
+    const upb_enumdef *e = NameMap_GetEnum(ce);
+    if (!e) {
+      ZVAL_NULL(val);
+      return;
+    }
+    EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor));
+    zend_object_std_init(&ret->std, EnumDescriptor_class_entry);
+    ret->std.handlers = &EnumDescriptor_object_handlers;
+    ret->enumdef = e;
+    ret->cache_key = key;
+    ObjCache_Add(key, &ret->std);
+    ZVAL_OBJ(val, &ret->std);
+  }
 }
 
+// Caller owns a ref on the returned zval.
+static void EnumDescriptor_FromEnumDef(zval *val, const upb_enumdef *m) {
+  if (!m) {
+    ZVAL_NULL(val);
+  } else {
+    char *classname =
+        GetPhpClassname(upb_enumdef_file(m), upb_enumdef_fullname(m));
+    zend_string *str = zend_string_init(classname, strlen(classname), 0);
+    zend_class_entry *ce = zend_lookup_class(str);  // May autoload the class.
+
+    zend_string_release (str);
+
+    if (!ce) {
+      zend_error(E_ERROR, "Couldn't load generated class %s", classname);
+    }
+
+    free(classname);
+    EnumDescriptor_FromClassEntry(val, ce);
+  }
+}
+
+/*
+ * EnumDescriptor::getValue()
+ *
+ * Returns an EnumValueDescriptor for this index. Note: we are not looking
+ * up by numeric enum value, but by the index in the list of enum values.
+ */
 PHP_METHOD(EnumDescriptor, getValue) {
-  long index;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
+  EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());
+  zend_long index;
+  zval ret;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
     zend_error(E_USER_ERROR, "Expect integer for index.\n");
     return;
   }
 
-  EnumDescriptor *desc = UNBOX(EnumDescriptor, getThis());
-  EnumDescriptorInternal *intern = desc->intern;
   int field_num = upb_enumdef_numvals(intern->enumdef);
   if (index < 0 || index >= field_num) {
     zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
@@ -280,74 +205,164 @@
       !upb_enum_done(&iter) && i < index;
       upb_enum_next(&iter), i++);
 
-  ZVAL_OBJ(return_value, enum_value_descriptor_type->create_object(
-                             enum_value_descriptor_type TSRMLS_CC));
-  EnumValueDescriptor *enum_value_php =
-      UNBOX(EnumValueDescriptor, return_value);
-  enum_value_php->name = upb_enum_iter_name(&iter);
-  enum_value_php->number = upb_enum_iter_number(&iter);
+  EnumValueDescriptor_Make(&ret, upb_enum_iter_name(&iter),
+                           upb_enum_iter_number(&iter));
+  RETURN_COPY_VALUE(&ret);
 }
 
+/*
+ * EnumDescriptor::getValueCount()
+ *
+ * Returns the number of values in this enum.
+ */
 PHP_METHOD(EnumDescriptor, getValueCount) {
-  EnumDescriptor *desc = UNBOX(EnumDescriptor, getThis());
-  EnumDescriptorInternal *intern = desc->intern;
+  EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());
   RETURN_LONG(upb_enumdef_numvals(intern->enumdef));
 }
 
-// -----------------------------------------------------------------------------
-// EnumValueDescriptor
-// -----------------------------------------------------------------------------
+/*
+ * EnumDescriptor::getPublicDescriptor()
+ *
+ * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
+ * have two separate EnumDescriptor classes. We use a single class for both
+ * the public and private descriptor.
+ */
+PHP_METHOD(EnumDescriptor, getPublicDescriptor) {
+  RETURN_COPY(getThis());
+}
 
-static zend_function_entry enum_value_descriptor_methods[] = {
-  PHP_ME(EnumValueDescriptor, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumValueDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
+static zend_function_entry EnumDescriptor_methods[] = {
+  PHP_ME(EnumDescriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(EnumDescriptor, getValueCount, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(EnumDescriptor, getValue, arginfo_getByIndex, ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
-DEFINE_CLASS(EnumValueDescriptor, enum_value_descriptor,
-             "Google\\Protobuf\\EnumValueDescriptor");
+// -----------------------------------------------------------------------------
+// Oneof
+// -----------------------------------------------------------------------------
 
-static void enum_value_descriptor_free_c(EnumValueDescriptor *self TSRMLS_DC) {
+typedef struct {
+  zend_object std;
+  const upb_oneofdef *oneofdef;
+} OneofDescriptor;
+
+zend_class_entry *OneofDescriptor_class_entry;
+static zend_object_handlers OneofDescriptor_object_handlers;
+
+static void OneofDescriptor_destructor(zend_object* obj) {
+  OneofDescriptor *intern = (OneofDescriptor*)obj;
+  ObjCache_Delete(intern->oneofdef);
 }
 
-static void enum_value_descriptor_init_c_instance(EnumValueDescriptor *self TSRMLS_DC) {
-  self->name = NULL;
-  self->number = 0;
+static void OneofDescriptor_FromOneofDef(zval *val, const upb_oneofdef *o) {
+  if (o == NULL) {
+    ZVAL_NULL(val);
+    return;
+  }
+
+  if (!ObjCache_Get(o, val)) {
+    OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor));
+    zend_object_std_init(&ret->std, OneofDescriptor_class_entry);
+    ret->std.handlers = &OneofDescriptor_object_handlers;
+    ret->oneofdef = o;
+    ObjCache_Add(o, &ret->std);
+    ZVAL_OBJ(val, &ret->std);
+  }
 }
 
-PHP_METHOD(EnumValueDescriptor, getName) {
-  EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis());
-  PHP_PROTO_RETVAL_STRINGL(intern->name, strlen(intern->name), 1);
+/*
+ * OneofDescriptor::getName()
+ *
+ * Returns the name of this oneof.
+ */
+PHP_METHOD(OneofDescriptor, getName) {
+  OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
+  RETURN_STRING(upb_oneofdef_name(intern->oneofdef));
 }
 
-PHP_METHOD(EnumValueDescriptor, getNumber) {
-  EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis());
-  RETURN_LONG(intern->number);
+/*
+ * OneofDescriptor::getField()
+ *
+ * Returns a field from this oneof. The given index must be in the range
+ *   [0, getFieldCount() - 1].
+ */
+PHP_METHOD(OneofDescriptor, getField) {
+  OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
+  zend_long index;
+  zval ret;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
+    zend_error(E_USER_ERROR, "Expect integer for index.\n");
+    return;
+  }
+
+  int field_num = upb_oneofdef_numfields(intern->oneofdef);
+  if (index < 0 || index >= field_num) {
+    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
+    return;
+  }
+
+  upb_oneof_iter iter;
+  int i;
+  for(upb_oneof_begin(&iter, intern->oneofdef), i = 0;
+      !upb_oneof_done(&iter) && i < index;
+      upb_oneof_next(&iter), i++);
+  const upb_fielddef *field = upb_oneof_iter_field(&iter);
+
+  FieldDescriptor_FromFieldDef(&ret, field);
+  RETURN_COPY_VALUE(&ret);
 }
 
+/*
+ * OneofDescriptor::getFieldCount()
+ *
+ * Returns the number of fields in this oneof.
+ */
+PHP_METHOD(OneofDescriptor, getFieldCount) {
+  OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
+  RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef));
+}
+
+static zend_function_entry OneofDescriptor_methods[] = {
+  PHP_ME(OneofDescriptor, getName,  arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(OneofDescriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC)
+  PHP_ME(OneofDescriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
 // -----------------------------------------------------------------------------
 // FieldDescriptor
 // -----------------------------------------------------------------------------
 
-static zend_function_entry field_descriptor_methods[] = {
-  PHP_ME(FieldDescriptor, getName,   NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldDescriptor, getLabel,  NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldDescriptor, getType,   NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldDescriptor, isMap,     NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldDescriptor, getMessageType, NULL, ZEND_ACC_PUBLIC)
-  ZEND_FE_END
-};
+typedef struct {
+  zend_object std;
+  const upb_fielddef *fielddef;
+} FieldDescriptor;
 
-DEFINE_CLASS(FieldDescriptor, field_descriptor,
-             "Google\\Protobuf\\FieldDescriptor");
+zend_class_entry *FieldDescriptor_class_entry;
+static zend_object_handlers FieldDescriptor_object_handlers;
 
-static void field_descriptor_free_c(FieldDescriptor *self TSRMLS_DC) {
+static void FieldDescriptor_destructor(zend_object* obj) {
+  FieldDescriptor *intern = (FieldDescriptor*)obj;
+  ObjCache_Delete(intern->fielddef);
 }
 
-static void field_descriptor_init_c_instance(FieldDescriptor *self TSRMLS_DC) {
-  self->fielddef = NULL;
+// Caller owns a ref on the returned zval.
+static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f) {
+  if (f == NULL) {
+    ZVAL_NULL(val);
+    return;
+  }
+
+  if (!ObjCache_Get(f, val)) {
+    FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor));
+    zend_object_std_init(&ret->std, FieldDescriptor_class_entry);
+    ret->std.handlers = &FieldDescriptor_object_handlers;
+    ret->fielddef = f;
+    ObjCache_Add(f, &ret->std);
+    ZVAL_OBJ(val, &ret->std);
+  }
 }
 
 upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {
@@ -383,499 +398,486 @@
   return 0;
 }
 
+/*
+ * FieldDescriptor::getName()
+ *
+ * Returns the name of this field.
+ */
 PHP_METHOD(FieldDescriptor, getName) {
-  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
-  const char* name = upb_fielddef_name(intern->fielddef);
-  PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1);
+  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
+  RETURN_STRING(upb_fielddef_name(intern->fielddef));
 }
 
+/*
+ * FieldDescriptor::getNumber()
+ *
+ * Returns the number of this field.
+ */
 PHP_METHOD(FieldDescriptor, getNumber) {
-  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
   RETURN_LONG(upb_fielddef_number(intern->fielddef));
 }
 
+/*
+ * FieldDescriptor::getLabel()
+ *
+ * Returns the label of this field as an integer.
+ */
 PHP_METHOD(FieldDescriptor, getLabel) {
-  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
   RETURN_LONG(upb_fielddef_label(intern->fielddef));
 }
 
+/*
+ * FieldDescriptor::getType()
+ *
+ * Returns the type of this field as an integer.
+ */
 PHP_METHOD(FieldDescriptor, getType) {
-  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
   RETURN_LONG(upb_fielddef_descriptortype(intern->fielddef));
 }
 
+/*
+ * FieldDescriptor::isMap()
+ *
+ * Returns true if this field is a map.
+ */
 PHP_METHOD(FieldDescriptor, isMap) {
-  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
   RETURN_BOOL(upb_fielddef_ismap(intern->fielddef));
 }
 
+/*
+ * FieldDescriptor::getEnumType()
+ *
+ * Returns the EnumDescriptor for this field, which must be an enum.
+ */
 PHP_METHOD(FieldDescriptor, getEnumType) {
-  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
-  if (upb_fielddef_type(intern->fielddef) != UPB_TYPE_ENUM) {
-    zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
+  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
+  const upb_enumdef *e = upb_fielddef_enumsubdef(intern->fielddef);
+  zval ret;
+
+  if (!e) {
+    zend_throw_exception_ex(NULL, 0,
                             "Cannot get enum type for non-enum field '%s'",
                             upb_fielddef_name(intern->fielddef));
     return;
   }
-  const upb_enumdef *enumdef = upb_fielddef_enumsubdef(intern->fielddef);
-  PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(enumdef);
 
-  if (desc_php == NULL) {
-    EnumDescriptorInternal* intern = get_enumdef_enumdesc(enumdef);
-
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(desc_php);
-    ZVAL_OBJ(desc_php, enum_descriptor_type->create_object(
-                                        enum_descriptor_type TSRMLS_CC));
-    Z_DELREF_P(desc_php);
-#else
-    desc_php =
-        enum_descriptor_type->create_object(enum_descriptor_type TSRMLS_CC);
-    GC_DELREF(desc_php);
-#endif
-    EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(EnumDescriptor, desc_php);
-    desc->intern = intern;
-    add_def_obj(enumdef, desc_php);
-    add_ce_obj(intern->klass, desc_php);
-  }
-
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(desc_php, 1, 0);
-#else
-  GC_ADDREF(desc_php);
-  RETURN_OBJ(desc_php);
-#endif
+  EnumDescriptor_FromEnumDef(&ret, e);
+  RETURN_COPY_VALUE(&ret);
 }
 
+/*
+ * FieldDescriptor::getMessageType()
+ *
+ * Returns the Descriptor for this field, which must be a message.
+ */
 PHP_METHOD(FieldDescriptor, getMessageType) {
-  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
-  if (upb_fielddef_type(intern->fielddef) != UPB_TYPE_MESSAGE) {
+  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
+  Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef);
+
+  if (!desc) {
     zend_throw_exception_ex(
-        NULL, 0 TSRMLS_CC, "Cannot get message type for non-message field '%s'",
+        NULL, 0, "Cannot get message type for non-message field '%s'",
         upb_fielddef_name(intern->fielddef));
     return;
   }
-  const upb_msgdef *msgdef = upb_fielddef_msgsubdef(intern->fielddef);
-  PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(msgdef);
 
-  if (desc_php == NULL) {
-    DescriptorInternal* intern = get_msgdef_desc(msgdef);
-
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(desc_php);
-    ZVAL_OBJ(desc_php, descriptor_type->create_object(
-                                   descriptor_type TSRMLS_CC));
-    Z_DELREF_P(desc_php);
-#else
-    desc_php =
-        descriptor_type->create_object(descriptor_type TSRMLS_CC);
-    GC_DELREF(desc_php);
-#endif
-    Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
-    desc->intern = intern;
-    add_def_obj(msgdef, desc_php);
-    add_ce_obj(intern->klass, desc_php);
-  }
-
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(desc_php, 1, 0);
-#else
-  GC_ADDREF(desc_php);
-  RETURN_OBJ(desc_php);
-#endif
+  RETURN_OBJ_COPY(&desc->std);
 }
 
-// -----------------------------------------------------------------------------
-// Oneof
-// -----------------------------------------------------------------------------
-
-static zend_function_entry oneof_descriptor_methods[] = {
-  PHP_ME(Oneof, getName,  NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Oneof, getField, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Oneof, getFieldCount, NULL, ZEND_ACC_PUBLIC)
+static zend_function_entry FieldDescriptor_methods[] = {
+  PHP_ME(FieldDescriptor, getName,   arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getLabel,  arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getType,   arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, isMap,     arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getEnumType, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getMessageType, arginfo_void, ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
-DEFINE_CLASS(Oneof, oneof_descriptor,
-             "Google\\Protobuf\\OneofDescriptor");
+// -----------------------------------------------------------------------------
+// Descriptor
+// -----------------------------------------------------------------------------
 
-static void oneof_descriptor_free_c(Oneof *self TSRMLS_DC) {
+zend_class_entry *Descriptor_class_entry;
+static zend_object_handlers Descriptor_object_handlers;
+
+static void Descriptor_destructor(zend_object* obj) {
+  // We don't really need to do anything here, we don't allow this to be
+  // collected before the end of the request.
 }
 
-static void oneof_descriptor_init_c_instance(Oneof *self TSRMLS_DC) {
-  self->oneofdef = NULL;
+static zend_class_entry *Descriptor_GetGeneratedClass(const upb_msgdef *m) {
+  char *classname =
+      GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));
+  zend_string *str = zend_string_init(classname, strlen(classname), 0);
+  zend_class_entry *ce = zend_lookup_class(str);  // May autoload the class.
+
+  zend_string_release (str);
+
+  if (!ce) {
+    zend_error(E_ERROR, "Couldn't load generated class %s", classname);
+  }
+
+  free(classname);
+  return ce;
 }
 
-PHP_METHOD(Oneof, getName) {
-  Oneof *intern = UNBOX(Oneof, getThis());
-  const char *name = upb_oneofdef_name(intern->oneofdef);
-  PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1);
+void Descriptor_FromMessageDef(zval *val, const upb_msgdef *m) {
+  if (m == NULL) {
+    ZVAL_NULL(val);
+    return;
+  }
+
+  if (!ObjCache_Get(m, val)) {
+    zend_class_entry *ce = NULL;
+    if (!upb_msgdef_mapentry(m)) {  // Map entries don't have a class.
+      ce = Descriptor_GetGeneratedClass(m);
+      if (!ce) {
+        ZVAL_NULL(val);
+        return;
+      }
+    }
+    Descriptor* ret = emalloc(sizeof(Descriptor));
+    zend_object_std_init(&ret->std, Descriptor_class_entry);
+    ret->std.handlers = &Descriptor_object_handlers;
+    ret->class_entry = ce;
+    ret->msgdef = m;
+    ObjCache_Add(m, &ret->std);
+    Descriptors_Add(&ret->std);
+    ZVAL_OBJ(val, &ret->std);
+  }
 }
 
-PHP_METHOD(Oneof, getField) {
-  long index;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
+static void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce) {
+  if (ce) {
+    Descriptor_FromMessageDef(val, NameMap_GetMessage(ce));
+  } else {
+    ZVAL_NULL(val);
+  }
+}
+
+static Descriptor* Descriptor_GetFromZval(zval *val) {
+  if (Z_TYPE_P(val) == IS_NULL) {
+    return NULL;
+  } else {
+    zend_object* ret = Z_OBJ_P(val);
+    zval_ptr_dtor(val);
+    return (Descriptor*)ret;
+  }
+}
+
+// C Functions from def.h //////////////////////////////////////////////////////
+
+// These are documented in the header file.
+
+Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce) {
+  zval desc;
+  Descriptor_FromClassEntry(&desc, ce);
+  return Descriptor_GetFromZval(&desc);
+}
+
+Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m) {
+  zval desc;
+  Descriptor_FromMessageDef(&desc, m);
+  return Descriptor_GetFromZval(&desc);
+}
+
+Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f) {
+  return Descriptor_GetFromMessageDef(upb_fielddef_msgsubdef(f));
+}
+
+/*
+ * Descriptor::getPublicDescriptor()
+ *
+ * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
+ * have two separate EnumDescriptor classes. We use a single class for both
+ * the public and private descriptor.
+ */
+PHP_METHOD(Descriptor, getPublicDescriptor) {
+  RETURN_COPY(getThis());
+}
+
+/*
+ * Descriptor::getFullName()
+ *
+ * Returns the full name for this message type.
+ */
+PHP_METHOD(Descriptor, getFullName) {
+  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+  RETURN_STRING(upb_msgdef_fullname(intern->msgdef));
+}
+
+/*
+ * Descriptor::getField()
+ *
+ * Returns a FieldDescriptor for the given index, which must be in the range
+ * [0, getFieldCount()-1].
+ */
+PHP_METHOD(Descriptor, getField) {
+  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+  int count = upb_msgdef_numfields(intern->msgdef);
+  zval ret;
+  zend_long index;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
     zend_error(E_USER_ERROR, "Expect integer for index.\n");
     return;
   }
 
-  Oneof *intern = UNBOX(Oneof, getThis());
-  int field_num = upb_oneofdef_numfields(intern->oneofdef);
+  if (index < 0 || index >= count) {
+    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
+    return;
+  }
+
+  FieldDescriptor_FromFieldDef(&ret, upb_msgdef_field(intern->msgdef, index));
+  RETURN_COPY_VALUE(&ret);
+}
+
+/*
+ * Descriptor::getFieldCount()
+ *
+ * Returns the number of fields in this message.
+ */
+PHP_METHOD(Descriptor, getFieldCount) {
+  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+  RETURN_LONG(upb_msgdef_numfields(intern->msgdef));
+}
+
+/*
+ * Descriptor::getOneofDecl()
+ *
+ * Returns a OneofDescriptor for the given index, which must be in the range
+ * [0, getOneofDeclCount()].
+ */
+PHP_METHOD(Descriptor, getOneofDecl) {
+  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+  zend_long index;
+  zval ret;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
+    zend_error(E_USER_ERROR, "Expect integer for index.\n");
+    return;
+  }
+
+  int field_num = upb_msgdef_numoneofs(intern->msgdef);
   if (index < 0 || index >= field_num) {
     zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
     return;
   }
 
-  upb_oneof_iter iter;
+  upb_msg_oneof_iter iter;
   int i;
-  for(upb_oneof_begin(&iter, intern->oneofdef), i = 0;
-      !upb_oneof_done(&iter) && i < index;
-      upb_oneof_next(&iter), i++);
-  const upb_fielddef *field = upb_oneof_iter_field(&iter);
+  for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0;
+      !upb_msg_oneof_done(&iter) && i < index;
+      upb_msg_oneof_next(&iter), i++);
+  const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter);
 
-  PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field);
-  if (field_hashtable_value == NULL) {
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(field_hashtable_value);
-    ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
-                                        field_descriptor_type TSRMLS_CC));
-#else
-    field_hashtable_value =
-        field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
-#endif
-    FieldDescriptor *field_php =
-        UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
-    field_php->fielddef = field;
-    add_def_obj(field, field_hashtable_value);
-  }
-
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(field_hashtable_value, 1, 0);
-#else
-  GC_ADDREF(field_hashtable_value);
-  RETURN_OBJ(field_hashtable_value);
-#endif
+  OneofDescriptor_FromOneofDef(&ret, oneof);
+  RETURN_COPY_VALUE(&ret);
 }
 
-PHP_METHOD(Oneof, getFieldCount) {
-  Oneof *intern = UNBOX(Oneof, getThis());
-  RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef));
+/*
+ * Descriptor::getOneofDeclCount()
+ *
+ * Returns the number of oneofs in this message.
+ */
+PHP_METHOD(Descriptor, getOneofDeclCount) {
+  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+  RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));
 }
 
+/*
+ * Descriptor::getClass()
+ *
+ * Returns the name of the PHP class for this message.
+ */
+PHP_METHOD(Descriptor, getClass) {
+  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+  const char* classname = ZSTR_VAL(intern->class_entry->name);
+  RETURN_STRING(classname);
+}
+
+
+static zend_function_entry Descriptor_methods[] = {
+  PHP_ME(Descriptor, getClass, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getFullName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getOneofDecl, arginfo_getByIndex, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getOneofDeclCount, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
 // -----------------------------------------------------------------------------
 // DescriptorPool
 // -----------------------------------------------------------------------------
 
-static zend_function_entry descriptor_pool_methods[] = {
-  PHP_ME(DescriptorPool, getGeneratedPool, NULL,
-         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
-  ZEND_FE_END
-};
+typedef struct DescriptorPool {
+  zend_object std;
+  upb_symtab *symtab;
+} DescriptorPool;
 
-static zend_function_entry internal_descriptor_pool_methods[] = {
-  PHP_ME(InternalDescriptorPool, getGeneratedPool, NULL,
-         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(InternalDescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)
-  ZEND_FE_END
-};
+zend_class_entry *DescriptorPool_class_entry;
+static zend_object_handlers DescriptorPool_object_handlers;
 
-DEFINE_CLASS(DescriptorPool, descriptor_pool,
-             "Google\\Protobuf\\DescriptorPool");
-DEFINE_CLASS(InternalDescriptorPool, internal_descriptor_pool,
-             "Google\\Protobuf\\Internal\\DescriptorPool");
+static DescriptorPool *GetPool(const zval* this_ptr) {
+  return (DescriptorPool*)Z_OBJ_P(this_ptr);
+}
 
-// wrapper of generated pool
-#if PHP_MAJOR_VERSION < 7
-zval* generated_pool_php;
-zval* internal_generated_pool_php;
-#else
-zend_object *generated_pool_php;
-zend_object *internal_generated_pool_php;
-#endif
-InternalDescriptorPoolImpl *generated_pool;
-InternalDescriptorPoolImpl generated_pool_impl;  // The actual generated pool
+/**
+ * Object handler to create an DescriptorPool.
+ */
+static zend_object* DescriptorPool_create(zend_class_entry *class_type) {
+  DescriptorPool *intern = emalloc(sizeof(DescriptorPool));
+  zend_object_std_init(&intern->std, class_type);
+  intern->std.handlers = &DescriptorPool_object_handlers;
+  intern->symtab = upb_symtab_new();
+  // Skip object_properties_init(), we don't allow derived classes.
+  return &intern->std;
+}
 
-void init_generated_pool_once(TSRMLS_D) {
-  if (generated_pool == NULL) {
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(generated_pool_php);
-    MAKE_STD_ZVAL(internal_generated_pool_php);
-    ZVAL_OBJ(internal_generated_pool_php,
-             internal_descriptor_pool_type->create_object(
-                 internal_descriptor_pool_type TSRMLS_CC));
-    ZVAL_OBJ(generated_pool_php, descriptor_pool_type->create_object(
-                                     descriptor_pool_type TSRMLS_CC));
-#else
-    internal_generated_pool_php = internal_descriptor_pool_type->create_object(
-        internal_descriptor_pool_type TSRMLS_CC);
-    generated_pool_php =
-        descriptor_pool_type->create_object(descriptor_pool_type TSRMLS_CC);
-#endif
-    generated_pool = &generated_pool_impl;
+/**
+ * Object handler to free an DescriptorPool.
+ */
+static void DescriptorPool_destructor(zend_object* obj) {
+  DescriptorPool* intern = (DescriptorPool*)obj;
+  if (intern->symtab) {
+    upb_symtab_free(intern->symtab);
+  }
+  intern->symtab = NULL;
+  zend_object_std_dtor(&intern->std);
+}
+
+void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab) {
+  ZVAL_OBJ(zv, DescriptorPool_create(DescriptorPool_class_entry));
+
+  if (symtab) {
+    DescriptorPool *intern = GetPool(zv);
+    upb_symtab_free(intern->symtab);
+    intern->symtab = symtab;
   }
 }
 
-static void internal_descriptor_pool_init_c_instance(
-    InternalDescriptorPool *pool TSRMLS_DC) {
-  pool->intern = &generated_pool_impl;
+upb_symtab *DescriptorPool_Steal(zval *zv) {
+  DescriptorPool *intern = GetPool(zv);
+  upb_symtab *ret = intern->symtab;
+  intern->symtab = NULL;
+  return ret;
 }
 
-static void internal_descriptor_pool_free_c(
-    InternalDescriptorPool *pool TSRMLS_DC) {
+upb_symtab *DescriptorPool_GetSymbolTable() {
+  DescriptorPool *intern = GetPool(get_generated_pool());
+  return intern->symtab;
 }
 
-void internal_descriptor_pool_impl_init(
-    InternalDescriptorPoolImpl *pool TSRMLS_DC) {
-  pool->symtab = upb_symtab_new();
-  pool->fill_handler_cache =
-      upb_handlercache_new(add_handlers_for_message, NULL);
-  pool->pb_serialize_handler_cache = upb_pb_encoder_newcache();
-  pool->json_serialize_handler_cache = upb_json_printer_newcache(false);
-  pool->json_serialize_handler_preserve_cache = upb_json_printer_newcache(true);
-  pool->fill_method_cache = upb_pbcodecache_new(pool->fill_handler_cache);
-  pool->json_fill_method_cache = upb_json_codecache_new();
-}
 
-void internal_descriptor_pool_impl_destroy(
-    InternalDescriptorPoolImpl *pool TSRMLS_DC) {
-  upb_symtab_free(pool->symtab);
-  upb_handlercache_free(pool->fill_handler_cache);
-  upb_handlercache_free(pool->pb_serialize_handler_cache);
-  upb_handlercache_free(pool->json_serialize_handler_cache);
-  upb_handlercache_free(pool->json_serialize_handler_preserve_cache);
-  upb_pbcodecache_free(pool->fill_method_cache);
-  upb_json_codecache_free(pool->json_fill_method_cache);
-}
-
-static void descriptor_pool_init_c_instance(DescriptorPool *pool TSRMLS_DC) {
-  assert(generated_pool != NULL);
-  pool->intern = generated_pool;
-}
-
-static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
-}
-
+/*
+ * DescriptorPool::getGeneratedPool()
+ *
+ * Returns the generated DescriptorPool.
+ */
 PHP_METHOD(DescriptorPool, getGeneratedPool) {
-  init_generated_pool_once(TSRMLS_C);
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(generated_pool_php, 1, 0);
-#else
-  GC_ADDREF(generated_pool_php);
-  RETURN_OBJ(generated_pool_php);
-#endif
+  zval ret;
+  ZVAL_COPY(&ret, get_generated_pool());
+  RETURN_COPY_VALUE(&ret);
 }
 
-PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
-  init_generated_pool_once(TSRMLS_C);
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(internal_generated_pool_php, 1, 0);
-#else
-  GC_ADDREF(internal_generated_pool_php);
-  RETURN_OBJ(internal_generated_pool_php);
-#endif
-}
+/*
+ * DescriptorPool::getDescriptorByClassName()
+ *
+ * Returns a Descriptor object for the given PHP class name.
+ */
+PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
+  char *classname = NULL;
+  zend_long classname_len;
+  zend_class_entry *ce;
+  zend_string *str;
+  zval ret;
 
-static bool is_reserved(const char *segment, int length) {
-  bool result;
-  char* lower = ALLOC_N(char, length + 1);
-  memset(lower, 0, length + 1);
-  memcpy(lower, segment, length);
-  int i = 0;
-  while(lower[i]) {
-    lower[i] = (char)tolower(lower[i]);
-    i++;
-  }
-  lower[length] = 0;
-  result = is_reserved_name(lower);
-  FREE(lower);
-  return result;
-}
-
-static void fill_prefix(const char *segment, int length,
-                        const char *prefix_given,
-                        const char *package_name,
-                        stringsink *classname) {
-  if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
-    stringsink_string(classname, NULL, prefix_given,
-                      strlen(prefix_given), NULL);
-  } else {
-    if (is_reserved(segment, length)) {
-      if (package_name != NULL &&
-          strcmp("google.protobuf", package_name) == 0) {
-        stringsink_string(classname, NULL, "GPB", 3, NULL);
-      } else {
-        stringsink_string(classname, NULL, "PB", 2, NULL);
-      }
-    }
-  }
-}
-
-static void fill_segment(const char *segment, int length,
-                         stringsink *classname, bool use_camel) {
-  if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
-    char first = segment[0] + ('A' - 'a');
-    stringsink_string(classname, NULL, &first, 1, NULL);
-    stringsink_string(classname, NULL, segment + 1, length - 1, NULL);
-  } else {
-    stringsink_string(classname, NULL, segment, length, NULL);
-  }
-}
-
-static void fill_namespace(const char *package, const char *php_namespace,
-                           stringsink *classname) {
-  if (php_namespace != NULL) {
-    if (strlen(php_namespace) != 0) {
-      stringsink_string(classname, NULL, php_namespace, strlen(php_namespace),
-                        NULL);
-      stringsink_string(classname, NULL, "\\", 1, NULL);
-    }
-  } else if (package != NULL) {
-    int i = 0, j = 0;
-    size_t package_len = strlen(package);
-    while (i < package_len) {
-      j = i;
-      while (j < package_len && package[j] != '.') {
-        j++;
-      }
-      fill_prefix(package + i, j - i, "", package, classname);
-      fill_segment(package + i, j - i, classname, true);
-      stringsink_string(classname, NULL, "\\", 1, NULL);
-      i = j + 1;
-    }
-  }
-}
-
-static void fill_classname(const char *fullname,
-                           const char *package,
-                           const char *prefix,
-                           stringsink *classname,
-                           bool use_nested_submsg) {
-  int classname_start = 0;
-  if (package != NULL) {
-    size_t package_len = strlen(package);
-    classname_start = package_len == 0 ? 0 : package_len + 1;
-  }
-  size_t fullname_len = strlen(fullname);
-  bool is_first_segment = true;
-
-  int i = classname_start, j;
-  while (i < fullname_len) {
-    j = i;
-    while (j < fullname_len && fullname[j] != '.') {
-      j++;
-    }
-    if (use_nested_submsg || (is_first_segment && j == fullname_len)) {
-      fill_prefix(fullname + i, j - i, prefix, package, classname);
-    }
-    is_first_segment = false;
-    fill_segment(fullname + i, j - i, classname, false);
-    if (j != fullname_len) {
-      if (use_nested_submsg) {
-        stringsink_string(classname, NULL, "\\", 1, NULL);
-      } else {
-        stringsink_string(classname, NULL, "_", 1, NULL);
-      }
-    }
-    i = j + 1;
-  }
-}
-
-static void fill_classname_for_desc(void *desc, bool is_enum) {
-  const upb_filedef *file;
-  const char *fullname;
-  bool use_nested_submsg;
-
-  if (is_enum) {
-    EnumDescriptorInternal* enumdesc = desc;
-    file = upb_enumdef_file(enumdesc->enumdef);
-    fullname = upb_enumdef_fullname(enumdesc->enumdef);
-    use_nested_submsg = enumdesc->use_nested_submsg;
-  } else {
-    DescriptorInternal* msgdesc = desc;
-    file = upb_msgdef_file(msgdesc->msgdef);
-    fullname = upb_msgdef_fullname(msgdesc->msgdef);
-    use_nested_submsg = msgdesc->use_nested_submsg;
-  }
-
-  // Prepend '.' to package name to make it absolute. In the 5 additional
-  // bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if
-  // given message is google.protobuf.Empty.
-  const char *package = upb_filedef_package(file);
-  const char *php_namespace = upb_filedef_phpnamespace(file);
-  const char *prefix = upb_filedef_phpprefix(file);
-  stringsink namesink;
-  stringsink_init(&namesink);
-
-  fill_namespace(package, php_namespace, &namesink);
-  fill_classname(fullname, package, prefix, &namesink, use_nested_submsg);
-  stringsink_string(&namesink, NULL, "\0", 1, NULL);
-
-  if (is_enum) {
-    EnumDescriptorInternal* enumdesc = desc;
-    enumdesc->classname = strdup(namesink.ptr);
-  } else {
-    DescriptorInternal* msgdesc = desc;
-    msgdesc->classname = strdup(namesink.ptr);
-  }
-
-  stringsink_uninit(&namesink);
-}
-
-void register_class(void *desc, bool is_enum TSRMLS_DC) {
-  const char *classname;
-  const char *fullname;
-  zend_class_entry* ret;
-
-  if (is_enum) {
-    EnumDescriptorInternal* enumdesc = desc;
-    if (enumdesc->klass) {
-      return;
-    }
-    classname = enumdesc->classname;
-    fullname = upb_enumdef_fullname(enumdesc->enumdef);
-  } else {
-    DescriptorInternal* msgdesc = desc;
-    if (msgdesc->klass) {
-      return;
-    }
-    if (!msgdesc->classname) {
-      return;
-    }
-    classname = msgdesc->classname;
-    fullname = upb_msgdef_fullname(msgdesc->msgdef);
-  }
-
-  PHP_PROTO_CE_DECLARE pce;
-  if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) ==
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
       FAILURE) {
-    zend_error(
-        E_ERROR,
-        "Generated message class %s hasn't been defined (%s)",
-        classname, fullname);
     return;
   }
-  ret = PHP_PROTO_CE_UNREF(pce);
-  if (is_enum) {
-    EnumDescriptorInternal* enumdesc = desc;
-    add_ce_enumdesc(ret, desc);
-    enumdesc->klass = ret;
+
+  str = zend_string_init(classname, strlen(classname), 0);
+  ce = zend_lookup_class(str);  // May autoload the class.
+  zend_string_release (str);
+
+  if (!ce) {
+    RETURN_NULL();
+  }
+
+  Descriptor_FromClassEntry(&ret, ce);
+  RETURN_COPY_VALUE(&ret);
+}
+
+/*
+ * DescriptorPool::getEnumDescriptorByClassName()
+ *
+ * Returns a EnumDescriptor object for the given PHP class name.
+ */
+PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
+  char *classname = NULL;
+  zend_long classname_len;
+  zend_class_entry *ce;
+  zend_string *str;
+  zval ret;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
+      FAILURE) {
+    return;
+  }
+
+  str = zend_string_init(classname, strlen(classname), 0);
+  ce = zend_lookup_class(str);  // May autoload the class.
+  zend_string_release (str);
+
+  if (!ce) {
+    RETURN_NULL();
+  }
+
+  EnumDescriptor_FromClassEntry(&ret, ce);
+  RETURN_COPY_VALUE(&ret);
+}
+
+/*
+ * DescriptorPool::getEnumDescriptorByProtoName()
+ *
+ * Returns a Descriptor object for the given protobuf message name.
+ */
+PHP_METHOD(DescriptorPool, getDescriptorByProtoName) {
+  DescriptorPool *intern = GetPool(getThis());
+  char *protoname = NULL;
+  zend_long protoname_len;
+  const upb_msgdef *m;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &protoname, &protoname_len) ==
+      FAILURE) {
+    return;
+  }
+
+  if (*protoname == '.') protoname++;
+
+  m = upb_symtab_lookupmsg(intern->symtab, protoname);
+
+  if (m) {
+    RETURN_OBJ_COPY(&Descriptor_GetFromMessageDef(m)->std);
   } else {
-    DescriptorInternal* msgdesc = desc;
-    add_ce_desc(ret, desc);
-    msgdesc->klass = ret;
-    // Map entries don't have existing php class.
-    if (!upb_msgdef_mapentry(msgdesc->msgdef)) {
-      if (msgdesc->layout == NULL) {
-        MessageLayout* layout = create_layout(msgdesc->msgdef);
-        msgdesc->layout = layout;
-      }
-    }
+    RETURN_NULL();
   }
 }
 
+/*
+ * depends_on_descriptor()
+ *
+ * Returns true if this FileDescriptorProto depends on descriptor.proto.
+ */
 bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) {
   const upb_strview *deps;
   upb_strview name = upb_strview_makez("google/protobuf/descriptor.proto");
@@ -891,247 +893,265 @@
   return false;
 }
 
-static void internal_add_single_generated_file(
-    const upb_filedef* file,
-    InternalDescriptorPoolImpl* pool,
-    bool use_nested_submsg TSRMLS_DC) {
+/*
+ * add_name_mappings()
+ *
+ * Adds the messages and enums in this file to the NameMap.
+ */
+static void add_name_mappings(const upb_filedef *file) {
   size_t i;
-  // For each enum/message, we need its PHP class, upb descriptor and its PHP
-  // wrapper. These information are needed later for encoding, decoding and type
-  // checking. However, sometimes we just have one of them. In order to find
-  // them quickly, here, we store the mapping for them.
   for (i = 0; i < upb_filedef_msgcount(file); i++) {
-    const upb_msgdef *msgdef = upb_filedef_msg(file, i);
-    CREATE_HASHTABLE_VALUE(desc, desc_php, Descriptor, descriptor_type);
-    desc->intern = SYS_MALLOC(DescriptorInternal);
-    desc->intern->msgdef = msgdef;
-    desc->intern->pool = pool;
-    desc->intern->layout = NULL;
-    desc->intern->klass = NULL;
-    desc->intern->use_nested_submsg = use_nested_submsg;
-    desc->intern->classname = NULL;
-
-    add_def_obj(desc->intern->msgdef, desc_php);
-    add_msgdef_desc(desc->intern->msgdef, desc->intern);
-
-    // Unlike other messages, MapEntry is shared by all map fields and doesn't
-    // have generated PHP class.
-    if (upb_msgdef_mapentry(msgdef)) {
-      continue;
-    }
-
-    fill_classname_for_desc(desc->intern, false);
-    add_class_desc(desc->intern->classname, desc->intern);
-    add_proto_desc(upb_msgdef_fullname(desc->intern->msgdef), desc->intern);
+    NameMap_AddMessage(upb_filedef_msg(file, i));
   }
 
   for (i = 0; i < upb_filedef_enumcount(file); i++) {
-    const upb_enumdef *enumdef = upb_filedef_enum(file, i);
-    CREATE_HASHTABLE_VALUE(desc, desc_php, EnumDescriptor, enum_descriptor_type);
-    desc->intern = SYS_MALLOC(EnumDescriptorInternal);
-    desc->intern->enumdef = enumdef;
-    desc->intern->klass = NULL;
-    desc->intern->use_nested_submsg = use_nested_submsg;
-    desc->intern->classname = NULL;
-
-    add_def_obj(desc->intern->enumdef, desc_php);
-    add_enumdef_enumdesc(desc->intern->enumdef, desc->intern);
-    fill_classname_for_desc(desc->intern, true);
-    add_class_enumdesc(desc->intern->classname, desc->intern);
+    NameMap_AddEnum(upb_filedef_enum(file, i));
   }
 }
 
-const bool parse_and_add_descriptor(const char *data,
-                                    PHP_PROTO_SIZE data_len,
-                                    InternalDescriptorPoolImpl *pool,
-                                    upb_arena *arena,
-                                    bool use_nested_submsg TSRMLS_DC) {
+static void add_descriptor(DescriptorPool *pool,
+                           const google_protobuf_FileDescriptorProto *file) {
+  upb_strview name = google_protobuf_FileDescriptorProto_name(file);
+  upb_status status;
+  const upb_filedef *file_def;
+  upb_status_clear(&status);
+
+  if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) {
+    // Already added.
+    // TODO(teboring): Re-enable this warning when aggregate metadata is
+    // deprecated.
+    // zend_error(E_USER_WARNING,
+    //            "proto descriptor was previously loaded (included in multiple "
+    //            "metadata bundles?): " UPB_STRVIEW_FORMAT,
+    //            UPB_STRVIEW_ARGS(name));
+    return;
+  }
+
+  // The PHP code generator currently special-cases descriptor.proto.  It
+  // doesn't add it as a dependency even if the proto file actually does
+  // depend on it.
+  if (depends_on_descriptor(file)) {
+    google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab);
+  }
+
+  file_def = upb_symtab_addfile(pool->symtab, file, &status);
+  CheckUpbStatus(&status, "Unable to load descriptor");
+  add_name_mappings(file_def);
+}
+
+/*
+ * add_descriptor()
+ *
+ * Adds the given descriptor data to this DescriptorPool.
+ */
+static void add_descriptor_set(DescriptorPool *pool, const char *data,
+                               int data_len, upb_arena *arena) {
   size_t i, n;
   google_protobuf_FileDescriptorSet *set;
   const google_protobuf_FileDescriptorProto* const* files;
-  const upb_filedef* file;
-  upb_status status;
 
-  set = google_protobuf_FileDescriptorSet_parse(
-      data, data_len, arena);
+  set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena);
 
   if (!set) {
     zend_error(E_ERROR, "Failed to parse binary descriptor\n");
-    return false;
+    return;
   }
 
   files = google_protobuf_FileDescriptorSet_file(set, &n);
 
   for (i = 0; i < n; i++) {
-    // Check whether file has already been added.
-    upb_strview name = google_protobuf_FileDescriptorProto_name(files[i]);
-    // TODO(teboring): Needs another look up method which takes data and length.
-    file = upb_symtab_lookupfile2(pool->symtab, name.data, name.size);
-    if (file != NULL) {
-      continue;
-    }
-
-    // The PHP code generator currently special-cases descriptor.proto.  It
-    // doesn't add it as a dependency even if the proto file actually does
-    // depend on it.
-    if (depends_on_descriptor(files[i]) &&
-        upb_symtab_lookupfile(
-            pool->symtab, "google/protobuf/descriptor.proto") ==
-                NULL) {
-      if (!parse_and_add_descriptor((char *)descriptor_proto,
-                                    descriptor_proto_len, pool, arena,
-                                    use_nested_submsg TSRMLS_CC)) {
-        return false;
-      }
-    }
-
-    upb_status_clear(&status);
-    file = upb_symtab_addfile(pool->symtab, files[i], &status);
-    check_upb_status(&status, "Unable to load descriptor");
-
-    internal_add_single_generated_file(file, pool, use_nested_submsg TSRMLS_CC);
+    const google_protobuf_FileDescriptorProto* file = files[i];
+    add_descriptor(pool, file);
   }
-
-  return true;
 }
 
-void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
-                                 InternalDescriptorPoolImpl *pool,
-                                 bool use_nested_submsg TSRMLS_DC) {
-  int i;
+bool DescriptorPool_HasFile(const char *filename) {
+  DescriptorPool *intern = GetPool(get_generated_pool());
+  return upb_symtab_lookupfile(intern->symtab, filename) != NULL;
+}
+
+void DescriptorPool_AddDescriptor(const char *filename, const char *data,
+                                  int size) {
+  upb_arena *arena = upb_arena_new();
+  const google_protobuf_FileDescriptorProto *file =
+      google_protobuf_FileDescriptorProto_parse(data, size, arena);
+
+  if (!file) {
+    zend_error(E_ERROR, "Failed to parse binary descriptor for %s\n", filename);
+    return;
+  }
+
+  add_descriptor(GetPool(get_generated_pool()), file);
+  upb_arena_free(arena);
+}
+
+/*
+ * DescriptorPool::internalAddGeneratedFile()
+ *
+ * Adds the given descriptor data to this DescriptorPool.
+ */
+PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
+  DescriptorPool *intern = GetPool(getThis());
+  char *data = NULL;
+  zend_long data_len;
+  zend_bool use_nested_submsg = false;
   upb_arena *arena;
 
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
+                            &use_nested_submsg) != SUCCESS) {
+    return;
+  }
+
   arena = upb_arena_new();
-  parse_and_add_descriptor(data, data_len, pool, arena,
-                           use_nested_submsg TSRMLS_CC);
+  add_descriptor_set(intern, data, data_len, arena);
   upb_arena_free(arena);
-  return;
 }
 
-PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
-  char *data = NULL;
-  PHP_PROTO_SIZE data_len;
-  zend_bool use_nested_submsg = false;
+ZEND_BEGIN_ARG_INFO_EX(arginfo_lookupByName, 0, 0, 1)
+  ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
-                            &data, &data_len, &use_nested_submsg) ==
-      FAILURE) {
-    return;
-  }
+ZEND_BEGIN_ARG_INFO_EX(arginfo_addgeneratedfile, 0, 0, 2)
+  ZEND_ARG_INFO(0, data)
+  ZEND_ARG_INFO(0, data_len)
+ZEND_END_ARG_INFO()
 
-  InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
-  internal_add_generated_file(data, data_len, pool->intern,
-                              use_nested_submsg TSRMLS_CC);
+static zend_function_entry DescriptorPool_methods[] = {
+  PHP_ME(DescriptorPool, getGeneratedPool, arginfo_void,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(DescriptorPool, getDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
+  PHP_ME(DescriptorPool, getDescriptorByProtoName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
+  PHP_ME(DescriptorPool, getEnumDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
+  PHP_ME(DescriptorPool, internalAddGeneratedFile, arginfo_addgeneratedfile, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+// -----------------------------------------------------------------------------
+// InternalDescriptorPool
+// -----------------------------------------------------------------------------
+
+// For the C extension, Google\Protobuf\Internal\DescriptorPool is not a
+// separate instantiable object, it just returns a
+// Google\Protobuf\DescriptorPool.
+
+zend_class_entry *InternalDescriptorPool_class_entry;
+
+/*
+ * InternalDescriptorPool::getGeneratedPool()
+ *
+ * Returns the generated DescriptorPool. Note that this is identical to
+ * DescriptorPool::getGeneratedPool(), and in fact returns a DescriptorPool
+ * instance.
+ */
+PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
+  RETURN_COPY(get_generated_pool());
 }
 
-PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
-  char *classname = NULL;
-  PHP_PROTO_SIZE classname_len;
+static zend_function_entry InternalDescriptorPool_methods[] = {
+  PHP_ME(InternalDescriptorPool, getGeneratedPool, arginfo_void,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
-                            &classname_len) == FAILURE) {
-    return;
-  }
+// -----------------------------------------------------------------------------
+// GPBType
+// -----------------------------------------------------------------------------
 
-  PHP_PROTO_CE_DECLARE pce;
-  if (php_proto_zend_lookup_class(classname, classname_len, &pce) ==
-      FAILURE) {
-    RETURN_NULL();
-  }
+zend_class_entry* gpb_type_type;
 
-  PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(PHP_PROTO_CE_UNREF(pce));
-  if (desc_php == NULL) {
-    DescriptorInternal* intern = get_ce_desc(PHP_PROTO_CE_UNREF(pce));
-    if (intern == NULL) {
-      RETURN_NULL();
-    }
+static zend_function_entry gpb_type_methods[] = {
+  ZEND_FE_END
+};
 
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(desc_php);
-    ZVAL_OBJ(desc_php, descriptor_type->create_object(
-                                   descriptor_type TSRMLS_CC));
-    Z_DELREF_P(desc_php);
-#else
-    desc_php =
-        descriptor_type->create_object(descriptor_type TSRMLS_CC);
-    GC_DELREF(desc_php);
-#endif
-    Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
-    desc->intern = intern;
-    add_def_obj(intern->msgdef, desc_php);
-    add_ce_obj(PHP_PROTO_CE_UNREF(pce), desc_php);
-  }
+// -----------------------------------------------------------------------------
+// Module Init
+// -----------------------------------------------------------------------------
 
-  zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc_php);
+void Def_ModuleInit() {
+  zend_class_entry tmp_ce;
+  zend_object_handlers *h;
 
-  if (!instanceof_function(instance_ce, descriptor_type TSRMLS_CC)) {
-    RETURN_NULL();
-  }
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor",
+                   OneofDescriptor_methods);
+  OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+  OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+  h = &OneofDescriptor_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = &OneofDescriptor_destructor;
 
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(desc_php, 1, 0);
-#else
-  GC_ADDREF(desc_php);
-  RETURN_OBJ(desc_php);
-#endif
-}
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor",
+                   EnumValueDescriptor_methods);
+  EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+  EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+  h = &EnumValueDescriptor_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
 
-PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
-  char *classname = NULL;
-  PHP_PROTO_SIZE classname_len;
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor",
+                   EnumDescriptor_methods);
+  EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+  EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+  h = &EnumDescriptor_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = &EnumDescriptor_destructor;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
-                            &classname_len) == FAILURE) {
-    return;
-  }
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor",
+                   Descriptor_methods);
 
-  PHP_PROTO_CE_DECLARE pce;
-  if (php_proto_zend_lookup_class(classname, classname_len, &pce) ==
-      FAILURE) {
-    RETURN_NULL();
-  }
+  Descriptor_class_entry = zend_register_internal_class(&tmp_ce);
+  Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  Descriptor_class_entry->create_object = CreateHandler_ReturnNull;
+  h = &Descriptor_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = Descriptor_destructor;
 
-  zend_class_entry* ce = PHP_PROTO_CE_UNREF(pce);
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor",
+                   FieldDescriptor_methods);
+  FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+  FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+  h = &FieldDescriptor_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = &FieldDescriptor_destructor;
 
-  PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(ce);
-  if (desc_php == NULL) {
-#if PHP_MAJOR_VERSION < 7
-    EnumDescriptorInternal* intern = get_class_enumdesc(ce->name);
-#else
-    EnumDescriptorInternal* intern = get_class_enumdesc(ZSTR_VAL(ce->name));
-#endif
-    register_class(intern, true TSRMLS_CC);
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DescriptorPool",
+                   DescriptorPool_methods);
+  DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
+  DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  DescriptorPool_class_entry->create_object = DescriptorPool_create;
+  h = &DescriptorPool_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = DescriptorPool_destructor;
 
-    if (intern == NULL) {
-      RETURN_NULL();
-    }
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",
+                   InternalDescriptorPool_methods);
+  InternalDescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
 
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(desc_php);
-    ZVAL_OBJ(desc_php, enum_descriptor_type->create_object(
-                                        enum_descriptor_type TSRMLS_CC));
-    Z_DELREF_P(desc_php);
-#else
-    desc_php =
-        enum_descriptor_type->create_object(enum_descriptor_type TSRMLS_CC);
-    GC_DELREF(desc_php);
-#endif
-    EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(EnumDescriptor, desc_php);
-    desc->intern = intern;
-    add_def_obj(intern->enumdef, desc_php);
-    add_ce_obj(ce, desc_php);
-  }
-
-  zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc_php);
-
-  if (!instanceof_function(instance_ce, enum_descriptor_type TSRMLS_CC)) {
-    RETURN_NULL();
-  }
-
-#if PHP_MAJOR_VERSION < 7
-  RETURN_ZVAL(desc_php, 1, 0);
-#else
-  GC_ADDREF(desc_php);
-  RETURN_OBJ(desc_php);
-#endif
+  // GPBType.
+#define STR(str) (str), strlen(str)
+  zend_class_entry class_type;
+  INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
+                   gpb_type_methods);
+  gpb_type_type = zend_register_internal_class(&class_type);
+  zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1);
+  zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2);
+  zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3);
+  zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4);
+  zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5);
+  zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6);
+  zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7);
+  zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8);
+  zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9);
+  zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10);
+  zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11);
+  zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12);
+  zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13);
+  zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14);
+  zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15);
+  zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16);
+  zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17);
+  zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18);
+#undef STR
 }
diff --git a/php/ext/google/protobuf/def.h b/php/ext/google/protobuf/def.h
new file mode 100644
index 0000000..e705642
--- /dev/null
+++ b/php/ext/google/protobuf/def.h
@@ -0,0 +1,95 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PHP_PROTOBUF_DEF_H_
+#define PHP_PROTOBUF_DEF_H_
+
+#include <php.h>
+
+#include "php-upb.h"
+
+// Initializes the Def module, which defines all of the descriptor classes.
+void Def_ModuleInit();
+
+// Creates a new DescriptorPool to wrap the given symtab. The DescriptorPool
+// takes ownership of the given symtab. If symtab is NULL, the DescriptorPool
+// will create an empty symtab instead.
+void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab);
+
+// Given a zval representing a DescriptorPool, steals and returns its symtab,
+// which is now owned by the caller.
+upb_symtab *DescriptorPool_Steal(zval *zv);
+
+upb_symtab *DescriptorPool_GetSymbolTable();
+
+// Returns true if the global descriptor pool already has the given filename.
+bool DescriptorPool_HasFile(const char *filename);
+
+// Adds the given descriptor with the given filename to the global pool.
+void DescriptorPool_AddDescriptor(const char *filename, const char *data, int size);
+
+typedef struct Descriptor {
+  zend_object std;
+  const upb_msgdef *msgdef;
+  zend_class_entry *class_entry;
+} Descriptor;
+
+// Gets or creates a Descriptor* for the given class entry, upb_msgdef, or
+// upb_fielddef. The returned Descriptor* will live for the entire request,
+// so no ref is necessary to keep it alive. The caller does *not* own a ref
+// on the returned object.
+Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce);
+Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m);
+Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f);
+
+// Packages up a upb_fieldtype_t with a Descriptor, since many functions need
+// both.
+typedef struct {
+  upb_fieldtype_t type;
+  const Descriptor *desc;  // When type == UPB_TYPE_MESSAGE.
+} TypeInfo;
+
+static inline TypeInfo TypeInfo_Get(const upb_fielddef *f) {
+  TypeInfo ret = {upb_fielddef_type(f), Descriptor_GetFromFieldDef(f)};
+  return ret;
+}
+
+static inline TypeInfo TypeInfo_FromType(upb_fieldtype_t type) {
+  TypeInfo ret = {type};
+  return ret;
+}
+
+static inline bool TypeInfo_Eq(TypeInfo a, TypeInfo b) {
+  if (a.type != b.type) return false;
+  if (a.type == UPB_TYPE_MESSAGE && a.desc != b.desc) return false;
+  return true;
+}
+
+#endif  // PHP_PROTOBUF_DEF_H_
diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c
deleted file mode 100644
index 8eaa5d2..0000000
--- a/php/ext/google/protobuf/encode_decode.c
+++ /dev/null
@@ -1,2283 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-#include <php.h>
-#include <Zend/zend_exceptions.h>
-
-#include "protobuf.h"
-#include "utf8.h"
-
-/* stringsink *****************************************************************/
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
-  stringsink *sink = _sink;
-  sink->len = 0;
-  return sink;
-}
-
-size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
-                         size_t len, const upb_bufhandle *handle) {
-  stringsink *sink = _sink;
-  size_t new_size = sink->size;
-
-  PHP_PROTO_UNUSED(hd);
-  PHP_PROTO_UNUSED(handle);
-
-  while (sink->len + len > new_size) {
-    new_size *= 2;
-  }
-
-  if (new_size != sink->size) {
-    sink->ptr = realloc(sink->ptr, new_size);
-    sink->size = new_size;
-  }
-
-  memcpy(sink->ptr + sink->len, ptr, len);
-  sink->len += len;
-
-  return len;
-}
-
-void stringsink_init(stringsink *sink) {
-  upb_byteshandler_init(&sink->handler);
-  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
-  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
-  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
-  sink->size = 32;
-  sink->ptr = malloc(sink->size);
-  PHP_PROTO_ASSERT(sink->ptr != NULL);
-  sink->len = 0;
-}
-
-void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
-
-void stringsink_uninit_opaque(void *sink) { stringsink_uninit(sink); }
-
-/* stackenv *****************************************************************/
-
-// Stack-allocated context during an encode/decode operation. Contains the upb
-// environment and its stack-based allocator, an initial buffer for allocations
-// to avoid malloc() when possible, and a template for PHP exception messages
-// if any error occurs.
-#define STACK_ENV_STACKBYTES 4096
-typedef struct {
-  upb_arena *arena;
-  upb_status status;
-  const char *php_error_template;
-  char allocbuf[STACK_ENV_STACKBYTES];
-} stackenv;
-
-
-static void stackenv_init(stackenv* se, const char* errmsg);
-static void stackenv_uninit(stackenv* se);
-
-static void stackenv_init(stackenv* se, const char* errmsg) {
-  se->php_error_template = errmsg;
-  se->arena = upb_arena_new();
-  upb_status_clear(&se->status);
-}
-
-static void stackenv_uninit(stackenv* se) {
-  upb_arena_free(se->arena);
-
-  if (!upb_ok(&se->status)) {
-    // TODO(teboring): have a way to verify that this is actually a parse error,
-    // instead of just throwing "parse error" unconditionally.
-    TSRMLS_FETCH();
-    zend_throw_exception_ex(NULL, 0 TSRMLS_CC, se->php_error_template,
-                            upb_status_errmsg(&se->status));
-  }
-}
-
-// -----------------------------------------------------------------------------
-// Parsing.
-// -----------------------------------------------------------------------------
-
-bool is_wrapper_msg(const upb_msgdef* m) {
-  switch (upb_msgdef_wellknowntype(m)) {
-    case UPB_WELLKNOWN_DOUBLEVALUE:
-    case UPB_WELLKNOWN_FLOATVALUE:
-    case UPB_WELLKNOWN_INT64VALUE:
-    case UPB_WELLKNOWN_UINT64VALUE:
-    case UPB_WELLKNOWN_INT32VALUE:
-    case UPB_WELLKNOWN_UINT32VALUE:
-    case UPB_WELLKNOWN_STRINGVALUE:
-    case UPB_WELLKNOWN_BYTESVALUE:
-    case UPB_WELLKNOWN_BOOLVALUE:
-      return true;
-    default:
-      return false;
-  }
-}
-
-typedef struct {
-  void* closure;
-  void* submsg;
-  bool is_msg;
-} wrapperfields_parseframe_t;
-
-#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
-
-// Creates a handlerdata that simply contains the offset for this field.
-static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
-  size_t* hd_ofs = (size_t*)malloc(sizeof(size_t));
-  PHP_PROTO_ASSERT(hd_ofs != NULL);
-  *hd_ofs = ofs;
-  upb_handlers_addcleanup(h, hd_ofs, free);
-  return hd_ofs;
-}
-
-static const void* newhandlerfielddata(
-    upb_handlers* h, const upb_fielddef* field) {
-  const void** hd_field = malloc(sizeof(void*));
-  PHP_PROTO_ASSERT(hd_field != NULL);
-  *hd_field = field;
-  upb_handlers_addcleanup(h, hd_field, free);
-  return hd_field;
-}
-
-typedef struct {
-  void* closure;
-  stringsink sink;
-} stringfields_parseframe_t;
-
-typedef size_t (*encodeunknown_handlerfunc)(void* _sink, const void* hd,
-                                            const char* ptr, size_t len,
-                                            const upb_bufhandle* handle);
-
-typedef struct {
-  encodeunknown_handlerfunc handler;
-} unknownfields_handlerdata_t;
-
-// Creates a handlerdata for unknown fields.
-static const void *newunknownfieldshandlerdata(upb_handlers* h) {
-  unknownfields_handlerdata_t* hd =
-      (unknownfields_handlerdata_t*)malloc(sizeof(unknownfields_handlerdata_t));
-  PHP_PROTO_ASSERT(hd != NULL);
-  hd->handler = stringsink_string;
-  upb_handlers_addcleanup(h, hd, free);
-  return hd;
-}
-
-typedef struct {
-  const upb_fielddef *fd;
-  size_t ofs;
-  const upb_msgdef *md;
-} submsg_handlerdata_t;
-
-// Creates a handlerdata that contains field and submessage type information.
-static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
-                                        const upb_fielddef* f) {
-  submsg_handlerdata_t* hd =
-      (submsg_handlerdata_t*)malloc(sizeof(submsg_handlerdata_t));
-  PHP_PROTO_ASSERT(hd != NULL);
-  hd->fd = f;
-  hd->ofs = ofs;
-  hd->md = upb_fielddef_msgsubdef(f);
-  upb_handlers_addcleanup(h, hd, free);
-  return hd;
-}
-
-typedef struct {
-  size_t ofs;              // union data slot
-  size_t case_ofs;         // oneof_case field
-  int property_ofs;        // properties table cache
-  uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
-  const upb_msgdef *md;    // msgdef, for oneof submessage handler
-  const upb_msgdef *parent_md;  // msgdef, for parent submessage
-} oneof_handlerdata_t;
-
-static const void *newoneofhandlerdata(upb_handlers *h,
-                                       uint32_t ofs,
-                                       uint32_t case_ofs,
-                                       int property_ofs,
-                                       const upb_msgdef *m,
-                                       const upb_fielddef *f) {
-  oneof_handlerdata_t* hd =
-      (oneof_handlerdata_t*)malloc(sizeof(oneof_handlerdata_t));
-  PHP_PROTO_ASSERT(hd != NULL);
-  hd->ofs = ofs;
-  hd->case_ofs = case_ofs;
-  hd->property_ofs = property_ofs;
-  hd->parent_md = m;
-  // We reuse the field tag number as a oneof union discriminant tag. Note that
-  // we don't expose these numbers to the user, so the only requirement is that
-  // we have some unique ID for each union case/possibility. The field tag
-  // numbers are already present and are easy to use so there's no reason to
-  // create a separate ID space. In addition, using the field tag number here
-  // lets us easily look up the field in the oneof accessor.
-  hd->oneof_case_num = upb_fielddef_number(f);
-  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
-    hd->md = upb_fielddef_msgsubdef(f);
-  } else {
-    hd->md = NULL;
-  }
-  upb_handlers_addcleanup(h, hd, free);
-  return hd;
-}
-
-// A handler that starts a repeated field.  Gets the Repeated*Field instance for
-// this field (such an instance always exists even in an empty message).
-static void *startseq_handler(void* closure, const void* hd) {
-  MessageHeader* msg = closure;
-  const upb_fielddef** field = (const upb_fielddef**) hd;
-  CACHED_VALUE* cache = find_zval_property(msg, *field);
-  TSRMLS_FETCH();
-  repeated_field_ensure_created(*field, cache PHP_PROTO_TSRMLS_CC);
-  return CACHED_PTR_TO_ZVAL_PTR(cache);
-}
-
-// Handlers that append primitive values to a repeated field.
-#define DEFINE_APPEND_HANDLER(type, ctype)                          \
-  static bool append##type##_handler(void* closure, const void* hd, \
-                                     ctype val) {                   \
-    zval* array = (zval*)closure;                                   \
-    TSRMLS_FETCH();                                                 \
-    RepeatedField* intern = UNBOX(RepeatedField, array);            \
-    repeated_field_push_native(intern, &val);                       \
-    return true;                                                    \
-  }
-
-DEFINE_APPEND_HANDLER(bool,   bool)
-DEFINE_APPEND_HANDLER(int32,  int32_t)
-DEFINE_APPEND_HANDLER(uint32, uint32_t)
-DEFINE_APPEND_HANDLER(float,  float)
-DEFINE_APPEND_HANDLER(int64,  int64_t)
-DEFINE_APPEND_HANDLER(uint64, uint64_t)
-DEFINE_APPEND_HANDLER(double, double)
-
-// Appends a string or 'bytes' string to a repeated field.
-static void* appendstr_handler(void *closure,
-                               const void *hd,
-                               size_t size_hint) {
-  PHP_PROTO_UNUSED(hd);
-
-  stringfields_parseframe_t* frame =
-      (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
-  PHP_PROTO_ASSERT(frame != NULL);
-  frame->closure = closure;
-  stringsink_init(&frame->sink);
-
-  return frame;
-}
-
-static bool appendstr_end_handler(void *closure, const void *hd) {
-  stringfields_parseframe_t* frame = closure;
-
-  zval* array = (zval*)frame->closure;
-  TSRMLS_FETCH();
-  RepeatedField* intern = UNBOX(RepeatedField, array);
-
-#if PHP_MAJOR_VERSION < 7
-  zval* str;
-  MAKE_STD_ZVAL(str);
-  PHP_PROTO_ZVAL_STRINGL(str, frame->sink.ptr, frame->sink.len, 1);
-  repeated_field_push_native(intern, &str);
-#else
-  zend_string* str = zend_string_init(frame->sink.ptr, frame->sink.len, 1);
-  repeated_field_push_native(intern, &str);
-#endif
-
-  stringsink_uninit(&frame->sink);
-  free(frame);
-
-  return true;
-}
-
-// Handlers that append primitive values to a repeated field.
-#define DEFINE_SINGULAR_HANDLER(type, ctype)                \
-  static bool type##_handler(void* closure, const void* hd, \
-                                     ctype val) {           \
-    MessageHeader* msg = (MessageHeader*)closure;           \
-    const size_t *ofs = hd;                                 \
-    DEREF(message_data(msg), *ofs, ctype) = val;            \
-    return true;                                            \
-  }
-
-DEFINE_SINGULAR_HANDLER(bool,   bool)
-DEFINE_SINGULAR_HANDLER(int32,  int32_t)
-DEFINE_SINGULAR_HANDLER(uint32, uint32_t)
-DEFINE_SINGULAR_HANDLER(float,  float)
-DEFINE_SINGULAR_HANDLER(int64,  int64_t)
-DEFINE_SINGULAR_HANDLER(uint64, uint64_t)
-DEFINE_SINGULAR_HANDLER(double, double)
-
-#undef DEFINE_SINGULAR_HANDLER
-
-#if PHP_MAJOR_VERSION < 7
-static void new_php_string(zval** value_ptr, const char* str, size_t len) {
-  SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
-  if (Z_TYPE_PP(value_ptr) == IS_STRING &&
-      !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
-    FREE(Z_STRVAL_PP(value_ptr));
-  }
-  ZVAL_STRINGL(*value_ptr, str, len, 1);
-}
-#else
-static void new_php_string(zval* value_ptr, const char* str, size_t len) {
-  if (Z_TYPE_P(value_ptr) == IS_STRING) {
-    zend_string_release(Z_STR_P(value_ptr));
-  }
-  ZVAL_NEW_STR(value_ptr, zend_string_init(str, len, 0));
-}
-#endif
-
-// Sets a non-repeated string/bytes field in a message.
-static void* str_handler(void *closure,
-                         const void *hd,
-                         size_t size_hint) {
-  PHP_PROTO_UNUSED(hd);
-
-  stringfields_parseframe_t* frame =
-      (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
-  PHP_PROTO_ASSERT(frame != NULL);
-  frame->closure = closure;
-  stringsink_init(&frame->sink);
-
-  return frame;
-}
-
-static bool str_end_handler(void *closure, const void *hd) {
-  stringfields_parseframe_t* frame = closure;
-  const upb_fielddef **field = (const upb_fielddef **) hd;
-  MessageHeader* msg = (MessageHeader*)frame->closure;
-
-  CACHED_VALUE* cached = find_zval_property(msg, *field);
-
-  new_php_string(cached, frame->sink.ptr, frame->sink.len);
-
-  stringsink_uninit(&frame->sink);
-  free(frame);
-
-  return true;
-}
-
-static bool map_str_end_handler(void *closure, const void *hd) {
-  stringfields_parseframe_t* frame = closure;
-  const size_t *ofs = hd;
-  MessageHeader* msg = (MessageHeader*)frame->closure;
-
-  new_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*),
-                 frame->sink.ptr, frame->sink.len);
-
-  stringsink_uninit(&frame->sink);
-  free(frame);
-
-  return true;
-}
-
-static size_t stringdata_handler(void* closure, const void* hd,
-                                 const char* str, size_t len,
-                                 const upb_bufhandle* handle) {
-  stringfields_parseframe_t* frame = closure;
-  return stringsink_string(&frame->sink, hd, str, len, handle);
-}
-
-// Appends a submessage to a repeated field.
-static void *appendsubmsg_handler(void *closure, const void *hd) {
-  zval* array = (zval*)closure;
-  TSRMLS_FETCH();
-  RepeatedField* intern = UNBOX(RepeatedField, array);
-
-  const submsg_handlerdata_t *submsgdata = hd;
-  DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  zend_class_entry* subklass = subdesc->klass;
-  MessageHeader* submsg;
-
-#if PHP_MAJOR_VERSION < 7
-  zval* val = NULL;
-  MAKE_STD_ZVAL(val);
-  ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
-  repeated_field_push_native(intern, &val);
-  submsg = UNBOX(MessageHeader, val);
-#else
-  zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-  repeated_field_push_native(intern, &obj);
-  submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
-#endif
-  custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-
-  return submsg;
-}
-
-// Appends a wrapper submessage to a repeated field.
-static void *appendwrappersubmsg_handler(void *closure, const void *hd) {
-  zval* array = (zval*)closure;
-  TSRMLS_FETCH();
-  RepeatedField* intern = UNBOX(RepeatedField, array);
-
-  const submsg_handlerdata_t *submsgdata = hd;
-  DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  zend_class_entry* subklass = subdesc->klass;
-  MessageHeader* submsg;
-  wrapperfields_parseframe_t* frame =
-      (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
-
-#if PHP_MAJOR_VERSION < 7
-  zval* val = NULL;
-  MAKE_STD_ZVAL(val);
-  ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
-  repeated_field_push_native(intern, &val);
-  submsg = UNBOX(MessageHeader, val);
-#else
-  zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-  repeated_field_push_native(intern, &obj);
-  submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
-#endif
-  custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-
-  frame->closure = closure;
-  frame->submsg = submsg;
-  frame->is_msg = true;
-
-  return frame;
-}
-
-// Sets a non-repeated submessage field in a message.
-static void *submsg_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const submsg_handlerdata_t* submsgdata = hd;
-  TSRMLS_FETCH();
-  DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  zend_class_entry* subklass = subdesc->klass;
-  zval* submsg_php;
-  MessageHeader* submsg;
-
-  CACHED_VALUE* cached = find_zval_property(msg, submsgdata->fd);
-
-  if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-#if PHP_MAJOR_VERSION < 7
-    zval val;
-    ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
-    MessageHeader* intern = UNBOX(MessageHeader, &val);
-    custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-    REPLACE_ZVAL_VALUE(cached, &val, 1);
-    zval_dtor(&val);
-#else
-    zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-    ZVAL_OBJ(cached, obj);
-    MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
-    custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-#endif
-  }
-
-  submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
-
-  submsg = UNBOX(MessageHeader, submsg_php);
-  return submsg;
-}
-
-static void *map_submsg_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const submsg_handlerdata_t* submsgdata = hd;
-  TSRMLS_FETCH();
-  DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  zend_class_entry* subklass = subdesc->klass;
-  zval* submsg_php;
-  MessageHeader* submsg;
-
-  CACHED_VALUE* cached =
-      DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*);
-
-  if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-#if PHP_MAJOR_VERSION < 7
-    zval val;
-    ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
-    MessageHeader* intern = UNBOX(MessageHeader, &val);
-    custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-    REPLACE_ZVAL_VALUE(cached, &val, 1);
-    zval_dtor(&val);
-#else
-    zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-    ZVAL_OBJ(cached, obj);
-    MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
-    custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-#endif
-  }
-
-  submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
-
-  submsg = UNBOX(MessageHeader, submsg_php);
-  return submsg;
-}
-
-static void *map_wrapper_submsg_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const submsg_handlerdata_t* submsgdata = hd;
-  TSRMLS_FETCH();
-  DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  zend_class_entry* subklass = subdesc->klass;
-  zval* submsg_php;
-  MessageHeader* submsg;
-  wrapperfields_parseframe_t* frame =
-      (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
-
-  CACHED_VALUE* cached =
-      DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*);
-
-  if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-#if PHP_MAJOR_VERSION < 7
-    zval val;
-    ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
-    MessageHeader* intern = UNBOX(MessageHeader, &val);
-    custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-    REPLACE_ZVAL_VALUE(cached, &val, 1);
-    zval_dtor(&val);
-#else
-    zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-    ZVAL_OBJ(cached, obj);
-    MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
-    custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-#endif
-  }
-
-  submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
-
-  submsg = UNBOX(MessageHeader, submsg_php);
-  frame->closure = closure;
-  frame->submsg = submsg;
-  frame->is_msg = true;
-  return frame;
-}
-
-// Handler data for startmap/endmap handlers.
-typedef struct {
-  const upb_fielddef* fd;
-  const upb_msgdef* value_md;
-  upb_fieldtype_t key_field_type;
-  upb_fieldtype_t value_field_type;
-} map_handlerdata_t;
-
-// Temporary frame for map parsing: at the beginning of a map entry message, a
-// submsg handler allocates a frame to hold (i) a reference to the Map object
-// into which this message will be inserted and (ii) storage slots to
-// temporarily hold the key and value for this map entry until the end of the
-// submessage. When the submessage ends, another handler is called to insert the
-// value into the map.
-typedef struct {
-  char key_storage[NATIVE_SLOT_MAX_SIZE];
-  char value_storage[NATIVE_SLOT_MAX_SIZE];
-} map_parse_frame_data_t;
-
-PHP_PROTO_WRAP_OBJECT_START(map_parse_frame_t)
-  map_parse_frame_data_t* data;  // Place needs to be consistent with
-                                 // MessageHeader.
-  zval* map;
-  // In php7, we cannot allocate zval dynamically. So we need to add zval here
-  // to help decoding.
-  zval key_zval;
-  zval value_zval;
-PHP_PROTO_WRAP_OBJECT_END
-typedef struct map_parse_frame_t map_parse_frame_t;
-
-static void map_slot_init(
-    void* memory, upb_fieldtype_t type, zval* cache,
-    const upb_msgdef* value_msg PHP_PROTO_TSRMLS_DC) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
-      // Store zval** in memory in order to be consistent with the layout of
-      // singular fields.
-      zval** holder = ALLOC(zval*);
-      *(zval***)memory = holder;
-      zval* tmp;
-      MAKE_STD_ZVAL(tmp);
-      PHP_PROTO_ZVAL_STRINGL(tmp, "", 0, 1);
-      *holder = tmp;
-#else
-      *(zval**)memory = cache;
-      PHP_PROTO_ZVAL_STRINGL(*(zval**)memory, "", 0, 1);
-#endif
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      DescriptorInternal* subdesc = get_msgdef_desc(value_msg);
-      register_class(subdesc, false TSRMLS_CC);
-      zend_class_entry* subklass = subdesc->klass;
-      MessageHeader* submsg;
-#if PHP_MAJOR_VERSION < 7
-      zval** holder = ALLOC(zval*);
-      zval* tmp;
-      MAKE_STD_ZVAL(tmp);
-      ZVAL_OBJ(tmp, subklass->create_object(subklass TSRMLS_CC));
-      submsg = UNBOX(MessageHeader, tmp);
-      custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-      *holder = tmp;
-      *(zval***)memory = holder;
-#else
-      *(zval**)memory = cache;
-      ZVAL_OBJ(*(zval**)memory, subklass->create_object(subklass TSRMLS_CC));
-      submsg = UNBOX(MessageHeader, cache);
-      custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-#endif
-      break;
-    }
-    default:
-      native_slot_init(type, memory, NULL);
-  }
-}
-
-static void map_slot_uninit(void* memory, upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_MESSAGE:
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
-      zval** holder = *(zval***)memory;
-      zval_ptr_dtor(holder);
-      FREE(holder);
-#else
-      php_proto_zval_ptr_dtor(*(zval**)memory);
-#endif
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-static void map_slot_key(upb_fieldtype_t type, const void* from,
-                         const char** keyval,
-                         size_t* length) {
-  if (type == UPB_TYPE_STRING) {
-#if PHP_MAJOR_VERSION < 7
-    zval* key_php = **(zval***)from;
-#else
-    zval* key_php = *(zval**)from;
-#endif
-    *keyval = Z_STRVAL_P(key_php);
-    *length = Z_STRLEN_P(key_php);
-  } else {
-    *keyval = from;
-    *length = native_slot_size(type);
-  }
-}
-
-static void map_slot_value(upb_fieldtype_t type, const void* from,
-                           upb_value* v) {
-  size_t len;
-  void* to = upb_value_memory(v);
-#ifndef NDEBUG
-  v->ctype = UPB_CTYPE_UINT64;
-#endif
-
-  memset(to, 0, native_slot_size(type));
-
-  switch (type) {
-#if PHP_MAJOR_VERSION < 7
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_MESSAGE: {
-      *(zval**)to = **(zval***)from;
-      Z_ADDREF_PP((zval**)to);
-      break;
-    }
-#else
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      *(zend_string**)to = Z_STR_P(*(zval**)from);
-      zend_string_addref(*(zend_string**)to);
-      break;
-    case UPB_TYPE_MESSAGE:
-      if (!ZVAL_IS_NULL(*(zval**)from)) {
-        *(zend_object**)to = Z_OBJ_P(*(zval**)from);
-        GC_ADDREF(*(zend_object**)to);
-      }
-      break;
-#endif
-    default:
-      len = native_slot_size(type);
-      memcpy(to, from, len);
-  }
-}
-
-// Handler to begin a map entry: allocates a temporary frame. This is the
-// 'startsubmsg' handler on the msgdef that contains the map field.
-static void *startmapentry_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const map_handlerdata_t* mapdata = hd;
-  CACHED_VALUE* cache = find_zval_property(msg, mapdata->fd);
-  TSRMLS_FETCH();
-  map_field_ensure_created(mapdata->fd, cache PHP_PROTO_TSRMLS_CC);
-  zval* map = CACHED_PTR_TO_ZVAL_PTR(cache);
-
-  map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
-  frame->data = ALLOC(map_parse_frame_data_t);
-  frame->map = map;
-
-  map_slot_init(&frame->data->key_storage, mapdata->key_field_type,
-                &frame->key_zval, NULL PHP_PROTO_TSRMLS_CC);
-  map_slot_init(&frame->data->value_storage, mapdata->value_field_type,
-                &frame->value_zval, mapdata->value_md PHP_PROTO_TSRMLS_CC);
-
-  return frame;
-}
-
-// Handler to end a map entry: inserts the value defined during the message into
-// the map. This is the 'endmsg' handler on the map entry msgdef.
-static bool endmap_handler(void* closure, const void* hd, upb_status* s) {
-  map_parse_frame_t* frame = closure;
-  const map_handlerdata_t* mapdata = hd;
-
-  TSRMLS_FETCH();
-  Map *map = UNBOX(Map, frame->map);
-
-  const char* keyval = NULL;
-  upb_value v;
-  size_t length;
-
-  map_slot_key(map->key_type, &frame->data->key_storage, &keyval, &length);
-  map_slot_value(map->value_type, &frame->data->value_storage, &v);
-
-  map_index_set(map, keyval, length, v);
-
-  map_slot_uninit(&frame->data->key_storage, mapdata->key_field_type);
-  map_slot_uninit(&frame->data->value_storage, mapdata->value_field_type);
-  FREE(frame->data);
-  FREE(frame);
-
-  return true;
-}
-
-// Allocates a new map_handlerdata_t given the map entry message definition. If
-// the offset of the field within the parent message is also given, that is
-// added to the handler data as well. Note that this is called *twice* per map
-// field: once in the parent message handler setup when setting the startsubmsg
-// handler and once in the map entry message handler setup when setting the
-// key/value and endmsg handlers. The reason is that there is no easy way to
-// pass the handlerdata down to the sub-message handler setup.
-static map_handlerdata_t* new_map_handlerdata(
-    const upb_fielddef* field,
-    const upb_msgdef* mapentry_def) {
-  const upb_fielddef* key_field;
-  const upb_fielddef* value_field;
-  // TODO(teboring): Use emalloc and efree.
-  map_handlerdata_t* hd =
-      (map_handlerdata_t*)malloc(sizeof(map_handlerdata_t));
-  PHP_PROTO_ASSERT(hd != NULL);
-  hd->fd = field;
-  key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
-  PHP_PROTO_ASSERT(key_field != NULL);
-  hd->key_field_type = upb_fielddef_type(key_field);
-  value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
-  PHP_PROTO_ASSERT(value_field != NULL);
-  hd->value_field_type = upb_fielddef_type(value_field);
-  if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE) {
-    hd->value_md = upb_fielddef_msgsubdef(value_field);
-  } else {
-    hd->value_md = NULL;
-  }
-
-  return hd;
-}
-
-// Handlers that set primitive values in oneofs.
-#define DEFINE_ONEOF_HANDLER(type, ctype)                          \
-  static bool oneof##type##_handler(void* closure, const void* hd, \
-                                    ctype val) {                   \
-    const oneof_handlerdata_t* oneofdata = hd;                     \
-    DEREF(message_data(closure), oneofdata->case_ofs, uint32_t) =  \
-        oneofdata->oneof_case_num;                                 \
-    DEREF(message_data(closure), oneofdata->ofs, ctype) = val;     \
-    return true;                                                   \
-  }
-
-DEFINE_ONEOF_HANDLER(bool,   bool)
-DEFINE_ONEOF_HANDLER(int32,  int32_t)
-DEFINE_ONEOF_HANDLER(uint32, uint32_t)
-DEFINE_ONEOF_HANDLER(float,  float)
-DEFINE_ONEOF_HANDLER(int64,  int64_t)
-DEFINE_ONEOF_HANDLER(uint64, uint64_t)
-DEFINE_ONEOF_HANDLER(double, double)
-
-#undef DEFINE_ONEOF_HANDLER
-
-static void oneof_cleanup(MessageHeader* msg,
-                          const oneof_handlerdata_t* oneofdata) {
-  uint32_t old_case_num =
-      DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
-  if (old_case_num == 0) {
-    return;
-  }
-
-  const upb_fielddef* old_field =
-      upb_msgdef_itof(oneofdata->parent_md, old_case_num);
-  bool need_clean = false;
-
-  switch (upb_fielddef_type(old_field)) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      need_clean = true;
-      break;
-    case UPB_TYPE_MESSAGE:
-      if (oneofdata->oneof_case_num != old_case_num) {
-        need_clean = true;
-      }
-      break;
-    default:
-      break;
-  }
-
-  if (need_clean) {
-#if PHP_MAJOR_VERSION < 7
-    SEPARATE_ZVAL_IF_NOT_REF(
-        DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
-    php_proto_zval_ptr_dtor(
-        *DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
-    MAKE_STD_ZVAL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
-    ZVAL_NULL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
-#endif
-  }
-}
-
-// Handlers for string/bytes in a oneof.
-static bool oneofstr_end_handler(void *closure, const void *hd) {
-  stringfields_parseframe_t* frame = closure;
-  MessageHeader* msg = (MessageHeader*)frame->closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-
-  oneof_cleanup(msg, oneofdata);
-
-  DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
-      oneofdata->oneof_case_num;
-  DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
-      OBJ_PROP(&msg->std, oneofdata->property_ofs);
-
-  new_php_string(DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*),
-                 frame->sink.ptr, frame->sink.len);
-
-  stringsink_uninit(&frame->sink);
-  free(frame);
-
-  return true;
-}
-
-static void *oneofstr_handler(void *closure,
-                              const void *hd,
-                              size_t size_hint) {
-  PHP_PROTO_UNUSED(hd);
-
-  stringfields_parseframe_t* frame =
-      (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
-  PHP_PROTO_ASSERT(frame != NULL);
-  frame->closure = closure;
-  stringsink_init(&frame->sink);
-
-  return frame;
-}
-
-// Handler for a submessage field in a oneof.
-static void* oneofsubmsg_handler(void* closure, const void* hd) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
-  TSRMLS_FETCH();
-  DescriptorInternal* subdesc = get_msgdef_desc(oneofdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  zend_class_entry* subklass = subdesc->klass;
-  zval* submsg_php;
-  MessageHeader* submsg;
-
-  if (oldcase != oneofdata->oneof_case_num) {
-    oneof_cleanup(msg, oneofdata);
-
-    // Create new message.
-    DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
-        OBJ_PROP(&msg->std, oneofdata->property_ofs);
-#if PHP_MAJOR_VERSION < 7
-    zval val;
-    ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
-    REPLACE_ZVAL_VALUE(DEREF(message_data(msg), oneofdata->ofs, zval**),
-                       &val, 1);
-    zval_dtor(&val);
-#else
-    zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-    ZVAL_OBJ(DEREF(message_data(msg), oneofdata->ofs, zval*), obj);
-#endif
-  }
-
-  DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
-      oneofdata->oneof_case_num;
-
-  submsg_php = CACHED_PTR_TO_ZVAL_PTR(
-      DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
-  submsg = UNBOX(MessageHeader, submsg_php);
-  custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-  return submsg;
-}
-
-// Sets a non-repeated wrapper submessage field in a message.
-static void* wrapper_submsg_handler(void* closure, const void* hd) {
-  MessageHeader* msg = closure;
-  const submsg_handlerdata_t* submsgdata = hd;
-  TSRMLS_FETCH();
-  DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  zval* submsg_php;
-  MessageHeader* submsg;
-  wrapperfields_parseframe_t* frame =
-      (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
-
-  CACHED_VALUE* cached = find_zval_property(msg, submsgdata->fd);
-  submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
-  frame->closure = closure;
-
-  if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_OBJECT) {
-    submsg = UNBOX(MessageHeader, submsg_php);
-    frame->submsg = submsg;
-    frame->is_msg = true;
-  } else {
-    if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-      // Needs to initiate the wrapper message
-      const upb_msgdef* msgdef = subdesc->msgdef;
-      const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
-      native_slot_get_default(upb_fielddef_type(f), cached TSRMLS_CC);
-    }
-    // In this case, wrapper message hasn't been created and value will be
-    // stored in cache directly.
-    frame->submsg = cached;
-    frame->is_msg = false;
-  }
-
-  return frame;
-}
-
-// Handler for a wrapper submessage field in a oneof.
-static void* wrapper_oneofsubmsg_handler(void* closure, const void* hd) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
-  TSRMLS_FETCH();
-  DescriptorInternal* subdesc = get_msgdef_desc(oneofdata->md);
-  register_class(subdesc, false TSRMLS_CC);
-  wrapperfields_parseframe_t* frame =
-      (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
-  CACHED_VALUE* cached = OBJ_PROP(&msg->std, oneofdata->property_ofs);
-  MessageHeader* submsg;
-
-  if (oldcase != oneofdata->oneof_case_num) {
-    oneof_cleanup(msg, oneofdata);
-    if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-      // Needs to initiate the wrapper message
-      const upb_msgdef* msgdef = subdesc->msgdef;
-      const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
-      native_slot_get_default(upb_fielddef_type(f), cached TSRMLS_CC);
-    }
-    frame->submsg = cached;
-    frame->is_msg = false;
-  } else if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_OBJECT) {
-    submsg = UNBOX(MessageHeader, CACHED_PTR_TO_ZVAL_PTR(cached));
-    frame->submsg = submsg;
-    frame->is_msg = true;
-  } else {
-    // In this case, wrapper message hasn't been created and value will be
-    // stored in cache directly.
-    frame->submsg = cached;
-    frame->is_msg = false;
-  }
-
-  DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
-      oneofdata->oneof_case_num;
-
-  return frame;
-}
-
-static bool wrapper_submsg_end_handler(void *closure, const void *hd) {
-  wrapperfields_parseframe_t* frame = closure;
-  free(frame);
-  return true;
-}
-
-// Set up handlers for a repeated field.
-static void add_handlers_for_repeated_field(upb_handlers *h,
-                                            const upb_fielddef *f,
-                                            size_t offset) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  attr.handler_data = newhandlerfielddata(h, f);
-  upb_handlers_setstartseq(h, f, startseq_handler, &attr);
-
-  switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype)                                 \
-  case utype:                                                     \
-    upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
-    break;
-
-    SET_HANDLER(UPB_TYPE_BOOL,   bool);
-    SET_HANDLER(UPB_TYPE_INT32,  int32);
-    SET_HANDLER(UPB_TYPE_UINT32, uint32);
-    SET_HANDLER(UPB_TYPE_ENUM,   int32);
-    SET_HANDLER(UPB_TYPE_FLOAT,  float);
-    SET_HANDLER(UPB_TYPE_INT64,  int64);
-    SET_HANDLER(UPB_TYPE_UINT64, uint64);
-    SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      upb_handlers_setstartstr(h, f, appendstr_handler, NULL);
-      upb_handlers_setstring(h, f, stringdata_handler, NULL);
-      upb_handlers_setendstr(h, f, appendstr_end_handler, &attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newsubmsghandlerdata(h, 0, f);
-      if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, appendwrappersubmsg_handler, &attr);
-        upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
-      }
-      break;
-    }
-  }
-}
-
-// Set up handlers for a singular field.
-static void add_handlers_for_singular_field(upb_handlers *h,
-                                            const upb_fielddef *f,
-                                            size_t offset, bool is_map) {
-  switch (upb_fielddef_type(f)) {
-#define SET_HANDLER(utype, ltype)                          \
-  case utype: {                                            \
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;           \
-    attr.handler_data = newhandlerdata(h, offset);         \
-    upb_handlers_set##ltype(h, f, ltype##_handler, &attr); \
-    break;                                                 \
-  }
-
-    SET_HANDLER(UPB_TYPE_BOOL,   bool);
-    SET_HANDLER(UPB_TYPE_INT32,  int32);
-    SET_HANDLER(UPB_TYPE_UINT32, uint32);
-    SET_HANDLER(UPB_TYPE_ENUM,   int32);
-    SET_HANDLER(UPB_TYPE_FLOAT,  float);
-    SET_HANDLER(UPB_TYPE_INT64,  int64);
-    SET_HANDLER(UPB_TYPE_UINT64, uint64);
-    SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      if (is_map) {
-        attr.handler_data = newhandlerdata(h, offset);
-      } else {
-        attr.handler_data = newhandlerfielddata(h, f);
-      }
-      upb_handlers_setstartstr(h, f, str_handler, &attr);
-      upb_handlers_setstring(h, f, stringdata_handler, &attr);
-      if (is_map) {
-        upb_handlers_setendstr(h, f, map_str_end_handler, &attr);
-      } else {
-        upb_handlers_setendstr(h, f, str_end_handler, &attr);
-      }
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      if (is_map) {
-        attr.handler_data = newsubmsghandlerdata(h, offset, f);
-        if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
-          upb_handlers_setstartsubmsg(h, f, map_wrapper_submsg_handler, &attr);
-          upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
-        } else {
-          upb_handlers_setstartsubmsg(h, f, map_submsg_handler, &attr);
-        }
-      } else if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
-        attr.handler_data = newsubmsghandlerdata(h, 0, f);
-        upb_handlers_setstartsubmsg(h, f, wrapper_submsg_handler, &attr);
-        upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
-      } else {
-        attr.handler_data = newsubmsghandlerdata(h, 0, f);
-        upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
-      }
-      break;
-    }
-  }
-}
-
-// Adds handlers to a map field.
-static void add_handlers_for_mapfield(upb_handlers* h,
-                                      const upb_fielddef* fielddef,
-                                      size_t offset) {
-  const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
-  map_handlerdata_t* hd = new_map_handlerdata(fielddef, map_msgdef);
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_addcleanup(h, hd, free);
-  attr.handler_data = hd;
-  upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
-}
-
-// Adds handlers to a map-entry msgdef.
-static void add_handlers_for_mapentry(
-    const upb_msgdef* msgdef, upb_handlers* h) {
-  const upb_fielddef* key_field = map_entry_key(msgdef);
-  const upb_fielddef* value_field = map_entry_value(msgdef);
-  map_handlerdata_t* hd = new_map_handlerdata(0, msgdef);
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_addcleanup(h, hd, free);
-  attr.handler_data = hd;
-  upb_handlers_setendmsg(h, endmap_handler, &attr);
-
-  add_handlers_for_singular_field(h, key_field,
-                                  offsetof(map_parse_frame_data_t,
-                                           key_storage), true);
-  add_handlers_for_singular_field(h, value_field,
-                                  offsetof(map_parse_frame_data_t,
-                                           value_storage), true);
-}
-
-// Set up handlers for a oneof field.
-static void add_handlers_for_oneof_field(upb_handlers *h,
-                                         const upb_msgdef *m,
-                                         const upb_fielddef *f,
-                                         size_t offset,
-                                         size_t oneof_case_offset,
-                                         int property_cache_offset) {
-
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  attr.handler_data = newoneofhandlerdata(h, offset, oneof_case_offset,
-                                          property_cache_offset, m, f);
-
-  switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype)                                 \
-  case utype:                                                     \
-    upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
-    break;
-
-    SET_HANDLER(UPB_TYPE_BOOL,   bool);
-    SET_HANDLER(UPB_TYPE_INT32,  int32);
-    SET_HANDLER(UPB_TYPE_UINT32, uint32);
-    SET_HANDLER(UPB_TYPE_ENUM,   int32);
-    SET_HANDLER(UPB_TYPE_FLOAT,  float);
-    SET_HANDLER(UPB_TYPE_INT64,  int64);
-    SET_HANDLER(UPB_TYPE_UINT64, uint64);
-    SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      upb_handlers_setstartstr(h, f, oneofstr_handler, &attr);
-      upb_handlers_setstring(h, f, stringdata_handler, NULL);
-      upb_handlers_setendstr(h, f, oneofstr_end_handler, &attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, wrapper_oneofsubmsg_handler, &attr);
-        upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
-      }
-      break;
-    }
-  }
-}
-
-#define DEFINE_WRAPPER_HANDLER(utype, type, ctype)           \
-  static bool type##wrapper_handler(                         \
-      void* closure, const void* hd, ctype val) {            \
-    wrapperfields_parseframe_t* frame = closure;             \
-    if (frame->is_msg) {                                     \
-      MessageHeader* msg = frame->submsg;                    \
-      const size_t *ofs = hd;                                \
-      DEREF(message_data(msg), *ofs, ctype) = val;           \
-    } else {                                                 \
-      TSRMLS_FETCH();                                        \
-      native_slot_get(utype, &val, frame->submsg TSRMLS_CC); \
-    }                                                        \
-    return true;                                             \
-  }
-
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_BOOL,   bool,   bool)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_INT32,  int32,  int32_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_UINT32, uint32, uint32_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_FLOAT,  float,  float)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_INT64,  int64,  int64_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_UINT64, uint64, uint64_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_DOUBLE, double, double)
-
-#undef DEFINE_WRAPPER_HANDLER
-
-static bool strwrapper_end_handler(void *closure, const void *hd) {
-  stringfields_parseframe_t* frame = closure;
-  const upb_fielddef **field = (const upb_fielddef **) hd;
-  wrapperfields_parseframe_t* wrapper_frame = frame->closure;
-  MessageHeader* msg;
-  CACHED_VALUE* cached;
-
-  if (wrapper_frame->is_msg) {
-    msg = wrapper_frame->submsg;
-    cached = find_zval_property(msg, *field);
-  } else {
-    cached = wrapper_frame->submsg;
-  }
-
-  new_php_string(cached, frame->sink.ptr, frame->sink.len);
-
-  stringsink_uninit(&frame->sink);
-  free(frame);
-
-  return true;
-}
-
-static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
-                                     upb_handlers* h) {
-  const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
-  DescriptorInternal* desc;
-  size_t offset;
-
-  TSRMLS_FETCH();
-  desc = get_msgdef_desc(msgdef);
-  offset = desc->layout->fields[upb_fielddef_index(f)].offset;
-
-  switch (upb_msgdef_wellknowntype(msgdef)) {
-#define SET_HANDLER(utype, ltype)                                 \
-  case utype: {                                                   \
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;                  \
-    attr.handler_data = newhandlerdata(h, offset);                \
-    upb_handlers_set##ltype(h, f, ltype##wrapper_handler, &attr); \
-    break;                                                        \
-  }
-
-    SET_HANDLER(UPB_WELLKNOWN_BOOLVALUE,   bool);
-    SET_HANDLER(UPB_WELLKNOWN_INT32VALUE,  int32);
-    SET_HANDLER(UPB_WELLKNOWN_UINT32VALUE, uint32);
-    SET_HANDLER(UPB_WELLKNOWN_FLOATVALUE,  float);
-    SET_HANDLER(UPB_WELLKNOWN_INT64VALUE,  int64);
-    SET_HANDLER(UPB_WELLKNOWN_UINT64VALUE, uint64);
-    SET_HANDLER(UPB_WELLKNOWN_DOUBLEVALUE, double);
-
-#undef SET_HANDLER
-
-    case UPB_WELLKNOWN_STRINGVALUE:
-    case UPB_WELLKNOWN_BYTESVALUE: {
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newhandlerfielddata(h, f);
-
-      upb_handlers_setstartstr(h, f, str_handler, &attr);
-      upb_handlers_setstring(h, f, stringdata_handler, &attr);
-      upb_handlers_setendstr(h, f, strwrapper_end_handler, &attr);
-      break;
-    }
-    default:
-      // Cannot reach here.
-      break;
-  }
-}
-
-static bool add_unknown_handler(void* closure, const void* hd, const char* buf,
-                         size_t size) {
-  encodeunknown_handlerfunc handler =
-      ((unknownfields_handlerdata_t*)hd)->handler;
-
-  MessageHeader* msg = (MessageHeader*)closure;
-  stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
-  if (unknown == NULL) {
-    DEREF(message_data(msg), 0, stringsink*) = ALLOC(stringsink);
-    unknown = DEREF(message_data(msg), 0, stringsink*);
-    stringsink_init(unknown);
-  }
-
-  handler(unknown, NULL, buf, size, NULL);
-
-  return true;
-}
-
-void add_handlers_for_message(const void* closure, upb_handlers* h) {
-  const upb_msgdef* msgdef = upb_handlers_msgdef(h);
-  TSRMLS_FETCH();
-  DescriptorInternal* desc = get_msgdef_desc(msgdef);
-  register_class(desc, false TSRMLS_CC);
-  upb_msg_field_iter i;
-
-  // If this is a mapentry message type, set up a special set of handlers and
-  // bail out of the normal (user-defined) message type handling.
-  if (upb_msgdef_mapentry(msgdef)) {
-    add_handlers_for_mapentry(msgdef, h);
-    return;
-  }
-
-  // If this is a wrapper message type, set up a special set of handlers and
-  // bail out of the normal (user-defined) message type handling.
-  if (is_wrapper_msg(msgdef)) {
-    add_handlers_for_wrapper(msgdef, h);
-    return;
-  }
-
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  attr.handler_data = newunknownfieldshandlerdata(h);
-  upb_handlers_setunknown(h, add_unknown_handler, &attr);
-
-  for (upb_msg_field_begin(&i, desc->msgdef);
-       !upb_msg_field_done(&i);
-       upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
-
-    if (upb_fielddef_containingoneof(f)) {
-      size_t oneof_case_offset =
-          desc->layout->fields[upb_fielddef_index(f)].case_offset;
-      int property_cache_index =
-          desc->layout->fields[upb_fielddef_index(f)].cache_index;
-      add_handlers_for_oneof_field(h, desc->msgdef, f, offset,
-                                   oneof_case_offset, property_cache_index);
-    } else if (is_map_field(f)) {
-      add_handlers_for_mapfield(h, f, offset);
-    } else if (upb_fielddef_isseq(f)) {
-      add_handlers_for_repeated_field(h, f, offset);
-    } else {
-      add_handlers_for_singular_field(h, f, offset, false);
-    }
-  }
-}
-
-// Constructs the handlers for filling a message's data into an in-memory
-// object.
-const upb_handlers* get_fill_handlers(DescriptorInternal* desc) {
-  return upb_handlercache_get(desc->pool->fill_handler_cache, desc->msgdef);
-}
-
-static const upb_pbdecodermethod *msgdef_decodermethod(DescriptorInternal* desc) {
-  return upb_pbcodecache_get(desc->pool->fill_method_cache, desc->msgdef);
-}
-
-static const upb_json_parsermethod *msgdef_jsonparsermethod(DescriptorInternal* desc) {
-  return upb_json_codecache_get(desc->pool->json_fill_method_cache, desc->msgdef);
-}
-
-// -----------------------------------------------------------------------------
-// Serializing.
-// -----------------------------------------------------------------------------
-
-static void putmsg(zval* msg, const DescriptorInternal* desc, upb_sink sink,
-                   int depth, bool is_json TSRMLS_DC);
-static void putrawmsg(MessageHeader* msg, const DescriptorInternal* desc,
-                      upb_sink sink, int depth, bool is_json,
-                      bool open_msg TSRMLS_DC);
-static void putwrappervalue(
-    zval* value, const upb_fielddef* f,
-    upb_sink sink, int depth, bool is_json TSRMLS_DC);
-static void putjsonany(MessageHeader* msg, const DescriptorInternal* desc,
-                       upb_sink sink, int depth TSRMLS_DC);
-static void putjsonlistvalue(
-    MessageHeader* msg, const DescriptorInternal* desc,
-    upb_sink sink, int depth TSRMLS_DC);
-static void putjsonstruct(
-    MessageHeader* msg, const DescriptorInternal* desc,
-    upb_sink sink, int depth TSRMLS_DC);
-
-static void putstr(zval* str, const upb_fielddef* f, upb_sink sink,
-                   bool force_default);
-
-static void putrawstr(const char* str, int len, const upb_fielddef* f,
-                      upb_sink sink, bool force_default);
-
-static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink sink,
-                      int depth, bool is_json TSRMLS_DC);
-static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
-                         upb_sink sink, int depth, bool is_json TSRMLS_DC);
-
-static void putarray(zval* array, const upb_fielddef* f, upb_sink sink,
-                     int depth, bool is_json TSRMLS_DC);
-static void putmap(zval* map, const upb_fielddef* f, upb_sink sink,
-                   int depth, bool is_json TSRMLS_DC);
-
-static upb_selector_t getsel(const upb_fielddef* f, upb_handlertype_t type) {
-  upb_selector_t ret;
-  bool ok = upb_handlers_getselector(f, type, &ret);
-  PHP_PROTO_ASSERT(ok);
-  return ret;
-}
-
-static void put_optional_value(const void* memory, int len,
-                               const upb_fielddef* f,
-                               int depth, upb_sink sink,
-                               bool is_json TSRMLS_DC) {
-  PHP_PROTO_ASSERT(upb_fielddef_label(f) == UPB_LABEL_OPTIONAL);
-
-  switch (upb_fielddef_type(f)) {
-#define T(upbtypeconst, upbtype, ctype, default_value)                         \
-  case upbtypeconst: {                                                         \
-    ctype value = DEREF(memory, 0, ctype);                                     \
-    if (is_json || value != default_value) {                                   \
-      upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); \
-      upb_sink_put##upbtype(sink, sel, value);                                 \
-    }                                                                          \
-  } break;
-
-    T(UPB_TYPE_FLOAT, float, float, 0.0)
-    T(UPB_TYPE_DOUBLE, double, double, 0.0)
-    T(UPB_TYPE_BOOL, bool, uint8_t, 0)
-    T(UPB_TYPE_ENUM, int32, int32_t, 0)
-    T(UPB_TYPE_INT32, int32, int32_t, 0)
-    T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
-    T(UPB_TYPE_INT64, int64, int64_t, 0)
-    T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
-
-#undef T
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      putrawstr(memory, len, f, sink, is_json);
-      break;
-    case UPB_TYPE_MESSAGE: {
-#if PHP_MAJOR_VERSION < 7
-      MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
-#else
-      MessageHeader *submsg =
-          (MessageHeader*)((char*)(*(zend_object**)memory) -
-              XtOffsetOf(MessageHeader, std));
-#endif
-      putrawsubmsg(submsg, f, sink, depth, is_json TSRMLS_CC);
-      break;
-    }
-    default:
-      PHP_PROTO_ASSERT(false);
-  }
-}
-
-// Only string/bytes fields are stored as zval.
-static const char* raw_value(void* memory, const upb_fielddef* f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-#if PHP_MAJOR_VERSION < 7
-      return Z_STRVAL_PP((zval**)memory);
-#else
-      return ZSTR_VAL(*(zend_string**)memory);
-#endif
-      break;
-    default:
-      return memory;
-  }
-}
-
-static int raw_value_len(void* memory, int len, const upb_fielddef* f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-#if PHP_MAJOR_VERSION < 7
-      return Z_STRLEN_PP((zval**)memory);
-#else
-      return ZSTR_LEN(*(zend_string**)memory);
-#endif
-    default:
-      return len;
-  }
-}
-
-static void putmap(zval* map, const upb_fielddef* f, upb_sink sink,
-                   int depth, bool is_json TSRMLS_DC) {
-  upb_sink subsink;
-  const upb_fielddef* key_field;
-  const upb_fielddef* value_field;
-  MapIter it;
-  int len, size;
-
-  PHP_PROTO_ASSERT(map != NULL);
-  Map* intern = UNBOX(Map, map);
-  size = upb_strtable_count(&intern->table);
-  if (size == 0) return;
-
-  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
-  PHP_PROTO_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
-  key_field = map_field_key(f);
-  value_field = map_field_value(f);
-
-  for (map_begin(map, &it TSRMLS_CC); !map_done(&it); map_next(&it)) {
-    upb_status status;
-
-    upb_sink entry_sink;
-    upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
-                         &entry_sink);
-    upb_sink_startmsg(entry_sink);
-
-    // Serialize key.
-    const char *key = map_iter_key(&it, &len);
-    put_optional_value(key, len, key_field, depth + 1,
-                       entry_sink, is_json TSRMLS_CC);
-
-    // Serialize value.
-    upb_value value = map_iter_value(&it, &len);
-    put_optional_value(raw_value(upb_value_memory(&value), value_field),
-                       raw_value_len(upb_value_memory(&value), len, value_field),
-                       value_field, depth + 1, entry_sink, is_json TSRMLS_CC);
-
-    upb_sink_endmsg(entry_sink, &status);
-    upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-  }
-
-  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static void putmsg(zval* msg_php, const DescriptorInternal* desc, upb_sink sink,
-                   int depth, bool is_json TSRMLS_DC) {
-  MessageHeader* msg = UNBOX(MessageHeader, msg_php);
-  putrawmsg(msg, desc, sink, depth, is_json, true TSRMLS_CC);
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
-    DescriptorInternal* desc, bool preserve_proto_fieldnames);
-
-static void putjsonany(MessageHeader* msg, const DescriptorInternal* desc,
-                       upb_sink sink, int depth TSRMLS_DC) {
-  upb_status status;
-  const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
-  const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
-
-  zval* type_url_php_str;
-  const upb_msgdef *payload_type = NULL;
-
-  upb_sink_startmsg(sink);
-
-  /* Handle type url */
-  type_url_php_str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, type_field));
-  if (Z_STRLEN_P(type_url_php_str) > 0) {
-    putstr(type_url_php_str, type_field, sink, false);
-  }
-
-  {
-    const char* type_url_str = Z_STRVAL_P(type_url_php_str);
-    size_t type_url_len = Z_STRLEN_P(type_url_php_str);
-    if (type_url_len <= 20 ||
-        strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
-      zend_error(E_ERROR, "Invalid type url: %s", type_url_str);
-    }
-
-    /* Resolve type url */
-    type_url_str += 20;
-    type_url_len -= 20;
-
-    payload_type = upb_symtab_lookupmsg2(
-        generated_pool->symtab, type_url_str, type_url_len);
-    if (payload_type == NULL) {
-      zend_error(E_ERROR, "Unknown type: %s", type_url_str);
-      return;
-    }
-  }
-
-  {
-    zval* value_php_str;
-    const char* value_str;
-    size_t value_len;
-
-    value_php_str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, value_field));
-    value_str = Z_STRVAL_P(value_php_str);
-    value_len = Z_STRLEN_P(value_php_str);
-
-    if (value_len > 0) {
-      DescriptorInternal* payload_desc = get_msgdef_desc(payload_type);
-      register_class(payload_desc, false TSRMLS_CC);
-      zend_class_entry* payload_klass = payload_desc->klass;
-      zval val;
-      upb_sink subsink;
-      bool is_wellknown;
-
-      /* Create message of the payload type. */
-      ZVAL_OBJ(&val, payload_klass->create_object(payload_klass TSRMLS_CC));
-      MessageHeader* intern = UNBOX(MessageHeader, &val);
-      custom_data_init(payload_klass, intern PHP_PROTO_TSRMLS_CC);
-
-      merge_from_string(value_str, value_len, payload_desc, intern);
-
-      is_wellknown =
-          upb_msgdef_wellknowntype(payload_desc->msgdef) !=
-              UPB_WELLKNOWN_UNSPECIFIED;
-      if (is_wellknown) {
-        upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
-                          &subsink);
-      }
-
-      subsink.handlers =
-          msgdef_json_serialize_handlers(payload_desc, true);
-      subsink.closure = sink.closure;
-      putrawmsg(intern, payload_desc, subsink, depth, true,
-                is_wellknown TSRMLS_CC);
-
-      zval_dtor(&val);
-    }
-  }
-
-  upb_sink_endmsg(sink, &status);
-}
-
-static void putjsonlistvalue(
-    MessageHeader* msg, const DescriptorInternal* desc,
-    upb_sink sink, int depth TSRMLS_DC) {
-  upb_status status;
-  upb_sink subsink;
-  const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
-  zval* array;
-  RepeatedField* intern;
-  HashTable *ht;
-  int size;
-
-  upb_sink_startmsg(sink);
-
-  array = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-  if (ZVAL_IS_NULL(array)) {
-    upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-    upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-  } else {
-    intern = UNBOX(RepeatedField, array);
-    ht = PHP_PROTO_HASH_OF(intern->array);
-    size = zend_hash_num_elements(ht);
-
-    if (size == 0) {
-      upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-      upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-    } else {
-      putarray(array, f, sink, depth, true TSRMLS_CC);
-    }
-  }
-
-  upb_sink_endmsg(sink, &status);
-}
-
-static void putjsonstruct(
-    MessageHeader* msg, const DescriptorInternal* desc,
-    upb_sink sink, int depth TSRMLS_DC) {
-  upb_status status;
-  upb_sink subsink;
-  const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
-  zval* map;
-  Map* intern;
-  int size;
-
-  upb_sink_startmsg(sink);
-
-  map = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-  if (ZVAL_IS_NULL(map)) {
-    upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-    upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-  } else {
-    intern = UNBOX(Map, map);
-    size = upb_strtable_count(&intern->table);
-
-    if (size == 0) {
-      upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-      upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-    } else {
-      putmap(map, f, sink, depth, true TSRMLS_CC);
-    }
-  }
-
-  upb_sink_endmsg(sink, &status);
-}
-
-static void putrawmsg(MessageHeader* msg, const DescriptorInternal* desc,
-                      upb_sink sink, int depth, bool is_json,
-                      bool open_msg TSRMLS_DC) {
-  upb_msg_field_iter i;
-  upb_status status;
-
-  if (is_json &&
-      upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
-    putjsonany(msg, desc, sink, depth TSRMLS_CC);
-    return;
-  }
-
-  if (is_json &&
-      upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
-    putjsonlistvalue(msg, desc, sink, depth TSRMLS_CC);
-    return;
-  }
-
-  if (is_json &&
-      upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_STRUCT) {
-    putjsonstruct(msg, desc, sink, depth TSRMLS_CC);
-    return;
-  }
-
-  if (open_msg) {
-    upb_sink_startmsg(sink);
-  }
-
-  // Protect against cycles (possible because users may freely reassign message
-  // and repeated fields) by imposing a maximum recursion depth.
-  if (depth > ENCODE_MAX_NESTING) {
-    zend_error(E_ERROR,
-             "Maximum recursion depth exceeded during encoding.");
-  }
-
-  for (upb_msg_field_begin(&i, desc->msgdef); !upb_msg_field_done(&i);
-       upb_msg_field_next(&i)) {
-    upb_fielddef* f = upb_msg_iter_field(&i);
-    uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
-    bool containing_oneof = false;
-
-    if (upb_fielddef_containingoneof(f)) {
-      uint32_t oneof_case_offset =
-          desc->layout->fields[upb_fielddef_index(f)].case_offset;
-      // For a oneof, check that this field is actually present -- skip all the
-      // below if not.
-      if (DEREF(message_data(msg), oneof_case_offset, uint32_t) !=
-          upb_fielddef_number(f)) {
-        continue;
-      }
-      // Otherwise, fall through to the appropriate singular-field handler
-      // below.
-      containing_oneof = true;
-    }
-
-    if (is_map_field(f)) {
-      zval* map = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-      if (!ZVAL_IS_NULL(map)) {
-        putmap(map, f, sink, depth, is_json TSRMLS_CC);
-      }
-    } else if (upb_fielddef_isseq(f)) {
-      zval* array = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-      if (!ZVAL_IS_NULL(array)) {
-        putarray(array, f, sink, depth, is_json TSRMLS_CC);
-      }
-    } else if (upb_fielddef_isstring(f)) {
-      zval* str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-      if (containing_oneof || (is_json && is_wrapper_msg(desc->msgdef)) ||
-          Z_STRLEN_P(str) > 0) {
-        putstr(str, f, sink, is_json && is_wrapper_msg(desc->msgdef));
-      }
-    } else if (upb_fielddef_issubmsg(f)) {
-      zval* submsg = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-      if (is_wrapper_msg(upb_fielddef_msgsubdef(f)) &&
-          Z_TYPE_P(submsg) != IS_NULL && Z_TYPE_P(submsg) != IS_OBJECT) {
-        putwrappervalue(submsg, f, sink, depth, is_json TSRMLS_CC);
-      } else {
-        putsubmsg(submsg, f, sink, depth, is_json TSRMLS_CC);
-      }
-    } else {
-      upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-
-#define T(upbtypeconst, upbtype, ctype, default_value)     \
-  case upbtypeconst: {                                     \
-    ctype value = DEREF(message_data(msg), offset, ctype); \
-    if (containing_oneof ||                                \
-        (is_json && is_wrapper_msg(desc->msgdef)) ||       \
-        value != default_value) {                          \
-      upb_sink_put##upbtype(sink, sel, value);             \
-    }                                                      \
-  } break;
-
-      switch (upb_fielddef_type(f)) {
-        T(UPB_TYPE_FLOAT, float, float, 0.0)
-        T(UPB_TYPE_DOUBLE, double, double, 0.0)
-        T(UPB_TYPE_BOOL, bool, uint8_t, 0)
-        case UPB_TYPE_ENUM:
-        T(UPB_TYPE_INT32, int32, int32_t, 0)
-        T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
-        T(UPB_TYPE_INT64, int64, int64_t, 0)
-        T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
-
-        case UPB_TYPE_STRING:
-        case UPB_TYPE_BYTES:
-        case UPB_TYPE_MESSAGE:
-          zend_error(E_ERROR, "Internal error.");
-      }
-
-#undef T
-    }
-  }
-
-  stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
-  if (unknown != NULL) {
-    upb_sink_putunknown(sink, unknown->ptr, unknown->len);
-  }
-
-  if (open_msg) {
-    upb_sink_endmsg(sink, &status);
-  }
-}
-
-static void putstr(zval* str, const upb_fielddef *f,
-                   upb_sink sink, bool force_default) {
-  upb_sink subsink;
-
-  if (ZVAL_IS_NULL(str)) return;
-
-  PHP_PROTO_ASSERT(Z_TYPE_P(str) == IS_STRING);
-
-  upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), Z_STRLEN_P(str),
-                    &subsink);
-
-  // For oneof string field, we may get here with string length is zero.
-  if (Z_STRLEN_P(str) > 0 || force_default) {
-    // Ensure that the string has the correct encoding. We also check at
-    // field-set time, but the user may have mutated the string object since
-    // then.
-    if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
-        !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) {
-      zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
-      return;
-    }
-    upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str),
-                       Z_STRLEN_P(str), NULL);
-  }
-
-  upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
-}
-
-static void putrawstr(const char* str, int len, const upb_fielddef* f,
-                      upb_sink sink, bool force_default) {
-  upb_sink subsink;
-
-  if (len == 0 && !force_default) return;
-
-  // Ensure that the string has the correct encoding. We also check at field-set
-  // time, but the user may have mutated the string object since then.
-  if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
-      !is_structurally_valid_utf8(str, len)) {
-    zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
-    return;
-  }
-
-  upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), len, &subsink);
-  upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), str, len, NULL);
-  upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
-}
-
-static void putsubmsg(zval* submsg_php, const upb_fielddef* f, upb_sink sink,
-                      int depth, bool is_json TSRMLS_DC) {
-  if (Z_TYPE_P(submsg_php) == IS_NULL) return;
-
-  MessageHeader *submsg = UNBOX(MessageHeader, submsg_php);
-  putrawsubmsg(submsg, f, sink, depth, is_json TSRMLS_CC);
-}
-
-static void putwrappervalue(
-    zval* value, const upb_fielddef* f,
-    upb_sink sink, int depth, bool is_json TSRMLS_DC) {
-  upb_sink subsink;
-  const upb_msgdef* msgdef = upb_fielddef_msgsubdef(f);
-  const upb_fielddef* value_field = upb_msgdef_itof(msgdef, 1);
-  upb_selector_t sel =
-      getsel(value_field, upb_handlers_getprimitivehandlertype(value_field));
-
-  upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
-
-#define T(upbtypeconst, upbtype, ctype, default_value)      \
-  case upbtypeconst: {                                      \
-    ctype value_raw;                                        \
-    native_slot_set(upb_fielddef_type(value_field), NULL,   \
-                    &value_raw, value PHP_PROTO_TSRMLS_CC); \
-    if ((is_json && is_wrapper_msg(msgdef)) ||              \
-        value_raw != default_value) {                       \
-      upb_sink_put##upbtype(subsink, sel, value_raw);       \
-    }                                                       \
-  } break;
-
-  switch (upb_fielddef_type(value_field)) {
-    T(UPB_TYPE_FLOAT, float, float, 0.0)
-    T(UPB_TYPE_DOUBLE, double, double, 0.0)
-    T(UPB_TYPE_BOOL, bool, uint8_t, 0)
-    T(UPB_TYPE_INT32, int32, int32_t, 0)
-    T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
-    T(UPB_TYPE_INT64, int64, int64_t, 0)
-    T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      if ((is_json && is_wrapper_msg(msgdef)) ||
-          Z_STRLEN_P(value) > 0) {
-        putstr(value, value_field, subsink, is_json && is_wrapper_msg(msgdef));
-      }
-      break;
-    }
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_MESSAGE:
-      zend_error(E_ERROR, "Internal error.");
-  }
-
-#undef T
-
-  upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-}
-
-static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
-                         upb_sink sink, int depth, bool is_json TSRMLS_DC) {
-  upb_sink subsink;
-
-  const upb_msgdef* m = upb_fielddef_msgsubdef(f);
-  DescriptorInternal* subdesc = get_msgdef_desc(m);
-
-  upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
-  putrawmsg(submsg, subdesc, subsink, depth + 1, is_json, true TSRMLS_CC);
-  upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-}
-
-static void putarray(zval* array, const upb_fielddef* f, upb_sink sink,
-                     int depth, bool is_json TSRMLS_DC) {
-  upb_sink subsink;
-  upb_fieldtype_t type = upb_fielddef_type(f);
-  upb_selector_t sel = 0;
-  int size, i;
-
-  PHP_PROTO_ASSERT(array != NULL);
-  RepeatedField* intern = UNBOX(RepeatedField, array);
-  HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
-  size = zend_hash_num_elements(ht);
-  if (size == 0) return;
-
-  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
-  if (upb_fielddef_isprimitive(f)) {
-    sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  }
-
-  for (i = 0; i < size; i++) {
-    void* memory = repeated_field_index_native(intern, i TSRMLS_CC);
-    switch (type) {
-#define T(upbtypeconst, upbtype, ctype)                      \
-  case upbtypeconst:                                         \
-    upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
-    break;
-
-      T(UPB_TYPE_FLOAT, float, float)
-      T(UPB_TYPE_DOUBLE, double, double)
-      T(UPB_TYPE_BOOL, bool, int8_t)
-      case UPB_TYPE_ENUM:
-        T(UPB_TYPE_INT32, int32, int32_t)
-        T(UPB_TYPE_UINT32, uint32, uint32_t)
-        T(UPB_TYPE_INT64, int64, int64_t)
-        T(UPB_TYPE_UINT64, uint64, uint64_t)
-
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
-        const char* rawstr = Z_STRVAL_P(*(zval**)memory);
-        int len = Z_STRLEN_P(*(zval**)memory);
-#else
-        const char* rawstr = ZSTR_VAL(*(zend_string**)memory);
-        int len = ZSTR_LEN(*(zend_string**)memory);
-#endif
-        putrawstr(rawstr, len, f, subsink,
-                  is_json && is_wrapper_msg(upb_fielddef_containingtype(f)));
-        break;
-      }
-      case UPB_TYPE_MESSAGE: {
-#if PHP_MAJOR_VERSION < 7
-        MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
-#else
-        MessageHeader *submsg =
-            (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
-                XtOffsetOf(MessageHeader, std));
-#endif
-        putrawsubmsg(submsg, f, subsink, depth, is_json TSRMLS_CC);
-        break;
-      }
-
-#undef T
-    }
-  }
-  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static const upb_handlers* msgdef_pb_serialize_handlers(DescriptorInternal* desc) {
-  return upb_handlercache_get(desc->pool->pb_serialize_handler_cache,
-                              desc->msgdef);
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
-    DescriptorInternal* desc, bool preserve_proto_fieldnames) {
-  if (preserve_proto_fieldnames) {
-    return upb_handlercache_get(
-        desc->pool->json_serialize_handler_preserve_cache, desc->msgdef);
-  } else {
-    return upb_handlercache_get(desc->pool->json_serialize_handler_cache,
-                                desc->msgdef);
-  }
-}
-
-// -----------------------------------------------------------------------------
-// PHP encode/decode methods
-// -----------------------------------------------------------------------------
-
-void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) {
-  DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val));
-
-  stringsink sink;
-  stringsink_init(&sink);
-
-  {
-    const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc);
-
-    stackenv se;
-    upb_pb_encoder* encoder;
-
-    stackenv_init(&se, "Error occurred during encoding: %s");
-    encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
-
-    putmsg(val, desc, upb_pb_encoder_input(encoder), 0, false TSRMLS_CC);
-
-    PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
-
-    stackenv_uninit(&se);
-    stringsink_uninit(&sink);
-  }
-}
-
-PHP_METHOD(Message, serializeToString) {
-  serialize_to_string(getThis(), return_value TSRMLS_CC);
-}
-
-void merge_from_string(const char* data, int data_len, DescriptorInternal* desc,
-                       MessageHeader* msg) {
-  const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
-  const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
-  stackenv se;
-  upb_sink sink;
-  upb_pbdecoder* decoder;
-  void* closure;
-  stackenv_init(&se, "Error occurred during parsing: %s");
-
-  if (is_wrapper_msg(desc->msgdef)) {
-    wrapperfields_parseframe_t* frame =
-        (wrapperfields_parseframe_t*)malloc(
-            sizeof(wrapperfields_parseframe_t));
-    frame->submsg = msg;
-    frame->is_msg = true;
-    closure = frame;
-  } else {
-    closure = msg;
-  }
-
-  upb_sink_reset(&sink, h, closure);
-  decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
-  upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder));
-
-  if (is_wrapper_msg(desc->msgdef)) {
-    free((wrapperfields_parseframe_t*)closure);
-  }
-
-  stackenv_uninit(&se);
-}
-
-PHP_METHOD(Message, mergeFromString) {
-  DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
-  char *data = NULL;
-  PHP_PROTO_SIZE data_len;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
-      FAILURE) {
-    return;
-  }
-
-  merge_from_string(data, data_len, desc, msg);
-}
-
-PHP_METHOD(Message, serializeToJsonString) {
-  DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
-
-  zend_bool preserve_proto_fieldnames = false;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
-                            &preserve_proto_fieldnames) == FAILURE) {
-    return;
-  }
-
-  stringsink sink;
-  stringsink_init(&sink);
-
-  {
-    const upb_handlers* serialize_handlers =
-        msgdef_json_serialize_handlers(desc, preserve_proto_fieldnames);
-    upb_json_printer* printer;
-    stackenv se;
-
-    stackenv_init(&se, "Error occurred during encoding: %s");
-    printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
-
-    putmsg(getThis(), desc, upb_json_printer_input(printer), 0, true TSRMLS_CC);
-
-    PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
-
-    stackenv_uninit(&se);
-    stringsink_uninit(&sink);
-  }
-}
-
-PHP_METHOD(Message, mergeFromJsonString) {
-  DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
-  char *data = NULL;
-  PHP_PROTO_SIZE data_len;
-  zend_bool ignore_json_unknown = false;
-
-  if (zend_parse_parameters(
-          ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &data, &data_len,
-          &ignore_json_unknown) ==
-      FAILURE) {
-    return;
-  }
-
-  // TODO(teboring): Check and respect string encoding. If not UTF-8, we need to
-  // convert, because string handlers pass data directly to message string
-  // fields.
-
-  // TODO(teboring): Clear message.
-
-  {
-    const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
-    stackenv se;
-    upb_sink sink;
-    upb_json_parser* parser;
-    void* closure;
-    stackenv_init(&se, "Error occurred during parsing: %s");
-
-    if (is_wrapper_msg(desc->msgdef)) {
-      wrapperfields_parseframe_t* frame =
-          (wrapperfields_parseframe_t*)malloc(
-              sizeof(wrapperfields_parseframe_t));
-      frame->submsg = msg;
-      frame->is_msg = true;
-      closure = frame;
-    } else {
-      closure = msg;
-    }
-
-    upb_sink_reset(&sink, get_fill_handlers(desc), closure);
-    parser = upb_json_parser_create(se.arena, method, generated_pool->symtab,
-                                    sink, &se.status, ignore_json_unknown);
-    upb_bufsrc_putbuf(data, data_len, upb_json_parser_input(parser));
-
-    if (is_wrapper_msg(desc->msgdef)) {
-      free((wrapperfields_parseframe_t*)closure);
-    }
-    stackenv_uninit(&se);
-  }
-}
-
-// TODO(teboring): refactoring with putrawmsg
-static void discard_unknown_fields(MessageHeader* msg) {
-  upb_msg_field_iter it;
-
-  stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
-  if (unknown != NULL) {
-    stringsink_uninit(unknown);
-    FREE(unknown);
-    DEREF(message_data(msg), 0, stringsink*) = NULL;
-  }
-
-  // Recursively discard unknown fields of submessages.
-  DescriptorInternal* desc = msg->descriptor;
-  TSRMLS_FETCH();
-  for (upb_msg_field_begin(&it, desc->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    upb_fielddef* f = upb_msg_iter_field(&it);
-
-    if (upb_fielddef_containingoneof(f)) {
-      uint32_t oneof_case_offset =
-          desc->layout->fields[upb_fielddef_index(f)].case_offset;
-      // For a oneof, check that this field is actually present -- skip all the
-      // below if not.
-      if (DEREF(message_data(msg), oneof_case_offset, uint32_t) !=
-          upb_fielddef_number(f)) {
-        continue;
-      }
-      // Otherwise, fall through to the appropriate singular-field handler
-      // below.
-    }
-
-    if (is_map_field(f)) {
-      MapIter map_it;
-      int len;
-      const upb_fielddef* value_field;
-
-      value_field = map_field_value(f);
-      if (!upb_fielddef_issubmsg(value_field)) continue;
-
-      zval* map_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-      if (ZVAL_IS_NULL(map_php)) continue;
-
-      for (map_begin(map_php, &map_it TSRMLS_CC);
-           !map_done(&map_it); map_next(&map_it)) {
-        upb_value value = map_iter_value(&map_it, &len);
-        const void* memory = raw_value(upb_value_memory(&value), value_field);
-#if PHP_MAJOR_VERSION < 7
-        MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
-#else
-        MessageHeader *submsg =
-            (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
-                XtOffsetOf(MessageHeader, std));
-#endif
-        discard_unknown_fields(submsg);
-      }
-    } else if (upb_fielddef_isseq(f)) {
-      if (!upb_fielddef_issubmsg(f)) continue;
-
-      zval* array_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-      if (ZVAL_IS_NULL(array_php)) continue;
-
-      int size, i;
-      RepeatedField* intern = UNBOX(RepeatedField, array_php);
-      HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
-      size = zend_hash_num_elements(ht);
-      if (size == 0) continue;
-
-      for (i = 0; i < size; i++) {
-        void* memory = repeated_field_index_native(intern, i TSRMLS_CC);
-#if PHP_MAJOR_VERSION < 7
-        MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
-#else
-        MessageHeader *submsg =
-            (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
-                XtOffsetOf(MessageHeader, std));
-#endif
-        discard_unknown_fields(submsg);
-      }
-    } else if (upb_fielddef_issubmsg(f)) {
-      zval* submsg_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
-      if (Z_TYPE_P(submsg_php) == IS_NULL) continue;
-      MessageHeader* submsg = UNBOX(MessageHeader, submsg_php);
-      discard_unknown_fields(submsg);
-    }
-  }
-}
-
-PHP_METHOD(Message, discardUnknownFields) {
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-  discard_unknown_fields(msg);
-}
diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c
index 1878a0a..f5890d9 100644
--- a/php/ext/google/protobuf/map.c
+++ b/php/ext/google/protobuf/map.c
@@ -28,393 +28,258 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <ext/spl/spl_iterators.h>
+#include "map.h"
+
 #include <Zend/zend_API.h>
 #include <Zend/zend_interfaces.h>
 
+#include <ext/spl/spl_iterators.h>
+
+#include "arena.h"
+#include "convert.h"
+#include "message.h"
+#include "php-upb.h"
 #include "protobuf.h"
-#include "utf8.h"
 
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
-  ZEND_ARG_INFO(0, index)
-ZEND_END_ARG_INFO()
+static void MapFieldIter_make(zval *val, zval *map_field);
 
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
-  ZEND_ARG_INFO(0, index)
-  ZEND_ARG_INFO(0, newval)
-ZEND_END_ARG_INFO()
+// -----------------------------------------------------------------------------
+// MapField
+// -----------------------------------------------------------------------------
 
-ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
-ZEND_END_ARG_INFO()
+typedef struct {
+  zend_object std;
+  zval arena;
+  upb_map *map;
+  MapField_Type type;
+} MapField;
 
-// Utilities
+zend_class_entry *MapField_class_entry;
+static zend_object_handlers MapField_object_handlers;
 
-void* upb_value_memory(upb_value* v) {
-  return (void*)(&v->val);
+static bool MapType_Eq(MapField_Type a, MapField_Type b) {
+  return a.key_type == b.key_type && TypeInfo_Eq(a.val_type, b.val_type);
 }
 
-// -----------------------------------------------------------------------------
-// Basic map operations on top of upb's strtable.
-//
-// Note that we roll our own `Map` container here because, as for
-// `RepeatedField`, we want a strongly-typed container. This is so that any user
-// errors due to incorrect map key or value types are raised as close as
-// possible to the error site, rather than at some deferred point (e.g.,
-// serialization).
-//
-// We build our `Map` on top of upb_strtable so that we're able to take
-// advantage of the native_slot storage abstraction, as RepeatedField does.
-// (This is not quite a perfect mapping -- see the key conversions below -- but
-// gives us full support and error-checking for all value types for free.)
-// -----------------------------------------------------------------------------
+static TypeInfo KeyType(MapField_Type type) {
+  TypeInfo ret = {type.key_type};
+  return ret;
+}
 
-// Map values are stored using the native_slot abstraction (as with repeated
-// field values), but keys are a bit special. Since we use a strtable, we need
-// to store keys as sequences of bytes such that equality of those bytes maps
-// one-to-one to equality of keys. We store strings directly (i.e., they map to
-// their own bytes) and integers as native integers (using the native_slot
-// abstraction).
+MapField_Type MapType_Get(const upb_fielddef *f) {
+  const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
+  const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
+  const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
+  MapField_Type type = {
+      upb_fielddef_type(key_f),
+      {upb_fielddef_type(val_f), Descriptor_GetFromFieldDef(val_f)}};
+  return type;
+}
 
-// Note that there is another tradeoff here in keeping string keys as native
-// strings rather than PHP strings: traversing the Map requires conversion to
-// PHP string values on every traversal, potentially creating more garbage. We
-// should consider ways to cache a PHP version of the key if this becomes an
-// issue later.
+// PHP Object Handlers /////////////////////////////////////////////////////////
 
-// Forms a key to use with the underlying strtable from a PHP key value. |buf|
-// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to
-// construct a key byte sequence if needed. |out_key| and |out_length| provide
-// the resulting key data/length.
-#define TABLE_KEY_BUF_LENGTH 8  // sizeof(uint64_t)
-static bool table_key(Map* self, zval* key,
-                      char* buf,
-                      const char** out_key,
-                      size_t* out_length TSRMLS_DC) {
-  switch (self->key_type) {
-    case UPB_TYPE_STRING:
-      if (!protobuf_convert_to_string(key)) {
-        return false;
+/**
+ * MapField_create()
+ *
+ * PHP class entry function to allocate and initialize a new MapField
+ * object.
+ */
+static zend_object* MapField_create(zend_class_entry *class_type) {
+  MapField *intern = emalloc(sizeof(MapField));
+  zend_object_std_init(&intern->std, class_type);
+  intern->std.handlers = &MapField_object_handlers;
+  Arena_Init(&intern->arena);
+  intern->map = NULL;
+  // Skip object_properties_init(), we don't allow derived classes.
+  return &intern->std;
+}
+
+/**
+ * MapField_dtor()
+ *
+ * Object handler to destroy a MapField. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void MapField_destructor(zend_object* obj) {
+  MapField* intern = (MapField*)obj;
+  ObjCache_Delete(intern->map);
+  zval_ptr_dtor(&intern->arena);
+  zend_object_std_dtor(&intern->std);
+}
+
+/**
+ * MapField_compare_objects()
+ *
+ * Object handler for comparing two repeated field objects. Called whenever PHP
+ * code does:
+ *
+ *   $map1 == $map2
+ */
+static int MapField_compare_objects(zval *map1, zval *map2) {
+  MapField* intern1 = (MapField*)Z_OBJ_P(map1);
+  MapField* intern2 = (MapField*)Z_OBJ_P(map2);
+
+  return MapType_Eq(intern1->type, intern2->type) &&
+                 MapEq(intern1->map, intern2->map, intern1->type)
+             ? 0
+             : 1;
+}
+
+/**
+ * MapField_clone_obj()
+ *
+ * Object handler for cloning an object in PHP. Called when PHP code does:
+ *
+ *   $map2 = clone $map1;
+ */
+static zend_object *MapField_clone_obj(PROTO_VAL *object) {
+  MapField* intern = PROTO_VAL_P(object);
+  upb_arena *arena = Arena_Get(&intern->arena);
+  upb_map *clone =
+      upb_map_new(arena, intern->type.key_type, intern->type.val_type.type);
+  size_t iter = UPB_MAP_BEGIN;
+
+  while (upb_mapiter_next(intern->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(intern->map, iter);
+    upb_msgval val = upb_mapiter_value(intern->map, iter);
+    upb_map_set(clone, key, val, arena);
+  }
+
+  zval ret;
+  MapField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena);
+  return Z_OBJ_P(&ret);
+}
+
+static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member,
+                                   int type, void **cache_slot) {
+  return NULL;  // We don't offer direct references to our properties.
+}
+
+static HashTable *Map_GetProperties(PROTO_VAL *object) {
+  return NULL;  // We do not have a properties table.
+}
+
+// C Functions from map.h //////////////////////////////////////////////////////
+
+// These are documented in the header file.
+
+void MapField_GetPhpWrapper(zval *val, upb_map *map, MapField_Type type,
+                            zval *arena) {
+  if (!map) {
+    ZVAL_NULL(val);
+    return;
+  }
+
+  if (!ObjCache_Get(map, val)) {
+    MapField *intern = emalloc(sizeof(MapField));
+    zend_object_std_init(&intern->std, MapField_class_entry);
+    intern->std.handlers = &MapField_object_handlers;
+    ZVAL_COPY(&intern->arena, arena);
+    intern->map = map;
+    intern->type = type;
+    // Skip object_properties_init(), we don't allow derived classes.
+    ObjCache_Add(intern->map, &intern->std);
+    ZVAL_OBJ(val, &intern->std);
+  }
+}
+
+upb_map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_arena *arena) {
+  if (Z_ISREF_P(val)) {
+    ZVAL_DEREF(val);
+  }
+
+  if (Z_TYPE_P(val) == IS_ARRAY) {
+    upb_map *map = upb_map_new(arena, type.key_type, type.val_type.type);
+    HashTable *table = HASH_OF(val);
+    HashPosition pos;
+
+    zend_hash_internal_pointer_reset_ex(table, &pos);
+
+    while (true) {
+      zval php_key;
+      zval *php_val;
+      upb_msgval upb_key;
+      upb_msgval upb_val;
+
+      zend_hash_get_current_key_zval_ex(table, &php_key, &pos);
+      php_val = zend_hash_get_current_data_ex(table, &pos);
+
+      if (!php_val) return map;
+
+      if (!Convert_PhpToUpb(&php_key, &upb_key, KeyType(type), arena) ||
+          !Convert_PhpToUpbAutoWrap(php_val, &upb_val, type.val_type, arena)) {
+        return NULL;
       }
-      if (!is_structurally_valid_utf8(Z_STRVAL_P(key), Z_STRLEN_P(key))) {
-        zend_error(E_USER_ERROR, "Given key is not UTF8 encoded.");
-        return false;
-      }
-      *out_key = Z_STRVAL_P(key);
-      *out_length = Z_STRLEN_P(key);
-      break;
 
-#define CASE_TYPE(upb_type, type, c_type, php_type)                     \
-  case UPB_TYPE_##upb_type: {                                           \
-    c_type type##_value;                                                \
-    if (!protobuf_convert_to_##type(key, &type##_value)) {              \
-      return false;                                                     \
-    }                                                                   \
-    native_slot_set_by_array(self->key_type, NULL, buf, key TSRMLS_CC); \
-    *out_key = buf;                                                     \
-    *out_length = native_slot_size(self->key_type);                     \
-    break;                                                              \
-  }
-      CASE_TYPE(BOOL, bool, int8_t, BOOL)
-      CASE_TYPE(INT32, int32, int32_t, LONG)
-      CASE_TYPE(INT64, int64, int64_t, LONG)
-      CASE_TYPE(UINT32, uint32, uint32_t, LONG)
-      CASE_TYPE(UINT64, uint64, uint64_t, LONG)
-
-#undef CASE_TYPE
-
-    default:
-      // Map constructor should not allow a Map with another key type to be
-      // constructed.
-      assert(false);
-      break;
-  }
-
-  return true;
-}
-
-// -----------------------------------------------------------------------------
-// MapField methods
-// -----------------------------------------------------------------------------
-
-static zend_function_entry map_field_methods[] = {
-  PHP_ME(MapField, __construct,  NULL,              ZEND_ACC_PUBLIC)
-  PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
-  PHP_ME(MapField, offsetGet,    arginfo_offsetGet, ZEND_ACC_PUBLIC)
-  PHP_ME(MapField, offsetSet,    arginfo_offsetSet, ZEND_ACC_PUBLIC)
-  PHP_ME(MapField, offsetUnset,  arginfo_offsetGet, ZEND_ACC_PUBLIC)
-  PHP_ME(MapField, count,        arginfo_void,      ZEND_ACC_PUBLIC)
-  PHP_ME(MapField, getIterator,  arginfo_void,      ZEND_ACC_PUBLIC)
-  ZEND_FE_END
-};
-
-// Forward declare static functions.
-
-static void map_field_write_dimension(zval *object, zval *key,
-                                      zval *value TSRMLS_DC);
-
-// -----------------------------------------------------------------------------
-// MapField creation/destruction
-// -----------------------------------------------------------------------------
-
-zend_class_entry* map_field_type;
-zend_class_entry* map_field_iter_type;
-
-zend_object_handlers* map_field_handlers;
-zend_object_handlers* map_field_iter_handlers;
-
-static void map_begin_internal(Map *map, MapIter *iter) {
-  iter->self = map;
-  upb_strtable_begin(&iter->it, &map->table);
-}
-
-static HashTable *map_field_get_gc(zval *object, CACHED_VALUE **table,
-                                   int *n TSRMLS_DC) {
-  // TODO(teboring): Unfortunately, zend engine does not support garbage
-  // collection for custom array. We have to use zend engine's native array
-  // instead.
-  *table = NULL;
-  *n = 0;
-  return NULL;
-}
-
-// Define map value element free function.
-#if PHP_MAJOR_VERSION < 7
-static inline void php_proto_map_string_release(void *value) {
-  zval_ptr_dtor(value);
-}
-
-static inline void php_proto_map_object_release(void *value) {
-  zval_ptr_dtor(value);
-}
-#else
-static inline void php_proto_map_string_release(void *value) {
-  zend_string* object = *(zend_string**)value;
-  zend_string_release(object);
-}
-static inline void php_proto_map_object_release(void *value) {
-  zend_object* object = *(zend_object**)value;
-  GC_DELREF(object);
-  if(GC_REFCOUNT(object) == 0) {
-    zend_objects_store_del(object);
-  }
-}
-#endif
-
-// Define object free method.
-PHP_PROTO_OBJECT_FREE_START(Map, map_field)
-MapIter it;
-int len;
-for (map_begin_internal(intern, &it); !map_done(&it); map_next(&it)) {
-  upb_value value = map_iter_value(&it, &len);
-  void *mem = upb_value_memory(&value);
-  switch (intern->value_type) {
-    case UPB_TYPE_MESSAGE:
-      php_proto_map_object_release(mem);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      php_proto_map_string_release(mem);
-      break;
-    default:
-      break;
-  }
-}
-upb_strtable_uninit(&intern->table);
-PHP_PROTO_OBJECT_FREE_END
-
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(Map, map_field)
-PHP_PROTO_OBJECT_DTOR_END
-
-// Define object create method.
-PHP_PROTO_OBJECT_CREATE_START(Map, map_field)
-// Table value type is always UINT64: this ensures enough space to store the
-// native_slot value.
-if (!upb_strtable_init(&intern->table, UPB_CTYPE_UINT64)) {
-  zend_error(E_USER_ERROR, "Could not allocate table.");
-}
-PHP_PROTO_OBJECT_CREATE_END(Map, map_field)
-
-// Init class entry.
-PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapField", Map,
-                           map_field)
-zend_class_implements(map_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
-                      zend_ce_aggregate, spl_ce_Countable);
-map_field_handlers->write_dimension = map_field_write_dimension;
-map_field_handlers->get_gc = map_field_get_gc;
-PHP_PROTO_INIT_CLASS_END
-
-void map_field_ensure_created(const upb_fielddef *field,
-                              CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
-  if (ZVAL_IS_NULL(CACHED_PTR_TO_ZVAL_PTR(map_field))) {
-    zval_ptr_dtor(map_field);
-#if PHP_MAJOR_VERSION < 7
-    MAKE_STD_ZVAL(CACHED_PTR_TO_ZVAL_PTR(map_field));
-#endif
-    map_field_create_with_field(map_field_type, field,
-                                map_field PHP_PROTO_TSRMLS_CC);
-  }
-}
-
-void map_field_create_with_field(const zend_class_entry *ce,
-                                 const upb_fielddef *field,
-                                 CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
-  const upb_fielddef *key_field = map_field_key(field);
-  const upb_fielddef *value_field = map_field_value(field);
-  map_field_create_with_type(
-      ce, upb_fielddef_type(key_field), upb_fielddef_type(value_field),
-      field_type_class(value_field TSRMLS_CC), map_field PHP_PROTO_TSRMLS_CC);
-}
-
-void map_field_create_with_type(const zend_class_entry *ce,
-                                upb_fieldtype_t key_type,
-                                upb_fieldtype_t value_type,
-                                const zend_class_entry *msg_ce,
-                                CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
-  CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(CACHED_PTR_TO_ZVAL_PTR(map_field),
-                                   map_field_type);
-  Map *intern = UNBOX(Map, CACHED_TO_ZVAL_PTR(*map_field));
-  intern->key_type = key_type;
-  intern->value_type = value_type;
-  intern->msg_ce = msg_ce;
-}
-
-// -----------------------------------------------------------------------------
-// MapField Handlers
-// -----------------------------------------------------------------------------
-
-static bool map_field_read_dimension(zval *object, zval *key, int type,
-                                     CACHED_VALUE *retval TSRMLS_DC) {
-  Map *intern = UNBOX(Map, object);
-
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_UINT64;
-#endif
-  if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
-    return false;
-  }
-
-  if (upb_strtable_lookup2(&intern->table, keyval, length, &v)) {
-    void* mem = upb_value_memory(&v);
-    native_slot_get_by_map_value(intern->value_type, mem, retval TSRMLS_CC);
-    return true;
-  } else {
-    zend_error(E_USER_ERROR, "Given key doesn't exist.");
-    return false;
-  }
-}
-
-static void map_index_unset(Map *intern, const char* keyval, int length) {
-  upb_value old_value;
-  if (upb_strtable_remove2(&intern->table, keyval, length, &old_value)) {
-    switch (intern->value_type) {
-      case UPB_TYPE_MESSAGE: {
-#if PHP_MAJOR_VERSION < 7
-        zval_ptr_dtor(upb_value_memory(&old_value));
-#else
-        zend_object* object = *(zend_object**)upb_value_memory(&old_value);
-        GC_DELREF(object);
-        if(GC_REFCOUNT(object) == 0) {
-          zend_objects_store_del(object);
-        }
-#endif
-        break;
-      }
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
-        zval_ptr_dtor(upb_value_memory(&old_value));
-#else
-        zend_string* object = *(zend_string**)upb_value_memory(&old_value);
-        zend_string_release(object);
-#endif
-        break;
-      }
-      default:
-        break;
+      upb_map_set(map, upb_key, upb_val, arena);
+      zend_hash_move_forward_ex(table, &pos);
+      zval_dtor(&php_key);
     }
+  } else if (Z_TYPE_P(val) == IS_OBJECT &&
+             Z_OBJCE_P(val) == MapField_class_entry) {
+    MapField *intern = (MapField*)Z_OBJ_P(val);
+
+    if (!MapType_Eq(intern->type, type)) {
+      php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field.");
+      return NULL;
+    }
+
+    upb_arena_fuse(arena, Arena_Get(&intern->arena));
+    return intern->map;
+  } else {
+    php_error_docref(NULL, E_USER_ERROR, "Must be a map");
+    return NULL;
   }
 }
 
-bool map_index_set(Map *intern, const char* keyval, int length, upb_value v) {
-  // Replace any existing value by issuing a 'remove' operation first.
-  map_index_unset(intern, keyval, length);
+bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type) {
+  size_t iter = UPB_MAP_BEGIN;
 
-  if (!upb_strtable_insert2(&intern->table, keyval, length, v)) {
-    zend_error(E_USER_ERROR, "Could not insert into table");
-    return false;
+  if ((m1 == NULL) != (m2 == NULL)) return false;
+  if (m1 == NULL) return true;
+  if (upb_map_size(m1) != upb_map_size(m2)) return false;
+
+  while (upb_mapiter_next(m1, &iter)) {
+    upb_msgval key = upb_mapiter_key(m1, iter);
+    upb_msgval val1 = upb_mapiter_value(m1, iter);
+    upb_msgval val2;
+
+    if (!upb_map_get(m2, key, &val2)) return false;
+    if (!ValueEq(val1, val2, type.val_type)) return false;
   }
 
   return true;
 }
 
-static void map_field_write_dimension(zval *object, zval *key,
-                                      zval *value TSRMLS_DC) {
-  Map *intern = UNBOX(Map, object);
 
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-  void* mem;
-  if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
-    return;
-  }
+// MapField PHP methods ////////////////////////////////////////////////////////
 
-  mem = upb_value_memory(&v);
-  memset(mem, 0, native_slot_size(intern->value_type));
-  if (!native_slot_set_by_map(intern->value_type, intern->msg_ce, mem,
-                                value TSRMLS_CC)) {
-    return;
-  }
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_UINT64;
-#endif
-
-  map_index_set(intern, keyval, length, v);
-}
-
-static bool map_field_unset_dimension(zval *object, zval *key TSRMLS_DC) {
-  Map *intern = UNBOX(Map, object);
-
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
-    return false;
-  }
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_UINT64;
-#endif
-
-  map_index_unset(intern, keyval, length);
-
-  return true;
-}
-
-// -----------------------------------------------------------------------------
-// PHP MapField Methods
-// -----------------------------------------------------------------------------
-
+/**
+ * MapField::__construct()
+ *
+ * Constructs an instance of MapField.
+ * @param long Key type.
+ * @param long Value type.
+ * @param string Message/Enum class (message/enum value types only).
+ */
 PHP_METHOD(MapField, __construct) {
-  long key_type, value_type;
+  MapField *intern = (MapField*)Z_OBJ_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  zend_long key_type, val_type;
   zend_class_entry* klass = NULL;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|C", &key_type,
-                            &value_type, &klass) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|C", &key_type, &val_type,
+                            &klass) != SUCCESS) {
     return;
   }
 
-  Map *intern = UNBOX(Map, getThis());
-  intern->key_type = to_fieldtype(key_type);
-  intern->value_type = to_fieldtype(value_type);
-  intern->msg_ce = klass;
+  intern->type.key_type = pbphp_dtype_to_type(key_type);
+  intern->type.val_type.type = pbphp_dtype_to_type(val_type);
+  intern->type.val_type.desc = Descriptor_GetFromClassEntry(klass);
 
   // Check that the key type is an allowed type.
-  switch (intern->key_type) {
+  switch (intern->type.key_type) {
     case UPB_TYPE_INT32:
     case UPB_TYPE_INT64:
     case UPB_TYPE_UINT32:
@@ -427,107 +292,323 @@
     default:
       zend_error(E_USER_ERROR, "Invalid key type for map.");
   }
+
+  if (intern->type.val_type.type == UPB_TYPE_MESSAGE && klass == NULL) {
+    php_error_docref(NULL, E_USER_ERROR,
+                     "Message/enum type must have concrete class.");
+    return;
+  }
+
+  intern->map =
+      upb_map_new(arena, intern->type.key_type, intern->type.val_type.type);
+  ObjCache_Add(intern->map, &intern->std);
 }
 
+/**
+ * MapField::offsetExists()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   isset($map[$idx]);
+ *   empty($map[$idx]);
+ *
+ * @param long The index to be checked.
+ * @return bool True if the element at the given index exists.
+ */
 PHP_METHOD(MapField, offsetExists) {
+  MapField *intern = (MapField*)Z_OBJ_P(getThis());
   zval *key;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) ==
-      FAILURE) {
+  upb_msgval upb_key;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
+      !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
     return;
   }
 
-  Map *intern = UNBOX(Map, getThis());
-
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_UINT64;
-#endif
-  if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
-    RETURN_BOOL(false);
-  }
-
-  RETURN_BOOL(upb_strtable_lookup2(&intern->table, keyval, length, &v));
+  RETURN_BOOL(upb_map_get(intern->map, upb_key, NULL));
 }
 
+/**
+ * MapField::offsetGet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   $x = $map[$idx];
+ *
+ * @param long The index of the element to be fetched.
+ * @return object The stored element at given index.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ */
 PHP_METHOD(MapField, offsetGet) {
-  zval *index;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) ==
-      FAILURE) {
+  MapField *intern = (MapField*)Z_OBJ_P(getThis());
+  zval *key;
+  zval ret;
+  upb_msgval upb_key, upb_val;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
+      !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
     return;
   }
-  map_field_read_dimension(getThis(), index, BP_VAR_R,
-                           ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
+
+  if (!upb_map_get(intern->map, upb_key, &upb_val)) {
+    zend_error(E_USER_ERROR, "Given key doesn't exist.");
+    return;
+  }
+
+  Convert_UpbToPhp(upb_val, &ret, intern->type.val_type, &intern->arena);
+  RETURN_COPY_VALUE(&ret);
 }
 
+/**
+ * MapField::offsetSet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   $map[$idx] = $x;
+ *
+ * @param long The index of the element to be assigned.
+ * @param object The element to be assigned.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ * @exception Incorrect type of the element.
+ */
 PHP_METHOD(MapField, offsetSet) {
-  zval *index, *value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) ==
-      FAILURE) {
+  MapField *intern = (MapField*)Z_OBJ_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  zval *key, *val;
+  upb_msgval upb_key, upb_val;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS ||
+      !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL) ||
+      !Convert_PhpToUpb(val, &upb_val, intern->type.val_type, arena)) {
     return;
   }
-  map_field_write_dimension(getThis(), index, value TSRMLS_CC);
+
+  upb_map_set(intern->map, upb_key, upb_val, arena);
 }
 
+/**
+ * MapField::offsetUnset()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ *   unset($map[$idx]);
+ *
+ * @param long The index of the element to be removed.
+ * @exception Invalid type for index.
+ * @exception The element to be removed is not at the end of the MapField.
+ */
 PHP_METHOD(MapField, offsetUnset) {
-  zval *index;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) ==
-      FAILURE) {
+  MapField *intern = (MapField*)Z_OBJ_P(getThis());
+  zval *key;
+  upb_msgval upb_key;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
+      !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
     return;
   }
-  map_field_unset_dimension(getThis(), index TSRMLS_CC);
+
+  upb_map_delete(intern->map, upb_key);
 }
 
+/**
+ * MapField::count()
+ *
+ * Implements the Countable interface. Invoked when PHP code calls:
+ *
+ *   $len = count($map);
+ * Return the number of stored elements.
+ * This will also be called for: count($map)
+ * @return long The number of stored elements.
+ */
 PHP_METHOD(MapField, count) {
-  Map *intern = UNBOX(Map, getThis());
+  MapField *intern = (MapField*)Z_OBJ_P(getThis());
 
   if (zend_parse_parameters_none() == FAILURE) {
     return;
   }
 
-  RETURN_LONG(upb_strtable_count(&intern->table));
+  RETURN_LONG(upb_map_size(intern->map));
 }
 
+/**
+ * MapField::getIterator()
+ *
+ * Implements the IteratorAggregate interface. Invoked when PHP code calls:
+ *
+ *   foreach ($arr) {}
+ *
+ * @return object Beginning iterator.
+ */
 PHP_METHOD(MapField, getIterator) {
-  CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value,
-                                   map_field_iter_type);
+  zval ret;
+  MapFieldIter_make(&ret, getThis());
+  RETURN_COPY_VALUE(&ret);
+}
 
-  MapIter *iter = UNBOX(MapIter, return_value);
-  map_begin(getThis(), iter TSRMLS_CC);
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
+  ZEND_ARG_INFO(0, key_type)
+  ZEND_ARG_INFO(0, value_type)
+  ZEND_ARG_INFO(0, value_class)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
+  ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
+  ZEND_ARG_INFO(0, index)
+  ZEND_ARG_INFO(0, newval)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry MapField_methods[] = {
+  PHP_ME(MapField, __construct,  arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, offsetGet,    arginfo_offsetGet, ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, offsetSet,    arginfo_offsetSet, ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, offsetUnset,  arginfo_offsetGet, ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, count,        arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, getIterator,  arginfo_void,      ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+// -----------------------------------------------------------------------------
+// MapFieldIter
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  zend_object std;
+  zval map_field;
+  size_t position;
+} MapFieldIter;
+
+zend_class_entry *MapFieldIter_class_entry;
+static zend_object_handlers MapFieldIter_object_handlers;
+
+/**
+ * MapFieldIter_create()
+ *
+ * PHP class entry function to allocate and initialize a new MapFieldIter
+ * object.
+ */
+zend_object* MapFieldIter_create(zend_class_entry *class_type) {
+  MapFieldIter *intern = emalloc(sizeof(MapFieldIter));
+  zend_object_std_init(&intern->std, class_type);
+  intern->std.handlers = &MapFieldIter_object_handlers;
+  ZVAL_NULL(&intern->map_field);
+  intern->position = 0;
+  // Skip object_properties_init(), we don't allow derived classes.
+  return &intern->std;
+}
+
+/**
+ * MapFieldIter_dtor()
+ *
+ * Object handler to destroy a MapFieldIter. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void map_field_iter_dtor(zend_object* obj) {
+  MapFieldIter* intern = (MapFieldIter*)obj;
+  zval_ptr_dtor(&intern->map_field);
+  zend_object_std_dtor(&intern->std);
+}
+
+/**
+ * MapFieldIter_make()
+ *
+ * Function to create a MapFieldIter directly from C.
+ */
+static void MapFieldIter_make(zval *val, zval *map_field) {
+  MapFieldIter *iter;
+  ZVAL_OBJ(val,
+           MapFieldIter_class_entry->create_object(MapFieldIter_class_entry));
+  iter = (MapFieldIter*)Z_OBJ_P(val);
+  ZVAL_COPY(&iter->map_field, map_field);
 }
 
 // -----------------------------------------------------------------------------
-// Map Iterator
+// PHP MapFieldIter Methods
 // -----------------------------------------------------------------------------
 
-void map_begin(zval *map_php, MapIter *iter TSRMLS_DC) {
-  Map *self = UNBOX(Map, map_php);
-  map_begin_internal(self, iter);
+/*
+ * When a user writes:
+ *
+ *   foreach($arr as $key => $val) {}
+ *
+ * PHP translates this into:
+ *
+ *   $iter = $arr->getIterator();
+ *   for ($iter->rewind(); $iter->valid(); $iter->next()) {
+ *     $key = $iter->key();
+ *     $val = $iter->current();
+ *   }
+ */
+
+/**
+ * MapFieldIter::rewind()
+ *
+ * Implements the Iterator interface. Sets the iterator to the first element.
+ */
+PHP_METHOD(MapFieldIter, rewind) {
+  MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+  MapField *map_field = (MapField*)Z_OBJ_P(&intern->map_field);
+  intern->position = UPB_MAP_BEGIN;
+  upb_mapiter_next(map_field->map, &intern->position);
 }
 
-void map_next(MapIter *iter) {
-  upb_strtable_next(&iter->it);
+/**
+ * MapFieldIter::current()
+ *
+ * Implements the Iterator interface. Returns the current value.
+ */
+PHP_METHOD(MapFieldIter, current) {
+  MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+  MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+  upb_msgval upb_val = upb_mapiter_value(field->map, intern->position);
+  zval ret;
+  Convert_UpbToPhp(upb_val, &ret, field->type.val_type, &field->arena);
+  RETURN_COPY_VALUE(&ret);
 }
 
-bool map_done(MapIter *iter) {
-  return upb_strtable_done(&iter->it);
+/**
+ * MapFieldIter::key()
+ *
+ * Implements the Iterator interface. Returns the current key.
+ */
+PHP_METHOD(MapFieldIter, key) {
+  MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+  MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+  upb_msgval upb_key = upb_mapiter_key(field->map, intern->position);
+  zval ret;
+  Convert_UpbToPhp(upb_key, &ret, KeyType(field->type), NULL);
+  RETURN_COPY_VALUE(&ret);
 }
 
-const char *map_iter_key(MapIter *iter, int *len) {
-  *len = upb_strtable_iter_keylength(&iter->it);
-  return upb_strtable_iter_key(&iter->it);
+/**
+ * MapFieldIter::next()
+ *
+ * Implements the Iterator interface. Advances to the next element.
+ */
+PHP_METHOD(MapFieldIter, next) {
+  MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+  MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+  upb_mapiter_next(field->map, &intern->position);
 }
 
-upb_value map_iter_value(MapIter *iter, int *len) {
-  *len = native_slot_size(iter->self->value_type);
-  return upb_strtable_iter_value(&iter->it);
+/**
+ * MapFieldIter::valid()
+ *
+ * Implements the Iterator interface. Returns true if this is a valid element.
+ */
+PHP_METHOD(MapFieldIter, valid) {
+  MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+  MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+  bool done = upb_mapiter_done(field->map, intern->position);
+  RETURN_BOOL(!done);
 }
 
-// -----------------------------------------------------------------------------
-// MapFieldIter methods
-// -----------------------------------------------------------------------------
 static zend_function_entry map_field_iter_methods[] = {
   PHP_ME(MapFieldIter, rewind,      arginfo_void, ZEND_ACC_PUBLIC)
   PHP_ME(MapFieldIter, current,     arginfo_void, ZEND_ACC_PUBLIC)
@@ -538,65 +619,50 @@
 };
 
 // -----------------------------------------------------------------------------
-// MapFieldIter creation/destruction
+// Module init.
 // -----------------------------------------------------------------------------
 
-// Define object free method.
-PHP_PROTO_OBJECT_EMPTY_FREE_START(MapIter, map_field_iter)
-PHP_PROTO_OBJECT_FREE_END
+/**
+ * Map_ModuleInit()
+ *
+ * Called when the C extension is loaded to register all types.
+ */
 
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(MapIter, map_field_iter)
-PHP_PROTO_OBJECT_DTOR_END
+void Map_ModuleInit() {
+  zend_class_entry tmp_ce;
+  zend_object_handlers *h;
 
-// Define object create method.
-PHP_PROTO_OBJECT_CREATE_START(MapIter, map_field_iter)
-intern->self = NULL;
-PHP_PROTO_OBJECT_CREATE_END(MapIter, map_field_iter)
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapField",
+                   MapField_methods);
 
-// Init class entry.
-PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapFieldIter",
-                           MapIter, map_field_iter)
-zend_class_implements(map_field_iter_type TSRMLS_CC, 1, zend_ce_iterator);
-PHP_PROTO_INIT_CLASS_END
+  MapField_class_entry = zend_register_internal_class(&tmp_ce);
+  zend_class_implements(MapField_class_entry, 3, spl_ce_ArrayAccess,
+                        zend_ce_aggregate, spl_ce_Countable);
+  MapField_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  MapField_class_entry->create_object = MapField_create;
 
-// -----------------------------------------------------------------------------
-// PHP MapFieldIter Methods
-// -----------------------------------------------------------------------------
+  h = &MapField_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = MapField_destructor;
+#if PHP_VERSION_ID < 80000
+  h->compare_objects = MapField_compare_objects;
+#else
+  h->compare = MapField_compare_objects;
+#endif
+  h->clone_obj = MapField_clone_obj;
+  h->get_properties = Map_GetProperties;
+  h->get_property_ptr_ptr = Map_GetPropertyPtrPtr;
 
-PHP_METHOD(MapFieldIter, rewind) {
-  MapIter *intern = UNBOX(MapIter, getThis());
-  map_begin_internal(intern->self, intern);
-}
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter",
+                   map_field_iter_methods);
 
-PHP_METHOD(MapFieldIter, current) {
-  MapIter *intern = UNBOX(MapIter, getThis());
-  Map *map_field = intern->self;
+  MapFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
+  zend_class_implements(MapFieldIter_class_entry, 1, zend_ce_iterator);
+  MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
+  MapFieldIter_class_entry->create_object = MapFieldIter_create;
 
-  int value_length = 0;
-  upb_value value = map_iter_value(intern, &value_length);
-
-  void* mem = upb_value_memory(&value);
-  native_slot_get_by_map_value(map_field->value_type, mem,
-                               ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
-PHP_METHOD(MapFieldIter, key) {
-  MapIter *intern = UNBOX(MapIter, getThis());
-  Map *map_field = intern->self;
-
-  int key_length = 0;
-  const char* key = map_iter_key(intern, &key_length);
-
-  native_slot_get_by_map_key(map_field->key_type, key, key_length,
-                             ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
-PHP_METHOD(MapFieldIter, next) {
-  MapIter *intern = UNBOX(MapIter, getThis());
-  map_next(intern);
-}
-
-PHP_METHOD(MapFieldIter, valid) {
-  MapIter *intern = UNBOX(MapIter, getThis());
-  RETURN_BOOL(!map_done(intern));
+  h = &MapFieldIter_object_handlers;
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = map_field_iter_dtor;
 }
diff --git a/php/ext/google/protobuf/map.h b/php/ext/google/protobuf/map.h
new file mode 100644
index 0000000..c523cd0
--- /dev/null
+++ b/php/ext/google/protobuf/map.h
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PHP_PROTOBUF_MAP_H_
+#define PHP_PROTOBUF_MAP_H_
+
+#include <php.h>
+
+#include "def.h"
+#include "php-upb.h"
+
+void Map_ModuleInit();
+
+typedef struct {
+  upb_fieldtype_t key_type;
+  TypeInfo val_type;
+} MapField_Type;
+
+MapField_Type MapType_Get(const upb_fielddef *f);
+
+// Gets a upb_map* for the PHP object |val|:
+//  * If |val| is a RepeatedField object, we first check its type and verify
+//    that that the elements have the correct type for |f|. If so, we return the
+//    wrapped upb_map*. We also make sure that this map's arena is fused to
+//    |arena|, so the returned upb_map is guaranteed to live as long as
+//    |arena|.
+//  * If |val| is a PHP Map, we attempt to create a new upb_map using
+//    |arena| and add all of the PHP elements to it.
+//
+// If an error occurs, we raise a PHP error and return NULL.
+upb_map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_arena *arena);
+
+// Creates a PHP MapField object for the given upb_map* and |f| and returns it
+// in |val|. The PHP object will keep a reference to this |arena| to ensure the
+// underlying array data stays alive.
+//
+// If |map| is NULL, this will return a PHP null object.
+void MapField_GetPhpWrapper(zval *val, upb_map *arr, MapField_Type type,
+                            zval *arena);
+
+bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type);
+
+#endif  // PHP_PROTOBUF_MAP_H_
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index e8d4c6f..923890b 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -28,1820 +28,1307 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <php.h>
-#include <Zend/zend_exceptions.h>
-#include <stdlib.h>
+#include "message.h"
+
 #include <inttypes.h>
+#include <php.h>
+#include <stdlib.h>
 
-#if PHP_MAJOR_VERSION < 7
-#include <Zend/zend_compile.h>
-#else
+// This is not self-contained: it must be after other Zend includes.
+#include <Zend/zend_exceptions.h>
 #include <Zend/zend_inheritance.h>
-#endif
 
+#include "arena.h"
+#include "array.h"
+#include "convert.h"
+#include "def.h"
+#include "map.h"
+#include "php-upb.h"
 #include "protobuf.h"
-#include "utf8.h"
-
-zend_class_entry* message_type;
-zend_object_handlers* message_handlers;
-static const char TYPE_URL_PREFIX[] = "type.googleapis.com/";
-static void hex_to_binary(const char* hex, char** binary, int* binary_len);
-
-static  zend_function_entry message_methods[] = {
-  PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED)
-  PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED)
-  {NULL, NULL, NULL}
-};
-
-// Forward declare static functions.
-
-#if PHP_MAJOR_VERSION < 7
-static void message_set_property(zval* object, zval* member, zval* value,
-                                 php_proto_zend_literal key TSRMLS_DC);
-static zval* message_get_property(zval* object, zval* member, int type,
-                                  const zend_literal* key TSRMLS_DC);
-static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type,
-                                           php_proto_zend_literal key TSRMLS_DC);
-static HashTable* message_get_gc(zval* object, zval*** table, int* n TSRMLS_DC);
-#else
-#if PHP_VERSION_ID < 70400
-static void message_set_property(zval* object, zval* member, zval* value,
-                                 void** cache_slot);
-#else
-static zval* message_set_property(zval* object, zval* member, zval* value,
-                                  void** cache_slot);
-#endif
-static zval* message_get_property(zval* object, zval* member, int type,
-                                  void** cache_slot, zval* rv);
-static zval* message_get_property_ptr_ptr(zval* object, zval* member, int type,
-                                          void** cache_slot);
-static HashTable* message_get_gc(zval* object, zval** table, int* n);
-#endif
-static HashTable* message_get_properties(zval* object TSRMLS_DC);
 
 // -----------------------------------------------------------------------------
-// PHP Message Handlers
+// Message
 // -----------------------------------------------------------------------------
 
-// Define object free method.
-PHP_PROTO_OBJECT_FREE_START(MessageHeader, message)
-  if (intern->data) {
-    if (*(void**)intern->data != NULL) {
-      stringsink_uninit_opaque(*(void**)intern->data);
-      FREE(*(void**)intern->data);
+typedef struct {
+  zend_object std;
+  zval arena;
+  const Descriptor* desc;
+  upb_msg *msg;
+} Message;
+
+zend_class_entry *message_ce;
+static zend_object_handlers message_object_handlers;
+
+static void Message_SuppressDefaultProperties(zend_class_entry *class_type) {
+  // We suppress all default properties, because all our properties are handled
+  // by our read_property handler.
+  //
+  // This also allows us to put our zend_object member at the beginning of our
+  // struct -- instead of putting it at the end with pointer fixups to access
+  // our own data, as recommended in the docs -- because Zend won't add any of
+  // its own storage directly after the zend_object if default_properties_count
+  // == 0.
+  //
+  // This is not officially supported, but since it simplifies the code, we'll
+  // do it for as long as it works in practice.
+  class_type->default_properties_count = 0;
+}
+
+// PHP Object Handlers /////////////////////////////////////////////////////////
+
+/**
+ * Message_create()
+ *
+ * PHP class entry function to allocate and initialize a new Message object.
+ */
+static zend_object* Message_create(zend_class_entry *class_type) {
+  Message *intern = emalloc(sizeof(Message));
+  Message_SuppressDefaultProperties(class_type);
+  zend_object_std_init(&intern->std, class_type);
+  intern->std.handlers = &message_object_handlers;
+  Arena_Init(&intern->arena);
+  return &intern->std;
+}
+
+/**
+ * Message_dtor()
+ *
+ * Object handler to destroy a Message. This releases all resources associated
+ * with the message. Note that it is possible to access a destroyed object from
+ * PHP in rare cases.
+ */
+static void Message_dtor(zend_object* obj) {
+  Message* intern = (Message*)obj;
+  ObjCache_Delete(intern->msg);
+  zval_dtor(&intern->arena);
+  zend_object_std_dtor(&intern->std);
+}
+
+/**
+ * get_field()
+ *
+ * Helper function to look up a field given a member name (as a string).
+ */
+static const upb_fielddef *get_field(Message *msg, PROTO_STR *member) {
+  const upb_msgdef *m = msg->desc->msgdef;
+  const upb_fielddef *f =
+      upb_msgdef_ntof(m, PROTO_STRVAL_P(member), PROTO_STRLEN_P(member));
+
+  if (!f) {
+    zend_throw_exception_ex(NULL, 0, "No such property %s.",
+                            ZSTR_VAL(msg->desc->class_entry->name));
+  }
+
+  return f;
+}
+
+static void Message_get(Message *intern, const upb_fielddef *f, zval *rv) {
+  upb_arena *arena = Arena_Get(&intern->arena);
+
+  if (upb_fielddef_ismap(f)) {
+    upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
+    MapField_GetPhpWrapper(rv, msgval.map, MapType_Get(f), &intern->arena);
+  } else if (upb_fielddef_isseq(f)) {
+    upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
+    RepeatedField_GetPhpWrapper(rv, msgval.array, TypeInfo_Get(f),
+                                &intern->arena);
+  } else {
+    if (upb_fielddef_issubmsg(f) && !upb_msg_has(intern->msg, f)) {
+      ZVAL_NULL(rv);
+      return;
     }
-    FREE(intern->data);
+    upb_msgval msgval = upb_msg_get(intern->msg, f);
+    Convert_UpbToPhp(msgval, rv, TypeInfo_Get(f), &intern->arena);
   }
-PHP_PROTO_OBJECT_FREE_END
+}
 
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(MessageHeader, message)
-PHP_PROTO_OBJECT_DTOR_END
+static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) {
+  upb_arena *arena = Arena_Get(&intern->arena);
+  upb_msgval msgval;
 
-// Define object create method.
-PHP_PROTO_OBJECT_CREATE_START(MessageHeader, message)
-// Because php call this create func before calling the sub-message's
-// constructor defined in PHP, it's possible that the descriptor of this class
-// hasn't been added to descriptor pool (when the class is first
-// instantiated). In that case, we will defer the initialization of the custom
-// data to the parent Message's constructor, which will be called by
-// sub-message's constructors after the descriptor has been added.
-PHP_PROTO_OBJECT_CREATE_END(MessageHeader, message)
-
-// Init class entry.
-PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\Message",
-                           MessageHeader, message)
-  message_handlers->write_property = message_set_property;
-  message_handlers->read_property = message_get_property;
-  message_handlers->get_property_ptr_ptr = message_get_property_ptr_ptr;
-  message_handlers->get_properties = message_get_properties;
-  message_handlers->get_gc = message_get_gc;
-PHP_PROTO_INIT_CLASS_END
-
-static void message_set_property_internal(zval* object, zval* member,
-                                          zval* value TSRMLS_DC) {
-  const upb_fielddef* field;
-
-  MessageHeader* self = UNBOX(MessageHeader, object);
-
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
-  if (field == NULL) {
-    zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(member));
+  if (upb_fielddef_ismap(f)) {
+    msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena);
+    if (!msgval.map_val) return false;
+  } else if (upb_fielddef_isseq(f)) {
+    msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena);
+    if (!msgval.array_val) return false;
+  } else if (upb_fielddef_issubmsg(f) && Z_TYPE_P(val) == IS_NULL) {
+    upb_msg_clearfield(intern->msg, f);
+    return true;
+  } else {
+    if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) return false;
   }
 
-  layout_set(self->descriptor->layout, self, field, value TSRMLS_CC);
+  upb_msg_set(intern->msg, f, msgval, arena);
+  return true;
 }
 
-#if PHP_MAJOR_VERSION < 7
-static void message_set_property(zval* object, zval* member, zval* value,
-                                 php_proto_zend_literal key TSRMLS_DC) {
-#elif PHP_VERSION_ID < 70400
-static void message_set_property(zval* object, zval* member, zval* value,
-                                 void** cache_slot) {
-#else
-static zval* message_set_property(zval* object, zval* member, zval* value,
-                                  void** cache_slot) {
-#endif
-  if (Z_TYPE_P(member) != IS_STRING) {
-    zend_error(E_USER_ERROR, "Unexpected type for field name");
-#if PHP_VERSION_ID < 70400
-    return;
-#else
-    return value;
-#endif
+static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
+
+/**
+ * ValueEq()
+ */
+bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type) {
+  switch (type.type) {
+    case UPB_TYPE_BOOL:
+      return val1.bool_val == val2.bool_val;
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return val1.int32_val == val2.int32_val;
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return val1.int64_val == val2.int64_val;
+    case UPB_TYPE_FLOAT:
+      return val1.float_val == val2.float_val;
+    case UPB_TYPE_DOUBLE:
+      return val1.double_val == val2.double_val;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return val1.str_val.size == val2.str_val.size &&
+          memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) == 0;
+    case UPB_TYPE_MESSAGE:
+      return MessageEq(val1.msg_val, val2.msg_val, type.desc->msgdef);
+    default:
+      return false;
   }
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-  if (Z_OBJCE_P(object) != EG(scope)) {
-#else
-  if (Z_OBJCE_P(object) != zend_get_executed_scope()) {
-#endif
-    // User cannot set property directly (e.g., $m->a = 1)
-    zend_error(E_USER_ERROR, "Cannot access private property.");
-#if PHP_VERSION_ID < 70400
-    return;
-#else
-    return value;
-#endif
-  }
-
-  message_set_property_internal(object, member, value TSRMLS_CC);
-#if PHP_VERSION_ID >= 70400
-  return value;
-#endif
 }
 
-static zval* message_get_property_internal(zval* object,
-                                           zval* member TSRMLS_DC) {
-  MessageHeader* self = UNBOX(MessageHeader, object);
-  const upb_fielddef* field;
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
-  if (field == NULL) {
-    return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
-  }
+/**
+ * MessageEq()
+ */
+static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) {
+  upb_msg_field_iter i;
 
-  zend_property_info* property_info;
-#if PHP_MAJOR_VERSION < 7
-  property_info =
-      zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC);
-#else
-  property_info =
-      zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true);
-#endif
-  return layout_get(
-      self->descriptor->layout, self, field,
-      OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC);
-}
+  for(upb_msg_field_begin(&i, m);
+      !upb_msg_field_done(&i);
+      upb_msg_field_next(&i)) {
+    const upb_fielddef *f = upb_msg_iter_field(&i);
 
-static void message_get_oneof_property_internal(zval* object, zval* member,
-                                                zval* return_value TSRMLS_DC) {
-  MessageHeader* self = UNBOX(MessageHeader, object);
-  const upb_fielddef* field;
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
-  if (field == NULL) {
-    return;
-  }
-
-  layout_get(self->descriptor->layout, self, field,
-             ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
-#if PHP_MAJOR_VERSION < 7
-static zval* message_get_property(zval* object, zval* member, int type,
-                                  const zend_literal* key TSRMLS_DC) {
-#else
-static zval* message_get_property(zval* object, zval* member, int type,
-                                  void** cache_slot, zval* rv) {
-#endif
-  if (Z_TYPE_P(member) != IS_STRING) {
-    zend_error(E_USER_ERROR, "Property name has to be a string.");
-    return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
-  }
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-  if (Z_OBJCE_P(object) != EG(scope)) {
-#else
-  if (Z_OBJCE_P(object) != zend_get_executed_scope()) {
-#endif
-    // User cannot get property directly (e.g., $a = $m->a)
-    zend_error(E_USER_ERROR, "Cannot access private property.");
-    return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
-  }
-
-  return message_get_property_internal(object, member TSRMLS_CC);
-}
-
-#if PHP_MAJOR_VERSION < 7
-static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type,
-                                           php_proto_zend_literal key
-                                               TSRMLS_DC) {
-#else
-static zval* message_get_property_ptr_ptr(zval* object, zval* member, int type,
-                                          void** cache_slot) {
-#endif
-  return NULL;
-}
-
-static HashTable* message_get_properties(zval* object TSRMLS_DC) {
-  return NULL;
-}
-
-static HashTable* message_get_gc(zval* object, CACHED_VALUE** table,
-                                 int* n TSRMLS_DC) {
-  zend_object* zobj = Z_OBJ_P(object);
-  *table = zobj->properties_table;
-  *n = zobj->ce->default_properties_count;
-  return NULL;
-}
-
-// -----------------------------------------------------------------------------
-// C Message Utilities
-// -----------------------------------------------------------------------------
-
-void* message_data(MessageHeader* msg) {
-  return msg->data;
-}
-
-void custom_data_init(const zend_class_entry* ce,
-                      MessageHeader* intern PHP_PROTO_TSRMLS_DC) {
-  DescriptorInternal* desc = get_ce_desc(ce);
-  intern->data = ALLOC_N(uint8_t, desc->layout->size);
-  // We wrap first so that everything in the message object is GC-rooted in
-  // case a collection happens during object creation in layout_init().
-  intern->descriptor = desc;
-  layout_init(desc->layout, message_data(intern),
-              &intern->std PHP_PROTO_TSRMLS_CC);
-}
-
-#define INIT_MESSAGE_WITH_ARRAY                                    \
-  {                                                                \
-    zval* array_wrapper = NULL;                                    \
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,           \
-                              "|a!", &array_wrapper) == FAILURE) { \
-      return;                                                      \
-    }                                                              \
-    Message_construct(getThis(), array_wrapper);                   \
-  }
-
-// -----------------------------------------------------------------------------
-// PHP Methods
-// -----------------------------------------------------------------------------
-
-static void append_wrapper_message(
-    zend_class_entry* subklass, RepeatedField* intern, zval* value TSRMLS_DC) {
-  MessageHeader* submsg;
-  const upb_fielddef* field;
-#if PHP_MAJOR_VERSION < 7
-  zval* val = NULL;
-  MAKE_STD_ZVAL(val);
-  ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
-  repeated_field_push_native(intern, &val);
-  submsg = UNBOX(MessageHeader, val);
-#else
-  zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-  repeated_field_push_native(intern, &obj);
-  submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
-#endif
-  custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-
-  field = upb_msgdef_itof(submsg->descriptor->msgdef, 1);
-  layout_set(submsg->descriptor->layout, submsg, field, value TSRMLS_CC);
-}
-
-static void set_wrapper_message_as_map_value(
-    zend_class_entry* subklass, zval* map, zval* key,  zval* value TSRMLS_DC) {
-  MessageHeader* submsg;
-  const upb_fielddef* field;
-#if PHP_MAJOR_VERSION < 7
-  zval* val = NULL;
-  MAKE_STD_ZVAL(val);
-  ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
-  map_field_handlers->write_dimension(
-      map, key, val TSRMLS_CC);
-  submsg = UNBOX(MessageHeader, val);
-#else
-  zval val;
-  zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
-  ZVAL_OBJ(&val, obj);
-  map_field_handlers->write_dimension(map, key, &val TSRMLS_CC);
-  submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
-#endif
-  custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-
-  field = upb_msgdef_itof(submsg->descriptor->msgdef, 1);
-  layout_set(submsg->descriptor->layout, submsg, field, value TSRMLS_CC);
-}
-
-void Message_construct(zval* msg, zval* array_wrapper) {
-  TSRMLS_FETCH();
-  zend_class_entry* ce = Z_OBJCE_P(msg);
-  MessageHeader* intern = NULL;
-
-  if (!class_added(ce)) {
-#if PHP_MAJOR_VERSION < 7
-    DescriptorInternal* desc = get_class_desc(ce->name);
-#else
-    DescriptorInternal* desc = get_class_desc(ZSTR_VAL(ce->name));
-#endif
-    register_class(desc, false TSRMLS_CC);
-  }
-
-  intern = UNBOX(MessageHeader, msg);
-  custom_data_init(ce, intern PHP_PROTO_TSRMLS_CC);
-
-  if (array_wrapper == NULL) {
-    return;
-  }
-
-  HashTable* array = Z_ARRVAL_P(array_wrapper);
-  HashPosition pointer;
-  zval key;
-  void* value;
-  const upb_fielddef* field;
-
-  for (zend_hash_internal_pointer_reset_ex(array, &pointer);
-       php_proto_zend_hash_get_current_data_ex(array, (void**)&value,
-                                               &pointer) == SUCCESS;
-       zend_hash_move_forward_ex(array, &pointer)) {
-    zend_hash_get_current_key_zval_ex(array, &key, &pointer);
-    field = upb_msgdef_ntofz(intern->descriptor->msgdef, Z_STRVAL_P(&key));
-#if PHP_MAJOR_VERSION >= 7
-    if (Z_ISREF_P((CACHED_VALUE*)value)) {
-      value = Z_REFVAL_P((CACHED_VALUE*)value);
+    if (upb_fielddef_haspresence(f)) {
+      if (upb_msg_has(m1, f) != upb_msg_has(m2, f)) {
+        return false;
+      }
+      if (!upb_msg_has(m1, f)) continue;
     }
-#endif
-    if (field == NULL) {
-      zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(&key));
-    }
-    if (upb_fielddef_ismap(field)) {
-      PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
-      zval* submap = message_get_property_internal(msg, &key TSRMLS_CC);
-      PHP_PROTO_FAKE_SCOPE_END;
-      HashTable* subtable = HASH_OF(
-          CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value));
-      HashPosition subpointer;
-      zval subkey;
-      void* memory;
-      bool is_wrapper = false;
-      zend_class_entry* subklass = NULL;
-      const upb_msgdef* mapentry = upb_fielddef_msgsubdef(field);
-      const upb_fielddef *value_field = upb_msgdef_itof(mapentry, 2);
 
-      if (upb_fielddef_issubmsg(value_field)) {
-        const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(value_field);
-        is_wrapper = is_wrapper_msg(submsgdef);
+    upb_msgval val1 = upb_msg_get(m1, f);
+    upb_msgval val2 = upb_msg_get(m2, f);
 
-        if (is_wrapper) {
-          DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
-          register_class(subdesc, false TSRMLS_CC);
-          subklass = subdesc->klass;
-        }
-      }
-
-      for (zend_hash_internal_pointer_reset_ex(subtable, &subpointer);
-           php_proto_zend_hash_get_current_data_ex(subtable, (void**)&memory,
-                                                   &subpointer) == SUCCESS;
-           zend_hash_move_forward_ex(subtable, &subpointer)) {
-        zend_hash_get_current_key_zval_ex(subtable, &subkey, &subpointer);
-        if (is_wrapper &&
-            Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory)) != IS_OBJECT) {
-          set_wrapper_message_as_map_value(
-              subklass, submap, &subkey,
-              CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
-        } else {
-          map_field_handlers->write_dimension(
-              submap, &subkey,
-              CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
-        }
-        zval_dtor(&subkey);
-      }
-    } else if (upb_fielddef_isseq(field)) {
-      PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
-      zval* subarray = message_get_property_internal(msg, &key TSRMLS_CC);
-      PHP_PROTO_FAKE_SCOPE_END;
-      HashTable* subtable = HASH_OF(
-          CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value));
-      HashPosition subpointer;
-      void* memory;
-      bool is_wrapper = false;
-      zend_class_entry* subklass = NULL;
-
-      if (upb_fielddef_issubmsg(field)) {
-        const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
-        is_wrapper = is_wrapper_msg(submsgdef);
-
-        if (is_wrapper) {
-          DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
-          register_class(subdesc, false TSRMLS_CC);
-          subklass = subdesc->klass;
-        }
-      }
-
-      for (zend_hash_internal_pointer_reset_ex(subtable, &subpointer);
-           php_proto_zend_hash_get_current_data_ex(subtable, (void**)&memory,
-                                                   &subpointer) == SUCCESS;
-           zend_hash_move_forward_ex(subtable, &subpointer)) {
-        if (is_wrapper &&
-            Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory)) != IS_OBJECT) {
-          RepeatedField* intern = UNBOX(RepeatedField, subarray);
-          append_wrapper_message(
-              subklass, intern,
-              CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
-        } else {
-          repeated_field_handlers->write_dimension(
-              subarray, NULL,
-              CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
-        }
-      }
-    } else if (upb_fielddef_issubmsg(field)) {
-      const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
-      DescriptorInternal* desc = get_msgdef_desc(submsgdef);
-      register_class(desc, false TSRMLS_CC);
-
-      CACHED_VALUE* cached = NULL;
-      if (upb_fielddef_containingoneof(field)) {
-        void* memory = slot_memory(intern->descriptor->layout,
-                                   message_data(intern), field);
-        uint32_t* oneof_case = slot_oneof_case(intern->descriptor->layout,
-                                               message_data(intern), field);
-        int property_cache_index =
-            intern->descriptor->layout->fields[upb_fielddef_index(field)]
-                .cache_index;
-        cached = OBJ_PROP(Z_OBJ_P(msg), property_cache_index);
-        *(CACHED_VALUE**)(memory) = cached;
-        *oneof_case = upb_fielddef_number(field);
-      } else {
-        zend_property_info* property_info;
-        PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
-#if PHP_MAJOR_VERSION < 7
-        property_info =
-            zend_get_property_info(Z_OBJCE_P(msg), &key, true TSRMLS_CC);
-#else
-        property_info =
-            zend_get_property_info(Z_OBJCE_P(msg), Z_STR_P(&key), true);
-#endif
-        PHP_PROTO_FAKE_SCOPE_END;
-        cached = OBJ_PROP(Z_OBJ_P(msg), property_info->offset);
-      }
-#if PHP_MAJOR_VERSION < 7
-      SEPARATE_ZVAL_IF_NOT_REF(cached);
-#endif
-      zval* submsg = CACHED_PTR_TO_ZVAL_PTR(cached);
-      ZVAL_OBJ(submsg, desc->klass->create_object(desc->klass TSRMLS_CC));
-      Message_construct(submsg, NULL);
-      MessageHeader* to = UNBOX(MessageHeader, submsg);
-      const upb_filedef *file = upb_msgdef_file(submsgdef);
-      if (!strcmp(upb_filedef_name(file), "google/protobuf/wrappers.proto") &&
-          Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value)) != IS_OBJECT) {
-        const upb_fielddef *value_field = upb_msgdef_itof(submsgdef, 1);
-        layout_set(to->descriptor->layout, to,
-                   value_field, CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value)
-                   TSRMLS_CC);
-      } else {
-        MessageHeader* from =
-            UNBOX(MessageHeader,
-                  CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value));
-        if(from->descriptor != to->descriptor) {
-          zend_error(E_USER_ERROR,
-                     "Cannot merge messages with different class.");
-          return;
-        }
-
-        layout_merge(from->descriptor->layout, from, to TSRMLS_CC);
-      }
+    if (upb_fielddef_ismap(f)) {
+      if (!MapEq(val1.map_val, val2.map_val, MapType_Get(f))) return false;
+    } else if (upb_fielddef_isseq(f)) {
+      if (!ArrayEq(val1.array_val, val2.array_val, TypeInfo_Get(f))) return false;
     } else {
-      message_set_property_internal(msg, &key,
-          CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC);
+      if (!ValueEq(val1, val2, TypeInfo_Get(f))) return false;
     }
+  }
+
+  return true;
+}
+
+/**
+ * Message_compare_objects()
+ *
+ * Object handler for comparing two message objects. Called whenever PHP code
+ * does:
+ *
+ *   $m1 == $m2
+ */
+static int Message_compare_objects(zval *m1, zval *m2) {
+  Message* intern1 = (Message*)Z_OBJ_P(m1);
+  Message* intern2 = (Message*)Z_OBJ_P(m2);
+  const upb_msgdef *m = intern1->desc->msgdef;
+
+  if (intern2->desc->msgdef != m) return 1;
+
+  return MessageEq(intern1->msg, intern2->msg, m) ? 0 : 1;
+}
+
+/**
+ * Message_has_property()
+ *
+ * Object handler for testing whether a property exists. Called when PHP code
+ * does any of:
+ *
+ *   isset($message->foobar);
+ *   property_exists($message->foobar);
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like this
+ * (if the field has presence):
+ *
+ *   public function hasOptionalInt32()
+ *   {
+ *       return isset($this->optional_int32);
+ *   }
+ */
+static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member,
+                                int has_set_exists,
+                                void **cache_slot) {
+  Message* intern = PROTO_VAL_P(obj);
+  const upb_fielddef *f = get_field(intern, member);
+
+  if (!f) return 0;
+
+  if (!upb_fielddef_haspresence(f)) {
+    zend_throw_exception_ex(
+        NULL, 0,
+        "Cannot call isset() on field %s which does not have presence.",
+        upb_fielddef_name(f));
+    return 0;
+  }
+
+  return upb_msg_has(intern->msg, f);
+}
+
+/**
+ * Message_unset_property()
+ *
+ * Object handler for unsetting a property. Called when PHP code calls:
+ *
+ *   unset($message->foobar);
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like this
+ * (if the field has presence):
+ *
+ *   public function clearOptionalInt32()
+ *   {
+ *       unset($this->optional_int32);
+ *   }
+ */
+static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member,
+                                   void **cache_slot) {
+  Message* intern = PROTO_VAL_P(obj);
+  const upb_fielddef *f = get_field(intern, member);
+
+  if (!f) return;
+
+  if (!upb_fielddef_haspresence(f)) {
+    zend_throw_exception_ex(
+        NULL, 0,
+        "Cannot call unset() on field %s which does not have presence.",
+        upb_fielddef_name(f));
+    return;
+  }
+
+  upb_msg_clearfield(intern->msg, f);
+}
+
+
+/**
+ * Message_read_property()
+ *
+ * Object handler for reading a property in PHP. Called when PHP code does:
+ *
+ *   $x = $message->foobar;
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like:
+ *
+ *   public function getOptionalInt32()
+ *   {
+ *       return $this->optional_int32;
+ *   }
+ *
+ * We lookup the field and return the scalar, RepeatedField, or MapField for
+ * this field.
+ */
+static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member,
+                                   int type, void **cache_slot, zval *rv) {
+  Message* intern = PROTO_VAL_P(obj);
+  const upb_fielddef *f = get_field(intern, member);
+
+  if (!f) return &EG(uninitialized_zval);
+  Message_get(intern, f, rv);
+  return rv;
+}
+
+/**
+ * Message_write_property()
+ *
+ * Object handler for writing a property in PHP. Called when PHP code does:
+ *
+ *   $message->foobar = $x;
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like:
+ *
+ *   public function setOptionalInt32($var)
+ *   {
+ *       GPBUtil::checkInt32($var);
+ *       $this->optional_int32 = $var;
+ *
+ *       return $this;
+ *   }
+ *
+ * The C extension version of checkInt32() doesn't actually check anything, so
+ * we perform all checking and conversion in this function.
+ */
+static PROTO_RETURN_VAL Message_write_property(
+    PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) {
+  Message* intern = PROTO_VAL_P(obj);
+  const upb_fielddef *f = get_field(intern, member);
+
+  if (f && Message_set(intern, f, val)) {
+#if PHP_VERSION_ID < 70400
+    return;
+#else
+    return val;
+#endif
+  } else {
+#if PHP_VERSION_ID < 70400
+    return;
+#else
+    return &EG(error_zval);
+#endif
+  }
+}
+
+/**
+ * Message_get_property_ptr_ptr()
+ *
+ * Object handler for the get_property_ptr_ptr event in PHP. This returns a
+ * reference to our internal properties. We don't support this, so we return
+ * NULL.
+ */
+static zval *Message_get_property_ptr_ptr(PROTO_VAL *object, PROTO_STR *member,
+                                          int type,
+                                          void **cache_slot) {
+  return NULL;  // We do not have a properties table.
+}
+
+/**
+ * Message_clone_obj()
+ *
+ * Object handler for cloning an object in PHP. Called when PHP code does:
+ *
+ *   $msg2 = clone $msg;
+ */
+static zend_object *Message_clone_obj(PROTO_VAL *object) {
+  Message* intern = PROTO_VAL_P(object);
+  upb_msg *clone = upb_msg_new(intern->desc->msgdef, Arena_Get(&intern->arena));
+
+  // TODO: copy unknown fields?
+  // TODO: use official upb msg copy function
+  memcpy(clone, intern->msg, upb_msgdef_layout(intern->desc->msgdef)->size);
+  zval ret;
+  Message_GetPhpWrapper(&ret, intern->desc, clone, &intern->arena);
+  return Z_OBJ_P(&ret);
+}
+
+/**
+ * Message_get_properties()
+ *
+ * Object handler for the get_properties event in PHP. This returns a HashTable
+ * of our internal properties. We don't support this, so we return NULL.
+ */
+static HashTable *Message_get_properties(PROTO_VAL *object) {
+  return NULL;  // We don't offer direct references to our properties.
+}
+
+// C Functions from message.h. /////////////////////////////////////////////////
+
+// These are documented in the header file.
+
+void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg,
+                           zval *arena) {
+  if (!msg) {
+    ZVAL_NULL(val);
+    return;
+  }
+
+  if (!ObjCache_Get(msg, val)) {
+    Message *intern = emalloc(sizeof(Message));
+    Message_SuppressDefaultProperties(desc->class_entry);
+    zend_object_std_init(&intern->std, desc->class_entry);
+    intern->std.handlers = &message_object_handlers;
+    ZVAL_COPY(&intern->arena, arena);
+    intern->desc = desc;
+    intern->msg = msg;
+    ZVAL_OBJ(val, &intern->std);
+    ObjCache_Add(intern->msg, &intern->std);
+  }
+}
+
+bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena,
+                           upb_msg **msg) {
+  PBPHP_ASSERT(desc);
+
+  if (Z_ISREF_P(val)) {
+    ZVAL_DEREF(val);
+  }
+
+  if (Z_TYPE_P(val) == IS_OBJECT &&
+      instanceof_function(Z_OBJCE_P(val), desc->class_entry)) {
+    Message *intern = (Message*)Z_OBJ_P(val);
+    upb_arena_fuse(arena, Arena_Get(&intern->arena));
+    *msg = intern->msg;
+    return true;
+  } else {
+    zend_throw_exception_ex(zend_ce_type_error, 0,
+                            "Given value is not an instance of %s.",
+                            ZSTR_VAL(desc->class_entry->name));
+    return false;
+  }
+}
+
+// Message PHP methods /////////////////////////////////////////////////////////
+
+/**
+ * Message_InitFromPhp()
+ *
+ * Helper method to handle the initialization of a message from a PHP value, eg.
+ *
+ *   $m = new TestMessage([
+ *       'optional_int32' => -42,
+ *       'optional_bool' => true,
+ *       'optional_string' => 'a',
+ *       'optional_enum' => TestEnum::ONE,
+ *       'optional_message' => new Sub([
+ *           'a' => 33
+ *       ]),
+ *       'repeated_int32' => [-42, -52],
+ *       'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
+ *       'repeated_message' => [new Sub(['a' => 34]),
+ *                              new Sub(['a' => 35])],
+ *       'map_int32_int32' => [-62 => -62],
+ *       'map_int32_enum' => [1 => TestEnum::ONE],
+ *       'map_int32_message' => [1 => new Sub(['a' => 36])],
+ *   ]);
+ *
+ * The initializer must be an array.
+ */
+bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init,
+                         upb_arena *arena) {
+  HashTable* table = HASH_OF(init);
+  HashPosition pos;
+
+  if (Z_ISREF_P(init)) {
+    ZVAL_DEREF(init);
+  }
+
+  if (Z_TYPE_P(init) != IS_ARRAY) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Initializer for a message %s must be an array.",
+                            upb_msgdef_fullname(m));
+    return false;
+  }
+
+  zend_hash_internal_pointer_reset_ex(table, &pos);
+
+  while (true) {  // Iterate over key/value pairs.
+    zval key;
+    zval *val;
+    const upb_fielddef *f;
+    upb_msgval msgval;
+
+    zend_hash_get_current_key_zval_ex(table, &key, &pos);
+    val = zend_hash_get_current_data_ex(table, &pos);
+
+    if (!val) return true;  // Finished iteration.
+
+    if (Z_ISREF_P(val)) {
+      ZVAL_DEREF(val);
+    }
+
+    f = upb_msgdef_ntof(m, Z_STRVAL_P(&key), Z_STRLEN_P(&key));
+
+    if (!f) {
+      zend_throw_exception_ex(NULL, 0,
+                              "No such field %s", Z_STRVAL_P(&key));
+      return false;
+    }
+
+    if (upb_fielddef_ismap(f)) {
+      msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena);
+      if (!msgval.map_val) return false;
+    } else if (upb_fielddef_isseq(f)) {
+      msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena);
+      if (!msgval.array_val) return false;
+    } else {
+      if (!Convert_PhpToUpbAutoWrap(val, &msgval, TypeInfo_Get(f), arena)) {
+        return false;
+      }
+    }
+
+    upb_msg_set(msg, f, msgval, arena);
+    zend_hash_move_forward_ex(table, &pos);
     zval_dtor(&key);
   }
 }
 
-// At the first time the message is created, the class entry hasn't been
-// modified. As a result, the first created instance will be a normal zend
-// object. Here, we manually modify it to our message in such a case.
+static void Message_Initialize(Message *intern, const Descriptor *desc) {
+  intern->desc = desc;
+  intern->msg = upb_msg_new(desc->msgdef, Arena_Get(&intern->arena));
+  ObjCache_Add(intern->msg, &intern->std);
+}
+
+/**
+ * Message::__construct()
+ *
+ * Constructor for Message.
+ * @param array Map of initial values ['k' = val]
+ */
 PHP_METHOD(Message, __construct) {
-  INIT_MESSAGE_WITH_ARRAY;
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const Descriptor* desc;
+  zend_class_entry *ce = Z_OBJCE_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  zval *init_arr = NULL;
+
+  // This descriptor should always be available, as the generated __construct
+  // method calls initOnce() to load the descriptor prior to calling us.
+  //
+  // However, if the user created their own class derived from Message, this
+  // will trigger an infinite construction loop and blow the stack.  We
+  // temporarily clear create_object to break this loop (see check in
+  // NameMap_GetMessage()).
+  PBPHP_ASSERT(ce->create_object == Message_create);
+  ce->create_object = NULL;
+  desc = Descriptor_GetFromClassEntry(ce);
+  ce->create_object = Message_create;
+
+  if (!desc) {
+    zend_throw_exception_ex(
+        NULL, 0,
+        "Couldn't find descriptor. Note only generated code may derive from "
+        "\\Google\\Protobuf\\Internal\\Message");
+    return;
+  }
+
+  Message_Initialize(intern, desc);
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) {
+    return;
+  }
+
+  if (init_arr) {
+    Message_InitFromPhp(intern->msg, desc->msgdef, init_arr, arena);
+  }
 }
 
+/**
+ * Message::discardUnknownFields()
+ *
+ * Discards any unknown fields for this message or any submessages.
+ */
+PHP_METHOD(Message, discardUnknownFields) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  upb_msg_discardunknown(intern->msg, intern->desc->msgdef, 64);
+}
+
+/**
+ * Message::clear()
+ *
+ * Clears all fields of this message.
+ */
 PHP_METHOD(Message, clear) {
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-  DescriptorInternal* desc = msg->descriptor;
-  register_class(desc, false TSRMLS_CC);
-  zend_class_entry* ce = desc->klass;
-
-  zend_object_std_dtor(&msg->std TSRMLS_CC);
-  object_properties_init(&msg->std, ce);
-
-  layout_init(desc->layout, message_data(msg), &msg->std TSRMLS_CC);
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  upb_msg_clear(intern->msg, intern->desc->msgdef);
 }
 
+/**
+ * Message::mergeFrom()
+ *
+ * Merges from the given message, which must be of the same class as us.
+ * @param object Message to merge from.
+ */
 PHP_METHOD(Message, mergeFrom) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  Message* from;
+  upb_arena *arena = Arena_Get(&intern->arena);
+  const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
   zval* value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &value,
-                            message_type) == FAILURE) {
+  char *pb;
+  size_t size;
+  bool ok;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &value,
+                            intern->desc->class_entry) == FAILURE) {
     return;
   }
 
-  MessageHeader* from = UNBOX(MessageHeader, value);
-  MessageHeader* to = UNBOX(MessageHeader, getThis());
+  from = (Message*)Z_OBJ_P(value);
 
-  if(from->descriptor != to->descriptor) {
-    zend_error(E_USER_ERROR, "Cannot merge messages with different class.");
+  // Should be guaranteed since we passed the class type to
+  // zend_parse_parameters().
+  PBPHP_ASSERT(from->desc == intern->desc);
+
+  // TODO(haberman): use a temp arena for this once we can make upb_decode()
+  // copy strings.
+  pb = upb_encode(from->msg, l, arena, &size);
+
+  if (!pb) {
+    zend_throw_exception_ex(NULL, 0, "Max nesting exceeded");
     return;
   }
 
-  layout_merge(from->descriptor->layout, from, to TSRMLS_CC);
+  ok = upb_decode(pb, size, intern->msg, l, arena);
+  PBPHP_ASSERT(ok);
 }
 
-PHP_METHOD(Message, readWrapperValue) {
-  char* member;
-  PHP_PROTO_SIZE length;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &member,
-                            &length) == FAILURE) {
+/**
+ * Message::mergeFromString()
+ *
+ * Merges from the given string.
+ * @param string Binary protobuf data to merge.
+ */
+PHP_METHOD(Message, mergeFromString) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  char *data = NULL;
+  char *data_copy = NULL;
+  zend_long data_len;
+  const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
+  upb_arena *arena = Arena_Get(&intern->arena);
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) ==
+      FAILURE) {
     return;
   }
 
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-  const upb_fielddef* field =
-      upb_msgdef_ntofz(msg->descriptor->msgdef, member);
+  // TODO(haberman): avoid this copy when we can make the decoder copy.
+  data_copy = upb_arena_malloc(arena, data_len);
+  memcpy(data_copy, data, data_len);
 
-  if (upb_fielddef_containingoneof(field)) {
-    uint32_t* oneof_case =
-        slot_oneof_case(msg->descriptor->layout, message_data(msg), field);
-    if (*oneof_case != upb_fielddef_number(field)) {
-      RETURN_NULL();
-    }
+  if (!upb_decode(data_copy, data_len, intern->msg, l, arena)) {
+    zend_throw_exception_ex(NULL, 0, "Error occurred during parsing");
+    return;
+  }
+}
+
+/**
+ * Message::serializeToString()
+ *
+ * Serializes this message instance to protobuf data.
+ * @return string Serialized protobuf data.
+ */
+PHP_METHOD(Message, serializeToString) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
+  upb_arena *tmp_arena = upb_arena_new();
+  char *data;
+  size_t size;
+
+  data = upb_encode(intern->msg, l, tmp_arena, &size);
+
+  if (!data) {
+    zend_throw_exception_ex(NULL, 0, "Error occurred during serialization");
+    upb_arena_free(tmp_arena);
+    return;
   }
 
-  zval* cached_zval =
-      CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, field));
+  RETVAL_STRINGL(data, size);
+  upb_arena_free(tmp_arena);
+}
 
-  if (Z_TYPE_P(cached_zval) == IS_NULL) {
+/**
+ * Message::mergeFromJsonString()
+ *
+ * Merges the JSON data parsed from the given string.
+ * @param string Serialized JSON data.
+ */
+PHP_METHOD(Message, mergeFromJsonString) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  char *data = NULL;
+  char *data_copy = NULL;
+  zend_long data_len;
+  upb_arena *arena = Arena_Get(&intern->arena);
+  upb_status status;
+  zend_bool ignore_json_unknown = false;
+  int options = 0;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
+                            &ignore_json_unknown) == FAILURE) {
+    return;
+  }
+
+  // TODO(haberman): avoid this copy when we can make the decoder copy.
+  data_copy = upb_arena_malloc(arena, data_len + 1);
+  memcpy(data_copy, data, data_len);
+  data_copy[data_len] = '\0';
+
+  if (ignore_json_unknown) {
+    options |= UPB_JSONDEC_IGNOREUNKNOWN;
+  }
+
+  upb_status_clear(&status);
+  if (!upb_json_decode(data_copy, data_len, intern->msg, intern->desc->msgdef,
+                       DescriptorPool_GetSymbolTable(), options, arena,
+                       &status)) {
+    zend_throw_exception_ex(NULL, 0, "Error occurred during parsing: %s",
+                            upb_status_errmsg(&status));
+    return;
+  }
+}
+
+/**
+ * Message::serializeToJsonString()
+ *
+ * Serializes this object to JSON.
+ * @return string Serialized JSON data.
+ */
+PHP_METHOD(Message, serializeToJsonString) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  size_t size;
+  int options = 0;
+  char buf[1024];
+  zend_bool preserve_proto_fieldnames = false;
+  upb_status status;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b",
+                            &preserve_proto_fieldnames) == FAILURE) {
+    return;
+  }
+
+  if (preserve_proto_fieldnames) {
+    options |= UPB_JSONENC_PROTONAMES;
+  }
+
+  upb_status_clear(&status);
+  size = upb_json_encode(intern->msg, intern->desc->msgdef,
+                         DescriptorPool_GetSymbolTable(), options, buf,
+                         sizeof(buf), &status);
+
+  if (!upb_ok(&status)) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Error occurred during JSON serialization: %s",
+                            upb_status_errmsg(&status));
+    return;
+  }
+
+  if (size >= sizeof(buf)) {
+    char *buf2 = malloc(size + 1);
+    upb_json_encode(intern->msg, intern->desc->msgdef,
+                    DescriptorPool_GetSymbolTable(), options, buf2, size + 1,
+                    &status);
+    RETVAL_STRINGL(buf2, size);
+    free(buf2);
+  } else {
+    RETVAL_STRINGL(buf, size);
+  }
+}
+
+/**
+ * Message::readWrapperValue()
+ *
+ * Returns an unboxed value for the given field. This is called from generated
+ * methods for wrapper fields, eg.
+ *
+ *   public function getDoubleValueUnwrapped()
+ *   {
+ *       return $this->readWrapperValue("double_value");
+ *   }
+ *
+ * @return Unwrapped field value or null.
+ */
+PHP_METHOD(Message, readWrapperValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  char* member;
+  const upb_fielddef *f;
+  zend_long size;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &member, &size) == FAILURE) {
+    return;
+  }
+
+  f = upb_msgdef_ntof(intern->desc->msgdef, member, size);
+
+  if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) {
+    zend_throw_exception_ex(NULL, 0, "Message %s has no field %s",
+                            upb_msgdef_fullname(intern->desc->msgdef), member);
+    return;
+  }
+
+  if (upb_msg_has(intern->msg, f)) {
+    const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val;
+    const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+    const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
+    upb_msgval msgval = upb_msg_get(wrapper, val_f);
+    zval ret;
+    Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(val_f), &intern->arena);
+    RETURN_COPY_VALUE(&ret);
+  } else {
+    RETURN_NULL();
+  }
+}
+
+/**
+ * Message::writeWrapperValue()
+ *
+ * Sets the given wrapper field to the given unboxed value. This is called from
+ * generated methods for wrapper fields, eg.
+ *
+ *
+ *   public function setDoubleValueUnwrapped($var)
+ *   {
+ *       $this->writeWrapperValue("double_value", $var);
+ *       return $this;
+ *   }
+ *
+ * @param Unwrapped field value or null.
+ */
+PHP_METHOD(Message, writeWrapperValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  char* member;
+  const upb_fielddef *f;
+  upb_msgval msgval;
+  zend_long size;
+  zval* val;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &member, &size, &val) ==
+      FAILURE) {
+    return;
+  }
+
+  f = upb_msgdef_ntof(intern->desc->msgdef, member, size);
+
+  if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) {
+    zend_throw_exception_ex(NULL, 0, "Message %s has no field %s",
+                            upb_msgdef_fullname(intern->desc->msgdef), member);
+    return;
+  }
+
+  if (Z_ISREF_P(val)) {
+    ZVAL_DEREF(val);
+  }
+
+  if (Z_TYPE_P(val) == IS_NULL) {
+    upb_msg_clearfield(intern->msg, f);
+  } else {
+    const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+    const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
+    upb_msg *wrapper;
+
+    if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) {
+      return;  // Error is already set.
+    }
+
+    wrapper = upb_msg_mutable(intern->msg, f, arena).msg;
+    upb_msg_set(wrapper, val_f, msgval, arena);
+  }
+}
+
+/**
+ * Message::whichOneof()
+ *
+ * Given a oneof name, returns the name of the field that is set for this oneof,
+ * or otherwise the empty string.
+ *
+ * @return string The field name in this oneof that is currently set.
+ */
+PHP_METHOD(Message, whichOneof) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_oneofdef* oneof;
+  const upb_fielddef* field;
+  char* name;
+  zend_long len;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &len) == FAILURE) {
+    return;
+  }
+
+  oneof = upb_msgdef_ntoo(intern->desc->msgdef, name, len);
+
+  if (!oneof) {
+    zend_throw_exception_ex(NULL, 0, "Message %s has no oneof %s",
+                            upb_msgdef_fullname(intern->desc->msgdef), name);
+    return;
+  }
+
+  field = upb_msg_whichoneof(intern->msg, oneof);
+  RETURN_STRING(field ? upb_fielddef_name(field) : "");
+}
+
+/**
+ * Message::hasOneof()
+ *
+ * Returns the presence of the given oneof field, given a field number. Called
+ * from generated code methods such as:
+ *
+ *    public function hasDoubleValueOneof()
+ *    {
+ *        return $this->hasOneof(10);
+ *    }
+ *
+ * @return boolean
+ */
+PHP_METHOD(Message, hasOneof) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  zend_long field_num;
+  const upb_fielddef* f;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &field_num) == FAILURE) {
+    return;
+  }
+
+  f = upb_msgdef_itof(intern->desc->msgdef, field_num);
+
+  if (!f || !upb_fielddef_realcontainingoneof(f)) {
+    php_error_docref(NULL, E_USER_ERROR,
+                     "Internal error, no such oneof field %d\n",
+                     (int)field_num);
+  }
+
+  RETVAL_BOOL(upb_msg_has(intern->msg, f));
+}
+
+/**
+ * Message::readOneof()
+ *
+ * Returns the contents of the given oneof field, given a field number. Called
+ * from generated code methods such as:
+ *
+ *    public function getDoubleValueOneof()
+ *    {
+ *        return $this->readOneof(10);
+ *    }
+ *
+ * @return object The oneof's field value.
+ */
+PHP_METHOD(Message, readOneof) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  zend_long field_num;
+  const upb_fielddef* f;
+  zval ret;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &field_num) == FAILURE) {
+    return;
+  }
+
+  f = upb_msgdef_itof(intern->desc->msgdef, field_num);
+
+  if (!f || !upb_fielddef_realcontainingoneof(f)) {
+    php_error_docref(NULL, E_USER_ERROR,
+                     "Internal error, no such oneof field %d\n",
+                     (int)field_num);
+  }
+
+  if (upb_fielddef_issubmsg(f) && !upb_msg_has(intern->msg, f)) {
     RETURN_NULL();
   }
 
-  if (Z_TYPE_P(cached_zval) == IS_OBJECT) {
-    const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
-    const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
-    MessageHeader* submsg = UNBOX(MessageHeader, cached_zval);
-    CACHED_VALUE* cached_value = find_zval_property(submsg, value_field);
-    layout_get(submsg->descriptor->layout, submsg, value_field,
-               cached_value TSRMLS_CC);
-    RETURN_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cached_value), 1, 0);
-  } else {
-    RETURN_ZVAL(cached_zval, 1, 0);
-  }
-}
-
-PHP_METHOD(Message, writeWrapperValue) {
-  char* member;
-  PHP_PROTO_SIZE length;
-  zval* value;
-  if (zend_parse_parameters(
-      ZEND_NUM_ARGS() TSRMLS_CC, "sz", &member, &length, &value) ==
-      FAILURE) {
-    return;
-  }
-
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-  const upb_fielddef* field = upb_msgdef_ntofz(msg->descriptor->msgdef, member);
-
-  zval* cached_zval =
-      CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, field));
-
-  if (Z_TYPE_P(value) == IS_NULL) {
-    MessageHeader* msg = UNBOX(MessageHeader, getThis());
-    layout_set(msg->descriptor->layout, msg,
-               field, value TSRMLS_CC);
-    return;
-  }
-
   {
-    // Type Checking
-    const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
-    const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
-    upb_fieldtype_t type = upb_fielddef_type(value_field);
-    switch(type) {
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES: {
-        if (!protobuf_convert_to_string(value)) {
-          return;
-        }
-        if (type == UPB_TYPE_STRING &&
-            !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
-          zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
-          return;
-        }
-      }
-      break;
-#define CASE_TYPE(upb_type, type, c_type)                    \
-  case UPB_TYPE_##upb_type: {                                \
-    c_type type##_value;                                     \
-    if (!protobuf_convert_to_##type(value, &type##_value)) { \
-      return;                                                \
-    }                                                        \
-    break;                                                   \
-  }
-      CASE_TYPE(INT32,  int32,  int32_t)
-      CASE_TYPE(UINT32, uint32, uint32_t)
-      CASE_TYPE(ENUM,   int32,  int32_t)
-      CASE_TYPE(INT64,  int64,  int64_t)
-      CASE_TYPE(UINT64, uint64, uint64_t)
-      CASE_TYPE(FLOAT,  float,  float)
-      CASE_TYPE(DOUBLE, double, double)
-      CASE_TYPE(BOOL,   bool,   int8_t)
-
-#undef CASE_TYPE
-      case UPB_TYPE_MESSAGE:
-        zend_error(E_ERROR, "No wrapper for message.");
-        break;
-    }
+    upb_msgval msgval = upb_msg_get(intern->msg, f);
+    Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(f), &intern->arena);
   }
 
-  if (upb_fielddef_containingoneof(field)) {
-    uint32_t* oneof_case =
-        slot_oneof_case(msg->descriptor->layout, message_data(msg), field);
-    if (*oneof_case != upb_fielddef_number(field)) {
-      zval null_value;
-      ZVAL_NULL(&null_value);
-      layout_set(msg->descriptor->layout, msg, field, &null_value TSRMLS_CC);
-      cached_zval = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, field));
-      ZVAL_ZVAL(cached_zval, value, 1, 0);
-      return;
-    }
-  }
-
-  if (Z_TYPE_P(cached_zval) == IS_OBJECT) {
-    const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
-    const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
-    MessageHeader* submsg = UNBOX(MessageHeader, cached_zval);
-    layout_set(submsg->descriptor->layout, submsg,
-               value_field, value TSRMLS_CC);
-  } else {
-    ZVAL_ZVAL(cached_zval, value, 1, 0);
-  }
+  RETURN_COPY_VALUE(&ret);
 }
 
-PHP_METHOD(Message, readOneof) {
-  PHP_PROTO_LONG index;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
-      FAILURE) {
-    return;
-  }
-
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
-  const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
-
-  // Unlike singular fields, oneof fields share cached property. So we cannot
-  // let layout_get modify the cached property. Instead, we pass in the return
-  // value directly.
-  layout_get(msg->descriptor->layout, msg, field,
-             ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
+/**
+ * Message::writeOneof()
+ *
+ * Sets the contents of the given oneof field, given a field number. Called
+ * from generated code methods such as:
+ *
+ *    public function setDoubleValueOneof($var)
+ *   {
+ *       GPBUtil::checkMessage($var, \Google\Protobuf\DoubleValue::class);
+ *       $this->writeOneof(10, $var);
+ *
+ *       return $this;
+ *   }
+ *
+ * The C extension version of GPBUtil::check*() does nothing, so we perform
+ * all type checking and conversion here.
+ *
+ * @param integer The field number we are setting.
+ * @param object The field value we want to set.
+ */
 PHP_METHOD(Message, writeOneof) {
-  PHP_PROTO_LONG index;
-  zval* value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &index, &value) ==
-      FAILURE) {
-    return;
-  }
-
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
-  const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
-
-  layout_set(msg->descriptor->layout, msg, field, value TSRMLS_CC);
-}
-
-PHP_METHOD(Message, whichOneof) {
-  char* oneof_name;
-  PHP_PROTO_SIZE length;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &oneof_name,
-                            &length) == FAILURE) {
-    return;
-  }
-
-  MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
-  const upb_oneofdef* oneof =
-      upb_msgdef_ntoo(msg->descriptor->msgdef, oneof_name, length);
-  const char* oneof_case_name = layout_get_oneof_case(
-      msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC);
-  PHP_PROTO_RETURN_STRING(oneof_case_name, 1);
-}
-
-// -----------------------------------------------------------------------------
-// Well Known Types Support
-// -----------------------------------------------------------------------------
-
-#define PHP_PROTO_FIELD_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD,       \
-                                  LOWER_FIELD)                                 \
-  PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) {                                  \
-    zval member;                                                               \
-    PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1);                            \
-    PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type);                            \
-    zval* value = message_get_property_internal(getThis(), &member TSRMLS_CC); \
-    PHP_PROTO_FAKE_SCOPE_END;                                                  \
-    zval_dtor(&member);                                                        \
-    PHP_PROTO_RETVAL_ZVAL(value);                                              \
-  }                                                                            \
-  PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) {                                  \
-    zval* value = NULL;                                                        \
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) ==       \
-        FAILURE) {                                                             \
-      return;                                                                  \
-    }                                                                          \
-    zval member;                                                               \
-    PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1);                            \
-    message_set_property_internal(getThis(), &member, value TSRMLS_CC);        \
-    zval_dtor(&member);                                                        \
-    PHP_PROTO_RETVAL_ZVAL(getThis());                                          \
-  }
-
-#define PHP_PROTO_ONEOF_FIELD_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \
-                                        LOWER_FIELD)                           \
-  PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) {                                  \
-    zval member;                                                               \
-    PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1);                            \
-    PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type);                            \
-    message_get_oneof_property_internal(getThis(), &member,                    \
-                                        return_value TSRMLS_CC);               \
-    PHP_PROTO_FAKE_SCOPE_END;                                                  \
-    zval_dtor(&member);                                                        \
-  }                                                                            \
-  PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) {                                  \
-    zval* value = NULL;                                                        \
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) ==       \
-        FAILURE) {                                                             \
-      return;                                                                  \
-    }                                                                          \
-    zval member;                                                               \
-    PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1);                            \
-    message_set_property_internal(getThis(), &member, value TSRMLS_CC);        \
-    zval_dtor(&member);                                                        \
-    PHP_PROTO_RETVAL_ZVAL(getThis());                                          \
-  }
-
-#define PHP_PROTO_ONEOF_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \
-                                  LOWER_FIELD)                           \
-  PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) {                            \
-    MessageHeader* msg = UNBOX(MessageHeader, getThis());                \
-    PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type);                      \
-    const upb_oneofdef* oneof = upb_msgdef_ntoo(                         \
-        msg->descriptor->msgdef, LOWER_FIELD, strlen(LOWER_FIELD));      \
-    const char* oneof_case_name = layout_get_oneof_case(                 \
-        msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC);    \
-    PHP_PROTO_FAKE_SCOPE_END;                                            \
-    PHP_PROTO_RETURN_STRING(oneof_case_name, 1);                         \
-  }
-
-// Forward declare file init functions
-static void init_file_any(TSRMLS_D);
-static void init_file_api(TSRMLS_D);
-static void init_file_duration(TSRMLS_D);
-static void init_file_field_mask(TSRMLS_D);
-static void init_file_empty(TSRMLS_D);
-static void init_file_source_context(TSRMLS_D);
-static void init_file_struct(TSRMLS_D);
-static void init_file_timestamp(TSRMLS_D);
-static void init_file_type(TSRMLS_D);
-static void init_file_wrappers(TSRMLS_D);
-
-// Define file init functions
-static void init_file_any(TSRMLS_D) {
-  if (is_inited_file_any) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f"
-      "120f676f6f676c652e70726f746f62756622260a03416e7912100a087479"
-      "70655f75726c180120012809120d0a0576616c756518022001280c426f0a"
-      "13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f"
-      "50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566"
-      "2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f"
-      "746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_any = true;
-}
-
-static void init_file_api(TSRMLS_D) {
-  if (is_inited_file_api) return;
-  init_file_source_context(TSRMLS_C);
-  init_file_type(TSRMLS_C);
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0aee050a19676f6f676c652f70726f746f6275662f6170692e70726f746f"
-      "120f676f6f676c652e70726f746f6275661a24676f6f676c652f70726f74"
-      "6f6275662f736f757263655f636f6e746578742e70726f746f1a1a676f6f"
-      "676c652f70726f746f6275662f747970652e70726f746f2281020a034170"
-      "69120c0a046e616d6518012001280912280a076d6574686f647318022003"
-      "280b32172e676f6f676c652e70726f746f6275662e4d6574686f6412280a"
-      "076f7074696f6e7318032003280b32172e676f6f676c652e70726f746f62"
-      "75662e4f7074696f6e120f0a0776657273696f6e18042001280912360a0e"
-      "736f757263655f636f6e7465787418052001280b321e2e676f6f676c652e"
-      "70726f746f6275662e536f75726365436f6e7465787412260a066d697869"
-      "6e7318062003280b32162e676f6f676c652e70726f746f6275662e4d6978"
-      "696e12270a0673796e74617818072001280e32172e676f6f676c652e7072"
-      "6f746f6275662e53796e74617822d5010a064d6574686f64120c0a046e61"
-      "6d6518012001280912180a10726571756573745f747970655f75726c1802"
-      "2001280912190a11726571756573745f73747265616d696e671803200128"
-      "0812190a11726573706f6e73655f747970655f75726c180420012809121a"
-      "0a12726573706f6e73655f73747265616d696e6718052001280812280a07"
-      "6f7074696f6e7318062003280b32172e676f6f676c652e70726f746f6275"
-      "662e4f7074696f6e12270a0673796e74617818072001280e32172e676f6f"
-      "676c652e70726f746f6275662e53796e74617822230a054d6978696e120c"
-      "0a046e616d65180120012809120c0a04726f6f7418022001280942750a13"
-      "636f6d2e676f6f676c652e70726f746f627566420841706950726f746f50"
-      "015a2b676f6f676c652e676f6c616e672e6f72672f67656e70726f746f2f"
-      "70726f746f6275662f6170693b617069a20203475042aa021e476f6f676c"
-      "652e50726f746f6275662e57656c6c4b6e6f776e5479706573620670726f"
-      "746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_api = true;
-}
-
-static void init_file_duration(TSRMLS_D) {
-  if (is_inited_file_duration) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e"
-      "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261"
-      "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73"
-      "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642"
-      "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67"
-      "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e"
-      "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765"
-      "6c6c4b6e6f776e5479706573620670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_duration = true;
-}
-
-static void init_file_field_mask(TSRMLS_D) {
-  if (is_inited_file_field_mask) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0ae3010a20676f6f676c652f70726f746f6275662f6669656c645f6d6173"
-      "6b2e70726f746f120f676f6f676c652e70726f746f627566221a0a094669"
-      "656c644d61736b120d0a0570617468731801200328094289010a13636f6d"
-      "2e676f6f676c652e70726f746f627566420e4669656c644d61736b50726f"
-      "746f50015a39676f6f676c652e676f6c616e672e6f72672f67656e70726f"
-      "746f2f70726f746f6275662f6669656c645f6d61736b3b6669656c645f6d"
-      "61736ba20203475042aa021e476f6f676c652e50726f746f6275662e5765"
-      "6c6c4b6e6f776e5479706573620670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_field_mask = true;
-}
-
-static void init_file_empty(TSRMLS_D) {
-  if (is_inited_file_empty) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0ab7010a1b676f6f676c652f70726f746f6275662f656d7074792e70726f"
-      "746f120f676f6f676c652e70726f746f62756622070a05456d7074794276"
-      "0a13636f6d2e676f6f676c652e70726f746f627566420a456d7074795072"
-      "6f746f50015a276769746875622e636f6d2f676f6c616e672f70726f746f"
-      "6275662f7074797065732f656d707479f80101a20203475042aa021e476f"
-      "6f676c652e50726f746f6275662e57656c6c4b6e6f776e54797065736206"
-      "70726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_empty = true;
-}
-
-static void init_file_source_context(TSRMLS_D) {
-  if (is_inited_file_source_context) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0afb010a24676f6f676c652f70726f746f6275662f736f757263655f636f"
-      "6e746578742e70726f746f120f676f6f676c652e70726f746f6275662222"
-      "0a0d536f75726365436f6e7465787412110a0966696c655f6e616d651801"
-      "200128094295010a13636f6d2e676f6f676c652e70726f746f6275664212"
-      "536f75726365436f6e7465787450726f746f50015a41676f6f676c652e67"
-      "6f6c616e672e6f72672f67656e70726f746f2f70726f746f6275662f736f"
-      "757263655f636f6e746578743b736f757263655f636f6e74657874a20203"
-      "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77"
-      "6e5479706573620670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_source_context = true;
-}
-
-static void init_file_struct(TSRMLS_D) {
-  if (is_inited_file_struct) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0a81050a1c676f6f676c652f70726f746f6275662f7374727563742e7072"
-      "6f746f120f676f6f676c652e70726f746f6275662284010a065374727563"
-      "7412330a066669656c647318012003280b32232e676f6f676c652e70726f"
-      "746f6275662e5374727563742e4669656c6473456e7472791a450a0b4669"
-      "656c6473456e747279120b0a036b657918012001280912250a0576616c75"
-      "6518022001280b32162e676f6f676c652e70726f746f6275662e56616c75"
-      "653a02380122ea010a0556616c756512300a0a6e756c6c5f76616c756518"
-      "012001280e321a2e676f6f676c652e70726f746f6275662e4e756c6c5661"
-      "6c7565480012160a0c6e756d6265725f76616c7565180220012801480012"
-      "160a0c737472696e675f76616c7565180320012809480012140a0a626f6f"
-      "6c5f76616c75651804200128084800122f0a0c7374727563745f76616c75"
-      "6518052001280b32172e676f6f676c652e70726f746f6275662e53747275"
-      "6374480012300a0a6c6973745f76616c756518062001280b321a2e676f6f"
-      "676c652e70726f746f6275662e4c69737456616c7565480042060a046b69"
-      "6e6422330a094c69737456616c756512260a0676616c7565731801200328"
-      "0b32162e676f6f676c652e70726f746f6275662e56616c75652a1b0a094e"
-      "756c6c56616c7565120e0a0a4e554c4c5f56414c554510004281010a1363"
-      "6f6d2e676f6f676c652e70726f746f627566420b53747275637450726f74"
-      "6f50015a316769746875622e636f6d2f676f6c616e672f70726f746f6275"
-      "662f7074797065732f7374727563743b7374727563747062f80101a20203"
-      "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77"
-      "6e5479706573620670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_struct = true;
-}
-
-static void init_file_timestamp(TSRMLS_D) {
-  if (is_inited_file_timestamp) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0ae7010a1f676f6f676c652f70726f746f6275662f74696d657374616d70"
-      "2e70726f746f120f676f6f676c652e70726f746f627566222b0a0954696d"
-      "657374616d70120f0a077365636f6e6473180120012803120d0a056e616e"
-      "6f73180220012805427e0a13636f6d2e676f6f676c652e70726f746f6275"
-      "66420e54696d657374616d7050726f746f50015a2b6769746875622e636f"
-      "6d2f676f6c616e672f70726f746f6275662f7074797065732f74696d6573"
-      "74616d70f80101a20203475042aa021e476f6f676c652e50726f746f6275"
-      "662e57656c6c4b6e6f776e5479706573620670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_timestamp = true;
-}
-
-static void init_file_type(TSRMLS_D) {
-  if (is_inited_file_type) return;
-  init_file_any(TSRMLS_C);
-  init_file_source_context(TSRMLS_C);
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0aba0c0a1a676f6f676c652f70726f746f6275662f747970652e70726f74"
-      "6f120f676f6f676c652e70726f746f6275661a19676f6f676c652f70726f"
-      "746f6275662f616e792e70726f746f1a24676f6f676c652f70726f746f62"
-      "75662f736f757263655f636f6e746578742e70726f746f22d7010a045479"
-      "7065120c0a046e616d6518012001280912260a066669656c647318022003"
-      "280b32162e676f6f676c652e70726f746f6275662e4669656c64120e0a06"
-      "6f6e656f667318032003280912280a076f7074696f6e7318042003280b32"
-      "172e676f6f676c652e70726f746f6275662e4f7074696f6e12360a0e736f"
-      "757263655f636f6e7465787418052001280b321e2e676f6f676c652e7072"
-      "6f746f6275662e536f75726365436f6e7465787412270a0673796e746178"
-      "18062001280e32172e676f6f676c652e70726f746f6275662e53796e7461"
-      "7822d5050a054669656c6412290a046b696e6418012001280e321b2e676f"
-      "6f676c652e70726f746f6275662e4669656c642e4b696e6412370a0b6361"
-      "7264696e616c69747918022001280e32222e676f6f676c652e70726f746f"
-      "6275662e4669656c642e43617264696e616c697479120e0a066e756d6265"
-      "72180320012805120c0a046e616d6518042001280912100a08747970655f"
-      "75726c18062001280912130a0b6f6e656f665f696e646578180720012805"
-      "120e0a067061636b656418082001280812280a076f7074696f6e73180920"
-      "03280b32172e676f6f676c652e70726f746f6275662e4f7074696f6e1211"
-      "0a096a736f6e5f6e616d65180a2001280912150a0d64656661756c745f76"
-      "616c7565180b2001280922c8020a044b696e6412100a0c545950455f554e"
-      "4b4e4f574e1000120f0a0b545950455f444f55424c451001120e0a0a5459"
-      "50455f464c4f41541002120e0a0a545950455f494e5436341003120f0a0b"
-      "545950455f55494e5436341004120e0a0a545950455f494e543332100512"
-      "100a0c545950455f46495845443634100612100a0c545950455f46495845"
-      "4433321007120d0a09545950455f424f4f4c1008120f0a0b545950455f53"
-      "5452494e471009120e0a0a545950455f47524f5550100a12100a0c545950"
-      "455f4d455353414745100b120e0a0a545950455f4259544553100c120f0a"
-      "0b545950455f55494e543332100d120d0a09545950455f454e554d100e12"
-      "110a0d545950455f5346495845443332100f12110a0d545950455f534649"
-      "58454436341010120f0a0b545950455f53494e5433321011120f0a0b5459"
-      "50455f53494e543634101222740a0b43617264696e616c69747912170a13"
-      "43415244494e414c4954595f554e4b4e4f574e100012180a144341524449"
-      "4e414c4954595f4f5054494f4e414c100112180a1443415244494e414c49"
-      "54595f5245515549524544100212180a1443415244494e414c4954595f52"
-      "45504541544544100322ce010a04456e756d120c0a046e616d6518012001"
-      "2809122d0a09656e756d76616c756518022003280b321a2e676f6f676c65"
-      "2e70726f746f6275662e456e756d56616c756512280a076f7074696f6e73"
-      "18032003280b32172e676f6f676c652e70726f746f6275662e4f7074696f"
-      "6e12360a0e736f757263655f636f6e7465787418042001280b321e2e676f"
-      "6f676c652e70726f746f6275662e536f75726365436f6e7465787412270a"
-      "0673796e74617818052001280e32172e676f6f676c652e70726f746f6275"
-      "662e53796e74617822530a09456e756d56616c7565120c0a046e616d6518"
-      "0120012809120e0a066e756d62657218022001280512280a076f7074696f"
-      "6e7318032003280b32172e676f6f676c652e70726f746f6275662e4f7074"
-      "696f6e223b0a064f7074696f6e120c0a046e616d6518012001280912230a"
-      "0576616c756518022001280b32142e676f6f676c652e70726f746f627566"
-      "2e416e792a2e0a0653796e74617812110a0d53594e5441585f50524f544f"
-      "32100012110a0d53594e5441585f50524f544f331001427d0a13636f6d2e"
-      "676f6f676c652e70726f746f62756642095479706550726f746f50015a2f"
-      "676f6f676c652e676f6c616e672e6f72672f67656e70726f746f2f70726f"
-      "746f6275662f70747970653b7074797065f80101a20203475042aa021e47"
-      "6f6f676c652e50726f746f6275662e57656c6c4b6e6f776e547970657362"
-      "0670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_type = true;
-}
-
-static void init_file_wrappers(TSRMLS_D) {
-  if (is_inited_file_wrappers) return;
-  init_generated_pool_once(TSRMLS_C);
-  const char* generated_file =
-      "0abf030a1e676f6f676c652f70726f746f6275662f77726170706572732e"
-      "70726f746f120f676f6f676c652e70726f746f627566221c0a0b446f7562"
-      "6c6556616c7565120d0a0576616c7565180120012801221b0a0a466c6f61"
-      "7456616c7565120d0a0576616c7565180120012802221b0a0a496e743634"
-      "56616c7565120d0a0576616c7565180120012803221c0a0b55496e743634"
-      "56616c7565120d0a0576616c7565180120012804221b0a0a496e74333256"
-      "616c7565120d0a0576616c7565180120012805221c0a0b55496e74333256"
-      "616c7565120d0a0576616c756518012001280d221a0a09426f6f6c56616c"
-      "7565120d0a0576616c7565180120012808221c0a0b537472696e6756616c"
-      "7565120d0a0576616c7565180120012809221b0a0a427974657356616c75"
-      "65120d0a0576616c756518012001280c427c0a13636f6d2e676f6f676c65"
-      "2e70726f746f627566420d577261707065727350726f746f50015a2a6769"
-      "746875622e636f6d2f676f6c616e672f70726f746f6275662f7074797065"
-      "732f7772617070657273f80101a20203475042aa021e476f6f676c652e50"
-      "726f746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33";
-  char* binary;
-  int binary_len;
-  hex_to_binary(generated_file, &binary, &binary_len);
-  internal_add_generated_file(binary, binary_len,
-                              generated_pool, true TSRMLS_CC);
-  FREE(binary);
-  is_inited_file_wrappers = true;
-}
-
-// -----------------------------------------------------------------------------
-// Define enum
-// -----------------------------------------------------------------------------
-
-// -----------------------------------------------------------------------------
-// Field_Cardinality
-// -----------------------------------------------------------------------------
-
-static zend_function_entry field_cardinality_methods[] = {
-  PHP_ME(Field_Cardinality, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Field_Cardinality, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* field_cardinality_type;
-
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Cardinality",
-                                Field_Cardinality, field_cardinality)
-  zend_declare_class_constant_long(field_cardinality_type,
-                                   "CARDINALITY_UNKNOWN", 19, 0 TSRMLS_CC);
-  zend_declare_class_constant_long(field_cardinality_type,
-                                   "CARDINALITY_OPTIONAL", 20, 1 TSRMLS_CC);
-  zend_declare_class_constant_long(field_cardinality_type,
-                                   "CARDINALITY_REQUIRED", 20, 2 TSRMLS_CC);
-  zend_declare_class_constant_long(field_cardinality_type,
-                                   "CARDINALITY_REPEATED", 20, 3 TSRMLS_CC);
-  const char *alias = "Google\\Protobuf\\Field_Cardinality";
-#if PHP_VERSION_ID < 70300
-  zend_register_class_alias_ex(alias, strlen(alias), field_cardinality_type TSRMLS_CC);
-#else
-  zend_register_class_alias_ex(alias, strlen(alias), field_cardinality_type, 1);
-#endif
-PHP_PROTO_INIT_ENUMCLASS_END
-
-PHP_METHOD(Field_Cardinality, name) {
-  PHP_PROTO_LONG value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
-      FAILURE) {
-    return;
-  }
-  switch (value) {
-    case 0:
-      PHP_PROTO_RETURN_STRING("CARDINALITY_UNKNOWN", 1);
-    case 1:
-      PHP_PROTO_RETURN_STRING("CARDINALITY_OPTIONAL", 1);
-    case 2:
-      PHP_PROTO_RETURN_STRING("CARDINALITY_REQUIRED", 1);
-    case 3:
-      PHP_PROTO_RETURN_STRING("CARDINALITY_REPEATED", 1);
-    default:
-      zend_throw_exception_ex(
-          NULL, 0 TSRMLS_CC,
-          "Enum Google\\Protobuf\\Field_Cardinality has no name "
-#if PHP_MAJOR_VERSION < 7
-          "defined for value %d.",
-#else
-          "defined for value " ZEND_LONG_FMT ".",
-#endif
-          value);
-  }
-}
-
-PHP_METHOD(Field_Cardinality, value) {
-  char *name = NULL;
-  PHP_PROTO_SIZE name_len;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
-      FAILURE) {
-    return;
-  }
-
-  if (strncmp(name, "CARDINALITY_UNKNOWN", name_len) == 0) RETURN_LONG(0);
-  if (strncmp(name, "CARDINALITY_OPTIONAL", name_len) == 0) RETURN_LONG(1);
-  if (strncmp(name, "CARDINALITY_REQUIRED", name_len) == 0) RETURN_LONG(2);
-  if (strncmp(name, "CARDINALITY_REPEATED", name_len) == 0) RETURN_LONG(3);
-
-  zend_throw_exception_ex(
-      NULL, 0 TSRMLS_CC,
-      "Enum Google\\Protobuf\\Field_Cardinality has no value "
-      "defined for name %s.",
-      name);
-}
-
-// -----------------------------------------------------------------------------
-// Field_Kind
-// -----------------------------------------------------------------------------
-
-static zend_function_entry field_kind_methods[] = {
-  PHP_ME(Field_Kind, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Field_Kind, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* field_kind_type;
-
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Kind",
-                                Field_Kind, field_kind)
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_UNKNOWN", 12, 0 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_DOUBLE", 11, 1 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_FLOAT", 10, 2 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_INT64", 10, 3 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_UINT64", 11, 4 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_INT32", 10, 5 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_FIXED64", 12, 6 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_FIXED32", 12, 7 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_BOOL", 9, 8 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_STRING", 11, 9 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_GROUP", 10, 10 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_MESSAGE", 12, 11 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_BYTES", 10, 12 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_UINT32", 11, 13 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_ENUM", 9, 14 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_SFIXED32", 13, 15 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_SFIXED64", 13, 16 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_SINT32", 11, 17 TSRMLS_CC);
-  zend_declare_class_constant_long(field_kind_type,
-                                   "TYPE_SINT64", 11, 18 TSRMLS_CC);
-  const char *alias = "Google\\Protobuf\\Field_Kind";
-#if PHP_VERSION_ID < 70300
-  zend_register_class_alias_ex(alias, strlen(alias), field_kind_type TSRMLS_CC);
-#else
-  zend_register_class_alias_ex(alias, strlen(alias), field_kind_type, 1);
-#endif
-PHP_PROTO_INIT_ENUMCLASS_END
-
-PHP_METHOD(Field_Kind, name) {
-  PHP_PROTO_LONG value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
-      FAILURE) {
-    return;
-  }
-  switch (value) {
-    case 0:
-      PHP_PROTO_RETURN_STRING("TYPE_UNKNOWN", 1);
-    case 1:
-      PHP_PROTO_RETURN_STRING("TYPE_DOUBLE", 1);
-    case 2:
-      PHP_PROTO_RETURN_STRING("TYPE_FLOAT", 1);
-    case 3:
-      PHP_PROTO_RETURN_STRING("TYPE_INT64", 1);
-    case 4:
-      PHP_PROTO_RETURN_STRING("TYPE_UINT64", 1);
-    case 5:
-      PHP_PROTO_RETURN_STRING("TYPE_INT32", 1);
-    case 6:
-      PHP_PROTO_RETURN_STRING("TYPE_FIXED64", 1);
-    case 7:
-      PHP_PROTO_RETURN_STRING("TYPE_FIXED32", 1);
-    case 8:
-      PHP_PROTO_RETURN_STRING("TYPE_BOOL", 1);
-    case 9:
-      PHP_PROTO_RETURN_STRING("TYPE_STRING", 1);
-    case 10:
-      PHP_PROTO_RETURN_STRING("TYPE_GROUP", 1);
-    case 11:
-      PHP_PROTO_RETURN_STRING("TYPE_MESSAGE", 1);
-    case 12:
-      PHP_PROTO_RETURN_STRING("TYPE_BYTES", 1);
-    case 13:
-      PHP_PROTO_RETURN_STRING("TYPE_UINT32", 1);
-    case 14:
-      PHP_PROTO_RETURN_STRING("TYPE_ENUM", 1);
-    case 15:
-      PHP_PROTO_RETURN_STRING("TYPE_SFIXED32", 1);
-    case 16:
-      PHP_PROTO_RETURN_STRING("TYPE_SFIXED64", 1);
-    case 17:
-      PHP_PROTO_RETURN_STRING("TYPE_SINT32", 1);
-    case 18:
-      PHP_PROTO_RETURN_STRING("TYPE_SINT64", 1);
-    default:
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Enum Google\\Protobuf\\Field_Kind has no name "
-#if PHP_MAJOR_VERSION < 7
-                              "defined for value %d.",
-#else
-                              "defined for value " ZEND_LONG_FMT ".",
-#endif
-                              value);
-  }
-}
-
-PHP_METHOD(Field_Kind, value) {
-  char *name = NULL;
-  PHP_PROTO_SIZE name_len;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
-      FAILURE) {
-    return;
-  }
-
-  if (strncmp(name, "TYPE_UNKNOWN", name_len) == 0) RETURN_LONG(0);
-  if (strncmp(name, "TYPE_DOUBLE", name_len) == 0) RETURN_LONG(1);
-  if (strncmp(name, "TYPE_FLOAT", name_len) == 0) RETURN_LONG(2);
-  if (strncmp(name, "TYPE_INT64", name_len) == 0) RETURN_LONG(3);
-  if (strncmp(name, "TYPE_UINT64", name_len) == 0) RETURN_LONG(4);
-  if (strncmp(name, "TYPE_INT32", name_len) == 0) RETURN_LONG(5);
-  if (strncmp(name, "TYPE_FIXED64", name_len) == 0) RETURN_LONG(6);
-  if (strncmp(name, "TYPE_FIXED32", name_len) == 0) RETURN_LONG(7);
-  if (strncmp(name, "TYPE_BOOL", name_len) == 0) RETURN_LONG(8);
-  if (strncmp(name, "TYPE_STRING", name_len) == 0) RETURN_LONG(9);
-  if (strncmp(name, "TYPE_GROUP", name_len) == 0) RETURN_LONG(10);
-  if (strncmp(name, "TYPE_MESSAGE", name_len) == 0) RETURN_LONG(11);
-  if (strncmp(name, "TYPE_BYTES", name_len) == 0) RETURN_LONG(12);
-  if (strncmp(name, "TYPE_UINT32", name_len) == 0) RETURN_LONG(13);
-  if (strncmp(name, "TYPE_ENUM", name_len) == 0) RETURN_LONG(14);
-  if (strncmp(name, "TYPE_SFIXED32", name_len) == 0) RETURN_LONG(15);
-  if (strncmp(name, "TYPE_SFIXED64", name_len) == 0) RETURN_LONG(16);
-  if (strncmp(name, "TYPE_SINT32", name_len) == 0) RETURN_LONG(17);
-  if (strncmp(name, "TYPE_SINT64", name_len) == 0) RETURN_LONG(18);
-
-  zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                          "Enum Google\\Protobuf\\Field_Kind has no value "
-                          "defined for name %s.",
-                          name);
-}
-
-// -----------------------------------------------------------------------------
-// NullValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry null_value_methods[] = {
-  PHP_ME(NullValue, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(NullValue, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* null_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\NullValue",
-                                NullValue, null_value)
-  zend_declare_class_constant_long(null_value_type,
-                                   "NULL_VALUE", 10, 0 TSRMLS_CC);
-PHP_PROTO_INIT_ENUMCLASS_END
-
-PHP_METHOD(NullValue, name) {
-  PHP_PROTO_LONG value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
-      FAILURE) {
-    return;
-  }
-  switch (value) {
-    case 0:
-      PHP_PROTO_RETURN_STRING("NULL_VALUE", 1);
-    default:
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Enum Google\\Protobuf\\NullValue has no name "
-#if PHP_MAJOR_VERSION < 7
-                              "defined for value %d.",
-#else
-                              "defined for value " ZEND_LONG_FMT ".",
-#endif
-                              value);
-  }
-}
-
-PHP_METHOD(NullValue, value) {
-  char *name = NULL;
-  PHP_PROTO_SIZE name_len;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
-      FAILURE) {
-    return;
-  }
-
-  if (strncmp(name, "NULL_VALUE", name_len) == 0) RETURN_LONG(0);
-
-  zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                          "Enum Google\\Protobuf\\NullValue has no value "
-                          "defined for name %s.",
-                          name);
-}
-
-// -----------------------------------------------------------------------------
-// Syntax
-// -----------------------------------------------------------------------------
-
-static zend_function_entry syntax_methods[] = {
-  PHP_ME(Syntax, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Syntax, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* syntax_type;
-
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Syntax",
-                                Syntax, syntax)
-  zend_declare_class_constant_long(syntax_type,
-                                   "SYNTAX_PROTO2", 13, 0 TSRMLS_CC);
-  zend_declare_class_constant_long(syntax_type,
-                                   "SYNTAX_PROTO3", 13, 1 TSRMLS_CC);
-PHP_PROTO_INIT_ENUMCLASS_END
-
-PHP_METHOD(Syntax, name) {
-  PHP_PROTO_LONG value;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
-      FAILURE) {
-    return;
-  }
-  switch (value) {
-    case 0:
-      PHP_PROTO_RETURN_STRING("SYNTAX_PROTO2", 1);
-    case 1:
-      PHP_PROTO_RETURN_STRING("SYNTAX_PROTO3", 1);
-    default:
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Enum Google\\Protobuf\\Syntax has no name "
-#if PHP_MAJOR_VERSION < 7
-                              "defined for value %d.",
-#else
-                              "defined for value " ZEND_LONG_FMT ".",
-#endif
-                              value);
-  }
-}
-
-PHP_METHOD(Syntax, value) {
-  char *name = NULL;
-  PHP_PROTO_SIZE name_len;
-
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
-      FAILURE) {
-    return;
-  }
-
-  if (strncmp(name, "SYNTAX_PROTO2", name_len) == 0) RETURN_LONG(0);
-  if (strncmp(name, "SYNTAX_PROTO3", name_len) == 0) RETURN_LONG(1);
-
-  zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                          "Enum Google\\Protobuf\\Syntax has no value "
-                          "defined for name %s.",
-                          name);
-}
-
-// -----------------------------------------------------------------------------
-// Define message
-// -----------------------------------------------------------------------------
-
-// -----------------------------------------------------------------------------
-// Any
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry any_methods[] = {
-  PHP_ME(Any, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Any, getTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Any, setTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Any, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Any, setValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Any, pack,     NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Any, unpack,   NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Any, is,       NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* any_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Any", Any, any)
-  zend_declare_property_string(any_type, "type_url", strlen("type_url"),
-                               "" ,ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(any_type, "value", strlen("value"),
-                               "" ,ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-static void hex_to_binary(const char* hex, char** binary, int* binary_len) {
-  int i;
-  int hex_len = strlen(hex);
-  *binary_len = hex_len / 2;
-  *binary = ALLOC_N(char, *binary_len);
-  for (i = 0; i < *binary_len; i++) {
-    char value = 0;
-    if (hex[i * 2] >= '0' && hex[i * 2] <= '9') {
-      value += (hex[i * 2] - '0') * 16;
-    } else {
-      value += (hex[i * 2] - 'a' + 10) * 16;
-    }
-    if (hex[i * 2 + 1] >= '0' && hex[i * 2 + 1] <= '9') {
-      value += hex[i * 2 + 1] - '0';
-    } else {
-      value += hex[i * 2 + 1] - 'a' + 10;
-    }
-    (*binary)[i] = value;
-  }
-}
-
-PHP_METHOD(Any, __construct) {
-  init_file_any(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Any, any, TypeUrl, "type_url")
-PHP_PROTO_FIELD_ACCESSORS(Any, any, Value,   "value")
-
-PHP_METHOD(Any, unpack) {
-  // Get type url.
-  zval type_url_member;
-  PHP_PROTO_ZVAL_STRING(&type_url_member, "type_url", 1);
-  PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
-  zval* type_url_php = php_proto_message_read_property(
-      getThis(), &type_url_member PHP_PROTO_TSRMLS_CC);
-  zval_dtor(&type_url_member);
-  PHP_PROTO_FAKE_SCOPE_END;
-
-  // Get fully-qualified name from type url.
-  size_t url_prefix_len = strlen(TYPE_URL_PREFIX);
-  const char* type_url = Z_STRVAL_P(type_url_php);
-  size_t type_url_len = Z_STRLEN_P(type_url_php);
-
-  if (url_prefix_len > type_url_len ||
-      strncmp(TYPE_URL_PREFIX, type_url, url_prefix_len) != 0) {
-    zend_throw_exception(
-        NULL, "Type url needs to be type.googleapis.com/fully-qualified",
-        0 TSRMLS_CC);
-    return;
-  }
-
-  const char* fully_qualified_name = type_url + url_prefix_len;
-  DescriptorInternal* desc = get_proto_desc(fully_qualified_name);
-  if (desc == NULL) {
-    zend_throw_exception(
-        NULL, "Specified message in any hasn't been added to descriptor pool",
-        0 TSRMLS_CC);
-    return;
-  }
-  register_class(desc, false TSRMLS_CC);
-  zend_class_entry* klass = desc->klass;
-  ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC));
-  MessageHeader* msg = UNBOX(MessageHeader, return_value);
-  custom_data_init(klass, msg PHP_PROTO_TSRMLS_CC);
-
-  // Get value.
-  zval value_member;
-  PHP_PROTO_ZVAL_STRING(&value_member, "value", 1);
-  PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
-  zval* value = php_proto_message_read_property(
-      getThis(), &value_member PHP_PROTO_TSRMLS_CC);
-  zval_dtor(&value_member);
-  PHP_PROTO_FAKE_SCOPE_END;
-
-  merge_from_string(Z_STRVAL_P(value), Z_STRLEN_P(value), desc, msg);
-}
-
-PHP_METHOD(Any, pack) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  zend_long field_num;
+  const upb_fielddef* f;
+  upb_arena *arena = Arena_Get(&intern->arena);
+  upb_msgval msgval;
   zval* val;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &val) ==
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz", &field_num, &val) ==
       FAILURE) {
     return;
   }
 
-  if (!instanceof_function(Z_OBJCE_P(val), message_type TSRMLS_CC)) {
+  f = upb_msgdef_itof(intern->desc->msgdef, field_num);
+
+  if (upb_fielddef_issubmsg(f) && Z_TYPE_P(val) == IS_NULL) {
+    upb_msg_clearfield(intern->msg, f);
+    return;
+  } else if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) {
+    return;
+  }
+
+  upb_msg_set(intern->msg, f, msgval, arena);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 0)
+  ZEND_ARG_INFO(0, data)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mergeFrom, 0, 0, 1)
+  ZEND_ARG_INFO(0, data)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mergeFromWithArg, 0, 0, 1)
+  ZEND_ARG_INFO(0, data)
+  ZEND_ARG_INFO(0, arg)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_read, 0, 0, 1)
+  ZEND_ARG_INFO(0, field)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_write, 0, 0, 2)
+  ZEND_ARG_INFO(0, field)
+  ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry Message_methods[] = {
+  PHP_ME(Message, clear,                 arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, discardUnknownFields,  arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, serializeToString,     arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, mergeFromString,       arginfo_mergeFrom, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, serializeToJsonString, arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(Message, mergeFromJsonString,   arginfo_mergeFromWithArg, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, mergeFrom,             arginfo_mergeFrom, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, readWrapperValue,      arginfo_read,      ZEND_ACC_PROTECTED)
+  PHP_ME(Message, writeWrapperValue,     arginfo_write,     ZEND_ACC_PROTECTED)
+  PHP_ME(Message, hasOneof,              arginfo_read,      ZEND_ACC_PROTECTED)
+  PHP_ME(Message, readOneof,             arginfo_read,      ZEND_ACC_PROTECTED)
+  PHP_ME(Message, writeOneof,            arginfo_write,     ZEND_ACC_PROTECTED)
+  PHP_ME(Message, whichOneof,            arginfo_read,      ZEND_ACC_PROTECTED)
+  PHP_ME(Message, __construct,           arginfo_construct, ZEND_ACC_PROTECTED)
+  ZEND_FE_END
+};
+
+// Well-known types ////////////////////////////////////////////////////////////
+
+static const char TYPE_URL_PREFIX[] = "type.googleapis.com/";
+
+static upb_msgval Message_getval(Message *intern, const char *field_name) {
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name);
+  PBPHP_ASSERT(f);
+  return upb_msg_get(intern->msg, f);
+}
+
+static void Message_setval(Message *intern, const char *field_name,
+                           upb_msgval val) {
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name);
+  PBPHP_ASSERT(f);
+  return upb_msg_set(intern->msg, f, val, Arena_Get(&intern->arena));
+}
+
+static upb_msgval StringVal(upb_strview view) {
+  upb_msgval ret;
+  ret.str_val = view;
+  return ret;
+}
+
+static bool TryStripUrlPrefix(upb_strview *str) {
+  size_t size = strlen(TYPE_URL_PREFIX);
+  if (str->size < size || memcmp(TYPE_URL_PREFIX, str->data, size) != 0) {
+    return false;
+  }
+  str->data += size;
+  str->size -= size;
+  return true;
+}
+
+static bool StrViewEq(upb_strview view, const char *str) {
+  size_t size = strlen(str);
+  return view.size == size && memcmp(view.data, str, size) == 0;
+}
+
+PHP_METHOD(google_protobuf_Any, unpack) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  upb_strview type_url = Message_getval(intern, "type_url").str_val;
+  upb_strview value = Message_getval(intern, "value").str_val;
+  upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_msgdef *m;
+  Descriptor *desc;
+  zval ret;
+
+  // Ensure that type_url has TYPE_URL_PREFIX as a prefix.
+  if (!TryStripUrlPrefix(&type_url)) {
+    zend_throw_exception(
+        NULL, "Type url needs to be type.googleapis.com/fully-qualified",
+        0);
+    return;
+  }
+
+  m = upb_symtab_lookupmsg2(symtab, type_url.data, type_url.size);
+
+  if (m == NULL) {
+    zend_throw_exception(
+        NULL, "Specified message in any hasn't been added to descriptor pool",
+        0);
+    return;
+  }
+
+  desc = Descriptor_GetFromMessageDef(m);
+  PBPHP_ASSERT(desc->class_entry->create_object == Message_create);
+  zend_object *obj = Message_create(desc->class_entry);
+  Message *msg = (Message*)obj;
+  Message_Initialize(msg, desc);
+  ZVAL_OBJ(&ret, obj);
+
+  // Get value.
+  if (!upb_decode(value.data, value.size, msg->msg,
+                  upb_msgdef_layout(desc->msgdef), Arena_Get(&msg->arena))) {
+    zend_throw_exception_ex(NULL, 0, "Error occurred during parsing");
+    zval_dtor(&ret);
+    return;
+  }
+
+  // Fuse since the parsed message could alias "value".
+  upb_arena_fuse(Arena_Get(&intern->arena), Arena_Get(&msg->arena));
+
+  RETURN_COPY_VALUE(&ret);
+}
+
+PHP_METHOD(google_protobuf_Any, pack) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  upb_arena *arena = Arena_Get(&intern->arena);
+  zval *val;
+  Message *msg;
+  upb_strview value;
+  upb_strview type_url;
+  const char *full_name;
+  char *buf;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &val) ==
+      FAILURE) {
+    return;
+  }
+
+  if (!instanceof_function(Z_OBJCE_P(val), message_ce)) {
     zend_error(E_USER_ERROR, "Given value is not an instance of Message.");
     return;
   }
 
-  // Set value by serialized data.
-  zval data;
-  serialize_to_string(val, &data TSRMLS_CC);
+  msg = (Message*)Z_OBJ_P(val);
 
-  zval member;
-  PHP_PROTO_ZVAL_STRING(&member, "value", 1);
+  // Serialize and set value.
+  value.data = upb_encode(msg->msg, upb_msgdef_layout(msg->desc->msgdef), arena,
+                          &value.size);
+  Message_setval(intern, "value", StringVal(value));
 
-  PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
-  message_handlers->write_property(getThis(), &member, &data,
-                                   NULL PHP_PROTO_TSRMLS_CC);
-  zval_dtor(&data);
-  zval_dtor(&member);
-  PHP_PROTO_FAKE_SCOPE_END;
-
-  // Set type url.
-  DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val));
-  const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
-  size_t type_url_len =
-      strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
-  char* type_url = ALLOC_N(char, type_url_len);
-  sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
-  zval type_url_php;
-  PHP_PROTO_ZVAL_STRING(&type_url_php, type_url, 1);
-  PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
-
-  PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
-  message_handlers->write_property(getThis(), &member, &type_url_php,
-                                   NULL PHP_PROTO_TSRMLS_CC);
-  zval_dtor(&type_url_php);
-  zval_dtor(&member);
-  PHP_PROTO_FAKE_SCOPE_END;
-  FREE(type_url);
+  // Set type url: type_url_prefix + fully_qualified_name
+  full_name = upb_msgdef_fullname(msg->desc->msgdef);
+  type_url.size = strlen(TYPE_URL_PREFIX) + strlen(full_name);
+  buf = upb_arena_malloc(arena, type_url.size + 1);
+  memcpy(buf, TYPE_URL_PREFIX, strlen(TYPE_URL_PREFIX));
+  memcpy(buf + strlen(TYPE_URL_PREFIX), full_name, strlen(full_name));
+  type_url.data = buf;
+  Message_setval(intern, "type_url", StringVal(type_url));
 }
 
-PHP_METHOD(Any, is) {
+PHP_METHOD(google_protobuf_Any, is) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  upb_strview type_url = Message_getval(intern, "type_url").str_val;
   zend_class_entry *klass = NULL;
+  const upb_msgdef *m;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &klass) ==
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &klass) ==
       FAILURE) {
     return;
   }
 
-  DescriptorInternal* desc = get_ce_desc(klass);
-  if (desc == NULL) {
+  m = NameMap_GetMessage(klass);
+
+  if (m == NULL) {
     RETURN_BOOL(false);
   }
 
-  // Create corresponded type url.
-  const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
-  size_t type_url_len =
-      strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
-  char* type_url = ALLOC_N(char, type_url_len);
-  sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
-
-  // Fetch stored type url.
-  zval member;
-  PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
-  PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
-  zval* value =
-      php_proto_message_read_property(getThis(), &member PHP_PROTO_TSRMLS_CC);
-  zval_dtor(&member);
-  PHP_PROTO_FAKE_SCOPE_END;
-
-  // Compare two type url.
-  bool is = strcmp(type_url, Z_STRVAL_P(value)) == 0;
-  FREE(type_url);
-
-  RETURN_BOOL(is);
+  RETURN_BOOL(TryStripUrlPrefix(&type_url) &&
+              StrViewEq(type_url, upb_msgdef_fullname(m)));
 }
 
-// -----------------------------------------------------------------------------
-// Duration
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry duration_methods[] = {
-  PHP_ME(Duration, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Duration, getSeconds, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Duration, setSeconds, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Duration, getNanos, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Duration, setNanos, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* duration_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Duration",
-                                 Duration, duration)
-  zend_declare_property_long(duration_type, "seconds", strlen("seconds"),
-                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(duration_type, "nanos", strlen("nanos"),
-                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Duration, __construct) {
-  init_file_duration(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Seconds, "seconds")
-PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Nanos,   "nanos")
-
-// -----------------------------------------------------------------------------
-// Timestamp
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry timestamp_methods[] = {
-  PHP_ME(Timestamp, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timestamp, fromDateTime, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timestamp, toDateTime, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timestamp, getSeconds, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timestamp, setSeconds, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timestamp, getNanos, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timestamp, setNanos, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* timestamp_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Timestamp",
-                                 Timestamp, timestamp)
-  zend_declare_property_long(timestamp_type, "seconds", strlen("seconds"),
-                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(timestamp_type, "nanos", strlen("nanos"),
-                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Timestamp, __construct) {
-  init_file_timestamp(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Seconds, "seconds")
-PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Nanos,   "nanos")
-
-PHP_METHOD(Timestamp, fromDateTime) {
+PHP_METHOD(google_protobuf_Timestamp, fromDateTime) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
   zval* datetime;
+  const char *classname = "\\DatetimeInterface";
+  zend_string *classname_str = zend_string_init(classname, strlen(classname), 0);
+  zend_class_entry *date_interface_ce = zend_lookup_class(classname_str);
+  zend_string_release(classname_str);
 
-  PHP_PROTO_CE_DECLARE date_interface_ce;
-  if (php_proto_zend_lookup_class("\\DatetimeInterface", 18,
-                                  &date_interface_ce) == FAILURE) {
+  if (date_interface_ce == NULL) {
     zend_error(E_ERROR, "Make sure date extension is enabled.");
     return;
   }
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &datetime,
-                            PHP_PROTO_CE_UNREF(date_interface_ce)) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &datetime,
+                            date_interface_ce) == FAILURE) {
     zend_error(E_USER_ERROR, "Expect DatetimeInterface.");
     return;
   }
 
-  int64_t timestamp_seconds;
+  upb_msgval timestamp_seconds;
   {
     zval retval;
     zval function_name;
 
-#if PHP_MAJOR_VERSION < 7
-    INIT_ZVAL(retval);
-    INIT_ZVAL(function_name);
-#endif
-
-    PHP_PROTO_ZVAL_STRING(&function_name, "date_timestamp_get", 1);
+    ZVAL_STRING(&function_name, "date_timestamp_get");
 
     if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
-            ZVAL_PTR_TO_CACHED_PTR(datetime) TSRMLS_CC) == FAILURE) {
+                           datetime) == FAILURE ||
+        !Convert_PhpToUpb(&retval, &timestamp_seconds,
+                          TypeInfo_FromType(UPB_TYPE_INT64), NULL)) {
       zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
       return;
     }
 
-    protobuf_convert_to_int64(&retval, &timestamp_seconds);
-
     zval_dtor(&retval);
     zval_dtor(&function_name);
   }
 
-  int64_t timestamp_micros;
+  upb_msgval timestamp_nanos;
   {
     zval retval;
     zval function_name;
     zval format_string;
 
-#if PHP_MAJOR_VERSION < 7
-    INIT_ZVAL(retval);
-    INIT_ZVAL(function_name);
-    INIT_ZVAL(format_string);
-#endif
+    ZVAL_STRING(&function_name, "date_format");
+    ZVAL_STRING(&format_string, "u");
 
-    PHP_PROTO_ZVAL_STRING(&function_name, "date_format", 1);
-    PHP_PROTO_ZVAL_STRING(&format_string, "u", 1);
-
-    CACHED_VALUE params[2] = {
-      ZVAL_PTR_TO_CACHED_VALUE(datetime),
-      ZVAL_TO_CACHED_VALUE(format_string),
+    zval params[2] = {
+        *datetime,
+        format_string,
     };
 
-    if (call_user_function(EG(function_table), NULL, &function_name, &retval,
-            ARRAY_SIZE(params), params TSRMLS_CC) == FAILURE) {
+    if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2,
+                           params) == FAILURE ||
+        !Convert_PhpToUpb(&retval, &timestamp_nanos,
+                          TypeInfo_FromType(UPB_TYPE_INT32), NULL)) {
       zend_error(E_ERROR, "Cannot format DateTime.");
       return;
     }
 
-    protobuf_convert_to_int64(&retval, &timestamp_micros);
+    timestamp_nanos.int32_val *= 1000;
 
     zval_dtor(&retval);
     zval_dtor(&function_name);
     zval_dtor(&format_string);
   }
 
-  // Set seconds
-  MessageHeader* self = UNBOX(MessageHeader, getThis());
-  const upb_fielddef* field =
-      upb_msgdef_ntofz(self->descriptor->msgdef, "seconds");
-  void* storage = message_data(self);
-  void* memory = slot_memory(self->descriptor->layout, storage, field);
-  *(int64_t*)memory = timestamp_seconds;
-
-  // Set nanos
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos");
-  storage = message_data(self);
-  memory = slot_memory(self->descriptor->layout, storage, field);
-  *(int32_t*)memory = timestamp_micros * 1000;
+  Message_setval(intern, "seconds", timestamp_seconds);
+  Message_setval(intern, "nanos", timestamp_nanos);
 
   RETURN_NULL();
 }
 
-PHP_METHOD(Timestamp, toDateTime) {
-  // Get seconds
-  MessageHeader* self = UNBOX(MessageHeader, getThis());
-  const upb_fielddef* field =
-      upb_msgdef_ntofz(self->descriptor->msgdef, "seconds");
-  void* storage = message_data(self);
-  void* memory = slot_memory(self->descriptor->layout, storage, field);
-  int64_t seconds = *(int64_t*)memory;
-
-  // Get nanos
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos");
-  memory = slot_memory(self->descriptor->layout, storage, field);
-  int32_t nanos = *(int32_t*)memory;
+PHP_METHOD(google_protobuf_Timestamp, toDateTime) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  upb_msgval seconds = Message_getval(intern, "seconds");
+  upb_msgval nanos = Message_getval(intern, "nanos");
 
   // Get formatted time string.
   char formatted_time[32];
   snprintf(formatted_time, sizeof(formatted_time), "%" PRId64 ".%06" PRId32,
-           seconds, nanos / 1000);
+           seconds.int64_val, nanos.int32_val / 1000);
 
   // Create Datetime object.
   zval datetime;
@@ -1849,23 +1336,17 @@
   zval format_string;
   zval formatted_time_php;
 
-#if PHP_MAJOR_VERSION < 7
-  INIT_ZVAL(function_name);
-  INIT_ZVAL(format_string);
-  INIT_ZVAL(formatted_time_php);
-#endif
+  ZVAL_STRING(&function_name, "date_create_from_format");
+  ZVAL_STRING(&format_string, "U.u");
+  ZVAL_STRING(&formatted_time_php, formatted_time);
 
-  PHP_PROTO_ZVAL_STRING(&function_name, "date_create_from_format", 1);
-  PHP_PROTO_ZVAL_STRING(&format_string, "U.u", 1);
-  PHP_PROTO_ZVAL_STRING(&formatted_time_php, formatted_time, 1);
-
-  CACHED_VALUE params[2] = {
-    ZVAL_TO_CACHED_VALUE(format_string),
-    ZVAL_TO_CACHED_VALUE(formatted_time_php),
+  zval params[2] = {
+    format_string,
+    formatted_time_php,
   };
 
-  if (call_user_function(EG(function_table), NULL, &function_name, &datetime,
-          ARRAY_SIZE(params), params TSRMLS_CC) == FAILURE) {
+  if (call_user_function(EG(function_table), NULL, &function_name, &datetime, 2,
+                         params) == FAILURE) {
     zend_error(E_ERROR, "Cannot create DateTime.");
     return;
   }
@@ -1874,861 +1355,40 @@
   zval_dtor(&format_string);
   zval_dtor(&formatted_time_php);
 
-#if PHP_MAJOR_VERSION < 7
-  zval* datetime_ptr = &datetime;
-  PHP_PROTO_RETVAL_ZVAL(datetime_ptr);
-#else
   ZVAL_OBJ(return_value, Z_OBJ(datetime));
+}
+
+#include "wkt.inc"
+
+/**
+ * Message_ModuleInit()
+ *
+ * Called when the C extension is loaded to register all types.
+ */
+void Message_ModuleInit() {
+  zend_class_entry tmp_ce;
+  zend_object_handlers *h = &message_object_handlers;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Message",
+                   Message_methods);
+
+  message_ce = zend_register_internal_class(&tmp_ce);
+  message_ce->create_object = Message_create;
+
+  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+  h->dtor_obj = Message_dtor;
+#if PHP_VERSION_ID < 80000
+  h->compare_objects = Message_compare_objects;
+#else
+  h->compare = Message_compare_objects;
 #endif
+  h->read_property = Message_read_property;
+  h->write_property = Message_write_property;
+  h->has_property = Message_has_property;
+  h->unset_property = Message_unset_property;
+  h->get_properties = Message_get_properties;
+  h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
+  h->clone_obj = Message_clone_obj;
+
+  WellKnownTypes_ModuleInit();  /* From wkt.inc. */
 }
-
-// -----------------------------------------------------------------------------
-// Api
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry api_methods[] = {
-  PHP_ME(Api, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, getMethods, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, setMethods, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, getOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, setOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, getVersion, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, setVersion, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, getSourceContext, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, setSourceContext, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, getMixins, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, setMixins, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, getSyntax, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Api, setSyntax, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* api_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Api",
-                                 Api, api)
-  zend_declare_property_string(api_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(api_type, "methods", strlen("methods"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(api_type, "options", strlen("options"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(api_type, "version", strlen("version"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(api_type, "source_context", strlen("source_context"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(api_type, "mixins", strlen("mixins"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(api_type, "syntax", strlen("syntax"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Api, __construct) {
-  init_file_api(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Methods, "methods")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Version, "version")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, SourceContext, "source_context")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Mixins, "mixins")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// BoolValue
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry bool_value_methods[] = {
-  PHP_ME(BoolValue, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(BoolValue, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(BoolValue, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* bool_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\BoolValue",
-                                 BoolValue, bool_value)
-  zend_declare_property_bool(bool_value_type, "value", strlen("value"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(BoolValue, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(BoolValue, bool_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// BytesValue
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry bytes_value_methods[] = {
-  PHP_ME(BytesValue, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(BytesValue, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(BytesValue, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* bytes_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\BytesValue",
-                                 BytesValue, bytes_value)
-  zend_declare_property_string(bytes_value_type, "value", strlen("value"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(BytesValue, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(BytesValue, bytes_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// DoubleValue
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry double_value_methods[] = {
-  PHP_ME(DoubleValue, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(DoubleValue, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(DoubleValue, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* double_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\DoubleValue",
-                                 DoubleValue, double_value)
-  zend_declare_property_double(double_value_type, "value", strlen("value"), 0,
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(DoubleValue, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(DoubleValue, double_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Enum
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry enum_methods[] = {
-  PHP_ME(Enum, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, getEnumvalue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, setEnumvalue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, getOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, setOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, getSourceContext, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, setSourceContext, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, getSyntax, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Enum, setSyntax, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* enum_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Enum",
-                                 Enum, enum)
-  zend_declare_property_string(enum_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(enum_type, "enumvalue", strlen("enumvalue"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(enum_type, "options", strlen("options"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(enum_type, "source_context", strlen("source_context"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(enum_type, "syntax", strlen("syntax"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Enum, __construct) {
-  init_file_type(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Enumvalue, "enumvalue")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, SourceContext, "source_context")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// EnumValue
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry enum_value_methods[] = {
-  PHP_ME(EnumValue, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumValue, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumValue, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumValue, getNumber, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumValue, setNumber, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumValue, getOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(EnumValue, setOptions, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* enum_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\EnumValue",
-                                 EnumValue, enum_value)
-  zend_declare_property_string(enum_value_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(enum_value_type, "number", strlen("number"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(enum_value_type, "options", strlen("options"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(EnumValue, __construct) {
-  init_file_type(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Number, "number")
-PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Options, "options")
-
-// -----------------------------------------------------------------------------
-// FieldMask
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry field_mask_methods[] = {
-  PHP_ME(FieldMask, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldMask, getPaths, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FieldMask, setPaths, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* field_mask_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\FieldMask",
-                                 FieldMask, field_mask)
-  zend_declare_property_null(field_mask_type, "paths", strlen("paths"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(FieldMask, __construct) {
-  init_file_field_mask(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(FieldMask, field_mask, Paths, "paths")
-
-// -----------------------------------------------------------------------------
-// Field
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry field_methods[] = {
-  PHP_ME(Field, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getKind, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setKind, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getCardinality, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setCardinality, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getNumber, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setNumber, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getOneofIndex, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setOneofIndex, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getPacked, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setPacked, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getJsonName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setJsonName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, getDefaultValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Field, setDefaultValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* field_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Field",
-                                 Field, field)
-  zend_declare_property_long(field_type, "kind", strlen("kind"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(field_type, "cardinality", strlen("cardinality"),
-                             0, ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(field_type, "number", strlen("number"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(field_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(field_type, "type_url", strlen("type_url"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(field_type, "oneof_index", strlen("oneof_index"),
-                             0, ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_bool(field_type, "packed", strlen("packed"), false,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(field_type, "options", strlen("options"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(field_type, "json_name", strlen("json_name"),
-                               "", ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(field_type, "default_value",
-                               strlen("default_value"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Field, __construct) {
-  init_file_type(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Kind, "kind")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Cardinality, "cardinality")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Number, "number")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, TypeUrl, "type_url")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, OneofIndex, "oneof_index")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Packed, "packed")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, JsonName, "json_name")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, DefaultValue, "default_value")
-
-// -----------------------------------------------------------------------------
-// FloatValue
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry float_value_methods[] = {
-  PHP_ME(FloatValue, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FloatValue, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(FloatValue, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* float_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\FloatValue",
-                                 FloatValue, float_value)
-  zend_declare_property_double(float_value_type, "value", strlen("value"), 0,
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(FloatValue, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(FloatValue, float_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// GPBEmpty
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry empty_methods[] = {
-  PHP_ME(GPBEmpty, __construct, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* empty_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\GPBEmpty",
-                                 GPBEmpty, empty)
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(GPBEmpty, __construct) {
-  init_file_empty(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-
-// -----------------------------------------------------------------------------
-// Int32Value
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry int32_value_methods[] = {
-  PHP_ME(Int32Value, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Int32Value, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Int32Value, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* int32_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Int32Value",
-                                 Int32Value, int32_value)
-  zend_declare_property_long(int32_value_type, "value", strlen("value"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Int32Value, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Int32Value, int32_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Int64Value
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry int64_value_methods[] = {
-  PHP_ME(Int64Value, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Int64Value, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Int64Value, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* int64_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Int64Value",
-                                 Int64Value, int64_value)
-  zend_declare_property_long(int64_value_type, "value", strlen("value"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Int64Value, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Int64Value, int64_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// ListValue
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry list_value_methods[] = {
-  PHP_ME(ListValue, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(ListValue, getValues, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(ListValue, setValues, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* list_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\ListValue",
-                                 ListValue, list_value)
-  zend_declare_property_null(list_value_type, "values", strlen("values"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(ListValue, __construct) {
-  init_file_struct(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(ListValue, list_value, Values, "values")
-
-// -----------------------------------------------------------------------------
-// Method
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry method_methods[] = {
-  PHP_ME(Method, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, getRequestTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, setRequestTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, getRequestStreaming, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, setRequestStreaming, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, getResponseTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, setResponseTypeUrl, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, getResponseStreaming, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, setResponseStreaming, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, getOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, setOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, getSyntax, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Method, setSyntax, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* method_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Method",
-                                 Method, method)
-  zend_declare_property_string(method_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(method_type, "request_type_url",
-                               strlen("request_type_url"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_bool(method_type, "request_streaming",
-                             strlen("request_streaming"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(method_type, "response_type_url",
-                               strlen("response_type_url"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_bool(method_type, "response_streaming",
-                             strlen("response_streaming"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(method_type, "options", strlen("options"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(method_type, "syntax", strlen("syntax"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Method, __construct) {
-  init_file_api(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Method, method, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, RequestTypeUrl, "request_type_url")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, RequestStreaming, "request_streaming")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, ResponseTypeUrl, "response_type_url")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, ResponseStreaming, "response_streaming")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// Mixin
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry mixin_methods[] = {
-  PHP_ME(Mixin, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Mixin, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Mixin, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Mixin, getRoot, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Mixin, setRoot, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* mixin_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Mixin",
-                                 Mixin, mixin)
-  zend_declare_property_string(mixin_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(mixin_type, "root", strlen("root"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Mixin, __construct) {
-  init_file_api(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Mixin, mixin, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Mixin, mixin, Root, "root")
-
-// -----------------------------------------------------------------------------
-// Option
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry option_methods[] = {
-  PHP_ME(Option, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Option, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Option, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Option, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Option, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* option_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Option",
-                                 Option, option)
-  zend_declare_property_string(option_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(option_type, "value", strlen("value"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Option, __construct) {
-  init_file_type(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Option, option, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Option, option, Value, "value")
-
-// -----------------------------------------------------------------------------
-// SourceContext
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry source_context_methods[] = {
-  PHP_ME(SourceContext, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(SourceContext, getFileName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(SourceContext, setFileName, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* source_context_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\SourceContext",
-                                 SourceContext, source_context)
-  zend_declare_property_string(source_context_type, "file_name",
-                               strlen("file_name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(SourceContext, __construct) {
-  init_file_source_context(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(SourceContext, source_context, FileName, "file_name")
-
-// -----------------------------------------------------------------------------
-// StringValue
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry string_value_methods[] = {
-  PHP_ME(StringValue, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(StringValue, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(StringValue, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* string_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\StringValue",
-                                 StringValue, string_value)
-  zend_declare_property_string(string_value_type, "value", strlen("value"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(StringValue, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(StringValue, string_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Struct
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry struct_methods[] = {
-  PHP_ME(Struct, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Struct, getFields, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Struct, setFields, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* struct_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Struct",
-                                 Struct, struct)
-  zend_declare_property_null(struct_type, "fields", strlen("fields"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Struct, __construct) {
-  init_file_struct(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Struct, struct, Fields, "fields")
-
-// -----------------------------------------------------------------------------
-// Type
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry type_methods[] = {
-  PHP_ME(Type, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, getName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, setName, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, getFields, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, setFields, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, getOneofs, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, setOneofs, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, getOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, setOptions, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, getSourceContext, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, setSourceContext, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, getSyntax, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Type, setSyntax, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* type_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Type",
-                                 Type, type)
-  zend_declare_property_string(type_type, "name", strlen("name"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(type_type, "fields", strlen("fields"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_string(type_type, "oneofs", strlen("oneofs"), "",
-                               ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(type_type, "options", strlen("options"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_null(type_type, "source_context", strlen("source_context"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-  zend_declare_property_long(type_type, "syntax", strlen("syntax"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Type, __construct) {
-  init_file_type(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Fields, "fields")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Oneofs, "oneofs")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, SourceContext, "source_context")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// UInt32Value
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry u_int32_value_methods[] = {
-  PHP_ME(UInt32Value, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(UInt32Value, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(UInt32Value, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* u_int32_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\UInt32Value",
-                                 UInt32Value, u_int32_value)
-  zend_declare_property_long(u_int32_value_type, "value", strlen("value"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(UInt32Value, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(UInt32Value, u_int32_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// UInt64Value
-// -----------------------------------------------------------------------------
-
-static  zend_function_entry u_int64_value_methods[] = {
-  PHP_ME(UInt64Value, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(UInt64Value, getValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(UInt64Value, setValue, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* u_int64_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\UInt64Value",
-                                 UInt64Value, u_int64_value)
-  zend_declare_property_long(u_int64_value_type, "value", strlen("value"), 0,
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(UInt64Value, __construct) {
-  init_file_wrappers(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(UInt64Value, u_int64_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Value
-// -----------------------------------------------------------------------------
-
-static zend_function_entry value_methods[] = {
-  PHP_ME(Value, __construct, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, getNullValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, setNullValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, getNumberValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, setNumberValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, getStringValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, setStringValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, getBoolValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, setBoolValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, getStructValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, setStructValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, getListValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, setListValue, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Value, getKind, NULL, ZEND_ACC_PUBLIC)
-  {NULL, NULL, NULL}
-};
-
-zend_class_entry* value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Value",
-                                 Value, value)
-  zend_declare_property_null(value_type, "kind", strlen("kind"),
-                             ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Value, __construct) {
-  init_file_struct(TSRMLS_C);
-  INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, NullValue, "null_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, NumberValue, "number_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StringValue, "string_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, BoolValue, "bool_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StructValue, "struct_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, ListValue, "list_value")
-PHP_PROTO_ONEOF_ACCESSORS(Value, value, Kind, "kind")
-
-// -----------------------------------------------------------------------------
-// GPBMetadata files for well known types
-// -----------------------------------------------------------------------------
-
-#define DEFINE_GPBMETADATA_FILE(LOWERNAME, CAMELNAME, CLASSNAME)      \
-  zend_class_entry* gpb_metadata_##LOWERNAME##_type;                  \
-  static zend_function_entry gpb_metadata_##LOWERNAME##_methods[] = { \
-    PHP_ME(GPBMetadata_##CAMELNAME, initOnce, NULL,                   \
-           ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)                         \
-    ZEND_FE_END                                                       \
-  };                                                                  \
-  void gpb_metadata_##LOWERNAME##_init(TSRMLS_D) {                    \
-    zend_class_entry class_type;                                      \
-    INIT_CLASS_ENTRY(class_type, CLASSNAME,                           \
-                     gpb_metadata_##LOWERNAME##_methods);             \
-    gpb_metadata_##LOWERNAME##_type =                                 \
-        zend_register_internal_class(&class_type TSRMLS_CC);          \
-  }                                                                   \
-  PHP_METHOD(GPBMetadata_##CAMELNAME, initOnce) {                     \
-    init_file_##LOWERNAME(TSRMLS_C);                                  \
-  }
-
-DEFINE_GPBMETADATA_FILE(any, Any, "GPBMetadata\\Google\\Protobuf\\Any");
-DEFINE_GPBMETADATA_FILE(api, Api, "GPBMetadata\\Google\\Protobuf\\Api");
-DEFINE_GPBMETADATA_FILE(duration, Duration,
-                        "GPBMetadata\\Google\\Protobuf\\Duration");
-DEFINE_GPBMETADATA_FILE(field_mask, FieldMask,
-                        "GPBMetadata\\Google\\Protobuf\\FieldMask");
-DEFINE_GPBMETADATA_FILE(empty, Empty,
-                        "GPBMetadata\\Google\\Protobuf\\GPBEmpty");
-DEFINE_GPBMETADATA_FILE(source_context, SourceContext,
-                        "GPBMetadata\\Google\\Protobuf\\SourceContext");
-DEFINE_GPBMETADATA_FILE(struct, Struct,
-                        "GPBMetadata\\Google\\Protobuf\\Struct");
-DEFINE_GPBMETADATA_FILE(timestamp, Timestamp,
-                        "GPBMetadata\\Google\\Protobuf\\Timestamp");
-DEFINE_GPBMETADATA_FILE(type, Type, "GPBMetadata\\Google\\Protobuf\\Type");
-DEFINE_GPBMETADATA_FILE(wrappers, Wrappers,
-                        "GPBMetadata\\Google\\Protobuf\\Wrappers");
-
-#undef DEFINE_GPBMETADATA_FILE
diff --git a/php/ext/google/protobuf/message.h b/php/ext/google/protobuf/message.h
new file mode 100644
index 0000000..5b49e0d
--- /dev/null
+++ b/php/ext/google/protobuf/message.h
@@ -0,0 +1,61 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PHP_PROTOBUF_MESSAGE_H_
+#define PHP_PROTOBUF_MESSAGE_H_
+
+#include <stdbool.h>
+
+#include "def.h"
+
+// Registers the PHP Message class.
+void Message_ModuleInit();
+
+// Gets a upb_msg* for the PHP object |val|, which must either be a Message
+// object or 'null'. Returns true and stores the message in |msg| if the
+// conversion succeeded (we can't return upb_msg* because null->NULL is a valid
+// conversion). Returns false and raises a PHP error if this isn't a Message
+// object or null, or if the Message object doesn't match this Descriptor.
+//
+// The given |arena| will be fused to this message's arena.
+bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena,
+                           upb_msg **msg);
+
+// Gets or creates a PHP Message object to wrap the given upb_msg* and |desc|
+// and returns it in |val|. The PHP object will keep a reference to this |arena|
+// to ensure the underlying message data stays alive.
+//
+// If |msg| is NULL, this will return a PHP null.
+void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg,
+                           zval *arena);
+
+bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type);
+
+#endif  // PHP_PROTOBUF_MESSAGE_H_
diff --git a/php/ext/google/protobuf/names.c b/php/ext/google/protobuf/names.c
new file mode 100644
index 0000000..6108ff4
--- /dev/null
+++ b/php/ext/google/protobuf/names.c
@@ -0,0 +1,227 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "names.h"
+
+#include <stdlib.h>
+
+#include "protobuf.h"
+
+/* stringsink *****************************************************************/
+
+typedef struct {
+  char *ptr;
+  size_t len, size;
+} stringsink;
+
+static size_t stringsink_string(stringsink *sink, const char *ptr, size_t len) {
+  size_t new_size = sink->size;
+
+  while (sink->len + len > new_size) {
+    new_size *= 2;
+  }
+
+  if (new_size != sink->size) {
+    sink->ptr = realloc(sink->ptr, new_size);
+    sink->size = new_size;
+  }
+
+  memcpy(sink->ptr + sink->len, ptr, len);
+  sink->len += len;
+
+  return len;
+}
+
+static void stringsink_init(stringsink *sink) {
+  sink->size = 32;
+  sink->ptr = malloc(sink->size);
+  PBPHP_ASSERT(sink->ptr != NULL);
+  sink->len = 0;
+}
+
+static void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
+
+/* def name -> classname ******************************************************/
+
+const char *const kReservedNames[] = {
+    "abstract",     "and",        "array",      "as",           "break",
+    "callable",     "case",       "catch",      "class",        "clone",
+    "const",        "continue",   "declare",    "default",      "die",
+    "do",           "echo",       "else",       "elseif",       "empty",
+    "enddeclare",   "endfor",     "endforeach", "endif",        "endswitch",
+    "endwhile",     "eval",       "exit",       "extends",      "final",
+    "finally",      "fn",         "for",        "foreach",      "function",
+    "if",           "implements", "include",    "include_once", "instanceof",
+    "global",       "goto",       "insteadof",  "interface",    "isset",
+    "list",         "match",      "namespace",  "new",          "or",
+    "print",        "private",    "protected",  "public",       "require",
+    "require_once", "return",     "static",     "switch",       "throw",
+    "trait",        "try",        "unset",      "use",          "var",
+    "while",        "xor",        "yield",      "int",          "float",
+    "bool",         "string",     "true",       "false",        "null",
+    "void",         "iterable",   NULL};
+
+bool is_reserved_name(const char* name) {
+  int i;
+  for (i = 0; kReservedNames[i]; i++) {
+    if (strcmp(kReservedNames[i], name) == 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static char nolocale_tolower(char ch) {
+  if (ch >= 'A' && ch <= 'Z') {
+    return ch - ('A' - 'a');
+  } else {
+    return ch;
+  }
+}
+
+static char nolocale_toupper(char ch) {
+  if (ch >= 'a' && ch <= 'z') {
+    return ch - ('a' - 'A');
+  } else {
+    return ch;
+  }
+}
+
+static bool is_reserved(const char *segment, int length) {
+  bool result;
+  char* lower = calloc(1, length + 1);
+  memcpy(lower, segment, length);
+  int i = 0;
+  while(lower[i]) {
+    lower[i] = nolocale_tolower(lower[i]);
+    i++;
+  }
+  lower[length] = 0;
+  result = is_reserved_name(lower);
+  free(lower);
+  return result;
+}
+
+static void fill_prefix(const char *segment, int length,
+                        const char *prefix_given,
+                        const char *package_name,
+                        stringsink *classname) {
+  if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
+    stringsink_string(classname, prefix_given, strlen(prefix_given));
+  } else {
+    if (is_reserved(segment, length)) {
+      if (package_name != NULL &&
+          strcmp("google.protobuf", package_name) == 0) {
+        stringsink_string(classname, "GPB", 3);
+      } else {
+        stringsink_string(classname, "PB", 2);
+      }
+    }
+  }
+}
+
+static void fill_segment(const char *segment, int length,
+                         stringsink *classname, bool use_camel) {
+  if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
+    char first = nolocale_toupper(segment[0]);
+    stringsink_string(classname, &first, 1);
+    stringsink_string(classname, segment + 1, length - 1);
+  } else {
+    stringsink_string(classname, segment, length);
+  }
+}
+
+static void fill_namespace(const char *package, const char *php_namespace,
+                           stringsink *classname) {
+  if (php_namespace != NULL) {
+    if (strlen(php_namespace) != 0) {
+      stringsink_string(classname, php_namespace, strlen(php_namespace));
+      stringsink_string(classname, "\\", 1);
+    }
+  } else if (package != NULL) {
+    int i = 0, j = 0;
+    size_t package_len = strlen(package);
+    while (i < package_len) {
+      j = i;
+      while (j < package_len && package[j] != '.') {
+        j++;
+      }
+      fill_prefix(package + i, j - i, "", package, classname);
+      fill_segment(package + i, j - i, classname, true);
+      stringsink_string(classname, "\\", 1);
+      i = j + 1;
+    }
+  }
+}
+
+static void fill_classname(const char *fullname,
+                           const char *package,
+                           const char *prefix,
+                           stringsink *classname) {
+  int classname_start = 0;
+  if (package != NULL) {
+    size_t package_len = strlen(package);
+    classname_start = package_len == 0 ? 0 : package_len + 1;
+  }
+  size_t fullname_len = strlen(fullname);
+
+  int i = classname_start, j;
+  while (i < fullname_len) {
+    j = i;
+    while (j < fullname_len && fullname[j] != '.') {
+      j++;
+    }
+    fill_prefix(fullname + i, j - i, prefix, package, classname);
+    fill_segment(fullname + i, j - i, classname, false);
+    if (j != fullname_len) {
+      stringsink_string(classname, "\\", 1);
+    }
+    i = j + 1;
+  }
+}
+
+char *GetPhpClassname(const upb_filedef *file, const char *fullname) {
+  // Prepend '.' to package name to make it absolute. In the 5 additional
+  // bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if
+  // given message is google.protobuf.Empty.
+  const char *package = upb_filedef_package(file);
+  const char *php_namespace = upb_filedef_phpnamespace(file);
+  const char *prefix = upb_filedef_phpprefix(file);
+  char *ret;
+  stringsink namesink;
+  stringsink_init(&namesink);
+
+  fill_namespace(package, php_namespace, &namesink);
+  fill_classname(fullname, package, prefix, &namesink);
+  stringsink_string(&namesink, "\0", 1);
+  ret = strdup(namesink.ptr);
+  stringsink_uninit(&namesink);
+  return ret;
+}
diff --git a/php/ext/google/protobuf/utf8.h b/php/ext/google/protobuf/names.h
similarity index 85%
rename from php/ext/google/protobuf/utf8.h
rename to php/ext/google/protobuf/names.h
index 28b8d87..75101c5 100644
--- a/php/ext/google/protobuf/utf8.h
+++ b/php/ext/google/protobuf/names.h
@@ -28,9 +28,13 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef GOOGLE_PROTOBUF_UTF8_H_
-#define GOOGLE_PROTOBUF_UTF8_H_
+#ifndef PHP_PROTOBUF_NAMES_H_
+#define PHP_PROTOBUF_NAMES_H_
 
-bool is_structurally_valid_utf8(const char* buf, int len);
+#include "php-upb.h"
 
-#endif  // GOOGLE_PROTOBUF_UTF8_H_
+// Translates a protobuf symbol name (eg. foo.bar.Baz) into a PHP class name
+// (eg. \Foo\Bar\Baz).
+char *GetPhpClassname(const upb_filedef *file, const char *fullname);
+
+#endif  // PHP_PROTOBUF_NAMES_H_
diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml
index 5cb2b46..7aaa5e2 100644
--- a/php/ext/google/protobuf/package.xml
+++ b/php/ext/google/protobuf/package.xml
@@ -10,42 +10,51 @@
   <email>protobuf-opensource@google.com</email>
   <active>yes</active>
  </lead>
- <date>2020-02-12</date>
- <time>12:46:57</time>
+ <date>2021-06-04</date>
+ <time>21:17:28</time>
  <version>
-  <release>3.11.4</release>
-  <api>3.11.4</api>
+  <release>3.17.3</release>
+  <api>3.17.3</api>
  </version>
  <stability>
   <release>stable</release>
   <api>stable</api>
  </stability>
  <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
- <notes>GA release.</notes>
+ <notes>
+ * No new changes in 3.17.2
+ </notes>
  <contents>
   <dir baseinstalldir="/" name="/">
     <file baseinstalldir="/" name="config.m4" role="src"/>
+    <file baseinstalldir="/" name="arena.c" role="src"/>
+    <file baseinstalldir="/" name="arena.h" role="src"/>
     <file baseinstalldir="/" name="array.c" role="src"/>
-    <file baseinstalldir="/" name="builtin_descriptors.inc" role="src"/>
+    <file baseinstalldir="/" name="array.h" role="src"/>
+    <file baseinstalldir="/" name="convert.c" role="src"/>
+    <file baseinstalldir="/" name="convert.h" role="src"/>
     <file baseinstalldir="/" name="def.c" role="src"/>
-    <file baseinstalldir="/" name="encode_decode.c" role="src"/>
+    <file baseinstalldir="/" name="def.h" role="src"/>
     <file baseinstalldir="/" name="map.c" role="src"/>
+    <file baseinstalldir="/" name="map.h" role="src"/>
     <file baseinstalldir="/" name="message.c" role="src"/>
+    <file baseinstalldir="/" name="message.h" role="src"/>
+    <file baseinstalldir="/" name="names.c" role="src"/>
+    <file baseinstalldir="/" name="names.h" role="src"/>
+    <file baseinstalldir="/" name="php-upb.c" role="src"/>
+    <file baseinstalldir="/" name="php-upb.h" role="src"/>
     <file baseinstalldir="/" name="protobuf.c" role="src"/>
     <file baseinstalldir="/" name="protobuf.h" role="src"/>
-    <file baseinstalldir="/" name="storage.c" role="src"/>
-    <file baseinstalldir="/" name="type_check.c" role="src"/>
-    <file baseinstalldir="/" name="upb.c" role="src"/>
-    <file baseinstalldir="/" name="upb.h" role="src"/>
-    <file baseinstalldir="/" name="utf8.c" role="src"/>
-    <file baseinstalldir="/" name="utf8.h" role="src"/>
+    <file baseinstalldir="/" name="wkt.inc" role="src"/>
+    <file baseinstalldir="/" name="third_party/wyhash/wyhash.h" role="src"/>
+    <file baseinstalldir="/" name="third_party/wyhash/LICENSE" role="doc"/>
     <file baseinstalldir="/" name="LICENSE" role="doc"/>
   </dir>
  </contents>
  <dependencies>
   <required>
    <php>
-    <min>5.5.9</min>
+    <min>7.0.0</min>
    </php>
    <pearinstaller>
     <min>1.4.0</min>
@@ -529,5 +538,507 @@
    <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
    <notes>GA release.</notes>
   </release>
+  <release>
+   <version>
+    <release>3.12.0RC1</release>
+    <api>3.12.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-04-30</date>
+   <time>14:23:34</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.12.0RC2</release>
+    <api>3.12.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-05-12</date>
+   <time>12:48:03</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.12.0</release>
+    <api>3.12.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-05-15</date>
+   <time>13:26:23</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.12.1</release>
+    <api>3.12.1</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-05-20</date>
+   <time>10:18:13</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.12.2</release>
+    <api>3.12.2</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-05-26</date>
+   <time>13:57:10</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.12.3</release>
+    <api>3.12.3</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-06-01</date>
+   <time>01:09:39</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0RC1</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-08-05</date>
+   <time>11:21:41</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0RC2</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-08-05</date>
+   <time>11:22:52</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0RC3</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-08-12</date>
+   <time>13:46:54</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0</release>
+    <api>3.13.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-08-14</date>
+   <time>14:07:59</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.13.0.1</release>
+    <api>3.13.0.1</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-10-08</date>
+   <time>14:07:59</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.14.0RC1</release>
+    <api>3.14.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-11-05</date>
+   <time>13:39:47</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.14.0RC2</release>
+    <api>3.14.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-11-10</date>
+   <time>16:28:41</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.14.0RC3</release>
+    <api>3.14.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2020-11-11</date>
+   <time>10:35:18</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.14.0</release>
+    <api>3.14.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-11-12</date>
+   <time>14:06:40</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.0RC1</release>
+    <api>3.15.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2021-02-05</date>
+   <time>14:15:36</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.0RC2</release>
+    <api>3.15.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2021-02-17</date>
+   <time>09:10:33</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.0</release>
+    <api>3.15.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-02-18</date>
+   <time>10:33:10</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.1</release>
+    <api>3.15.1</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-02-19</date>
+   <time>10:50:04</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.2</release>
+    <api>3.15.2</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-02-23</date>
+   <time>11:35:09</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.3</release>
+    <api>3.15.3</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-02-24</date>
+   <time>16:49:52</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.4</release>
+    <api>3.15.4</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-03-02</date>
+   <time>15:25:02</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.5</release>
+    <api>3.15.5</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-03-04</date>
+   <time>10:45:30</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.6</release>
+    <api>3.15.6</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-03-10</date>
+   <time>10:11:34</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.15.7</release>
+    <api>3.15.7</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-04-02</date>
+   <time>10:01:42</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.16.0RC1</release>
+    <api>3.16.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2021-04-02</date>
+   <time>16:11:33</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.16.0RC2</release>
+    <api>3.16.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2021-05-03</date>
+   <time>16:40:57</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.16.0</release>
+    <api>3.16.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-05-05</date>
+   <time>16:34:02</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.17.0RC1</release>
+    <api>3.17.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2021-05-06</date>
+   <time>11:08:58</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.17.0RC2</release>
+    <api>3.17.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2021-05-07</date>
+   <time>15:58:19</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.17.0</release>
+    <api>3.17.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-05-11</date>
+   <time>13:29:14</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.17.1</release>
+    <api>3.17.1</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-05-19</date>
+   <time>16:06:12</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+ * Fixed PHP memory leaks and arginfo errors. (#8614)
+ * Fixed JSON parser to allow multiple values from the same oneof as long as
+   all but one are null.
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.17.2</release>
+    <api>3.17.2</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-05-25</date>
+   <time>19:32:12</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.17.3</release>
+    <api>3.17.3</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2021-06-04</date>
+   <time>21:17:28</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+   </notes>
+  </release>
  </changelog>
 </package>
diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c
new file mode 100644
index 0000000..774c8d2
--- /dev/null
+++ b/php/ext/google/protobuf/php-upb.c
@@ -0,0 +1,9243 @@
+/* Amalgamated source file */
+#include "php-upb.h"
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google LLC nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is where we define macros used across upb.
+ *
+ * All of these macros are undef'd in port_undef.inc to avoid leaking them to
+ * users.
+ *
+ * The correct usage is:
+ *
+ *   #include "upb/foobar.h"
+ *   #include "upb/baz.h"
+ *
+ *   // MUST be last included header.
+ *   #include "upb/port_def.inc"
+ *
+ *   // Code for this file.
+ *   // <...>
+ *
+ *   // Can be omitted for .c files, required for .h.
+ *   #include "upb/port_undef.inc"
+ *
+ * This file is private and must not be included by users!
+ */
+
+#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+      (defined(__cplusplus) && __cplusplus >= 201103L) ||           \
+      (defined(_MSC_VER) && _MSC_VER >= 1900))
+#error upb requires C99 or C++11 or MSVC >= 2015.
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#if UINTPTR_MAX == 0xffffffff
+#define UPB_SIZE(size32, size64) size32
+#else
+#define UPB_SIZE(size32, size64) size64
+#endif
+
+/* If we always read/write as a consistent type to each address, this shouldn't
+ * violate aliasing.
+ */
+#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
+
+#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
+  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
+      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
+      : default
+
+#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
+  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
+  *UPB_PTR_AT(msg, offset, fieldtype) = value;
+
+#define UPB_MAPTYPE_STRING 0
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__) || defined(__clang__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
+#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
+#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
+#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
+
+/* Hints to the compiler about likely/unlikely branches. */
+#if defined (__GNUC__) || defined(__clang__)
+#define UPB_LIKELY(x) __builtin_expect((x),1)
+#define UPB_UNLIKELY(x) __builtin_expect((x),0)
+#else
+#define UPB_LIKELY(x) (x)
+#define UPB_UNLIKELY(x) (x)
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg)))
+#elif defined(_MSC_VER)
+#define UPB_NOINLINE
+#define UPB_FORCEINLINE
+#define UPB_NORETURN __declspec(noreturn)
+#define UPB_PRINTF(str, first_vararg)
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#define UPB_PRINTF(str, first_vararg)
+#endif
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
+ */
+#ifdef NDEBUG
+#ifdef __GNUC__
+#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
+#elif defined _MSC_VER
+#define UPB_ASSUME(expr) if (!(expr)) __assume(0)
+#else
+#define UPB_ASSUME(expr) do {} while (false && (expr))
+#endif
+#else
+#define UPB_ASSUME(expr) assert(expr)
+#endif
+
+/* UPB_ASSERT(): in release mode, we use the expression without letting it be
+ * evaluated.  This prevents "unused variable" warnings. */
+#ifdef NDEBUG
+#define UPB_ASSERT(expr) do {} while (false && (expr))
+#else
+#define UPB_ASSERT(expr) assert(expr)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
+#else
+#define UPB_UNREACHABLE() do { assert(0); } while(0)
+#endif
+
+/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
+#ifdef __APPLE__
+#define UPB_SETJMP(buf) _setjmp(buf)
+#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
+#else
+#define UPB_SETJMP(buf) setjmp(buf)
+#define UPB_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */
+#define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr))
+
+/* Configure whether fasttable is switched on or not. *************************/
+
+#if defined(__has_attribute)
+#define UPB_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define UPB_HAS_ATTRIBUTE(x) 0
+#endif
+
+#if UPB_HAS_ATTRIBUTE(musttail)
+#define UPB_MUSTTAIL __attribute__((musttail))
+#else
+#define UPB_MUSTTAIL
+#endif
+
+#undef UPB_HAS_ATTRIBUTE
+
+/* This check is not fully robust: it does not require that we have "musttail"
+ * support available. We need tail calls to avoid consuming arbitrary amounts
+ * of stack space.
+ *
+ * GCC/Clang can mostly be trusted to generate tail calls as long as
+ * optimization is enabled, but, debug builds will not generate tail calls
+ * unless "musttail" is available.
+ *
+ * We should probably either:
+ *   1. require that the compiler supports musttail.
+ *   2. add some fallback code for when musttail isn't available (ie. return
+ *      instead of tail calling). This is safe and portable, but this comes at
+ *      a CPU cost.
+ */
+#if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__)
+#define UPB_FASTTABLE_SUPPORTED 1
+#else
+#define UPB_FASTTABLE_SUPPORTED 0
+#endif
+
+/* define UPB_ENABLE_FASTTABLE to force fast table support.
+ * This is useful when we want to ensure we are really getting fasttable,
+ * for example for testing or benchmarking. */
+#if defined(UPB_ENABLE_FASTTABLE)
+#if !UPB_FASTTABLE_SUPPORTED
+#error fasttable is x86-64/ARM64 only and requires GCC or Clang.
+#endif
+#define UPB_FASTTABLE 1
+/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
+ * This is useful for releasing code that might be used on multiple platforms,
+ * for example the PHP or Ruby C extensions. */
+#elif defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
+#else
+#define UPB_FASTTABLE 0
+#endif
+
+/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
+ * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */
+#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE_INIT(...)
+#else
+#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
+#endif
+
+#undef UPB_FASTTABLE_SUPPORTED
+
+/* ASAN poisoning (for arena) *************************************************/
+
+#if defined(__SANITIZE_ADDRESS__)
+#define UPB_ASAN 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  __asan_poison_memory_region((addr), (size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  __asan_unpoison_memory_region((addr), (size))
+#else
+#define UPB_ASAN 0
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#endif
+
+/** upb/decode.c ************************************************************/
+
+#include <setjmp.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+/* Maps descriptor type -> elem_size_lg2.  */
+static const uint8_t desctype_to_elem_size_lg2[] = {
+    -1,               /* invalid descriptor type */
+    3,  /* DOUBLE */
+    2,   /* FLOAT */
+    3,   /* INT64 */
+    3,  /* UINT64 */
+    2,   /* INT32 */
+    3,  /* FIXED64 */
+    2,  /* FIXED32 */
+    0,    /* BOOL */
+    UPB_SIZE(3, 4),  /* STRING */
+    UPB_SIZE(2, 3),  /* GROUP */
+    UPB_SIZE(2, 3),  /* MESSAGE */
+    UPB_SIZE(3, 4),  /* BYTES */
+    2,  /* UINT32 */
+    2,    /* ENUM */
+    2,   /* SFIXED32 */
+    3,   /* SFIXED64 */
+    2,   /* SINT32 */
+    3,   /* SINT64 */
+};
+
+/* Maps descriptor type -> upb map size.  */
+static const uint8_t desctype_to_mapsize[] = {
+    -1,                 /* invalid descriptor type */
+    8,                  /* DOUBLE */
+    4,                  /* FLOAT */
+    8,                  /* INT64 */
+    8,                  /* UINT64 */
+    4,                  /* INT32 */
+    8,                  /* FIXED64 */
+    4,                  /* FIXED32 */
+    1,                  /* BOOL */
+    UPB_MAPTYPE_STRING, /* STRING */
+    sizeof(void *),     /* GROUP */
+    sizeof(void *),     /* MESSAGE */
+    UPB_MAPTYPE_STRING, /* BYTES */
+    4,                  /* UINT32 */
+    4,                  /* ENUM */
+    4,                  /* SFIXED32 */
+    8,                  /* SFIXED64 */
+    4,                  /* SINT32 */
+    8,                  /* SINT64 */
+};
+
+static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) |
+                                   (1 << UPB_DTYPE_FIXED32) |
+                                   (1 << UPB_DTYPE_SFIXED32);
+
+static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
+                                   (1 << UPB_DTYPE_FIXED64) |
+                                   (1 << UPB_DTYPE_SFIXED64);
+
+/* Op: an action to be performed for a wire-type/field-type combination. */
+#define OP_SCALAR_LG2(n) (n)      /* n in [0, 2, 3] => op in [0, 2, 3] */
+#define OP_STRING 4
+#define OP_BYTES 5
+#define OP_SUBMSG 6
+/* Ops above are scalar-only. Repeated fields can use any op.  */
+#define OP_FIXPCK_LG2(n) (n + 5)  /* n in [2, 3] => op in [7, 8] */
+#define OP_VARPCK_LG2(n) (n + 9)  /* n in [0, 2, 3] => op in [9, 11, 12] */
+
+static const int8_t varint_ops[19] = {
+    -1,               /* field not found */
+    -1,               /* DOUBLE */
+    -1,               /* FLOAT */
+    OP_SCALAR_LG2(3), /* INT64 */
+    OP_SCALAR_LG2(3), /* UINT64 */
+    OP_SCALAR_LG2(2), /* INT32 */
+    -1,               /* FIXED64 */
+    -1,               /* FIXED32 */
+    OP_SCALAR_LG2(0), /* BOOL */
+    -1,               /* STRING */
+    -1,               /* GROUP */
+    -1,               /* MESSAGE */
+    -1,               /* BYTES */
+    OP_SCALAR_LG2(2), /* UINT32 */
+    OP_SCALAR_LG2(2), /* ENUM */
+    -1,               /* SFIXED32 */
+    -1,               /* SFIXED64 */
+    OP_SCALAR_LG2(2), /* SINT32 */
+    OP_SCALAR_LG2(3), /* SINT64 */
+};
+
+static const int8_t delim_ops[37] = {
+    /* For non-repeated field type. */
+    -1,        /* field not found */
+    -1,        /* DOUBLE */
+    -1,        /* FLOAT */
+    -1,        /* INT64 */
+    -1,        /* UINT64 */
+    -1,        /* INT32 */
+    -1,        /* FIXED64 */
+    -1,        /* FIXED32 */
+    -1,        /* BOOL */
+    OP_STRING, /* STRING */
+    -1,        /* GROUP */
+    OP_SUBMSG, /* MESSAGE */
+    OP_BYTES,  /* BYTES */
+    -1,        /* UINT32 */
+    -1,        /* ENUM */
+    -1,        /* SFIXED32 */
+    -1,        /* SFIXED64 */
+    -1,        /* SINT32 */
+    -1,        /* SINT64 */
+    /* For repeated field type. */
+    OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
+    OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
+    OP_VARPCK_LG2(3), /* REPEATED INT64 */
+    OP_VARPCK_LG2(3), /* REPEATED UINT64 */
+    OP_VARPCK_LG2(2), /* REPEATED INT32 */
+    OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */
+    OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */
+    OP_VARPCK_LG2(0), /* REPEATED BOOL */
+    OP_STRING,        /* REPEATED STRING */
+    OP_SUBMSG,        /* REPEATED GROUP */
+    OP_SUBMSG,        /* REPEATED MESSAGE */
+    OP_BYTES,         /* REPEATED BYTES */
+    OP_VARPCK_LG2(2), /* REPEATED UINT32 */
+    OP_VARPCK_LG2(2), /* REPEATED ENUM */
+    OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
+    OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */
+    OP_VARPCK_LG2(2), /* REPEATED SINT32 */
+    OP_VARPCK_LG2(3), /* REPEATED SINT64 */
+};
+
+typedef union {
+  bool bool_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  uint32_t size;
+} wireval;
+
+static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                              const upb_msglayout *layout);
+
+UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); }
+
+// We don't want to mark this NORETURN, see comment in .h.
+// Unfortunately this code to suppress the warning doesn't appear to be working.
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-warning-option"
+#pragma clang diagnostic ignored "-Wsuggest-attribute"
+#endif
+
+const char *fastdecode_err(upb_decstate *d) {
+  longjmp(d->err, 1);
+  return NULL;
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+const uint8_t upb_utf8_offsets[] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) {
+  if (!decode_verifyutf8_inl(buf, len)) decode_err(d);
+}
+
+static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) {
+  bool need_realloc = arr->size - arr->len < elem;
+  if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, &d->arena)) {
+    decode_err(d);
+  }
+  return need_realloc;
+}
+
+typedef struct {
+  const char *ptr;
+  uint64_t val;
+} decode_vret;
+
+UPB_NOINLINE
+static decode_vret decode_longvarint64(const char *ptr, uint64_t val) {
+  decode_vret ret = {NULL, 0};
+  uint64_t byte;
+  int i;
+  for (i = 1; i < 10; i++) {
+    byte = (uint8_t)ptr[i];
+    val += (byte - 1) << (i * 7);
+    if (!(byte & 0x80)) {
+      ret.ptr = ptr + i + 1;
+      ret.val = val;
+      return ret;
+    }
+  }
+  return ret;
+}
+
+UPB_FORCEINLINE
+static const char *decode_varint64(upb_decstate *d, const char *ptr,
+                                   uint64_t *val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = byte;
+    return ptr + 1;
+  } else {
+    decode_vret res = decode_longvarint64(ptr, byte);
+    if (!res.ptr) decode_err(d);
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char *decode_tag(upb_decstate *d, const char *ptr,
+                                   uint32_t *val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = byte;
+    return ptr + 1;
+  } else {
+    const char *start = ptr;
+    decode_vret res = decode_longvarint64(ptr, byte);
+    ptr = res.ptr;
+    *val = res.val;
+    if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d);
+    return ptr;
+  }
+}
+
+static void decode_munge(int type, wireval *val) {
+  switch (type) {
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      val->bool_val = val->uint64_val != 0;
+      break;
+    case UPB_DESCRIPTOR_TYPE_SINT32: {
+      uint32_t n = val->uint32_val;
+      val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_SINT64: {
+      uint64_t n = val->uint64_val;
+      val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      if (!_upb_isle()) {
+        /* The next stage will memcpy(dst, &val, 4) */
+        val->uint32_val = val->uint64_val;
+      }
+      break;
+  }
+}
+
+static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
+                                                 uint32_t field_number) {
+  static upb_msglayout_field none = {0, 0, 0, 0, 0, 0};
+
+  /* Lots of optimization opportunities here. */
+  int i;
+  if (l == NULL) return &none;
+  for (i = 0; i < l->field_count; i++) {
+    if (l->fields[i].number == field_number) {
+      return &l->fields[i];
+    }
+  }
+
+  return &none; /* Unknown field. */
+}
+
+static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
+                                 const upb_msglayout_field *field) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  return _upb_msg_new_inl(subl, &d->arena);
+}
+
+UPB_NOINLINE
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+                                  int overrun) {
+  ptr = decode_isdonefallback_inl(d, ptr, overrun);
+  if (ptr == NULL) {
+    decode_err(d);
+  }
+  return ptr;
+}
+
+static const char *decode_readstr(upb_decstate *d, const char *ptr, int size,
+                                  upb_strview *str) {
+  if (d->alias) {
+    str->data = ptr;
+  } else {
+    char *data =  upb_arena_malloc(&d->arena, size);
+    if (!data) decode_err(d);
+    memcpy(data, ptr, size);
+    str->data = data;
+  }
+  str->size = size;
+  return ptr + size;
+}
+
+UPB_FORCEINLINE
+static const char *decode_tosubmsg(upb_decstate *d, const char *ptr,
+                                   upb_msg *submsg, const upb_msglayout *layout,
+                                   const upb_msglayout_field *field, int size) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  int saved_delta = decode_pushlimit(d, ptr, size);
+  if (--d->depth < 0) decode_err(d);
+  if (!decode_isdone(d, &ptr)) {
+    ptr = decode_msg(d, ptr, submsg, subl);
+  }
+  if (d->end_group != DECODE_NOGROUP) decode_err(d);
+  decode_poplimit(d, ptr, saved_delta);
+  d->depth++;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *decode_group(upb_decstate *d, const char *ptr,
+                                upb_msg *submsg, const upb_msglayout *subl,
+                                uint32_t number) {
+  if (--d->depth < 0) decode_err(d);
+  if (decode_isdone(d, &ptr)) {
+    decode_err(d);
+  }
+  ptr = decode_msg(d, ptr, submsg, subl);
+  if (d->end_group != number) decode_err(d);
+  d->end_group = DECODE_NOGROUP;
+  d->depth++;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *decode_togroup(upb_decstate *d, const char *ptr,
+                                  upb_msg *submsg, const upb_msglayout *layout,
+                                  const upb_msglayout_field *field) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  return decode_group(d, ptr, submsg, subl, field->number);
+}
+
+static const char *decode_toarray(upb_decstate *d, const char *ptr,
+                                  upb_msg *msg, const upb_msglayout *layout,
+                                  const upb_msglayout_field *field, wireval val,
+                                  int op) {
+  upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
+  upb_array *arr = *arrp;
+  void *mem;
+
+  if (arr) {
+    decode_reserve(d, arr, 1);
+  } else {
+    size_t lg2 = desctype_to_elem_size_lg2[field->descriptortype];
+    arr = _upb_array_new(&d->arena, 4, lg2);
+    if (!arr) decode_err(d);
+    *arrp = arr;
+  }
+
+  switch (op) {
+    case OP_SCALAR_LG2(0):
+    case OP_SCALAR_LG2(2):
+    case OP_SCALAR_LG2(3):
+      /* Append scalar value. */
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
+      arr->len++;
+      memcpy(mem, &val, 1 << op);
+      return ptr;
+    case OP_STRING:
+      decode_verifyutf8(d, ptr, val.size);
+      /* Fallthrough. */
+    case OP_BYTES: {
+      /* Append bytes. */
+      upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len;
+      arr->len++;
+      return decode_readstr(d, ptr, val.size, str);
+    }
+    case OP_SUBMSG: {
+      /* Append submessage / group. */
+      upb_msg *submsg = decode_newsubmsg(d, layout, field);
+      *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
+          submsg;
+      arr->len++;
+      if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
+        return decode_togroup(d, ptr, submsg, layout, field);
+      } else {
+        return decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
+      }
+    }
+    case OP_FIXPCK_LG2(2):
+    case OP_FIXPCK_LG2(3): {
+      /* Fixed packed. */
+      int lg2 = op - OP_FIXPCK_LG2(0);
+      int mask = (1 << lg2) - 1;
+      size_t count = val.size >> lg2;
+      if ((val.size & mask) != 0) {
+        decode_err(d); /* Length isn't a round multiple of elem size. */
+      }
+      decode_reserve(d, arr, count);
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+      arr->len += count;
+      memcpy(mem, ptr, val.size);  /* XXX: ptr boundary. */
+      return ptr + val.size;
+    }
+    case OP_VARPCK_LG2(0):
+    case OP_VARPCK_LG2(2):
+    case OP_VARPCK_LG2(3): {
+      /* Varint packed. */
+      int lg2 = op - OP_VARPCK_LG2(0);
+      int scale = 1 << lg2;
+      int saved_limit = decode_pushlimit(d, ptr, val.size);
+      char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+      while (!decode_isdone(d, &ptr)) {
+        wireval elem;
+        ptr = decode_varint64(d, ptr, &elem.uint64_val);
+        decode_munge(field->descriptortype, &elem);
+        if (decode_reserve(d, arr, 1)) {
+          out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+        }
+        arr->len++;
+        memcpy(out, &elem, scale);
+        out += scale;
+      }
+      decode_poplimit(d, ptr, saved_limit);
+      return ptr;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                const upb_msglayout *layout,
+                                const upb_msglayout_field *field, wireval val) {
+  upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
+  upb_map *map = *map_p;
+  upb_map_entry ent;
+  const upb_msglayout *entry = layout->submsgs[field->submsg_index];
+
+  if (!map) {
+    /* Lazily create map. */
+    const upb_msglayout *entry = layout->submsgs[field->submsg_index];
+    const upb_msglayout_field *key_field = &entry->fields[0];
+    const upb_msglayout_field *val_field = &entry->fields[1];
+    char key_size = desctype_to_mapsize[key_field->descriptortype];
+    char val_size = desctype_to_mapsize[val_field->descriptortype];
+    UPB_ASSERT(key_field->offset == 0);
+    UPB_ASSERT(val_field->offset == sizeof(upb_strview));
+    map = _upb_map_new(&d->arena, key_size, val_size);
+    *map_p = map;
+  }
+
+  /* Parse map entry. */
+  memset(&ent, 0, sizeof(ent));
+
+  if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
+      entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
+    /* Create proactively to handle the case where it doesn't appear. */
+    ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena));
+  }
+
+  ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size);
+  _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
+  return ptr;
+}
+
+static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                const upb_msglayout *layout,
+                                const upb_msglayout_field *field, wireval val,
+                                int op) {
+  void *mem = UPB_PTR_AT(msg, field->offset, void);
+  int type = field->descriptortype;
+
+  /* Set presence if necessary. */
+  if (field->presence < 0) {
+    /* Oneof case */
+    uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
+    if (op == OP_SUBMSG && *oneof_case != field->number) {
+      memset(mem, 0, sizeof(void*));
+    }
+    *oneof_case = field->number;
+  } else if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  }
+
+  /* Store into message. */
+  switch (op) {
+    case OP_SUBMSG: {
+      upb_msg **submsgp = mem;
+      upb_msg *submsg = *submsgp;
+      if (!submsg) {
+        submsg = decode_newsubmsg(d, layout, field);
+        *submsgp = submsg;
+      }
+      if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
+        ptr = decode_togroup(d, ptr, submsg, layout, field);
+      } else {
+        ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
+      }
+      break;
+    }
+    case OP_STRING:
+      decode_verifyutf8(d, ptr, val.size);
+      /* Fallthrough. */
+    case OP_BYTES:
+      return decode_readstr(d, ptr, val.size, mem);
+    case OP_SCALAR_LG2(3):
+      memcpy(mem, &val, 8);
+      break;
+    case OP_SCALAR_LG2(2):
+      memcpy(mem, &val, 4);
+      break;
+    case OP_SCALAR_LG2(0):
+      memcpy(mem, &val, 1);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr,
+                                   upb_msg *msg, const upb_msglayout *layout) {
+#if UPB_FASTTABLE
+  if (layout && layout->table_mask != (unsigned char)-1) {
+    uint16_t tag = fastdecode_loadtag(*ptr);
+    intptr_t table = decode_totable(layout);
+    *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag);
+    return true;
+  }
+#endif
+  return false;
+}
+
+UPB_NOINLINE
+static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                              const upb_msglayout *layout) {
+  while (true) {
+    uint32_t tag;
+    const upb_msglayout_field *field;
+    int field_number;
+    int wire_type;
+    const char *field_start = ptr;
+    wireval val;
+    int op;
+
+    UPB_ASSERT(ptr < d->limit_ptr);
+    ptr = decode_tag(d, ptr, &tag);
+    field_number = tag >> 3;
+    wire_type = tag & 7;
+
+    field = upb_find_field(layout, field_number);
+
+    switch (wire_type) {
+      case UPB_WIRE_TYPE_VARINT:
+        ptr = decode_varint64(d, ptr, &val.uint64_val);
+        op = varint_ops[field->descriptortype];
+        decode_munge(field->descriptortype, &val);
+        break;
+      case UPB_WIRE_TYPE_32BIT:
+        memcpy(&val.uint32_val, ptr, 4);
+        val.uint32_val = _upb_be_swap32(val.uint32_val);
+        ptr += 4;
+        op = OP_SCALAR_LG2(2);
+        if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_64BIT:
+        memcpy(&val.uint64_val, ptr, 8);
+        val.uint64_val = _upb_be_swap64(val.uint64_val);
+        ptr += 8;
+        op = OP_SCALAR_LG2(3);
+        if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_DELIMITED: {
+        int ndx = field->descriptortype;
+        uint64_t size;
+        if (_upb_isrepeated(field)) ndx += 18;
+        ptr = decode_varint64(d, ptr, &size);
+        if (size >= INT32_MAX ||
+            ptr - d->end + (int32_t)size > d->limit) {
+          decode_err(d); /* Length overflow. */
+        }
+        op = delim_ops[ndx];
+        val.size = size;
+        break;
+      }
+      case UPB_WIRE_TYPE_START_GROUP:
+        val.uint32_val = field_number;
+        op = OP_SUBMSG;
+        if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_END_GROUP:
+        d->end_group = field_number;
+        return ptr;
+      default:
+        decode_err(d);
+    }
+
+    if (op >= 0) {
+      /* Parse, using op for dispatch. */
+      switch (field->label) {
+        case UPB_LABEL_REPEATED:
+        case _UPB_LABEL_PACKED:
+          ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
+          break;
+        case _UPB_LABEL_MAP:
+          ptr = decode_tomap(d, ptr, msg, layout, field, val);
+          break;
+        default:
+          ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
+          break;
+      }
+    } else {
+    unknown:
+      /* Skip unknown field. */
+      if (field_number == 0) decode_err(d);
+      if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size;
+      if (msg) {
+        if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+          d->unknown = field_start;
+          d->unknown_msg = msg;
+          ptr = decode_group(d, ptr, NULL, NULL, field_number);
+          d->unknown_msg = NULL;
+          field_start = d->unknown;
+        }
+        if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
+                                 &d->arena)) {
+          decode_err(d);
+        }
+      } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+        ptr = decode_group(d, ptr, NULL, NULL, field_number);
+      }
+    }
+
+    if (decode_isdone(d, &ptr)) return ptr;
+    if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr;
+  }
+}
+
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+                               upb_msg *msg, intptr_t table, uint64_t hasbits,
+                               uint64_t data) {
+  (void)data;
+  *(uint32_t*)msg |= hasbits;
+  return decode_msg(d, ptr, msg, decode_totablep(table));
+}
+
+static bool decode_top(struct upb_decstate *d, const char *buf, void *msg,
+                       const upb_msglayout *l) {
+  if (!decode_tryfastdispatch(d, &buf, msg, l)) {
+    decode_msg(d, buf, msg, l);
+  }
+  return d->end_group == DECODE_NOGROUP;
+}
+
+bool _upb_decode(const char *buf, size_t size, void *msg,
+                 const upb_msglayout *l, upb_arena *arena, int options) {
+  bool ok;
+  upb_decstate state;
+  unsigned depth = (unsigned)options >> 16;
+
+  if (size == 0) {
+    return true;
+  } else if (size <= 16) {
+    memset(&state.patch, 0, 32);
+    memcpy(&state.patch, buf, size);
+    buf = state.patch;
+    state.end = buf + size;
+    state.limit = 0;
+    state.alias = false;
+  } else {
+    state.end = buf + size - 16;
+    state.limit = 16;
+    state.alias = options & UPB_DECODE_ALIAS;
+  }
+
+  state.limit_ptr = state.end;
+  state.unknown_msg = NULL;
+  state.depth = depth ? depth : 64;
+  state.end_group = DECODE_NOGROUP;
+  state.arena.head = arena->head;
+  state.arena.last_size = arena->last_size;
+  state.arena.cleanup_metadata = arena->cleanup_metadata;
+  state.arena.parent = arena;
+
+  if (UPB_UNLIKELY(UPB_SETJMP(state.err))) {
+    ok = false;
+  } else {
+    ok = decode_top(&state, buf, msg, l);
+  }
+
+  arena->head.ptr = state.arena.head.ptr;
+  arena->head.end = state.arena.head.end;
+  arena->cleanup_metadata = state.arena.cleanup_metadata;
+  return ok;
+}
+
+#undef OP_SCALAR_LG2
+#undef OP_FIXPCK_LG2
+#undef OP_VARPCK_LG2
+#undef OP_STRING
+#undef OP_SUBMSG
+
+/** upb/encode.c ************************************************************/
+/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
+
+
+#include <setjmp.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+#define UPB_PB_VARINT_MAX_LEN 10
+
+UPB_NOINLINE
+static size_t encode_varint64(uint64_t val, char *buf) {
+  size_t i = 0;
+  do {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    buf[i++] = byte;
+  } while (val);
+  return i;
+}
+
+static uint32_t encode_zz32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
+static uint64_t encode_zz64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
+
+typedef struct {
+  jmp_buf err;
+  upb_alloc *alloc;
+  char *buf, *ptr, *limit;
+  int options;
+  int depth;
+  _upb_mapsorter sorter;
+} upb_encstate;
+
+static size_t upb_roundup_pow2(size_t bytes) {
+  size_t ret = 128;
+  while (ret < bytes) {
+    ret *= 2;
+  }
+  return ret;
+}
+
+UPB_NORETURN static void encode_err(upb_encstate *e) {
+  UPB_LONGJMP(e->err, 1);
+}
+
+UPB_NOINLINE
+static void encode_growbuffer(upb_encstate *e, size_t bytes) {
+  size_t old_size = e->limit - e->buf;
+  size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
+  char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
+
+  if (!new_buf) encode_err(e);
+
+  /* We want previous data at the end, realloc() put it at the beginning. */
+  if (old_size > 0) {
+    memmove(new_buf + new_size - old_size, e->buf, old_size);
+  }
+
+  e->ptr = new_buf + new_size - (e->limit - e->ptr);
+  e->limit = new_buf + new_size;
+  e->buf = new_buf;
+
+  e->ptr -= bytes;
+}
+
+/* Call to ensure that at least "bytes" bytes are available for writing at
+ * e->ptr.  Returns false if the bytes could not be allocated. */
+UPB_FORCEINLINE
+static void encode_reserve(upb_encstate *e, size_t bytes) {
+  if ((size_t)(e->ptr - e->buf) < bytes) {
+    encode_growbuffer(e, bytes);
+    return;
+  }
+
+  e->ptr -= bytes;
+}
+
+/* Writes the given bytes to the buffer, handling reserve/advance. */
+static void encode_bytes(upb_encstate *e, const void *data, size_t len) {
+  if (len == 0) return;  /* memcpy() with zero size is UB */
+  encode_reserve(e, len);
+  memcpy(e->ptr, data, len);
+}
+
+static void encode_fixed64(upb_encstate *e, uint64_t val) {
+  val = _upb_be_swap64(val);
+  encode_bytes(e, &val, sizeof(uint64_t));
+}
+
+static void encode_fixed32(upb_encstate *e, uint32_t val) {
+  val = _upb_be_swap32(val);
+  encode_bytes(e, &val, sizeof(uint32_t));
+}
+
+UPB_NOINLINE
+static void encode_longvarint(upb_encstate *e, uint64_t val) {
+  size_t len;
+  char *start;
+
+  encode_reserve(e, UPB_PB_VARINT_MAX_LEN);
+  len = encode_varint64(val, e->ptr);
+  start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
+  memmove(start, e->ptr, len);
+  e->ptr = start;
+}
+
+UPB_FORCEINLINE
+static void encode_varint(upb_encstate *e, uint64_t val) {
+  if (val < 128 && e->ptr != e->buf) {
+    --e->ptr;
+    *e->ptr = val;
+  } else {
+    encode_longvarint(e, val);
+  }
+}
+
+static void encode_double(upb_encstate *e, double d) {
+  uint64_t u64;
+  UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
+  memcpy(&u64, &d, sizeof(uint64_t));
+  encode_fixed64(e, u64);
+}
+
+static void encode_float(upb_encstate *e, float d) {
+  uint32_t u32;
+  UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
+  memcpy(&u32, &d, sizeof(uint32_t));
+  encode_fixed32(e, u32);
+}
+
+static void encode_tag(upb_encstate *e, uint32_t field_number,
+                       uint8_t wire_type) {
+  encode_varint(e, (field_number << 3) | wire_type);
+}
+
+static void encode_fixedarray(upb_encstate *e, const upb_array *arr,
+                               size_t elem_size, uint32_t tag) {
+  size_t bytes = arr->len * elem_size;
+  const char* data = _upb_array_constptr(arr);
+  const char* ptr = data + bytes - elem_size;
+  if (tag) {
+    while (true) {
+      encode_bytes(e, ptr, elem_size);
+      encode_varint(e, tag);
+      if (ptr == data) break;
+      ptr -= elem_size;
+    }
+  } else {
+    encode_bytes(e, data, bytes);
+  }
+}
+
+static void encode_message(upb_encstate *e, const char *msg,
+                           const upb_msglayout *m, size_t *size);
+
+static void encode_scalar(upb_encstate *e, const void *_field_mem,
+                          const upb_msglayout *m, const upb_msglayout_field *f,
+                          bool skip_zero_value) {
+  const char *field_mem = _field_mem;
+  int wire_type;
+
+#define CASE(ctype, type, wtype, encodeval) \
+  {                                         \
+    ctype val = *(ctype *)field_mem;        \
+    if (skip_zero_value && val == 0) {      \
+      return;                               \
+    }                                       \
+    encode_##type(e, encodeval);            \
+    wire_type = wtype;                      \
+    break;                                  \
+  }
+
+  switch (f->descriptortype) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+      CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+      CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz32(val));
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz64(val));
+    case UPB_DESCRIPTOR_TYPE_STRING:
+    case UPB_DESCRIPTOR_TYPE_BYTES: {
+      upb_strview view = *(upb_strview*)field_mem;
+      if (skip_zero_value && view.size == 0) {
+        return;
+      }
+      encode_bytes(e, view.data, view.size);
+      encode_varint(e, view.size);
+      wire_type = UPB_WIRE_TYPE_DELIMITED;
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_GROUP: {
+      size_t size;
+      void *submsg = *(void **)field_mem;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e);
+      encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+      encode_message(e, submsg, subm, &size);
+      wire_type = UPB_WIRE_TYPE_START_GROUP;
+      e->depth++;
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
+      size_t size;
+      void *submsg = *(void **)field_mem;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e);
+      encode_message(e, submsg, subm, &size);
+      encode_varint(e, size);
+      wire_type = UPB_WIRE_TYPE_DELIMITED;
+      e->depth++;
+      break;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+#undef CASE
+
+  encode_tag(e, f->number, wire_type);
+}
+
+static void encode_array(upb_encstate *e, const char *field_mem,
+                         const upb_msglayout *m, const upb_msglayout_field *f) {
+  const upb_array *arr = *(const upb_array**)field_mem;
+  bool packed = f->label == _UPB_LABEL_PACKED;
+  size_t pre_len = e->limit - e->ptr;
+
+  if (arr == NULL || arr->len == 0) {
+    return;
+  }
+
+#define VARINT_CASE(ctype, encode)                                       \
+  {                                                                      \
+    const ctype *start = _upb_array_constptr(arr);                       \
+    const ctype *ptr = start + arr->len;                                 \
+    uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
+    do {                                                                 \
+      ptr--;                                                             \
+      encode_varint(e, encode);                                          \
+      if (tag) encode_varint(e, tag);                                    \
+    } while (ptr != start);                                              \
+  }                                                                      \
+  break;
+
+#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
+
+  switch (f->descriptortype) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      encode_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      encode_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      encode_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+      encode_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+      VARINT_CASE(uint64_t, *ptr);
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      VARINT_CASE(uint32_t, *ptr);
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      VARINT_CASE(int32_t, (int64_t)*ptr);
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      VARINT_CASE(bool, *ptr);
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      VARINT_CASE(int32_t, encode_zz32(*ptr));
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      VARINT_CASE(int64_t, encode_zz64(*ptr));
+    case UPB_DESCRIPTOR_TYPE_STRING:
+    case UPB_DESCRIPTOR_TYPE_BYTES: {
+      const upb_strview *start = _upb_array_constptr(arr);
+      const upb_strview *ptr = start + arr->len;
+      do {
+        ptr--;
+        encode_bytes(e, ptr->data, ptr->size);
+        encode_varint(e, ptr->size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+      } while (ptr != start);
+      return;
+    }
+    case UPB_DESCRIPTOR_TYPE_GROUP: {
+      const void *const*start = _upb_array_constptr(arr);
+      const void *const*ptr = start + arr->len;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (--e->depth == 0) encode_err(e);
+      do {
+        size_t size;
+        ptr--;
+        encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+        encode_message(e, *ptr, subm, &size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
+      const void *const*start = _upb_array_constptr(arr);
+      const void *const*ptr = start + arr->len;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (--e->depth == 0) encode_err(e);
+      do {
+        size_t size;
+        ptr--;
+        encode_message(e, *ptr, subm, &size);
+        encode_varint(e, size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+  }
+#undef VARINT_CASE
+
+  if (packed) {
+    encode_varint(e, e->limit - e->ptr - pre_len);
+    encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+  }
+}
+
+static void encode_mapentry(upb_encstate *e, uint32_t number,
+                            const upb_msglayout *layout,
+                            const upb_map_entry *ent) {
+  const upb_msglayout_field *key_field = &layout->fields[0];
+  const upb_msglayout_field *val_field = &layout->fields[1];
+  size_t pre_len = e->limit - e->ptr;
+  size_t size;
+  encode_scalar(e, &ent->v, layout, val_field, false);
+  encode_scalar(e, &ent->k, layout, key_field, false);
+  size = (e->limit - e->ptr) - pre_len;
+  encode_varint(e, size);
+  encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED);
+}
+
+static void encode_map(upb_encstate *e, const char *field_mem,
+                       const upb_msglayout *m, const upb_msglayout_field *f) {
+  const upb_map *map = *(const upb_map**)field_mem;
+  const upb_msglayout *layout = m->submsgs[f->submsg_index];
+  UPB_ASSERT(layout->field_count == 2);
+
+  if (map == NULL) return;
+
+  if (e->options & UPB_ENCODE_DETERMINISTIC) {
+    _upb_sortedmap sorted;
+    _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
+                           &sorted);
+    upb_map_entry ent;
+    while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+    _upb_mapsorter_popmap(&e->sorter, &sorted);
+  } else {
+    upb_strtable_iter i;
+    upb_strtable_begin(&i, &map->table);
+    for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+      upb_strview key = upb_strtable_iter_key(&i);
+      const upb_value val = upb_strtable_iter_value(&i);
+      upb_map_entry ent;
+      _upb_map_fromkey(key, &ent.k, map->key_size);
+      _upb_map_fromvalue(val, &ent.v, map->val_size);
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+  }
+}
+
+static void encode_scalarfield(upb_encstate *e, const char *msg,
+                               const upb_msglayout *m,
+                               const upb_msglayout_field *f) {
+  bool skip_empty = false;
+  if (f->presence == 0) {
+    /* Proto3 presence. */
+    skip_empty = true;
+  } else if (f->presence > 0) {
+    /* Proto2 presence: hasbit. */
+    if (!_upb_hasbit_field(msg, f)) return;
+  } else {
+    /* Field is in a oneof. */
+    if (_upb_getoneofcase_field(msg, f) != f->number) return;
+  }
+  encode_scalar(e, msg + f->offset, m, f, skip_empty);
+}
+
+static void encode_message(upb_encstate *e, const char *msg,
+                           const upb_msglayout *m, size_t *size) {
+  size_t pre_len = e->limit - e->ptr;
+  const upb_msglayout_field *f = &m->fields[m->field_count];
+  const upb_msglayout_field *first = &m->fields[0];
+
+  if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) {
+    size_t unknown_size;
+    const char *unknown = upb_msg_getunknown(msg, &unknown_size);
+
+    if (unknown) {
+      encode_bytes(e, unknown, unknown_size);
+    }
+  }
+
+  while (f != first) {
+    f--;
+    if (_upb_isrepeated(f)) {
+      encode_array(e, msg + f->offset, m, f);
+    } else if (f->label == _UPB_LABEL_MAP) {
+      encode_map(e, msg + f->offset, m, f);
+    } else {
+      encode_scalarfield(e, msg, m, f);
+    }
+  }
+
+  *size = (e->limit - e->ptr) - pre_len;
+}
+
+char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
+                    upb_arena *arena, size_t *size) {
+  upb_encstate e;
+  unsigned depth = (unsigned)options >> 16;
+
+  e.alloc = upb_arena_alloc(arena);
+  e.buf = NULL;
+  e.limit = NULL;
+  e.ptr = NULL;
+  e.depth = depth ? depth : 64;
+  e.options = options;
+  _upb_mapsorter_init(&e.sorter);
+  char *ret = NULL;
+
+  if (UPB_SETJMP(e.err)) {
+    *size = 0;
+    ret = NULL;
+  } else {
+    encode_message(&e, msg, l, size);
+    *size = e.limit - e.ptr;
+    if (*size == 0) {
+      static char ch;
+      ret = &ch;
+    } else {
+      UPB_ASSERT(e.ptr);
+      ret = e.ptr;
+    }
+  }
+
+  _upb_mapsorter_destroy(&e.sorter);
+  return ret;
+}
+
+/** upb/msg.c ************************************************************/
+
+
+/** upb_msg *******************************************************************/
+
+static const size_t overhead = sizeof(upb_msg_internal);
+
+static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
+  ptrdiff_t size = sizeof(upb_msg_internal);
+  return (upb_msg_internal*)((char*)msg - size);
+}
+
+upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
+  return _upb_msg_new_inl(l, a);
+}
+
+void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) {
+  void *mem = UPB_PTR_AT(msg, -sizeof(upb_msg_internal), char);
+  memset(mem, 0, upb_msg_sizeof(l));
+}
+
+bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                         upb_arena *arena) {
+
+  upb_msg_internal *in = upb_msg_getinternal(msg);
+  if (!in->unknown) {
+    size_t size = 128;
+    while (size < len) size *= 2;
+    in->unknown = upb_arena_malloc(arena, size + overhead);
+    if (!in->unknown) return false;
+    in->unknown->size = size;
+    in->unknown->len = 0;
+  } else if (in->unknown->size - in->unknown->len < len) {
+    size_t need = in->unknown->len + len;
+    size_t size = in->unknown->size;
+    while (size < need)  size *= 2;
+    in->unknown = upb_arena_realloc(
+        arena, in->unknown, in->unknown->size + overhead, size + overhead);
+    if (!in->unknown) return false;
+    in->unknown->size = size;
+  }
+  memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len);
+  in->unknown->len += len;
+  return true;
+}
+
+void _upb_msg_discardunknown_shallow(upb_msg *msg) {
+  upb_msg_internal *in = upb_msg_getinternal(msg);
+  if (in->unknown) {
+    in->unknown->len = 0;
+  }
+}
+
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
+  const upb_msg_internal *in = upb_msg_getinternal_const(msg);
+  if (in->unknown) {
+    *len = in->unknown->len;
+    return (char*)(in->unknown + 1);
+  } else {
+    *len = 0;
+    return NULL;
+  }
+}
+
+/** upb_array *****************************************************************/
+
+bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
+  size_t new_size = UPB_MAX(arr->size, 4);
+  int elem_size_lg2 = arr->data & 7;
+  size_t old_bytes = arr->size << elem_size_lg2;
+  size_t new_bytes;
+  void* ptr = _upb_array_ptr(arr);
+
+  /* Log2 ceiling of size. */
+  while (new_size < min_size) new_size *= 2;
+
+  new_bytes = new_size << elem_size_lg2;
+  ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes);
+
+  if (!ptr) {
+    return false;
+  }
+
+  arr->data = _upb_tag_arrptr(ptr, elem_size_lg2);
+  arr->size = new_size;
+  return true;
+}
+
+static upb_array *getorcreate_array(upb_array **arr_ptr, int elem_size_lg2,
+                                    upb_arena *arena) {
+  upb_array *arr = *arr_ptr;
+  if (!arr) {
+    arr = _upb_array_new(arena, 4, elem_size_lg2);
+    if (!arr) return NULL;
+    *arr_ptr = arr;
+  }
+  return arr;
+}
+
+void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
+                                 int elem_size_lg2, upb_arena *arena) {
+  upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+  return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr)
+                                                    : NULL;
+}
+
+bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
+                                int elem_size_lg2, upb_arena *arena) {
+  upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+  if (!arr) return false;
+
+  size_t elems = arr->len;
+
+  if (!_upb_array_resize(arr, elems + 1, arena)) {
+    return false;
+  }
+
+  char *data = _upb_array_ptr(arr);
+  memcpy(data + (elems << elem_size_lg2), value, 1 << elem_size_lg2);
+  return true;
+}
+
+/** upb_map *******************************************************************/
+
+upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
+  upb_map *map = upb_arena_malloc(a, sizeof(upb_map));
+
+  if (!map) {
+    return NULL;
+  }
+
+  upb_strtable_init(&map->table, 4, a);
+  map->key_size = key_size;
+  map->val_size = value_size;
+
+  return map;
+}
+
+static void _upb_mapsorter_getkeys(const void *_a, const void *_b, void *a_key,
+                                   void *b_key, size_t size) {
+  const upb_tabent *const*a = _a;
+  const upb_tabent *const*b = _b;
+  upb_strview a_tabkey = upb_tabstrview((*a)->key);
+  upb_strview b_tabkey = upb_tabstrview((*b)->key);
+  _upb_map_fromkey(a_tabkey, a_key, size);
+  _upb_map_fromkey(b_tabkey, b_key, size);
+}
+
+static int _upb_mapsorter_cmpi64(const void *_a, const void *_b) {
+  int64_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpu64(const void *_a, const void *_b) {
+  uint64_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpi32(const void *_a, const void *_b) {
+  int32_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpu32(const void *_a, const void *_b) {
+  uint32_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpbool(const void *_a, const void *_b) {
+  bool a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 1);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpstr(const void *_a, const void *_b) {
+  upb_strview a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING);
+  size_t common_size = UPB_MIN(a.size, b.size);
+  int cmp = memcmp(a.data, b.data, common_size);
+  if (cmp) return cmp;
+  return a.size - b.size;
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+                            const upb_map *map, _upb_sortedmap *sorted) {
+  int map_size = _upb_map_size(map);
+  sorted->start = s->size;
+  sorted->pos = sorted->start;
+  sorted->end = sorted->start + map_size;
+
+  /* Grow s->entries if necessary. */
+  if (sorted->end > s->cap) {
+    s->cap = _upb_lg2ceilsize(sorted->end);
+    s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
+    if (!s->entries) return false;
+  }
+
+  s->size = sorted->end;
+
+  /* Copy non-empty entries from the table to s->entries. */
+  upb_tabent const**dst = &s->entries[sorted->start];
+  const upb_tabent *src = map->table.t.entries;
+  const upb_tabent *end = src + upb_table_size(&map->table.t);
+  for (; src < end; src++) {
+    if (!upb_tabent_isempty(src)) {
+      *dst = src;
+      dst++;
+    }
+  }
+  UPB_ASSERT(dst == &s->entries[sorted->end]);
+
+  /* Sort entries according to the key type. */
+
+  int (*compar)(const void *, const void *);
+
+  switch (key_type) {
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      compar = _upb_mapsorter_cmpi64;
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      compar = _upb_mapsorter_cmpu64;
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      compar = _upb_mapsorter_cmpi32;
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      compar = _upb_mapsorter_cmpu32;
+      break;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      compar = _upb_mapsorter_cmpbool;
+      break;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      compar = _upb_mapsorter_cmpstr;
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
+  return true;
+}
+
+/** upb/table.c ************************************************************/
+/*
+ * upb_table Implementation
+ *
+ * Implementation is heavily inspired by Lua's ltable.c.
+ */
+
+#include <string.h>
+
+#include "third_party/wyhash/wyhash.h"
+
+/* Must be last. */
+
+#define UPB_MAXARRSIZE 16  /* 64k. */
+
+/* From Chromium. */
+#define ARRAY_SIZE(x) \
+    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
+
+static const double MAX_LOAD = 0.85;
+
+/* The minimum utilization of the array part of a mixed hash/array table.  This
+ * is a speed/memory-usage tradeoff (though it's not straightforward because of
+ * cache effects).  The lower this is, the more memory we'll use. */
+static const double MIN_DENSITY = 0.1;
+
+static bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
+
+static upb_value _upb_value_val(uint64_t val) {
+  upb_value ret;
+  _upb_value_setval(&ret, val);
+  return ret;
+}
+
+static int log2ceil(uint64_t v) {
+  int ret = 0;
+  bool pow2 = is_pow2(v);
+  while (v >>= 1) ret++;
+  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
+  return UPB_MIN(UPB_MAXARRSIZE, ret);
+}
+
+char *upb_strdup2(const char *s, size_t len, upb_arena *a) {
+  size_t n;
+  char *p;
+
+  /* Prevent overflow errors. */
+  if (len == SIZE_MAX) return NULL;
+  /* Always null-terminate, even if binary data; but don't rely on the input to
+   * have a null-terminating byte since it may be a raw binary buffer. */
+  n = len + 1;
+  p = upb_arena_malloc(a, n);
+  if (p) {
+    memcpy(p, s, len);
+    p[len] = 0;
+  }
+  return p;
+}
+
+/* A type to represent the lookup key of either a strtable or an inttable. */
+typedef union {
+  uintptr_t num;
+  struct {
+    const char *str;
+    size_t len;
+  } str;
+} lookupkey_t;
+
+static lookupkey_t strkey2(const char *str, size_t len) {
+  lookupkey_t k;
+  k.str.str = str;
+  k.str.len = len;
+  return k;
+}
+
+static lookupkey_t intkey(uintptr_t key) {
+  lookupkey_t k;
+  k.num = key;
+  return k;
+}
+
+typedef uint32_t hashfunc_t(upb_tabkey key);
+typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
+
+/* Base table (shared code) ***************************************************/
+
+static uint32_t upb_inthash(uintptr_t key) {
+  return (uint32_t)key;
+}
+
+static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
+  return t->entries + (hash & t->mask);
+}
+
+static bool upb_arrhas(upb_tabval key) {
+  return key.val != (uint64_t)-1;
+}
+
+
+static bool isfull(upb_table *t) {
+  return t->count == t->max_count;
+}
+
+static bool init(upb_table *t, uint8_t size_lg2, upb_arena *a) {
+  size_t bytes;
+
+  t->count = 0;
+  t->size_lg2 = size_lg2;
+  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
+  t->max_count = upb_table_size(t) * MAX_LOAD;
+  bytes = upb_table_size(t) * sizeof(upb_tabent);
+  if (bytes > 0) {
+    t->entries = upb_arena_malloc(a, bytes);
+    if (!t->entries) return false;
+    memset(t->entries, 0, bytes);
+  } else {
+    t->entries = NULL;
+  }
+  return true;
+}
+
+static upb_tabent *emptyent(upb_table *t, upb_tabent *e) {
+  upb_tabent *begin = t->entries;
+  upb_tabent *end = begin + upb_table_size(t);
+  for (e = e + 1; e < end; e++) {
+    if (upb_tabent_isempty(e)) return e;
+  }
+  for (e = begin; e < end; e++) {
+    if (upb_tabent_isempty(e)) return e;
+  }
+  UPB_ASSERT(false);
+  return NULL;
+}
+
+static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
+  return (upb_tabent*)upb_getentry(t, hash);
+}
+
+static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
+                                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e;
+
+  if (t->size_lg2 == 0) return NULL;
+  e = upb_getentry(t, hash);
+  if (upb_tabent_isempty(e)) return NULL;
+  while (1) {
+    if (eql(e->key, key)) return e;
+    if ((e = e->next) == NULL) return NULL;
+  }
+}
+
+static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
+                                     uint32_t hash, eqlfunc_t *eql) {
+  return (upb_tabent*)findentry(t, key, hash, eql);
+}
+
+static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
+                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e = findentry(t, key, hash, eql);
+  if (e) {
+    if (v) {
+      _upb_value_setval(v, e->val.val);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* The given key must not already exist in the table. */
+static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
+                   upb_value val, uint32_t hash,
+                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
+  upb_tabent *mainpos_e;
+  upb_tabent *our_e;
+
+  UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
+
+  t->count++;
+  mainpos_e = getentry_mutable(t, hash);
+  our_e = mainpos_e;
+
+  if (upb_tabent_isempty(mainpos_e)) {
+    /* Our main position is empty; use it. */
+    our_e->next = NULL;
+  } else {
+    /* Collision. */
+    upb_tabent *new_e = emptyent(t, mainpos_e);
+    /* Head of collider's chain. */
+    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
+    if (chain == mainpos_e) {
+      /* Existing ent is in its main position (it has the same hash as us, and
+       * is the head of our chain).  Insert to new ent and append to this chain. */
+      new_e->next = mainpos_e->next;
+      mainpos_e->next = new_e;
+      our_e = new_e;
+    } else {
+      /* Existing ent is not in its main position (it is a node in some other
+       * chain).  This implies that no existing ent in the table has our hash.
+       * Evict it (updating its chain) and use its ent for head of our chain. */
+      *new_e = *mainpos_e;  /* copies next. */
+      while (chain->next != mainpos_e) {
+        chain = (upb_tabent*)chain->next;
+        UPB_ASSERT(chain);
+      }
+      chain->next = new_e;
+      our_e = mainpos_e;
+      our_e->next = NULL;
+    }
+  }
+  our_e->key = tabkey;
+  our_e->val.val = val.val;
+  UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
+}
+
+static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
+               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
+  upb_tabent *chain = getentry_mutable(t, hash);
+  if (upb_tabent_isempty(chain)) return false;
+  if (eql(chain->key, key)) {
+    /* Element to remove is at the head of its chain. */
+    t->count--;
+    if (val) _upb_value_setval(val, chain->val.val);
+    if (removed) *removed = chain->key;
+    if (chain->next) {
+      upb_tabent *move = (upb_tabent*)chain->next;
+      *chain = *move;
+      move->key = 0;  /* Make the slot empty. */
+    } else {
+      chain->key = 0;  /* Make the slot empty. */
+    }
+    return true;
+  } else {
+    /* Element to remove is either in a non-head position or not in the
+     * table. */
+    while (chain->next && !eql(chain->next->key, key)) {
+      chain = (upb_tabent*)chain->next;
+    }
+    if (chain->next) {
+      /* Found element to remove. */
+      upb_tabent *rm = (upb_tabent*)chain->next;
+      t->count--;
+      if (val) _upb_value_setval(val, chain->next->val.val);
+      if (removed) *removed = rm->key;
+      rm->key = 0;  /* Make the slot empty. */
+      chain->next = rm->next;
+      return true;
+    } else {
+      /* Element to remove is not in the table. */
+      return false;
+    }
+  }
+}
+
+static size_t next(const upb_table *t, size_t i) {
+  do {
+    if (++i >= upb_table_size(t))
+      return SIZE_MAX - 1;  /* Distinct from -1. */
+  } while(upb_tabent_isempty(&t->entries[i]));
+
+  return i;
+}
+
+static size_t begin(const upb_table *t) {
+  return next(t, -1);
+}
+
+
+/* upb_strtable ***************************************************************/
+
+/* A simple "subclass" of upb_table that only adds a hash function for strings. */
+
+static upb_tabkey strcopy(lookupkey_t k2, upb_arena *a) {
+  uint32_t len = (uint32_t) k2.str.len;
+  char *str = upb_arena_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
+  if (str == NULL) return 0;
+  memcpy(str, &len, sizeof(uint32_t));
+  if (k2.str.len) memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
+  str[sizeof(uint32_t) + k2.str.len] = '\0';
+  return (uintptr_t)str;
+}
+
+static uint32_t table_hash(const char *p, size_t n) {
+  return wyhash(p, n, 0, _wyp);
+}
+
+static uint32_t strhash(upb_tabkey key) {
+  uint32_t len;
+  char *str = upb_tabstr(key, &len);
+  return table_hash(str, len);
+}
+
+static bool streql(upb_tabkey k1, lookupkey_t k2) {
+  uint32_t len;
+  char *str = upb_tabstr(k1, &len);
+  return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0);
+}
+
+bool upb_strtable_init(upb_strtable *t, size_t expected_size, upb_arena *a) {
+  // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2 denominator.
+  size_t need_entries = (expected_size + 1) * 1204 / 1024;
+  UPB_ASSERT(need_entries >= expected_size * 0.85);
+  int size_lg2 = _upb_lg2ceil(need_entries);
+  return init(&t->t, size_lg2, a);
+}
+
+void upb_strtable_clear(upb_strtable *t) {
+  size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
+  t->t.count = 0;
+  memset((char*)t->t.entries, 0, bytes);
+}
+
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_arena *a) {
+  upb_strtable new_table;
+  upb_strtable_iter i;
+
+  if (!init(&new_table.t, size_lg2, a))
+    return false;
+  upb_strtable_begin(&i, t);
+  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+    upb_strview key = upb_strtable_iter_key(&i);
+    upb_strtable_insert(&new_table, key.data, key.size,
+                        upb_strtable_iter_value(&i), a);
+  }
+  *t = new_table;
+  return true;
+}
+
+bool upb_strtable_insert(upb_strtable *t, const char *k, size_t len,
+                         upb_value v, upb_arena *a) {
+  lookupkey_t key;
+  upb_tabkey tabkey;
+  uint32_t hash;
+
+  if (isfull(&t->t)) {
+    /* Need to resize.  New table of double the size, add old elements to it. */
+    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
+      return false;
+    }
+  }
+
+  key = strkey2(k, len);
+  tabkey = strcopy(key, a);
+  if (tabkey == 0) return false;
+
+  hash = table_hash(key.str.str, key.str.len);
+  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
+  return true;
+}
+
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v) {
+  uint32_t hash = table_hash(key, len);
+  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
+}
+
+bool upb_strtable_remove(upb_strtable *t, const char *key, size_t len,
+                         upb_value *val) {
+  uint32_t hash = table_hash(key, len);
+  upb_tabkey tabkey;
+  return rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql);
+}
+
+/* Iteration */
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
+  i->t = t;
+  i->index = begin(&t->t);
+}
+
+void upb_strtable_next(upb_strtable_iter *i) {
+  i->index = next(&i->t->t, i->index);
+}
+
+bool upb_strtable_done(const upb_strtable_iter *i) {
+  if (!i->t) return true;
+  return i->index >= upb_table_size(&i->t->t) ||
+         upb_tabent_isempty(str_tabent(i));
+}
+
+upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) {
+  upb_strview key;
+  uint32_t len;
+  UPB_ASSERT(!upb_strtable_done(i));
+  key.data = upb_tabstr(str_tabent(i)->key, &len);
+  key.size = len;
+  return key;
+}
+
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
+  UPB_ASSERT(!upb_strtable_done(i));
+  return _upb_value_val(str_tabent(i)->val.val);
+}
+
+void upb_strtable_iter_setdone(upb_strtable_iter *i) {
+  i->t = NULL;
+  i->index = SIZE_MAX;
+}
+
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2) {
+  if (upb_strtable_done(i1) && upb_strtable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index;
+}
+
+
+/* upb_inttable ***************************************************************/
+
+/* For inttables we use a hybrid structure where small keys are kept in an
+ * array and large keys are put in the hash table. */
+
+static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
+
+static bool inteql(upb_tabkey k1, lookupkey_t k2) {
+  return k1 == k2.num;
+}
+
+static upb_tabval *mutable_array(upb_inttable *t) {
+  return (upb_tabval*)t->array;
+}
+
+static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
+  if (key < t->array_size) {
+    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
+  } else {
+    upb_tabent *e =
+        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
+    return e ? &e->val : NULL;
+  }
+}
+
+static const upb_tabval *inttable_val_const(const upb_inttable *t,
+                                            uintptr_t key) {
+  return inttable_val((upb_inttable*)t, key);
+}
+
+size_t upb_inttable_count(const upb_inttable *t) {
+  return t->t.count + t->array_count;
+}
+
+static void check(upb_inttable *t) {
+  UPB_UNUSED(t);
+#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
+  {
+    /* This check is very expensive (makes inserts/deletes O(N)). */
+    size_t count = 0;
+    upb_inttable_iter i;
+    upb_inttable_begin(&i, t);
+    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
+      UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
+    }
+    UPB_ASSERT(count == upb_inttable_count(t));
+  }
+#endif
+}
+
+bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
+                            upb_arena *a) {
+  size_t array_bytes;
+
+  if (!init(&t->t, hsize_lg2, a)) return false;
+  /* Always make the array part at least 1 long, so that we know key 0
+   * won't be in the hash part, which simplifies things. */
+  t->array_size = UPB_MAX(1, asize);
+  t->array_count = 0;
+  array_bytes = t->array_size * sizeof(upb_value);
+  t->array = upb_arena_malloc(a, array_bytes);
+  if (!t->array) {
+    return false;
+  }
+  memset(mutable_array(t), 0xff, array_bytes);
+  check(t);
+  return true;
+}
+
+bool upb_inttable_init(upb_inttable *t, upb_arena *a) {
+  return upb_inttable_sizedinit(t, 0, 4, a);
+}
+
+bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val,
+                         upb_arena *a) {
+  upb_tabval tabval;
+  tabval.val = val.val;
+  UPB_ASSERT(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
+
+  if (key < t->array_size) {
+    UPB_ASSERT(!upb_arrhas(t->array[key]));
+    t->array_count++;
+    mutable_array(t)[key].val = val.val;
+  } else {
+    if (isfull(&t->t)) {
+      /* Need to resize the hash part, but we re-use the array part. */
+      size_t i;
+      upb_table new_table;
+
+      if (!init(&new_table, t->t.size_lg2 + 1, a)) {
+        return false;
+      }
+
+      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
+        const upb_tabent *e = &t->t.entries[i];
+        uint32_t hash;
+        upb_value v;
+
+        _upb_value_setval(&v, e->val.val);
+        hash = upb_inthash(e->key);
+        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
+      }
+
+      UPB_ASSERT(t->t.count == new_table.count);
+
+      t->t = new_table;
+    }
+    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
+  }
+  check(t);
+  return true;
+}
+
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
+  const upb_tabval *table_v = inttable_val_const(t, key);
+  if (!table_v) return false;
+  if (v) _upb_value_setval(v, table_v->val);
+  return true;
+}
+
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
+  upb_tabval *table_v = inttable_val(t, key);
+  if (!table_v) return false;
+  table_v->val = val.val;
+  return true;
+}
+
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
+  bool success;
+  if (key < t->array_size) {
+    if (upb_arrhas(t->array[key])) {
+      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
+      t->array_count--;
+      if (val) {
+        _upb_value_setval(val, t->array[key].val);
+      }
+      mutable_array(t)[key] = empty;
+      success = true;
+    } else {
+      success = false;
+    }
+  } else {
+    success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
+  }
+  check(t);
+  return success;
+}
+
+void upb_inttable_compact(upb_inttable *t, upb_arena *a) {
+  /* A power-of-two histogram of the table keys. */
+  size_t counts[UPB_MAXARRSIZE + 1] = {0};
+
+  /* The max key in each bucket. */
+  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
+
+  upb_inttable_iter i;
+  size_t arr_count;
+  int size_lg2;
+  upb_inttable new_t;
+
+  upb_inttable_begin(&i, t);
+  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    uintptr_t key = upb_inttable_iter_key(&i);
+    int bucket = log2ceil(key);
+    max[bucket] = UPB_MAX(max[bucket], key);
+    counts[bucket]++;
+  }
+
+  /* Find the largest power of two that satisfies the MIN_DENSITY
+   * definition (while actually having some keys). */
+  arr_count = upb_inttable_count(t);
+
+  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
+    if (counts[size_lg2] == 0) {
+      /* We can halve again without losing any entries. */
+      continue;
+    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
+      break;
+    }
+
+    arr_count -= counts[size_lg2];
+  }
+
+  UPB_ASSERT(arr_count <= upb_inttable_count(t));
+
+  {
+    /* Insert all elements into new, perfectly-sized table. */
+    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
+    size_t hash_count = upb_inttable_count(t) - arr_count;
+    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
+    int hashsize_lg2 = log2ceil(hash_size);
+
+    upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a);
+    upb_inttable_begin(&i, t);
+    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+      uintptr_t k = upb_inttable_iter_key(&i);
+      upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i), a);
+    }
+    UPB_ASSERT(new_t.array_size == arr_size);
+    UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
+  }
+  *t = new_t;
+}
+
+/* Iteration. */
+
+static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
+  UPB_ASSERT(!i->array_part);
+  return &i->t->t.entries[i->index];
+}
+
+static upb_tabval int_arrent(const upb_inttable_iter *i) {
+  UPB_ASSERT(i->array_part);
+  return i->t->array[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
+  i->t = t;
+  i->index = -1;
+  i->array_part = true;
+  upb_inttable_next(i);
+}
+
+void upb_inttable_next(upb_inttable_iter *iter) {
+  const upb_inttable *t = iter->t;
+  if (iter->array_part) {
+    while (++iter->index < t->array_size) {
+      if (upb_arrhas(int_arrent(iter))) {
+        return;
+      }
+    }
+    iter->array_part = false;
+    iter->index = begin(&t->t);
+  } else {
+    iter->index = next(&t->t, iter->index);
+  }
+}
+
+bool upb_inttable_done(const upb_inttable_iter *i) {
+  if (!i->t) return true;
+  if (i->array_part) {
+    return i->index >= i->t->array_size ||
+           !upb_arrhas(int_arrent(i));
+  } else {
+    return i->index >= upb_table_size(&i->t->t) ||
+           upb_tabent_isempty(int_tabent(i));
+  }
+}
+
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
+  UPB_ASSERT(!upb_inttable_done(i));
+  return i->array_part ? i->index : int_tabent(i)->key;
+}
+
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
+  UPB_ASSERT(!upb_inttable_done(i));
+  return _upb_value_val(
+      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val);
+}
+
+void upb_inttable_iter_setdone(upb_inttable_iter *i) {
+  i->t = NULL;
+  i->index = SIZE_MAX;
+  i->array_part = false;
+}
+
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                                          const upb_inttable_iter *i2) {
+  if (upb_inttable_done(i1) && upb_inttable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index &&
+         i1->array_part == i2->array_part;
+}
+
+/** upb/upb.c ************************************************************/
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* upb_status *****************************************************************/
+
+void upb_status_clear(upb_status *status) {
+  if (!status) return;
+  status->ok = true;
+  status->msg[0] = '\0';
+}
+
+bool upb_ok(const upb_status *status) { return status->ok; }
+
+const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
+
+void upb_status_seterrmsg(upb_status *status, const char *msg) {
+  if (!status) return;
+  status->ok = false;
+  strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_status_vseterrf(status, fmt, args);
+  va_end(args);
+}
+
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
+  if (!status) return;
+  status->ok = false;
+  vsnprintf(status->msg, sizeof(status->msg), fmt, args);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) {
+  size_t len;
+  if (!status) return;
+  status->ok = false;
+  len = strlen(status->msg);
+  vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+/* upb_alloc ******************************************************************/
+
+static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                                  size_t size) {
+  UPB_UNUSED(alloc);
+  UPB_UNUSED(oldsize);
+  if (size == 0) {
+    free(ptr);
+    return NULL;
+  } else {
+    return realloc(ptr, size);
+  }
+}
+
+static uint32_t *upb_cleanup_pointer(uintptr_t cleanup_metadata) {
+  return (uint32_t *)(cleanup_metadata & ~0x1);
+}
+
+static bool upb_cleanup_has_initial_block(uintptr_t cleanup_metadata) {
+  return cleanup_metadata & 0x1;
+}
+
+static uintptr_t upb_cleanup_metadata(uint32_t *cleanup,
+                                      bool has_initial_block) {
+  return (uintptr_t)cleanup | has_initial_block;
+}
+
+upb_alloc upb_alloc_global = {&upb_global_allocfunc};
+
+/* upb_arena ******************************************************************/
+
+/* Be conservative and choose 16 in case anyone is using SSE. */
+
+struct mem_block {
+  struct mem_block *next;
+  uint32_t size;
+  uint32_t cleanups;
+  /* Data follows. */
+};
+
+typedef struct cleanup_ent {
+  upb_cleanup_func *cleanup;
+  void *ud;
+} cleanup_ent;
+
+static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16);
+
+static upb_arena *arena_findroot(upb_arena *a) {
+  /* Path splitting keeps time complexity down, see:
+   *   https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
+  while (a->parent != a) {
+    upb_arena *next = a->parent;
+    a->parent = next->parent;
+    a = next;
+  }
+  return a;
+}
+
+static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr,
+                               size_t size) {
+  mem_block *block = ptr;
+
+  /* The block is for arena |a|, but should appear in the freelist of |root|. */
+  block->next = root->freelist;
+  block->size = (uint32_t)size;
+  block->cleanups = 0;
+  root->freelist = block;
+  a->last_size = block->size;
+  if (!root->freelist_tail) root->freelist_tail = block;
+
+  a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
+  a->head.end = UPB_PTR_AT(block, size, char);
+  a->cleanup_metadata = upb_cleanup_metadata(
+      &block->cleanups, upb_cleanup_has_initial_block(a->cleanup_metadata));
+
+  UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr);
+}
+
+static bool upb_arena_allocblock(upb_arena *a, size_t size) {
+  upb_arena *root = arena_findroot(a);
+  size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve;
+  mem_block *block = upb_malloc(root->block_alloc, block_size);
+
+  if (!block) return false;
+  upb_arena_addblock(a, root, block, block_size);
+  return true;
+}
+
+void *_upb_arena_slowmalloc(upb_arena *a, size_t size) {
+  if (!upb_arena_allocblock(a, size)) return NULL;  /* Out of memory. */
+  UPB_ASSERT(_upb_arenahas(a) >= size);
+  return upb_arena_malloc(a, size);
+}
+
+static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                               size_t size) {
+  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
+  return upb_arena_realloc(a, ptr, oldsize, size);
+}
+
+/* Public Arena API ***********************************************************/
+
+upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) {
+  const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve;
+  upb_arena *a;
+
+  /* We need to malloc the initial block. */
+  n = first_block_overhead + 256;
+  if (!alloc || !(mem = upb_malloc(alloc, n))) {
+    return NULL;
+  }
+
+  a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
+  n -= sizeof(*a);
+
+  a->head.alloc.func = &upb_arena_doalloc;
+  a->block_alloc = alloc;
+  a->parent = a;
+  a->refcount = 1;
+  a->freelist = NULL;
+  a->freelist_tail = NULL;
+  a->cleanup_metadata = upb_cleanup_metadata(NULL, false);
+
+  upb_arena_addblock(a, a, mem, n);
+
+  return a;
+}
+
+upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
+  upb_arena *a;
+
+  /* Round block size down to alignof(*a) since we will allocate the arena
+   * itself at the end. */
+  n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena));
+
+  if (UPB_UNLIKELY(n < sizeof(upb_arena))) {
+    return arena_initslow(mem, n, alloc);
+  }
+
+  a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
+
+  a->head.alloc.func = &upb_arena_doalloc;
+  a->block_alloc = alloc;
+  a->parent = a;
+  a->refcount = 1;
+  a->last_size = UPB_MAX(128, n);
+  a->head.ptr = mem;
+  a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char);
+  a->freelist = NULL;
+  a->cleanup_metadata = upb_cleanup_metadata(NULL, true);
+
+  return a;
+}
+
+static void arena_dofree(upb_arena *a) {
+  mem_block *block = a->freelist;
+  UPB_ASSERT(a->parent == a);
+  UPB_ASSERT(a->refcount == 0);
+
+  while (block) {
+    /* Load first since we are deleting block. */
+    mem_block *next = block->next;
+
+    if (block->cleanups > 0) {
+      cleanup_ent *end = UPB_PTR_AT(block, block->size, void);
+      cleanup_ent *ptr = end - block->cleanups;
+
+      for (; ptr < end; ptr++) {
+        ptr->cleanup(ptr->ud);
+      }
+    }
+
+    upb_free(a->block_alloc, block);
+    block = next;
+  }
+}
+
+void upb_arena_free(upb_arena *a) {
+  a = arena_findroot(a);
+  if (--a->refcount == 0) arena_dofree(a);
+}
+
+bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
+  cleanup_ent *ent;
+  uint32_t* cleanups = upb_cleanup_pointer(a->cleanup_metadata);
+
+  if (!cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) {
+    if (!upb_arena_allocblock(a, 128)) return false;  /* Out of memory. */
+    UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent));
+    cleanups = upb_cleanup_pointer(a->cleanup_metadata);
+  }
+
+  a->head.end -= sizeof(cleanup_ent);
+  ent = (cleanup_ent*)a->head.end;
+  (*cleanups)++;
+  UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent));
+
+  ent->cleanup = func;
+  ent->ud = ud;
+
+  return true;
+}
+
+bool upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
+  upb_arena *r1 = arena_findroot(a1);
+  upb_arena *r2 = arena_findroot(a2);
+
+  if (r1 == r2) return true;  /* Already fused. */
+
+  /* Do not fuse initial blocks since we cannot lifetime extend them. */
+  if (upb_cleanup_has_initial_block(r1->cleanup_metadata)) return false;
+  if (upb_cleanup_has_initial_block(r2->cleanup_metadata)) return false;
+
+  /* Only allow fuse with a common allocator */
+  if (r1->block_alloc != r2->block_alloc) return false;
+
+  /* We want to join the smaller tree to the larger tree.
+   * So swap first if they are backwards. */
+  if (r1->refcount < r2->refcount) {
+    upb_arena *tmp = r1;
+    r1 = r2;
+    r2 = tmp;
+  }
+
+  /* r1 takes over r2's freelist and refcount. */
+  r1->refcount += r2->refcount;
+  if (r2->freelist_tail) {
+    UPB_ASSERT(r2->freelist_tail->next == NULL);
+    r2->freelist_tail->next = r1->freelist;
+    r1->freelist = r2->freelist;
+  }
+  r2->parent = r1;
+  return true;
+}
+
+/** upb/decode_fast.c ************************************************************/
+// Fast decoder: ~3x the speed of decode.c, but requires x86-64/ARM64.
+// Also the table size grows by 2x.
+//
+// Could potentially be ported to other 64-bit archs that pass at least six
+// arguments in registers and have 8 unused high bits in pointers.
+//
+// The overall design is to create specialized functions for every possible
+// field type (eg. oneof boolean field with a 1 byte tag) and then dispatch
+// to the specialized function as quickly as possible.
+
+
+
+/* Must be last. */
+
+#if UPB_FASTTABLE
+
+// The standard set of arguments passed to each parsing function.
+// Thanks to x86-64 calling conventions, these will stay in registers.
+#define UPB_PARSE_PARAMS                                          \
+  upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+      uint64_t hasbits, uint64_t data
+
+#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
+
+#define RETURN_GENERIC(m)                                                      \
+  /* Uncomment either of these for debugging purposes. */                      \
+  /* fprintf(stderr, m); */                                                    \
+  /*__builtin_trap(); */                                                       \
+  return fastdecode_generic(d, ptr, msg, table, hasbits, 0);
+
+typedef enum {
+  CARD_s = 0,  /* Singular (optional, non-repeated) */
+  CARD_o = 1,  /* Oneof */
+  CARD_r = 2,  /* Repeated */
+  CARD_p = 3   /* Packed Repeated */
+} upb_card;
+
+UPB_NOINLINE
+static const char *fastdecode_isdonefallback(UPB_PARSE_PARAMS) {
+  int overrun = data;
+  ptr = decode_isdonefallback_inl(d, ptr, overrun);
+  if (ptr == NULL) {
+    return fastdecode_err(d);
+  }
+  data = fastdecode_loadtag(ptr);
+  UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_dispatch(UPB_PARSE_PARAMS) {
+  if (UPB_UNLIKELY(ptr >= d->limit_ptr)) {
+    int overrun = ptr - d->end;
+    if (UPB_LIKELY(overrun == d->limit)) {
+      // Parse is finished.
+      *(uint32_t*)msg |= hasbits;  // Sync hasbits.
+      return ptr;
+    } else {
+      data = overrun;
+      UPB_MUSTTAIL return fastdecode_isdonefallback(UPB_PARSE_ARGS);
+    }
+  }
+
+  // Read two bytes of tag data (for a one-byte tag, the high byte is junk).
+  data = fastdecode_loadtag(ptr);
+  UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_checktag(uint16_t data, int tagbytes) {
+  if (tagbytes == 1) {
+    return (data & 0xff) == 0;
+  } else {
+    return data == 0;
+  }
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_longsize(const char *ptr, int *size) {
+  int i;
+  UPB_ASSERT(*size & 0x80);
+  *size &= 0xff;
+  for (i = 0; i < 3; i++) {
+    ptr++;
+    size_t byte = (uint8_t)ptr[-1];
+    *size += (byte - 1) << (7 + 7 * i);
+    if (UPB_LIKELY((byte & 0x80) == 0)) return ptr;
+  }
+  ptr++;
+  size_t byte = (uint8_t)ptr[-1];
+  // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected
+  // for a 32 bit varint.
+  if (UPB_UNLIKELY(byte >= 8)) return NULL;
+  *size += (byte - 1) << 28;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck(const char *ptr, size_t len,
+                                   const char *end) {
+  uintptr_t uptr = (uintptr_t)ptr;
+  uintptr_t uend = (uintptr_t)end + 16;
+  uintptr_t res = uptr + len;
+  return res < uptr || res > uend;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck2(const char *ptr, size_t len,
+                                    const char *end) {
+  // This is one extra branch compared to the more normal:
+  //   return (size_t)(end - ptr) < size;
+  // However it is one less computation if we are just about to use "ptr + len":
+  //   https://godbolt.org/z/35YGPz
+  // In microbenchmarks this shows an overall 4% improvement.
+  uintptr_t uptr = (uintptr_t)ptr;
+  uintptr_t uend = (uintptr_t)end;
+  uintptr_t res = uptr + len;
+  return res < uptr || res > uend;
+}
+
+typedef const char *fastdecode_delimfunc(upb_decstate *d, const char *ptr,
+                                         void *ctx);
+
+UPB_FORCEINLINE
+static const char *fastdecode_delimited(upb_decstate *d, const char *ptr,
+                                        fastdecode_delimfunc *func, void *ctx) {
+  ptr++;
+  int len = (int8_t)ptr[-1];
+  if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) {
+    // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer.
+    // If it exceeds the buffer limit, limit/limit_ptr will change during
+    // sub-message parsing, so we need to preserve delta, not limit.
+    if (UPB_UNLIKELY(len & 0x80)) {
+      // Size varint >1 byte (length >= 128).
+      ptr = fastdecode_longsize(ptr, &len);
+      if (!ptr) {
+        // Corrupt wire format: size exceeded INT_MAX.
+        return NULL;
+      }
+    }
+    if (ptr - d->end + (int)len > d->limit) {
+      // Corrupt wire format: invalid limit.
+      return NULL;
+    }
+    int delta = decode_pushlimit(d, ptr, len);
+    ptr = func(d, ptr, ctx);
+    decode_poplimit(d, ptr, delta);
+  } else {
+    // Fast case: Sub-message is <128 bytes and fits in the current buffer.
+    // This means we can preserve limit/limit_ptr verbatim.
+    const char *saved_limit_ptr = d->limit_ptr;
+    int saved_limit = d->limit;
+    d->limit_ptr = ptr + len;
+    d->limit = d->limit_ptr - d->end;
+    UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+    ptr = func(d, ptr, ctx);
+    d->limit_ptr = saved_limit_ptr;
+    d->limit = saved_limit;
+    UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+  }
+  return ptr;
+}
+
+/* singular, oneof, repeated field handling ***********************************/
+
+typedef struct {
+  upb_array *arr;
+  void *end;
+} fastdecode_arr;
+
+typedef enum {
+  FD_NEXT_ATLIMIT,
+  FD_NEXT_SAMEFIELD,
+  FD_NEXT_OTHERFIELD
+} fastdecode_next;
+
+typedef struct {
+  void *dst;
+  fastdecode_next next;
+  uint32_t tag;
+} fastdecode_nextret;
+
+UPB_FORCEINLINE
+static void *fastdecode_resizearr(upb_decstate *d, void *dst,
+                                  fastdecode_arr *farr, int valbytes) {
+  if (UPB_UNLIKELY(dst == farr->end)) {
+    size_t old_size = farr->arr->size;
+    size_t old_bytes = old_size * valbytes;
+    size_t new_size = old_size * 2;
+    size_t new_bytes = new_size * valbytes;
+    char *old_ptr = _upb_array_ptr(farr->arr);
+    char *new_ptr = upb_arena_realloc(&d->arena, old_ptr, old_bytes, new_bytes);
+    uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+    farr->arr->size = new_size;
+    farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2);
+    dst = (void*)(new_ptr + (old_size * valbytes));
+    farr->end = (void*)(new_ptr + (new_size * valbytes));
+  }
+  return dst;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) {
+  if (tagbytes == 1) {
+    return (uint8_t)tag == (uint8_t)data;
+  } else {
+    return (uint16_t)tag == (uint16_t)data;
+  }
+}
+
+UPB_FORCEINLINE
+static void fastdecode_commitarr(void *dst, fastdecode_arr *farr,
+                                 int valbytes) {
+  farr->arr->len =
+      (size_t)((char *)dst - (char *)_upb_array_ptr(farr->arr)) / valbytes;
+}
+
+UPB_FORCEINLINE
+static fastdecode_nextret fastdecode_nextrepeated(upb_decstate *d, void *dst,
+                                                  const char **ptr,
+                                                  fastdecode_arr *farr,
+                                                  uint64_t data, int tagbytes,
+                                                  int valbytes) {
+  fastdecode_nextret ret;
+  dst = (char *)dst + valbytes;
+
+  if (UPB_LIKELY(!decode_isdone(d, ptr))) {
+    ret.tag = fastdecode_loadtag(*ptr);
+    if (fastdecode_tagmatch(ret.tag, data, tagbytes)) {
+      ret.next = FD_NEXT_SAMEFIELD;
+    } else {
+      fastdecode_commitarr(dst, farr, valbytes);
+      ret.next = FD_NEXT_OTHERFIELD;
+    }
+  } else {
+    fastdecode_commitarr(dst, farr, valbytes);
+    ret.next = FD_NEXT_ATLIMIT;
+  }
+
+  ret.dst = dst;
+  return ret;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_fieldmem(upb_msg *msg, uint64_t data) {
+  size_t ofs = data >> 48;
+  return (char *)msg + ofs;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                 uint64_t *data, uint64_t *hasbits,
+                                 fastdecode_arr *farr, int valbytes,
+                                 upb_card card) {
+  switch (card) {
+    case CARD_s: {
+      uint8_t hasbit_index = *data >> 24;
+      // Set hasbit and return pointer to scalar field.
+      *hasbits |= 1ull << hasbit_index;
+      return fastdecode_fieldmem(msg, *data);
+    }
+    case CARD_o: {
+      uint16_t case_ofs = *data >> 32;
+      uint32_t *oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t);
+      uint8_t field_number = *data >> 24;
+      *oneof_case = field_number;
+      return fastdecode_fieldmem(msg, *data);
+    }
+    case CARD_r: {
+      // Get pointer to upb_array and allocate/expand if necessary.
+      uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+      upb_array **arr_p = fastdecode_fieldmem(msg, *data);
+      char *begin;
+      *(uint32_t*)msg |= *hasbits;
+      *hasbits = 0;
+      if (UPB_LIKELY(!*arr_p)) {
+        farr->arr = _upb_array_new(&d->arena, 8, elem_size_lg2);
+        *arr_p = farr->arr;
+      } else {
+        farr->arr = *arr_p;
+      }
+      begin = _upb_array_ptr(farr->arr);
+      farr->end = begin + (farr->arr->size * valbytes);
+      *data = fastdecode_loadtag(ptr);
+      return begin + (farr->arr->len * valbytes);
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_flippacked(uint64_t *data, int tagbytes) {
+  *data ^= (0x2 ^ 0x0);  // Patch data to match packed wiretype.
+  return fastdecode_checktag(*data, tagbytes);
+}
+
+#define FASTDECODE_CHECKPACKED(tagbytes, card, func)                           \
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {                    \
+    if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {            \
+      UPB_MUSTTAIL return func(UPB_PARSE_ARGS);                                \
+    }                                                                          \
+    RETURN_GENERIC("packed check tag mismatch\n");                             \
+  }
+
+/* varint fields **************************************************************/
+
+UPB_FORCEINLINE
+static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) {
+  if (valbytes == 1) {
+    return val != 0;
+  } else if (zigzag) {
+    if (valbytes == 4) {
+      uint32_t n = val;
+      return (n >> 1) ^ -(int32_t)(n & 1);
+    } else if (valbytes == 8) {
+      return (val >> 1) ^ -(int64_t)(val & 1);
+    }
+    UPB_UNREACHABLE();
+  }
+  return val;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_varint64(const char *ptr, uint64_t *val) {
+  ptr++;
+  *val = (uint8_t)ptr[-1];
+  if (UPB_UNLIKELY(*val & 0x80)) {
+    int i;
+    for (i = 0; i < 8; i++) {
+      ptr++;
+      uint64_t byte = (uint8_t)ptr[-1];
+      *val += (byte - 1) << (7 + 7 * i);
+      if (UPB_LIKELY((byte & 0x80) == 0)) goto done;
+    }
+    ptr++;
+    uint64_t byte = (uint8_t)ptr[-1];
+    if (byte > 1) {
+      return NULL;
+    }
+    *val += (byte - 1) << 63;
+  }
+done:
+  UPB_ASSUME(ptr != NULL);
+  return ptr;
+}
+
+#define FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
+                                  valbytes, card, zigzag, packed)              \
+  uint64_t val;                                                                \
+  void *dst;                                                                   \
+  fastdecode_arr farr;                                                         \
+                                                                               \
+  FASTDECODE_CHECKPACKED(tagbytes, card, packed);                              \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes,     \
+                            card);                                             \
+  if (card == CARD_r) {                                                        \
+    if (UPB_UNLIKELY(!dst)) {                                                  \
+      RETURN_GENERIC("need array resize\n");                                   \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, valbytes);                       \
+  }                                                                            \
+                                                                               \
+  ptr += tagbytes;                                                             \
+  ptr = fastdecode_varint64(ptr, &val);                                        \
+  if (ptr == NULL)                                                             \
+    return fastdecode_err(d);                                                  \
+  val = fastdecode_munge(val, valbytes, zigzag);                               \
+  memcpy(dst, &val, valbytes);                                                 \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, valbytes);                        \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+typedef struct {
+  uint8_t valbytes;
+  bool zigzag;
+  void *dst;
+  fastdecode_arr farr;
+} fastdecode_varintdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr,
+                                             void *ctx) {
+  fastdecode_varintdata *data = ctx;
+  void *dst = data->dst;
+  uint64_t val;
+
+  while (!decode_isdone(d, &ptr)) {
+    dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes);
+    ptr = fastdecode_varint64(ptr, &val);
+    if (ptr == NULL) return NULL;
+    val = fastdecode_munge(val, data->valbytes, data->zigzag);
+    memcpy(dst, &val, data->valbytes);
+    dst = (char *)dst + data->valbytes;
+  }
+
+  fastdecode_commitarr(dst, &data->farr, data->valbytes);
+  return ptr;
+}
+
+#define FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes,   \
+                                valbytes, zigzag, unpacked)                    \
+  fastdecode_varintdata ctx = {valbytes, zigzag};                              \
+                                                                               \
+  FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked);                          \
+                                                                               \
+  ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr,       \
+                                valbytes, CARD_r);                             \
+  if (UPB_UNLIKELY(!ctx.dst)) {                                                \
+    RETURN_GENERIC("need array resize\n");                                     \
+  }                                                                            \
+                                                                               \
+  ptr += tagbytes;                                                             \
+  ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx);        \
+                                                                               \
+  if (UPB_UNLIKELY(ptr == NULL)) {                                             \
+    return fastdecode_err(d);                                                  \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(d, ptr, msg, table, hasbits, 0);
+
+#define FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                          valbytes, card, zigzag, unpacked, packed)        \
+  if (card == CARD_p) {                                                    \
+    FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes,   \
+                            valbytes, zigzag, unpacked);                   \
+  } else {                                                                 \
+    FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
+                              valbytes, card, zigzag, packed);             \
+  }
+
+#define z_ZZ true
+#define b_ZZ false
+#define v_ZZ false
+
+/* Generate all combinations:
+ * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */
+
+#define F(card, type, valbytes, tagbytes)                                      \
+  UPB_NOINLINE                                                                 \
+  const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+    FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, valbytes,   \
+                      CARD_##card, type##_ZZ,                                  \
+                      upb_pr##type##valbytes##_##tagbytes##bt,                 \
+                      upb_pp##type##valbytes##_##tagbytes##bt);                \
+  }
+
+#define TYPES(card, tagbytes) \
+  F(card, b, 1, tagbytes)     \
+  F(card, v, 4, tagbytes)     \
+  F(card, v, 8, tagbytes)     \
+  F(card, z, 4, tagbytes)     \
+  F(card, z, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef z_ZZ
+#undef b_ZZ
+#undef v_ZZ
+#undef o_ONEOF
+#undef s_ONEOF
+#undef r_ONEOF
+#undef F
+#undef TYPES
+#undef TAGBYTES
+#undef FASTDECODE_UNPACKEDVARINT
+#undef FASTDECODE_PACKEDVARINT
+#undef FASTDECODE_VARINT
+
+
+/* fixed fields ***************************************************************/
+
+#define FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes,  \
+                                 valbytes, card, packed)                       \
+  void *dst;                                                                   \
+  fastdecode_arr farr;                                                         \
+                                                                               \
+  FASTDECODE_CHECKPACKED(tagbytes, card, packed)                               \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes,     \
+                            card);                                             \
+  if (card == CARD_r) {                                                        \
+    if (UPB_UNLIKELY(!dst)) {                                                  \
+      RETURN_GENERIC("couldn't allocate array in arena\n");                    \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, valbytes);                       \
+  }                                                                            \
+                                                                               \
+  ptr += tagbytes;                                                             \
+  memcpy(dst, ptr, valbytes);                                                  \
+  ptr += valbytes;                                                             \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, valbytes);                        \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+#define FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
+                               valbytes, unpacked)                          \
+  FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked)                        \
+                                                                            \
+  ptr += tagbytes;                                                          \
+  int size = (uint8_t)ptr[0];                                               \
+  ptr++;                                                                    \
+  if (size & 0x80) {                                                        \
+    ptr = fastdecode_longsize(ptr, &size);                                  \
+  }                                                                         \
+                                                                            \
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr) ||       \
+                   (size % valbytes) != 0)) {                               \
+    return fastdecode_err(d);                                               \
+  }                                                                         \
+                                                                            \
+  upb_array **arr_p = fastdecode_fieldmem(msg, data);                       \
+  upb_array *arr = *arr_p;                                                  \
+  uint8_t elem_size_lg2 = __builtin_ctz(valbytes);                          \
+  int elems = size / valbytes;                                              \
+                                                                            \
+  if (UPB_LIKELY(!arr)) {                                                   \
+    *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2);         \
+    if (!arr) {                                                             \
+      return fastdecode_err(d);                                             \
+    }                                                                       \
+  } else {                                                                  \
+    _upb_array_resize(arr, elems, &d->arena);                               \
+  }                                                                         \
+                                                                            \
+  char *dst = _upb_array_ptr(arr);                                          \
+  memcpy(dst, ptr, size);                                                   \
+  arr->len = elems;                                                         \
+                                                                            \
+  ptr += size;                                                              \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+#define FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                         valbytes, card, unpacked, packed)                \
+  if (card == CARD_p) {                                                   \
+    FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes,   \
+                           valbytes, unpacked);                           \
+  } else {                                                                \
+    FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
+                             valbytes, card, packed);                     \
+  }
+
+/* Generate all combinations:
+ * {s,o,r,p} x {f4,f8} x {1bt,2bt} */
+
+#define F(card, valbytes, tagbytes)                                         \
+  UPB_NOINLINE                                                              \
+  const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+    FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
+                     CARD_##card, upb_ppf##valbytes##_##tagbytes##bt,       \
+                     upb_prf##valbytes##_##tagbytes##bt);                   \
+  }
+
+#define TYPES(card, tagbytes) \
+  F(card, 4, tagbytes)        \
+  F(card, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+#undef FASTDECODE_UNPACKEDFIXED
+#undef FASTDECODE_PACKEDFIXED
+
+/* string fields **************************************************************/
+
+typedef const char *fastdecode_copystr_func(struct upb_decstate *d,
+                                            const char *ptr, upb_msg *msg,
+                                            const upb_msglayout *table,
+                                            uint64_t hasbits, upb_strview *dst);
+
+UPB_NOINLINE
+static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr,
+                                         upb_msg *msg, intptr_t table,
+                                         uint64_t hasbits, uint64_t data) {
+  upb_strview *dst = (upb_strview*)data;
+  if (!decode_verifyutf8_inl(dst->data, dst->size)) {
+    return fastdecode_err(d);
+  }
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+}
+
+#define FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, validate_utf8) \
+  int size = (uint8_t)ptr[0]; /* Could plumb through hasbits. */               \
+  ptr++;                                                                       \
+  if (size & 0x80) {                                                           \
+    ptr = fastdecode_longsize(ptr, &size);                                     \
+  }                                                                            \
+                                                                               \
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) {         \
+    dst->size = 0;                                                             \
+    return fastdecode_err(d);                                                  \
+  }                                                                            \
+                                                                               \
+  if (d->alias) {                                                              \
+    dst->data = ptr;                                                           \
+    dst->size = size;                                                          \
+  } else {                                                                     \
+    char *data = upb_arena_malloc(&d->arena, size);                            \
+    if (!data) {                                                               \
+      return fastdecode_err(d);                                                \
+    }                                                                          \
+    memcpy(data, ptr, size);                                                   \
+    dst->data = data;                                                          \
+    dst->size = size;                                                          \
+  }                                                                            \
+                                                                               \
+  ptr += size;                                                                 \
+  if (validate_utf8) {                                                         \
+    data = (uint64_t)dst;                                                      \
+    UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS);                 \
+  } else {                                                                     \
+    UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);                   \
+  }
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_utf8(struct upb_decstate *d,
+                                              const char *ptr, upb_msg *msg,
+                                              intptr_t table, uint64_t hasbits,
+                                              uint64_t data) {
+  upb_strview *dst = (upb_strview*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
+}
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_noutf8(struct upb_decstate *d,
+                                                const char *ptr, upb_msg *msg,
+                                                intptr_t table,
+                                                uint64_t hasbits,
+                                                uint64_t data) {
+  upb_strview *dst = (upb_strview*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
+}
+
+UPB_FORCEINLINE
+static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size,
+                              int copy, char *data, upb_strview *dst) {
+  d->arena.head.ptr += copy;
+  dst->data = data;
+  UPB_UNPOISON_MEMORY_REGION(data, copy);
+  memcpy(data, ptr, copy);
+  UPB_POISON_MEMORY_REGION(data + size, copy - size);
+}
+
+#define FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                              card, validate_utf8)                             \
+  upb_strview *dst;                                                            \
+  fastdecode_arr farr;                                                         \
+  int64_t size;                                                                \
+  size_t arena_has;                                                            \
+  size_t common_has;                                                           \
+  char *buf;                                                                   \
+                                                                               \
+  UPB_ASSERT(!d->alias);                                                       \
+  UPB_ASSERT(fastdecode_checktag(data, tagbytes));                             \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
+                            sizeof(upb_strview), card);                        \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));            \
+  }                                                                            \
+                                                                               \
+  size = (uint8_t)ptr[tagbytes];                                               \
+  ptr += tagbytes + 1;                                                         \
+  dst->size = size;                                                            \
+                                                                               \
+  buf = d->arena.head.ptr;                                                     \
+  arena_has = _upb_arenahas(&d->arena);                                        \
+  common_has = UPB_MIN(arena_has, (d->end - ptr) + 16);                        \
+                                                                               \
+  if (UPB_LIKELY(size <= 15 - tagbytes)) {                                     \
+    if (arena_has < 16)                                                        \
+      goto longstr;                                                            \
+    d->arena.head.ptr += 16;                                                   \
+    memcpy(buf, ptr - tagbytes - 1, 16);                                       \
+    dst->data = buf + tagbytes + 1;                                            \
+  } else if (UPB_LIKELY(size <= 32)) {                                         \
+    if (UPB_UNLIKELY(common_has < 32))                                         \
+      goto longstr;                                                            \
+    fastdecode_docopy(d, ptr, size, 32, buf, dst);                             \
+  } else if (UPB_LIKELY(size <= 64)) {                                         \
+    if (UPB_UNLIKELY(common_has < 64))                                         \
+      goto longstr;                                                            \
+    fastdecode_docopy(d, ptr, size, 64, buf, dst);                             \
+  } else if (UPB_LIKELY(size < 128)) {                                         \
+    if (UPB_UNLIKELY(common_has < 128))                                        \
+      goto longstr;                                                            \
+    fastdecode_docopy(d, ptr, size, 128, buf, dst);                            \
+  } else {                                                                     \
+    goto longstr;                                                              \
+  }                                                                            \
+                                                                               \
+  ptr += size;                                                                 \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {       \
+      return fastdecode_err(d);                                                \
+    }                                                                          \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));             \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  if (card != CARD_r && validate_utf8) {                                       \
+    data = (uint64_t)dst;                                                      \
+    UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS);                 \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);                     \
+                                                                               \
+  longstr:                                                                     \
+  ptr--;                                                                       \
+  if (validate_utf8) {                                                         \
+    UPB_MUSTTAIL return fastdecode_longstring_utf8(d, ptr, msg, table,         \
+                                                   hasbits, (uint64_t)dst);    \
+  } else {                                                                     \
+    UPB_MUSTTAIL return fastdecode_longstring_noutf8(d, ptr, msg, table,       \
+                                                     hasbits, (uint64_t)dst);  \
+  }
+
+#define FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, card,   \
+                          copyfunc, validate_utf8)                             \
+  upb_strview *dst;                                                            \
+  fastdecode_arr farr;                                                         \
+  int64_t size;                                                                \
+                                                                               \
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {                    \
+    RETURN_GENERIC("string field tag mismatch\n");                             \
+  }                                                                            \
+                                                                               \
+  if (UPB_UNLIKELY(!d->alias)) {                                               \
+    UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS);                              \
+  }                                                                            \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
+                            sizeof(upb_strview), card);                        \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));            \
+  }                                                                            \
+                                                                               \
+  size = (int8_t)ptr[tagbytes];                                                \
+  ptr += tagbytes + 1;                                                         \
+  dst->data = ptr;                                                             \
+  dst->size = size;                                                            \
+                                                                               \
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) {               \
+    ptr--;                                                                     \
+    if (validate_utf8) {                                                       \
+      return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits,           \
+                                        (uint64_t)dst);                        \
+    } else {                                                                   \
+      return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits,         \
+                                          (uint64_t)dst);                      \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  ptr += size;                                                                 \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {       \
+      return fastdecode_err(d);                                                \
+    }                                                                          \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));             \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      if (UPB_UNLIKELY(!d->alias)) {                                           \
+        /* Buffer flipped and we can't alias any more. Bounce to */            \
+        /* copyfunc(), but via dispatch since we need to reload table */       \
+        /* data also. */                                                       \
+        fastdecode_commitarr(dst, &farr, sizeof(upb_strview));                 \
+        data = ret.tag;                                                        \
+        UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);            \
+      }                                                                        \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  if (card != CARD_r && validate_utf8) {                                       \
+    data = (uint64_t)dst;                                                      \
+    UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS);                 \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+/* Generate all combinations:
+ * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */
+
+#define s_VALIDATE true
+#define b_VALIDATE false
+
+#define F(card, tagbytes, type)                                        \
+  UPB_NOINLINE                                                         \
+  const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) {   \
+    FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
+                          CARD_##card, type##_VALIDATE);               \
+  }                                                                    \
+  const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) {   \
+    FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                      CARD_##card, upb_c##card##type##_##tagbytes##bt, \
+                      type##_VALIDATE);                                \
+  }
+
+#define UTF8(card, tagbytes) \
+  F(card, tagbytes, s)       \
+  F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+  UTF8(card, 1)        \
+  UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef s_VALIDATE
+#undef b_VALIDATE
+#undef F
+#undef TAGBYTES
+#undef FASTDECODE_LONGSTRING
+#undef FASTDECODE_COPYSTRING
+#undef FASTDECODE_STRING
+
+/* message fields *************************************************************/
+
+UPB_INLINE
+upb_msg *decode_newmsg_ceil(upb_decstate *d, const upb_msglayout *l,
+                            int msg_ceil_bytes) {
+  size_t size = l->size + sizeof(upb_msg_internal);
+  char *msg_data;
+  if (UPB_LIKELY(msg_ceil_bytes > 0 &&
+                 _upb_arenahas(&d->arena) >= msg_ceil_bytes)) {
+    UPB_ASSERT(size <= (size_t)msg_ceil_bytes);
+    msg_data = d->arena.head.ptr;
+    d->arena.head.ptr += size;
+    UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes);
+    memset(msg_data, 0, msg_ceil_bytes);
+    UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size);
+  } else {
+    msg_data = (char*)upb_arena_malloc(&d->arena, size);
+    memset(msg_data, 0, size);
+  }
+  return msg_data + sizeof(upb_msg_internal);
+}
+
+typedef struct {
+  intptr_t table;
+  upb_msg *msg;
+} fastdecode_submsgdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr,
+                                       void *ctx) {
+  fastdecode_submsgdata *submsg = ctx;
+  ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0);
+  UPB_ASSUME(ptr != NULL);
+  return ptr;
+}
+
+#define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes,    \
+                          msg_ceil_bytes, card)                           \
+                                                                          \
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {               \
+    RETURN_GENERIC("submessage field tag mismatch\n");                    \
+  }                                                                       \
+                                                                          \
+  if (--d->depth == 0) return fastdecode_err(d);                          \
+                                                                          \
+  upb_msg **dst;                                                          \
+  uint32_t submsg_idx = (data >> 16) & 0xff;                              \
+  const upb_msglayout *tablep = decode_totablep(table);                   \
+  const upb_msglayout *subtablep = tablep->submsgs[submsg_idx];           \
+  fastdecode_submsgdata submsg = {decode_totable(subtablep)};             \
+  fastdecode_arr farr;                                                    \
+                                                                          \
+  if (subtablep->table_mask == (uint8_t)-1) {                             \
+    RETURN_GENERIC("submessage doesn't have fast tables.");               \
+  }                                                                       \
+                                                                          \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,          \
+                            sizeof(upb_msg *), card);                     \
+                                                                          \
+  if (card == CARD_s) {                                                   \
+    *(uint32_t *)msg |= hasbits;                                          \
+    hasbits = 0;                                                          \
+  }                                                                       \
+                                                                          \
+  again:                                                                  \
+  if (card == CARD_r) {                                                   \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg *));         \
+  }                                                                       \
+                                                                          \
+  submsg.msg = *dst;                                                      \
+                                                                          \
+  if (card == CARD_r || UPB_LIKELY(!submsg.msg)) {                        \
+    *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \
+  }                                                                       \
+                                                                          \
+  ptr += tagbytes;                                                        \
+  ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg);       \
+                                                                          \
+  if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) {      \
+    return fastdecode_err(d);                                             \
+  }                                                                       \
+                                                                          \
+  if (card == CARD_r) {                                                   \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                     \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *));          \
+    switch (ret.next) {                                                   \
+      case FD_NEXT_SAMEFIELD:                                             \
+        dst = ret.dst;                                                    \
+        goto again;                                                       \
+      case FD_NEXT_OTHERFIELD:                                            \
+        d->depth++;                                                       \
+        data = ret.tag;                                                   \
+        UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);       \
+      case FD_NEXT_ATLIMIT:                                               \
+        d->depth++;                                                       \
+        return ptr;                                                       \
+    }                                                                     \
+  }                                                                       \
+                                                                          \
+  d->depth++;                                                             \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+#define F(card, tagbytes, size_ceil, ceil_arg)                               \
+  const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(               \
+      UPB_PARSE_PARAMS) {                                                    \
+    FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \
+                      CARD_##card);                                          \
+  }
+
+#define SIZES(card, tagbytes) \
+  F(card, tagbytes, 64, 64) \
+  F(card, tagbytes, 128, 128) \
+  F(card, tagbytes, 192, 192) \
+  F(card, tagbytes, 256, 256) \
+  F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+  SIZES(card, 1) \
+  SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+#undef FASTDECODE_SUBMSG
+
+#endif  /* UPB_FASTTABLE */
+
+/** bazel-out/k8-fastbuild/bin/external/com_google_protobuf/google/protobuf/descriptor.upb.c ************************************************************//* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+
+
+static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = {
+  &google_protobuf_FileDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
+  &google_protobuf_FileDescriptorSet_submsgs[0],
+  &google_protobuf_FileDescriptorSet__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
+  &google_protobuf_DescriptorProto_msginit,
+  &google_protobuf_EnumDescriptorProto_msginit,
+  &google_protobuf_FieldDescriptorProto_msginit,
+  &google_protobuf_FileOptions_msginit,
+  &google_protobuf_ServiceDescriptorProto_msginit,
+  &google_protobuf_SourceCodeInfo_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {3, UPB_SIZE(36, 72), 0, 0, 12, 3},
+  {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
+  {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
+  {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
+  {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
+  {8, UPB_SIZE(28, 56), 3, 3, 11, 1},
+  {9, UPB_SIZE(32, 64), 4, 5, 11, 1},
+  {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
+  {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
+  {12, UPB_SIZE(20, 40), 5, 0, 12, 1},
+};
+
+const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
+  &google_protobuf_FileDescriptorProto_submsgs[0],
+  &google_protobuf_FileDescriptorProto__fields[0],
+  UPB_SIZE(64, 128), 12, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = {
+  &google_protobuf_DescriptorProto_msginit,
+  &google_protobuf_DescriptorProto_ExtensionRange_msginit,
+  &google_protobuf_DescriptorProto_ReservedRange_msginit,
+  &google_protobuf_EnumDescriptorProto_msginit,
+  &google_protobuf_FieldDescriptorProto_msginit,
+  &google_protobuf_MessageOptions_msginit,
+  &google_protobuf_OneofDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
+  {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
+  {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
+  {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
+  {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
+  {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
+  {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
+  {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
+  {10, UPB_SIZE(44, 88), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_msginit = {
+  &google_protobuf_DescriptorProto_submsgs[0],
+  &google_protobuf_DescriptorProto__fields[0],
+  UPB_SIZE(48, 96), 10, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
+  &google_protobuf_ExtensionRangeOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+  {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
+  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
+  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
+  UPB_SIZE(16, 24), 3, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
+  NULL,
+  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
+  UPB_SIZE(16, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
+  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
+  &google_protobuf_ExtensionRangeOptions_submsgs[0],
+  &google_protobuf_ExtensionRangeOptions__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
+  &google_protobuf_FieldOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
+  {1, UPB_SIZE(24, 24), 1, 0, 12, 1},
+  {2, UPB_SIZE(32, 40), 2, 0, 12, 1},
+  {3, UPB_SIZE(12, 12), 3, 0, 5, 1},
+  {4, UPB_SIZE(4, 4), 4, 0, 14, 1},
+  {5, UPB_SIZE(8, 8), 5, 0, 14, 1},
+  {6, UPB_SIZE(40, 56), 6, 0, 12, 1},
+  {7, UPB_SIZE(48, 72), 7, 0, 12, 1},
+  {8, UPB_SIZE(64, 104), 8, 0, 11, 1},
+  {9, UPB_SIZE(16, 16), 9, 0, 5, 1},
+  {10, UPB_SIZE(56, 88), 10, 0, 12, 1},
+  {17, UPB_SIZE(20, 20), 11, 0, 8, 1},
+};
+
+const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
+  &google_protobuf_FieldDescriptorProto_submsgs[0],
+  &google_protobuf_FieldDescriptorProto__fields[0],
+  UPB_SIZE(72, 112), 11, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
+  &google_protobuf_OneofOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
+  &google_protobuf_OneofDescriptorProto_submsgs[0],
+  &google_protobuf_OneofDescriptorProto__fields[0],
+  UPB_SIZE(16, 32), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
+  &google_protobuf_EnumOptions_msginit,
+  &google_protobuf_EnumValueDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
+  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
+  {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
+  {5, UPB_SIZE(24, 48), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
+  &google_protobuf_EnumDescriptorProto_submsgs[0],
+  &google_protobuf_EnumDescriptorProto__fields[0],
+  UPB_SIZE(32, 64), 5, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
+  NULL,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
+  UPB_SIZE(16, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
+  &google_protobuf_EnumValueOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(8, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(4, 4), 2, 0, 5, 1},
+  {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
+  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
+  &google_protobuf_EnumValueDescriptorProto__fields[0],
+  UPB_SIZE(24, 32), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
+  &google_protobuf_MethodDescriptorProto_msginit,
+  &google_protobuf_ServiceOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
+  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
+};
+
+const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
+  &google_protobuf_ServiceDescriptorProto_submsgs[0],
+  &google_protobuf_ServiceDescriptorProto__fields[0],
+  UPB_SIZE(24, 48), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
+  &google_protobuf_MethodOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {3, UPB_SIZE(20, 40), 3, 0, 12, 1},
+  {4, UPB_SIZE(28, 56), 4, 0, 11, 1},
+  {5, UPB_SIZE(1, 1), 5, 0, 8, 1},
+  {6, UPB_SIZE(2, 2), 6, 0, 8, 1},
+};
+
+const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
+  &google_protobuf_MethodDescriptorProto_submsgs[0],
+  &google_protobuf_MethodDescriptorProto__fields[0],
+  UPB_SIZE(32, 64), 6, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
+  {1, UPB_SIZE(20, 24), 1, 0, 12, 1},
+  {8, UPB_SIZE(28, 40), 2, 0, 12, 1},
+  {9, UPB_SIZE(4, 4), 3, 0, 14, 1},
+  {10, UPB_SIZE(8, 8), 4, 0, 8, 1},
+  {11, UPB_SIZE(36, 56), 5, 0, 12, 1},
+  {16, UPB_SIZE(9, 9), 6, 0, 8, 1},
+  {17, UPB_SIZE(10, 10), 7, 0, 8, 1},
+  {18, UPB_SIZE(11, 11), 8, 0, 8, 1},
+  {20, UPB_SIZE(12, 12), 9, 0, 8, 1},
+  {23, UPB_SIZE(13, 13), 10, 0, 8, 1},
+  {27, UPB_SIZE(14, 14), 11, 0, 8, 1},
+  {31, UPB_SIZE(15, 15), 12, 0, 8, 1},
+  {36, UPB_SIZE(44, 72), 13, 0, 12, 1},
+  {37, UPB_SIZE(52, 88), 14, 0, 12, 1},
+  {39, UPB_SIZE(60, 104), 15, 0, 12, 1},
+  {40, UPB_SIZE(68, 120), 16, 0, 12, 1},
+  {41, UPB_SIZE(76, 136), 17, 0, 12, 1},
+  {42, UPB_SIZE(16, 16), 18, 0, 8, 1},
+  {44, UPB_SIZE(84, 152), 19, 0, 12, 1},
+  {45, UPB_SIZE(92, 168), 20, 0, 12, 1},
+  {999, UPB_SIZE(100, 184), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FileOptions_msginit = {
+  &google_protobuf_FileOptions_submsgs[0],
+  &google_protobuf_FileOptions__fields[0],
+  UPB_SIZE(104, 192), 21, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
+  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
+  {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
+  {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
+  {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_MessageOptions_msginit = {
+  &google_protobuf_MessageOptions_submsgs[0],
+  &google_protobuf_MessageOptions__fields[0],
+  UPB_SIZE(16, 16), 5, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 14, 1},
+  {2, UPB_SIZE(12, 12), 2, 0, 8, 1},
+  {3, UPB_SIZE(13, 13), 3, 0, 8, 1},
+  {5, UPB_SIZE(14, 14), 4, 0, 8, 1},
+  {6, UPB_SIZE(8, 8), 5, 0, 14, 1},
+  {10, UPB_SIZE(15, 15), 6, 0, 8, 1},
+  {999, UPB_SIZE(16, 16), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FieldOptions_msginit = {
+  &google_protobuf_FieldOptions_submsgs[0],
+  &google_protobuf_FieldOptions__fields[0],
+  UPB_SIZE(24, 24), 7, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
+  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_OneofOptions_msginit = {
+  &google_protobuf_OneofOptions_submsgs[0],
+  &google_protobuf_OneofOptions__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
+  {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_EnumOptions_msginit = {
+  &google_protobuf_EnumOptions_submsgs[0],
+  &google_protobuf_EnumOptions__fields[0],
+  UPB_SIZE(8, 16), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
+  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
+  &google_protobuf_EnumValueOptions_submsgs[0],
+  &google_protobuf_EnumValueOptions__fields[0],
+  UPB_SIZE(8, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
+  {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_ServiceOptions_msginit = {
+  &google_protobuf_ServiceOptions_submsgs[0],
+  &google_protobuf_ServiceOptions__fields[0],
+  UPB_SIZE(8, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
+  {33, UPB_SIZE(8, 8), 1, 0, 8, 1},
+  {34, UPB_SIZE(4, 4), 2, 0, 14, 1},
+  {999, UPB_SIZE(12, 16), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_MethodOptions_msginit = {
+  &google_protobuf_MethodOptions_submsgs[0],
+  &google_protobuf_MethodOptions__fields[0],
+  UPB_SIZE(16, 24), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_NamePart_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
+  {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
+  {3, UPB_SIZE(32, 32), 1, 0, 12, 1},
+  {4, UPB_SIZE(8, 8), 2, 0, 4, 1},
+  {5, UPB_SIZE(16, 16), 3, 0, 3, 1},
+  {6, UPB_SIZE(24, 24), 4, 0, 1, 1},
+  {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
+  {8, UPB_SIZE(48, 64), 6, 0, 12, 1},
+};
+
+const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
+  &google_protobuf_UninterpretedOption_submsgs[0],
+  &google_protobuf_UninterpretedOption__fields[0],
+  UPB_SIZE(64, 96), 7, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 2},
+  {2, UPB_SIZE(1, 1), 2, 0, 8, 2},
+};
+
+const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
+  NULL,
+  &google_protobuf_UninterpretedOption_NamePart__fields[0],
+  UPB_SIZE(16, 32), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
+  &google_protobuf_SourceCodeInfo_Location_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
+  &google_protobuf_SourceCodeInfo_submsgs[0],
+  &google_protobuf_SourceCodeInfo__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
+  {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
+  {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
+  {3, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {4, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {6, UPB_SIZE(28, 56), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
+  NULL,
+  &google_protobuf_SourceCodeInfo_Location__fields[0],
+  UPB_SIZE(32, 64), 5, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
+  &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
+  &google_protobuf_GeneratedCodeInfo_submsgs[0],
+  &google_protobuf_GeneratedCodeInfo__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
+  {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
+  {2, UPB_SIZE(12, 16), 1, 0, 12, 1},
+  {3, UPB_SIZE(4, 4), 2, 0, 5, 1},
+  {4, UPB_SIZE(8, 8), 3, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
+  NULL,
+  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
+  UPB_SIZE(24, 48), 4, false, 255,
+};
+
+
+
+/** bazel-out/k8-fastbuild/bin/external/com_google_protobuf/google/protobuf/descriptor.upbdefs.c ************************************************************//* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+
+extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
+extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
+extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
+extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_FileOptions_msginit;
+extern const upb_msglayout google_protobuf_MessageOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldOptions_msginit;
+extern const upb_msglayout google_protobuf_OneofOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
+extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
+extern const upb_msglayout google_protobuf_MethodOptions_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
+
+static const upb_msglayout *layouts[27] = {
+  &google_protobuf_FileDescriptorSet_msginit,
+  &google_protobuf_FileDescriptorProto_msginit,
+  &google_protobuf_DescriptorProto_msginit,
+  &google_protobuf_DescriptorProto_ExtensionRange_msginit,
+  &google_protobuf_DescriptorProto_ReservedRange_msginit,
+  &google_protobuf_ExtensionRangeOptions_msginit,
+  &google_protobuf_FieldDescriptorProto_msginit,
+  &google_protobuf_OneofDescriptorProto_msginit,
+  &google_protobuf_EnumDescriptorProto_msginit,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
+  &google_protobuf_EnumValueDescriptorProto_msginit,
+  &google_protobuf_ServiceDescriptorProto_msginit,
+  &google_protobuf_MethodDescriptorProto_msginit,
+  &google_protobuf_FileOptions_msginit,
+  &google_protobuf_MessageOptions_msginit,
+  &google_protobuf_FieldOptions_msginit,
+  &google_protobuf_OneofOptions_msginit,
+  &google_protobuf_EnumOptions_msginit,
+  &google_protobuf_EnumValueOptions_msginit,
+  &google_protobuf_ServiceOptions_msginit,
+  &google_protobuf_MethodOptions_msginit,
+  &google_protobuf_UninterpretedOption_msginit,
+  &google_protobuf_UninterpretedOption_NamePart_msginit,
+  &google_protobuf_SourceCodeInfo_msginit,
+  &google_protobuf_SourceCodeInfo_Location_msginit,
+  &google_protobuf_GeneratedCodeInfo_msginit,
+  &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
+};
+
+static const char descriptor[7601] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 
+'t', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
+'f', '\"', 'M', '\n', '\021', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'S', 'e', 't', '\022', '8', '\n', 
+'\004', 'f', 'i', 'l', 'e', '\030', '\001', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 
+'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', 
+'\004', 'f', 'i', 'l', 'e', '\"', '\344', '\004', '\n', '\023', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 
+'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 
+'\030', '\n', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', 
+'\022', '\036', '\n', '\n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 'd', 'e', 'p', 
+'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', '+', '\n', '\021', 'p', 'u', 'b', 'l', 'i', 'c', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 
+'n', 'c', 'y', '\030', '\n', ' ', '\003', '(', '\005', 'R', '\020', 'p', 'u', 'b', 'l', 'i', 'c', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 
+'c', 'y', '\022', '\'', '\n', '\017', 'w', 'e', 'a', 'k', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\013', ' ', '\003', 
+'(', '\005', 'R', '\016', 'w', 'e', 'a', 'k', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', 'C', '\n', '\014', 'm', 'e', 's', 
+'s', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', 
+'\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', 
+'\030', '\005', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 
+'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', 
+'T', 'y', 'p', 'e', '\022', 'A', '\n', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\006', ' ', '\003', '(', '\013', '2', '\'', '.', 'g', 
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', 
+'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'C', '\n', '\t', 
+'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\007', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 
+'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', '6', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 
+'s', '\030', '\010', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\020', 
+'s', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'd', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\t', ' ', '\001', '(', '\013', '2', '\037', '.', 
+'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 
+'e', 'I', 'n', 'f', 'o', 'R', '\016', 's', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', '\026', '\n', '\006', 
+'s', 'y', 'n', 't', 'a', 'x', '\030', '\014', ' ', '\001', '(', '\t', 'R', '\006', 's', 'y', 'n', 't', 'a', 'x', '\"', '\271', '\006', '\n', '\017', 
+'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', 
+' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', ';', '\n', '\005', 'f', 'i', 'e', 'l', 'd', '\030', '\002', ' ', '\003', '(', '\013', 
+'2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 
+'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'f', 'i', 'e', 'l', 'd', '\022', 'C', '\n', '\t', 
+'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\006', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 
+'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', 'A', '\n', '\013', 'n', 'e', 's', 't', 'e', 'd', 
+'_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 
+'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\n', 'n', 'e', 's', 
+'t', 'e', 'd', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', 
+'\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', 
+'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', 
+'X', '\n', '\017', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\005', ' ', '\003', '(', '\013', '2', 
+'/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 
+'t', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'R', '\016', 
+'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\n', 'o', 'n', 'e', 'o', 'f', '_', 'd', 
+'e', 'c', 'l', '\030', '\010', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
+'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\t', 
+'o', 'n', 'e', 'o', 'f', 'D', 'e', 'c', 'l', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\007', ' ', '\001', '(', 
+'\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 's', 's', 'a', 
+'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\016', 'r', 'e', 's', 
+'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\t', ' ', '\003', '(', '\013', '2', '.', '.', 'g', 'o', 'o', 'g', 'l', 
+'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 
+'o', '.', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 
+'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', 
+'\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', 'z', '\n', '\016', 'E', 'x', 't', 'e', 
+'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 
+'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', 
+'\022', '@', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 
+'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 
+'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\032', '7', '\n', '\r', 'R', 'e', 's', 'e', 'r', 
+'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', 
+'s', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '|', 
+'\n', '\025', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'X', 
+'\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', 
+' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 
+'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 
+'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', 
+'\301', '\006', '\n', '\024', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', 
+'\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', 
+'m', 'b', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', 'A', '\n', '\005', 'l', 'a', 'b', 
+'e', 'l', '\030', '\004', ' ', '\001', '(', '\016', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
+'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'L', 'a', 
+'b', 'e', 'l', 'R', '\005', 'l', 'a', 'b', 'e', 'l', '\022', '>', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\005', ' ', '\001', '(', '\016', '2', 
+'*', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 
+'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'T', 'y', 'p', 'e', 'R', '\004', 't', 'y', 'p', 'e', '\022', 
+'\033', '\n', '\t', 't', 'y', 'p', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\010', 't', 'y', 'p', 'e', 'N', 
+'a', 'm', 'e', '\022', '\032', '\n', '\010', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'e', 'x', 
+'t', 'e', 'n', 'd', 'e', 'e', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', 
+' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\013', 'o', 'n', 'e', 
+'o', 'f', '_', 'i', 'n', 'd', 'e', 'x', '\030', '\t', ' ', '\001', '(', '\005', 'R', '\n', 'o', 'n', 'e', 'o', 'f', 'I', 'n', 'd', 'e', 
+'x', '\022', '\033', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', 'R', '\010', 'j', 's', 'o', 
+'n', 'N', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\010', ' ', '\001', '(', '\013', '2', '\035', '.', 
+'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 
+'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '\'', '\n', '\017', 'p', 'r', 'o', 't', 'o', '3', '_', 'o', 'p', 
+'t', 'i', 'o', 'n', 'a', 'l', '\030', '\021', ' ', '\001', '(', '\010', 'R', '\016', 'p', 'r', 'o', 't', 'o', '3', 'O', 'p', 't', 'i', 'o', 
+'n', 'a', 'l', '\"', '\266', '\002', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', 
+'L', 'E', '\020', '\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', 
+'Y', 'P', 'E', '_', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', 
+'4', '\020', '\004', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', 
+'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 
+'D', '3', '2', '\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', 
+'Y', 'P', 'E', '_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', 
+'P', '\020', '\n', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', 
+'T', 'Y', 'P', 'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', 
+'3', '2', '\020', '\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', 
+'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 
+'X', 'E', 'D', '6', '4', '\020', '\020', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', 
+'\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 'C', '\n', '\005', 'L', 'a', 'b', 'e', 'l', 
+'\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 'O', 'P', 'T', 'I', 'O', 'N', 'A', 'L', '\020', '\001', '\022', '\022', '\n', '\016', 'L', 
+'A', 'B', 'E', 'L', '_', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', '\020', '\002', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 
+'R', 'E', 'P', 'E', 'A', 'T', 'E', 'D', '\020', '\003', '\"', 'c', '\n', '\024', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', 
+'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 
+'n', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\035', '.', 'g', 
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', 'i', 'o', 
+'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\343', '\002', '\n', '\023', 'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 
+'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', 
+'\004', 'n', 'a', 'm', 'e', '\022', '?', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', ')', '.', 'g', 'o', 
+'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', 
+'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '6', '\n', '\007', 'o', 
+'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 
+'t', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 
+'s', '\022', ']', '\n', '\016', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\004', ' ', '\003', '(', '\013', 
+'2', '6', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', 'e', 
+'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', 
+'d', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', 
+'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\005', ' ', '\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', 
+'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', ';', '\n', '\021', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 
+'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', 's', 't', 'a', 'r', 
+'t', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '\203', '\001', '\n', '\030', 'E', 
+'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', 
+'\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', 'm', 
+'b', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', ';', '\n', '\007', 'o', 'p', 't', 'i', 
+'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '!', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
+'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 
+'o', 'n', 's', '\"', '\247', '\001', '\n', '\026', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 
+'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', 
+'\022', '>', '\n', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\030', '\002', ' ', '\003', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', 
+'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 
+'r', 'P', 'r', 'o', 't', 'o', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', 
+'\030', '\003', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 
+'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\211', 
+'\002', '\n', '\025', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', 
+'\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\035', '\n', '\n', 'i', 'n', 
+'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'i', 'n', 'p', 'u', 't', 'T', 'y', 'p', 'e', 
+'\022', '\037', '\n', '\013', 'o', 'u', 't', 'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\n', 'o', 'u', 
+'t', 'p', 'u', 't', 'T', 'y', 'p', 'e', '\022', '8', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\001', '(', '\013', 
+'2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 
+'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '0', '\n', '\020', 'c', 'l', 'i', 'e', 'n', 
+'t', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', 
+'\017', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\022', '0', '\n', '\020', 's', 'e', 'r', 'v', 'e', 
+'r', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\006', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', 
+'\017', 's', 'e', 'r', 'v', 'e', 'r', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\"', '\221', '\t', '\n', '\013', 'F', 'i', 'l', 'e', 
+'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '!', '\n', '\014', 'j', 'a', 'v', 'a', '_', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\001', 
+' ', '\001', '(', '\t', 'R', '\013', 'j', 'a', 'v', 'a', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '0', '\n', '\024', 'j', 'a', 'v', 'a', 
+'_', 'o', 'u', 't', 'e', 'r', '_', 'c', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\022', 'j', 
+'a', 'v', 'a', 'O', 'u', 't', 'e', 'r', 'C', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\022', '5', '\n', '\023', 'j', 'a', 'v', 'a', 
+'_', 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', '_', 'f', 'i', 'l', 'e', 's', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 
+'l', 's', 'e', 'R', '\021', 'j', 'a', 'v', 'a', 'M', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'F', 'i', 'l', 'e', 's', '\022', 'D', '\n', 
+'\035', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', '_', 'e', 'q', 'u', 'a', 'l', 's', '_', 'a', 'n', 'd', 
+'_', 'h', 'a', 's', 'h', '\030', '\024', ' ', '\001', '(', '\010', 'B', '\002', '\030', '\001', 'R', '\031', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', 
+'r', 'a', 't', 'e', 'E', 'q', 'u', 'a', 'l', 's', 'A', 'n', 'd', 'H', 'a', 's', 'h', '\022', ':', '\n', '\026', 'j', 'a', 'v', 'a', 
+'_', 's', 't', 'r', 'i', 'n', 'g', '_', 'c', 'h', 'e', 'c', 'k', '_', 'u', 't', 'f', '8', '\030', '\033', ' ', '\001', '(', '\010', ':', 
+'\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'S', 't', 'r', 'i', 'n', 'g', 'C', 'h', 'e', 'c', 'k', 'U', 't', 
+'f', '8', '\022', 'S', '\n', '\014', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', '_', 'f', 'o', 'r', '\030', '\t', ' ', '\001', '(', '\016', '2', 
+')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 
+'i', 'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', 'd', 'e', ':', '\005', 'S', 'P', 'E', 'E', 'D', 'R', 
+'\013', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'F', 'o', 'r', '\022', '\035', '\n', '\n', 'g', 'o', '_', 'p', 'a', 'c', 'k', 'a', 'g', 
+'e', '\030', '\013', ' ', '\001', '(', '\t', 'R', '\t', 'g', 'o', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '5', '\n', '\023', 'c', 'c', '_', 
+'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\020', ' ', '\001', '(', '\010', ':', '\005', 'f', 
+'a', 'l', 's', 'e', 'R', '\021', 'c', 'c', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '9', 
+'\n', '\025', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\021', 
+' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 
+'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '5', '\n', '\023', 'p', 'y', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 
+'v', 'i', 'c', 'e', 's', '\030', '\022', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'p', 'y', 'G', 'e', 'n', 
+'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '7', '\n', '\024', 'p', 'h', 'p', '_', 'g', 'e', 'n', 'e', 'r', 
+'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '*', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', 
+'\022', 'p', 'h', 'p', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '%', '\n', '\n', 'd', 'e', 
+'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\027', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 
+'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '.', '\n', '\020', 'c', 'c', '_', 'e', 'n', 'a', 'b', 'l', 'e', '_', 'a', 'r', 'e', 
+'n', 'a', 's', '\030', '\037', ' ', '\001', '(', '\010', ':', '\004', 't', 'r', 'u', 'e', 'R', '\016', 'c', 'c', 'E', 'n', 'a', 'b', 'l', 'e', 
+'A', 'r', 'e', 'n', 'a', 's', '\022', '*', '\n', '\021', 'o', 'b', 'j', 'c', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', 
+'i', 'x', '\030', '$', ' ', '\001', '(', '\t', 'R', '\017', 'o', 'b', 'j', 'c', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', 
+'\022', ')', '\n', '\020', 'c', 's', 'h', 'a', 'r', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', '%', ' ', '\001', '(', 
+'\t', 'R', '\017', 'c', 's', 'h', 'a', 'r', 'p', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 's', 'w', 'i', 
+'f', 't', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\'', ' ', '\001', '(', '\t', 'R', '\013', 's', 'w', 'i', 'f', 't', 'P', 'r', 'e', 
+'f', 'i', 'x', '\022', '(', '\n', '\020', 'p', 'h', 'p', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '(', 
+' ', '\001', '(', '\t', 'R', '\016', 'p', 'h', 'p', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', '\022', '#', '\n', '\r', 'p', 
+'h', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ')', ' ', '\001', '(', '\t', 'R', '\014', 'p', 'h', 'p', 'N', 'a', 
+'m', 'e', 's', 'p', 'a', 'c', 'e', '\022', '4', '\n', '\026', 'p', 'h', 'p', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'n', 
+'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ',', ' ', '\001', '(', '\t', 'R', '\024', 'p', 'h', 'p', 'M', 'e', 't', 'a', 'd', 'a', 
+'t', 'a', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 'r', 'u', 'b', 'y', '_', 'p', 'a', 'c', 'k', 'a', 
+'g', 'e', '\030', '-', ' ', '\001', '(', '\t', 'R', '\013', 'r', 'u', 'b', 'y', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', 'X', '\n', '\024', 
+'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', 
+'(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 
+'t', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 
+'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', ':', '\n', '\014', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', 
+'d', 'e', '\022', '\t', '\n', '\005', 'S', 'P', 'E', 'E', 'D', '\020', '\001', '\022', '\r', '\n', '\t', 'C', 'O', 'D', 'E', '_', 'S', 'I', 'Z', 
+'E', '\020', '\002', '\022', '\020', '\n', '\014', 'L', 'I', 'T', 'E', '_', 'R', 'U', 'N', 'T', 'I', 'M', 'E', '\020', '\003', '*', '\t', '\010', '\350', 
+'\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '&', '\020', '\'', '\"', '\321', '\002', '\n', '\016', 'M', 'e', 's', 's', 'a', 'g', 'e', 
+'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '<', '\n', '\027', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 's', 'e', 't', '_', 'w', 'i', 
+'r', 'e', '_', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\024', 'm', 
+'e', 's', 's', 'a', 'g', 'e', 'S', 'e', 't', 'W', 'i', 'r', 'e', 'F', 'o', 'r', 'm', 'a', 't', '\022', 'L', '\n', '\037', 'n', 'o', 
+'_', 's', 't', 'a', 'n', 'd', 'a', 'r', 'd', '_', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'a', 'c', 'c', 'e', 
+'s', 's', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\034', 'n', 'o', 'S', 't', 'a', 'n', 
+'d', 'a', 'r', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'A', 'c', 'c', 'e', 's', 's', 'o', 'r', '\022', '%', '\n', 
+'\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', 
+'\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '\033', '\n', '\t', 'm', 'a', 'p', '_', 'e', 'n', 't', 'r', 'y', '\030', 
+'\007', ' ', '\001', '(', '\010', 'R', '\010', 'm', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 
+'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 
+'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 
+'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\010', '\020', '\t', 'J', '\004', '\010', 
+'\t', '\020', '\n', '\"', '\342', '\003', '\n', '\014', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'A', '\n', '\005', 'c', 
+'t', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 
+'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'C', 'T', 'y', 'p', 'e', ':', '\006', 'S', 
+'T', 'R', 'I', 'N', 'G', 'R', '\005', 'c', 't', 'y', 'p', 'e', '\022', '\026', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\002', ' ', 
+'\001', '(', '\010', 'R', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\022', 'G', '\n', '\006', 'j', 's', 't', 'y', 'p', 'e', '\030', '\006', ' ', '\001', 
+'(', '\016', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 
+'d', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'J', 'S', 'T', 'y', 'p', 'e', ':', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', 
+'L', 'R', '\006', 'j', 's', 't', 'y', 'p', 'e', '\022', '\031', '\n', '\004', 'l', 'a', 'z', 'y', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', 
+'f', 'a', 'l', 's', 'e', 'R', '\004', 'l', 'a', 'z', 'y', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', 
+'\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', 
+'\022', '\031', '\n', '\004', 'w', 'e', 'a', 'k', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\004', 'w', 'e', 
+'a', 'k', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 
+'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
+'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 
+'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', '/', '\n', '\005', 'C', 'T', 'y', 'p', 
+'e', '\022', '\n', '\n', '\006', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\000', '\022', '\010', '\n', '\004', 'C', 'O', 'R', 'D', '\020', '\001', '\022', '\020', 
+'\n', '\014', 'S', 'T', 'R', 'I', 'N', 'G', '_', 'P', 'I', 'E', 'C', 'E', '\020', '\002', '\"', '5', '\n', '\006', 'J', 'S', 'T', 'y', 'p', 
+'e', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', 'L', '\020', '\000', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'S', 'T', 
+'R', 'I', 'N', 'G', '\020', '\001', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'U', 'M', 'B', 'E', 'R', '\020', '\002', '*', '\t', '\010', '\350', 
+'\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\004', '\020', '\005', '\"', 's', '\n', '\014', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', 
+'i', 'o', 'n', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 
+'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 
+'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 
+'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', 
+'\200', '\200', '\200', '\200', '\002', '\"', '\300', '\001', '\n', '\013', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\037', '\n', '\013', 
+'a', 'l', 'l', 'o', 'w', '_', 'a', 'l', 'i', 'a', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\n', 'a', 'l', 'l', 'o', 'w', 'A', 
+'l', 'i', 'a', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', 
+'\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 
+'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', 
+'$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 
+'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 
+'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\005', '\020', '\006', 
+'\"', '\236', '\001', '\n', '\020', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 
+'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 
+'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 
+'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', 
+'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 
+'t', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 
+'*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\234', '\001', '\n', '\016', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', 
+'t', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '!', ' ', '\001', '(', '\010', 
+':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', 
+'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', 
+'2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 
+'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 
+'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\340', '\002', '\n', '\r', 
+'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 
+'e', 'd', '\030', '!', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 
+'e', 'd', '\022', 'q', '\n', '\021', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', '_', 'l', 'e', 'v', 'e', 'l', '\030', '\"', 
+' ', '\001', '(', '\016', '2', '/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 
+'t', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'I', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 
+'v', 'e', 'l', ':', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', 'R', 
+'\020', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 
+'t', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', 
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 
+'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 
+'d', 'O', 'p', 't', 'i', 'o', 'n', '\"', 'P', '\n', '\020', 'I', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 
+'e', 'l', '\022', '\027', '\n', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', 
+'\020', '\000', '\022', '\023', '\n', '\017', 'N', 'O', '_', 'S', 'I', 'D', 'E', '_', 'E', 'F', 'F', 'E', 'C', 'T', 'S', '\020', '\001', '\022', '\016', 
+'\n', '\n', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'T', '\020', '\002', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 
+'\"', '\232', '\003', '\n', '\023', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\022', 
+'A', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 
+'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 
+'n', '.', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', 'R', '\004', 'n', 'a', 'm', 'e', '\022', ')', '\n', '\020', 'i', 'd', 'e', 'n', 't', 
+'i', 'f', 'i', 'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'i', 'd', 'e', 'n', 't', 'i', 
+'f', 'i', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', 
+'_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\004', 'R', '\020', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', 'I', 'n', 't', 
+'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'n', 'e', 'g', 'a', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', '_', 'v', 'a', 'l', 
+'u', 'e', '\030', '\005', ' ', '\001', '(', '\003', 'R', '\020', 'n', 'e', 'g', 'a', 't', 'i', 'v', 'e', 'I', 'n', 't', 'V', 'a', 'l', 'u', 
+'e', '\022', '!', '\n', '\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\006', ' ', '\001', '(', '\001', 'R', '\013', 
+'d', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', 
+'u', 'e', '\030', '\007', ' ', '\001', '(', '\014', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '\'', '\n', '\017', 
+'a', 'g', 'g', 'r', 'e', 'g', 'a', 't', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\016', 'a', 'g', 
+'g', 'r', 'e', 'g', 'a', 't', 'e', 'V', 'a', 'l', 'u', 'e', '\032', 'J', '\n', '\010', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', 
+'\033', '\n', '\t', 'n', 'a', 'm', 'e', '_', 'p', 'a', 'r', 't', '\030', '\001', ' ', '\002', '(', '\t', 'R', '\010', 'n', 'a', 'm', 'e', 'P', 
+'a', 'r', 't', '\022', '!', '\n', '\014', 'i', 's', '_', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\002', '(', '\010', 
+'R', '\013', 'i', 's', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', '\247', '\002', '\n', '\016', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 
+'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'D', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\003', '(', '\013', 
+'2', '(', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 
+'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 
+'o', 'n', '\032', '\316', '\001', '\n', '\010', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', 
+' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\026', '\n', '\004', 's', 'p', 'a', 'n', '\030', '\002', ' ', 
+'\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 's', 'p', 'a', 'n', '\022', ')', '\n', '\020', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 
+'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'l', 'e', 'a', 'd', 'i', 'n', 'g', 'C', 'o', 
+'m', 'm', 'e', 'n', 't', 's', '\022', '+', '\n', '\021', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', '_', 'c', 'o', 'm', 'm', 'e', 'n', 
+'t', 's', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\020', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', 'C', 'o', 'm', 'm', 'e', 'n', 't', 
+'s', '\022', ':', '\n', '\031', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 'd', 'e', 't', 'a', 'c', 'h', 'e', 'd', '_', 'c', 'o', 'm', 
+'m', 'e', 'n', 't', 's', '\030', '\006', ' ', '\003', '(', '\t', 'R', '\027', 'l', 'e', 'a', 'd', 'i', 'n', 'g', 'D', 'e', 't', 'a', 'c', 
+'h', 'e', 'd', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\"', '\321', '\001', '\n', '\021', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 
+'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'M', '\n', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', 
+'\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', 
+'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 
+'R', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\032', 'm', '\n', '\n', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 
+'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', 
+'\022', '\037', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'f', 'i', 'l', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 's', 'o', 
+'u', 'r', 'c', 'e', 'F', 'i', 'l', 'e', '\022', '\024', '\n', '\005', 'b', 'e', 'g', 'i', 'n', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\005', 
+'b', 'e', 'g', 'i', 'n', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\004', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', 'B', '~', 
+'\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\020', 'D', 'e', 
+'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 's', 'H', '\001', 'Z', '-', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', 
+'/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\032', 
+'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'R', 'e', 'f', 'l', 'e', 'c', 't', 'i', 'o', 
+'n', 
+};
+
+static upb_def_init *deps[1] = {
+  NULL
+};
+
+upb_def_init google_protobuf_descriptor_proto_upbdefinit = {
+  deps,
+  layouts,
+  "google/protobuf/descriptor.proto",
+  UPB_STRVIEW_INIT(descriptor, 7601)
+};
+
+/** upb/def.c ************************************************************/
+
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+typedef struct {
+  size_t len;
+  char str[1];  /* Null-terminated string data follows. */
+} str_t;
+
+struct upb_fielddef {
+  const upb_filedef *file;
+  const upb_msgdef *msgdef;
+  const char *full_name;
+  const char *json_name;
+  union {
+    int64_t sint;
+    uint64_t uint;
+    double dbl;
+    float flt;
+    bool boolean;
+    str_t *str;
+  } defaultval;
+  const upb_oneofdef *oneof;
+  union {
+    const upb_msgdef *msgdef;
+    const upb_enumdef *enumdef;
+    const google_protobuf_FieldDescriptorProto *unresolved;
+  } sub;
+  uint32_t number_;
+  uint16_t index_;
+  uint16_t layout_index;
+  bool is_extension_;
+  bool lazy_;
+  bool packed_;
+  bool proto3_optional_;
+  upb_descriptortype_t type_;
+  upb_label_t label_;
+};
+
+struct upb_msgdef {
+  const upb_msglayout *layout;
+  const upb_filedef *file;
+  const char *full_name;
+
+  /* Tables for looking up fields by number and name. */
+  upb_inttable itof;
+  upb_strtable ntof;
+
+  const upb_fielddef *fields;
+  const upb_oneofdef *oneofs;
+  int field_count;
+  int oneof_count;
+  int real_oneof_count;
+
+  /* Is this a map-entry message? */
+  bool map_entry;
+  upb_wellknowntype_t well_known_type;
+
+  /* TODO(haberman): proper extension ranges (there can be multiple). */
+};
+
+struct upb_enumdef {
+  const upb_filedef *file;
+  const char *full_name;
+  upb_strtable ntoi;
+  upb_inttable iton;
+  int32_t defaultval;
+};
+
+struct upb_oneofdef {
+  const upb_msgdef *parent;
+  const char *full_name;
+  int field_count;
+  bool synthetic;
+  const upb_fielddef **fields;
+  upb_strtable ntof;
+  upb_inttable itof;
+};
+
+struct upb_filedef {
+  const char *name;
+  const char *package;
+  const char *phpprefix;
+  const char *phpnamespace;
+
+  const upb_filedef **deps;
+  const upb_msgdef *msgs;
+  const upb_enumdef *enums;
+  const upb_fielddef *exts;
+  const upb_symtab *symtab;
+
+  int dep_count;
+  int msg_count;
+  int enum_count;
+  int ext_count;
+  upb_syntax_t syntax;
+};
+
+struct upb_symtab {
+  upb_arena *arena;
+  upb_strtable syms;  /* full_name -> packed def ptr */
+  upb_strtable files;  /* file_name -> upb_filedef* */
+  size_t bytes_loaded;
+};
+
+/* Inside a symtab we store tagged pointers to specific def types. */
+typedef enum {
+  UPB_DEFTYPE_FIELD = 0,
+
+  /* Only inside symtab table. */
+  UPB_DEFTYPE_MSG = 1,
+  UPB_DEFTYPE_ENUM = 2,
+
+  /* Only inside message table. */
+  UPB_DEFTYPE_ONEOF = 1,
+  UPB_DEFTYPE_FIELD_JSONNAME = 2
+} upb_deftype_t;
+
+static const void *unpack_def(upb_value v, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+  return (num & 3) == type ? (const void*)(num & ~3) : NULL;
+}
+
+static upb_value pack_def(const void *ptr, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)ptr | type;
+  return upb_value_constptr((const void*)num);
+}
+
+/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
+static bool upb_isbetween(char c, char low, char high) {
+  return c >= low && c <= high;
+}
+
+static bool upb_isletter(char c) {
+  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+  return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static const char *shortdefname(const char *fullname) {
+  const char *p;
+
+  if (fullname == NULL) {
+    return NULL;
+  } else if ((p = strrchr(fullname, '.')) == NULL) {
+    /* No '.' in the name, return the full string. */
+    return fullname;
+  } else {
+    /* Return one past the last '.'. */
+    return p + 1;
+  }
+}
+
+/* All submessage fields are lower than all other fields.
+ * Secondly, fields are increasing in order. */
+uint32_t field_rank(const upb_fielddef *f) {
+  uint32_t ret = upb_fielddef_number(f);
+  const uint32_t high_bit = 1 << 30;
+  UPB_ASSERT(ret < high_bit);
+  if (!upb_fielddef_issubmsg(f))
+    ret |= high_bit;
+  return ret;
+}
+
+int cmp_fields(const void *p1, const void *p2) {
+  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
+  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
+  return field_rank(f1) - field_rank(f2);
+}
+
+static void upb_status_setoom(upb_status *status) {
+  upb_status_seterrmsg(status, "out of memory");
+}
+
+static void assign_msg_wellknowntype(upb_msgdef *m) {
+  const char *name = upb_msgdef_fullname(m);
+  if (name == NULL) {
+    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+    return;
+  }
+  if (!strcmp(name, "google.protobuf.Any")) {
+    m->well_known_type = UPB_WELLKNOWN_ANY;
+  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
+    m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
+  } else if (!strcmp(name, "google.protobuf.Duration")) {
+    m->well_known_type = UPB_WELLKNOWN_DURATION;
+  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
+    m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
+  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
+    m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
+  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
+    m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
+  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
+    m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
+  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
+    m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
+  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
+    m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
+  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
+    m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
+  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
+    m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
+  } else if (!strcmp(name, "google.protobuf.StringValue")) {
+    m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
+  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
+    m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
+  } else if (!strcmp(name, "google.protobuf.Value")) {
+    m->well_known_type = UPB_WELLKNOWN_VALUE;
+  } else if (!strcmp(name, "google.protobuf.ListValue")) {
+    m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
+  } else if (!strcmp(name, "google.protobuf.Struct")) {
+    m->well_known_type = UPB_WELLKNOWN_STRUCT;
+  } else {
+    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+  }
+}
+
+
+/* upb_enumdef ****************************************************************/
+
+const char *upb_enumdef_fullname(const upb_enumdef *e) {
+  return e->full_name;
+}
+
+const char *upb_enumdef_name(const upb_enumdef *e) {
+  return shortdefname(e->full_name);
+}
+
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
+  return e->file;
+}
+
+int32_t upb_enumdef_default(const upb_enumdef *e) {
+  UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
+  return e->defaultval;
+}
+
+int upb_enumdef_numvals(const upb_enumdef *e) {
+  return (int)upb_strtable_count(&e->ntoi);
+}
+
+void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
+  /* We iterate over the ntoi table, to account for duplicate numbers. */
+  upb_strtable_begin(i, &e->ntoi);
+}
+
+void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
+bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
+
+bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
+                      size_t len, int32_t *num) {
+  upb_value v;
+  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
+    return false;
+  }
+  if (num) *num = upb_value_getint32(v);
+  return true;
+}
+
+const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
+  upb_value v;
+  return upb_inttable_lookup(&def->iton, num, &v) ? upb_value_getcstr(v) : NULL;
+}
+
+const char *upb_enum_iter_name(upb_enum_iter *iter) {
+  return upb_strtable_iter_key(iter).data;
+}
+
+int32_t upb_enum_iter_number(upb_enum_iter *iter) {
+  return upb_value_getint32(upb_strtable_iter_value(iter));
+}
+
+
+/* upb_fielddef ***************************************************************/
+
+const char *upb_fielddef_fullname(const upb_fielddef *f) {
+  return f->full_name;
+}
+
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
+  switch (f->type_) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      return UPB_TYPE_DOUBLE;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      return UPB_TYPE_FLOAT;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+      return UPB_TYPE_INT64;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      return UPB_TYPE_INT32;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      return UPB_TYPE_UINT64;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      return UPB_TYPE_UINT32;
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      return UPB_TYPE_ENUM;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      return UPB_TYPE_BOOL;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      return UPB_TYPE_STRING;
+    case UPB_DESCRIPTOR_TYPE_BYTES:
+      return UPB_TYPE_BYTES;
+    case UPB_DESCRIPTOR_TYPE_GROUP:
+    case UPB_DESCRIPTOR_TYPE_MESSAGE:
+      return UPB_TYPE_MESSAGE;
+  }
+  UPB_UNREACHABLE();
+}
+
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
+  return f->type_;
+}
+
+uint32_t upb_fielddef_index(const upb_fielddef *f) {
+  return f->index_;
+}
+
+upb_label_t upb_fielddef_label(const upb_fielddef *f) {
+  return f->label_;
+}
+
+uint32_t upb_fielddef_number(const upb_fielddef *f) {
+  return f->number_;
+}
+
+bool upb_fielddef_isextension(const upb_fielddef *f) {
+  return f->is_extension_;
+}
+
+bool upb_fielddef_lazy(const upb_fielddef *f) {
+  return f->lazy_;
+}
+
+bool upb_fielddef_packed(const upb_fielddef *f) {
+  return f->packed_;
+}
+
+const char *upb_fielddef_name(const upb_fielddef *f) {
+  return shortdefname(f->full_name);
+}
+
+const char *upb_fielddef_jsonname(const upb_fielddef *f) {
+  return f->json_name;
+}
+
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
+  return f->file;
+}
+
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
+  return f->msgdef;
+}
+
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
+  return f->oneof;
+}
+
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) {
+  if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL;
+  return f->oneof;
+}
+
+upb_msgval upb_fielddef_default(const upb_fielddef *f) {
+  UPB_ASSERT(!upb_fielddef_issubmsg(f));
+  upb_msgval ret;
+  if (upb_fielddef_isstring(f)) {
+    str_t *str = f->defaultval.str;
+    if (str) {
+      ret.str_val.data = str->str;
+      ret.str_val.size = str->len;
+    } else {
+      ret.str_val.size = 0;
+    }
+  } else {
+    memcpy(&ret, &f->defaultval, 8);
+  }
+  return ret;
+}
+
+static void chkdefaulttype(const upb_fielddef *f, int ctype) {
+  UPB_UNUSED(f);
+  UPB_UNUSED(ctype);
+}
+
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT64);
+  return f->defaultval.sint;
+}
+
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT32);
+  return (int32_t)f->defaultval.sint;
+}
+
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT64);
+  return f->defaultval.uint;
+}
+
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT32);
+  return (uint32_t)f->defaultval.uint;
+}
+
+bool upb_fielddef_defaultbool(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_BOOL);
+  return f->defaultval.boolean;
+}
+
+float upb_fielddef_defaultfloat(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_FLOAT);
+  return f->defaultval.flt;
+}
+
+double upb_fielddef_defaultdouble(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_DOUBLE);
+  return f->defaultval.dbl;
+}
+
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
+  str_t *str = f->defaultval.str;
+  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
+         upb_fielddef_type(f) == UPB_TYPE_ENUM);
+  if (str) {
+    if (len) *len = str->len;
+    return str->str;
+  } else {
+    if (len) *len = 0;
+    return NULL;
+  }
+}
+
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE ? f->sub.msgdef : NULL;
+}
+
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_ENUM ? f->sub.enumdef : NULL;
+}
+
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) {
+  return &f->msgdef->layout->fields[f->layout_index];
+}
+
+bool upb_fielddef_issubmsg(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
+}
+
+bool upb_fielddef_isstring(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES;
+}
+
+bool upb_fielddef_isseq(const upb_fielddef *f) {
+  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
+}
+
+bool upb_fielddef_isprimitive(const upb_fielddef *f) {
+  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
+}
+
+bool upb_fielddef_ismap(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
+         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
+}
+
+bool upb_fielddef_hassubdef(const upb_fielddef *f) {
+  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
+}
+
+bool upb_fielddef_haspresence(const upb_fielddef *f) {
+  if (upb_fielddef_isseq(f)) return false;
+  return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) ||
+         f->file->syntax == UPB_SYNTAX_PROTO2;
+}
+
+static bool between(int32_t x, int32_t low, int32_t high) {
+  return x >= low && x <= high;
+}
+
+bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
+bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
+bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
+
+bool upb_fielddef_checkdescriptortype(int32_t type) {
+  return between(type, 1, 18);
+}
+
+/* upb_msgdef *****************************************************************/
+
+const char *upb_msgdef_fullname(const upb_msgdef *m) {
+  return m->full_name;
+}
+
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
+  return m->file;
+}
+
+const char *upb_msgdef_name(const upb_msgdef *m) {
+  return shortdefname(m->full_name);
+}
+
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
+  return m->file->syntax;
+}
+
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
+  upb_value val;
+  return upb_inttable_lookup(&m->itof, i, &val) ? upb_value_getconstptr(val)
+                                                : NULL;
+}
+
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return unpack_def(val, UPB_DEFTYPE_FIELD);
+}
+
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return unpack_def(val, UPB_DEFTYPE_ONEOF);
+}
+
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return false;
+  }
+
+  *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
+  *f = unpack_def(val, UPB_DEFTYPE_FIELD);
+  return *o || *f;  /* False if this was a JSON name. */
+}
+
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+                                              const char *name, size_t len) {
+  upb_value val;
+  const upb_fielddef* f;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  f = unpack_def(val, UPB_DEFTYPE_FIELD);
+  if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME);
+
+  return f;
+}
+
+int upb_msgdef_numfields(const upb_msgdef *m) {
+  return m->field_count;
+}
+
+int upb_msgdef_numoneofs(const upb_msgdef *m) {
+  return m->oneof_count;
+}
+
+int upb_msgdef_numrealoneofs(const upb_msgdef *m) {
+  return m->real_oneof_count;
+}
+
+int upb_msgdef_fieldcount(const upb_msgdef *m) {
+  return m->field_count;
+}
+
+int upb_msgdef_oneofcount(const upb_msgdef *m) {
+  return m->oneof_count;
+}
+
+int upb_msgdef_realoneofcount(const upb_msgdef *m) {
+  return m->real_oneof_count;
+}
+
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) {
+  return m->layout;
+}
+
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i) {
+  UPB_ASSERT(i >= 0 && i < m->field_count);
+  return &m->fields[i];
+}
+
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i) {
+  UPB_ASSERT(i >= 0 && i < m->oneof_count);
+  return &m->oneofs[i];
+}
+
+bool upb_msgdef_mapentry(const upb_msgdef *m) {
+  return m->map_entry;
+}
+
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
+  return m->well_known_type;
+}
+
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
+  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+         type <= UPB_WELLKNOWN_UINT32VALUE;
+}
+
+bool upb_msgdef_iswrapper(const upb_msgdef *m) {
+  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+         type <= UPB_WELLKNOWN_BOOLVALUE;
+}
+
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
+  upb_inttable_begin(iter, &m->itof);
+}
+
+void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
+
+bool upb_msg_field_done(const upb_msg_field_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
+  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+                                const upb_msg_field_iter * iter2) {
+  return upb_inttable_iter_isequal(iter1, iter2);
+}
+
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
+  upb_strtable_begin(iter, &m->ntof);
+  /* We need to skip past any initial fields. */
+  while (!upb_strtable_done(iter) &&
+         !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
+    upb_strtable_next(iter);
+  }
+}
+
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
+  /* We need to skip past fields to return only oneofs. */
+  do {
+    upb_strtable_next(iter);
+  } while (!upb_strtable_done(iter) &&
+           !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
+}
+
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
+  return upb_strtable_done(iter);
+}
+
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
+  return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
+}
+
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
+  upb_strtable_iter_setdone(iter);
+}
+
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+                                const upb_msg_oneof_iter *iter2) {
+  return upb_strtable_iter_isequal(iter1, iter2);
+}
+
+/* upb_oneofdef ***************************************************************/
+
+const char *upb_oneofdef_name(const upb_oneofdef *o) {
+  return shortdefname(o->full_name);
+}
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
+  return o->parent;
+}
+
+int upb_oneofdef_fieldcount(const upb_oneofdef *o) {
+  return o->field_count;
+}
+
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i) {
+  UPB_ASSERT(i < o->field_count);
+  return o->fields[i];
+}
+
+int upb_oneofdef_numfields(const upb_oneofdef *o) {
+  return o->field_count;
+}
+
+uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
+  return o - o->parent->oneofs;
+}
+
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o) {
+  return o->synthetic;
+}
+
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup(&o->itof, num, &val) ? upb_value_getptr(val)
+                                                  : NULL;
+}
+
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
+  upb_inttable_begin(iter, &o->itof);
+}
+
+void upb_oneof_next(upb_oneof_iter *iter) {
+  upb_inttable_next(iter);
+}
+
+bool upb_oneof_done(upb_oneof_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
+  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f) {
+  return f->name;
+}
+
+const char *upb_filedef_package(const upb_filedef *f) {
+  return f->package;
+}
+
+const char *upb_filedef_phpprefix(const upb_filedef *f) {
+  return f->phpprefix;
+}
+
+const char *upb_filedef_phpnamespace(const upb_filedef *f) {
+  return f->phpnamespace;
+}
+
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
+  return f->syntax;
+}
+
+int upb_filedef_msgcount(const upb_filedef *f) {
+  return f->msg_count;
+}
+
+int upb_filedef_depcount(const upb_filedef *f) {
+  return f->dep_count;
+}
+
+int upb_filedef_enumcount(const upb_filedef *f) {
+  return f->enum_count;
+}
+
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
+}
+
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
+}
+
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
+}
+
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f) {
+  return f->symtab;
+}
+
+void upb_symtab_free(upb_symtab *s) {
+  upb_arena_free(s->arena);
+  upb_gfree(s);
+}
+
+upb_symtab *upb_symtab_new(void) {
+  upb_symtab *s = upb_gmalloc(sizeof(*s));
+
+  if (!s) {
+    return NULL;
+  }
+
+  s->arena = upb_arena_new();
+  s->bytes_loaded = 0;
+
+  if (!upb_strtable_init(&s->syms, 32, s->arena) ||
+      !upb_strtable_init(&s->files, 4, s->arena)) {
+    upb_arena_free(s->arena);
+    upb_gfree(s);
+    s = NULL;
+  }
+  return s;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  return upb_strtable_lookup(&s->syms, sym, &v) ?
+      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
+                                        size_t len) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
+      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  return upb_strtable_lookup(&s->syms, sym, &v) ?
+      unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
+  upb_value v;
+  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
+                                                  : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile2(
+    const upb_symtab *s, const char *name, size_t len) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->files, name, len, &v) ?
+      upb_value_getconstptr(v) : NULL;
+}
+
+int upb_symtab_filecount(const upb_symtab *s) {
+  return (int)upb_strtable_count(&s->files);
+}
+
+/* Code to build defs from descriptor protos. *********************************/
+
+/* There is a question of how much validation to do here.  It will be difficult
+ * to perfectly match the amount of validation performed by proto2.  But since
+ * this code is used to directly build defs from Ruby (for example) we do need
+ * to validate important constraints like uniqueness of names and numbers. */
+
+#define CHK_OOM(x) if (!(x)) { symtab_oomerr(ctx); }
+
+typedef struct {
+  upb_symtab *symtab;
+  upb_filedef *file;              /* File we are building. */
+  upb_arena *arena;               /* Allocate defs here. */
+  const upb_msglayout **layouts;  /* NULL if we should build layouts. */
+  upb_status *status;             /* Record errors here. */
+  jmp_buf err;                    /* longjmp() on error. */
+} symtab_addctx;
+
+UPB_NORETURN UPB_NOINLINE UPB_PRINTF(2, 3)
+static void symtab_errf(symtab_addctx *ctx, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_status_vseterrf(ctx->status, fmt, argp);
+  va_end(argp);
+  UPB_LONGJMP(ctx->err, 1);
+}
+
+UPB_NORETURN UPB_NOINLINE
+static void symtab_oomerr(symtab_addctx *ctx) {
+  upb_status_setoom(ctx->status);
+  UPB_LONGJMP(ctx->err, 1);
+}
+
+void *symtab_alloc(symtab_addctx *ctx, size_t bytes) {
+  void *ret = upb_arena_malloc(ctx->arena, bytes);
+  if (!ret) symtab_oomerr(ctx);
+  return ret;
+}
+
+static void check_ident(symtab_addctx *ctx, upb_strview name, bool full) {
+  const char *str = name.data;
+  size_t len = name.size;
+  bool start = true;
+  size_t i;
+  for (i = 0; i < len; i++) {
+    char c = str[i];
+    if (c == '.') {
+      if (start || !full) {
+        symtab_errf(ctx, "invalid name: unexpected '.' (%.*s)", (int)len, str);
+      }
+      start = true;
+    } else if (start) {
+      if (!upb_isletter(c)) {
+        symtab_errf(
+            ctx,
+            "invalid name: path components must start with a letter (%.*s)",
+            (int)len, str);
+      }
+      start = false;
+    } else {
+      if (!upb_isalphanum(c)) {
+        symtab_errf(ctx, "invalid name: non-alphanumeric character (%.*s)",
+                    (int)len, str);
+      }
+    }
+  }
+  if (start) {
+    symtab_errf(ctx, "invalid name: empty part (%.*s)", (int)len, str);
+  }
+}
+
+static size_t div_round_up(size_t n, size_t d) {
+  return (n + d - 1) / d;
+}
+
+static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return 8;
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_FLOAT:
+      return 4;
+    case UPB_TYPE_BOOL:
+      return 1;
+    case UPB_TYPE_MESSAGE:
+      return sizeof(void*);
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_STRING:
+      return sizeof(upb_strview);
+  }
+  UPB_UNREACHABLE();
+}
+
+static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
+  if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) {
+    upb_map_entry ent;
+    UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
+    return sizeof(ent.k);
+  } else if (upb_fielddef_isseq(f)) {
+    return sizeof(void*);
+  } else {
+    return upb_msgval_sizeof(upb_fielddef_type(f));
+  }
+}
+
+static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) {
+  uint32_t ret;
+
+  l->size = UPB_ALIGN_UP(l->size, size);
+  ret = l->size;
+  l->size += size;
+  return ret;
+}
+
+static int field_number_cmp(const void *p1, const void *p2) {
+  const upb_msglayout_field *f1 = p1;
+  const upb_msglayout_field *f2 = p2;
+  return f1->number - f2->number;
+}
+
+static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) {
+  int i;
+  int n = upb_msgdef_numfields(m);
+  for (i = 0; i < n; i++) {
+    upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number);
+    UPB_ASSERT(f);
+    f->layout_index = i;
+  }
+}
+
+/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
+ * It computes a dynamic layout for all of the fields in |m|. */
+static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
+  upb_msglayout *l = (upb_msglayout*)m->layout;
+  upb_msg_field_iter it;
+  upb_msg_oneof_iter oit;
+  size_t hasbit;
+  size_t field_count = upb_msgdef_numfields(m);
+  size_t submsg_count = 0;
+  const upb_msglayout **submsgs;
+  upb_msglayout_field *fields;
+
+  memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry));
+
+  /* Count sub-messages. */
+  for (size_t i = 0; i < field_count; i++) {
+    if (upb_fielddef_issubmsg(&m->fields[i])) {
+      submsg_count++;
+    }
+  }
+
+  fields = symtab_alloc(ctx, field_count * sizeof(*fields));
+  submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs));
+
+  l->field_count = upb_msgdef_numfields(m);
+  l->fields = fields;
+  l->submsgs = submsgs;
+  l->table_mask = 0;
+
+  /* TODO(haberman): initialize fast tables so that reflection-based parsing
+   * can get the same speeds as linked-in types. */
+  l->fasttable[0].field_parser = &fastdecode_generic;
+  l->fasttable[0].field_data = 0;
+
+  if (upb_msgdef_mapentry(m)) {
+    /* TODO(haberman): refactor this method so this special case is more
+     * elegant. */
+    const upb_fielddef *key = upb_msgdef_itof(m, 1);
+    const upb_fielddef *val = upb_msgdef_itof(m, 2);
+    fields[0].number = 1;
+    fields[1].number = 2;
+    fields[0].label = UPB_LABEL_OPTIONAL;
+    fields[1].label = UPB_LABEL_OPTIONAL;
+    fields[0].presence = 0;
+    fields[1].presence = 0;
+    fields[0].descriptortype = upb_fielddef_descriptortype(key);
+    fields[1].descriptortype = upb_fielddef_descriptortype(val);
+    fields[0].offset = 0;
+    fields[1].offset = sizeof(upb_strview);
+    fields[1].submsg_index = 0;
+
+    if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) {
+      submsgs[0] = upb_fielddef_msgsubdef(val)->layout;
+    }
+
+    l->field_count = 2;
+    l->size = 2 * sizeof(upb_strview);
+    l->size = UPB_ALIGN_UP(l->size, 8);
+    return;
+  }
+
+  /* Allocate data offsets in three stages:
+   *
+   * 1. hasbits.
+   * 2. regular fields.
+   * 3. oneof fields.
+   *
+   * OPT: There is a lot of room for optimization here to minimize the size.
+   */
+
+  /* Allocate hasbits and set basic field attributes. */
+  submsg_count = 0;
+  for (upb_msg_field_begin(&it, m), hasbit = 0;
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    upb_fielddef* f = upb_msg_iter_field(&it);
+    upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
+
+    field->number = upb_fielddef_number(f);
+    field->descriptortype = upb_fielddef_descriptortype(f);
+    field->label = upb_fielddef_label(f);
+
+    if (field->descriptortype == UPB_DTYPE_STRING &&
+        f->file->syntax == UPB_SYNTAX_PROTO2) {
+      /* See TableDescriptorType() in upbc/generator.cc for details and
+       * rationale. */
+      field->descriptortype = UPB_DTYPE_BYTES;
+    }
+
+    if (upb_fielddef_ismap(f)) {
+      field->label = _UPB_LABEL_MAP;
+    } else if (upb_fielddef_packed(f)) {
+      field->label = _UPB_LABEL_PACKED;
+    }
+
+    if (upb_fielddef_issubmsg(f)) {
+      const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+      field->submsg_index = submsg_count++;
+      submsgs[field->submsg_index] = subm->layout;
+    }
+
+    if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) {
+      /* We don't use hasbit 0, so that 0 can indicate "no presence" in the
+       * table. This wastes one hasbit, but we don't worry about it for now. */
+      field->presence = ++hasbit;
+    } else {
+      field->presence = 0;
+    }
+  }
+
+  /* Account for space used by hasbits. */
+  l->size = div_round_up(hasbit, 8);
+
+  /* Allocate non-oneof fields. */
+  for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* f = upb_msg_iter_field(&it);
+    size_t field_size = upb_msg_fielddefsize(f);
+    size_t index = upb_fielddef_index(f);
+
+    if (upb_fielddef_realcontainingoneof(f)) {
+      /* Oneofs are handled separately below. */
+      continue;
+    }
+
+    fields[index].offset = upb_msglayout_place(l, field_size);
+  }
+
+  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
+   * and space for the actual data. */
+  for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
+    upb_oneof_iter fit;
+
+    size_t case_size = sizeof(uint32_t);  /* Could potentially optimize this. */
+    size_t field_size = 0;
+    uint32_t case_offset;
+    uint32_t data_offset;
+
+    if (upb_oneofdef_issynthetic(o)) continue;
+
+    /* Calculate field size: the max of all field sizes. */
+    for (upb_oneof_begin(&fit, o);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* f = upb_oneof_iter_field(&fit);
+      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
+    }
+
+    /* Align and allocate case offset. */
+    case_offset = upb_msglayout_place(l, case_size);
+    data_offset = upb_msglayout_place(l, field_size);
+
+    for (upb_oneof_begin(&fit, o);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* f = upb_oneof_iter_field(&fit);
+      fields[upb_fielddef_index(f)].offset = data_offset;
+      fields[upb_fielddef_index(f)].presence = ~case_offset;
+    }
+  }
+
+  /* Size of the entire structure should be a multiple of its greatest
+   * alignment.  TODO: track overall alignment for real? */
+  l->size = UPB_ALIGN_UP(l->size, 8);
+
+  /* Sort fields by number. */
+  qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp);
+  assign_layout_indices(m, fields);
+}
+
+static char *strviewdup(symtab_addctx *ctx, upb_strview view) {
+  return upb_strdup2(view.data, view.size, ctx->arena);
+}
+
+static bool streql2(const char *a, size_t n, const char *b) {
+  return n == strlen(b) && memcmp(a, b, n) == 0;
+}
+
+static bool streql_view(upb_strview view, const char *b) {
+  return streql2(view.data, view.size, b);
+}
+
+static const char *makefullname(symtab_addctx *ctx, const char *prefix,
+                                upb_strview name) {
+  if (prefix) {
+    /* ret = prefix + '.' + name; */
+    size_t n = strlen(prefix);
+    char *ret = symtab_alloc(ctx, n + name.size + 2);
+    strcpy(ret, prefix);
+    ret[n] = '.';
+    memcpy(&ret[n + 1], name.data, name.size);
+    ret[n + 1 + name.size] = '\0';
+    return ret;
+  } else {
+    return strviewdup(ctx, name);
+  }
+}
+
+static void finalize_oneofs(symtab_addctx *ctx, upb_msgdef *m) {
+  int i;
+  int synthetic_count = 0;
+  upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs;
+
+  for (i = 0; i < m->oneof_count; i++) {
+    upb_oneofdef *o = &mutable_oneofs[i];
+
+    if (o->synthetic && o->field_count != 1) {
+      symtab_errf(ctx, "Synthetic oneofs must have one field, not %d: %s",
+                  o->field_count, upb_oneofdef_name(o));
+    }
+
+    if (o->synthetic) {
+      synthetic_count++;
+    } else if (synthetic_count != 0) {
+      symtab_errf(ctx, "Synthetic oneofs must be after all other oneofs: %s",
+                  upb_oneofdef_name(o));
+    }
+
+    o->fields = symtab_alloc(ctx, sizeof(upb_fielddef *) * o->field_count);
+    o->field_count = 0;
+  }
+
+  for (i = 0; i < m->field_count; i++) {
+    const upb_fielddef *f = &m->fields[i];
+    upb_oneofdef *o = (upb_oneofdef*)f->oneof;
+    if (o) {
+      o->fields[o->field_count++] = f;
+    }
+  }
+
+  m->real_oneof_count = m->oneof_count - synthetic_count;
+}
+
+size_t getjsonname(const char *name, char *buf, size_t len) {
+  size_t src, dst = 0;
+  bool ucase_next = false;
+
+#define WRITE(byte) \
+  ++dst; \
+  if (dst < len) buf[dst - 1] = byte; \
+  else if (dst == len) buf[dst - 1] = '\0'
+
+  if (!name) {
+    WRITE('\0');
+    return 0;
+  }
+
+  /* Implement the transformation as described in the spec:
+   *   1. upper case all letters after an underscore.
+   *   2. remove all underscores.
+   */
+  for (src = 0; name[src]; src++) {
+    if (name[src] == '_') {
+      ucase_next = true;
+      continue;
+    }
+
+    if (ucase_next) {
+      WRITE(toupper(name[src]));
+      ucase_next = false;
+    } else {
+      WRITE(name[src]);
+    }
+  }
+
+  WRITE('\0');
+  return dst;
+
+#undef WRITE
+}
+
+static char* makejsonname(symtab_addctx *ctx, const char* name) {
+  size_t size = getjsonname(name, NULL, 0);
+  char* json_name = symtab_alloc(ctx, size);
+  getjsonname(name, json_name, size);
+  return json_name;
+}
+
+static void symtab_add(symtab_addctx *ctx, const char *name, upb_value v) {
+  if (upb_strtable_lookup(&ctx->symtab->syms, name, NULL)) {
+    symtab_errf(ctx, "duplicate symbol '%s'", name);
+  }
+  size_t len = strlen(name);
+  CHK_OOM(upb_strtable_insert(&ctx->symtab->syms, name, len, v,
+                              ctx->symtab->arena));
+}
+
+/* Given a symbol and the base symbol inside which it is defined, find the
+ * symbol's definition in t. */
+static const void *symtab_resolve(symtab_addctx *ctx, const upb_fielddef *f,
+                                  const char *base, upb_strview sym,
+                                  upb_deftype_t type) {
+  const upb_strtable *t = &ctx->symtab->syms;
+  if(sym.size == 0) goto notfound;
+  if(sym.data[0] == '.') {
+    /* Symbols starting with '.' are absolute, so we do a single lookup.
+     * Slice to omit the leading '.' */
+    upb_value v;
+    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
+      goto notfound;
+    }
+
+    const void *ret = unpack_def(v, type);
+    if (!ret) {
+      symtab_errf(ctx, "type mismatch when resolving field %s, name %s",
+                  f->full_name, sym.data);
+    }
+    return ret;
+  } else {
+    /* Remove components from base until we find an entry or run out.
+     * TODO: This branch is totally broken, but currently not used. */
+    (void)base;
+    UPB_ASSERT(false);
+    goto notfound;
+  }
+
+notfound:
+  symtab_errf(ctx, "couldn't resolve name '" UPB_STRVIEW_FORMAT "'",
+              UPB_STRVIEW_ARGS(sym));
+}
+
+static void create_oneofdef(
+    symtab_addctx *ctx, upb_msgdef *m,
+    const google_protobuf_OneofDescriptorProto *oneof_proto) {
+  upb_oneofdef *o;
+  upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
+  upb_value v;
+
+  o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
+  o->parent = m;
+  o->full_name = makefullname(ctx, m->full_name, name);
+  o->field_count = 0;
+  o->synthetic = false;
+
+  v = pack_def(o, UPB_DEFTYPE_ONEOF);
+  symtab_add(ctx, o->full_name, v);
+  CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, v, ctx->arena));
+
+  CHK_OOM(upb_inttable_init(&o->itof, ctx->arena));
+  CHK_OOM(upb_strtable_init(&o->ntof, 4, ctx->arena));
+}
+
+static str_t *newstr(symtab_addctx *ctx, const char *data, size_t len) {
+  str_t *ret = symtab_alloc(ctx, sizeof(*ret) + len);
+  if (!ret) return NULL;
+  ret->len = len;
+  if (len) memcpy(ret->str, data, len);
+  ret->str[len] = '\0';
+  return ret;
+}
+
+static void parse_default(symtab_addctx *ctx, const char *str, size_t len,
+                          upb_fielddef *f) {
+  char *end;
+  char nullz[64];
+  errno = 0;
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_FLOAT:
+      /* Standard C number parsing functions expect null-terminated strings. */
+      if (len >= sizeof(nullz) - 1) {
+        symtab_errf(ctx, "Default too long: %.*s", (int)len, str);
+      }
+      memcpy(nullz, str, len);
+      nullz[len] = '\0';
+      str = nullz;
+      break;
+    default:
+      break;
+  }
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32: {
+      long val = strtol(str, &end, 0);
+      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_ENUM: {
+      const upb_enumdef *e = f->sub.enumdef;
+      int32_t val;
+      if (!upb_enumdef_ntoi(e, str, len, &val)) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_INT64: {
+      long long val = strtoll(str, &end, 0);
+      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(str, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case UPB_TYPE_UINT64: {
+      unsigned long long val = strtoull(str, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      double val = strtod(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.dbl = val;
+      break;
+    }
+    case UPB_TYPE_FLOAT: {
+      float val = strtof(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.flt = val;
+      break;
+    }
+    case UPB_TYPE_BOOL: {
+      if (streql2(str, len, "false")) {
+        f->defaultval.boolean = false;
+      } else if (streql2(str, len, "true")) {
+        f->defaultval.boolean = true;
+      } else {
+      }
+      break;
+    }
+    case UPB_TYPE_STRING:
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case UPB_TYPE_BYTES:
+      /* XXX: need to interpret the C-escaped value. */
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case UPB_TYPE_MESSAGE:
+      /* Should not have a default value. */
+      symtab_errf(ctx, "Message should not have a default (%s)",
+                  upb_fielddef_fullname(f));
+  }
+
+  return;
+
+invalid:
+  symtab_errf(ctx, "Invalid default '%.*s' for field %s", (int)len, str,
+              upb_fielddef_fullname(f));
+}
+
+static void set_default_default(symtab_addctx *ctx, upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_ENUM:
+      f->defaultval.sint = 0;
+      break;
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_UINT32:
+      f->defaultval.uint = 0;
+      break;
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_FLOAT:
+      f->defaultval.dbl = 0;
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      f->defaultval.str = newstr(ctx, NULL, 0);
+      break;
+    case UPB_TYPE_BOOL:
+      f->defaultval.boolean = false;
+      break;
+    case UPB_TYPE_MESSAGE:
+      break;
+  }
+}
+
+static void create_fielddef(
+    symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
+    const google_protobuf_FieldDescriptorProto *field_proto) {
+  upb_fielddef *f;
+  const google_protobuf_FieldOptions *options;
+  upb_strview name;
+  const char *full_name;
+  const char *json_name;
+  const char *shortname;
+  uint32_t field_number;
+
+  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
+    symtab_errf(ctx, "field has no name (%s)", upb_msgdef_fullname(m));
+  }
+
+  name = google_protobuf_FieldDescriptorProto_name(field_proto);
+  check_ident(ctx, name, false);
+  full_name = makefullname(ctx, prefix, name);
+  shortname = shortdefname(full_name);
+
+  if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
+    json_name = strviewdup(
+        ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
+  } else {
+    json_name = makejsonname(ctx, shortname);
+  }
+
+  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
+
+  if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
+    symtab_errf(ctx, "invalid field number (%u)", field_number);
+  }
+
+  if (m) {
+    /* direct message field. */
+    upb_value v, field_v, json_v;
+    size_t json_size;
+
+    f = (upb_fielddef*)&m->fields[m->field_count];
+    f->index_ = m->field_count++;
+    f->msgdef = m;
+    f->is_extension_ = false;
+
+    if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
+      symtab_errf(ctx, "duplicate field name (%s)", shortname);
+    }
+
+    if (upb_strtable_lookup(&m->ntof, json_name, NULL)) {
+      symtab_errf(ctx, "duplicate json_name (%s)", json_name);
+    }
+
+    if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
+      symtab_errf(ctx, "duplicate field number (%u)", field_number);
+    }
+
+    field_v = pack_def(f, UPB_DEFTYPE_FIELD);
+    json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME);
+    v = upb_value_constptr(f);
+    json_size = strlen(json_name);
+
+    CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, field_v,
+                                ctx->arena));
+    CHK_OOM(upb_inttable_insert(&m->itof, field_number, v, ctx->arena));
+
+    if (strcmp(shortname, json_name) != 0) {
+      upb_strtable_insert(&m->ntof, json_name, json_size, json_v, ctx->arena);
+    }
+
+    if (ctx->layouts) {
+      const upb_msglayout_field *fields = m->layout->fields;
+      int count = m->layout->field_count;
+      bool found = false;
+      int i;
+      for (i = 0; i < count; i++) {
+        if (fields[i].number == field_number) {
+          f->layout_index = i;
+          found = true;
+          break;
+        }
+      }
+      UPB_ASSERT(found);
+    }
+  } else {
+    /* extension field. */
+    f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++];
+    f->is_extension_ = true;
+    symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD));
+  }
+
+  f->full_name = full_name;
+  f->json_name = json_name;
+  f->file = ctx->file;
+  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
+  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
+  f->number_ = field_number;
+  f->oneof = NULL;
+  f->proto3_optional_ =
+      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
+
+  /* We can't resolve the subdef or (in the case of extensions) the containing
+   * message yet, because it may not have been defined yet.  We stash a pointer
+   * to the field_proto until later when we can properly resolve it. */
+  f->sub.unresolved = field_proto;
+
+  if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
+    symtab_errf(ctx, "proto3 fields cannot be required (%s)", f->full_name);
+  }
+
+  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    int oneof_index =
+        google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
+    upb_oneofdef *oneof;
+    upb_value v = upb_value_constptr(f);
+
+    if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
+      symtab_errf(ctx, "fields in oneof must have OPTIONAL label (%s)",
+                  f->full_name);
+    }
+
+    if (!m) {
+      symtab_errf(ctx, "oneof_index provided for extension field (%s)",
+                  f->full_name);
+    }
+
+    if (oneof_index >= m->oneof_count) {
+      symtab_errf(ctx, "oneof_index out of range (%s)", f->full_name);
+    }
+
+    oneof = (upb_oneofdef *)&m->oneofs[oneof_index];
+    f->oneof = oneof;
+
+    oneof->field_count++;
+    if (f->proto3_optional_) {
+      oneof->synthetic = true;
+    }
+    CHK_OOM(upb_inttable_insert(&oneof->itof, f->number_, v, ctx->arena));
+    CHK_OOM(
+        upb_strtable_insert(&oneof->ntof, name.data, name.size, v, ctx->arena));
+  } else {
+    f->oneof = NULL;
+    if (f->proto3_optional_) {
+      symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)",
+                  f->full_name);
+    }
+  }
+
+  options = google_protobuf_FieldDescriptorProto_has_options(field_proto) ?
+    google_protobuf_FieldDescriptorProto_options(field_proto) : NULL;
+
+  if (options && google_protobuf_FieldOptions_has_packed(options)) {
+    f->packed_ = google_protobuf_FieldOptions_packed(options);
+  } else {
+    /* Repeated fields default to packed for proto3 only. */
+    f->packed_ = upb_fielddef_isprimitive(f) &&
+        f->label_ == UPB_LABEL_REPEATED && f->file->syntax == UPB_SYNTAX_PROTO3;
+  }
+
+  if (options) {
+    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
+  } else {
+    f->lazy_ = false;
+  }
+}
+
+static void create_enumdef(
+    symtab_addctx *ctx, const char *prefix,
+    const google_protobuf_EnumDescriptorProto *enum_proto) {
+  upb_enumdef *e;
+  const google_protobuf_EnumValueDescriptorProto *const *values;
+  upb_strview name;
+  size_t i, n;
+
+  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
+  check_ident(ctx, name, false);
+
+  e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
+  e->full_name = makefullname(ctx, prefix, name);
+  symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM));
+
+  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
+  CHK_OOM(upb_strtable_init(&e->ntoi, n, ctx->arena));
+  CHK_OOM(upb_inttable_init(&e->iton, ctx->arena));
+
+  e->file = ctx->file;
+  e->defaultval = 0;
+
+  if (n == 0) {
+    symtab_errf(ctx, "enums must contain at least one value (%s)",
+                e->full_name);
+  }
+
+  for (i = 0; i < n; i++) {
+    const google_protobuf_EnumValueDescriptorProto *value = values[i];
+    upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
+    char *name2 = strviewdup(ctx, name);
+    int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
+    upb_value v = upb_value_int32(num);
+
+    if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
+      symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)",
+                  e->full_name);
+    }
+
+    if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
+      symtab_errf(ctx, "duplicate enum label '%s'", name2);
+    }
+
+    CHK_OOM(name2)
+    CHK_OOM(upb_strtable_insert(&e->ntoi, name2, strlen(name2), v, ctx->arena));
+
+    if (!upb_inttable_lookup(&e->iton, num, NULL)) {
+      upb_value v = upb_value_cstr(name2);
+      CHK_OOM(upb_inttable_insert(&e->iton, num, v, ctx->arena));
+    }
+  }
+
+  upb_inttable_compact(&e->iton, ctx->arena);
+}
+
+static void create_msgdef(symtab_addctx *ctx, const char *prefix,
+                          const google_protobuf_DescriptorProto *msg_proto) {
+  upb_msgdef *m;
+  const google_protobuf_MessageOptions *options;
+  const google_protobuf_OneofDescriptorProto *const *oneofs;
+  const google_protobuf_FieldDescriptorProto *const *fields;
+  const google_protobuf_EnumDescriptorProto *const *enums;
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n_oneof, n_field, n;
+  upb_strview name;
+
+  name = google_protobuf_DescriptorProto_name(msg_proto);
+  check_ident(ctx, name, false);
+
+  m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
+  m->full_name = makefullname(ctx, prefix, name);
+  symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG));
+
+  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof);
+  fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field);
+
+  CHK_OOM(upb_inttable_init(&m->itof, ctx->arena));
+  CHK_OOM(upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena));
+
+  m->file = ctx->file;
+  m->map_entry = false;
+
+  options = google_protobuf_DescriptorProto_options(msg_proto);
+
+  if (options) {
+    m->map_entry = google_protobuf_MessageOptions_map_entry(options);
+  }
+
+  if (ctx->layouts) {
+    m->layout = *ctx->layouts;
+    ctx->layouts++;
+  } else {
+    /* Allocate now (to allow cross-linking), populate later. */
+    m->layout = symtab_alloc(
+        ctx, sizeof(*m->layout) + sizeof(_upb_fasttable_entry));
+  }
+
+  m->oneof_count = 0;
+  m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof);
+  for (i = 0; i < n_oneof; i++) {
+    create_oneofdef(ctx, m, oneofs[i]);
+  }
+
+  m->field_count = 0;
+  m->fields = symtab_alloc(ctx, sizeof(*m->fields) * n_field);
+  for (i = 0; i < n_field; i++) {
+    create_fielddef(ctx, m->full_name, m, fields[i]);
+  }
+
+  finalize_oneofs(ctx, m);
+  assign_msg_wellknowntype(m);
+  upb_inttable_compact(&m->itof, ctx->arena);
+
+  /* This message is built.  Now build nested messages and enums. */
+
+  enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_enumdef(ctx, m->full_name, enums[i]);
+  }
+
+  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_msgdef(ctx, m->full_name, msgs[i]);
+  }
+}
+
+static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
+                               upb_filedef *file) {
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n;
+
+  file->msg_count++;
+
+  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    count_types_in_msg(msgs[i], file);
+  }
+
+  google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+  file->enum_count += n;
+
+  google_protobuf_DescriptorProto_extension(msg_proto, &n);
+  file->ext_count += n;
+}
+
+static void count_types_in_file(
+    const google_protobuf_FileDescriptorProto *file_proto,
+    upb_filedef *file) {
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n;
+
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    count_types_in_msg(msgs[i], file);
+  }
+
+  google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  file->enum_count += n;
+
+  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->ext_count += n;
+}
+
+static void resolve_fielddef(symtab_addctx *ctx, const char *prefix,
+                             upb_fielddef *f) {
+  upb_strview name;
+  const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
+
+  if (f->is_extension_) {
+    if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
+      symtab_errf(ctx, "extension for field '%s' had no extendee",
+                  f->full_name);
+    }
+
+    name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
+    f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+  }
+
+  if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
+      !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
+    symtab_errf(ctx, "field '%s' is missing type name", f->full_name);
+  }
+
+  name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
+
+  if (upb_fielddef_issubmsg(f)) {
+    f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+  } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
+    f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
+  }
+
+  /* Have to delay resolving of the default value until now because of the enum
+   * case, since enum defaults are specified with a label. */
+  if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
+    upb_strview defaultval =
+        google_protobuf_FieldDescriptorProto_default_value(field_proto);
+
+    if (f->file->syntax == UPB_SYNTAX_PROTO3) {
+      symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)",
+                  f->full_name);
+    }
+
+    if (upb_fielddef_issubmsg(f)) {
+      symtab_errf(ctx, "message fields cannot have explicit defaults (%s)",
+                  f->full_name);
+    }
+
+    parse_default(ctx, defaultval.data, defaultval.size, f);
+  } else {
+    set_default_default(ctx, f);
+  }
+}
+
+static void build_filedef(
+    symtab_addctx *ctx, upb_filedef *file,
+    const google_protobuf_FileDescriptorProto *file_proto) {
+  const google_protobuf_FileOptions *file_options_proto;
+  const google_protobuf_DescriptorProto *const *msgs;
+  const google_protobuf_EnumDescriptorProto *const *enums;
+  const google_protobuf_FieldDescriptorProto *const *exts;
+  const upb_strview* strs;
+  size_t i, n;
+
+  count_types_in_file(file_proto, file);
+
+  file->msgs = symtab_alloc(ctx, sizeof(*file->msgs) * file->msg_count);
+  file->enums = symtab_alloc(ctx, sizeof(*file->enums) * file->enum_count);
+  file->exts = symtab_alloc(ctx, sizeof(*file->exts) * file->ext_count);
+
+  /* We increment these as defs are added. */
+  file->msg_count = 0;
+  file->enum_count = 0;
+  file->ext_count = 0;
+
+  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
+    symtab_errf(ctx, "File has no name");
+  }
+
+  file->name =
+      strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
+  file->phpprefix = NULL;
+  file->phpnamespace = NULL;
+
+  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
+    upb_strview package =
+        google_protobuf_FileDescriptorProto_package(file_proto);
+    check_ident(ctx, package, true);
+    file->package = strviewdup(ctx, package);
+  } else {
+    file->package = NULL;
+  }
+
+  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
+    upb_strview syntax =
+        google_protobuf_FileDescriptorProto_syntax(file_proto);
+
+    if (streql_view(syntax, "proto2")) {
+      file->syntax = UPB_SYNTAX_PROTO2;
+    } else if (streql_view(syntax, "proto3")) {
+      file->syntax = UPB_SYNTAX_PROTO3;
+    } else {
+      symtab_errf(ctx, "Invalid syntax '" UPB_STRVIEW_FORMAT "'",
+                  UPB_STRVIEW_ARGS(syntax));
+    }
+  } else {
+    file->syntax = UPB_SYNTAX_PROTO2;
+  }
+
+  /* Read options. */
+  file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
+  if (file_options_proto) {
+    if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
+      file->phpprefix = strviewdup(
+          ctx,
+          google_protobuf_FileOptions_php_class_prefix(file_options_proto));
+    }
+    if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
+      file->phpnamespace = strviewdup(
+          ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
+    }
+  }
+
+  /* Verify dependencies. */
+  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
+  file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n);
+
+  for (i = 0; i < n; i++) {
+    upb_strview dep_name = strs[i];
+    upb_value v;
+    if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
+                              dep_name.size, &v)) {
+      symtab_errf(ctx,
+                  "Depends on file '" UPB_STRVIEW_FORMAT
+                  "', but it has not been loaded",
+                  UPB_STRVIEW_ARGS(dep_name));
+    }
+    file->deps[i] = upb_value_getconstptr(v);
+  }
+
+  /* Create messages. */
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_msgdef(ctx, file->package, msgs[i]);
+  }
+
+  /* Create enums. */
+  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_enumdef(ctx, file->package, enums[i]);
+  }
+
+  /* Create extensions. */
+  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->exts = symtab_alloc(ctx, sizeof(*file->exts) * n);
+  for (i = 0; i < n; i++) {
+    create_fielddef(ctx, file->package, NULL, exts[i]);
+  }
+
+  /* Now that all names are in the table, build layouts and resolve refs. */
+  for (i = 0; i < (size_t)file->ext_count; i++) {
+    resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]);
+  }
+
+  for (i = 0; i < (size_t)file->msg_count; i++) {
+    const upb_msgdef *m = &file->msgs[i];
+    int j;
+    for (j = 0; j < m->field_count; j++) {
+      resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]);
+    }
+  }
+
+  if (!ctx->layouts) {
+    for (i = 0; i < (size_t)file->msg_count; i++) {
+      const upb_msgdef *m = &file->msgs[i];
+      make_layout(ctx, m);
+    }
+  }
+}
+
+static void remove_filedef(upb_symtab *s, upb_filedef *file) {
+  int i;
+  for (i = 0; i < file->msg_count; i++) {
+    const char *name = file->msgs[i].full_name;
+    upb_strtable_remove(&s->syms, name, strlen(name), NULL);
+  }
+  for (i = 0; i < file->enum_count; i++) {
+    const char *name = file->enums[i].full_name;
+    upb_strtable_remove(&s->syms, name, strlen(name), NULL);
+  }
+  for (i = 0; i < file->ext_count; i++) {
+    const char *name = file->exts[i].full_name;
+    upb_strtable_remove(&s->syms, name, strlen(name), NULL);
+  }
+}
+
+static const upb_filedef *_upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+    const upb_msglayout **layouts, upb_status *status) {
+  upb_arena *file_arena = upb_arena_new();
+  upb_filedef *file;
+  symtab_addctx ctx;
+
+  if (!file_arena) return NULL;
+
+  file = upb_arena_malloc(file_arena, sizeof(*file));
+  if (!file) goto done;
+
+  ctx.file = file;
+  ctx.symtab = s;
+  ctx.arena = file_arena;
+  ctx.layouts = layouts;
+  ctx.status = status;
+
+  file->msg_count = 0;
+  file->enum_count = 0;
+  file->ext_count = 0;
+  file->symtab = s;
+
+  if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) {
+    UPB_ASSERT(!upb_ok(status));
+    remove_filedef(s, file);
+    file = NULL;
+  } else {
+    build_filedef(&ctx, file, file_proto);
+    upb_strtable_insert(&s->files, file->name, strlen(file->name),
+                        upb_value_constptr(file), ctx.arena);
+    UPB_ASSERT(upb_ok(status));
+    upb_arena_fuse(s->arena, file_arena);
+  }
+
+done:
+  upb_arena_free(file_arena);
+  return file;
+}
+
+const upb_filedef *upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+    upb_status *status) {
+  return _upb_symtab_addfile(s, file_proto, NULL, status);
+}
+
+/* Include here since we want most of this file to be stdio-free. */
+#include <stdio.h>
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
+  /* Since this function should never fail (it would indicate a bug in upb) we
+   * print errors to stderr instead of returning error status to the user. */
+  upb_def_init **deps = init->deps;
+  google_protobuf_FileDescriptorProto *file;
+  upb_arena *arena;
+  upb_status status;
+
+  upb_status_clear(&status);
+
+  if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
+    return true;
+  }
+
+  arena = upb_arena_new();
+
+  for (; *deps; deps++) {
+    if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
+  }
+
+  file = google_protobuf_FileDescriptorProto_parse_ex(
+      init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS);
+  s->bytes_loaded += init->descriptor.size;
+
+  if (!file) {
+    upb_status_seterrf(
+        &status,
+        "Failed to parse compiled-in descriptor for file '%s'. This should "
+        "never happen.",
+        init->filename);
+    goto err;
+  }
+
+  if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err;
+
+  upb_arena_free(arena);
+  return true;
+
+err:
+  fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
+          upb_status_errmsg(&status));
+  upb_arena_free(arena);
+  return false;
+}
+
+size_t _upb_symtab_bytesloaded(const upb_symtab *s) {
+  return s->bytes_loaded;
+}
+
+upb_arena *_upb_symtab_arena(const upb_symtab *s) {
+  return s->arena;
+}
+
+#undef CHK_OOM
+
+/** upb/reflection.c ************************************************************/
+
+#include <string.h>
+
+
+static size_t get_field_size(const upb_msglayout_field *f) {
+  static unsigned char sizes[] = {
+    0,/* 0 */
+    8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
+    4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
+    8, /* UPB_DESCRIPTOR_TYPE_INT64 */
+    8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
+    4, /* UPB_DESCRIPTOR_TYPE_INT32 */
+    8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
+    4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
+    1, /* UPB_DESCRIPTOR_TYPE_BOOL */
+    sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
+    sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
+    sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
+    sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
+    4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
+    4, /* UPB_DESCRIPTOR_TYPE_ENUM */
+    4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
+    8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
+    4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
+    8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
+  };
+  return _upb_repeated_or_map(f) ? sizeof(void *) : sizes[f->descriptortype];
+}
+
+/* Strings/bytes are special-cased in maps. */
+static char _upb_fieldtype_to_mapsize[12] = {
+  0,
+  1,  /* UPB_TYPE_BOOL */
+  4,  /* UPB_TYPE_FLOAT */
+  4,  /* UPB_TYPE_INT32 */
+  4,  /* UPB_TYPE_UINT32 */
+  4,  /* UPB_TYPE_ENUM */
+  sizeof(void*),  /* UPB_TYPE_MESSAGE */
+  8,  /* UPB_TYPE_DOUBLE */
+  8,  /* UPB_TYPE_INT64 */
+  8,  /* UPB_TYPE_UINT64 */
+  0,  /* UPB_TYPE_STRING */
+  0,  /* UPB_TYPE_BYTES */
+};
+
+static const char _upb_fieldtype_to_sizelg2[12] = {
+  0,
+  0,  /* UPB_TYPE_BOOL */
+  2,  /* UPB_TYPE_FLOAT */
+  2,  /* UPB_TYPE_INT32 */
+  2,  /* UPB_TYPE_UINT32 */
+  2,  /* UPB_TYPE_ENUM */
+  UPB_SIZE(2, 3),  /* UPB_TYPE_MESSAGE */
+  3,  /* UPB_TYPE_DOUBLE */
+  3,  /* UPB_TYPE_INT64 */
+  3,  /* UPB_TYPE_UINT64 */
+  UPB_SIZE(3, 4),  /* UPB_TYPE_STRING */
+  UPB_SIZE(3, 4),  /* UPB_TYPE_BYTES */
+};
+
+/** upb_msg *******************************************************************/
+
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
+  return _upb_msg_new(upb_msgdef_layout(m), a);
+}
+
+static bool in_oneof(const upb_msglayout_field *field) {
+  return field->presence < 0;
+}
+
+static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  const char *mem = UPB_PTR_AT(msg, field->offset, char);
+  upb_msgval val = {0};
+  memcpy(&val, mem, get_field_size(field));
+  return val;
+}
+
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  if (in_oneof(field)) {
+    return _upb_getoneofcase_field(msg, field) == field->number;
+  } else if (field->presence > 0) {
+    return _upb_hasbit_field(msg, field);
+  } else {
+    UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
+               field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
+    return _upb_msg_getraw(msg, f).msg_val != NULL;
+  }
+}
+
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+                                       const upb_oneofdef *o) {
+  const upb_fielddef *f = upb_oneofdef_field(o, 0);
+  if (upb_oneofdef_issynthetic(o)) {
+    UPB_ASSERT(upb_oneofdef_fieldcount(o) == 1);
+    return upb_msg_has(msg, f) ? f : NULL;
+  } else {
+    const upb_msglayout_field *field = upb_fielddef_layout(f);
+    uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
+    f = oneof_case ? upb_oneofdef_itof(o, oneof_case) : NULL;
+    UPB_ASSERT((f != NULL) == (oneof_case != 0));
+    return f;
+  }
+}
+
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
+  if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
+    return _upb_msg_getraw(msg, f);
+  } else {
+    return upb_fielddef_default(f);
+  }
+}
+
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
+                              upb_arena *a) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  upb_mutmsgval ret;
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+  bool wrong_oneof =
+      in_oneof(field) && _upb_getoneofcase_field(msg, field) != field->number;
+
+  memcpy(&ret, mem, sizeof(void*));
+
+  if (a && (!ret.msg || wrong_oneof)) {
+    if (upb_fielddef_ismap(f)) {
+      const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+      const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
+      const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
+      ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
+    } else if (upb_fielddef_isseq(f)) {
+      ret.array = upb_array_new(a, upb_fielddef_type(f));
+    } else {
+      UPB_ASSERT(upb_fielddef_issubmsg(f));
+      ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
+    }
+
+    memcpy(mem, &ret, sizeof(void*));
+
+    if (wrong_oneof) {
+      *_upb_oneofcase_field(msg, field) = field->number;
+    } else if (field->presence > 0) {
+      _upb_sethas_field(msg, field);
+    }
+  }
+  return ret;
+}
+
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+                 upb_arena *a) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+  UPB_UNUSED(a);  /* We reserve the right to make set insert into a map. */
+  memcpy(mem, &val, get_field_size(field));
+  if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  } else if (in_oneof(field)) {
+    *_upb_oneofcase_field(msg, field) = field->number;
+  }
+}
+
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+
+  if (field->presence > 0) {
+    _upb_clearhas_field(msg, field);
+  } else if (in_oneof(field)) {
+    uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
+    if (*oneof_case != field->number) return;
+    *oneof_case = 0;
+  }
+
+  memset(mem, 0, get_field_size(field));
+}
+
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m) {
+  _upb_msg_clear(msg, upb_msgdef_layout(m));
+}
+
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+                  const upb_symtab *ext_pool, const upb_fielddef **out_f,
+                  upb_msgval *out_val, size_t *iter) {
+  int i = *iter;
+  int n = upb_msgdef_fieldcount(m);
+  const upb_msgval zero = {0};
+  UPB_UNUSED(ext_pool);
+  while (++i < n) {
+    const upb_fielddef *f = upb_msgdef_field(m, i);
+    upb_msgval val = _upb_msg_getraw(msg, f);
+
+    /* Skip field if unset or empty. */
+    if (upb_fielddef_haspresence(f)) {
+      if (!upb_msg_has(msg, f)) continue;
+    } else {
+      upb_msgval test = val;
+      if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
+        /* Clear string pointer, only size matters (ptr could be non-NULL). */
+        test.str_val.data = NULL;
+      }
+      /* Continue if NULL or 0. */
+      if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
+
+      /* Continue on empty array or map. */
+      if (upb_fielddef_ismap(f)) {
+        if (upb_map_size(test.map_val) == 0) continue;
+      } else if (upb_fielddef_isseq(f)) {
+        if (upb_array_size(test.array_val) == 0) continue;
+      }
+    }
+
+    *out_val = val;
+    *out_f = f;
+    *iter = i;
+    return true;
+  }
+  *iter = i;
+  return false;
+}
+
+bool _upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int depth) {
+  size_t iter = UPB_MSG_BEGIN;
+  const upb_fielddef *f;
+  upb_msgval val;
+  bool ret = true;
+
+  if (--depth == 0) return false;
+
+  _upb_msg_discardunknown_shallow(msg);
+
+  while (upb_msg_next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
+    const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+    if (!subm) continue;
+    if (upb_fielddef_ismap(f)) {
+      const upb_fielddef *val_f = upb_msgdef_itof(subm, 2);
+      const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f);
+      upb_map *map = (upb_map*)val.map_val;
+      size_t iter = UPB_MAP_BEGIN;
+
+      if (!val_m) continue;
+
+      while (upb_mapiter_next(map, &iter)) {
+        upb_msgval map_val = upb_mapiter_value(map, iter);
+        if (!_upb_msg_discardunknown((upb_msg*)map_val.msg_val, val_m, depth)) {
+          ret = false;
+        }
+      }
+    } else if (upb_fielddef_isseq(f)) {
+      const upb_array *arr = val.array_val;
+      size_t i, n = upb_array_size(arr);
+      for (i = 0; i < n; i++) {
+        upb_msgval elem = upb_array_get(arr, i);
+        if (!_upb_msg_discardunknown((upb_msg*)elem.msg_val, subm, depth)) {
+          ret = false;
+        }
+      }
+    } else {
+      if (!_upb_msg_discardunknown((upb_msg*)val.msg_val, subm, depth)) {
+        ret = false;
+      }
+    }
+  }
+
+  return ret;
+}
+
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth) {
+  return _upb_msg_discardunknown(msg, m, maxdepth);
+}
+
+/** upb_array *****************************************************************/
+
+upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
+  return _upb_array_new(a, 4, _upb_fieldtype_to_sizelg2[type]);
+}
+
+size_t upb_array_size(const upb_array *arr) {
+  return arr->len;
+}
+
+upb_msgval upb_array_get(const upb_array *arr, size_t i) {
+  upb_msgval ret;
+  const char* data = _upb_array_constptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->len);
+  memcpy(&ret, data + (i << lg2), 1 << lg2);
+  return ret;
+}
+
+void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
+  char* data = _upb_array_ptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->len);
+  memcpy(data + (i << lg2), &val, 1 << lg2);
+}
+
+bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
+  if (!upb_array_resize(arr, arr->len + 1, arena)) {
+    return false;
+  }
+  upb_array_set(arr, arr->len - 1, val);
+  return true;
+}
+
+bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) {
+  return _upb_array_resize(arr, size, arena);
+}
+
+/** upb_map *******************************************************************/
+
+upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
+                     upb_fieldtype_t value_type) {
+  return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
+                      _upb_fieldtype_to_mapsize[value_type]);
+}
+
+size_t upb_map_size(const upb_map *map) {
+  return _upb_map_size(map);
+}
+
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
+  return _upb_map_get(map, &key, map->key_size, val, map->val_size);
+}
+
+void upb_map_clear(upb_map *map) {
+  _upb_map_clear(map);
+}
+
+bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
+                 upb_arena *arena) {
+  return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena);
+}
+
+bool upb_map_delete(upb_map *map, upb_msgval key) {
+  return _upb_map_delete(map, &key, map->key_size);
+}
+
+bool upb_mapiter_next(const upb_map *map, size_t *iter) {
+  return _upb_map_next(map, iter);
+}
+
+bool upb_mapiter_done(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  UPB_ASSERT(iter != UPB_MAP_BEGIN);
+  i.t = &map->table;
+  i.index = iter;
+  return upb_strtable_done(&i);
+}
+
+/* Returns the key and value for this entry of the map. */
+upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  upb_msgval ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
+  return ret;
+}
+
+upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  upb_msgval ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
+  return ret;
+}
+
+/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
+
+/** upb/json_decode.c ************************************************************/
+
+#include <errno.h>
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Special header, must be included last. */
+
+typedef struct {
+  const char *ptr, *end;
+  upb_arena *arena;  /* TODO: should we have a tmp arena for tmp data? */
+  const upb_symtab *any_pool;
+  int depth;
+  upb_status *status;
+  jmp_buf err;
+  int line;
+  const char *line_begin;
+  bool is_first;
+  int options;
+  const upb_fielddef *debug_field;
+} jsondec;
+
+enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL };
+
+/* Forward declarations of mutually-recursive functions. */
+static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m);
+static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f);
+static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg,
+                                   const upb_msgdef *m);
+static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m);
+
+static bool jsondec_streql(upb_strview str, const char *lit) {
+  return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0;
+}
+
+static bool jsondec_isnullvalue(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_ENUM &&
+         strcmp(upb_enumdef_fullname(upb_fielddef_enumsubdef(f)),
+                "google.protobuf.NullValue") == 0;
+}
+
+static bool jsondec_isvalue(const upb_fielddef *f) {
+  return (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+          upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(f)) ==
+              UPB_WELLKNOWN_VALUE) ||
+         jsondec_isnullvalue(f);
+}
+
+UPB_NORETURN static void jsondec_err(jsondec *d, const char *msg) {
+  upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: %s", d->line,
+                     (int)(d->ptr - d->line_begin), msg);
+  UPB_LONGJMP(d->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsondec_errf(jsondec *d, const char *fmt, ...) {
+  va_list argp;
+  upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: ", d->line,
+                     (int)(d->ptr - d->line_begin));
+  va_start(argp, fmt);
+  upb_status_vappenderrf(d->status, fmt, argp);
+  va_end(argp);
+  UPB_LONGJMP(d->err, 1);
+}
+
+static void jsondec_skipws(jsondec *d) {
+  while (d->ptr != d->end) {
+    switch (*d->ptr) {
+      case '\n':
+        d->line++;
+        d->line_begin = d->ptr;
+        /* Fallthrough. */
+      case '\r':
+      case '\t':
+      case ' ':
+        d->ptr++;
+        break;
+      default:
+        return;
+    }
+  }
+  jsondec_err(d, "Unexpected EOF");
+}
+
+static bool jsondec_tryparsech(jsondec *d, char ch) {
+  if (d->ptr == d->end || *d->ptr != ch) return false;
+  d->ptr++;
+  return true;
+}
+
+static void jsondec_parselit(jsondec *d, const char *lit) {
+  size_t avail = d->end - d->ptr;
+  size_t len = strlen(lit);
+  if (avail < len || memcmp(d->ptr, lit, len) != 0) {
+    jsondec_errf(d, "Expected: '%s'", lit);
+  }
+  d->ptr += len;
+}
+
+static void jsondec_wsch(jsondec *d, char ch) {
+  jsondec_skipws(d);
+  if (!jsondec_tryparsech(d, ch)) {
+    jsondec_errf(d, "Expected: '%c'", ch);
+  }
+}
+
+static void jsondec_true(jsondec *d) { jsondec_parselit(d, "true"); }
+static void jsondec_false(jsondec *d) { jsondec_parselit(d, "false"); }
+static void jsondec_null(jsondec *d) { jsondec_parselit(d, "null"); }
+
+static void jsondec_entrysep(jsondec *d) {
+  jsondec_skipws(d);
+  jsondec_parselit(d, ":");
+}
+
+static int jsondec_rawpeek(jsondec *d) {
+  switch (*d->ptr) {
+    case '{':
+      return JD_OBJECT;
+    case '[':
+      return JD_ARRAY;
+    case '"':
+      return JD_STRING;
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      return JD_NUMBER;
+    case 't':
+      return JD_TRUE;
+    case 'f':
+      return JD_FALSE;
+    case 'n':
+      return JD_NULL;
+    default:
+      jsondec_errf(d, "Unexpected character: '%c'", *d->ptr);
+  }
+}
+
+/* JSON object/array **********************************************************/
+
+/* These are used like so:
+ *
+ * jsondec_objstart(d);
+ * while (jsondec_objnext(d)) {
+ *   ...
+ * }
+ * jsondec_objend(d) */
+
+static int jsondec_peek(jsondec *d) {
+  jsondec_skipws(d);
+  return jsondec_rawpeek(d);
+}
+
+static void jsondec_push(jsondec *d) {
+  if (--d->depth < 0) {
+    jsondec_err(d, "Recursion limit exceeded");
+  }
+  d->is_first = true;
+}
+
+static bool jsondec_seqnext(jsondec *d, char end_ch) {
+  bool is_first = d->is_first;
+  d->is_first = false;
+  jsondec_skipws(d);
+  if (*d->ptr == end_ch) return false;
+  if (!is_first) jsondec_parselit(d, ",");
+  return true;
+}
+
+static void jsondec_arrstart(jsondec *d) {
+  jsondec_push(d);
+  jsondec_wsch(d, '[');
+}
+
+static void jsondec_arrend(jsondec *d) {
+  d->depth++;
+  jsondec_wsch(d, ']');
+}
+
+static bool jsondec_arrnext(jsondec *d) {
+  return jsondec_seqnext(d, ']');
+}
+
+static void jsondec_objstart(jsondec *d) {
+  jsondec_push(d);
+  jsondec_wsch(d, '{');
+}
+
+static void jsondec_objend(jsondec *d) {
+  d->depth++;
+  jsondec_wsch(d, '}');
+}
+
+static bool jsondec_objnext(jsondec *d) {
+  if (!jsondec_seqnext(d, '}')) return false;
+  if (jsondec_peek(d) != JD_STRING) {
+    jsondec_err(d, "Object must start with string");
+  }
+  return true;
+}
+
+/* JSON number ****************************************************************/
+
+static bool jsondec_tryskipdigits(jsondec *d) {
+  const char *start = d->ptr;
+
+  while (d->ptr < d->end) {
+    if (*d->ptr < '0' || *d->ptr > '9') {
+      break;
+    }
+    d->ptr++;
+  }
+
+  return d->ptr != start;
+}
+
+static void jsondec_skipdigits(jsondec *d) {
+  if (!jsondec_tryskipdigits(d)) {
+    jsondec_err(d, "Expected one or more digits");
+  }
+}
+
+static double jsondec_number(jsondec *d) {
+  const char *start = d->ptr;
+
+  assert(jsondec_rawpeek(d) == JD_NUMBER);
+
+  /* Skip over the syntax of a number, as specified by JSON. */
+  if (*d->ptr == '-') d->ptr++;
+
+  if (jsondec_tryparsech(d, '0')) {
+    if (jsondec_tryskipdigits(d)) {
+      jsondec_err(d, "number cannot have leading zero");
+    }
+  } else {
+    jsondec_skipdigits(d);
+  }
+
+  if (d->ptr == d->end) goto parse;
+  if (jsondec_tryparsech(d, '.')) {
+    jsondec_skipdigits(d);
+  }
+  if (d->ptr == d->end) goto parse;
+
+  if (*d->ptr == 'e' || *d->ptr == 'E') {
+    d->ptr++;
+    if (d->ptr == d->end) {
+      jsondec_err(d, "Unexpected EOF in number");
+    }
+    if (*d->ptr == '+' || *d->ptr == '-') {
+      d->ptr++;
+    }
+    jsondec_skipdigits(d);
+  }
+
+parse:
+  /* Having verified the syntax of a JSON number, use strtod() to parse
+   * (strtod() accepts a superset of JSON syntax). */
+  errno = 0;
+  {
+    char* end;
+    double val = strtod(start, &end);
+    assert(end == d->ptr);
+
+    /* Currently the min/max-val conformance tests fail if we check this.  Does
+     * this mean the conformance tests are wrong or strtod() is wrong, or
+     * something else?  Investigate further. */
+    /*
+    if (errno == ERANGE) {
+      jsondec_err(d, "Number out of range");
+    }
+    */
+
+    if (val > DBL_MAX || val < -DBL_MAX) {
+      jsondec_err(d, "Number out of range");
+    }
+
+    return val;
+  }
+}
+
+/* JSON string ****************************************************************/
+
+static char jsondec_escape(jsondec *d) {
+  switch (*d->ptr++) {
+    case '"':
+      return '\"';
+    case '\\':
+      return '\\';
+    case '/':
+      return '/';
+    case 'b':
+      return '\b';
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    default:
+      jsondec_err(d, "Invalid escape char");
+  }
+}
+
+static uint32_t jsondec_codepoint(jsondec *d) {
+  uint32_t cp = 0;
+  const char *end;
+
+  if (d->end - d->ptr < 4) {
+    jsondec_err(d, "EOF inside string");
+  }
+
+  end = d->ptr + 4;
+  while (d->ptr < end) {
+    char ch = *d->ptr++;
+    if (ch >= '0' && ch <= '9') {
+      ch -= '0';
+    } else if (ch >= 'a' && ch <= 'f') {
+      ch = ch - 'a' + 10;
+    } else if (ch >= 'A' && ch <= 'F') {
+      ch = ch - 'A' + 10;
+    } else {
+      jsondec_err(d, "Invalid hex digit");
+    }
+    cp = (cp << 4) | ch;
+  }
+
+  return cp;
+}
+
+/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */
+static size_t jsondec_unicode(jsondec *d, char* out) {
+  uint32_t cp = jsondec_codepoint(d);
+  if (cp >= 0xd800 && cp <= 0xdbff) {
+    /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */
+    uint32_t high = cp;
+    uint32_t low;
+    jsondec_parselit(d, "\\u");
+    low = jsondec_codepoint(d);
+    if (low < 0xdc00 || low > 0xdfff) {
+      jsondec_err(d, "Invalid low surrogate");
+    }
+    cp = (high & 0x3ff) << 10;
+    cp |= (low & 0x3ff);
+    cp += 0x10000;
+  } else if (cp >= 0xdc00 && cp <= 0xdfff) {
+    jsondec_err(d, "Unpaired low surrogate");
+  }
+
+  /* Write to UTF-8 */
+  if (cp <= 0x7f) {
+    out[0] = cp;
+    return 1;
+  } else if (cp <= 0x07FF) {
+    out[0] = ((cp >> 6) & 0x1F) | 0xC0;
+    out[1] = ((cp >> 0) & 0x3F) | 0x80;
+    return 2;
+  } else if (cp <= 0xFFFF) {
+    out[0] = ((cp >> 12) & 0x0F) | 0xE0;
+    out[1] = ((cp >> 6) & 0x3F) | 0x80;
+    out[2] = ((cp >> 0) & 0x3F) | 0x80;
+    return 3;
+  } else if (cp < 0x10FFFF) {
+    out[0] = ((cp >> 18) & 0x07) | 0xF0;
+    out[1] = ((cp >> 12) & 0x3f) | 0x80;
+    out[2] = ((cp >> 6) & 0x3f) | 0x80;
+    out[3] = ((cp >> 0) & 0x3f) | 0x80;
+    return 4;
+  } else {
+    jsondec_err(d, "Invalid codepoint");
+  }
+}
+
+static void jsondec_resize(jsondec *d, char **buf, char **end, char **buf_end) {
+  size_t oldsize = *buf_end - *buf;
+  size_t len = *end - *buf;
+  size_t size = UPB_MAX(8, 2 * oldsize);
+
+  *buf = upb_arena_realloc(d->arena, *buf, len, size);
+  if (!*buf) jsondec_err(d, "Out of memory");
+
+  *end = *buf + len;
+  *buf_end = *buf + size;
+}
+
+static upb_strview jsondec_string(jsondec *d) {
+  char *buf = NULL;
+  char *end = NULL;
+  char *buf_end = NULL;
+
+  jsondec_skipws(d);
+
+  if (*d->ptr++ != '"') {
+    jsondec_err(d, "Expected string");
+  }
+
+  while (d->ptr < d->end) {
+    char ch = *d->ptr++;
+
+    if (end == buf_end) {
+      jsondec_resize(d, &buf, &end, &buf_end);
+    }
+
+    switch (ch) {
+      case '"': {
+        upb_strview ret;
+        ret.data = buf;
+        ret.size = end - buf;
+        *end = '\0';  /* Needed for possible strtod(). */
+        return ret;
+      }
+      case '\\':
+        if (d->ptr == d->end) goto eof;
+        if (*d->ptr == 'u') {
+          d->ptr++;
+          if (buf_end - end < 4) {
+            /* Allow space for maximum-sized code point (4 bytes). */
+            jsondec_resize(d, &buf, &end, &buf_end);
+          }
+          end += jsondec_unicode(d, end);
+        } else {
+          *end++ = jsondec_escape(d);
+        }
+        break;
+      default:
+        if ((unsigned char)*d->ptr < 0x20) {
+          jsondec_err(d, "Invalid char in JSON string");
+        }
+        *end++ = ch;
+        break;
+    }
+  }
+
+eof:
+  jsondec_err(d, "EOF inside string");
+}
+
+static void jsondec_skipval(jsondec *d) {
+  switch (jsondec_peek(d)) {
+    case JD_OBJECT:
+      jsondec_objstart(d);
+      while (jsondec_objnext(d)) {
+        jsondec_string(d);
+        jsondec_entrysep(d);
+        jsondec_skipval(d);
+      }
+      jsondec_objend(d);
+      break;
+    case JD_ARRAY:
+      jsondec_arrstart(d);
+      while (jsondec_arrnext(d)) {
+        jsondec_skipval(d);
+      }
+      jsondec_arrend(d);
+      break;
+    case JD_TRUE:
+      jsondec_true(d);
+      break;
+    case JD_FALSE:
+      jsondec_false(d);
+      break;
+    case JD_NULL:
+      jsondec_null(d);
+      break;
+    case JD_STRING:
+      jsondec_string(d);
+      break;
+    case JD_NUMBER:
+      jsondec_number(d);
+      break;
+  }
+}
+
+/* Base64 decoding for bytes fields. ******************************************/
+
+static unsigned int jsondec_base64_tablelookup(const char ch) {
+  /* Table includes the normal base64 chars plus the URL-safe variant. */
+  const signed char table[256] = {
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       62 /*+*/, -1,       62 /*-*/, -1,       63 /*/ */, 52 /*0*/,
+      53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/,  59 /*7*/,
+      60 /*8*/, 61 /*9*/, -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       0 /*A*/,  1 /*B*/,  2 /*C*/,  3 /*D*/,   4 /*E*/,
+      5 /*F*/,  6 /*G*/,  07 /*H*/, 8 /*I*/,  9 /*J*/,  10 /*K*/,  11 /*L*/,
+      12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/,  18 /*S*/,
+      19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/,  25 /*Z*/,
+      -1,       -1,       -1,       -1,       63 /*_*/, -1,        26 /*a*/,
+      27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/,  33 /*h*/,
+      34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/,  40 /*o*/,
+      41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/,  47 /*v*/,
+      48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1};
+
+  /* Sign-extend return value so high bit will be set on any unexpected char. */
+  return table[(unsigned)ch];
+}
+
+static char *jsondec_partialbase64(jsondec *d, const char *ptr, const char *end,
+                                   char *out) {
+  int32_t val = -1;
+
+  switch (end - ptr) {
+    case 2:
+      val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+            jsondec_base64_tablelookup(ptr[1]) << 12;
+      out[0] = val >> 16;
+      out += 1;
+      break;
+    case 3:
+      val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+            jsondec_base64_tablelookup(ptr[1]) << 12 |
+            jsondec_base64_tablelookup(ptr[2]) << 6;
+      out[0] = val >> 16;
+      out[1] = (val >> 8) & 0xff;
+      out += 2;
+      break;
+  }
+
+  if (val < 0) {
+    jsondec_err(d, "Corrupt base64");
+  }
+
+  return out;
+}
+
+static size_t jsondec_base64(jsondec *d, upb_strview str) {
+  /* We decode in place. This is safe because this is a new buffer (not
+   * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */
+  char *out = (char*)str.data;
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  const char *end4 = ptr + (str.size & -4);  /* Round down to multiple of 4. */
+
+  for (; ptr < end4; ptr += 4, out += 3) {
+    int val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+              jsondec_base64_tablelookup(ptr[1]) << 12 |
+              jsondec_base64_tablelookup(ptr[2]) << 6 |
+              jsondec_base64_tablelookup(ptr[3]) << 0;
+
+    if (val < 0) {
+      /* Junk chars or padding. Remove trailing padding, if any. */
+      if (end - ptr == 4 && ptr[3] == '=') {
+        if (ptr[2] == '=') {
+          end -= 2;
+        } else {
+          end -= 1;
+        }
+      }
+      break;
+    }
+
+    out[0] = val >> 16;
+    out[1] = (val >> 8) & 0xff;
+    out[2] = val & 0xff;
+  }
+
+  if (ptr < end) {
+    /* Process remaining chars. We do not require padding. */
+    out = jsondec_partialbase64(d, ptr, end, out);
+  }
+
+  return out - str.data;
+}
+
+/* Low-level integer parsing **************************************************/
+
+/* We use these hand-written routines instead of strto[u]l() because the "long
+ * long" variants aren't in c89. Also our version allows setting a ptr limit. */
+
+static const char *jsondec_buftouint64(jsondec *d, const char *ptr,
+                                       const char *end, uint64_t *val) {
+  uint64_t u64 = 0;
+  while (ptr < end) {
+    unsigned ch = *ptr - '0';
+    if (ch >= 10) break;
+    if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) {
+      jsondec_err(d, "Integer overflow");
+    }
+    u64 *= 10;
+    u64 += ch;
+    ptr++;
+  }
+
+  *val = u64;
+  return ptr;
+}
+
+static const char *jsondec_buftoint64(jsondec *d, const char *ptr,
+                                      const char *end, int64_t *val) {
+  bool neg = false;
+  uint64_t u64;
+
+  if (ptr != end && *ptr == '-') {
+    ptr++;
+    neg = true;
+  }
+
+  ptr = jsondec_buftouint64(d, ptr, end, &u64);
+  if (u64 > (uint64_t)INT64_MAX + neg) {
+    jsondec_err(d, "Integer overflow");
+  }
+
+  *val = neg ? -u64 : u64;
+  return ptr;
+}
+
+static uint64_t jsondec_strtouint64(jsondec *d, upb_strview str) {
+  const char *end = str.data + str.size;
+  uint64_t ret;
+  if (jsondec_buftouint64(d, str.data, end, &ret) != end) {
+    jsondec_err(d, "Non-number characters in quoted integer");
+  }
+  return ret;
+}
+
+static int64_t jsondec_strtoint64(jsondec *d, upb_strview str) {
+  const char *end = str.data + str.size;
+  int64_t ret;
+  if (jsondec_buftoint64(d, str.data, end, &ret) != end) {
+    jsondec_err(d, "Non-number characters in quoted integer");
+  }
+  return ret;
+}
+
+/* Primitive value types ******************************************************/
+
+/* Parse INT32 or INT64 value. */
+static upb_msgval jsondec_int(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val;
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER: {
+      double dbl = jsondec_number(d);
+      if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) {
+        jsondec_err(d, "JSON number is out of range.");
+      }
+      val.int64_val = dbl;  /* must be guarded, overflow here is UB */
+      if (val.int64_val != dbl) {
+        jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl,
+                     val.int64_val);
+      }
+      break;
+    }
+    case JD_STRING: {
+      upb_strview str = jsondec_string(d);
+      val.int64_val = jsondec_strtoint64(d, str);
+      break;
+    }
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_INT32) {
+    if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) {
+      jsondec_err(d, "Integer out of range.");
+    }
+    val.int32_val = (int32_t)val.int64_val;
+  }
+
+  return val;
+}
+
+/* Parse UINT32 or UINT64 value. */
+static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val = {0};
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER: {
+      double dbl = jsondec_number(d);
+      if (dbl > 18446744073709549568.0 || dbl < 0) {
+        jsondec_err(d, "JSON number is out of range.");
+      }
+      val.uint64_val = dbl;  /* must be guarded, overflow here is UB */
+      if (val.uint64_val != dbl) {
+        jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl,
+                     val.uint64_val);
+      }
+      break;
+    }
+    case JD_STRING: {
+      upb_strview str = jsondec_string(d);
+      val.uint64_val = jsondec_strtouint64(d, str);
+      break;
+    }
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_UINT32) {
+    if (val.uint64_val > UINT32_MAX) {
+      jsondec_err(d, "Integer out of range.");
+    }
+    val.uint32_val = (uint32_t)val.uint64_val;
+  }
+
+  return val;
+}
+
+/* Parse DOUBLE or FLOAT value. */
+static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) {
+  upb_strview str;
+  upb_msgval val = {0};
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER:
+      val.double_val = jsondec_number(d);
+      break;
+    case JD_STRING:
+      str = jsondec_string(d);
+      if (jsondec_streql(str, "NaN")) {
+        val.double_val = NAN;
+      } else if (jsondec_streql(str, "Infinity")) {
+        val.double_val = INFINITY;
+      } else if (jsondec_streql(str, "-Infinity")) {
+        val.double_val = -INFINITY;
+      } else {
+        val.double_val = strtod(str.data, NULL);
+      }
+      break;
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_FLOAT) {
+    if (val.double_val != INFINITY && val.double_val != -INFINITY &&
+        (val.double_val > FLT_MAX || val.double_val < -FLT_MAX)) {
+      jsondec_err(d, "Float out of range");
+    }
+    val.float_val = val.double_val;
+  }
+
+  return val;
+}
+
+/* Parse STRING or BYTES value. */
+static upb_msgval jsondec_strfield(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val;
+  val.str_val = jsondec_string(d);
+  if (upb_fielddef_type(f) == UPB_TYPE_BYTES) {
+    val.str_val.size = jsondec_base64(d, val.str_val);
+  }
+  return val;
+}
+
+static upb_msgval jsondec_enum(jsondec *d, const upb_fielddef *f) {
+  switch (jsondec_peek(d)) {
+    case JD_STRING: {
+      const upb_enumdef *e = upb_fielddef_enumsubdef(f);
+      upb_strview str = jsondec_string(d);
+      upb_msgval val;
+      if (!upb_enumdef_ntoi(e, str.data, str.size, &val.int32_val)) {
+        if (d->options & UPB_JSONDEC_IGNOREUNKNOWN) {
+          val.int32_val = 0;
+        } else {
+          jsondec_errf(d, "Unknown enumerator: '" UPB_STRVIEW_FORMAT "'",
+                       UPB_STRVIEW_ARGS(str));
+        }
+      }
+      return val;
+    }
+    case JD_NULL: {
+      if (jsondec_isnullvalue(f)) {
+        upb_msgval val;
+        jsondec_null(d);
+        val.int32_val = 0;
+        return val;
+      }
+    }
+      /* Fallthrough. */
+    default:
+      return jsondec_int(d, f);
+  }
+}
+
+static upb_msgval jsondec_bool(jsondec *d, const upb_fielddef *f) {
+  bool is_map_key = upb_fielddef_number(f) == 1 &&
+                    upb_msgdef_mapentry(upb_fielddef_containingtype(f));
+  upb_msgval val;
+
+  if (is_map_key) {
+    upb_strview str = jsondec_string(d);
+    if (jsondec_streql(str, "true")) {
+      val.bool_val = true;
+    } else if (jsondec_streql(str, "false")) {
+      val.bool_val = false;
+    } else {
+      jsondec_err(d, "Invalid boolean map key");
+    }
+  } else {
+    switch (jsondec_peek(d)) {
+      case JD_TRUE:
+        val.bool_val = true;
+        jsondec_true(d);
+        break;
+      case JD_FALSE:
+        val.bool_val = false;
+        jsondec_false(d);
+        break;
+      default:
+        jsondec_err(d, "Expected true or false");
+    }
+  }
+
+  return val;
+}
+
+/* Composite types (array/message/map) ****************************************/
+
+static void jsondec_array(jsondec *d, upb_msg *msg, const upb_fielddef *f) {
+  upb_array *arr = upb_msg_mutable(msg, f, d->arena).array;
+
+  jsondec_arrstart(d);
+  while (jsondec_arrnext(d)) {
+    upb_msgval elem = jsondec_value(d, f);
+    upb_array_append(arr, elem, d->arena);
+  }
+  jsondec_arrend(d);
+}
+
+static void jsondec_map(jsondec *d, upb_msg *msg, const upb_fielddef *f) {
+  upb_map *map = upb_msg_mutable(msg, f, d->arena).map;
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+  const upb_fielddef *key_f = upb_msgdef_itof(entry, 1);
+  const upb_fielddef *val_f = upb_msgdef_itof(entry, 2);
+
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    upb_msgval key, val;
+    key = jsondec_value(d, key_f);
+    jsondec_entrysep(d);
+    val = jsondec_value(d, val_f);
+    upb_map_set(map, key, val, d->arena);
+  }
+  jsondec_objend(d);
+}
+
+static void jsondec_tomsg(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    jsondec_object(d, msg, m);
+  } else {
+    jsondec_wellknown(d, msg, m);
+  }
+}
+
+static upb_msgval jsondec_msg(jsondec *d, const upb_fielddef *f) {
+  const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+  upb_msg *msg = upb_msg_new(m, d->arena);
+  upb_msgval val;
+
+  jsondec_tomsg(d, msg, m);
+  val.msg_val = msg;
+  return val;
+}
+
+static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_strview name;
+  const upb_fielddef *f;
+  const upb_fielddef *preserved;
+
+  name = jsondec_string(d);
+  jsondec_entrysep(d);
+  f = upb_msgdef_lookupjsonname(m, name.data, name.size);
+
+  if (!f) {
+    if ((d->options & UPB_JSONDEC_IGNOREUNKNOWN) == 0) {
+      jsondec_errf(d, "No such field: " UPB_STRVIEW_FORMAT,
+                   UPB_STRVIEW_ARGS(name));
+    }
+    jsondec_skipval(d);
+    return;
+  }
+
+  if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) {
+    /* JSON "null" indicates a default value, so no need to set anything. */
+    jsondec_null(d);
+    return;
+  }
+
+  if (upb_fielddef_realcontainingoneof(f) &&
+      upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) {
+    jsondec_err(d, "More than one field for this oneof.");
+  }
+
+  preserved = d->debug_field;
+  d->debug_field = f;
+
+  if (upb_fielddef_ismap(f)) {
+    jsondec_map(d, msg, f);
+  } else if (upb_fielddef_isseq(f)) {
+    jsondec_array(d, msg, f);
+  } else if (upb_fielddef_issubmsg(f)) {
+    upb_msg *submsg = upb_msg_mutable(msg, f, d->arena).msg;
+    const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+    jsondec_tomsg(d, submsg, subm);
+  } else {
+    upb_msgval val = jsondec_value(d, f);
+    upb_msg_set(msg, f, val, d->arena);
+  }
+
+  d->debug_field = preserved;
+}
+
+static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    jsondec_field(d, msg, m);
+  }
+  jsondec_objend(d);
+}
+
+static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      return jsondec_bool(d, f);
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_DOUBLE:
+      return jsondec_double(d, f);
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      return jsondec_uint(d, f);
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+      return jsondec_int(d, f);
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return jsondec_strfield(d, f);
+    case UPB_TYPE_ENUM:
+      return jsondec_enum(d, f);
+    case UPB_TYPE_MESSAGE:
+      return jsondec_msg(d, f);
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+/* Well-known types ***********************************************************/
+
+static int jsondec_tsdigits(jsondec *d, const char **ptr, size_t digits,
+                            const char *after) {
+  uint64_t val;
+  const char *p = *ptr;
+  const char *end = p + digits;
+  size_t after_len = after ? strlen(after) : 0;
+
+  UPB_ASSERT(digits <= 9);  /* int can't overflow. */
+
+  if (jsondec_buftouint64(d, p, end, &val) != end ||
+      (after_len && memcmp(end, after, after_len) != 0)) {
+    jsondec_err(d, "Malformed timestamp");
+  }
+
+  UPB_ASSERT(val < INT_MAX);
+
+  *ptr = end + after_len;
+  return (int)val;
+}
+
+static int jsondec_nanos(jsondec *d, const char **ptr, const char *end) {
+  uint64_t nanos = 0;
+  const char *p = *ptr;
+
+  if (p != end && *p == '.') {
+    const char *nano_end = jsondec_buftouint64(d, p + 1, end, &nanos);
+    int digits = (int)(nano_end - p - 1);
+    int exp_lg10 = 9 - digits;
+    if (digits > 9) {
+      jsondec_err(d, "Too many digits for partial seconds");
+    }
+    while (exp_lg10--) nanos *= 10;
+    *ptr = nano_end;
+  }
+
+  UPB_ASSERT(nanos < INT_MAX);
+
+  return (int)nanos;
+}
+
+/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */
+int jsondec_epochdays(int y, int m, int d) {
+  const uint32_t year_base = 4800;    /* Before min year, multiple of 400. */
+  const uint32_t m_adj = m - 3;       /* March-based month. */
+  const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0;
+  const uint32_t adjust = carry ? 12 : 0;
+  const uint32_t y_adj = y + year_base - carry;
+  const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048;
+  const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400;
+  return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632;
+}
+
+static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) {
+  return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s;
+}
+
+static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_msgval seconds;
+  upb_msgval nanos;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+
+  if (str.size < 20) goto malformed;
+
+  {
+    /* 1972-01-01T01:00:00 */
+    int year = jsondec_tsdigits(d, &ptr, 4, "-");
+    int mon = jsondec_tsdigits(d, &ptr, 2, "-");
+    int day = jsondec_tsdigits(d, &ptr, 2, "T");
+    int hour = jsondec_tsdigits(d, &ptr, 2, ":");
+    int min = jsondec_tsdigits(d, &ptr, 2, ":");
+    int sec = jsondec_tsdigits(d, &ptr, 2, NULL);
+
+    seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec);
+  }
+
+  nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+  {
+    /* [+-]08:00 or Z */
+    int ofs_hour = 0;
+    int ofs_min = 0;
+    bool neg = false;
+
+    if (ptr == end) goto malformed;
+
+    switch (*ptr++) {
+      case '-':
+        neg = true;
+        /* fallthrough */
+      case '+':
+        if ((end - ptr) != 5) goto malformed;
+        ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":");
+        ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL);
+        ofs_min = ((ofs_hour * 60) + ofs_min) * 60;
+        seconds.int64_val += (neg ? ofs_min : -ofs_min);
+        break;
+      case 'Z':
+        if (ptr != end) goto malformed;
+        break;
+      default:
+        goto malformed;
+    }
+  }
+
+  if (seconds.int64_val < -62135596800) {
+    jsondec_err(d, "Timestamp out of range");
+  }
+
+  upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena);
+  upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena);
+  return;
+
+malformed:
+  jsondec_err(d, "Malformed timestamp");
+}
+
+static void jsondec_duration(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_msgval seconds;
+  upb_msgval nanos;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  const int64_t max = (uint64_t)3652500 * 86400;
+
+  /* "3.000000001s", "3s", etc. */
+  ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val);
+  nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+  if (end - ptr != 1 || *ptr != 's') {
+    jsondec_err(d, "Malformed duration");
+  }
+
+  if (seconds.int64_val < -max || seconds.int64_val > max) {
+    jsondec_err(d, "Duration out of range");
+  }
+
+  if (seconds.int64_val < 0) {
+    nanos.int32_val = - nanos.int32_val;
+  }
+
+  upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena);
+  upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena);
+}
+
+static void jsondec_listvalue(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *values_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *value_m = upb_fielddef_msgsubdef(values_f);
+  upb_array *values = upb_msg_mutable(msg, values_f, d->arena).array;
+
+  jsondec_arrstart(d);
+  while (jsondec_arrnext(d)) {
+    upb_msg *value_msg = upb_msg_new(value_m, d->arena);
+    upb_msgval value;
+    value.msg_val = value_msg;
+    upb_array_append(values, value, d->arena);
+    jsondec_wellknownvalue(d, value_msg, value_m);
+  }
+  jsondec_arrend(d);
+}
+
+static void jsondec_struct(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *fields_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f);
+  const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2);
+  const upb_msgdef *value_m = upb_fielddef_msgsubdef(value_f);
+  upb_map *fields = upb_msg_mutable(msg, fields_f, d->arena).map;
+
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    upb_msgval key, value;
+    upb_msg *value_msg = upb_msg_new(value_m, d->arena);
+    key.str_val = jsondec_string(d);
+    value.msg_val = value_msg;
+    upb_map_set(fields, key, value, d->arena);
+    jsondec_entrysep(d);
+    jsondec_wellknownvalue(d, value_msg, value_m);
+  }
+  jsondec_objend(d);
+}
+
+static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg,
+                                   const upb_msgdef *m) {
+  upb_msgval val;
+  const upb_fielddef *f;
+  upb_msg *submsg;
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER:
+      /* double number_value = 2; */
+      f = upb_msgdef_itof(m, 2);
+      val.double_val = jsondec_number(d);
+      break;
+    case JD_STRING:
+      /* string string_value = 3; */
+      f = upb_msgdef_itof(m, 3);
+      val.str_val = jsondec_string(d);
+      break;
+    case JD_FALSE:
+      /* bool bool_value = 4; */
+      f = upb_msgdef_itof(m, 4);
+      val.bool_val = false;
+      jsondec_false(d);
+      break;
+    case JD_TRUE:
+      /* bool bool_value = 4; */
+      f = upb_msgdef_itof(m, 4);
+      val.bool_val = true;
+      jsondec_true(d);
+      break;
+    case JD_NULL:
+      /* NullValue null_value = 1; */
+      f = upb_msgdef_itof(m, 1);
+      val.int32_val = 0;
+      jsondec_null(d);
+      break;
+    /* Note: these cases return, because upb_msg_mutable() is enough. */
+    case JD_OBJECT:
+      /* Struct struct_value = 5; */
+      f = upb_msgdef_itof(m, 5);
+      submsg = upb_msg_mutable(msg, f, d->arena).msg;
+      jsondec_struct(d, submsg, upb_fielddef_msgsubdef(f));
+      return;
+    case JD_ARRAY:
+      /* ListValue list_value = 6; */
+      f = upb_msgdef_itof(m, 6);
+      submsg = upb_msg_mutable(msg, f, d->arena).msg;
+      jsondec_listvalue(d, submsg, upb_fielddef_msgsubdef(f));
+      return;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  upb_msg_set(msg, f, val, d->arena);
+}
+
+static upb_strview jsondec_mask(jsondec *d, const char *buf, const char *end) {
+  /* FieldMask fields grow due to inserted '_' characters, so we can't do the
+   * transform in place. */
+  const char *ptr = buf;
+  upb_strview ret;
+  char *out;
+
+  ret.size = end - ptr;
+  while (ptr < end) {
+    ret.size += (*ptr >= 'A' && *ptr <= 'Z');
+    ptr++;
+  }
+
+  out = upb_arena_malloc(d->arena, ret.size);
+  ptr = buf;
+  ret.data = out;
+
+  while (ptr < end) {
+    char ch = *ptr++;
+    if (ch >= 'A' && ch <= 'Z') {
+      *out++ = '_';
+      *out++ = ch + 32;
+    } else if (ch == '_') {
+      jsondec_err(d, "field mask may not contain '_'");
+    } else {
+      *out++ = ch;
+    }
+  }
+
+  return ret;
+}
+
+static void jsondec_fieldmask(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  /* repeated string paths = 1; */
+  const upb_fielddef *paths_f = upb_msgdef_itof(m, 1);
+  upb_array *arr = upb_msg_mutable(msg, paths_f, d->arena).array;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  upb_msgval val;
+
+  while (ptr < end) {
+    const char *elem_end = memchr(ptr, ',', end - ptr);
+    if (elem_end) {
+      val.str_val = jsondec_mask(d, ptr, elem_end);
+      ptr = elem_end + 1;
+    } else {
+      val.str_val = jsondec_mask(d, ptr, end);
+      ptr = end;
+    }
+    upb_array_append(arr, val, d->arena);
+  }
+}
+
+static void jsondec_anyfield(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    /* For regular types: {"@type": "[user type]", "f1": <V1>, "f2": <V2>}
+     * where f1, f2, etc. are the normal fields of this type. */
+    jsondec_field(d, msg, m);
+  } else {
+    /* For well-known types: {"@type": "[well-known type]", "value": <X>}
+     * where <X> is whatever encoding the WKT normally uses. */
+    upb_strview str = jsondec_string(d);
+    jsondec_entrysep(d);
+    if (!jsondec_streql(str, "value")) {
+      jsondec_err(d, "Key for well-known type must be 'value'");
+    }
+    jsondec_wellknown(d, msg, m);
+  }
+}
+
+static const upb_msgdef *jsondec_typeurl(jsondec *d, upb_msg *msg,
+                                         const upb_msgdef *m) {
+  const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *type_m;
+  upb_strview type_url = jsondec_string(d);
+  const char *end = type_url.data + type_url.size;
+  const char *ptr = end;
+  upb_msgval val;
+
+  val.str_val = type_url;
+  upb_msg_set(msg, type_url_f, val, d->arena);
+
+  /* Find message name after the last '/' */
+  while (ptr > type_url.data && *--ptr != '/') {}
+
+  if (ptr == type_url.data || ptr == end) {
+    jsondec_err(d, "Type url must have at least one '/' and non-empty host");
+  }
+
+  ptr++;
+  type_m = upb_symtab_lookupmsg2(d->any_pool, ptr, end - ptr);
+
+  if (!type_m) {
+    jsondec_err(d, "Type was not found");
+  }
+
+  return type_m;
+}
+
+static void jsondec_any(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  /* string type_url = 1;
+   * bytes value = 2; */
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 2);
+  upb_msg *any_msg;
+  const upb_msgdef *any_m = NULL;
+  const char *pre_type_data = NULL;
+  const char *pre_type_end = NULL;
+  upb_msgval encoded;
+
+  jsondec_objstart(d);
+
+  /* Scan looking for "@type", which is not necessarily first. */
+  while (!any_m && jsondec_objnext(d)) {
+    const char *start = d->ptr;
+    upb_strview name = jsondec_string(d);
+    jsondec_entrysep(d);
+    if (jsondec_streql(name, "@type")) {
+      any_m = jsondec_typeurl(d, msg, m);
+      if (pre_type_data) {
+        pre_type_end = start;
+        while (*pre_type_end != ',') pre_type_end--;
+      }
+    } else {
+      if (!pre_type_data) pre_type_data = start;
+      jsondec_skipval(d);
+    }
+  }
+
+  if (!any_m) {
+    jsondec_err(d, "Any object didn't contain a '@type' field");
+  }
+
+  any_msg = upb_msg_new(any_m, d->arena);
+
+  if (pre_type_data) {
+    size_t len = pre_type_end - pre_type_data + 1;
+    char *tmp = upb_arena_malloc(d->arena, len);
+    const char *saved_ptr = d->ptr;
+    const char *saved_end = d->end;
+    memcpy(tmp, pre_type_data, len - 1);
+    tmp[len - 1] = '}';
+    d->ptr = tmp;
+    d->end = tmp + len;
+    d->is_first = true;
+    while (jsondec_objnext(d)) {
+      jsondec_anyfield(d, any_msg, any_m);
+    }
+    d->ptr = saved_ptr;
+    d->end = saved_end;
+  }
+
+  while (jsondec_objnext(d)) {
+    jsondec_anyfield(d, any_msg, any_m);
+  }
+
+  jsondec_objend(d);
+
+  encoded.str_val.data = upb_encode(any_msg, upb_msgdef_layout(any_m), d->arena,
+                                    &encoded.str_val.size);
+  upb_msg_set(msg, value_f, encoded, d->arena);
+}
+
+static void jsondec_wrapper(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 1);
+  upb_msgval val = jsondec_value(d, value_f);
+  upb_msg_set(msg, value_f, val, d->arena);
+}
+
+static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  switch (upb_msgdef_wellknowntype(m)) {
+    case UPB_WELLKNOWN_ANY:
+      jsondec_any(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_FIELDMASK:
+      jsondec_fieldmask(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_DURATION:
+      jsondec_duration(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_TIMESTAMP:
+      jsondec_timestamp(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_VALUE:
+      jsondec_wellknownvalue(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_LISTVALUE:
+      jsondec_listvalue(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_STRUCT:
+      jsondec_struct(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_DOUBLEVALUE:
+    case UPB_WELLKNOWN_FLOATVALUE:
+    case UPB_WELLKNOWN_INT64VALUE:
+    case UPB_WELLKNOWN_UINT64VALUE:
+    case UPB_WELLKNOWN_INT32VALUE:
+    case UPB_WELLKNOWN_UINT32VALUE:
+    case UPB_WELLKNOWN_STRINGVALUE:
+    case UPB_WELLKNOWN_BYTESVALUE:
+    case UPB_WELLKNOWN_BOOLVALUE:
+      jsondec_wrapper(d, msg, m);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
+                     const upb_msgdef *m, const upb_symtab *any_pool,
+                     int options, upb_arena *arena, upb_status *status) {
+  jsondec d;
+
+  if (size == 0) return true;
+
+  d.ptr = buf;
+  d.end = buf + size;
+  d.arena = arena;
+  d.any_pool = any_pool;
+  d.status = status;
+  d.options = options;
+  d.depth = 64;
+  d.line = 1;
+  d.line_begin = d.ptr;
+  d.debug_field = NULL;
+  d.is_first = false;
+
+  if (UPB_SETJMP(d.err)) return false;
+
+  jsondec_tomsg(&d, msg, m);
+  return true;
+}
+
+/** upb/json_encode.c ************************************************************/
+
+#include <ctype.h>
+#include <float.h>
+#include <inttypes.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+typedef struct {
+  char *buf, *ptr, *end;
+  size_t overflow;
+  int indent_depth;
+  int options;
+  const upb_symtab *ext_pool;
+  jmp_buf err;
+  upb_status *status;
+  upb_arena *arena;
+} jsonenc;
+
+static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
+static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f);
+static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg,
+                             const upb_msgdef *m);
+static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m, bool first);
+static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
+
+UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) {
+  upb_status_seterrmsg(e->status, msg);
+  longjmp(e->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsonenc_errf(jsonenc *e, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_status_vseterrf(e->status, fmt, argp);
+  va_end(argp);
+  longjmp(e->err, 1);
+}
+
+static upb_arena *jsonenc_arena(jsonenc *e) {
+  /* Create lazily, since it's only needed for Any */
+  if (!e->arena) {
+    e->arena = upb_arena_new();
+  }
+  return e->arena;
+}
+
+static void jsonenc_putbytes(jsonenc *e, const void *data, size_t len) {
+  size_t have = e->end - e->ptr;
+  if (UPB_LIKELY(have >= len)) {
+    memcpy(e->ptr, data, len);
+    e->ptr += len;
+  } else {
+    if (have) {
+      memcpy(e->ptr, data, have);
+      e->ptr += have;
+    }
+    e->overflow += (len - have);
+  }
+}
+
+static void jsonenc_putstr(jsonenc *e, const char *str) {
+  jsonenc_putbytes(e, str, strlen(str));
+}
+
+UPB_PRINTF(2, 3)
+static void jsonenc_printf(jsonenc *e, const char *fmt, ...) {
+  size_t n;
+  size_t have = e->end - e->ptr;
+  va_list args;
+
+  va_start(args, fmt);
+  n = vsnprintf(e->ptr, have, fmt, args);
+  va_end(args);
+
+  if (UPB_LIKELY(have > n)) {
+    e->ptr += n;
+  } else {
+    e->ptr = UPB_PTRADD(e->ptr, have);
+    e->overflow += (n - have);
+  }
+}
+
+static void jsonenc_nanos(jsonenc *e, int32_t nanos) {
+  int digits = 9;
+
+  if (nanos == 0) return;
+  if (nanos < 0 || nanos >= 1000000000) {
+    jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos");
+  }
+
+  while (nanos % 1000 == 0) {
+    nanos /= 1000;
+    digits -= 3;
+  }
+
+  jsonenc_printf(e, ".%.*" PRId32, digits, nanos);
+}
+
+static void jsonenc_timestamp(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2);
+  int64_t seconds = upb_msg_get(msg, seconds_f).int64_val;
+  int32_t nanos = upb_msg_get(msg, nanos_f).int32_val;
+  int L, N, I, J, K, hour, min, sec;
+
+  if (seconds < -62135596800) {
+    jsonenc_err(e,
+                "error formatting timestamp as JSON: minimum acceptable value "
+                "is 0001-01-01T00:00:00Z");
+  } else if (seconds > 253402300799) {
+    jsonenc_err(e,
+                "error formatting timestamp as JSON: maximum acceptable value "
+                "is 9999-12-31T23:59:59Z");
+  }
+
+  /* Julian Day -> Y/M/D, Algorithm from:
+   * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
+   *   Processing Calendar Dates," Communications of the Association of
+   *   Computing Machines, vol. 11 (1968), p. 657.  */
+  L = (int)(seconds / 86400) + 68569 + 2440588;
+  N = 4 * L / 146097;
+  L = L - (146097 * N + 3) / 4;
+  I = 4000 * (L + 1) / 1461001;
+  L = L - 1461 * I / 4 + 31;
+  J = 80 * L / 2447;
+  K = L - 2447 * J / 80;
+  L = J / 11;
+  J = J + 2 - 12 * L;
+  I = 100 * (N - 49) + I + L;
+
+  sec = seconds % 60;
+  min = (seconds / 60) % 60;
+  hour = (seconds / 3600) % 24;
+
+  jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec);
+  jsonenc_nanos(e, nanos);
+  jsonenc_putstr(e, "Z\"");
+}
+
+static void jsonenc_duration(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2);
+  int64_t seconds = upb_msg_get(msg, seconds_f).int64_val;
+  int32_t nanos = upb_msg_get(msg, nanos_f).int32_val;
+
+  if (seconds > 315576000000 || seconds < -315576000000 ||
+      (seconds < 0) != (nanos < 0)) {
+    jsonenc_err(e, "bad duration");
+  }
+
+  if (nanos < 0) {
+    nanos = -nanos;
+  }
+
+  jsonenc_printf(e, "\"%" PRId64, seconds);
+  jsonenc_nanos(e, nanos);
+  jsonenc_putstr(e, "s\"");
+}
+
+static void jsonenc_enum(int32_t val, const upb_fielddef *f, jsonenc *e) {
+  const upb_enumdef *e_def = upb_fielddef_enumsubdef(f);
+
+  if (strcmp(upb_enumdef_fullname(e_def), "google.protobuf.NullValue") == 0) {
+    jsonenc_putstr(e, "null");
+  } else {
+    const char *name = upb_enumdef_iton(e_def, val);
+
+    if (name) {
+      jsonenc_printf(e, "\"%s\"", name);
+    } else {
+      jsonenc_printf(e, "%" PRId32, val);
+    }
+  }
+}
+
+static void jsonenc_bytes(jsonenc *e, upb_strview str) {
+  /* This is the regular base64, not the "web-safe" version. */
+  static const char base64[] =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  const unsigned char *ptr = (unsigned char*)str.data;
+  const unsigned char *end = UPB_PTRADD(ptr, str.size);
+  char buf[4];
+
+  jsonenc_putstr(e, "\"");
+
+  while (end - ptr >= 3) {
+    buf[0] = base64[ptr[0] >> 2];
+    buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+    buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)];
+    buf[3] = base64[ptr[2] & 0x3f];
+    jsonenc_putbytes(e, buf, 4);
+    ptr += 3;
+  }
+
+  switch (end - ptr) {
+    case 2:
+      buf[0] = base64[ptr[0] >> 2];
+      buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+      buf[2] = base64[(ptr[1] & 0xf) << 2];
+      buf[3] = '=';
+      jsonenc_putbytes(e, buf, 4);
+      break;
+    case 1:
+      buf[0] = base64[ptr[0] >> 2];
+      buf[1] = base64[((ptr[0] & 0x3) << 4)];
+      buf[2] = '=';
+      buf[3] = '=';
+      jsonenc_putbytes(e, buf, 4);
+      break;
+  }
+
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_stringbody(jsonenc *e, upb_strview str) {
+  const char *ptr = str.data;
+  const char *end = UPB_PTRADD(ptr, str.size);
+
+  while (ptr < end) {
+    switch (*ptr) {
+      case '\n':
+        jsonenc_putstr(e, "\\n");
+        break;
+      case '\r':
+        jsonenc_putstr(e, "\\r");
+        break;
+      case '\t':
+        jsonenc_putstr(e, "\\t");
+        break;
+      case '\"':
+        jsonenc_putstr(e, "\\\"");
+        break;
+      case '\f':
+        jsonenc_putstr(e, "\\f");
+        break;
+      case '\b':
+        jsonenc_putstr(e, "\\b");
+        break;
+      case '\\':
+        jsonenc_putstr(e, "\\\\");
+        break;
+      default:
+        if ((uint8_t)*ptr < 0x20) {
+          jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr);
+        } else {
+          /* This could be a non-ASCII byte.  We rely on the string being valid
+           * UTF-8. */
+          jsonenc_putbytes(e, ptr, 1);
+        }
+        break;
+    }
+    ptr++;
+  }
+}
+
+static void jsonenc_string(jsonenc *e, upb_strview str) {
+  jsonenc_putstr(e, "\"");
+  jsonenc_stringbody(e, str);
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_double(jsonenc *e, const char *fmt, double val) {
+  if (val == INFINITY) {
+    jsonenc_putstr(e, "\"Infinity\"");
+  } else if (val == -INFINITY) {
+    jsonenc_putstr(e, "\"-Infinity\"");
+  } else if (val != val) {
+    jsonenc_putstr(e, "\"NaN\"");
+  } else {
+    jsonenc_printf(e, fmt, val);
+  }
+}
+
+static void jsonenc_wrapper(jsonenc *e, const upb_msg *msg,
+                            const upb_msgdef *m) {
+  const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
+  upb_msgval val = upb_msg_get(msg, val_f);
+  jsonenc_scalar(e, val, val_f);
+}
+
+static const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) {
+  /* Find last '/', if any. */
+  const char *end = type_url.data + type_url.size;
+  const char *ptr = end;
+  const upb_msgdef *ret;
+
+  if (!e->ext_pool) {
+    jsonenc_err(e, "Tried to encode Any, but no symtab was provided");
+  }
+
+  if (type_url.size == 0) goto badurl;
+
+  while (true) {
+    if (--ptr == type_url.data) {
+      /* Type URL must contain at least one '/', with host before. */
+      goto badurl;
+    }
+    if (*ptr == '/') {
+      ptr++;
+      break;
+    }
+  }
+
+  ret = upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr);
+
+  if (!ret) {
+    jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr);
+  }
+
+  return ret;
+
+badurl:
+  jsonenc_errf(
+      e, "Bad type URL: " UPB_STRVIEW_FORMAT, UPB_STRVIEW_ARGS(type_url));
+}
+
+static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 2);
+  upb_strview type_url = upb_msg_get(msg, type_url_f).str_val;
+  upb_strview value = upb_msg_get(msg, value_f).str_val;
+  const upb_msgdef *any_m = jsonenc_getanymsg(e, type_url);
+  const upb_msglayout *any_layout = upb_msgdef_layout(any_m);
+  upb_arena *arena = jsonenc_arena(e);
+  upb_msg *any = upb_msg_new(any_m, arena);
+
+  if (!upb_decode(value.data, value.size, any, any_layout, arena)) {
+    jsonenc_err(e, "Error decoding message in Any");
+  }
+
+  jsonenc_putstr(e, "{\"@type\":");
+  jsonenc_string(e, type_url);
+
+  if (upb_msgdef_wellknowntype(any_m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */
+    jsonenc_msgfields(e, any, any_m, false);
+  } else {
+    /* Well-known type: {"@type": "...","value": <well-known encoding>} */
+    jsonenc_putstr(e, ",\"value\":");
+    jsonenc_msgfield(e, any, any_m);
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_putsep(jsonenc *e, const char *str, bool *first) {
+  if (*first) {
+    *first = false;
+  } else {
+    jsonenc_putstr(e, str);
+  }
+}
+
+static void jsonenc_fieldpath(jsonenc *e, upb_strview path) {
+  const char *ptr = path.data;
+  const char *end = ptr + path.size;
+
+  while (ptr < end) {
+    char ch = *ptr;
+
+    if (ch >= 'A' && ch <= 'Z') {
+      jsonenc_err(e, "Field mask element may not have upper-case letter.");
+    } else if (ch == '_') {
+      if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') {
+        jsonenc_err(e, "Underscore must be followed by a lowercase letter.");
+      }
+      ch = *++ptr - 32;
+    }
+
+    jsonenc_putbytes(e, &ch, 1);
+    ptr++;
+  }
+}
+
+static void jsonenc_fieldmask(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *paths_f = upb_msgdef_itof(m, 1);
+  const upb_array *paths = upb_msg_get(msg, paths_f).array_val;
+  bool first = true;
+  size_t i, n = 0;
+
+  if (paths) n = upb_array_size(paths);
+
+  jsonenc_putstr(e, "\"");
+
+  for (i = 0; i < n; i++) {
+    jsonenc_putsep(e, ",", &first);
+    jsonenc_fieldpath(e, upb_array_get(paths, i).str_val);
+  }
+
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_struct(jsonenc *e, const upb_msg *msg,
+                           const upb_msgdef *m) {
+  const upb_fielddef *fields_f = upb_msgdef_itof(m, 1);
+  const upb_map *fields = upb_msg_get(msg, fields_f).map_val;
+  const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f);
+  const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2);
+  size_t iter = UPB_MAP_BEGIN;
+  bool first = true;
+
+  jsonenc_putstr(e, "{");
+
+  if (fields) {
+    while (upb_mapiter_next(fields, &iter)) {
+      upb_msgval key = upb_mapiter_key(fields, iter);
+      upb_msgval val = upb_mapiter_value(fields, iter);
+
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_string(e, key.str_val);
+      jsonenc_putstr(e, ":");
+      jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f));
+    }
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_listvalue(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *values_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *values_m = upb_fielddef_msgsubdef(values_f);
+  const upb_array *values = upb_msg_get(msg, values_f).array_val;
+  size_t i;
+  bool first = true;
+
+  jsonenc_putstr(e, "[");
+
+  if (values) {
+    const size_t size = upb_array_size(values);
+    for (i = 0; i < size; i++) {
+      upb_msgval elem = upb_array_get(values, i);
+
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_value(e, elem.msg_val, values_m);
+    }
+  }
+
+  jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  /* TODO(haberman): do we want a reflection method to get oneof case? */
+  size_t iter = UPB_MSG_BEGIN;
+  const upb_fielddef *f;
+  upb_msgval val;
+
+  if (!upb_msg_next(msg, m, NULL,  &f, &val, &iter)) {
+    jsonenc_err(e, "No value set in Value proto");
+  }
+
+  switch (upb_fielddef_number(f)) {
+    case 1:
+      jsonenc_putstr(e, "null");
+      break;
+    case 2:
+      jsonenc_double(e, "%.17g", val.double_val);
+      break;
+    case 3:
+      jsonenc_string(e, val.str_val);
+      break;
+    case 4:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case 5:
+      jsonenc_struct(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+    case 6:
+      jsonenc_listvalue(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+  }
+}
+
+static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg,
+                             const upb_msgdef *m) {
+  switch (upb_msgdef_wellknowntype(m)) {
+    case UPB_WELLKNOWN_UNSPECIFIED:
+      jsonenc_msg(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_ANY:
+      jsonenc_any(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_FIELDMASK:
+      jsonenc_fieldmask(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_DURATION:
+      jsonenc_duration(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_TIMESTAMP:
+      jsonenc_timestamp(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_DOUBLEVALUE:
+    case UPB_WELLKNOWN_FLOATVALUE:
+    case UPB_WELLKNOWN_INT64VALUE:
+    case UPB_WELLKNOWN_UINT64VALUE:
+    case UPB_WELLKNOWN_INT32VALUE:
+    case UPB_WELLKNOWN_UINT32VALUE:
+    case UPB_WELLKNOWN_STRINGVALUE:
+    case UPB_WELLKNOWN_BYTESVALUE:
+    case UPB_WELLKNOWN_BOOLVALUE:
+      jsonenc_wrapper(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_VALUE:
+      jsonenc_value(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_LISTVALUE:
+      jsonenc_listvalue(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_STRUCT:
+      jsonenc_struct(e, msg, m);
+      break;
+  }
+}
+
+static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_FLOAT:
+      jsonenc_double(e, "%.9g", val.float_val);
+      break;
+    case UPB_TYPE_DOUBLE:
+      jsonenc_double(e, "%.17g", val.double_val);
+      break;
+    case UPB_TYPE_INT32:
+      jsonenc_printf(e, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      jsonenc_string(e, val.str_val);
+      break;
+    case UPB_TYPE_BYTES:
+      jsonenc_bytes(e, val.str_val);
+      break;
+    case UPB_TYPE_ENUM:
+      jsonenc_enum(val.int32_val, f, e);
+      break;
+    case UPB_TYPE_MESSAGE:
+      jsonenc_msgfield(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+  }
+}
+
+static void jsonenc_mapkey(jsonenc *e, upb_msgval val, const upb_fielddef *f) {
+  jsonenc_putstr(e, "\"");
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_INT32:
+      jsonenc_printf(e, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      jsonenc_printf(e, "%" PRId64, val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      jsonenc_printf(e, "%" PRIu64, val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      jsonenc_stringbody(e, val.str_val);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  jsonenc_putstr(e, "\":");
+}
+
+static void jsonenc_array(jsonenc *e, const upb_array *arr,
+                         const upb_fielddef *f) {
+  size_t i;
+  size_t size = arr ? upb_array_size(arr) : 0;
+  bool first = true;
+
+  jsonenc_putstr(e, "[");
+
+  for (i = 0; i < size; i++) {
+    jsonenc_putsep(e, ",", &first);
+    jsonenc_scalar(e, upb_array_get(arr, i), f);
+  }
+
+  jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_map(jsonenc *e, const upb_map *map, const upb_fielddef *f) {
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+  const upb_fielddef *key_f = upb_msgdef_itof(entry, 1);
+  const upb_fielddef *val_f = upb_msgdef_itof(entry, 2);
+  size_t iter = UPB_MAP_BEGIN;
+  bool first = true;
+
+  jsonenc_putstr(e, "{");
+
+  if (map) {
+    while (upb_mapiter_next(map, &iter)) {
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f);
+      jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f);
+    }
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_fieldval(jsonenc *e, const upb_fielddef *f,
+                             upb_msgval val, bool *first) {
+  const char *name;
+
+  if (e->options & UPB_JSONENC_PROTONAMES) {
+    name = upb_fielddef_name(f);
+  } else {
+    name = upb_fielddef_jsonname(f);
+  }
+
+  jsonenc_putsep(e, ",", first);
+  jsonenc_printf(e, "\"%s\":", name);
+
+  if (upb_fielddef_ismap(f)) {
+    jsonenc_map(e, val.map_val, f);
+  } else if (upb_fielddef_isseq(f)) {
+    jsonenc_array(e, val.array_val, f);
+  } else {
+    jsonenc_scalar(e, val, f);
+  }
+}
+
+static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m, bool first) {
+  upb_msgval val;
+  const upb_fielddef *f;
+
+  if (e->options & UPB_JSONENC_EMITDEFAULTS) {
+    /* Iterate over all fields. */
+    int i = 0;
+    int n = upb_msgdef_fieldcount(m);
+    for (i = 0; i < n; i++) {
+      f = upb_msgdef_field(m, i);
+      if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
+        jsonenc_fieldval(e, f, upb_msg_get(msg, f), &first);
+      }
+    }
+  } else {
+    /* Iterate over non-empty fields. */
+    size_t iter = UPB_MSG_BEGIN;
+    while (upb_msg_next(msg, m, e->ext_pool, &f, &val, &iter)) {
+      jsonenc_fieldval(e, f, val, &first);
+    }
+  }
+}
+
+static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  jsonenc_putstr(e, "{");
+  jsonenc_msgfields(e, msg, m, true);
+  jsonenc_putstr(e, "}");
+}
+
+static size_t jsonenc_nullz(jsonenc *e, size_t size) {
+  size_t ret = e->ptr - e->buf + e->overflow;
+
+  if (size > 0) {
+    if (e->ptr == e->end) e->ptr--;
+    *e->ptr = '\0';
+  }
+
+  return ret;
+}
+
+size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
+                       const upb_symtab *ext_pool, int options, char *buf,
+                       size_t size, upb_status *status) {
+  jsonenc e;
+
+  e.buf = buf;
+  e.ptr = buf;
+  e.end = UPB_PTRADD(buf, size);
+  e.overflow = 0;
+  e.options = options;
+  e.ext_pool = ext_pool;
+  e.status = status;
+  e.arena = NULL;
+
+  if (setjmp(e.err)) return -1;
+
+  jsonenc_msgfield(&e, msg, m);
+  if (e.arena) upb_arena_free(e.arena);
+  return jsonenc_nullz(&e, size);
+}
+
+/** upb/port_undef.inc ************************************************************/
+/* See port_def.inc.  This should #undef all macros #defined there. */
+
+#undef UPB_SIZE
+#undef UPB_PTR_AT
+#undef UPB_READ_ONEOF
+#undef UPB_WRITE_ONEOF
+#undef UPB_MAPTYPE_STRING
+#undef UPB_INLINE
+#undef UPB_ALIGN_UP
+#undef UPB_ALIGN_DOWN
+#undef UPB_ALIGN_MALLOC
+#undef UPB_ALIGN_OF
+#undef UPB_LIKELY
+#undef UPB_UNLIKELY
+#undef UPB_FORCEINLINE
+#undef UPB_NOINLINE
+#undef UPB_NORETURN
+#undef UPB_PRINTF
+#undef UPB_MAX
+#undef UPB_MIN
+#undef UPB_UNUSED
+#undef UPB_ASSUME
+#undef UPB_ASSERT
+#undef UPB_UNREACHABLE
+#undef UPB_SETJMP
+#undef UPB_LONGJMP
+#undef UPB_PTRADD
+#undef UPB_MUSTTAIL
+#undef UPB_FASTTABLE_SUPPORTED
+#undef UPB_FASTTABLE
+#undef UPB_FASTTABLE_INIT
+#undef UPB_POISON_MEMORY_REGION
+#undef UPB_UNPOISON_MEMORY_REGION
+#undef UPB_ASAN
diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h
new file mode 100644
index 0000000..77a87c7
--- /dev/null
+++ b/php/ext/google/protobuf/php-upb.h
@@ -0,0 +1,4572 @@
+/* Amalgamated source file */
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google LLC nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is where we define macros used across upb.
+ *
+ * All of these macros are undef'd in port_undef.inc to avoid leaking them to
+ * users.
+ *
+ * The correct usage is:
+ *
+ *   #include "upb/foobar.h"
+ *   #include "upb/baz.h"
+ *
+ *   // MUST be last included header.
+ *   #include "upb/port_def.inc"
+ *
+ *   // Code for this file.
+ *   // <...>
+ *
+ *   // Can be omitted for .c files, required for .h.
+ *   #include "upb/port_undef.inc"
+ *
+ * This file is private and must not be included by users!
+ */
+
+#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+      (defined(__cplusplus) && __cplusplus >= 201103L) ||           \
+      (defined(_MSC_VER) && _MSC_VER >= 1900))
+#error upb requires C99 or C++11 or MSVC >= 2015.
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#if UINTPTR_MAX == 0xffffffff
+#define UPB_SIZE(size32, size64) size32
+#else
+#define UPB_SIZE(size32, size64) size64
+#endif
+
+/* If we always read/write as a consistent type to each address, this shouldn't
+ * violate aliasing.
+ */
+#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
+
+#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
+  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
+      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
+      : default
+
+#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
+  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
+  *UPB_PTR_AT(msg, offset, fieldtype) = value;
+
+#define UPB_MAPTYPE_STRING 0
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__) || defined(__clang__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
+#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
+#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
+#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
+
+/* Hints to the compiler about likely/unlikely branches. */
+#if defined (__GNUC__) || defined(__clang__)
+#define UPB_LIKELY(x) __builtin_expect((x),1)
+#define UPB_UNLIKELY(x) __builtin_expect((x),0)
+#else
+#define UPB_LIKELY(x) (x)
+#define UPB_UNLIKELY(x) (x)
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg)))
+#elif defined(_MSC_VER)
+#define UPB_NOINLINE
+#define UPB_FORCEINLINE
+#define UPB_NORETURN __declspec(noreturn)
+#define UPB_PRINTF(str, first_vararg)
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#define UPB_PRINTF(str, first_vararg)
+#endif
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
+ */
+#ifdef NDEBUG
+#ifdef __GNUC__
+#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
+#elif defined _MSC_VER
+#define UPB_ASSUME(expr) if (!(expr)) __assume(0)
+#else
+#define UPB_ASSUME(expr) do {} while (false && (expr))
+#endif
+#else
+#define UPB_ASSUME(expr) assert(expr)
+#endif
+
+/* UPB_ASSERT(): in release mode, we use the expression without letting it be
+ * evaluated.  This prevents "unused variable" warnings. */
+#ifdef NDEBUG
+#define UPB_ASSERT(expr) do {} while (false && (expr))
+#else
+#define UPB_ASSERT(expr) assert(expr)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
+#else
+#define UPB_UNREACHABLE() do { assert(0); } while(0)
+#endif
+
+/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
+#ifdef __APPLE__
+#define UPB_SETJMP(buf) _setjmp(buf)
+#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
+#else
+#define UPB_SETJMP(buf) setjmp(buf)
+#define UPB_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */
+#define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr))
+
+/* Configure whether fasttable is switched on or not. *************************/
+
+#if defined(__has_attribute)
+#define UPB_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define UPB_HAS_ATTRIBUTE(x) 0
+#endif
+
+#if UPB_HAS_ATTRIBUTE(musttail)
+#define UPB_MUSTTAIL __attribute__((musttail))
+#else
+#define UPB_MUSTTAIL
+#endif
+
+#undef UPB_HAS_ATTRIBUTE
+
+/* This check is not fully robust: it does not require that we have "musttail"
+ * support available. We need tail calls to avoid consuming arbitrary amounts
+ * of stack space.
+ *
+ * GCC/Clang can mostly be trusted to generate tail calls as long as
+ * optimization is enabled, but, debug builds will not generate tail calls
+ * unless "musttail" is available.
+ *
+ * We should probably either:
+ *   1. require that the compiler supports musttail.
+ *   2. add some fallback code for when musttail isn't available (ie. return
+ *      instead of tail calling). This is safe and portable, but this comes at
+ *      a CPU cost.
+ */
+#if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__)
+#define UPB_FASTTABLE_SUPPORTED 1
+#else
+#define UPB_FASTTABLE_SUPPORTED 0
+#endif
+
+/* define UPB_ENABLE_FASTTABLE to force fast table support.
+ * This is useful when we want to ensure we are really getting fasttable,
+ * for example for testing or benchmarking. */
+#if defined(UPB_ENABLE_FASTTABLE)
+#if !UPB_FASTTABLE_SUPPORTED
+#error fasttable is x86-64/ARM64 only and requires GCC or Clang.
+#endif
+#define UPB_FASTTABLE 1
+/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
+ * This is useful for releasing code that might be used on multiple platforms,
+ * for example the PHP or Ruby C extensions. */
+#elif defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
+#else
+#define UPB_FASTTABLE 0
+#endif
+
+/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
+ * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */
+#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE_INIT(...)
+#else
+#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
+#endif
+
+#undef UPB_FASTTABLE_SUPPORTED
+
+/* ASAN poisoning (for arena) *************************************************/
+
+#if defined(__SANITIZE_ADDRESS__)
+#define UPB_ASAN 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  __asan_poison_memory_region((addr), (size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  __asan_unpoison_memory_region((addr), (size))
+#else
+#define UPB_ASAN 0
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#endif
+
+/** upb/decode.h ************************************************************/
+/*
+ * upb_decode: parsing into a upb_msg using a upb_msglayout.
+ */
+
+#ifndef UPB_DECODE_H_
+#define UPB_DECODE_H_
+
+
+/** upb/msg.h ************************************************************/
+/*
+ * Public APIs for message operations that do not require descriptors.
+ * These functions can be used even in build that does not want to depend on
+ * reflection or descriptors.
+ *
+ * Descriptor-based reflection functionality lives in reflection.h.
+ */
+
+#ifndef UPB_MSG_H_
+#define UPB_MSG_H_
+
+#include <stddef.h>
+
+
+/** upb/upb.h ************************************************************/
+/*
+ * This file contains shared definitions that are widely used across upb.
+ */
+
+#ifndef UPB_H_
+#define UPB_H_
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* upb_status *****************************************************************/
+
+#define UPB_STATUS_MAX_MESSAGE 127
+
+typedef struct {
+  bool ok;
+  char msg[UPB_STATUS_MAX_MESSAGE];  /* Error message; NULL-terminated. */
+} upb_status;
+
+const char *upb_status_errmsg(const upb_status *status);
+bool upb_ok(const upb_status *status);
+
+/* These are no-op if |status| is NULL. */
+void upb_status_clear(upb_status *status);
+void upb_status_seterrmsg(upb_status *status, const char *msg);
+void upb_status_seterrf(upb_status *status, const char *fmt, ...)
+    UPB_PRINTF(2, 3);
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args)
+    UPB_PRINTF(2, 0);
+void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args)
+    UPB_PRINTF(2, 0);
+
+/** upb_strview ************************************************************/
+
+typedef struct {
+  const char *data;
+  size_t size;
+} upb_strview;
+
+UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
+  upb_strview ret;
+  ret.data = data;
+  ret.size = size;
+  return ret;
+}
+
+UPB_INLINE upb_strview upb_strview_makez(const char *data) {
+  return upb_strview_make(data, strlen(data));
+}
+
+UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
+  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
+}
+
+#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
+
+#define UPB_STRVIEW_FORMAT "%.*s"
+#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
+
+/** upb_alloc *****************************************************************/
+
+/* A upb_alloc is a possibly-stateful allocator object.
+ *
+ * It could either be an arena allocator (which doesn't require individual
+ * free() calls) or a regular malloc() (which does).  The client must therefore
+ * free memory unless it knows that the allocator is an arena allocator. */
+
+struct upb_alloc;
+typedef struct upb_alloc upb_alloc;
+
+/* A malloc()/free() function.
+ * If "size" is 0 then the function acts like free(), otherwise it acts like
+ * realloc().  Only "oldsize" bytes from a previous allocation are preserved. */
+typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size);
+
+struct upb_alloc {
+  upb_alloc_func *func;
+};
+
+UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
+  UPB_ASSERT(alloc);
+  return alloc->func(alloc, NULL, 0, size);
+}
+
+UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size) {
+  UPB_ASSERT(alloc);
+  return alloc->func(alloc, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
+  assert(alloc);
+  alloc->func(alloc, ptr, 0, 0);
+}
+
+/* The global allocator used by upb.  Uses the standard malloc()/free(). */
+
+extern upb_alloc upb_alloc_global;
+
+/* Functions that hard-code the global malloc.
+ *
+ * We still get benefit because we can put custom logic into our global
+ * allocator, like injecting out-of-memory faults in debug/testing builds. */
+
+UPB_INLINE void *upb_gmalloc(size_t size) {
+  return upb_malloc(&upb_alloc_global, size);
+}
+
+UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
+  return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_gfree(void *ptr) {
+  upb_free(&upb_alloc_global, ptr);
+}
+
+/* upb_arena ******************************************************************/
+
+/* upb_arena is a specific allocator implementation that uses arena allocation.
+ * The user provides an allocator that will be used to allocate the underlying
+ * arena blocks.  Arenas by nature do not require the individual allocations
+ * to be freed.  However the Arena does allow users to register cleanup
+ * functions that will run when the arena is destroyed.
+ *
+ * A upb_arena is *not* thread-safe.
+ *
+ * You could write a thread-safe arena allocator that satisfies the
+ * upb_alloc interface, but it would not be as efficient for the
+ * single-threaded case. */
+
+typedef void upb_cleanup_func(void *ud);
+
+struct upb_arena;
+typedef struct upb_arena upb_arena;
+
+typedef struct {
+  /* We implement the allocator interface.
+   * This must be the first member of upb_arena!
+   * TODO(haberman): remove once handlers are gone. */
+  upb_alloc alloc;
+
+  char *ptr, *end;
+} _upb_arena_head;
+
+/* Creates an arena from the given initial block (if any -- n may be 0).
+ * Additional blocks will be allocated from |alloc|.  If |alloc| is NULL, this
+ * is a fixed-size arena and cannot grow. */
+upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
+void upb_arena_free(upb_arena *a);
+bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
+bool upb_arena_fuse(upb_arena *a, upb_arena *b);
+void *_upb_arena_slowmalloc(upb_arena *a, size_t size);
+
+UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
+
+UPB_INLINE size_t _upb_arenahas(upb_arena *a) {
+  _upb_arena_head *h = (_upb_arena_head*)a;
+  return (size_t)(h->end - h->ptr);
+}
+
+UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
+  _upb_arena_head *h = (_upb_arena_head*)a;
+  void* ret;
+  size = UPB_ALIGN_MALLOC(size);
+
+  if (UPB_UNLIKELY(_upb_arenahas(a) < size)) {
+    return _upb_arena_slowmalloc(a, size);
+  }
+
+  ret = h->ptr;
+  h->ptr += size;
+  UPB_UNPOISON_MEMORY_REGION(ret, size);
+
+#if UPB_ASAN
+  {
+    size_t guard_size = 32;
+    if (_upb_arenahas(a) >= guard_size) {
+      h->ptr += guard_size;
+    } else {
+      h->ptr = h->end;
+    }
+  }
+#endif
+
+  return ret;
+}
+
+UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
+                                   size_t size) {
+  void *ret = upb_arena_malloc(a, size);
+
+  if (ret && oldsize > 0) {
+    memcpy(ret, ptr, oldsize);
+  }
+
+  return ret;
+}
+
+UPB_INLINE upb_arena *upb_arena_new(void) {
+  return upb_arena_init(NULL, 0, &upb_alloc_global);
+}
+
+/* Constants ******************************************************************/
+
+/* Generic function type. */
+typedef void upb_func(void);
+
+/* A list of types as they are encoded on-the-wire. */
+typedef enum {
+  UPB_WIRE_TYPE_VARINT      = 0,
+  UPB_WIRE_TYPE_64BIT       = 1,
+  UPB_WIRE_TYPE_DELIMITED   = 2,
+  UPB_WIRE_TYPE_START_GROUP = 3,
+  UPB_WIRE_TYPE_END_GROUP   = 4,
+  UPB_WIRE_TYPE_32BIT       = 5
+} upb_wiretype_t;
+
+/* The types a field can have.  Note that this list is not identical to the
+ * types defined in descriptor.proto, which gives INT32 and SINT32 separate
+ * types (we distinguish the two with the "integer encoding" enum below). */
+typedef enum {
+  UPB_TYPE_BOOL     = 1,
+  UPB_TYPE_FLOAT    = 2,
+  UPB_TYPE_INT32    = 3,
+  UPB_TYPE_UINT32   = 4,
+  UPB_TYPE_ENUM     = 5,  /* Enum values are int32. */
+  UPB_TYPE_MESSAGE  = 6,
+  UPB_TYPE_DOUBLE   = 7,
+  UPB_TYPE_INT64    = 8,
+  UPB_TYPE_UINT64   = 9,
+  UPB_TYPE_STRING   = 10,
+  UPB_TYPE_BYTES    = 11
+} upb_fieldtype_t;
+
+/* The repeated-ness of each field; this matches descriptor.proto. */
+typedef enum {
+  UPB_LABEL_OPTIONAL = 1,
+  UPB_LABEL_REQUIRED = 2,
+  UPB_LABEL_REPEATED = 3
+} upb_label_t;
+
+/* Descriptor types, as defined in descriptor.proto. */
+typedef enum {
+  /* Old (long) names.  TODO(haberman): remove */
+  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
+  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
+  UPB_DESCRIPTOR_TYPE_INT64    = 3,
+  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
+  UPB_DESCRIPTOR_TYPE_INT32    = 5,
+  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
+  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
+  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
+  UPB_DESCRIPTOR_TYPE_STRING   = 9,
+  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
+  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
+  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
+  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
+  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
+  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
+  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
+  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
+  UPB_DESCRIPTOR_TYPE_SINT64   = 18,
+
+  UPB_DTYPE_DOUBLE   = 1,
+  UPB_DTYPE_FLOAT    = 2,
+  UPB_DTYPE_INT64    = 3,
+  UPB_DTYPE_UINT64   = 4,
+  UPB_DTYPE_INT32    = 5,
+  UPB_DTYPE_FIXED64  = 6,
+  UPB_DTYPE_FIXED32  = 7,
+  UPB_DTYPE_BOOL     = 8,
+  UPB_DTYPE_STRING   = 9,
+  UPB_DTYPE_GROUP    = 10,
+  UPB_DTYPE_MESSAGE  = 11,
+  UPB_DTYPE_BYTES    = 12,
+  UPB_DTYPE_UINT32   = 13,
+  UPB_DTYPE_ENUM     = 14,
+  UPB_DTYPE_SFIXED32 = 15,
+  UPB_DTYPE_SFIXED64 = 16,
+  UPB_DTYPE_SINT32   = 17,
+  UPB_DTYPE_SINT64   = 18
+} upb_descriptortype_t;
+
+#define UPB_MAP_BEGIN ((size_t)-1)
+
+UPB_INLINE bool _upb_isle(void) {
+  int x = 1;
+  return *(char*)&x == 1;
+}
+
+UPB_INLINE uint32_t _upb_be_swap32(uint32_t val) {
+  if (_upb_isle()) {
+    return val;
+  } else {
+    return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+           ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
+  }
+}
+
+UPB_INLINE uint64_t _upb_be_swap64(uint64_t val) {
+  if (_upb_isle()) {
+    return val;
+  } else {
+    return ((uint64_t)_upb_be_swap32(val) << 32) | _upb_be_swap32(val >> 32);
+  }
+}
+
+UPB_INLINE int _upb_lg2ceil(int x) {
+  if (x <= 1) return 0;
+#ifdef __GNUC__
+  return 32 - __builtin_clz(x - 1);
+#else
+  int lg2 = 0;
+  while (1 << lg2 < x) lg2++;
+  return lg2;
+#endif
+}
+
+UPB_INLINE int _upb_lg2ceilsize(int x) {
+  return 1 << _upb_lg2ceil(x);
+}
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_H_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void upb_msg;
+
+/* For users these are opaque. They can be obtained from upb_msgdef_layout()
+ * but users cannot access any of the members. */
+struct upb_msglayout;
+typedef struct upb_msglayout upb_msglayout;
+
+/* Adds unknown data (serialized protobuf data) to the given message.  The data
+ * is copied into the message instance. */
+void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                        upb_arena *arena);
+
+/* Returns a reference to the message's unknown data. */
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* UPB_MSG_INT_H_ */
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* If set, strings will alias the input buffer instead of copying into the
+   * arena. */
+  UPB_DECODE_ALIAS = 1,
+};
+
+#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
+
+bool _upb_decode(const char *buf, size_t size, upb_msg *msg,
+                 const upb_msglayout *l, upb_arena *arena, int options);
+
+UPB_INLINE
+bool upb_decode(const char *buf, size_t size, upb_msg *msg,
+                const upb_msglayout *l, upb_arena *arena) {
+  return _upb_decode(buf, size, msg, l, arena, 0);
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* UPB_DECODE_H_ */
+
+/** upb/decode_internal.h ************************************************************/
+/*
+ * Internal implementation details of the decoder that are shared between
+ * decode.c and decode_fast.c.
+ */
+
+#ifndef UPB_DECODE_INT_H_
+#define UPB_DECODE_INT_H_
+
+#include <setjmp.h>
+
+
+/** upb/msg_internal.h ************************************************************//*
+** Our memory representation for parsing tables and messages themselves.
+** Functions in this file are used by generated code and possibly reflection.
+**
+** The definitions in this file are internal to upb.
+**/
+
+#ifndef UPB_MSG_INT_H_
+#define UPB_MSG_INT_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/** upb/table_internal.h ************************************************************/
+/*
+ * upb_table
+ *
+ * This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
+ * This file defines very fast int->upb_value (inttable) and string->upb_value
+ * (strtable) hash tables.
+ *
+ * The table uses chained scatter with Brent's variation (inspired by the Lua
+ * implementation of hash tables).  The hash function for strings is Austin
+ * Appleby's "MurmurHash."
+ *
+ * The inttable uses uintptr_t as its key, which guarantees it can be used to
+ * store pointers or integers of at least 32 bits (upb isn't really useful on
+ * systems where sizeof(void*) < 4).
+ *
+ * The table must be homogeneous (all values of the same type).  In debug
+ * mode, we check this on insert and lookup.
+ */
+
+#ifndef UPB_TABLE_H_
+#define UPB_TABLE_H_
+
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* upb_value ******************************************************************/
+
+typedef struct {
+  uint64_t val;
+} upb_value;
+
+/* Variant that works with a length-delimited rather than NULL-delimited string,
+ * as supported by strtable. */
+char *upb_strdup2(const char *s, size_t len, upb_arena *a);
+
+UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) {
+  v->val = val;
+}
+
+/* For each value ctype, define the following set of functions:
+ *
+ * // Get/set an int32 from a upb_value.
+ * int32_t upb_value_getint32(upb_value val);
+ * void upb_value_setint32(upb_value *val, int32_t cval);
+ *
+ * // Construct a new upb_value from an int32.
+ * upb_value upb_value_int32(int32_t val); */
+#define FUNCS(name, membername, type_t, converter, proto_type) \
+  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
+    val->val = (converter)cval; \
+  } \
+  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
+    upb_value ret; \
+    upb_value_set ## name(&ret, val); \
+    return ret; \
+  } \
+  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
+    return (type_t)(converter)val.val; \
+  }
+
+FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
+FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
+FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
+FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
+FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
+FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
+FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
+FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
+FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
+
+#undef FUNCS
+
+UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
+  memcpy(&val->val, &cval, sizeof(cval));
+}
+
+UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
+  memcpy(&val->val, &cval, sizeof(cval));
+}
+
+UPB_INLINE upb_value upb_value_float(float cval) {
+  upb_value ret;
+  upb_value_setfloat(&ret, cval);
+  return ret;
+}
+
+UPB_INLINE upb_value upb_value_double(double cval) {
+  upb_value ret;
+  upb_value_setdouble(&ret, cval);
+  return ret;
+}
+
+#undef SET_TYPE
+
+
+/* upb_tabkey *****************************************************************/
+
+/* Either:
+ *   1. an actual integer key, or
+ *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
+ *
+ * ...depending on whether this is a string table or an int table.  We would
+ * make this a union of those two types, but C89 doesn't support statically
+ * initializing a non-first union member. */
+typedef uintptr_t upb_tabkey;
+
+UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
+  char* mem = (char*)key;
+  if (len) memcpy(len, mem, sizeof(*len));
+  return mem + sizeof(*len);
+}
+
+UPB_INLINE upb_strview upb_tabstrview(upb_tabkey key) {
+  upb_strview ret;
+  uint32_t len;
+  ret.data = upb_tabstr(key, &len);
+  ret.size = len;
+  return ret;
+}
+
+/* upb_tabval *****************************************************************/
+
+typedef struct upb_tabval {
+  uint64_t val;
+} upb_tabval;
+
+#define UPB_TABVALUE_EMPTY_INIT  {-1}
+
+/* upb_table ******************************************************************/
+
+typedef struct _upb_tabent {
+  upb_tabkey key;
+  upb_tabval val;
+
+  /* Internal chaining.  This is const so we can create static initializers for
+   * tables.  We cast away const sometimes, but *only* when the containing
+   * upb_table is known to be non-const.  This requires a bit of care, but
+   * the subtlety is confined to table.c. */
+  const struct _upb_tabent *next;
+} upb_tabent;
+
+typedef struct {
+  size_t count;          /* Number of entries in the hash part. */
+  uint32_t mask;         /* Mask to turn hash value -> bucket. */
+  uint32_t max_count;    /* Max count before we hit our load limit. */
+  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
+  upb_tabent *entries;
+} upb_table;
+
+typedef struct {
+  upb_table t;
+} upb_strtable;
+
+typedef struct {
+  upb_table t;              /* For entries that don't fit in the array part. */
+  const upb_tabval *array;  /* Array part of the table. See const note above. */
+  size_t array_size;        /* Array part size. */
+  size_t array_count;       /* Array part number of elements. */
+} upb_inttable;
+
+UPB_INLINE size_t upb_table_size(const upb_table *t) {
+  if (t->size_lg2 == 0)
+    return 0;
+  else
+    return 1 << t->size_lg2;
+}
+
+/* Internal-only functions, in .h file only out of necessity. */
+UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
+  return e->key == 0;
+}
+
+/* Initialize and uninitialize a table, respectively.  If memory allocation
+ * failed, false is returned that the table is uninitialized. */
+bool upb_inttable_init(upb_inttable *table, upb_arena *a);
+bool upb_strtable_init(upb_strtable *table, size_t expected_size, upb_arena *a);
+
+/* Returns the number of values in the table. */
+size_t upb_inttable_count(const upb_inttable *t);
+UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
+  return t->t.count;
+}
+
+void upb_strtable_clear(upb_strtable *t);
+
+/* Inserts the given key into the hashtable with the given value.  The key must
+ * not already exist in the hash table.  For string tables, the key must be
+ * NULL-terminated, and the table will make an internal copy of the key.
+ * Inttables must not insert a value of UINTPTR_MAX.
+ *
+ * If a table resize was required but memory allocation failed, false is
+ * returned and the table is unchanged. */
+bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val,
+                         upb_arena *a);
+bool upb_strtable_insert(upb_strtable *t, const char *key, size_t len,
+                         upb_value val, upb_arena *a);
+
+/* Looks up key in this table, returning "true" if the key was found.
+ * If v is non-NULL, copies the value for this key into *v. */
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v);
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_lookup2(t, key, strlen(key), v);
+}
+
+/* Removes an item from the table.  Returns true if the remove was successful,
+ * and stores the removed item in *val if non-NULL. */
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
+bool upb_strtable_remove(upb_strtable *t, const char *key, size_t len,
+                          upb_value *val);
+
+/* Updates an existing entry in an inttable.  If the entry does not exist,
+ * returns false and does nothing.  Unlike insert/remove, this does not
+ * invalidate iterators. */
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
+
+/* Optimizes the table for the current set of entries, for both memory use and
+ * lookup time.  Client should call this after all entries have been inserted;
+ * inserting more entries is legal, but will likely require a table resize. */
+void upb_inttable_compact(upb_inttable *t, upb_arena *a);
+
+/* Exposed for testing only. */
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_arena *a);
+
+/* Iterators ******************************************************************/
+
+/* Iterators for int and string tables.  We are subject to some kind of unusual
+ * design constraints:
+ *
+ * For high-level languages:
+ *  - we must be able to guarantee that we don't crash or corrupt memory even if
+ *    the program accesses an invalidated iterator.
+ *
+ * For C++11 range-based for:
+ *  - iterators must be copyable
+ *  - iterators must be comparable
+ *  - it must be possible to construct an "end" value.
+ *
+ * Iteration order is undefined.
+ *
+ * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
+ * guaranteed to work even on an invalidated iterator, as long as the table it
+ * is iterating over has not been freed.  Calling next() or accessing data from
+ * an invalidated iterator yields unspecified elements from the table, but it is
+ * guaranteed not to crash and to return real table elements (except when done()
+ * is true). */
+
+
+/* upb_strtable_iter **********************************************************/
+
+/*   upb_strtable_iter i;
+ *   upb_strtable_begin(&i, t);
+ *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+ *     const char *key = upb_strtable_iter_key(&i);
+ *     const upb_value val = upb_strtable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_strtable *t;
+  size_t index;
+} upb_strtable_iter;
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
+void upb_strtable_next(upb_strtable_iter *i);
+bool upb_strtable_done(const upb_strtable_iter *i);
+upb_strview upb_strtable_iter_key(const upb_strtable_iter *i);
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
+void upb_strtable_iter_setdone(upb_strtable_iter *i);
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2);
+
+
+/* upb_inttable_iter **********************************************************/
+
+/*   upb_inttable_iter i;
+ *   upb_inttable_begin(&i, t);
+ *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ *     uintptr_t key = upb_inttable_iter_key(&i);
+ *     upb_value val = upb_inttable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_inttable *t;
+  size_t index;
+  bool array_part;
+} upb_inttable_iter;
+
+UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) {
+  return &i->t->t.entries[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
+void upb_inttable_next(upb_inttable_iter *i);
+bool upb_inttable_done(const upb_inttable_iter *i);
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
+void upb_inttable_iter_setdone(upb_inttable_iter *i);
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                               const upb_inttable_iter *i2);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* UPB_TABLE_H_ */
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** upb_msglayout *************************************************************/
+
+/* upb_msglayout represents the memory layout of a given upb_msgdef.  The
+ * members are public so generated code can initialize them, but users MUST NOT
+ * read or write any of its members. */
+
+/* These aren't real labels according to descriptor.proto, but in the table we
+ * use these for map/packed fields instead of UPB_LABEL_REPEATED. */
+enum {
+  _UPB_LABEL_MAP = 4,
+  _UPB_LABEL_PACKED = 7  /* Low 3 bits are common with UPB_LABEL_REPEATED. */
+};
+
+typedef struct {
+  uint32_t number;
+  uint16_t offset;
+  int16_t presence;       /* If >0, hasbit_index.  If <0, ~oneof_index. */
+  uint16_t submsg_index;  /* undefined if descriptortype != MESSAGE or GROUP. */
+  uint8_t descriptortype;
+  uint8_t label;          /* google.protobuf.Label or _UPB_LABEL_* above. */
+} upb_msglayout_field;
+
+struct upb_decstate;
+struct upb_msglayout;
+
+typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr,
+                                      upb_msg *msg, intptr_t table,
+                                      uint64_t hasbits, uint64_t data);
+
+typedef struct {
+  uint64_t field_data;
+  _upb_field_parser *field_parser;
+} _upb_fasttable_entry;
+
+struct upb_msglayout {
+  const struct upb_msglayout *const* submsgs;
+  const upb_msglayout_field *fields;
+  /* Must be aligned to sizeof(void*).  Doesn't include internal members like
+   * unknown fields, extension dict, pointer to msglayout, etc. */
+  uint16_t size;
+  uint16_t field_count;
+  bool extendable;
+  uint8_t table_mask;
+  /* To constant-initialize the tables of variable length, we need a flexible
+   * array member, and we need to compile in C99 mode. */
+  _upb_fasttable_entry fasttable[];
+};
+
+/** upb_msg *******************************************************************/
+
+/* Internal members of a upb_msg.  We can change this without breaking binary
+ * compatibility.  We put these before the user's data.  The user's upb_msg*
+ * points after the upb_msg_internal. */
+
+typedef struct {
+  uint32_t len;
+  uint32_t size;
+  /* Data follows. */
+} upb_msg_unknowndata;
+
+/* Used when a message is not extendable. */
+typedef struct {
+  upb_msg_unknowndata *unknown;
+} upb_msg_internal;
+
+/* Maps upb_fieldtype_t -> memory size. */
+extern char _upb_fieldtype_to_size[12];
+
+UPB_INLINE size_t upb_msg_sizeof(const upb_msglayout *l) {
+  return l->size + sizeof(upb_msg_internal);
+}
+
+UPB_INLINE upb_msg *_upb_msg_new_inl(const upb_msglayout *l, upb_arena *a) {
+  size_t size = upb_msg_sizeof(l);
+  void *mem = upb_arena_malloc(a, size);
+  upb_msg *msg;
+  if (UPB_UNLIKELY(!mem)) return NULL;
+  msg = UPB_PTR_AT(mem, sizeof(upb_msg_internal), upb_msg);
+  memset(mem, 0, size);
+  return msg;
+}
+
+/* Creates a new messages with the given layout on the given arena. */
+upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a);
+
+UPB_INLINE upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
+  ptrdiff_t size = sizeof(upb_msg_internal);
+  return (upb_msg_internal*)((char*)msg - size);
+}
+
+/* Clears the given message. */
+void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l);
+
+/* Discards the unknown fields for this message only. */
+void _upb_msg_discardunknown_shallow(upb_msg *msg);
+
+/* Adds unknown data (serialized protobuf data) to the given message.  The data
+ * is copied into the message instance. */
+bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                         upb_arena *arena);
+
+/** Hasbit access *************************************************************/
+
+UPB_INLINE bool _upb_hasbit(const upb_msg *msg, size_t idx) {
+  return (*UPB_PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
+}
+
+UPB_INLINE void _upb_sethas(const upb_msg *msg, size_t idx) {
+  (*UPB_PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
+}
+
+UPB_INLINE void _upb_clearhas(const upb_msg *msg, size_t idx) {
+  (*UPB_PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
+}
+
+UPB_INLINE size_t _upb_msg_hasidx(const upb_msglayout_field *f) {
+  UPB_ASSERT(f->presence > 0);
+  return f->presence;
+}
+
+UPB_INLINE bool _upb_hasbit_field(const upb_msg *msg,
+                                  const upb_msglayout_field *f) {
+  return _upb_hasbit(msg, _upb_msg_hasidx(f));
+}
+
+UPB_INLINE void _upb_sethas_field(const upb_msg *msg,
+                                  const upb_msglayout_field *f) {
+  _upb_sethas(msg, _upb_msg_hasidx(f));
+}
+
+UPB_INLINE void _upb_clearhas_field(const upb_msg *msg,
+                                    const upb_msglayout_field *f) {
+  _upb_clearhas(msg, _upb_msg_hasidx(f));
+}
+
+/** Oneof case access *********************************************************/
+
+UPB_INLINE uint32_t *_upb_oneofcase(upb_msg *msg, size_t case_ofs) {
+  return UPB_PTR_AT(msg, case_ofs, uint32_t);
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase(const void *msg, size_t case_ofs) {
+  return *UPB_PTR_AT(msg, case_ofs, uint32_t);
+}
+
+UPB_INLINE size_t _upb_oneofcase_ofs(const upb_msglayout_field *f) {
+  UPB_ASSERT(f->presence < 0);
+  return ~(ptrdiff_t)f->presence;
+}
+
+UPB_INLINE uint32_t *_upb_oneofcase_field(upb_msg *msg,
+                                          const upb_msglayout_field *f) {
+  return _upb_oneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_msg *msg,
+                                            const upb_msglayout_field *f) {
+  return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_msg *msg, size_t ofs) {
+  return *UPB_PTR_AT(msg, ofs, const upb_msg*) != NULL;
+}
+
+UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) {
+  return (field->label & 3) == UPB_LABEL_REPEATED;
+}
+
+UPB_INLINE bool _upb_repeated_or_map(const upb_msglayout_field *field) {
+  return field->label >= UPB_LABEL_REPEATED;
+}
+
+/** upb_array *****************************************************************/
+
+/* Our internal representation for repeated fields.  */
+typedef struct {
+  uintptr_t data;   /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
+  size_t len;   /* Measured in elements. */
+  size_t size;  /* Measured in elements. */
+  uint64_t junk;
+} upb_array;
+
+UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) {
+  UPB_ASSERT((arr->data & 7) <= 4);
+  return (void*)(arr->data & ~(uintptr_t)7);
+}
+
+UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) {
+  UPB_ASSERT(elem_size_lg2 <= 4);
+  return (uintptr_t)ptr | elem_size_lg2;
+}
+
+UPB_INLINE void *_upb_array_ptr(upb_array *arr) {
+  return (void*)_upb_array_constptr(arr);
+}
+
+UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) {
+  UPB_ASSERT(elem_size_lg2 <= 4);
+  UPB_ASSERT(((uintptr_t)ptr & 7) == 0);
+  return (uintptr_t)ptr | (unsigned)elem_size_lg2;
+}
+
+UPB_INLINE upb_array *_upb_array_new(upb_arena *a, size_t init_size,
+                                     int elem_size_lg2) {
+  const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_array), 8);
+  const size_t bytes = sizeof(upb_array) + (init_size << elem_size_lg2);
+  upb_array *arr = (upb_array*)upb_arena_malloc(a, bytes);
+  if (!arr) return NULL;
+  arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2);
+  arr->len = 0;
+  arr->size = init_size;
+  return arr;
+}
+
+/* Resizes the capacity of the array to be at least min_size. */
+bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena);
+
+/* Fallback functions for when the accessors require a resize. */
+void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
+                                 int elem_size_lg2, upb_arena *arena);
+bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
+                                int elem_size_lg2, upb_arena *arena);
+
+UPB_INLINE bool _upb_array_reserve(upb_array *arr, size_t size,
+                                   upb_arena *arena) {
+  if (arr->size < size) return _upb_array_realloc(arr, size, arena);
+  return true;
+}
+
+UPB_INLINE bool _upb_array_resize(upb_array *arr, size_t size,
+                                  upb_arena *arena) {
+  if (!_upb_array_reserve(arr, size, arena)) return false;
+  arr->len = size;
+  return true;
+}
+
+UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
+                                           size_t *size) {
+  const upb_array *arr = *UPB_PTR_AT(msg, ofs, const upb_array*);
+  if (arr) {
+    if (size) *size = arr->len;
+    return _upb_array_constptr(arr);
+  } else {
+    if (size) *size = 0;
+    return NULL;
+  }
+}
+
+UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
+                                             size_t *size) {
+  upb_array *arr = *UPB_PTR_AT(msg, ofs, upb_array*);
+  if (arr) {
+    if (size) *size = arr->len;
+    return _upb_array_ptr(arr);
+  } else {
+    if (size) *size = 0;
+    return NULL;
+  }
+}
+
+UPB_INLINE void *_upb_array_resize_accessor2(void *msg, size_t ofs, size_t size,
+                                             int elem_size_lg2,
+                                             upb_arena *arena) {
+  upb_array **arr_ptr = UPB_PTR_AT(msg, ofs, upb_array *);
+  upb_array *arr = *arr_ptr;
+  if (!arr || arr->size < size) {
+    return _upb_array_resize_fallback(arr_ptr, size, elem_size_lg2, arena);
+  }
+  arr->len = size;
+  return _upb_array_ptr(arr);
+}
+
+UPB_INLINE bool _upb_array_append_accessor2(void *msg, size_t ofs,
+                                            int elem_size_lg2,
+                                            const void *value,
+                                            upb_arena *arena) {
+  upb_array **arr_ptr = UPB_PTR_AT(msg, ofs, upb_array *);
+  size_t elem_size = 1 << elem_size_lg2;
+  upb_array *arr = *arr_ptr;
+  void *ptr;
+  if (!arr || arr->len == arr->size) {
+    return _upb_array_append_fallback(arr_ptr, value, elem_size_lg2, arena);
+  }
+  ptr = _upb_array_ptr(arr);
+  memcpy(UPB_PTR_AT(ptr, arr->len * elem_size, char), value, elem_size);
+  arr->len++;
+  return true;
+}
+
+/* Used by old generated code, remove once all code has been regenerated. */
+UPB_INLINE int _upb_sizelg2(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_BOOL:
+      return 0;
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return 2;
+    case UPB_TYPE_MESSAGE:
+      return UPB_SIZE(2, 3);
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return 3;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return UPB_SIZE(3, 4);
+  }
+  UPB_UNREACHABLE();
+}
+UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
+                                             upb_fieldtype_t type,
+                                             upb_arena *arena) {
+  return _upb_array_resize_accessor2(msg, ofs, size, _upb_sizelg2(type), arena);
+}
+UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
+                                            size_t elem_size, upb_fieldtype_t type,
+                                            const void *value,
+                                            upb_arena *arena) {
+  (void)elem_size;
+  return _upb_array_append_accessor2(msg, ofs, _upb_sizelg2(type), value,
+                                     arena);
+}
+
+/** upb_map *******************************************************************/
+
+/* Right now we use strmaps for everything.  We'll likely want to use
+ * integer-specific maps for integer-keyed maps.*/
+typedef struct {
+  /* Size of key and val, based on the map type.  Strings are represented as '0'
+   * because they must be handled specially. */
+  char key_size;
+  char val_size;
+
+  upb_strtable table;
+} upb_map;
+
+/* Map entries aren't actually stored, they are only used during parsing.  For
+ * parsing, it helps a lot if all map entry messages have the same layout.
+ * The compiler and def.c must ensure that all map entries have this layout. */
+typedef struct {
+  upb_msg_internal internal;
+  union {
+    upb_strview str;  /* For str/bytes. */
+    upb_value val;    /* For all other types. */
+  } k;
+  union {
+    upb_strview str;  /* For str/bytes. */
+    upb_value val;    /* For all other types. */
+  } v;
+} upb_map_entry;
+
+/* Creates a new map on the given arena with this key/value type. */
+upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size);
+
+/* Converting between internal table representation and user values.
+ *
+ * _upb_map_tokey() and _upb_map_fromkey() are inverses.
+ * _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
+ *
+ * These functions account for the fact that strings are treated differently
+ * from other types when stored in a map.
+ */
+
+UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    return *(upb_strview*)key;
+  } else {
+    return upb_strview_make((const char*)key, size);
+  }
+}
+
+UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    memcpy(out, &key, sizeof(key));
+  } else {
+    memcpy(out, key.data, size);
+  }
+}
+
+UPB_INLINE bool _upb_map_tovalue(const void *val, size_t size, upb_value *msgval,
+                                 upb_arena *a) {
+  if (size == UPB_MAPTYPE_STRING) {
+    upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp));
+    if (!strp) return false;
+    *strp = *(upb_strview*)val;
+    *msgval = upb_value_ptr(strp);
+  } else {
+    memcpy(msgval, val, size);
+  }
+  return true;
+}
+
+UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    const upb_strview *strp = (const upb_strview*)upb_value_getptr(val);
+    memcpy(out, strp, sizeof(upb_strview));
+  } else {
+    memcpy(out, &val, size);
+  }
+}
+
+/* Map operations, shared by reflection and generated code. */
+
+UPB_INLINE size_t _upb_map_size(const upb_map *map) {
+  return map->table.t.count;
+}
+
+UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key,
+                             size_t key_size, void *val, size_t val_size) {
+  upb_value tabval;
+  upb_strview k = _upb_map_tokey(key, key_size);
+  bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
+  if (ret && val) {
+    _upb_map_fromvalue(tabval, val, val_size);
+  }
+  return ret;
+}
+
+UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) {
+  upb_strtable_iter it;
+  it.t = &map->table;
+  it.index = *iter;
+  upb_strtable_next(&it);
+  *iter = it.index;
+  if (upb_strtable_done(&it)) return NULL;
+  return (void*)str_tabent(&it);
+}
+
+UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size,
+                             void *val, size_t val_size, upb_arena *a) {
+  upb_strview strkey = _upb_map_tokey(key, key_size);
+  upb_value tabval = {0};
+  if (!_upb_map_tovalue(val, val_size, &tabval, a)) return false;
+
+  /* TODO(haberman): add overwrite operation to minimize number of lookups. */
+  upb_strtable_remove(&map->table, strkey.data, strkey.size, NULL);
+  return upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a);
+}
+
+UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) {
+  upb_strview k = _upb_map_tokey(key, key_size);
+  return upb_strtable_remove(&map->table, k.data, k.size, NULL);
+}
+
+UPB_INLINE void _upb_map_clear(upb_map *map) {
+  upb_strtable_clear(&map->table);
+}
+
+/* Message map operations, these get the map from the message first. */
+
+UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  return map ? _upb_map_size(map) : 0;
+}
+
+UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs,
+                                 const void *key, size_t key_size, void *val,
+                                 size_t val_size) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return false;
+  return _upb_map_get(map, key, key_size, val, val_size);
+}
+
+UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs,
+                                   size_t *iter) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return NULL;
+  return _upb_map_next(map, iter);
+}
+
+UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key,
+                                 size_t key_size, void *val, size_t val_size,
+                                 upb_arena *arena) {
+  upb_map **map = UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!*map) {
+    *map = _upb_map_new(arena, key_size, val_size);
+  }
+  return _upb_map_set(*map, key, key_size, val, val_size, arena);
+}
+
+UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key,
+                                    size_t key_size) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return false;
+  return _upb_map_delete(map, key, key_size);
+}
+
+UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return;
+  _upb_map_clear(map);
+}
+
+/* Accessing map key/value from a pointer, used by generated code only. */
+
+UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) {
+  const upb_tabent *ent = (const upb_tabent*)msg;
+  uint32_t u32len;
+  upb_strview k;
+  k.data = upb_tabstr(ent->key, &u32len);
+  k.size = u32len;
+  _upb_map_fromkey(k, key, size);
+}
+
+UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) {
+  const upb_tabent *ent = (const upb_tabent*)msg;
+  upb_value v = {ent->val.val};
+  _upb_map_fromvalue(v, val, size);
+}
+
+UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) {
+  upb_tabent *ent = (upb_tabent*)msg;
+  /* This is like _upb_map_tovalue() except the entry already exists so we can
+   * reuse the allocated upb_strview for string fields. */
+  if (size == UPB_MAPTYPE_STRING) {
+    upb_strview *strp = (upb_strview*)(uintptr_t)ent->val.val;
+    memcpy(strp, val, sizeof(*strp));
+  } else {
+    memcpy(&ent->val.val, val, size);
+  }
+}
+
+/** _upb_mapsorter *************************************************************/
+
+/* _upb_mapsorter sorts maps and provides ordered iteration over the entries.
+ * Since maps can be recursive (map values can be messages which contain other maps).
+ * _upb_mapsorter can contain a stack of maps. */
+
+typedef struct {
+  upb_tabent const**entries;
+  int size;
+  int cap;
+} _upb_mapsorter;
+
+typedef struct {
+  int start;
+  int pos;
+  int end;
+} _upb_sortedmap;
+
+UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter *s) {
+  s->entries = NULL;
+  s->size = 0;
+  s->cap = 0;
+}
+
+UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter *s) {
+  if (s->entries) free(s->entries);
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+                            const upb_map *map, _upb_sortedmap *sorted);
+
+UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter *s, _upb_sortedmap *sorted) {
+  s->size = sorted->start;
+}
+
+UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter *s, const upb_map *map,
+                                    _upb_sortedmap *sorted,
+                                    upb_map_entry *ent) {
+  if (sorted->pos == sorted->end) return false;
+  const upb_tabent *tabent = s->entries[sorted->pos++];
+  upb_strview key = upb_tabstrview(tabent->key);
+  _upb_map_fromkey(key, &ent->k, map->key_size);
+  upb_value val = {tabent->val.val};
+  _upb_map_fromvalue(val, &ent->v, map->val_size);
+  return true;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif /* UPB_MSG_INT_H_ */
+
+/** upb/upb_internal.h ************************************************************/
+#ifndef UPB_INT_H_
+#define UPB_INT_H_
+
+
+struct mem_block;
+typedef struct mem_block mem_block;
+
+struct upb_arena {
+  _upb_arena_head head;
+  /* Stores cleanup metadata for this arena.
+   * - a pointer to the current cleanup counter.
+   * - a boolean indicating if there is an unowned initial block.  */
+  uintptr_t cleanup_metadata;
+
+  /* Allocator to allocate arena blocks.  We are responsible for freeing these
+   * when we are destroyed. */
+  upb_alloc *block_alloc;
+  uint32_t last_size;
+
+  /* When multiple arenas are fused together, each arena points to a parent
+   * arena (root points to itself). The root tracks how many live arenas
+   * reference it. */
+  uint32_t refcount;  /* Only used when a->parent == a */
+  struct upb_arena *parent;
+
+  /* Linked list of blocks to free/cleanup. */
+  mem_block *freelist, *freelist_tail;
+};
+
+#endif  /* UPB_INT_H_ */
+
+/* Must be last. */
+
+#define DECODE_NOGROUP (uint32_t)-1
+
+typedef struct upb_decstate {
+  const char *end;         /* Can read up to 16 bytes slop beyond this. */
+  const char *limit_ptr;   /* = end + UPB_MIN(limit, 0) */
+  upb_msg *unknown_msg;    /* If non-NULL, add unknown data at buffer flip. */
+  const char *unknown;     /* Start of unknown data. */
+  int limit;               /* Submessage limit relative to end. */
+  int depth;
+  uint32_t end_group;   /* field number of END_GROUP tag, else DECODE_NOGROUP */
+  bool alias;
+  char patch[32];
+  upb_arena arena;
+  jmp_buf err;
+} upb_decstate;
+
+/* Error function that will abort decoding with longjmp(). We can't declare this
+ * UPB_NORETURN, even though it is appropriate, because if we do then compilers
+ * will "helpfully" refuse to tailcall to it
+ * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal
+ * of our optimizations. That is also why we must declare it in a separate file,
+ * otherwise the compiler will see that it calls longjmp() and deduce that it is
+ * noreturn. */
+const char *fastdecode_err(upb_decstate *d);
+
+extern const uint8_t upb_utf8_offsets[];
+
+UPB_INLINE
+bool decode_verifyutf8_inl(const char *buf, int len) {
+  int i, j;
+  uint8_t offset;
+
+  i = 0;
+  while (i < len) {
+    offset = upb_utf8_offsets[(uint8_t)buf[i]];
+    if (offset == 0 || i + offset > len) {
+      return false;
+    }
+    for (j = i + 1; j < i + offset; j++) {
+      if ((buf[j] & 0xc0) != 0x80) {
+        return false;
+      }
+    }
+    i += offset;
+  }
+  return i == len;
+}
+
+/* x86-64 pointers always have the high 16 bits matching. So we can shift
+ * left 8 and right 8 without loss of information. */
+UPB_INLINE intptr_t decode_totable(const upb_msglayout *tablep) {
+  return ((intptr_t)tablep << 8) | tablep->table_mask;
+}
+
+UPB_INLINE const upb_msglayout *decode_totablep(intptr_t table) {
+  return (const upb_msglayout*)(table >> 8);
+}
+
+UPB_INLINE
+const char *decode_isdonefallback_inl(upb_decstate *d, const char *ptr,
+                                      int overrun) {
+  if (overrun < d->limit) {
+    /* Need to copy remaining data into patch buffer. */
+    UPB_ASSERT(overrun < 16);
+    if (d->unknown_msg) {
+      if (!_upb_msg_addunknown(d->unknown_msg, d->unknown, ptr - d->unknown,
+                               &d->arena)) {
+        return NULL;
+      }
+      d->unknown = &d->patch[0] + overrun;
+    }
+    memset(d->patch + 16, 0, 16);
+    memcpy(d->patch, d->end, 16);
+    ptr = &d->patch[0] + overrun;
+    d->end = &d->patch[16];
+    d->limit -= 16;
+    d->limit_ptr = d->end + d->limit;
+    d->alias = false;
+    UPB_ASSERT(ptr < d->limit_ptr);
+    return ptr;
+  } else {
+    return NULL;
+  }
+}
+
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+                                  int overrun);
+
+UPB_INLINE
+bool decode_isdone(upb_decstate *d, const char **ptr) {
+  int overrun = *ptr - d->end;
+  if (UPB_LIKELY(*ptr < d->limit_ptr)) {
+    return false;
+  } else if (UPB_LIKELY(overrun == d->limit)) {
+    return true;
+  } else {
+    *ptr = decode_isdonefallback(d, *ptr, overrun);
+    return false;
+  }
+}
+
+#if UPB_FASTTABLE
+UPB_INLINE
+const char *fastdecode_tagdispatch(upb_decstate *d, const char *ptr,
+                                    upb_msg *msg, intptr_t table,
+                                    uint64_t hasbits, uint64_t tag) {
+  const upb_msglayout *table_p = decode_totablep(table);
+  uint8_t mask = table;
+  uint64_t data;
+  size_t idx = tag & mask;
+  UPB_ASSUME((idx & 7) == 0);
+  idx >>= 3;
+  data = table_p->fasttable[idx].field_data ^ tag;
+  UPB_MUSTTAIL return table_p->fasttable[idx].field_parser(d, ptr, msg, table,
+                                                           hasbits, data);
+}
+#endif
+
+UPB_INLINE uint32_t fastdecode_loadtag(const char* ptr) {
+  uint16_t tag;
+  memcpy(&tag, ptr, 2);
+  return tag;
+}
+
+UPB_INLINE void decode_checklimit(upb_decstate *d) {
+  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+}
+
+UPB_INLINE int decode_pushlimit(upb_decstate *d, const char *ptr, int size) {
+  int limit = size + (int)(ptr - d->end);
+  int delta = d->limit - limit;
+  decode_checklimit(d);
+  d->limit = limit;
+  d->limit_ptr = d->end + UPB_MIN(0, limit);
+  decode_checklimit(d);
+  return delta;
+}
+
+UPB_INLINE void decode_poplimit(upb_decstate *d, const char *ptr,
+                                int saved_delta) {
+  UPB_ASSERT(ptr - d->end == d->limit);
+  decode_checklimit(d);
+  d->limit += saved_delta;
+  d->limit_ptr = d->end + UPB_MIN(0, d->limit);
+  decode_checklimit(d);
+}
+
+
+#endif  /* UPB_DECODE_INT_H_ */
+
+/** upb/encode.h ************************************************************/
+/*
+ * upb_encode: parsing into a upb_msg using a upb_msglayout.
+ */
+
+#ifndef UPB_ENCODE_H_
+#define UPB_ENCODE_H_
+
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* If set, the results of serializing will be deterministic across all
+   * instances of this binary. There are no guarantees across different
+   * binary builds.
+   *
+   * If your proto contains maps, the encoder will need to malloc()/free()
+   * memory during encode. */
+  UPB_ENCODE_DETERMINISTIC = 1,
+
+  /* When set, unknown fields are not printed. */
+  UPB_ENCODE_SKIPUNKNOWN = 2,
+};
+
+#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+
+char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
+                    upb_arena *arena, size_t *size);
+
+UPB_INLINE char *upb_encode(const void *msg, const upb_msglayout *l,
+                            upb_arena *arena, size_t *size) {
+  return upb_encode_ex(msg, l, 0, arena, size);
+}
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_ENCODE_H_ */
+
+/** upb/decode_fast.h ************************************************************/
+// These are the specialized field parser functions for the fast parser.
+// Generated tables will refer to these by name.
+//
+// The function names are encoded with names like:
+//
+//   //  123 4
+//   upb_pss_1bt();   // Parse singular string, 1 byte tag.
+//
+// In position 1:
+//   - 'p' for parse, most function use this
+//   - 'c' for copy, for when we are copying strings instead of aliasing
+//
+// In position 2 (cardinality):
+//   - 's' for singular, with or without hasbit
+//   - 'o' for oneof
+//   - 'r' for non-packed repeated
+//   - 'p' for packed repeated
+//
+// In position 3 (type):
+//   - 'b1' for bool
+//   - 'v4' for 4-byte varint
+//   - 'v8' for 8-byte varint
+//   - 'z4' for zig-zag-encoded 4-byte varint
+//   - 'z8' for zig-zag-encoded 8-byte varint
+//   - 'f4' for 4-byte fixed
+//   - 'f8' for 8-byte fixed
+//   - 'm' for sub-message
+//   - 's' for string (validate UTF-8)
+//   - 'b' for bytes
+//
+// In position 4 (tag length):
+//   - '1' for one-byte tags (field numbers 1-15)
+//   - '2' for two-byte tags (field numbers 16-2048)
+
+#ifndef UPB_DECODE_FAST_H_
+#define UPB_DECODE_FAST_H_
+
+
+struct upb_decstate;
+
+// The fallback, generic parsing function that can handle any field type.
+// This just uses the regular (non-fast) parser to parse a single field.
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+                               upb_msg *msg, intptr_t table, uint64_t hasbits,
+                               uint64_t data);
+
+#define UPB_PARSE_PARAMS                                                 \
+  struct upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+      uint64_t hasbits, uint64_t data
+
+/* primitive fields ***********************************************************/
+
+#define F(card, type, valbytes, tagbytes) \
+  const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define TYPES(card, tagbytes) \
+  F(card, b, 1, tagbytes)     \
+  F(card, v, 4, tagbytes)     \
+  F(card, v, 8, tagbytes)     \
+  F(card, z, 4, tagbytes)     \
+  F(card, z, 8, tagbytes)     \
+  F(card, f, 4, tagbytes)     \
+  F(card, f, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+/* string fields **************************************************************/
+
+#define F(card, tagbytes, type)                                     \
+  const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \
+  const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define UTF8(card, tagbytes) \
+  F(card, tagbytes, s)       \
+  F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+  UTF8(card, 1)        \
+  UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef F
+#undef TAGBYTES
+
+/* sub-message fields *********************************************************/
+
+#define F(card, tagbytes, size_ceil, ceil_arg) \
+  const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS);
+
+#define SIZES(card, tagbytes) \
+  F(card, tagbytes, 64, 64) \
+  F(card, tagbytes, 128, 128) \
+  F(card, tagbytes, 192, 192) \
+  F(card, tagbytes, 256, 256) \
+  F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+  SIZES(card, 1) \
+  SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+
+#undef UPB_PARSE_PARAMS
+
+#endif  /* UPB_DECODE_FAST_H_ */
+
+/** google/protobuf/descriptor.upb.h ************************************************************//* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
+#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct google_protobuf_FileDescriptorSet;
+struct google_protobuf_FileDescriptorProto;
+struct google_protobuf_DescriptorProto;
+struct google_protobuf_DescriptorProto_ExtensionRange;
+struct google_protobuf_DescriptorProto_ReservedRange;
+struct google_protobuf_ExtensionRangeOptions;
+struct google_protobuf_FieldDescriptorProto;
+struct google_protobuf_OneofDescriptorProto;
+struct google_protobuf_EnumDescriptorProto;
+struct google_protobuf_EnumDescriptorProto_EnumReservedRange;
+struct google_protobuf_EnumValueDescriptorProto;
+struct google_protobuf_ServiceDescriptorProto;
+struct google_protobuf_MethodDescriptorProto;
+struct google_protobuf_FileOptions;
+struct google_protobuf_MessageOptions;
+struct google_protobuf_FieldOptions;
+struct google_protobuf_OneofOptions;
+struct google_protobuf_EnumOptions;
+struct google_protobuf_EnumValueOptions;
+struct google_protobuf_ServiceOptions;
+struct google_protobuf_MethodOptions;
+struct google_protobuf_UninterpretedOption;
+struct google_protobuf_UninterpretedOption_NamePart;
+struct google_protobuf_SourceCodeInfo;
+struct google_protobuf_SourceCodeInfo_Location;
+struct google_protobuf_GeneratedCodeInfo;
+struct google_protobuf_GeneratedCodeInfo_Annotation;
+typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet;
+typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto;
+typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto;
+typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange;
+typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange;
+typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions;
+typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto;
+typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto;
+typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto;
+typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange;
+typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto;
+typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto;
+typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto;
+typedef struct google_protobuf_FileOptions google_protobuf_FileOptions;
+typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions;
+typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions;
+typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions;
+typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions;
+typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions;
+typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions;
+typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions;
+typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption;
+typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart;
+typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo;
+typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location;
+typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo;
+typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation;
+extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
+extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
+extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
+extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_FileOptions_msginit;
+extern const upb_msglayout google_protobuf_MessageOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldOptions_msginit;
+extern const upb_msglayout google_protobuf_OneofOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
+extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
+extern const upb_msglayout google_protobuf_MethodOptions_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
+  google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
+  google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
+} google_protobuf_FieldDescriptorProto_Label;
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
+  google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
+  google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
+  google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
+  google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
+  google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
+  google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
+  google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
+  google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
+  google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
+} google_protobuf_FieldDescriptorProto_Type;
+
+typedef enum {
+  google_protobuf_FieldOptions_STRING = 0,
+  google_protobuf_FieldOptions_CORD = 1,
+  google_protobuf_FieldOptions_STRING_PIECE = 2
+} google_protobuf_FieldOptions_CType;
+
+typedef enum {
+  google_protobuf_FieldOptions_JS_NORMAL = 0,
+  google_protobuf_FieldOptions_JS_STRING = 1,
+  google_protobuf_FieldOptions_JS_NUMBER = 2
+} google_protobuf_FieldOptions_JSType;
+
+typedef enum {
+  google_protobuf_FileOptions_SPEED = 1,
+  google_protobuf_FileOptions_CODE_SIZE = 2,
+  google_protobuf_FileOptions_LITE_RUNTIME = 3
+} google_protobuf_FileOptions_OptimizeMode;
+
+typedef enum {
+  google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
+  google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
+  google_protobuf_MethodOptions_IDEMPOTENT = 2
+} google_protobuf_MethodOptions_IdempotencyLevel;
+
+
+/* google.protobuf.FileDescriptorSet */
+
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) {
+  return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) {
+  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) {
+  struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FileDescriptorProto */
+
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
+UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); }
+UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); }
+UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); }
+UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
+
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+}
+UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(36, 72), UPB_SIZE(3, 4), &val,
+      arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(44, 88), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 96), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(48, 96), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(52, 104), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(52, 104), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FileDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value;
+}
+UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 112), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(56, 112), 2, &val,
+      arena);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(60, 120), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(60, 120), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
+}
+
+/* google.protobuf.DescriptorProto */
+
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); }
+UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); }
+UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
+UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
+UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(32, 64), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(32, 64), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_DescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(36, 72), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+}
+UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.DescriptorProto.ExtensionRange */
+
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) {
+  struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.DescriptorProto.ReservedRange */
+
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+/* google.protobuf.ExtensionRangeOptions */
+
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) {
+  return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FieldDescriptorProto */
+
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); }
+UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(64, 104), const google_protobuf_FieldOptions*); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 11); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); }
+
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 7);
+  *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
+  _upb_sethas(msg, 8);
+  *UPB_PTR_AT(msg, UPB_SIZE(64, 104), google_protobuf_FieldOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 9);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 10);
+  *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 11);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value;
+}
+
+/* google.protobuf.OneofDescriptorProto */
+
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); }
+
+UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.EnumDescriptorProto */
+
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+
+UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.EnumDescriptorProto.EnumReservedRange */
+
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+/* google.protobuf.EnumValueDescriptorProto */
+
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); }
+
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.ServiceDescriptorProto */
+
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); }
+
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.MethodDescriptorProto */
+
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+
+/* google.protobuf.FileOptions */
+
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) {
+  return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 8); }
+UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 9); }
+UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 11); }
+UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 12); }
+UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 18); }
+UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 19); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 20); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(100, 184)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(100, 184), len); }
+
+UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 7);
+  *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 8);
+  *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 9);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 10);
+  *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 11);
+  *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 12);
+  *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 13);
+  *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 14);
+  *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 15);
+  *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 16);
+  *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 17);
+  *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 18);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 19);
+  *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 20);
+  *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(100, 184), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(100, 184), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(100, 184), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.MessageOptions */
+
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) {
+  return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); }
+
+UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(8, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FieldOptions */
+
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) {
+  return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 16)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(16, 16), len); }
+
+UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 16), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 16), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 16), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.OneofOptions */
+
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) {
+  return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.EnumOptions */
+
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) {
+  return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.EnumValueOptions */
+
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) {
+  return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.ServiceOptions */
+
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) {
+  return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.MethodOptions */
+
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) {
+  return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); }
+UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 16)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(12, 16), len); }
+
+UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value;
+}
+UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 16), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 16), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(12, 16), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.UninterpretedOption */
+
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+}
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); }
+UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); }
+
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(56, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value;
+}
+
+/* google.protobuf.UninterpretedOption.NamePart */
+
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+
+/* google.protobuf.SourceCodeInfo */
+
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) {
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) {
+  struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.SourceCodeInfo.Location */
+
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
+}
+
+UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
+
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(20, 40), 2, &val,
+      arena);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
+}
+UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.GeneratedCodeInfo */
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) {
+  struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.GeneratedCodeInfo.Annotation */
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
+}
+
+UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len);
+}
+UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 32), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(20, 32), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
+
+/** upb/def.h ************************************************************/
+/*
+ * Defs are upb's internal representation of the constructs that can appear
+ * in a .proto file:
+ *
+ * - upb_msgdef: describes a "message" construct.
+ * - upb_fielddef: describes a message field.
+ * - upb_filedef: describes a .proto file and its defs.
+ * - upb_enumdef: describes an enum.
+ * - upb_oneofdef: describes a oneof.
+ *
+ * TODO: definitions of services.
+ */
+
+#ifndef UPB_DEF_H_
+#define UPB_DEF_H_
+
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* __cplusplus */
+
+struct upb_enumdef;
+typedef struct upb_enumdef upb_enumdef;
+struct upb_fielddef;
+typedef struct upb_fielddef upb_fielddef;
+struct upb_filedef;
+typedef struct upb_filedef upb_filedef;
+struct upb_msgdef;
+typedef struct upb_msgdef upb_msgdef;
+struct upb_oneofdef;
+typedef struct upb_oneofdef upb_oneofdef;
+struct upb_symtab;
+typedef struct upb_symtab upb_symtab;
+
+typedef enum {
+  UPB_SYNTAX_PROTO2 = 2,
+  UPB_SYNTAX_PROTO3 = 3
+} upb_syntax_t;
+
+/* All the different kind of well known type messages. For simplicity of check,
+ * number wrappers and string wrappers are grouped together. Make sure the
+ * order and merber of these groups are not changed.
+ */
+typedef enum {
+  UPB_WELLKNOWN_UNSPECIFIED,
+  UPB_WELLKNOWN_ANY,
+  UPB_WELLKNOWN_FIELDMASK,
+  UPB_WELLKNOWN_DURATION,
+  UPB_WELLKNOWN_TIMESTAMP,
+  /* number wrappers */
+  UPB_WELLKNOWN_DOUBLEVALUE,
+  UPB_WELLKNOWN_FLOATVALUE,
+  UPB_WELLKNOWN_INT64VALUE,
+  UPB_WELLKNOWN_UINT64VALUE,
+  UPB_WELLKNOWN_INT32VALUE,
+  UPB_WELLKNOWN_UINT32VALUE,
+  /* string wrappers */
+  UPB_WELLKNOWN_STRINGVALUE,
+  UPB_WELLKNOWN_BYTESVALUE,
+  UPB_WELLKNOWN_BOOLVALUE,
+  UPB_WELLKNOWN_VALUE,
+  UPB_WELLKNOWN_LISTVALUE,
+  UPB_WELLKNOWN_STRUCT
+} upb_wellknowntype_t;
+
+/* upb_fielddef ***************************************************************/
+
+/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
+ * protobuf wire format. */
+#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
+
+const char *upb_fielddef_fullname(const upb_fielddef *f);
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
+upb_label_t upb_fielddef_label(const upb_fielddef *f);
+uint32_t upb_fielddef_number(const upb_fielddef *f);
+const char *upb_fielddef_name(const upb_fielddef *f);
+const char *upb_fielddef_jsonname(const upb_fielddef *f);
+bool upb_fielddef_isextension(const upb_fielddef *f);
+bool upb_fielddef_lazy(const upb_fielddef *f);
+bool upb_fielddef_packed(const upb_fielddef *f);
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f);
+uint32_t upb_fielddef_index(const upb_fielddef *f);
+bool upb_fielddef_issubmsg(const upb_fielddef *f);
+bool upb_fielddef_isstring(const upb_fielddef *f);
+bool upb_fielddef_isseq(const upb_fielddef *f);
+bool upb_fielddef_isprimitive(const upb_fielddef *f);
+bool upb_fielddef_ismap(const upb_fielddef *f);
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
+bool upb_fielddef_defaultbool(const upb_fielddef *f);
+float upb_fielddef_defaultfloat(const upb_fielddef *f);
+double upb_fielddef_defaultdouble(const upb_fielddef *f);
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
+bool upb_fielddef_hassubdef(const upb_fielddef *f);
+bool upb_fielddef_haspresence(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f);
+
+/* upb_oneofdef ***************************************************************/
+
+typedef upb_inttable_iter upb_oneof_iter;
+
+const char *upb_oneofdef_name(const upb_oneofdef *o);
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
+uint32_t upb_oneofdef_index(const upb_oneofdef *o);
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o);
+int upb_oneofdef_fieldcount(const upb_oneofdef *o);
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i);
+
+/* Oneof lookups:
+ * - ntof:  look up a field by name.
+ * - ntofz: look up a field by name (as a null-terminated string).
+ * - itof:  look up a field by number. */
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length);
+UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
+                                                  const char *name) {
+  return upb_oneofdef_ntof(o, name, strlen(name));
+}
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
+
+/* DEPRECATED, slated for removal. */
+int upb_oneofdef_numfields(const upb_oneofdef *o);
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
+void upb_oneof_next(upb_oneof_iter *iter);
+bool upb_oneof_done(upb_oneof_iter *iter);
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
+void upb_oneof_iter_setdone(upb_oneof_iter *iter);
+bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
+                            const upb_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_msgdef *****************************************************************/
+
+typedef upb_inttable_iter upb_msg_field_iter;
+typedef upb_strtable_iter upb_msg_oneof_iter;
+
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY   1
+#define UPB_MAPENTRY_VALUE 2
+
+/* Well-known field tag numbers for Any messages. */
+#define UPB_ANY_TYPE 1
+#define UPB_ANY_VALUE 2
+
+/* Well-known field tag numbers for timestamp messages. */
+#define UPB_DURATION_SECONDS 1
+#define UPB_DURATION_NANOS 2
+
+/* Well-known field tag numbers for duration messages. */
+#define UPB_TIMESTAMP_SECONDS 1
+#define UPB_TIMESTAMP_NANOS 2
+
+const char *upb_msgdef_fullname(const upb_msgdef *m);
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
+const char *upb_msgdef_name(const upb_msgdef *m);
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
+bool upb_msgdef_iswrapper(const upb_msgdef *m);
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
+int upb_msgdef_fieldcount(const upb_msgdef *m);
+int upb_msgdef_oneofcount(const upb_msgdef *m);
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i);
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i);
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len);
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len);
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m);
+
+UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
+                                               const char *name) {
+  return upb_msgdef_ntoo(m, name, strlen(name));
+}
+
+UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
+                                                const char *name) {
+  return upb_msgdef_ntof(m, name, strlen(name));
+}
+
+/* Lookup of either field or oneof by name.  Returns whether either was found.
+ * If the return is true, then the found def will be set, and the non-found
+ * one set to NULL. */
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o);
+
+UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
+                                       const upb_fielddef **f,
+                                       const upb_oneofdef **o) {
+  return upb_msgdef_lookupname(m, name, strlen(name), f, o);
+}
+
+/* Returns a field by either JSON name or regular proto name. */
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+                                              const char *name, size_t len);
+
+/* DEPRECATED, slated for removal */
+int upb_msgdef_numfields(const upb_msgdef *m);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+int upb_msgdef_numrealoneofs(const upb_msgdef *m);
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
+void upb_msg_field_next(upb_msg_field_iter *iter);
+bool upb_msg_field_done(const upb_msg_field_iter *iter);
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+                                const upb_msg_field_iter * iter2);
+void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
+void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+                                const upb_msg_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_enumdef ****************************************************************/
+
+typedef upb_strtable_iter upb_enum_iter;
+
+const char *upb_enumdef_fullname(const upb_enumdef *e);
+const char *upb_enumdef_name(const upb_enumdef *e);
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
+int32_t upb_enumdef_default(const upb_enumdef *e);
+int upb_enumdef_numvals(const upb_enumdef *e);
+
+/* Enum lookups:
+ * - ntoi:  look up a name with specified length.
+ * - ntoiz: look up a name provided as a null-terminated string.
+ * - iton:  look up an integer, returning the name as a null-terminated
+ *          string. */
+bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
+                      int32_t *num);
+UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
+                                  const char *name, int32_t *num) {
+  return upb_enumdef_ntoi(e, name, strlen(name), num);
+}
+const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
+
+void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
+void upb_enum_next(upb_enum_iter *iter);
+bool upb_enum_done(upb_enum_iter *iter);
+const char *upb_enum_iter_name(upb_enum_iter *iter);
+int32_t upb_enum_iter_number(upb_enum_iter *iter);
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f);
+const char *upb_filedef_package(const upb_filedef *f);
+const char *upb_filedef_phpprefix(const upb_filedef *f);
+const char *upb_filedef_phpnamespace(const upb_filedef *f);
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
+int upb_filedef_depcount(const upb_filedef *f);
+int upb_filedef_msgcount(const upb_filedef *f);
+int upb_filedef_enumcount(const upb_filedef *f);
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f);
+
+/* upb_symtab *****************************************************************/
+
+upb_symtab *upb_symtab_new(void);
+void upb_symtab_free(upb_symtab* s);
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
+const upb_msgdef *upb_symtab_lookupmsg2(
+    const upb_symtab *s, const char *sym, size_t len);
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
+const upb_filedef *upb_symtab_lookupfile2(
+    const upb_symtab *s, const char *name, size_t len);
+int upb_symtab_filecount(const upb_symtab *s);
+const upb_filedef *upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
+    upb_status *status);
+size_t _upb_symtab_bytesloaded(const upb_symtab *s);
+upb_arena *_upb_symtab_arena(const upb_symtab *s);
+
+/* For generated code only: loads a generated descriptor. */
+typedef struct upb_def_init {
+  struct upb_def_init **deps;     /* Dependencies of this file. */
+  const upb_msglayout **layouts;  /* Pre-order layouts of all messages. */
+  const char *filename;
+  upb_strview descriptor;         /* Serialized descriptor. */
+} upb_def_init;
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif  /* __cplusplus */
+
+#endif /* UPB_DEF_H_ */
+
+/** google/protobuf/descriptor.upbdefs.h ************************************************************//* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_
+#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+extern upb_def_init google_protobuf_descriptor_proto_upbdefinit;
+
+UPB_INLINE const upb_msgdef *google_protobuf_FileDescriptorSet_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_FileDescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_ExtensionRange_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_ReservedRange_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ReservedRange");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_ExtensionRangeOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.ExtensionRangeOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_FieldDescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_OneofDescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.OneofDescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_EnumDescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_EnumDescriptorProto_EnumReservedRange_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto.EnumReservedRange");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_EnumValueDescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_ServiceDescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_MethodDescriptorProto_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_FileOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.FileOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_MessageOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_FieldOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_OneofOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.OneofOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_EnumOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_EnumValueOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_ServiceOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_MethodOptions_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_UninterpretedOption_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_UninterpretedOption_NamePart_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_SourceCodeInfo_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_SourceCodeInfo_Location_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_GeneratedCodeInfo_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.GeneratedCodeInfo");
+}
+
+UPB_INLINE const upb_msgdef *google_protobuf_GeneratedCodeInfo_Annotation_getmsgdef(upb_symtab *s) {
+  _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit);
+  return upb_symtab_lookupmsg(s, "google.protobuf.GeneratedCodeInfo.Annotation");
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ */
+
+/** upb/reflection.h ************************************************************/
+#ifndef UPB_REFLECTION_H_
+#define UPB_REFLECTION_H_
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef union {
+  bool bool_val;
+  float float_val;
+  double double_val;
+  int32_t int32_val;
+  int64_t int64_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  const upb_map* map_val;
+  const upb_msg* msg_val;
+  const upb_array* array_val;
+  upb_strview str_val;
+} upb_msgval;
+
+typedef union {
+  upb_map* map;
+  upb_msg* msg;
+  upb_array* array;
+} upb_mutmsgval;
+
+upb_msgval upb_fielddef_default(const upb_fielddef *f);
+
+/** upb_msg *******************************************************************/
+
+/* Creates a new message of the given type in the given arena. */
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a);
+
+/* Returns the value associated with this field. */
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns a mutable pointer to a map, array, or submessage value.  If the given
+ * arena is non-NULL this will construct a new object if it was not previously
+ * present.  May not be called for primitive fields. */
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a);
+
+/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns the field that is set in the oneof, or NULL if none are set. */
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+                                       const upb_oneofdef *o);
+
+/* Sets the given field to the given value.  For a msg/array/map/string, the
+ * value must be in the same arena.  */
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+                 upb_arena *a);
+
+/* Clears any field presence and sets the value back to its default. */
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f);
+
+/* Clear all data and unknown fields. */
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m);
+
+/* Iterate over present fields.
+ *
+ * size_t iter = UPB_MSG_BEGIN;
+ * const upb_fielddef *f;
+ * upb_msgval val;
+ * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) {
+ *   process_field(f, val);
+ * }
+ *
+ * If ext_pool is NULL, no extensions will be returned.  If the given symtab
+ * returns extensions that don't match what is in this message, those extensions
+ * will be skipped.
+ */
+
+#define UPB_MSG_BEGIN -1
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+                  const upb_symtab *ext_pool, const upb_fielddef **f,
+                  upb_msgval *val, size_t *iter);
+
+/* Clears all unknown field data from this message and all submessages. */
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth);
+
+/** upb_array *****************************************************************/
+
+/* Creates a new array on the given arena that holds elements of this type. */
+upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type);
+
+/* Returns the size of the array. */
+size_t upb_array_size(const upb_array *arr);
+
+/* Returns the given element, which must be within the array's current size. */
+upb_msgval upb_array_get(const upb_array *arr, size_t i);
+
+/* Sets the given element, which must be within the array's current size. */
+void upb_array_set(upb_array *arr, size_t i, upb_msgval val);
+
+/* Appends an element to the array.  Returns false on allocation failure. */
+bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena);
+
+/* Changes the size of a vector.  New elements are initialized to empty/0.
+ * Returns false on allocation failure. */
+bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena);
+
+/** upb_map *******************************************************************/
+
+/* Creates a new map on the given arena with the given key/value size. */
+upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
+                     upb_fieldtype_t value_type);
+
+/* Returns the number of entries in the map. */
+size_t upb_map_size(const upb_map *map);
+
+/* Stores a value for the given key into |*val| (or the zero value if the key is
+ * not present).  Returns whether the key was present.  The |val| pointer may be
+ * NULL, in which case the function tests whether the given key is present.  */
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
+
+/* Removes all entries in the map. */
+void upb_map_clear(upb_map *map);
+
+/* Sets the given key to the given value.  Returns true if this was a new key in
+ * the map, or false if an existing key was replaced. */
+bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
+                 upb_arena *arena);
+
+/* Deletes this key from the table.  Returns true if the key was present. */
+bool upb_map_delete(upb_map *map, upb_msgval key);
+
+/* Map iteration:
+ *
+ * size_t iter = UPB_MAP_BEGIN;
+ * while (upb_mapiter_next(map, &iter)) {
+ *   upb_msgval key = upb_mapiter_key(map, iter);
+ *   upb_msgval val = upb_mapiter_value(map, iter);
+ *
+ *   // If mutating is desired.
+ *   upb_mapiter_setvalue(map, iter, value2);
+ * }
+ */
+
+/* Advances to the next entry.  Returns false if no more entries are present. */
+bool upb_mapiter_next(const upb_map *map, size_t *iter);
+
+/* Returns true if the iterator still points to a valid entry, or false if the
+ * iterator is past the last element. It is an error to call this function with
+ * UPB_MAP_BEGIN (you must call next() at least once first). */
+bool upb_mapiter_done(const upb_map *map, size_t iter);
+
+/* Returns the key and value for this entry of the map. */
+upb_msgval upb_mapiter_key(const upb_map *map, size_t iter);
+upb_msgval upb_mapiter_value(const upb_map *map, size_t iter);
+
+/* Sets the value for this entry.  The iterator must not be done, and the
+ * iterator must not have been initialized const. */
+void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_H_ */
+
+/** upb/json_decode.h ************************************************************/
+#ifndef UPB_JSONDECODE_H_
+#define UPB_JSONDECODE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  UPB_JSONDEC_IGNOREUNKNOWN = 1
+};
+
+bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
+                     const upb_msgdef *m, const upb_symtab *any_pool,
+                     int options, upb_arena *arena, upb_status *status);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_JSONDECODE_H_ */
+
+/** upb/json_encode.h ************************************************************/
+#ifndef UPB_JSONENCODE_H_
+#define UPB_JSONENCODE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* When set, emits 0/default values.  TODO(haberman): proto3 only? */
+  UPB_JSONENC_EMITDEFAULTS = 1,
+
+  /* When set, use normal (snake_caes) field names instead of JSON (camelCase)
+     names. */
+  UPB_JSONENC_PROTONAMES = 2
+};
+
+/* Encodes the given |msg| to JSON format.  The message's reflection is given in
+ * |m|.  The symtab in |symtab| is used to find extensions (if NULL, extensions
+ * will not be printed).
+ *
+ * Output is placed in the given buffer, and always NULL-terminated.  The output
+ * size (excluding NULL) is returned.  This means that a return value >= |size|
+ * implies that the output was truncated.  (These are the same semantics as
+ * snprintf()). */
+size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
+                       const upb_symtab *ext_pool, int options, char *buf,
+                       size_t size, upb_status *status);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_JSONENCODE_H_ */
+
+/** upb/port_undef.inc ************************************************************/
+/* See port_def.inc.  This should #undef all macros #defined there. */
+
+#undef UPB_SIZE
+#undef UPB_PTR_AT
+#undef UPB_READ_ONEOF
+#undef UPB_WRITE_ONEOF
+#undef UPB_MAPTYPE_STRING
+#undef UPB_INLINE
+#undef UPB_ALIGN_UP
+#undef UPB_ALIGN_DOWN
+#undef UPB_ALIGN_MALLOC
+#undef UPB_ALIGN_OF
+#undef UPB_LIKELY
+#undef UPB_UNLIKELY
+#undef UPB_FORCEINLINE
+#undef UPB_NOINLINE
+#undef UPB_NORETURN
+#undef UPB_PRINTF
+#undef UPB_MAX
+#undef UPB_MIN
+#undef UPB_UNUSED
+#undef UPB_ASSUME
+#undef UPB_ASSERT
+#undef UPB_UNREACHABLE
+#undef UPB_SETJMP
+#undef UPB_LONGJMP
+#undef UPB_PTRADD
+#undef UPB_MUSTTAIL
+#undef UPB_FASTTABLE_SUPPORTED
+#undef UPB_FASTTABLE
+#undef UPB_FASTTABLE_INIT
+#undef UPB_POISON_MEMORY_REGION
+#undef UPB_UNPOISON_MEMORY_REGION
+#undef UPB_ASAN
diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c
index e9ac935..888b434 100644
--- a/php/ext/google/protobuf/protobuf.c
+++ b/php/ext/google/protobuf/protobuf.c
@@ -30,273 +30,259 @@
 
 #include "protobuf.h"
 
-#include <zend_hash.h>
+#include <php.h>
+#include <Zend/zend_interfaces.h>
 
-static PHP_GINIT_FUNCTION(protobuf);
-static PHP_GSHUTDOWN_FUNCTION(protobuf);
-static PHP_RINIT_FUNCTION(protobuf);
-static PHP_RSHUTDOWN_FUNCTION(protobuf);
-static PHP_MINIT_FUNCTION(protobuf);
-static PHP_MSHUTDOWN_FUNCTION(protobuf);
+#include "arena.h"
+#include "array.h"
+#include "convert.h"
+#include "def.h"
+#include "map.h"
+#include "message.h"
+#include "names.h"
+
+// -----------------------------------------------------------------------------
+// Module "globals"
+// -----------------------------------------------------------------------------
+
+// Despite the name, module "globals" are really thread-locals:
+//  * PROTOBUF_G(var) accesses the thread-local variable for 'var'. Either:
+//    * PROTOBUF_G(var) -> protobuf_globals.var (Non-ZTS / non-thread-safe)
+//    * PROTOBUF_G(var) -> <Zend magic>         (ZTS / thread-safe builds)
+
+#define PROTOBUF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(protobuf, v)
+
+ZEND_BEGIN_MODULE_GLOBALS(protobuf)
+  // Set by the user to make the descriptor pool persist between requests.
+  zend_bool keep_descriptor_pool_after_request;
+
+  // Currently we make the generated pool a "global", which means that if a user
+  // does explicitly create threads within their request, the other threads will
+  // get different results from DescriptorPool::getGeneratedPool(). We require
+  // that all descriptors are loaded from the main thread.
+  zval generated_pool;
+
+  // A upb_symtab that we are saving for the next request so that we don't have
+  // to rebuild it from scratch. When keep_descriptor_pool_after_request==true,
+  // we steal the upb_symtab from the global DescriptorPool object just before
+  // destroying it.
+  upb_symtab *saved_symtab;
+
+  // Object cache (see interface in protobuf.h).
+  HashTable object_cache;
+
+  // Name cache (see interface in protobuf.h).
+  HashTable name_msg_cache;
+  HashTable name_enum_cache;
+
+  // An array of descriptor objects constructed during this request. These are
+  // logically referenced by the corresponding class entry, but since we can't
+  // actually write a class entry destructor, we reference them here, to be
+  // destroyed on request shutdown.
+  HashTable descriptors;
+ZEND_END_MODULE_GLOBALS(protobuf)
 
 ZEND_DECLARE_MODULE_GLOBALS(protobuf)
 
-// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
-// instances.
-static HashTable* upb_def_to_php_obj_map;
-static upb_inttable upb_def_to_desc_map_persistent;
-static upb_inttable upb_def_to_enumdesc_map_persistent;
-// Global map from message/enum's php class entry to corresponding wrapper
-// Descriptor/EnumDescriptor instances.
-static HashTable* ce_to_php_obj_map;
-static upb_strtable ce_to_desc_map_persistent;
-static upb_strtable ce_to_enumdesc_map_persistent;
-// Global map from message/enum's proto fully-qualified name to corresponding
-// wrapper Descriptor/EnumDescriptor instances.
-static upb_strtable proto_to_desc_map_persistent;
-static upb_strtable class_to_desc_map_persistent;
-
-upb_strtable reserved_names;
-
-// -----------------------------------------------------------------------------
-// Global maps.
-// -----------------------------------------------------------------------------
-
-static void add_to_table(HashTable* t, const void* def, void* value) {
-  zval* pDest = NULL;
-  php_proto_zend_hash_index_update_mem(t, (zend_ulong)def, &value,
-                                       sizeof(zval*), (void**)&pDest);
+const zval *get_generated_pool() {
+  return &PROTOBUF_G(generated_pool);
 }
 
-static void* get_from_table(const HashTable* t, const void* def) {
-  void** value;
-  if (php_proto_zend_hash_index_find_mem(t, (zend_ulong)def, (void**)&value) ==
-      FAILURE) {
-    return NULL;
+// This is a PHP extension (not a Zend extension). What follows is a summary of
+// a PHP extension's lifetime and when various handlers are called.
+//
+//  * PHP_GINIT_FUNCTION(protobuf) / PHP_GSHUTDOWN_FUNCTION(protobuf)
+//    are the constructor/destructor for the globals. The sequence over the
+//    course of a process lifetime is:
+//
+//    # Process startup
+//    GINIT(<Main Thread Globals>)
+//    MINIT
+//
+//    foreach request:
+//      RINIT
+//        # Request is processed here.
+//      RSHUTDOWN
+//
+//    foreach thread:
+//      GINIT(<This Thread Globals>)
+//        # Code for the thread runs here.
+//      GSHUTDOWN(<This Thread Globals>)
+//
+//    # Process Shutdown
+//    #
+//    # These should be running per the docs, but I have not been able to
+//    # actually get the process-wide shutdown functions to run.
+//    #
+//    # MSHUTDOWN
+//    # GSHUTDOWN(<Main Thread Globals>)
+//
+//  * Threads can be created either explicitly by the user, inside a request,
+//    or implicitly by the runtime, to process multiple requests concurrently.
+//    If the latter is being used, then the "foreach thread" block above
+//    actually looks like this:
+//
+//    foreach thread:
+//      GINIT(<This Thread Globals>)
+//      # A non-main thread will only receive requests when using a threaded
+//      # MPM with Apache
+//      foreach request:
+//        RINIT
+//          # Request is processed here.
+//        RSHUTDOWN
+//      GSHUTDOWN(<This Thread Globals>)
+//
+// That said, it appears that few people use threads with PHP:
+//   * The pthread package documented at
+//     https://www.php.net/manual/en/class.thread.php nas not been released
+//     since 2016, and the current release fails to compile against any PHP
+//     newer than 7.0.33.
+//     * The GitHub master branch supports 7.2+, but this has not been released
+//       to PECL.
+//     * Its owner has disavowed it as "broken by design" and "in an untenable
+//       position for the future": https://github.com/krakjoe/pthreads/issues/929
+//   * The only way to use PHP with requests in different threads is to use the
+//     Apache 2 mod_php with the "worker" MPM. But this is explicitly
+//     discouraged by the documentation: https://serverfault.com/a/231660
+
+static PHP_GSHUTDOWN_FUNCTION(protobuf) {
+  if (protobuf_globals->saved_symtab) {
+    upb_symtab_free(protobuf_globals->saved_symtab);
   }
-  return *value;
 }
 
-void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) {
-#if PHP_MAJOR_VERSION < 7
-  Z_ADDREF_P(value);
+static PHP_GINIT_FUNCTION(protobuf) {
+  ZVAL_NULL(&protobuf_globals->generated_pool);
+  protobuf_globals->saved_symtab = NULL;
+}
+
+/**
+ * PHP_RINIT_FUNCTION(protobuf)
+ *
+ * This function is run at the beginning of processing each request.
+ */
+static PHP_RINIT_FUNCTION(protobuf) {
+  // Create the global generated pool.
+  // Reuse the symtab (if any) left to us by the last request.
+  upb_symtab *symtab = PROTOBUF_G(saved_symtab);
+  DescriptorPool_CreateWithSymbolTable(&PROTOBUF_G(generated_pool), symtab);
+
+  zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0);
+  zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0);
+  zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0);
+  zend_hash_init(&PROTOBUF_G(descriptors), 64, NULL, ZVAL_PTR_DTOR, 0);
+
+  return SUCCESS;
+}
+
+/**
+ * PHP_RSHUTDOWN_FUNCTION(protobuf)
+ *
+ * This function is run at the end of processing each request.
+ */
+static PHP_RSHUTDOWN_FUNCTION(protobuf) {
+  // Preserve the symtab if requested.
+  if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
+    zval *zv = &PROTOBUF_G(generated_pool);
+    PROTOBUF_G(saved_symtab) = DescriptorPool_Steal(zv);
+  }
+
+  zval_dtor(&PROTOBUF_G(generated_pool));
+  zend_hash_destroy(&PROTOBUF_G(object_cache));
+  zend_hash_destroy(&PROTOBUF_G(name_msg_cache));
+  zend_hash_destroy(&PROTOBUF_G(name_enum_cache));
+  zend_hash_destroy(&PROTOBUF_G(descriptors));
+
+  return SUCCESS;
+}
+
+// -----------------------------------------------------------------------------
+// Object Cache.
+// -----------------------------------------------------------------------------
+
+void Descriptors_Add(zend_object *desc) {
+  // The hash table will own a ref (it will destroy it when the table is
+  // destroyed), but for some reason the insert operation does not add a ref, so
+  // we do that here with ZVAL_OBJ_COPY().
+  zval zv;
+  ZVAL_OBJ_COPY(&zv, desc);
+  zend_hash_next_index_insert(&PROTOBUF_G(descriptors), &zv);
+}
+
+void ObjCache_Add(const void *upb_obj, zend_object *php_obj) {
+  zend_ulong k = (zend_ulong)upb_obj;
+  zend_hash_index_add_ptr(&PROTOBUF_G(object_cache), k, php_obj);
+}
+
+void ObjCache_Delete(const void *upb_obj) {
+  if (upb_obj) {
+    zend_ulong k = (zend_ulong)upb_obj;
+    int ret = zend_hash_index_del(&PROTOBUF_G(object_cache), k);
+    PBPHP_ASSERT(ret == SUCCESS);
+  }
+}
+
+bool ObjCache_Get(const void *upb_obj, zval *val) {
+  zend_ulong k = (zend_ulong)upb_obj;
+  zend_object *obj = zend_hash_index_find_ptr(&PROTOBUF_G(object_cache), k);
+
+  if (obj) {
+    ZVAL_OBJ_COPY(val, obj);
+    return true;
+  } else {
+    ZVAL_NULL(val);
+    return false;
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Name Cache.
+// -----------------------------------------------------------------------------
+
+void NameMap_AddMessage(const upb_msgdef *m) {
+  char *k = GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));
+  zend_hash_str_add_ptr(&PROTOBUF_G(name_msg_cache), k, strlen(k), (void*)m);
+  free(k);
+}
+
+void NameMap_AddEnum(const upb_enumdef *e) {
+  char *k = GetPhpClassname(upb_enumdef_file(e), upb_enumdef_fullname(e));
+  zend_hash_str_add_ptr(&PROTOBUF_G(name_enum_cache), k, strlen(k), (void*)e);
+  free(k);
+}
+
+const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) {
+  const upb_msgdef *ret =
+      zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
+
+  if (!ret && ce->create_object) {
+#if PHP_VERSION_ID < 80000
+    zval tmp;
+    zval zv;
+    ZVAL_OBJ(&tmp, ce->create_object(ce));
+    zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv);
+    zval_ptr_dtor(&tmp);
 #else
-  GC_ADDREF(value);
+    zval zv;
+    zend_object *tmp = ce->create_object(ce);
+    zend_call_method_with_0_params(tmp, ce, NULL, "__construct", &zv);
+    OBJ_RELEASE(tmp);
 #endif
-  add_to_table(upb_def_to_php_obj_map, def, value);
-}
-
-PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def) {
-  return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(upb_def_to_php_obj_map, def);
-}
-
-void add_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc) {
-  upb_inttable_insertptr(&upb_def_to_desc_map_persistent,
-                         m, upb_value_ptr(desc));
-}
-
-DescriptorInternal* get_msgdef_desc(const upb_msgdef* m) {
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_PTR;
-#endif
-  if (!upb_inttable_lookupptr(&upb_def_to_desc_map_persistent, m, &v)) {
-    return NULL;
-  } else {
-    return upb_value_getptr(v);
+    zval_ptr_dtor(&zv);
+    ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
   }
+
+  return ret;
 }
 
-void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc) {
-  upb_inttable_insertptr(&upb_def_to_enumdesc_map_persistent,
-                         e, upb_value_ptr(desc));
-}
-
-EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e) {
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_PTR;
-#endif
-  if (!upb_inttable_lookupptr(&upb_def_to_enumdesc_map_persistent, e, &v)) {
-    return NULL;
-  } else {
-    return upb_value_getptr(v);
-  }
-}
-
-void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value) {
-#if PHP_MAJOR_VERSION < 7
-  Z_ADDREF_P(value);
-#else
-  GC_ADDREF(value);
-#endif
-  add_to_table(ce_to_php_obj_map, ce, value);
-}
-
-PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce) {
-  return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(ce_to_php_obj_map, ce);
-}
-
-void add_ce_desc(const zend_class_entry* ce, DescriptorInternal* desc) {
-#if PHP_MAJOR_VERSION < 7
-  const char* klass = ce->name;
-#else
-  const char* klass = ZSTR_VAL(ce->name);
-#endif
-  upb_strtable_insert(&ce_to_desc_map_persistent, klass,
-                      upb_value_ptr(desc));
-}
-
-DescriptorInternal* get_ce_desc(const zend_class_entry* ce) {
-#if PHP_MAJOR_VERSION < 7
-  const char* klass = ce->name;
-#else
-  const char* klass = ZSTR_VAL(ce->name);
-#endif
-
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_PTR;
-#endif
-
-  if (!upb_strtable_lookup(&ce_to_desc_map_persistent, klass, &v)) {
-    return NULL;
-  } else {
-    return upb_value_getptr(v);
-  }
-}
-
-void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc) {
-#if PHP_MAJOR_VERSION < 7
-  const char* klass = ce->name;
-#else
-  const char* klass = ZSTR_VAL(ce->name);
-#endif
-  upb_strtable_insert(&ce_to_enumdesc_map_persistent, klass,
-                      upb_value_ptr(desc));
-}
-
-EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce) {
-#if PHP_MAJOR_VERSION < 7
-  const char* klass = ce->name;
-#else
-  const char* klass = ZSTR_VAL(ce->name);
-#endif
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_PTR;
-#endif
-  if (!upb_strtable_lookup(&ce_to_enumdesc_map_persistent, klass, &v)) {
-    return NULL;
-  } else {
-    return upb_value_getptr(v);
-  }
-}
-
-bool class_added(const void* ce) {
-  return get_ce_desc(ce) != NULL;
-}
-
-void add_proto_desc(const char* proto, DescriptorInternal* desc) {
-  upb_strtable_insert(&proto_to_desc_map_persistent, proto,
-                      upb_value_ptr(desc));
-}
-
-DescriptorInternal* get_proto_desc(const char* proto) {
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_PTR;
-#endif
-  if (!upb_strtable_lookup(&proto_to_desc_map_persistent, proto, &v)) {
-    return NULL;
-  } else {
-    return upb_value_getptr(v);
-  }
-}
-
-void add_class_desc(const char* klass, DescriptorInternal* desc) {
-  upb_strtable_insert(&class_to_desc_map_persistent, klass,
-                      upb_value_ptr(desc));
-}
-
-DescriptorInternal* get_class_desc(const char* klass) {
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_PTR;
-#endif
-  if (!upb_strtable_lookup(&class_to_desc_map_persistent, klass, &v)) {
-    return NULL;
-  } else {
-    return upb_value_getptr(v);
-  }
-}
-
-void add_class_enumdesc(const char* klass, EnumDescriptorInternal* desc) {
-  upb_strtable_insert(&class_to_desc_map_persistent, klass,
-                      upb_value_ptr(desc));
-}
-
-EnumDescriptorInternal* get_class_enumdesc(const char* klass) {
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_PTR;
-#endif
-  if (!upb_strtable_lookup(&class_to_desc_map_persistent, klass, &v)) {
-    return NULL;
-  } else {
-    return upb_value_getptr(v);
-  }
+const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce) {
+  const upb_enumdef *ret =
+      zend_hash_find_ptr(&PROTOBUF_G(name_enum_cache), ce->name);
+  return ret;
 }
 
 // -----------------------------------------------------------------------------
-// Well Known Types.
-// -----------------------------------------------------------------------------
-
-bool is_inited_file_any;
-bool is_inited_file_api;
-bool is_inited_file_duration;
-bool is_inited_file_field_mask;
-bool is_inited_file_empty;
-bool is_inited_file_source_context;
-bool is_inited_file_struct;
-bool is_inited_file_timestamp;
-bool is_inited_file_type;
-bool is_inited_file_wrappers;
-
-// -----------------------------------------------------------------------------
-// Reserved Name.
-// -----------------------------------------------------------------------------
-
-// Although we already have kReservedNames, we still add them to hash table to
-// speed up look up.
-const char *const kReservedNames[] = {
-    "abstract",   "and",        "array",        "as",           "break",
-    "callable",   "case",       "catch",        "class",        "clone",
-    "const",      "continue",   "declare",      "default",      "die",
-    "do",         "echo",       "else",         "elseif",       "empty",
-    "enddeclare", "endfor",     "endforeach",   "endif",        "endswitch",
-    "endwhile",   "eval",       "exit",         "extends",      "final",
-    "for",        "foreach",    "function",     "global",       "goto",
-    "if",         "implements", "include",      "include_once", "instanceof",
-    "insteadof",  "interface",  "isset",        "list",         "namespace",
-    "new",        "or",         "print",        "private",      "protected",
-    "public",     "require",    "require_once", "return",       "static",
-    "switch",     "throw",      "trait",        "try",          "unset",
-    "use",        "var",        "while",        "xor",          "int",
-    "float",      "bool",       "string",       "true",         "false",
-    "null",       "void",       "iterable"};
-const int kReservedNamesSize = 73;
-
-bool is_reserved_name(const char* name) {
-  upb_value v;
-#ifndef NDEBUG
-  v.ctype = UPB_CTYPE_UINT64;
-#endif
-  return upb_strtable_lookup2(&reserved_names, name, strlen(name), &v);
-}
-
-// -----------------------------------------------------------------------------
-// Utilities.
+// Module init.
 // -----------------------------------------------------------------------------
 
 zend_function_entry protobuf_functions[] = {
@@ -308,203 +294,6 @@
   ZEND_MOD_END
 };
 
-zend_module_entry protobuf_module_entry = {
-  STANDARD_MODULE_HEADER_EX,
-  NULL,
-  protobuf_deps,
-  PHP_PROTOBUF_EXTNAME,     // extension name
-  protobuf_functions,       // function list
-  PHP_MINIT(protobuf),      // process startup
-  PHP_MSHUTDOWN(protobuf),  // process shutdown
-  PHP_RINIT(protobuf),      // request shutdown
-  PHP_RSHUTDOWN(protobuf),  // request shutdown
-  NULL,                 // extension info
-  PHP_PROTOBUF_VERSION, // extension version
-  PHP_MODULE_GLOBALS(protobuf),  // globals descriptor
-  PHP_GINIT(protobuf),  // globals ctor
-  PHP_GSHUTDOWN(protobuf),  // globals dtor
-  NULL,  // post deactivate
-  STANDARD_MODULE_PROPERTIES_EX
-};
-
-// install module
-ZEND_GET_MODULE(protobuf)
-
-// global variables
-static PHP_GINIT_FUNCTION(protobuf) {
-}
-
-static PHP_GSHUTDOWN_FUNCTION(protobuf) {
-}
-
-#if PHP_MAJOR_VERSION >= 7
-static void php_proto_hashtable_descriptor_release(zval* value) {
-  void* ptr = Z_PTR_P(value);
-  zend_object* object = *(zend_object**)ptr;
-  GC_DELREF(object);
-  if(GC_REFCOUNT(object) == 0) {
-    zend_objects_store_del(object);
-  }
-  efree(ptr);
-}
-#endif
-
-static void initialize_persistent_descriptor_pool(TSRMLS_D) {
-  upb_inttable_init(&upb_def_to_desc_map_persistent, UPB_CTYPE_PTR);
-  upb_inttable_init(&upb_def_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
-  upb_strtable_init(&ce_to_desc_map_persistent, UPB_CTYPE_PTR);
-  upb_strtable_init(&ce_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
-  upb_strtable_init(&proto_to_desc_map_persistent, UPB_CTYPE_PTR);
-  upb_strtable_init(&class_to_desc_map_persistent, UPB_CTYPE_PTR);
-
-  internal_descriptor_pool_impl_init(&generated_pool_impl TSRMLS_CC);
-
-  is_inited_file_any = false;
-  is_inited_file_api = false;
-  is_inited_file_duration = false;
-  is_inited_file_field_mask = false;
-  is_inited_file_empty = false;
-  is_inited_file_source_context = false;
-  is_inited_file_struct = false;
-  is_inited_file_timestamp = false;
-  is_inited_file_type = false;
-  is_inited_file_wrappers = false;
-}
-
-static PHP_RINIT_FUNCTION(protobuf) {
-  ALLOC_HASHTABLE(upb_def_to_php_obj_map);
-  zend_hash_init(upb_def_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
-
-  ALLOC_HASHTABLE(ce_to_php_obj_map);
-  zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
-
-  generated_pool = NULL;
-  generated_pool_php = NULL;
-  internal_generated_pool_php = NULL;
-
-  if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
-    // Needs to clean up obsolete class entry
-    upb_strtable_iter i;
-    upb_value v;
-
-    DescriptorInternal* desc;
-    for(upb_strtable_begin(&i, &ce_to_desc_map_persistent);
-        !upb_strtable_done(&i);
-        upb_strtable_next(&i)) {
-      v = upb_strtable_iter_value(&i);
-      desc = upb_value_getptr(v);
-      desc->klass = NULL;
-    }
-
-    EnumDescriptorInternal* enumdesc;
-    for(upb_strtable_begin(&i, &ce_to_enumdesc_map_persistent);
-        !upb_strtable_done(&i);
-        upb_strtable_next(&i)) {
-      v = upb_strtable_iter_value(&i);
-      enumdesc = upb_value_getptr(v);
-      enumdesc->klass = NULL;
-    }
-  } else {
-    initialize_persistent_descriptor_pool(TSRMLS_C);
-  }
-
-  return 0;
-}
-
-static void cleanup_desc_table(upb_inttable* t) {
-  upb_inttable_iter i;
-  upb_value v;
-  DescriptorInternal* desc;
-  for(upb_inttable_begin(&i, t);
-      !upb_inttable_done(&i);
-      upb_inttable_next(&i)) {
-    v = upb_inttable_iter_value(&i);
-    desc = upb_value_getptr(v);
-    if (desc->layout) {
-      free_layout(desc->layout);
-      desc->layout = NULL;
-    }
-    free(desc->classname);
-    SYS_FREE(desc);
-  }
-}
-
-static void cleanup_enumdesc_table(upb_inttable* t) {
-  upb_inttable_iter i;
-  upb_value v;
-  EnumDescriptorInternal* desc;
-  for(upb_inttable_begin(&i, t);
-      !upb_inttable_done(&i);
-      upb_inttable_next(&i)) {
-    v = upb_inttable_iter_value(&i);
-    desc = upb_value_getptr(v);
-    free(desc->classname);
-    SYS_FREE(desc);
-  }
-}
-
-static void cleanup_persistent_descriptor_pool(TSRMLS_D) {
-  // Clean up
-
-  // Only needs to clean one map out of three (def=>desc, ce=>desc, proto=>desc)
-  cleanup_desc_table(&upb_def_to_desc_map_persistent);
-  cleanup_enumdesc_table(&upb_def_to_enumdesc_map_persistent);
-
-  internal_descriptor_pool_impl_destroy(&generated_pool_impl TSRMLS_CC);
-
-  upb_inttable_uninit(&upb_def_to_desc_map_persistent);
-  upb_inttable_uninit(&upb_def_to_enumdesc_map_persistent);
-  upb_strtable_uninit(&ce_to_desc_map_persistent);
-  upb_strtable_uninit(&ce_to_enumdesc_map_persistent);
-  upb_strtable_uninit(&proto_to_desc_map_persistent);
-  upb_strtable_uninit(&class_to_desc_map_persistent);
-}
-
-static PHP_RSHUTDOWN_FUNCTION(protobuf) {
-  zend_hash_destroy(upb_def_to_php_obj_map);
-  FREE_HASHTABLE(upb_def_to_php_obj_map);
-
-  zend_hash_destroy(ce_to_php_obj_map);
-  FREE_HASHTABLE(ce_to_php_obj_map);
-
-#if PHP_MAJOR_VERSION < 7
-  if (generated_pool_php != NULL) {
-    zval_dtor(generated_pool_php);
-    FREE_ZVAL(generated_pool_php);
-  }
-  if (internal_generated_pool_php != NULL) {
-    zval_dtor(internal_generated_pool_php);
-    FREE_ZVAL(internal_generated_pool_php);
-  }
-#else
-  if (generated_pool_php != NULL) {
-    zval tmp;
-    ZVAL_OBJ(&tmp, generated_pool_php);
-    zval_dtor(&tmp);
-  }
-  if (internal_generated_pool_php != NULL) {
-    zval tmp;
-    ZVAL_OBJ(&tmp, internal_generated_pool_php);
-    zval_dtor(&tmp);
-  }
-#endif
-
-  if (!PROTOBUF_G(keep_descriptor_pool_after_request)) {
-    cleanup_persistent_descriptor_pool(TSRMLS_C);
-  }
-
-  return 0;
-}
-
-static void reserved_names_init() {
-  size_t i;
-  upb_value v = upb_value_bool(false);
-  for (i = 0; i < kReservedNamesSize; i++) {
-    upb_strtable_insert2(&reserved_names, kReservedNames[i],
-                         strlen(kReservedNames[i]), v);
-  }
-}
-
 PHP_INI_BEGIN()
 STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0",
                   PHP_INI_SYSTEM, OnUpdateBool,
@@ -514,86 +303,37 @@
 
 static PHP_MINIT_FUNCTION(protobuf) {
   REGISTER_INI_ENTRIES();
-
-  upb_strtable_init(&reserved_names, UPB_CTYPE_UINT64);
-  reserved_names_init();
-
-  if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
-    initialize_persistent_descriptor_pool(TSRMLS_C);
-  }
-
-  descriptor_pool_init(TSRMLS_C);
-  descriptor_init(TSRMLS_C);
-  enum_descriptor_init(TSRMLS_C);
-  enum_value_descriptor_init(TSRMLS_C);
-  field_descriptor_init(TSRMLS_C);
-  gpb_type_init(TSRMLS_C);
-  internal_descriptor_pool_init(TSRMLS_C);
-  map_field_init(TSRMLS_C);
-  map_field_iter_init(TSRMLS_C);
-  message_init(TSRMLS_C);
-  oneof_descriptor_init(TSRMLS_C);
-  repeated_field_init(TSRMLS_C);
-  repeated_field_iter_init(TSRMLS_C);
-  util_init(TSRMLS_C);
-
-  gpb_metadata_any_init(TSRMLS_C);
-  gpb_metadata_api_init(TSRMLS_C);
-  gpb_metadata_duration_init(TSRMLS_C);
-  gpb_metadata_field_mask_init(TSRMLS_C);
-  gpb_metadata_empty_init(TSRMLS_C);
-  gpb_metadata_source_context_init(TSRMLS_C);
-  gpb_metadata_struct_init(TSRMLS_C);
-  gpb_metadata_timestamp_init(TSRMLS_C);
-  gpb_metadata_type_init(TSRMLS_C);
-  gpb_metadata_wrappers_init(TSRMLS_C);
-
-  any_init(TSRMLS_C);
-  api_init(TSRMLS_C);
-  bool_value_init(TSRMLS_C);
-  bytes_value_init(TSRMLS_C);
-  double_value_init(TSRMLS_C);
-  duration_init(TSRMLS_C);
-  enum_init(TSRMLS_C);
-  enum_value_init(TSRMLS_C);
-  field_cardinality_init(TSRMLS_C);
-  field_init(TSRMLS_C);
-  field_kind_init(TSRMLS_C);
-  field_mask_init(TSRMLS_C);
-  float_value_init(TSRMLS_C);
-  empty_init(TSRMLS_C);
-  int32_value_init(TSRMLS_C);
-  int64_value_init(TSRMLS_C);
-  list_value_init(TSRMLS_C);
-  method_init(TSRMLS_C);
-  mixin_init(TSRMLS_C);
-  null_value_init(TSRMLS_C);
-  option_init(TSRMLS_C);
-  source_context_init(TSRMLS_C);
-  string_value_init(TSRMLS_C);
-  struct_init(TSRMLS_C);
-  syntax_init(TSRMLS_C);
-  timestamp_init(TSRMLS_C);
-  type_init(TSRMLS_C);
-  u_int32_value_init(TSRMLS_C);
-  u_int64_value_init(TSRMLS_C);
-  value_init(TSRMLS_C);
-
-  return 0;
+  Arena_ModuleInit();
+  Array_ModuleInit();
+  Convert_ModuleInit();
+  Def_ModuleInit();
+  Map_ModuleInit();
+  Message_ModuleInit();
+  return SUCCESS;
 }
 
 static PHP_MSHUTDOWN_FUNCTION(protobuf) {
-  if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
-    cleanup_persistent_descriptor_pool(TSRMLS_C);
-  }
-
-  upb_strtable_uninit(&reserved_names);
-
-  PEFREE(message_handlers);
-  PEFREE(repeated_field_handlers);
-  PEFREE(repeated_field_iter_handlers);
-  PEFREE(map_field_handlers);
-  PEFREE(map_field_iter_handlers);
-
-  return 0;
+  UNREGISTER_INI_ENTRIES();
+  return SUCCESS;
 }
+
+zend_module_entry protobuf_module_entry = {
+  STANDARD_MODULE_HEADER_EX,
+  NULL,
+  protobuf_deps,
+  "protobuf",               // extension name
+  protobuf_functions,       // function list
+  PHP_MINIT(protobuf),      // process startup
+  PHP_MSHUTDOWN(protobuf),  // process shutdown
+  PHP_RINIT(protobuf),      // request shutdown
+  PHP_RSHUTDOWN(protobuf),  // request shutdown
+  NULL,                     // extension info
+  PHP_PROTOBUF_VERSION,     // extension version
+  PHP_MODULE_GLOBALS(protobuf),  // globals descriptor
+  PHP_GINIT(protobuf),      // globals ctor
+  PHP_GSHUTDOWN(protobuf),  // globals dtor
+  NULL,                     // post deactivate
+  STANDARD_MODULE_PROPERTIES_EX
+};
+
+ZEND_GET_MODULE(protobuf)
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index 88cc400..0a71ad0 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -28,1556 +28,107 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
-#define __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
+#ifndef PHP_PROTOBUF_H_
+#define PHP_PROTOBUF_H_
 
 #include <php.h>
+#include <stdbool.h>
 
-// ubp.h has to be placed after php.h. Othwise, php.h will introduce NDEBUG.
-#include "upb.h"
+#include "php-upb.h"
 
-#define PHP_PROTOBUF_EXTNAME "protobuf"
-#define PHP_PROTOBUF_VERSION "3.11.4"
-
-#define MAX_LENGTH_OF_INT64 20
-#define SIZEOF_INT64 8
-
-/* From Chromium. */
-#define ARRAY_SIZE(x) \
-    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
-
-#define PHP_PROTO_UNUSED(var) (void)var
-/* PHP_PROTO_ASSERT(): in release mode, we use the expression without letting
- * it be evaluated.  This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define PHP_PROTO_ASSERT(expr) do {} while (false && (expr))
-#else
-#define PHP_PROTO_ASSERT(expr) assert(expr)
-#endif
-
-// -----------------------------------------------------------------------------
-// PHP7 Wrappers
-// ----------------------------------------------------------------------------
+const zval *get_generated_pool();
 
 #if PHP_VERSION_ID < 70300
 #define GC_ADDREF(h) ++GC_REFCOUNT(h)
 #define GC_DELREF(h) --GC_REFCOUNT(h)
 #endif
 
-#if PHP_MAJOR_VERSION < 7
-
-#define php_proto_zend_literal const zend_literal*
-#define PHP_PROTO_CASE_IS_BOOL IS_BOOL
-#define PHP_PROTO_SIZE int
-#define PHP_PROTO_LONG long
-#define PHP_PROTO_TSRMLS_DC TSRMLS_DC
-#define PHP_PROTO_TSRMLS_CC TSRMLS_CC
-
-// PHP String
-
-#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
-  ZVAL_STRING(zval_ptr, s, copy)
-#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
-  ZVAL_STRINGL(zval_ptr, s, len, copy)
-#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s, copy)
-#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len, copy)
-#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len, copy)
-#define php_proto_zend_make_printable_zval(from, to) \
-  {                                                  \
-    int use_copy;                                    \
-    zend_make_printable_zval(from, to, &use_copy);   \
-  }
-
-// PHP Array
-
-#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(array)
-
-#define php_proto_zend_hash_index_update_zval(ht, h, pData) \
-  zend_hash_index_update(ht, h, &(pData), sizeof(void*), NULL)
-
-#define php_proto_zend_hash_update_zval(ht, key, key_len, value) \
-  zend_hash_update(ht, key, key_len, value, sizeof(void*), NULL)
-
-#define php_proto_zend_hash_update(ht, key, key_len) \
-  zend_hash_update(ht, key, key_len, 0, 0, NULL)
-
-#define php_proto_zend_hash_index_update_mem(ht, h, pData, nDataSize, pDest) \
-  zend_hash_index_update(ht, h, pData, nDataSize, pDest)
-
-#define php_proto_zend_hash_update_mem(ht, key, key_len, pData, nDataSize, \
-                                       pDest)                              \
-  zend_hash_update(ht, key, key_len, pData, nDataSize, pDest)
-
-#define php_proto_zend_hash_index_find_zval(ht, h, pDest) \
-  zend_hash_index_find(ht, h, pDest)
-
-#define php_proto_zend_hash_find(ht, key, key_len, pDest) \
-  zend_hash_find(ht, key, key_len, pDest)
-
-#define php_proto_zend_hash_index_find_mem(ht, h, pDest) \
-  zend_hash_index_find(ht, h, pDest)
-
-#define php_proto_zend_hash_find_zval(ht, key, key_len, pDest) \
-  zend_hash_find(ht, key, key_len, pDest)
-
-#define php_proto_zend_hash_find_mem(ht, key, key_len, pDest) \
-  zend_hash_find(ht, key, key_len, pDest)
-
-#define php_proto_zend_hash_next_index_insert_zval(ht, pData) \
-  zend_hash_next_index_insert(ht, pData, sizeof(void*), NULL)
-
-#define php_proto_zend_hash_next_index_insert_mem(ht, pData, nDataSize, pDest) \
-  zend_hash_next_index_insert(ht, pData, nDataSize, pDest)
-
-#define php_proto_zend_hash_get_current_data_ex(ht, pDest, pos) \
-  zend_hash_get_current_data_ex(ht, pDest, pos)
-
-// PHP Object
-
-#define PHP_PROTO_WRAP_OBJECT_START(name) \
-  struct name {                           \
-    zend_object std;
-#define PHP_PROTO_WRAP_OBJECT_END \
-  };
-
-#define PHP_PROTO_INIT_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)   \
-  void LOWWERNAME##_init(TSRMLS_D) {                                         \
-    zend_class_entry class_type;                                             \
-    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
-                        LOWWERNAME##_methods);                               \
-    LOWWERNAME##_type = zend_register_internal_class_ex(                     \
-        &class_type, message_type, NULL TSRMLS_CC);                          \
-    LOWWERNAME##_type->create_object = message_create;                       \
-    zend_do_inheritance(LOWWERNAME##_type, message_type TSRMLS_CC);
-#define PHP_PROTO_INIT_SUBMSGCLASS_END \
-  }
-
-#define PHP_PROTO_INIT_ENUMCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)     \
-  void LOWWERNAME##_init(TSRMLS_D) {                                         \
-    zend_class_entry class_type;                                             \
-    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
-                        LOWWERNAME##_methods);                               \
-    LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC);
-#define PHP_PROTO_INIT_ENUMCLASS_END \
-  }
-
-#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)         \
-  void LOWWERNAME##_init(TSRMLS_D) {                                         \
-    zend_class_entry class_type;                                             \
-    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
-                        LOWWERNAME##_methods);                               \
-    LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
-    LOWWERNAME##_type->create_object = LOWWERNAME##_create;                  \
-    LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers, 1);               \
-    memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(),            \
-           sizeof(zend_object_handlers));
-#define PHP_PROTO_INIT_CLASS_END \
-  }
-
-#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \
-  static zend_object_value LOWWERNAME##_create(         \
-      zend_class_entry* ce TSRMLS_DC) {                 \
-    PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce);             \
-    zend_object_std_init(&intern->std, ce TSRMLS_CC);   \
-    object_properties_init(&intern->std, ce);
-#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME)                          \
-  PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
-  }
-
-#define PHP_PROTO_OBJECT_EMPTY_FREE_START(classname, lowername) \
-  void lowername##_free(void* object TSRMLS_DC) {               \
-    classname* intern = object;
-#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
-  void lowername##_free(void* object TSRMLS_DC) {         \
-    classname* intern = object;
-#define PHP_PROTO_OBJECT_FREE_END                 \
-    zend_object_std_dtor(&intern->std TSRMLS_CC); \
-    efree(intern);                                \
-  }
-
-#define PHP_PROTO_OBJECT_EMPTY_DTOR_START(classname, lowername)
-#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername)
-#define PHP_PROTO_OBJECT_DTOR_END
-
-#define CACHED_VALUE zval*
-#define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
-#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*(CACHED_VALUE*)(VALUE))
-#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
-#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (VALUE)
-#define ZVAL_TO_CACHED_VALUE(VALUE) (&VALUE)
-
-#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
-  ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC));
-
-#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) \
-  SEPARATE_ZVAL_IF_NOT_REF(value)
-
-#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL EG(uninitialized_zval_ptr)
-
-#define OBJ_PROP(OBJECT, OFFSET) &((OBJECT)->properties_table[OFFSET])
-
-#define php_proto_zval_ptr_dtor(zval_ptr) \
-  zval_ptr_dtor(&(zval_ptr))
-
-#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \
-  class_object* intern;                                        \
-  intern = (class_object*)emalloc(sizeof(class_object));       \
-  memset(intern, 0, sizeof(class_object));
-
-#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
-  zend_object_value retval = {0};                                             \
-  retval.handle = zend_objects_store_put(                                     \
-      intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,         \
-      class_object_free, NULL TSRMLS_CC);                                     \
-  retval.handlers = handler;                                                  \
-  return retval;
-
-#define PHP_PROTO_ALLOC_ARRAY(zval_ptr)  \
-  ALLOC_HASHTABLE(Z_ARRVAL_P(zval_ptr)); \
-  Z_TYPE_P(zval_ptr) = IS_ARRAY;
-
-#define ZVAL_OBJ(zval_ptr, call_create) \
-  Z_TYPE_P(zval_ptr) = IS_OBJECT;       \
-  Z_OBJVAL_P(zval_ptr) = call_create;
-
-#define UNBOX(class_name, val) \
-  (class_name*)zend_object_store_get_object(val TSRMLS_CC);
-
-#define UNBOX_HASHTABLE_VALUE(class_name, val) UNBOX(class_name, val)
-
-#define HASHTABLE_VALUE_DTOR ZVAL_PTR_DTOR
-
-#define PHP_PROTO_HASHTABLE_VALUE zval*
-#define HASHTABLE_VALUE_CE(val) Z_OBJCE_P(val)
-
-#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
-  OBJ_TYPE* OBJ;                                                            \
-  PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ;                                    \
-  MAKE_STD_ZVAL(WRAPPED_OBJ);                                               \
-  ZVAL_OBJ(WRAPPED_OBJ,                                                     \
-           OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY TSRMLS_CC));      \
-  OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ);                       \
-  Z_DELREF_P(desc_php);
-
-#define PHP_PROTO_CE_DECLARE zend_class_entry**
-#define PHP_PROTO_CE_UNREF(ce) (*ce)
-
-#define php_proto_zend_lookup_class(name, name_length, ce) \
-  zend_lookup_class(name, name_length, ce TSRMLS_CC)
-
-#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_ZVAL(return_value, value, 1, 0)
-
-#else  // PHP_MAJOR_VERSION >= 7
-
-#define php_proto_zend_literal void**
-#define PHP_PROTO_CASE_IS_BOOL IS_TRUE: case IS_FALSE
-#define PHP_PROTO_SIZE size_t
-#define PHP_PROTO_LONG zend_long
-#define PHP_PROTO_TSRMLS_DC
-#define PHP_PROTO_TSRMLS_CC
-
-// PHP String
-
-#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
-  ZVAL_STRING(zval_ptr, s)
-#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
-  ZVAL_STRINGL(zval_ptr, s, len)
-#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s)
-#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len)
-#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len)
-#define php_proto_zend_make_printable_zval(from, to) \
-  zend_make_printable_zval(from, to)
-
-// PHP Array
-
-#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(&array)
-
-static inline int php_proto_zend_hash_index_update_zval(HashTable* ht, zend_ulong h,
-                                                        zval* pData) {
-  void* result = NULL;
-  result = zend_hash_index_update(ht, h, pData);
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_update(HashTable* ht, const char* key,
-                                             size_t key_len) {
-  void* result = NULL;
-  zval temp;
-  ZVAL_LONG(&temp, 0);
-  result = zend_hash_str_update(ht, key, key_len, &temp);
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, zend_ulong h,
-                                                   void* pData, uint nDataSize,
-                                                   void** pDest) {
-  void* result = NULL;
-  result = zend_hash_index_update_mem(ht, h, pData, nDataSize);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_update_zval(HashTable* ht,
-                                                  const char* key, uint key_len,
-                                                  zval* pData) {
-  void* result = NULL;
-  zend_string* internal_key = zend_string_init(key, key_len, 0);
-  result = zend_hash_update(ht, internal_key, pData);
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_update_mem(HashTable* ht, const char* key,
-                                                 uint key_len, void* pData,
-                                                 uint nDataSize, void** pDest) {
-  zend_string* internal_key = zend_string_init(key, key_len, 0);
-  void* result = zend_hash_update_mem(ht, internal_key, pData, nDataSize);
-  zend_string_release(internal_key);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht,
-                                                      zend_ulong h, void** pDest) {
-  zval* result = zend_hash_index_find(ht, h);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_find(const HashTable* ht, const char* key,
-                                           size_t key_len, void** pDest) {
-  void* result = NULL;
-  result = zend_hash_str_find(ht, key, key_len);
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht,
-                                                     zend_ulong h, void** pDest) {
-  void* result = NULL;
-  result = zend_hash_index_find_ptr(ht, h);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_find_zval(const HashTable* ht,
-                                                const char* key, uint key_len,
-                                                void** pDest) {
-  zend_string* internal_key = zend_string_init(key, key_len, 1);
-  zval* result = zend_hash_find(ht, internal_key);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_find_mem(const HashTable* ht,
-                                                const char* key, uint key_len,
-                                                void** pDest) {
-  zend_string* internal_key = zend_string_init(key, key_len, 1);
-  void* result = zend_hash_find_ptr(ht, internal_key);
-  zend_string_release(internal_key);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_next_index_insert_zval(HashTable* ht,
-                                                             void* pData) {
-  zval tmp;
-  ZVAL_OBJ(&tmp, *(zend_object**)pData);
-  zval* result = zend_hash_next_index_insert(ht, &tmp);
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_next_index_insert_mem(HashTable* ht,
-                                                            void* pData,
-                                                            uint nDataSize,
-                                                            void** pDest) {
-  void* result = NULL;
-  result = zend_hash_next_index_insert_mem(ht, pData, nDataSize);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
-                                                          void** pDest,
-                                                          HashPosition* pos) {
-  void* result = NULL;
-  result = zend_hash_get_current_data_ex(ht, pos);
-  if (pDest != NULL) *pDest = result;
-  return result != NULL ? SUCCESS : FAILURE;
-}
-
-// PHP Object
-
-#define PHP_PROTO_WRAP_OBJECT_START(name) struct name {
-#define PHP_PROTO_WRAP_OBJECT_END \
-  zend_object std;                \
-  };
-
-#define PHP_PROTO_INIT_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
-  void LOWWERNAME##_init(TSRMLS_D) {                                       \
-    zend_class_entry class_type;                                           \
-    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),          \
-                        LOWWERNAME##_methods);                             \
-    LOWWERNAME##_type = zend_register_internal_class(&class_type);         \
-    zend_do_inheritance(LOWWERNAME##_type, message_type);
-#define PHP_PROTO_INIT_SUBMSGCLASS_END \
-  }
-
-#define PHP_PROTO_INIT_ENUMCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)     \
-  void LOWWERNAME##_init(TSRMLS_D) {                                         \
-    zend_class_entry class_type;                                             \
-    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
-                        LOWWERNAME##_methods);                               \
-    LOWWERNAME##_type = zend_register_internal_class(&class_type);
-#define PHP_PROTO_INIT_ENUMCLASS_END \
-  }
-
-#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)         \
-  void LOWWERNAME##_init(TSRMLS_D) {                                         \
-    zend_class_entry class_type;                                             \
-    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
-                        LOWWERNAME##_methods);                               \
-    LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
-    LOWWERNAME##_type->create_object = LOWWERNAME##_create;                  \
-    LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers, 1);               \
-    memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(),            \
-           sizeof(zend_object_handlers));                                    \
-    LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free;                     \
-    LOWWERNAME##_handlers->dtor_obj = LOWWERNAME##_dtor;                     \
-    LOWWERNAME##_handlers->offset = XtOffsetOf(CAMELNAME, std);
-#define PHP_PROTO_INIT_CLASS_END \
-  }
-
-#define PHP_PROTO_OBJECT_EMPTY_FREE_START(classname, lowername) \
-  void lowername##_free(zend_object* object) {
-#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
-  void lowername##_free(zend_object* object) {            \
-    classname* intern =                                   \
-        (classname*)((char*)object - XtOffsetOf(classname, std));
-#define PHP_PROTO_OBJECT_FREE_END           \
-  }
-
-#define PHP_PROTO_OBJECT_EMPTY_DTOR_START(classname, lowername) \
-  void lowername##_dtor(zend_object* object) {
-#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername) \
-  void lowername##_dtor(zend_object* object) {            \
-    classname* intern =                                   \
-        (classname*)((char*)object - XtOffsetOf(classname, std));
-#define PHP_PROTO_OBJECT_DTOR_END           \
-    zend_object_std_dtor(object TSRMLS_CC); \
-  }
-
-#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME)                     \
-  static zend_object* LOWWERNAME##_create(zend_class_entry* ce TSRMLS_DC) { \
-    PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce);                                 \
-    zend_object_std_init(&intern->std, ce TSRMLS_CC);                       \
-    object_properties_init(&intern->std, ce);
-#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME)                          \
-  PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
-  }
-
-#define CACHED_VALUE zval
-#define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
-#define CACHED_PTR_TO_ZVAL_PTR(VALUE) ((CACHED_VALUE*)(VALUE))
-#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
-#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (*VALUE)
-#define ZVAL_TO_CACHED_VALUE(VALUE) (VALUE)
-
-#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
-  ZVAL_OBJ(zval_ptr, class_type->create_object(class_type));
-
-#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) ;
-
-#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL &EG(uninitialized_zval)
-
-#define php_proto_zval_ptr_dtor(zval_ptr) \
-  zval_ptr_dtor(zval_ptr)
-
-#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type)               \
-  class_object* intern;                                                      \
-  int size = sizeof(class_object) + zend_object_properties_size(class_type); \
-  intern = ecalloc(1, size);                                                 \
-  memset(intern, 0, size);
-
-#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
-  intern->std.handlers = handler;                                             \
-  return &intern->std;
-
-#define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \
-  ZVAL_NEW_ARR(zval_ptr)
-
-#define UNBOX(class_name, val) \
-  (class_name*)((char*)Z_OBJ_P(val) - XtOffsetOf(class_name, std));
-
-#define UNBOX_HASHTABLE_VALUE(class_name, val) \
-  (class_name*)((char*)val - XtOffsetOf(class_name, std))
-
-#define HASHTABLE_VALUE_DTOR php_proto_hashtable_descriptor_release
-
-#define PHP_PROTO_HASHTABLE_VALUE zend_object*
-#define HASHTABLE_VALUE_CE(val) val->ce
-
-#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
-  OBJ_TYPE* OBJ;                                                            \
-  PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ;                                    \
-  WRAPPED_OBJ = OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY);            \
-  OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ);                       \
-  GC_DELREF(WRAPPED_OBJ);
-
-#define PHP_PROTO_CE_DECLARE zend_class_entry*
-#define PHP_PROTO_CE_UNREF(ce) (ce)
-
-static inline int php_proto_zend_lookup_class(
-    const char* name, int name_length, zend_class_entry** ce TSRMLS_DC) {
-  zend_string *zstr_name = zend_string_init(name, name_length, 0);
-  *ce = zend_lookup_class(zstr_name);
-  zend_string_release(zstr_name);
-  return *ce != NULL ? SUCCESS : FAILURE;
-}
-
-#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_COPY(return_value, value)
-
-#endif  // PHP_MAJOR_VERSION >= 7
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass)  \
-  zend_class_entry* old_scope = EG(scope); \
-  EG(scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \
-  old_scope = EG(scope);                    \
-  EG(scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_END EG(scope) = old_scope;
+// Since php 7.4, the write_property() object handler now returns the assigned
+// value (after possible type coercions) rather than void.
+// https://github.com/php/php-src/blob/PHP-7.4.0/UPGRADING.INTERNALS#L171-L173
+#if PHP_VERSION_ID < 70400
+#define PROTO_RETURN_VAL void
 #else
-#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass)       \
-  zend_class_entry* old_scope = EG(fake_scope); \
-  EG(fake_scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \
-  old_scope = EG(fake_scope);               \
-  EG(fake_scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_END EG(fake_scope) = old_scope;
+#define PROTO_RETURN_VAL zval*
 #endif
 
-// Define PHP class
-#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \
-  PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME)       \
-  PHP_PROTO_INIT_CLASS_END
-
-#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME)  \
-  PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \
-  LOWERNAME##_init_c_instance(intern TSRMLS_CC); \
-  PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME)
-
-#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME)  \
-  PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \
-  LOWERNAME##_free_c(intern TSRMLS_CC);             \
-  PHP_PROTO_OBJECT_FREE_END
-
-#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME)        \
-  PHP_PROTO_OBJECT_EMPTY_DTOR_START(CAMELNAME, LOWERNAME) \
-  PHP_PROTO_OBJECT_DTOR_END
-
-#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \
-  zend_class_entry *LOWERNAME##_type;              \
-  zend_object_handlers *LOWERNAME##_handlers;      \
-  DEFINE_PROTOBUF_FREE(NAME, LOWERNAME)            \
-  DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME)            \
-  DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME)          \
-  DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME)
-
-// -----------------------------------------------------------------------------
-// Forward Declaration
-// ----------------------------------------------------------------------------
-
-struct Any;
-struct Api;
-struct BoolValue;
-struct BytesValue;
-struct Descriptor;
-struct DescriptorInternal;
-struct DescriptorPool;
-struct DoubleValue;
-struct Duration;
-struct Enum;
-struct EnumDescriptor;
-struct EnumDescriptorInternal;
-struct EnumValue;
-struct EnumValueDescriptor;
-struct Field;
-struct FieldDescriptor;
-struct FieldMask;
-struct Field_Cardinality;
-struct Field_Kind;
-struct FloatValue;
-struct GPBEmpty;
-struct Int32Value;
-struct Int64Value;
-struct InternalDescriptorPool;
-struct InternalDescriptorPoolImpl;
-struct ListValue;
-struct Map;
-struct MapIter;
-struct MessageField;
-struct MessageHeader;
-struct MessageLayout;
-struct Method;
-struct Mixin;
-struct NullValue;
-struct Oneof;
-struct Option;
-struct RepeatedField;
-struct RepeatedFieldIter;
-struct SourceContext;
-struct StringValue;
-struct Struct;
-struct Syntax;
-struct Timestamp;
-struct Type;
-struct UInt32Value;
-struct UInt64Value;
-struct Value;
-
-typedef struct Any Any;
-typedef struct Api Api;
-typedef struct BoolValue BoolValue;
-typedef struct BytesValue BytesValue;
-typedef struct Descriptor Descriptor;
-typedef struct DescriptorInternal DescriptorInternal;
-typedef struct DescriptorPool DescriptorPool;
-typedef struct DoubleValue DoubleValue;
-typedef struct Duration Duration;
-typedef struct EnumDescriptor EnumDescriptor;
-typedef struct EnumDescriptorInternal EnumDescriptorInternal;
-typedef struct Enum Enum;
-typedef struct EnumValueDescriptor EnumValueDescriptor;
-typedef struct EnumValue EnumValue;
-typedef struct Field_Cardinality Field_Cardinality;
-typedef struct FieldDescriptor FieldDescriptor;
-typedef struct Field Field;
-typedef struct Field_Kind Field_Kind;
-typedef struct FieldMask FieldMask;
-typedef struct FloatValue FloatValue;
-typedef struct GPBEmpty GPBEmpty;
-typedef struct Int32Value Int32Value;
-typedef struct Int64Value Int64Value;
-typedef struct InternalDescriptorPool InternalDescriptorPool;
-typedef struct InternalDescriptorPoolImpl InternalDescriptorPoolImpl;
-typedef struct ListValue ListValue;
-typedef struct MapIter MapIter;
-typedef struct Map Map;
-typedef struct MessageField MessageField;
-typedef struct MessageHeader MessageHeader;
-typedef struct MessageLayout MessageLayout;
-typedef struct Method Method;
-typedef struct Mixin Mixin;
-typedef struct NullValue NullValue;
-typedef struct Oneof Oneof;
-typedef struct Option Option;
-typedef struct RepeatedFieldIter RepeatedFieldIter;
-typedef struct RepeatedField RepeatedField;
-typedef struct SourceContext SourceContext;
-typedef struct StringValue StringValue;
-typedef struct Struct Struct;
-typedef struct Syntax Syntax;
-typedef struct Timestamp Timestamp;
-typedef struct Type Type;
-typedef struct UInt32Value UInt32Value;
-typedef struct UInt64Value UInt64Value;
-typedef struct Value Value;
-
-// -----------------------------------------------------------------------------
-// Globals.
-// -----------------------------------------------------------------------------
-
-ZEND_BEGIN_MODULE_GLOBALS(protobuf)
-  zend_bool keep_descriptor_pool_after_request;
-ZEND_END_MODULE_GLOBALS(protobuf)
-
-ZEND_EXTERN_MODULE_GLOBALS(protobuf)
-
-#ifdef ZTS
-#define PROTOBUF_G(v) TSRMG(protobuf_globals_id, zend_protobuf_globals *, v)
+// Sine php 8.0, the Object Handlers API was changed to receive zend_object*
+// instead of zval* and zend_string* instead of zval* for property names.
+// https://github.com/php/php-src/blob/php-8.0.0beta1/UPGRADING.INTERNALS#L37-L39
+#if PHP_VERSION_ID < 80000
+#define PROTO_VAL zval
+#define PROTO_STR zval
+#define PROTO_VAL_P(obj) (void*)Z_OBJ_P(obj)
+#define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj)
+#define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj)
+#define ZVAL_OBJ_COPY(z, o) do { ZVAL_OBJ(z, o); GC_ADDREF(o); } while (0)
+#define RETVAL_OBJ_COPY(r) ZVAL_OBJ_COPY(return_value, r)
+#define RETURN_OBJ_COPY(r) do { RETVAL_OBJ_COPY(r); return; } while (0)
+#define RETURN_COPY(zv) do { ZVAL_COPY(return_value, zv); return; } while (0)
+#define RETURN_COPY_VALUE(zv) do { ZVAL_COPY_VALUE(return_value, zv); return; } while (0)
 #else
-#define PROTOBUF_G(v) (protobuf_globals.v)
+#define PROTO_VAL zend_object
+#define PROTO_STR zend_string
+#define PROTO_VAL_P(obj) (void*)(obj)
+#define PROTO_STRVAL_P(obj) ZSTR_VAL(obj)
+#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj)
 #endif
 
-// Init module and PHP classes.
-void any_init(TSRMLS_D);
-void api_init(TSRMLS_D);
-void bool_value_init(TSRMLS_D);
-void bytes_value_init(TSRMLS_D);
-void descriptor_init(TSRMLS_D);
-void descriptor_pool_init(TSRMLS_D);
-void double_value_init(TSRMLS_D);
-void duration_init(TSRMLS_D);
-void empty_init(TSRMLS_D);
-void enum_descriptor_init(TSRMLS_D);
-void enum_value_descriptor_init(TSRMLS_D);
-void enum_init(TSRMLS_D);
-void enum_value_init(TSRMLS_D);
-void field_cardinality_init(TSRMLS_D);
-void field_descriptor_init(TSRMLS_D);
-void field_init(TSRMLS_D);
-void field_kind_init(TSRMLS_D);
-void field_mask_init(TSRMLS_D);
-void float_value_init(TSRMLS_D);
-void gpb_type_init(TSRMLS_D);
-void int32_value_init(TSRMLS_D);
-void int64_value_init(TSRMLS_D);
-void internal_descriptor_pool_init(TSRMLS_D);
-void list_value_init(TSRMLS_D);
-void map_field_init(TSRMLS_D);
-void map_field_iter_init(TSRMLS_D);
-void message_init(TSRMLS_D);
-void method_init(TSRMLS_D);
-void mixin_init(TSRMLS_D);
-void null_value_init(TSRMLS_D);
-void oneof_descriptor_init(TSRMLS_D);
-void option_init(TSRMLS_D);
-void repeated_field_init(TSRMLS_D);
-void repeated_field_iter_init(TSRMLS_D);
-void source_context_init(TSRMLS_D);
-void string_value_init(TSRMLS_D);
-void struct_init(TSRMLS_D);
-void syntax_init(TSRMLS_D);
-void timestamp_init(TSRMLS_D);
-void type_init(TSRMLS_D);
-void u_int32_value_init(TSRMLS_D);
-void u_int64_value_init(TSRMLS_D);
-void util_init(TSRMLS_D);
-void value_init(TSRMLS_D);
+ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
+ZEND_END_ARG_INFO()
 
-void gpb_metadata_any_init(TSRMLS_D);
-void gpb_metadata_api_init(TSRMLS_D);
-void gpb_metadata_duration_init(TSRMLS_D);
-void gpb_metadata_field_mask_init(TSRMLS_D);
-void gpb_metadata_empty_init(TSRMLS_D);
-void gpb_metadata_source_context_init(TSRMLS_D);
-void gpb_metadata_struct_init(TSRMLS_D);
-void gpb_metadata_timestamp_init(TSRMLS_D);
-void gpb_metadata_type_init(TSRMLS_D);
-void gpb_metadata_wrappers_init(TSRMLS_D);
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setter, 0, 0, 1)
+  ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
 
-// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
-// instances.
-void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value);
-PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def);
-void add_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc);
-DescriptorInternal* get_msgdef_desc(const upb_msgdef* m);
-void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc);
-EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e);
+#define PHP_PROTOBUF_VERSION "3.17.3"
 
-// Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
-// instances.
-void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value);
-PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce);
-bool class_added(const void* ce);
-void add_ce_desc(const zend_class_entry* ce, DescriptorInternal* desc);
-DescriptorInternal* get_ce_desc(const zend_class_entry* ce);
-void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc);
-EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce);
+// ptr -> PHP object cache. This is a weak map that caches lazily-created
+// wrapper objects around upb types:
+//  * upb_msg* -> Message
+//  * upb_array* -> RepeatedField
+//  * upb_map*, -> MapField
+//  * upb_msgdef* -> Descriptor
+//  * upb_enumdef* -> EnumDescriptor
+//  * upb_msgdef* -> Descriptor
+//
+// Each wrapped object should add itself to the map when it is constructed, and
+// remove itself from the map when it is destroyed. This is how we ensure that
+// the map only contains live objects. The map is weak so it does not actually
+// take references to the cached objects.
+void ObjCache_Add(const void *key, zend_object *php_obj);
+void ObjCache_Delete(const void *key);
+bool ObjCache_Get(const void *key, zval *val);
 
-// Global map from message/enum's proto fully-qualified name to corresponding
-// wrapper Descriptor/EnumDescriptor instances.
-void add_proto_desc(const char* proto, DescriptorInternal* desc);
-DescriptorInternal* get_proto_desc(const char* proto);
-void add_class_desc(const char* klass, DescriptorInternal* desc);
-DescriptorInternal* get_class_desc(const char* klass);
-void add_class_enumdesc(const char* klass, EnumDescriptorInternal* desc);
-EnumDescriptorInternal* get_class_enumdesc(const char* klass);
+// PHP class name map. This is necessary because the pb_name->php_class_name
+// transformation is non-reversible, so when we need to look up a msgdef or
+// enumdef by PHP class, we can't turn the class name into a pb_name.
+//  * php_class_name -> upb_msgdef*
+//  * php_class_name -> upb_enumdef*
+void NameMap_AddMessage(const upb_msgdef *m);
+void NameMap_AddEnum(const upb_enumdef *m);
+const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce);
+const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce);
 
-extern zend_class_entry* map_field_type;
-extern zend_class_entry* repeated_field_type;
+// Add this descriptor object to the global list of descriptors that will be
+// kept alive for the duration of the request but destroyed when the request
+// is ending.
+void Descriptors_Add(zend_object *desc);
 
-// -----------------------------------------------------------------------------
-// Descriptor.
-// -----------------------------------------------------------------------------
-
-PHP_PROTO_WRAP_OBJECT_START(DescriptorPool)
-  InternalDescriptorPoolImpl* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(DescriptorPool, getGeneratedPool);
-PHP_METHOD(DescriptorPool, getDescriptorByClassName);
-PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName);
-
-struct InternalDescriptorPoolImpl {
-  upb_symtab* symtab;
-  upb_handlercache* fill_handler_cache;
-  upb_handlercache* pb_serialize_handler_cache;
-  upb_handlercache* json_serialize_handler_cache;
-  upb_handlercache* json_serialize_handler_preserve_cache;
-  upb_pbcodecache* fill_method_cache;
-  upb_json_codecache* json_fill_method_cache;
-};
-
-PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
-  InternalDescriptorPoolImpl* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
-PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
-
-void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len,
-                                 InternalDescriptorPoolImpl* pool,
-                                 bool use_nested_submsg TSRMLS_DC);
-void init_generated_pool_once(TSRMLS_D);
-void add_handlers_for_message(const void* closure, upb_handlers* h);
-void register_class(void *desc, bool is_enum TSRMLS_DC);
-
-// wrapper of generated pool
-#if PHP_MAJOR_VERSION < 7
-extern zval* generated_pool_php;
-extern zval* internal_generated_pool_php;
-void descriptor_pool_free(void* object TSRMLS_DC);
-void internal_descriptor_pool_free(void* object TSRMLS_DC);
+// We need our own assert() because PHP takes control of NDEBUG in its headers.
+#ifdef PBPHP_ENABLE_ASSERTS
+#define PBPHP_ASSERT(x)                                                    \
+  do {                                                                     \
+    if (!(x)) {                                                            \
+      fprintf(stderr, "Assertion failure at %s:%d %s", __FILE__, __LINE__, \
+              #x);                                                         \
+      abort();                                                             \
+    }                                                                      \
+  } while (false)
 #else
-extern zend_object *generated_pool_php;
-extern zend_object *internal_generated_pool_php;
-void descriptor_pool_free(zend_object* object);
-void internal_descriptor_pool_free(zend_object* object);
-#endif
-extern InternalDescriptorPoolImpl* generated_pool;
-// The actual generated pool
-extern InternalDescriptorPoolImpl generated_pool_impl;
-
-void internal_descriptor_pool_impl_init(
-    InternalDescriptorPoolImpl *pool TSRMLS_DC);
-void internal_descriptor_pool_impl_destroy(
-    InternalDescriptorPoolImpl *pool TSRMLS_DC);
-
-struct DescriptorInternal {
-  InternalDescriptorPoolImpl* pool;
-  const upb_msgdef* msgdef;
-  MessageLayout* layout;
-  zend_class_entry* klass;  // begins as NULL
-  bool use_nested_submsg;
-  char* classname;
-};
-
-PHP_PROTO_WRAP_OBJECT_START(Descriptor)
-  DescriptorInternal* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(Descriptor, getClass);
-PHP_METHOD(Descriptor, getFullName);
-PHP_METHOD(Descriptor, getField);
-PHP_METHOD(Descriptor, getFieldCount);
-PHP_METHOD(Descriptor, getOneofDecl);
-PHP_METHOD(Descriptor, getOneofDeclCount);
-
-extern zend_class_entry* descriptor_type;
-
-void descriptor_name_set(Descriptor *desc, const char *name);
-
-PHP_PROTO_WRAP_OBJECT_START(FieldDescriptor)
-  const upb_fielddef* fielddef;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(FieldDescriptor, getName);
-PHP_METHOD(FieldDescriptor, getNumber);
-PHP_METHOD(FieldDescriptor, getLabel);
-PHP_METHOD(FieldDescriptor, getType);
-PHP_METHOD(FieldDescriptor, isMap);
-PHP_METHOD(FieldDescriptor, getEnumType);
-PHP_METHOD(FieldDescriptor, getMessageType);
-
-extern zend_class_entry* field_descriptor_type;
-
-struct EnumDescriptorInternal {
-  const upb_enumdef* enumdef;
-  zend_class_entry* klass;  // begins as NULL
-  bool use_nested_submsg;
-  char* classname;
-};
-
-PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
-  EnumDescriptorInternal* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(EnumDescriptor, getValue);
-PHP_METHOD(EnumDescriptor, getValueCount);
-
-extern zend_class_entry* enum_descriptor_type;
-
-PHP_PROTO_WRAP_OBJECT_START(EnumValueDescriptor)
-  const char* name;
-  int32_t number;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(EnumValueDescriptor, getName);
-PHP_METHOD(EnumValueDescriptor, getNumber);
-
-extern zend_class_entry* enum_value_descriptor_type;
-
-// -----------------------------------------------------------------------------
-// Message class creation.
-// -----------------------------------------------------------------------------
-
-void* message_data(MessageHeader* msg);
-void custom_data_init(const zend_class_entry* ce,
-                      MessageHeader* msg PHP_PROTO_TSRMLS_DC);
-
-extern zend_class_entry* message_type;
-extern zend_object_handlers* message_handlers;
-
-// -----------------------------------------------------------------------------
-// Message layout / storage.
-// -----------------------------------------------------------------------------
-
-/*
- * In c extension, each protobuf message is a zval instance. The zval instance
- * is like union, which can be used to store int, string, zend_object_value and
- * etc. For protobuf message, the zval instance is used to store the
- * zend_object_value.
- *
- * The zend_object_value is composed of handlers and a handle to look up the
- * actual stored data. The handlers are pointers to functions, e.g., read,
- * write, and etc, to access properties.
- *
- * The actual data of protobuf messages is stored as MessageHeader in zend
- * engine's central repository. Each MessageHeader instance is composed of a
- * zend_object, a Descriptor instance and the real message data.
- *
- * For the reason that PHP's native types may not be large enough to store
- * protobuf message's field (e.g., int64), all message's data is stored in
- * custom memory layout and is indexed by the Descriptor instance.
- *
- * The zend_object contains the zend class entry and the properties table. The
- * zend class entry contains all information about protobuf message's
- * corresponding PHP class. The most useful information is the offset table of
- * properties. Because read access to properties requires returning zval
- * instance, we need to convert data from the custom layout to zval instance.
- * Instead of creating zval instance for every read access, we use the zval
- * instances in the properties table in the zend_object as cache.  When
- * accessing properties, the offset is needed to find the zval property in
- * zend_object's properties table. These properties will be updated using the
- * data from custom memory layout only when reading these properties.
- *
- * zval
- * |-zend_object_value obj
- *   |-zend_object_handlers* handlers -> |-read_property_handler
- *   |                                   |-write_property_handler
- *   |                              ++++++++++++++++++++++
- *   |-zend_object_handle handle -> + central repository +
- *                                  ++++++++++++++++++++++
- *  MessageHeader <-----------------|
- *  |-zend_object std
- *  | |-class_entry* ce -> class_entry
- *  | |                    |-HashTable properties_table (name->offset)
- *  | |-zval** properties_table <------------------------------|
- *  |                         |------> zval* property(cache)
- *  |-Descriptor* desc (name->offset)
- *  |-void** data <-----------|
- *           |-----------------------> void* property(data)
- *
- */
-
-#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
-
-struct MessageField {
-  size_t offset;
-  int cache_index;  // Each field except oneof field has a zval cache to avoid
-                    // multiple creation when being accessed.
-  size_t case_offset;   // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
-};
-
-struct MessageLayout {
-  const upb_msgdef* msgdef;
-  void* empty_template;  // Can memcpy() onto a layout to clear it.
-  MessageField* fields;
-  size_t size;
-};
-
-PHP_PROTO_WRAP_OBJECT_START(MessageHeader)
-  void* data;  // Point to the real message data.
-               // Place needs to be consistent with map_parse_frame_data_t.
-  DescriptorInternal* descriptor;  // Kept alive by self.class.descriptor
-                                   // reference.
-PHP_PROTO_WRAP_OBJECT_END
-
-MessageLayout* create_layout(const upb_msgdef* msgdef);
-void layout_init(MessageLayout* layout, void* storage,
-                 zend_object* object PHP_PROTO_TSRMLS_DC);
-zval* layout_get(MessageLayout* layout, MessageHeader* header,
-                 const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC);
-void layout_set(MessageLayout* layout, MessageHeader* header,
-                const upb_fielddef* field, zval* val TSRMLS_DC);
-void layout_merge(MessageLayout* layout, MessageHeader* from,
-                  MessageHeader* to TSRMLS_DC);
-const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
-                                  const upb_oneofdef* oneof TSRMLS_DC);
-void free_layout(MessageLayout* layout);
-uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
-                          const upb_fielddef* field);
-void* slot_memory(MessageLayout* layout, const void* storage,
-                  const upb_fielddef* field);
-
-PHP_METHOD(Message, clear);
-PHP_METHOD(Message, mergeFrom);
-PHP_METHOD(Message, readWrapperValue);
-PHP_METHOD(Message, writeWrapperValue);
-PHP_METHOD(Message, readOneof);
-PHP_METHOD(Message, writeOneof);
-PHP_METHOD(Message, whichOneof);
-PHP_METHOD(Message, __construct);
-
-// -----------------------------------------------------------------------------
-// Encode / Decode.
-// -----------------------------------------------------------------------------
-
-// Maximum depth allowed during encoding, to avoid stack overflows due to
-// cycles.
-#define ENCODE_MAX_NESTING 63
-
-// Constructs the upb decoder method for parsing messages of this type.
-// This is called from the message class creation code.
-const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
-                                                     const void *owner);
-void serialize_to_string(zval* val, zval* return_value TSRMLS_DC);
-void merge_from_string(const char* data, int data_len, DescriptorInternal* desc,
-                       MessageHeader* msg);
-
-PHP_METHOD(Message, serializeToString);
-PHP_METHOD(Message, mergeFromString);
-PHP_METHOD(Message, serializeToJsonString);
-PHP_METHOD(Message, mergeFromJsonString);
-PHP_METHOD(Message, discardUnknownFields);
-
-// -----------------------------------------------------------------------------
-// Type check / conversion.
-// -----------------------------------------------------------------------------
-
-bool protobuf_convert_to_int32(zval* from, int32_t* to);
-bool protobuf_convert_to_uint32(zval* from, uint32_t* to);
-bool protobuf_convert_to_int64(zval* from, int64_t* to);
-bool protobuf_convert_to_uint64(zval* from, uint64_t* to);
-bool protobuf_convert_to_float(zval* from, float* to);
-bool protobuf_convert_to_double(zval* from, double* to);
-bool protobuf_convert_to_bool(zval* from, int8_t* to);
-bool protobuf_convert_to_string(zval* from);
-
-void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type,
-                          zval* val, zval* return_value);
-void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type,
-                     PHP_PROTO_LONG value_type, zval* val, zval* return_value);
-
-PHP_METHOD(Util, checkInt32);
-PHP_METHOD(Util, checkUint32);
-PHP_METHOD(Util, checkInt64);
-PHP_METHOD(Util, checkUint64);
-PHP_METHOD(Util, checkEnum);
-PHP_METHOD(Util, checkFloat);
-PHP_METHOD(Util, checkDouble);
-PHP_METHOD(Util, checkBool);
-PHP_METHOD(Util, checkString);
-PHP_METHOD(Util, checkBytes);
-PHP_METHOD(Util, checkMessage);
-PHP_METHOD(Util, checkMapField);
-PHP_METHOD(Util, checkRepeatedField);
-
-// -----------------------------------------------------------------------------
-// Native slot storage abstraction.
-// -----------------------------------------------------------------------------
-
-#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
-
-size_t native_slot_size(upb_fieldtype_t type);
-bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
-                     void* memory, zval* value TSRMLS_DC);
-// String/Message is stored differently in array/map from normal message fields.
-// So we need to make a special method to handle that.
-bool native_slot_set_by_array(upb_fieldtype_t type,
-                              const zend_class_entry* klass, void* memory,
-                              zval* value TSRMLS_DC);
-bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass,
-                            void* memory, zval* value TSRMLS_DC);
-void native_slot_init(upb_fieldtype_t type, void* memory, CACHED_VALUE* cache);
-// For each property, in order to avoid conversion between the zval object and
-// the actual data type during parsing/serialization, the containing message
-// object use the custom memory layout to store the actual data type for each
-// property inside of it.  To access a property from php code, the property
-// needs to be converted to a zval object. The message object is not responsible
-// for providing such a zval object. Instead the caller needs to provide one
-// (cache) and update it with the actual data (memory).
-void native_slot_get(upb_fieldtype_t type, const void* memory,
-                     CACHED_VALUE* cache TSRMLS_DC);
-// String/Message is stored differently in array/map from normal message fields.
-// So we need to make a special method to handle that.
-void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
-                     CACHED_VALUE* cache TSRMLS_DC);
-void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory,
-                                int length, CACHED_VALUE* cache TSRMLS_DC);
-void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory,
-                                  CACHED_VALUE* cache TSRMLS_DC);
-void native_slot_get_default(upb_fieldtype_t type,
-                             CACHED_VALUE* cache TSRMLS_DC);
-
-// -----------------------------------------------------------------------------
-// Map Field.
-// -----------------------------------------------------------------------------
-
-extern zend_object_handlers* map_field_handlers;
-extern zend_object_handlers* map_field_iter_handlers;
-
-PHP_PROTO_WRAP_OBJECT_START(Map)
-  upb_fieldtype_t key_type;
-  upb_fieldtype_t value_type;
-  const zend_class_entry* msg_ce;  // class entry for value message
-  upb_strtable table;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_PROTO_WRAP_OBJECT_START(MapIter)
-  Map* self;
-  upb_strtable_iter it;
-PHP_PROTO_WRAP_OBJECT_END
-
-void map_begin(zval* self, MapIter* iter TSRMLS_DC);
-void map_next(MapIter* iter);
-bool map_done(MapIter* iter);
-const char* map_iter_key(MapIter* iter, int* len);
-upb_value map_iter_value(MapIter* iter, int* len);
-
-// These operate on a map-entry msgdef.
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
-
-void map_field_ensure_created(const upb_fielddef *field,
-                              CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC);
-void map_field_create_with_field(const zend_class_entry* ce,
-                                 const upb_fielddef* field,
-                                 CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
-void map_field_create_with_type(const zend_class_entry* ce,
-                                upb_fieldtype_t key_type,
-                                upb_fieldtype_t value_type,
-                                const zend_class_entry* msg_ce,
-                                CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
-void* upb_value_memory(upb_value* v);
-
-#define MAP_KEY_FIELD 1
-#define MAP_VALUE_FIELD 2
-
-// These operate on a map field (i.e., a repeated field of submessages whose
-// submessage type is a map-entry msgdef).
-bool is_map_field(const upb_fielddef* field);
-const upb_fielddef* map_field_key(const upb_fielddef* field);
-const upb_fielddef* map_field_value(const upb_fielddef* field);
-
-bool map_index_set(Map *intern, const char* keyval, int length, upb_value v);
-
-PHP_METHOD(MapField, __construct);
-PHP_METHOD(MapField, offsetExists);
-PHP_METHOD(MapField, offsetGet);
-PHP_METHOD(MapField, offsetSet);
-PHP_METHOD(MapField, offsetUnset);
-PHP_METHOD(MapField, count);
-PHP_METHOD(MapField, getIterator);
-
-PHP_METHOD(MapFieldIter, rewind);
-PHP_METHOD(MapFieldIter, current);
-PHP_METHOD(MapFieldIter, key);
-PHP_METHOD(MapFieldIter, next);
-PHP_METHOD(MapFieldIter, valid);
-
-// -----------------------------------------------------------------------------
-// Repeated Field.
-// -----------------------------------------------------------------------------
-
-extern zend_object_handlers* repeated_field_handlers;
-extern zend_object_handlers* repeated_field_iter_handlers;
-
-PHP_PROTO_WRAP_OBJECT_START(RepeatedField)
-#if PHP_MAJOR_VERSION < 7
-  zval* array;
-#else
-  zval array;
-#endif
-  upb_fieldtype_t type;
-  const zend_class_entry* msg_ce;  // class entry for containing message
-                                   // (for message field only).
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_PROTO_WRAP_OBJECT_START(RepeatedFieldIter)
-  RepeatedField* repeated_field;
-  long position;
-PHP_PROTO_WRAP_OBJECT_END
-
-void repeated_field_ensure_created(
-    const upb_fielddef *field,
-    CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC);
-void repeated_field_create_with_field(
-    zend_class_entry* ce, const upb_fielddef* field,
-    CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC);
-void repeated_field_create_with_type(
-    zend_class_entry* ce, upb_fieldtype_t type, const zend_class_entry* msg_ce,
-    CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC);
-// Return the element at the index position from the repeated field. There is
-// not restriction on the type of stored elements.
-void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC);
-// Add the element to the end of the repeated field. There is not restriction on
-// the type of stored elements.
-void repeated_field_push_native(RepeatedField *intern, void *value);
-
-PHP_METHOD(RepeatedField, __construct);
-PHP_METHOD(RepeatedField, append);
-PHP_METHOD(RepeatedField, offsetExists);
-PHP_METHOD(RepeatedField, offsetGet);
-PHP_METHOD(RepeatedField, offsetSet);
-PHP_METHOD(RepeatedField, offsetUnset);
-PHP_METHOD(RepeatedField, count);
-PHP_METHOD(RepeatedField, getIterator);
-
-PHP_METHOD(RepeatedFieldIter, rewind);
-PHP_METHOD(RepeatedFieldIter, current);
-PHP_METHOD(RepeatedFieldIter, key);
-PHP_METHOD(RepeatedFieldIter, next);
-PHP_METHOD(RepeatedFieldIter, valid);
-
-// -----------------------------------------------------------------------------
-// Oneof Field.
-// -----------------------------------------------------------------------------
-
-PHP_PROTO_WRAP_OBJECT_START(Oneof)
-  const upb_oneofdef* oneofdef;
-  int index;    // Index of field in oneof. -1 if not set.
-  char value[NATIVE_SLOT_MAX_SIZE];
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(Oneof, getName);
-PHP_METHOD(Oneof, getField);
-PHP_METHOD(Oneof, getFieldCount);
-
-extern zend_class_entry* oneof_descriptor_type;
-
-// Oneof case slot value to indicate that no oneof case is set. The value `0` is
-// safe because field numbers are used as case identifiers, and no field can
-// have a number of 0.
-#define ONEOF_CASE_NONE 0
-
-// -----------------------------------------------------------------------------
-// Well Known Type.
-// -----------------------------------------------------------------------------
-
-extern bool is_inited_file_any;
-extern bool is_inited_file_api;
-extern bool is_inited_file_duration;
-extern bool is_inited_file_field_mask;
-extern bool is_inited_file_empty;
-extern bool is_inited_file_source_context;
-extern bool is_inited_file_struct;
-extern bool is_inited_file_timestamp;
-extern bool is_inited_file_type;
-extern bool is_inited_file_wrappers;
-
-PHP_METHOD(GPBMetadata_Any, initOnce);
-PHP_METHOD(GPBMetadata_Api, initOnce);
-PHP_METHOD(GPBMetadata_Duration, initOnce);
-PHP_METHOD(GPBMetadata_FieldMask, initOnce);
-PHP_METHOD(GPBMetadata_Empty, initOnce);
-PHP_METHOD(GPBMetadata_SourceContext, initOnce);
-PHP_METHOD(GPBMetadata_Struct, initOnce);
-PHP_METHOD(GPBMetadata_Timestamp, initOnce);
-PHP_METHOD(GPBMetadata_Type, initOnce);
-PHP_METHOD(GPBMetadata_Wrappers, initOnce);
-
-PHP_METHOD(Any, __construct);
-PHP_METHOD(Any, getTypeUrl);
-PHP_METHOD(Any, setTypeUrl);
-PHP_METHOD(Any, getValue);
-PHP_METHOD(Any, setValue);
-PHP_METHOD(Any, unpack);
-PHP_METHOD(Any, pack);
-PHP_METHOD(Any, is);
-
-PHP_METHOD(Duration, __construct);
-PHP_METHOD(Duration, getSeconds);
-PHP_METHOD(Duration, setSeconds);
-PHP_METHOD(Duration, getNanos);
-PHP_METHOD(Duration, setNanos);
-
-PHP_METHOD(Timestamp, __construct);
-PHP_METHOD(Timestamp, fromDateTime);
-PHP_METHOD(Timestamp, toDateTime);
-PHP_METHOD(Timestamp, getSeconds);
-PHP_METHOD(Timestamp, setSeconds);
-PHP_METHOD(Timestamp, getNanos);
-PHP_METHOD(Timestamp, setNanos);
-
-PHP_METHOD(Api, __construct);
-PHP_METHOD(Api, getName);
-PHP_METHOD(Api, setName);
-PHP_METHOD(Api, getMethods);
-PHP_METHOD(Api, setMethods);
-PHP_METHOD(Api, getOptions);
-PHP_METHOD(Api, setOptions);
-PHP_METHOD(Api, getVersion);
-PHP_METHOD(Api, setVersion);
-PHP_METHOD(Api, getSourceContext);
-PHP_METHOD(Api, setSourceContext);
-PHP_METHOD(Api, getMixins);
-PHP_METHOD(Api, setMixins);
-PHP_METHOD(Api, getSyntax);
-PHP_METHOD(Api, setSyntax);
-
-PHP_METHOD(BoolValue, __construct);
-PHP_METHOD(BoolValue, getValue);
-PHP_METHOD(BoolValue, setValue);
-
-PHP_METHOD(BytesValue, __construct);
-PHP_METHOD(BytesValue, getValue);
-PHP_METHOD(BytesValue, setValue);
-
-PHP_METHOD(DoubleValue, __construct);
-PHP_METHOD(DoubleValue, getValue);
-PHP_METHOD(DoubleValue, setValue);
-
-PHP_METHOD(Enum, __construct);
-PHP_METHOD(Enum, getName);
-PHP_METHOD(Enum, setName);
-PHP_METHOD(Enum, getEnumvalue);
-PHP_METHOD(Enum, setEnumvalue);
-PHP_METHOD(Enum, getOptions);
-PHP_METHOD(Enum, setOptions);
-PHP_METHOD(Enum, getSourceContext);
-PHP_METHOD(Enum, setSourceContext);
-PHP_METHOD(Enum, getSyntax);
-PHP_METHOD(Enum, setSyntax);
-
-PHP_METHOD(EnumValue, __construct);
-PHP_METHOD(EnumValue, getName);
-PHP_METHOD(EnumValue, setName);
-PHP_METHOD(EnumValue, getNumber);
-PHP_METHOD(EnumValue, setNumber);
-PHP_METHOD(EnumValue, getOptions);
-PHP_METHOD(EnumValue, setOptions);
-
-PHP_METHOD(FieldMask, __construct);
-PHP_METHOD(FieldMask, getPaths);
-PHP_METHOD(FieldMask, setPaths);
-
-PHP_METHOD(Field, __construct);
-PHP_METHOD(Field, getKind);
-PHP_METHOD(Field, setKind);
-PHP_METHOD(Field, getCardinality);
-PHP_METHOD(Field, setCardinality);
-PHP_METHOD(Field, getNumber);
-PHP_METHOD(Field, setNumber);
-PHP_METHOD(Field, getName);
-PHP_METHOD(Field, setName);
-PHP_METHOD(Field, getTypeUrl);
-PHP_METHOD(Field, setTypeUrl);
-PHP_METHOD(Field, getOneofIndex);
-PHP_METHOD(Field, setOneofIndex);
-PHP_METHOD(Field, getPacked);
-PHP_METHOD(Field, setPacked);
-PHP_METHOD(Field, getOptions);
-PHP_METHOD(Field, setOptions);
-PHP_METHOD(Field, getJsonName);
-PHP_METHOD(Field, setJsonName);
-PHP_METHOD(Field, getDefaultValue);
-PHP_METHOD(Field, setDefaultValue);
-
-PHP_METHOD(Field_Cardinality, name);
-PHP_METHOD(Field_Cardinality, value);
-
-PHP_METHOD(Field_Kind, name);
-PHP_METHOD(Field_Kind, value);
-
-PHP_METHOD(FloatValue, __construct);
-PHP_METHOD(FloatValue, getValue);
-PHP_METHOD(FloatValue, setValue);
-
-PHP_METHOD(GPBEmpty, __construct);
-
-PHP_METHOD(Int32Value, __construct);
-PHP_METHOD(Int32Value, getValue);
-PHP_METHOD(Int32Value, setValue);
-
-PHP_METHOD(Int64Value, __construct);
-PHP_METHOD(Int64Value, getValue);
-PHP_METHOD(Int64Value, setValue);
-
-PHP_METHOD(ListValue, __construct);
-PHP_METHOD(ListValue, getValues);
-PHP_METHOD(ListValue, setValues);
-
-PHP_METHOD(Method, __construct);
-PHP_METHOD(Method, getName);
-PHP_METHOD(Method, setName);
-PHP_METHOD(Method, getRequestTypeUrl);
-PHP_METHOD(Method, setRequestTypeUrl);
-PHP_METHOD(Method, getRequestStreaming);
-PHP_METHOD(Method, setRequestStreaming);
-PHP_METHOD(Method, getResponseTypeUrl);
-PHP_METHOD(Method, setResponseTypeUrl);
-PHP_METHOD(Method, getResponseStreaming);
-PHP_METHOD(Method, setResponseStreaming);
-PHP_METHOD(Method, getOptions);
-PHP_METHOD(Method, setOptions);
-PHP_METHOD(Method, getSyntax);
-PHP_METHOD(Method, setSyntax);
-
-PHP_METHOD(Mixin, __construct);
-PHP_METHOD(Mixin, getName);
-PHP_METHOD(Mixin, setName);
-PHP_METHOD(Mixin, getRoot);
-PHP_METHOD(Mixin, setRoot);
-
-PHP_METHOD(NullValue, name);
-PHP_METHOD(NullValue, value);
-
-PHP_METHOD(Option, __construct);
-PHP_METHOD(Option, getName);
-PHP_METHOD(Option, setName);
-PHP_METHOD(Option, getValue);
-PHP_METHOD(Option, setValue);
-
-PHP_METHOD(SourceContext, __construct);
-PHP_METHOD(SourceContext, getFileName);
-PHP_METHOD(SourceContext, setFileName);
-
-PHP_METHOD(StringValue, __construct);
-PHP_METHOD(StringValue, getValue);
-PHP_METHOD(StringValue, setValue);
-
-PHP_METHOD(Struct, __construct);
-PHP_METHOD(Struct, getFields);
-PHP_METHOD(Struct, setFields);
-
-PHP_METHOD(Syntax, name);
-PHP_METHOD(Syntax, value);
-
-PHP_METHOD(Type, __construct);
-PHP_METHOD(Type, getName);
-PHP_METHOD(Type, setName);
-PHP_METHOD(Type, getFields);
-PHP_METHOD(Type, setFields);
-PHP_METHOD(Type, getOneofs);
-PHP_METHOD(Type, setOneofs);
-PHP_METHOD(Type, getOptions);
-PHP_METHOD(Type, setOptions);
-PHP_METHOD(Type, getSourceContext);
-PHP_METHOD(Type, setSourceContext);
-PHP_METHOD(Type, getSyntax);
-PHP_METHOD(Type, setSyntax);
-
-PHP_METHOD(UInt32Value, __construct);
-PHP_METHOD(UInt32Value, getValue);
-PHP_METHOD(UInt32Value, setValue);
-
-PHP_METHOD(UInt64Value, __construct);
-PHP_METHOD(UInt64Value, getValue);
-PHP_METHOD(UInt64Value, setValue);
-
-PHP_METHOD(Value, __construct);
-PHP_METHOD(Value, getNullValue);
-PHP_METHOD(Value, setNullValue);
-PHP_METHOD(Value, getNumberValue);
-PHP_METHOD(Value, setNumberValue);
-PHP_METHOD(Value, getStringValue);
-PHP_METHOD(Value, setStringValue);
-PHP_METHOD(Value, getBoolValue);
-PHP_METHOD(Value, setBoolValue);
-PHP_METHOD(Value, getStructValue);
-PHP_METHOD(Value, setStructValue);
-PHP_METHOD(Value, getListValue);
-PHP_METHOD(Value, setListValue);
-PHP_METHOD(Value, getKind);
-
-extern zend_class_entry* any_type;
-extern zend_class_entry* api_type;
-extern zend_class_entry* bool_value_type;
-extern zend_class_entry* bytes_value_type;
-extern zend_class_entry* double_value_type;
-extern zend_class_entry* duration_type;
-extern zend_class_entry* empty_type;
-extern zend_class_entry* enum_type;
-extern zend_class_entry* enum_value_type;
-extern zend_class_entry* field_cardinality_type;
-extern zend_class_entry* field_kind_type;
-extern zend_class_entry* field_mask_type;
-extern zend_class_entry* field_type;
-extern zend_class_entry* float_value_type;
-extern zend_class_entry* int32_value_type;
-extern zend_class_entry* int64_value_type;
-extern zend_class_entry* list_value_type;
-extern zend_class_entry* method_type;
-extern zend_class_entry* mixin_type;
-extern zend_class_entry* null_value_type;
-extern zend_class_entry* option_type;
-extern zend_class_entry* source_context_type;
-extern zend_class_entry* string_value_type;
-extern zend_class_entry* struct_type;
-extern zend_class_entry* syntax_type;
-extern zend_class_entry* timestamp_type;
-extern zend_class_entry* type_type;
-extern zend_class_entry* uint32_value_type;
-extern zend_class_entry* uint64_value_type;
-extern zend_class_entry* value_type;
-
-// -----------------------------------------------------------------------------
-// Upb.
-// -----------------------------------------------------------------------------
-
-upb_fieldtype_t to_fieldtype(upb_descriptortype_t type);
-const zend_class_entry* field_type_class(
-    const upb_fielddef* field PHP_PROTO_TSRMLS_DC);
-void stringsink_uninit_opaque(void *sink);
-
-typedef struct {
-  upb_byteshandler handler;
-  upb_bytessink sink;
-  char *ptr;
-  size_t len, size;
-} stringsink;
-
-void stringsink_init(stringsink *sink);
-void stringsink_uninit(stringsink *sink);
-size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
-                         size_t len, const upb_bufhandle *handle);
-
-// -----------------------------------------------------------------------------
-// Utilities.
-// -----------------------------------------------------------------------------
-
-// Memory management
-#define SYS_MALLOC(class_name) (class_name*) malloc(sizeof(class_name))
-#define SYS_MALLOC_N(class_name, n) (class_name*) malloc(sizeof(class_name) * n)
-#define SYS_FREE(ptr) free(ptr)
-#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
-#define PEMALLOC(class_name, persistent) (class_name*) pemalloc(sizeof(class_name), persistent)
-#define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
-#define FREE(object) efree(object)
-#define PEFREE(object) pefree(object, 1)
-
-// Find corresponding zval property for the field.
-CACHED_VALUE* find_zval_property(MessageHeader* msg, const upb_fielddef* field);
-
-// String argument.
-#define STR(str) (str), strlen(str)
-
-// Zend Value
-#if PHP_MAJOR_VERSION < 7
-#define Z_OBJ_P(zval_p)                                       \
-  ((zend_object*)(EG(objects_store)                           \
-                      .object_buckets[Z_OBJ_HANDLE_P(zval_p)] \
-                      .bucket.obj.object))
+#define PBPHP_ASSERT(x) \
+  do {                  \
+  } while (false && (x))
 #endif
 
-// Message handler
-static inline zval* php_proto_message_read_property(
-    zval* msg, zval* member PHP_PROTO_TSRMLS_DC) {
-#if PHP_MAJOR_VERSION < 7
-  return message_handlers->read_property(msg, member, BP_VAR_R,
-                                         NULL PHP_PROTO_TSRMLS_CC);
-#else
-  return message_handlers->read_property(msg, member, BP_VAR_R, NULL,
-                                         NULL PHP_PROTO_TSRMLS_CC);
-#endif
-}
-
-// Reserved name
-bool is_reserved_name(const char* name);
-bool is_valid_constant_name(const char* name);
-
-// For lazy wrapper
-bool is_wrapper_msg(const upb_msgdef* m);
-
-#endif  // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
+#endif  // PHP_PROTOBUF_H_
diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c
deleted file mode 100644
index fec7335..0000000
--- a/php/ext/google/protobuf/storage.c
+++ /dev/null
@@ -1,1180 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <stdint.h>
-#include <protobuf.h>
-#include <Zend/zend.h>
-
-#include "utf8.h"
-
-// -----------------------------------------------------------------------------
-// Native slot storage.
-// -----------------------------------------------------------------------------
-
-#define DEREF(memory, type) *(type*)(memory)
-
-size_t native_slot_size(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_FLOAT: return 4;
-    case UPB_TYPE_DOUBLE: return 8;
-    case UPB_TYPE_BOOL: return 1;
-    case UPB_TYPE_STRING: return sizeof(void*);
-    case UPB_TYPE_BYTES: return sizeof(void*);
-    case UPB_TYPE_MESSAGE: return sizeof(void*);
-    case UPB_TYPE_ENUM: return 4;
-    case UPB_TYPE_INT32: return 4;
-    case UPB_TYPE_INT64: return 8;
-    case UPB_TYPE_UINT32: return 4;
-    case UPB_TYPE_UINT64: return 8;
-    default: return 0;
-  }
-}
-
-static bool native_slot_is_default(upb_fieldtype_t type, const void* memory) {
-  switch (type) {
-#define CASE_TYPE(upb_type, c_type)    \
-  case UPB_TYPE_##upb_type: {          \
-    return DEREF(memory, c_type) == 0; \
-  }
-    CASE_TYPE(INT32,  int32_t )
-    CASE_TYPE(UINT32, uint32_t)
-    CASE_TYPE(ENUM,   int32_t )
-    CASE_TYPE(INT64,  int64_t )
-    CASE_TYPE(UINT64, uint64_t)
-    CASE_TYPE(FLOAT,  float   )
-    CASE_TYPE(DOUBLE, double  )
-    CASE_TYPE(BOOL,   int8_t  )
-
-#undef CASE_TYPE
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      return Z_STRLEN_P(CACHED_PTR_TO_ZVAL_PTR(memory)) == 0;
-    case UPB_TYPE_MESSAGE:
-      return Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(memory)) == IS_NULL;
-    default: return false;
-  }
-}
-
-bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
-                     void* memory, zval* value PHP_PROTO_TSRMLS_DC) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      if (!protobuf_convert_to_string(value)) {
-        return false;
-      }
-      if (type == UPB_TYPE_STRING &&
-          !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
-        zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
-        return false;
-      }
-
-      zval* cached_zval = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
-      if (EXPECTED(cached_zval != NULL)) {
-#if PHP_MAJOR_VERSION < 7
-        REPLACE_ZVAL_VALUE((zval**)memory, value, 1);
-#elif PHP_VERSION_ID < 70400
-        zend_assign_to_variable(cached_zval, value, IS_CV);
-#else
-        zend_assign_to_variable(cached_zval, value, IS_CV, 0);
-#endif
-      }
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_NULL) {
-        zend_error(E_USER_ERROR, "Given value is not message.");
-        return false;
-      }
-      if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
-        zend_error(E_USER_ERROR, "Given message does not have correct class.");
-        return false;
-      }
-
-#if PHP_MAJOR_VERSION < 7
-      REPLACE_ZVAL_VALUE((CACHED_VALUE*)memory, value, 1);
-#else
-      zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
-      if (EXPECTED(property_ptr != value)) {
-        php_proto_zval_ptr_dtor(property_ptr);
-      }
-
-      ZVAL_ZVAL(property_ptr, value, 1, 0);
-#endif
-
-      break;
-    }
-
-#define CASE_TYPE(upb_type, type, c_type, php_type)              \
-  case UPB_TYPE_##upb_type: {                                    \
-    c_type type##_value;                                         \
-    if (protobuf_convert_to_##type(value, &type##_value)) {      \
-      DEREF(memory, c_type) = type##_value;                      \
-    }                                                            \
-    break;                                                       \
-  }
-      CASE_TYPE(INT32,  int32,  int32_t,  LONG)
-      CASE_TYPE(UINT32, uint32, uint32_t, LONG)
-      CASE_TYPE(ENUM,   int32,  int32_t,  LONG)
-      CASE_TYPE(INT64,  int64,  int64_t,  LONG)
-      CASE_TYPE(UINT64, uint64, uint64_t, LONG)
-      CASE_TYPE(FLOAT,  float,  float,    DOUBLE)
-      CASE_TYPE(DOUBLE, double, double,   DOUBLE)
-      CASE_TYPE(BOOL,   bool,   int8_t,   BOOL)
-
-#undef CASE_TYPE
-
-    default:
-      break;
-  }
-
-  return true;
-}
-
-bool native_slot_set_by_array(upb_fieldtype_t type,
-                              const zend_class_entry* klass, void* memory,
-                              zval* value TSRMLS_DC) {
-#if PHP_MAJOR_VERSION >= 7
-  if (Z_ISREF_P(value)) {
-    ZVAL_DEREF(value);
-  }
-#endif
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      if (!protobuf_convert_to_string(value)) {
-        return false;
-      }
-      if (type == UPB_TYPE_STRING &&
-          !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
-        zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
-        return false;
-      }
-
-      // Handles repeated/map string field. Memory provided by
-      // RepeatedField/Map is not initialized.
-#if PHP_MAJOR_VERSION < 7
-      MAKE_STD_ZVAL(DEREF(memory, zval*));
-      PHP_PROTO_ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value),
-                             Z_STRLEN_P(value), 1);
-#else
-      *(zend_string**)memory =
-          zend_string_init(Z_STRVAL_P(value), Z_STRLEN_P(value), 0);
-#endif
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (Z_TYPE_P(value) != IS_OBJECT) {
-        zend_error(E_USER_ERROR, "Given value is not message.");
-        return false;
-      }
-      if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
-        zend_error(E_USER_ERROR, "Given message does not have correct class.");
-        return false;
-      }
-#if PHP_MAJOR_VERSION < 7
-      if (EXPECTED(DEREF(memory, zval*) != value)) {
-        DEREF(memory, zval*) = value;
-        Z_ADDREF_P(value);
-      }
-#else
-      DEREF(memory, zval*) = value;
-      GC_ADDREF(Z_OBJ_P(value));
-#endif
-      break;
-    }
-    default:
-      return native_slot_set(type, klass, memory, value TSRMLS_CC);
-  }
-  return true;
-}
-
-bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass,
-                            void* memory, zval* value TSRMLS_DC) {
-#if PHP_MAJOR_VERSION >= 7
-  if (Z_ISREF_P(value)) {
-    ZVAL_DEREF(value);
-  }
-#endif
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      if (!protobuf_convert_to_string(value)) {
-        return false;
-      }
-      if (type == UPB_TYPE_STRING &&
-          !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
-        zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
-        return false;
-      }
-
-      // Handles repeated/map string field. Memory provided by
-      // RepeatedField/Map is not initialized.
-#if PHP_MAJOR_VERSION < 7
-      MAKE_STD_ZVAL(DEREF(memory, zval*));
-      PHP_PROTO_ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value),
-                             Z_STRLEN_P(value), 1);
-#else
-      *(zend_string**)memory =
-          zend_string_init(Z_STRVAL_P(value), Z_STRLEN_P(value), 0);
-#endif
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (Z_TYPE_P(value) != IS_OBJECT) {
-        zend_error(E_USER_ERROR, "Given value is not message.");
-        return false;
-      }
-      if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
-        zend_error(E_USER_ERROR, "Given message does not have correct class.");
-        return false;
-      }
-#if PHP_MAJOR_VERSION < 7
-      if (EXPECTED(DEREF(memory, zval*) != value)) {
-        DEREF(memory, zval*) = value;
-        Z_ADDREF_P(value);
-      }
-#else
-      DEREF(memory, zend_object*) = Z_OBJ_P(value);
-      GC_ADDREF(Z_OBJ_P(value));
-#endif
-      break;
-    }
-    default:
-      return native_slot_set(type, klass, memory, value TSRMLS_CC);
-  }
-  return true;
-}
-
-void native_slot_init(upb_fieldtype_t type, void* memory, CACHED_VALUE* cache) {
-  switch (type) {
-    case UPB_TYPE_FLOAT:
-      DEREF(memory, float) = 0.0;
-      break;
-    case UPB_TYPE_DOUBLE:
-      DEREF(memory, double) = 0.0;
-      break;
-    case UPB_TYPE_BOOL:
-      DEREF(memory, int8_t) = 0;
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_MESSAGE:
-      DEREF(memory, CACHED_VALUE*) = cache;
-      break;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-      DEREF(memory, int32_t) = 0;
-      break;
-    case UPB_TYPE_INT64:
-      DEREF(memory, int64_t) = 0;
-      break;
-    case UPB_TYPE_UINT32:
-      DEREF(memory, uint32_t) = 0;
-      break;
-    case UPB_TYPE_UINT64:
-      DEREF(memory, uint64_t) = 0;
-      break;
-    default:
-      break;
-  }
-}
-
-void native_slot_get(upb_fieldtype_t type, const void* memory,
-                     CACHED_VALUE* cache TSRMLS_DC) {
-  switch (type) {
-#define CASE(upb_type, php_type, c_type)                                   \
-  case UPB_TYPE_##upb_type:                                                \
-    PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);                             \
-    ZVAL_##php_type(CACHED_PTR_TO_ZVAL_PTR(cache), DEREF(memory, c_type)); \
-    return;
-
-    CASE(FLOAT, DOUBLE, float)
-    CASE(DOUBLE, DOUBLE, double)
-    CASE(BOOL, BOOL, int8_t)
-    CASE(INT32, LONG, int32_t)
-    CASE(ENUM, LONG, uint32_t)
-
-#undef CASE
-
-#if SIZEOF_LONG == 4
-#define CASE(upb_type, c_type)                                       \
-  case UPB_TYPE_##upb_type: {                                        \
-    PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);                       \
-    char buffer[MAX_LENGTH_OF_INT64];                                \
-    sprintf(buffer, "%lld", DEREF(memory, c_type));                  \
-    PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), buffer, 1); \
-    return;                                                          \
-  }
-#else
-#define CASE(upb_type, c_type)                                       \
-  case UPB_TYPE_##upb_type: {                                        \
-    PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);                       \
-    ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), DEREF(memory, c_type)); \
-    return;                                                          \
-  }
-#endif
-CASE(UINT64, uint64_t)
-CASE(INT64,  int64_t)
-#undef CASE
-
-    case UPB_TYPE_UINT32: {
-      // Prepend bit-1 for negative numbers, so that uint32 value will be
-      // consistent on both 32-bit and 64-bit architectures.
-      PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
-      int value = DEREF(memory, int32_t);
-      if (sizeof(int) == 8) {
-        value |= (-((value >> 31) & 0x1) & 0xFFFFFFFF00000000);
-      }
-      ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), value);
-      return;
-    }
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      // For optional string/bytes/message fields, the cache is owned by the
-      // containing message and should have been updated during
-      // setting/decoding. However, oneof accessor call this function by
-      // providing the return value directly, which is not the same as the cache
-      // value.
-      zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
-      if (CACHED_PTR_TO_ZVAL_PTR(cache) != value) {
-        PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), Z_STRVAL_P(value),
-                               Z_STRLEN_P(value), 1);
-      }
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      // Same as above for string/bytes fields.
-      zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
-      if (CACHED_PTR_TO_ZVAL_PTR(cache) != value) {
-        ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
-      }
-      return;
-    }
-    default:
-      return;
-  }
-}
-
-void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
-                              CACHED_VALUE* cache TSRMLS_DC) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
-      zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
-      if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) {
-        PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache),
-                               Z_STRVAL_P(value), Z_STRLEN_P(value), 1);
-      }
-#else
-      ZVAL_NEW_STR(cache, zend_string_dup(*(zend_string**)memory, 0));
-#endif
-      return;
-    }
-    case UPB_TYPE_MESSAGE: {
-#if PHP_MAJOR_VERSION < 7
-      zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
-      if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) {
-        ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
-      }
-#else
-      ZVAL_COPY(CACHED_PTR_TO_ZVAL_PTR(cache), memory);
-#endif
-      return;
-    }
-    default:
-      native_slot_get(type, memory, cache TSRMLS_CC);
-  }
-}
-
-void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory,
-                                int length, CACHED_VALUE* cache TSRMLS_DC) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), memory, length, 1);
-      return;
-    }
-    default:
-      native_slot_get(type, memory, cache TSRMLS_CC);
-  }
-}
-
-void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory,
-                              CACHED_VALUE* cache TSRMLS_DC) {
-  switch (type) {
-    case UPB_TYPE_MESSAGE: {
-#if PHP_MAJOR_VERSION < 7
-      zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
-      if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) {
-        ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
-      }
-#else
-      GC_ADDREF(*(zend_object**)memory);
-      ZVAL_OBJ(cache, *(zend_object**)memory);
-#endif
-      return;
-    }
-    default:
-      native_slot_get_by_array(type, memory, cache TSRMLS_CC);
-  }
-}
-
-void native_slot_get_default(upb_fieldtype_t type,
-                             CACHED_VALUE* cache TSRMLS_DC) {
-  switch (type) {
-#define CASE(upb_type, php_type)                       \
-  case UPB_TYPE_##upb_type:                            \
-    PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);         \
-    ZVAL_##php_type(CACHED_PTR_TO_ZVAL_PTR(cache), 0); \
-    return;
-
-    CASE(FLOAT, DOUBLE)
-    CASE(DOUBLE, DOUBLE)
-    CASE(BOOL, BOOL)
-    CASE(INT32, LONG)
-    CASE(UINT32, LONG)
-    CASE(ENUM, LONG)
-
-#undef CASE
-
-#if SIZEOF_LONG == 4
-#define CASE(upb_type)                                            \
-  case UPB_TYPE_##upb_type: {                                     \
-    PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);                    \
-    PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), "0", 1); \
-    return;                                                       \
-  }
-#else
-#define CASE(upb_type)                           \
-  case UPB_TYPE_##upb_type: {                    \
-    PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);   \
-    ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), 0); \
-    return;                                      \
-  }
-#endif
-CASE(UINT64)
-CASE(INT64)
-#undef CASE
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
-      PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), "", 0, 1);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
-      ZVAL_NULL(CACHED_PTR_TO_ZVAL_PTR(cache));
-      return;
-    }
-    default:
-      return;
-  }
-}
-
-// -----------------------------------------------------------------------------
-// Map field utilities.
-// ----------------------------------------------------------------------------
-
-const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
-  const upb_msgdef* subdef;
-  if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
-      upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
-    return NULL;
-  }
-  subdef = upb_fielddef_msgsubdef(field);
-  return upb_msgdef_mapentry(subdef) ? subdef : NULL;
-}
-
-const upb_msgdef* map_entry_msgdef(const upb_fielddef* field) {
-  const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
-  assert(subdef);
-  return subdef;
-}
-
-bool is_map_field(const upb_fielddef* field) {
-  return tryget_map_entry_msgdef(field) != NULL;
-}
-
-const upb_fielddef* map_field_key(const upb_fielddef* field) {
-  const upb_msgdef* subdef = map_entry_msgdef(field);
-  return map_entry_key(subdef);
-}
-
-const upb_fielddef* map_field_value(const upb_fielddef* field) {
-  const upb_msgdef* subdef = map_entry_msgdef(field);
-  return map_entry_value(subdef);
-}
-
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
-  const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
-  assert(key_field != NULL);
-  return key_field;
-}
-
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
-  const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
-  assert(value_field != NULL);
-  return value_field;
-}
-
-const zend_class_entry* field_type_class(
-    const upb_fielddef* field PHP_PROTO_TSRMLS_DC) {
-  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-    DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
-    register_class(desc, false TSRMLS_CC);
-    return desc->klass;
-  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
-    EnumDescriptorInternal* desc =
-        get_enumdef_enumdesc(upb_fielddef_enumsubdef(field));
-    register_class(desc, false TSRMLS_CC);
-    return desc->klass;
-  }
-  return NULL;
-}
-
-// -----------------------------------------------------------------------------
-// Memory layout management.
-// -----------------------------------------------------------------------------
-
-static size_t align_up_to(size_t offset, size_t granularity) {
-  // Granularity must be a power of two.
-  return (offset + granularity - 1) & ~(granularity - 1);
-}
-
-uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
-                          const upb_fielddef* field) {
-  return (uint32_t*)(((uint8_t*)storage) +
-                     layout->fields[upb_fielddef_index(field)].case_offset);
-}
-
-void* slot_memory(MessageLayout* layout, const void* storage,
-                         const upb_fielddef* field) {
-  return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset;
-}
-
-MessageLayout* create_layout(const upb_msgdef* msgdef) {
-  MessageLayout* layout = SYS_MALLOC(MessageLayout);
-  int nfields = upb_msgdef_numfields(msgdef);
-  upb_msg_field_iter it;
-  upb_msg_oneof_iter oit;
-  size_t off = 0;
-  int i = 0;
-
-  // Reserve space for unknown fields.
-  off += sizeof(void*);
-
-  layout->empty_template = NULL;
-
-  TSRMLS_FETCH();
-  DescriptorInternal* desc = get_msgdef_desc(msgdef);
-  register_class(desc, false TSRMLS_CC);
-  layout->fields = SYS_MALLOC_N(MessageField, nfields);
-
-  for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    size_t field_size;
-
-    if (upb_fielddef_containingoneof(field)) {
-      // Oneofs are handled separately below.
-      continue;
-    }
-
-    // Allocate |field_size| bytes for this field in the layout.
-    field_size = 0;
-    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      field_size = sizeof(zval*);
-    } else {
-      field_size = native_slot_size(upb_fielddef_type(field));
-    }
-
-    // Align current offset up to | size | granularity.
-    off = align_up_to(off, field_size);
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    layout->fields[upb_fielddef_index(field)].case_offset =
-        MESSAGE_FIELD_NO_CASE;
-
-    const char* fieldname = upb_fielddef_name(field);
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-    zend_class_entry* old_scope = EG(scope);
-    EG(scope) = desc->klass;
-#else
-    zend_class_entry* old_scope = EG(fake_scope);
-    EG(fake_scope) = desc->klass;
-#endif
-
-#if PHP_MAJOR_VERSION < 7
-    zval member;
-    ZVAL_STRINGL(&member, fieldname, strlen(fieldname), 0);
-    zend_property_info* property_info =
-        zend_get_property_info(desc->klass, &member, true TSRMLS_CC);
-#else
-    zend_string* member = zend_string_init(fieldname, strlen(fieldname), 1);
-    zend_property_info* property_info =
-        zend_get_property_info(desc->klass, member, true);
-    zend_string_release(member);
-#endif
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-    EG(scope) = old_scope;
-#else
-    EG(fake_scope) = old_scope;
-#endif
-
-    layout->fields[upb_fielddef_index(field)].cache_index =
-        property_info->offset;
-    off += field_size;
-  }
-
-  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
-  // one slot per oneof.
-  //
-  // We assign all value slots first, then pack the 'case' fields at the end,
-  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
-  // bytes respectively and we want to avoid alignment overhead.
-  //
-  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
-  // space for oneof cases is conceptually as wide as field tag numbers.  In
-  // practice, it's unlikely that a oneof would have more than e.g.  256 or 64K
-  // members (8 or 16 bits respectively), so conceivably we could assign
-  // consecutive case numbers and then pick a smaller oneof case slot size, but
-  // the complexity to implement this indirection is probably not worthwhile.
-  for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
-    upb_oneof_iter fit;
-
-    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
-    // all fields.
-    size_t field_size = NATIVE_SLOT_MAX_SIZE;
-    // Align the offset .
-    off = align_up_to( off, field_size);
-    // Assign all fields in the oneof this same offset.
-    const char* oneofname = upb_oneofdef_name(oneof);
-    for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* field = upb_oneof_iter_field(&fit);
-      layout->fields[upb_fielddef_index(field)].offset = off;
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-      zend_class_entry* old_scope = EG(scope);
-      EG(scope) = desc->klass;
-#else
-      zend_class_entry* old_scope = EG(fake_scope);
-      EG(fake_scope) = desc->klass;
-#endif
-
-#if PHP_MAJOR_VERSION < 7
-      zval member;
-      ZVAL_STRINGL(&member, oneofname, strlen(oneofname), 0);
-      zend_property_info* property_info =
-          zend_get_property_info(desc->klass, &member, true TSRMLS_CC);
-#else
-      zend_string* member = zend_string_init(oneofname, strlen(oneofname), 1);
-      zend_property_info* property_info =
-          zend_get_property_info(desc->klass, member, true);
-      zend_string_release(member);
-#endif
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-      EG(scope) = old_scope;
-#else
-      EG(fake_scope) = old_scope;
-#endif
-
-      layout->fields[upb_fielddef_index(field)].cache_index =
-          property_info->offset;
-    }
-    i++;
-    off += field_size;
-  }
-
-  // Now the case offset.
-  for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
-    upb_oneof_iter fit;
-
-    size_t field_size = sizeof(uint32_t);
-    // Align the offset .
-    off = (off + field_size - 1) & ~(field_size - 1);
-    // Assign all fields in the oneof this same offset.
-    for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* field = upb_oneof_iter_field(&fit);
-      layout->fields[upb_fielddef_index(field)].case_offset = off;
-    }
-    off += field_size;
-  }
-
-  layout->size = off;
-  layout->msgdef = msgdef;
-
-  // Create the empty message template.
-  layout->empty_template = SYS_MALLOC_N(char, layout->size);
-  memset(layout->empty_template, 0, layout->size);
-
-  return layout;
-}
-
-void free_layout(MessageLayout* layout) {
-  SYS_FREE(layout->empty_template);
-  SYS_FREE(layout->fields);
-  SYS_FREE(layout);
-}
-
-void layout_init(MessageLayout* layout, void* storage,
-                 zend_object* object PHP_PROTO_TSRMLS_DC) {
-  memcpy(storage, layout->empty_template, layout->size);
-}
-
-// Switch memory for processing for singular fields based on field type.
-//   * primitive fields: memory
-//   * others (string, bytes and message): cache (the correspond zval
-//   property)
-static void* value_memory(
-    upb_fieldtype_t type, void* memory, CACHED_VALUE* cache) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_MESSAGE:
-      return cache;
-    default:
-      // No operation
-      break;
-  }
-  return memory;
-}
-
-CACHED_VALUE* find_zval_property(
-    MessageHeader* header, const upb_fielddef* field) {
-  int property_cache_index =
-      header->descriptor->layout->fields[upb_fielddef_index(field)]
-          .cache_index;
-  return OBJ_PROP(&header->std, property_cache_index);
-}
-
-zval* layout_get(MessageLayout* layout, MessageHeader* header,
-                 const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC) {
-  const void* storage = message_data(header);
-  void* memory = slot_memory(layout, storage, field);
-  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
-
-  if (upb_fielddef_containingoneof(field)) {
-    if (*oneof_case != upb_fielddef_number(field)) {
-      native_slot_get_default(upb_fielddef_type(field), cache TSRMLS_CC);
-      return CACHED_PTR_TO_ZVAL_PTR(cache);
-    }
-    // Intentional fall through to be handled as a signuarl field.
-  } else if (is_map_field(field)) {
-    map_field_ensure_created(field, cache PHP_PROTO_TSRMLS_CC);
-    return CACHED_PTR_TO_ZVAL_PTR(cache);
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    repeated_field_ensure_created(field, cache PHP_PROTO_TSRMLS_CC);
-    return CACHED_PTR_TO_ZVAL_PTR(cache);
-  }
-
-  CACHED_VALUE* stored_cache = find_zval_property(header, field);
-
-  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE &&
-      is_wrapper_msg(upb_fielddef_msgsubdef(field))) {
-    zval * cached_zval = CACHED_PTR_TO_ZVAL_PTR(stored_cache);
-#if PHP_MAJOR_VERSION >= 7
-    zend_object* obj;
-#endif
-    if (Z_TYPE_P(cached_zval) != IS_OBJECT &&
-        Z_TYPE_P(cached_zval) != IS_NULL) {
-      // Needs to expand value to wrapper.
-      const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
-      const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
-      MessageHeader* submsg;
-      DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
-      register_class(subdesc, false TSRMLS_CC);
-      zend_class_entry* subklass = subdesc->klass;
-#if PHP_MAJOR_VERSION < 7
-      zval* val = NULL;
-      MAKE_STD_ZVAL(val);
-      ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
-      submsg = UNBOX(MessageHeader, val);
-#else
-      obj = subklass->create_object(subklass TSRMLS_CC);
-      submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
-#endif
-      custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-
-      layout_set(subdesc->layout, submsg, value_field, cached_zval TSRMLS_CC);
-#if PHP_MAJOR_VERSION < 7
-      ZVAL_ZVAL(cached_zval, val, 1, 1);
-#else
-      ZVAL_OBJ(cached_zval, obj);
-#endif
-    }
-    if (stored_cache != cache) {
-      ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), cached_zval, 1, 0);
-    }
-  } else {
-    upb_fieldtype_t type = upb_fielddef_type(field);
-    native_slot_get(type, value_memory(type, memory, stored_cache),
-                    cache TSRMLS_CC);
-  }
-  return CACHED_PTR_TO_ZVAL_PTR(cache);
-}
-
-void layout_set(MessageLayout* layout, MessageHeader* header,
-                const upb_fielddef* field, zval* val TSRMLS_DC) {
-  void* storage = message_data(header);
-  void* memory = slot_memory(layout, storage, field);
-  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
-
-  if (upb_fielddef_containingoneof(field)) {
-    *oneof_case = upb_fielddef_number(field);
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    // Works for both repeated and map fields
-    CACHED_VALUE* cached = find_zval_property(header, field);
-    zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR(cached);
-
-    if (EXPECTED(property_ptr != val)) {
-      zend_class_entry *subce = NULL;
-      zval converted_value;
-
-      if (upb_fielddef_ismap(field)) {
-        const upb_msgdef* mapmsg = upb_fielddef_msgsubdef(field);
-        const upb_fielddef* keyfield = upb_msgdef_ntof(mapmsg, "key", 3);
-        const upb_fielddef* valuefield = upb_msgdef_ntof(mapmsg, "value", 5);
-        if (upb_fielddef_descriptortype(valuefield) ==
-            UPB_DESCRIPTOR_TYPE_MESSAGE) {
-          const upb_msgdef* submsg = upb_fielddef_msgsubdef(valuefield);
-          DescriptorInternal* subdesc = get_msgdef_desc(submsg);
-          register_class(subdesc, false TSRMLS_CC);
-          subce = subdesc->klass;
-        }
-        check_map_field(subce, upb_fielddef_descriptortype(keyfield),
-                        upb_fielddef_descriptortype(valuefield), val,
-                        &converted_value);
-      } else {
-        if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-          const upb_msgdef* submsg = upb_fielddef_msgsubdef(field);
-          DescriptorInternal* subdesc = get_msgdef_desc(submsg);
-          register_class(subdesc, false TSRMLS_CC);
-          subce = subdesc->klass;
-        }
-
-        check_repeated_field(subce, upb_fielddef_descriptortype(field), val,
-                             &converted_value);
-      }
-#if PHP_MAJOR_VERSION < 7
-      REPLACE_ZVAL_VALUE((zval**)cached, &converted_value, 1);
-#else
-      php_proto_zval_ptr_dtor(property_ptr);
-      ZVAL_ZVAL(property_ptr, &converted_value, 1, 0);
-#endif
-      zval_dtor(&converted_value);
-    }
-    return;
-  }
-
-  upb_fieldtype_t type = upb_fielddef_type(field);
-  zend_class_entry *ce = NULL;
-  if (type == UPB_TYPE_MESSAGE) {
-    const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
-    DescriptorInternal* desc = get_msgdef_desc(msg);
-    register_class(desc, false TSRMLS_CC);
-    ce = desc->klass;
-  }
-  CACHED_VALUE* cache = find_zval_property(header, field);
-  native_slot_set(
-      type, ce, value_memory(upb_fielddef_type(field), memory, cache),
-      val TSRMLS_CC);
-}
-
-static void native_slot_merge(
-    const upb_fielddef* field, const void* from_memory,
-    void* to_memory PHP_PROTO_TSRMLS_DC) {
-  upb_fieldtype_t type = upb_fielddef_type(field);
-  zend_class_entry* ce = NULL;
-  if (!native_slot_is_default(type, from_memory)) {
-    switch (type) {
-#define CASE_TYPE(upb_type, c_type)                        \
-  case UPB_TYPE_##upb_type: {                              \
-    DEREF(to_memory, c_type) = DEREF(from_memory, c_type); \
-    break;                                                 \
-  }
-      CASE_TYPE(INT32, int32_t)
-      CASE_TYPE(UINT32, uint32_t)
-      CASE_TYPE(ENUM, int32_t)
-      CASE_TYPE(INT64, int64_t)
-      CASE_TYPE(UINT64, uint64_t)
-      CASE_TYPE(FLOAT, float)
-      CASE_TYPE(DOUBLE, double)
-      CASE_TYPE(BOOL, int8_t)
-
-#undef CASE_TYPE
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        native_slot_set(type, NULL, to_memory,
-                        CACHED_PTR_TO_ZVAL_PTR(from_memory) PHP_PROTO_TSRMLS_CC);
-        break;
-      case UPB_TYPE_MESSAGE: {
-        const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
-        DescriptorInternal* desc = get_msgdef_desc(msg);
-        register_class(desc, false TSRMLS_CC);
-        ce = desc->klass;
-        if (native_slot_is_default(type, to_memory)) {
-#if PHP_MAJOR_VERSION < 7
-          SEPARATE_ZVAL_IF_NOT_REF((zval**)to_memory);
-#endif
-          CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(
-              CACHED_PTR_TO_ZVAL_PTR(to_memory), ce);
-          MessageHeader* submsg =
-              UNBOX(MessageHeader, CACHED_PTR_TO_ZVAL_PTR(to_memory));
-          custom_data_init(ce, submsg PHP_PROTO_TSRMLS_CC);
-        }
-
-        MessageHeader* sub_from =
-            UNBOX(MessageHeader,
-                  CACHED_PTR_TO_ZVAL_PTR(from_memory));
-        MessageHeader* sub_to =
-            UNBOX(MessageHeader,
-                  CACHED_PTR_TO_ZVAL_PTR(to_memory));
-
-        layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC);
-        break;
-      }
-    }
-  }
-}
-
-static void native_slot_merge_by_array(const upb_fielddef* field, const void* from_memory,
-                         void* to_memory PHP_PROTO_TSRMLS_DC) {
-  upb_fieldtype_t type = upb_fielddef_type(field);
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
-      MAKE_STD_ZVAL(DEREF(to_memory, zval*));
-      PHP_PROTO_ZVAL_STRINGL(DEREF(to_memory, zval*),
-                             Z_STRVAL_P(*(zval**)from_memory),
-                             Z_STRLEN_P(*(zval**)from_memory), 1);
-#else
-      DEREF(to_memory, zend_string*) =
-          zend_string_dup(*(zend_string**)from_memory, 0);
-#endif
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
-      register_class(desc, false TSRMLS_CC);
-      zend_class_entry* ce = desc->klass;
-#if PHP_MAJOR_VERSION < 7
-      MAKE_STD_ZVAL(DEREF(to_memory, zval*));
-      CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(DEREF(to_memory, zval*), ce);
-#else
-      DEREF(to_memory, zend_object*) = ce->create_object(ce TSRMLS_CC);
-#endif
-      MessageHeader* sub_from = UNBOX_HASHTABLE_VALUE(
-          MessageHeader, DEREF(from_memory, PHP_PROTO_HASHTABLE_VALUE));
-      MessageHeader* sub_to = UNBOX_HASHTABLE_VALUE(
-          MessageHeader, DEREF(to_memory, PHP_PROTO_HASHTABLE_VALUE));
-      custom_data_init(ce, sub_to PHP_PROTO_TSRMLS_CC);
-
-      layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC);
-      break;
-    }
-    default:
-      native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC);
-      break;
-  }
-}
-
-void layout_merge(MessageLayout* layout, MessageHeader* from,
-                  MessageHeader* to PHP_PROTO_TSRMLS_DC) {
-  int i, j;
-  upb_msg_field_iter it;
-
-  for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it);
-       upb_msg_field_next(&it), i++) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-
-    void* to_memory = slot_memory(layout, message_data(to), field);
-    void* from_memory = slot_memory(layout, message_data(from), field);
-
-    if (upb_fielddef_containingoneof(field)) {
-      uint32_t oneof_case_offset =
-          layout->fields[upb_fielddef_index(field)].case_offset;
-      // For a oneof, check that this field is actually present -- skip all the
-      // below if not.
-      if (DEREF((message_data(from) + oneof_case_offset), uint32_t) !=
-          upb_fielddef_number(field)) {
-        continue;
-      }
-      uint32_t* from_oneof_case = slot_oneof_case(layout, message_data(from), field);
-      uint32_t* to_oneof_case = slot_oneof_case(layout, message_data(to), field);
-
-      // For non-singular fields, the related memory needs to point to the
-      // actual zval in properties table first.
-      switch (upb_fielddef_type(field)) {
-        case UPB_TYPE_MESSAGE:
-        case UPB_TYPE_STRING:
-        case UPB_TYPE_BYTES: {
-          int property_cache_index =
-              layout->fields[upb_fielddef_index(field)].cache_index;
-          DEREF(to_memory, CACHED_VALUE*) =
-              OBJ_PROP(&to->std, property_cache_index);
-          break;
-        }
-        default:
-          break;
-      }
-
-      *to_oneof_case = *from_oneof_case;
-
-      // Otherwise, fall through to the appropriate singular-field handler
-      // below.
-    }
-
-    if (is_map_field(field)) {
-      int size, key_length, value_length;
-      MapIter map_it;
-
-      CACHED_VALUE* from_cache = find_zval_property(from, field);
-      CACHED_VALUE* to_cache = find_zval_property(to, field);
-
-      if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(from_cache)) == IS_NULL) {
-        continue;
-      }
-      map_field_ensure_created(field, to_cache PHP_PROTO_TSRMLS_CC);
-
-      zval* to_map_php = CACHED_PTR_TO_ZVAL_PTR(to_cache);
-      zval* from_map_php = CACHED_PTR_TO_ZVAL_PTR(from_cache);
-
-      Map* to_map = UNBOX(Map, to_map_php);
-      Map* from_map = UNBOX(Map, from_map_php);
-
-      size = upb_strtable_count(&from_map->table);
-      if (size == 0) continue;
-
-      const upb_msgdef *mapentry_def = upb_fielddef_msgsubdef(field);
-      const upb_fielddef *value_field = upb_msgdef_itof(mapentry_def, 2);
-
-      for (map_begin(from_map_php, &map_it TSRMLS_CC); !map_done(&map_it);
-           map_next(&map_it)) {
-        const char* key = map_iter_key(&map_it, &key_length);
-        upb_value from_value = map_iter_value(&map_it, &value_length);
-        upb_value to_value;
-        void* from_mem = upb_value_memory(&from_value);
-        void* to_mem = upb_value_memory(&to_value);
-        memset(to_mem, 0, native_slot_size(to_map->value_type));
-
-        native_slot_merge_by_array(value_field, from_mem,
-                                   to_mem PHP_PROTO_TSRMLS_CC);
-
-        map_index_set(to_map, key, key_length, to_value);
-      }
-
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      CACHED_VALUE* from_cache = find_zval_property(from, field);
-      CACHED_VALUE* to_cache = find_zval_property(to, field);
-
-      if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(from_cache)) == IS_NULL) {
-        continue;
-      }
-      repeated_field_ensure_created(field, to_cache PHP_PROTO_TSRMLS_CC);
-
-      zval* to_array_php = CACHED_PTR_TO_ZVAL_PTR(to_cache);
-      zval* from_array_php = CACHED_PTR_TO_ZVAL_PTR(from_cache);
-      RepeatedField* to_array = UNBOX(RepeatedField, to_array_php);
-      RepeatedField* from_array = UNBOX(RepeatedField, from_array_php);
-
-      int size = zend_hash_num_elements(PHP_PROTO_HASH_OF(from_array->array));
-      if (size > 0) {
-        for (j = 0; j < size; j++) {
-          void* from_memory = NULL;
-          void* to_memory =
-              ALLOC_N(char, native_slot_size(upb_fielddef_type(field)));
-          memset(to_memory, 0, native_slot_size(upb_fielddef_type(field)));
-
-          if (to_array->type == UPB_TYPE_MESSAGE) {
-            php_proto_zend_hash_index_find_zval(
-                PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory);
-#if PHP_MAJOR_VERSION >= 7
-            from_memory = &Z_OBJ_P((zval*)from_memory);
-#endif
-          } else {
-            php_proto_zend_hash_index_find_mem(
-                PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory);
-          }
-
-          native_slot_merge_by_array(field, from_memory,
-                                     to_memory PHP_PROTO_TSRMLS_CC);
-          repeated_field_push_native(to_array, to_memory);
-          FREE(to_memory);
-        }
-      }
-    } else {
-      switch (upb_fielddef_type(field)) {
-        case UPB_TYPE_STRING:
-        case UPB_TYPE_BYTES:
-        case UPB_TYPE_MESSAGE: {
-          CACHED_VALUE* from_cache = find_zval_property(from, field);
-          CACHED_VALUE* to_cache = find_zval_property(to, field);
-          native_slot_merge(field, from_cache, to_cache PHP_PROTO_TSRMLS_CC);
-          break;
-        }
-        default:
-          native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC);
-          break;
-      }
-    }
-  }
-}
-
-const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
-                                  const upb_oneofdef* oneof TSRMLS_DC) {
-  upb_oneof_iter i;
-  const upb_fielddef* first_field = NULL;
-
-  // Oneof is guaranteed to have at least one field. Get the first field.
-  for(upb_oneof_begin(&i, oneof); !upb_oneof_done(&i); upb_oneof_next(&i)) {
-    first_field = upb_oneof_iter_field(&i);
-    break;
-  }
-
-  uint32_t* oneof_case = slot_oneof_case(layout, storage, first_field);
-  if (*oneof_case == 0) {
-    return "";
-  }
-  const upb_fielddef* field = upb_oneofdef_itof(oneof, *oneof_case);
-  return upb_fielddef_name(field);
-}
diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c
deleted file mode 100644
index 84d06be..0000000
--- a/php/ext/google/protobuf/type_check.c
+++ /dev/null
@@ -1,680 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//                The Zend Engine License, version 2.00
-// Copyright (c) 1999-2002 Zend Technologies Ltd. All rights reserved.
-// --------------------------------------------------------------------
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, is permitted provided that the following conditions
-// are met:
-//
-//   1. Redistributions of source code must retain the above copyright
-//      notice, this list of conditions and the following disclaimer.
-//
-//   2. Redistributions in binary form must reproduce the above
-//      copyright notice, this list of conditions and the following
-//      disclaimer in the documentation and/or other materials provided
-//      with the distribution.
-//
-//   3. The names "Zend" and "Zend Engine" must not be used to endorse
-//      or promote products derived from this software without prior
-//      permission from Zend Technologies Ltd. For written permission,
-//      please contact license@zend.com.
-//
-//   4. Zend Technologies Ltd. may publish revised and/or new versions
-//      of the license from time to time. Each version will be given a
-//      distinguishing version number.
-//      Once covered code has been published under a particular version
-//      of the license, you may always continue to use it under the
-//      terms of that version. You may also choose to use such covered
-//      code under the terms of any subsequent version of the license
-//      published by Zend Technologies Ltd. No one other than Zend
-//      Technologies Ltd. has the right to modify the terms applicable
-//      to covered code created under this License.
-//
-//   5. Redistributions of any form whatsoever must retain the following
-//      acknowledgment:
-//      "This product includes the Zend Engine, freely available at
-//      http://www.zend.com"
-//
-//   6. All advertising materials mentioning features or use of this
-//      software must display the following acknowledgment:
-//      "The Zend Engine is freely available at http://www.zend.com"
-//
-// THIS SOFTWARE IS PROVIDED BY ZEND TECHNOLOGIES LTD. ``AS IS'' AND
-// ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-// PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ZEND
-// TECHNOLOGIES LTD.  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-// SUCH DAMAGE.
-
-#include <Zend/zend_operators.h>
-#include <Zend/zend_exceptions.h>
-
-#include "protobuf.h"
-#include "utf8.h"
-
-static zend_class_entry* util_type;
-static const char int64_min_digits[] = "9223372036854775808";
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1)
-  ZEND_ARG_INFO(1, val)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_message, 0, 0, 2)
-  ZEND_ARG_INFO(1, val)
-  ZEND_ARG_INFO(0, klass)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_repeated, 0, 0, 2)
-  ZEND_ARG_INFO(1, val)
-  ZEND_ARG_INFO(0, type)
-  ZEND_ARG_INFO(0, klass)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_map, 0, 0, 3)
-  ZEND_ARG_INFO(1, val)
-  ZEND_ARG_INFO(0, key_type)
-  ZEND_ARG_INFO(0, value_type)
-  ZEND_ARG_INFO(0, klass)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry util_methods[] = {
-  PHP_ME(Util, checkInt32,  arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkUint32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkInt64,  arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkUint64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkEnum,   arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkFloat,  arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkDouble, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkBool,   arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkString, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkBytes,  arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkMessage, arg_check_message, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkMapField,    arg_check_map, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(Util, checkRepeatedField, arg_check_repeated,
-         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  ZEND_FE_END
-};
-
-void util_init(TSRMLS_D) {
-  zend_class_entry class_type;
-  INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil",
-                   util_methods);
-  util_type = zend_register_internal_class(&class_type TSRMLS_CC);
-}
-
-// -----------------------------------------------------------------------------
-// Type checking/conversion.
-// -----------------------------------------------------------------------------
-
-// This is modified from is_numeric_string in zend_operators.h. The behavior of
-// this function is the same as is_numeric_string, except that this takes
-// int64_t as input instead of long.
-static zend_uchar convert_numeric_string(
-    const char *str, int length, int64_t *lval, double *dval) {
-  const char *ptr;
-  int base = 10, digits = 0, dp_or_e = 0;
-  double local_dval = 0.0;
-  zend_uchar type;
-
-  if (length == 0) {
-    return IS_NULL;
-  }
-
-  while (*str == ' ' || *str == '\t' || *str == '\n' ||
-         *str == '\r' || *str == '\v' || *str == '\f') {
-    str++;
-    length--;
-  }
-  ptr = str;
-
-  if (*ptr == '-' || *ptr == '+') {
-    ptr++;
-  }
-
-  if (ZEND_IS_DIGIT(*ptr)) {
-    // Handle hex numbers
-    // str is used instead of ptr to disallow signs and keep old behavior.
-    if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
-      base = 16;
-      ptr += 2;
-    }
-
-    // Skip any leading 0s.
-    while (*ptr == '0') {
-      ptr++;
-    }
-
-    // Count the number of digits. If a decimal point/exponent is found,
-    // it's a double. Otherwise, if there's a dval or no need to check for
-    // a full match, stop when there are too many digits for a int64 */
-    for (type = IS_LONG;
-        !(digits >= MAX_LENGTH_OF_INT64 && dval);
-        digits++, ptr++) {
-check_digits:
-      if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
-        continue;
-      } else if (base == 10) {
-        if (*ptr == '.' && dp_or_e < 1) {
-          goto process_double;
-        } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
-          const char *e = ptr + 1;
-
-          if (*e == '-' || *e == '+') {
-            ptr = e++;
-          }
-          if (ZEND_IS_DIGIT(*e)) {
-            goto process_double;
-          }
-        }
-      }
-      break;
-    }
-
-    if (base == 10) {
-      if (digits >= MAX_LENGTH_OF_INT64) {
-        dp_or_e = -1;
-        goto process_double;
-      }
-    } else if (!(digits < SIZEOF_INT64 * 2 ||
-               (digits == SIZEOF_INT64 * 2 && ptr[-digits] <= '7'))) {
-      if (dval) {
-        local_dval = zend_hex_strtod(str, &ptr);
-      }
-      type = IS_DOUBLE;
-    }
-  } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
-process_double:
-    type = IS_DOUBLE;
-
-    // If there's a dval, do the conversion; else continue checking
-    // the digits if we need to check for a full match.
-    if (dval) {
-      local_dval = zend_strtod(str, &ptr);
-    } else if (dp_or_e != -1) {
-      dp_or_e = (*ptr++ == '.') ? 1 : 2;
-      goto check_digits;
-    }
-  } else {
-    return IS_NULL;
-  }
-  if (ptr != str + length) {
-    zend_error(E_NOTICE, "A non well formed numeric value encountered");
-    return 0;
-  }
-
-  if (type == IS_LONG) {
-    if (digits == MAX_LENGTH_OF_INT64 - 1) {
-      int cmp = strcmp(&ptr[-digits], int64_min_digits);
-
-      if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
-        if (dval) {
-          *dval = zend_strtod(str, NULL);
-        }
-
-	return IS_DOUBLE;
-      }
-    }
-    if (lval) {
-      *lval = strtoll(str, NULL, base);
-    }
-    return IS_LONG;
-  } else {
-    if (dval) {
-      *dval = local_dval;
-    }
-    return IS_DOUBLE;
-  }
-}
-
-#define CONVERT_TO_INTEGER(type)                                             \
-  static bool convert_int64_to_##type(int64_t val, type##_t* type##_value) { \
-    *type##_value = (type##_t)val;                                           \
-    return true;                                                             \
-  }                                                                          \
-                                                                             \
-  static bool convert_double_to_##type(double val, type##_t* type##_value) { \
-    *type##_value = (type##_t)zend_dval_to_lval(val);                        \
-    return true;                                                             \
-  }                                                                          \
-                                                                             \
-  static bool convert_string_to_##type(const char* val, int len,             \
-                                       type##_t* type##_value) {             \
-    int64_t lval;                                                            \
-    double dval;                                                             \
-    TSRMLS_FETCH();                                                          \
-    switch (convert_numeric_string(val, len, &lval, &dval)) {                \
-      case IS_DOUBLE: {                                                      \
-        return convert_double_to_##type(dval, type##_value);                 \
-      }                                                                      \
-      case IS_LONG: {                                                        \
-        return convert_int64_to_##type(lval, type##_value);                  \
-      }                                                                      \
-      default:                                                               \
-        zend_throw_exception(NULL,                                           \
-                   "Given string value cannot be converted to integer.",     \
-                   0 TSRMLS_CC);                                             \
-        return false;                                                        \
-    }                                                                        \
-  }                                                                          \
-                                                                             \
-  bool protobuf_convert_to_##type(zval* from, type##_t* to) {                \
-    TSRMLS_FETCH();                                                          \
-    switch (Z_TYPE_P(from)) {                                                \
-      case IS_LONG: {                                                        \
-        return convert_int64_to_##type(Z_LVAL_P(from), to);                  \
-      }                                                                      \
-      case IS_DOUBLE: {                                                      \
-        return convert_double_to_##type(Z_DVAL_P(from), to);                 \
-      }                                                                      \
-      case IS_STRING: {                                                      \
-        return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from),  \
-                                        to);                                 \
-      }                                                                      \
-      default: {                                                             \
-        zend_throw_exception(NULL,                                           \
-                   "Given value cannot be converted to integer.",            \
-                   0 TSRMLS_CC);                                             \
-        return false;                                                        \
-      }                                                                      \
-    }                                                                        \
-    return false;                                                            \
-  }
-
-CONVERT_TO_INTEGER(int32);
-CONVERT_TO_INTEGER(uint32);
-CONVERT_TO_INTEGER(int64);
-CONVERT_TO_INTEGER(uint64);
-
-#undef CONVERT_TO_INTEGER
-
-#define CONVERT_TO_FLOAT(type)                                              \
-  static bool convert_int64_to_##type(int64_t val, type* type##_value) {    \
-    *type##_value = (type)val;                                              \
-    return true;                                                            \
-  }                                                                         \
-                                                                            \
-  static bool convert_double_to_##type(double val, type* type##_value) {    \
-    *type##_value = (type)val;                                              \
-    return true;                                                            \
-  }                                                                         \
-                                                                            \
-  static bool convert_string_to_##type(const char* val, int len,            \
-                                       type* type##_value) {                \
-    int64_t lval;                                                           \
-    double dval;                                                            \
-                                                                            \
-    TSRMLS_FETCH();                                                         \
-    switch (convert_numeric_string(val, len, &lval, &dval)) {               \
-      case IS_DOUBLE: {                                                     \
-        *type##_value = (type)dval;                                         \
-        return true;                                                        \
-      }                                                                     \
-      case IS_LONG: {                                                       \
-        *type##_value = (type)lval;                                         \
-        return true;                                                        \
-      }                                                                     \
-      default:                                                              \
-        zend_throw_exception(NULL,                                          \
-                   "Given string value cannot be converted to integer.",    \
-                   0 TSRMLS_CC);                                            \
-        return false;                                                       \
-    }                                                                       \
-  }                                                                         \
-                                                                            \
-  bool protobuf_convert_to_##type(zval* from, type* to) {                   \
-    TSRMLS_FETCH();                                                         \
-    switch (Z_TYPE_P(from)) {                                               \
-      case IS_LONG: {                                                       \
-        return convert_int64_to_##type(Z_LVAL_P(from), to);                 \
-      }                                                                     \
-      case IS_DOUBLE: {                                                     \
-        return convert_double_to_##type(Z_DVAL_P(from), to);                \
-      }                                                                     \
-      case IS_STRING: {                                                     \
-        return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
-                                        to);                                \
-      }                                                                     \
-      default: {                                                            \
-        zend_throw_exception(NULL,                                          \
-                   "Given value cannot be converted to integer.",           \
-                   0 TSRMLS_CC);                                            \
-        return false;                                                       \
-      }                                                                     \
-    }                                                                       \
-    return false;                                                           \
-  }
-
-CONVERT_TO_FLOAT(float);
-CONVERT_TO_FLOAT(double);
-
-#undef CONVERT_TO_FLOAT
-
-bool protobuf_convert_to_bool(zval* from, int8_t* to) {
-  TSRMLS_FETCH();
-  switch (Z_TYPE_P(from)) {
-#if PHP_MAJOR_VERSION < 7
-    case IS_BOOL:
-      *to = (int8_t)Z_BVAL_P(from);
-      break;
-#else
-    case IS_TRUE:
-      *to = 1;
-      break;
-    case IS_FALSE:
-      *to = 0;
-      break;
-#endif
-    case IS_LONG:
-      *to = (int8_t)(Z_LVAL_P(from) != 0);
-      break;
-    case IS_DOUBLE:
-      *to = (int8_t)(Z_LVAL_P(from) != 0);
-      break;
-    case IS_STRING: {
-      if (Z_STRLEN_P(from) == 0 ||
-          (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) {
-        *to = 0;
-      } else {
-        *to = 1;
-      }
-    } break;
-    default: {
-      zend_throw_exception(
-          NULL, "Given value cannot be converted to bool.",
-          0 TSRMLS_CC);
-      return false;
-    }
-  }
-  return true;
-}
-
-bool protobuf_convert_to_string(zval* from) {
-#if PHP_MAJOR_VERSION >= 7
-  if (Z_ISREF_P(from)) {
-    ZVAL_DEREF(from);
-  }
-#endif
-  TSRMLS_FETCH();
-  switch (Z_TYPE_P(from)) {
-    case IS_STRING: {
-      return true;
-    }
-#if PHP_MAJOR_VERSION < 7
-    case IS_BOOL:
-#else
-    case IS_TRUE:
-    case IS_FALSE:
-#endif
-    case IS_LONG:
-    case IS_DOUBLE: {
-      zval tmp;
-      php_proto_zend_make_printable_zval(from, &tmp);
-      ZVAL_COPY_VALUE(from, &tmp);
-      return true;
-    }
-    default:
-      zend_throw_exception(
-          NULL, "Given value cannot be converted to string.",
-          0 TSRMLS_CC);
-      return false;
-  }
-}
-
-// -----------------------------------------------------------------------------
-// PHP Functions.
-// -----------------------------------------------------------------------------
-
-// The implementation of type checking for primitive fields is empty. This is
-// because type checking is done when direct assigning message fields (e.g.,
-// foo->a = 1). Functions defined here are place holders in generated code for
-// pure PHP implementation (c extension and pure PHP share the same generated
-// code).
-#define PHP_TYPE_CHECK(type) \
-  PHP_METHOD(Util, check##type) {}
-
-PHP_TYPE_CHECK(Int32)
-PHP_TYPE_CHECK(Uint32)
-PHP_TYPE_CHECK(Int64)
-PHP_TYPE_CHECK(Uint64)
-PHP_TYPE_CHECK(Enum)
-PHP_TYPE_CHECK(Float)
-PHP_TYPE_CHECK(Double)
-PHP_TYPE_CHECK(Bool)
-PHP_TYPE_CHECK(String)
-PHP_TYPE_CHECK(Bytes)
-
-#undef PHP_TYPE_CHECK
-
-PHP_METHOD(Util, checkMessage) {
-  zval* val;
-  zend_class_entry* klass = NULL;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!C", &val, &klass) ==
-      FAILURE) {
-    return;
-  }
-  if (val == NULL) {
-    RETURN_NULL();
-  }
-  if (!instanceof_function(Z_OBJCE_P(val), klass TSRMLS_CC)) {
-    zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                            "Given value is not an instance of %s.",
-#if PHP_MAJOR_VERSION < 7
-                            klass->name);
-#else
-                            ZSTR_VAL(klass->name));
-#endif
-    return;
-  }
-  RETURN_ZVAL(val, 1, 0);
-}
-
-void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type,
-                          zval* val, zval* return_value) {
-#if PHP_MAJOR_VERSION >= 7
-  if (Z_ISREF_P(val)) {
-    ZVAL_DEREF(val);
-  }
-#endif
-
-  TSRMLS_FETCH();
-  if (Z_TYPE_P(val) == IS_ARRAY) {
-    HashTable* table = HASH_OF(val);
-    HashPosition pointer;
-    void* memory;
-
-#if PHP_MAJOR_VERSION < 7
-    zval* repeated_field;
-    MAKE_STD_ZVAL(repeated_field);
-#else
-    zval repeated_field;
-#endif
-
-    repeated_field_create_with_type(repeated_field_type, to_fieldtype(type),
-                                    klass, &repeated_field TSRMLS_CC);
-
-    for (zend_hash_internal_pointer_reset_ex(table, &pointer);
-         php_proto_zend_hash_get_current_data_ex(table, (void**)&memory,
-                                                 &pointer) == SUCCESS;
-         zend_hash_move_forward_ex(table, &pointer)) {
-      repeated_field_handlers->write_dimension(
-          CACHED_TO_ZVAL_PTR(repeated_field), NULL,
-          CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
-    }
-
-    RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 1);
-
-  } else if (Z_TYPE_P(val) == IS_OBJECT) {
-    if (!instanceof_function(Z_OBJCE_P(val), repeated_field_type TSRMLS_CC)) {
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Given value is not an instance of %s.",
-#if PHP_MAJOR_VERSION < 7
-                              repeated_field_type->name);
-#else
-                              ZSTR_VAL(repeated_field_type->name));
-#endif
-      return;
-    }
-    RepeatedField* intern = UNBOX(RepeatedField, val);
-    if (to_fieldtype(type) != intern->type) {
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Incorrect repeated field type.");
-      return;
-    }
-    if (klass != NULL && intern->msg_ce != klass) {
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Expect a repeated field of %s, but %s is given.",
-#if PHP_MAJOR_VERSION < 7
-                              klass->name, intern->msg_ce->name);
-#else
-                              ZSTR_VAL(klass->name),
-                              ZSTR_VAL(intern->msg_ce->name));
-#endif
-      return;
-    }
-    RETURN_ZVAL(val, 1, 0);
-  } else {
-    zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                            "Incorrect repeated field type.");
-    return;
-  }
-}
-
-PHP_METHOD(Util, checkRepeatedField) {
-  zval* val;
-  PHP_PROTO_LONG type;
-  const zend_class_entry* klass = NULL;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type,
-                            &klass) == FAILURE) {
-    return;
-  }
-  RETURN_ZVAL(val, 1, 0);
-}
-
-void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type,
-                     PHP_PROTO_LONG value_type, zval* val, zval* return_value) {
-#if PHP_MAJOR_VERSION >= 7
-  if (Z_ISREF_P(val)) {
-    ZVAL_DEREF(val);
-  }
-#endif
-
-  TSRMLS_FETCH();
-  if (Z_TYPE_P(val) == IS_ARRAY) {
-    HashTable* table = Z_ARRVAL_P(val);
-    HashPosition pointer;
-    zval key;
-    void* value;
-
-#if PHP_MAJOR_VERSION < 7
-    zval* map_field;
-    MAKE_STD_ZVAL(map_field);
-#else
-    zval map_field;
-#endif
-
-    map_field_create_with_type(map_field_type, to_fieldtype(key_type),
-                               to_fieldtype(value_type), klass,
-                               &map_field TSRMLS_CC);
-
-    for (zend_hash_internal_pointer_reset_ex(table, &pointer);
-         php_proto_zend_hash_get_current_data_ex(table, (void**)&value,
-                                                 &pointer) == SUCCESS;
-         zend_hash_move_forward_ex(table, &pointer)) {
-      zend_hash_get_current_key_zval_ex(table, &key, &pointer);
-      map_field_handlers->write_dimension(
-          CACHED_TO_ZVAL_PTR(map_field), &key,
-          CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC);
-      zval_dtor(&key);
-    }
-
-    RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 1);
-  } else if (Z_TYPE_P(val) == IS_OBJECT) {
-    if (!instanceof_function(Z_OBJCE_P(val), map_field_type TSRMLS_CC)) {
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Given value is not an instance of %s.",
-#if PHP_MAJOR_VERSION < 7
-                              map_field_type->name);
-#else
-                              ZSTR_VAL(map_field_type->name));
-#endif
-      return;
-    }
-    Map* intern = UNBOX(Map, val);
-    if (to_fieldtype(key_type) != intern->key_type) {
-      zend_throw_exception(
-          NULL, "Incorrect map field key type.",
-          0 TSRMLS_CC);
-      return;
-    }
-    if (to_fieldtype(value_type) != intern->value_type) {
-      zend_throw_exception(
-          NULL, "Incorrect map field value type.",
-          0 TSRMLS_CC);
-      return;
-    }
-    if (klass != NULL && intern->msg_ce != klass) {
-      zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
-                              "Expect a map field of %s, but %s is given.",
-#if PHP_MAJOR_VERSION < 7
-                              klass->name, intern->msg_ce->name);
-#else
-                              ZSTR_VAL(klass->name),
-                              ZSTR_VAL(intern->msg_ce->name));
-#endif
-      return;
-    }
-    RETURN_ZVAL(val, 1, 0);
-  } else {
-      zend_throw_exception(
-          NULL, "Incorrect map field type.",
-          0 TSRMLS_CC);
-    return;
-  }
-}
-
-PHP_METHOD(Util, checkMapField) {
-  zval* val;
-  PHP_PROTO_LONG key_type, value_type;
-  const zend_class_entry* klass = NULL;
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type,
-                            &value_type, &klass) == FAILURE) {
-    return;
-  }
-  RETURN_ZVAL(val, 1, 0);
-}
diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c
deleted file mode 100644
index 7608fe7..0000000
--- a/php/ext/google/protobuf/upb.c
+++ /dev/null
@@ -1,13302 +0,0 @@
-/* Amalgamated source file */
-#include "upb.h"
-/*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-*   #include "upb/foobar.h"
-*   #include "upb/baz.h"
-*
-*   // MUST be last included header.
-*   #include "upb/port_def.inc"
-*
-*   // Code for this file.
-*   // <...>
-*
-*   // Can be omitted for .c files, required for .h.
-*   #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#ifndef UINTPTR_MAX
-#error must include stdint.h first
-#endif
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-#define UPB_FIELD_AT(msg, fieldtype, offset) \
-  *(fieldtype*)((const char*)(msg) + offset)
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
-  UPB_FIELD_AT(msg, int, case_offset) == case_val                              \
-      ? UPB_FIELD_AT(msg, fieldtype, offset)                                   \
-      : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
-  UPB_FIELD_AT(msg, int, case_offset) = case_val;                             \
-  UPB_FIELD_AT(msg, fieldtype, offset) = value;
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else  /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include <stdio.h>
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include <stdarg.h>
-#include <stdio.h>
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
-    (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated.  This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode.  This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include <math.h>
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-
-#include <string.h>
-
-
-/* Maps descriptor type -> upb field type.  */
-const uint8_t upb_desctype_to_fieldtype[] = {
-  UPB_WIRE_TYPE_END_GROUP,  /* ENDGROUP */
-  UPB_TYPE_DOUBLE,          /* DOUBLE */
-  UPB_TYPE_FLOAT,           /* FLOAT */
-  UPB_TYPE_INT64,           /* INT64 */
-  UPB_TYPE_UINT64,          /* UINT64 */
-  UPB_TYPE_INT32,           /* INT32 */
-  UPB_TYPE_UINT64,          /* FIXED64 */
-  UPB_TYPE_UINT32,          /* FIXED32 */
-  UPB_TYPE_BOOL,            /* BOOL */
-  UPB_TYPE_STRING,          /* STRING */
-  UPB_TYPE_MESSAGE,         /* GROUP */
-  UPB_TYPE_MESSAGE,         /* MESSAGE */
-  UPB_TYPE_BYTES,           /* BYTES */
-  UPB_TYPE_UINT32,          /* UINT32 */
-  UPB_TYPE_ENUM,            /* ENUM */
-  UPB_TYPE_INT32,           /* SFIXED32 */
-  UPB_TYPE_INT64,           /* SFIXED64 */
-  UPB_TYPE_INT32,           /* SINT32 */
-  UPB_TYPE_INT64,           /* SINT64 */
-};
-
-/* Data pertaining to the parse. */
-typedef struct {
-  const char *ptr;           /* Current parsing position. */
-  const char *field_start;   /* Start of this field. */
-  const char *limit;         /* End of delimited region or end of buffer. */
-  upb_arena *arena;
-  int depth;
-  uint32_t end_group;  /* Set to field number of END_GROUP tag, if any. */
-} upb_decstate;
-
-/* Data passed by value to each parsing function. */
-typedef struct {
-  char *msg;
-  const upb_msglayout *layout;
-  upb_decstate *state;
-} upb_decframe;
-
-#define CHK(x) if (!(x)) { return 0; }
-
-static bool upb_skip_unknowngroup(upb_decstate *d, int field_number);
-static bool upb_decode_message(upb_decstate *d, char *msg,
-                               const upb_msglayout *l);
-
-static bool upb_decode_varint(const char **ptr, const char *limit,
-                              uint64_t *val) {
-  uint8_t byte;
-  int bitpos = 0;
-  const char *p = *ptr;
-  *val = 0;
-
-  do {
-    CHK(bitpos < 70 && p < limit);
-    byte = *p;
-    *val |= (uint64_t)(byte & 0x7F) << bitpos;
-    p++;
-    bitpos += 7;
-  } while (byte & 0x80);
-
-  *ptr = p;
-  return true;
-}
-
-static bool upb_decode_varint32(const char **ptr, const char *limit,
-                                uint32_t *val) {
-  uint64_t u64;
-  CHK(upb_decode_varint(ptr, limit, &u64) && u64 <= UINT32_MAX);
-  *val = (uint32_t)u64;
-  return true;
-}
-
-static bool upb_decode_64bit(const char **ptr, const char *limit,
-                             uint64_t *val) {
-  CHK(limit - *ptr >= 8);
-  memcpy(val, *ptr, 8);
-  *ptr += 8;
-  return true;
-}
-
-static bool upb_decode_32bit(const char **ptr, const char *limit,
-                             uint32_t *val) {
-  CHK(limit - *ptr >= 4);
-  memcpy(val, *ptr, 4);
-  *ptr += 4;
-  return true;
-}
-
-static int32_t upb_zzdecode_32(uint32_t n) {
-  return (n >> 1) ^ -(int32_t)(n & 1);
-}
-
-static int64_t upb_zzdecode_64(uint64_t n) {
-  return (n >> 1) ^ -(int64_t)(n & 1);
-}
-
-static bool upb_decode_string(const char **ptr, const char *limit,
-                              int *outlen) {
-  uint32_t len;
-
-  CHK(upb_decode_varint32(ptr, limit, &len) &&
-      len < INT32_MAX &&
-      limit - *ptr >= (int32_t)len);
-
-  *outlen = len;
-  return true;
-}
-
-static void upb_set32(void *msg, size_t ofs, uint32_t val) {
-  memcpy((char*)msg + ofs, &val, sizeof(val));
-}
-
-static bool upb_append_unknown(upb_decstate *d, upb_decframe *frame) {
-  upb_msg_addunknown(frame->msg, d->field_start, d->ptr - d->field_start,
-                     d->arena);
-  return true;
-}
-
-
-static bool upb_skip_unknownfielddata(upb_decstate *d, uint32_t tag,
-                                      uint32_t group_fieldnum) {
-  switch (tag & 7) {
-    case UPB_WIRE_TYPE_VARINT: {
-      uint64_t val;
-      return upb_decode_varint(&d->ptr, d->limit, &val);
-    }
-    case UPB_WIRE_TYPE_32BIT: {
-      uint32_t val;
-      return upb_decode_32bit(&d->ptr, d->limit, &val);
-    }
-    case UPB_WIRE_TYPE_64BIT: {
-      uint64_t val;
-      return upb_decode_64bit(&d->ptr, d->limit, &val);
-    }
-    case UPB_WIRE_TYPE_DELIMITED: {
-      int len;
-      CHK(upb_decode_string(&d->ptr, d->limit, &len));
-      d->ptr += len;
-      return true;
-    }
-    case UPB_WIRE_TYPE_START_GROUP:
-      return upb_skip_unknowngroup(d, tag >> 3);
-    case UPB_WIRE_TYPE_END_GROUP:
-      return (tag >> 3) == group_fieldnum;
-  }
-  return false;
-}
-
-static bool upb_skip_unknowngroup(upb_decstate *d, int field_number) {
-  while (d->ptr < d->limit && d->end_group == 0) {
-    uint32_t tag = 0;
-    CHK(upb_decode_varint32(&d->ptr, d->limit, &tag));
-    CHK(upb_skip_unknownfielddata(d, tag, field_number));
-  }
-
-  CHK(d->end_group == field_number);
-  d->end_group = 0;
-  return true;
-}
-
-static bool upb_array_grow(upb_array *arr, size_t elements, size_t elem_size,
-                           upb_arena *arena) {
-  size_t needed = arr->len + elements;
-  size_t new_size = UPB_MAX(arr->size, 8);
-  size_t new_bytes;
-  size_t old_bytes;
-  void *new_data;
-  upb_alloc *alloc = upb_arena_alloc(arena);
-
-  while (new_size < needed) {
-    new_size *= 2;
-  }
-
-  old_bytes = arr->len * elem_size;
-  new_bytes = new_size * elem_size;
-  new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes);
-  CHK(new_data);
-
-  arr->data = new_data;
-  arr->size = new_size;
-  return true;
-}
-
-static void *upb_array_reserve(upb_array *arr, size_t elements,
-                               size_t elem_size, upb_arena *arena) {
-  if (arr->size - arr->len < elements) {
-    CHK(upb_array_grow(arr, elements, elem_size, arena));
-  }
-  return (char*)arr->data + (arr->len * elem_size);
-}
-
-bool upb_array_add(upb_array *arr, size_t elements, size_t elem_size,
-                   const void *data, upb_arena *arena) {
-  void *dest = upb_array_reserve(arr, elements, elem_size, arena);
-
-  CHK(dest);
-  arr->len += elements;
-  memcpy(dest, data, elements * elem_size);
-
-  return true;
-}
-
-static upb_array *upb_getarr(upb_decframe *frame,
-                             const upb_msglayout_field *field) {
-  UPB_ASSERT(field->label == UPB_LABEL_REPEATED);
-  return *(upb_array**)&frame->msg[field->offset];
-}
-
-static upb_array *upb_getorcreatearr(upb_decframe *frame,
-                                     const upb_msglayout_field *field) {
-  upb_array *arr = upb_getarr(frame, field);
-
-  if (!arr) {
-    arr = upb_array_new(frame->state->arena);
-    CHK(arr);
-    *(upb_array**)&frame->msg[field->offset] = arr;
-  }
-
-  return arr;
-}
-
-static upb_msg *upb_getorcreatemsg(upb_decframe *frame,
-                                   const upb_msglayout_field *field,
-                                   const upb_msglayout **subm) {
-  upb_msg **submsg = (void*)(frame->msg + field->offset);
-  *subm = frame->layout->submsgs[field->submsg_index];
-
-  UPB_ASSERT(field->label != UPB_LABEL_REPEATED);
-
-  if (!*submsg) {
-    *submsg = upb_msg_new(*subm, frame->state->arena);
-    CHK(*submsg);
-  }
-
-  return *submsg;
-}
-
-static upb_msg *upb_addmsg(upb_decframe *frame,
-                           const upb_msglayout_field *field,
-                           const upb_msglayout **subm) {
-  upb_msg *submsg;
-  upb_array *arr = upb_getorcreatearr(frame, field);
-
-  *subm = frame->layout->submsgs[field->submsg_index];
-  submsg = upb_msg_new(*subm, frame->state->arena);
-  CHK(submsg);
-  upb_array_add(arr, 1, sizeof(submsg), &submsg, frame->state->arena);
-
-  return submsg;
-}
-
-static void upb_sethasbit(upb_decframe *frame,
-                          const upb_msglayout_field *field) {
-  int32_t hasbit = field->presence;
-  UPB_ASSERT(field->presence > 0);
-  frame->msg[hasbit / 8] |= (1 << (hasbit % 8));
-}
-
-static void upb_setoneofcase(upb_decframe *frame,
-                             const upb_msglayout_field *field) {
-  UPB_ASSERT(field->presence < 0);
-  upb_set32(frame->msg, ~field->presence, field->number);
-}
-
-static bool upb_decode_addval(upb_decframe *frame,
-                               const upb_msglayout_field *field, void *val,
-                               size_t size) {
-  char *field_mem = frame->msg + field->offset;
-  upb_array *arr;
-
-  if (field->label == UPB_LABEL_REPEATED) {
-    arr = upb_getorcreatearr(frame, field);
-    CHK(arr);
-    field_mem = upb_array_reserve(arr, 1, size, frame->state->arena);
-    CHK(field_mem);
-  }
-
-  memcpy(field_mem, val, size);
-  return true;
-}
-
-static void upb_decode_setpresent(upb_decframe *frame,
-                                  const upb_msglayout_field *field) {
-  if (field->label == UPB_LABEL_REPEATED) {
-   upb_array *arr = upb_getarr(frame, field);
-   UPB_ASSERT(arr->len < arr->size);
-   arr->len++;
-  } else if (field->presence < 0) {
-    upb_setoneofcase(frame, field);
-  } else if (field->presence > 0) {
-    upb_sethasbit(frame, field);
-  }
-}
-
-static bool upb_decode_msgfield(upb_decstate *d, upb_msg *msg,
-                                const upb_msglayout *layout, int limit) {
-  const char* saved_limit = d->limit;
-  d->limit = d->ptr + limit;
-  CHK(--d->depth >= 0);
-  upb_decode_message(d, msg, layout);
-  d->depth++;
-  d->limit = saved_limit;
-  CHK(d->end_group == 0);
-  return true;
-}
-
-static bool upb_decode_groupfield(upb_decstate *d, upb_msg *msg,
-                                  const upb_msglayout *layout,
-                                  int field_number) {
-  CHK(--d->depth >= 0);
-  upb_decode_message(d, msg, layout);
-  d->depth++;
-  CHK(d->end_group == field_number);
-  d->end_group = 0;
-  return true;
-}
-
-static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame,
-                                   const upb_msglayout_field *field) {
-  uint64_t val;
-  CHK(upb_decode_varint(&d->ptr, d->limit, &val));
-
-  switch (field->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM: {
-      uint32_t val32 = (uint32_t)val;
-      CHK(upb_decode_addval(frame, field, &val32, sizeof(val32)));
-      break;
-    }
-    case UPB_DESCRIPTOR_TYPE_BOOL: {
-      bool valbool = val != 0;
-      CHK(upb_decode_addval(frame, field, &valbool, sizeof(valbool)));
-      break;
-    }
-    case UPB_DESCRIPTOR_TYPE_SINT32: {
-      int32_t decoded = upb_zzdecode_32((uint32_t)val);
-      CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded)));
-      break;
-    }
-    case UPB_DESCRIPTOR_TYPE_SINT64: {
-      int64_t decoded = upb_zzdecode_64(val);
-      CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded)));
-      break;
-    }
-    default:
-      return upb_append_unknown(d, frame);
-  }
-
-  upb_decode_setpresent(frame, field);
-  return true;
-}
-
-static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame,
-                                  const upb_msglayout_field *field) {
-  uint64_t val;
-  CHK(upb_decode_64bit(&d->ptr, d->limit, &val));
-
-  switch (field->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-      CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
-      break;
-    default:
-      return upb_append_unknown(d, frame);
-  }
-
-  upb_decode_setpresent(frame, field);
-  return true;
-}
-
-static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame,
-                                  const upb_msglayout_field *field) {
-  uint32_t val;
-  CHK(upb_decode_32bit(&d->ptr, d->limit, &val));
-
-  switch (field->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
-      break;
-    default:
-      return upb_append_unknown(d, frame);
-  }
-
-  upb_decode_setpresent(frame, field);
-  return true;
-}
-
-static bool upb_decode_fixedpacked(upb_decstate *d, upb_array *arr,
-                                   uint32_t len, int elem_size) {
-  size_t elements = len / elem_size;
-
-  CHK((size_t)(elements * elem_size) == len);
-  CHK(upb_array_add(arr, elements, elem_size, d->ptr, d->arena));
-  d->ptr += len;
-
-  return true;
-}
-
-static upb_strview upb_decode_strfield(upb_decstate *d, uint32_t len) {
-  upb_strview ret;
-  ret.data = d->ptr;
-  ret.size = len;
-  d->ptr += len;
-  return ret;
-}
-
-static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
-                               const upb_msglayout_field *field, int len) {
-  upb_array *arr = upb_getorcreatearr(frame, field);
-  CHK(arr);
-
-#define VARINT_CASE(ctype, decode) \
-  VARINT_CASE_EX(ctype, decode, decode)
-
-#define VARINT_CASE_EX(ctype, decode, dtype)                           \
-  {                                                                    \
-    const char *ptr = d->ptr;                                          \
-    const char *limit = ptr + len;                                     \
-    while (ptr < limit) {                                              \
-      uint64_t val;                                                    \
-      ctype decoded;                                                   \
-      CHK(upb_decode_varint(&ptr, limit, &val));                       \
-      decoded = (decode)((dtype)val);                                  \
-      CHK(upb_array_add(arr, 1, sizeof(decoded), &decoded, d->arena)); \
-    }                                                                  \
-    d->ptr = ptr;                                                      \
-    return true;                                                       \
-  }
-
-  switch (field->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_STRING:
-    case UPB_DESCRIPTOR_TYPE_BYTES: {
-      upb_strview str = upb_decode_strfield(d, len);
-      return upb_array_add(arr, 1, sizeof(str), &str, d->arena);
-    }
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      return upb_decode_fixedpacked(d, arr, len, sizeof(int32_t));
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-      return upb_decode_fixedpacked(d, arr, len, sizeof(int64_t));
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      VARINT_CASE(uint32_t, uint32_t);
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      VARINT_CASE(uint64_t, uint64_t);
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      VARINT_CASE(bool, bool);
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      VARINT_CASE_EX(int32_t, upb_zzdecode_32, uint32_t);
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-      VARINT_CASE_EX(int64_t, upb_zzdecode_64, uint64_t);
-    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-      const upb_msglayout *subm;
-      upb_msg *submsg = upb_addmsg(frame, field, &subm);
-      CHK(submsg);
-      return upb_decode_msgfield(d, submsg, subm, len);
-    }
-    case UPB_DESCRIPTOR_TYPE_GROUP:
-      return upb_append_unknown(d, frame);
-  }
-#undef VARINT_CASE
-  UPB_UNREACHABLE();
-}
-
-static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame,
-                                      const upb_msglayout_field *field) {
-  int len;
-
-  CHK(upb_decode_string(&d->ptr, d->limit, &len));
-
-  if (field->label == UPB_LABEL_REPEATED) {
-    return upb_decode_toarray(d, frame, field, len);
-  } else {
-    switch (field->descriptortype) {
-      case UPB_DESCRIPTOR_TYPE_STRING:
-      case UPB_DESCRIPTOR_TYPE_BYTES: {
-        upb_strview str = upb_decode_strfield(d, len);
-        CHK(upb_decode_addval(frame, field, &str, sizeof(str)));
-        break;
-      }
-      case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-        const upb_msglayout *subm;
-        upb_msg *submsg = upb_getorcreatemsg(frame, field, &subm);
-        CHK(submsg);
-        CHK(upb_decode_msgfield(d, submsg, subm, len));
-        break;
-      }
-      default:
-        /* TODO(haberman): should we accept the last element of a packed? */
-        d->ptr += len;
-        return upb_append_unknown(d, frame);
-    }
-    upb_decode_setpresent(frame, field);
-    return true;
-  }
-}
-
-static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
-                                                 uint32_t field_number) {
-  /* Lots of optimization opportunities here. */
-  int i;
-  for (i = 0; i < l->field_count; i++) {
-    if (l->fields[i].number == field_number) {
-      return &l->fields[i];
-    }
-  }
-
-  return NULL;  /* Unknown field. */
-}
-
-static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) {
-  uint32_t tag;
-  const upb_msglayout_field *field;
-  int field_number;
-
-  d->field_start = d->ptr;
-  CHK(upb_decode_varint32(&d->ptr, d->limit, &tag));
-  field_number = tag >> 3;
-  field = upb_find_field(frame->layout, field_number);
-
-  if (field) {
-    switch (tag & 7) {
-      case UPB_WIRE_TYPE_VARINT:
-        return upb_decode_varintfield(d, frame, field);
-      case UPB_WIRE_TYPE_32BIT:
-        return upb_decode_32bitfield(d, frame, field);
-      case UPB_WIRE_TYPE_64BIT:
-        return upb_decode_64bitfield(d, frame, field);
-      case UPB_WIRE_TYPE_DELIMITED:
-        return upb_decode_delimitedfield(d, frame, field);
-      case UPB_WIRE_TYPE_START_GROUP: {
-        const upb_msglayout *layout;
-        upb_msg *group;
-
-        if (field->label == UPB_LABEL_REPEATED) {
-          group = upb_addmsg(frame, field, &layout);
-        } else {
-          group = upb_getorcreatemsg(frame, field, &layout);
-        }
-
-        return upb_decode_groupfield(d, group, layout, field_number);
-      }
-      case UPB_WIRE_TYPE_END_GROUP:
-        d->end_group = field_number;
-        return true;
-      default:
-        CHK(false);
-    }
-  } else {
-    CHK(field_number != 0);
-    CHK(upb_skip_unknownfielddata(d, tag, -1));
-    CHK(upb_append_unknown(d, frame));
-    return true;
-  }
-  UPB_UNREACHABLE();
-}
-
-static bool upb_decode_message(upb_decstate *d, char *msg, const upb_msglayout *l) {
-  upb_decframe frame;
-  frame.msg = msg;
-  frame.layout = l;
-  frame.state = d;
-
-  while (d->ptr < d->limit) {
-    CHK(upb_decode_field(d, &frame));
-  }
-
-  return true;
-}
-
-bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l,
-                upb_arena *arena) {
-  upb_decstate state;
-  state.ptr = buf;
-  state.limit = buf + size;
-  state.arena = arena;
-  state.depth = 64;
-  state.end_group = 0;
-
-  CHK(upb_decode_message(&state, msg, l));
-  return state.end_group == 0;
-}
-
-#undef CHK
-/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
-
-
-#include <string.h>
-
-
-
-#define UPB_PB_VARINT_MAX_LEN 10
-#define CHK(x) do { if (!(x)) { return false; } } while(0)
-
-static size_t upb_encode_varint(uint64_t val, char *buf) {
-  size_t i;
-  if (val < 128) { buf[0] = val; return 1; }
-  i = 0;
-  while (val) {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    buf[i++] = byte;
-  }
-  return i;
-}
-
-static uint32_t upb_zzencode_32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
-static uint64_t upb_zzencode_64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
-
-typedef struct {
-  upb_alloc *alloc;
-  char *buf, *ptr, *limit;
-} upb_encstate;
-
-static size_t upb_roundup_pow2(size_t bytes) {
-  size_t ret = 128;
-  while (ret < bytes) {
-    ret *= 2;
-  }
-  return ret;
-}
-
-static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) {
-  size_t old_size = e->limit - e->buf;
-  size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
-  char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
-  CHK(new_buf);
-
-  /* We want previous data at the end, realloc() put it at the beginning. */
-  if (old_size > 0) {
-    memmove(new_buf + new_size - old_size, e->buf, old_size);
-  }
-
-  e->ptr = new_buf + new_size - (e->limit - e->ptr);
-  e->limit = new_buf + new_size;
-  e->buf = new_buf;
-  return true;
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr.  Returns false if the bytes could not be allocated. */
-static bool upb_encode_reserve(upb_encstate *e, size_t bytes) {
-  CHK(UPB_LIKELY((size_t)(e->ptr - e->buf) >= bytes) ||
-      upb_encode_growbuffer(e, bytes));
-
-  e->ptr -= bytes;
-  return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) {
-  CHK(upb_encode_reserve(e, len));
-  memcpy(e->ptr, data, len);
-  return true;
-}
-
-static bool upb_put_fixed64(upb_encstate *e, uint64_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return upb_put_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool upb_put_fixed32(upb_encstate *e, uint32_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return upb_put_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool upb_put_varint(upb_encstate *e, uint64_t val) {
-  size_t len;
-  char *start;
-  CHK(upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN));
-  len = upb_encode_varint(val, e->ptr);
-  start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
-  memmove(start, e->ptr, len);
-  e->ptr = start;
-  return true;
-}
-
-static bool upb_put_double(upb_encstate *e, double d) {
-  uint64_t u64;
-  UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
-  memcpy(&u64, &d, sizeof(uint64_t));
-  return upb_put_fixed64(e, u64);
-}
-
-static bool upb_put_float(upb_encstate *e, float d) {
-  uint32_t u32;
-  UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
-  memcpy(&u32, &d, sizeof(uint32_t));
-  return upb_put_fixed32(e, u32);
-}
-
-static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) {
-  uint32_t ret;
-  uint32_t offset = ~f->presence;
-  memcpy(&ret, msg + offset, sizeof(ret));
-  return ret;
-}
-
-static bool upb_readhasbit(const char *msg, const upb_msglayout_field *f) {
-  uint32_t hasbit = f->presence;
-  UPB_ASSERT(f->presence > 0);
-  return msg[hasbit / 8] & (1 << (hasbit % 8));
-}
-
-static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) {
-  return upb_put_varint(e, (field_number << 3) | wire_type);
-}
-
-static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr,
-                               size_t size) {
-  size_t bytes = arr->len * size;
-  return upb_put_bytes(e, arr->data, bytes) && upb_put_varint(e, bytes);
-}
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
-                        const upb_msglayout *m, size_t *size);
-
-static bool upb_encode_array(upb_encstate *e, const char *field_mem,
-                             const upb_msglayout *m,
-                             const upb_msglayout_field *f) {
-  const upb_array *arr = *(const upb_array**)field_mem;
-
-  if (arr == NULL || arr->len == 0) {
-    return true;
-  }
-
-#define VARINT_CASE(ctype, encode) { \
-  ctype *start = arr->data; \
-  ctype *ptr = start + arr->len; \
-  size_t pre_len = e->limit - e->ptr; \
-  do { \
-    ptr--; \
-    CHK(upb_put_varint(e, encode)); \
-  } while (ptr != start); \
-  CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \
-} \
-break; \
-do { ; } while(0)
-
-  switch (f->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      CHK(upb_put_fixedarray(e, arr, sizeof(double)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      CHK(upb_put_fixedarray(e, arr, sizeof(float)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      VARINT_CASE(uint64_t, *ptr);
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-      VARINT_CASE(uint32_t, *ptr);
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      VARINT_CASE(int32_t, (int64_t)*ptr);
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      VARINT_CASE(bool, *ptr);
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      VARINT_CASE(int32_t, upb_zzencode_32(*ptr));
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-      VARINT_CASE(int64_t, upb_zzencode_64(*ptr));
-    case UPB_DESCRIPTOR_TYPE_STRING:
-    case UPB_DESCRIPTOR_TYPE_BYTES: {
-      upb_strview *start = arr->data;
-      upb_strview *ptr = start + arr->len;
-      do {
-        ptr--;
-        CHK(upb_put_bytes(e, ptr->data, ptr->size) &&
-            upb_put_varint(e, ptr->size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-      } while (ptr != start);
-      return true;
-    }
-    case UPB_DESCRIPTOR_TYPE_GROUP: {
-      void **start = arr->data;
-      void **ptr = start + arr->len;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      do {
-        size_t size;
-        ptr--;
-        CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
-            upb_encode_message(e, *ptr, subm, &size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP));
-      } while (ptr != start);
-      return true;
-    }
-    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-      void **start = arr->data;
-      void **ptr = start + arr->len;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      do {
-        size_t size;
-        ptr--;
-        CHK(upb_encode_message(e, *ptr, subm, &size) &&
-            upb_put_varint(e, size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-      } while (ptr != start);
-      return true;
-    }
-  }
-#undef VARINT_CASE
-
-  /* We encode all primitive arrays as packed, regardless of what was specified
-   * in the .proto file.  Could special case 1-sized arrays. */
-  CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-  return true;
-}
-
-static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
-                                   const upb_msglayout *m,
-                                   const upb_msglayout_field *f,
-                                   bool skip_zero_value) {
-#define CASE(ctype, type, wire_type, encodeval) do { \
-  ctype val = *(ctype*)field_mem; \
-  if (skip_zero_value && val == 0) { \
-    return true; \
-  } \
-  return upb_put_ ## type(e, encodeval) && \
-      upb_put_tag(e, f->number, wire_type); \
-} while(0)
-
-  switch (f->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-      CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val));
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-      CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val));
-    case UPB_DESCRIPTOR_TYPE_STRING:
-    case UPB_DESCRIPTOR_TYPE_BYTES: {
-      upb_strview view = *(upb_strview*)field_mem;
-      if (skip_zero_value && view.size == 0) {
-        return true;
-      }
-      return upb_put_bytes(e, view.data, view.size) &&
-          upb_put_varint(e, view.size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
-    }
-    case UPB_DESCRIPTOR_TYPE_GROUP: {
-      size_t size;
-      void *submsg = *(void **)field_mem;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      if (submsg == NULL) {
-        return true;
-      }
-      return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
-          upb_encode_message(e, submsg, subm, &size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
-    }
-    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-      size_t size;
-      void *submsg = *(void **)field_mem;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      if (submsg == NULL) {
-        return true;
-      }
-      return upb_encode_message(e, submsg, subm, &size) &&
-          upb_put_varint(e, size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
-    }
-  }
-#undef CASE
-  UPB_UNREACHABLE();
-}
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
-                        const upb_msglayout *m, size_t *size) {
-  int i;
-  size_t pre_len = e->limit - e->ptr;
-  const char *unknown;
-  size_t unknown_size;
-
-  for (i = m->field_count - 1; i >= 0; i--) {
-    const upb_msglayout_field *f = &m->fields[i];
-
-    if (f->label == UPB_LABEL_REPEATED) {
-      CHK(upb_encode_array(e, msg + f->offset, m, f));
-    } else {
-      bool skip_empty = false;
-      if (f->presence == 0) {
-        /* Proto3 presence. */
-        skip_empty = true;
-      } else if (f->presence > 0) {
-        /* Proto2 presence: hasbit. */
-        if (!upb_readhasbit(msg, f)) {
-          continue;
-        }
-      } else {
-        /* Field is in a oneof. */
-        if (upb_readcase(msg, f) != f->number) {
-          continue;
-        }
-      }
-      CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, skip_empty));
-    }
-  }
-
-  unknown = upb_msg_getunknown(msg, &unknown_size);
-
-  if (unknown) {
-    upb_put_bytes(e, unknown, unknown_size);
-  }
-
-  *size = (e->limit - e->ptr) - pre_len;
-  return true;
-}
-
-char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena,
-                 size_t *size) {
-  upb_encstate e;
-  e.alloc = upb_arena_alloc(arena);
-  e.buf = NULL;
-  e.limit = NULL;
-  e.ptr = NULL;
-
-  if (!upb_encode_message(&e, msg, m, size)) {
-    *size = 0;
-    return NULL;
-  }
-
-  *size = e.limit - e.ptr;
-
-  if (*size == 0) {
-    static char ch;
-    return &ch;
-  } else {
-    UPB_ASSERT(e.ptr);
-    return e.ptr;
-  }
-}
-
-#undef CHK
-
-
-
-
-#define VOIDPTR_AT(msg, ofs) (void*)((char*)msg + (int)ofs)
-
-/* Internal members of a upb_msg.  We can change this without breaking binary
- * compatibility.  We put these before the user's data.  The user's upb_msg*
- * points after the upb_msg_internal. */
-
-/* Used when a message is not extendable. */
-typedef struct {
-  char *unknown;
-  size_t unknown_len;
-  size_t unknown_size;
-} upb_msg_internal;
-
-/* Used when a message is extendable. */
-typedef struct {
-  upb_inttable *extdict;
-  upb_msg_internal base;
-} upb_msg_internal_withext;
-
-static int upb_msg_internalsize(const upb_msglayout *l) {
-  return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
-}
-
-static size_t upb_msg_sizeof(const upb_msglayout *l) {
-  return l->size + upb_msg_internalsize(l);
-}
-
-static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
-  return VOIDPTR_AT(msg, -sizeof(upb_msg_internal));
-}
-
-static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
-  return VOIDPTR_AT(msg, -sizeof(upb_msg_internal));
-}
-
-static upb_msg_internal_withext *upb_msg_getinternalwithext(
-    upb_msg *msg, const upb_msglayout *l) {
-  UPB_ASSERT(l->extendable);
-  return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext));
-}
-
-upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) {
-  upb_alloc *alloc = upb_arena_alloc(a);
-  void *mem = upb_malloc(alloc, upb_msg_sizeof(l));
-  upb_msg_internal *in;
-  upb_msg *msg;
-
-  if (!mem) {
-    return NULL;
-  }
-
-  msg = VOIDPTR_AT(mem, upb_msg_internalsize(l));
-
-  /* Initialize normal members. */
-  memset(msg, 0, l->size);
-
-  /* Initialize internal members. */
-  in = upb_msg_getinternal(msg);
-  in->unknown = NULL;
-  in->unknown_len = 0;
-  in->unknown_size = 0;
-
-  if (l->extendable) {
-    upb_msg_getinternalwithext(msg, l)->extdict = NULL;
-  }
-
-  return msg;
-}
-
-upb_array *upb_array_new(upb_arena *a) {
-  upb_array *ret = upb_arena_malloc(a, sizeof(upb_array));
-
-  if (!ret) {
-    return NULL;
-  }
-
-  ret->data = NULL;
-  ret->len = 0;
-  ret->size = 0;
-
-  return ret;
-}
-
-void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                        upb_arena *arena) {
-  upb_msg_internal *in = upb_msg_getinternal(msg);
-  if (len > in->unknown_size - in->unknown_len) {
-    upb_alloc *alloc = upb_arena_alloc(arena);
-    size_t need = in->unknown_size + len;
-    size_t newsize = UPB_MAX(in->unknown_size * 2, need);
-    in->unknown = upb_realloc(alloc, in->unknown, in->unknown_size, newsize);
-    in->unknown_size = newsize;
-  }
-  memcpy(in->unknown + in->unknown_len, data, len);
-  in->unknown_len += len;
-}
-
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
-  const upb_msg_internal* in = upb_msg_getinternal_const(msg);
-  *len = in->unknown_len;
-  return in->unknown;
-}
-
-#undef VOIDPTR_AT
-
-
-#ifdef UPB_MSVC_VSNPRINTF
-/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and
- * vsnprintf. To support them, missing functions are manually implemented
- * using the existing secure functions. */
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) {
-  if (!s) {
-    return _vscprintf(format, arg);
-  }
-  int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg);
-  if (ret < 0) {
-	ret = _vscprintf(format, arg);
-  }
-  return ret;
-}
-
-int msvc_snprintf(char* s, size_t n, const char* format, ...) {
-  va_list arg;
-  va_start(arg, format);
-  int ret = msvc_vsnprintf(s, n, format, arg);
-  va_end(arg);
-  return ret;
-}
-#endif
-/*
-** upb_table Implementation
-**
-** Implementation is heavily inspired by Lua's ltable.c.
-*/
-
-
-#include <string.h>
-
-
-#define UPB_MAXARRSIZE 16  /* 64k. */
-
-/* From Chromium. */
-#define ARRAY_SIZE(x) \
-    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
-
-static void upb_check_alloc(upb_table *t, upb_alloc *a) {
-  UPB_UNUSED(t);
-  UPB_UNUSED(a);
-  UPB_ASSERT_DEBUGVAR(t->alloc == a);
-}
-
-static const double MAX_LOAD = 0.85;
-
-/* The minimum utilization of the array part of a mixed hash/array table.  This
- * is a speed/memory-usage tradeoff (though it's not straightforward because of
- * cache effects).  The lower this is, the more memory we'll use. */
-static const double MIN_DENSITY = 0.1;
-
-bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
-
-int log2ceil(uint64_t v) {
-  int ret = 0;
-  bool pow2 = is_pow2(v);
-  while (v >>= 1) ret++;
-  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
-  return UPB_MIN(UPB_MAXARRSIZE, ret);
-}
-
-char *upb_strdup(const char *s, upb_alloc *a) {
-  return upb_strdup2(s, strlen(s), a);
-}
-
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
-  size_t n;
-  char *p;
-
-  /* Prevent overflow errors. */
-  if (len == SIZE_MAX) return NULL;
-  /* Always null-terminate, even if binary data; but don't rely on the input to
-   * have a null-terminating byte since it may be a raw binary buffer. */
-  n = len + 1;
-  p = upb_malloc(a, n);
-  if (p) {
-    memcpy(p, s, len);
-    p[len] = 0;
-  }
-  return p;
-}
-
-/* A type to represent the lookup key of either a strtable or an inttable. */
-typedef union {
-  uintptr_t num;
-  struct {
-    const char *str;
-    size_t len;
-  } str;
-} lookupkey_t;
-
-static lookupkey_t strkey2(const char *str, size_t len) {
-  lookupkey_t k;
-  k.str.str = str;
-  k.str.len = len;
-  return k;
-}
-
-static lookupkey_t intkey(uintptr_t key) {
-  lookupkey_t k;
-  k.num = key;
-  return k;
-}
-
-typedef uint32_t hashfunc_t(upb_tabkey key);
-typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
-
-/* Base table (shared code) ***************************************************/
-
-/* For when we need to cast away const. */
-static upb_tabent *mutable_entries(upb_table *t) {
-  return (upb_tabent*)t->entries;
-}
-
-static bool isfull(upb_table *t) {
-  if (upb_table_size(t) == 0) {
-    return true;
-  } else {
-    return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
-  }
-}
-
-static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2,
-                 upb_alloc *a) {
-  size_t bytes;
-
-  t->count = 0;
-  t->ctype = ctype;
-  t->size_lg2 = size_lg2;
-  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
-#ifndef NDEBUG
-  t->alloc = a;
-#endif
-  bytes = upb_table_size(t) * sizeof(upb_tabent);
-  if (bytes > 0) {
-    t->entries = upb_malloc(a, bytes);
-    if (!t->entries) return false;
-    memset(mutable_entries(t), 0, bytes);
-  } else {
-    t->entries = NULL;
-  }
-  return true;
-}
-
-static void uninit(upb_table *t, upb_alloc *a) {
-  upb_check_alloc(t, a);
-  upb_free(a, mutable_entries(t));
-}
-
-static upb_tabent *emptyent(upb_table *t) {
-  upb_tabent *e = mutable_entries(t) + upb_table_size(t);
-  while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); }
-}
-
-static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
-  return (upb_tabent*)upb_getentry(t, hash);
-}
-
-static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
-                                   uint32_t hash, eqlfunc_t *eql) {
-  const upb_tabent *e;
-
-  if (t->size_lg2 == 0) return NULL;
-  e = upb_getentry(t, hash);
-  if (upb_tabent_isempty(e)) return NULL;
-  while (1) {
-    if (eql(e->key, key)) return e;
-    if ((e = e->next) == NULL) return NULL;
-  }
-}
-
-static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
-                                     uint32_t hash, eqlfunc_t *eql) {
-  return (upb_tabent*)findentry(t, key, hash, eql);
-}
-
-static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
-                   uint32_t hash, eqlfunc_t *eql) {
-  const upb_tabent *e = findentry(t, key, hash, eql);
-  if (e) {
-    if (v) {
-      _upb_value_setval(v, e->val.val, t->ctype);
-    }
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* The given key must not already exist in the table. */
-static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
-                   upb_value val, uint32_t hash,
-                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
-  upb_tabent *mainpos_e;
-  upb_tabent *our_e;
-
-  UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
-  UPB_ASSERT_DEBUGVAR(val.ctype == t->ctype);
-
-  t->count++;
-  mainpos_e = getentry_mutable(t, hash);
-  our_e = mainpos_e;
-
-  if (upb_tabent_isempty(mainpos_e)) {
-    /* Our main position is empty; use it. */
-    our_e->next = NULL;
-  } else {
-    /* Collision. */
-    upb_tabent *new_e = emptyent(t);
-    /* Head of collider's chain. */
-    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
-    if (chain == mainpos_e) {
-      /* Existing ent is in its main posisiton (it has the same hash as us, and
-       * is the head of our chain).  Insert to new ent and append to this chain. */
-      new_e->next = mainpos_e->next;
-      mainpos_e->next = new_e;
-      our_e = new_e;
-    } else {
-      /* Existing ent is not in its main position (it is a node in some other
-       * chain).  This implies that no existing ent in the table has our hash.
-       * Evict it (updating its chain) and use its ent for head of our chain. */
-      *new_e = *mainpos_e;  /* copies next. */
-      while (chain->next != mainpos_e) {
-        chain = (upb_tabent*)chain->next;
-        UPB_ASSERT(chain);
-      }
-      chain->next = new_e;
-      our_e = mainpos_e;
-      our_e->next = NULL;
-    }
-  }
-  our_e->key = tabkey;
-  our_e->val.val = val.val;
-  UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
-}
-
-static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
-               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
-  upb_tabent *chain = getentry_mutable(t, hash);
-  if (upb_tabent_isempty(chain)) return false;
-  if (eql(chain->key, key)) {
-    /* Element to remove is at the head of its chain. */
-    t->count--;
-    if (val) _upb_value_setval(val, chain->val.val, t->ctype);
-    if (removed) *removed = chain->key;
-    if (chain->next) {
-      upb_tabent *move = (upb_tabent*)chain->next;
-      *chain = *move;
-      move->key = 0;  /* Make the slot empty. */
-    } else {
-      chain->key = 0;  /* Make the slot empty. */
-    }
-    return true;
-  } else {
-    /* Element to remove is either in a non-head position or not in the
-     * table. */
-    while (chain->next && !eql(chain->next->key, key)) {
-      chain = (upb_tabent*)chain->next;
-    }
-    if (chain->next) {
-      /* Found element to remove. */
-      upb_tabent *rm = (upb_tabent*)chain->next;
-      t->count--;
-      if (val) _upb_value_setval(val, chain->next->val.val, t->ctype);
-      if (removed) *removed = rm->key;
-      rm->key = 0;  /* Make the slot empty. */
-      chain->next = rm->next;
-      return true;
-    } else {
-      /* Element to remove is not in the table. */
-      return false;
-    }
-  }
-}
-
-static size_t next(const upb_table *t, size_t i) {
-  do {
-    if (++i >= upb_table_size(t))
-      return SIZE_MAX;
-  } while(upb_tabent_isempty(&t->entries[i]));
-
-  return i;
-}
-
-static size_t begin(const upb_table *t) {
-  return next(t, -1);
-}
-
-
-/* upb_strtable ***************************************************************/
-
-/* A simple "subclass" of upb_table that only adds a hash function for strings. */
-
-static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
-  uint32_t len = (uint32_t) k2.str.len;
-  char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
-  if (str == NULL) return 0;
-  memcpy(str, &len, sizeof(uint32_t));
-  memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
-  str[sizeof(uint32_t) + k2.str.len] = '\0';
-  return (uintptr_t)str;
-}
-
-static uint32_t strhash(upb_tabkey key) {
-  uint32_t len;
-  char *str = upb_tabstr(key, &len);
-  return upb_murmur_hash2(str, len, 0);
-}
-
-static bool streql(upb_tabkey k1, lookupkey_t k2) {
-  uint32_t len;
-  char *str = upb_tabstr(k1, &len);
-  return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
-}
-
-bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
-  return init(&t->t, ctype, 2, a);
-}
-
-void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
-  size_t i;
-  for (i = 0; i < upb_table_size(&t->t); i++)
-    upb_free(a, (void*)t->t.entries[i].key);
-  uninit(&t->t, a);
-}
-
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
-  upb_strtable new_table;
-  upb_strtable_iter i;
-
-  upb_check_alloc(&t->t, a);
-
-  if (!init(&new_table.t, t->t.ctype, size_lg2, a))
-    return false;
-  upb_strtable_begin(&i, t);
-  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
-    upb_strtable_insert3(
-        &new_table,
-        upb_strtable_iter_key(&i),
-        upb_strtable_iter_keylength(&i),
-        upb_strtable_iter_value(&i),
-        a);
-  }
-  upb_strtable_uninit2(t, a);
-  *t = new_table;
-  return true;
-}
-
-bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
-                          upb_value v, upb_alloc *a) {
-  lookupkey_t key;
-  upb_tabkey tabkey;
-  uint32_t hash;
-
-  upb_check_alloc(&t->t, a);
-
-  if (isfull(&t->t)) {
-    /* Need to resize.  New table of double the size, add old elements to it. */
-    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
-      return false;
-    }
-  }
-
-  key = strkey2(k, len);
-  tabkey = strcopy(key, a);
-  if (tabkey == 0) return false;
-
-  hash = upb_murmur_hash2(key.str.str, key.str.len, 0);
-  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
-  return true;
-}
-
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
-                          upb_value *v) {
-  uint32_t hash = upb_murmur_hash2(key, len, 0);
-  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
-}
-
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
-                         upb_value *val, upb_alloc *alloc) {
-  uint32_t hash = upb_murmur_hash2(key, len, 0);
-  upb_tabkey tabkey;
-  if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
-    upb_free(alloc, (void*)tabkey);
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* Iteration */
-
-static const upb_tabent *str_tabent(const upb_strtable_iter *i) {
-  return &i->t->t.entries[i->index];
-}
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
-  i->t = t;
-  i->index = begin(&t->t);
-}
-
-void upb_strtable_next(upb_strtable_iter *i) {
-  i->index = next(&i->t->t, i->index);
-}
-
-bool upb_strtable_done(const upb_strtable_iter *i) {
-  if (!i->t) return true;
-  return i->index >= upb_table_size(&i->t->t) ||
-         upb_tabent_isempty(str_tabent(i));
-}
-
-const char *upb_strtable_iter_key(const upb_strtable_iter *i) {
-  UPB_ASSERT(!upb_strtable_done(i));
-  return upb_tabstr(str_tabent(i)->key, NULL);
-}
-
-size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) {
-  uint32_t len;
-  UPB_ASSERT(!upb_strtable_done(i));
-  upb_tabstr(str_tabent(i)->key, &len);
-  return len;
-}
-
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
-  UPB_ASSERT(!upb_strtable_done(i));
-  return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype);
-}
-
-void upb_strtable_iter_setdone(upb_strtable_iter *i) {
-  i->t = NULL;
-  i->index = SIZE_MAX;
-}
-
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
-                               const upb_strtable_iter *i2) {
-  if (upb_strtable_done(i1) && upb_strtable_done(i2))
-    return true;
-  return i1->t == i2->t && i1->index == i2->index;
-}
-
-
-/* upb_inttable ***************************************************************/
-
-/* For inttables we use a hybrid structure where small keys are kept in an
- * array and large keys are put in the hash table. */
-
-static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
-
-static bool inteql(upb_tabkey k1, lookupkey_t k2) {
-  return k1 == k2.num;
-}
-
-static upb_tabval *mutable_array(upb_inttable *t) {
-  return (upb_tabval*)t->array;
-}
-
-static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
-  if (key < t->array_size) {
-    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
-  } else {
-    upb_tabent *e =
-        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
-    return e ? &e->val : NULL;
-  }
-}
-
-static const upb_tabval *inttable_val_const(const upb_inttable *t,
-                                            uintptr_t key) {
-  return inttable_val((upb_inttable*)t, key);
-}
-
-size_t upb_inttable_count(const upb_inttable *t) {
-  return t->t.count + t->array_count;
-}
-
-static void check(upb_inttable *t) {
-  UPB_UNUSED(t);
-#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
-  {
-    /* This check is very expensive (makes inserts/deletes O(N)). */
-    size_t count = 0;
-    upb_inttable_iter i;
-    upb_inttable_begin(&i, t);
-    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
-      UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
-    }
-    UPB_ASSERT(count == upb_inttable_count(t));
-  }
-#endif
-}
-
-bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
-                            size_t asize, int hsize_lg2, upb_alloc *a) {
-  size_t array_bytes;
-
-  if (!init(&t->t, ctype, hsize_lg2, a)) return false;
-  /* Always make the array part at least 1 long, so that we know key 0
-   * won't be in the hash part, which simplifies things. */
-  t->array_size = UPB_MAX(1, asize);
-  t->array_count = 0;
-  array_bytes = t->array_size * sizeof(upb_value);
-  t->array = upb_malloc(a, array_bytes);
-  if (!t->array) {
-    uninit(&t->t, a);
-    return false;
-  }
-  memset(mutable_array(t), 0xff, array_bytes);
-  check(t);
-  return true;
-}
-
-bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
-  return upb_inttable_sizedinit(t, ctype, 0, 4, a);
-}
-
-void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
-  uninit(&t->t, a);
-  upb_free(a, mutable_array(t));
-}
-
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
-                          upb_alloc *a) {
-  upb_tabval tabval;
-  tabval.val = val.val;
-  UPB_ASSERT(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
-
-  upb_check_alloc(&t->t, a);
-
-  if (key < t->array_size) {
-    UPB_ASSERT(!upb_arrhas(t->array[key]));
-    t->array_count++;
-    mutable_array(t)[key].val = val.val;
-  } else {
-    if (isfull(&t->t)) {
-      /* Need to resize the hash part, but we re-use the array part. */
-      size_t i;
-      upb_table new_table;
-
-      if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) {
-        return false;
-      }
-
-      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
-        const upb_tabent *e = &t->t.entries[i];
-        uint32_t hash;
-        upb_value v;
-
-        _upb_value_setval(&v, e->val.val, t->t.ctype);
-        hash = upb_inthash(e->key);
-        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
-      }
-
-      UPB_ASSERT(t->t.count == new_table.count);
-
-      uninit(&t->t, a);
-      t->t = new_table;
-    }
-    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
-  }
-  check(t);
-  return true;
-}
-
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
-  const upb_tabval *table_v = inttable_val_const(t, key);
-  if (!table_v) return false;
-  if (v) _upb_value_setval(v, table_v->val, t->t.ctype);
-  return true;
-}
-
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
-  upb_tabval *table_v = inttable_val(t, key);
-  if (!table_v) return false;
-  table_v->val = val.val;
-  return true;
-}
-
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
-  bool success;
-  if (key < t->array_size) {
-    if (upb_arrhas(t->array[key])) {
-      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
-      t->array_count--;
-      if (val) {
-        _upb_value_setval(val, t->array[key].val, t->t.ctype);
-      }
-      mutable_array(t)[key] = empty;
-      success = true;
-    } else {
-      success = false;
-    }
-  } else {
-    success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
-  }
-  check(t);
-  return success;
-}
-
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
-  upb_check_alloc(&t->t, a);
-  return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
-}
-
-upb_value upb_inttable_pop(upb_inttable *t) {
-  upb_value val;
-  bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
-  UPB_ASSERT(ok);
-  return val;
-}
-
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
-                             upb_alloc *a) {
-  upb_check_alloc(&t->t, a);
-  return upb_inttable_insert2(t, (uintptr_t)key, val, a);
-}
-
-bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
-                            upb_value *v) {
-  return upb_inttable_lookup(t, (uintptr_t)key, v);
-}
-
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
-  return upb_inttable_remove(t, (uintptr_t)key, val);
-}
-
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
-  /* A power-of-two histogram of the table keys. */
-  size_t counts[UPB_MAXARRSIZE + 1] = {0};
-
-  /* The max key in each bucket. */
-  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
-
-  upb_inttable_iter i;
-  size_t arr_count;
-  int size_lg2;
-  upb_inttable new_t;
-
-  upb_check_alloc(&t->t, a);
-
-  upb_inttable_begin(&i, t);
-  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    uintptr_t key = upb_inttable_iter_key(&i);
-    int bucket = log2ceil(key);
-    max[bucket] = UPB_MAX(max[bucket], key);
-    counts[bucket]++;
-  }
-
-  /* Find the largest power of two that satisfies the MIN_DENSITY
-   * definition (while actually having some keys). */
-  arr_count = upb_inttable_count(t);
-
-  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
-    if (counts[size_lg2] == 0) {
-      /* We can halve again without losing any entries. */
-      continue;
-    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
-      break;
-    }
-
-    arr_count -= counts[size_lg2];
-  }
-
-  UPB_ASSERT(arr_count <= upb_inttable_count(t));
-
-  {
-    /* Insert all elements into new, perfectly-sized table. */
-    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
-    size_t hash_count = upb_inttable_count(t) - arr_count;
-    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
-    int hashsize_lg2 = log2ceil(hash_size);
-
-    upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a);
-    upb_inttable_begin(&i, t);
-    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-      uintptr_t k = upb_inttable_iter_key(&i);
-      upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
-    }
-    UPB_ASSERT(new_t.array_size == arr_size);
-    UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
-  }
-  upb_inttable_uninit2(t, a);
-  *t = new_t;
-}
-
-/* Iteration. */
-
-static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
-  UPB_ASSERT(!i->array_part);
-  return &i->t->t.entries[i->index];
-}
-
-static upb_tabval int_arrent(const upb_inttable_iter *i) {
-  UPB_ASSERT(i->array_part);
-  return i->t->array[i->index];
-}
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
-  i->t = t;
-  i->index = -1;
-  i->array_part = true;
-  upb_inttable_next(i);
-}
-
-void upb_inttable_next(upb_inttable_iter *iter) {
-  const upb_inttable *t = iter->t;
-  if (iter->array_part) {
-    while (++iter->index < t->array_size) {
-      if (upb_arrhas(int_arrent(iter))) {
-        return;
-      }
-    }
-    iter->array_part = false;
-    iter->index = begin(&t->t);
-  } else {
-    iter->index = next(&t->t, iter->index);
-  }
-}
-
-bool upb_inttable_done(const upb_inttable_iter *i) {
-  if (!i->t) return true;
-  if (i->array_part) {
-    return i->index >= i->t->array_size ||
-           !upb_arrhas(int_arrent(i));
-  } else {
-    return i->index >= upb_table_size(&i->t->t) ||
-           upb_tabent_isempty(int_tabent(i));
-  }
-}
-
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
-  UPB_ASSERT(!upb_inttable_done(i));
-  return i->array_part ? i->index : int_tabent(i)->key;
-}
-
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
-  UPB_ASSERT(!upb_inttable_done(i));
-  return _upb_value_val(
-      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val,
-      i->t->t.ctype);
-}
-
-void upb_inttable_iter_setdone(upb_inttable_iter *i) {
-  i->t = NULL;
-  i->index = SIZE_MAX;
-  i->array_part = false;
-}
-
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
-                                          const upb_inttable_iter *i2) {
-  if (upb_inttable_done(i1) && upb_inttable_done(i2))
-    return true;
-  return i1->t == i2->t && i1->index == i2->index &&
-         i1->array_part == i2->array_part;
-}
-
-#if defined(UPB_UNALIGNED_READS_OK) || defined(__s390x__)
-/* -----------------------------------------------------------------------------
- * MurmurHash2, by Austin Appleby (released as public domain).
- * Reformatted and C99-ified by Joshua Haberman.
- * Note - This code makes a few assumptions about how your machine behaves -
- *   1. We can read a 4-byte value from any address without crashing
- *   2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
- * And it has a few limitations -
- *   1. It will not work incrementally.
- *   2. It will not produce the same results on little-endian and big-endian
- *      machines. */
-uint32_t upb_murmur_hash2(const void *key, size_t len, uint32_t seed) {
-  /* 'm' and 'r' are mixing constants generated offline.
-   * They're not really 'magic', they just happen to work well. */
-  const uint32_t m = 0x5bd1e995;
-  const int32_t r = 24;
-
-  /* Initialize the hash to a 'random' value */
-  uint32_t h = seed ^ len;
-
-  /* Mix 4 bytes at a time into the hash */
-  const uint8_t * data = (const uint8_t *)key;
-  while(len >= 4) {
-    uint32_t k = *(uint32_t *)data;
-
-    k *= m;
-    k ^= k >> r;
-    k *= m;
-
-    h *= m;
-    h ^= k;
-
-    data += 4;
-    len -= 4;
-  }
-
-  /* Handle the last few bytes of the input array */
-  switch(len) {
-    case 3: h ^= data[2] << 16;
-    case 2: h ^= data[1] << 8;
-    case 1: h ^= data[0]; h *= m;
-  };
-
-  /* Do a few final mixes of the hash to ensure the last few
-   * bytes are well-incorporated. */
-  h ^= h >> 13;
-  h *= m;
-  h ^= h >> 15;
-
-  return h;
-}
-
-#else /* !UPB_UNALIGNED_READS_OK */
-
-/* -----------------------------------------------------------------------------
- * MurmurHashAligned2, by Austin Appleby
- * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
- * on certain platforms.
- * Performance will be lower than MurmurHash2 */
-
-#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
-
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed) {
-  const uint32_t m = 0x5bd1e995;
-  const int32_t r = 24;
-  const uint8_t * data = (const uint8_t *)key;
-  uint32_t h = (uint32_t)(seed ^ len);
-  uint8_t align = (uintptr_t)data & 3;
-
-  if(align && (len >= 4)) {
-    /* Pre-load the temp registers */
-    uint32_t t = 0, d = 0;
-    int32_t sl;
-    int32_t sr;
-
-    switch(align) {
-      case 1: t |= data[2] << 16;
-      case 2: t |= data[1] << 8;
-      case 3: t |= data[0];
-    }
-
-    t <<= (8 * align);
-
-    data += 4-align;
-    len -= 4-align;
-
-    sl = 8 * (4-align);
-    sr = 8 * align;
-
-    /* Mix */
-
-    while(len >= 4) {
-      uint32_t k;
-
-      d = *(uint32_t *)data;
-      t = (t >> sr) | (d << sl);
-
-      k = t;
-
-      MIX(h,k,m);
-
-      t = d;
-
-      data += 4;
-      len -= 4;
-    }
-
-    /* Handle leftover data in temp registers */
-
-    d = 0;
-
-    if(len >= align) {
-      uint32_t k;
-
-      switch(align) {
-        case 3: d |= data[2] << 16;
-        case 2: d |= data[1] << 8;
-        case 1: d |= data[0];
-      }
-
-      k = (t >> sr) | (d << sl);
-      MIX(h,k,m);
-
-      data += align;
-      len -= align;
-
-      /* ----------
-       * Handle tail bytes */
-
-      switch(len) {
-        case 3: h ^= data[2] << 16;
-        case 2: h ^= data[1] << 8;
-        case 1: h ^= data[0]; h *= m;
-      };
-    } else {
-      switch(len) {
-        case 3: d |= data[2] << 16;
-        case 2: d |= data[1] << 8;
-        case 1: d |= data[0];
-        case 0: h ^= (t >> sr) | (d << sl); h *= m;
-      }
-    }
-
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-  } else {
-    while(len >= 4) {
-      uint32_t k = *(uint32_t *)data;
-
-      MIX(h,k,m);
-
-      data += 4;
-      len -= 4;
-    }
-
-    /* ----------
-     * Handle tail bytes */
-
-    switch(len) {
-      case 3: h ^= data[2] << 16;
-      case 2: h ^= data[1] << 8;
-      case 1: h ^= data[0]; h *= m;
-    };
-
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-  }
-}
-#undef MIX
-
-#endif /* UPB_UNALIGNED_READS_OK */
-
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-/* Guarantee null-termination and provide ellipsis truncation.
- * It may be tempting to "optimize" this by initializing these final
- * four bytes up-front and then being careful never to overwrite them,
- * this is safer and simpler. */
-static void nullz(upb_status *status) {
-  const char *ellipsis = "...";
-  size_t len = strlen(ellipsis);
-  UPB_ASSERT(sizeof(status->msg) > len);
-  memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len);
-}
-
-/* upb_status *****************************************************************/
-
-void upb_status_clear(upb_status *status) {
-  if (!status) return;
-  status->ok = true;
-  status->msg[0] = '\0';
-}
-
-bool upb_ok(const upb_status *status) { return status->ok; }
-
-const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
-
-void upb_status_seterrmsg(upb_status *status, const char *msg) {
-  if (!status) return;
-  status->ok = false;
-  strncpy(status->msg, msg, sizeof(status->msg));
-  nullz(status);
-}
-
-void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  upb_status_vseterrf(status, fmt, args);
-  va_end(args);
-}
-
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
-  if (!status) return;
-  status->ok = false;
-  _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
-  nullz(status);
-}
-
-/* upb_alloc ******************************************************************/
-
-static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                                  size_t size) {
-  UPB_UNUSED(alloc);
-  UPB_UNUSED(oldsize);
-  if (size == 0) {
-    free(ptr);
-    return NULL;
-  } else {
-    return realloc(ptr, size);
-  }
-}
-
-upb_alloc upb_alloc_global = {&upb_global_allocfunc};
-
-/* upb_arena ******************************************************************/
-
-/* Be conservative and choose 16 in case anyone is using SSE. */
-static const size_t maxalign = 16;
-
-static size_t align_up_max(size_t size) {
-  return ((size + maxalign - 1) / maxalign) * maxalign;
-}
-
-struct upb_arena {
-  /* We implement the allocator interface.
-   * This must be the first member of upb_arena! */
-  upb_alloc alloc;
-
-  /* Allocator to allocate arena blocks.  We are responsible for freeing these
-   * when we are destroyed. */
-  upb_alloc *block_alloc;
-
-  size_t bytes_allocated;
-  size_t next_block_size;
-  size_t max_block_size;
-
-  /* Linked list of blocks.  Points to an arena_block, defined in env.c */
-  void *block_head;
-
-  /* Cleanup entries.  Pointer to a cleanup_ent, defined in env.c */
-  void *cleanup_head;
-};
-
-typedef struct mem_block {
-  struct mem_block *next;
-  size_t size;
-  size_t used;
-  bool owned;
-  /* Data follows. */
-} mem_block;
-
-typedef struct cleanup_ent {
-  struct cleanup_ent *next;
-  upb_cleanup_func *cleanup;
-  void *ud;
-} cleanup_ent;
-
-static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size,
-                               bool owned) {
-  mem_block *block = ptr;
-
-  block->next = a->block_head;
-  block->size = size;
-  block->used = align_up_max(sizeof(mem_block));
-  block->owned = owned;
-
-  a->block_head = block;
-
-  /* TODO(haberman): ASAN poison. */
-}
-
-static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) {
-  size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block);
-  mem_block *block = upb_malloc(a->block_alloc, block_size);
-
-  if (!block) {
-    return NULL;
-  }
-
-  upb_arena_addblock(a, block, block_size, true);
-  a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size);
-
-  return block;
-}
-
-static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                               size_t size) {
-  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
-  mem_block *block = a->block_head;
-  void *ret;
-
-  if (size == 0) {
-    return NULL;  /* We are an arena, don't need individual frees. */
-  }
-
-  size = align_up_max(size);
-
-  /* TODO(haberman): special-case if this is a realloc of the last alloc? */
-
-  if (!block || block->size - block->used < size) {
-    /* Slow path: have to allocate a new block. */
-    block = upb_arena_allocblock(a, size);
-
-    if (!block) {
-      return NULL;  /* Out of memory. */
-    }
-  }
-
-  ret = (char*)block + block->used;
-  block->used += size;
-
-  if (oldsize > 0) {
-    memcpy(ret, ptr, oldsize);  /* Preserve existing data. */
-  }
-
-  /* TODO(haberman): ASAN unpoison. */
-
-  a->bytes_allocated += size;
-  return ret;
-}
-
-/* Public Arena API ***********************************************************/
-
-#define upb_alignof(type) offsetof (struct { char c; type member; }, member)
-
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
-  const size_t first_block_overhead = sizeof(upb_arena) + sizeof(mem_block);
-  upb_arena *a;
-  bool owned = false;
-
-  /* Round block size down to alignof(*a) since we will allocate the arena
-   * itself at the end. */
-  n &= ~(upb_alignof(upb_arena) - 1);
-
-  if (n < first_block_overhead) {
-    /* We need to malloc the initial block. */
-    n = first_block_overhead + 256;
-    owned = true;
-    if (!alloc || !(mem = upb_malloc(alloc, n))) {
-      return NULL;
-    }
-  }
-
-  a = (void*)((char*)mem + n - sizeof(*a));
-  n -= sizeof(*a);
-
-  a->alloc.func = &upb_arena_doalloc;
-  a->block_alloc = &upb_alloc_global;
-  a->bytes_allocated = 0;
-  a->next_block_size = 256;
-  a->max_block_size = 16384;
-  a->cleanup_head = NULL;
-  a->block_head = NULL;
-  a->block_alloc = alloc;
-
-  upb_arena_addblock(a, mem, n, owned);
-
-  return a;
-}
-
-#undef upb_alignof
-
-void upb_arena_free(upb_arena *a) {
-  cleanup_ent *ent = a->cleanup_head;
-  mem_block *block = a->block_head;
-
-  while (ent) {
-    ent->cleanup(ent->ud);
-    ent = ent->next;
-  }
-
-  /* Must do this after running cleanup functions, because this will delete
-   * the memory we store our cleanup entries in! */
-  while (block) {
-    /* Load first since we are deleting block. */
-    mem_block *next = block->next;
-
-    if (block->owned) {
-      upb_free(a->block_alloc, block);
-    }
-
-    block = next;
-  }
-}
-
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
-  cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent));
-  if (!ent) {
-    return false;  /* Out of memory. */
-  }
-
-  ent->cleanup = func;
-  ent->ud = ud;
-  ent->next = a->cleanup_head;
-  a->cleanup_head = ent;
-
-  return true;
-}
-
-size_t upb_arena_bytesallocated(const upb_arena *a) {
-  return a->bytes_allocated;
-}
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include <stddef.h>
-
-
-static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = {
-  &google_protobuf_FileDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
-  &google_protobuf_FileDescriptorSet_submsgs[0],
-  &google_protobuf_FileDescriptorSet__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
-  &google_protobuf_DescriptorProto_msginit,
-  &google_protobuf_EnumDescriptorProto_msginit,
-  &google_protobuf_FieldDescriptorProto_msginit,
-  &google_protobuf_FileOptions_msginit,
-  &google_protobuf_ServiceDescriptorProto_msginit,
-  &google_protobuf_SourceCodeInfo_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {3, UPB_SIZE(36, 72), 0, 0, 9, 3},
-  {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
-  {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
-  {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
-  {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
-  {8, UPB_SIZE(28, 56), 4, 3, 11, 1},
-  {9, UPB_SIZE(32, 64), 5, 5, 11, 1},
-  {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
-  {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
-  {12, UPB_SIZE(20, 40), 3, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
-  &google_protobuf_FileDescriptorProto_submsgs[0],
-  &google_protobuf_FileDescriptorProto__fields[0],
-  UPB_SIZE(64, 128), 12, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[8] = {
-  &google_protobuf_DescriptorProto_msginit,
-  &google_protobuf_DescriptorProto_ExtensionRange_msginit,
-  &google_protobuf_DescriptorProto_ReservedRange_msginit,
-  &google_protobuf_EnumDescriptorProto_msginit,
-  &google_protobuf_FieldDescriptorProto_msginit,
-  &google_protobuf_MessageOptions_msginit,
-  &google_protobuf_OneofDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
-  {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
-  {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
-  {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
-  {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
-  {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
-  {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
-  {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
-  {10, UPB_SIZE(44, 88), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_msginit = {
-  &google_protobuf_DescriptorProto_submsgs[0],
-  &google_protobuf_DescriptorProto__fields[0],
-  UPB_SIZE(48, 96), 10, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
-  &google_protobuf_ExtensionRangeOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-  {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
-  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
-  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
-  UPB_SIZE(16, 24), 3, false,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
-  NULL,
-  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
-  UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
-  &google_protobuf_ExtensionRangeOptions_submsgs[0],
-  &google_protobuf_ExtensionRangeOptions__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
-  &google_protobuf_FieldOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[10] = {
-  {1, UPB_SIZE(32, 32), 5, 0, 9, 1},
-  {2, UPB_SIZE(40, 48), 6, 0, 9, 1},
-  {3, UPB_SIZE(24, 24), 3, 0, 5, 1},
-  {4, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {5, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {6, UPB_SIZE(48, 64), 7, 0, 9, 1},
-  {7, UPB_SIZE(56, 80), 8, 0, 9, 1},
-  {8, UPB_SIZE(72, 112), 10, 0, 11, 1},
-  {9, UPB_SIZE(28, 28), 4, 0, 5, 1},
-  {10, UPB_SIZE(64, 96), 9, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
-  &google_protobuf_FieldDescriptorProto_submsgs[0],
-  &google_protobuf_FieldDescriptorProto__fields[0],
-  UPB_SIZE(80, 128), 10, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
-  &google_protobuf_OneofOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
-  &google_protobuf_OneofDescriptorProto_submsgs[0],
-  &google_protobuf_OneofDescriptorProto__fields[0],
-  UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
-  &google_protobuf_EnumOptions_msginit,
-  &google_protobuf_EnumValueDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
-  {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
-  {5, UPB_SIZE(24, 48), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
-  &google_protobuf_EnumDescriptorProto_submsgs[0],
-  &google_protobuf_EnumDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
-  NULL,
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
-  UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
-  &google_protobuf_EnumValueOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(8, 8), 2, 0, 9, 1},
-  {2, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
-  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
-  &google_protobuf_EnumValueDescriptorProto__fields[0],
-  UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
-  &google_protobuf_MethodDescriptorProto_msginit,
-  &google_protobuf_ServiceOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
-};
-
-const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
-  &google_protobuf_ServiceDescriptorProto_submsgs[0],
-  &google_protobuf_ServiceDescriptorProto__fields[0],
-  UPB_SIZE(24, 48), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
-  &google_protobuf_MethodOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
-  {1, UPB_SIZE(4, 8), 3, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 4, 0, 9, 1},
-  {3, UPB_SIZE(20, 40), 5, 0, 9, 1},
-  {4, UPB_SIZE(28, 56), 6, 0, 11, 1},
-  {5, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {6, UPB_SIZE(2, 2), 2, 0, 8, 1},
-};
-
-const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
-  &google_protobuf_MethodDescriptorProto_submsgs[0],
-  &google_protobuf_MethodDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 6, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
-  {1, UPB_SIZE(28, 32), 11, 0, 9, 1},
-  {8, UPB_SIZE(36, 48), 12, 0, 9, 1},
-  {9, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {10, UPB_SIZE(16, 16), 2, 0, 8, 1},
-  {11, UPB_SIZE(44, 64), 13, 0, 9, 1},
-  {16, UPB_SIZE(17, 17), 3, 0, 8, 1},
-  {17, UPB_SIZE(18, 18), 4, 0, 8, 1},
-  {18, UPB_SIZE(19, 19), 5, 0, 8, 1},
-  {20, UPB_SIZE(20, 20), 6, 0, 8, 1},
-  {23, UPB_SIZE(21, 21), 7, 0, 8, 1},
-  {27, UPB_SIZE(22, 22), 8, 0, 8, 1},
-  {31, UPB_SIZE(23, 23), 9, 0, 8, 1},
-  {36, UPB_SIZE(52, 80), 14, 0, 9, 1},
-  {37, UPB_SIZE(60, 96), 15, 0, 9, 1},
-  {39, UPB_SIZE(68, 112), 16, 0, 9, 1},
-  {40, UPB_SIZE(76, 128), 17, 0, 9, 1},
-  {41, UPB_SIZE(84, 144), 18, 0, 9, 1},
-  {42, UPB_SIZE(24, 24), 10, 0, 8, 1},
-  {44, UPB_SIZE(92, 160), 19, 0, 9, 1},
-  {45, UPB_SIZE(100, 176), 20, 0, 9, 1},
-  {999, UPB_SIZE(108, 192), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileOptions_msginit = {
-  &google_protobuf_FileOptions_submsgs[0],
-  &google_protobuf_FileOptions__fields[0],
-  UPB_SIZE(112, 208), 21, false,
-};
-
-static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
-  {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
-  {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
-  {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MessageOptions_msginit = {
-  &google_protobuf_MessageOptions_submsgs[0],
-  &google_protobuf_MessageOptions__fields[0],
-  UPB_SIZE(12, 16), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
-  {1, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {2, UPB_SIZE(24, 24), 3, 0, 8, 1},
-  {3, UPB_SIZE(25, 25), 4, 0, 8, 1},
-  {5, UPB_SIZE(26, 26), 5, 0, 8, 1},
-  {6, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {10, UPB_SIZE(27, 27), 6, 0, 8, 1},
-  {999, UPB_SIZE(28, 32), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FieldOptions_msginit = {
-  &google_protobuf_FieldOptions_submsgs[0],
-  &google_protobuf_FieldOptions__fields[0],
-  UPB_SIZE(32, 40), 7, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_OneofOptions_msginit = {
-  &google_protobuf_OneofOptions_submsgs[0],
-  &google_protobuf_OneofOptions__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
-  {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumOptions_msginit = {
-  &google_protobuf_EnumOptions_submsgs[0],
-  &google_protobuf_EnumOptions__fields[0],
-  UPB_SIZE(8, 16), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
-  &google_protobuf_EnumValueOptions_submsgs[0],
-  &google_protobuf_EnumValueOptions__fields[0],
-  UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
-  {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ServiceOptions_msginit = {
-  &google_protobuf_ServiceOptions_submsgs[0],
-  &google_protobuf_ServiceOptions__fields[0],
-  UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
-  {33, UPB_SIZE(16, 16), 2, 0, 8, 1},
-  {34, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {999, UPB_SIZE(20, 24), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MethodOptions_msginit = {
-  &google_protobuf_MethodOptions_submsgs[0],
-  &google_protobuf_MethodOptions__fields[0],
-  UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_NamePart_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
-  {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
-  {3, UPB_SIZE(32, 32), 4, 0, 9, 1},
-  {4, UPB_SIZE(8, 8), 1, 0, 4, 1},
-  {5, UPB_SIZE(16, 16), 2, 0, 3, 1},
-  {6, UPB_SIZE(24, 24), 3, 0, 1, 1},
-  {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
-  {8, UPB_SIZE(48, 64), 6, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
-  &google_protobuf_UninterpretedOption_submsgs[0],
-  &google_protobuf_UninterpretedOption__fields[0],
-  UPB_SIZE(64, 96), 7, false,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
-  {1, UPB_SIZE(4, 8), 2, 0, 9, 2},
-  {2, UPB_SIZE(1, 1), 1, 0, 8, 2},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
-  NULL,
-  &google_protobuf_UninterpretedOption_NamePart__fields[0],
-  UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
-  &google_protobuf_SourceCodeInfo_Location_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
-  &google_protobuf_SourceCodeInfo_submsgs[0],
-  &google_protobuf_SourceCodeInfo__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
-  {1, UPB_SIZE(20, 40), 0, 0, 5, 3},
-  {2, UPB_SIZE(24, 48), 0, 0, 5, 3},
-  {3, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {4, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {6, UPB_SIZE(28, 56), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
-  NULL,
-  &google_protobuf_SourceCodeInfo_Location__fields[0],
-  UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
-  &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
-  &google_protobuf_GeneratedCodeInfo_submsgs[0],
-  &google_protobuf_GeneratedCodeInfo__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
-  {1, UPB_SIZE(20, 32), 0, 0, 5, 3},
-  {2, UPB_SIZE(12, 16), 3, 0, 9, 1},
-  {3, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {4, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
-  NULL,
-  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
-  UPB_SIZE(24, 48), 4, false,
-};
-
-
-
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-typedef struct {
-  size_t len;
-  char str[1];  /* Null-terminated string data follows. */
-} str_t;
-
-static str_t *newstr(upb_alloc *alloc, const char *data, size_t len) {
-  str_t *ret = upb_malloc(alloc, sizeof(*ret) + len);
-  if (!ret) return NULL;
-  ret->len = len;
-  memcpy(ret->str, data, len);
-  ret->str[len] = '\0';
-  return ret;
-}
-
-struct upb_fielddef {
-  const upb_filedef *file;
-  const upb_msgdef *msgdef;
-  const char *full_name;
-  union {
-    int64_t sint;
-    uint64_t uint;
-    double dbl;
-    float flt;
-    bool boolean;
-    str_t *str;
-  } defaultval;
-  const upb_oneofdef *oneof;
-  union {
-    const upb_msgdef *msgdef;
-    const upb_enumdef *enumdef;
-    const google_protobuf_FieldDescriptorProto *unresolved;
-  } sub;
-  uint32_t number_;
-  uint32_t index_;
-  uint32_t selector_base;  /* Used to index into a upb::Handlers table. */
-  bool is_extension_;
-  bool lazy_;
-  bool packed_;
-  upb_descriptortype_t type_;
-  upb_label_t label_;
-};
-
-struct upb_msgdef {
-  const upb_filedef *file;
-  const char *full_name;
-  uint32_t selector_count;
-  uint32_t submsg_field_count;
-
-  /* Tables for looking up fields by number and name. */
-  upb_inttable itof;
-  upb_strtable ntof;
-
-  const upb_fielddef *fields;
-  const upb_oneofdef *oneofs;
-  int field_count;
-  int oneof_count;
-
-  /* Is this a map-entry message? */
-  bool map_entry;
-  upb_wellknowntype_t well_known_type;
-
-  /* TODO(haberman): proper extension ranges (there can be multiple). */
-};
-
-struct upb_enumdef {
-  const upb_filedef *file;
-  const char *full_name;
-  upb_strtable ntoi;
-  upb_inttable iton;
-  int32_t defaultval;
-};
-
-struct upb_oneofdef {
-  const upb_msgdef *parent;
-  const char *full_name;
-  uint32_t index;
-  upb_strtable ntof;
-  upb_inttable itof;
-};
-
-struct upb_filedef {
-  const char *name;
-  const char *package;
-  const char *phpprefix;
-  const char *phpnamespace;
-  upb_syntax_t syntax;
-
-  const upb_filedef **deps;
-  const upb_msgdef *msgs;
-  const upb_enumdef *enums;
-  const upb_fielddef *exts;
-
-  int dep_count;
-  int msg_count;
-  int enum_count;
-  int ext_count;
-};
-
-struct upb_symtab {
-  upb_arena *arena;
-  upb_strtable syms;  /* full_name -> packed def ptr */
-  upb_strtable files;  /* file_name -> upb_filedef* */
-};
-
-/* Inside a symtab we store tagged pointers to specific def types. */
-typedef enum {
-  UPB_DEFTYPE_MSG = 0,
-  UPB_DEFTYPE_ENUM = 1,
-  UPB_DEFTYPE_FIELD = 2,
-  UPB_DEFTYPE_ONEOF = 3
-} upb_deftype_t;
-
-static const void *unpack_def(upb_value v, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
-  return (num & 3) == type ? (const void*)(num & ~3) : NULL;
-}
-
-static upb_value pack_def(const void *ptr, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)ptr | type;
-  return upb_value_constptr((const void*)num);
-}
-
-/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
-static bool upb_isbetween(char c, char low, char high) {
-  return c >= low && c <= high;
-}
-
-static bool upb_isletter(char c) {
-  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
-}
-
-static bool upb_isalphanum(char c) {
-  return upb_isletter(c) || upb_isbetween(c, '0', '9');
-}
-
-static bool upb_isident(upb_strview name, bool full, upb_status *s) {
-  const char *str = name.data;
-  size_t len = name.size;
-  bool start = true;
-  size_t i;
-  for (i = 0; i < len; i++) {
-    char c = str[i];
-    if (c == '.') {
-      if (start || !full) {
-        upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
-        return false;
-      }
-      start = true;
-    } else if (start) {
-      if (!upb_isletter(c)) {
-        upb_status_seterrf(
-            s, "invalid name: path components must start with a letter (%s)",
-            str);
-        return false;
-      }
-      start = false;
-    } else {
-      if (!upb_isalphanum(c)) {
-        upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
-                           str);
-        return false;
-      }
-    }
-  }
-  return !start;
-}
-
-static const char *shortdefname(const char *fullname) {
-  const char *p;
-
-  if (fullname == NULL) {
-    return NULL;
-  } else if ((p = strrchr(fullname, '.')) == NULL) {
-    /* No '.' in the name, return the full string. */
-    return fullname;
-  } else {
-    /* Return one past the last '.'. */
-    return p + 1;
-  }
-}
-
-/* All submessage fields are lower than all other fields.
- * Secondly, fields are increasing in order. */
-uint32_t field_rank(const upb_fielddef *f) {
-  uint32_t ret = upb_fielddef_number(f);
-  const uint32_t high_bit = 1 << 30;
-  UPB_ASSERT(ret < high_bit);
-  if (!upb_fielddef_issubmsg(f))
-    ret |= high_bit;
-  return ret;
-}
-
-int cmp_fields(const void *p1, const void *p2) {
-  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
-  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
-  return field_rank(f1) - field_rank(f2);
-}
-
-/* A few implementation details of handlers.  We put these here to avoid
- * a def -> handlers dependency. */
-
-#define UPB_STATIC_SELECTOR_COUNT 3  /* Warning: also in upb/handlers.h. */
-
-static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
-  return upb_fielddef_isseq(f) ? 2 : 0;
-}
-
-static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
-  uint32_t ret = 1;
-  if (upb_fielddef_isseq(f)) ret += 2;    /* STARTSEQ/ENDSEQ */
-  if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
-  if (upb_fielddef_issubmsg(f)) {
-    /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
-    ret += 0;
-    if (upb_fielddef_lazy(f)) {
-      /* STARTSTR/ENDSTR/STRING (for lazy) */
-      ret += 3;
-    }
-  }
-  return ret;
-}
-
-static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
-  /* Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
-   * lowest indexes, but we do not publicly guarantee this. */
-  upb_msg_field_iter j;
-  upb_msg_oneof_iter k;
-  int i;
-  uint32_t selector;
-  int n = upb_msgdef_numfields(m);
-  upb_fielddef **fields;
-
-  if (n == 0) {
-    m->selector_count = UPB_STATIC_SELECTOR_COUNT;
-    m->submsg_field_count = 0;
-    return true;
-  }
-
-  fields = upb_gmalloc(n * sizeof(*fields));
-  if (!fields) {
-    upb_status_setoom(s);
-    return false;
-  }
-
-  m->submsg_field_count = 0;
-  for(i = 0, upb_msg_field_begin(&j, m);
-      !upb_msg_field_done(&j);
-      upb_msg_field_next(&j), i++) {
-    upb_fielddef *f = upb_msg_iter_field(&j);
-    UPB_ASSERT(f->msgdef == m);
-    if (upb_fielddef_issubmsg(f)) {
-      m->submsg_field_count++;
-    }
-    fields[i] = f;
-  }
-
-  qsort(fields, n, sizeof(*fields), cmp_fields);
-
-  selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
-  for (i = 0; i < n; i++) {
-    upb_fielddef *f = fields[i];
-    f->index_ = i;
-    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
-    selector += upb_handlers_selectorcount(f);
-  }
-  m->selector_count = selector;
-
-  for(upb_msg_oneof_begin(&k, m), i = 0;
-      !upb_msg_oneof_done(&k);
-      upb_msg_oneof_next(&k), i++) {
-    upb_oneofdef *o = (upb_oneofdef*)upb_msg_iter_oneof(&k);
-    o->index = i;
-  }
-
-  upb_gfree(fields);
-  return true;
-}
-
-static void assign_msg_wellknowntype(upb_msgdef *m) {
-  const char *name = upb_msgdef_fullname(m);
-  if (name == NULL) {
-    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
-    return;
-  }
-  if (!strcmp(name, "google.protobuf.Any")) {
-    m->well_known_type = UPB_WELLKNOWN_ANY;
-  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
-    m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
-  } else if (!strcmp(name, "google.protobuf.Duration")) {
-    m->well_known_type = UPB_WELLKNOWN_DURATION;
-  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
-    m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
-  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
-    m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
-  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
-    m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
-  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
-    m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
-  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
-    m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
-  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
-    m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
-  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
-    m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
-  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
-    m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
-  } else if (!strcmp(name, "google.protobuf.StringValue")) {
-    m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
-  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
-    m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
-  } else if (!strcmp(name, "google.protobuf.Value")) {
-    m->well_known_type = UPB_WELLKNOWN_VALUE;
-  } else if (!strcmp(name, "google.protobuf.ListValue")) {
-    m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
-  } else if (!strcmp(name, "google.protobuf.Struct")) {
-    m->well_known_type = UPB_WELLKNOWN_STRUCT;
-  } else {
-    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
-  }
-}
-
-
-/* upb_enumdef ****************************************************************/
-
-const char *upb_enumdef_fullname(const upb_enumdef *e) {
-  return e->full_name;
-}
-
-const char *upb_enumdef_name(const upb_enumdef *e) {
-  return shortdefname(e->full_name);
-}
-
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
-  return e->file;
-}
-
-int32_t upb_enumdef_default(const upb_enumdef *e) {
-  UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
-  return e->defaultval;
-}
-
-int upb_enumdef_numvals(const upb_enumdef *e) {
-  return upb_strtable_count(&e->ntoi);
-}
-
-void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
-  /* We iterate over the ntoi table, to account for duplicate numbers. */
-  upb_strtable_begin(i, &e->ntoi);
-}
-
-void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
-bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
-
-bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
-                      size_t len, int32_t *num) {
-  upb_value v;
-  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
-    return false;
-  }
-  if (num) *num = upb_value_getint32(v);
-  return true;
-}
-
-const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
-  upb_value v;
-  return upb_inttable_lookup32(&def->iton, num, &v) ?
-      upb_value_getcstr(v) : NULL;
-}
-
-const char *upb_enum_iter_name(upb_enum_iter *iter) {
-  return upb_strtable_iter_key(iter);
-}
-
-int32_t upb_enum_iter_number(upb_enum_iter *iter) {
-  return upb_value_getint32(upb_strtable_iter_value(iter));
-}
-
-
-/* upb_fielddef ***************************************************************/
-
-const char *upb_fielddef_fullname(const upb_fielddef *f) {
-  return f->full_name;
-}
-
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
-  switch (f->type_) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      return UPB_TYPE_DOUBLE;
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      return UPB_TYPE_FLOAT;
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-      return UPB_TYPE_INT64;
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      return UPB_TYPE_INT32;
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      return UPB_TYPE_UINT64;
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-      return UPB_TYPE_UINT32;
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      return UPB_TYPE_ENUM;
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      return UPB_TYPE_BOOL;
-    case UPB_DESCRIPTOR_TYPE_STRING:
-      return UPB_TYPE_STRING;
-    case UPB_DESCRIPTOR_TYPE_BYTES:
-      return UPB_TYPE_BYTES;
-    case UPB_DESCRIPTOR_TYPE_GROUP:
-    case UPB_DESCRIPTOR_TYPE_MESSAGE:
-      return UPB_TYPE_MESSAGE;
-  }
-  UPB_UNREACHABLE();
-}
-
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
-  return f->type_;
-}
-
-uint32_t upb_fielddef_index(const upb_fielddef *f) {
-  return f->index_;
-}
-
-upb_label_t upb_fielddef_label(const upb_fielddef *f) {
-  return f->label_;
-}
-
-uint32_t upb_fielddef_number(const upb_fielddef *f) {
-  return f->number_;
-}
-
-bool upb_fielddef_isextension(const upb_fielddef *f) {
-  return f->is_extension_;
-}
-
-bool upb_fielddef_lazy(const upb_fielddef *f) {
-  return f->lazy_;
-}
-
-bool upb_fielddef_packed(const upb_fielddef *f) {
-  return f->packed_;
-}
-
-const char *upb_fielddef_name(const upb_fielddef *f) {
-  return shortdefname(f->full_name);
-}
-
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) {
-  return f->selector_base;
-}
-
-size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) {
-  const char *name = upb_fielddef_name(f);
-  size_t src, dst = 0;
-  bool ucase_next = false;
-
-#define WRITE(byte) \
-  ++dst; \
-  if (dst < len) buf[dst - 1] = byte; \
-  else if (dst == len) buf[dst - 1] = '\0'
-
-  if (!name) {
-    WRITE('\0');
-    return 0;
-  }
-
-  /* Implement the transformation as described in the spec:
-   *   1. upper case all letters after an underscore.
-   *   2. remove all underscores.
-   */
-  for (src = 0; name[src]; src++) {
-    if (name[src] == '_') {
-      ucase_next = true;
-      continue;
-    }
-
-    if (ucase_next) {
-      WRITE(toupper(name[src]));
-      ucase_next = false;
-    } else {
-      WRITE(name[src]);
-    }
-  }
-
-  WRITE('\0');
-  return dst;
-
-#undef WRITE
-}
-
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
-  return f->msgdef;
-}
-
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
-  return f->oneof;
-}
-
-static void chkdefaulttype(const upb_fielddef *f, int ctype) {
-  UPB_UNUSED(f);
-  UPB_UNUSED(ctype);
-}
-
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_INT64);
-  return f->defaultval.sint;
-}
-
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_INT32);
-  return f->defaultval.sint;
-}
-
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_UINT64);
-  return f->defaultval.uint;
-}
-
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_UINT32);
-  return f->defaultval.uint;
-}
-
-bool upb_fielddef_defaultbool(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_BOOL);
-  return f->defaultval.boolean;
-}
-
-float upb_fielddef_defaultfloat(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_FLOAT);
-  return f->defaultval.flt;
-}
-
-double upb_fielddef_defaultdouble(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_DOUBLE);
-  return f->defaultval.dbl;
-}
-
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
-  str_t *str = f->defaultval.str;
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
-         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
-         upb_fielddef_type(f) == UPB_TYPE_ENUM);
-  if (str) {
-    if (len) *len = str->len;
-    return str->str;
-  } else {
-    if (len) *len = 0;
-    return NULL;
-  }
-}
-
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
-  return f->sub.msgdef;
-}
-
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_ENUM);
-  return f->sub.enumdef;
-}
-
-bool upb_fielddef_issubmsg(const upb_fielddef *f) {
-  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
-}
-
-bool upb_fielddef_isstring(const upb_fielddef *f) {
-  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
-         upb_fielddef_type(f) == UPB_TYPE_BYTES;
-}
-
-bool upb_fielddef_isseq(const upb_fielddef *f) {
-  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
-}
-
-bool upb_fielddef_isprimitive(const upb_fielddef *f) {
-  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
-}
-
-bool upb_fielddef_ismap(const upb_fielddef *f) {
-  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
-         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
-}
-
-bool upb_fielddef_hassubdef(const upb_fielddef *f) {
-  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
-}
-
-bool upb_fielddef_haspresence(const upb_fielddef *f) {
-  if (upb_fielddef_isseq(f)) return false;
-  if (upb_fielddef_issubmsg(f)) return true;
-  return f->file->syntax == UPB_SYNTAX_PROTO2;
-}
-
-static bool between(int32_t x, int32_t low, int32_t high) {
-  return x >= low && x <= high;
-}
-
-bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
-bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
-bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
-
-bool upb_fielddef_checkdescriptortype(int32_t type) {
-  return between(type, 1, 18);
-}
-
-/* upb_msgdef *****************************************************************/
-
-const char *upb_msgdef_fullname(const upb_msgdef *m) {
-  return m->full_name;
-}
-
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
-  return m->file;
-}
-
-const char *upb_msgdef_name(const upb_msgdef *m) {
-  return shortdefname(m->full_name);
-}
-
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
-  return m->file->syntax;
-}
-
-size_t upb_msgdef_selectorcount(const upb_msgdef *m) {
-  return m->selector_count;
-}
-
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) {
-  return m->submsg_field_count;
-}
-
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
-  upb_value val;
-  return upb_inttable_lookup32(&m->itof, i, &val) ?
-      upb_value_getconstptr(val) : NULL;
-}
-
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
-                                    size_t len) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  return unpack_def(val, UPB_DEFTYPE_FIELD);
-}
-
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
-                                    size_t len) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  return unpack_def(val, UPB_DEFTYPE_ONEOF);
-}
-
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
-                           const upb_fielddef **f, const upb_oneofdef **o) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return false;
-  }
-
-  *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
-  *f = unpack_def(val, UPB_DEFTYPE_FIELD);
-  UPB_ASSERT((*o != NULL) ^ (*f != NULL));  /* Exactly one of the two should be set. */
-  return true;
-}
-
-int upb_msgdef_numfields(const upb_msgdef *m) {
-  /* The number table contains only fields. */
-  return upb_inttable_count(&m->itof);
-}
-
-int upb_msgdef_numoneofs(const upb_msgdef *m) {
-  /* The name table includes oneofs, and the number table does not. */
-  return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof);
-}
-
-bool upb_msgdef_mapentry(const upb_msgdef *m) {
-  return m->map_entry;
-}
-
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
-  return m->well_known_type;
-}
-
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
-         type <= UPB_WELLKNOWN_UINT32VALUE;
-}
-
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
-  upb_inttable_begin(iter, &m->itof);
-}
-
-void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
-
-bool upb_msg_field_done(const upb_msg_field_iter *iter) {
-  return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
-  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
-  upb_inttable_iter_setdone(iter);
-}
-
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
-                                const upb_msg_field_iter * iter2) {
-  return upb_inttable_iter_isequal(iter1, iter2);
-}
-
-void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
-  upb_strtable_begin(iter, &m->ntof);
-  /* We need to skip past any initial fields. */
-  while (!upb_strtable_done(iter) &&
-         !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
-    upb_strtable_next(iter);
-  }
-}
-
-void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
-  /* We need to skip past fields to return only oneofs. */
-  do {
-    upb_strtable_next(iter);
-  } while (!upb_strtable_done(iter) &&
-           !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
-}
-
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
-  return upb_strtable_done(iter);
-}
-
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
-  return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
-}
-
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
-  upb_strtable_iter_setdone(iter);
-}
-
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
-                                const upb_msg_oneof_iter *iter2) {
-  return upb_strtable_iter_isequal(iter1, iter2);
-}
-
-/* upb_oneofdef ***************************************************************/
-
-const char *upb_oneofdef_name(const upb_oneofdef *o) {
-  return shortdefname(o->full_name);
-}
-
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
-  return o->parent;
-}
-
-int upb_oneofdef_numfields(const upb_oneofdef *o) {
-  return upb_strtable_count(&o->ntof);
-}
-
-uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
-  return o->index;
-}
-
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
-                                      const char *name, size_t length) {
-  upb_value val;
-  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
-      upb_value_getptr(val) : NULL;
-}
-
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
-  upb_value val;
-  return upb_inttable_lookup32(&o->itof, num, &val) ?
-      upb_value_getptr(val) : NULL;
-}
-
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
-  upb_inttable_begin(iter, &o->itof);
-}
-
-void upb_oneof_next(upb_oneof_iter *iter) {
-  upb_inttable_next(iter);
-}
-
-bool upb_oneof_done(upb_oneof_iter *iter) {
-  return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
-  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
-  upb_inttable_iter_setdone(iter);
-}
-
-/* Code to build defs from descriptor protos. *********************************/
-
-/* There is a question of how much validation to do here.  It will be difficult
- * to perfectly match the amount of validation performed by proto2.  But since
- * this code is used to directly build defs from Ruby (for example) we do need
- * to validate important constraints like uniqueness of names and numbers. */
-
-#define CHK(x) if (!(x)) { return false; }
-#define CHK_OOM(x) if (!(x)) { upb_status_setoom(ctx->status); return false; }
-
-typedef struct {
-  const upb_symtab *symtab;
-  upb_filedef *file;  /* File we are building. */
-  upb_alloc *alloc;    /* Allocate defs here. */
-  upb_alloc *tmp;      /* Alloc for addtab and any other tmp data. */
-  upb_strtable *addtab;  /* full_name -> packed def ptr for new defs. */
-  upb_status *status;  /* Record errors here. */
-} symtab_addctx;
-
-static char* strviewdup(const symtab_addctx *ctx, upb_strview view) {
-  return upb_strdup2(view.data, view.size, ctx->alloc);
-}
-
-static bool streql2(const char *a, size_t n, const char *b) {
-  return n == strlen(b) && memcmp(a, b, n) == 0;
-}
-
-static bool streql_view(upb_strview view, const char *b) {
-  return streql2(view.data, view.size, b);
-}
-
-static const char *makefullname(const symtab_addctx *ctx, const char *prefix,
-                                upb_strview name) {
-  if (prefix) {
-    /* ret = prefix + '.' + name; */
-    size_t n = strlen(prefix);
-    char *ret = upb_malloc(ctx->alloc, n + name.size + 2);
-    CHK_OOM(ret);
-    strcpy(ret, prefix);
-    ret[n] = '.';
-    memcpy(&ret[n + 1], name.data, name.size);
-    ret[n + 1 + name.size] = '\0';
-    return ret;
-  } else {
-    return strviewdup(ctx, name);
-  }
-}
-
-static bool symtab_add(const symtab_addctx *ctx, const char *name,
-                       upb_value v) {
-  upb_value tmp;
-  if (upb_strtable_lookup(ctx->addtab, name, &tmp) ||
-      upb_strtable_lookup(&ctx->symtab->syms, name, &tmp)) {
-    upb_status_seterrf(ctx->status, "duplicate symbol '%s'", name);
-    return false;
-  }
-
-  CHK_OOM(upb_strtable_insert3(ctx->addtab, name, strlen(name), v, ctx->tmp));
-  return true;
-}
-
-/* Given a symbol and the base symbol inside which it is defined, find the
- * symbol's definition in t. */
-static bool resolvename(const upb_strtable *t, const upb_fielddef *f,
-                        const char *base, upb_strview sym,
-                        upb_deftype_t type, upb_status *status,
-                        const void **def) {
-  if(sym.size == 0) return NULL;
-  if(sym.data[0] == '.') {
-    /* Symbols starting with '.' are absolute, so we do a single lookup.
-     * Slice to omit the leading '.' */
-    upb_value v;
-    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
-      return false;
-    }
-
-    *def = unpack_def(v, type);
-
-    if (!*def) {
-      upb_status_seterrf(status,
-                         "type mismatch when resolving field %s, name %s",
-                         f->full_name, sym.data);
-      return false;
-    }
-
-    return true;
-  } else {
-    /* Remove components from base until we find an entry or run out.
-     * TODO: This branch is totally broken, but currently not used. */
-    (void)base;
-    UPB_ASSERT(false);
-    return false;
-  }
-}
-
-const void *symtab_resolve(const symtab_addctx *ctx, const upb_fielddef *f,
-                           const char *base, upb_strview sym,
-                           upb_deftype_t type) {
-  const void *ret;
-  if (!resolvename(ctx->addtab, f, base, sym, type, ctx->status, &ret) &&
-      !resolvename(&ctx->symtab->syms, f, base, sym, type, ctx->status, &ret)) {
-    if (upb_ok(ctx->status)) {
-      upb_status_seterrf(ctx->status, "couldn't resolve name '%s'", sym.data);
-    }
-    return false;
-  }
-  return ret;
-}
-
-static bool create_oneofdef(
-    const symtab_addctx *ctx, upb_msgdef *m,
-    const google_protobuf_OneofDescriptorProto *oneof_proto) {
-  upb_oneofdef *o;
-  upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
-  upb_value v;
-
-  o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
-  o->parent = m;
-  o->full_name = makefullname(ctx, m->full_name, name);
-
-  v = pack_def(o, UPB_DEFTYPE_ONEOF);
-  CHK_OOM(symtab_add(ctx, o->full_name, v));
-  CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc));
-
-  CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-  CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
-  return true;
-}
-
-static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len,
-                          upb_fielddef *f) {
-  char *end;
-  char nullz[64];
-  errno = 0;
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      /* Standard C number parsing functions expect null-terminated strings. */
-      if (len >= sizeof(nullz) - 1) {
-        return false;
-      }
-      memcpy(nullz, str, len);
-      nullz[len] = '\0';
-      str = nullz;
-      break;
-    default:
-      break;
-  }
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32: {
-      long val = strtol(str, &end, 0);
-      CHK(val <= INT32_MAX && val >= INT32_MIN && errno != ERANGE && !*end);
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_ENUM: {
-      const upb_enumdef *e = f->sub.enumdef;
-      int32_t val;
-      CHK(upb_enumdef_ntoi(e, str, len, &val));
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_INT64: {
-      /* XXX: Need to write our own strtoll, since it's not available in c89. */
-      long long val = strtol(str, &end, 0);
-      CHK(val <= INT64_MAX && val >= INT64_MIN && errno != ERANGE && !*end);
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_UINT32: {
-      unsigned long val = strtoul(str, &end, 0);
-      CHK(val <= UINT32_MAX && errno != ERANGE && !*end);
-      f->defaultval.uint = val;
-      break;
-    }
-    case UPB_TYPE_UINT64: {
-      /* XXX: Need to write our own strtoull, since it's not available in c89. */
-      unsigned long long val = strtoul(str, &end, 0);
-      CHK(val <= UINT64_MAX && errno != ERANGE && !*end);
-      f->defaultval.uint = val;
-      break;
-    }
-    case UPB_TYPE_DOUBLE: {
-      double val = strtod(str, &end);
-      CHK(errno != ERANGE && !*end);
-      f->defaultval.dbl = val;
-      break;
-    }
-    case UPB_TYPE_FLOAT: {
-      /* XXX: Need to write our own strtof, since it's not available in c89. */
-      float val = strtod(str, &end);
-      CHK(errno != ERANGE && !*end);
-      f->defaultval.flt = val;
-      break;
-    }
-    case UPB_TYPE_BOOL: {
-      if (streql2(str, len, "false")) {
-        f->defaultval.boolean = false;
-      } else if (streql2(str, len, "true")) {
-        f->defaultval.boolean = true;
-      } else {
-        return false;
-      }
-      break;
-    }
-    case UPB_TYPE_STRING:
-      f->defaultval.str = newstr(ctx->alloc, str, len);
-      break;
-    case UPB_TYPE_BYTES:
-      /* XXX: need to interpret the C-escaped value. */
-      f->defaultval.str = newstr(ctx->alloc, str, len);
-      break;
-    case UPB_TYPE_MESSAGE:
-      /* Should not have a default value. */
-      return false;
-  }
-  return true;
-}
-
-static void set_default_default(const symtab_addctx *ctx, upb_fielddef *f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_ENUM:
-      f->defaultval.sint = 0;
-      break;
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_UINT32:
-      f->defaultval.uint = 0;
-      break;
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      f->defaultval.dbl = 0;
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      f->defaultval.str = newstr(ctx->alloc, NULL, 0);
-      break;
-    case UPB_TYPE_BOOL:
-      f->defaultval.boolean = false;
-      break;
-    case UPB_TYPE_MESSAGE:
-      break;
-  }
-}
-
-static bool create_fielddef(
-    const symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
-    const google_protobuf_FieldDescriptorProto *field_proto) {
-  upb_alloc *alloc = ctx->alloc;
-  upb_fielddef *f;
-  const google_protobuf_FieldOptions *options;
-  upb_strview name;
-  const char *full_name;
-  const char *shortname;
-  uint32_t field_number;
-
-  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
-    upb_status_seterrmsg(ctx->status, "field has no name");
-    return false;
-  }
-
-  name = google_protobuf_FieldDescriptorProto_name(field_proto);
-  CHK(upb_isident(name, false, ctx->status));
-  full_name = makefullname(ctx, prefix, name);
-  shortname = shortdefname(full_name);
-
-  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
-
-  if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
-    upb_status_seterrf(ctx->status, "invalid field number (%u)", field_number);
-    return false;
-  }
-
-  if (m) {
-    /* direct message field. */
-    upb_value v, packed_v;
-
-    f = (upb_fielddef*)&m->fields[m->field_count++];
-    f->msgdef = m;
-    f->is_extension_ = false;
-
-    packed_v = pack_def(f, UPB_DEFTYPE_FIELD);
-    v = upb_value_constptr(f);
-
-    if (!upb_strtable_insert3(&m->ntof, name.data, name.size, packed_v, alloc)) {
-      upb_status_seterrf(ctx->status, "duplicate field name (%s)", shortname);
-      return false;
-    }
-
-    if (!upb_inttable_insert2(&m->itof, field_number, v, alloc)) {
-      upb_status_seterrf(ctx->status, "duplicate field number (%u)",
-                         field_number);
-      return false;
-    }
-  } else {
-    /* extension field. */
-    f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count];
-    f->is_extension_ = true;
-    CHK_OOM(symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD)));
-  }
-
-  f->full_name = full_name;
-  f->file = ctx->file;
-  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
-  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
-  f->number_ = field_number;
-  f->oneof = NULL;
-
-  /* We can't resolve the subdef or (in the case of extensions) the containing
-   * message yet, because it may not have been defined yet.  We stash a pointer
-   * to the field_proto until later when we can properly resolve it. */
-  f->sub.unresolved = field_proto;
-
-  if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
-    upb_status_seterrf(ctx->status, "proto3 fields cannot be required (%s)",
-                       f->full_name);
-    return false;
-  }
-
-  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
-    int oneof_index =
-        google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
-    upb_oneofdef *oneof;
-    upb_value v = upb_value_constptr(f);
-
-    if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
-      upb_status_seterrf(ctx->status,
-                         "fields in oneof must have OPTIONAL label (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (!m) {
-      upb_status_seterrf(ctx->status,
-                         "oneof_index provided for extension field (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (oneof_index >= m->oneof_count) {
-      upb_status_seterrf(ctx->status, "oneof_index out of range (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    oneof = (upb_oneofdef*)&m->oneofs[oneof_index];
-    f->oneof = oneof;
-
-    CHK(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc));
-    CHK(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc));
-  } else {
-    f->oneof = NULL;
-  }
-
-  if (google_protobuf_FieldDescriptorProto_has_options(field_proto)) {
-    options = google_protobuf_FieldDescriptorProto_options(field_proto);
-    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
-    f->packed_ = google_protobuf_FieldOptions_packed(options);
-  } else {
-    f->lazy_ = false;
-    f->packed_ = false;
-  }
-
-  return true;
-}
-
-static bool create_enumdef(
-    const symtab_addctx *ctx, const char *prefix,
-    const google_protobuf_EnumDescriptorProto *enum_proto) {
-  upb_enumdef *e;
-  const google_protobuf_EnumValueDescriptorProto *const *values;
-  upb_strview name;
-  size_t i, n;
-
-  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
-  CHK(upb_isident(name, false, ctx->status));
-
-  e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
-  e->full_name = makefullname(ctx, prefix, name);
-  CHK_OOM(symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM)));
-
-  CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, ctx->alloc));
-  CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc));
-
-  e->file = ctx->file;
-  e->defaultval = 0;
-
-  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
-
-  if (n == 0) {
-    upb_status_seterrf(ctx->status,
-                       "enums must contain at least one value (%s)",
-                       e->full_name);
-    return false;
-  }
-
-  for (i = 0; i < n; i++) {
-    const google_protobuf_EnumValueDescriptorProto *value = values[i];
-    upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
-    char *name2 = strviewdup(ctx, name);
-    int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
-    upb_value v = upb_value_int32(num);
-
-    if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
-      upb_status_seterrf(ctx->status,
-                         "for proto3, the first enum value must be zero (%s)",
-                         e->full_name);
-      return false;
-    }
-
-    if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate enum label '%s'", name2);
-      return false;
-    }
-
-    CHK_OOM(name2)
-    CHK_OOM(
-        upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc));
-
-    if (!upb_inttable_lookup(&e->iton, num, NULL)) {
-      upb_value v = upb_value_cstr(name2);
-      CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc));
-    }
-  }
-
-  upb_inttable_compact2(&e->iton, ctx->alloc);
-
-  return true;
-}
-
-static bool create_msgdef(const symtab_addctx *ctx, const char *prefix,
-                          const google_protobuf_DescriptorProto *msg_proto) {
-  upb_msgdef *m;
-  const google_protobuf_MessageOptions *options;
-  const google_protobuf_OneofDescriptorProto *const *oneofs;
-  const google_protobuf_FieldDescriptorProto *const *fields;
-  const google_protobuf_EnumDescriptorProto *const *enums;
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-  upb_strview name;
-
-  name = google_protobuf_DescriptorProto_name(msg_proto);
-  CHK(upb_isident(name, false, ctx->status));
-
-  m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
-  m->full_name = makefullname(ctx, prefix, name);
-  CHK_OOM(symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG)));
-
-  CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-  CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
-  m->file = ctx->file;
-  m->map_entry = false;
-
-  options = google_protobuf_DescriptorProto_options(msg_proto);
-
-  if (options) {
-    m->map_entry = google_protobuf_MessageOptions_map_entry(options);
-  }
-
-  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n);
-  m->oneof_count = 0;
-  m->oneofs = upb_malloc(ctx->alloc, sizeof(*m->oneofs) * n);
-  for (i = 0; i < n; i++) {
-    CHK(create_oneofdef(ctx, m, oneofs[i]));
-  }
-
-  fields = google_protobuf_DescriptorProto_field(msg_proto, &n);
-  m->field_count = 0;
-  m->fields = upb_malloc(ctx->alloc, sizeof(*m->fields) * n);
-  for (i = 0; i < n; i++) {
-    CHK(create_fielddef(ctx, m->full_name, m, fields[i]));
-  }
-
-  CHK(assign_msg_indices(m, ctx->status));
-  assign_msg_wellknowntype(m);
-  upb_inttable_compact2(&m->itof, ctx->alloc);
-
-  /* This message is built.  Now build nested messages and enums. */
-
-  enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_enumdef(ctx, m->full_name, enums[i]));
-  }
-
-  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_msgdef(ctx, m->full_name, msgs[i]));
-  }
-
-  return true;
-}
-
-typedef struct {
-  int msg_count;
-  int enum_count;
-  int ext_count;
-} decl_counts;
-
-static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
-                               decl_counts *counts) {
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-
-  counts->msg_count++;
-
-  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    count_types_in_msg(msgs[i], counts);
-  }
-
-  google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  counts->enum_count += n;
-
-  google_protobuf_DescriptorProto_extension(msg_proto, &n);
-  counts->ext_count += n;
-}
-
-static void count_types_in_file(
-    const google_protobuf_FileDescriptorProto *file_proto,
-    decl_counts *counts) {
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    count_types_in_msg(msgs[i], counts);
-  }
-
-  google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  counts->enum_count += n;
-
-  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  counts->ext_count += n;
-}
-
-static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix,
-                             upb_fielddef *f) {
-  upb_strview name;
-  const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
-
-  if (f->is_extension_) {
-    if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
-      upb_status_seterrf(ctx->status,
-                         "extension for field '%s' had no extendee",
-                         f->full_name);
-      return false;
-    }
-
-    name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
-    f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
-    CHK(f->msgdef);
-  }
-
-  if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
-      !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
-    upb_status_seterrf(ctx->status, "field '%s' is missing type name",
-                       f->full_name);
-    return false;
-  }
-
-  name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
-
-  if (upb_fielddef_issubmsg(f)) {
-    f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
-    CHK(f->sub.msgdef);
-  } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
-    f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
-    CHK(f->sub.enumdef);
-  }
-
-  /* Have to delay resolving of the default value until now because of the enum
-   * case, since enum defaults are specified with a label. */
-  if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
-    upb_strview defaultval =
-        google_protobuf_FieldDescriptorProto_default_value(field_proto);
-
-    if (f->file->syntax == UPB_SYNTAX_PROTO3) {
-      upb_status_seterrf(ctx->status,
-                         "proto3 fields cannot have explicit defaults (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (upb_fielddef_issubmsg(f)) {
-      upb_status_seterrf(ctx->status,
-                         "message fields cannot have explicit defaults (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (!parse_default(ctx, defaultval.data, defaultval.size, f)) {
-      upb_status_seterrf(ctx->status,
-                         "couldn't parse default '" UPB_STRVIEW_FORMAT
-                         "' for field (%s)",
-                         UPB_STRVIEW_ARGS(defaultval), f->full_name);
-      return false;
-    }
-  } else {
-    set_default_default(ctx, f);
-  }
-
-  return true;
-}
-
-static bool build_filedef(
-    const symtab_addctx *ctx, upb_filedef *file,
-    const google_protobuf_FileDescriptorProto *file_proto) {
-  upb_alloc *alloc = ctx->alloc;
-  const google_protobuf_FileOptions *file_options_proto;
-  const google_protobuf_DescriptorProto *const *msgs;
-  const google_protobuf_EnumDescriptorProto *const *enums;
-  const google_protobuf_FieldDescriptorProto *const *exts;
-  const upb_strview* strs;
-  size_t i, n;
-  decl_counts counts = {0};
-
-  count_types_in_file(file_proto, &counts);
-
-  file->msgs = upb_malloc(alloc, sizeof(*file->msgs) * counts.msg_count);
-  file->enums = upb_malloc(alloc, sizeof(*file->enums) * counts.enum_count);
-  file->exts = upb_malloc(alloc, sizeof(*file->exts) * counts.ext_count);
-
-  CHK_OOM(counts.msg_count == 0 || file->msgs);
-  CHK_OOM(counts.enum_count == 0 || file->enums);
-  CHK_OOM(counts.ext_count == 0 || file->exts);
-
-  /* We increment these as defs are added. */
-  file->msg_count = 0;
-  file->enum_count = 0;
-  file->ext_count = 0;
-
-  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
-    upb_status_seterrmsg(ctx->status, "File has no name");
-    return false;
-  }
-
-  file->name =
-      strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
-  file->phpprefix = NULL;
-  file->phpnamespace = NULL;
-
-  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
-    upb_strview package =
-        google_protobuf_FileDescriptorProto_package(file_proto);
-    CHK(upb_isident(package, true, ctx->status));
-    file->package = strviewdup(ctx, package);
-  } else {
-    file->package = NULL;
-  }
-
-  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
-    upb_strview syntax =
-        google_protobuf_FileDescriptorProto_syntax(file_proto);
-
-    if (streql_view(syntax, "proto2")) {
-      file->syntax = UPB_SYNTAX_PROTO2;
-    } else if (streql_view(syntax, "proto3")) {
-      file->syntax = UPB_SYNTAX_PROTO3;
-    } else {
-      upb_status_seterrf(ctx->status, "Invalid syntax '%s'", syntax);
-      return false;
-    }
-  } else {
-    file->syntax = UPB_SYNTAX_PROTO2;
-  }
-
-  /* Read options. */
-  file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
-  if (file_options_proto) {
-    if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
-      file->phpprefix = strviewdup(
-          ctx,
-          google_protobuf_FileOptions_php_class_prefix(file_options_proto));
-    }
-    if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
-      file->phpnamespace = strviewdup(
-          ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
-    }
-  }
-
-  /* Verify dependencies. */
-  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
-  file->deps = upb_malloc(alloc, sizeof(*file->deps) * n) ;
-  CHK_OOM(n == 0 || file->deps);
-
-  for (i = 0; i < n; i++) {
-    upb_strview dep_name = strs[i];
-    upb_value v;
-    if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
-                              dep_name.size, &v)) {
-      upb_status_seterrf(ctx->status,
-                         "Depends on file '" UPB_STRVIEW_FORMAT
-                         "', but it has not been loaded",
-                         UPB_STRVIEW_ARGS(dep_name));
-      return false;
-    }
-    file->deps[i] = upb_value_getconstptr(v);
-  }
-
-  /* Create messages. */
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_msgdef(ctx, file->package, msgs[i]));
-  }
-
-  /* Create enums. */
-  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_enumdef(ctx, file->package, enums[i]));
-  }
-
-  /* Create extensions. */
-  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  file->exts = upb_malloc(alloc, sizeof(*file->exts) * n);
-  CHK_OOM(n == 0 || file->exts);
-  for (i = 0; i < n; i++) {
-    CHK(create_fielddef(ctx, file->package, NULL, exts[i]));
-  }
-
-  /* Now that all names are in the table, resolve references. */
-  for (i = 0; i < file->ext_count; i++) {
-    CHK(resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]));
-  }
-
-  for (i = 0; i < file->msg_count; i++) {
-    const upb_msgdef *m = &file->msgs[i];
-    int j;
-    for (j = 0; j < m->field_count; j++) {
-      CHK(resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]));
-    }
-  }
-
-  return true;
- }
-
-static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx,
-                                 upb_status *status) {
-  const upb_filedef *file = ctx->file;
-  upb_alloc *alloc = upb_arena_alloc(s->arena);
-  upb_strtable_iter iter;
-
-  CHK_OOM(upb_strtable_insert3(&s->files, file->name, strlen(file->name),
-                               upb_value_constptr(file), alloc));
-
-  upb_strtable_begin(&iter, ctx->addtab);
-  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
-    const char *key = upb_strtable_iter_key(&iter);
-    size_t keylen = upb_strtable_iter_keylength(&iter);
-    upb_value value = upb_strtable_iter_value(&iter);
-    CHK_OOM(upb_strtable_insert3(&s->syms, key, keylen, value, alloc));
-  }
-
-  return true;
-}
-
-/* upb_filedef ****************************************************************/
-
-const char *upb_filedef_name(const upb_filedef *f) {
-  return f->name;
-}
-
-const char *upb_filedef_package(const upb_filedef *f) {
-  return f->package;
-}
-
-const char *upb_filedef_phpprefix(const upb_filedef *f) {
-  return f->phpprefix;
-}
-
-const char *upb_filedef_phpnamespace(const upb_filedef *f) {
-  return f->phpnamespace;
-}
-
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
-  return f->syntax;
-}
-
-int upb_filedef_msgcount(const upb_filedef *f) {
-  return f->msg_count;
-}
-
-int upb_filedef_depcount(const upb_filedef *f) {
-  return f->dep_count;
-}
-
-int upb_filedef_enumcount(const upb_filedef *f) {
-  return f->enum_count;
-}
-
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
-}
-
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
-}
-
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
-}
-
-void upb_symtab_free(upb_symtab *s) {
-  upb_arena_free(s->arena);
-  upb_gfree(s);
-}
-
-upb_symtab *upb_symtab_new(void) {
-  upb_symtab *s = upb_gmalloc(sizeof(*s));
-  upb_alloc *alloc;
-
-  if (!s) {
-    return NULL;
-  }
-
-  s->arena = upb_arena_new();
-  alloc = upb_arena_alloc(s->arena);
-
-  if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, alloc) ||
-      !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, alloc)) {
-    upb_arena_free(s->arena);
-    upb_gfree(s);
-    s = NULL;
-  }
-  return s;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ?
-      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
-                                        size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
-      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ?
-      unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
-}
-
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
-  upb_value v;
-  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
-                                                  : NULL;
-}
-
-const upb_filedef *upb_symtab_lookupfile2(
-    const upb_symtab *s, const char *name, size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->files, name, len, &v) ?
-      upb_value_getconstptr(v) : NULL;
-}
-
-const upb_filedef *upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
-    upb_status *status) {
-  upb_arena *tmparena = upb_arena_new();
-  upb_strtable addtab;
-  upb_alloc *alloc = upb_arena_alloc(s->arena);
-  upb_filedef *file = upb_malloc(alloc, sizeof(*file));
-  bool ok;
-  symtab_addctx ctx;
-
-  ctx.file = file;
-  ctx.symtab = s;
-  ctx.alloc = alloc;
-  ctx.tmp = upb_arena_alloc(tmparena);
-  ctx.addtab = &addtab;
-  ctx.status = status;
-
-  ok = file &&
-      upb_strtable_init2(&addtab, UPB_CTYPE_CONSTPTR, ctx.tmp) &&
-      build_filedef(&ctx, file, file_proto) &&
-      upb_symtab_addtotabs(s, &ctx, status);
-
-  upb_arena_free(tmparena);
-  return ok ? file : NULL;
-}
-
-/* Include here since we want most of this file to be stdio-free. */
-#include <stdio.h>
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
-  /* Since this function should never fail (it would indicate a bug in upb) we
-   * print errors to stderr instead of returning error status to the user. */
-  upb_def_init **deps = init->deps;
-  google_protobuf_FileDescriptorProto *file;
-  upb_arena *arena;
-  upb_status status;
-
-  upb_status_clear(&status);
-
-  if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
-    return true;
-  }
-
-  arena = upb_arena_new();
-
-  for (; *deps; deps++) {
-    if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
-  }
-
-  file = google_protobuf_FileDescriptorProto_parse(
-      init->descriptor.data, init->descriptor.size, arena);
-
-  if (!file) {
-    upb_status_seterrf(
-        &status,
-        "Failed to parse compiled-in descriptor for file '%s'. This should "
-        "never happen.",
-        init->filename);
-    goto err;
-  }
-
-  if (!upb_symtab_addfile(s, file, &status)) goto err;
-
-  upb_arena_free(arena);
-  return true;
-
-err:
-  fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
-          upb_status_errmsg(&status));
-  upb_arena_free(arena);
-  return false;
-}
-
-#undef CHK
-#undef CHK_OOM
-
-
-
-static bool is_power_of_two(size_t val) {
-  return (val & (val - 1)) == 0;
-}
-
-/* Align up to the given power of 2. */
-static size_t align_up(size_t val, size_t align) {
-  UPB_ASSERT(is_power_of_two(align));
-  return (val + align - 1) & ~(align - 1);
-}
-
-static size_t div_round_up(size_t n, size_t d) {
-  return (n + d - 1) / d;
-}
-
-static size_t upb_msgval_sizeof2(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT64:
-      return 8;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_FLOAT:
-      return 4;
-    case UPB_TYPE_BOOL:
-      return 1;
-    case UPB_TYPE_MESSAGE:
-      return sizeof(void*);
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_STRING:
-      return sizeof(upb_strview);
-  }
-  UPB_UNREACHABLE();
-}
-
-static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
-  if (upb_fielddef_isseq(f)) {
-    return sizeof(void*);
-  } else {
-    return upb_msgval_sizeof2(upb_fielddef_type(f));
-  }
-}
-
-
-/** upb_msglayout *************************************************************/
-
-static void upb_msglayout_free(upb_msglayout *l) {
-  upb_gfree(l);
-}
-
-static size_t upb_msglayout_place(upb_msglayout *l, size_t size) {
-  size_t ret;
-
-  l->size = align_up(l->size, size);
-  ret = l->size;
-  l->size += size;
-  return ret;
-}
-
-static bool upb_msglayout_init(const upb_msgdef *m,
-                               upb_msglayout *l,
-                               upb_msgfactory *factory) {
-  upb_msg_field_iter it;
-  upb_msg_oneof_iter oit;
-  size_t hasbit;
-  size_t submsg_count = 0;
-  const upb_msglayout **submsgs;
-  upb_msglayout_field *fields;
-
-  for (upb_msg_field_begin(&it, m);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* f = upb_msg_iter_field(&it);
-    if (upb_fielddef_issubmsg(f)) {
-      submsg_count++;
-    }
-  }
-
-  memset(l, 0, sizeof(*l));
-
-  fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields));
-  submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs));
-
-  if ((!fields && upb_msgdef_numfields(m)) ||
-      (!submsgs && submsg_count)) {
-    /* OOM. */
-    upb_gfree(fields);
-    upb_gfree(submsgs);
-    return false;
-  }
-
-  l->field_count = upb_msgdef_numfields(m);
-  l->fields = fields;
-  l->submsgs = submsgs;
-
-  /* Allocate data offsets in three stages:
-   *
-   * 1. hasbits.
-   * 2. regular fields.
-   * 3. oneof fields.
-   *
-   * OPT: There is a lot of room for optimization here to minimize the size.
-   */
-
-  /* Allocate hasbits and set basic field attributes. */
-  submsg_count = 0;
-  for (upb_msg_field_begin(&it, m), hasbit = 0;
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* f = upb_msg_iter_field(&it);
-    upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
-
-    field->number = upb_fielddef_number(f);
-    field->descriptortype = upb_fielddef_descriptortype(f);
-    field->label = upb_fielddef_label(f);
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msglayout *sub_layout =
-          upb_msgfactory_getlayout(factory, upb_fielddef_msgsubdef(f));
-      field->submsg_index = submsg_count++;
-      submsgs[field->submsg_index] = sub_layout;
-    }
-
-    if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) {
-      field->presence = (hasbit++);
-    } else {
-      field->presence = 0;
-    }
-  }
-
-  /* Account for space used by hasbits. */
-  l->size = div_round_up(hasbit, 8);
-
-  /* Allocate non-oneof fields. */
-  for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* f = upb_msg_iter_field(&it);
-    size_t field_size = upb_msg_fielddefsize(f);
-    size_t index = upb_fielddef_index(f);
-
-    if (upb_fielddef_containingoneof(f)) {
-      /* Oneofs are handled separately below. */
-      continue;
-    }
-
-    fields[index].offset = upb_msglayout_place(l, field_size);
-  }
-
-  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
-   * and space for the actual data. */
-  for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
-    upb_oneof_iter fit;
-
-    size_t case_size = sizeof(uint32_t);  /* Could potentially optimize this. */
-    size_t field_size = 0;
-    uint32_t case_offset;
-    uint32_t data_offset;
-
-    /* Calculate field size: the max of all field sizes. */
-    for (upb_oneof_begin(&fit, o);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* f = upb_oneof_iter_field(&fit);
-      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
-    }
-
-    /* Align and allocate case offset. */
-    case_offset = upb_msglayout_place(l, case_size);
-    data_offset = upb_msglayout_place(l, field_size);
-
-    for (upb_oneof_begin(&fit, o);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* f = upb_oneof_iter_field(&fit);
-      fields[upb_fielddef_index(f)].offset = data_offset;
-      fields[upb_fielddef_index(f)].presence = ~case_offset;
-    }
-  }
-
-  /* Size of the entire structure should be a multiple of its greatest
-   * alignment.  TODO: track overall alignment for real? */
-  l->size = align_up(l->size, 8);
-
-  return true;
-}
-
-
-/** upb_msgfactory ************************************************************/
-
-struct upb_msgfactory {
-  const upb_symtab *symtab;  /* We own a ref. */
-  upb_inttable layouts;
-};
-
-upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) {
-  upb_msgfactory *ret = upb_gmalloc(sizeof(*ret));
-
-  ret->symtab = symtab;
-  upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR);
-
-  return ret;
-}
-
-void upb_msgfactory_free(upb_msgfactory *f) {
-  upb_inttable_iter i;
-  upb_inttable_begin(&i, &f->layouts);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i));
-    upb_msglayout_free(l);
-  }
-
-  upb_inttable_uninit(&f->layouts);
-  upb_gfree(f);
-}
-
-const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) {
-  return f->symtab;
-}
-
-const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
-                                              const upb_msgdef *m) {
-  upb_value v;
-  UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m);
-  UPB_ASSERT(!upb_msgdef_mapentry(m));
-
-  if (upb_inttable_lookupptr(&f->layouts, m, &v)) {
-    UPB_ASSERT(upb_value_getptr(v));
-    return upb_value_getptr(v);
-  } else {
-    /* In case of circular dependency, layout has to be inserted first. */
-    upb_msglayout *l = upb_gmalloc(sizeof(*l));
-    upb_msgfactory *mutable_f = (void*)f;
-    upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l));
-    UPB_ASSERT(l);
-    if (!upb_msglayout_init(m, l, f)) {
-      upb_msglayout_free(l);
-    }
-    return l;
-  }
-}
-/*
-** TODO(haberman): it's unclear whether a lot of the consistency checks should
-** UPB_ASSERT() or return false.
-*/
-
-
-#include <string.h>
-
-
-
-struct upb_handlers {
-  upb_handlercache *cache;
-  const upb_msgdef *msg;
-  const upb_handlers **sub;
-  const void *top_closure_type;
-  upb_handlers_tabent table[1];  /* Dynamically-sized field handler array. */
-};
-
-static void *upb_calloc(upb_arena *arena, size_t size) {
-  void *mem = upb_malloc(upb_arena_alloc(arena), size);
-  if (mem) {
-    memset(mem, 0, size);
-  }
-  return mem;
-}
-
-/* Defined for the sole purpose of having a unique pointer value for
- * UPB_NO_CLOSURE. */
-char _upb_noclosure;
-
-/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
- * subhandlers for this submessage field. */
-#define SUBH(h, selector) (h->sub[selector])
-
-/* The selector for a submessage field is the field index. */
-#define SUBH_F(h, f) SUBH(h, upb_fielddef_index(f))
-
-static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
-                         upb_handlertype_t type) {
-  upb_selector_t sel;
-  bool ok;
-
-  ok = upb_handlers_getselector(f, type, &sel);
-
-  UPB_ASSERT(upb_handlers_msgdef(h) == upb_fielddef_containingtype(f));
-  UPB_ASSERT(ok);
-
-  return sel;
-}
-
-static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
-                             upb_handlertype_t type) {
-  int32_t sel = trygetsel(h, f, type);
-  UPB_ASSERT(sel >= 0);
-  return sel;
-}
-
-static const void **returntype(upb_handlers *h, const upb_fielddef *f,
-                               upb_handlertype_t type) {
-  return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type;
-}
-
-static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
-                  upb_handlertype_t type, upb_func *func,
-                  const upb_handlerattr *attr) {
-  upb_handlerattr set_attr = UPB_HANDLERATTR_INIT;
-  const void *closure_type;
-  const void **context_closure_type;
-
-  UPB_ASSERT(!h->table[sel].func);
-
-  if (attr) {
-    set_attr = *attr;
-  }
-
-  /* Check that the given closure type matches the closure type that has been
-   * established for this context (if any). */
-  closure_type = set_attr.closure_type;
-
-  if (type == UPB_HANDLER_STRING) {
-    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
-  } else if (f && upb_fielddef_isseq(f) &&
-             type != UPB_HANDLER_STARTSEQ &&
-             type != UPB_HANDLER_ENDSEQ) {
-    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
-  } else {
-    context_closure_type = &h->top_closure_type;
-  }
-
-  if (closure_type && *context_closure_type &&
-      closure_type != *context_closure_type) {
-    return false;
-  }
-
-  if (closure_type)
-    *context_closure_type = closure_type;
-
-  /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
-   * matches any pre-existing expectations about what type is expected. */
-  if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
-    const void *return_type = set_attr.return_closure_type;
-    const void *table_return_type = h->table[sel].attr.return_closure_type;
-    if (return_type && table_return_type && return_type != table_return_type) {
-      return false;
-    }
-
-    if (table_return_type && !return_type) {
-      set_attr.return_closure_type = table_return_type;
-    }
-  }
-
-  h->table[sel].func = (upb_func*)func;
-  h->table[sel].attr = set_attr;
-  return true;
-}
-
-/* Returns the effective closure type for this handler (which will propagate
- * from outer frames if this frame has no START* handler).  Not implemented for
- * UPB_HANDLER_STRING at the moment since this is not needed.  Returns NULL is
- * the effective closure type is unspecified (either no handler was registered
- * to specify it or the handler that was registered did not specify the closure
- * type). */
-const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
-                                   upb_handlertype_t type) {
-  const void *ret;
-  upb_selector_t sel;
-
-  UPB_ASSERT(type != UPB_HANDLER_STRING);
-  ret = h->top_closure_type;
-
-  if (upb_fielddef_isseq(f) &&
-      type != UPB_HANDLER_STARTSEQ &&
-      type != UPB_HANDLER_ENDSEQ &&
-      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
-    ret = h->table[sel].attr.return_closure_type;
-  }
-
-  if (type == UPB_HANDLER_STRING &&
-      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
-    ret = h->table[sel].attr.return_closure_type;
-  }
-
-  /* The effective type of the submessage; not used yet.
-   * if (type == SUBMESSAGE &&
-   *     h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
-   *   ret = h->table[sel].attr.return_closure_type;
-   * } */
-
-  return ret;
-}
-
-/* Checks whether the START* handler specified by f & type is missing even
- * though it is required to convert the established type of an outer frame
- * ("closure_type") into the established type of an inner frame (represented in
- * the return closure type of this handler's attr. */
-bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
-                upb_status *status) {
-  const void *closure_type;
-  const upb_handlerattr *attr;
-  const void *return_closure_type;
-
-  upb_selector_t sel = handlers_getsel(h, f, type);
-  if (h->table[sel].func) return true;
-  closure_type = effective_closure_type(h, f, type);
-  attr = &h->table[sel].attr;
-  return_closure_type = attr->return_closure_type;
-  if (closure_type && return_closure_type &&
-      closure_type != return_closure_type) {
-    return false;
-  }
-  return true;
-}
-
-static upb_handlers *upb_handlers_new(const upb_msgdef *md,
-                                      upb_handlercache *cache,
-                                      upb_arena *arena) {
-  int extra;
-  upb_handlers *h;
-
-  extra = sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1);
-  h = upb_calloc(arena, sizeof(*h) + extra);
-  if (!h) return NULL;
-
-  h->cache = cache;
-  h->msg = md;
-
-  if (upb_msgdef_submsgfieldcount(md) > 0) {
-    size_t bytes = upb_msgdef_submsgfieldcount(md) * sizeof(*h->sub);
-    h->sub = upb_calloc(arena, bytes);
-    if (!h->sub) return NULL;
-  } else {
-    h->sub = 0;
-  }
-
-  /* calloc() above initialized all handlers to NULL. */
-  return h;
-}
-
-/* Public interface ***********************************************************/
-
-#define SETTER(name, handlerctype, handlertype)                       \
-  bool upb_handlers_set##name(upb_handlers *h, const upb_fielddef *f, \
-                              handlerctype func,                      \
-                              const upb_handlerattr *attr) {          \
-    int32_t sel = trygetsel(h, f, handlertype);                       \
-    return doset(h, sel, f, handlertype, (upb_func *)func, attr);     \
-  }
-
-SETTER(int32,       upb_int32_handlerfunc*,       UPB_HANDLER_INT32)
-SETTER(int64,       upb_int64_handlerfunc*,       UPB_HANDLER_INT64)
-SETTER(uint32,      upb_uint32_handlerfunc*,      UPB_HANDLER_UINT32)
-SETTER(uint64,      upb_uint64_handlerfunc*,      UPB_HANDLER_UINT64)
-SETTER(float,       upb_float_handlerfunc*,       UPB_HANDLER_FLOAT)
-SETTER(double,      upb_double_handlerfunc*,      UPB_HANDLER_DOUBLE)
-SETTER(bool,        upb_bool_handlerfunc*,        UPB_HANDLER_BOOL)
-SETTER(startstr,    upb_startstr_handlerfunc*,    UPB_HANDLER_STARTSTR)
-SETTER(string,      upb_string_handlerfunc*,      UPB_HANDLER_STRING)
-SETTER(endstr,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSTR)
-SETTER(startseq,    upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSEQ)
-SETTER(startsubmsg, upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSUBMSG)
-SETTER(endsubmsg,   upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSUBMSG)
-SETTER(endseq,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSEQ)
-
-#undef SETTER
-
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
-                             const upb_handlerattr *attr) {
-  return doset(h, UPB_UNKNOWN_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
-                              const upb_handlerattr *attr) {
-  return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
-                            const upb_handlerattr *attr) {
-  return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
-                                 const upb_handlers *sub) {
-  UPB_ASSERT(sub);
-  UPB_ASSERT(upb_fielddef_issubmsg(f));
-  if (SUBH_F(h, f)) return false;  /* Can't reset. */
-  if (upb_handlers_msgdef(sub) != upb_fielddef_msgsubdef(f)) {
-    return false;
-  }
-  SUBH_F(h, f) = sub;
-  return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
-                                                const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_issubmsg(f));
-  return SUBH_F(h, f);
-}
-
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
-                                  const void **handler_data) {
-  upb_func *ret = (upb_func *)h->table[s].func;
-  if (ret && handler_data) {
-    *handler_data = h->table[s].attr.handler_data;
-  }
-  return ret;
-}
-
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
-                          upb_handlerattr *attr) {
-  if (!upb_handlers_gethandler(h, sel, NULL))
-    return false;
-  *attr = h->table[sel].attr;
-  return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
-                                                    upb_selector_t sel) {
-  /* STARTSUBMSG selector in sel is the field's selector base. */
-  return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
-}
-
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
-
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
-  return upb_handlercache_addcleanup(h->cache, p, func);
-}
-
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
-    case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
-    case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
-    case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
-    case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
-    case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
-    case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
-    default: UPB_ASSERT(false); return -1;  /* Invalid input. */
-  }
-}
-
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
-                              upb_selector_t *s) {
-  uint32_t selector_base = upb_fielddef_selectorbase(f);
-  switch (type) {
-    case UPB_HANDLER_INT32:
-    case UPB_HANDLER_INT64:
-    case UPB_HANDLER_UINT32:
-    case UPB_HANDLER_UINT64:
-    case UPB_HANDLER_FLOAT:
-    case UPB_HANDLER_DOUBLE:
-    case UPB_HANDLER_BOOL:
-      if (!upb_fielddef_isprimitive(f) ||
-          upb_handlers_getprimitivehandlertype(f) != type)
-        return false;
-      *s = selector_base;
-      break;
-    case UPB_HANDLER_STRING:
-      if (upb_fielddef_isstring(f)) {
-        *s = selector_base;
-      } else if (upb_fielddef_lazy(f)) {
-        *s = selector_base + 3;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_STARTSTR:
-      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
-        *s = selector_base + 1;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_ENDSTR:
-      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
-        *s = selector_base + 2;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_STARTSEQ:
-      if (!upb_fielddef_isseq(f)) return false;
-      *s = selector_base - 2;
-      break;
-    case UPB_HANDLER_ENDSEQ:
-      if (!upb_fielddef_isseq(f)) return false;
-      *s = selector_base - 1;
-      break;
-    case UPB_HANDLER_STARTSUBMSG:
-      if (!upb_fielddef_issubmsg(f)) return false;
-      /* Selectors for STARTSUBMSG are at the beginning of the table so that the
-       * selector can also be used as an index into the "sub" array of
-       * subhandlers.  The indexes for the two into these two tables are the
-       * same, except that in the handler table the static selectors come first. */
-      *s = upb_fielddef_index(f) + UPB_STATIC_SELECTOR_COUNT;
-      break;
-    case UPB_HANDLER_ENDSUBMSG:
-      if (!upb_fielddef_issubmsg(f)) return false;
-      *s = selector_base;
-      break;
-  }
-  UPB_ASSERT((size_t)*s < upb_msgdef_selectorcount(upb_fielddef_containingtype(f)));
-  return true;
-}
-
-/* upb_handlercache ***********************************************************/
-
-struct upb_handlercache {
-  upb_arena *arena;
-  upb_inttable tab;  /* maps upb_msgdef* -> upb_handlers*. */
-  upb_handlers_callback *callback;
-  const void *closure;
-};
-
-const upb_handlers *upb_handlercache_get(upb_handlercache *c,
-                                         const upb_msgdef *md) {
-  upb_msg_field_iter i;
-  upb_value v;
-  upb_handlers *h;
-
-  if (upb_inttable_lookupptr(&c->tab, md, &v)) {
-    return upb_value_getptr(v);
-  }
-
-  h = upb_handlers_new(md, c, c->arena);
-  v = upb_value_ptr(h);
-
-  if (!h) return NULL;
-  if (!upb_inttable_insertptr(&c->tab, md, v)) return NULL;
-
-  c->callback(c->closure, h);
-
-  /* For each submessage field, get or create a handlers object and set it as
-   * the subhandlers. */
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
-      const upb_handlers *sub_mh = upb_handlercache_get(c, subdef);
-
-      if (!sub_mh) return NULL;
-
-      upb_handlers_setsubhandlers(h, f, sub_mh);
-    }
-  }
-
-  return h;
-}
-
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
-                                       const void *closure) {
-  upb_handlercache *cache = upb_gmalloc(sizeof(*cache));
-
-  if (!cache) return NULL;
-
-  cache->arena = upb_arena_new();
-
-  cache->callback = callback;
-  cache->closure = closure;
-
-  if (!upb_inttable_init(&cache->tab, UPB_CTYPE_PTR)) goto oom;
-
-  return cache;
-
-oom:
-  upb_gfree(cache);
-  return NULL;
-}
-
-void upb_handlercache_free(upb_handlercache *cache) {
-  upb_inttable_uninit(&cache->tab);
-  upb_arena_free(cache->arena);
-  upb_gfree(cache);
-}
-
-bool upb_handlercache_addcleanup(upb_handlercache *c, void *p,
-                                 upb_handlerfree *func) {
-  return upb_arena_addcleanup(c->arena, p, func);
-}
-
-/* upb_byteshandler ***********************************************************/
-
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
-                                  upb_startstr_handlerfunc *func, void *d) {
-  h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_STARTSTR_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-bool upb_byteshandler_setstring(upb_byteshandler *h,
-                                upb_string_handlerfunc *func, void *d) {
-  h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_STRING_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
-                                upb_endfield_handlerfunc *func, void *d) {
-  h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_ENDSTR_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-/** Handlers for upb_msg ******************************************************/
-
-typedef struct {
-  size_t offset;
-  int32_t hasbit;
-} upb_msg_handlerdata;
-
-/* Fallback implementation if the handler is not specialized by the producer. */
-#define MSG_WRITER(type, ctype)                                               \
-  bool upb_msg_set ## type (void *c, const void *hd, ctype val) {             \
-    uint8_t *m = c;                                                           \
-    const upb_msg_handlerdata *d = hd;                                        \
-    if (d->hasbit > 0)                                                        \
-      *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8);                   \
-    *(ctype*)&m[d->offset] = val;                                             \
-    return true;                                                              \
-  }                                                                           \
-
-MSG_WRITER(double, double)
-MSG_WRITER(float,  float)
-MSG_WRITER(int32,  int32_t)
-MSG_WRITER(int64,  int64_t)
-MSG_WRITER(uint32, uint32_t)
-MSG_WRITER(uint64, uint64_t)
-MSG_WRITER(bool,   bool)
-
-bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f,
-                              size_t offset, int32_t hasbit) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  bool ok;
-
-  upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d));
-  if (!d) return false;
-  d->offset = offset;
-  d->hasbit = hasbit;
-
-  attr.handler_data = d;
-  attr.alwaysok = true;
-  upb_handlers_addcleanup(h, d, upb_gfree);
-
-#define TYPE(u, l) \
-  case UPB_TYPE_##u: \
-    ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break;
-
-  ok = false;
-
-  switch (upb_fielddef_type(f)) {
-    TYPE(INT64,  int64);
-    TYPE(INT32,  int32);
-    TYPE(ENUM,   int32);
-    TYPE(UINT64, uint64);
-    TYPE(UINT32, uint32);
-    TYPE(DOUBLE, double);
-    TYPE(FLOAT,  float);
-    TYPE(BOOL,   bool);
-    default: UPB_ASSERT(false); break;
-  }
-#undef TYPE
-
-  return ok;
-}
-
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
-                                  upb_selector_t s,
-                                  upb_fieldtype_t *type,
-                                  size_t *offset,
-                                  int32_t *hasbit) {
-  const upb_msg_handlerdata *d;
-  const void *p;
-  upb_func *f = upb_handlers_gethandler(h, s, &p);
-
-  if ((upb_int64_handlerfunc*)f == upb_msg_setint64) {
-    *type = UPB_TYPE_INT64;
-  } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) {
-    *type = UPB_TYPE_INT32;
-  } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) {
-    *type = UPB_TYPE_UINT64;
-  } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) {
-    *type = UPB_TYPE_UINT32;
-  } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) {
-    *type = UPB_TYPE_DOUBLE;
-  } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) {
-    *type = UPB_TYPE_FLOAT;
-  } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) {
-    *type = UPB_TYPE_BOOL;
-  } else {
-    return false;
-  }
-
-  d = p;
-  *offset = d->offset;
-  *hasbit = d->hasbit;
-  return true;
-}
-
-
-bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) {
-  void *subc;
-  bool ret;
-  upb_bufhandle handle = UPB_BUFHANDLE_INIT;
-  handle.buf = buf;
-  ret = upb_bytessink_start(sink, len, &subc);
-  if (ret && len != 0) {
-    ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len);
-  }
-  if (ret) {
-    ret = upb_bytessink_end(sink);
-  }
-  return ret;
-}
-/*
-** protobuf decoder bytecode compiler
-**
-** Code to compile a upb::Handlers into bytecode for decoding a protobuf
-** according to that specific schema and destination handlers.
-**
-** Bytecode definition is in decoder.int.h.
-*/
-
-#include <stdarg.h>
-
-#ifdef UPB_DUMP_BYTECODE
-#include <stdio.h>
-#endif
-
-
-#define MAXLABEL 5
-#define EMPTYLABEL -1
-
-/* upb_pbdecodermethod ********************************************************/
-
-static void freemethod(upb_pbdecodermethod *method) {
-  upb_inttable_uninit(&method->dispatch);
-  upb_gfree(method);
-}
-
-static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
-                                      mgroup *group) {
-  upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret));
-  upb_byteshandler_init(&ret->input_handler_);
-
-  ret->group = group;
-  ret->dest_handlers_ = dest_handlers;
-  upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
-
-  return ret;
-}
-
-const upb_handlers *upb_pbdecodermethod_desthandlers(
-    const upb_pbdecodermethod *m) {
-  return m->dest_handlers_;
-}
-
-const upb_byteshandler *upb_pbdecodermethod_inputhandler(
-    const upb_pbdecodermethod *m) {
-  return &m->input_handler_;
-}
-
-bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
-  return m->is_native_;
-}
-
-
-/* mgroup *********************************************************************/
-
-static void freegroup(mgroup *g) {
-  upb_inttable_iter i;
-
-  upb_inttable_begin(&i, &g->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    freemethod(upb_value_getptr(upb_inttable_iter_value(&i)));
-  }
-
-  upb_inttable_uninit(&g->methods);
-  upb_gfree(g->bytecode);
-  upb_gfree(g);
-}
-
-mgroup *newgroup(void) {
-  mgroup *g = upb_gmalloc(sizeof(*g));
-  upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
-  g->bytecode = NULL;
-  g->bytecode_end = NULL;
-  return g;
-}
-
-
-/* bytecode compiler **********************************************************/
-
-/* Data used only at compilation time. */
-typedef struct {
-  mgroup *group;
-
-  uint32_t *pc;
-  int fwd_labels[MAXLABEL];
-  int back_labels[MAXLABEL];
-
-  /* For fields marked "lazy", parse them lazily or eagerly? */
-  bool lazy;
-} compiler;
-
-static compiler *newcompiler(mgroup *group, bool lazy) {
-  compiler *ret = upb_gmalloc(sizeof(*ret));
-  int i;
-
-  ret->group = group;
-  ret->lazy = lazy;
-  for (i = 0; i < MAXLABEL; i++) {
-    ret->fwd_labels[i] = EMPTYLABEL;
-    ret->back_labels[i] = EMPTYLABEL;
-  }
-  return ret;
-}
-
-static void freecompiler(compiler *c) {
-  upb_gfree(c);
-}
-
-const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
-
-/* How many words an instruction is. */
-static int instruction_len(uint32_t instr) {
-  switch (getop(instr)) {
-    case OP_SETDISPATCH: return 1 + ptr_words;
-    case OP_TAGN: return 3;
-    case OP_SETBIGGROUPNUM: return 2;
-    default: return 1;
-  }
-}
-
-bool op_has_longofs(int32_t instruction) {
-  switch (getop(instruction)) {
-    case OP_CALL:
-    case OP_BRANCH:
-    case OP_CHECKDELIM:
-      return true;
-    /* The "tag" instructions only have 8 bytes available for the jump target,
-     * but that is ok because these opcodes only require short jumps. */
-    case OP_TAG1:
-    case OP_TAG2:
-    case OP_TAGN:
-      return false;
-    default:
-      UPB_ASSERT(false);
-      return false;
-  }
-}
-
-static int32_t getofs(uint32_t instruction) {
-  if (op_has_longofs(instruction)) {
-    return (int32_t)instruction >> 8;
-  } else {
-    return (int8_t)(instruction >> 8);
-  }
-}
-
-static void setofs(uint32_t *instruction, int32_t ofs) {
-  if (op_has_longofs(*instruction)) {
-    *instruction = getop(*instruction) | (uint32_t)ofs << 8;
-  } else {
-    *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
-  }
-  UPB_ASSERT(getofs(*instruction) == ofs);  /* Would fail in cases of overflow. */
-}
-
-static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; }
-
-/* Defines a local label at the current PC location.  All previous forward
- * references are updated to point to this location.  The location is noted
- * for any future backward references. */
-static void label(compiler *c, unsigned int label) {
-  int val;
-  uint32_t *codep;
-
-  UPB_ASSERT(label < MAXLABEL);
-  val = c->fwd_labels[label];
-  codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
-  while (codep) {
-    int ofs = getofs(*codep);
-    setofs(codep, c->pc - codep - instruction_len(*codep));
-    codep = ofs ? codep + ofs : NULL;
-  }
-  c->fwd_labels[label] = EMPTYLABEL;
-  c->back_labels[label] = pcofs(c);
-}
-
-/* Creates a reference to a numbered label; either a forward reference
- * (positive arg) or backward reference (negative arg).  For forward references
- * the value returned now is actually a "next" pointer into a linked list of all
- * instructions that use this label and will be patched later when the label is
- * defined with label().
- *
- * The returned value is the offset that should be written into the instruction.
- */
-static int32_t labelref(compiler *c, int label) {
-  UPB_ASSERT(label < MAXLABEL);
-  if (label == LABEL_DISPATCH) {
-    /* No resolving required. */
-    return 0;
-  } else if (label < 0) {
-    /* Backward local label.  Relative to the next instruction. */
-    uint32_t from = (c->pc + 1) - c->group->bytecode;
-    return c->back_labels[-label] - from;
-  } else {
-    /* Forward local label: prepend to (possibly-empty) linked list. */
-    int *lptr = &c->fwd_labels[label];
-    int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
-    *lptr = pcofs(c);
-    return ret;
-  }
-}
-
-static void put32(compiler *c, uint32_t v) {
-  mgroup *g = c->group;
-  if (c->pc == g->bytecode_end) {
-    int ofs = pcofs(c);
-    size_t oldsize = g->bytecode_end - g->bytecode;
-    size_t newsize = UPB_MAX(oldsize * 2, 64);
-    /* TODO(haberman): handle OOM. */
-    g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t),
-                                            newsize * sizeof(uint32_t));
-    g->bytecode_end = g->bytecode + newsize;
-    c->pc = g->bytecode + ofs;
-  }
-  *c->pc++ = v;
-}
-
-static void putop(compiler *c, int op, ...) {
-  va_list ap;
-  va_start(ap, op);
-
-  switch (op) {
-    case OP_SETDISPATCH: {
-      uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
-      put32(c, OP_SETDISPATCH);
-      put32(c, ptr);
-      if (sizeof(uintptr_t) > sizeof(uint32_t))
-        put32(c, (uint64_t)ptr >> 32);
-      break;
-    }
-    case OP_STARTMSG:
-    case OP_ENDMSG:
-    case OP_PUSHLENDELIM:
-    case OP_POP:
-    case OP_SETDELIM:
-    case OP_HALT:
-    case OP_RET:
-    case OP_DISPATCH:
-      put32(c, op);
-      break;
-    case OP_PARSE_DOUBLE:
-    case OP_PARSE_FLOAT:
-    case OP_PARSE_INT64:
-    case OP_PARSE_UINT64:
-    case OP_PARSE_INT32:
-    case OP_PARSE_FIXED64:
-    case OP_PARSE_FIXED32:
-    case OP_PARSE_BOOL:
-    case OP_PARSE_UINT32:
-    case OP_PARSE_SFIXED32:
-    case OP_PARSE_SFIXED64:
-    case OP_PARSE_SINT32:
-    case OP_PARSE_SINT64:
-    case OP_STARTSEQ:
-    case OP_ENDSEQ:
-    case OP_STARTSUBMSG:
-    case OP_ENDSUBMSG:
-    case OP_STARTSTR:
-    case OP_STRING:
-    case OP_ENDSTR:
-    case OP_PUSHTAGDELIM:
-      put32(c, op | va_arg(ap, upb_selector_t) << 8);
-      break;
-    case OP_SETBIGGROUPNUM:
-      put32(c, op);
-      put32(c, va_arg(ap, int));
-      break;
-    case OP_CALL: {
-      const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
-      put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
-      break;
-    }
-    case OP_CHECKDELIM:
-    case OP_BRANCH: {
-      uint32_t instruction = op;
-      int label = va_arg(ap, int);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      break;
-    }
-    case OP_TAG1:
-    case OP_TAG2: {
-      int label = va_arg(ap, int);
-      uint64_t tag = va_arg(ap, uint64_t);
-      uint32_t instruction = op | (tag << 16);
-      UPB_ASSERT(tag <= 0xffff);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      break;
-    }
-    case OP_TAGN: {
-      int label = va_arg(ap, int);
-      uint64_t tag = va_arg(ap, uint64_t);
-      uint32_t instruction = op | (upb_value_size(tag) << 16);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      put32(c, tag);
-      put32(c, tag >> 32);
-      break;
-    }
-  }
-
-  va_end(ap);
-}
-
-#if defined(UPB_DUMP_BYTECODE)
-
-const char *upb_pbdecoder_getopname(unsigned int op) {
-#define QUOTE(x) #x
-#define EXPAND_AND_QUOTE(x) QUOTE(x)
-#define OPNAME(x) OP_##x
-#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
-#define T(x) OP(PARSE_##x)
-  /* Keep in sync with list in decoder.int.h. */
-  switch ((opcode)op) {
-    T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
-    T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
-    OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
-    OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
-    OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
-    OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
-    OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
-  }
-  return "<unknown op>";
-#undef OP
-#undef T
-}
-
-#endif
-
-#ifdef UPB_DUMP_BYTECODE
-
-static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
-
-  uint32_t *begin = p;
-
-  while (p < end) {
-    fprintf(f, "%p  %8tx", p, p - begin);
-    uint32_t instr = *p++;
-    uint8_t op = getop(instr);
-    fprintf(f, " %s", upb_pbdecoder_getopname(op));
-    switch ((opcode)op) {
-      case OP_SETDISPATCH: {
-        const upb_inttable *dispatch;
-        memcpy(&dispatch, p, sizeof(void*));
-        p += ptr_words;
-        const upb_pbdecodermethod *method =
-            (void *)((char *)dispatch -
-                     offsetof(upb_pbdecodermethod, dispatch));
-        fprintf(f, " %s", upb_msgdef_fullname(
-                              upb_handlers_msgdef(method->dest_handlers_)));
-        break;
-      }
-      case OP_DISPATCH:
-      case OP_STARTMSG:
-      case OP_ENDMSG:
-      case OP_PUSHLENDELIM:
-      case OP_POP:
-      case OP_SETDELIM:
-      case OP_HALT:
-      case OP_RET:
-        break;
-      case OP_PARSE_DOUBLE:
-      case OP_PARSE_FLOAT:
-      case OP_PARSE_INT64:
-      case OP_PARSE_UINT64:
-      case OP_PARSE_INT32:
-      case OP_PARSE_FIXED64:
-      case OP_PARSE_FIXED32:
-      case OP_PARSE_BOOL:
-      case OP_PARSE_UINT32:
-      case OP_PARSE_SFIXED32:
-      case OP_PARSE_SFIXED64:
-      case OP_PARSE_SINT32:
-      case OP_PARSE_SINT64:
-      case OP_STARTSEQ:
-      case OP_ENDSEQ:
-      case OP_STARTSUBMSG:
-      case OP_ENDSUBMSG:
-      case OP_STARTSTR:
-      case OP_STRING:
-      case OP_ENDSTR:
-      case OP_PUSHTAGDELIM:
-        fprintf(f, " %d", instr >> 8);
-        break;
-      case OP_SETBIGGROUPNUM:
-        fprintf(f, " %d", *p++);
-        break;
-      case OP_CHECKDELIM:
-      case OP_CALL:
-      case OP_BRANCH:
-        fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        break;
-      case OP_TAG1:
-      case OP_TAG2: {
-        fprintf(f, " tag:0x%x", instr >> 16);
-        if (getofs(instr)) {
-          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        }
-        break;
-      }
-      case OP_TAGN: {
-        uint64_t tag = *p++;
-        tag |= (uint64_t)*p++ << 32;
-        fprintf(f, " tag:0x%llx", (long long)tag);
-        fprintf(f, " n:%d", instr >> 16);
-        if (getofs(instr)) {
-          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        }
-        break;
-      }
-    }
-    fputs("\n", f);
-  }
-}
-
-#endif
-
-static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
-  uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
-  uint64_t encoded_tag = upb_vencode32(tag);
-  /* No tag should be greater than 5 bytes. */
-  UPB_ASSERT(encoded_tag <= 0xffffffffff);
-  return encoded_tag;
-}
-
-static void putchecktag(compiler *c, const upb_fielddef *f,
-                        int wire_type, int dest) {
-  uint64_t tag = get_encoded_tag(f, wire_type);
-  switch (upb_value_size(tag)) {
-    case 1:
-      putop(c, OP_TAG1, dest, tag);
-      break;
-    case 2:
-      putop(c, OP_TAG2, dest, tag);
-      break;
-    default:
-      putop(c, OP_TAGN, dest, tag);
-      break;
-  }
-}
-
-static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
-  upb_selector_t selector;
-  bool ok = upb_handlers_getselector(f, type, &selector);
-  UPB_ASSERT(ok);
-  return selector;
-}
-
-/* Takes an existing, primary dispatch table entry and repacks it with a
- * different alternate wire type.  Called when we are inserting a secondary
- * dispatch table entry for an alternate wire type. */
-static uint64_t repack(uint64_t dispatch, int new_wt2) {
-  uint64_t ofs;
-  uint8_t wt1;
-  uint8_t old_wt2;
-  upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
-  UPB_ASSERT(old_wt2 == NO_WIRE_TYPE);  /* wt2 should not be set yet. */
-  return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
-}
-
-/* Marks the current bytecode position as the dispatch target for this message,
- * field, and wire type. */
-static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
-                           const upb_fielddef *f, int wire_type) {
-  /* Offset is relative to msg base. */
-  uint64_t ofs = pcofs(c) - method->code_base.ofs;
-  uint32_t fn = upb_fielddef_number(f);
-  upb_inttable *d = &method->dispatch;
-  upb_value v;
-  if (upb_inttable_remove(d, fn, &v)) {
-    /* TODO: prioritize based on packed setting in .proto file. */
-    uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
-    upb_inttable_insert(d, fn, upb_value_uint64(repacked));
-    upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
-  } else {
-    uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
-    upb_inttable_insert(d, fn, upb_value_uint64(val));
-  }
-}
-
-static void putpush(compiler *c, const upb_fielddef *f) {
-  if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
-    putop(c, OP_PUSHLENDELIM);
-  } else {
-    uint32_t fn = upb_fielddef_number(f);
-    if (fn >= 1 << 24) {
-      putop(c, OP_PUSHTAGDELIM, 0);
-      putop(c, OP_SETBIGGROUPNUM, fn);
-    } else {
-      putop(c, OP_PUSHTAGDELIM, fn);
-    }
-  }
-}
-
-static upb_pbdecodermethod *find_submethod(const compiler *c,
-                                           const upb_pbdecodermethod *method,
-                                           const upb_fielddef *f) {
-  const upb_handlers *sub =
-      upb_handlers_getsubhandlers(method->dest_handlers_, f);
-  upb_value v;
-  return upb_inttable_lookupptr(&c->group->methods, sub, &v)
-             ? upb_value_getptr(v)
-             : NULL;
-}
-
-static void putsel(compiler *c, opcode op, upb_selector_t sel,
-                   const upb_handlers *h) {
-  if (upb_handlers_gethandler(h, sel, NULL)) {
-    putop(c, op, sel);
-  }
-}
-
-/* Puts an opcode to call a callback, but only if a callback actually exists for
- * this field and handler type. */
-static void maybeput(compiler *c, opcode op, const upb_handlers *h,
-                     const upb_fielddef *f, upb_handlertype_t type) {
-  putsel(c, op, getsel(f, type), h);
-}
-
-static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
-  if (!upb_fielddef_lazy(f))
-    return false;
-
-  return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR), NULL) ||
-         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING), NULL) ||
-         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR), NULL);
-}
-
-
-/* bytecode compiler code generation ******************************************/
-
-/* Symbolic names for our local labels. */
-#define LABEL_LOOPSTART 1  /* Top of a repeated field loop. */
-#define LABEL_LOOPBREAK 2  /* To jump out of a repeated loop */
-#define LABEL_FIELD     3  /* Jump backward to find the most recent field. */
-#define LABEL_ENDMSG    4  /* To reach the OP_ENDMSG instr for this msg. */
-
-/* Generates bytecode to parse a single non-lazy message field. */
-static void generate_msgfield(compiler *c, const upb_fielddef *f,
-                              upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-  const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
-  int wire_type;
-
-  if (!sub_m) {
-    /* Don't emit any code for this field at all; it will be parsed as an
-     * unknown field.
-     *
-     * TODO(haberman): we should change this to parse it as a string field
-     * instead.  It will probably be faster, but more importantly, once we
-     * start vending unknown fields, a field shouldn't be treated as unknown
-     * just because it doesn't have subhandlers registered. */
-    return;
-  }
-
-  label(c, LABEL_FIELD);
-
-  wire_type =
-      (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
-          ? UPB_WIRE_TYPE_DELIMITED
-          : UPB_WIRE_TYPE_START_GROUP;
-
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
-   label(c, LABEL_LOOPSTART);
-    putpush(c, f);
-    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
-    putop(c, OP_CALL, sub_m);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
-    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
-      putop(c, OP_SETDELIM);
-    }
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putpush(c, f);
-    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
-    putop(c, OP_CALL, sub_m);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
-    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
-      putop(c, OP_SETDELIM);
-    }
-  }
-}
-
-/* Generates bytecode to parse a single string or lazy submessage field. */
-static void generate_delimfield(compiler *c, const upb_fielddef *f,
-                                upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-
-  label(c, LABEL_FIELD);
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
-   label(c, LABEL_LOOPSTART);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
-    /* Need to emit even if no handler to skip past the string. */
-    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
-    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
-    putop(c, OP_POP);
-    putop(c, OP_SETDELIM);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
-    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
-    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
-    putop(c, OP_POP);
-    putop(c, OP_SETDELIM);
-  }
-}
-
-/* Generates bytecode to parse a single primitive field. */
-static void generate_primitivefield(compiler *c, const upb_fielddef *f,
-                                    upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-  upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
-  opcode parse_type;
-  upb_selector_t sel;
-  int wire_type;
-
-  label(c, LABEL_FIELD);
-
-  /* From a decoding perspective, ENUM is the same as INT32. */
-  if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
-    descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
-
-  parse_type = (opcode)descriptor_type;
-
-  /* TODO(haberman): generate packed or non-packed first depending on "packed"
-   * setting in the fielddef.  This will favor (in speed) whichever was
-   * specified. */
-
-  UPB_ASSERT((int)parse_type >= 0 && parse_type <= OP_MAX);
-  sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Packed */
-   label(c, LABEL_LOOPSTART);
-    putop(c, parse_type, sel);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Non-packed */
-   label(c, LABEL_LOOPSTART);
-    putop(c, parse_type, sel);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);  /* Packed and non-packed join. */
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-    putop(c, OP_SETDELIM);  /* Could remove for non-packed by dup ENDSEQ. */
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, parse_type, sel);
-  }
-}
-
-/* Adds bytecode for parsing the given message to the given decoderplan,
- * while adding all dispatch targets to this message's dispatch table. */
-static void compile_method(compiler *c, upb_pbdecodermethod *method) {
-  const upb_handlers *h;
-  const upb_msgdef *md;
-  uint32_t* start_pc;
-  upb_msg_field_iter i;
-  upb_value val;
-
-  UPB_ASSERT(method);
-
-  /* Clear all entries in the dispatch table. */
-  upb_inttable_uninit(&method->dispatch);
-  upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
-
-  h = upb_pbdecodermethod_desthandlers(method);
-  md = upb_handlers_msgdef(h);
-
- method->code_base.ofs = pcofs(c);
-  putop(c, OP_SETDISPATCH, &method->dispatch);
-  putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
- label(c, LABEL_FIELD);
-  start_pc = c->pc;
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_fieldtype_t type = upb_fielddef_type(f);
-
-    if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
-      generate_msgfield(c, f, method);
-    } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
-               type == UPB_TYPE_MESSAGE) {
-      generate_delimfield(c, f, method);
-    } else {
-      generate_primitivefield(c, f, method);
-    }
-  }
-
-  /* If there were no fields, or if no handlers were defined, we need to
-   * generate a non-empty loop body so that we can at least dispatch for unknown
-   * fields and check for the end of the message. */
-  if (c->pc == start_pc) {
-    /* Check for end-of-message. */
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    /* Unconditionally dispatch. */
-    putop(c, OP_DISPATCH, 0);
-  }
-
-  /* For now we just loop back to the last field of the message (or if none,
-   * the DISPATCH opcode for the message). */
-  putop(c, OP_BRANCH, -LABEL_FIELD);
-
-  /* Insert both a label and a dispatch table entry for this end-of-msg. */
- label(c, LABEL_ENDMSG);
-  val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
-  upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
-
-  putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
-  putop(c, OP_RET);
-
-  upb_inttable_compact(&method->dispatch);
-}
-
-/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
- * Returns the method for these handlers.
- *
- * Generates a new method for every destination handlers reachable from "h". */
-static void find_methods(compiler *c, const upb_handlers *h) {
-  upb_value v;
-  upb_msg_field_iter i;
-  const upb_msgdef *md;
-  upb_pbdecodermethod *method;
-
-  if (upb_inttable_lookupptr(&c->group->methods, h, &v))
-    return;
-
-  method = newmethod(h, c->group);
-  upb_inttable_insertptr(&c->group->methods, h, upb_value_ptr(method));
-
-  /* Find submethods. */
-  md = upb_handlers_msgdef(h);
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    const upb_handlers *sub_h;
-    if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
-        (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
-      /* We only generate a decoder method for submessages with handlers.
-       * Others will be parsed as unknown fields. */
-      find_methods(c, sub_h);
-    }
-  }
-}
-
-/* (Re-)compile bytecode for all messages in "msgs."
- * Overwrites any existing bytecode in "c". */
-static void compile_methods(compiler *c) {
-  upb_inttable_iter i;
-
-  /* Start over at the beginning of the bytecode. */
-  c->pc = c->group->bytecode;
-
-  upb_inttable_begin(&i, &c->group->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
-    compile_method(c, method);
-  }
-}
-
-static void set_bytecode_handlers(mgroup *g) {
-  upb_inttable_iter i;
-  upb_inttable_begin(&i, &g->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
-    upb_byteshandler *h = &m->input_handler_;
-
-    m->code_base.ptr = g->bytecode + m->code_base.ofs;
-
-    upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
-    upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
-    upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
-  }
-}
-
-
-/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
- * handlers and other mgroups (but verify we have a transitive closure). */
-const mgroup *mgroup_new(const upb_handlers *dest, bool lazy) {
-  mgroup *g;
-  compiler *c;
-
-  g = newgroup();
-  c = newcompiler(g, lazy);
-  find_methods(c, dest);
-
-  /* We compile in two passes:
-   * 1. all messages are assigned relative offsets from the beginning of the
-   *    bytecode (saved in method->code_base).
-   * 2. forwards OP_CALL instructions can be correctly linked since message
-   *    offsets have been previously assigned.
-   *
-   * Could avoid the second pass by linking OP_CALL instructions somehow. */
-  compile_methods(c);
-  compile_methods(c);
-  g->bytecode_end = c->pc;
-  freecompiler(c);
-
-#ifdef UPB_DUMP_BYTECODE
-  {
-    FILE *f = fopen("/tmp/upb-bytecode", "w");
-    UPB_ASSERT(f);
-    dumpbc(g->bytecode, g->bytecode_end, stderr);
-    dumpbc(g->bytecode, g->bytecode_end, f);
-    fclose(f);
-
-    f = fopen("/tmp/upb-bytecode.bin", "wb");
-    UPB_ASSERT(f);
-    fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
-    fclose(f);
-  }
-#endif
-
-  set_bytecode_handlers(g);
-  return g;
-}
-
-
-/* upb_pbcodecache ************************************************************/
-
-upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest) {
-  upb_pbcodecache *c = upb_gmalloc(sizeof(*c));
-
-  if (!c) return NULL;
-
-  c->dest = dest;
-  c->lazy = false;
-
-  c->arena = upb_arena_new();
-  if (!upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR)) return NULL;
-
-  return c;
-}
-
-void upb_pbcodecache_free(upb_pbcodecache *c) {
-  upb_inttable_iter i;
-
-  upb_inttable_begin(&i, &c->groups);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_value val = upb_inttable_iter_value(&i);
-    freegroup((void*)upb_value_getconstptr(val));
-  }
-
-  upb_inttable_uninit(&c->groups);
-  upb_arena_free(c->arena);
-  upb_gfree(c);
-}
-
-void upb_pbdecodermethodopts_setlazy(upb_pbcodecache *c, bool lazy) {
-  UPB_ASSERT(upb_inttable_count(&c->groups) == 0);
-  c->lazy = lazy;
-}
-
-const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
-                                               const upb_msgdef *md) {
-  upb_value v;
-  bool ok;
-  const upb_handlers *h;
-  const mgroup *g;
-
-  h = upb_handlercache_get(c->dest, md);
-  if (upb_inttable_lookupptr(&c->groups, md, &v)) {
-    g = upb_value_getconstptr(v);
-  } else {
-    g = mgroup_new(h, c->lazy);
-    ok = upb_inttable_insertptr(&c->groups, md, upb_value_constptr(g));
-    UPB_ASSERT(ok);
-  }
-
-  ok = upb_inttable_lookupptr(&g->methods, h, &v);
-  UPB_ASSERT(ok);
-  return upb_value_getptr(v);
-}
-/*
-** upb::Decoder (Bytecode Decoder VM)
-**
-** Bytecode must previously have been generated using the bytecode compiler in
-** compile_decoder.c.  This decoder then walks through the bytecode op-by-op to
-** parse the input.
-**
-** Decoding is fully resumable; we just keep a pointer to the current bytecode
-** instruction and resume from there.  A fair amount of the logic here is to
-** handle the fact that values can span buffer seams and we have to be able to
-** be capable of suspending/resuming from any byte in the stream.  This
-** sometimes requires keeping a few trailing bytes from the last buffer around
-** in the "residual" buffer.
-*/
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#ifdef UPB_DUMP_BYTECODE
-#include <stdio.h>
-#endif
-
-
-#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
-
-/* Error messages that are shared between the bytecode and JIT decoders. */
-const char *kPbDecoderStackOverflow = "Nesting too deep.";
-const char *kPbDecoderSubmessageTooLong =
-    "Submessage end extends past enclosing submessage.";
-
-/* Error messages shared within this file. */
-static const char *kUnterminatedVarint = "Unterminated varint.";
-
-/* upb_pbdecoder **************************************************************/
-
-static opcode halt = OP_HALT;
-
-/* A dummy character we can point to when the user passes us a NULL buffer.
- * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
- * behavior, which would invalidate functions like curbufleft(). */
-static const char dummy_char;
-
-/* Whether an op consumes any of the input buffer. */
-static bool consumes_input(opcode op) {
-  switch (op) {
-    case OP_SETDISPATCH:
-    case OP_STARTMSG:
-    case OP_ENDMSG:
-    case OP_STARTSEQ:
-    case OP_ENDSEQ:
-    case OP_STARTSUBMSG:
-    case OP_ENDSUBMSG:
-    case OP_STARTSTR:
-    case OP_ENDSTR:
-    case OP_PUSHTAGDELIM:
-    case OP_POP:
-    case OP_SETDELIM:
-    case OP_SETBIGGROUPNUM:
-    case OP_CHECKDELIM:
-    case OP_CALL:
-    case OP_RET:
-    case OP_BRANCH:
-      return false;
-    default:
-      return true;
-  }
-}
-
-static size_t stacksize(upb_pbdecoder *d, size_t entries) {
-  UPB_UNUSED(d);
-  return entries * sizeof(upb_pbdecoder_frame);
-}
-
-static size_t callstacksize(upb_pbdecoder *d, size_t entries) {
-  UPB_UNUSED(d);
-
-  return entries * sizeof(uint32_t*);
-}
-
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
-
-/* It's unfortunate that we have to micro-manage the compiler with
- * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
- * specific to one hardware configuration.  But empirically on a Core i7,
- * performance increases 30-50% with these annotations.  Every instance where
- * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
- * benchmarks. */
-
-static void seterr(upb_pbdecoder *d, const char *msg) {
-  upb_status_seterrmsg(d->status, msg);
-}
-
-void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
-  seterr(d, msg);
-}
-
-
-/* Buffering ******************************************************************/
-
-/* We operate on one buffer at a time, which is either the user's buffer passed
- * to our "decode" callback or some residual bytes from the previous buffer. */
-
-/* How many bytes can be safely read from d->ptr without reading past end-of-buf
- * or past the current delimited end. */
-static size_t curbufleft(const upb_pbdecoder *d) {
-  UPB_ASSERT(d->data_end >= d->ptr);
-  return d->data_end - d->ptr;
-}
-
-/* How many bytes are available before end-of-buffer. */
-static size_t bufleft(const upb_pbdecoder *d) {
-  return d->end - d->ptr;
-}
-
-/* Overall stream offset of d->ptr. */
-uint64_t offset(const upb_pbdecoder *d) {
-  return d->bufstart_ofs + (d->ptr - d->buf);
-}
-
-/* How many bytes are available before the end of this delimited region. */
-size_t delim_remaining(const upb_pbdecoder *d) {
-  return d->top->end_ofs - offset(d);
-}
-
-/* Advances d->ptr. */
-static void advance(upb_pbdecoder *d, size_t len) {
-  UPB_ASSERT(curbufleft(d) >= len);
-  d->ptr += len;
-}
-
-static bool in_buf(const char *p, const char *buf, const char *end) {
-  return p >= buf && p <= end;
-}
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
-  return in_buf(p, d->residual, d->residual_end);
-}
-
-/* Calculates the delim_end value, which is affected by both the current buffer
- * and the parsing stack, so must be called whenever either is updated. */
-static void set_delim_end(upb_pbdecoder *d) {
-  size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
-  if (delim_ofs <= (size_t)(d->end - d->buf)) {
-    d->delim_end = d->buf + delim_ofs;
-    d->data_end = d->delim_end;
-  } else {
-    d->data_end = d->end;
-    d->delim_end = NULL;
-  }
-}
-
-static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
-  d->ptr = buf;
-  d->buf = buf;
-  d->end = end;
-  set_delim_end(d);
-}
-
-static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
-  UPB_ASSERT(curbufleft(d) == 0);
-  d->bufstart_ofs += (d->end - d->buf);
-  switchtobuf(d, buf, buf + len);
-}
-
-static void checkpoint(upb_pbdecoder *d) {
-  /* The assertion here is in the interests of efficiency, not correctness.
-   * We are trying to ensure that we don't checkpoint() more often than
-   * necessary. */
-  UPB_ASSERT(d->checkpoint != d->ptr);
-  d->checkpoint = d->ptr;
-}
-
-/* Skips "bytes" bytes in the stream, which may be more than available.  If we
- * skip more bytes than are available, we return a long read count to the caller
- * indicating how many bytes can be skipped over before passing actual data
- * again.  Skipped bytes can pass a NULL buffer and the decoder guarantees they
- * won't actually be read.
- */
-static int32_t skip(upb_pbdecoder *d, size_t bytes) {
-  UPB_ASSERT(!in_residual_buf(d, d->ptr) || d->size_param == 0);
-  UPB_ASSERT(d->skip == 0);
-  if (bytes > delim_remaining(d)) {
-    seterr(d, "Skipped value extended beyond enclosing submessage.");
-    return upb_pbdecoder_suspend(d);
-  } else if (bufleft(d) >= bytes) {
-    /* Skipped data is all in current buffer, and more is still available. */
-    advance(d, bytes);
-    d->skip = 0;
-    return DECODE_OK;
-  } else {
-    /* Skipped data extends beyond currently available buffers. */
-    d->pc = d->last;
-    d->skip = bytes - curbufleft(d);
-    d->bufstart_ofs += (d->end - d->buf);
-    d->residual_end = d->residual;
-    switchtobuf(d, d->residual, d->residual_end);
-    return d->size_param + d->skip;
-  }
-}
-
-
-/* Resumes the decoder from an initial state or from a previous suspend. */
-int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
-                             size_t size, const upb_bufhandle *handle) {
-  UPB_UNUSED(p);  /* Useless; just for the benefit of the JIT. */
-
-  /* d->skip and d->residual_end could probably elegantly be represented
-   * as a single variable, to more easily represent this invariant. */
-  UPB_ASSERT(!(d->skip && d->residual_end > d->residual));
-
-  /* We need to remember the original size_param, so that the value we return
-   * is relative to it, even if we do some skipping first. */
-  d->size_param = size;
-  d->handle = handle;
-
-  /* Have to handle this case specially (ie. not with skip()) because the user
-   * is allowed to pass a NULL buffer here, which won't allow us to safely
-   * calculate a d->end or use our normal functions like curbufleft(). */
-  if (d->skip && d->skip >= size) {
-    d->skip -= size;
-    d->bufstart_ofs += size;
-    buf = &dummy_char;
-    size = 0;
-
-    /* We can't just return now, because we might need to execute some ops
-     * like CHECKDELIM, which could call some callbacks and pop the stack. */
-  }
-
-  /* We need to pretend that this was the actual buffer param, since some of the
-   * calculations assume that d->ptr/d->buf is relative to this. */
-  d->buf_param = buf;
-
-  if (!buf) {
-    /* NULL buf is ok if its entire span is covered by the "skip" above, but
-     * by this point we know that "skip" doesn't cover the buffer. */
-    seterr(d, "Passed NULL buffer over non-skippable region.");
-    return upb_pbdecoder_suspend(d);
-  }
-
-  if (d->residual_end > d->residual) {
-    /* We have residual bytes from the last buffer. */
-    UPB_ASSERT(d->ptr == d->residual);
-  } else {
-    switchtobuf(d, buf, buf + size);
-  }
-
-  d->checkpoint = d->ptr;
-
-  /* Handle skips that don't cover the whole buffer (as above). */
-  if (d->skip) {
-    size_t skip_bytes = d->skip;
-    d->skip = 0;
-    CHECK_RETURN(skip(d, skip_bytes));
-    checkpoint(d);
-  }
-
-  /* If we're inside an unknown group, continue to parse unknown values. */
-  if (d->top->groupnum < 0) {
-    CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
-    checkpoint(d);
-  }
-
-  return DECODE_OK;
-}
-
-/* Suspends the decoder at the last checkpoint, without saving any residual
- * bytes.  If there are any unconsumed bytes, returns a short byte count. */
-size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
-  d->pc = d->last;
-  if (d->checkpoint == d->residual) {
-    /* Checkpoint was in residual buf; no user bytes were consumed. */
-    d->ptr = d->residual;
-    return 0;
-  } else {
-    size_t ret = d->size_param - (d->end - d->checkpoint);
-    UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
-    UPB_ASSERT(d->buf == d->buf_param || d->buf == &dummy_char);
-
-    d->bufstart_ofs += (d->checkpoint - d->buf);
-    d->residual_end = d->residual;
-    switchtobuf(d, d->residual, d->residual_end);
-    return ret;
-  }
-}
-
-/* Suspends the decoder at the last checkpoint, and saves any unconsumed
- * bytes in our residual buffer.  This is necessary if we need more user
- * bytes to form a complete value, which might not be contiguous in the
- * user's buffers.  Always consumes all user bytes. */
-static size_t suspend_save(upb_pbdecoder *d) {
-  /* We hit end-of-buffer before we could parse a full value.
-   * Save any unconsumed bytes (if any) to the residual buffer. */
-  d->pc = d->last;
-
-  if (d->checkpoint == d->residual) {
-    /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
-    UPB_ASSERT((d->residual_end - d->residual) + d->size_param <=
-           sizeof(d->residual));
-    if (!in_residual_buf(d, d->ptr)) {
-      d->bufstart_ofs -= (d->residual_end - d->residual);
-    }
-    memcpy(d->residual_end, d->buf_param, d->size_param);
-    d->residual_end += d->size_param;
-  } else {
-    /* Checkpoint was in user buf; old residual bytes not needed. */
-    size_t save;
-    UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
-
-    d->ptr = d->checkpoint;
-    save = curbufleft(d);
-    UPB_ASSERT(save <= sizeof(d->residual));
-    memcpy(d->residual, d->ptr, save);
-    d->residual_end = d->residual + save;
-    d->bufstart_ofs = offset(d);
-  }
-
-  switchtobuf(d, d->residual, d->residual_end);
-  return d->size_param;
-}
-
-/* Copies the next "bytes" bytes into "buf" and advances the stream.
- * Requires that this many bytes are available in the current buffer. */
-UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
-                                         size_t bytes) {
-  UPB_ASSERT(bytes <= curbufleft(d));
-  memcpy(buf, d->ptr, bytes);
-  advance(d, bytes);
-}
-
-/* Slow path for getting the next "bytes" bytes, regardless of whether they are
- * available in the current buffer or not.  Returns a status code as described
- * in decoder.int.h. */
-UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
-                                          size_t bytes) {
-  const size_t avail = curbufleft(d);
-  consumebytes(d, buf, avail);
-  bytes -= avail;
-  UPB_ASSERT(bytes > 0);
-  if (in_residual_buf(d, d->ptr)) {
-    advancetobuf(d, d->buf_param, d->size_param);
-  }
-  if (curbufleft(d) >= bytes) {
-    consumebytes(d, (char *)buf + avail, bytes);
-    return DECODE_OK;
-  } else if (d->data_end == d->delim_end) {
-    seterr(d, "Submessage ended in the middle of a value or group");
-    return upb_pbdecoder_suspend(d);
-  } else {
-    return suspend_save(d);
-  }
-}
-
-/* Gets the next "bytes" bytes, regardless of whether they are available in the
- * current buffer or not.  Returns a status code as described in decoder.int.h.
- */
-UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
-                                        size_t bytes) {
-  if (curbufleft(d) >= bytes) {
-    /* Buffer has enough data to satisfy. */
-    consumebytes(d, buf, bytes);
-    return DECODE_OK;
-  } else {
-    return getbytes_slow(d, buf, bytes);
-  }
-}
-
-UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
-                                          size_t bytes) {
-  size_t ret = curbufleft(d);
-  memcpy(buf, d->ptr, ret);
-  if (in_residual_buf(d, d->ptr)) {
-    size_t copy = UPB_MIN(bytes - ret, d->size_param);
-    memcpy((char *)buf + ret, d->buf_param, copy);
-    ret += copy;
-  }
-  return ret;
-}
-
-UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
-                                        size_t bytes) {
-  if (curbufleft(d) >= bytes) {
-    memcpy(buf, d->ptr, bytes);
-    return bytes;
-  } else {
-    return peekbytes_slow(d, buf, bytes);
-  }
-}
-
-
-/* Decoding of wire types *****************************************************/
-
-/* Slow path for decoding a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
-                                                      uint64_t *u64) {
-  uint8_t byte = 0x80;
-  int bitpos;
-  *u64 = 0;
-  for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
-    CHECK_RETURN(getbytes(d, &byte, 1));
-    *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
-  }
-  if(bitpos == 70 && (byte & 0x80)) {
-    seterr(d, kUnterminatedVarint);
-    return upb_pbdecoder_suspend(d);
-  }
-  return DECODE_OK;
-}
-
-/* Decodes a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
-  if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
-    *u64 = *d->ptr;
-    advance(d, 1);
-    return DECODE_OK;
-  } else if (curbufleft(d) >= 10) {
-    /* Fast case. */
-    upb_decoderet r = upb_vdecode_fast(d->ptr);
-    if (r.p == NULL) {
-      seterr(d, kUnterminatedVarint);
-      return upb_pbdecoder_suspend(d);
-    }
-    advance(d, r.p - d->ptr);
-    *u64 = r.val;
-    return DECODE_OK;
-  } else {
-    /* Slow case -- varint spans buffer seam. */
-    return upb_pbdecoder_decode_varint_slow(d, u64);
-  }
-}
-
-/* Decodes a 32-bit varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
-  uint64_t u64;
-  int32_t ret = decode_varint(d, &u64);
-  if (ret >= 0) return ret;
-  if (u64 > UINT32_MAX) {
-    seterr(d, "Unterminated 32-bit varint");
-    /* TODO(haberman) guarantee that this function return is >= 0 somehow,
-     * so we know this path will always be treated as error by our caller.
-     * Right now the size_t -> int32_t can overflow and produce negative values.
-     */
-    *u32 = 0;
-    return upb_pbdecoder_suspend(d);
-  }
-  *u32 = u64;
-  return DECODE_OK;
-}
-
-/* Decodes a fixed32 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
-  return getbytes(d, u32, 4);
-}
-
-/* Decodes a fixed64 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
-  return getbytes(d, u64, 8);
-}
-
-/* Non-static versions of the above functions.
- * These are called by the JIT for fallback paths. */
-int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
-  return decode_fixed32(d, u32);
-}
-
-int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
-  return decode_fixed64(d, u64);
-}
-
-static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
-static float  as_float(uint32_t n)  { float  f; memcpy(&f, &n, 4); return f; }
-
-/* Pushes a frame onto the decoder stack. */
-static bool decoder_push(upb_pbdecoder *d, uint64_t end) {
-  upb_pbdecoder_frame *fr = d->top;
-
-  if (end > fr->end_ofs) {
-    seterr(d, kPbDecoderSubmessageTooLong);
-    return false;
-  } else if (fr == d->limit) {
-    seterr(d, kPbDecoderStackOverflow);
-    return false;
-  }
-
-  fr++;
-  fr->end_ofs = end;
-  fr->dispatch = NULL;
-  fr->groupnum = 0;
-  d->top = fr;
-  return true;
-}
-
-static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
-  /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
-   * field number) prior to hitting any enclosing submessage end, pushing our
-   * existing delim end prevents us from continuing to parse values from a
-   * corrupt proto that doesn't give us an END tag in time. */
-  if (!decoder_push(d, d->top->end_ofs))
-    return false;
-  d->top->groupnum = arg;
-  return true;
-}
-
-/* Pops a frame from the decoder stack. */
-static void decoder_pop(upb_pbdecoder *d) { d->top--; }
-
-UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
-                                                 uint64_t expected) {
-  uint64_t data = 0;
-  size_t bytes = upb_value_size(expected);
-  size_t read = peekbytes(d, &data, bytes);
-  if (read == bytes && data == expected) {
-    /* Advance past matched bytes. */
-    int32_t ok = getbytes(d, &data, read);
-    UPB_ASSERT(ok < 0);
-    return DECODE_OK;
-  } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
-    return suspend_save(d);
-  } else {
-    return DECODE_MISMATCH;
-  }
-}
-
-int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
-                                  uint8_t wire_type) {
-  if (fieldnum >= 0)
-    goto have_tag;
-
-  while (true) {
-    uint32_t tag;
-    CHECK_RETURN(decode_v32(d, &tag));
-    wire_type = tag & 0x7;
-    fieldnum = tag >> 3;
-
-have_tag:
-    if (fieldnum == 0) {
-      seterr(d, "Saw invalid field number (0)");
-      return upb_pbdecoder_suspend(d);
-    }
-
-    switch (wire_type) {
-      case UPB_WIRE_TYPE_32BIT:
-        CHECK_RETURN(skip(d, 4));
-        break;
-      case UPB_WIRE_TYPE_64BIT:
-        CHECK_RETURN(skip(d, 8));
-        break;
-      case UPB_WIRE_TYPE_VARINT: {
-        uint64_t u64;
-        CHECK_RETURN(decode_varint(d, &u64));
-        break;
-      }
-      case UPB_WIRE_TYPE_DELIMITED: {
-        uint32_t len;
-        CHECK_RETURN(decode_v32(d, &len));
-        CHECK_RETURN(skip(d, len));
-        break;
-      }
-      case UPB_WIRE_TYPE_START_GROUP:
-        CHECK_SUSPEND(pushtagdelim(d, -fieldnum));
-        break;
-      case UPB_WIRE_TYPE_END_GROUP:
-        if (fieldnum == -d->top->groupnum) {
-          decoder_pop(d);
-        } else if (fieldnum == d->top->groupnum) {
-          return DECODE_ENDGROUP;
-        } else {
-          seterr(d, "Unmatched ENDGROUP tag.");
-          return upb_pbdecoder_suspend(d);
-        }
-        break;
-      default:
-        seterr(d, "Invalid wire type");
-        return upb_pbdecoder_suspend(d);
-    }
-
-    if (d->top->groupnum >= 0) {
-      /* TODO: More code needed for handling unknown groups. */
-      upb_sink_putunknown(d->top->sink, d->checkpoint, d->ptr - d->checkpoint);
-      return DECODE_OK;
-    }
-
-    /* Unknown group -- continue looping over unknown fields. */
-    checkpoint(d);
-  }
-}
-
-static void goto_endmsg(upb_pbdecoder *d) {
-  upb_value v;
-  bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
-  UPB_ASSERT(found);
-  d->pc = d->top->base + upb_value_getuint64(v);
-}
-
-/* Parses a tag and jumps to the corresponding bytecode instruction for this
- * field.
- *
- * If the tag is unknown (or the wire type doesn't match), parses the field as
- * unknown.  If the tag is a valid ENDGROUP tag, jumps to the bytecode
- * instruction for the end of message. */
-static int32_t dispatch(upb_pbdecoder *d) {
-  upb_inttable *dispatch = d->top->dispatch;
-  uint32_t tag;
-  uint8_t wire_type;
-  uint32_t fieldnum;
-  upb_value val;
-  int32_t retval;
-
-  /* Decode tag. */
-  CHECK_RETURN(decode_v32(d, &tag));
-  wire_type = tag & 0x7;
-  fieldnum = tag >> 3;
-
-  /* Lookup tag.  Because of packed/non-packed compatibility, we have to
-   * check the wire type against two possibilities. */
-  if (fieldnum != DISPATCH_ENDMSG &&
-      upb_inttable_lookup32(dispatch, fieldnum, &val)) {
-    uint64_t v = upb_value_getuint64(val);
-    if (wire_type == (v & 0xff)) {
-      d->pc = d->top->base + (v >> 16);
-      return DECODE_OK;
-    } else if (wire_type == ((v >> 8) & 0xff)) {
-      bool found =
-          upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
-      UPB_ASSERT(found);
-      d->pc = d->top->base + upb_value_getuint64(val);
-      return DECODE_OK;
-    }
-  }
-
-  /* We have some unknown fields (or ENDGROUP) to parse.  The DISPATCH or TAG
-   * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
-   * we need to back up to, so that when we're done skipping unknown data we
-   * can re-check the delimited end. */
-  d->last--;  /* Necessary if we get suspended */
-  d->pc = d->last;
-  UPB_ASSERT(getop(*d->last) == OP_CHECKDELIM);
-
-  /* Unknown field or ENDGROUP. */
-  retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
-
-  CHECK_RETURN(retval);
-
-  if (retval == DECODE_ENDGROUP) {
-    goto_endmsg(d);
-    return DECODE_OK;
-  }
-
-  return DECODE_OK;
-}
-
-/* Callers know that the stack is more than one deep because the opcodes that
- * call this only occur after PUSH operations. */
-upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
-  UPB_ASSERT(d->top != d->stack);
-  return d->top - 1;
-}
-
-
-/* The main decoding loop *****************************************************/
-
-/* The main decoder VM function.  Uses traditional bytecode dispatch loop with a
- * switch() statement. */
-size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
-                      const upb_bufhandle* handle) {
-
-#define VMCASE(op, code) \
-  case op: { code; if (consumes_input(op)) checkpoint(d); break; }
-#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
-  VMCASE(OP_PARSE_ ## type, { \
-    ctype val; \
-    CHECK_RETURN(decode_ ## wt(d, &val)); \
-    upb_sink_put ## name(d->top->sink, arg, (convfunc)(val)); \
-  })
-
-  while(1) {
-    int32_t instruction;
-    opcode op;
-    uint32_t arg;
-    int32_t longofs;
-
-    d->last = d->pc;
-    instruction = *d->pc++;
-    op = getop(instruction);
-    arg = instruction >> 8;
-    longofs = arg;
-    UPB_ASSERT(d->ptr != d->residual_end);
-    UPB_UNUSED(group);
-#ifdef UPB_DUMP_BYTECODE
-    fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
-                    "%x %s (%d)\n",
-            (int)offset(d),
-            (int)(d->ptr - d->buf),
-            (int)(d->data_end - d->ptr),
-            (int)(d->end - d->ptr),
-            (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
-            (int)(d->pc - 1 - group->bytecode),
-            upb_pbdecoder_getopname(op),
-            arg);
-#endif
-    switch (op) {
-      /* Technically, we are losing data if we see a 32-bit varint that is not
-       * properly sign-extended.  We could detect this and error about the data
-       * loss, but proto2 does not do this, so we pass. */
-      PRIMITIVE_OP(INT32,    varint,  int32,  int32_t,      uint64_t)
-      PRIMITIVE_OP(INT64,    varint,  int64,  int64_t,      uint64_t)
-      PRIMITIVE_OP(UINT32,   varint,  uint32, uint32_t,     uint64_t)
-      PRIMITIVE_OP(UINT64,   varint,  uint64, uint64_t,     uint64_t)
-      PRIMITIVE_OP(FIXED32,  fixed32, uint32, uint32_t,     uint32_t)
-      PRIMITIVE_OP(FIXED64,  fixed64, uint64, uint64_t,     uint64_t)
-      PRIMITIVE_OP(SFIXED32, fixed32, int32,  int32_t,      uint32_t)
-      PRIMITIVE_OP(SFIXED64, fixed64, int64,  int64_t,      uint64_t)
-      PRIMITIVE_OP(BOOL,     varint,  bool,   bool,         uint64_t)
-      PRIMITIVE_OP(DOUBLE,   fixed64, double, as_double,    uint64_t)
-      PRIMITIVE_OP(FLOAT,    fixed32, float,  as_float,     uint32_t)
-      PRIMITIVE_OP(SINT32,   varint,  int32,  upb_zzdec_32, uint64_t)
-      PRIMITIVE_OP(SINT64,   varint,  int64,  upb_zzdec_64, uint64_t)
-
-      VMCASE(OP_SETDISPATCH,
-        d->top->base = d->pc - 1;
-        memcpy(&d->top->dispatch, d->pc, sizeof(void*));
-        d->pc += sizeof(void*) / sizeof(uint32_t);
-      )
-      VMCASE(OP_STARTMSG,
-        CHECK_SUSPEND(upb_sink_startmsg(d->top->sink));
-      )
-      VMCASE(OP_ENDMSG,
-        CHECK_SUSPEND(upb_sink_endmsg(d->top->sink, d->status));
-      )
-      VMCASE(OP_STARTSEQ,
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startseq(outer->sink, arg, &d->top->sink));
-      )
-      VMCASE(OP_ENDSEQ,
-        CHECK_SUSPEND(upb_sink_endseq(d->top->sink, arg));
-      )
-      VMCASE(OP_STARTSUBMSG,
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startsubmsg(outer->sink, arg, &d->top->sink));
-      )
-      VMCASE(OP_ENDSUBMSG,
-        upb_sink subsink = (d->top + 1)->sink;
-        CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, subsink, arg));
-      )
-      VMCASE(OP_STARTSTR,
-        uint32_t len = delim_remaining(d);
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startstr(outer->sink, arg, len, &d->top->sink));
-        if (len == 0) {
-          d->pc++;  /* Skip OP_STRING. */
-        }
-      )
-      VMCASE(OP_STRING,
-        uint32_t len = curbufleft(d);
-        size_t n = upb_sink_putstring(d->top->sink, arg, d->ptr, len, handle);
-        if (n > len) {
-          if (n > delim_remaining(d)) {
-            seterr(d, "Tried to skip past end of string.");
-            return upb_pbdecoder_suspend(d);
-          } else {
-            int32_t ret = skip(d, n);
-            /* This shouldn't return DECODE_OK, because n > len. */
-            UPB_ASSERT(ret >= 0);
-            return ret;
-          }
-        }
-        advance(d, n);
-        if (n < len || d->delim_end == NULL) {
-          /* We aren't finished with this string yet. */
-          d->pc--;  /* Repeat OP_STRING. */
-          if (n > 0) checkpoint(d);
-          return upb_pbdecoder_suspend(d);
-        }
-      )
-      VMCASE(OP_ENDSTR,
-        CHECK_SUSPEND(upb_sink_endstr(d->top->sink, arg));
-      )
-      VMCASE(OP_PUSHTAGDELIM,
-        CHECK_SUSPEND(pushtagdelim(d, arg));
-      )
-      VMCASE(OP_SETBIGGROUPNUM,
-        d->top->groupnum = *d->pc++;
-      )
-      VMCASE(OP_POP,
-        UPB_ASSERT(d->top > d->stack);
-        decoder_pop(d);
-      )
-      VMCASE(OP_PUSHLENDELIM,
-        uint32_t len;
-        CHECK_RETURN(decode_v32(d, &len));
-        CHECK_SUSPEND(decoder_push(d, offset(d) + len));
-        set_delim_end(d);
-      )
-      VMCASE(OP_SETDELIM,
-        set_delim_end(d);
-      )
-      VMCASE(OP_CHECKDELIM,
-        /* We are guaranteed of this assert because we never allow ourselves to
-         * consume bytes beyond data_end, which covers delim_end when non-NULL.
-         */
-        UPB_ASSERT(!(d->delim_end && d->ptr > d->delim_end));
-        if (d->ptr == d->delim_end)
-          d->pc += longofs;
-      )
-      VMCASE(OP_CALL,
-        d->callstack[d->call_len++] = d->pc;
-        d->pc += longofs;
-      )
-      VMCASE(OP_RET,
-        UPB_ASSERT(d->call_len > 0);
-        d->pc = d->callstack[--d->call_len];
-      )
-      VMCASE(OP_BRANCH,
-        d->pc += longofs;
-      )
-      VMCASE(OP_TAG1,
-        uint8_t expected;
-        CHECK_SUSPEND(curbufleft(d) > 0);
-        expected = (arg >> 8) & 0xff;
-        if (*d->ptr == expected) {
-          advance(d, 1);
-        } else {
-          int8_t shortofs;
-         badtag:
-          shortofs = arg;
-          if (shortofs == LABEL_DISPATCH) {
-            CHECK_RETURN(dispatch(d));
-          } else {
-            d->pc += shortofs;
-            break; /* Avoid checkpoint(). */
-          }
-        }
-      )
-      VMCASE(OP_TAG2,
-        uint16_t expected;
-        CHECK_SUSPEND(curbufleft(d) > 0);
-        expected = (arg >> 8) & 0xffff;
-        if (curbufleft(d) >= 2) {
-          uint16_t actual;
-          memcpy(&actual, d->ptr, 2);
-          if (expected == actual) {
-            advance(d, 2);
-          } else {
-            goto badtag;
-          }
-        } else {
-          int32_t result = upb_pbdecoder_checktag_slow(d, expected);
-          if (result == DECODE_MISMATCH) goto badtag;
-          if (result >= 0) return result;
-        }
-      )
-      VMCASE(OP_TAGN, {
-        uint64_t expected;
-        int32_t result;
-        memcpy(&expected, d->pc, 8);
-        d->pc += 2;
-        result = upb_pbdecoder_checktag_slow(d, expected);
-        if (result == DECODE_MISMATCH) goto badtag;
-        if (result >= 0) return result;
-      })
-      VMCASE(OP_DISPATCH, {
-        CHECK_RETURN(dispatch(d));
-      })
-      VMCASE(OP_HALT, {
-        return d->size_param;
-      })
-    }
-  }
-}
-
-
-/* BytesHandler handlers ******************************************************/
-
-void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
-  upb_pbdecoder *d = closure;
-  UPB_UNUSED(size_hint);
-  d->top->end_ofs = UINT64_MAX;
-  d->bufstart_ofs = 0;
-  d->call_len = 1;
-  d->callstack[0] = &halt;
-  d->pc = pc;
-  d->skip = 0;
-  return d;
-}
-
-bool upb_pbdecoder_end(void *closure, const void *handler_data) {
-  upb_pbdecoder *d = closure;
-  const upb_pbdecodermethod *method = handler_data;
-  uint64_t end;
-  char dummy;
-
-  if (d->residual_end > d->residual) {
-    seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
-    return false;
-  }
-
-  if (d->skip) {
-    seterr(d, "Unexpected EOF inside skipped data");
-    return false;
-  }
-
-  if (d->top->end_ofs != UINT64_MAX) {
-    seterr(d, "Unexpected EOF inside delimited string");
-    return false;
-  }
-
-  /* The user's end() call indicates that the message ends here. */
-  end = offset(d);
-  d->top->end_ofs = end;
-
-  {
-    const uint32_t *p = d->pc;
-    d->stack->end_ofs = end;
-    /* Check the previous bytecode, but guard against beginning. */
-    if (p != method->code_base.ptr) p--;
-    if (getop(*p) == OP_CHECKDELIM) {
-      /* Rewind from OP_TAG* to OP_CHECKDELIM. */
-      UPB_ASSERT(getop(*d->pc) == OP_TAG1 ||
-             getop(*d->pc) == OP_TAG2 ||
-             getop(*d->pc) == OP_TAGN ||
-             getop(*d->pc) == OP_DISPATCH);
-      d->pc = p;
-    }
-    upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
-  }
-
-  if (d->call_len != 0) {
-    seterr(d, "Unexpected EOF inside submessage or group");
-    return false;
-  }
-
-  return true;
-}
-
-size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
-                            size_t size, const upb_bufhandle *handle) {
-  int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
-
-  if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
-  CHECK_RETURN(result);
-
-  return run_decoder_vm(decoder, group, handle);
-}
-
-
-/* Public API *****************************************************************/
-
-void upb_pbdecoder_reset(upb_pbdecoder *d) {
-  d->top = d->stack;
-  d->top->groupnum = 0;
-  d->ptr = d->residual;
-  d->buf = d->residual;
-  d->end = d->residual;
-  d->residual_end = d->residual;
-}
-
-upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m,
-                                    upb_sink sink, upb_status *status) {
-  const size_t default_max_nesting = 64;
-#ifndef NDEBUG
-  size_t size_before = upb_arena_bytesallocated(a);
-#endif
-
-  upb_pbdecoder *d = upb_arena_malloc(a, sizeof(upb_pbdecoder));
-  if (!d) return NULL;
-
-  d->method_ = m;
-  d->callstack = upb_arena_malloc(a, callstacksize(d, default_max_nesting));
-  d->stack = upb_arena_malloc(a, stacksize(d, default_max_nesting));
-  if (!d->stack || !d->callstack) {
-    return NULL;
-  }
-
-  d->arena = a;
-  d->limit = d->stack + default_max_nesting - 1;
-  d->stack_size = default_max_nesting;
-  d->status = status;
-
-  upb_pbdecoder_reset(d);
-  upb_bytessink_reset(&d->input_, &m->input_handler_, d);
-
-  if (d->method_->dest_handlers_) {
-    if (sink.handlers != d->method_->dest_handlers_)
-      return NULL;
-  }
-  d->top->sink = sink;
-
-  /* If this fails, increase the value in decoder.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
-                      UPB_PB_DECODER_SIZE);
-  return d;
-}
-
-uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
-  return offset(d);
-}
-
-const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
-  return d->method_;
-}
-
-upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d) {
-  return d->input_;
-}
-
-size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
-  return d->stack_size;
-}
-
-bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
-  UPB_ASSERT(d->top >= d->stack);
-
-  if (max < (size_t)(d->top - d->stack)) {
-    /* Can't set a limit smaller than what we are currently at. */
-    return false;
-  }
-
-  if (max > d->stack_size) {
-    /* Need to reallocate stack and callstack to accommodate. */
-    size_t old_size = stacksize(d, d->stack_size);
-    size_t new_size = stacksize(d, max);
-    void *p = upb_arena_realloc(d->arena, d->stack, old_size, new_size);
-    if (!p) {
-      return false;
-    }
-    d->stack = p;
-
-    old_size = callstacksize(d, d->stack_size);
-    new_size = callstacksize(d, max);
-    p = upb_arena_realloc(d->arena, d->callstack, old_size, new_size);
-    if (!p) {
-      return false;
-    }
-    d->callstack = p;
-
-    d->stack_size = max;
-  }
-
-  d->limit = d->stack + max - 1;
-  return true;
-}
-/*
-** upb::Encoder
-**
-** Since we are implementing pure handlers (ie. without any out-of-band access
-** to pre-computed lengths), we have to buffer all submessages before we can
-** emit even their first byte.
-**
-** Not knowing the size of submessages also means we can't write a perfect
-** zero-copy implementation, even with buffering.  Lengths are stored as
-** varints, which means that we don't know how many bytes to reserve for the
-** length until we know what the length is.
-**
-** This leaves us with three main choices:
-**
-** 1. buffer all submessage data in a temporary buffer, then copy it exactly
-**    once into the output buffer.
-**
-** 2. attempt to buffer data directly into the output buffer, estimating how
-**    many bytes each length will take.  When our guesses are wrong, use
-**    memmove() to grow or shrink the allotted space.
-**
-** 3. buffer directly into the output buffer, allocating a max length
-**    ahead-of-time for each submessage length.  If we overallocated, we waste
-**    space, but no memcpy() or memmove() is required.  This approach requires
-**    defining a maximum size for submessages and rejecting submessages that
-**    exceed that size.
-**
-** (2) and (3) have the potential to have better performance, but they are more
-** complicated and subtle to implement:
-**
-**   (3) requires making an arbitrary choice of the maximum message size; it
-**       wastes space when submessages are shorter than this and fails
-**       completely when they are longer.  This makes it more finicky and
-**       requires configuration based on the input.  It also makes it impossible
-**       to perfectly match the output of reference encoders that always use the
-**       optimal amount of space for each length.
-**
-**   (2) requires guessing the the size upfront, and if multiple lengths are
-**       guessed wrong the minimum required number of memmove() operations may
-**       be complicated to compute correctly.  Implemented properly, it may have
-**       a useful amortized or average cost, but more investigation is required
-**       to determine this and what the optimal algorithm is to achieve it.
-**
-**   (1) makes you always pay for exactly one copy, but its implementation is
-**       the simplest and its performance is predictable.
-**
-** So for now, we implement (1) only.  If we wish to optimize later, we should
-** be able to do it without affecting users.
-**
-** The strategy is to buffer the segments of data that do *not* depend on
-** unknown lengths in one buffer, and keep a separate buffer of segment pointers
-** and lengths.  When the top-level submessage ends, we can go beginning to end,
-** alternating the writing of lengths with memcpy() of the rest of the data.
-** At the top level though, no buffering is required.
-*/
-
-
-
-/* The output buffer is divided into segments; a segment is a string of data
- * that is "ready to go" -- it does not need any varint lengths inserted into
- * the middle.  The seams between segments are where varints will be inserted
- * once they are known.
- *
- * We also use the concept of a "run", which is a range of encoded bytes that
- * occur at a single submessage level.  Every segment contains one or more runs.
- *
- * A segment can span messages.  Consider:
- *
- *                  .--Submessage lengths---------.
- *                  |       |                     |
- *                  |       V                     V
- *                  V      | |---------------    | |-----------------
- * Submessages:    | |-----------------------------------------------
- * Top-level msg: ------------------------------------------------------------
- *
- * Segments:          -----   -------------------   -----------------
- * Runs:              *----   *--------------*---   *----------------
- * (* marks the start)
- *
- * Note that the top-level menssage is not in any segment because it does not
- * have any length preceding it.
- *
- * A segment is only interrupted when another length needs to be inserted.  So
- * observe how the second segment spans both the inner submessage and part of
- * the next enclosing message. */
-typedef struct {
-  uint32_t msglen;  /* The length to varint-encode before this segment. */
-  uint32_t seglen;  /* Length of the segment. */
-} upb_pb_encoder_segment;
-
-struct upb_pb_encoder {
-  upb_arena *arena;
-
-  /* Our input and output. */
-  upb_sink input_;
-  upb_bytessink output_;
-
-  /* The "subclosure" -- used as the inner closure as part of the bytessink
-   * protocol. */
-  void *subc;
-
-  /* The output buffer and limit, and our current write position.  "buf"
-   * initially points to "initbuf", but is dynamically allocated if we need to
-   * grow beyond the initial size. */
-  char *buf, *ptr, *limit;
-
-  /* The beginning of the current run, or undefined if we are at the top
-   * level. */
-  char *runbegin;
-
-  /* The list of segments we are accumulating. */
-  upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
-
-  /* The stack of enclosing submessages.  Each entry in the stack points to the
-   * segment where this submessage's length is being accumulated. */
-  int *stack, *top, *stacklimit;
-
-  /* Depth of startmsg/endmsg calls. */
-  int depth;
-};
-
-/* low-level buffering ********************************************************/
-
-/* Low-level functions for interacting with the output buffer. */
-
-/* TODO(haberman): handle pushback */
-static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
-  size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
-  UPB_ASSERT(n == len);
-}
-
-static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
-  return &e->segbuf[*e->top];
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr.  Returns false if the bytes could not be allocated. */
-static bool reserve(upb_pb_encoder *e, size_t bytes) {
-  if ((size_t)(e->limit - e->ptr) < bytes) {
-    /* Grow buffer. */
-    char *new_buf;
-    size_t needed = bytes + (e->ptr - e->buf);
-    size_t old_size = e->limit - e->buf;
-
-    size_t new_size = old_size;
-
-    while (new_size < needed) {
-      new_size *= 2;
-    }
-
-    new_buf = upb_arena_realloc(e->arena, e->buf, old_size, new_size);
-
-    if (new_buf == NULL) {
-      return false;
-    }
-
-    e->ptr = new_buf + (e->ptr - e->buf);
-    e->runbegin = new_buf + (e->runbegin - e->buf);
-    e->limit = new_buf + new_size;
-    e->buf = new_buf;
-  }
-
-  return true;
-}
-
-/* Call when "bytes" bytes have been writte at e->ptr.  The caller *must* have
- * previously called reserve() with at least this many bytes. */
-static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
-  UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes);
-  e->ptr += bytes;
-}
-
-/* Call when all of the bytes for a handler have been written.  Flushes the
- * bytes if possible and necessary, returning false if this failed. */
-static bool commit(upb_pb_encoder *e) {
-  if (!e->top) {
-    /* We aren't inside a delimited region.  Flush our accumulated bytes to
-     * the output.
-     *
-     * TODO(haberman): in the future we may want to delay flushing for
-     * efficiency reasons. */
-    putbuf(e, e->buf, e->ptr - e->buf);
-    e->ptr = e->buf;
-  }
-
-  return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
-  if (!reserve(e, len)) {
-    return false;
-  }
-
-  memcpy(e->ptr, data, len);
-  encoder_advance(e, len);
-  return true;
-}
-
-/* Finish the current run by adding the run totals to the segment and message
- * length. */
-static void accumulate(upb_pb_encoder *e) {
-  size_t run_len;
-  UPB_ASSERT(e->ptr >= e->runbegin);
-  run_len = e->ptr - e->runbegin;
-  e->segptr->seglen += run_len;
-  top(e)->msglen += run_len;
-  e->runbegin = e->ptr;
-}
-
-/* Call to indicate the start of delimited region for which the full length is
- * not yet known.  All data will be buffered until the length is known.
- * Delimited regions may be nested; their lengths will all be tracked properly. */
-static bool start_delim(upb_pb_encoder *e) {
-  if (e->top) {
-    /* We are already buffering, advance to the next segment and push it on the
-     * stack. */
-    accumulate(e);
-
-    if (++e->top == e->stacklimit) {
-      /* TODO(haberman): grow stack? */
-      return false;
-    }
-
-    if (++e->segptr == e->seglimit) {
-      /* Grow segment buffer. */
-      size_t old_size =
-          (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
-      size_t new_size = old_size * 2;
-      upb_pb_encoder_segment *new_buf =
-          upb_arena_realloc(e->arena, e->segbuf, old_size, new_size);
-
-      if (new_buf == NULL) {
-        return false;
-      }
-
-      e->segptr = new_buf + (e->segptr - e->segbuf);
-      e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
-      e->segbuf = new_buf;
-    }
-  } else {
-    /* We were previously at the top level, start buffering. */
-    e->segptr = e->segbuf;
-    e->top = e->stack;
-    e->runbegin = e->ptr;
-  }
-
-  *e->top = e->segptr - e->segbuf;
-  e->segptr->seglen = 0;
-  e->segptr->msglen = 0;
-
-  return true;
-}
-
-/* Call to indicate the end of a delimited region.  We now know the length of
- * the delimited region.  If we are not nested inside any other delimited
- * regions, we can now emit all of the buffered data we accumulated. */
-static bool end_delim(upb_pb_encoder *e) {
-  size_t msglen;
-  accumulate(e);
-  msglen = top(e)->msglen;
-
-  if (e->top == e->stack) {
-    /* All lengths are now available, emit all buffered data. */
-    char buf[UPB_PB_VARINT_MAX_LEN];
-    upb_pb_encoder_segment *s;
-    const char *ptr = e->buf;
-    for (s = e->segbuf; s <= e->segptr; s++) {
-      size_t lenbytes = upb_vencode64(s->msglen, buf);
-      putbuf(e, buf, lenbytes);
-      putbuf(e, ptr, s->seglen);
-      ptr += s->seglen;
-    }
-
-    e->ptr = e->buf;
-    e->top = NULL;
-  } else {
-    /* Need to keep buffering; propagate length info into enclosing
-     * submessages. */
-    --e->top;
-    top(e)->msglen += msglen + upb_varint_size(msglen);
-  }
-
-  return true;
-}
-
-
-/* tag_t **********************************************************************/
-
-/* A precomputed (pre-encoded) tag and length. */
-
-typedef struct {
-  uint8_t bytes;
-  char tag[7];
-} tag_t;
-
-/* Allocates a new tag for this field, and sets it in these handlerattr. */
-static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
-                    upb_handlerattr *attr) {
-  uint32_t n = upb_fielddef_number(f);
-
-  tag_t *tag = upb_gmalloc(sizeof(tag_t));
-  tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
-
-  attr->handler_data = tag;
-  upb_handlers_addcleanup(h, tag, upb_gfree);
-}
-
-static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
-  return encode_bytes(e, tag->tag, tag->bytes);
-}
-
-
-/* encoding of wire types *****************************************************/
-
-static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return encode_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return encode_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool encode_varint(upb_pb_encoder *e, uint64_t val) {
-  if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
-    return false;
-  }
-
-  encoder_advance(e, upb_vencode64(val, e->ptr));
-  return true;
-}
-
-static uint64_t dbl2uint64(double d) {
-  uint64_t ret;
-  memcpy(&ret, &d, sizeof(uint64_t));
-  return ret;
-}
-
-static uint32_t flt2uint32(float d) {
-  uint32_t ret;
-  memcpy(&ret, &d, sizeof(uint32_t));
-  return ret;
-}
-
-
-/* encoding of proto types ****************************************************/
-
-static bool startmsg(void *c, const void *hd) {
-  upb_pb_encoder *e = c;
-  UPB_UNUSED(hd);
-  if (e->depth++ == 0) {
-    upb_bytessink_start(e->output_, 0, &e->subc);
-  }
-  return true;
-}
-
-static bool endmsg(void *c, const void *hd, upb_status *status) {
-  upb_pb_encoder *e = c;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(status);
-  if (--e->depth == 0) {
-    upb_bytessink_end(e->output_);
-  }
-  return true;
-}
-
-static void *encode_startdelimfield(void *c, const void *hd) {
-  bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
-  return ok ? c : UPB_BREAK;
-}
-
-static bool encode_unknown(void *c, const void *hd, const char *buf,
-                           size_t len) {
-  UPB_UNUSED(hd);
-  return encode_bytes(c, buf, len) && commit(c);
-}
-
-static bool encode_enddelimfield(void *c, const void *hd) {
-  UPB_UNUSED(hd);
-  return end_delim(c);
-}
-
-static void *encode_startgroup(void *c, const void *hd) {
-  return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
-}
-
-static bool encode_endgroup(void *c, const void *hd) {
-  return encode_tag(c, hd) && commit(c);
-}
-
-static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
-  UPB_UNUSED(size_hint);
-  return encode_startdelimfield(c, hd);
-}
-
-static size_t encode_strbuf(void *c, const void *hd, const char *buf,
-                            size_t len, const upb_bufhandle *h) {
-  UPB_UNUSED(hd);
-  UPB_UNUSED(h);
-  return encode_bytes(c, buf, len) ? len : 0;
-}
-
-#define T(type, ctype, convert, encode)                                  \
-  static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
-    return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e);  \
-  }                                                                      \
-  static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
-    UPB_UNUSED(hd);                                                      \
-    return encode(e, (convert)(val));                                    \
-  }
-
-T(double,   double,   dbl2uint64,   encode_fixed64)
-T(float,    float,    flt2uint32,   encode_fixed32)
-T(int64,    int64_t,  uint64_t,     encode_varint)
-T(int32,    int32_t,  int64_t,      encode_varint)
-T(fixed64,  uint64_t, uint64_t,     encode_fixed64)
-T(fixed32,  uint32_t, uint32_t,     encode_fixed32)
-T(bool,     bool,     bool,         encode_varint)
-T(uint32,   uint32_t, uint32_t,     encode_varint)
-T(uint64,   uint64_t, uint64_t,     encode_varint)
-T(enum,     int32_t,  uint32_t,     encode_varint)
-T(sfixed32, int32_t,  uint32_t,     encode_fixed32)
-T(sfixed64, int64_t,  uint64_t,     encode_fixed64)
-T(sint32,   int32_t,  upb_zzenc_32, encode_varint)
-T(sint64,   int64_t,  upb_zzenc_64, encode_varint)
-
-#undef T
-
-
-/* code to build the handlers *************************************************/
-
-#include <stdio.h>
-static void newhandlers_callback(const void *closure, upb_handlers *h) {
-  const upb_msgdef *m;
-  upb_msg_field_iter i;
-
-  UPB_UNUSED(closure);
-
-  upb_handlers_setstartmsg(h, startmsg, NULL);
-  upb_handlers_setendmsg(h, endmsg, NULL);
-  upb_handlers_setunknown(h, encode_unknown, NULL);
-
-  m = upb_handlers_msgdef(h);
-  for(upb_msg_field_begin(&i, m);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
-                  upb_fielddef_packed(f);
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-    upb_wiretype_t wt =
-        packed ? UPB_WIRE_TYPE_DELIMITED
-               : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
-
-    /* Pre-encode the tag for this field. */
-    new_tag(h, f, wt, &attr);
-
-    if (packed) {
-      upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
-      upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
-    }
-
-#define T(upper, lower, upbtype)                                     \
-  case UPB_DESCRIPTOR_TYPE_##upper:                                  \
-    if (packed) {                                                    \
-      upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
-    } else {                                                         \
-      upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
-    }                                                                \
-    break;
-
-    switch (upb_fielddef_descriptortype(f)) {
-      T(DOUBLE,   double,   double);
-      T(FLOAT,    float,    float);
-      T(INT64,    int64,    int64);
-      T(INT32,    int32,    int32);
-      T(FIXED64,  fixed64,  uint64);
-      T(FIXED32,  fixed32,  uint32);
-      T(BOOL,     bool,     bool);
-      T(UINT32,   uint32,   uint32);
-      T(UINT64,   uint64,   uint64);
-      T(ENUM,     enum,     int32);
-      T(SFIXED32, sfixed32, int32);
-      T(SFIXED64, sfixed64, int64);
-      T(SINT32,   sint32,   int32);
-      T(SINT64,   sint64,   int64);
-      case UPB_DESCRIPTOR_TYPE_STRING:
-      case UPB_DESCRIPTOR_TYPE_BYTES:
-        upb_handlers_setstartstr(h, f, encode_startstr, &attr);
-        upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
-        upb_handlers_setstring(h, f, encode_strbuf, &attr);
-        break;
-      case UPB_DESCRIPTOR_TYPE_MESSAGE:
-        upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
-        upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
-        break;
-      case UPB_DESCRIPTOR_TYPE_GROUP: {
-        /* Endgroup takes a different tag (wire_type = END_GROUP). */
-        upb_handlerattr attr2 = UPB_HANDLERATTR_INIT;
-        new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
-
-        upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
-        upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
-
-        break;
-      }
-    }
-
-#undef T
-  }
-}
-
-void upb_pb_encoder_reset(upb_pb_encoder *e) {
-  e->segptr = NULL;
-  e->top = NULL;
-  e->depth = 0;
-}
-
-
-/* public API *****************************************************************/
-
-upb_handlercache *upb_pb_encoder_newcache(void) {
-  return upb_handlercache_new(newhandlers_callback, NULL);
-}
-
-upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h,
-                                      upb_bytessink output) {
-  const size_t initial_bufsize = 256;
-  const size_t initial_segbufsize = 16;
-  /* TODO(haberman): make this configurable. */
-  const size_t stack_size = 64;
-#ifndef NDEBUG
-  const size_t size_before = upb_arena_bytesallocated(arena);
-#endif
-
-  upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder));
-  if (!e) return NULL;
-
-  e->buf = upb_arena_malloc(arena, initial_bufsize);
-  e->segbuf = upb_arena_malloc(arena, initial_segbufsize * sizeof(*e->segbuf));
-  e->stack = upb_arena_malloc(arena, stack_size * sizeof(*e->stack));
-
-  if (!e->buf || !e->segbuf || !e->stack) {
-    return NULL;
-  }
-
-  e->limit = e->buf + initial_bufsize;
-  e->seglimit = e->segbuf + initial_segbufsize;
-  e->stacklimit = e->stack + stack_size;
-
-  upb_pb_encoder_reset(e);
-  upb_sink_reset(&e->input_, h, e);
-
-  e->arena = arena;
-  e->output_ = output;
-  e->subc = output.closure;
-  e->ptr = e->buf;
-
-  /* If this fails, increase the value in encoder.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
-                      UPB_PB_ENCODER_SIZE);
-  return e;
-}
-
-upb_sink upb_pb_encoder_input(upb_pb_encoder *e) { return e->input_; }
-/*
- * upb::pb::TextPrinter
- *
- * OPT: This is not optimized at all.  It uses printf() which parses the format
- * string every time, and it allocates memory for every put.
- */
-
-
-#include <ctype.h>
-#include <float.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-
-
-struct upb_textprinter {
-  upb_sink input_;
-  upb_bytessink output_;
-  int indent_depth_;
-  bool single_line_;
-  void *subc;
-};
-
-#define CHECK(x) if ((x) < 0) goto err;
-
-static const char *shortname(const char *longname) {
-  const char *last = strrchr(longname, '.');
-  return last ? last + 1 : longname;
-}
-
-static int indent(upb_textprinter *p) {
-  int i;
-  if (!p->single_line_)
-    for (i = 0; i < p->indent_depth_; i++)
-      upb_bytessink_putbuf(p->output_, p->subc, "  ", 2, NULL);
-  return 0;
-}
-
-static int endfield(upb_textprinter *p) {
-  const char ch = (p->single_line_ ? ' ' : '\n');
-  upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
-  return 0;
-}
-
-static int putescaped(upb_textprinter *p, const char *buf, size_t len,
-                      bool preserve_utf8) {
-  /* Based on CEscapeInternal() from Google's protobuf release. */
-  char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
-  const char *end = buf + len;
-
-  /* I think hex is prettier and more useful, but proto2 uses octal; should
-   * investigate whether it can parse hex also. */
-  const bool use_hex = false;
-  bool last_hex_escape = false; /* true if last output char was \xNN */
-
-  for (; buf < end; buf++) {
-    bool is_hex_escape;
-
-    if (dstend - dst < 4) {
-      upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
-      dst = dstbuf;
-    }
-
-    is_hex_escape = false;
-    switch (*buf) {
-      case '\n': *(dst++) = '\\'; *(dst++) = 'n';  break;
-      case '\r': *(dst++) = '\\'; *(dst++) = 'r';  break;
-      case '\t': *(dst++) = '\\'; *(dst++) = 't';  break;
-      case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
-      case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
-      case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
-      default:
-        /* Note that if we emit \xNN and the buf character after that is a hex
-         * digit then that digit must be escaped too to prevent it being
-         * interpreted as part of the character code by C. */
-        if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
-            (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
-          sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
-          is_hex_escape = use_hex;
-          dst += 4;
-        } else {
-          *(dst++) = *buf; break;
-        }
-    }
-    last_hex_escape = is_hex_escape;
-  }
-  /* Flush remaining data. */
-  upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
-  return 0;
-}
-
-bool putf(upb_textprinter *p, const char *fmt, ...) {
-  va_list args;
-  va_list args_copy;
-  char *str;
-  int written;
-  int len;
-  bool ok;
-
-  va_start(args, fmt);
-
-  /* Run once to get the length of the string. */
-  _upb_va_copy(args_copy, args);
-  len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
-  va_end(args_copy);
-
-  /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
-  str = upb_gmalloc(len + 1);
-  if (!str) return false;
-  written = vsprintf(str, fmt, args);
-  va_end(args);
-  UPB_ASSERT(written == len);
-
-  ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
-  upb_gfree(str);
-  return ok;
-}
-
-
-/* handlers *******************************************************************/
-
-static bool textprinter_startmsg(void *c, const void *hd) {
-  upb_textprinter *p = c;
-  UPB_UNUSED(hd);
-  if (p->indent_depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc);
-  }
-  return true;
-}
-
-static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
-  upb_textprinter *p = c;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(s);
-  if (p->indent_depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-#define TYPE(name, ctype, fmt) \
-  static bool textprinter_put ## name(void *closure, const void *handler_data, \
-                                      ctype val) {                             \
-    upb_textprinter *p = closure;                                              \
-    const upb_fielddef *f = handler_data;                                      \
-    CHECK(indent(p));                                                          \
-    putf(p, "%s: " fmt, upb_fielddef_name(f), val);                            \
-    CHECK(endfield(p));                                                        \
-    return true;                                                               \
-  err:                                                                         \
-    return false;                                                              \
-}
-
-static bool textprinter_putbool(void *closure, const void *handler_data,
-                                bool val) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  CHECK(indent(p));
-  putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
-  CHECK(endfield(p));
-  return true;
-err:
-  return false;
-}
-
-#define STRINGIFY_HELPER(x) #x
-#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
-
-TYPE(int32,  int32_t,  "%" PRId32)
-TYPE(int64,  int64_t,  "%" PRId64)
-TYPE(uint32, uint32_t, "%" PRIu32)
-TYPE(uint64, uint64_t, "%" PRIu64)
-TYPE(float,  float,    "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
-TYPE(double, double,   "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
-
-#undef TYPE
-
-/* Output a symbolic value from the enum if found, else just print as int32. */
-static bool textprinter_putenum(void *closure, const void *handler_data,
-                                int32_t val) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  const upb_enumdef *enum_def = upb_fielddef_enumsubdef(f);
-  const char *label = upb_enumdef_iton(enum_def, val);
-  if (label) {
-    indent(p);
-    putf(p, "%s: %s", upb_fielddef_name(f), label);
-    endfield(p);
-  } else {
-    if (!textprinter_putint32(closure, handler_data, val))
-      return false;
-  }
-  return true;
-}
-
-static void *textprinter_startstr(void *closure, const void *handler_data,
-                      size_t size_hint) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  UPB_UNUSED(size_hint);
-  indent(p);
-  putf(p, "%s: \"", upb_fielddef_name(f));
-  return p;
-}
-
-static bool textprinter_endstr(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  UPB_UNUSED(handler_data);
-  putf(p, "\"");
-  endfield(p);
-  return true;
-}
-
-static size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
-                                 size_t len, const upb_bufhandle *handle) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = hd;
-  UPB_UNUSED(handle);
-  CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
-  return len;
-err:
-  return 0;
-}
-
-static void *textprinter_startsubmsg(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  const char *name = handler_data;
-  CHECK(indent(p));
-  putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
-  p->indent_depth_++;
-  return p;
-err:
-  return UPB_BREAK;
-}
-
-static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  UPB_UNUSED(handler_data);
-  p->indent_depth_--;
-  CHECK(indent(p));
-  upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
-  CHECK(endfield(p));
-  return true;
-err:
-  return false;
-}
-
-static void onmreg(const void *c, upb_handlers *h) {
-  const upb_msgdef *m = upb_handlers_msgdef(h);
-  upb_msg_field_iter i;
-  UPB_UNUSED(c);
-
-  upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
-  upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
-
-  for(upb_msg_field_begin(&i, m);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-    attr.handler_data = f;
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_INT32:
-        upb_handlers_setint32(h, f, textprinter_putint32, &attr);
-        break;
-      case UPB_TYPE_INT64:
-        upb_handlers_setint64(h, f, textprinter_putint64, &attr);
-        break;
-      case UPB_TYPE_UINT32:
-        upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
-        break;
-      case UPB_TYPE_UINT64:
-        upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
-        break;
-      case UPB_TYPE_FLOAT:
-        upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
-        break;
-      case UPB_TYPE_DOUBLE:
-        upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
-        break;
-      case UPB_TYPE_BOOL:
-        upb_handlers_setbool(h, f, textprinter_putbool, &attr);
-        break;
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
-        upb_handlers_setstring(h, f, textprinter_putstr, &attr);
-        upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
-        break;
-      case UPB_TYPE_MESSAGE: {
-        const char *name =
-            upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_GROUP
-                ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
-                : upb_fielddef_name(f);
-        attr.handler_data = name;
-        upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
-        upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
-        break;
-      }
-      case UPB_TYPE_ENUM:
-        upb_handlers_setint32(h, f, textprinter_putenum, &attr);
-        break;
-    }
-  }
-}
-
-static void textprinter_reset(upb_textprinter *p, bool single_line) {
-  p->single_line_ = single_line;
-  p->indent_depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
-                                        upb_bytessink output) {
-  upb_textprinter *p = upb_arena_malloc(arena, sizeof(upb_textprinter));
-  if (!p) return NULL;
-
-  p->output_ = output;
-  upb_sink_reset(&p->input_, h, p);
-  textprinter_reset(p, false);
-
-  return p;
-}
-
-upb_handlercache *upb_textprinter_newcache(void) {
-  return upb_handlercache_new(&onmreg, NULL);
-}
-
-upb_sink upb_textprinter_input(upb_textprinter *p) { return p->input_; }
-
-void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
-  p->single_line_ = single_line;
-}
-
-
-/* Index is descriptor type. */
-const uint8_t upb_pb_native_wire_types[] = {
-  UPB_WIRE_TYPE_END_GROUP,     /* ENDGROUP */
-  UPB_WIRE_TYPE_64BIT,         /* DOUBLE */
-  UPB_WIRE_TYPE_32BIT,         /* FLOAT */
-  UPB_WIRE_TYPE_VARINT,        /* INT64 */
-  UPB_WIRE_TYPE_VARINT,        /* UINT64 */
-  UPB_WIRE_TYPE_VARINT,        /* INT32 */
-  UPB_WIRE_TYPE_64BIT,         /* FIXED64 */
-  UPB_WIRE_TYPE_32BIT,         /* FIXED32 */
-  UPB_WIRE_TYPE_VARINT,        /* BOOL */
-  UPB_WIRE_TYPE_DELIMITED,     /* STRING */
-  UPB_WIRE_TYPE_START_GROUP,   /* GROUP */
-  UPB_WIRE_TYPE_DELIMITED,     /* MESSAGE */
-  UPB_WIRE_TYPE_DELIMITED,     /* BYTES */
-  UPB_WIRE_TYPE_VARINT,        /* UINT32 */
-  UPB_WIRE_TYPE_VARINT,        /* ENUM */
-  UPB_WIRE_TYPE_32BIT,         /* SFIXED32 */
-  UPB_WIRE_TYPE_64BIT,         /* SFIXED64 */
-  UPB_WIRE_TYPE_VARINT,        /* SINT32 */
-  UPB_WIRE_TYPE_VARINT,        /* SINT64 */
-};
-
-/* A basic branch-based decoder, uses 32-bit values to get good performance
- * on 32-bit architectures (but performs well on 64-bits also).
- * This scheme comes from the original Google Protobuf implementation
- * (proto2). */
-upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
-  upb_decoderet err = {NULL, 0};
-  const char *p = r.p;
-  uint32_t low = (uint32_t)r.val;
-  uint32_t high = 0;
-  uint32_t b;
-  b = *(p++); low  |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
-  b = *(p++); low  |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
-  b = *(p++); low  |= (b & 0x7fU) << 28;
-              high  = (b & 0x7fU) >>  4; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) <<  3; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
-  return err;
-
-done:
-  r.val = ((uint64_t)high << 32) | low;
-  r.p = p;
-  return r;
-}
-
-/* Like the previous, but uses 64-bit values. */
-upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
-  const char *p = r.p;
-  uint64_t val = r.val;
-  uint64_t b;
-  upb_decoderet err = {NULL, 0};
-  b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
-  return err;
-
-done:
-  r.val = val;
-  r.p = p;
-  return r;
-}
-
-// #line 1 "upb/json/parser.rl"
-/*
-** upb::json::Parser (upb_json_parser)
-**
-** A parser that uses the Ragel State Machine Compiler to generate
-** the finite automata.
-**
-** Ragel only natively handles regular languages, but we can manually
-** program it a bit to handle context-free languages like JSON, by using
-** the "fcall" and "fret" constructs.
-**
-** This parser can handle the basics, but needs several things to be fleshed
-** out:
-**
-** - handling of unicode escape sequences (including high surrogate pairs).
-** - properly check and report errors for unknown fields, stack overflow,
-**   improper array nesting (or lack of nesting).
-** - handling of base64 sequences with padding characters.
-** - handling of push-back (non-success returns from sink functions).
-** - handling of keys/escape-sequences/etc that span input buffers.
-*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <float.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <time.h>
-
-
-
-#define UPB_JSON_MAX_DEPTH 64
-
-/* Type of value message */
-enum {
-  VALUE_NULLVALUE   = 0,
-  VALUE_NUMBERVALUE = 1,
-  VALUE_STRINGVALUE = 2,
-  VALUE_BOOLVALUE   = 3,
-  VALUE_STRUCTVALUE = 4,
-  VALUE_LISTVALUE   = 5
-};
-
-/* Forward declare */
-static bool is_top_level(upb_json_parser *p);
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type);
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type);
-
-static bool is_number_wrapper_object(upb_json_parser *p);
-static bool does_number_wrapper_start(upb_json_parser *p);
-static bool does_number_wrapper_end(upb_json_parser *p);
-
-static bool is_string_wrapper_object(upb_json_parser *p);
-static bool does_string_wrapper_start(upb_json_parser *p);
-static bool does_string_wrapper_end(upb_json_parser *p);
-
-static bool does_fieldmask_start(upb_json_parser *p);
-static bool does_fieldmask_end(upb_json_parser *p);
-static void start_fieldmask_object(upb_json_parser *p);
-static void end_fieldmask_object(upb_json_parser *p);
-
-static void start_wrapper_object(upb_json_parser *p);
-static void end_wrapper_object(upb_json_parser *p);
-
-static void start_value_object(upb_json_parser *p, int value_type);
-static void end_value_object(upb_json_parser *p);
-
-static void start_listvalue_object(upb_json_parser *p);
-static void end_listvalue_object(upb_json_parser *p);
-
-static void start_structvalue_object(upb_json_parser *p);
-static void end_structvalue_object(upb_json_parser *p);
-
-static void start_object(upb_json_parser *p);
-static void end_object(upb_json_parser *p);
-
-static void start_any_object(upb_json_parser *p, const char *ptr);
-static bool end_any_object(upb_json_parser *p, const char *ptr);
-
-static bool start_subobject(upb_json_parser *p);
-static void end_subobject(upb_json_parser *p);
-
-static void start_member(upb_json_parser *p);
-static void end_member(upb_json_parser *p);
-static bool end_membername(upb_json_parser *p);
-
-static void start_any_member(upb_json_parser *p, const char *ptr);
-static void end_any_member(upb_json_parser *p, const char *ptr);
-static bool end_any_membername(upb_json_parser *p);
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
-             const upb_bufhandle *handle);
-static bool end(void *closure, const void *hd);
-
-static const char eof_ch = 'e';
-
-/* stringsink */
-typedef struct {
-  upb_byteshandler handler;
-  upb_bytessink sink;
-  char *ptr;
-  size_t len, size;
-} upb_stringsink;
-
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
-  upb_stringsink *sink = _sink;
-  sink->len = 0;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(size_hint);
-  return sink;
-}
-
-static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
-                                size_t len, const upb_bufhandle *handle) {
-  upb_stringsink *sink = _sink;
-  size_t new_size = sink->size;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  while (sink->len + len > new_size) {
-    new_size *= 2;
-  }
-
-  if (new_size != sink->size) {
-    sink->ptr = realloc(sink->ptr, new_size);
-    sink->size = new_size;
-  }
-
-  memcpy(sink->ptr + sink->len, ptr, len);
-  sink->len += len;
-
-  return len;
-}
-
-void upb_stringsink_init(upb_stringsink *sink) {
-  upb_byteshandler_init(&sink->handler);
-  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
-  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
-  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
-  sink->size = 32;
-  sink->ptr = malloc(sink->size);
-  sink->len = 0;
-}
-
-void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); }
-
-typedef struct {
-  /* For encoding Any value field in binary format. */
-  upb_handlercache *encoder_handlercache;
-  upb_stringsink stringsink;
-
-  /* For decoding Any value field in json format. */
-  upb_json_codecache *parser_codecache;
-  upb_sink sink;
-  upb_json_parser *parser;
-
-  /* Mark the range of uninterpreted values in json input before type url. */
-  const char *before_type_url_start;
-  const char *before_type_url_end;
-
-  /* Mark the range of uninterpreted values in json input after type url. */
-  const char *after_type_url_start;
-} upb_jsonparser_any_frame;
-
-typedef struct {
-  upb_sink sink;
-
-  /* The current message in which we're parsing, and the field whose value we're
-   * expecting next. */
-  const upb_msgdef *m;
-  const upb_fielddef *f;
-
-  /* The table mapping json name to fielddef for this message. */
-  const upb_strtable *name_table;
-
-  /* We are in a repeated-field context. We need this flag to decide whether to
-   * handle the array as a normal repeated field or a
-   * google.protobuf.ListValue/google.protobuf.Value. */
-  bool is_repeated;
-
-  /* We are in a repeated-field context, ready to emit mapentries as
-   * submessages. This flag alters the start-of-object (open-brace) behavior to
-   * begin a sequence of mapentry messages rather than a single submessage. */
-  bool is_map;
-
-  /* We are in a map-entry message context. This flag is set when parsing the
-   * value field of a single map entry and indicates to all value-field parsers
-   * (subobjects, strings, numbers, and bools) that the map-entry submessage
-   * should end as soon as the value is parsed. */
-  bool is_mapentry;
-
-  /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
-   * message's map field that we're currently parsing. This differs from |f|
-   * because |f| is the field in the *current* message (i.e., the map-entry
-   * message itself), not the parent's field that leads to this map. */
-  const upb_fielddef *mapfield;
-
-  /* We are in an Any message context. This flag is set when parsing the Any
-   * message and indicates to all field parsers (subobjects, strings, numbers,
-   * and bools) that the parsed field should be serialized as binary data or
-   * cached (type url not found yet). */
-  bool is_any;
-
-  /* The type of packed message in Any. */
-  upb_jsonparser_any_frame *any_frame;
-
-  /* True if the field to be parsed is unknown. */
-  bool is_unknown_field;
-} upb_jsonparser_frame;
-
-static void init_frame(upb_jsonparser_frame* frame) {
-  frame->m = NULL;
-  frame->f = NULL;
-  frame->name_table = NULL;
-  frame->is_repeated = false;
-  frame->is_map = false;
-  frame->is_mapentry = false;
-  frame->mapfield = NULL;
-  frame->is_any = false;
-  frame->any_frame = NULL;
-  frame->is_unknown_field = false;
-}
-
-struct upb_json_parser {
-  upb_arena *arena;
-  const upb_json_parsermethod *method;
-  upb_bytessink input_;
-
-  /* Stack to track the JSON scopes we are in. */
-  upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
-  upb_jsonparser_frame *top;
-  upb_jsonparser_frame *limit;
-
-  upb_status *status;
-
-  /* Ragel's internal parsing stack for the parsing state machine. */
-  int current_state;
-  int parser_stack[UPB_JSON_MAX_DEPTH];
-  int parser_top;
-
-  /* The handle for the current buffer. */
-  const upb_bufhandle *handle;
-
-  /* Accumulate buffer.  See details in parser.rl. */
-  const char *accumulated;
-  size_t accumulated_len;
-  char *accumulate_buf;
-  size_t accumulate_buf_size;
-
-  /* Multi-part text data.  See details in parser.rl. */
-  int multipart_state;
-  upb_selector_t string_selector;
-
-  /* Input capture.  See details in parser.rl. */
-  const char *capture;
-
-  /* Intermediate result of parsing a unicode escape sequence. */
-  uint32_t digit;
-
-  /* For resolve type url in Any. */
-  const upb_symtab *symtab;
-
-  /* Whether to proceed if unknown field is met. */
-  bool ignore_json_unknown;
-
-  /* Cache for parsing timestamp due to base and zone are handled in different
-   * handlers. */
-  struct tm tm;
-};
-
-static upb_jsonparser_frame* start_jsonparser_frame(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  inner = p->top + 1;
-  init_frame(inner);
-  return inner;
-}
-
-struct upb_json_codecache {
-  upb_arena *arena;
-  upb_inttable methods;   /* upb_msgdef* -> upb_json_parsermethod* */
-};
-
-struct upb_json_parsermethod {
-  const upb_json_codecache *cache;
-  upb_byteshandler input_handler_;
-
-  /* Maps json_name -> fielddef */
-  upb_strtable name_table;
-};
-
-#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-
-static upb_jsonparser_any_frame *json_parser_any_frame_new(
-    upb_json_parser *p) {
-  upb_jsonparser_any_frame *frame;
-
-  frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
-
-  frame->encoder_handlercache = upb_pb_encoder_newcache();
-  frame->parser_codecache = upb_json_codecache_new();
-  frame->parser = NULL;
-  frame->before_type_url_start = NULL;
-  frame->before_type_url_end = NULL;
-  frame->after_type_url_start = NULL;
-
-  upb_stringsink_init(&frame->stringsink);
-
-  return frame;
-}
-
-static void json_parser_any_frame_set_payload_type(
-    upb_json_parser *p,
-    upb_jsonparser_any_frame *frame,
-    const upb_msgdef *payload_type) {
-  const upb_handlers *h;
-  const upb_json_parsermethod *parser_method;
-  upb_pb_encoder *encoder;
-
-  /* Initialize encoder. */
-  h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
-  encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
-
-  /* Initialize parser. */
-  parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
-  upb_sink_reset(&frame->sink, h, encoder);
-  frame->parser =
-      upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink,
-                             p->status, p->ignore_json_unknown);
-}
-
-static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) {
-  upb_handlercache_free(frame->encoder_handlercache);
-  upb_json_codecache_free(frame->parser_codecache);
-  upb_stringsink_uninit(&frame->stringsink);
-}
-
-static bool json_parser_any_frame_has_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->parser != NULL;
-}
-
-static bool json_parser_any_frame_has_value_before_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->before_type_url_start != frame->before_type_url_end;
-}
-
-static bool json_parser_any_frame_has_value_after_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->after_type_url_start != NULL;
-}
-
-static bool json_parser_any_frame_has_value(
-  upb_jsonparser_any_frame *frame) {
-  return json_parser_any_frame_has_value_before_type_url(frame) ||
-         json_parser_any_frame_has_value_after_type_url(frame);
-}
-
-static void json_parser_any_frame_set_before_type_url_end(
-    upb_jsonparser_any_frame *frame,
-    const char *ptr) {
-  if (frame->parser == NULL) {
-    frame->before_type_url_end = ptr;
-  }
-}
-
-static void json_parser_any_frame_set_after_type_url_start_once(
-    upb_jsonparser_any_frame *frame,
-    const char *ptr) {
-  if (json_parser_any_frame_has_type_url(frame) &&
-      frame->after_type_url_start == NULL) {
-    frame->after_type_url_start = ptr;
-  }
-}
-
-/* Used to signal that a capture has been suspended. */
-static char suspend_capture;
-
-static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
-                                             upb_handlertype_t type) {
-  upb_selector_t sel;
-  bool ok = upb_handlers_getselector(p->top->f, type, &sel);
-  UPB_ASSERT(ok);
-  return sel;
-}
-
-static upb_selector_t parser_getsel(upb_json_parser *p) {
-  return getsel_for_handlertype(
-      p, upb_handlers_getprimitivehandlertype(p->top->f));
-}
-
-static bool check_stack(upb_json_parser *p) {
-  if ((p->top + 1) == p->limit) {
-    upb_status_seterrmsg(p->status, "Nesting too deep");
-    return false;
-  }
-
-  return true;
-}
-
-static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
-  upb_value v;
-  const upb_json_codecache *cache = p->method->cache;
-  bool ok;
-  const upb_json_parsermethod *method;
-
-  ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
-  UPB_ASSERT(ok);
-  method = upb_value_getconstptr(v);
-
-  frame->name_table = &method->name_table;
-}
-
-/* There are GCC/Clang built-ins for overflow checking which we could start
- * using if there was any performance benefit to it. */
-
-static bool checked_add(size_t a, size_t b, size_t *c) {
-  if (SIZE_MAX - a < b) return false;
-  *c = a + b;
-  return true;
-}
-
-static size_t saturating_multiply(size_t a, size_t b) {
-  /* size_t is unsigned, so this is defined behavior even on overflow. */
-  size_t ret = a * b;
-  if (b != 0 && ret / b != a) {
-    ret = SIZE_MAX;
-  }
-  return ret;
-}
-
-
-/* Base64 decoding ************************************************************/
-
-/* TODO(haberman): make this streaming. */
-
-static const signed char b64table[] = {
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,
-  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
-  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
-  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
-  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
-  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
-  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,
-  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
-  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
-  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
-  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
-};
-
-/* Returns the table value sign-extended to 32 bits.  Knowing that the upper
- * bits will be 1 for unrecognized characters makes it easier to check for
- * this error condition later (see below). */
-int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
-
-/* Returns true if the given character is not a valid base64 character or
- * padding. */
-bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
-
-static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
-                        size_t len) {
-  const char *limit = ptr + len;
-  for (; ptr < limit; ptr += 4) {
-    uint32_t val;
-    char output[3];
-
-    if (limit - ptr < 4) {
-      upb_status_seterrf(p->status,
-                         "Base64 input for bytes field not a multiple of 4: %s",
-                         upb_fielddef_name(p->top->f));
-      return false;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12 |
-          b64lookup(ptr[2]) << 6  |
-          b64lookup(ptr[3]);
-
-    /* Test the upper bit; returns true if any of the characters returned -1. */
-    if (val & 0x80000000) {
-      goto otherchar;
-    }
-
-    output[0] = val >> 16;
-    output[1] = (val >> 8) & 0xff;
-    output[2] = val & 0xff;
-    upb_sink_putstring(p->top->sink, sel, output, 3, NULL);
-  }
-  return true;
-
-otherchar:
-  if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
-      nonbase64(ptr[3]) ) {
-    upb_status_seterrf(p->status,
-                       "Non-base64 characters in bytes field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  } if (ptr[2] == '=') {
-    uint32_t val;
-    char output;
-
-    /* Last group contains only two input bytes, one output byte. */
-    if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
-      goto badpadding;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12;
-
-    UPB_ASSERT(!(val & 0x80000000));
-    output = val >> 16;
-    upb_sink_putstring(p->top->sink, sel, &output, 1, NULL);
-    return true;
-  } else {
-    uint32_t val;
-    char output[2];
-
-    /* Last group contains only three input bytes, two output bytes. */
-    if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
-      goto badpadding;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12 |
-          b64lookup(ptr[2]) << 6;
-
-    output[0] = val >> 16;
-    output[1] = (val >> 8) & 0xff;
-    upb_sink_putstring(p->top->sink, sel, output, 2, NULL);
-    return true;
-  }
-
-badpadding:
-  upb_status_seterrf(p->status,
-                     "Incorrect base64 padding for field: %s (%.*s)",
-                     upb_fielddef_name(p->top->f),
-                     4, ptr);
-  return false;
-}
-
-
-/* Accumulate buffer **********************************************************/
-
-/* Functionality for accumulating a buffer.
- *
- * Some parts of the parser need an entire value as a contiguous string.  For
- * example, to look up a member name in a hash table, or to turn a string into
- * a number, the relevant library routines need the input string to be in
- * contiguous memory, even if the value spanned two or more buffers in the
- * input.  These routines handle that.
- *
- * In the common case we can just point to the input buffer to get this
- * contiguous string and avoid any actual copy.  So we optimistically begin
- * this way.  But there are a few cases where we must instead copy into a
- * separate buffer:
- *
- *   1. The string was not contiguous in the input (it spanned buffers).
- *
- *   2. The string included escape sequences that need to be interpreted to get
- *      the true value in a contiguous buffer. */
-
-static void assert_accumulate_empty(upb_json_parser *p) {
-  UPB_ASSERT(p->accumulated == NULL);
-  UPB_ASSERT(p->accumulated_len == 0);
-}
-
-static void accumulate_clear(upb_json_parser *p) {
-  p->accumulated = NULL;
-  p->accumulated_len = 0;
-}
-
-/* Used internally by accumulate_append(). */
-static bool accumulate_realloc(upb_json_parser *p, size_t need) {
-  void *mem;
-  size_t old_size = p->accumulate_buf_size;
-  size_t new_size = UPB_MAX(old_size, 128);
-  while (new_size < need) {
-    new_size = saturating_multiply(new_size, 2);
-  }
-
-  mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
-  if (!mem) {
-    upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
-    return false;
-  }
-
-  p->accumulate_buf = mem;
-  p->accumulate_buf_size = new_size;
-  return true;
-}
-
-/* Logically appends the given data to the append buffer.
- * If "can_alias" is true, we will try to avoid actually copying, but the buffer
- * must be valid until the next accumulate_append() call (if any). */
-static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
-                              bool can_alias) {
-  size_t need;
-
-  if (!p->accumulated && can_alias) {
-    p->accumulated = buf;
-    p->accumulated_len = len;
-    return true;
-  }
-
-  if (!checked_add(p->accumulated_len, len, &need)) {
-    upb_status_seterrmsg(p->status, "Integer overflow.");
-    return false;
-  }
-
-  if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
-    return false;
-  }
-
-  if (p->accumulated != p->accumulate_buf) {
-    memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
-    p->accumulated = p->accumulate_buf;
-  }
-
-  memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
-  p->accumulated_len += len;
-  return true;
-}
-
-/* Returns a pointer to the data accumulated since the last accumulate_clear()
- * call, and writes the length to *len.  This with point either to the input
- * buffer or a temporary accumulate buffer. */
-static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
-  UPB_ASSERT(p->accumulated);
-  *len = p->accumulated_len;
-  return p->accumulated;
-}
-
-
-/* Mult-part text data ********************************************************/
-
-/* When we have text data in the input, it can often come in multiple segments.
- * For example, there may be some raw string data followed by an escape
- * sequence.  The two segments are processed with different logic.  Also buffer
- * seams in the input can cause multiple segments.
- *
- * As we see segments, there are two main cases for how we want to process them:
- *
- *  1. we want to push the captured input directly to string handlers.
- *
- *  2. we need to accumulate all the parts into a contiguous buffer for further
- *     processing (field name lookup, string->number conversion, etc). */
-
-/* This is the set of states for p->multipart_state. */
-enum {
-  /* We are not currently processing multipart data. */
-  MULTIPART_INACTIVE = 0,
-
-  /* We are processing multipart data by accumulating it into a contiguous
-   * buffer. */
-  MULTIPART_ACCUMULATE = 1,
-
-  /* We are processing multipart data by pushing each part directly to the
-   * current string handlers. */
-  MULTIPART_PUSHEAGERLY = 2
-};
-
-/* Start a multi-part text value where we accumulate the data for processing at
- * the end. */
-static void multipart_startaccum(upb_json_parser *p) {
-  assert_accumulate_empty(p);
-  UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_ACCUMULATE;
-}
-
-/* Start a multi-part text value where we immediately push text data to a string
- * value with the given selector. */
-static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
-  assert_accumulate_empty(p);
-  UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_PUSHEAGERLY;
-  p->string_selector = sel;
-}
-
-static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
-                           bool can_alias) {
-  switch (p->multipart_state) {
-    case MULTIPART_INACTIVE:
-      upb_status_seterrmsg(
-          p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
-      return false;
-
-    case MULTIPART_ACCUMULATE:
-      if (!accumulate_append(p, buf, len, can_alias)) {
-        return false;
-      }
-      break;
-
-    case MULTIPART_PUSHEAGERLY: {
-      const upb_bufhandle *handle = can_alias ? p->handle : NULL;
-      upb_sink_putstring(p->top->sink, p->string_selector, buf, len, handle);
-      break;
-    }
-  }
-
-  return true;
-}
-
-/* Note: this invalidates the accumulate buffer!  Call only after reading its
- * contents. */
-static void multipart_end(upb_json_parser *p) {
-  UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_INACTIVE;
-  accumulate_clear(p);
-}
-
-
-/* Input capture **************************************************************/
-
-/* Functionality for capturing a region of the input as text.  Gracefully
- * handles the case where a buffer seam occurs in the middle of the captured
- * region. */
-
-static void capture_begin(upb_json_parser *p, const char *ptr) {
-  UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
-  UPB_ASSERT(p->capture == NULL);
-  p->capture = ptr;
-}
-
-static bool capture_end(upb_json_parser *p, const char *ptr) {
-  UPB_ASSERT(p->capture);
-  if (multipart_text(p, p->capture, ptr - p->capture, true)) {
-    p->capture = NULL;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* This is called at the end of each input buffer (ie. when we have hit a
- * buffer seam).  If we are in the middle of capturing the input, this
- * processes the unprocessed capture region. */
-static void capture_suspend(upb_json_parser *p, const char **ptr) {
-  if (!p->capture) return;
-
-  if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
-    /* We use this as a signal that we were in the middle of capturing, and
-     * that capturing should resume at the beginning of the next buffer.
-     * 
-     * We can't use *ptr here, because we have no guarantee that this pointer
-     * will be valid when we resume (if the underlying memory is freed, then
-     * using the pointer at all, even to compare to NULL, is likely undefined
-     * behavior). */
-    p->capture = &suspend_capture;
-  } else {
-    /* Need to back up the pointer to the beginning of the capture, since
-     * we were not able to actually preserve it. */
-    *ptr = p->capture;
-  }
-}
-
-static void capture_resume(upb_json_parser *p, const char *ptr) {
-  if (p->capture) {
-    UPB_ASSERT(p->capture == &suspend_capture);
-    p->capture = ptr;
-  }
-}
-
-
-/* Callbacks from the parser **************************************************/
-
-/* These are the functions called directly from the parser itself.
- * We define these in the same order as their declarations in the parser. */
-
-static char escape_char(char in) {
-  switch (in) {
-    case 'r': return '\r';
-    case 't': return '\t';
-    case 'n': return '\n';
-    case 'f': return '\f';
-    case 'b': return '\b';
-    case '/': return '/';
-    case '"': return '"';
-    case '\\': return '\\';
-    default:
-      UPB_ASSERT(0);
-      return 'x';
-  }
-}
-
-static bool escape(upb_json_parser *p, const char *ptr) {
-  char ch = escape_char(*ptr);
-  return multipart_text(p, &ch, 1, false);
-}
-
-static void start_hex(upb_json_parser *p) {
-  p->digit = 0;
-}
-
-static void hexdigit(upb_json_parser *p, const char *ptr) {
-  char ch = *ptr;
-
-  p->digit <<= 4;
-
-  if (ch >= '0' && ch <= '9') {
-    p->digit += (ch - '0');
-  } else if (ch >= 'a' && ch <= 'f') {
-    p->digit += ((ch - 'a') + 10);
-  } else {
-    UPB_ASSERT(ch >= 'A' && ch <= 'F');
-    p->digit += ((ch - 'A') + 10);
-  }
-}
-
-static bool end_hex(upb_json_parser *p) {
-  uint32_t codepoint = p->digit;
-
-  /* emit the codepoint as UTF-8. */
-  char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
-  int length = 0;
-  if (codepoint <= 0x7F) {
-    utf8[0] = codepoint;
-    length = 1;
-  } else if (codepoint <= 0x07FF) {
-    utf8[1] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[0] = (codepoint & 0x1F) | 0xC0;
-    length = 2;
-  } else /* codepoint <= 0xFFFF */ {
-    utf8[2] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[1] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[0] = (codepoint & 0x0F) | 0xE0;
-    length = 3;
-  }
-  /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
-   * we have to wait for the next escape to get the full code point). */
-
-  return multipart_text(p, utf8, length, false);
-}
-
-static void start_text(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_text(upb_json_parser *p, const char *ptr) {
-  return capture_end(p, ptr);
-}
-
-static bool start_number(upb_json_parser *p, const char *ptr) {
-  if (is_top_level(p)) {
-    if (is_number_wrapper_object(p)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_NUMBERVALUE);
-    } else {
-      return false;
-    }
-  } else if (does_number_wrapper_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_NUMBERVALUE);
-  }
-
-  multipart_startaccum(p);
-  capture_begin(p, ptr);
-  return true;
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted);
-
-static bool end_number_nontop(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  if (p->top->f == NULL) {
-    multipart_end(p);
-    return true;
-  }
-
-  return parse_number(p, false);
-}
-
-static bool end_number(upb_json_parser *p, const char *ptr) {
-  if (!end_number_nontop(p, ptr)) {
-    return false;
-  }
-
-  if (does_number_wrapper_end(p)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-/* |buf| is NULL-terminated. |buf| itself will never include quotes;
- * |is_quoted| tells us whether this text originally appeared inside quotes. */
-static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
-                                     bool is_quoted) {
-  size_t len = strlen(buf);
-  const char *bufend = buf + len;
-  char *end;
-  upb_fieldtype_t type = upb_fielddef_type(p->top->f);
-  double val;
-  double dummy;
-  double inf = UPB_INFINITY;
-
-  errno = 0;
-
-  if (len == 0 || buf[0] == ' ') {
-    return false;
-  }
-
-  /* For integer types, first try parsing with integer-specific routines.
-   * If these succeed, they will be more accurate for int64/uint64 than
-   * strtod().
-   */
-  switch (type) {
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32: {
-      long val = strtol(buf, &end, 0);
-      if (errno == ERANGE || end != bufend) {
-        break;
-      } else if (val > INT32_MAX || val < INT32_MIN) {
-        return false;
-      } else {
-        upb_sink_putint32(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    case UPB_TYPE_UINT32: {
-      unsigned long val = strtoul(buf, &end, 0);
-      if (end != bufend) {
-        break;
-      } else if (val > UINT32_MAX || errno == ERANGE) {
-        return false;
-      } else {
-        upb_sink_putuint32(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    /* XXX: We can't handle [u]int64 properly on 32-bit machines because
-     * strto[u]ll isn't in C89. */
-    case UPB_TYPE_INT64: {
-      long val = strtol(buf, &end, 0);
-      if (errno == ERANGE || end != bufend) {
-        break;
-      } else {
-        upb_sink_putint64(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    case UPB_TYPE_UINT64: {
-      unsigned long val = strtoul(p->accumulated, &end, 0);
-      if (end != bufend) {
-        break;
-      } else if (errno == ERANGE) {
-        return false;
-      } else {
-        upb_sink_putuint64(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    default:
-      break;
-  }
-
-  if (type != UPB_TYPE_DOUBLE && type != UPB_TYPE_FLOAT && is_quoted) {
-    /* Quoted numbers for integer types are not allowed to be in double form. */
-    return false;
-  }
-
-  if (len == strlen("Infinity") && strcmp(buf, "Infinity") == 0) {
-    /* C89 does not have an INFINITY macro. */
-    val = inf;
-  } else if (len == strlen("-Infinity") && strcmp(buf, "-Infinity") == 0) {
-    val = -inf;
-  } else {
-    val = strtod(buf, &end);
-    if (errno == ERANGE || end != bufend) {
-      return false;
-    }
-  }
-
-  switch (type) {
-#define CASE(capitaltype, smalltype, ctype, min, max)                     \
-    case UPB_TYPE_ ## capitaltype: {                                      \
-      if (modf(val, &dummy) != 0 || val > max || val < min) {             \
-        return false;                                                     \
-      } else {                                                            \
-        upb_sink_put ## smalltype(p->top->sink, parser_getsel(p),        \
-                                  (ctype)val);                            \
-        return true;                                                      \
-      }                                                                   \
-      break;                                                              \
-    }
-    case UPB_TYPE_ENUM:
-    CASE(INT32, int32, int32_t, INT32_MIN, INT32_MAX);
-    CASE(INT64, int64, int64_t, INT64_MIN, INT64_MAX);
-    CASE(UINT32, uint32, uint32_t, 0, UINT32_MAX);
-    CASE(UINT64, uint64, uint64_t, 0, UINT64_MAX);
-#undef CASE
-
-    case UPB_TYPE_DOUBLE:
-      upb_sink_putdouble(p->top->sink, parser_getsel(p), val);
-      return true;
-    case UPB_TYPE_FLOAT:
-      if ((val > FLT_MAX || val < -FLT_MAX) && val != inf && val != -inf) {
-        return false;
-      } else {
-        upb_sink_putfloat(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    default:
-      return false;
-  }
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted) {
-  size_t len;
-  const char *buf;
-
-  /* strtol() and friends unfortunately do not support specifying the length of
-   * the input string, so we need to force a copy into a NULL-terminated buffer. */
-  if (!multipart_text(p, "\0", 1, false)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (parse_number_from_buffer(p, buf, is_quoted)) {
-    multipart_end(p);
-    return true;
-  } else {
-    upb_status_seterrf(p->status, "error parsing number: %s", buf);
-    multipart_end(p);
-    return false;
-  }
-}
-
-static bool parser_putbool(upb_json_parser *p, bool val) {
-  bool ok;
-
-  if (p->top->f == NULL) {
-    return true;
-  }
-
-  if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
-    upb_status_seterrf(p->status,
-                       "Boolean value specified for non-bool field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-
-  ok = upb_sink_putbool(p->top->sink, parser_getsel(p), val);
-  UPB_ASSERT(ok);
-
-  return true;
-}
-
-static bool end_bool(upb_json_parser *p, bool val) {
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_BOOLVALUE);
-    } else {
-      return false;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_BOOLVALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_BOOLVALUE);
-  }
-
-  if (p->top->is_unknown_field) {
-    return true;
-  }
-
-  if (!parser_putbool(p, val)) {
-    return false;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-static bool end_null(upb_json_parser *p) {
-  const char *zero_ptr = "0";
-
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_NULLVALUE);
-    } else {
-      return true;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_NULLVALUE);
-  } else {
-    return true;
-  }
-
-  /* Fill null_value field. */
-  multipart_startaccum(p);
-  capture_begin(p, zero_ptr);
-  capture_end(p, zero_ptr + 1);
-  parse_number(p, false);
-
-  end_value_object(p);
-  if (!is_top_level(p)) {
-    end_subobject(p);
-  }
-
-  return true;
-}
-
-static bool start_any_stringval(upb_json_parser *p) {
-  multipart_startaccum(p);
-  return true;
-}
-
-static bool start_stringval(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    if (is_string_wrapper_object(p) ||
-        is_number_wrapper_object(p)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
-      start_fieldmask_object(p);
-      return true;
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-               is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
-      start_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_STRINGVALUE);
-    } else {
-      return false;
-    }
-  } else if (does_string_wrapper_start(p) ||
-             does_number_wrapper_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (does_fieldmask_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_fieldmask_object(p);
-    return true;
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_TIMESTAMP) ||
-             is_wellknown_field(p, UPB_WELLKNOWN_DURATION)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_STRINGVALUE);
-  }
-
-  if (p->top->f == NULL) {
-    multipart_startaccum(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return start_any_stringval(p);
-  }
-
-  if (upb_fielddef_isstring(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    if (!check_stack(p)) return false;
-
-    /* Start a new parser frame: parser frames correspond one-to-one with
-     * handler frames, and string events occur in a sub-frame. */
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-    upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-    inner->m = p->top->m;
-    inner->f = p->top->f;
-    p->top = inner;
-
-    if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
-      /* For STRING fields we push data directly to the handlers as it is
-       * parsed.  We don't do this yet for BYTES fields, because our base64
-       * decoder is not streaming.
-       *
-       * TODO(haberman): make base64 decoding streaming also. */
-      multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
-      return true;
-    } else {
-      multipart_startaccum(p);
-      return true;
-    }
-  } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL &&
-             upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) {
-    /* No need to push a frame -- numeric values in quotes remain in the
-     * current parser frame.  These values must accumulate so we can convert
-     * them all at once at the end. */
-    multipart_startaccum(p);
-    return true;
-  } else {
-    upb_status_seterrf(p->status,
-                       "String specified for bool or submessage field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-}
-
-static bool end_any_stringval(upb_json_parser *p) {
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-
-  /* Set type_url */
-  upb_selector_t sel;
-  upb_jsonparser_frame *inner;
-  if (!check_stack(p)) return false;
-  inner = p->top + 1;
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-  upb_sink_putstring(inner->sink, sel, buf, len, NULL);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(inner->sink, sel);
-
-  multipart_end(p);
-
-  /* Resolve type url */
-  if (strncmp(buf, "type.googleapis.com/", 20) == 0 && len > 20) {
-    const upb_msgdef *payload_type = NULL;
-    buf += 20;
-    len -= 20;
-
-    payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
-    if (payload_type == NULL) {
-      upb_status_seterrf(
-          p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
-      return false;
-    }
-
-    json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type);
-
-    return true;
-  } else {
-    upb_status_seterrf(
-        p->status, "Invalid type url: %.*s\n", (int)len, buf);
-    return false;
-  }
-}
-
-static bool end_stringval_nontop(upb_json_parser *p) {
-  bool ok = true;
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->f == NULL) {
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return end_any_stringval(p);
-  }
-
-  switch (upb_fielddef_type(p->top->f)) {
-    case UPB_TYPE_BYTES:
-      if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
-                       p->accumulated, p->accumulated_len)) {
-        return false;
-      }
-      /* Fall through. */
-
-    case UPB_TYPE_STRING: {
-      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-      upb_sink_endstr(p->top->sink, sel);
-      p->top--;
-      break;
-    }
-
-    case UPB_TYPE_ENUM: {
-      /* Resolve enum symbolic name to integer value. */
-      const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f);
-
-      size_t len;
-      const char *buf = accumulate_getptr(p, &len);
-
-      int32_t int_val = 0;
-      ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
-
-      if (ok) {
-        upb_selector_t sel = parser_getsel(p);
-        upb_sink_putint32(p->top->sink, sel, int_val);
-      } else {
-        upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
-      }
-
-      break;
-    }
-
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      ok = parse_number(p, true);
-      break;
-
-    default:
-      UPB_ASSERT(false);
-      upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
-      ok = false;
-      break;
-  }
-
-  multipart_end(p);
-
-  return ok;
-}
-
-static bool end_stringval(upb_json_parser *p) {
-  /* FieldMask's stringvals have been ended when handling them. Only need to
-   * close FieldMask here.*/
-  if (does_fieldmask_end(p)) {
-    end_fieldmask_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (!end_stringval_nontop(p)) {
-    return false;
-  }
-
-  if (does_string_wrapper_end(p) ||
-      does_number_wrapper_end(p)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_DURATION) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
-    end_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-static void start_duration_base(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_duration_base(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  char seconds_buf[14];
-  char nanos_buf[12];
-  char *end;
-  int64_t seconds = 0;
-  int32_t nanos = 0;
-  double val = 0.0;
-  const char *seconds_membername = "seconds";
-  const char *nanos_membername = "nanos";
-  size_t fraction_start;
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  memset(seconds_buf, 0, 14);
-  memset(nanos_buf, 0, 12);
-
-  /* Find out base end. The maximus duration is 315576000000, which cannot be
-   * represented by double without losing precision. Thus, we need to handle
-   * fraction and base separately. */
-  for (fraction_start = 0; fraction_start < len && buf[fraction_start] != '.';
-       fraction_start++);
-
-  /* Parse base */
-  memcpy(seconds_buf, buf, fraction_start);
-  seconds = strtol(seconds_buf, &end, 10);
-  if (errno == ERANGE || end != seconds_buf + fraction_start) {
-    upb_status_seterrf(p->status, "error parsing duration: %s",
-                       seconds_buf);
-    return false;
-  }
-
-  if (seconds > 315576000000) {
-    upb_status_seterrf(p->status, "error parsing duration: "
-                                   "maximum acceptable value is "
-                                   "315576000000");
-    return false;
-  }
-
-  if (seconds < -315576000000) {
-    upb_status_seterrf(p->status, "error parsing duration: "
-                                   "minimum acceptable value is "
-                                   "-315576000000");
-    return false;
-  }
-
-  /* Parse fraction */
-  nanos_buf[0] = '0';
-  memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
-  val = strtod(nanos_buf, &end);
-  if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
-    upb_status_seterrf(p->status, "error parsing duration: %s",
-                       nanos_buf);
-    return false;
-  }
-
-  nanos = val * 1000000000;
-  if (seconds < 0) nanos = -nanos;
-
-  /* Clean up buffer */
-  multipart_end(p);
-
-  /* Set seconds */
-  start_member(p);
-  capture_begin(p, seconds_membername);
-  capture_end(p, seconds_membername + 7);
-  end_membername(p);
-  upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
-  end_member(p);
-
-  /* Set nanos */
-  start_member(p);
-  capture_begin(p, nanos_membername);
-  capture_end(p, nanos_membername + 5);
-  end_membername(p);
-  upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
-  end_member(p);
-
-  /* Continue previous arena */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static int parse_timestamp_number(upb_json_parser *p) {
-  size_t len;
-  const char *buf;
-  int val;
-
-  /* atoi() and friends unfortunately do not support specifying the length of
-   * the input string, so we need to force a copy into a NULL-terminated buffer. */
-  multipart_text(p, "\0", 1, false);
-
-  buf = accumulate_getptr(p, &len);
-  val = atoi(buf);
-  multipart_end(p);
-  multipart_startaccum(p);
-
-  return val;
-}
-
-static void start_year(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_year(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_year = parse_timestamp_number(p) - 1900;
-  return true;
-}
-
-static void start_month(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_month(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_mon = parse_timestamp_number(p) - 1;
-  return true;
-}
-
-static void start_day(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_day(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_mday = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_hour(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_hour(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_hour = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_minute(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_minute(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_min = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_second(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_second(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_sec = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_timestamp_base(upb_json_parser *p) {
-  memset(&p->tm, 0, sizeof(struct tm));
-}
-
-static void start_timestamp_fraction(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  char nanos_buf[12];
-  char *end;
-  double val = 0.0;
-  int32_t nanos;
-  const char *nanos_membername = "nanos";
-
-  memset(nanos_buf, 0, 12);
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (len > 10) {
-    upb_status_seterrf(p->status,
-        "error parsing timestamp: at most 9-digit fraction.");
-    return false;
-  }
-
-  /* Parse nanos */
-  nanos_buf[0] = '0';
-  memcpy(nanos_buf + 1, buf, len);
-  val = strtod(nanos_buf, &end);
-
-  if (errno == ERANGE || end != nanos_buf + len + 1) {
-    upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
-                       nanos_buf);
-    return false;
-  }
-
-  nanos = val * 1000000000;
-
-  /* Clean up previous environment */
-  multipart_end(p);
-
-  /* Set nanos */
-  start_member(p);
-  capture_begin(p, nanos_membername);
-  capture_end(p, nanos_membername + 5);
-  end_membername(p);
-  upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
-  end_member(p);
-
-  /* Continue previous environment */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static int div_round_up2(int n, int d) {
-  return (n + d - 1) / d;
-}
-
-/* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */
-static int epoch_days(int year, int month, int day) {
-  static const uint16_t month_yday[12] = {0,   31,  59,  90,  120, 151,
-                                          181, 212, 243, 273, 304, 334};
-  int febs_since_0 = month > 2 ? year + 1 : year;
-  int leap_days_since_0 = div_round_up2(febs_since_0, 4) -
-                          div_round_up2(febs_since_0, 100) +
-                          div_round_up2(febs_since_0, 400);
-  int days_since_0 =
-      365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0;
-
-  /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD).
-   * Since the "BC" system does not have a year zero, 1 BC == year zero. */
-  return days_since_0 - 719528;
-}
-
-static int64_t upb_timegm(const struct tm *tp) {
-  int64_t ret = epoch_days(tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday);
-  ret = (ret * 24) + tp->tm_hour;
-  ret = (ret * 60) + tp->tm_min;
-  ret = (ret * 60) + tp->tm_sec;
-  return ret;
-}
-
-static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  int hours;
-  int64_t seconds;
-  const char *seconds_membername = "seconds";
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (buf[0] != 'Z') {
-    if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
-      upb_status_seterrf(p->status, "error parsing timestamp offset");
-      return false;
-    }
-
-    if (buf[0] == '+') {
-      hours = -hours;
-    }
-
-    p->tm.tm_hour += hours;
-  }
-
-  /* Normalize tm */
-  seconds = upb_timegm(&p->tm);
-
-  /* Check timestamp boundary */
-  if (seconds < -62135596800) {
-    upb_status_seterrf(p->status, "error parsing timestamp: "
-                                   "minimum acceptable value is "
-                                   "0001-01-01T00:00:00Z");
-    return false;
-  }
-
-  /* Clean up previous environment */
-  multipart_end(p);
-
-  /* Set seconds */
-  start_member(p);
-  capture_begin(p, seconds_membername);
-  capture_end(p, seconds_membername + 7);
-  end_membername(p);
-  upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
-  end_member(p);
-
-  /* Continue previous environment */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
-  return capture_end(p, ptr);
-}
-
-static bool start_fieldmask_path(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  if (!check_stack(p)) return false;
-
-  /* Start a new parser frame: parser frames correspond one-to-one with
-   * handler frames, and string events occur in a sub-frame. */
-  inner = start_jsonparser_frame(p);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  inner->m = p->top->m;
-  inner->f = p->top->f;
-  p->top = inner;
-
-  multipart_startaccum(p);
-  return true;
-}
-
-static bool lower_camel_push(
-    upb_json_parser *p, upb_selector_t sel, const char *ptr, size_t len) {
-  const char *limit = ptr + len;
-  bool first = true;
-  for (;ptr < limit; ptr++) {
-    if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
-      char lower = tolower(*ptr);
-      upb_sink_putstring(p->top->sink, sel, "_", 1, NULL);
-      upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL);
-    } else {
-      upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL);
-    }
-    first = false;
-  }
-  return true;
-}
-
-static bool end_fieldmask_path(upb_json_parser *p) {
-  upb_selector_t sel;
-
-  if (!lower_camel_push(
-           p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
-           p->accumulated, p->accumulated_len)) {
-    return false;
-  }
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(p->top->sink, sel);
-  p->top--;
-
-  multipart_end(p);
-  return true;
-}
-
-static void start_member(upb_json_parser *p) {
-  UPB_ASSERT(!p->top->f);
-  multipart_startaccum(p);
-}
-
-/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
- * field based on the current contents of the accumulate buffer. */
-static bool parse_mapentry_key(upb_json_parser *p) {
-
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-
-  /* Emit the key field. We do a bit of ad-hoc parsing here because the
-   * parser state machine has already decided that this is a string field
-   * name, and we are reinterpreting it as some arbitrary key type. In
-   * particular, integer and bool keys are quoted, so we need to parse the
-   * quoted string contents here. */
-
-  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
-  if (p->top->f == NULL) {
-    upb_status_seterrmsg(p->status, "mapentry message has no key");
-    return false;
-  }
-  switch (upb_fielddef_type(p->top->f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      /* Invoke end_number. The accum buffer has the number's text already. */
-      if (!parse_number(p, true)) {
-        return false;
-      }
-      break;
-    case UPB_TYPE_BOOL:
-      if (len == 4 && !strncmp(buf, "true", 4)) {
-        if (!parser_putbool(p, true)) {
-          return false;
-        }
-      } else if (len == 5 && !strncmp(buf, "false", 5)) {
-        if (!parser_putbool(p, false)) {
-          return false;
-        }
-      } else {
-        upb_status_seterrmsg(p->status,
-                             "Map bool key not 'true' or 'false'");
-        return false;
-      }
-      multipart_end(p);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      upb_sink subsink;
-      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-      upb_sink_startstr(p->top->sink, sel, len, &subsink);
-      sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-      upb_sink_putstring(subsink, sel, buf, len, NULL);
-      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-      upb_sink_endstr(subsink, sel);
-      multipart_end(p);
-      break;
-    }
-    default:
-      upb_status_seterrmsg(p->status, "Invalid field type for map key");
-      return false;
-  }
-
-  return true;
-}
-
-/* Helper: emit one map entry (as a submessage in the map field sequence). This
- * is invoked from end_membername(), at the end of the map entry's key string,
- * with the map key in the accumulate buffer. It parses the key from that
- * buffer, emits the handler calls to start the mapentry submessage (setting up
- * its subframe in the process), and sets up state in the subframe so that the
- * value parser (invoked next) will emit the mapentry's value field and then
- * end the mapentry message. */
-
-static bool handle_mapentry(upb_json_parser *p) {
-  const upb_fielddef *mapfield;
-  const upb_msgdef *mapentrymsg;
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  /* Map entry: p->top->sink is the seq frame, so we need to start a frame
-   * for the mapentry itself, and then set |f| in that frame so that the map
-   * value field is parsed, and also set a flag to end the frame after the
-   * map-entry value is parsed. */
-  if (!check_stack(p)) return false;
-
-  mapfield = p->top->mapfield;
-  mapentrymsg = upb_fielddef_msgsubdef(mapfield);
-
-  inner = start_jsonparser_frame(p);
-  p->top->f = mapfield;
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
-  upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
-  inner->m = mapentrymsg;
-  inner->mapfield = mapfield;
-
-  /* Don't set this to true *yet* -- we reuse parsing handlers below to push
-   * the key field value to the sink, and these handlers will pop the frame
-   * if they see is_mapentry (when invoked by the parser state machine, they
-   * would have just seen the map-entry value, not key). */
-  inner->is_mapentry = false;
-  p->top = inner;
-
-  /* send STARTMSG in submsg frame. */
-  upb_sink_startmsg(p->top->sink);
-
-  parse_mapentry_key(p);
-
-  /* Set up the value field to receive the map-entry value. */
-  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
-  p->top->is_mapentry = true;  /* set up to pop frame after value is parsed. */
-  p->top->mapfield = mapfield;
-  if (p->top->f == NULL) {
-    upb_status_seterrmsg(p->status, "mapentry message has no value");
-    return false;
-  }
-
-  return true;
-}
-
-static bool end_membername(upb_json_parser *p) {
-  UPB_ASSERT(!p->top->f);
-
-  if (!p->top->m) {
-    p->top->is_unknown_field = true;
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return end_any_membername(p);
-  } else if (p->top->is_map) {
-    return handle_mapentry(p);
-  } else {
-    size_t len;
-    const char *buf = accumulate_getptr(p, &len);
-    upb_value v;
-
-    if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
-      p->top->f = upb_value_getconstptr(v);
-      multipart_end(p);
-
-      return true;
-    } else if (p->ignore_json_unknown) {
-      p->top->is_unknown_field = true;
-      multipart_end(p);
-      return true;
-    } else {
-      upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
-      return false;
-    }
-  }
-}
-
-static bool end_any_membername(upb_json_parser *p) {
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-  upb_value v;
-
-  if (len == 5 && strncmp(buf, "@type", len) == 0) {
-    upb_strtable_lookup2(p->top->name_table, "type_url", 8, &v);
-    p->top->f = upb_value_getconstptr(v);
-    multipart_end(p);
-    return true;
-  } else {
-    p->top->is_unknown_field = true;
-    multipart_end(p);
-    return true;
-  }
-}
-
-static void end_member(upb_json_parser *p) {
-  /* If we just parsed a map-entry value, end that frame too. */
-  if (p->top->is_mapentry) {
-    upb_selector_t sel;
-    bool ok;
-    const upb_fielddef *mapfield;
-
-    UPB_ASSERT(p->top > p->stack);
-    /* send ENDMSG on submsg. */
-    upb_sink_endmsg(p->top->sink, p->status);
-    mapfield = p->top->mapfield;
-
-    /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
-    p->top--;
-    ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
-    UPB_ASSERT(ok);
-    upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
-  }
-
-  p->top->f = NULL;
-  p->top->is_unknown_field = false;
-}
-
-static void start_any_member(upb_json_parser *p, const char *ptr) {
-  start_member(p);
-  json_parser_any_frame_set_after_type_url_start_once(p->top->any_frame, ptr);
-}
-
-static void end_any_member(upb_json_parser *p, const char *ptr) {
-  json_parser_any_frame_set_before_type_url_end(p->top->any_frame, ptr);
-  end_member(p);
-}
-
-static bool start_subobject(upb_json_parser *p) {
-  if (p->top->is_unknown_field) {
-    if (!check_stack(p)) return false;
-
-    p->top = start_jsonparser_frame(p);
-    return true;
-  }
-
-  if (upb_fielddef_ismap(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    /* Beginning of a map. Start a new parser frame in a repeated-field
-     * context. */
-    if (!check_stack(p)) return false;
-
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
-    upb_sink_startseq(p->top->sink, sel, &inner->sink);
-    inner->m = upb_fielddef_msgsubdef(p->top->f);
-    inner->mapfield = p->top->f;
-    inner->is_map = true;
-    p->top = inner;
-
-    return true;
-  } else if (upb_fielddef_issubmsg(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    /* Beginning of a subobject. Start a new parser frame in the submsg
-     * context. */
-    if (!check_stack(p)) return false;
-
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
-    upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
-    inner->m = upb_fielddef_msgsubdef(p->top->f);
-    set_name_table(p, inner);
-    p->top = inner;
-
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
-      p->top->is_any = true;
-      p->top->any_frame = json_parser_any_frame_new(p);
-    } else {
-      p->top->is_any = false;
-      p->top->any_frame = NULL;
-    }
-
-    return true;
-  } else {
-    upb_status_seterrf(p->status,
-                       "Object specified for non-message/group field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-}
-
-static bool start_subobject_full(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_STRUCTVALUE);
-      if (!start_subobject(p)) return false;
-      start_structvalue_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
-      start_structvalue_object(p);
-    } else {
-      return true;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_STRUCT)) {
-    if (!start_subobject(p)) return false;
-    start_structvalue_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) return false;
-    start_value_object(p, VALUE_STRUCTVALUE);
-    if (!start_subobject(p)) return false;
-    start_structvalue_object(p);
-  }
-
-  return start_subobject(p);
-}
-
-static void end_subobject(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    return;
-  }
-
-  if (p->top->is_map) {
-    upb_selector_t sel;
-    p->top--;
-    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
-    upb_sink_endseq(p->top->sink, sel);
-  } else {
-    upb_selector_t sel;
-    bool is_unknown = p->top->m == NULL;
-    p->top--;
-    if (!is_unknown) {
-      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
-      upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
-    }
-  }
-}
-
-static void end_subobject_full(upb_json_parser *p) {
-  end_subobject(p);
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
-    end_structvalue_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-}
-
-static bool start_array(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_LISTVALUE);
-      if (!start_subobject(p)) return false;
-      start_listvalue_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
-      start_listvalue_object(p);
-    } else {
-      return false;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_LISTVALUE) &&
-             (!upb_fielddef_isseq(p->top->f) ||
-              p->top->is_repeated)) {
-    if (!start_subobject(p)) return false;
-    start_listvalue_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE) &&
-             (!upb_fielddef_isseq(p->top->f) ||
-              p->top->is_repeated)) {
-    if (!start_subobject(p)) return false;
-    start_value_object(p, VALUE_LISTVALUE);
-    if (!start_subobject(p)) return false;
-    start_listvalue_object(p);
-  }
-
-  if (p->top->is_unknown_field) {
-    inner = start_jsonparser_frame(p);
-    inner->is_unknown_field = true;
-    p->top = inner;
-
-    return true;
-  }
-
-  if (!upb_fielddef_isseq(p->top->f)) {
-    upb_status_seterrf(p->status,
-                       "Array specified for non-repeated field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-
-  if (!check_stack(p)) return false;
-
-  inner = start_jsonparser_frame(p);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
-  upb_sink_startseq(p->top->sink, sel, &inner->sink);
-  inner->m = p->top->m;
-  inner->f = p->top->f;
-  inner->is_repeated = true;
-  p->top = inner;
-
-  return true;
-}
-
-static void end_array(upb_json_parser *p) {
-  upb_selector_t sel;
-
-  UPB_ASSERT(p->top > p->stack);
-
-  p->top--;
-
-  if (p->top->is_unknown_field) {
-    return;
-  }
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
-  upb_sink_endseq(p->top->sink, sel);
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
-    end_listvalue_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-}
-
-static void start_object(upb_json_parser *p) {
-  if (!p->top->is_map && p->top->m != NULL) {
-    upb_sink_startmsg(p->top->sink);
-  }
-}
-
-static void end_object(upb_json_parser *p) {
-  if (!p->top->is_map && p->top->m != NULL) {
-    upb_sink_endmsg(p->top->sink, p->status);
-  }
-}
-
-static void start_any_object(upb_json_parser *p, const char *ptr) {
-  start_object(p);
-  p->top->any_frame->before_type_url_start = ptr;
-  p->top->any_frame->before_type_url_end = ptr;
-}
-
-static bool end_any_object(upb_json_parser *p, const char *ptr) {
-  const char *value_membername = "value";
-  bool is_well_known_packed = false;
-  const char *packed_end = ptr + 1;
-  upb_selector_t sel;
-  upb_jsonparser_frame *inner;
-
-  if (json_parser_any_frame_has_value(p->top->any_frame) &&
-      !json_parser_any_frame_has_type_url(p->top->any_frame)) {
-    upb_status_seterrmsg(p->status, "No valid type url");
-    return false;
-  }
-
-  /* Well known types data is represented as value field. */
-  if (upb_msgdef_wellknowntype(p->top->any_frame->parser->top->m) !=
-          UPB_WELLKNOWN_UNSPECIFIED) {
-    is_well_known_packed = true;
-
-    if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
-      p->top->any_frame->before_type_url_start =
-          memchr(p->top->any_frame->before_type_url_start, ':',
-                 p->top->any_frame->before_type_url_end -
-                 p->top->any_frame->before_type_url_start);
-      if (p->top->any_frame->before_type_url_start == NULL) {
-        upb_status_seterrmsg(p->status, "invalid data for well known type.");
-        return false;
-      }
-      p->top->any_frame->before_type_url_start++;
-    }
-
-    if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-      p->top->any_frame->after_type_url_start =
-          memchr(p->top->any_frame->after_type_url_start, ':',
-                 (ptr + 1) -
-                 p->top->any_frame->after_type_url_start);
-      if (p->top->any_frame->after_type_url_start == NULL) {
-        upb_status_seterrmsg(p->status, "Invalid data for well known type.");
-        return false;
-      }
-      p->top->any_frame->after_type_url_start++;
-      packed_end = ptr;
-    }
-  }
-
-  if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL,
-               p->top->any_frame->before_type_url_start,
-               p->top->any_frame->before_type_url_end -
-               p->top->any_frame->before_type_url_start, NULL)) {
-      return false;
-    }
-  } else {
-    if (!is_well_known_packed) {
-      if (!parse(p->top->any_frame->parser, NULL, "{", 1, NULL)) {
-        return false;
-      }
-    }
-  }
-
-  if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame) &&
-      json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL, ",", 1, NULL)) {
-      return false;
-    }
-  }
-
-  if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL,
-               p->top->any_frame->after_type_url_start,
-               packed_end - p->top->any_frame->after_type_url_start, NULL)) {
-      return false;
-    }
-  } else {
-    if (!is_well_known_packed) {
-      if (!parse(p->top->any_frame->parser, NULL, "}", 1, NULL)) {
-        return false;
-      }
-    }
-  }
-
-  if (!end(p->top->any_frame->parser, NULL)) {
-    return false;
-  }
-
-  p->top->is_any = false;
-
-  /* Set value */
-  start_member(p);
-  capture_begin(p, value_membername);
-  capture_end(p, value_membername + 5);
-  end_membername(p);
-
-  if (!check_stack(p)) return false;
-  inner = p->top + 1;
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-  upb_sink_putstring(inner->sink, sel, p->top->any_frame->stringsink.ptr,
-                     p->top->any_frame->stringsink.len, NULL);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(inner->sink, sel);
-
-  end_member(p);
-
-  end_object(p);
-
-  /* Deallocate any parse frame. */
-  json_parser_any_frame_free(p->top->any_frame);
-
-  return true;
-}
-
-static bool is_string_wrapper(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type == UPB_WELLKNOWN_STRINGVALUE ||
-         type == UPB_WELLKNOWN_BYTESVALUE;
-}
-
-static bool is_fieldmask(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type == UPB_WELLKNOWN_FIELDMASK;
-}
-
-static void start_fieldmask_object(upb_json_parser *p) {
-  const char *membername = "paths";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + 5);
-  end_membername(p);
-
-  start_array(p);
-}
-
-static void end_fieldmask_object(upb_json_parser *p) {
-  end_array(p);
-  end_member(p);
-  end_object(p);
-}
-
-static void start_wrapper_object(upb_json_parser *p) {
-  const char *membername = "value";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + 5);
-  end_membername(p);
-}
-
-static void end_wrapper_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_value_object(upb_json_parser *p, int value_type) {
-  const char *nullmember = "null_value";
-  const char *numbermember = "number_value";
-  const char *stringmember = "string_value";
-  const char *boolmember = "bool_value";
-  const char *structmember = "struct_value";
-  const char *listmember = "list_value";
-  const char *membername = "";
-
-  switch (value_type) {
-    case VALUE_NULLVALUE:
-      membername = nullmember;
-      break;
-    case VALUE_NUMBERVALUE:
-      membername = numbermember;
-      break;
-    case VALUE_STRINGVALUE:
-      membername = stringmember;
-      break;
-    case VALUE_BOOLVALUE:
-      membername = boolmember;
-      break;
-    case VALUE_STRUCTVALUE:
-      membername = structmember;
-      break;
-    case VALUE_LISTVALUE:
-      membername = listmember;
-      break;
-  }
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_value_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_listvalue_object(upb_json_parser *p) {
-  const char *membername = "values";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_listvalue_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_structvalue_object(upb_json_parser *p) {
-  const char *membername = "fields";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_structvalue_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static bool is_top_level(upb_json_parser *p) {
-  return p->top == p->stack && p->top->f == NULL && !p->top->is_unknown_field;
-}
-
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type) {
-  return p->top->m != NULL && upb_msgdef_wellknowntype(p->top->m) == type;
-}
-
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         (upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(p->top->f))
-              == type);
-}
-
-static bool does_number_wrapper_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         upb_msgdef_isnumberwrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_number_wrapper_end(upb_json_parser *p) {
-  return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool is_number_wrapper_object(upb_json_parser *p) {
-  return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool does_string_wrapper_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         is_string_wrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_string_wrapper_end(upb_json_parser *p) {
-  return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool is_string_wrapper_object(upb_json_parser *p) {
-  return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool does_fieldmask_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         is_fieldmask(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_fieldmask_end(upb_json_parser *p) {
-  return p->top->m != NULL && is_fieldmask(p->top->m);
-}
-
-#define CHECK_RETURN_TOP(x) if (!(x)) goto error
-
-
-/* The actual parser **********************************************************/
-
-/* What follows is the Ragel parser itself.  The language is specified in Ragel
- * and the actions call our C functions above.
- *
- * Ragel has an extensive set of functionality, and we use only a small part of
- * it.  There are many action types but we only use a few:
- *
- *   ">" -- transition into a machine
- *   "%" -- transition out of a machine
- *   "@" -- transition into a final state of a machine.
- *
- * "@" transitions are tricky because a machine can transition into a final
- * state repeatedly.  But in some cases we know this can't happen, for example
- * a string which is delimited by a final '"' can only transition into its
- * final state once, when the closing '"' is seen. */
-
-
-// #line 2780 "upb/json/parser.rl"
-
-
-
-// #line 2583 "upb/json/parser.c"
-static const char _json_actions[] = {
-	0, 1, 0, 1, 1, 1, 3, 1, 
-	4, 1, 6, 1, 7, 1, 8, 1, 
-	9, 1, 11, 1, 12, 1, 13, 1, 
-	14, 1, 15, 1, 16, 1, 17, 1, 
-	18, 1, 19, 1, 20, 1, 22, 1, 
-	23, 1, 24, 1, 35, 1, 37, 1, 
-	39, 1, 40, 1, 42, 1, 43, 1, 
-	44, 1, 46, 1, 48, 1, 49, 1, 
-	50, 1, 51, 1, 53, 1, 54, 2, 
-	4, 9, 2, 5, 6, 2, 7, 3, 
-	2, 7, 9, 2, 21, 26, 2, 25, 
-	10, 2, 27, 28, 2, 29, 30, 2, 
-	32, 34, 2, 33, 31, 2, 38, 36, 
-	2, 40, 42, 2, 45, 2, 2, 46, 
-	54, 2, 47, 36, 2, 49, 54, 2, 
-	50, 54, 2, 51, 54, 2, 52, 41, 
-	2, 53, 54, 3, 32, 34, 35, 4, 
-	21, 26, 27, 28
-};
-
-static const short _json_key_offsets[] = {
-	0, 0, 12, 13, 18, 23, 28, 29, 
-	30, 31, 32, 33, 34, 35, 36, 37, 
-	38, 43, 44, 48, 53, 58, 63, 67, 
-	71, 74, 77, 79, 83, 87, 89, 91, 
-	96, 98, 100, 109, 115, 121, 127, 133, 
-	135, 139, 142, 144, 146, 149, 150, 154, 
-	156, 158, 160, 162, 163, 165, 167, 168, 
-	170, 172, 173, 175, 177, 178, 180, 182, 
-	183, 185, 187, 191, 193, 195, 196, 197, 
-	198, 199, 201, 206, 208, 210, 212, 221, 
-	222, 222, 222, 227, 232, 237, 238, 239, 
-	240, 241, 241, 242, 243, 244, 244, 245, 
-	246, 247, 247, 252, 253, 257, 262, 267, 
-	272, 276, 276, 279, 282, 285, 288, 291, 
-	294, 294, 294, 294, 294, 294
-};
-
-static const char _json_trans_keys[] = {
-	32, 34, 45, 91, 102, 110, 116, 123, 
-	9, 13, 48, 57, 34, 32, 93, 125, 
-	9, 13, 32, 44, 93, 9, 13, 32, 
-	93, 125, 9, 13, 97, 108, 115, 101, 
-	117, 108, 108, 114, 117, 101, 32, 34, 
-	125, 9, 13, 34, 32, 58, 9, 13, 
-	32, 93, 125, 9, 13, 32, 44, 125, 
-	9, 13, 32, 44, 125, 9, 13, 32, 
-	34, 9, 13, 45, 48, 49, 57, 48, 
-	49, 57, 46, 69, 101, 48, 57, 69, 
-	101, 48, 57, 43, 45, 48, 57, 48, 
-	57, 48, 57, 46, 69, 101, 48, 57, 
-	34, 92, 34, 92, 34, 47, 92, 98, 
-	102, 110, 114, 116, 117, 48, 57, 65, 
-	70, 97, 102, 48, 57, 65, 70, 97, 
-	102, 48, 57, 65, 70, 97, 102, 48, 
-	57, 65, 70, 97, 102, 34, 92, 45, 
-	48, 49, 57, 48, 49, 57, 46, 115, 
-	48, 57, 115, 48, 57, 34, 46, 115, 
-	48, 57, 48, 57, 48, 57, 48, 57, 
-	48, 57, 45, 48, 57, 48, 57, 45, 
-	48, 57, 48, 57, 84, 48, 57, 48, 
-	57, 58, 48, 57, 48, 57, 58, 48, 
-	57, 48, 57, 43, 45, 46, 90, 48, 
-	57, 48, 57, 58, 48, 48, 34, 48, 
-	57, 43, 45, 90, 48, 57, 34, 44, 
-	34, 44, 34, 44, 34, 45, 91, 102, 
-	110, 116, 123, 48, 57, 34, 32, 93, 
-	125, 9, 13, 32, 44, 93, 9, 13, 
-	32, 93, 125, 9, 13, 97, 108, 115, 
-	101, 117, 108, 108, 114, 117, 101, 32, 
-	34, 125, 9, 13, 34, 32, 58, 9, 
-	13, 32, 93, 125, 9, 13, 32, 44, 
-	125, 9, 13, 32, 44, 125, 9, 13, 
-	32, 34, 9, 13, 32, 9, 13, 32, 
-	9, 13, 32, 9, 13, 32, 9, 13, 
-	32, 9, 13, 32, 9, 13, 0
-};
-
-static const char _json_single_lengths[] = {
-	0, 8, 1, 3, 3, 3, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	3, 1, 2, 3, 3, 3, 2, 2, 
-	1, 3, 0, 2, 2, 0, 0, 3, 
-	2, 2, 9, 0, 0, 0, 0, 2, 
-	2, 1, 2, 0, 1, 1, 2, 0, 
-	0, 0, 0, 1, 0, 0, 1, 0, 
-	0, 1, 0, 0, 1, 0, 0, 1, 
-	0, 0, 4, 0, 0, 1, 1, 1, 
-	1, 0, 3, 2, 2, 2, 7, 1, 
-	0, 0, 3, 3, 3, 1, 1, 1, 
-	1, 0, 1, 1, 1, 0, 1, 1, 
-	1, 0, 3, 1, 2, 3, 3, 3, 
-	2, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const char _json_range_lengths[] = {
-	0, 2, 0, 1, 1, 1, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 3, 3, 3, 3, 0, 
-	1, 1, 0, 1, 1, 0, 1, 1, 
-	1, 1, 1, 0, 1, 1, 0, 1, 
-	1, 0, 1, 1, 0, 1, 1, 0, 
-	1, 1, 0, 1, 1, 0, 0, 0, 
-	0, 1, 1, 0, 0, 0, 1, 0, 
-	0, 0, 1, 1, 1, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 1, 0, 1, 1, 1, 1, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const short _json_index_offsets[] = {
-	0, 0, 11, 13, 18, 23, 28, 30, 
-	32, 34, 36, 38, 40, 42, 44, 46, 
-	48, 53, 55, 59, 64, 69, 74, 78, 
-	82, 85, 89, 91, 95, 99, 101, 103, 
-	108, 111, 114, 124, 128, 132, 136, 140, 
-	143, 147, 150, 153, 155, 158, 160, 164, 
-	166, 168, 170, 172, 174, 176, 178, 180, 
-	182, 184, 186, 188, 190, 192, 194, 196, 
-	198, 200, 202, 207, 209, 211, 213, 215, 
-	217, 219, 221, 226, 229, 232, 235, 244, 
-	246, 247, 248, 253, 258, 263, 265, 267, 
-	269, 271, 272, 274, 276, 278, 279, 281, 
-	283, 285, 286, 291, 293, 297, 302, 307, 
-	312, 316, 317, 320, 323, 326, 329, 332, 
-	335, 336, 337, 338, 339, 340
-};
-
-static const unsigned char _json_indicies[] = {
-	0, 2, 3, 4, 5, 6, 7, 8, 
-	0, 3, 1, 9, 1, 11, 12, 1, 
-	11, 10, 13, 14, 12, 13, 1, 14, 
-	1, 1, 14, 10, 15, 1, 16, 1, 
-	17, 1, 18, 1, 19, 1, 20, 1, 
-	21, 1, 22, 1, 23, 1, 24, 1, 
-	25, 26, 27, 25, 1, 28, 1, 29, 
-	30, 29, 1, 30, 1, 1, 30, 31, 
-	32, 33, 34, 32, 1, 35, 36, 27, 
-	35, 1, 36, 26, 36, 1, 37, 38, 
-	39, 1, 38, 39, 1, 41, 42, 42, 
-	40, 43, 1, 42, 42, 43, 40, 44, 
-	44, 45, 1, 45, 1, 45, 40, 41, 
-	42, 42, 39, 40, 47, 48, 46, 50, 
-	51, 49, 52, 52, 52, 52, 52, 52, 
-	52, 52, 53, 1, 54, 54, 54, 1, 
-	55, 55, 55, 1, 56, 56, 56, 1, 
-	57, 57, 57, 1, 59, 60, 58, 61, 
-	62, 63, 1, 64, 65, 1, 66, 67, 
-	1, 68, 1, 67, 68, 1, 69, 1, 
-	66, 67, 65, 1, 70, 1, 71, 1, 
-	72, 1, 73, 1, 74, 1, 75, 1, 
-	76, 1, 77, 1, 78, 1, 79, 1, 
-	80, 1, 81, 1, 82, 1, 83, 1, 
-	84, 1, 85, 1, 86, 1, 87, 1, 
-	88, 1, 89, 89, 90, 91, 1, 92, 
-	1, 93, 1, 94, 1, 95, 1, 96, 
-	1, 97, 1, 98, 1, 99, 99, 100, 
-	98, 1, 102, 1, 101, 104, 105, 103, 
-	1, 1, 101, 106, 107, 108, 109, 110, 
-	111, 112, 107, 1, 113, 1, 114, 115, 
-	117, 118, 1, 117, 116, 119, 120, 118, 
-	119, 1, 120, 1, 1, 120, 116, 121, 
-	1, 122, 1, 123, 1, 124, 1, 125, 
-	126, 1, 127, 1, 128, 1, 129, 130, 
-	1, 131, 1, 132, 1, 133, 134, 135, 
-	136, 134, 1, 137, 1, 138, 139, 138, 
-	1, 139, 1, 1, 139, 140, 141, 142, 
-	143, 141, 1, 144, 145, 136, 144, 1, 
-	145, 135, 145, 1, 146, 147, 147, 1, 
-	148, 148, 1, 149, 149, 1, 150, 150, 
-	1, 151, 151, 1, 152, 152, 1, 1, 
-	1, 1, 1, 1, 1, 0
-};
-
-static const char _json_trans_targs[] = {
-	1, 0, 2, 107, 3, 6, 10, 13, 
-	16, 106, 4, 3, 106, 4, 5, 7, 
-	8, 9, 108, 11, 12, 109, 14, 15, 
-	110, 16, 17, 111, 18, 18, 19, 20, 
-	21, 22, 111, 21, 22, 24, 25, 31, 
-	112, 26, 28, 27, 29, 30, 33, 113, 
-	34, 33, 113, 34, 32, 35, 36, 37, 
-	38, 39, 33, 113, 34, 41, 42, 46, 
-	42, 46, 43, 45, 44, 114, 48, 49, 
-	50, 51, 52, 53, 54, 55, 56, 57, 
-	58, 59, 60, 61, 62, 63, 64, 65, 
-	66, 67, 73, 72, 68, 69, 70, 71, 
-	72, 115, 74, 67, 72, 76, 116, 76, 
-	116, 77, 79, 81, 82, 85, 90, 94, 
-	98, 80, 117, 117, 83, 82, 80, 83, 
-	84, 86, 87, 88, 89, 117, 91, 92, 
-	93, 117, 95, 96, 97, 117, 98, 99, 
-	105, 100, 100, 101, 102, 103, 104, 105, 
-	103, 104, 117, 106, 106, 106, 106, 106, 
-	106
-};
-
-static const unsigned char _json_trans_actions[] = {
-	0, 0, 113, 107, 53, 0, 0, 0, 
-	125, 59, 45, 0, 55, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 101, 51, 47, 0, 0, 45, 
-	49, 49, 104, 0, 0, 0, 0, 0, 
-	3, 0, 0, 0, 0, 0, 5, 15, 
-	0, 0, 71, 7, 13, 0, 74, 9, 
-	9, 9, 77, 80, 11, 37, 37, 37, 
-	0, 0, 0, 39, 0, 41, 86, 0, 
-	0, 0, 17, 19, 0, 21, 23, 0, 
-	25, 27, 0, 29, 31, 0, 33, 35, 
-	0, 135, 83, 135, 0, 0, 0, 0, 
-	0, 92, 0, 89, 89, 98, 43, 0, 
-	131, 95, 113, 107, 53, 0, 0, 0, 
-	125, 59, 69, 110, 45, 0, 55, 0, 
-	0, 0, 0, 0, 0, 119, 0, 0, 
-	0, 122, 0, 0, 0, 116, 0, 101, 
-	51, 47, 0, 0, 45, 49, 49, 104, 
-	0, 0, 128, 0, 57, 63, 65, 61, 
-	67
-};
-
-static const unsigned char _json_eof_actions[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 1, 0, 1, 0, 0, 1, 1, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 57, 63, 65, 61, 67, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const int json_start = 1;
-
-static const int json_en_number_machine = 23;
-static const int json_en_string_machine = 32;
-static const int json_en_duration_machine = 40;
-static const int json_en_timestamp_machine = 47;
-static const int json_en_fieldmask_machine = 75;
-static const int json_en_value_machine = 78;
-static const int json_en_main = 1;
-
-
-// #line 2783 "upb/json/parser.rl"
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
-             const upb_bufhandle *handle) {
-  upb_json_parser *parser = closure;
-
-  /* Variables used by Ragel's generated code. */
-  int cs = parser->current_state;
-  int *stack = parser->parser_stack;
-  int top = parser->parser_top;
-
-  const char *p = buf;
-  const char *pe = buf + size;
-  const char *eof = &eof_ch;
-
-  parser->handle = handle;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  capture_resume(parser, buf);
-
-  
-// #line 2861 "upb/json/parser.c"
-	{
-	int _klen;
-	unsigned int _trans;
-	const char *_acts;
-	unsigned int _nacts;
-	const char *_keys;
-
-	if ( p == pe )
-		goto _test_eof;
-	if ( cs == 0 )
-		goto _out;
-_resume:
-	_keys = _json_trans_keys + _json_key_offsets[cs];
-	_trans = _json_index_offsets[cs];
-
-	_klen = _json_single_lengths[cs];
-	if ( _klen > 0 ) {
-		const char *_lower = _keys;
-		const char *_mid;
-		const char *_upper = _keys + _klen - 1;
-		while (1) {
-			if ( _upper < _lower )
-				break;
-
-			_mid = _lower + ((_upper-_lower) >> 1);
-			if ( (*p) < *_mid )
-				_upper = _mid - 1;
-			else if ( (*p) > *_mid )
-				_lower = _mid + 1;
-			else {
-				_trans += (unsigned int)(_mid - _keys);
-				goto _match;
-			}
-		}
-		_keys += _klen;
-		_trans += _klen;
-	}
-
-	_klen = _json_range_lengths[cs];
-	if ( _klen > 0 ) {
-		const char *_lower = _keys;
-		const char *_mid;
-		const char *_upper = _keys + (_klen<<1) - 2;
-		while (1) {
-			if ( _upper < _lower )
-				break;
-
-			_mid = _lower + (((_upper-_lower) >> 1) & ~1);
-			if ( (*p) < _mid[0] )
-				_upper = _mid - 2;
-			else if ( (*p) > _mid[1] )
-				_lower = _mid + 2;
-			else {
-				_trans += (unsigned int)((_mid - _keys)>>1);
-				goto _match;
-			}
-		}
-		_trans += _klen;
-	}
-
-_match:
-	_trans = _json_indicies[_trans];
-	cs = _json_trans_targs[_trans];
-
-	if ( _json_trans_actions[_trans] == 0 )
-		goto _again;
-
-	_acts = _json_actions + _json_trans_actions[_trans];
-	_nacts = (unsigned int) *_acts++;
-	while ( _nacts-- > 0 )
-	{
-		switch ( *_acts++ )
-		{
-	case 1:
-// #line 2588 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 2:
-// #line 2590 "upb/json/parser.rl"
-	{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
-	break;
-	case 3:
-// #line 2594 "upb/json/parser.rl"
-	{ start_text(parser, p); }
-	break;
-	case 4:
-// #line 2595 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_text(parser, p)); }
-	break;
-	case 5:
-// #line 2601 "upb/json/parser.rl"
-	{ start_hex(parser); }
-	break;
-	case 6:
-// #line 2602 "upb/json/parser.rl"
-	{ hexdigit(parser, p); }
-	break;
-	case 7:
-// #line 2603 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_hex(parser)); }
-	break;
-	case 8:
-// #line 2609 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(escape(parser, p)); }
-	break;
-	case 9:
-// #line 2615 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 10:
-// #line 2620 "upb/json/parser.rl"
-	{ start_year(parser, p); }
-	break;
-	case 11:
-// #line 2621 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_year(parser, p)); }
-	break;
-	case 12:
-// #line 2625 "upb/json/parser.rl"
-	{ start_month(parser, p); }
-	break;
-	case 13:
-// #line 2626 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_month(parser, p)); }
-	break;
-	case 14:
-// #line 2630 "upb/json/parser.rl"
-	{ start_day(parser, p); }
-	break;
-	case 15:
-// #line 2631 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_day(parser, p)); }
-	break;
-	case 16:
-// #line 2635 "upb/json/parser.rl"
-	{ start_hour(parser, p); }
-	break;
-	case 17:
-// #line 2636 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_hour(parser, p)); }
-	break;
-	case 18:
-// #line 2640 "upb/json/parser.rl"
-	{ start_minute(parser, p); }
-	break;
-	case 19:
-// #line 2641 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_minute(parser, p)); }
-	break;
-	case 20:
-// #line 2645 "upb/json/parser.rl"
-	{ start_second(parser, p); }
-	break;
-	case 21:
-// #line 2646 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_second(parser, p)); }
-	break;
-	case 22:
-// #line 2651 "upb/json/parser.rl"
-	{ start_duration_base(parser, p); }
-	break;
-	case 23:
-// #line 2652 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
-	break;
-	case 24:
-// #line 2654 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 25:
-// #line 2659 "upb/json/parser.rl"
-	{ start_timestamp_base(parser); }
-	break;
-	case 26:
-// #line 2661 "upb/json/parser.rl"
-	{ start_timestamp_fraction(parser, p); }
-	break;
-	case 27:
-// #line 2662 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
-	break;
-	case 28:
-// #line 2664 "upb/json/parser.rl"
-	{ start_timestamp_zone(parser, p); }
-	break;
-	case 29:
-// #line 2665 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
-	break;
-	case 30:
-// #line 2667 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 31:
-// #line 2672 "upb/json/parser.rl"
-	{ start_fieldmask_path_text(parser, p); }
-	break;
-	case 32:
-// #line 2673 "upb/json/parser.rl"
-	{ end_fieldmask_path_text(parser, p); }
-	break;
-	case 33:
-// #line 2678 "upb/json/parser.rl"
-	{ start_fieldmask_path(parser); }
-	break;
-	case 34:
-// #line 2679 "upb/json/parser.rl"
-	{ end_fieldmask_path(parser); }
-	break;
-	case 35:
-// #line 2685 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 36:
-// #line 2690 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
-          {stack[top++] = cs; cs = 47;goto _again;}
-        } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_DURATION)) {
-          {stack[top++] = cs; cs = 40;goto _again;}
-        } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_FIELDMASK)) {
-          {stack[top++] = cs; cs = 75;goto _again;}
-        } else {
-          {stack[top++] = cs; cs = 32;goto _again;}
-        }
-      }
-	break;
-	case 37:
-// #line 2703 "upb/json/parser.rl"
-	{ p--; {stack[top++] = cs; cs = 78;goto _again;} }
-	break;
-	case 38:
-// #line 2708 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          start_any_member(parser, p);
-        } else {
-          start_member(parser);
-        }
-      }
-	break;
-	case 39:
-// #line 2715 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_membername(parser)); }
-	break;
-	case 40:
-// #line 2718 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          end_any_member(parser, p);
-        } else {
-          end_member(parser);
-        }
-      }
-	break;
-	case 41:
-// #line 2729 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          start_any_object(parser, p);
-        } else {
-          start_object(parser);
-        }
-      }
-	break;
-	case 42:
-// #line 2738 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          CHECK_RETURN_TOP(end_any_object(parser, p));
-        } else {
-          end_object(parser);
-        }
-      }
-	break;
-	case 43:
-// #line 2750 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_array(parser)); }
-	break;
-	case 44:
-// #line 2754 "upb/json/parser.rl"
-	{ end_array(parser); }
-	break;
-	case 45:
-// #line 2759 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_number(parser, p)); }
-	break;
-	case 46:
-// #line 2760 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_number(parser, p)); }
-	break;
-	case 47:
-// #line 2762 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_stringval(parser)); }
-	break;
-	case 48:
-// #line 2763 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_stringval(parser)); }
-	break;
-	case 49:
-// #line 2765 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
-	break;
-	case 50:
-// #line 2767 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
-	break;
-	case 51:
-// #line 2769 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_null(parser)); }
-	break;
-	case 52:
-// #line 2771 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
-	break;
-	case 53:
-// #line 2772 "upb/json/parser.rl"
-	{ end_subobject_full(parser); }
-	break;
-	case 54:
-// #line 2777 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-// #line 3185 "upb/json/parser.c"
-		}
-	}
-
-_again:
-	if ( cs == 0 )
-		goto _out;
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	const char *__acts = _json_actions + _json_eof_actions[cs];
-	unsigned int __nacts = (unsigned int) *__acts++;
-	while ( __nacts-- > 0 ) {
-		switch ( *__acts++ ) {
-	case 0:
-// #line 2586 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; 	if ( p == pe )
-		goto _test_eof;
-goto _again;} }
-	break;
-	case 46:
-// #line 2760 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_number(parser, p)); }
-	break;
-	case 49:
-// #line 2765 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
-	break;
-	case 50:
-// #line 2767 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
-	break;
-	case 51:
-// #line 2769 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_null(parser)); }
-	break;
-	case 53:
-// #line 2772 "upb/json/parser.rl"
-	{ end_subobject_full(parser); }
-	break;
-// #line 3227 "upb/json/parser.c"
-		}
-	}
-	}
-
-	_out: {}
-	}
-
-// #line 2805 "upb/json/parser.rl"
-
-  if (p != pe) {
-    upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
-  } else {
-    capture_suspend(parser, &p);
-  }
-
-error:
-  /* Save parsing state back to parser. */
-  parser->current_state = cs;
-  parser->parser_top = top;
-
-  return p - buf;
-}
-
-static bool end(void *closure, const void *hd) {
-  upb_json_parser *parser = closure;
-
-  /* Prevent compile warning on unused static constants. */
-  UPB_UNUSED(json_start);
-  UPB_UNUSED(json_en_duration_machine);
-  UPB_UNUSED(json_en_fieldmask_machine);
-  UPB_UNUSED(json_en_number_machine);
-  UPB_UNUSED(json_en_string_machine);
-  UPB_UNUSED(json_en_timestamp_machine);
-  UPB_UNUSED(json_en_value_machine);
-  UPB_UNUSED(json_en_main);
-
-  parse(parser, hd, &eof_ch, 0, NULL);
-
-  return parser->current_state >= 106;
-}
-
-static void json_parser_reset(upb_json_parser *p) {
-  int cs;
-  int top;
-
-  p->top = p->stack;
-  init_frame(p->top);
-
-  /* Emit Ragel initialization of the parser. */
-  
-// #line 3278 "upb/json/parser.c"
-	{
-	cs = json_start;
-	top = 0;
-	}
-
-// #line 2847 "upb/json/parser.rl"
-  p->current_state = cs;
-  p->parser_top = top;
-  accumulate_clear(p);
-  p->multipart_state = MULTIPART_INACTIVE;
-  p->capture = NULL;
-  p->accumulated = NULL;
-}
-
-static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
-                                               const upb_msgdef *md) {
-  upb_msg_field_iter i;
-  upb_alloc *alloc = upb_arena_alloc(c->arena);
-
-  upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
-
-  m->cache = c;
-
-  upb_byteshandler_init(&m->input_handler_);
-  upb_byteshandler_setstring(&m->input_handler_, parse, m);
-  upb_byteshandler_setendstr(&m->input_handler_, end, m);
-
-  upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc);
-
-  /* Build name_table */
-
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_value v = upb_value_constptr(f);
-    char *buf;
-
-    /* Add an entry for the JSON name. */
-    size_t len = upb_fielddef_getjsonname(f, NULL, 0);
-    buf = upb_malloc(alloc, len);
-    upb_fielddef_getjsonname(f, buf, len);
-    upb_strtable_insert3(&m->name_table, buf, strlen(buf), v, alloc);
-
-    if (strcmp(buf, upb_fielddef_name(f)) != 0) {
-      /* Since the JSON name is different from the regular field name, add an
-       * entry for the raw name (compliant proto3 JSON parsers must accept
-       * both). */
-      const char *name = upb_fielddef_name(f);
-      upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
-    }
-  }
-
-  return m;
-}
-
-/* Public API *****************************************************************/
-
-upb_json_parser *upb_json_parser_create(upb_arena *arena,
-                                        const upb_json_parsermethod *method,
-                                        const upb_symtab* symtab,
-                                        upb_sink output,
-                                        upb_status *status,
-                                        bool ignore_json_unknown) {
-#ifndef NDEBUG
-  const size_t size_before = upb_arena_bytesallocated(arena);
-#endif
-  upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
-  if (!p) return false;
-
-  p->arena = arena;
-  p->method = method;
-  p->status = status;
-  p->limit = p->stack + UPB_JSON_MAX_DEPTH;
-  p->accumulate_buf = NULL;
-  p->accumulate_buf_size = 0;
-  upb_bytessink_reset(&p->input_, &method->input_handler_, p);
-
-  json_parser_reset(p);
-  p->top->sink = output;
-  p->top->m = upb_handlers_msgdef(output.handlers);
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
-    p->top->is_any = true;
-    p->top->any_frame = json_parser_any_frame_new(p);
-  } else {
-    p->top->is_any = false;
-    p->top->any_frame = NULL;
-  }
-  set_name_table(p, p->top);
-  p->symtab = symtab;
-
-  p->ignore_json_unknown = ignore_json_unknown;
-
-  /* If this fails, uncomment and increase the value in parser.h. */
-  /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
-                      UPB_JSON_PARSER_SIZE);
-  return p;
-}
-
-upb_bytessink upb_json_parser_input(upb_json_parser *p) {
-  return p->input_;
-}
-
-const upb_byteshandler *upb_json_parsermethod_inputhandler(
-    const upb_json_parsermethod *m) {
-  return &m->input_handler_;
-}
-
-upb_json_codecache *upb_json_codecache_new(void) {
-  upb_alloc *alloc;
-  upb_json_codecache *c;
-
-  c = upb_gmalloc(sizeof(*c));
-
-  c->arena = upb_arena_new();
-  alloc = upb_arena_alloc(c->arena);
-
-  upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
-
-  return c;
-}
-
-void upb_json_codecache_free(upb_json_codecache *c) {
-  upb_arena_free(c->arena);
-  upb_gfree(c);
-}
-
-const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
-                                                    const upb_msgdef *md) {
-  upb_json_parsermethod *m;
-  upb_value v;
-  upb_msg_field_iter i;
-  upb_alloc *alloc = upb_arena_alloc(c->arena);
-
-  if (upb_inttable_lookupptr(&c->methods, md, &v)) {
-    return upb_value_getconstptr(v);
-  }
-
-  m = parsermethod_new(c, md);
-  v = upb_value_constptr(m);
-
-  if (!m) return NULL;
-  if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL;
-
-  /* Populate parser methods for all submessages, so the name tables will
-   * be available during parsing. */
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
-      const upb_json_parsermethod *sub_method =
-          upb_json_codecache_get(c, subdef);
-
-      if (!sub_method) return NULL;
-    }
-  }
-
-  return m;
-}
-/*
-** This currently uses snprintf() to format primitives, and could be optimized
-** further.
-*/
-
-
-#include <ctype.h>
-#include <stdint.h>
-#include <string.h>
-#include <time.h>
-
-
-struct upb_json_printer {
-  upb_sink input_;
-  /* BytesSink closure. */
-  void *subc_;
-  upb_bytessink output_;
-
-  /* We track the depth so that we know when to emit startstr/endstr on the
-   * output. */
-  int depth_;
-
-  /* Have we emitted the first element? This state is necessary to emit commas
-   * without leaving a trailing comma in arrays/maps. We keep this state per
-   * frame depth.
-   *
-   * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
-   * We count frames (contexts in which we separate elements by commas) as both
-   * repeated fields and messages (maps), and the worst case is a
-   * message->repeated field->submessage->repeated field->... nesting. */
-  bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
-
-  /* To print timestamp, printer needs to cache its seconds and nanos values
-   * and convert them when ending timestamp message. See comments of
-   * printer_sethandlers_timestamp for more detail. */
-  int64_t seconds;
-  int32_t nanos;
-};
-
-/* StringPiece; a pointer plus a length. */
-typedef struct {
-  char *ptr;
-  size_t len;
-} strpc;
-
-void freestrpc(void *ptr) {
-  strpc *pc = ptr;
-  upb_gfree(pc->ptr);
-  upb_gfree(pc);
-}
-
-typedef struct {
-  bool preserve_fieldnames;
-} upb_json_printercache;
-
-/* Convert fielddef name to JSON name and return as a string piece. */
-strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
-                bool preserve_fieldnames) {
-  /* TODO(haberman): handle malloc failure. */
-  strpc *ret = upb_gmalloc(sizeof(*ret));
-  if (preserve_fieldnames) {
-    ret->ptr = upb_gstrdup(upb_fielddef_name(f));
-    ret->len = strlen(ret->ptr);
-  } else {
-    size_t len;
-    ret->len = upb_fielddef_getjsonname(f, NULL, 0);
-    ret->ptr = upb_gmalloc(ret->len);
-    len = upb_fielddef_getjsonname(f, ret->ptr, ret->len);
-    UPB_ASSERT(len == ret->len);
-    ret->len--;  /* NULL */
-  }
-
-  upb_handlers_addcleanup(h, ret, freestrpc);
-  return ret;
-}
-
-/* Convert a null-terminated const char* to a string piece. */
-strpc *newstrpc_str(upb_handlers *h, const char * str) {
-  strpc * ret = upb_gmalloc(sizeof(*ret));
-  ret->ptr = upb_gstrdup(str);
-  ret->len = strlen(str);
-  upb_handlers_addcleanup(h, ret, freestrpc);
-  return ret;
-}
-
-/* ------------ JSON string printing: values, maps, arrays ------------------ */
-
-static void print_data(
-    upb_json_printer *p, const char *buf, unsigned int len) {
-  /* TODO: Will need to change if we support pushback from the sink. */
-  size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
-  UPB_ASSERT(n == len);
-}
-
-static void print_comma(upb_json_printer *p) {
-  if (!p->first_elem_[p->depth_]) {
-    print_data(p, ",", 1);
-  }
-  p->first_elem_[p->depth_] = false;
-}
-
-/* Helpers that print properly formatted elements to the JSON output stream. */
-
-/* Used for escaping control chars in strings. */
-static const char kControlCharLimit = 0x20;
-
-UPB_INLINE bool is_json_escaped(char c) {
-  /* See RFC 4627. */
-  unsigned char uc = (unsigned char)c;
-  return uc < kControlCharLimit || uc == '"' || uc == '\\';
-}
-
-UPB_INLINE const char* json_nice_escape(char c) {
-  switch (c) {
-    case '"':  return "\\\"";
-    case '\\': return "\\\\";
-    case '\b': return "\\b";
-    case '\f': return "\\f";
-    case '\n': return "\\n";
-    case '\r': return "\\r";
-    case '\t': return "\\t";
-    default:   return NULL;
-  }
-}
-
-/* Write a properly escaped string chunk. The surrounding quotes are *not*
- * printed; this is so that the caller has the option of emitting the string
- * content in chunks. */
-static void putstring(upb_json_printer *p, const char *buf, unsigned int len) {
-  const char* unescaped_run = NULL;
-  unsigned int i;
-  for (i = 0; i < len; i++) {
-    char c = buf[i];
-    /* Handle escaping. */
-    if (is_json_escaped(c)) {
-      /* Use a "nice" escape, like \n, if one exists for this character. */
-      const char* escape = json_nice_escape(c);
-      /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
-       * escape. */
-      char escape_buf[8];
-      if (!escape) {
-        unsigned char byte = (unsigned char)c;
-        _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
-        escape = escape_buf;
-      }
-
-      /* N.B. that we assume that the input encoding is equal to the output
-       * encoding (both UTF-8 for  now), so for chars >= 0x20 and != \, ", we
-       * can simply pass the bytes through. */
-
-      /* If there's a current run of unescaped chars, print that run first. */
-      if (unescaped_run) {
-        print_data(p, unescaped_run, &buf[i] - unescaped_run);
-        unescaped_run = NULL;
-      }
-      /* Then print the escape code. */
-      print_data(p, escape, strlen(escape));
-    } else {
-      /* Add to the current unescaped run of characters. */
-      if (unescaped_run == NULL) {
-        unescaped_run = &buf[i];
-      }
-    }
-  }
-
-  /* If the string ended in a run of unescaped characters, print that last run. */
-  if (unescaped_run) {
-    print_data(p, unescaped_run, &buf[len] - unescaped_run);
-  }
-}
-
-#define CHKLENGTH(x) if (!(x)) return -1;
-
-/* Helpers that format floating point values according to our custom formats.
- * Right now we use %.8g and %.17g for float/double, respectively, to match
- * proto2::util::JsonFormat's defaults.  May want to change this later. */
-
-const char neginf[] = "\"-Infinity\"";
-const char inf[] = "\"Infinity\"";
-
-static size_t fmt_double(double val, char* buf, size_t length) {
-  if (val == UPB_INFINITY) {
-    CHKLENGTH(length >= strlen(inf));
-    strcpy(buf, inf);
-    return strlen(inf);
-  } else if (val == -UPB_INFINITY) {
-    CHKLENGTH(length >= strlen(neginf));
-    strcpy(buf, neginf);
-    return strlen(neginf);
-  } else {
-    size_t n = _upb_snprintf(buf, length, "%.17g", val);
-    CHKLENGTH(n > 0 && n < length);
-    return n;
-  }
-}
-
-static size_t fmt_float(float val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%.8g", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_bool(bool val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_int64_as_number(long long val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%lld", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_uint64_as_number(
-    unsigned long long val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%llu", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_int64_as_string(long long val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "\"%lld\"", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_uint64_as_string(
-    unsigned long long val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "\"%llu\"", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-/* Print a map key given a field name. Called by scalar field handlers and by
- * startseq for repeated fields. */
-static bool putkey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  const strpc *key = handler_data;
-  print_comma(p);
-  print_data(p, "\"", 1);
-  putstring(p, key->ptr, key->len);
-  print_data(p, "\":", 2);
-  return true;
-}
-
-#define CHKFMT(val) if ((val) == (size_t)-1) return false;
-#define CHK(val)    if (!(val)) return false;
-
-#define TYPE_HANDLERS(type, fmt_func)                                        \
-  static bool put##type(void *closure, const void *handler_data, type val) { \
-    upb_json_printer *p = closure;                                           \
-    char data[64];                                                           \
-    size_t length = fmt_func(val, data, sizeof(data));                       \
-    UPB_UNUSED(handler_data);                                                \
-    CHKFMT(length);                                                          \
-    print_data(p, data, length);                                             \
-    return true;                                                             \
-  }                                                                          \
-  static bool scalar_##type(void *closure, const void *handler_data,         \
-                            type val) {                                      \
-    CHK(putkey(closure, handler_data));                                      \
-    CHK(put##type(closure, handler_data, val));                              \
-    return true;                                                             \
-  }                                                                          \
-  static bool repeated_##type(void *closure, const void *handler_data,       \
-                              type val) {                                    \
-    upb_json_printer *p = closure;                                           \
-    print_comma(p);                                                          \
-    CHK(put##type(closure, handler_data, val));                              \
-    return true;                                                             \
-  }
-
-#define TYPE_HANDLERS_MAPKEY(type, fmt_func)                                 \
-  static bool putmapkey_##type(void *closure, const void *handler_data,      \
-                            type val) {                                      \
-    upb_json_printer *p = closure;                                           \
-    char data[64];                                                           \
-    size_t length = fmt_func(val, data, sizeof(data));                       \
-    UPB_UNUSED(handler_data);                                                \
-    print_data(p, "\"", 1);                                                  \
-    print_data(p, data, length);                                             \
-    print_data(p, "\":", 2);                                                 \
-    return true;                                                             \
-  }
-
-TYPE_HANDLERS(double,   fmt_double)
-TYPE_HANDLERS(float,    fmt_float)
-TYPE_HANDLERS(bool,     fmt_bool)
-TYPE_HANDLERS(int32_t,  fmt_int64_as_number)
-TYPE_HANDLERS(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS(int64_t,  fmt_int64_as_string)
-TYPE_HANDLERS(uint64_t, fmt_uint64_as_string)
-
-/* double and float are not allowed to be map keys. */
-TYPE_HANDLERS_MAPKEY(bool,     fmt_bool)
-TYPE_HANDLERS_MAPKEY(int32_t,  fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(int64_t,  fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64_as_number)
-
-#undef TYPE_HANDLERS
-#undef TYPE_HANDLERS_MAPKEY
-
-typedef struct {
-  void *keyname;
-  const upb_enumdef *enumdef;
-} EnumHandlerData;
-
-static bool scalar_enum(void *closure, const void *handler_data,
-                        int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-  const char *symbolic_name;
-
-  CHK(putkey(closure, hd->keyname));
-
-  symbolic_name = upb_enumdef_iton(hd->enumdef, val);
-  if (symbolic_name) {
-    print_data(p, "\"", 1);
-    putstring(p, symbolic_name, strlen(symbolic_name));
-    print_data(p, "\"", 1);
-  } else {
-    putint32_t(closure, NULL, val);
-  }
-
-  return true;
-}
-
-static void print_enum_symbolic_name(upb_json_printer *p,
-                                     const upb_enumdef *def,
-                                     int32_t val) {
-  const char *symbolic_name = upb_enumdef_iton(def, val);
-  if (symbolic_name) {
-    print_data(p, "\"", 1);
-    putstring(p, symbolic_name, strlen(symbolic_name));
-    print_data(p, "\"", 1);
-  } else {
-    putint32_t(p, NULL, val);
-  }
-}
-
-static bool repeated_enum(void *closure, const void *handler_data,
-                          int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-  print_comma(p);
-
-  print_enum_symbolic_name(p, hd->enumdef, val);
-
-  return true;
-}
-
-static bool mapvalue_enum(void *closure, const void *handler_data,
-                          int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-
-  print_enum_symbolic_name(p, hd->enumdef, val);
-
-  return true;
-}
-
-static void *scalar_startsubmsg(void *closure, const void *handler_data) {
-  return putkey(closure, handler_data) ? closure : UPB_BREAK;
-}
-
-static void *repeated_startsubmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_comma(p);
-  return closure;
-}
-
-static void start_frame(upb_json_printer *p) {
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-}
-
-static void end_frame(upb_json_printer *p) {
-  print_data(p, "}", 1);
-  p->depth_--;
-}
-
-static bool printer_startmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  start_frame(p);
-  return true;
-}
-
-static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  end_frame(p);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static void *startseq(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  CHK(putkey(closure, handler_data));
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "[", 1);
-  return closure;
-}
-
-static bool endseq(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "]", 1);
-  p->depth_--;
-  return true;
-}
-
-static void *startmap(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  CHK(putkey(closure, handler_data));
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-  return closure;
-}
-
-static bool endmap(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "}", 1);
-  p->depth_--;
-  return true;
-}
-
-static size_t putstr(void *closure, const void *handler_data, const char *str,
-                     size_t len, const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-  putstring(p, str, len);
-  return len;
-}
-
-/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
-static size_t putbytes(void *closure, const void *handler_data, const char *str,
-                       size_t len, const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-
-  /* This is the regular base64, not the "web-safe" version. */
-  static const char base64[] =
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-  /* Base64-encode. */
-  char data[16000];
-  const char *limit = data + sizeof(data);
-  const unsigned char *from = (const unsigned char*)str;
-  char *to = data;
-  size_t remaining = len;
-  size_t bytes;
-
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-
-  print_data(p, "\"", 1);
-
-  while (remaining > 2) {
-    if (limit - to < 4) {
-      bytes = to - data;
-      putstring(p, data, bytes);
-      to = data;
-    }
-
-    to[0] = base64[from[0] >> 2];
-    to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
-    to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
-    to[3] = base64[from[2] & 0x3f];
-
-    remaining -= 3;
-    to += 4;
-    from += 3;
-  }
-
-  switch (remaining) {
-    case 2:
-      to[0] = base64[from[0] >> 2];
-      to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
-      to[2] = base64[(from[1] & 0xf) << 2];
-      to[3] = '=';
-      to += 4;
-      from += 2;
-      break;
-    case 1:
-      to[0] = base64[from[0] >> 2];
-      to[1] = base64[((from[0] & 0x3) << 4)];
-      to[2] = '=';
-      to[3] = '=';
-      to += 4;
-      from += 1;
-      break;
-  }
-
-  bytes = to - data;
-  putstring(p, data, bytes);
-  print_data(p, "\"", 1);
-  return len;
-}
-
-static void *scalar_startstr(void *closure, const void *handler_data,
-                             size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  CHK(putkey(closure, handler_data));
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t scalar_str(void *closure, const void *handler_data,
-                         const char *str, size_t len,
-                         const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool scalar_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static void *repeated_startstr(void *closure, const void *handler_data,
-                               size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_comma(p);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t repeated_str(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool repeated_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static void *mapkeyval_startstr(void *closure, const void *handler_data,
-                                size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t mapkey_str(void *closure, const void *handler_data,
-                         const char *str, size_t len,
-                         const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool mapkey_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\":", 2);
-  return true;
-}
-
-static bool mapvalue_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static size_t scalar_bytes(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  CHK(putkey(closure, handler_data));
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static size_t repeated_bytes(void *closure, const void *handler_data,
-                             const char *str, size_t len,
-                             const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  print_comma(p);
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static size_t mapkey_bytes(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  print_data(p, ":", 1);
-  return len;
-}
-
-static void set_enum_hd(upb_handlers *h,
-                        const upb_fielddef *f,
-                        bool preserve_fieldnames,
-                        upb_handlerattr *attr) {
-  EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
-  hd->enumdef = upb_fielddef_enumsubdef(f);
-  hd->keyname = newstrpc(h, f, preserve_fieldnames);
-  upb_handlers_addcleanup(h, hd, upb_gfree);
-  attr->handler_data = hd;
-}
-
-/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
- * in a map).
- *
- * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
- * key or value cases properly. The right way to do this is to allocate a
- * temporary structure at the start of a mapentry submessage, store key and
- * value data in it as key and value handlers are called, and then print the
- * key/value pair once at the end of the submessage. If we don't do this, we
- * should at least detect the case and throw an error. However, so far all of
- * our sources that emit mapentry messages do so canonically (with one key
- * field, and then one value field), so this is not a pressing concern at the
- * moment. */
-void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
-                                  upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  /* A mapentry message is printed simply as '"key": value'. Rather than
-   * special-case key and value for every type below, we just handle both
-   * fields explicitly here. */
-  const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
-  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  UPB_UNUSED(closure);
-
-  switch (upb_fielddef_type(key_field)) {
-    case UPB_TYPE_INT32:
-      upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
-      break;
-    case UPB_TYPE_INT64:
-      upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT32:
-      upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT64:
-      upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_BOOL:
-      upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
-      break;
-    case UPB_TYPE_STRING:
-      upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
-      upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
-      upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
-      break;
-    case UPB_TYPE_BYTES:
-      upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
-      break;
-    default:
-      UPB_ASSERT(false);
-      break;
-  }
-
-  switch (upb_fielddef_type(value_field)) {
-    case UPB_TYPE_INT32:
-      upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_INT64:
-      upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT32:
-      upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT64:
-      upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_BOOL:
-      upb_handlers_setbool(h, value_field, putbool, &empty_attr);
-      break;
-    case UPB_TYPE_FLOAT:
-      upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
-      break;
-    case UPB_TYPE_DOUBLE:
-      upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
-      break;
-    case UPB_TYPE_STRING:
-      upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
-      upb_handlers_setstring(h, value_field, putstr, &empty_attr);
-      upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
-      break;
-    case UPB_TYPE_BYTES:
-      upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
-      break;
-    case UPB_TYPE_ENUM: {
-      upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
-      set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
-      upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE:
-      /* No handler necessary -- the submsg handlers will print the message
-       * as appropriate. */
-      break;
-  }
-}
-
-static bool putseconds(void *closure, const void *handler_data,
-                       int64_t seconds) {
-  upb_json_printer *p = closure;
-  p->seconds = seconds;
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static bool putnanos(void *closure, const void *handler_data,
-                     int32_t nanos) {
-  upb_json_printer *p = closure;
-  p->nanos = nanos;
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static void *scalar_startstr_nokey(void *closure, const void *handler_data,
-                                   size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t putstr_nokey(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-  print_data(p, "\"", 1);
-  putstring(p, str, len);
-  print_data(p, "\"", 1);
-  return len + 2;
-}
-
-static void *startseq_nokey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "[", 1);
-  return closure;
-}
-
-static void *startseq_fieldmask(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  return closure;
-}
-
-static bool endseq_fieldmask(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_--;
-  return true;
-}
-
-static void *repeated_startstr_fieldmask(
-    void *closure, const void *handler_data,
-    size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_comma(p);
-  return p;
-}
-
-static size_t repeated_str_fieldmask(
-    void *closure, const void *handler_data,
-    const char *str, size_t len,
-    const upb_bufhandle *handle) {
-  const char* limit = str + len;
-  bool upper = false;
-  size_t result_len = 0;
-  for (; str < limit; str++) {
-    if (*str == '_') {
-      upper = true;
-      continue;
-    }
-    if (upper && *str >= 'a' && *str <= 'z') {
-      char upper_char = toupper(*str);
-      CHK(putstr(closure, handler_data, &upper_char, 1, handle));
-    } else {
-      CHK(putstr(closure, handler_data, str, 1, handle));
-    }
-    upper = false;
-    result_len++;
-  }
-  return result_len;
-}
-
-static void *startmap_nokey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-  return closure;
-}
-
-static bool putnull(void *closure, const void *handler_data,
-                    int32_t null) {
-  upb_json_printer *p = closure;
-  print_data(p, "null", 4);
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(null);
-  return true;
-}
-
-static bool printer_startdurationmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-#define UPB_DURATION_MAX_JSON_LEN 23
-#define UPB_DURATION_MAX_NANO_LEN 9
-
-static bool printer_enddurationmsg(void *closure, const void *handler_data,
-                                   upb_status *s) {
-  upb_json_printer *p = closure;
-  char buffer[UPB_DURATION_MAX_JSON_LEN];
-  size_t base_len;
-  size_t curr;
-  size_t i;
-
-  memset(buffer, 0, UPB_DURATION_MAX_JSON_LEN);
-
-  if (p->seconds < -315576000000) {
-    upb_status_seterrf(s, "error parsing duration: "
-                          "minimum acceptable value is "
-                          "-315576000000");
-    return false;
-  }
-
-  if (p->seconds > 315576000000) {
-    upb_status_seterrf(s, "error serializing duration: "
-                          "maximum acceptable value is "
-                          "315576000000");
-    return false;
-  }
-
-  _upb_snprintf(buffer, sizeof(buffer), "%ld", (long)p->seconds);
-  base_len = strlen(buffer);
-
-  if (p->nanos != 0) {
-    char nanos_buffer[UPB_DURATION_MAX_NANO_LEN + 3];
-    _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
-                  p->nanos / 1000000000.0);
-    /* Remove trailing 0. */
-    for (i = UPB_DURATION_MAX_NANO_LEN + 2;
-         nanos_buffer[i] == '0'; i--) {
-      nanos_buffer[i] = 0;
-    }
-    strcpy(buffer + base_len, nanos_buffer + 1);
-  }
-
-  curr = strlen(buffer);
-  strcpy(buffer + curr, "s");
-
-  p->seconds = 0;
-  p->nanos = 0;
-
-  print_data(p, "\"", 1);
-  print_data(p, buffer, strlen(buffer));
-  print_data(p, "\"", 1);
-
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static bool printer_starttimestampmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-#define UPB_TIMESTAMP_MAX_JSON_LEN 31
-#define UPB_TIMESTAMP_BEFORE_NANO_LEN 19
-#define UPB_TIMESTAMP_MAX_NANO_LEN 9
-
-static bool printer_endtimestampmsg(void *closure, const void *handler_data,
-                                    upb_status *s) {
-  upb_json_printer *p = closure;
-  char buffer[UPB_TIMESTAMP_MAX_JSON_LEN];
-  time_t time = p->seconds;
-  size_t curr;
-  size_t i;
-  size_t year_length =
-      strftime(buffer, UPB_TIMESTAMP_MAX_JSON_LEN, "%Y", gmtime(&time));
-
-  if (p->seconds < -62135596800) {
-    upb_status_seterrf(s, "error parsing timestamp: "
-                          "minimum acceptable value is "
-                          "0001-01-01T00:00:00Z");
-    return false;
-  }
-
-  if (p->seconds > 253402300799) {
-    upb_status_seterrf(s, "error parsing timestamp: "
-                          "maximum acceptable value is "
-                          "9999-12-31T23:59:59Z");
-    return false;
-  }
-
-  /* strftime doesn't guarantee 4 digits for year. Prepend 0 by ourselves. */
-  for (i = 0; i < 4 - year_length; i++) {
-    buffer[i] = '0';
-  }
-
-  strftime(buffer + (4 - year_length), UPB_TIMESTAMP_MAX_JSON_LEN,
-           "%Y-%m-%dT%H:%M:%S", gmtime(&time));
-  if (p->nanos != 0) {
-    char nanos_buffer[UPB_TIMESTAMP_MAX_NANO_LEN + 3];
-    _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
-                  p->nanos / 1000000000.0);
-    /* Remove trailing 0. */
-    for (i = UPB_TIMESTAMP_MAX_NANO_LEN + 2;
-         nanos_buffer[i] == '0'; i--) {
-      nanos_buffer[i] = 0;
-    }
-    strcpy(buffer + UPB_TIMESTAMP_BEFORE_NANO_LEN, nanos_buffer + 1);
-  }
-
-  curr = strlen(buffer);
-  strcpy(buffer + curr, "Z");
-
-  p->seconds = 0;
-  p->nanos = 0;
-
-  print_data(p, "\"", 1);
-  print_data(p, buffer, strlen(buffer));
-  print_data(p, "\"", 1);
-
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  return true;
-}
-
-static bool printer_startmsg_noframe(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-static bool printer_endmsg_noframe(
-    void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static bool printer_startmsg_fieldmask(
-    void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static bool printer_endmsg_fieldmask(
-    void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  print_data(p, "\"", 1);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static void *scalar_startstr_onlykey(
-    void *closure, const void *handler_data, size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(size_hint);
-  CHK(putkey(closure, handler_data));
-  return p;
-}
-
-/* Set up handlers for an Any submessage. */
-void printer_sethandlers_any(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* type_field = upb_msgdef_itof(md, UPB_ANY_TYPE);
-  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_ANY_VALUE);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  /* type_url's json name is "@type" */
-  upb_handlerattr type_name_attr = UPB_HANDLERATTR_INIT;
-  upb_handlerattr value_name_attr = UPB_HANDLERATTR_INIT;
-  strpc *type_url_json_name = newstrpc_str(h, "@type");
-  strpc *value_json_name = newstrpc_str(h, "value");
-
-  type_name_attr.handler_data = type_url_json_name;
-  value_name_attr.handler_data = value_json_name;
-
-  /* Set up handlers. */
-  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
-  upb_handlers_setstartstr(h, type_field, scalar_startstr, &type_name_attr);
-  upb_handlers_setstring(h, type_field, scalar_str, &empty_attr);
-  upb_handlers_setendstr(h, type_field, scalar_endstr, &empty_attr);
-
-  /* This is not the full and correct JSON encoding for the Any value field. It
-   * requires further processing by the wrapper code based on the type URL.
-   */
-  upb_handlers_setstartstr(h, value_field, scalar_startstr_onlykey,
-                           &value_name_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a fieldmask submessage. */
-void printer_sethandlers_fieldmask(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startseq_fieldmask, &empty_attr);
-  upb_handlers_setendseq(h, f, endseq_fieldmask, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_fieldmask, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_fieldmask, &empty_attr);
-
-  upb_handlers_setstartstr(h, f, repeated_startstr_fieldmask, &empty_attr);
-  upb_handlers_setstring(h, f, repeated_str_fieldmask, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a duration submessage. */
-void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* seconds_field =
-      upb_msgdef_itof(md, UPB_DURATION_SECONDS);
-  const upb_fielddef* nanos_field =
-      upb_msgdef_itof(md, UPB_DURATION_NANOS);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr);
-  upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
-  upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
-  upb_handlers_setendmsg(h, printer_enddurationmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a timestamp submessage. Instead of printing fields
- * separately, the json representation of timestamp follows RFC 3339 */
-void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* seconds_field =
-      upb_msgdef_itof(md, UPB_TIMESTAMP_SECONDS);
-  const upb_fielddef* nanos_field =
-      upb_msgdef_itof(md, UPB_TIMESTAMP_NANOS);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr);
-  upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
-  upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endtimestampmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_value(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  upb_msg_field_iter i;
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_msg_field_begin(&i, md);
-  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_ENUM:
-        upb_handlers_setint32(h, f, putnull, &empty_attr);
-        break;
-      case UPB_TYPE_DOUBLE:
-        upb_handlers_setdouble(h, f, putdouble, &empty_attr);
-        break;
-      case UPB_TYPE_STRING:
-        upb_handlers_setstartstr(h, f, scalar_startstr_nokey, &empty_attr);
-        upb_handlers_setstring(h, f, scalar_str, &empty_attr);
-        upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
-        break;
-      case UPB_TYPE_BOOL:
-        upb_handlers_setbool(h, f, putbool, &empty_attr);
-        break;
-      case UPB_TYPE_MESSAGE:
-        break;
-      default:
-        UPB_ASSERT(false);
-        break;
-    }
-  }
-
-  UPB_UNUSED(closure);
-}
-
-#define WRAPPER_SETHANDLERS(wrapper, type, putmethod)                      \
-void printer_sethandlers_##wrapper(const void *closure, upb_handlers *h) { \
-  const upb_msgdef *md = upb_handlers_msgdef(h);                           \
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);                          \
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;                \
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);      \
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);          \
-  upb_handlers_set##type(h, f, putmethod, &empty_attr);                    \
-  UPB_UNUSED(closure);                                                     \
-}
-
-WRAPPER_SETHANDLERS(doublevalue, double, putdouble)
-WRAPPER_SETHANDLERS(floatvalue,  float,  putfloat)
-WRAPPER_SETHANDLERS(int64value,  int64,  putint64_t)
-WRAPPER_SETHANDLERS(uint64value, uint64, putuint64_t)
-WRAPPER_SETHANDLERS(int32value,  int32,  putint32_t)
-WRAPPER_SETHANDLERS(uint32value, uint32, putuint32_t)
-WRAPPER_SETHANDLERS(boolvalue,   bool,   putbool)
-WRAPPER_SETHANDLERS(stringvalue, string, putstr_nokey)
-WRAPPER_SETHANDLERS(bytesvalue,  string, putbytes)
-
-#undef WRAPPER_SETHANDLERS
-
-void printer_sethandlers_listvalue(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startseq_nokey, &empty_attr);
-  upb_handlers_setendseq(h, f, endseq, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startmap_nokey, &empty_attr);
-  upb_handlers_setendseq(h, f, endmap, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  bool is_mapentry = upb_msgdef_mapentry(md);
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-  upb_msg_field_iter i;
-  const upb_json_printercache *cache = closure;
-  const bool preserve_fieldnames = cache->preserve_fieldnames;
-
-  if (is_mapentry) {
-    /* mapentry messages are sufficiently different that we handle them
-     * separately. */
-    printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
-    return;
-  }
-
-  switch (upb_msgdef_wellknowntype(md)) {
-    case UPB_WELLKNOWN_UNSPECIFIED:
-      break;
-    case UPB_WELLKNOWN_ANY:
-      printer_sethandlers_any(closure, h);
-      return;
-    case UPB_WELLKNOWN_FIELDMASK:
-      printer_sethandlers_fieldmask(closure, h);
-      return;
-    case UPB_WELLKNOWN_DURATION:
-      printer_sethandlers_duration(closure, h);
-      return;
-    case UPB_WELLKNOWN_TIMESTAMP:
-      printer_sethandlers_timestamp(closure, h);
-      return;
-    case UPB_WELLKNOWN_VALUE:
-      printer_sethandlers_value(closure, h);
-      return;
-    case UPB_WELLKNOWN_LISTVALUE:
-      printer_sethandlers_listvalue(closure, h);
-      return;
-    case UPB_WELLKNOWN_STRUCT:
-      printer_sethandlers_structvalue(closure, h);
-      return;
-#define WRAPPER(wellknowntype, name)        \
-  case wellknowntype:                       \
-    printer_sethandlers_##name(closure, h); \
-    return;                                 \
-
-    WRAPPER(UPB_WELLKNOWN_DOUBLEVALUE, doublevalue);
-    WRAPPER(UPB_WELLKNOWN_FLOATVALUE, floatvalue);
-    WRAPPER(UPB_WELLKNOWN_INT64VALUE, int64value);
-    WRAPPER(UPB_WELLKNOWN_UINT64VALUE, uint64value);
-    WRAPPER(UPB_WELLKNOWN_INT32VALUE, int32value);
-    WRAPPER(UPB_WELLKNOWN_UINT32VALUE, uint32value);
-    WRAPPER(UPB_WELLKNOWN_BOOLVALUE, boolvalue);
-    WRAPPER(UPB_WELLKNOWN_STRINGVALUE, stringvalue);
-    WRAPPER(UPB_WELLKNOWN_BYTESVALUE, bytesvalue);
-
-#undef WRAPPER
-  }
-
-  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
-#define TYPE(type, name, ctype)                                               \
-  case type:                                                                  \
-    if (upb_fielddef_isseq(f)) {                                              \
-      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr);            \
-    } else {                                                                  \
-      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);               \
-    }                                                                         \
-    break;
-
-  upb_msg_field_begin(&i, md);
-  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-
-    upb_handlerattr name_attr = UPB_HANDLERATTR_INIT;
-    name_attr.handler_data = newstrpc(h, f, preserve_fieldnames);
-
-    if (upb_fielddef_ismap(f)) {
-      upb_handlers_setstartseq(h, f, startmap, &name_attr);
-      upb_handlers_setendseq(h, f, endmap, &name_attr);
-    } else if (upb_fielddef_isseq(f)) {
-      upb_handlers_setstartseq(h, f, startseq, &name_attr);
-      upb_handlers_setendseq(h, f, endseq, &empty_attr);
-    }
-
-    switch (upb_fielddef_type(f)) {
-      TYPE(UPB_TYPE_FLOAT,  float,  float);
-      TYPE(UPB_TYPE_DOUBLE, double, double);
-      TYPE(UPB_TYPE_BOOL,   bool,   bool);
-      TYPE(UPB_TYPE_INT32,  int32,  int32_t);
-      TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
-      TYPE(UPB_TYPE_INT64,  int64,  int64_t);
-      TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
-      case UPB_TYPE_ENUM: {
-        /* For now, we always emit symbolic names for enums. We may want an
-         * option later to control this behavior, but we will wait for a real
-         * need first. */
-        upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
-        set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
-
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
-        } else {
-          upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
-        }
-
-        break;
-      }
-      case UPB_TYPE_STRING:
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
-          upb_handlers_setstring(h, f, repeated_str, &empty_attr);
-          upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
-        } else {
-          upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
-          upb_handlers_setstring(h, f, scalar_str, &empty_attr);
-          upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
-        }
-        break;
-      case UPB_TYPE_BYTES:
-        /* XXX: this doesn't support strings that span buffers yet. The base64
-         * encoder will need to be made resumable for this to work properly. */
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
-        } else {
-          upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
-        }
-        break;
-      case UPB_TYPE_MESSAGE:
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
-        } else {
-          upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
-        }
-        break;
-    }
-  }
-
-#undef TYPE
-}
-
-static void json_printer_reset(upb_json_printer *p) {
-  p->depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
-                                          upb_bytessink output) {
-#ifndef NDEBUG
-  size_t size_before = upb_arena_bytesallocated(a);
-#endif
-
-  upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer));
-  if (!p) return NULL;
-
-  p->output_ = output;
-  json_printer_reset(p);
-  upb_sink_reset(&p->input_, h, p);
-  p->seconds = 0;
-  p->nanos = 0;
-
-  /* If this fails, increase the value in printer.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
-                      UPB_JSON_PRINTER_SIZE);
-  return p;
-}
-
-upb_sink upb_json_printer_input(upb_json_printer *p) {
-  return p->input_;
-}
-
-upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) {
-  upb_json_printercache *cache = upb_gmalloc(sizeof(*cache));
-  upb_handlercache *ret = upb_handlercache_new(printer_sethandlers, cache);
-
-  cache->preserve_fieldnames = preserve_proto_fieldnames;
-  upb_handlercache_addcleanup(ret, cache, upb_gfree);
-
-  return ret;
-}
-/* See port_def.inc.  This should #undef all macros #defined there. */
-
-#undef UPB_SIZE
-#undef UPB_FIELD_AT
-#undef UPB_READ_ONEOF
-#undef UPB_WRITE_ONEOF
-#undef UPB_INLINE
-#undef UPB_FORCEINLINE
-#undef UPB_NOINLINE
-#undef UPB_NORETURN
-#undef UPB_MAX
-#undef UPB_MIN
-#undef UPB_UNUSED
-#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
-#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
diff --git a/php/ext/google/protobuf/upb.h b/php/ext/google/protobuf/upb.h
deleted file mode 100644
index 6746476..0000000
--- a/php/ext/google/protobuf/upb.h
+++ /dev/null
@@ -1,7095 +0,0 @@
-/* Amalgamated source file */
-
-// php.h intentionally defined NDEBUG. We have to define this macro in order to
-// be used together with php.h
-#ifndef NDEBUG
-#define NDEBUG
-#endif
-
-#include <stdint.h>/*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-*   #include "upb/foobar.h"
-*   #include "upb/baz.h"
-*
-*   // MUST be last included header.
-*   #include "upb/port_def.inc"
-*
-*   // Code for this file.
-*   // <...>
-*
-*   // Can be omitted for .c files, required for .h.
-*   #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#ifndef UINTPTR_MAX
-#error must include stdint.h first
-#endif
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-#define UPB_FIELD_AT(msg, fieldtype, offset) \
-  *(fieldtype*)((const char*)(msg) + offset)
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
-  UPB_FIELD_AT(msg, int, case_offset) == case_val                              \
-      ? UPB_FIELD_AT(msg, fieldtype, offset)                                   \
-      : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
-  UPB_FIELD_AT(msg, int, case_offset) = case_val;                             \
-  UPB_FIELD_AT(msg, fieldtype, offset) = value;
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else  /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include <stdio.h>
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include <stdarg.h>
-#include <stdio.h>
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
-    (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated.  This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode.  This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include <math.h>
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-/*
-** This file contains shared definitions that are widely used across upb.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_H_
-#define UPB_H_
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#ifdef __cplusplus
-#include <memory>
-namespace upb {
-class Arena;
-class Status;
-template <int N> class InlinedArena;
-}
-#endif
-
-
-/* upb_status *****************************************************************/
-
-/* upb_status represents a success or failure status and error message.
- * It owns no resources and allocates no memory, so it should work
- * even in OOM situations. */
-
-/* The maximum length of an error message before it will get truncated. */
-#define UPB_STATUS_MAX_MESSAGE 127
-
-typedef struct {
-  bool ok;
-  char msg[UPB_STATUS_MAX_MESSAGE];  /* Error message; NULL-terminated. */
-} upb_status;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_status_errmsg(const upb_status *status);
-bool upb_ok(const upb_status *status);
-
-/* Any of the functions that write to a status object allow status to be NULL,
- * to support use cases where the function's caller does not care about the
- * status message. */
-void upb_status_clear(upb_status *status);
-void upb_status_seterrmsg(upb_status *status, const char *msg);
-void upb_status_seterrf(upb_status *status, const char *fmt, ...);
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
-
-UPB_INLINE void upb_status_setoom(upb_status *status) {
-  upb_status_seterrmsg(status, "out of memory");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::Status {
- public:
-  Status() { upb_status_clear(&status_); }
-
-  upb_status* ptr() { return &status_; }
-
-  /* Returns true if there is no error. */
-  bool ok() const { return upb_ok(&status_); }
-
-  /* Guaranteed to be NULL-terminated. */
-  const char *error_message() const { return upb_status_errmsg(&status_); }
-
-  /* The error message will be truncated if it is longer than
-   * UPB_STATUS_MAX_MESSAGE-4. */
-  void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); }
-  void SetFormattedErrorMessage(const char *fmt, ...) {
-    va_list args;
-    va_start(args, fmt);
-    upb_status_vseterrf(&status_, fmt, args);
-    va_end(args);
-  }
-
-  /* Resets the status to a successful state with no message. */
-  void Clear() { upb_status_clear(&status_); }
-
- private:
-  upb_status status_;
-};
-
-#endif  /* __cplusplus */
-
-/** upb_strview ************************************************************/
-
-typedef struct {
-  const char *data;
-  size_t size;
-} upb_strview;
-
-UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
-  upb_strview ret;
-  ret.data = data;
-  ret.size = size;
-  return ret;
-}
-
-UPB_INLINE upb_strview upb_strview_makez(const char *data) {
-  return upb_strview_make(data, strlen(data));
-}
-
-UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
-  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
-}
-
-#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
-
-#define UPB_STRVIEW_FORMAT "%.*s"
-#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
-
-/** upb_alloc *****************************************************************/
-
-/* A upb_alloc is a possibly-stateful allocator object.
- *
- * It could either be an arena allocator (which doesn't require individual
- * free() calls) or a regular malloc() (which does).  The client must therefore
- * free memory unless it knows that the allocator is an arena allocator. */
-
-struct upb_alloc;
-typedef struct upb_alloc upb_alloc;
-
-/* A malloc()/free() function.
- * If "size" is 0 then the function acts like free(), otherwise it acts like
- * realloc().  Only "oldsize" bytes from a previous allocation are preserved. */
-typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
-                             size_t size);
-
-struct upb_alloc {
-  upb_alloc_func *func;
-};
-
-UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
-  UPB_ASSERT(alloc);
-  return alloc->func(alloc, NULL, 0, size);
-}
-
-UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                             size_t size) {
-  UPB_ASSERT(alloc);
-  return alloc->func(alloc, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
-  assert(alloc);
-  alloc->func(alloc, ptr, 0, 0);
-}
-
-/* The global allocator used by upb.  Uses the standard malloc()/free(). */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern upb_alloc upb_alloc_global;
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-/* Functions that hard-code the global malloc.
- *
- * We still get benefit because we can put custom logic into our global
- * allocator, like injecting out-of-memory faults in debug/testing builds. */
-
-UPB_INLINE void *upb_gmalloc(size_t size) {
-  return upb_malloc(&upb_alloc_global, size);
-}
-
-UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
-  return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_gfree(void *ptr) {
-  upb_free(&upb_alloc_global, ptr);
-}
-
-/* upb_arena ******************************************************************/
-
-/* upb_arena is a specific allocator implementation that uses arena allocation.
- * The user provides an allocator that will be used to allocate the underlying
- * arena blocks.  Arenas by nature do not require the individual allocations
- * to be freed.  However the Arena does allow users to register cleanup
- * functions that will run when the arena is destroyed.
- *
- * A upb_arena is *not* thread-safe.
- *
- * You could write a thread-safe arena allocator that satisfies the
- * upb_alloc interface, but it would not be as efficient for the
- * single-threaded case. */
-
-typedef void upb_cleanup_func(void *ud);
-
-struct upb_arena;
-typedef struct upb_arena upb_arena;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Creates an arena from the given initial block (if any -- n may be 0).
- * Additional blocks will be allocated from |alloc|.  If |alloc| is NULL, this
- * is a fixed-size arena and cannot grow. */
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
-void upb_arena_free(upb_arena *a);
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
-size_t upb_arena_bytesallocated(const upb_arena *a);
-
-UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
-
-/* Convenience wrappers around upb_alloc functions. */
-
-UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
-  return upb_malloc(upb_arena_alloc(a), size);
-}
-
-UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
-                                   size_t size) {
-  return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size);
-}
-
-UPB_INLINE upb_arena *upb_arena_new(void) {
-  return upb_arena_init(NULL, 0, &upb_alloc_global);
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::Arena {
- public:
-  /* A simple arena with no initial memory block and the default allocator. */
-  Arena() : ptr_(upb_arena_new(), upb_arena_free) {}
-
-  upb_arena* ptr() { return ptr_.get(); }
-
-  /* Allows this arena to be used as a generic allocator.
-   *
-   * The arena does not need free() calls so when using Arena as an allocator
-   * it is safe to skip them.  However they are no-ops so there is no harm in
-   * calling free() either. */
-  upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); }
-
-  /* Add a cleanup function to run when the arena is destroyed.
-   * Returns false on out-of-memory. */
-  bool AddCleanup(void *ud, upb_cleanup_func* func) {
-    return upb_arena_addcleanup(ptr_.get(), ud, func);
-  }
-
-  /* Total number of bytes that have been allocated.  It is undefined what
-   * Realloc() does to &arena_ counter. */
-  size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); }
-
- private:
-  std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
-};
-
-#endif
-
-/* upb::InlinedArena **********************************************************/
-
-/* upb::InlinedArena seeds the arenas with a predefined amount of memory.  No
- * heap memory will be allocated until the initial block is exceeded.
- *
- * These types only exist in C++ */
-
-#ifdef __cplusplus
-
-template <int N> class upb::InlinedArena : public upb::Arena {
- public:
-  InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {}
-
-  upb_arena* ptr() { return ptr_.get(); }
-
- private:
-  InlinedArena(const InlinedArena*) = delete;
-  InlinedArena& operator=(const InlinedArena*) = delete;
-
-  std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
-  char initial_block_[N];
-};
-
-#endif  /* __cplusplus */
-
-/* Constants ******************************************************************/
-
-/* Generic function type. */
-typedef void upb_func(void);
-
-/* A list of types as they are encoded on-the-wire. */
-typedef enum {
-  UPB_WIRE_TYPE_VARINT      = 0,
-  UPB_WIRE_TYPE_64BIT       = 1,
-  UPB_WIRE_TYPE_DELIMITED   = 2,
-  UPB_WIRE_TYPE_START_GROUP = 3,
-  UPB_WIRE_TYPE_END_GROUP   = 4,
-  UPB_WIRE_TYPE_32BIT       = 5
-} upb_wiretype_t;
-
-/* The types a field can have.  Note that this list is not identical to the
- * types defined in descriptor.proto, which gives INT32 and SINT32 separate
- * types (we distinguish the two with the "integer encoding" enum below). */
-typedef enum {
-  /* Types stored in 1 byte. */
-  UPB_TYPE_BOOL     = 1,
-  /* Types stored in 4 bytes. */
-  UPB_TYPE_FLOAT    = 2,
-  UPB_TYPE_INT32    = 3,
-  UPB_TYPE_UINT32   = 4,
-  UPB_TYPE_ENUM     = 5,  /* Enum values are int32. */
-  /* Types stored as pointers (probably 4 or 8 bytes). */
-  UPB_TYPE_STRING   = 6,
-  UPB_TYPE_BYTES    = 7,
-  UPB_TYPE_MESSAGE  = 8,
-  /* Types stored as 8 bytes. */
-  UPB_TYPE_DOUBLE   = 9,
-  UPB_TYPE_INT64    = 10,
-  UPB_TYPE_UINT64   = 11
-} upb_fieldtype_t;
-
-/* The repeated-ness of each field; this matches descriptor.proto. */
-typedef enum {
-  UPB_LABEL_OPTIONAL = 1,
-  UPB_LABEL_REQUIRED = 2,
-  UPB_LABEL_REPEATED = 3
-} upb_label_t;
-
-/* Descriptor types, as defined in descriptor.proto. */
-typedef enum {
-  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
-  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
-  UPB_DESCRIPTOR_TYPE_INT64    = 3,
-  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
-  UPB_DESCRIPTOR_TYPE_INT32    = 5,
-  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
-  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
-  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
-  UPB_DESCRIPTOR_TYPE_STRING   = 9,
-  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
-  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
-  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
-  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
-  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
-  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
-  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
-  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
-  UPB_DESCRIPTOR_TYPE_SINT64   = 18
-} upb_descriptortype_t;
-
-extern const uint8_t upb_desctype_to_fieldtype[];
-
-
-#endif  /* UPB_H_ */
-/*
-** upb_decode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_DECODE_H_
-#define UPB_DECODE_H_
-
-/*
-** Data structures for message tables, used for parsing and serialization.
-** This are much lighter-weight than full reflection, but they are do not
-** have enough information to convert to text format, JSON, etc.
-**
-** The definitions in this file are internal to upb.
-**/
-
-#ifndef UPB_MSG_H_
-#define UPB_MSG_H_
-
-#include <stdint.h>
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void upb_msg;
-
-/** upb_msglayout *************************************************************/
-
-/* upb_msglayout represents the memory layout of a given upb_msgdef.  The
- * members are public so generated code can initialize them, but users MUST NOT
- * read or write any of its members. */
-
-typedef struct {
-  uint32_t number;
-  uint16_t offset;
-  int16_t presence;      /* If >0, hasbit_index+1.  If <0, oneof_index+1. */
-  uint16_t submsg_index;  /* undefined if descriptortype != MESSAGE or GROUP. */
-  uint8_t descriptortype;
-  uint8_t label;
-} upb_msglayout_field;
-
-typedef struct upb_msglayout {
-  const struct upb_msglayout *const* submsgs;
-  const upb_msglayout_field *fields;
-  /* Must be aligned to sizeof(void*).  Doesn't include internal members like
-   * unknown fields, extension dict, pointer to msglayout, etc. */
-  uint16_t size;
-  uint16_t field_count;
-  bool extendable;
-} upb_msglayout;
-
-/** Message internal representation *******************************************/
-
-/* Our internal representation for repeated fields. */
-typedef struct {
-  void *data;   /* Each element is element_size. */
-  size_t len;   /* Measured in elements. */
-  size_t size;  /* Measured in elements. */
-} upb_array;
-
-upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a);
-upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a);
-
-void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                        upb_arena *arena);
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-
-upb_array *upb_array_new(upb_arena *a);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif /* UPB_MSG_H_ */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool upb_decode(const char *buf, size_t size, upb_msg *msg,
-                const upb_msglayout *l, upb_arena *arena);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif  /* UPB_DECODE_H_ */
-/*
-** upb_encode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_ENCODE_H_
-#define UPB_ENCODE_H_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena,
-                 size_t *size);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif  /* UPB_ENCODE_H_ */
-/*
-** upb_table
-**
-** This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
-** This file defines very fast int->upb_value (inttable) and string->upb_value
-** (strtable) hash tables.
-**
-** The table uses chained scatter with Brent's variation (inspired by the Lua
-** implementation of hash tables).  The hash function for strings is Austin
-** Appleby's "MurmurHash."
-**
-** The inttable uses uintptr_t as its key, which guarantees it can be used to
-** store pointers or integers of at least 32 bits (upb isn't really useful on
-** systems where sizeof(void*) < 4).
-**
-** The table must be homogenous (all values of the same type).  In debug
-** mode, we check this on insert and lookup.
-*/
-
-#ifndef UPB_TABLE_H_
-#define UPB_TABLE_H_
-
-#include <stdint.h>
-#include <string.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* upb_value ******************************************************************/
-
-/* A tagged union (stored untagged inside the table) so that we can check that
- * clients calling table accessors are correctly typed without having to have
- * an explosion of accessors. */
-typedef enum {
-  UPB_CTYPE_INT32    = 1,
-  UPB_CTYPE_INT64    = 2,
-  UPB_CTYPE_UINT32   = 3,
-  UPB_CTYPE_UINT64   = 4,
-  UPB_CTYPE_BOOL     = 5,
-  UPB_CTYPE_CSTR     = 6,
-  UPB_CTYPE_PTR      = 7,
-  UPB_CTYPE_CONSTPTR = 8,
-  UPB_CTYPE_FPTR     = 9,
-  UPB_CTYPE_FLOAT    = 10,
-  UPB_CTYPE_DOUBLE   = 11
-} upb_ctype_t;
-
-typedef struct {
-  uint64_t val;
-#ifndef NDEBUG
-  /* In debug mode we carry the value type around also so we can check accesses
-   * to be sure the right member is being read. */
-  upb_ctype_t ctype;
-#endif
-} upb_value;
-
-#ifdef NDEBUG
-#define SET_TYPE(dest, val)      UPB_UNUSED(val)
-#else
-#define SET_TYPE(dest, val) dest = val
-#endif
-
-/* Like strdup(), which isn't always available since it's not ANSI C. */
-char *upb_strdup(const char *s, upb_alloc *a);
-/* Variant that works with a length-delimited rather than NULL-delimited string,
- * as supported by strtable. */
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
-
-UPB_INLINE char *upb_gstrdup(const char *s) {
-  return upb_strdup(s, &upb_alloc_global);
-}
-
-UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val,
-                                  upb_ctype_t ctype) {
-  v->val = val;
-  SET_TYPE(v->ctype, ctype);
-}
-
-UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) {
-  upb_value ret;
-  _upb_value_setval(&ret, val, ctype);
-  return ret;
-}
-
-/* For each value ctype, define the following set of functions:
- *
- * // Get/set an int32 from a upb_value.
- * int32_t upb_value_getint32(upb_value val);
- * void upb_value_setint32(upb_value *val, int32_t cval);
- *
- * // Construct a new upb_value from an int32.
- * upb_value upb_value_int32(int32_t val); */
-#define FUNCS(name, membername, type_t, converter, proto_type) \
-  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
-    val->val = (converter)cval; \
-    SET_TYPE(val->ctype, proto_type); \
-  } \
-  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
-    upb_value ret; \
-    upb_value_set ## name(&ret, val); \
-    return ret; \
-  } \
-  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
-    UPB_ASSERT_DEBUGVAR(val.ctype == proto_type); \
-    return (type_t)(converter)val.val; \
-  }
-
-FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
-FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
-FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
-FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
-FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
-FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
-FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
-FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
-FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
-
-#undef FUNCS
-
-UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
-  memcpy(&val->val, &cval, sizeof(cval));
-  SET_TYPE(val->ctype, UPB_CTYPE_FLOAT);
-}
-
-UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
-  memcpy(&val->val, &cval, sizeof(cval));
-  SET_TYPE(val->ctype, UPB_CTYPE_DOUBLE);
-}
-
-UPB_INLINE upb_value upb_value_float(float cval) {
-  upb_value ret;
-  upb_value_setfloat(&ret, cval);
-  return ret;
-}
-
-UPB_INLINE upb_value upb_value_double(double cval) {
-  upb_value ret;
-  upb_value_setdouble(&ret, cval);
-  return ret;
-}
-
-#undef SET_TYPE
-
-
-/* upb_tabkey *****************************************************************/
-
-/* Either:
- *   1. an actual integer key, or
- *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
- *
- * ...depending on whether this is a string table or an int table.  We would
- * make this a union of those two types, but C89 doesn't support statically
- * initializing a non-first union member. */
-typedef uintptr_t upb_tabkey;
-
-UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
-  char* mem = (char*)key;
-  if (len) memcpy(len, mem, sizeof(*len));
-  return mem + sizeof(*len);
-}
-
-
-/* upb_tabval *****************************************************************/
-
-typedef struct {
-  uint64_t val;
-} upb_tabval;
-
-#define UPB_TABVALUE_EMPTY_INIT  {-1}
-
-
-/* upb_table ******************************************************************/
-
-typedef struct _upb_tabent {
-  upb_tabkey key;
-  upb_tabval val;
-
-  /* Internal chaining.  This is const so we can create static initializers for
-   * tables.  We cast away const sometimes, but *only* when the containing
-   * upb_table is known to be non-const.  This requires a bit of care, but
-   * the subtlety is confined to table.c. */
-  const struct _upb_tabent *next;
-} upb_tabent;
-
-typedef struct {
-  size_t count;          /* Number of entries in the hash part. */
-  size_t mask;           /* Mask to turn hash value -> bucket. */
-  upb_ctype_t ctype;     /* Type of all values. */
-  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
-
-  /* Hash table entries.
-   * Making this const isn't entirely accurate; what we really want is for it to
-   * have the same const-ness as the table it's inside.  But there's no way to
-   * declare that in C.  So we have to make it const so that we can statically
-   * initialize const hash tables.  Then we cast away const when we have to.
-   */
-  const upb_tabent *entries;
-
-#ifndef NDEBUG
-  /* This table's allocator.  We make the user pass it in to every relevant
-   * function and only use this to check it in debug mode.  We do this solely
-   * to keep upb_table as small as possible.  This might seem slightly paranoid
-   * but the plan is to use upb_table for all map fields and extension sets in
-   * a forthcoming message representation, so there could be a lot of these.
-   * If this turns out to be too annoying later, we can change it (since this
-   * is an internal-only header file). */
-  upb_alloc *alloc;
-#endif
-} upb_table;
-
-typedef struct {
-  upb_table t;
-} upb_strtable;
-
-typedef struct {
-  upb_table t;              /* For entries that don't fit in the array part. */
-  const upb_tabval *array;  /* Array part of the table. See const note above. */
-  size_t array_size;        /* Array part size. */
-  size_t array_count;       /* Array part number of elements. */
-} upb_inttable;
-
-#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \
-  {UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount}
-
-#define UPB_EMPTY_INTTABLE_INIT(ctype) \
-  UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0)
-
-#define UPB_ARRAY_EMPTYENT -1
-
-UPB_INLINE size_t upb_table_size(const upb_table *t) {
-  if (t->size_lg2 == 0)
-    return 0;
-  else
-    return 1 << t->size_lg2;
-}
-
-/* Internal-only functions, in .h file only out of necessity. */
-UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
-  return e->key == 0;
-}
-
-/* Used by some of the unit tests for generic hashing functionality. */
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed);
-
-UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
-  return key;
-}
-
-UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
-  return (uint32_t)key;
-}
-
-static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
-  return t->entries + (hash & t->mask);
-}
-
-UPB_INLINE bool upb_arrhas(upb_tabval key) {
-  return key.val != (uint64_t)-1;
-}
-
-/* Initialize and uninitialize a table, respectively.  If memory allocation
- * failed, false is returned that the table is uninitialized. */
-bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
-bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
-void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
-void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
-  return upb_inttable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
-  return upb_strtable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
-  upb_inttable_uninit2(table, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
-  upb_strtable_uninit2(table, &upb_alloc_global);
-}
-
-/* Returns the number of values in the table. */
-size_t upb_inttable_count(const upb_inttable *t);
-UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
-  return t->t.count;
-}
-
-void upb_inttable_packedsize(const upb_inttable *t, size_t *size);
-void upb_strtable_packedsize(const upb_strtable *t, size_t *size);
-upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs,
-                                size_t size);
-upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs,
-                                size_t size);
-
-/* Inserts the given key into the hashtable with the given value.  The key must
- * not already exist in the hash table.  For string tables, the key must be
- * NULL-terminated, and the table will make an internal copy of the key.
- * Inttables must not insert a value of UINTPTR_MAX.
- *
- * If a table resize was required but memory allocation failed, false is
- * returned and the table is unchanged. */
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
-                          upb_alloc *a);
-bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
-                          upb_value val, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
-                                    upb_value val) {
-  return upb_inttable_insert2(t, key, val, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
-                                     size_t len, upb_value val) {
-  return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
-                                    upb_value val) {
-  return upb_strtable_insert2(t, key, strlen(key), val);
-}
-
-/* Looks up key in this table, returning "true" if the key was found.
- * If v is non-NULL, copies the value for this key into *v. */
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
-                          upb_value *v);
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
-                                    upb_value *v) {
-  return upb_strtable_lookup2(t, key, strlen(key), v);
-}
-
-/* Removes an item from the table.  Returns true if the remove was successful,
- * and stores the removed item in *val if non-NULL. */
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
-                          upb_value *val, upb_alloc *alloc);
-
-UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
-                                     size_t len, upb_value *val) {
-  return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
-                                    upb_value *v) {
-  return upb_strtable_remove2(t, key, strlen(key), v);
-}
-
-/* Updates an existing entry in an inttable.  If the entry does not exist,
- * returns false and does nothing.  Unlike insert/remove, this does not
- * invalidate iterators. */
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
-
-/* Handy routines for treating an inttable like a stack.  May not be mixed with
- * other insert/remove calls. */
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
-upb_value upb_inttable_pop(upb_inttable *t);
-
-UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
-  return upb_inttable_push2(t, val, &upb_alloc_global);
-}
-
-/* Convenience routines for inttables with pointer keys. */
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
-                             upb_alloc *a);
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
-bool upb_inttable_lookupptr(
-    const upb_inttable *t, const void *key, upb_value *val);
-
-UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
-                                       upb_value val) {
-  return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
-}
-
-/* Optimizes the table for the current set of entries, for both memory use and
- * lookup time.  Client should call this after all entries have been inserted;
- * inserting more entries is legal, but will likely require a table resize. */
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
-
-UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
-  upb_inttable_compact2(t, &upb_alloc_global);
-}
-
-/* A special-case inlinable version of the lookup routine for 32-bit
- * integers. */
-UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
-                                      upb_value *v) {
-  *v = upb_value_int32(0);  /* Silence compiler warnings. */
-  if (key < t->array_size) {
-    upb_tabval arrval = t->array[key];
-    if (upb_arrhas(arrval)) {
-      _upb_value_setval(v, arrval.val, t->t.ctype);
-      return true;
-    } else {
-      return false;
-    }
-  } else {
-    const upb_tabent *e;
-    if (t->t.entries == NULL) return false;
-    for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
-      if ((uint32_t)e->key == key) {
-        _upb_value_setval(v, e->val.val, t->t.ctype);
-        return true;
-      }
-      if (e->next == NULL) return false;
-    }
-  }
-}
-
-/* Exposed for testing only. */
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
-
-/* Iterators ******************************************************************/
-
-/* Iterators for int and string tables.  We are subject to some kind of unusual
- * design constraints:
- *
- * For high-level languages:
- *  - we must be able to guarantee that we don't crash or corrupt memory even if
- *    the program accesses an invalidated iterator.
- *
- * For C++11 range-based for:
- *  - iterators must be copyable
- *  - iterators must be comparable
- *  - it must be possible to construct an "end" value.
- *
- * Iteration order is undefined.
- *
- * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
- * guaranteed to work even on an invalidated iterator, as long as the table it
- * is iterating over has not been freed.  Calling next() or accessing data from
- * an invalidated iterator yields unspecified elements from the table, but it is
- * guaranteed not to crash and to return real table elements (except when done()
- * is true). */
-
-
-/* upb_strtable_iter **********************************************************/
-
-/*   upb_strtable_iter i;
- *   upb_strtable_begin(&i, t);
- *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- *     const char *key = upb_strtable_iter_key(&i);
- *     const upb_value val = upb_strtable_iter_value(&i);
- *     // ...
- *   }
- */
-
-typedef struct {
-  const upb_strtable *t;
-  size_t index;
-} upb_strtable_iter;
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
-void upb_strtable_next(upb_strtable_iter *i);
-bool upb_strtable_done(const upb_strtable_iter *i);
-const char *upb_strtable_iter_key(const upb_strtable_iter *i);
-size_t upb_strtable_iter_keylength(const upb_strtable_iter *i);
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
-void upb_strtable_iter_setdone(upb_strtable_iter *i);
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
-                               const upb_strtable_iter *i2);
-
-
-/* upb_inttable_iter **********************************************************/
-
-/*   upb_inttable_iter i;
- *   upb_inttable_begin(&i, t);
- *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- *     uintptr_t key = upb_inttable_iter_key(&i);
- *     upb_value val = upb_inttable_iter_value(&i);
- *     // ...
- *   }
- */
-
-typedef struct {
-  const upb_inttable *t;
-  size_t index;
-  bool array_part;
-} upb_inttable_iter;
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
-void upb_inttable_next(upb_inttable_iter *i);
-bool upb_inttable_done(const upb_inttable_iter *i);
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
-void upb_inttable_iter_setdone(upb_inttable_iter *i);
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
-                               const upb_inttable_iter *i2);
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* UPB_TABLE_H_ */
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-
-/*
-** Functions for use by generated code.  These are not public and users must
-** not call them directly.
-*/
-
-#ifndef UPB_GENERATED_UTIL_H_
-#define UPB_GENERATED_UTIL_H_
-
-#include <stdint.h>
-
-
-#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)
-
-UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
-                                           size_t *size) {
-  const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*);
-  if (arr) {
-    if (size) *size = arr->len;
-    return arr->data;
-  } else {
-    if (size) *size = 0;
-    return NULL;
-  }
-}
-
-UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
-                                             size_t *size) {
-  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
-  if (arr) {
-    if (size) *size = arr->len;
-    return arr->data;
-  } else {
-    if (size) *size = 0;
-    return NULL;
-  }
-}
-
-/* TODO(haberman): this is a mess.  It will improve when upb_array no longer
- * carries reflective state (type, elem_size). */
-UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
-                                            size_t elem_size,
-                                            upb_fieldtype_t type,
-                                            upb_arena *arena) {
-  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
-
-  if (!arr) {
-    arr = upb_array_new(arena);
-    if (!arr) return NULL;
-    *PTR_AT(msg, ofs, upb_array*) = arr;
-  }
-
-  if (size > arr->size) {
-    size_t new_size = UPB_MAX(arr->size, 4);
-    size_t old_bytes = arr->size * elem_size;
-    size_t new_bytes;
-    while (new_size < size) new_size *= 2;
-    new_bytes = new_size * elem_size;
-    arr->data = upb_arena_realloc(arena, arr->data, old_bytes, new_bytes);
-    if (!arr->data) {
-      return NULL;
-    }
-    arr->size = new_size;
-  }
-
-  arr->len = size;
-  return arr->data;
-}
-
-UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
-                                           size_t elem_size,
-                                           upb_fieldtype_t type,
-                                           const void *value,
-                                           upb_arena *arena) {
-  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
-  size_t i = arr ? arr->len : 0;
-  void *data =
-      _upb_array_resize_accessor(msg, ofs, i + 1, elem_size, type, arena);
-  if (!data) return false;
-  memcpy(PTR_AT(data, i * elem_size, char), value, elem_size);
-  return true;
-}
-
-UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
-}
-
-UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
-}
-
-UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
-}
-
-UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) {
-  return *PTR_AT(msg, case_ofs, int32_t) == num;
-}
-
-#undef PTR_AT
-
-
-#endif  /* UPB_GENERATED_UTIL_H_ */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct google_protobuf_FileDescriptorSet;
-struct google_protobuf_FileDescriptorProto;
-struct google_protobuf_DescriptorProto;
-struct google_protobuf_DescriptorProto_ExtensionRange;
-struct google_protobuf_DescriptorProto_ReservedRange;
-struct google_protobuf_ExtensionRangeOptions;
-struct google_protobuf_FieldDescriptorProto;
-struct google_protobuf_OneofDescriptorProto;
-struct google_protobuf_EnumDescriptorProto;
-struct google_protobuf_EnumDescriptorProto_EnumReservedRange;
-struct google_protobuf_EnumValueDescriptorProto;
-struct google_protobuf_ServiceDescriptorProto;
-struct google_protobuf_MethodDescriptorProto;
-struct google_protobuf_FileOptions;
-struct google_protobuf_MessageOptions;
-struct google_protobuf_FieldOptions;
-struct google_protobuf_OneofOptions;
-struct google_protobuf_EnumOptions;
-struct google_protobuf_EnumValueOptions;
-struct google_protobuf_ServiceOptions;
-struct google_protobuf_MethodOptions;
-struct google_protobuf_UninterpretedOption;
-struct google_protobuf_UninterpretedOption_NamePart;
-struct google_protobuf_SourceCodeInfo;
-struct google_protobuf_SourceCodeInfo_Location;
-struct google_protobuf_GeneratedCodeInfo;
-struct google_protobuf_GeneratedCodeInfo_Annotation;
-typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet;
-typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto;
-typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto;
-typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange;
-typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange;
-typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions;
-typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto;
-typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange;
-typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto;
-typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto;
-typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto;
-typedef struct google_protobuf_FileOptions google_protobuf_FileOptions;
-typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions;
-typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions;
-typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions;
-typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions;
-typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions;
-typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions;
-typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions;
-typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption;
-typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart;
-typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo;
-typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location;
-typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo;
-typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation;
-extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
-extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
-extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
-extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_FileOptions_msginit;
-extern const upb_msglayout google_protobuf_MessageOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldOptions_msginit;
-extern const upb_msglayout google_protobuf_OneofOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
-extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
-extern const upb_msglayout google_protobuf_MethodOptions_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
-
-typedef enum {
-  google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
-  google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
-  google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
-} google_protobuf_FieldDescriptorProto_Label;
-
-typedef enum {
-  google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
-  google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
-  google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
-  google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
-  google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
-  google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
-  google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
-  google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
-  google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
-  google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
-  google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
-  google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
-  google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
-  google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
-  google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
-  google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
-  google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
-  google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
-} google_protobuf_FieldDescriptorProto_Type;
-
-typedef enum {
-  google_protobuf_FieldOptions_STRING = 0,
-  google_protobuf_FieldOptions_CORD = 1,
-  google_protobuf_FieldOptions_STRING_PIECE = 2
-} google_protobuf_FieldOptions_CType;
-
-typedef enum {
-  google_protobuf_FieldOptions_JS_NORMAL = 0,
-  google_protobuf_FieldOptions_JS_STRING = 1,
-  google_protobuf_FieldOptions_JS_NUMBER = 2
-} google_protobuf_FieldOptions_JSType;
-
-typedef enum {
-  google_protobuf_FileOptions_SPEED = 1,
-  google_protobuf_FileOptions_CODE_SIZE = 2,
-  google_protobuf_FileOptions_LITE_RUNTIME = 3
-} google_protobuf_FileOptions_OptimizeMode;
-
-typedef enum {
-  google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
-  google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
-  google_protobuf_MethodOptions_IDEMPOTENT = 2
-} google_protobuf_MethodOptions_IdempotencyLevel;
-
-
-/* google.protobuf.FileDescriptorSet */
-
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) {
-  return (google_protobuf_FileDescriptorSet *)upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
-}
-
-UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) {
-  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) {
-  struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FileDescriptorProto */
-
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_FileDescriptorProto *)upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); }
-UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FileOptions*, UPB_SIZE(28, 56)); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_SourceCodeInfo*, UPB_SIZE(32, 64)); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)); }
-
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(44, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(48, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(52, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) {
-  _upb_sethas(msg, 4);
-  UPB_FIELD_AT(msg, google_protobuf_FileOptions*, UPB_SIZE(28, 56)) = value;
-}
-UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_FileOptions*)upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) {
-  _upb_sethas(msg, 5);
-  UPB_FIELD_AT(msg, google_protobuf_SourceCodeInfo*, UPB_SIZE(32, 64)) = value;
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_SourceCodeInfo*)upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena);
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)) = value;
-}
-
-/* google.protobuf.DescriptorProto */
-
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto *)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_MessageOptions*, UPB_SIZE(12, 24)); }
-UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(24, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 56), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(32, 64), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, google_protobuf_MessageOptions*, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_MessageOptions*)upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(36, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-
-/* google.protobuf.DescriptorProto.ExtensionRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ExtensionRange *)upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, const google_protobuf_ExtensionRangeOptions*, UPB_SIZE(12, 16)); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, google_protobuf_ExtensionRangeOptions*, UPB_SIZE(12, 16)) = value;
-}
-UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) {
-  struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_ExtensionRangeOptions*)upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.DescriptorProto.ReservedRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange *)upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-
-/* google.protobuf.ExtensionRangeOptions */
-
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) {
-  return (google_protobuf_ExtensionRangeOptions *)upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
-}
-
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FieldDescriptorProto */
-
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto *)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FieldOptions*, UPB_SIZE(72, 112)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)); }
-
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 6);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 7);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 8);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
-  _upb_sethas(msg, 10);
-  UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(72, 112)) = value;
-}
-UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_FieldOptions*)upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 4);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 9);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)) = value;
-}
-
-/* google.protobuf.OneofDescriptorProto */
-
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_OneofDescriptorProto *)upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_OneofOptions*, UPB_SIZE(12, 24)); }
-
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, google_protobuf_OneofOptions*, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_OneofOptions*)upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.EnumDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto *)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_EnumOptions*, UPB_SIZE(12, 24)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, google_protobuf_EnumOptions*, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_EnumOptions*)upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-
-/* google.protobuf.EnumDescriptorProto.EnumReservedRange */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-
-/* google.protobuf.EnumValueDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_EnumValueDescriptorProto *)upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_EnumValueOptions*, UPB_SIZE(16, 24)); }
-
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, google_protobuf_EnumValueOptions*, UPB_SIZE(16, 24)) = value;
-}
-UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_EnumValueOptions*)upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.ServiceDescriptorProto */
-
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_ServiceDescriptorProto *)upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_ServiceOptions*, UPB_SIZE(12, 24)); }
-
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, google_protobuf_ServiceOptions*, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_ServiceOptions*)upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.MethodDescriptorProto */
-
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_MethodDescriptorProto *)upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_MethodOptions*, UPB_SIZE(28, 56)); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); }
-
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 4);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
-  _upb_sethas(msg, 6);
-  UPB_FIELD_AT(msg, google_protobuf_MethodOptions*, UPB_SIZE(28, 56)) = value;
-}
-UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_MethodOptions*)upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value;
-}
-
-/* google.protobuf.FileOptions */
-
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) {
-  return (google_protobuf_FileOptions *)upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(28, 32)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 12); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 48)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 13); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 64)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(18, 18)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(19, 19)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(20, 20)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(21, 21)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(22, 22)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(23, 23)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 14); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 80)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 15); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 96)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 16); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 112)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 17); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 128)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 18); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 144)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 19); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 160)); }
-UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 20); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 176)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(108, 192), len); }
-
-UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 11);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(28, 32)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 12);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 48)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 13);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 64)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(18, 18)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 5);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(19, 19)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 6);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(20, 20)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 7);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(21, 21)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 8);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(22, 22)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 9);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(23, 23)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 14);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 80)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 15);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 96)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 16);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 112)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 17);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 128)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 18);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 144)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 10);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 19);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 160)) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 20);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 176)) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 192), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(108, 192), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.MessageOptions */
-
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) {
-  return (google_protobuf_MessageOptions *)upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(3, 3)); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); }
-
-UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(3, 3)) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(8, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FieldOptions */
-
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) {
-  return (google_protobuf_FieldOptions *)upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(25, 25)); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); }
-
-UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(25, 25)) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 5);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 6);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.OneofOptions */
-
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) {
-  return (google_protobuf_OneofOptions *)upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
-}
-
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.EnumOptions */
-
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) {
-  return (google_protobuf_EnumOptions *)upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
-UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
-}
-UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.EnumValueOptions */
-
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) {
-  return (google_protobuf_EnumValueOptions *)upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.ServiceOptions */
-
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) {
-  return (google_protobuf_ServiceOptions *)upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.MethodOptions */
-
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) {
-  return (google_protobuf_MethodOptions *)upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)); }
-UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); }
-
-UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value;
-}
-UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.UninterpretedOption */
-
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption *)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
-}
-
-UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, int64_t, UPB_SIZE(16, 16)); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, double, UPB_SIZE(24, 24)); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); }
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(56, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 4);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, int64_t, UPB_SIZE(16, 16)) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, double, UPB_SIZE(24, 24)) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 6);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value;
-}
-
-/* google.protobuf.UninterpretedOption.NamePart */
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption_NamePart *)upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); }
-
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value;
-}
-
-/* google.protobuf.SourceCodeInfo */
-
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo *)upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) {
-  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) {
-  struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.SourceCodeInfo.Location */
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo_Location *)upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); }
-UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena);
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value;
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena);
-}
-
-/* google.protobuf.GeneratedCodeInfo */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo *)upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) {
-  struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.GeneratedCodeInfo.Annotation */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation *)upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
-
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len);
-}
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena);
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
-/*
-** Defs are upb's internal representation of the constructs that can appear
-** in a .proto file:
-**
-** - upb::MessageDefPtr (upb_msgdef): describes a "message" construct.
-** - upb::FieldDefPtr (upb_fielddef): describes a message field.
-** - upb::FileDefPtr (upb_filedef): describes a .proto file and its defs.
-** - upb::EnumDefPtr (upb_enumdef): describes an enum.
-** - upb::OneofDefPtr (upb_oneofdef): describes a oneof.
-**
-** TODO: definitions of services.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_DEF_H_
-#define UPB_DEF_H_
-
-
-#ifdef __cplusplus
-#include <cstring>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace upb {
-class EnumDefPtr;
-class FieldDefPtr;
-class FileDefPtr;
-class MessageDefPtr;
-class OneofDefPtr;
-class SymbolTable;
-}
-#endif
-
-
-struct upb_enumdef;
-typedef struct upb_enumdef upb_enumdef;
-struct upb_fielddef;
-typedef struct upb_fielddef upb_fielddef;
-struct upb_filedef;
-typedef struct upb_filedef upb_filedef;
-struct upb_msgdef;
-typedef struct upb_msgdef upb_msgdef;
-struct upb_oneofdef;
-typedef struct upb_oneofdef upb_oneofdef;
-struct upb_symtab;
-typedef struct upb_symtab upb_symtab;
-
-typedef enum {
-  UPB_SYNTAX_PROTO2 = 2,
-  UPB_SYNTAX_PROTO3 = 3
-} upb_syntax_t;
-
-/* All the different kind of well known type messages. For simplicity of check,
- * number wrappers and string wrappers are grouped together. Make sure the
- * order and merber of these groups are not changed.
- */
-typedef enum {
-  UPB_WELLKNOWN_UNSPECIFIED,
-  UPB_WELLKNOWN_ANY,
-  UPB_WELLKNOWN_FIELDMASK,
-  UPB_WELLKNOWN_DURATION,
-  UPB_WELLKNOWN_TIMESTAMP,
-  /* number wrappers */
-  UPB_WELLKNOWN_DOUBLEVALUE,
-  UPB_WELLKNOWN_FLOATVALUE,
-  UPB_WELLKNOWN_INT64VALUE,
-  UPB_WELLKNOWN_UINT64VALUE,
-  UPB_WELLKNOWN_INT32VALUE,
-  UPB_WELLKNOWN_UINT32VALUE,
-  /* string wrappers */
-  UPB_WELLKNOWN_STRINGVALUE,
-  UPB_WELLKNOWN_BYTESVALUE,
-  UPB_WELLKNOWN_BOOLVALUE,
-  UPB_WELLKNOWN_VALUE,
-  UPB_WELLKNOWN_LISTVALUE,
-  UPB_WELLKNOWN_STRUCT
-} upb_wellknowntype_t;
-
-/* upb_fielddef ***************************************************************/
-
-/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
- * protobuf wire format. */
-#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_fielddef_fullname(const upb_fielddef *f);
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
-upb_label_t upb_fielddef_label(const upb_fielddef *f);
-uint32_t upb_fielddef_number(const upb_fielddef *f);
-const char *upb_fielddef_name(const upb_fielddef *f);
-bool upb_fielddef_isextension(const upb_fielddef *f);
-bool upb_fielddef_lazy(const upb_fielddef *f);
-bool upb_fielddef_packed(const upb_fielddef *f);
-size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len);
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
-uint32_t upb_fielddef_index(const upb_fielddef *f);
-bool upb_fielddef_issubmsg(const upb_fielddef *f);
-bool upb_fielddef_isstring(const upb_fielddef *f);
-bool upb_fielddef_isseq(const upb_fielddef *f);
-bool upb_fielddef_isprimitive(const upb_fielddef *f);
-bool upb_fielddef_ismap(const upb_fielddef *f);
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
-bool upb_fielddef_defaultbool(const upb_fielddef *f);
-float upb_fielddef_defaultfloat(const upb_fielddef *f);
-double upb_fielddef_defaultdouble(const upb_fielddef *f);
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
-bool upb_fielddef_hassubdef(const upb_fielddef *f);
-bool upb_fielddef_haspresence(const upb_fielddef *f);
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
-
-/* Internal only. */
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A upb_fielddef describes a single field in a message.  It is most often
- * found as a part of a upb_msgdef, but can also stand alone to represent
- * an extension. */
-class upb::FieldDefPtr {
- public:
-  FieldDefPtr() : ptr_(nullptr) {}
-  explicit FieldDefPtr(const upb_fielddef *ptr) : ptr_(ptr) {}
-
-  const upb_fielddef* ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  typedef upb_fieldtype_t Type;
-  typedef upb_label_t Label;
-  typedef upb_descriptortype_t DescriptorType;
-
-  const char* full_name() const { return upb_fielddef_fullname(ptr_); }
-
-  Type type() const { return upb_fielddef_type(ptr_); }
-  Label label() const { return upb_fielddef_label(ptr_); }
-  const char* name() const { return upb_fielddef_name(ptr_); }
-  uint32_t number() const { return upb_fielddef_number(ptr_); }
-  bool is_extension() const { return upb_fielddef_isextension(ptr_); }
-
-  /* Copies the JSON name for this field into the given buffer.  Returns the
-   * actual size of the JSON name, including the NULL terminator.  If the
-   * return value is 0, the JSON name is unset.  If the return value is
-   * greater than len, the JSON name was truncated.  The buffer is always
-   * NULL-terminated if len > 0.
-   *
-   * The JSON name always defaults to a camelCased version of the regular
-   * name.  However if the regular name is unset, the JSON name will be unset
-   * also.
-   */
-  size_t GetJsonName(char *buf, size_t len) const {
-    return upb_fielddef_getjsonname(ptr_, buf, len);
-  }
-
-  /* Convenience version of the above function which copies the JSON name
-   * into the given string, returning false if the name is not set. */
-  template <class T>
-  bool GetJsonName(T* str) {
-    str->resize(GetJsonName(NULL, 0));
-    GetJsonName(&(*str)[0], str->size());
-    return str->size() > 0;
-  }
-
-  /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false,
-   * indicates whether this field should have lazy parsing handlers that yield
-   * the unparsed string for the submessage.
-   *
-   * TODO(haberman): I think we want to move this into a FieldOptions container
-   * when we add support for custom options (the FieldOptions struct will
-   * contain both regular FieldOptions like "lazy" *and* custom options). */
-  bool lazy() const { return upb_fielddef_lazy(ptr_); }
-
-  /* For non-string, non-submessage fields, this indicates whether binary
-   * protobufs are encoded in packed or non-packed format.
-   *
-   * TODO(haberman): see note above about putting options like this into a
-   * FieldOptions container. */
-  bool packed() const { return upb_fielddef_packed(ptr_); }
-
-  /* An integer that can be used as an index into an array of fields for
-   * whatever message this field belongs to.  Guaranteed to be less than
-   * f->containing_type()->field_count().  May only be accessed once the def has
-   * been finalized. */
-  uint32_t index() const { return upb_fielddef_index(ptr_); }
-
-  /* The MessageDef to which this field belongs.
-   *
-   * If this field has been added to a MessageDef, that message can be retrieved
-   * directly (this is always the case for frozen FieldDefs).
-   *
-   * If the field has not yet been added to a MessageDef, you can set the name
-   * of the containing type symbolically instead.  This is mostly useful for
-   * extensions, where the extension is declared separately from the message. */
-  MessageDefPtr containing_type() const;
-
-  /* The OneofDef to which this field belongs, or NULL if this field is not part
-   * of a oneof. */
-  OneofDefPtr containing_oneof() const;
-
-  /* The field's type according to the enum in descriptor.proto.  This is not
-   * the same as UPB_TYPE_*, because it distinguishes between (for example)
-   * INT32 and SINT32, whereas our "type" enum does not.  This return of
-   * descriptor_type() is a function of type(), integer_format(), and
-   * is_tag_delimited().  */
-  DescriptorType descriptor_type() const {
-    return upb_fielddef_descriptortype(ptr_);
-  }
-
-  /* Convenient field type tests. */
-  bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); }
-  bool IsString() const { return upb_fielddef_isstring(ptr_); }
-  bool IsSequence() const { return upb_fielddef_isseq(ptr_); }
-  bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); }
-  bool IsMap() const { return upb_fielddef_ismap(ptr_); }
-
-  /* Returns the non-string default value for this fielddef, which may either
-   * be something the client set explicitly or the "default default" (0 for
-   * numbers, empty for strings).  The field's type indicates the type of the
-   * returned value, except for enum fields that are still mutable.
-   *
-   * Requires that the given function matches the field's current type. */
-  int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); }
-  int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); }
-  uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); }
-  uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); }
-  bool default_bool() const { return upb_fielddef_defaultbool(ptr_); }
-  float default_float() const { return upb_fielddef_defaultfloat(ptr_); }
-  double default_double() const { return upb_fielddef_defaultdouble(ptr_); }
-
-  /* The resulting string is always NULL-terminated.  If non-NULL, the length
-   * will be stored in *len. */
-  const char *default_string(size_t * len) const {
-    return upb_fielddef_defaultstr(ptr_, len);
-  }
-
-  /* Returns the enum or submessage def for this field, if any.  The field's
-   * type must match (ie. you may only call enum_subdef() for fields where
-   * type() == UPB_TYPE_ENUM). */
-  EnumDefPtr enum_subdef() const;
-  MessageDefPtr message_subdef() const;
-
- private:
-  const upb_fielddef *ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_oneofdef ***************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef upb_inttable_iter upb_oneof_iter;
-
-const char *upb_oneofdef_name(const upb_oneofdef *o);
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
-int upb_oneofdef_numfields(const upb_oneofdef *o);
-uint32_t upb_oneofdef_index(const upb_oneofdef *o);
-
-/* Oneof lookups:
- * - ntof:  look up a field by name.
- * - ntofz: look up a field by name (as a null-terminated string).
- * - itof:  look up a field by number. */
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
-                                      const char *name, size_t length);
-UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
-                                                  const char *name) {
-  return upb_oneofdef_ntof(o, name, strlen(name));
-}
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
-
-/*  upb_oneof_iter i;
- *  for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) {
- *    // ...
- *  }
- */
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
-void upb_oneof_next(upb_oneof_iter *iter);
-bool upb_oneof_done(upb_oneof_iter *iter);
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
-void upb_oneof_iter_setdone(upb_oneof_iter *iter);
-bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
-                            const upb_oneof_iter *iter2);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Class that represents a oneof. */
-class upb::OneofDefPtr {
- public:
-  OneofDefPtr() : ptr_(nullptr) {}
-  explicit OneofDefPtr(const upb_oneofdef *ptr) : ptr_(ptr) {}
-
-  const upb_oneofdef* ptr() const { return ptr_; }
-  explicit operator bool() { return ptr_ != nullptr; }
-
-  /* Returns the MessageDef that owns this OneofDef. */
-  MessageDefPtr containing_type() const;
-
-  /* Returns the name of this oneof. This is the name used to look up the oneof
-   * by name once added to a message def. */
-  const char* name() const { return upb_oneofdef_name(ptr_); }
-
-  /* Returns the number of fields currently defined in the oneof. */
-  int field_count() const { return upb_oneofdef_numfields(ptr_); }
-
-  /* Looks up by name. */
-  FieldDefPtr FindFieldByName(const char *name, size_t len) const {
-    return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len));
-  }
-  FieldDefPtr FindFieldByName(const char* name) const {
-    return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name));
-  }
-
-  template <class T>
-  FieldDefPtr FindFieldByName(const T& str) const {
-    return FindFieldByName(str.c_str(), str.size());
-  }
-
-  /* Looks up by tag number. */
-  FieldDefPtr FindFieldByNumber(uint32_t num) const {
-    return FieldDefPtr(upb_oneofdef_itof(ptr_, num));
-  }
-
-  class const_iterator
-      : public std::iterator<std::forward_iterator_tag, FieldDefPtr> {
-   public:
-    void operator++() { upb_oneof_next(&iter_); }
-
-    FieldDefPtr operator*() const {
-      return FieldDefPtr(upb_oneof_iter_field(&iter_));
-    }
-
-    bool operator!=(const const_iterator& other) const {
-      return !upb_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-    bool operator==(const const_iterator& other) const {
-      return upb_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-   private:
-    friend class OneofDefPtr;
-
-    const_iterator() {}
-    explicit const_iterator(OneofDefPtr o) {
-      upb_oneof_begin(&iter_, o.ptr());
-    }
-    static const_iterator end() {
-      const_iterator iter;
-      upb_oneof_iter_setdone(&iter.iter_);
-      return iter;
-    }
-
-    upb_oneof_iter iter_;
-  };
-
-  const_iterator begin() const { return const_iterator(*this); }
-  const_iterator end() const { return const_iterator::end(); }
-
- private:
-  const upb_oneofdef *ptr_;
-};
-
-inline upb::OneofDefPtr upb::FieldDefPtr::containing_oneof() const {
-  return OneofDefPtr(upb_fielddef_containingoneof(ptr_));
-}
-
-#endif  /* __cplusplus */
-
-/* upb_msgdef *****************************************************************/
-
-typedef upb_inttable_iter upb_msg_field_iter;
-typedef upb_strtable_iter upb_msg_oneof_iter;
-
-/* Well-known field tag numbers for map-entry messages. */
-#define UPB_MAPENTRY_KEY   1
-#define UPB_MAPENTRY_VALUE 2
-
-/* Well-known field tag numbers for Any messages. */
-#define UPB_ANY_TYPE 1
-#define UPB_ANY_VALUE 2
-
-/* Well-known field tag numbers for timestamp messages. */
-#define UPB_DURATION_SECONDS 1
-#define UPB_DURATION_NANOS 2
-
-/* Well-known field tag numbers for duration messages. */
-#define UPB_TIMESTAMP_SECONDS 1
-#define UPB_TIMESTAMP_NANOS 2
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_msgdef_fullname(const upb_msgdef *m);
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
-const char *upb_msgdef_name(const upb_msgdef *m);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
-bool upb_msgdef_mapentry(const upb_msgdef *m);
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
-bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax);
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
-                                    size_t len);
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
-                                    size_t len);
-int upb_msgdef_numfields(const upb_msgdef *m);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
-
-UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
-                                               const char *name) {
-  return upb_msgdef_ntoo(m, name, strlen(name));
-}
-
-UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
-                                                const char *name) {
-  return upb_msgdef_ntof(m, name, strlen(name));
-}
-
-/* Internal-only. */
-size_t upb_msgdef_selectorcount(const upb_msgdef *m);
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m);
-
-/* Lookup of either field or oneof by name.  Returns whether either was found.
- * If the return is true, then the found def will be set, and the non-found
- * one set to NULL. */
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
-                           const upb_fielddef **f, const upb_oneofdef **o);
-
-UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
-                                       const upb_fielddef **f,
-                                       const upb_oneofdef **o) {
-  return upb_msgdef_lookupname(m, name, strlen(name), f, o);
-}
-
-/* Iteration over fields and oneofs.  For example:
- *
- * upb_msg_field_iter i;
- * for(upb_msg_field_begin(&i, m);
- *     !upb_msg_field_done(&i);
- *     upb_msg_field_next(&i)) {
- *   upb_fielddef *f = upb_msg_iter_field(&i);
- *   // ...
- * }
- *
- * For C we don't have separate iterators for const and non-const.
- * It is the caller's responsibility to cast the upb_fielddef* to
- * const if the upb_msgdef* is const. */
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
-void upb_msg_field_next(upb_msg_field_iter *iter);
-bool upb_msg_field_done(const upb_msg_field_iter *iter);
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
-                                const upb_msg_field_iter * iter2);
-
-/* Similar to above, we also support iterating through the oneofs in a
- * msgdef. */
-void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
-void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
-                                const upb_msg_oneof_iter *iter2);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Structure that describes a single .proto message type. */
-class upb::MessageDefPtr {
- public:
-  MessageDefPtr() : ptr_(nullptr) {}
-  explicit MessageDefPtr(const upb_msgdef *ptr) : ptr_(ptr) {}
-
-  const upb_msgdef *ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  const char* full_name() const { return upb_msgdef_fullname(ptr_); }
-  const char* name() const { return upb_msgdef_name(ptr_); }
-
-  /* The number of fields that belong to the MessageDef. */
-  int field_count() const { return upb_msgdef_numfields(ptr_); }
-
-  /* The number of oneofs that belong to the MessageDef. */
-  int oneof_count() const { return upb_msgdef_numoneofs(ptr_); }
-
-  upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); }
-
-  /* These return null pointers if the field is not found. */
-  FieldDefPtr FindFieldByNumber(uint32_t number) const {
-    return FieldDefPtr(upb_msgdef_itof(ptr_, number));
-  }
-  FieldDefPtr FindFieldByName(const char* name, size_t len) const {
-    return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len));
-  }
-  FieldDefPtr FindFieldByName(const char *name) const {
-    return FieldDefPtr(upb_msgdef_ntofz(ptr_, name));
-  }
-
-  template <class T>
-  FieldDefPtr FindFieldByName(const T& str) const {
-    return FindFieldByName(str.c_str(), str.size());
-  }
-
-  OneofDefPtr FindOneofByName(const char* name, size_t len) const {
-    return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len));
-  }
-
-  OneofDefPtr FindOneofByName(const char *name) const {
-    return OneofDefPtr(upb_msgdef_ntooz(ptr_, name));
-  }
-
-  template <class T>
-  OneofDefPtr FindOneofByName(const T &str) const {
-    return FindOneofByName(str.c_str(), str.size());
-  }
-
-  /* Is this message a map entry? */
-  bool mapentry() const { return upb_msgdef_mapentry(ptr_); }
-
-  /* Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for
-   * non-well-known message. */
-  upb_wellknowntype_t wellknowntype() const {
-    return upb_msgdef_wellknowntype(ptr_);
-  }
-
-  /* Whether is a number wrapper. */
-  bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); }
-
-  /* Iteration over fields.  The order is undefined. */
-  class const_field_iterator
-      : public std::iterator<std::forward_iterator_tag, FieldDefPtr> {
-   public:
-    void operator++() { upb_msg_field_next(&iter_); }
-
-    FieldDefPtr operator*() const {
-      return FieldDefPtr(upb_msg_iter_field(&iter_));
-    }
-
-    bool operator!=(const const_field_iterator &other) const {
-      return !upb_msg_field_iter_isequal(&iter_, &other.iter_);
-    }
-
-    bool operator==(const const_field_iterator &other) const {
-      return upb_msg_field_iter_isequal(&iter_, &other.iter_);
-    }
-
-   private:
-    friend class MessageDefPtr;
-
-    explicit const_field_iterator() {}
-
-    explicit const_field_iterator(MessageDefPtr msg) {
-      upb_msg_field_begin(&iter_, msg.ptr());
-    }
-
-    static const_field_iterator end() {
-      const_field_iterator iter;
-      upb_msg_field_iter_setdone(&iter.iter_);
-      return iter;
-    }
-
-    upb_msg_field_iter iter_;
-  };
-
-  /* Iteration over oneofs. The order is undefined. */
-  class const_oneof_iterator
-      : public std::iterator<std::forward_iterator_tag, OneofDefPtr> {
-   public:
-
-    void operator++() { upb_msg_oneof_next(&iter_); }
-
-    OneofDefPtr operator*() const {
-      return OneofDefPtr(upb_msg_iter_oneof(&iter_));
-    }
-
-    bool operator!=(const const_oneof_iterator& other) const {
-      return !upb_msg_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-    bool operator==(const const_oneof_iterator &other) const {
-      return upb_msg_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-   private:
-    friend class MessageDefPtr;
-
-    const_oneof_iterator() {}
-
-    explicit const_oneof_iterator(MessageDefPtr msg) {
-      upb_msg_oneof_begin(&iter_, msg.ptr());
-    }
-
-    static const_oneof_iterator end() {
-      const_oneof_iterator iter;
-      upb_msg_oneof_iter_setdone(&iter.iter_);
-      return iter;
-    }
-
-    upb_msg_oneof_iter iter_;
-  };
-
-  class ConstFieldAccessor {
-   public:
-    explicit ConstFieldAccessor(const upb_msgdef* md) : md_(md) {}
-    const_field_iterator begin() { return MessageDefPtr(md_).field_begin(); }
-    const_field_iterator end() { return MessageDefPtr(md_).field_end(); }
-   private:
-    const upb_msgdef* md_;
-  };
-
-  class ConstOneofAccessor {
-   public:
-    explicit ConstOneofAccessor(const upb_msgdef* md) : md_(md) {}
-    const_oneof_iterator begin() { return MessageDefPtr(md_).oneof_begin(); }
-    const_oneof_iterator end() { return MessageDefPtr(md_).oneof_end(); }
-   private:
-    const upb_msgdef* md_;
-  };
-
-  const_field_iterator field_begin() const {
-    return const_field_iterator(*this);
-  }
-
-  const_field_iterator field_end() const { return const_field_iterator::end(); }
-
-  const_oneof_iterator oneof_begin() const {
-    return const_oneof_iterator(*this);
-  }
-
-  const_oneof_iterator oneof_end() const { return const_oneof_iterator::end(); }
-
-  ConstFieldAccessor fields() const { return ConstFieldAccessor(ptr()); }
-  ConstOneofAccessor oneofs() const { return ConstOneofAccessor(ptr()); }
-
- private:
-  const upb_msgdef* ptr_;
-};
-
-inline upb::MessageDefPtr upb::FieldDefPtr::message_subdef() const {
-  return MessageDefPtr(upb_fielddef_msgsubdef(ptr_));
-}
-
-inline upb::MessageDefPtr upb::FieldDefPtr::containing_type() const {
-  return MessageDefPtr(upb_fielddef_containingtype(ptr_));
-}
-
-inline upb::MessageDefPtr upb::OneofDefPtr::containing_type() const {
-  return MessageDefPtr(upb_oneofdef_containingtype(ptr_));
-}
-
-#endif  /* __cplusplus */
-
-/* upb_enumdef ****************************************************************/
-
-typedef upb_strtable_iter upb_enum_iter;
-
-const char *upb_enumdef_fullname(const upb_enumdef *e);
-const char *upb_enumdef_name(const upb_enumdef *e);
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
-int32_t upb_enumdef_default(const upb_enumdef *e);
-int upb_enumdef_numvals(const upb_enumdef *e);
-
-/* Enum lookups:
- * - ntoi:  look up a name with specified length.
- * - ntoiz: look up a name provided as a null-terminated string.
- * - iton:  look up an integer, returning the name as a null-terminated
- *          string. */
-bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
-                      int32_t *num);
-UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
-                                  const char *name, int32_t *num) {
-  return upb_enumdef_ntoi(e, name, strlen(name), num);
-}
-const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
-
-/*  upb_enum_iter i;
- *  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
- *    // ...
- *  }
- */
-void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
-void upb_enum_next(upb_enum_iter *iter);
-bool upb_enum_done(upb_enum_iter *iter);
-const char *upb_enum_iter_name(upb_enum_iter *iter);
-int32_t upb_enum_iter_number(upb_enum_iter *iter);
-
-#ifdef __cplusplus
-
-class upb::EnumDefPtr {
- public:
-  EnumDefPtr() : ptr_(nullptr) {}
-  explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {}
-
-  const upb_enumdef* ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  const char* full_name() const { return upb_enumdef_fullname(ptr_); }
-  const char* name() const { return upb_enumdef_name(ptr_); }
-
-  /* The value that is used as the default when no field default is specified.
-   * If not set explicitly, the first value that was added will be used.
-   * The default value must be a member of the enum.
-   * Requires that value_count() > 0. */
-  int32_t default_value() const { return upb_enumdef_default(ptr_); }
-
-  /* Returns the number of values currently defined in the enum.  Note that
-   * multiple names can refer to the same number, so this may be greater than
-   * the total number of unique numbers. */
-  int value_count() const { return upb_enumdef_numvals(ptr_); }
-
-  /* Lookups from name to integer, returning true if found. */
-  bool FindValueByName(const char *name, int32_t *num) const {
-    return upb_enumdef_ntoiz(ptr_, name, num);
-  }
-
-  /* Finds the name corresponding to the given number, or NULL if none was
-   * found.  If more than one name corresponds to this number, returns the
-   * first one that was added. */
-  const char *FindValueByNumber(int32_t num) const {
-    return upb_enumdef_iton(ptr_, num);
-  }
-
-  /* Iteration over name/value pairs.  The order is undefined.
-   * Adding an enum val invalidates any iterators.
-   *
-   * TODO: make compatible with range-for, with elements as pairs? */
-  class Iterator {
-   public:
-    explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); }
-
-    int32_t number() { return upb_enum_iter_number(&iter_); }
-    const char *name() { return upb_enum_iter_name(&iter_); }
-    bool Done() { return upb_enum_done(&iter_); }
-    void Next() { return upb_enum_next(&iter_); }
-
-   private:
-    upb_enum_iter iter_;
-  };
-
- private:
-  const upb_enumdef *ptr_;
-};
-
-inline upb::EnumDefPtr upb::FieldDefPtr::enum_subdef() const {
-  return EnumDefPtr(upb_fielddef_enumsubdef(ptr_));
-}
-
-#endif  /* __cplusplus */
-
-/* upb_filedef ****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_filedef_name(const upb_filedef *f);
-const char *upb_filedef_package(const upb_filedef *f);
-const char *upb_filedef_phpprefix(const upb_filedef *f);
-const char *upb_filedef_phpnamespace(const upb_filedef *f);
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
-int upb_filedef_depcount(const upb_filedef *f);
-int upb_filedef_msgcount(const upb_filedef *f);
-int upb_filedef_enumcount(const upb_filedef *f);
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Class that represents a .proto file with some things defined in it.
- *
- * Many users won't care about FileDefs, but they are necessary if you want to
- * read the values of file-level options. */
-class upb::FileDefPtr {
- public:
-  explicit FileDefPtr(const upb_filedef *ptr) : ptr_(ptr) {}
-
-  const upb_filedef* ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  /* Get/set name of the file (eg. "foo/bar.proto"). */
-  const char* name() const { return upb_filedef_name(ptr_); }
-
-  /* Package name for definitions inside the file (eg. "foo.bar"). */
-  const char* package() const { return upb_filedef_package(ptr_); }
-
-  /* Sets the php class prefix which is prepended to all php generated classes
-   * from this .proto. Default is empty. */
-  const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); }
-
-  /* Use this option to change the namespace of php generated classes. Default
-   * is empty. When this option is empty, the package name will be used for
-   * determining the namespace. */
-  const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); }
-
-  /* Syntax for the file.  Defaults to proto2. */
-  upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); }
-
-  /* Get the list of dependencies from the file.  These are returned in the
-   * order that they were added to the FileDefPtr. */
-  int dependency_count() const { return upb_filedef_depcount(ptr_); }
-  const FileDefPtr dependency(int index) const {
-    return FileDefPtr(upb_filedef_dep(ptr_, index));
-  }
-
- private:
-  const upb_filedef* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_symtab *****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_symtab *upb_symtab_new(void);
-void upb_symtab_free(upb_symtab* s);
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
-const upb_msgdef *upb_symtab_lookupmsg2(
-    const upb_symtab *s, const char *sym, size_t len);
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
-const upb_filedef *upb_symtab_lookupfile2(
-    const upb_symtab *s, const char *name, size_t len);
-int upb_symtab_filecount(const upb_symtab *s);
-const upb_filedef *upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
-    upb_status *status);
-
-/* For generated code only: loads a generated descriptor. */
-typedef struct upb_def_init {
-  struct upb_def_init **deps;
-  const char *filename;
-  upb_strview descriptor;
-} upb_def_init;
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Non-const methods in upb::SymbolTable are NOT thread-safe. */
-class upb::SymbolTable {
- public:
-  SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {}
-  explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {}
-
-  const upb_symtab* ptr() const { return ptr_.get(); }
-  upb_symtab* ptr() { return ptr_.get(); }
-
-  /* Finds an entry in the symbol table with this exact name.  If not found,
-   * returns NULL. */
-  MessageDefPtr LookupMessage(const char *sym) const {
-    return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym));
-  }
-
-  EnumDefPtr LookupEnum(const char *sym) const {
-    return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym));
-  }
-
-  FileDefPtr LookupFile(const char *name) const {
-    return FileDefPtr(upb_symtab_lookupfile(ptr_.get(), name));
-  }
-
-  /* TODO: iteration? */
-
-  /* Adds the given serialized FileDescriptorProto to the pool. */
-  FileDefPtr AddFile(const google_protobuf_FileDescriptorProto *file_proto,
-                     Status *status) {
-    return FileDefPtr(
-        upb_symtab_addfile(ptr_.get(), file_proto, status->ptr()));
-  }
-
- private:
-  std::unique_ptr<upb_symtab, decltype(&upb_symtab_free)> ptr_;
-};
-
-UPB_INLINE const char* upb_safecstr(const std::string& str) {
-  UPB_ASSERT(str.size() == std::strlen(str.c_str()));
-  return str.c_str();
-}
-
-#endif  /* __cplusplus */
-
-
-#endif /* UPB_DEF_H_ */
-
-
-#ifndef UPB_MSGFACTORY_H_
-#define UPB_MSGFACTORY_H_
-
-/** upb_msgfactory ************************************************************/
-
-struct upb_msgfactory;
-typedef struct upb_msgfactory upb_msgfactory;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and
- * upb_visitorplan objects.  These are the objects necessary to represent,
- * populate, and and visit upb_msg objects.
- *
- * These caches are all populated by upb_msgdef, and lazily created on demand.
- */
-
-/* Creates and destroys a msgfactory, respectively.  The messages for this
- * msgfactory must come from |symtab| (which should outlive the msgfactory). */
-upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab);
-void upb_msgfactory_free(upb_msgfactory *f);
-
-const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f);
-
-/* The functions to get cached objects, lazily creating them on demand.  These
- * all require:
- *
- * - m is in upb_msgfactory_symtab(f)
- * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts).
- *
- * The returned objects will live for as long as the msgfactory does.
- *
- * TODO(haberman): consider making this thread-safe and take a const
- * upb_msgfactory. */
-const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
-                                              const upb_msgdef *m);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif /* UPB_MSGFACTORY_H_ */
-/*
-** upb::Handlers (upb_handlers)
-**
-** A upb_handlers is like a virtual table for a upb_msgdef.  Each field of the
-** message can have associated functions that will be called when we are
-** parsing or visiting a stream of data.  This is similar to how handlers work
-** in SAX (the Simple API for XML).
-**
-** The handlers have no idea where the data is coming from, so a single set of
-** handlers could be used with two completely different data sources (for
-** example, a parser and a visitor over in-memory objects).  This decoupling is
-** the most important feature of upb, because it allows parsers and serializers
-** to be highly reusable.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_HANDLERS_H
-#define UPB_HANDLERS_H
-
-
-
-#ifdef __cplusplus
-namespace upb {
-class HandlersPtr;
-class HandlerCache;
-template <class T> class Handler;
-template <class T> struct CanonicalType;
-}  /* namespace upb */
-#endif
-
-
-/* The maximum depth that the handler graph can have.  This is a resource limit
- * for the C stack since we sometimes need to recursively traverse the graph.
- * Cycles are ok; the traversal will stop when it detects a cycle, but we must
- * hit the cycle before the maximum depth is reached.
- *
- * If having a single static limit is too inflexible, we can add another variant
- * of Handlers::Freeze that allows specifying this as a parameter. */
-#define UPB_MAX_HANDLER_DEPTH 64
-
-/* All the different types of handlers that can be registered.
- * Only needed for the advanced functions in upb::Handlers. */
-typedef enum {
-  UPB_HANDLER_INT32,
-  UPB_HANDLER_INT64,
-  UPB_HANDLER_UINT32,
-  UPB_HANDLER_UINT64,
-  UPB_HANDLER_FLOAT,
-  UPB_HANDLER_DOUBLE,
-  UPB_HANDLER_BOOL,
-  UPB_HANDLER_STARTSTR,
-  UPB_HANDLER_STRING,
-  UPB_HANDLER_ENDSTR,
-  UPB_HANDLER_STARTSUBMSG,
-  UPB_HANDLER_ENDSUBMSG,
-  UPB_HANDLER_STARTSEQ,
-  UPB_HANDLER_ENDSEQ
-} upb_handlertype_t;
-
-#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1)
-
-#define UPB_BREAK NULL
-
-/* A convenient definition for when no closure is needed. */
-extern char _upb_noclosure;
-#define UPB_NO_CLOSURE &_upb_noclosure
-
-/* A selector refers to a specific field handler in the Handlers object
- * (for example: the STARTSUBMSG handler for field "field15"). */
-typedef int32_t upb_selector_t;
-
-/* Static selectors for upb::Handlers. */
-#define UPB_STARTMSG_SELECTOR 0
-#define UPB_ENDMSG_SELECTOR 1
-#define UPB_UNKNOWN_SELECTOR 2
-#define UPB_STATIC_SELECTOR_COUNT 3  /* Warning: also in upb/def.c. */
-
-/* Static selectors for upb::BytesHandler. */
-#define UPB_STARTSTR_SELECTOR 0
-#define UPB_STRING_SELECTOR 1
-#define UPB_ENDSTR_SELECTOR 2
-
-#ifdef __cplusplus
-template<class T> const void *UniquePtrForType() {
-  static const char ch = 0;
-  return &ch;
-}
-#endif
-
-/* upb_handlers ************************************************************/
-
-/* Handler attributes, to be registered with the handler itself. */
-typedef struct {
-  const void *handler_data;
-  const void *closure_type;
-  const void *return_closure_type;
-  bool alwaysok;
-} upb_handlerattr;
-
-#define UPB_HANDLERATTR_INIT {NULL, NULL, NULL, false}
-
-/* Bufhandle, data passed along with a buffer to indicate its provenance. */
-typedef struct {
-  /* The beginning of the buffer.  This may be different than the pointer
-   * passed to a StringBuf handler because the handler may receive data
-   * that is from the middle or end of a larger buffer. */
-  const char *buf;
-
-  /* The offset within the attached object where this buffer begins.  Only
-   * meaningful if there is an attached object. */
-  size_t objofs;
-
-  /* The attached object (if any) and a pointer representing its type. */
-  const void *obj;
-  const void *objtype;
-
-#ifdef __cplusplus
-  template <class T>
-  void SetAttachedObject(const T* _obj) {
-    obj = _obj;
-    objtype = UniquePtrForType<T>();
-  }
-
-  template <class T>
-  const T *GetAttachedObject() const {
-    return objtype == UniquePtrForType<T>() ? static_cast<const T *>(obj)
-                                            : NULL;
-  }
-#endif
-} upb_bufhandle;
-
-#define UPB_BUFHANDLE_INIT {NULL, 0, NULL, NULL}
-
-/* Handler function typedefs. */
-typedef void upb_handlerfree(void *d);
-typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf,
-                                     size_t n);
-typedef bool upb_startmsg_handlerfunc(void *c, const void*);
-typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
-typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
-typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
-typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
-typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
-typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
-typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
-typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
-typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
-                                       size_t size_hint);
-typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
-                                      size_t n, const upb_bufhandle* handle);
-
-struct upb_handlers;
-typedef struct upb_handlers upb_handlers;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Mutating accessors. */
-const upb_status *upb_handlers_status(upb_handlers *h);
-void upb_handlers_clearerr(upb_handlers *h);
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
-                             const upb_handlerattr *attr);
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
-                           upb_int32_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
-                           upb_int64_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
-                            upb_uint32_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
-                            upb_uint64_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
-                           upb_float_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
-                            upb_double_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
-                          upb_bool_handlerfunc *func,
-                          const upb_handlerattr *attr);
-bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
-                              upb_startstr_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
-                            upb_string_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
-                            upb_endfield_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
-                              upb_startfield_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
-                                 upb_startfield_handlerfunc *func,
-                                 const upb_handlerattr *attr);
-bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
-                               upb_endfield_handlerfunc *func,
-                               const upb_handlerattr *attr);
-bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
-                            upb_endfield_handlerfunc *func,
-                            const upb_handlerattr *attr);
-
-/* Read-only accessors. */
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
-                                                const upb_fielddef *f);
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
-                                                    upb_selector_t sel);
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
-                                  const void **handler_data);
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
-                          upb_handlerattr *attr);
-
-/* "Static" methods */
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
-                              upb_selector_t *s);
-UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
-  return start + 1;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-typedef upb_handlers Handlers;
-}
-
-/* Convenience macros for creating a Handler object that is wrapped with a
- * type-safe wrapper function that converts the "void*" parameters/returns
- * of the underlying C API into nice C++ function.
- *
- * Sample usage:
- *   void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
- *     // do stuff ...
- *   }
- *
- *   // Handler that doesn't need any data bound to it.
- *   void OnValue2(MyClosure* c, int32_t val) {
- *     // do stuff ...
- *   }
- *
- *   // Handler that returns bool so it can return failure if necessary.
- *   bool OnValue3(MyClosure* c, int32_t val) {
- *     // do stuff ...
- *     return ok;
- *   }
- *
- *   // Member function handler.
- *   class MyClosure {
- *    public:
- *     void OnValue(int32_t val) {
- *       // do stuff ...
- *     }
- *   };
- *
- *   // Takes ownership of the MyHandlerData.
- *   handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
- *   handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
- *   handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
- *   handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
- */
-
-/* In C++11, the "template" disambiguator can appear even outside templates,
- * so all calls can safely use this pair of macros. */
-
-#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>()
-
-/* We have to be careful to only evaluate "d" once. */
-#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
-
-/* Handler: a struct that contains the (handler, data, deleter) tuple that is
- * used to register all handlers.  Users can Make() these directly but it's
- * more convenient to use the UpbMakeHandler/UpbBind macros above. */
-template <class T> class upb::Handler {
- public:
-  /* The underlying, handler function signature that upb uses internally. */
-  typedef T FuncPtr;
-
-  /* Intentionally implicit. */
-  template <class F> Handler(F func);
-  ~Handler() { UPB_ASSERT(registered_); }
-
-  void AddCleanup(upb_handlers* h) const;
-  FuncPtr handler() const { return handler_; }
-  const upb_handlerattr& attr() const { return attr_; }
-
- private:
-  Handler(const Handler&) = delete;
-  Handler& operator=(const Handler&) = delete;
-
-  FuncPtr handler_;
-  mutable upb_handlerattr attr_;
-  mutable bool registered_;
-  void *cleanup_data_;
-  upb_handlerfree *cleanup_func_;
-};
-
-/* A upb::Handlers object represents the set of handlers associated with a
- * message in the graph of messages.  You can think of it as a big virtual
- * table with functions corresponding to all the events that can fire while
- * parsing or visiting a message of a specific type.
- *
- * Any handlers that are not set behave as if they had successfully consumed
- * the value.  Any unset Start* handlers will propagate their closure to the
- * inner frame.
- *
- * The easiest way to create the *Handler objects needed by the Set* methods is
- * with the UpbBind() and UpbMakeHandler() macros; see below. */
-class upb::HandlersPtr {
- public:
-  HandlersPtr(upb_handlers* ptr) : ptr_(ptr) {}
-
-  upb_handlers* ptr() const { return ptr_; }
-
-  typedef upb_selector_t Selector;
-  typedef upb_handlertype_t Type;
-
-  typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
-  typedef Handler<bool (*)(void *, const void *)> EndFieldHandler;
-  typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
-  typedef Handler<bool (*)(void *, const void *, upb_status *)>
-      EndMessageHandler;
-  typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
-  typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
-                             const upb_bufhandle *)>
-      StringHandler;
-
-  template <class T> struct ValueHandler {
-    typedef Handler<bool(*)(void *, const void *, T)> H;
-  };
-
-  typedef ValueHandler<int32_t>::H     Int32Handler;
-  typedef ValueHandler<int64_t>::H     Int64Handler;
-  typedef ValueHandler<uint32_t>::H    UInt32Handler;
-  typedef ValueHandler<uint64_t>::H    UInt64Handler;
-  typedef ValueHandler<float>::H       FloatHandler;
-  typedef ValueHandler<double>::H      DoubleHandler;
-  typedef ValueHandler<bool>::H        BoolHandler;
-
-  /* Any function pointer can be converted to this and converted back to its
-   * correct type. */
-  typedef void GenericFunction();
-
-  typedef void HandlersCallback(const void *closure, upb_handlers *h);
-
-  /* Returns the msgdef associated with this handlers object. */
-  MessageDefPtr message_def() const {
-    return MessageDefPtr(upb_handlers_msgdef(ptr()));
-  }
-
-  /* Adds the given pointer and function to the list of cleanup functions that
-   * will be run when these handlers are freed.  If this pointer has previously
-   * been registered, the function returns false and does nothing. */
-  bool AddCleanup(void *ptr, upb_handlerfree *cleanup) {
-    return upb_handlers_addcleanup(ptr_, ptr, cleanup);
-  }
-
-  /* Sets the startmsg handler for the message, which is defined as follows:
-   *
-   *   bool startmsg(MyType* closure) {
-   *     // Called when the message begins.  Returns true if processing should
-   *     // continue.
-   *     return true;
-   *   }
-   */
-  bool SetStartMessageHandler(const StartMessageHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartmsg(ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the endmsg handler for the message, which is defined as follows:
-   *
-   *   bool endmsg(MyType* closure, upb_status *status) {
-   *     // Called when processing of this message ends, whether in success or
-   *     // failure.  "status" indicates the final status of processing, and
-   *     // can also be modified in-place to update the final status.
-   *   }
-   */
-  bool SetEndMessageHandler(const EndMessageHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendmsg(ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the value handler for the given field, which is defined as follows
-   * (this is for an int32 field; other field types will pass their native
-   * C/C++ type for "val"):
-   *
-   *   bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
-   *     // Called when the field's value is encountered.  "d" contains
-   *     // whatever data was bound to this field when it was registered.
-   *     // Returns true if processing should continue.
-   *     return true;
-   *   }
-   *
-   *   handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...)));
-   *
-   * The value type must exactly match f->type().
-   * For example, a handler that takes an int32_t parameter may only be used for
-   * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM.
-   *
-   * Returns false if the handler failed to register; in this case the cleanup
-   * handler (if any) will be called immediately.
-   */
-  bool SetInt32Handler(FieldDefPtr f, const Int32Handler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setint32(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetInt64Handler (FieldDefPtr f,  const Int64Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setint64(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetUInt32Handler(FieldDefPtr f, const UInt32Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setuint32(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetUInt64Handler(FieldDefPtr f, const UInt64Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setuint64(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetFloatHandler (FieldDefPtr f,  const FloatHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setfloat(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetDoubleHandler(FieldDefPtr f, const DoubleHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setdouble(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetBoolHandler(FieldDefPtr f, const BoolHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setbool(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Like the previous, but templated on the type on the value (ie. int32).
-   * This is mostly useful to call from other templates.  To call this you must
-   * specify the template parameter explicitly, ie:
-   *   h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); */
-  template <class T>
-  bool SetValueHandler(
-      FieldDefPtr f,
-      const typename ValueHandler<typename CanonicalType<T>::Type>::H &handler);
-
-  /* Sets handlers for a string field, which are defined as follows:
-   *
-   *   MySubClosure* startstr(MyClosure* c, const MyHandlerData* d,
-   *                          size_t size_hint) {
-   *     // Called when a string value begins.  The return value indicates the
-   *     // closure for the string.  "size_hint" indicates the size of the
-   *     // string if it is known, however if the string is length-delimited
-   *     // and the end-of-string is not available size_hint will be zero.
-   *     // This case is indistinguishable from the case where the size is
-   *     // known to be zero.
-   *     //
-   *     // TODO(haberman): is it important to distinguish these cases?
-   *     // If we had ssize_t as a type we could make -1 "unknown", but
-   *     // ssize_t is POSIX (not ANSI) and therefore less portable.
-   *     // In practice I suspect it won't be important to distinguish.
-   *     return closure;
-   *   }
-   *
-   *   size_t str(MyClosure* closure, const MyHandlerData* d,
-   *              const char *str, size_t len) {
-   *     // Called for each buffer of string data; the multiple physical buffers
-   *     // are all part of the same logical string.  The return value indicates
-   *     // how many bytes were consumed.  If this number is less than "len",
-   *     // this will also indicate that processing should be halted for now,
-   *     // like returning false or UPB_BREAK from any other callback.  If
-   *     // number is greater than "len", the excess bytes will be skipped over
-   *     // and not passed to the callback.
-   *     return len;
-   *   }
-   *
-   *   bool endstr(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a string value ends.  Return value indicates whether
-   *     // processing should continue.
-   *     return true;
-   *   }
-   */
-  bool SetStartStringHandler(FieldDefPtr f, const StartStringHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartstr(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetStringHandler(FieldDefPtr f, const StringHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstring(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetEndStringHandler(FieldDefPtr f, const EndFieldHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendstr(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the startseq handler, which is defined as follows:
-   *
-   *   MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a sequence (repeated field) begins.  The returned
-   *     // pointer indicates the closure for the sequence (or UPB_BREAK
-   *     // to interrupt processing).
-   *     return closure;
-   *   }
-   *
-   *   h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...)));
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * repeated field.
-   */
-  bool SetStartSequenceHandler(FieldDefPtr f, const StartFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartseq(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the startsubmsg handler for the given field, which is defined as
-   * follows:
-   *
-   *   MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a submessage begins.  The returned pointer indicates the
-   *     // closure for the sequence (or UPB_BREAK to interrupt processing).
-   *     return closure;
-   *   }
-   *
-   *   h->SetStartSubMessageHandler(f, UpbBind(startsubmsg,
-   *                                           new MyHandlerData(...)));
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * submessage/group field.
-   */
-  bool SetStartSubMessageHandler(FieldDefPtr f, const StartFieldHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the endsubmsg handler for the given field, which is defined as
-   * follows:
-   *
-   *   bool endsubmsg(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a submessage ends.  Returns true to continue processing.
-   *     return true;
-   *   }
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * submessage/group field.
-   */
-  bool SetEndSubMessageHandler(FieldDefPtr f, const EndFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Starts the endsubseq handler for the given field, which is defined as
-   * follows:
-   *
-   *   bool endseq(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a sequence ends.  Returns true continue processing.
-   *     return true;
-   *   }
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * repeated field.
-   */
-  bool SetEndSequenceHandler(FieldDefPtr f, const EndFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendseq(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
- private:
-  upb_handlers* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_handlercache ***********************************************************/
-
-/* A upb_handlercache lazily builds and caches upb_handlers.  You pass it a
- * function (with optional closure) that can build handlers for a given
- * message on-demand, and the cache maintains a map of msgdef->handlers. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct upb_handlercache;
-typedef struct upb_handlercache upb_handlercache;
-
-typedef void upb_handlers_callback(const void *closure, upb_handlers *h);
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
-                                       const void *closure);
-void upb_handlercache_free(upb_handlercache *cache);
-const upb_handlers *upb_handlercache_get(upb_handlercache *cache,
-                                         const upb_msgdef *md);
-bool upb_handlercache_addcleanup(upb_handlercache *h, void *p,
-                                 upb_handlerfree *hfree);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::HandlerCache {
- public:
-  HandlerCache(upb_handlers_callback *callback, const void *closure)
-      : ptr_(upb_handlercache_new(callback, closure), upb_handlercache_free) {}
-  HandlerCache(HandlerCache&&) = default;
-  HandlerCache& operator=(HandlerCache&&) = default;
-  HandlerCache(upb_handlercache* c) : ptr_(c, upb_handlercache_free) {}
-
-  upb_handlercache* ptr() { return ptr_.get(); }
-
-  const upb_handlers *Get(MessageDefPtr md) {
-    return upb_handlercache_get(ptr_.get(), md.ptr());
-  }
-
- private:
-  std::unique_ptr<upb_handlercache, decltype(&upb_handlercache_free)> ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_byteshandler ***********************************************************/
-
-typedef struct {
-  upb_func *func;
-
-  /* It is wasteful to include the entire attributes here:
-   *
-   * * Some of the information is redundant (like storing the closure type
-   *   separately for each handler that must match).
-   * * Some of the info is only needed prior to freeze() (like closure types).
-   * * alignment padding wastes a lot of space for alwaysok_.
-   *
-   * If/when the size and locality of handlers is an issue, we can optimize this
-   * not to store the entire attr like this.  We do not expose the table's
-   * layout to allow this optimization in the future. */
-  upb_handlerattr attr;
-} upb_handlers_tabent;
-
-#define UPB_TABENT_INIT {NULL, UPB_HANDLERATTR_INIT}
-
-typedef struct {
-  upb_handlers_tabent table[3];
-} upb_byteshandler;
-
-#define UPB_BYTESHANDLER_INIT                             \
-  {                                                       \
-    { UPB_TABENT_INIT, UPB_TABENT_INIT, UPB_TABENT_INIT } \
-  }
-
-UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) {
-  upb_byteshandler init = UPB_BYTESHANDLER_INIT;
-  *handler = init;
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Caller must ensure that "d" outlives the handlers. */
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
-                                  upb_startstr_handlerfunc *func, void *d);
-bool upb_byteshandler_setstring(upb_byteshandler *h,
-                                upb_string_handlerfunc *func, void *d);
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
-                                upb_endfield_handlerfunc *func, void *d);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-typedef upb_byteshandler BytesHandler;
-}
-#endif
-
-/** Message handlers ******************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* These are the handlers used internally by upb_msgfactory_getmergehandlers().
- * They write scalar data to a known offset from the message pointer.
- *
- * These would be trivial for anyone to implement themselves, but it's better
- * to use these because some JITs will recognize and specialize these instead
- * of actually calling the function. */
-
-/* Sets a handler for the given primitive field that will write the data at the
- * given offset.  If hasbit > 0, also sets a hasbit at the given bit offset
- * (addressing each byte low to high). */
-bool upb_msg_setscalarhandler(upb_handlers *h,
-                              const upb_fielddef *f,
-                              size_t offset,
-                              int32_t hasbit);
-
-/* If the given handler is a msghandlers_primitive field, returns true and sets
- * *type, *offset and *hasbit.  Otherwise returns false. */
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
-                                  upb_selector_t s,
-                                  upb_fieldtype_t *type,
-                                  size_t *offset,
-                                  int32_t *hasbit);
-
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-/*
-** Inline definitions for handlers.h, which are particularly long and a bit
-** tricky.
-*/
-
-#ifndef UPB_HANDLERS_INL_H_
-#define UPB_HANDLERS_INL_H_
-
-#include <limits.h>
-#include <stddef.h>
-
-
-#ifdef __cplusplus
-
-/* Type detection and typedefs for integer types.
- * For platforms where there are multiple 32-bit or 64-bit types, we need to be
- * able to enumerate them so we can properly create overloads for all variants.
- *
- * If any platform existed where there were three integer types with the same
- * size, this would have to become more complicated.  For example, short, int,
- * and long could all be 32-bits.  Even more diabolically, short, int, long,
- * and long long could all be 64 bits and still be standard-compliant.
- * However, few platforms are this strange, and it's unlikely that upb will be
- * used on the strangest ones. */
-
-/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are
- * only defined when __STDC_LIMIT_MACROS are defined before the *first* include
- * of stdint.h.  We can't guarantee that someone else didn't include these first
- * without defining __STDC_LIMIT_MACROS. */
-#define UPB_INT32_MAX 0x7fffffffLL
-#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
-#define UPB_INT64_MAX 0x7fffffffffffffffLL
-#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
-
-#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
-#define UPB_INT_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
-#define UPB_LONG_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
-#define UPB_LONG_IS_64BITS 1
-#endif
-
-#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
-#define UPB_LLONG_IS_64BITS 1
-#endif
-
-/* We use macros instead of typedefs so we can undefine them later and avoid
- * leaking them outside this header file. */
-#if UPB_INT_IS_32BITS
-#define UPB_INT32_T int
-#define UPB_UINT32_T unsigned int
-
-#if UPB_LONG_IS_32BITS
-#define UPB_TWO_32BIT_TYPES 1
-#define UPB_INT32ALT_T long
-#define UPB_UINT32ALT_T unsigned long
-#endif  /* UPB_LONG_IS_32BITS */
-
-#elif UPB_LONG_IS_32BITS  /* && !UPB_INT_IS_32BITS */
-#define UPB_INT32_T long
-#define UPB_UINT32_T unsigned long
-#endif  /* UPB_INT_IS_32BITS */
-
-
-#if UPB_LONG_IS_64BITS
-#define UPB_INT64_T long
-#define UPB_UINT64_T unsigned long
-
-#if UPB_LLONG_IS_64BITS
-#define UPB_TWO_64BIT_TYPES 1
-#define UPB_INT64ALT_T long long
-#define UPB_UINT64ALT_T unsigned long long
-#endif  /* UPB_LLONG_IS_64BITS */
-
-#elif UPB_LLONG_IS_64BITS  /* && !UPB_LONG_IS_64BITS */
-#define UPB_INT64_T long long
-#define UPB_UINT64_T unsigned long long
-#endif  /* UPB_LONG_IS_64BITS */
-
-#undef UPB_INT32_MAX
-#undef UPB_INT32_MIN
-#undef UPB_INT64_MAX
-#undef UPB_INT64_MIN
-#undef UPB_INT_IS_32BITS
-#undef UPB_LONG_IS_32BITS
-#undef UPB_LONG_IS_64BITS
-#undef UPB_LLONG_IS_64BITS
-
-
-namespace upb {
-
-typedef void CleanupFunc(void *ptr);
-
-/* Template to remove "const" from "const T*" and just return "T*".
- *
- * We define a nonsense default because otherwise it will fail to instantiate as
- * a function parameter type even in cases where we don't expect any caller to
- * actually match the overload. */
-class CouldntRemoveConst {};
-template <class T> struct remove_constptr { typedef CouldntRemoveConst type; };
-template <class T> struct remove_constptr<const T *> { typedef T *type; };
-
-/* Template that we use below to remove a template specialization from
- * consideration if it matches a specific type. */
-template <class T, class U> struct disable_if_same { typedef void Type; };
-template <class T> struct disable_if_same<T, T> {};
-
-template <class T> void DeletePointer(void *p) { delete static_cast<T>(p); }
-
-template <class T1, class T2>
-struct FirstUnlessVoidOrBool {
-  typedef T1 value;
-};
-
-template <class T2>
-struct FirstUnlessVoidOrBool<void, T2> {
-  typedef T2 value;
-};
-
-template <class T2>
-struct FirstUnlessVoidOrBool<bool, T2> {
-  typedef T2 value;
-};
-
-template<class T, class U>
-struct is_same {
-  static bool value;
-};
-
-template<class T>
-struct is_same<T, T> {
-  static bool value;
-};
-
-template<class T, class U>
-bool is_same<T, U>::value = false;
-
-template<class T>
-bool is_same<T, T>::value = true;
-
-/* FuncInfo *******************************************************************/
-
-/* Info about the user's original, pre-wrapped function. */
-template <class C, class R = void>
-struct FuncInfo {
-  /* The type of the closure that the function takes (its first param). */
-  typedef C Closure;
-
-  /* The return type. */
-  typedef R Return;
-};
-
-/* Func ***********************************************************************/
-
-/* Func1, Func2, Func3: Template classes representing a function and its
- * signature.
- *
- * Since the function is a template parameter, calling the function can be
- * inlined at compile-time and does not require a function pointer at runtime.
- * These functions are not bound to a handler data so have no data or cleanup
- * handler. */
-struct UnboundFunc {
-  CleanupFunc *GetCleanup() { return nullptr; }
-  void *GetData() { return nullptr; }
-};
-
-template <class R, class P1, R F(P1), class I>
-struct Func1 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1) { return F(p1); }
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I>
-struct Func2 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2) { return F(p1, p2); }
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
-struct Func3 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I>
-struct Func4 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I>
-struct Func5 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
-    return F(p1, p2, p3, p4, p5);
-  }
-};
-
-/* BoundFunc ******************************************************************/
-
-/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
- * shall be bound to the function's second parameter.
- * 
- * Note that the second parameter is a const pointer, but our stored bound value
- * is non-const so we can free it when the handlers are destroyed. */
-template <class T>
-struct BoundFunc {
-  typedef typename remove_constptr<T>::type MutableP2;
-  explicit BoundFunc(MutableP2 data_) : data(data_) {}
-  CleanupFunc *GetCleanup() { return &DeletePointer<MutableP2>; }
-  MutableP2 GetData() { return data; }
-  MutableP2 data;
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I>
-struct BoundFunc2 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
-struct BoundFunc3 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I>
-struct BoundFunc4 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I>
-struct BoundFunc5 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-/* FuncSig ********************************************************************/
-
-/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
- * *signature*, but without a specific function attached.
- *
- * These classes contain member functions that can be invoked with a
- * specific function to return a Func/BoundFunc class. */
-template <class R, class P1>
-struct FuncSig1 {
-  template <R F(P1)>
-  Func1<R, P1, F, FuncInfo<P1, R> > GetFunc() {
-    return Func1<R, P1, F, FuncInfo<P1, R> >();
-  }
-};
-
-template <class R, class P1, class P2>
-struct FuncSig2 {
-  template <R F(P1, P2)>
-  Func2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc() {
-    return Func2<R, P1, P2, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2)>
-  BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3>
-struct FuncSig3 {
-  template <R F(P1, P2, P3)>
-  Func3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc() {
-    return Func3<R, P1, P2, P3, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3)>
-  BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3, class P4>
-struct FuncSig4 {
-  template <R F(P1, P2, P3, P4)>
-  Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc() {
-    return Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3, P4)>
-  BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-struct FuncSig5 {
-  template <R F(P1, P2, P3, P4, P5)>
-  Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc() {
-    return Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3, P4, P5)>
-  BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-/* Overloaded template function that can construct the appropriate FuncSig*
- * class given a function pointer by deducing the template parameters. */
-template <class R, class P1>
-inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig1<R, P1>();
-}
-
-template <class R, class P1, class P2>
-inline FuncSig2<R, P1, P2> MatchFunc(R (*f)(P1, P2)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig2<R, P1, P2>();
-}
-
-template <class R, class P1, class P2, class P3>
-inline FuncSig3<R, P1, P2, P3> MatchFunc(R (*f)(P1, P2, P3)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig3<R, P1, P2, P3>();
-}
-
-template <class R, class P1, class P2, class P3, class P4>
-inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig4<R, P1, P2, P3, P4>();
-}
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig5<R, P1, P2, P3, P4, P5>();
-}
-
-/* MethodSig ******************************************************************/
-
-/* CallMethod*: a function template that calls a given method. */
-template <class R, class C, R (C::*F)()>
-R CallMethod0(C *obj) {
-  return ((*obj).*F)();
-}
-
-template <class R, class C, class P1, R (C::*F)(P1)>
-R CallMethod1(C *obj, P1 arg1) {
-  return ((*obj).*F)(arg1);
-}
-
-template <class R, class C, class P1, class P2, R (C::*F)(P1, P2)>
-R CallMethod2(C *obj, P1 arg1, P2 arg2) {
-  return ((*obj).*F)(arg1, arg2);
-}
-
-template <class R, class C, class P1, class P2, class P3, R (C::*F)(P1, P2, P3)>
-R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
-  return ((*obj).*F)(arg1, arg2, arg3);
-}
-
-template <class R, class C, class P1, class P2, class P3, class P4,
-          R (C::*F)(P1, P2, P3, P4)>
-R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) {
-  return ((*obj).*F)(arg1, arg2, arg3, arg4);
-}
-
-/* MethodSig: like FuncSig, but for member functions.
- *
- * GetFunc() returns a normal FuncN object, so after calling GetFunc() no
- * more logic is required to special-case methods. */
-template <class R, class C>
-struct MethodSig0 {
-  template <R (C::*F)()>
-  Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> > GetFunc() {
-    return Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> >();
-  }
-};
-
-template <class R, class C, class P1>
-struct MethodSig1 {
-  template <R (C::*F)(P1)>
-  Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc() {
-    return Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1)>
-  BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc(
-      typename remove_constptr<P1>::type param1) {
-    return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >(
-        param1);
-  }
-};
-
-template <class R, class C, class P1, class P2>
-struct MethodSig2 {
-  template <R (C::*F)(P1, P2)>
-  Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
-  GetFunc() {
-    return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2)>
-  BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
-                      FuncInfo<C *, R> >(param1);
-  }
-};
-
-template <class R, class C, class P1, class P2, class P3>
-struct MethodSig3 {
-  template <R (C::*F)(P1, P2, P3)>
-  Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>, FuncInfo<C *, R> >
-  GetFunc() {
-    return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2, P3)>
-  BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-             FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-                      FuncInfo<C *, R> >(param1);
-  }
-};
-
-template <class R, class C, class P1, class P2, class P3, class P4>
-struct MethodSig4 {
-  template <R (C::*F)(P1, P2, P3, P4)>
-  Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-        FuncInfo<C *, R> >
-  GetFunc() {
-    return Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2, P3, P4)>
-  BoundFunc5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-             FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc5<R, C *, P1, P2, P3, P4,
-                      CallMethod4<R, C, P1, P2, P3, P4, F>, FuncInfo<C *, R> >(
-        param1);
-  }
-};
-
-template <class R, class C>
-inline MethodSig0<R, C> MatchFunc(R (C::*f)()) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig0<R, C>();
-}
-
-template <class R, class C, class P1>
-inline MethodSig1<R, C, P1> MatchFunc(R (C::*f)(P1)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig1<R, C, P1>();
-}
-
-template <class R, class C, class P1, class P2>
-inline MethodSig2<R, C, P1, P2> MatchFunc(R (C::*f)(P1, P2)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig2<R, C, P1, P2>();
-}
-
-template <class R, class C, class P1, class P2, class P3>
-inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig3<R, C, P1, P2, P3>();
-}
-
-template <class R, class C, class P1, class P2, class P3, class P4>
-inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig4<R, C, P1, P2, P3, P4>();
-}
-
-/* MaybeWrapReturn ************************************************************/
-
-/* Template class that attempts to wrap the return value of the function so it
- * matches the expected type.  There are two main adjustments it may make:
- *
- *   1. If the function returns void, make it return the expected type and with
- *      a value that always indicates success.
- *   2. If the function returns bool, make it return the expected type with a
- *      value that indicates success or failure.
- *
- * The "expected type" for return is:
- *   1. void* for start handlers.  If the closure parameter has a different type
- *      we will cast it to void* for the return in the success case.
- *   2. size_t for string buffer handlers.
- *   3. bool for everything else. */
-
-/* Template parameters are FuncN type and desired return type. */
-template <class F, class R, class Enable = void>
-struct MaybeWrapReturn;
-
-/* If the return type matches, return the given function unwrapped. */
-template <class F>
-struct MaybeWrapReturn<F, typename F::Return> {
-  typedef F Func;
-};
-
-/* Function wrapper that munges the return value from void to (bool)true. */
-template <class P1, class P2, void F(P1, P2)>
-bool ReturnTrue2(P1 p1, P2 p2) {
-  F(p1, p2);
-  return true;
-}
-
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-bool ReturnTrue3(P1 p1, P2 p2, P3 p3) {
-  F(p1, p2, p3);
-  return true;
-}
-
-/* Function wrapper that munges the return value from void to (void*)arg1  */
-template <class P1, class P2, void F(P1, P2)>
-void *ReturnClosure2(P1 p1, P2 p2) {
-  F(p1, p2);
-  return p1;
-}
-
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-void *ReturnClosure3(P1 p1, P2 p2, P3 p3) {
-  F(p1, p2, p3);
-  return p1;
-}
-
-/* Function wrapper that munges the return value from R to void*. */
-template <class R, class P1, class P2, R F(P1, P2)>
-void *CastReturnToVoidPtr2(P1 p1, P2 p2) {
-  return F(p1, p2);
-}
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) {
-  return F(p1, p2, p3);
-}
-
-/* Function wrapper that munges the return value from bool to void*. */
-template <class P1, class P2, bool F(P1, P2)>
-void *ReturnClosureOrBreak2(P1 p1, P2 p2) {
-  return F(p1, p2) ? p1 : UPB_BREAK;
-}
-
-template <class P1, class P2, class P3, bool F(P1, P2, P3)>
-void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) {
-  return F(p1, p2, p3) ? p1 : UPB_BREAK;
-}
-
-/* For the string callback, which takes five params, returns the size param. */
-template <class P1, class P2,
-          void F(P1, P2, const char *, size_t, const upb_bufhandle *)>
-size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4,
-                       const upb_bufhandle *p5) {
-  F(p1, p2, p3, p4, p5);
-  return p4;
-}
-
-/* For the string callback, which takes five params, returns the size param or
- * zero. */
-template <class P1, class P2,
-          bool F(P1, P2, const char *, size_t, const upb_bufhandle *)>
-size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4,
-                  const upb_bufhandle *p5) {
-  return F(p1, p2, p3, p4, p5) ? p4 : 0;
-}
-
-/* If we have a function returning void but want a function returning bool, wrap
- * it in a function that returns true. */
-template <class P1, class P2, void F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> {
-  typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> {
-  typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func;
-};
-
-/* If our function returns void but we want one returning void*, wrap it in a
- * function that returns the first argument. */
-template <class P1, class P2, void F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> {
-  typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> {
-  typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func;
-};
-
-/* If our function returns R* but we want one returning void*, wrap it in a
- * function that casts to void*. */
-template <class R, class P1, class P2, R *F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *,
-                       typename disable_if_same<R *, void *>::Type> {
-  typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F>, I> Func;
-};
-
-template <class R, class P1, class P2, class P3, R *F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *,
-                       typename disable_if_same<R *, void *>::Type> {
-  typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F>, I>
-      Func;
-};
-
-/* If our function returns bool but we want one returning void*, wrap it in a
- * function that returns either the first param or UPB_BREAK. */
-template <class P1, class P2, bool F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> {
-  typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, bool F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> {
-  typedef Func3<void *, P1, P2, P3, ReturnClosureOrBreak3<P1, P2, P3, F>, I>
-      Func;
-};
-
-/* If our function returns void but we want one returning size_t, wrap it in a
- * function that returns the size argument. */
-template <class P1, class P2,
-          void F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
-struct MaybeWrapReturn<
-    Func5<void, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
-          size_t> {
-  typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
-                ReturnStringLen<P1, P2, F>, I> Func;
-};
-
-/* If our function returns bool but we want one returning size_t, wrap it in a
- * function that returns either 0 or the buf size. */
-template <class P1, class P2,
-          bool F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
-struct MaybeWrapReturn<
-    Func5<bool, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
-    size_t> {
-  typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
-                ReturnNOr0<P1, P2, F>, I> Func;
-};
-
-/* ConvertParams **************************************************************/
-
-/* Template class that converts the function parameters if necessary, and
- * ignores the HandlerData parameter if appropriate.
- *
- * Template parameter is the are FuncN function type. */
-template <class F, class T>
-struct ConvertParams;
-
-/* Function that discards the handler data parameter. */
-template <class R, class P1, R F(P1)>
-R IgnoreHandlerData2(void *p1, const void *hd) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1));
-}
-
-template <class R, class P1, class P2Wrapper, class P2Wrapped,
-          R F(P1, P2Wrapped)>
-R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2);
-}
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2, p3);
-}
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
-R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2, p3, p4);
-}
-
-template <class R, class P1, R F(P1, const char*, size_t)>
-R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2,
-                                size_t p3, const upb_bufhandle *handle) {
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-  return F(static_cast<P1>(p1), p2, p3);
-}
-
-/* Function that casts the handler data parameter. */
-template <class R, class P1, class P2, R F(P1, P2)>
-R CastHandlerData2(void *c, const void *hd) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd));
-}
-
-template <class R, class P1, class P2, class P3Wrapper, class P3Wrapped,
-          R F(P1, P2, P3Wrapped)>
-R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3);
-}
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5)>
-R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4, p5);
-}
-
-template <class R, class P1, class P2, R F(P1, P2, const char *, size_t)>
-R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3,
-                              size_t p4, const upb_bufhandle *handle) {
-  UPB_UNUSED(handle);
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4);
-}
-
-/* For unbound functions, ignore the handler data. */
-template <class R, class P1, R F(P1), class I, class T>
-struct ConvertParams<Func1<R, P1, F, I>, T> {
-  typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func;
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I,
-          class R2, class P1_2, class P2_2, class P3_2>
-struct ConvertParams<Func2<R, P1, P2, F, I>,
-                     R2 (*)(P1_2, P2_2, P3_2)> {
-  typedef Func3<R, void *, const void *, P3_2,
-                IgnoreHandlerData3<R, P1, P3_2, P2, F>, I> Func;
-};
-
-/* For StringBuffer only; this ignores both the handler data and the
- * upb_bufhandle. */
-template <class R, class P1, R F(P1, const char *, size_t), class I, class T>
-struct ConvertParams<Func3<R, P1, const char *, size_t, F, I>, T> {
-  typedef Func5<R, void *, const void *, const char *, size_t,
-                const upb_bufhandle *, IgnoreHandlerDataIgnoreHandle<R, P1, F>,
-                I> Func;
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I, class T>
-struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I>, T> {
-  typedef Func5<R, void *, const void *, P2, P3, P4,
-                IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func;
-};
-
-/* For bound functions, cast the handler data. */
-template <class R, class P1, class P2, R F(P1, P2), class I, class T>
-struct ConvertParams<BoundFunc2<R, P1, P2, F, I>, T> {
-  typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I>
-      Func;
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I,
-          class R2, class P1_2, class P2_2, class P3_2>
-struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I>,
-                     R2 (*)(P1_2, P2_2, P3_2)> {
-  typedef Func3<R, void *, const void *, P3_2,
-                CastHandlerData3<R, P1, P2, P3_2, P3, F>, I> Func;
-};
-
-/* For StringBuffer only; this ignores the upb_bufhandle. */
-template <class R, class P1, class P2, R F(P1, P2, const char *, size_t),
-          class I, class T>
-struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I>, T> {
-  typedef Func5<R, void *, const void *, const char *, size_t,
-                const upb_bufhandle *,
-                CastHandlerDataIgnoreHandle<R, P1, P2, F>, I>
-      Func;
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I, class T>
-struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> {
-  typedef Func5<R, void *, const void *, P3, P4, P5,
-                CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func;
-};
-
-/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
- * variant C type. */
-#define TYPE_METHODS(utype, ltype, ctype, vtype)                      \
-  template <>                                                         \
-  struct CanonicalType<vtype> {                                       \
-    typedef ctype Type;                                               \
-  };                                                                  \
-  template <>                                                         \
-  inline bool HandlersPtr::SetValueHandler<vtype>(                    \
-      FieldDefPtr f, const HandlersPtr::utype##Handler &handler) {    \
-    handler.AddCleanup(ptr());                                        \
-    return upb_handlers_set##ltype(ptr(), f.ptr(), handler.handler(), \
-                                   &handler.attr());                  \
-  }
-
-TYPE_METHODS(Double, double, double,   double)
-TYPE_METHODS(Float,  float,  float,    float)
-TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T)
-TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T)
-TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64_T)
-TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32_T)
-TYPE_METHODS(Bool,   bool,   bool,     bool)
-
-#ifdef UPB_TWO_32BIT_TYPES
-TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32ALT_T)
-TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T)
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64ALT_T)
-TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T)
-#endif
-#undef TYPE_METHODS
-
-template <> struct CanonicalType<Status*> {
-  typedef Status* Type;
-};
-
-template <class F> struct ReturnOf;
-
-template <class R, class P1, class P2>
-struct ReturnOf<R (*)(P1, P2)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3>
-struct ReturnOf<R (*)(P1, P2, P3)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3, class P4>
-struct ReturnOf<R (*)(P1, P2, P3, P4)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-struct ReturnOf<R (*)(P1, P2, P3, P4, P5)> {
-  typedef R Return;
-};
-
-
-template <class T>
-template <class F>
-inline Handler<T>::Handler(F func)
-    : registered_(false),
-      cleanup_data_(func.GetData()),
-      cleanup_func_(func.GetCleanup()) {
-  attr_.handler_data = func.GetData();
-  typedef typename ReturnOf<T>::Return Return;
-  typedef typename ConvertParams<F, T>::Func ConvertedParamsFunc;
-  typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func
-      ReturnWrappedFunc;
-  handler_ = ReturnWrappedFunc().Call;
-
-  /* Set attributes based on what templates can statically tell us about the
-   * user's function. */
-
-  /* If the original function returns void, then we know that we wrapped it to
-   * always return ok. */
-  bool always_ok = is_same<typename F::FuncInfo::Return, void>::value;
-  attr_.alwaysok = always_ok;
-
-  /* Closure parameter and return type. */
-  attr_.closure_type = UniquePtrForType<typename F::FuncInfo::Closure>();
-
-  /* We use the closure type (from the first parameter) if the return type is
-   * void or bool, since these are the two cases we wrap to return the closure's
-   * type anyway.
-   *
-   * This is all nonsense for non START* handlers, but it doesn't matter because
-   * in that case the value will be ignored. */
-  typedef typename FirstUnlessVoidOrBool<typename F::FuncInfo::Return,
-                                         typename F::FuncInfo::Closure>::value
-      EffectiveReturn;
-  attr_.return_closure_type = UniquePtrForType<EffectiveReturn>();
-}
-
-template <class T>
-inline void Handler<T>::AddCleanup(upb_handlers* h) const {
-  UPB_ASSERT(!registered_);
-  registered_ = true;
-  if (cleanup_func_) {
-    bool ok = upb_handlers_addcleanup(h, cleanup_data_, cleanup_func_);
-    UPB_ASSERT(ok);
-  }
-}
-
-}  /* namespace upb */
-
-#endif  /* __cplusplus */
-
-
-#undef UPB_TWO_32BIT_TYPES
-#undef UPB_TWO_64BIT_TYPES
-#undef UPB_INT32_T
-#undef UPB_UINT32_T
-#undef UPB_INT32ALT_T
-#undef UPB_UINT32ALT_T
-#undef UPB_INT64_T
-#undef UPB_UINT64_T
-#undef UPB_INT64ALT_T
-#undef UPB_UINT64ALT_T
-
-
-#endif  /* UPB_HANDLERS_INL_H_ */
-
-#endif  /* UPB_HANDLERS_H */
-/*
-** upb::Sink (upb_sink)
-** upb::BytesSink (upb_bytessink)
-**
-** A upb_sink is an object that binds a upb_handlers object to some runtime
-** state.  It is the object that can actually receive data via the upb_handlers
-** interface.
-**
-** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or
-** thread-safe.  You can create as many of them as you want, but each one may
-** only be used in a single thread at a time.
-**
-** If we compare with class-based OOP, a you can think of a upb_def as an
-** abstract base class, a upb_handlers as a concrete derived class, and a
-** upb_sink as an object (class instance).
-*/
-
-#ifndef UPB_SINK_H
-#define UPB_SINK_H
-
-
-
-#ifdef __cplusplus
-namespace upb {
-class BytesSink;
-class Sink;
-}
-#endif
-
-/* upb_sink *******************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
-  const upb_handlers *handlers;
-  void *closure;
-} upb_sink;
-
-#define PUTVAL(type, ctype)                                           \
-  UPB_INLINE bool upb_sink_put##type(upb_sink s, upb_selector_t sel,  \
-                                     ctype val) {                     \
-    typedef upb_##type##_handlerfunc functype;                        \
-    functype *func;                                                   \
-    const void *hd;                                                   \
-    if (!s.handlers) return true;                                     \
-    func = (functype *)upb_handlers_gethandler(s.handlers, sel, &hd); \
-    if (!func) return true;                                           \
-    return func(s.closure, hd, val);                                  \
-  }
-
-PUTVAL(int32,  int32_t)
-PUTVAL(int64,  int64_t)
-PUTVAL(uint32, uint32_t)
-PUTVAL(uint64, uint64_t)
-PUTVAL(float,  float)
-PUTVAL(double, double)
-PUTVAL(bool,   bool)
-#undef PUTVAL
-
-UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
-  s->handlers = h;
-  s->closure = c;
-}
-
-UPB_INLINE size_t upb_sink_putstring(upb_sink s, upb_selector_t sel,
-                                     const char *buf, size_t n,
-                                     const upb_bufhandle *handle) {
-  typedef upb_string_handlerfunc func;
-  func *handler;
-  const void *hd;
-  if (!s.handlers) return n;
-  handler = (func *)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!handler) return n;
-  return handler(s.closure, hd, buf, n, handle);
-}
-
-UPB_INLINE bool upb_sink_putunknown(upb_sink s, const char *buf, size_t n) {
-  typedef upb_unknown_handlerfunc func;
-  func *handler;
-  const void *hd;
-  if (!s.handlers) return true;
-  handler =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_UNKNOWN_SELECTOR, &hd);
-
-  if (!handler) return n;
-  return handler(s.closure, hd, buf, n);
-}
-
-UPB_INLINE bool upb_sink_startmsg(upb_sink s) {
-  typedef upb_startmsg_handlerfunc func;
-  func *startmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  startmsg =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_STARTMSG_SELECTOR, &hd);
-
-  if (!startmsg) return true;
-  return startmsg(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_endmsg(upb_sink s, upb_status *status) {
-  typedef upb_endmsg_handlerfunc func;
-  func *endmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  endmsg =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_ENDMSG_SELECTOR, &hd);
-
-  if (!endmsg) return true;
-  return endmsg(s.closure, hd, status);
-}
-
-UPB_INLINE bool upb_sink_startseq(upb_sink s, upb_selector_t sel,
-                                  upb_sink *sub) {
-  typedef upb_startfield_handlerfunc func;
-  func *startseq;
-  const void *hd;
-  sub->closure = s.closure;
-  sub->handlers = s.handlers;
-  if (!s.handlers) return true;
-  startseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startseq) return true;
-  sub->closure = startseq(s.closure, hd);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endseq(upb_sink s, upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endseq;
-  const void *hd;
-  if (!s.handlers) return true;
-  endseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endseq) return true;
-  return endseq(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_startstr(upb_sink s, upb_selector_t sel,
-                                  size_t size_hint, upb_sink *sub) {
-  typedef upb_startstr_handlerfunc func;
-  func *startstr;
-  const void *hd;
-  sub->closure = s.closure;
-  sub->handlers = s.handlers;
-  if (!s.handlers) return true;
-  startstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startstr) return true;
-  sub->closure = startstr(s.closure, hd, size_hint);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endstr(upb_sink s, upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endstr;
-  const void *hd;
-  if (!s.handlers) return true;
-  endstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endstr) return true;
-  return endstr(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_startsubmsg(upb_sink s, upb_selector_t sel,
-                                     upb_sink *sub) {
-  typedef upb_startfield_handlerfunc func;
-  func *startsubmsg;
-  const void *hd;
-  sub->closure = s.closure;
-  if (!s.handlers) {
-    sub->handlers = NULL;
-    return true;
-  }
-  sub->handlers = upb_handlers_getsubhandlers_sel(s.handlers, sel);
-  startsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startsubmsg) return true;
-  sub->closure = startsubmsg(s.closure, hd);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_sink sub,
-                                   upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endsubmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  endsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endsubmsg) return true;
-  return endsubmsg(sub.closure, hd);
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A upb::Sink is an object that binds a upb::Handlers object to some runtime
- * state.  It represents an endpoint to which data can be sent.
- *
- * TODO(haberman): right now all of these functions take selectors.  Should they
- * take selectorbase instead?
- *
- * ie. instead of calling:
- *   sink->StartString(FOO_FIELD_START_STRING, ...)
- * a selector base would let you say:
- *   sink->StartString(FOO_FIELD, ...)
- *
- * This would make call sites a little nicer and require emitting fewer selector
- * definitions in .h files.
- *
- * But the current scheme has the benefit that you can retrieve a function
- * pointer for any handler with handlers->GetHandler(selector), without having
- * to have a separate GetHandler() function for each handler type.  The JIT
- * compiler uses this.  To accommodate we'd have to expose a separate
- * GetHandler() for every handler type.
- *
- * Also to ponder: selectors right now are independent of a specific Handlers
- * instance.  In other words, they allocate a number to every possible handler
- * that *could* be registered, without knowing anything about what handlers
- * *are* registered.  That means that using selectors as table offsets prohibits
- * us from compacting the handler table at Freeze() time.  If the table is very
- * sparse, this could be wasteful.
- *
- * Having another selector-like thing that is specific to a Handlers instance
- * would allow this compacting, but then it would be impossible to write code
- * ahead-of-time that can be bound to any Handlers instance at runtime.  For
- * example, a .proto file parser written as straight C will not know what
- * Handlers it will be bound to, so when it calls sink->StartString() what
- * selector will it pass?  It needs a selector like we have today, that is
- * independent of any particular upb::Handlers.
- *
- * Is there a way then to allow Handlers table compaction? */
-class upb::Sink {
- public:
-  /* Constructor with no initialization; must be Reset() before use. */
-  Sink() {}
-
-  Sink(const Sink&) = default;
-  Sink& operator=(const Sink&) = default;
-
-  Sink(const upb_sink& sink) : sink_(sink) {}
-  Sink &operator=(const upb_sink &sink) {
-    sink_ = sink;
-    return *this;
-  }
-
-  upb_sink sink() { return sink_; }
-
-  /* Constructs a new sink for the given frozen handlers and closure.
-   *
-   * TODO: once the Handlers know the expected closure type, verify that T
-   * matches it. */
-  template <class T> Sink(const upb_handlers* handlers, T* closure) {
-    Reset(handlers, closure);
-  }
-
-  upb_sink* ptr() { return &sink_; }
-
-  /* Resets the value of the sink. */
-  template <class T> void Reset(const upb_handlers* handlers, T* closure) {
-    upb_sink_reset(&sink_, handlers, closure);
-  }
-
-  /* Returns the top-level object that is bound to this sink.
-   *
-   * TODO: once the Handlers know the expected closure type, verify that T
-   * matches it. */
-  template <class T> T* GetObject() const {
-    return static_cast<T*>(sink_.closure);
-  }
-
-  /* Functions for pushing data into the sink.
-   *
-   * These return false if processing should stop (either due to error or just
-   * to suspend).
-   *
-   * These may not be called from within one of the same sink's handlers (in
-   * other words, handlers are not re-entrant). */
-
-  /* Should be called at the start and end of every message; both the top-level
-   * message and submessages.  This means that submessages should use the
-   * following sequence:
-   *   sink->StartSubMessage(startsubmsg_selector);
-   *   sink->StartMessage();
-   *   // ...
-   *   sink->EndMessage(&status);
-   *   sink->EndSubMessage(endsubmsg_selector); */
-  bool StartMessage() { return upb_sink_startmsg(sink_); }
-  bool EndMessage(upb_status *status) {
-    return upb_sink_endmsg(sink_, status);
-  }
-
-  /* Putting of individual values.  These work for both repeated and
-   * non-repeated fields, but for repeated fields you must wrap them in
-   * calls to StartSequence()/EndSequence(). */
-  bool PutInt32(HandlersPtr::Selector s, int32_t val) {
-    return upb_sink_putint32(sink_, s, val);
-  }
-
-  bool PutInt64(HandlersPtr::Selector s, int64_t val) {
-    return upb_sink_putint64(sink_, s, val);
-  }
-
-  bool PutUInt32(HandlersPtr::Selector s, uint32_t val) {
-    return upb_sink_putuint32(sink_, s, val);
-  }
-
-  bool PutUInt64(HandlersPtr::Selector s, uint64_t val) {
-    return upb_sink_putuint64(sink_, s, val);
-  }
-
-  bool PutFloat(HandlersPtr::Selector s, float val) {
-    return upb_sink_putfloat(sink_, s, val);
-  }
-
-  bool PutDouble(HandlersPtr::Selector s, double val) {
-    return upb_sink_putdouble(sink_, s, val);
-  }
-
-  bool PutBool(HandlersPtr::Selector s, bool val) {
-    return upb_sink_putbool(sink_, s, val);
-  }
-
-  /* Putting of string/bytes values.  Each string can consist of zero or more
-   * non-contiguous buffers of data.
-   *
-   * For StartString(), the function will write a sink for the string to "sub."
-   * The sub-sink must be used for any/all PutStringBuffer() calls. */
-  bool StartString(HandlersPtr::Selector s, size_t size_hint, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startstr(sink_, s, size_hint, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  size_t PutStringBuffer(HandlersPtr::Selector s, const char *buf, size_t len,
-                         const upb_bufhandle *handle) {
-    return upb_sink_putstring(sink_, s, buf, len, handle);
-  }
-
-  bool EndString(HandlersPtr::Selector s) {
-    return upb_sink_endstr(sink_, s);
-  }
-
-  /* For submessage fields.
-   *
-   * For StartSubMessage(), the function will write a sink for the string to
-   * "sub." The sub-sink must be used for any/all handlers called within the
-   * submessage. */
-  bool StartSubMessage(HandlersPtr::Selector s, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startsubmsg(sink_, s, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  bool EndSubMessage(HandlersPtr::Selector s, Sink sub) {
-    return upb_sink_endsubmsg(sink_, sub.sink_, s);
-  }
-
-  /* For repeated fields of any type, the sequence of values must be wrapped in
-   * these calls.
-   *
-   * For StartSequence(), the function will write a sink for the string to
-   * "sub." The sub-sink must be used for any/all handlers called within the
-   * sequence. */
-  bool StartSequence(HandlersPtr::Selector s, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startseq(sink_, s, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  bool EndSequence(HandlersPtr::Selector s) {
-    return upb_sink_endseq(sink_, s);
-  }
-
-  /* Copy and assign specifically allowed.
-   * We don't even bother making these members private because so many
-   * functions need them and this is mainly just a dumb data container anyway.
-   */
-
- private:
-  upb_sink sink_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_bytessink **************************************************************/
-
-typedef struct {
-  const upb_byteshandler *handler;
-  void *closure;
-} upb_bytessink ;
-
-UPB_INLINE void upb_bytessink_reset(upb_bytessink* s, const upb_byteshandler *h,
-                                    void *closure) {
-  s->handler = h;
-  s->closure = closure;
-}
-
-UPB_INLINE bool upb_bytessink_start(upb_bytessink s, size_t size_hint,
-                                    void **subc) {
-  typedef upb_startstr_handlerfunc func;
-  func *start;
-  *subc = s.closure;
-  if (!s.handler) return true;
-  start = (func *)s.handler->table[UPB_STARTSTR_SELECTOR].func;
-
-  if (!start) return true;
-  *subc = start(s.closure,
-                s.handler->table[UPB_STARTSTR_SELECTOR].attr.handler_data,
-                size_hint);
-  return *subc != NULL;
-}
-
-UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink s, void *subc,
-                                       const char *buf, size_t size,
-                                       const upb_bufhandle* handle) {
-  typedef upb_string_handlerfunc func;
-  func *putbuf;
-  if (!s.handler) return true;
-  putbuf = (func *)s.handler->table[UPB_STRING_SELECTOR].func;
-
-  if (!putbuf) return true;
-  return putbuf(subc, s.handler->table[UPB_STRING_SELECTOR].attr.handler_data,
-                buf, size, handle);
-}
-
-UPB_INLINE bool upb_bytessink_end(upb_bytessink s) {
-  typedef upb_endfield_handlerfunc func;
-  func *end;
-  if (!s.handler) return true;
-  end = (func *)s.handler->table[UPB_ENDSTR_SELECTOR].func;
-
-  if (!end) return true;
-  return end(s.closure,
-             s.handler->table[UPB_ENDSTR_SELECTOR].attr.handler_data);
-}
-
-#ifdef __cplusplus
-
-class upb::BytesSink {
- public:
-  BytesSink() {}
-
-  BytesSink(const BytesSink&) = default;
-  BytesSink& operator=(const BytesSink&) = default;
-
-  BytesSink(const upb_bytessink& sink) : sink_(sink) {}
-  BytesSink &operator=(const upb_bytessink &sink) {
-    sink_ = sink;
-    return *this;
-  }
-
-  upb_bytessink sink() { return sink_; }
-
-  /* Constructs a new sink for the given frozen handlers and closure.
-   *
-   * TODO(haberman): once the Handlers know the expected closure type, verify
-   * that T matches it. */
-  template <class T> BytesSink(const upb_byteshandler* handler, T* closure) {
-    upb_bytessink_reset(sink_, handler, closure);
-  }
-
-  /* Resets the value of the sink. */
-  template <class T> void Reset(const upb_byteshandler* handler, T* closure) {
-    upb_bytessink_reset(&sink_, handler, closure);
-  }
-
-  bool Start(size_t size_hint, void **subc) {
-    return upb_bytessink_start(sink_, size_hint, subc);
-  }
-
-  size_t PutBuffer(void *subc, const char *buf, size_t len,
-                   const upb_bufhandle *handle) {
-    return upb_bytessink_putbuf(sink_, subc, buf, len, handle);
-  }
-
-  bool End() {
-    return upb_bytessink_end(sink_);
-  }
-
- private:
-  upb_bytessink sink_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_bufsrc *****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-template <class T> bool PutBuffer(const T& str, BytesSink sink) {
-  return upb_bufsrc_putbuf(str.data(), str.size(), sink.sink());
-}
-}
-
-#endif  /* __cplusplus */
-
-
-#endif
-/*
-** Internal-only definitions for the decoder.
-*/
-
-#ifndef UPB_DECODER_INT_H_
-#define UPB_DECODER_INT_H_
-
-/*
-** upb::pb::Decoder
-**
-** A high performance, streaming, resumable decoder for the binary protobuf
-** format.
-**
-** This interface works the same regardless of what decoder backend is being
-** used.  A client of this class does not need to know whether decoding is using
-** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder.  By default,
-** it will always use the fastest available decoder.  However, you can call
-** set_allow_jit(false) to disable any JIT decoder that might be available.
-** This is primarily useful for testing purposes.
-*/
-
-#ifndef UPB_DECODER_H_
-#define UPB_DECODER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class CodeCache;
-class DecoderPtr;
-class DecoderMethodPtr;
-class DecoderMethodOptions;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-/* The maximum number of bytes we are required to buffer internally between
- * calls to the decoder.  The value is 14: a 5 byte unknown tag plus ten-byte
- * varint, less one because we are buffering an incomplete value.
- *
- * Should only be used by unit tests. */
-#define UPB_DECODER_MAX_RESIDUAL_BYTES 14
-
-/* upb_pbdecodermethod ********************************************************/
-
-struct upb_pbdecodermethod;
-typedef struct upb_pbdecodermethod upb_pbdecodermethod;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const upb_handlers *upb_pbdecodermethod_desthandlers(
-    const upb_pbdecodermethod *m);
-const upb_byteshandler *upb_pbdecodermethod_inputhandler(
-    const upb_pbdecodermethod *m);
-bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Represents the code to parse a protobuf according to a destination
- * Handlers. */
-class upb::pb::DecoderMethodPtr {
- public:
-  DecoderMethodPtr() : ptr_(nullptr) {}
-  DecoderMethodPtr(const upb_pbdecodermethod* ptr) : ptr_(ptr) {}
-
-  const upb_pbdecodermethod* ptr() { return ptr_; }
-
-  /* The destination handlers that are statically bound to this method.
-   * This method is only capable of outputting to a sink that uses these
-   * handlers. */
-  const Handlers *dest_handlers() const {
-    return upb_pbdecodermethod_desthandlers(ptr_);
-  }
-
-  /* The input handlers for this decoder method. */
-  const BytesHandler* input_handler() const {
-    return upb_pbdecodermethod_inputhandler(ptr_);
-  }
-
-  /* Whether this method is native. */
-  bool is_native() const {
-    return upb_pbdecodermethod_isnative(ptr_);
-  }
-
- private:
-  const upb_pbdecodermethod* ptr_;
-};
-
-#endif
-
-/* upb_pbdecoder **************************************************************/
-
-/* Preallocation hint: decoder won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the decoder library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_PB_DECODER_SIZE 4416
-
-struct upb_pbdecoder;
-typedef struct upb_pbdecoder upb_pbdecoder;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_pbdecoder *upb_pbdecoder_create(upb_arena *arena,
-                                    const upb_pbdecodermethod *method,
-                                    upb_sink output, upb_status *status);
-const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
-upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d);
-uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d);
-size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d);
-bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max);
-void upb_pbdecoder_reset(upb_pbdecoder *d);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A Decoder receives binary protobuf data on its input sink and pushes the
- * decoded data to its output sink. */
-class upb::pb::DecoderPtr {
- public:
-  DecoderPtr() : ptr_(nullptr) {}
-  DecoderPtr(upb_pbdecoder* ptr) : ptr_(ptr) {}
-
-  upb_pbdecoder* ptr() { return ptr_; }
-
-  /* Constructs a decoder instance for the given method, which must outlive this
-   * decoder.  Any errors during parsing will be set on the given status, which
-   * must also outlive this decoder.
-   *
-   * The sink must match the given method. */
-  static DecoderPtr Create(Arena *arena, DecoderMethodPtr method,
-                           upb::Sink output, Status *status) {
-    return DecoderPtr(upb_pbdecoder_create(arena->ptr(), method.ptr(),
-                                           output.sink(), status->ptr()));
-  }
-
-  /* Returns the DecoderMethod this decoder is parsing from. */
-  const DecoderMethodPtr method() const {
-    return DecoderMethodPtr(upb_pbdecoder_method(ptr_));
-  }
-
-  /* The sink on which this decoder receives input. */
-  BytesSink input() { return BytesSink(upb_pbdecoder_input(ptr())); }
-
-  /* Returns number of bytes successfully parsed.
-   *
-   * This can be useful for determining the stream position where an error
-   * occurred.
-   *
-   * This value may not be up-to-date when called from inside a parsing
-   * callback. */
-  uint64_t BytesParsed() { return upb_pbdecoder_bytesparsed(ptr()); }
-
-  /* Gets/sets the parsing nexting limit.  If the total number of nested
-   * submessages and repeated fields hits this limit, parsing will fail.  This
-   * is a resource limit that controls the amount of memory used by the parsing
-   * stack.
-   *
-   * Setting the limit will fail if the parser is currently suspended at a depth
-   * greater than this, or if memory allocation of the stack fails. */
-  size_t max_nesting() { return upb_pbdecoder_maxnesting(ptr()); }
-  bool set_max_nesting(size_t max) { return upb_pbdecoder_maxnesting(ptr()); }
-
-  void Reset() { upb_pbdecoder_reset(ptr()); }
-
-  static const size_t kSize = UPB_PB_DECODER_SIZE;
-
- private:
-  upb_pbdecoder *ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_pbcodecache ************************************************************/
-
-/* Lazily builds and caches decoder methods that will push data to the given
- * handlers.  The destination handlercache must outlive this object. */
-
-struct upb_pbcodecache;
-typedef struct upb_pbcodecache upb_pbcodecache;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest);
-void upb_pbcodecache_free(upb_pbcodecache *c);
-bool upb_pbcodecache_allowjit(const upb_pbcodecache *c);
-void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow);
-void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy);
-const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
-                                               const upb_msgdef *md);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A class for caching protobuf processing code, whether bytecode for the
- * interpreted decoder or machine code for the JIT.
- *
- * This class is not thread-safe. */
-class upb::pb::CodeCache {
- public:
-  CodeCache(upb::HandlerCache *dest)
-      : ptr_(upb_pbcodecache_new(dest->ptr()), upb_pbcodecache_free) {}
-  CodeCache(CodeCache&&) = default;
-  CodeCache& operator=(CodeCache&&) = default;
-
-  upb_pbcodecache* ptr() { return ptr_.get(); }
-  const upb_pbcodecache* ptr() const { return ptr_.get(); }
-
-  /* Whether the cache is allowed to generate machine code.  Defaults to true.
-   * There is no real reason to turn it off except for testing or if you are
-   * having a specific problem with the JIT.
-   *
-   * Note that allow_jit = true does not *guarantee* that the code will be JIT
-   * compiled.  If this platform is not supported or the JIT was not compiled
-   * in, the code may still be interpreted. */
-  bool allow_jit() const { return upb_pbcodecache_allowjit(ptr()); }
-
-  /* This may only be called when the object is first constructed, and prior to
-   * any code generation. */
-  void set_allow_jit(bool allow) { upb_pbcodecache_setallowjit(ptr(), allow); }
-
-  /* Should the decoder push submessages to lazy handlers for fields that have
-   * them?  The caller should set this iff the lazy handlers expect data that is
-   * in protobuf binary format and the caller wishes to lazy parse it. */
-  void set_lazy(bool lazy) { upb_pbcodecache_setlazy(ptr(), lazy); }
-
-  /* Returns a DecoderMethod that can push data to the given handlers.
-   * If a suitable method already exists, it will be returned from the cache. */
-  const DecoderMethodPtr Get(MessageDefPtr md) {
-    return DecoderMethodPtr(upb_pbcodecache_get(ptr(), md.ptr()));
-  }
-
- private:
-  std::unique_ptr<upb_pbcodecache, decltype(&upb_pbcodecache_free)> ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_DECODER_H_ */
-
-
-/* Opcode definitions.  The canonical meaning of each opcode is its
- * implementation in the interpreter (the JIT is written to match this).
- *
- * All instructions have the opcode in the low byte.
- * Instruction format for most instructions is:
- *
- * +-------------------+--------+
- * |     arg (24)      | op (8) |
- * +-------------------+--------+
- *
- * Exceptions are indicated below.  A few opcodes are multi-word. */
-typedef enum {
-  /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types.
-   * Arg for all of these is the upb selector for this field. */
-#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type
-  T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32),
-  T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64),
-#undef T
-  OP_STARTMSG       = 9,   /* No arg. */
-  OP_ENDMSG         = 10,  /* No arg. */
-  OP_STARTSEQ       = 11,
-  OP_ENDSEQ         = 12,
-  OP_STARTSUBMSG    = 14,
-  OP_ENDSUBMSG      = 19,
-  OP_STARTSTR       = 20,
-  OP_STRING         = 21,
-  OP_ENDSTR         = 22,
-
-  OP_PUSHTAGDELIM   = 23,  /* No arg. */
-  OP_PUSHLENDELIM   = 24,  /* No arg. */
-  OP_POP            = 25,  /* No arg. */
-  OP_SETDELIM       = 26,  /* No arg. */
-  OP_SETBIGGROUPNUM = 27,  /* two words:
-                            *   | unused (24)     | opc (8) |
-                            *   |        groupnum (32)      | */
-  OP_CHECKDELIM     = 28,
-  OP_CALL           = 29,
-  OP_RET            = 30,
-  OP_BRANCH         = 31,
-
-  /* Different opcodes depending on how many bytes expected. */
-  OP_TAG1           = 32,  /* | match tag (16) | jump target (8) | opc (8) | */
-  OP_TAG2           = 33,  /* | match tag (16) | jump target (8) | opc (8) | */
-  OP_TAGN           = 34,  /* three words: */
-                           /*   | unused (16) | jump target(8) | opc (8) | */
-                           /*   |           match tag 1 (32)             | */
-                           /*   |           match tag 2 (32)             | */
-
-  OP_SETDISPATCH    = 35,  /* N words: */
-                           /*   | unused (24)         | opc | */
-                           /*   | upb_inttable* (32 or 64)  | */
-
-  OP_DISPATCH       = 36,  /* No arg. */
-
-  OP_HALT           = 37   /* No arg. */
-} opcode;
-
-#define OP_MAX OP_HALT
-
-UPB_INLINE opcode getop(uint32_t instr) { return (opcode)(instr & 0xff); }
-
-struct upb_pbcodecache {
-  upb_arena *arena;
-  upb_handlercache *dest;
-  bool allow_jit;
-  bool lazy;
-
-  /* Map of upb_msgdef -> mgroup. */
-  upb_inttable groups;
-};
-
-/* Method group; represents a set of decoder methods that had their code
- * emitted together.  Immutable once created.  */
-typedef struct {
-  /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod.  Owned by us.
-   *
-   * Ideally this would be on pbcodecache (if we were actually caching code).
-   * Right now we don't actually cache anything, which is wasteful. */
-  upb_inttable methods;
-
-  /* The bytecode for our methods, if any exists.  Owned by us. */
-  uint32_t *bytecode;
-  uint32_t *bytecode_end;
-} mgroup;
-
-/* The maximum that any submessages can be nested.  Matches proto2's limit.
- * This specifies the size of the decoder's statically-sized array and therefore
- * setting it high will cause the upb::pb::Decoder object to be larger.
- *
- * If necessary we can add a runtime-settable property to Decoder that allow
- * this to be larger than the compile-time setting, but this would add
- * complexity, particularly since we would have to decide how/if to give users
- * the ability to set a custom memory allocation function. */
-#define UPB_DECODER_MAX_NESTING 64
-
-/* Internal-only struct used by the decoder. */
-typedef struct {
-  /* Space optimization note: we store two pointers here that the JIT
-   * doesn't need at all; the upb_handlers* inside the sink and
-   * the dispatch table pointer.  We can optimize so that the JIT uses
-   * smaller stack frames than the interpreter.  The only thing we need
-   * to guarantee is that the fallback routines can find end_ofs. */
-  upb_sink sink;
-
-  /* The absolute stream offset of the end-of-frame delimiter.
-   * Non-delimited frames (groups and non-packed repeated fields) reuse the
-   * delimiter of their parent, even though the frame may not end there.
-   *
-   * NOTE: the JIT stores a slightly different value here for non-top frames.
-   * It stores the value relative to the end of the enclosed message.  But the
-   * top frame is still stored the same way, which is important for ensuring
-   * that calls from the JIT into C work correctly. */
-  uint64_t end_ofs;
-  const uint32_t *base;
-
-  /* 0 indicates a length-delimited field.
-   * A positive number indicates a known group.
-   * A negative number indicates an unknown group. */
-  int32_t groupnum;
-  upb_inttable *dispatch;  /* Not used by the JIT. */
-} upb_pbdecoder_frame;
-
-struct upb_pbdecodermethod {
-  /* While compiling, the base is relative in "ofs", after compiling it is
-   * absolute in "ptr". */
-  union {
-    uint32_t ofs;     /* PC offset of method. */
-    void *ptr;        /* Pointer to bytecode or machine code for this method. */
-  } code_base;
-
-  /* The decoder method group to which this method belongs. */
-  const mgroup *group;
-
-  /* Whether this method is native code or bytecode. */
-  bool is_native_;
-
-  /* The handler one calls to invoke this method. */
-  upb_byteshandler input_handler_;
-
-  /* The destination handlers this method is bound to.  We own a ref. */
-  const upb_handlers *dest_handlers_;
-
-  /* Dispatch table -- used by both bytecode decoder and JIT when encountering a
-   * field number that wasn't the one we were expecting to see.  See
-   * decoder.int.h for the layout of this table. */
-  upb_inttable dispatch;
-};
-
-struct upb_pbdecoder {
-  upb_arena *arena;
-
-  /* Our input sink. */
-  upb_bytessink input_;
-
-  /* The decoder method we are parsing with (owned). */
-  const upb_pbdecodermethod *method_;
-
-  size_t call_len;
-  const uint32_t *pc, *last;
-
-  /* Current input buffer and its stream offset. */
-  const char *buf, *ptr, *end, *checkpoint;
-
-  /* End of the delimited region, relative to ptr, NULL if not in this buf. */
-  const char *delim_end;
-
-  /* End of the delimited region, relative to ptr, end if not in this buf. */
-  const char *data_end;
-
-  /* Overall stream offset of "buf." */
-  uint64_t bufstart_ofs;
-
-  /* Buffer for residual bytes not parsed from the previous buffer. */
-  char residual[UPB_DECODER_MAX_RESIDUAL_BYTES];
-  char *residual_end;
-
-  /* Bytes of data that should be discarded from the input before we start
-   * parsing again.  We set this when we internally determine that we can
-   * safely skip the next N bytes, but this region extends past the current
-   * user buffer. */
-  size_t skip;
-
-  /* Stores the user buffer passed to our decode function. */
-  const char *buf_param;
-  size_t size_param;
-  const upb_bufhandle *handle;
-
-  /* Our internal stack. */
-  upb_pbdecoder_frame *stack, *top, *limit;
-  const uint32_t **callstack;
-  size_t stack_size;
-
-  upb_status *status;
-};
-
-/* Decoder entry points; used as handlers. */
-void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint);
-size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
-                            size_t size, const upb_bufhandle *handle);
-bool upb_pbdecoder_end(void *closure, const void *handler_data);
-
-/* Decoder-internal functions that the JIT calls to handle fallback paths. */
-int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
-                             size_t size, const upb_bufhandle *handle);
-size_t upb_pbdecoder_suspend(upb_pbdecoder *d);
-int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
-                                  uint8_t wire_type);
-int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected);
-int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64);
-int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32);
-int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64);
-void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg);
-
-/* Error messages that are shared between the bytecode and JIT decoders. */
-extern const char *kPbDecoderStackOverflow;
-extern const char *kPbDecoderSubmessageTooLong;
-
-/* Access to decoderplan members needed by the decoder. */
-const char *upb_pbdecoder_getopname(unsigned int op);
-
-/* A special label that means "do field dispatch for this message and branch to
- * wherever that takes you." */
-#define LABEL_DISPATCH 0
-
-/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or
- * RET) for branching to when we find an appropriate ENDGROUP tag. */
-#define DISPATCH_ENDMSG 0
-
-/* It's important to use this invalid wire type instead of 0 (which is a valid
- * wire type). */
-#define NO_WIRE_TYPE 0xff
-
-/* The dispatch table layout is:
- *   [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ]
- *
- * If wt1 matches, jump to the 48-bit offset.  If wt2 matches, lookup
- * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there.
- *
- * We need two wire types because of packed/non-packed compatibility.  A
- * primitive repeated field can use either wire type and be valid.  While we
- * could key the table on fieldnum+wiretype, the table would be 8x sparser.
- *
- * Storing two wire types in the primary value allows us to quickly rule out
- * the second wire type without needing to do a separate lookup (this case is
- * less common than an unknown field). */
-UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1,
-                                               uint8_t wt2) {
-  return (ofs << 16) | (wt2 << 8) | wt1;
-}
-
-UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs,
-                                             uint8_t *wt1, uint8_t *wt2) {
-  *wt1 = (uint8_t)dispatch;
-  *wt2 = (uint8_t)(dispatch >> 8);
-  *ofs = dispatch >> 16;
-}
-
-/* All of the functions in decoder.c that return int32_t return values according
- * to the following scheme:
- *   1. negative values indicate a return code from the following list.
- *   2. positive values indicate that error or end of buffer was hit, and
- *      that the decode function should immediately return the given value
- *      (the decoder state has already been suspended and is ready to be
- *      resumed). */
-#define DECODE_OK -1
-#define DECODE_MISMATCH -2  /* Used only from checktag_slow(). */
-#define DECODE_ENDGROUP -3  /* Used only from checkunknown(). */
-
-#define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; }
-
-
-#endif  /* UPB_DECODER_INT_H_ */
-/*
-** A number of routines for varint manipulation (we keep them all around to
-** have multiple approaches available for benchmarking).
-*/
-
-#ifndef UPB_VARINT_DECODER_H_
-#define UPB_VARINT_DECODER_H_
-
-#include <assert.h>
-#include <stdint.h>
-#include <string.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define UPB_MAX_WIRE_TYPE 5
-
-/* The maximum number of bytes that it takes to encode a 64-bit varint. */
-#define UPB_PB_VARINT_MAX_LEN 10
-
-/* Array of the "native" (ie. non-packed-repeated) wire type for the given a
- * descriptor type (upb_descriptortype_t). */
-extern const uint8_t upb_pb_native_wire_types[];
-
-UPB_INLINE uint64_t byteswap64(uint64_t val)
-{
-  return ((((val) & 0xff00000000000000ull) >> 56)
-    | (((val) & 0x00ff000000000000ull) >> 40)
-    | (((val) & 0x0000ff0000000000ull) >> 24)
-    | (((val) & 0x000000ff00000000ull) >> 8)
-    | (((val) & 0x00000000ff000000ull) << 8)
-    | (((val) & 0x0000000000ff0000ull) << 24)
-    | (((val) & 0x000000000000ff00ull) << 40)
-    | (((val) & 0x00000000000000ffull) << 56));
-}
-
-/* Zig-zag encoding/decoding **************************************************/
-
-UPB_INLINE int32_t upb_zzdec_32(uint32_t n) {
-  return (n >> 1) ^ -(int32_t)(n & 1);
-}
-UPB_INLINE int64_t upb_zzdec_64(uint64_t n) {
-  return (n >> 1) ^ -(int64_t)(n & 1);
-}
-UPB_INLINE uint32_t upb_zzenc_32(int32_t n) {
-  return ((uint32_t)n << 1) ^ (n >> 31);
-}
-UPB_INLINE uint64_t upb_zzenc_64(int64_t n) {
-  return ((uint64_t)n << 1) ^ (n >> 63);
-}
-
-/* Decoding *******************************************************************/
-
-/* All decoding functions return this struct by value. */
-typedef struct {
-  const char *p;  /* NULL if the varint was unterminated. */
-  uint64_t val;
-} upb_decoderet;
-
-UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) {
-  upb_decoderet ret;
-  ret.p = p;
-  ret.val = val;
-  return ret;
-}
-
-upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r);
-upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r);
-
-/* Template for a function that checks the first two bytes with branching
- * and dispatches 2-10 bytes with a separate function.  Note that this may read
- * up to 10 bytes, so it must not be used unless there are at least ten bytes
- * left in the buffer! */
-#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function)                  \
-UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) {         \
-  uint8_t *p = (uint8_t*)_p;                                                   \
-  upb_decoderet r;                                                             \
-  if ((*p & 0x80) == 0) {                                                      \
-  /* Common case: one-byte varint. */                                          \
-    return upb_decoderet_make(_p + 1, *p & 0x7fU);                             \
-  }                                                                            \
-  r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7));    \
-  if ((*(p + 1) & 0x80) == 0) {                                                \
-    /* Two-byte varint. */                                                     \
-    return r;                                                                  \
-  }                                                                            \
-  /* Longer varint, fallback to out-of-line function. */                       \
-  return decode_max8_function(r);                                              \
-}
-
-UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32)
-UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64)
-#undef UPB_VARINT_DECODER_CHECK2
-
-/* Our canonical functions for decoding varints, based on the currently
- * favored best-performing implementations. */
-UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) {
-  if (sizeof(long) == 8)
-    return upb_vdecode_check2_branch64(p);
-  else
-    return upb_vdecode_check2_branch32(p);
-}
-
-
-/* Encoding *******************************************************************/
-
-UPB_INLINE int upb_value_size(uint64_t val) {
-#ifdef __GNUC__
-  int high_bit = 63 - __builtin_clzll(val);  /* 0-based, undef if val == 0. */
-#else
-  int high_bit = 0;
-  uint64_t tmp = val;
-  while(tmp >>= 1) high_bit++;
-#endif
-  return val == 0 ? 1 : high_bit / 8 + 1;
-}
-
-/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN
- * bytes long), returning how many bytes were used.
- *
- * TODO: benchmark and optimize if necessary. */
-UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) {
-  size_t i;
-  if (val == 0) { buf[0] = 0; return 1; }
-  i = 0;
-  while (val) {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    buf[i++] = byte;
-  }
-  return i;
-}
-
-UPB_INLINE size_t upb_varint_size(uint64_t val) {
-  char buf[UPB_PB_VARINT_MAX_LEN];
-  return upb_vencode64(val, buf);
-}
-
-/* Encodes a 32-bit varint, *not* sign-extended. */
-UPB_INLINE uint64_t upb_vencode32(uint32_t val) {
-  char buf[UPB_PB_VARINT_MAX_LEN];
-  size_t bytes = upb_vencode64(val, buf);
-  uint64_t ret = 0;
-  UPB_ASSERT(bytes <= 5);
-  memcpy(&ret, buf, bytes);
-#ifdef UPB_BIG_ENDIAN
-  ret = byteswap64(ret);
-#endif
-  UPB_ASSERT(ret <= 0xffffffffffU);
-  return ret;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* UPB_VARINT_DECODER_H_ */
-/*
-** upb::pb::Encoder (upb_pb_encoder)
-**
-** Implements a set of upb_handlers that write protobuf data to the binary wire
-** format.
-**
-** This encoder implementation does not have any access to any out-of-band or
-** precomputed lengths for submessages, so it must buffer submessages internally
-** before it can emit the first byte.
-*/
-
-#ifndef UPB_ENCODER_H_
-#define UPB_ENCODER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class EncoderPtr;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-#define UPB_PBENCODER_MAX_NESTING 100
-
-/* upb_pb_encoder *************************************************************/
-
-/* Preallocation hint: decoder won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the decoder library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_PB_ENCODER_SIZE 784
-
-struct upb_pb_encoder;
-typedef struct upb_pb_encoder upb_pb_encoder;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_sink upb_pb_encoder_input(upb_pb_encoder *p);
-upb_pb_encoder* upb_pb_encoder_create(upb_arena* a, const upb_handlers* h,
-                                      upb_bytessink output);
-
-/* Lazily builds and caches handlers that will push encoded data to a bytessink.
- * Any msgdef objects used with this object must outlive it. */
-upb_handlercache *upb_pb_encoder_newcache(void);
-
-#ifdef __cplusplus
-}  /* extern "C" { */
-
-class upb::pb::EncoderPtr {
- public:
-  EncoderPtr(upb_pb_encoder* ptr) : ptr_(ptr) {}
-
-  upb_pb_encoder* ptr() { return ptr_; }
-
-  /* Creates a new encoder in the given environment.  The Handlers must have
-   * come from NewHandlers() below. */
-  static EncoderPtr Create(Arena* arena, const Handlers* handlers,
-                           BytesSink output) {
-    return EncoderPtr(
-        upb_pb_encoder_create(arena->ptr(), handlers, output.sink()));
-  }
-
-  /* The input to the encoder. */
-  upb::Sink input() { return upb_pb_encoder_input(ptr()); }
-
-  /* Creates a new set of handlers for this MessageDef. */
-  static HandlerCache NewCache() {
-    return HandlerCache(upb_pb_encoder_newcache());
-  }
-
-  static const size_t kSize = UPB_PB_ENCODER_SIZE;
-
- private:
-  upb_pb_encoder* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_ENCODER_H_ */
-/*
-** upb::pb::TextPrinter (upb_textprinter)
-**
-** Handlers for writing to protobuf text format.
-*/
-
-#ifndef UPB_TEXT_H_
-#define UPB_TEXT_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class TextPrinterPtr;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-/* upb_textprinter ************************************************************/
-
-struct upb_textprinter;
-typedef struct upb_textprinter upb_textprinter;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* C API. */
-upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
-                                        upb_bytessink output);
-void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
-upb_sink upb_textprinter_input(upb_textprinter *p);
-upb_handlercache *upb_textprinter_newcache(void);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::pb::TextPrinterPtr {
- public:
-  TextPrinterPtr(upb_textprinter* ptr) : ptr_(ptr) {}
-
-  /* The given handlers must have come from NewHandlers().  It must outlive the
-   * TextPrinter. */
-  static TextPrinterPtr Create(Arena *arena, upb::HandlersPtr *handlers,
-                               BytesSink output) {
-    return TextPrinterPtr(
-        upb_textprinter_create(arena->ptr(), handlers->ptr(), output.sink()));
-  }
-
-  void SetSingleLineMode(bool single_line) {
-    upb_textprinter_setsingleline(ptr_, single_line);
-  }
-
-  Sink input() { return upb_textprinter_input(ptr_); }
-
-  /* If handler caching becomes a requirement we can add a code cache as in
-   * decoder.h */
-  static HandlerCache NewCache() {
-    return HandlerCache(upb_textprinter_newcache());
-  }
-
- private:
-  upb_textprinter* ptr_;
-};
-
-#endif
-
-#endif  /* UPB_TEXT_H_ */
-/*
-** upb::json::Parser (upb_json_parser)
-**
-** Parses JSON according to a specific schema.
-** Support for parsing arbitrary JSON (schema-less) will be added later.
-*/
-
-#ifndef UPB_JSON_PARSER_H_
-#define UPB_JSON_PARSER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace json {
-class CodeCache;
-class ParserPtr;
-class ParserMethodPtr;
-}  /* namespace json */
-}  /* namespace upb */
-#endif
-
-/* upb_json_parsermethod ******************************************************/
-
-struct upb_json_parsermethod;
-typedef struct upb_json_parsermethod upb_json_parsermethod;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const upb_byteshandler* upb_json_parsermethod_inputhandler(
-    const upb_json_parsermethod* m);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::json::ParserMethodPtr {
- public:
-  ParserMethodPtr() : ptr_(nullptr) {}
-  ParserMethodPtr(const upb_json_parsermethod* ptr) : ptr_(ptr) {}
-
-  const upb_json_parsermethod* ptr() const { return ptr_; }
-
-  const BytesHandler* input_handler() const {
-    return upb_json_parsermethod_inputhandler(ptr());
-  }
-
- private:
-  const upb_json_parsermethod* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_json_parser ************************************************************/
-
-/* Preallocation hint: parser won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the parser library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_JSON_PARSER_SIZE 5712
-
-struct upb_json_parser;
-typedef struct upb_json_parser upb_json_parser;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_json_parser* upb_json_parser_create(upb_arena* a,
-                                        const upb_json_parsermethod* m,
-                                        const upb_symtab* symtab,
-                                        upb_sink output,
-                                        upb_status *status,
-                                        bool ignore_json_unknown);
-upb_bytessink upb_json_parser_input(upb_json_parser* p);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Parses an incoming BytesStream, pushing the results to the destination
- * sink. */
-class upb::json::ParserPtr {
- public:
-  ParserPtr(upb_json_parser* ptr) : ptr_(ptr) {}
-
-  static ParserPtr Create(Arena* arena, ParserMethodPtr method,
-                          SymbolTable* symtab, Sink output, Status* status,
-                          bool ignore_json_unknown) {
-    upb_symtab* symtab_ptr = symtab ? symtab->ptr() : nullptr;
-    return ParserPtr(upb_json_parser_create(
-        arena->ptr(), method.ptr(), symtab_ptr, output.sink(), status->ptr(),
-        ignore_json_unknown));
-  }
-
-  BytesSink input() { return upb_json_parser_input(ptr_); }
-
- private:
-  upb_json_parser* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_json_codecache *********************************************************/
-
-/* Lazily builds and caches decoder methods that will push data to the given
- * handlers.  The upb_symtab object(s) must outlive this object. */
-
-struct upb_json_codecache;
-typedef struct upb_json_codecache upb_json_codecache;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_json_codecache *upb_json_codecache_new(void);
-void upb_json_codecache_free(upb_json_codecache *cache);
-const upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache,
-                                                    const upb_msgdef* md);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::json::CodeCache {
- public:
-  CodeCache() : ptr_(upb_json_codecache_new(), upb_json_codecache_free) {}
-
-  /* Returns a DecoderMethod that can push data to the given handlers.
-   * If a suitable method already exists, it will be returned from the cache. */
-  ParserMethodPtr Get(MessageDefPtr md) {
-    return upb_json_codecache_get(ptr_.get(), md.ptr());
-  }
-
- private:
-  std::unique_ptr<upb_json_codecache, decltype(&upb_json_codecache_free)> ptr_;
-};
-
-#endif
-
-#endif  /* UPB_JSON_PARSER_H_ */
-/*
-** upb::json::Printer
-**
-** Handlers that emit JSON according to a specific protobuf schema.
-*/
-
-#ifndef UPB_JSON_TYPED_PRINTER_H_
-#define UPB_JSON_TYPED_PRINTER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace json {
-class PrinterPtr;
-}  /* namespace json */
-}  /* namespace upb */
-#endif
-
-/* upb_json_printer ***********************************************************/
-
-#define UPB_JSON_PRINTER_SIZE 192
-
-struct upb_json_printer;
-typedef struct upb_json_printer upb_json_printer;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Native C API. */
-upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
-                                          upb_bytessink output);
-upb_sink upb_json_printer_input(upb_json_printer *p);
-const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
-                                                 bool preserve_fieldnames,
-                                                 const void *owner);
-
-/* Lazily builds and caches handlers that will push encoded data to a bytessink.
- * Any msgdef objects used with this object must outlive it. */
-upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Prints an incoming stream of data to a BytesSink in JSON format. */
-class upb::json::PrinterPtr {
- public:
-  PrinterPtr(upb_json_printer* ptr) : ptr_(ptr) {}
-
-  static PrinterPtr Create(Arena *arena, const upb::Handlers *handlers,
-                           BytesSink output) {
-    return PrinterPtr(
-        upb_json_printer_create(arena->ptr(), handlers, output.sink()));
-  }
-
-  /* The input to the printer. */
-  Sink input() { return upb_json_printer_input(ptr_); }
-
-  static const size_t kSize = UPB_JSON_PRINTER_SIZE;
-
-  static HandlerCache NewCache(bool preserve_proto_fieldnames) {
-    return upb_json_printer_newcache(preserve_proto_fieldnames);
-  }
-
- private:
-  upb_json_printer* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_JSON_TYPED_PRINTER_H_ */
-/* See port_def.inc.  This should #undef all macros #defined there. */
-
-#undef UPB_SIZE
-#undef UPB_FIELD_AT
-#undef UPB_READ_ONEOF
-#undef UPB_WRITE_ONEOF
-#undef UPB_INLINE
-#undef UPB_FORCEINLINE
-#undef UPB_NOINLINE
-#undef UPB_NORETURN
-#undef UPB_MAX
-#undef UPB_MIN
-#undef UPB_UNUSED
-#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
-#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
diff --git a/php/ext/google/protobuf/utf8.c b/php/ext/google/protobuf/utf8.c
deleted file mode 100644
index 2752a08..0000000
--- a/php/ext/google/protobuf/utf8.c
+++ /dev/null
@@ -1,68 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "utf8.h"
-
-static const uint8_t utf8_offset[] = {
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-    4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-bool is_structurally_valid_utf8(const char* buf, int len) {
-  int i, j;
-  uint8_t offset;
-
-  i = 0;
-  while (i < len) {
-    offset = utf8_offset[(uint8_t)buf[i]];
-    if (offset == 0 || i + offset > len) {
-      return false;
-    }
-    for (j = i + 1; j < i + offset; j++) {
-      if ((buf[j] & 0xc0) != 0x80) {
-        return false;
-      }
-    }
-    i += offset;
-  }
-  return i == len;
-}
diff --git a/php/ext/google/protobuf/wkt.inc b/php/ext/google/protobuf/wkt.inc
new file mode 100644
index 0000000..df3cce9
--- /dev/null
+++ b/php/ext/google/protobuf/wkt.inc
@@ -0,0 +1,3245 @@
+// This file is generated from the .proto files for the well-known
+// types. Do not edit!
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_lookup, 0, 0, 1)
+  ZEND_ARG_INFO(0, key)
+ZEND_END_ARG_INFO()
+
+static void google_protobuf_any_proto_AddDescriptor();
+static void google_protobuf_api_proto_AddDescriptor();
+static void google_protobuf_duration_proto_AddDescriptor();
+static void google_protobuf_empty_proto_AddDescriptor();
+static void google_protobuf_field_mask_proto_AddDescriptor();
+static void google_protobuf_source_context_proto_AddDescriptor();
+static void google_protobuf_struct_proto_AddDescriptor();
+static void google_protobuf_type_proto_AddDescriptor();
+static void google_protobuf_timestamp_proto_AddDescriptor();
+static void google_protobuf_wrappers_proto_AddDescriptor();
+/* google/protobuf/any.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_Any_ce;
+
+const char google_protobuf_any_proto_descriptor [212] = {
+'\n', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 
+'t', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', '&', '\n', '\003', 'A', 'n', 
+'y', '\022', '\020', '\n', '\010', 't', 'y', 'p', 'e', '_', 'u', 'r', 'l', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\r', '\n', '\005', 'v', 'a', 
+'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\014', 'B', 'v', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 
+'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\010', 'A', 'n', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', ',', 'g', 'o', 'o', 'g', 
+'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 
+'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'a', 'n', 'y', 'p', 'b', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 
+'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 
+'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_any_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/any.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/any.proto", google_protobuf_any_proto_descriptor,
+                               sizeof(google_protobuf_any_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_Any, initOnce) {
+  google_protobuf_any_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_Any_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_Any, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_Any_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Any",
+                   GPBMetadata_Google_Protobuf_Any_methods);
+
+  GPBMetadata_Google_Protobuf_Any_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_Any */
+
+zend_class_entry* google_protobuf_Any_ce;
+
+static PHP_METHOD(google_protobuf_Any, __construct) {
+  google_protobuf_any_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Any, getTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "type_url");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Any, setTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "type_url");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Any, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Any, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_is, 0, 0, 1)
+  ZEND_ARG_INFO(0, proto)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry google_protobuf_Any_phpmethods[] = {
+  PHP_ME(google_protobuf_Any, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Any, getTypeUrl, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Any, setTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Any, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Any, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Any, is, arginfo_is, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Any, pack, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Any, unpack, arginfo_void, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Any_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Any",
+                   google_protobuf_Any_phpmethods);
+
+  google_protobuf_Any_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Any_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Any_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Any_ce, message_ce);
+}
+
+/* google/protobuf/api.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_Api_ce;
+
+const char google_protobuf_api_proto_descriptor [751] = {
+'\n', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'p', 'i', '.', 'p', 'r', 'o', 
+'t', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\032', '$', 'g', 'o', 'o', 'g', 
+'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 
+'t', '.', 'p', 'r', 'o', 't', 'o', '\032', '\032', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 
+'t', 'y', 'p', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\201', '\002', '\n', '\003', 'A', 'p', 'i', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 
+'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '(', '\n', '\007', 'm', 'e', 't', 'h', 'o', 'd', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', 
+'\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', '\022', 
+'(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', 
+'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\017', '\n', '\007', 'v', 'e', 'r', 's', 'i', 
+'o', 'n', '\030', '\004', ' ', '\001', '(', '\t', '\022', '6', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 
+'t', '\030', '\005', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '&', '\n', '\006', 'm', 'i', 'x', 'i', 'n', 's', '\030', 
+'\006', ' ', '\003', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 
+'i', 'x', 'i', 'n', '\022', '\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\007', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 
+'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 't', 'a', 'x', '\"', '\325', '\001', '\n', '\006', 
+'M', 'e', 't', 'h', 'o', 'd', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\030', '\n', '\020', 'r', 
+'e', 'q', 'u', 'e', 's', 't', '_', 't', 'y', 'p', 'e', '_', 'u', 'r', 'l', '\030', '\002', ' ', '\001', '(', '\t', '\022', '\031', '\n', '\021', 
+'r', 'e', 'q', 'u', 'e', 's', 't', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\003', ' ', '\001', '(', '\010', '\022', '\031', 
+'\n', '\021', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 't', 'y', 'p', 'e', '_', 'u', 'r', 'l', '\030', '\004', ' ', '\001', '(', '\t', 
+'\022', '\032', '\n', '\022', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\005', ' ', 
+'\001', '(', '\010', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\006', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 
+'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\'', '\n', '\006', 's', 
+'y', 'n', 't', 'a', 'x', '\030', '\007', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 
+'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 't', 'a', 'x', '\"', '#', '\n', '\005', 'M', 'i', 'x', 'i', 'n', '\022', '\014', '\n', '\004', 'n', 
+'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\014', '\n', '\004', 'r', 'o', 'o', 't', '\030', '\002', ' ', '\001', '(', '\t', 'B', 'v', 
+'\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\010', 'A', 'p', 
+'i', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', ',', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 
+'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'a', 
+'p', 'i', 'p', 'b', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 
+'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', 
+'3', 
+};
+
+static void google_protobuf_api_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/api.proto")) return;
+  google_protobuf_source_context_proto_AddDescriptor();
+  google_protobuf_type_proto_AddDescriptor();
+  DescriptorPool_AddDescriptor("google/protobuf/api.proto", google_protobuf_api_proto_descriptor,
+                               sizeof(google_protobuf_api_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_Api, initOnce) {
+  google_protobuf_api_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_Api_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_Api, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_Api_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Api",
+                   GPBMetadata_Google_Protobuf_Api_methods);
+
+  GPBMetadata_Google_Protobuf_Api_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_Api */
+
+zend_class_entry* google_protobuf_Api_ce;
+
+static PHP_METHOD(google_protobuf_Api, __construct) {
+  google_protobuf_api_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Api, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Api, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Api, getMethods) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "methods");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Api, setMethods) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "methods");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Api, getOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Api, setOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Api, getVersion) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "version");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Api, setVersion) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "version");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Api, getSourceContext) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "source_context");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Api, setSourceContext) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "source_context");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Api, getMixins) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "mixins");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Api, setMixins) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "mixins");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Api, getSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Api, setSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Api_phpmethods[] = {
+  PHP_ME(google_protobuf_Api, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, getMethods, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, setMethods, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, getOptions, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, setOptions, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, getVersion, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, setVersion, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, getSourceContext, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, getMixins, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, setMixins, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, getSyntax, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Api, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Api_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Api",
+                   google_protobuf_Api_phpmethods);
+
+  google_protobuf_Api_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Api_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Api_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Api_ce, message_ce);
+}
+
+/* google_protobuf_Method */
+
+zend_class_entry* google_protobuf_Method_ce;
+
+static PHP_METHOD(google_protobuf_Method, __construct) {
+  google_protobuf_api_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Method, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Method, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Method, getRequestTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "request_type_url");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Method, setRequestTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "request_type_url");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Method, getRequestStreaming) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "request_streaming");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Method, setRequestStreaming) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "request_streaming");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Method, getResponseTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "response_type_url");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Method, setResponseTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "response_type_url");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Method, getResponseStreaming) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "response_streaming");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Method, setResponseStreaming) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "response_streaming");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Method, getOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Method, setOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Method, getSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Method, setSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Method_phpmethods[] = {
+  PHP_ME(google_protobuf_Method, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, getRequestTypeUrl, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, setRequestTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, getRequestStreaming, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, setRequestStreaming, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, getResponseTypeUrl, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, setResponseTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, getResponseStreaming, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, setResponseStreaming, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, getOptions, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, setOptions, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, getSyntax, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Method, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Method_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Method",
+                   google_protobuf_Method_phpmethods);
+
+  google_protobuf_Method_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Method_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Method_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Method_ce, message_ce);
+}
+
+/* google_protobuf_Mixin */
+
+zend_class_entry* google_protobuf_Mixin_ce;
+
+static PHP_METHOD(google_protobuf_Mixin, __construct) {
+  google_protobuf_api_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Mixin, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Mixin, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Mixin, getRoot) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "root");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Mixin, setRoot) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "root");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Mixin_phpmethods[] = {
+  PHP_ME(google_protobuf_Mixin, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Mixin, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Mixin, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Mixin, getRoot, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Mixin, setRoot, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Mixin_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Mixin",
+                   google_protobuf_Mixin_phpmethods);
+
+  google_protobuf_Mixin_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Mixin_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Mixin_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Mixin_ce, message_ce);
+}
+
+/* google/protobuf/duration.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_Duration_ce;
+
+const char google_protobuf_duration_proto_descriptor [235] = {
+'\n', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 'o', 
+'n', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', 
+'*', '\n', '\010', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', '\022', '\017', '\n', '\007', 's', 'e', 'c', 'o', 'n', 'd', 's', '\030', '\001', ' ', 
+'\001', '(', '\003', '\022', '\r', '\n', '\005', 'n', 'a', 'n', 'o', 's', '\030', '\002', ' ', '\001', '(', '\005', 'B', '\203', '\001', '\n', '\023', 'c', 'o', 
+'m', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\r', 'D', 'u', 'r', 'a', 't', 'i', 
+'o', 'n', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '1', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 
+'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 
+'d', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 
+'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 
+'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_duration_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/duration.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/duration.proto", google_protobuf_duration_proto_descriptor,
+                               sizeof(google_protobuf_duration_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_Duration, initOnce) {
+  google_protobuf_duration_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_Duration_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_Duration, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_Duration_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Duration",
+                   GPBMetadata_Google_Protobuf_Duration_methods);
+
+  GPBMetadata_Google_Protobuf_Duration_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_Duration */
+
+zend_class_entry* google_protobuf_Duration_ce;
+
+static PHP_METHOD(google_protobuf_Duration, __construct) {
+  google_protobuf_duration_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Duration, getSeconds) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "seconds");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Duration, setSeconds) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "seconds");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Duration, getNanos) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "nanos");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Duration, setNanos) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "nanos");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Duration_phpmethods[] = {
+  PHP_ME(google_protobuf_Duration, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Duration, getSeconds, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Duration, setSeconds, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Duration, getNanos, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Duration, setNanos, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Duration_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Duration",
+                   google_protobuf_Duration_phpmethods);
+
+  google_protobuf_Duration_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Duration_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Duration_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Duration_ce, message_ce);
+}
+
+/* google/protobuf/empty.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_GPBEmpty_ce;
+
+const char google_protobuf_empty_proto_descriptor [190] = {
+'\n', '\033', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'e', 'm', 'p', 't', 'y', '.', 'p', 
+'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', '\007', '\n', '\005', 
+'E', 'm', 'p', 't', 'y', 'B', '}', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 
+'b', 'u', 'f', 'B', '\n', 'E', 'm', 'p', 't', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '.', 'g', 'o', 'o', 'g', 'l', 'e', 
+'.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 
+'s', '/', 'k', 'n', 'o', 'w', 'n', '/', 'e', 'm', 'p', 't', 'y', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', 
+'\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 
+'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_empty_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/empty.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/empty.proto", google_protobuf_empty_proto_descriptor,
+                               sizeof(google_protobuf_empty_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_GPBEmpty, initOnce) {
+  google_protobuf_empty_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_GPBEmpty_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_GPBEmpty, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_GPBEmpty_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\GPBEmpty",
+                   GPBMetadata_Google_Protobuf_GPBEmpty_methods);
+
+  GPBMetadata_Google_Protobuf_GPBEmpty_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_Empty */
+
+zend_class_entry* google_protobuf_Empty_ce;
+
+static PHP_METHOD(google_protobuf_Empty, __construct) {
+  google_protobuf_empty_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static zend_function_entry google_protobuf_Empty_phpmethods[] = {
+  PHP_ME(google_protobuf_Empty, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Empty_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\GPBEmpty",
+                   google_protobuf_Empty_phpmethods);
+
+  google_protobuf_Empty_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Empty_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Empty_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Empty_ce, message_ce);
+}
+
+/* google/protobuf/field_mask.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_FieldMask_ce;
+
+const char google_protobuf_field_mask_proto_descriptor [223] = {
+'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'f', 'i', 'e', 'l', 'd', '_', 'm', 
+'a', 's', 'k', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 
+'f', '\"', '\032', '\n', '\t', 'F', 'i', 'e', 'l', 'd', 'M', 'a', 's', 'k', '\022', '\r', '\n', '\005', 'p', 'a', 't', 'h', 's', '\030', '\001', 
+' ', '\003', '(', '\t', 'B', '\205', '\001', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 
+'b', 'u', 'f', 'B', '\016', 'F', 'i', 'e', 'l', 'd', 'M', 'a', 's', 'k', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '2', 'g', 'o', 
+'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 
+'t', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'f', 'i', 'e', 'l', 'd', 'm', 'a', 's', 'k', 'p', 'b', '\370', '\001', 
+'\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_field_mask_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/field_mask.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/field_mask.proto", google_protobuf_field_mask_proto_descriptor,
+                               sizeof(google_protobuf_field_mask_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_FieldMask, initOnce) {
+  google_protobuf_field_mask_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_FieldMask_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_FieldMask, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_FieldMask_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\FieldMask",
+                   GPBMetadata_Google_Protobuf_FieldMask_methods);
+
+  GPBMetadata_Google_Protobuf_FieldMask_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_FieldMask */
+
+zend_class_entry* google_protobuf_FieldMask_ce;
+
+static PHP_METHOD(google_protobuf_FieldMask, __construct) {
+  google_protobuf_field_mask_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_FieldMask, getPaths) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "paths");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_FieldMask, setPaths) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "paths");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_FieldMask_phpmethods[] = {
+  PHP_ME(google_protobuf_FieldMask, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_FieldMask, getPaths, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_FieldMask, setPaths, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_FieldMask_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldMask",
+                   google_protobuf_FieldMask_phpmethods);
+
+  google_protobuf_FieldMask_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_FieldMask_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_FieldMask_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_FieldMask_ce, message_ce);
+}
+
+/* google/protobuf/source_context.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_SourceContext_ce;
+
+const char google_protobuf_source_context_proto_descriptor [240] = {
+'\n', '$', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 'o', 'u', 'r', 'c', 'e', '_', 
+'c', 'o', 'n', 't', 'e', 'x', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 
+'t', 'o', 'b', 'u', 'f', '\"', '\"', '\n', '\r', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\021', '\n', 
+'\t', 'f', 'i', 'l', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\212', '\001', '\n', '\023', 'c', 'o', 'm', '.', 
+'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\022', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 
+'n', 't', 'e', 'x', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '6', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 
+'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 
+'w', 'n', '/', 's', 'o', 'u', 'r', 'c', 'e', 'c', 'o', 'n', 't', 'e', 'x', 't', 'p', 'b', '\242', '\002', '\003', 'G', 'P', 'B', '\252', 
+'\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 
+'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_source_context_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/source_context.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/source_context.proto", google_protobuf_source_context_proto_descriptor,
+                               sizeof(google_protobuf_source_context_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_SourceContext, initOnce) {
+  google_protobuf_source_context_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_SourceContext_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_SourceContext, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_SourceContext_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\SourceContext",
+                   GPBMetadata_Google_Protobuf_SourceContext_methods);
+
+  GPBMetadata_Google_Protobuf_SourceContext_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_SourceContext */
+
+zend_class_entry* google_protobuf_SourceContext_ce;
+
+static PHP_METHOD(google_protobuf_SourceContext, __construct) {
+  google_protobuf_source_context_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_SourceContext, getFileName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "file_name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_SourceContext, setFileName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "file_name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_SourceContext_phpmethods[] = {
+  PHP_ME(google_protobuf_SourceContext, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_SourceContext, getFileName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_SourceContext, setFileName, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_SourceContext_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\SourceContext",
+                   google_protobuf_SourceContext_phpmethods);
+
+  google_protobuf_SourceContext_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_SourceContext_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_SourceContext_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_SourceContext_ce, message_ce);
+}
+
+/* google/protobuf/struct.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_Struct_ce;
+
+const char google_protobuf_struct_proto_descriptor [638] = {
+'\n', '\034', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 't', 'r', 'u', 'c', 't', '.', 
+'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', '\204', '\001', 
+'\n', '\006', 'S', 't', 'r', 'u', 'c', 't', '\022', '3', '\n', '\006', 'f', 'i', 'e', 'l', 'd', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', 
+'#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', '.', 
+'F', 'i', 'e', 'l', 'd', 's', 'E', 'n', 't', 'r', 'y', '\032', 'E', '\n', '\013', 'F', 'i', 'e', 'l', 'd', 's', 'E', 'n', 't', 'r', 
+'y', '\022', '\013', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', '\022', '%', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', 
+' ', '\001', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'V', 'a', 
+'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '\352', '\001', '\n', '\005', 'V', 'a', 'l', 'u', 'e', '\022', '0', '\n', '\n', 'n', 'u', 'l', 'l', 
+'_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 
+'t', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', 'H', '\000', '\022', '\026', '\n', '\014', 'n', 'u', 'm', 'b', 
+'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\001', 'H', '\000', '\022', '\026', '\n', '\014', 's', 't', 'r', 'i', 'n', 
+'g', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'H', '\000', '\022', '\024', '\n', '\n', 'b', 'o', 'o', 'l', '_', 'v', 
+'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\010', 'H', '\000', '\022', '/', '\n', '\014', 's', 't', 'r', 'u', 'c', 't', '_', 'v', 'a', 
+'l', 'u', 'e', '\030', '\005', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 
+'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'H', '\000', '\022', '0', '\n', '\n', 'l', 'i', 's', 't', '_', 'v', 'a', 'l', 'u', 'e', 
+'\030', '\006', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 
+'L', 'i', 's', 't', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'B', '\006', '\n', '\004', 'k', 'i', 'n', 'd', '\"', '3', '\n', '\t', 'L', 'i', 
+'s', 't', 'V', 'a', 'l', 'u', 'e', '\022', '&', '\n', '\006', 'v', 'a', 'l', 'u', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\026', 
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'V', 'a', 'l', 'u', 'e', '*', '\033', '\n', 
+'\t', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '\016', '\n', '\n', 'N', 'U', 'L', 'L', '_', 'V', 'A', 'L', 'U', 'E', '\020', 
+'\000', 'B', '\177', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', 
+'\013', 'S', 't', 'r', 'u', 'c', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '/', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 
+'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 
+'n', 'o', 'w', 'n', '/', 's', 't', 'r', 'u', 'c', 't', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 
+'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 
+'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_struct_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/struct.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/struct.proto", google_protobuf_struct_proto_descriptor,
+                               sizeof(google_protobuf_struct_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_Struct, initOnce) {
+  google_protobuf_struct_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_Struct_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_Struct, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_Struct_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Struct",
+                   GPBMetadata_Google_Protobuf_Struct_methods);
+
+  GPBMetadata_Google_Protobuf_Struct_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_Struct */
+
+zend_class_entry* google_protobuf_Struct_ce;
+
+static PHP_METHOD(google_protobuf_Struct, __construct) {
+  google_protobuf_struct_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Struct, getFields) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "fields");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Struct, setFields) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "fields");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Struct_phpmethods[] = {
+  PHP_ME(google_protobuf_Struct, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Struct, getFields, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Struct, setFields, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Struct_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Struct",
+                   google_protobuf_Struct_phpmethods);
+
+  google_protobuf_Struct_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Struct_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Struct_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Struct_ce, message_ce);
+}
+
+/* google_protobuf_Struct_FieldsEntry */
+
+zend_class_entry* google_protobuf_Struct_FieldsEntry_ce;
+
+static PHP_METHOD(google_protobuf_Struct_FieldsEntry, __construct) {
+  google_protobuf_struct_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Struct_FieldsEntry, getKey) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "key");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Struct_FieldsEntry, setKey) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "key");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Struct_FieldsEntry, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Struct_FieldsEntry, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Struct_FieldsEntry_phpmethods[] = {
+  PHP_ME(google_protobuf_Struct_FieldsEntry, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Struct_FieldsEntry, getKey, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Struct_FieldsEntry, setKey, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Struct_FieldsEntry, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Struct_FieldsEntry, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Struct_FieldsEntry_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Struct\\FieldsEntry",
+                   google_protobuf_Struct_FieldsEntry_phpmethods);
+
+  google_protobuf_Struct_FieldsEntry_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Struct_FieldsEntry_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Struct_FieldsEntry_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Struct_FieldsEntry_ce, message_ce);
+}
+
+/* google_protobuf_Value */
+
+zend_class_entry* google_protobuf_Value_ce;
+
+static PHP_METHOD(google_protobuf_Value, __construct) {
+  google_protobuf_struct_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Value, getNullValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "null_value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Value, setNullValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "null_value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Value, getNumberValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "number_value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Value, setNumberValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "number_value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Value, getStringValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "string_value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Value, setStringValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "string_value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Value, getBoolValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "bool_value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Value, setBoolValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "bool_value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Value, getStructValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "struct_value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Value, setStructValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "struct_value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Value, getListValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "list_value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Value, setListValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "list_value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Value, getKind) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_oneofdef *oneof = upb_msgdef_ntooz(intern->desc->msgdef,
+                                              "kind");
+  const upb_fielddef *field = upb_msg_whichoneof(intern->msg, oneof);
+  RETURN_STRING(field ? upb_fielddef_name(field) : "");
+}
+static zend_function_entry google_protobuf_Value_phpmethods[] = {
+  PHP_ME(google_protobuf_Value, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, getNullValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, setNullValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, getNumberValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, setNumberValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, getStringValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, setStringValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, getBoolValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, setBoolValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, getStructValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, setStructValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, getListValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, setListValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Value, getKind, arginfo_void, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Value_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Value",
+                   google_protobuf_Value_phpmethods);
+
+  google_protobuf_Value_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Value_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Value_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Value_ce, message_ce);
+}
+
+/* google_protobuf_ListValue */
+
+zend_class_entry* google_protobuf_ListValue_ce;
+
+static PHP_METHOD(google_protobuf_ListValue, __construct) {
+  google_protobuf_struct_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_ListValue, getValues) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "values");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_ListValue, setValues) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "values");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_ListValue_phpmethods[] = {
+  PHP_ME(google_protobuf_ListValue, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_ListValue, getValues, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_ListValue, setValues, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_ListValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\ListValue",
+                   google_protobuf_ListValue_phpmethods);
+
+  google_protobuf_ListValue_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_ListValue_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_ListValue_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_ListValue_ce, message_ce);
+}
+
+/* google_protobuf_NullValue */
+
+zend_class_entry* google_protobuf_NullValue_ce;
+
+PHP_METHOD(google_protobuf_NullValue, name) {
+  google_protobuf_struct_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.NullValue");
+  const char *name;
+  zend_long value;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) ==
+      FAILURE) {
+    return;
+  }
+  name = upb_enumdef_iton(e, value);
+  if (!name) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\NullValue has no name "
+                            "defined for value " ZEND_LONG_FMT ".",
+                            value);
+    return;
+  }
+  RETURN_STRING(name);
+}
+
+PHP_METHOD(google_protobuf_NullValue, value) {
+  google_protobuf_struct_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.NullValue");
+  char *name = NULL;
+  size_t name_len;
+  int32_t num;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name,
+                            &name_len) == FAILURE) {
+    return;
+  }
+  if (!upb_enumdef_ntoi(e, name, name_len, &num)) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\NullValue has no value "
+                            "defined for name %s.",
+                            name);
+    return;
+  }
+  RETURN_LONG(num);
+}
+
+static zend_function_entry google_protobuf_NullValue_phpmethods[] = {
+  PHP_ME(google_protobuf_NullValue, name, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(google_protobuf_NullValue, value, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_NullValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\NullValue",
+                   google_protobuf_NullValue_phpmethods);
+
+  google_protobuf_NullValue_ce = zend_register_internal_class(&tmp_ce);
+  zend_declare_class_constant_long(google_protobuf_NullValue_ce, "NULL_VALUE",
+                                   strlen("NULL_VALUE"), 0);
+}
+
+/* google/protobuf/type.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_Type_ce;
+
+const char google_protobuf_type_proto_descriptor [1592] = {
+'\n', '\032', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', '.', 'p', 'r', 
+'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\032', '\031', 'g', 'o', 'o', 
+'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '$', 'g', 
+'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 
+'t', 'e', 'x', 't', '.', 'p', 'r', 'o', 't', 'o', '\"', '\327', '\001', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\014', '\n', '\004', 'n', 'a', 
+'m', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '&', '\n', '\006', 'f', 'i', 'e', 'l', 'd', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', 
+'\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', '\022', '\016', 
+'\n', '\006', 'o', 'n', 'e', 'o', 'f', 's', '\030', '\003', ' ', '\003', '(', '\t', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', 
+'\030', '\004', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 
+'O', 'p', 't', 'i', 'o', 'n', '\022', '6', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', 
+'\005', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 
+'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\006', ' ', 
+'\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 
+'t', 'a', 'x', '\"', '\325', '\005', '\n', '\005', 'F', 'i', 'e', 'l', 'd', '\022', ')', '\n', '\004', 'k', 'i', 'n', 'd', '\030', '\001', ' ', '\001', 
+'(', '\016', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 
+'d', '.', 'K', 'i', 'n', 'd', '\022', '7', '\n', '\013', 'c', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\030', '\002', ' ', '\001', 
+'(', '\016', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 
+'d', '.', 'C', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\003', 
+' ', '\001', '(', '\005', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\004', ' ', '\001', '(', '\t', '\022', '\020', '\n', '\010', 't', 'y', 'p', 
+'e', '_', 'u', 'r', 'l', '\030', '\006', ' ', '\001', '(', '\t', '\022', '\023', '\n', '\013', 'o', 'n', 'e', 'o', 'f', '_', 'i', 'n', 'd', 'e', 
+'x', '\030', '\007', ' ', '\001', '(', '\005', '\022', '\016', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\010', ' ', '\001', '(', '\010', '\022', '(', 
+'\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\t', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\021', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', 
+'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', '\022', '\025', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 
+'e', '\030', '\013', ' ', '\001', '(', '\t', '\"', '\310', '\002', '\n', '\004', 'K', 'i', 'n', 'd', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 
+'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', 'L', 'E', '\020', 
+'\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', 
+'_', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', '4', '\020', '\004', 
+'\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 
+'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '3', '2', 
+'\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', 
+'_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', 'P', '\020', '\n', 
+'\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 
+'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '3', '2', '\020', 
+'\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 
+'S', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', 
+'6', '4', '\020', '\020', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', '\017', '\n', '\013', 
+'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 't', '\n', '\013', 'C', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 
+'i', 't', 'y', '\022', '\027', '\n', '\023', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 
+'N', '\020', '\000', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'O', 'P', 'T', 'I', 'O', 'N', 
+'A', 'L', '\020', '\001', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'Q', 'U', 'I', 
+'R', 'E', 'D', '\020', '\002', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'P', 'E', 
+'A', 'T', 'E', 'D', '\020', '\003', '\"', '\316', '\001', '\n', '\004', 'E', 'n', 'u', 'm', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', 
+' ', '\001', '(', '\t', '\022', '-', '\n', '\t', 'e', 'n', 'u', 'm', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', '\032', 
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 
+'e', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '6', '\n', '\016', 's', 'o', 'u', 
+'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 
+'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', 
+'\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\005', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 't', 'a', 'x', '\"', 'S', '\n', '\t', 'E', 'n', 'u', 'm', 'V', 'a', 
+'l', 'u', 'e', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', 
+'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', 
+'2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', 
+'\"', ';', '\n', '\006', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', 
+'#', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 
+'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', '*', '.', '\n', '\006', 'S', 'y', 'n', 't', 'a', 'x', '\022', '\021', '\n', '\r', 
+'S', 'Y', 'N', 'T', 'A', 'X', '_', 'P', 'R', 'O', 'T', 'O', '2', '\020', '\000', '\022', '\021', '\n', '\r', 'S', 'Y', 'N', 'T', 'A', 'X', 
+'_', 'P', 'R', 'O', 'T', 'O', '3', '\020', '\001', 'B', '{', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 
+'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\t', 'T', 'y', 'p', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '-', 'g', 'o', 'o', 
+'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 
+'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 't', 'y', 'p', 'e', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 
+'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 
+'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_type_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/type.proto")) return;
+  google_protobuf_any_proto_AddDescriptor();
+  google_protobuf_source_context_proto_AddDescriptor();
+  DescriptorPool_AddDescriptor("google/protobuf/type.proto", google_protobuf_type_proto_descriptor,
+                               sizeof(google_protobuf_type_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_Type, initOnce) {
+  google_protobuf_type_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_Type_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_Type, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_Type_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Type",
+                   GPBMetadata_Google_Protobuf_Type_methods);
+
+  GPBMetadata_Google_Protobuf_Type_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_Type */
+
+zend_class_entry* google_protobuf_Type_ce;
+
+static PHP_METHOD(google_protobuf_Type, __construct) {
+  google_protobuf_type_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Type, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Type, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Type, getFields) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "fields");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Type, setFields) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "fields");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Type, getOneofs) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "oneofs");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Type, setOneofs) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "oneofs");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Type, getOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Type, setOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Type, getSourceContext) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "source_context");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Type, setSourceContext) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "source_context");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Type, getSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Type, setSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Type_phpmethods[] = {
+  PHP_ME(google_protobuf_Type, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, getFields, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, setFields, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, getOneofs, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, setOneofs, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, getOptions, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, setOptions, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, getSourceContext, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, getSyntax, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Type, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Type_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Type",
+                   google_protobuf_Type_phpmethods);
+
+  google_protobuf_Type_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Type_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Type_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Type_ce, message_ce);
+}
+
+/* google_protobuf_Field */
+
+zend_class_entry* google_protobuf_Field_ce;
+
+static PHP_METHOD(google_protobuf_Field, __construct) {
+  google_protobuf_type_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Field, getKind) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "kind");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setKind) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "kind");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getCardinality) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "cardinality");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setCardinality) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "cardinality");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getNumber) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "number");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setNumber) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "number");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "type_url");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setTypeUrl) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "type_url");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getOneofIndex) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "oneof_index");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setOneofIndex) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "oneof_index");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getPacked) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "packed");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setPacked) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "packed");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getJsonName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "json_name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setJsonName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "json_name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Field, getDefaultValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "default_value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Field, setDefaultValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "default_value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Field_phpmethods[] = {
+  PHP_ME(google_protobuf_Field, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getKind, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setKind, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getCardinality, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setCardinality, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setNumber, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getTypeUrl, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getOneofIndex, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setOneofIndex, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getPacked, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setPacked, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getOptions, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setOptions, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getJsonName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setJsonName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, getDefaultValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Field, setDefaultValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Field_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field",
+                   google_protobuf_Field_phpmethods);
+
+  google_protobuf_Field_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Field_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Field_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Field_ce, message_ce);
+}
+
+/* google_protobuf_Field_Kind */
+
+zend_class_entry* google_protobuf_Field_Kind_ce;
+
+PHP_METHOD(google_protobuf_Field_Kind, name) {
+  google_protobuf_type_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Kind");
+  const char *name;
+  zend_long value;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) ==
+      FAILURE) {
+    return;
+  }
+  name = upb_enumdef_iton(e, value);
+  if (!name) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\Field\\Kind has no name "
+                            "defined for value " ZEND_LONG_FMT ".",
+                            value);
+    return;
+  }
+  RETURN_STRING(name);
+}
+
+PHP_METHOD(google_protobuf_Field_Kind, value) {
+  google_protobuf_type_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Kind");
+  char *name = NULL;
+  size_t name_len;
+  int32_t num;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name,
+                            &name_len) == FAILURE) {
+    return;
+  }
+  if (!upb_enumdef_ntoi(e, name, name_len, &num)) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\Field\\Kind has no value "
+                            "defined for name %s.",
+                            name);
+    return;
+  }
+  RETURN_LONG(num);
+}
+
+static zend_function_entry google_protobuf_Field_Kind_phpmethods[] = {
+  PHP_ME(google_protobuf_Field_Kind, name, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(google_protobuf_Field_Kind, value, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Field_Kind_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field\\Kind",
+                   google_protobuf_Field_Kind_phpmethods);
+
+  google_protobuf_Field_Kind_ce = zend_register_internal_class(&tmp_ce);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UNKNOWN",
+                                   strlen("TYPE_UNKNOWN"), 0);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_DOUBLE",
+                                   strlen("TYPE_DOUBLE"), 1);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FLOAT",
+                                   strlen("TYPE_FLOAT"), 2);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_INT64",
+                                   strlen("TYPE_INT64"), 3);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UINT64",
+                                   strlen("TYPE_UINT64"), 4);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_INT32",
+                                   strlen("TYPE_INT32"), 5);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FIXED64",
+                                   strlen("TYPE_FIXED64"), 6);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FIXED32",
+                                   strlen("TYPE_FIXED32"), 7);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_BOOL",
+                                   strlen("TYPE_BOOL"), 8);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_STRING",
+                                   strlen("TYPE_STRING"), 9);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_GROUP",
+                                   strlen("TYPE_GROUP"), 10);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_MESSAGE",
+                                   strlen("TYPE_MESSAGE"), 11);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_BYTES",
+                                   strlen("TYPE_BYTES"), 12);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UINT32",
+                                   strlen("TYPE_UINT32"), 13);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_ENUM",
+                                   strlen("TYPE_ENUM"), 14);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SFIXED32",
+                                   strlen("TYPE_SFIXED32"), 15);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SFIXED64",
+                                   strlen("TYPE_SFIXED64"), 16);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SINT32",
+                                   strlen("TYPE_SINT32"), 17);
+  zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SINT64",
+                                   strlen("TYPE_SINT64"), 18);
+}
+
+/* google_protobuf_Field_Cardinality */
+
+zend_class_entry* google_protobuf_Field_Cardinality_ce;
+
+PHP_METHOD(google_protobuf_Field_Cardinality, name) {
+  google_protobuf_type_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Cardinality");
+  const char *name;
+  zend_long value;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) ==
+      FAILURE) {
+    return;
+  }
+  name = upb_enumdef_iton(e, value);
+  if (!name) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\Field\\Cardinality has no name "
+                            "defined for value " ZEND_LONG_FMT ".",
+                            value);
+    return;
+  }
+  RETURN_STRING(name);
+}
+
+PHP_METHOD(google_protobuf_Field_Cardinality, value) {
+  google_protobuf_type_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Cardinality");
+  char *name = NULL;
+  size_t name_len;
+  int32_t num;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name,
+                            &name_len) == FAILURE) {
+    return;
+  }
+  if (!upb_enumdef_ntoi(e, name, name_len, &num)) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\Field\\Cardinality has no value "
+                            "defined for name %s.",
+                            name);
+    return;
+  }
+  RETURN_LONG(num);
+}
+
+static zend_function_entry google_protobuf_Field_Cardinality_phpmethods[] = {
+  PHP_ME(google_protobuf_Field_Cardinality, name, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(google_protobuf_Field_Cardinality, value, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Field_Cardinality_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field\\Cardinality",
+                   google_protobuf_Field_Cardinality_phpmethods);
+
+  google_protobuf_Field_Cardinality_ce = zend_register_internal_class(&tmp_ce);
+  zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_UNKNOWN",
+                                   strlen("CARDINALITY_UNKNOWN"), 0);
+  zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_OPTIONAL",
+                                   strlen("CARDINALITY_OPTIONAL"), 1);
+  zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_REQUIRED",
+                                   strlen("CARDINALITY_REQUIRED"), 2);
+  zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_REPEATED",
+                                   strlen("CARDINALITY_REPEATED"), 3);
+}
+
+/* google_protobuf_Enum */
+
+zend_class_entry* google_protobuf_Enum_ce;
+
+static PHP_METHOD(google_protobuf_Enum, __construct) {
+  google_protobuf_type_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Enum, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Enum, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Enum, getEnumvalue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "enumvalue");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Enum, setEnumvalue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "enumvalue");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Enum, getOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Enum, setOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Enum, getSourceContext) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "source_context");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Enum, setSourceContext) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "source_context");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Enum, getSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Enum, setSyntax) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "syntax");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Enum_phpmethods[] = {
+  PHP_ME(google_protobuf_Enum, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, getEnumvalue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, setEnumvalue, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, getOptions, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, setOptions, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, getSourceContext, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, getSyntax, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Enum, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Enum_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Enum",
+                   google_protobuf_Enum_phpmethods);
+
+  google_protobuf_Enum_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Enum_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Enum_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Enum_ce, message_ce);
+}
+
+/* google_protobuf_EnumValue */
+
+zend_class_entry* google_protobuf_EnumValue_ce;
+
+static PHP_METHOD(google_protobuf_EnumValue, __construct) {
+  google_protobuf_type_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_EnumValue, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_EnumValue, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_EnumValue, getNumber) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "number");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_EnumValue, setNumber) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "number");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_EnumValue, getOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_EnumValue, setOptions) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "options");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_EnumValue_phpmethods[] = {
+  PHP_ME(google_protobuf_EnumValue, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_EnumValue, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_EnumValue, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_EnumValue, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_EnumValue, setNumber, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_EnumValue, getOptions, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_EnumValue, setOptions, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_EnumValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValue",
+                   google_protobuf_EnumValue_phpmethods);
+
+  google_protobuf_EnumValue_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_EnumValue_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_EnumValue_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_EnumValue_ce, message_ce);
+}
+
+/* google_protobuf_Option */
+
+zend_class_entry* google_protobuf_Option_ce;
+
+static PHP_METHOD(google_protobuf_Option, __construct) {
+  google_protobuf_type_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Option, getName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Option, setName) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "name");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Option, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Option, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Option_phpmethods[] = {
+  PHP_ME(google_protobuf_Option, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Option, getName, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Option, setName, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Option, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Option, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Option_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Option",
+                   google_protobuf_Option_phpmethods);
+
+  google_protobuf_Option_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Option_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Option_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Option_ce, message_ce);
+}
+
+/* google_protobuf_Syntax */
+
+zend_class_entry* google_protobuf_Syntax_ce;
+
+PHP_METHOD(google_protobuf_Syntax, name) {
+  google_protobuf_type_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Syntax");
+  const char *name;
+  zend_long value;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) ==
+      FAILURE) {
+    return;
+  }
+  name = upb_enumdef_iton(e, value);
+  if (!name) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\Syntax has no name "
+                            "defined for value " ZEND_LONG_FMT ".",
+                            value);
+    return;
+  }
+  RETURN_STRING(name);
+}
+
+PHP_METHOD(google_protobuf_Syntax, value) {
+  google_protobuf_type_proto_AddDescriptor();
+  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();
+  const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Syntax");
+  char *name = NULL;
+  size_t name_len;
+  int32_t num;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name,
+                            &name_len) == FAILURE) {
+    return;
+  }
+  if (!upb_enumdef_ntoi(e, name, name_len, &num)) {
+    zend_throw_exception_ex(NULL, 0,
+                            "Google\\Protobuf\\Syntax has no value "
+                            "defined for name %s.",
+                            name);
+    return;
+  }
+  RETURN_LONG(num);
+}
+
+static zend_function_entry google_protobuf_Syntax_phpmethods[] = {
+  PHP_ME(google_protobuf_Syntax, name, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(google_protobuf_Syntax, value, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Syntax_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Syntax",
+                   google_protobuf_Syntax_phpmethods);
+
+  google_protobuf_Syntax_ce = zend_register_internal_class(&tmp_ce);
+  zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_PROTO2",
+                                   strlen("SYNTAX_PROTO2"), 0);
+  zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_PROTO3",
+                                   strlen("SYNTAX_PROTO3"), 1);
+}
+
+/* google/protobuf/timestamp.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_Timestamp_ce;
+
+const char google_protobuf_timestamp_proto_descriptor [239] = {
+'\n', '\037', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'i', 'm', 'e', 's', 't', 'a', 
+'m', 'p', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 
+'\"', '+', '\n', '\t', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '\022', '\017', '\n', '\007', 's', 'e', 'c', 'o', 'n', 'd', 's', '\030', 
+'\001', ' ', '\001', '(', '\003', '\022', '\r', '\n', '\005', 'n', 'a', 'n', 'o', 's', '\030', '\002', ' ', '\001', '(', '\005', 'B', '\205', '\001', '\n', '\023', 
+'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\016', 'T', 'i', 'm', 'e', 
+'s', 't', 'a', 'm', 'p', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '2', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 
+'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 
+'w', 'n', '/', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', 
+'\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 
+'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_timestamp_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/timestamp.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/timestamp.proto", google_protobuf_timestamp_proto_descriptor,
+                               sizeof(google_protobuf_timestamp_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_Timestamp, initOnce) {
+  google_protobuf_timestamp_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_Timestamp_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_Timestamp, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_Timestamp_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Timestamp",
+                   GPBMetadata_Google_Protobuf_Timestamp_methods);
+
+  GPBMetadata_Google_Protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_Timestamp */
+
+zend_class_entry* google_protobuf_Timestamp_ce;
+
+static PHP_METHOD(google_protobuf_Timestamp, __construct) {
+  google_protobuf_timestamp_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Timestamp, getSeconds) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "seconds");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Timestamp, setSeconds) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "seconds");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static PHP_METHOD(google_protobuf_Timestamp, getNanos) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "nanos");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Timestamp, setNanos) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "nanos");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1)
+  ZEND_ARG_INFO(0, datetime)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry google_protobuf_Timestamp_phpmethods[] = {
+  PHP_ME(google_protobuf_Timestamp, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Timestamp, getSeconds, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Timestamp, setSeconds, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Timestamp, getNanos, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Timestamp, setNanos, arginfo_setter, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Timestamp, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Timestamp, toDateTime, arginfo_void, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Timestamp_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Timestamp",
+                   google_protobuf_Timestamp_phpmethods);
+
+  google_protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Timestamp_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Timestamp_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Timestamp_ce, message_ce);
+}
+
+/* google/protobuf/wrappers.proto */
+
+zend_class_entry* GPBMetadata_Google_Protobuf_Wrappers_ce;
+
+const char google_protobuf_wrappers_proto_descriptor [455] = {
+'\n', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 
+'s', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', 
+'\034', '\n', '\013', 'D', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', 
+' ', '\001', '(', '\001', '\"', '\033', '\n', '\n', 'F', 'l', 'o', 'a', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 
+'u', 'e', '\030', '\001', ' ', '\001', '(', '\002', '\"', '\033', '\n', '\n', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', 
+'\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\003', '\"', '\034', '\n', '\013', 'U', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', 
+'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\004', '\"', '\033', '\n', '\n', 'I', 'n', 't', '3', 
+'2', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\005', '\"', '\034', '\n', '\013', 
+'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', 
+'\r', '\"', '\032', '\n', '\t', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', 
+' ', '\001', '(', '\010', '\"', '\034', '\n', '\013', 'S', 't', 'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 
+'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\"', '\033', '\n', '\n', 'B', 'y', 't', 'e', 's', 'V', 'a', 'l', 'u', 'e', '\022', '\r', 
+'\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\014', 'B', '\203', '\001', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 
+'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\r', 'W', 'r', 'a', 'p', 'p', 'e', 'r', 's', 'P', 'r', 'o', 
+'t', 'o', 'P', '\001', 'Z', '1', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 
+'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'w', 'r', 'a', 'p', 'p', 
+'e', 'r', 's', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 
+'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 
+'r', 'o', 't', 'o', '3', 
+};
+
+static void google_protobuf_wrappers_proto_AddDescriptor() {
+  if (DescriptorPool_HasFile("google/protobuf/wrappers.proto")) return;
+  DescriptorPool_AddDescriptor("google/protobuf/wrappers.proto", google_protobuf_wrappers_proto_descriptor,
+                               sizeof(google_protobuf_wrappers_proto_descriptor));
+}
+
+static PHP_METHOD(GPBMetadata_Google_Protobuf_Wrappers, initOnce) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+}
+
+static zend_function_entry GPBMetadata_Google_Protobuf_Wrappers_methods[] = {
+  PHP_ME(GPBMetadata_Google_Protobuf_Wrappers, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  ZEND_FE_END
+};
+
+static void GPBMetadata_Google_Protobuf_Wrappers_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Wrappers",
+                   GPBMetadata_Google_Protobuf_Wrappers_methods);
+
+  GPBMetadata_Google_Protobuf_Wrappers_ce = zend_register_internal_class(&tmp_ce);
+}
+
+/* google_protobuf_DoubleValue */
+
+zend_class_entry* google_protobuf_DoubleValue_ce;
+
+static PHP_METHOD(google_protobuf_DoubleValue, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_DoubleValue, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_DoubleValue, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_DoubleValue_phpmethods[] = {
+  PHP_ME(google_protobuf_DoubleValue, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_DoubleValue, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_DoubleValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_DoubleValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DoubleValue",
+                   google_protobuf_DoubleValue_phpmethods);
+
+  google_protobuf_DoubleValue_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_DoubleValue_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_DoubleValue_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_DoubleValue_ce, message_ce);
+}
+
+/* google_protobuf_FloatValue */
+
+zend_class_entry* google_protobuf_FloatValue_ce;
+
+static PHP_METHOD(google_protobuf_FloatValue, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_FloatValue, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_FloatValue, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_FloatValue_phpmethods[] = {
+  PHP_ME(google_protobuf_FloatValue, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_FloatValue, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_FloatValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_FloatValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FloatValue",
+                   google_protobuf_FloatValue_phpmethods);
+
+  google_protobuf_FloatValue_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_FloatValue_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_FloatValue_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_FloatValue_ce, message_ce);
+}
+
+/* google_protobuf_Int64Value */
+
+zend_class_entry* google_protobuf_Int64Value_ce;
+
+static PHP_METHOD(google_protobuf_Int64Value, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Int64Value, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Int64Value, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Int64Value_phpmethods[] = {
+  PHP_ME(google_protobuf_Int64Value, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Int64Value, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Int64Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Int64Value_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Int64Value",
+                   google_protobuf_Int64Value_phpmethods);
+
+  google_protobuf_Int64Value_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Int64Value_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Int64Value_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Int64Value_ce, message_ce);
+}
+
+/* google_protobuf_UInt64Value */
+
+zend_class_entry* google_protobuf_UInt64Value_ce;
+
+static PHP_METHOD(google_protobuf_UInt64Value, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_UInt64Value, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_UInt64Value, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_UInt64Value_phpmethods[] = {
+  PHP_ME(google_protobuf_UInt64Value, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_UInt64Value, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_UInt64Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_UInt64Value_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\UInt64Value",
+                   google_protobuf_UInt64Value_phpmethods);
+
+  google_protobuf_UInt64Value_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_UInt64Value_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_UInt64Value_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_UInt64Value_ce, message_ce);
+}
+
+/* google_protobuf_Int32Value */
+
+zend_class_entry* google_protobuf_Int32Value_ce;
+
+static PHP_METHOD(google_protobuf_Int32Value, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_Int32Value, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_Int32Value, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_Int32Value_phpmethods[] = {
+  PHP_ME(google_protobuf_Int32Value, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Int32Value, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_Int32Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_Int32Value_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Int32Value",
+                   google_protobuf_Int32Value_phpmethods);
+
+  google_protobuf_Int32Value_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_Int32Value_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_Int32Value_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_Int32Value_ce, message_ce);
+}
+
+/* google_protobuf_UInt32Value */
+
+zend_class_entry* google_protobuf_UInt32Value_ce;
+
+static PHP_METHOD(google_protobuf_UInt32Value, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_UInt32Value, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_UInt32Value, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_UInt32Value_phpmethods[] = {
+  PHP_ME(google_protobuf_UInt32Value, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_UInt32Value, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_UInt32Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_UInt32Value_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\UInt32Value",
+                   google_protobuf_UInt32Value_phpmethods);
+
+  google_protobuf_UInt32Value_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_UInt32Value_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_UInt32Value_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_UInt32Value_ce, message_ce);
+}
+
+/* google_protobuf_BoolValue */
+
+zend_class_entry* google_protobuf_BoolValue_ce;
+
+static PHP_METHOD(google_protobuf_BoolValue, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_BoolValue, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_BoolValue, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_BoolValue_phpmethods[] = {
+  PHP_ME(google_protobuf_BoolValue, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_BoolValue, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_BoolValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_BoolValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\BoolValue",
+                   google_protobuf_BoolValue_phpmethods);
+
+  google_protobuf_BoolValue_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_BoolValue_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_BoolValue_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_BoolValue_ce, message_ce);
+}
+
+/* google_protobuf_StringValue */
+
+zend_class_entry* google_protobuf_StringValue_ce;
+
+static PHP_METHOD(google_protobuf_StringValue, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_StringValue, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_StringValue, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_StringValue_phpmethods[] = {
+  PHP_ME(google_protobuf_StringValue, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_StringValue, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_StringValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_StringValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\StringValue",
+                   google_protobuf_StringValue_phpmethods);
+
+  google_protobuf_StringValue_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_StringValue_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_StringValue_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_StringValue_ce, message_ce);
+}
+
+/* google_protobuf_BytesValue */
+
+zend_class_entry* google_protobuf_BytesValue_ce;
+
+static PHP_METHOD(google_protobuf_BytesValue, __construct) {
+  google_protobuf_wrappers_proto_AddDescriptor();
+  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static PHP_METHOD(google_protobuf_BytesValue, getValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval ret;
+  Message_get(intern, f, &ret);
+  RETURN_COPY_VALUE(&ret);
+}
+
+static PHP_METHOD(google_protobuf_BytesValue, setValue) {
+  Message* intern = (Message*)Z_OBJ_P(getThis());
+  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,
+                                           "value");
+  zval *val;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val)
+      == FAILURE) {
+    return;
+  }
+  Message_set(intern, f, val);
+  RETURN_COPY(getThis());
+}
+
+static zend_function_entry google_protobuf_BytesValue_phpmethods[] = {
+  PHP_ME(google_protobuf_BytesValue, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_BytesValue, getValue, arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(google_protobuf_BytesValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static void google_protobuf_BytesValue_ModuleInit() {
+  zend_class_entry tmp_ce;
+
+  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\BytesValue",
+                   google_protobuf_BytesValue_phpmethods);
+
+  google_protobuf_BytesValue_ce = zend_register_internal_class(&tmp_ce);
+  google_protobuf_BytesValue_ce->ce_flags |= ZEND_ACC_FINAL;
+  google_protobuf_BytesValue_ce->create_object = Message_create;
+  zend_do_inheritance(google_protobuf_BytesValue_ce, message_ce);
+}
+
+static void WellKnownTypes_ModuleInit() {
+  GPBMetadata_Google_Protobuf_Any_ModuleInit();
+  google_protobuf_Any_ModuleInit();
+  GPBMetadata_Google_Protobuf_Api_ModuleInit();
+  google_protobuf_Api_ModuleInit();
+  google_protobuf_Method_ModuleInit();
+  google_protobuf_Mixin_ModuleInit();
+  GPBMetadata_Google_Protobuf_Duration_ModuleInit();
+  google_protobuf_Duration_ModuleInit();
+  GPBMetadata_Google_Protobuf_GPBEmpty_ModuleInit();
+  google_protobuf_Empty_ModuleInit();
+  GPBMetadata_Google_Protobuf_FieldMask_ModuleInit();
+  google_protobuf_FieldMask_ModuleInit();
+  GPBMetadata_Google_Protobuf_SourceContext_ModuleInit();
+  google_protobuf_SourceContext_ModuleInit();
+  GPBMetadata_Google_Protobuf_Struct_ModuleInit();
+  google_protobuf_Struct_ModuleInit();
+  google_protobuf_Struct_FieldsEntry_ModuleInit();
+  google_protobuf_Value_ModuleInit();
+  google_protobuf_ListValue_ModuleInit();
+  google_protobuf_NullValue_ModuleInit();
+  GPBMetadata_Google_Protobuf_Type_ModuleInit();
+  google_protobuf_Type_ModuleInit();
+  google_protobuf_Field_ModuleInit();
+  google_protobuf_Field_Kind_ModuleInit();
+  google_protobuf_Field_Cardinality_ModuleInit();
+  google_protobuf_Enum_ModuleInit();
+  google_protobuf_EnumValue_ModuleInit();
+  google_protobuf_Option_ModuleInit();
+  google_protobuf_Syntax_ModuleInit();
+  GPBMetadata_Google_Protobuf_Timestamp_ModuleInit();
+  google_protobuf_Timestamp_ModuleInit();
+  GPBMetadata_Google_Protobuf_Wrappers_ModuleInit();
+  google_protobuf_DoubleValue_ModuleInit();
+  google_protobuf_FloatValue_ModuleInit();
+  google_protobuf_Int64Value_ModuleInit();
+  google_protobuf_UInt64Value_ModuleInit();
+  google_protobuf_Int32Value_ModuleInit();
+  google_protobuf_UInt32Value_ModuleInit();
+  google_protobuf_BoolValue_ModuleInit();
+  google_protobuf_StringValue_ModuleInit();
+  google_protobuf_BytesValue_ModuleInit();
+}
diff --git a/php/generate_descriptor_protos.sh b/php/generate_descriptor_protos.sh
index f636cc0..9feaa96 100755
--- a/php/generate_descriptor_protos.sh
+++ b/php/generate_descriptor_protos.sh
@@ -3,6 +3,8 @@
 # Run this script to regenerate descriptor protos after the protocol compiler
 # changes.
 
+set -e
+
 if test ! -e src/google/protobuf/stubs/common.h; then
   cat >&2 << __EOF__
 Could not find source code.  Make sure you are running this script from the
@@ -13,4 +15,15 @@
 
 pushd src
 ./protoc --php_out=internal:../php/src google/protobuf/descriptor.proto
+./protoc --php_out=internal_generate_c_wkt:../php/src \
+  google/protobuf/any.proto \
+  google/protobuf/api.proto \
+  google/protobuf/duration.proto \
+  google/protobuf/empty.proto \
+  google/protobuf/field_mask.proto \
+  google/protobuf/source_context.proto \
+  google/protobuf/struct.proto \
+  google/protobuf/type.proto \
+  google/protobuf/timestamp.proto \
+  google/protobuf/wrappers.proto
 popd
diff --git a/php/generate_test_protos.sh b/php/generate_test_protos.sh
new file mode 100755
index 0000000..e86ca07
--- /dev/null
+++ b/php/generate_test_protos.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+set -e
+
+cd `dirname $0`
+
+./prepare_c_extension.sh
+
+if ../src/protoc --help > /dev/null; then
+  PROTOC=src/protoc
+else
+  (cd .. && bazel build -c opt :protoc)
+  PROTOC=bazel-bin/protoc
+fi
+
+
+if [[ -d tmp && -z $(find tests/proto ../$PROTOC -newer tmp) ]]; then
+  # Generated protos are already present and up to date, so we can skip protoc.
+  #
+  # Protoc is very fast, but sometimes it is not available (like if we haven't
+  # built it in Docker). Skipping it helps us proceed in this case.
+  echo "Test protos are up-to-date, skipping protoc."
+  exit 0
+fi
+
+rm -rf tmp
+mkdir -p tmp
+
+cd ..
+find php/tests/proto -type f -name "*.proto"| xargs $PROTOC --php_out=php/tmp -Isrc -Iphp/tests
+
+if [ "$1" = "--aggregate_metadata" ]; then
+  # Overwrite some of the files to use aggregation.
+  AGGREGATED_FILES="tests/proto/test.proto tests/proto/test_include.proto tests/proto/test_import_descriptor_proto.proto"
+  $PROTOC --php_out=aggregate_metadata=foo#bar:php/tmp -Isrc -Iphp/tests $AGGREGATED_FILES
+fi
+
+echo "Generated test protos from tests/proto -> tmp"
diff --git a/php/phpunit.xml b/php/phpunit.xml
deleted file mode 100644
index 769037c..0000000
--- a/php/phpunit.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<phpunit bootstrap="./tests/bootstrap_phpunit.php"
-         colors="true">
-  <testsuites>
-    <testsuite name="protobuf-tests">
-      <file>tests/php_implementation_test.php</file>
-      <file>tests/array_test.php</file>
-      <file>tests/encode_decode_test.php</file>
-      <file>tests/generated_class_test.php</file>
-      <file>tests/generated_phpdoc_test.php</file>
-      <file>tests/map_field_test.php</file>
-      <file>tests/well_known_test.php</file>
-      <file>tests/descriptors_test.php</file>
-      <file>tests/generated_service_test.php</file>
-      <file>tests/wrapper_type_setters_test.php</file>
-    </testsuite>
-  </testsuites>
-</phpunit>
diff --git a/php/prepare_c_extension.sh b/php/prepare_c_extension.sh
new file mode 100755
index 0000000..1b6b9f1
--- /dev/null
+++ b/php/prepare_c_extension.sh
@@ -0,0 +1,20 @@
+
+cd $(dirname $0)
+
+if [[ -f ext/google/protobuf/third_party/wyhash/wyhash.h && -z $(find ../third_party/wyhash -newer ext/google/protobuf/third_party) ]]; then
+  # Generated protos are already present and up to date, so we can skip protoc.
+  #
+  # Protoc is very fast, but sometimes it is not available (like if we haven't
+  # built it in Docker). Skipping it helps us proceed in this case.
+  echo "wyhash is up to date, skipping."
+  exit 0
+fi
+
+# wyhash has to live in the base third_party directory.
+# We copy it into the ext/google/protobuf directory for the build
+# (and for the release to PECL).
+rm -rf ext/google/protobuf/third_party
+mkdir -p ext/google/protobuf/third_party/wyhash
+cp ../third_party/wyhash/* ext/google/protobuf/third_party/wyhash
+
+echo "Copied wyhash from ../third_party -> ext/google/protobuf/third_party"
diff --git a/php/src/GPBMetadata/Google/Protobuf/Any.php b/php/src/GPBMetadata/Google/Protobuf/Any.php
index 22cc250..fbce4bf 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Any.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Any.php
@@ -14,15 +14,15 @@
         if (static::$is_initialized == true) {
           return;
         }
-        $pool->internalAddGeneratedFile(hex2bin(
-            "0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f" .
-            "120f676f6f676c652e70726f746f62756622260a03416e7912100a087479" .
-            "70655f75726c180120012809120d0a0576616c756518022001280c426f0a" .
-            "13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f" .
-            "50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566" .
-            "2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f" .
-            "746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"
-        ));
+        $pool->internalAddGeneratedFile(
+            '
+Ô
+google/protobuf/any.protogoogle.protobuf"&
+Any
+type_url (	

+value (Bv
+com.google.protobufBAnyProtoPZ,google.golang.org/protobuf/types/known/anypb¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
+        , true);
 
         static::$is_initialized = true;
     }
diff --git a/php/src/GPBMetadata/Google/Protobuf/Api.php b/php/src/GPBMetadata/Google/Protobuf/Api.php
index b18e0d3..75e0ec6 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Api.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Api.php
@@ -16,32 +16,31 @@
         }
         \GPBMetadata\Google\Protobuf\SourceContext::initOnce();
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        $pool->internalAddGeneratedFile(hex2bin(
-            "0ac8050a19676f6f676c652f70726f746f6275662f6170692e70726f746f" .
-            "120f676f6f676c652e70726f746f6275661a1a676f6f676c652f70726f74" .
-            "6f6275662f747970652e70726f746f2281020a03417069120c0a046e616d" .
-            "6518012001280912280a076d6574686f647318022003280b32172e676f6f" .
-            "676c652e70726f746f6275662e4d6574686f6412280a076f7074696f6e73" .
-            "18032003280b32172e676f6f676c652e70726f746f6275662e4f7074696f" .
-            "6e120f0a0776657273696f6e18042001280912360a0e736f757263655f63" .
-            "6f6e7465787418052001280b321e2e676f6f676c652e70726f746f627566" .
-            "2e536f75726365436f6e7465787412260a066d6978696e7318062003280b" .
-            "32162e676f6f676c652e70726f746f6275662e4d6978696e12270a067379" .
-            "6e74617818072001280e32172e676f6f676c652e70726f746f6275662e53" .
-            "796e74617822d5010a064d6574686f64120c0a046e616d65180120012809" .
-            "12180a10726571756573745f747970655f75726c18022001280912190a11" .
-            "726571756573745f73747265616d696e6718032001280812190a11726573" .
-            "706f6e73655f747970655f75726c180420012809121a0a12726573706f6e" .
-            "73655f73747265616d696e6718052001280812280a076f7074696f6e7318" .
-            "062003280b32172e676f6f676c652e70726f746f6275662e4f7074696f6e" .
-            "12270a0673796e74617818072001280e32172e676f6f676c652e70726f74" .
-            "6f6275662e53796e74617822230a054d6978696e120c0a046e616d651801" .
-            "20012809120c0a04726f6f7418022001280942750a13636f6d2e676f6f67" .
-            "6c652e70726f746f627566420841706950726f746f50015a2b676f6f676c" .
-            "652e676f6c616e672e6f72672f67656e70726f746f2f70726f746f627566" .
-            "2f6170693b617069a20203475042aa021e476f6f676c652e50726f746f62" .
-            "75662e57656c6c4b6e6f776e5479706573620670726f746f33"
-        ));
+        $pool->internalAddGeneratedFile(
+            '
+É
+google/protobuf/api.protogoogle.protobufgoogle/protobuf/type.proto"
+Api
+name (	(
+methods (2.google.protobuf.Method(
+options (2.google.protobuf.Option
+version (	6
+source_context (2.google.protobuf.SourceContext&
+mixins (2.google.protobuf.Mixin\'
+syntax (2.google.protobuf.Syntax"Õ
+Method
+name (	
+request_type_url (	
+request_streaming (
+response_type_url (	
+response_streaming ((
+options (2.google.protobuf.Option\'
+syntax (2.google.protobuf.Syntax"#
+Mixin
+name (	
+root (	Bv
+com.google.protobufBApiProtoPZ,google.golang.org/protobuf/types/known/apipb¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
+        , true);
 
         static::$is_initialized = true;
     }
diff --git a/php/src/GPBMetadata/Google/Protobuf/Duration.php b/php/src/GPBMetadata/Google/Protobuf/Duration.php
index b1c85ad..5d8023e 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Duration.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Duration.php
Binary files differ
diff --git a/php/src/GPBMetadata/Google/Protobuf/FieldMask.php b/php/src/GPBMetadata/Google/Protobuf/FieldMask.php
index 5812be1..f31bcc0 100644
--- a/php/src/GPBMetadata/Google/Protobuf/FieldMask.php
+++ b/php/src/GPBMetadata/Google/Protobuf/FieldMask.php
@@ -14,16 +14,14 @@
         if (static::$is_initialized == true) {
           return;
         }
-        $pool->internalAddGeneratedFile(hex2bin(
-            "0ae3010a20676f6f676c652f70726f746f6275662f6669656c645f6d6173" .
-            "6b2e70726f746f120f676f6f676c652e70726f746f627566221a0a094669" .
-            "656c644d61736b120d0a0570617468731801200328094289010a13636f6d" .
-            "2e676f6f676c652e70726f746f627566420e4669656c644d61736b50726f" .
-            "746f50015a39676f6f676c652e676f6c616e672e6f72672f67656e70726f" .
-            "746f2f70726f746f6275662f6669656c645f6d61736b3b6669656c645f6d" .
-            "61736ba20203475042aa021e476f6f676c652e50726f746f6275662e5765" .
-            "6c6c4b6e6f776e5479706573620670726f746f33"
-        ));
+        $pool->internalAddGeneratedFile(
+            '
+ß
+ google/protobuf/field_mask.protogoogle.protobuf"
+	FieldMask

+paths (	B…
+com.google.protobufBFieldMaskProtoPZ2google.golang.org/protobuf/types/known/fieldmaskpbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
+        , true);
 
         static::$is_initialized = true;
     }
diff --git a/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php b/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php
index 88f42a1..5e42536 100644
--- a/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php
+++ b/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php
@@ -14,15 +14,14 @@
         if (static::$is_initialized == true) {
           return;
         }
-        $pool->internalAddGeneratedFile(hex2bin(
-            "0ab7010a1b676f6f676c652f70726f746f6275662f656d7074792e70726f" .
-            "746f120f676f6f676c652e70726f746f62756622070a05456d7074794276" .
-            "0a13636f6d2e676f6f676c652e70726f746f627566420a456d7074795072" .
-            "6f746f50015a276769746875622e636f6d2f676f6c616e672f70726f746f" .
-            "6275662f7074797065732f656d707479f80101a20203475042aa021e476f" .
-            "6f676c652e50726f746f6275662e57656c6c4b6e6f776e54797065736206" .
-            "70726f746f33"
-        ));
+        $pool->internalAddGeneratedFile(
+            '
+¾
+google/protobuf/empty.protogoogle.protobuf"
+EmptyB}
+com.google.protobufB
+EmptyProtoPZ.google.golang.org/protobuf/types/known/emptypbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
+        , true);
 
         static::$is_initialized = true;
     }
diff --git a/php/src/GPBMetadata/Google/Protobuf/SourceContext.php b/php/src/GPBMetadata/Google/Protobuf/SourceContext.php
index 495c6de..797732d 100644
--- a/php/src/GPBMetadata/Google/Protobuf/SourceContext.php
+++ b/php/src/GPBMetadata/Google/Protobuf/SourceContext.php
Binary files differ
diff --git a/php/src/GPBMetadata/Google/Protobuf/Struct.php b/php/src/GPBMetadata/Google/Protobuf/Struct.php
index 96b42af..888a81a 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Struct.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Struct.php
Binary files differ
diff --git a/php/src/GPBMetadata/Google/Protobuf/Timestamp.php b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php
index 373665c..0943727 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Timestamp.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php
@@ -14,16 +14,15 @@
         if (static::$is_initialized == true) {
           return;
         }
-        $pool->internalAddGeneratedFile(hex2bin(
-            "0ae7010a1f676f6f676c652f70726f746f6275662f74696d657374616d70" .
-            "2e70726f746f120f676f6f676c652e70726f746f627566222b0a0954696d" .
-            "657374616d70120f0a077365636f6e6473180120012803120d0a056e616e" .
-            "6f73180220012805427e0a13636f6d2e676f6f676c652e70726f746f6275" .
-            "66420e54696d657374616d7050726f746f50015a2b6769746875622e636f" .
-            "6d2f676f6c616e672f70726f746f6275662f7074797065732f74696d6573" .
-            "74616d70f80101a20203475042aa021e476f6f676c652e50726f746f6275" .
-            "662e57656c6c4b6e6f776e5479706573620670726f746f33"
-        ));
+        $pool->internalAddGeneratedFile(
+            '
+ï
+google/protobuf/timestamp.protogoogle.protobuf"+
+	Timestamp
+seconds (

+nanos (B…
+com.google.protobufBTimestampProtoPZ2google.golang.org/protobuf/types/known/timestamppbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
+        , true);
 
         static::$is_initialized = true;
     }
diff --git a/php/src/GPBMetadata/Google/Protobuf/Type.php b/php/src/GPBMetadata/Google/Protobuf/Type.php
index 8fbe8cb..7d0bfbb 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Type.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Type.php
Binary files differ
diff --git a/php/src/GPBMetadata/Google/Protobuf/Wrappers.php b/php/src/GPBMetadata/Google/Protobuf/Wrappers.php
index dd72ff4..e7ea1a3 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Wrappers.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Wrappers.php
Binary files differ
diff --git a/php/src/Google/Protobuf/Any.php b/php/src/Google/Protobuf/Any.php
index 166c66a..8fdc3c4 100644
--- a/php/src/Google/Protobuf/Any.php
+++ b/php/src/Google/Protobuf/Any.php
@@ -5,7 +5,6 @@
 namespace Google\Protobuf;
 
 use Google\Protobuf\Internal\GPBType;
-use Google\Protobuf\Internal\Message;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBUtil;
 
@@ -39,10 +38,13 @@
  *       ...
  *  Example 4: Pack and unpack a message in Go
  *      foo := &pb.Foo{...}
- *      any, err := ptypes.MarshalAny(foo)
+ *      any, err := anypb.New(foo)
+ *      if err != nil {
+ *        ...
+ *      }
  *      ...
  *      foo := &pb.Foo{}
- *      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+ *      if err := any.UnmarshalTo(foo); err != nil {
  *        ...
  *      }
  * The pack methods provided by protobuf library will by default use
@@ -76,11 +78,12 @@
  *
  * Generated from protobuf message <code>google.protobuf.Any</code>
  */
-class Any extends \Google\Protobuf\Internal\Message
+class Any extends \Google\Protobuf\Internal\AnyBase
 {
     /**
      * A URL/resource name that uniquely identifies the type of the serialized
-     * protocol buffer message. The last segment of the URL's path must represent
+     * protocol buffer message. This string must contain at least
+     * one "/" character. The last segment of the URL's path must represent
      * the fully qualified name of the type (as in
      * `path/google.protobuf.Duration`). The name should be in a canonical form
      * (e.g., leading "." is not accepted).
@@ -104,15 +107,13 @@
      *
      * Generated from protobuf field <code>string type_url = 1;</code>
      */
-    private $type_url = '';
+    protected $type_url = '';
     /**
      * Must be a valid serialized protocol buffer of the above specified type.
      *
      * Generated from protobuf field <code>bytes value = 2;</code>
      */
-    private $value = '';
-
-    const TYPE_URL_PREFIX = 'type.googleapis.com/';
+    protected $value = '';
 
     /**
      * Constructor.
@@ -122,7 +123,8 @@
      *
      *     @type string $type_url
      *           A URL/resource name that uniquely identifies the type of the serialized
-     *           protocol buffer message. The last segment of the URL's path must represent
+     *           protocol buffer message. This string must contain at least
+     *           one "/" character. The last segment of the URL's path must represent
      *           the fully qualified name of the type (as in
      *           `path/google.protobuf.Duration`). The name should be in a canonical form
      *           (e.g., leading "." is not accepted).
@@ -154,7 +156,8 @@
 
     /**
      * A URL/resource name that uniquely identifies the type of the serialized
-     * protocol buffer message. The last segment of the URL's path must represent
+     * protocol buffer message. This string must contain at least
+     * one "/" character. The last segment of the URL's path must represent
      * the fully qualified name of the type (as in
      * `path/google.protobuf.Duration`). The name should be in a canonical form
      * (e.g., leading "." is not accepted).
@@ -186,7 +189,8 @@
 
     /**
      * A URL/resource name that uniquely identifies the type of the serialized
-     * protocol buffer message. The last segment of the URL's path must represent
+     * protocol buffer message. This string must contain at least
+     * one "/" character. The last segment of the URL's path must represent
      * the fully qualified name of the type (as in
      * `path/google.protobuf.Duration`). The name should be in a canonical form
      * (e.g., leading "." is not accepted).
@@ -246,80 +250,5 @@
         return $this;
     }
 
-    /**
-     * This method will try to resolve the type_url in Any message to get the
-     * targeted message type. If failed, an error will be thrown. Otherwise,
-     * the method will create a message of the targeted type and fill it with
-     * the decoded value in Any.
-     * @return Message unpacked message
-     * @throws \Exception Type url needs to be type.googleapis.com/fully-qualified.
-     * @throws \Exception Class hasn't been added to descriptor pool.
-     * @throws \Exception cannot decode data in value field.
-     */
-    public function unpack()
-    {
-        // Get fully qualified name from type url.
-        $url_prifix_len = strlen(GPBUtil::TYPE_URL_PREFIX);
-        if (substr($this->type_url, 0, $url_prifix_len) !=
-                GPBUtil::TYPE_URL_PREFIX) {
-            throw new \Exception(
-                "Type url needs to be type.googleapis.com/fully-qulified");
-        }
-        $fully_qualifed_name =
-            substr($this->type_url, $url_prifix_len);
-
-        // Create message according to fully qualified name.
-        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
-        $desc = $pool->getDescriptorByProtoName( ".".$fully_qualifed_name);
-        if (is_null($desc)) {
-            throw new \Exception("Class ".$fully_qualifed_name
-                                     ." hasn't been added to descriptor pool");
-        }
-        $klass = $desc->getClass();
-        $msg = new $klass();
-
-        // Merge data into message.
-        $msg->mergeFromString($this->value);
-        return $msg;
-    }
-
-    /**
-     * The type_url will be created according to the given message’s type and
-     * the value is encoded data from the given message..
-     * @param message: A proto message.
-     */
-    public function pack($msg)
-    {
-        if (!$msg instanceof Message) {
-            trigger_error("Given parameter is not a message instance.",
-                          E_USER_ERROR);
-            return;
-        }
-
-        // Set value using serialized message.
-        $this->value = $msg->serializeToString();
-
-        // Set type url.
-        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
-        $desc = $pool->getDescriptorByClassName(get_class($msg));
-        $fully_qualifed_name = $desc->getFullName();
-        $this->type_url = GPBUtil::TYPE_URL_PREFIX.substr(
-            $fully_qualifed_name, 1, strlen($fully_qualifed_name));
-    }
-
-    /**
-     * This method returns whether the type_url in any_message is corresponded
-     * to the given class.
-     * @param klass: The fully qualified PHP class name of a proto message type.
-     */
-    public function is($klass)
-    {
-        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
-        $desc = $pool->getDescriptorByClassName($klass);
-        $fully_qualifed_name = $desc->getFullName();
-        $type_url = GPBUtil::TYPE_URL_PREFIX.substr(
-            $fully_qualifed_name, 1, strlen($fully_qualifed_name));
-        return $this->type_url === $type_url;
-    }
 }
 
diff --git a/php/src/Google/Protobuf/Api.php b/php/src/Google/Protobuf/Api.php
index db37ffb..e7d76c0 100644
--- a/php/src/Google/Protobuf/Api.php
+++ b/php/src/Google/Protobuf/Api.php
@@ -28,7 +28,7 @@
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * The methods of this interface, in unspecified order.
      *
@@ -62,14 +62,14 @@
      *
      * Generated from protobuf field <code>string version = 4;</code>
      */
-    private $version = '';
+    protected $version = '';
     /**
      * Source context for the protocol buffer service represented by this
      * message.
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
      */
-    private $source_context = null;
+    protected $source_context = null;
     /**
      * Included interfaces. See [Mixin][].
      *
@@ -81,7 +81,7 @@
      *
      * Generated from protobuf field <code>.google.protobuf.Syntax syntax = 7;</code>
      */
-    private $syntax = 0;
+    protected $syntax = 0;
 
     /**
      * Constructor.
@@ -271,13 +271,23 @@
      * message.
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
-     * @return \Google\Protobuf\SourceContext
+     * @return \Google\Protobuf\SourceContext|null
      */
     public function getSourceContext()
     {
         return $this->source_context;
     }
 
+    public function hasSourceContext()
+    {
+        return isset($this->source_context);
+    }
+
+    public function clearSourceContext()
+    {
+        unset($this->source_context);
+    }
+
     /**
      * Source context for the protocol buffer service represented by this
      * message.
diff --git a/php/src/Google/Protobuf/BoolValue.php b/php/src/Google/Protobuf/BoolValue.php
index 13872eb..ecdbf4d 100644
--- a/php/src/Google/Protobuf/BoolValue.php
+++ b/php/src/Google/Protobuf/BoolValue.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>bool value = 1;</code>
      */
-    private $value = false;
+    protected $value = false;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/BytesValue.php b/php/src/Google/Protobuf/BytesValue.php
index f1b3817..1582e14 100644
--- a/php/src/Google/Protobuf/BytesValue.php
+++ b/php/src/Google/Protobuf/BytesValue.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>bytes value = 1;</code>
      */
-    private $value = '';
+    protected $value = '';
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Descriptor.php b/php/src/Google/Protobuf/Descriptor.php
index 986b81e..36436e2 100644
--- a/php/src/Google/Protobuf/Descriptor.php
+++ b/php/src/Google/Protobuf/Descriptor.php
@@ -97,4 +97,12 @@
     {
         return count($this->internal_desc->getOneofDecl());
     }
+
+    /**
+     * @return int Number of real oneofs in message
+     */
+    public function getRealOneofDeclCount()
+    {
+        return $this->internal_desc->getRealOneofDeclCount();
+    }
 }
diff --git a/php/src/Google/Protobuf/DoubleValue.php b/php/src/Google/Protobuf/DoubleValue.php
index 236d918..b72399f 100644
--- a/php/src/Google/Protobuf/DoubleValue.php
+++ b/php/src/Google/Protobuf/DoubleValue.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>double value = 1;</code>
      */
-    private $value = 0.0;
+    protected $value = 0.0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Duration.php b/php/src/Google/Protobuf/Duration.php
index 414a186..531cd50 100644
--- a/php/src/Google/Protobuf/Duration.php
+++ b/php/src/Google/Protobuf/Duration.php
@@ -25,7 +25,7 @@
  *     if (duration.seconds < 0 && duration.nanos > 0) {
  *       duration.seconds += 1;
  *       duration.nanos -= 1000000000;
- *     } else if (durations.seconds > 0 && duration.nanos < 0) {
+ *     } else if (duration.seconds > 0 && duration.nanos < 0) {
  *       duration.seconds -= 1;
  *       duration.nanos += 1000000000;
  *     }
@@ -66,7 +66,7 @@
      *
      * Generated from protobuf field <code>int64 seconds = 1;</code>
      */
-    private $seconds = 0;
+    protected $seconds = 0;
     /**
      * Signed fractions of a second at nanosecond resolution of the span
      * of time. Durations less than one second are represented with a 0
@@ -77,7 +77,7 @@
      *
      * Generated from protobuf field <code>int32 nanos = 2;</code>
      */
-    private $nanos = 0;
+    protected $nanos = 0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Enum.php b/php/src/Google/Protobuf/Enum.php
index 243c40d..e803e93 100644
--- a/php/src/Google/Protobuf/Enum.php
+++ b/php/src/Google/Protobuf/Enum.php
@@ -20,7 +20,7 @@
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * Enum value definitions.
      *
@@ -38,13 +38,13 @@
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 4;</code>
      */
-    private $source_context = null;
+    protected $source_context = null;
     /**
      * The source syntax.
      *
      * Generated from protobuf field <code>.google.protobuf.Syntax syntax = 5;</code>
      */
-    private $syntax = 0;
+    protected $syntax = 0;
 
     /**
      * Constructor.
@@ -151,13 +151,23 @@
      * The source context.
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 4;</code>
-     * @return \Google\Protobuf\SourceContext
+     * @return \Google\Protobuf\SourceContext|null
      */
     public function getSourceContext()
     {
         return $this->source_context;
     }
 
+    public function hasSourceContext()
+    {
+        return isset($this->source_context);
+    }
+
+    public function clearSourceContext()
+    {
+        unset($this->source_context);
+    }
+
     /**
      * The source context.
      *
diff --git a/php/src/Google/Protobuf/EnumValue.php b/php/src/Google/Protobuf/EnumValue.php
index 1dc3c7a..905f4ad 100644
--- a/php/src/Google/Protobuf/EnumValue.php
+++ b/php/src/Google/Protobuf/EnumValue.php
@@ -20,13 +20,13 @@
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * Enum value number.
      *
      * Generated from protobuf field <code>int32 number = 2;</code>
      */
-    private $number = 0;
+    protected $number = 0;
     /**
      * Protocol buffer options.
      *
diff --git a/php/src/Google/Protobuf/Field.php b/php/src/Google/Protobuf/Field.php
index 8da43e3..76a505e 100644
--- a/php/src/Google/Protobuf/Field.php
+++ b/php/src/Google/Protobuf/Field.php
@@ -20,45 +20,45 @@
      *
      * Generated from protobuf field <code>.google.protobuf.Field.Kind kind = 1;</code>
      */
-    private $kind = 0;
+    protected $kind = 0;
     /**
      * The field cardinality.
      *
      * Generated from protobuf field <code>.google.protobuf.Field.Cardinality cardinality = 2;</code>
      */
-    private $cardinality = 0;
+    protected $cardinality = 0;
     /**
      * The field number.
      *
      * Generated from protobuf field <code>int32 number = 3;</code>
      */
-    private $number = 0;
+    protected $number = 0;
     /**
      * The field name.
      *
      * Generated from protobuf field <code>string name = 4;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * The field type URL, without the scheme, for message or enumeration
      * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
      *
      * Generated from protobuf field <code>string type_url = 6;</code>
      */
-    private $type_url = '';
+    protected $type_url = '';
     /**
      * The index of the field type in `Type.oneofs`, for message or enumeration
      * types. The first type has index 1; zero means the type is not in the list.
      *
      * Generated from protobuf field <code>int32 oneof_index = 7;</code>
      */
-    private $oneof_index = 0;
+    protected $oneof_index = 0;
     /**
      * Whether to use alternative packed wire representation.
      *
      * Generated from protobuf field <code>bool packed = 8;</code>
      */
-    private $packed = false;
+    protected $packed = false;
     /**
      * The protocol buffer options.
      *
@@ -70,13 +70,13 @@
      *
      * Generated from protobuf field <code>string json_name = 10;</code>
      */
-    private $json_name = '';
+    protected $json_name = '';
     /**
      * The string value of the default value of this field. Proto2 syntax only.
      *
      * Generated from protobuf field <code>string default_value = 11;</code>
      */
-    private $default_value = '';
+    protected $default_value = '';
 
     /**
      * Constructor.
@@ -133,7 +133,7 @@
      */
     public function setKind($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Field_Kind::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Field\Kind::class);
         $this->kind = $var;
 
         return $this;
@@ -159,7 +159,7 @@
      */
     public function setCardinality($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Field_Cardinality::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Field\Cardinality::class);
         $this->cardinality = $var;
 
         return $this;
diff --git a/php/src/Google/Protobuf/Field/Cardinality.php b/php/src/Google/Protobuf/Field/Cardinality.php
index 479dc0b..a422199 100644
--- a/php/src/Google/Protobuf/Field/Cardinality.php
+++ b/php/src/Google/Protobuf/Field/Cardinality.php
@@ -54,6 +54,7 @@
         return self::$valueToName[$value];
     }
 
+
     public static function value($name)
     {
         $const = __CLASS__ . '::' . strtoupper($name);
diff --git a/php/src/Google/Protobuf/Field/Kind.php b/php/src/Google/Protobuf/Field/Kind.php
index f30bd2f..2d8dd77 100644
--- a/php/src/Google/Protobuf/Field/Kind.php
+++ b/php/src/Google/Protobuf/Field/Kind.php
@@ -159,6 +159,7 @@
         return self::$valueToName[$value];
     }
 
+
     public static function value($name)
     {
         $const = __CLASS__ . '::' . strtoupper($name);
diff --git a/php/src/Google/Protobuf/FieldDescriptor.php b/php/src/Google/Protobuf/FieldDescriptor.php
index ac9271f..6d08cea 100644
--- a/php/src/Google/Protobuf/FieldDescriptor.php
+++ b/php/src/Google/Protobuf/FieldDescriptor.php
@@ -114,4 +114,12 @@
     {
         return $this->internal_desc->isMap();
     }
+
+    /**
+     * @return boolean
+     */
+    public function hasOptionalKeyword()
+    {
+        return $this->internal_desc->hasOptionalKeyword();
+    }
 }
diff --git a/php/src/Google/Protobuf/FieldMask.php b/php/src/Google/Protobuf/FieldMask.php
index 8fb38cb..0b9659d 100644
--- a/php/src/Google/Protobuf/FieldMask.php
+++ b/php/src/Google/Protobuf/FieldMask.php
@@ -62,45 +62,39 @@
  * and leave the others untouched. If a resource is passed in to
  * describe the updated values, the API ignores the values of all
  * fields not covered by the mask.
- * If a repeated field is specified for an update operation, the existing
- * repeated values in the target resource will be overwritten by the new values.
- * Note that a repeated field is only allowed in the last position of a `paths`
- * string.
+ * If a repeated field is specified for an update operation, new values will
+ * be appended to the existing repeated field in the target resource. Note that
+ * a repeated field is only allowed in the last position of a `paths` string.
  * If a sub-message is specified in the last position of the field mask for an
- * update operation, then the existing sub-message in the target resource is
- * overwritten. Given the target message:
+ * update operation, then new value will be merged into the existing sub-message
+ * in the target resource.
+ * For example, given the target message:
  *     f {
  *       b {
- *         d : 1
- *         x : 2
+ *         d: 1
+ *         x: 2
  *       }
- *       c : 1
+ *       c: [1]
  *     }
  * And an update message:
  *     f {
  *       b {
- *         d : 10
+ *         d: 10
  *       }
+ *       c: [2]
  *     }
  * then if the field mask is:
- *  paths: "f.b"
+ *  paths: ["f.b", "f.c"]
  * then the result will be:
  *     f {
  *       b {
- *         d : 10
+ *         d: 10
+ *         x: 2
  *       }
- *       c : 1
+ *       c: [1, 2]
  *     }
- * However, if the update mask was:
- *  paths: "f.b.d"
- * then the result would be:
- *     f {
- *       b {
- *         d : 10
- *         x : 2
- *       }
- *       c : 1
- *     }
+ * An implementation may provide options to override this default behavior for
+ * repeated and message fields.
  * In order to reset a field's value to the default, the field must
  * be in the mask and set to the default value in the provided resource.
  * Hence, in order to reset all fields of a resource, provide a default
@@ -165,7 +159,7 @@
  * ## Field Mask Verification
  * The implementation of any API method which has a FieldMask type field in the
  * request should verify the included field paths, and return an
- * `INVALID_ARGUMENT` error if any path is duplicated or unmappable.
+ * `INVALID_ARGUMENT` error if any path is unmappable.
  *
  * Generated from protobuf message <code>google.protobuf.FieldMask</code>
  */
diff --git a/php/src/Google/Protobuf/FloatValue.php b/php/src/Google/Protobuf/FloatValue.php
index 47ba52e..4285358 100644
--- a/php/src/Google/Protobuf/FloatValue.php
+++ b/php/src/Google/Protobuf/FloatValue.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>float value = 1;</code>
      */
-    private $value = 0.0;
+    protected $value = 0.0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Int32Value.php b/php/src/Google/Protobuf/Int32Value.php
index d7fd528..cfd73cd 100644
--- a/php/src/Google/Protobuf/Int32Value.php
+++ b/php/src/Google/Protobuf/Int32Value.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>int32 value = 1;</code>
      */
-    private $value = 0;
+    protected $value = 0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Int64Value.php b/php/src/Google/Protobuf/Int64Value.php
index ca66305..143474f 100644
--- a/php/src/Google/Protobuf/Int64Value.php
+++ b/php/src/Google/Protobuf/Int64Value.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>int64 value = 1;</code>
      */
-    private $value = 0;
+    protected $value = 0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Internal/AnyBase.php b/php/src/Google/Protobuf/Internal/AnyBase.php
new file mode 100644
index 0000000..cba922d
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/AnyBase.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace Google\Protobuf\Internal;
+
+/**
+ * Base class for Google\Protobuf\Any, this contains hand-written convenience
+ * methods like pack() and unpack().
+ */
+class AnyBase extends \Google\Protobuf\Internal\Message
+{
+    const TYPE_URL_PREFIX = 'type.googleapis.com/';
+
+    /**
+     * This method will try to resolve the type_url in Any message to get the
+     * targeted message type. If failed, an error will be thrown. Otherwise,
+     * the method will create a message of the targeted type and fill it with
+     * the decoded value in Any.
+     * @return Message unpacked message
+     * @throws \Exception Type url needs to be type.googleapis.com/fully-qualified.
+     * @throws \Exception Class hasn't been added to descriptor pool.
+     * @throws \Exception cannot decode data in value field.
+     */
+    public function unpack()
+    {
+        // Get fully qualified name from type url.
+        $url_prifix_len = strlen(GPBUtil::TYPE_URL_PREFIX);
+        if (substr($this->type_url, 0, $url_prifix_len) !=
+                GPBUtil::TYPE_URL_PREFIX) {
+            throw new \Exception(
+                "Type url needs to be type.googleapis.com/fully-qulified");
+        }
+        $fully_qualifed_name =
+            substr($this->type_url, $url_prifix_len);
+
+        // Create message according to fully qualified name.
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByProtoName($fully_qualifed_name);
+        if (is_null($desc)) {
+            throw new \Exception("Class ".$fully_qualifed_name
+                                     ." hasn't been added to descriptor pool");
+        }
+        $klass = $desc->getClass();
+        $msg = new $klass();
+
+        // Merge data into message.
+        $msg->mergeFromString($this->value);
+        return $msg;
+    }
+
+    /**
+     * The type_url will be created according to the given message’s type and
+     * the value is encoded data from the given message..
+     * @param message: A proto message.
+     */
+    public function pack($msg)
+    {
+        if (!$msg instanceof Message) {
+            trigger_error("Given parameter is not a message instance.",
+                          E_USER_ERROR);
+            return;
+        }
+
+        // Set value using serialized message.
+        $this->value = $msg->serializeToString();
+
+        // Set type url.
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName(get_class($msg));
+        $fully_qualifed_name = $desc->getFullName();
+        $this->type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name;
+    }
+
+    /**
+     * This method returns whether the type_url in any_message is corresponded
+     * to the given class.
+     * @param klass: The fully qualified PHP class name of a proto message type.
+     */
+    public function is($klass)
+    {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName($klass);
+        $fully_qualifed_name = $desc->getFullName();
+        $type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name;
+        return $this->type_url === $type_url;
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/Descriptor.php b/php/src/Google/Protobuf/Internal/Descriptor.php
index 21ac5de..a7f80d5 100644
--- a/php/src/Google/Protobuf/Internal/Descriptor.php
+++ b/php/src/Google/Protobuf/Internal/Descriptor.php
@@ -185,8 +185,8 @@
             $containing,
             $file_proto,
             $message_name_without_package,
-            $legacy_classname,
             $classname,
+            $legacy_classname,
             $fullname);
         $desc->setFullName($fullname);
         $desc->setClass($classname);
diff --git a/php/src/Google/Protobuf/Internal/DescriptorPool.php b/php/src/Google/Protobuf/Internal/DescriptorPool.php
index f96b0fb..2880cee 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorPool.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorPool.php
@@ -152,6 +152,9 @@
             switch ($field->getType()) {
                 case GPBType::MESSAGE:
                     $proto = $field->getMessageType();
+                    if ($proto[0] == '.') {
+                      $proto = substr($proto, 1);
+                    }
                     $subdesc = $this->getDescriptorByProtoName($proto);
                     if (is_null($subdesc)) {
                         trigger_error(
@@ -162,6 +165,9 @@
                     break;
                 case GPBType::ENUM:
                     $proto = $field->getEnumType();
+                    if ($proto[0] == '.') {
+                      $proto = substr($proto, 1);
+                    }
                     $field->setEnumType(
                         $this->getEnumDescriptorByProtoName($proto));
                     break;
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php
index 7cc689d..c58c573 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php
@@ -20,48 +20,39 @@
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
      */
     private $field;
-    private $has_field = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
      */
     private $extension;
-    private $has_extension = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
      */
     private $nested_type;
-    private $has_nested_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
      */
     private $enum_type;
-    private $has_enum_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
      */
     private $extension_range;
-    private $has_extension_range = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
      */
     private $oneof_decl;
-    private $has_oneof_decl = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
      */
     private $reserved_range;
-    private $has_reserved_range = false;
     /**
      * Reserved field names, which may not be used by fields in the same message.
      * A given name may only be reserved once.
@@ -69,7 +60,6 @@
      * Generated from protobuf field <code>repeated string reserved_name = 10;</code>
      */
     private $reserved_name;
-    private $has_reserved_name = false;
 
     /**
      * Constructor.
@@ -102,7 +92,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -114,16 +114,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -142,16 +136,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->field = $arr;
-        $this->has_field = true;
 
         return $this;
     }
 
-    public function hasField()
-    {
-        return $this->has_field;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -170,16 +158,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->extension = $arr;
-        $this->has_extension = true;
 
         return $this;
     }
 
-    public function hasExtension()
-    {
-        return $this->has_extension;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -198,16 +180,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
         $this->nested_type = $arr;
-        $this->has_nested_type = true;
 
         return $this;
     }
 
-    public function hasNestedType()
-    {
-        return $this->has_nested_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -226,16 +202,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
         $this->enum_type = $arr;
-        $this->has_enum_type = true;
 
         return $this;
     }
 
-    public function hasEnumType()
-    {
-        return $this->has_enum_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -254,16 +224,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class);
         $this->extension_range = $arr;
-        $this->has_extension_range = true;
 
         return $this;
     }
 
-    public function hasExtensionRange()
-    {
-        return $this->has_extension_range;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -282,25 +246,29 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\OneofDescriptorProto::class);
         $this->oneof_decl = $arr;
-        $this->has_oneof_decl = true;
 
         return $this;
     }
 
-    public function hasOneofDecl()
-    {
-        return $this->has_oneof_decl;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
-     * @return \Google\Protobuf\Internal\MessageOptions
+     * @return \Google\Protobuf\Internal\MessageOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
      * @param \Google\Protobuf\Internal\MessageOptions $var
@@ -310,16 +278,10 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MessageOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -338,16 +300,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class);
         $this->reserved_range = $arr;
-        $this->has_reserved_range = true;
 
         return $this;
     }
 
-    public function hasReservedRange()
-    {
-        return $this->has_reserved_range;
-    }
-
     /**
      * Reserved field names, which may not be used by fields in the same message.
      * A given name may only be reserved once.
@@ -372,15 +328,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->reserved_name = $arr;
-        $this->has_reserved_name = true;
 
         return $this;
     }
 
-    public function hasReservedName()
-    {
-        return $this->has_reserved_name;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
index 82b5695..43c33c4 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
@@ -20,20 +20,17 @@
      *
      * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
-    protected $start = 0;
-    private $has_start = false;
+    protected $start = null;
     /**
      * Exclusive.
      *
      * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -61,7 +58,17 @@
      */
     public function getStart()
     {
-        return $this->start;
+        return isset($this->start) ? $this->start : 0;
+    }
+
+    public function hasStart()
+    {
+        return isset($this->start);
+    }
+
+    public function clearStart()
+    {
+        unset($this->start);
     }
 
     /**
@@ -75,16 +82,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
-        $this->has_start = true;
 
         return $this;
     }
 
-    public function hasStart()
-    {
-        return $this->has_start;
-    }
-
     /**
      * Exclusive.
      *
@@ -93,7 +94,17 @@
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -107,25 +118,29 @@
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\ExtensionRangeOptions
+     * @return \Google\Protobuf\Internal\ExtensionRangeOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
      * @param \Google\Protobuf\Internal\ExtensionRangeOptions $var
@@ -135,16 +150,10 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ExtensionRangeOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
index 8022151..f099cc3 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
@@ -24,15 +24,13 @@
      *
      * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
-    protected $start = 0;
-    private $has_start = false;
+    protected $start = null;
     /**
      * Exclusive.
      *
      * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
 
     /**
      * Constructor.
@@ -59,7 +57,17 @@
      */
     public function getStart()
     {
-        return $this->start;
+        return isset($this->start) ? $this->start : 0;
+    }
+
+    public function hasStart()
+    {
+        return isset($this->start);
+    }
+
+    public function clearStart()
+    {
+        unset($this->start);
     }
 
     /**
@@ -73,16 +81,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
-        $this->has_start = true;
 
         return $this;
     }
 
-    public function hasStart()
-    {
-        return $this->has_start;
-    }
-
     /**
      * Exclusive.
      *
@@ -91,7 +93,17 @@
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -105,16 +117,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
index f5c7fe1..bd50834 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
@@ -20,18 +20,15 @@
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
      */
     private $value;
-    private $has_value = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * Range of reserved numeric values. Reserved numeric values may not be used
      * by enum values in the same enum declaration. Reserved ranges may not
@@ -40,7 +37,6 @@
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4;</code>
      */
     private $reserved_range;
-    private $has_reserved_range = false;
     /**
      * Reserved enum value names, which may not be reused. A given name may only
      * be reserved once.
@@ -48,7 +44,6 @@
      * Generated from protobuf field <code>repeated string reserved_name = 5;</code>
      */
     private $reserved_name;
-    private $has_reserved_name = false;
 
     /**
      * Constructor.
@@ -79,7 +74,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -91,16 +96,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -119,25 +118,29 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumValueDescriptorProto::class);
         $this->value = $arr;
-        $this->has_value = true;
 
         return $this;
     }
 
-    public function hasValue()
-    {
-        return $this->has_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\EnumOptions
+     * @return \Google\Protobuf\Internal\EnumOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
      * @param \Google\Protobuf\Internal\EnumOptions $var
@@ -147,16 +150,10 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * Range of reserved numeric values. Reserved numeric values may not be used
      * by enum values in the same enum declaration. Reserved ranges may not
@@ -183,16 +180,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class);
         $this->reserved_range = $arr;
-        $this->has_reserved_range = true;
 
         return $this;
     }
 
-    public function hasReservedRange()
-    {
-        return $this->has_reserved_range;
-    }
-
     /**
      * Reserved enum value names, which may not be reused. A given name may only
      * be reserved once.
@@ -217,15 +208,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->reserved_name = $arr;
-        $this->has_reserved_name = true;
 
         return $this;
     }
 
-    public function hasReservedName()
-    {
-        return $this->has_reserved_name;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
index 949dd89..7282fcc 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
@@ -26,15 +26,13 @@
      *
      * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
-    protected $start = 0;
-    private $has_start = false;
+    protected $start = null;
     /**
      * Inclusive.
      *
      * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
 
     /**
      * Constructor.
@@ -61,7 +59,17 @@
      */
     public function getStart()
     {
-        return $this->start;
+        return isset($this->start) ? $this->start : 0;
+    }
+
+    public function hasStart()
+    {
+        return isset($this->start);
+    }
+
+    public function clearStart()
+    {
+        unset($this->start);
     }
 
     /**
@@ -75,16 +83,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
-        $this->has_start = true;
 
         return $this;
     }
 
-    public function hasStart()
-    {
-        return $this->has_start;
-    }
-
     /**
      * Inclusive.
      *
@@ -93,7 +95,17 @@
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -107,16 +119,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.
diff --git a/php/src/Google/Protobuf/Internal/EnumOptions.php b/php/src/Google/Protobuf/Internal/EnumOptions.php
index e650042..7a69676 100644
--- a/php/src/Google/Protobuf/Internal/EnumOptions.php
+++ b/php/src/Google/Protobuf/Internal/EnumOptions.php
@@ -21,8 +21,7 @@
      *
      * Generated from protobuf field <code>optional bool allow_alias = 2;</code>
      */
-    protected $allow_alias = false;
-    private $has_allow_alias = false;
+    protected $allow_alias = null;
     /**
      * Is this enum deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -31,15 +30,13 @@
      *
      * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -73,7 +70,17 @@
      */
     public function getAllowAlias()
     {
-        return $this->allow_alias;
+        return isset($this->allow_alias) ? $this->allow_alias : false;
+    }
+
+    public function hasAllowAlias()
+    {
+        return isset($this->allow_alias);
+    }
+
+    public function clearAllowAlias()
+    {
+        unset($this->allow_alias);
     }
 
     /**
@@ -88,16 +95,10 @@
     {
         GPBUtil::checkBool($var);
         $this->allow_alias = $var;
-        $this->has_allow_alias = true;
 
         return $this;
     }
 
-    public function hasAllowAlias()
-    {
-        return $this->has_allow_alias;
-    }
-
     /**
      * Is this enum deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -109,7 +110,17 @@
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -126,16 +137,10 @@
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -158,15 +163,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
index 3dd9558..0feaea6 100644
--- a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
@@ -20,18 +20,15 @@
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>optional int32 number = 2;</code>
      */
-    protected $number = 0;
-    private $has_number = false;
+    protected $number = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -55,7 +52,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -67,23 +74,27 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional int32 number = 2;</code>
      * @return int
      */
     public function getNumber()
     {
-        return $this->number;
+        return isset($this->number) ? $this->number : 0;
+    }
+
+    public function hasNumber()
+    {
+        return isset($this->number);
+    }
+
+    public function clearNumber()
+    {
+        unset($this->number);
     }
 
     /**
@@ -95,25 +106,29 @@
     {
         GPBUtil::checkInt32($var);
         $this->number = $var;
-        $this->has_number = true;
 
         return $this;
     }
 
-    public function hasNumber()
-    {
-        return $this->has_number;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\EnumValueOptions
+     * @return \Google\Protobuf\Internal\EnumValueOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
      * @param \Google\Protobuf\Internal\EnumValueOptions $var
@@ -123,15 +138,9 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumValueOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/EnumValueOptions.php b/php/src/Google/Protobuf/Internal/EnumValueOptions.php
index 9f9fb3b..84ba7bc 100644
--- a/php/src/Google/Protobuf/Internal/EnumValueOptions.php
+++ b/php/src/Google/Protobuf/Internal/EnumValueOptions.php
@@ -23,15 +23,13 @@
      *
      * Generated from protobuf field <code>optional bool deprecated = 1 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -64,7 +62,17 @@
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -81,16 +89,10 @@
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -113,15 +115,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php
index 00fbebe..b5e27c3 100644
--- a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php
+++ b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php
@@ -21,7 +21,6 @@
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -60,15 +59,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptor.php b/php/src/Google/Protobuf/Internal/FieldDescriptor.php
index 98b516f..ce83f63 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptor.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptor.php
@@ -229,7 +229,17 @@
         }
 
         $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1;
-        $packed = false;
+        // TODO: once proto2 is supported, this default should be false
+        // for proto2.
+        if ($proto->getLabel() === GPBLabel::REPEATED &&
+            $proto->getType() !== GPBType::MESSAGE &&
+            $proto->getType() !== GPBType::GROUP &&
+            $proto->getType() !== GPBType::STRING &&
+            $proto->getType() !== GPBType::BYTES) {
+          $packed = true;
+        } else {
+          $packed = false;
+        }
         $options = $proto->getOptions();
         if ($options !== null) {
             $packed = $options->getPacked();
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
index b43d988..9cf6f10 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
@@ -20,26 +20,22 @@
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>optional int32 number = 3;</code>
      */
-    protected $number = 0;
-    private $has_number = false;
+    protected $number = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
      */
-    protected $label = 0;
-    private $has_label = false;
+    protected $label = null;
     /**
      * If type_name is set, this need not be set.  If both this and type_name
      * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
      *
      * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
      */
-    protected $type = 0;
-    private $has_type = false;
+    protected $type = null;
     /**
      * For message and enum types, this is the name of the type.  If the name
      * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
@@ -49,16 +45,14 @@
      *
      * Generated from protobuf field <code>optional string type_name = 6;</code>
      */
-    protected $type_name = '';
-    private $has_type_name = false;
+    protected $type_name = null;
     /**
      * For extensions, this is the name of the type being extended.  It is
      * resolved in the same manner as type_name.
      *
      * Generated from protobuf field <code>optional string extendee = 2;</code>
      */
-    protected $extendee = '';
-    private $has_extendee = false;
+    protected $extendee = null;
     /**
      * For numeric types, contains the original text representation of the value.
      * For booleans, "true" or "false".
@@ -68,16 +62,14 @@
      *
      * Generated from protobuf field <code>optional string default_value = 7;</code>
      */
-    protected $default_value = '';
-    private $has_default_value = false;
+    protected $default_value = null;
     /**
      * If set, gives the index of a oneof in the containing type's oneof_decl
      * list.  This field is a member of that oneof.
      *
      * Generated from protobuf field <code>optional int32 oneof_index = 9;</code>
      */
-    protected $oneof_index = 0;
-    private $has_oneof_index = false;
+    protected $oneof_index = null;
     /**
      * JSON name of this field. The value is set by protocol compiler. If the
      * user has set a "json_name" option on this field, that option's value
@@ -86,13 +78,11 @@
      *
      * Generated from protobuf field <code>optional string json_name = 10;</code>
      */
-    protected $json_name = '';
-    private $has_json_name = false;
+    protected $json_name = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * If true, this is a proto3 "optional". When a proto3 field is optional, it
      * tracks presence regardless of field type.
@@ -115,8 +105,7 @@
      *
      * Generated from protobuf field <code>optional bool proto3_optional = 17;</code>
      */
-    protected $proto3_optional = false;
-    private $has_proto3_optional = false;
+    protected $proto3_optional = null;
 
     /**
      * Constructor.
@@ -186,7 +175,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -198,23 +197,27 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional int32 number = 3;</code>
      * @return int
      */
     public function getNumber()
     {
-        return $this->number;
+        return isset($this->number) ? $this->number : 0;
+    }
+
+    public function hasNumber()
+    {
+        return isset($this->number);
+    }
+
+    public function clearNumber()
+    {
+        unset($this->number);
     }
 
     /**
@@ -226,23 +229,27 @@
     {
         GPBUtil::checkInt32($var);
         $this->number = $var;
-        $this->has_number = true;
 
         return $this;
     }
 
-    public function hasNumber()
-    {
-        return $this->has_number;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
      * @return int
      */
     public function getLabel()
     {
-        return $this->label;
+        return isset($this->label) ? $this->label : 0;
+    }
+
+    public function hasLabel()
+    {
+        return isset($this->label);
+    }
+
+    public function clearLabel()
+    {
+        unset($this->label);
     }
 
     /**
@@ -252,18 +259,12 @@
      */
     public function setLabel($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Label::class);
         $this->label = $var;
-        $this->has_label = true;
 
         return $this;
     }
 
-    public function hasLabel()
-    {
-        return $this->has_label;
-    }
-
     /**
      * If type_name is set, this need not be set.  If both this and type_name
      * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
@@ -273,7 +274,17 @@
      */
     public function getType()
     {
-        return $this->type;
+        return isset($this->type) ? $this->type : 0;
+    }
+
+    public function hasType()
+    {
+        return isset($this->type);
+    }
+
+    public function clearType()
+    {
+        unset($this->type);
     }
 
     /**
@@ -286,18 +297,12 @@
      */
     public function setType($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Type::class);
         $this->type = $var;
-        $this->has_type = true;
 
         return $this;
     }
 
-    public function hasType()
-    {
-        return $this->has_type;
-    }
-
     /**
      * For message and enum types, this is the name of the type.  If the name
      * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
@@ -310,7 +315,17 @@
      */
     public function getTypeName()
     {
-        return $this->type_name;
+        return isset($this->type_name) ? $this->type_name : '';
+    }
+
+    public function hasTypeName()
+    {
+        return isset($this->type_name);
+    }
+
+    public function clearTypeName()
+    {
+        unset($this->type_name);
     }
 
     /**
@@ -328,16 +343,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->type_name = $var;
-        $this->has_type_name = true;
 
         return $this;
     }
 
-    public function hasTypeName()
-    {
-        return $this->has_type_name;
-    }
-
     /**
      * For extensions, this is the name of the type being extended.  It is
      * resolved in the same manner as type_name.
@@ -347,7 +356,17 @@
      */
     public function getExtendee()
     {
-        return $this->extendee;
+        return isset($this->extendee) ? $this->extendee : '';
+    }
+
+    public function hasExtendee()
+    {
+        return isset($this->extendee);
+    }
+
+    public function clearExtendee()
+    {
+        unset($this->extendee);
     }
 
     /**
@@ -362,16 +381,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->extendee = $var;
-        $this->has_extendee = true;
 
         return $this;
     }
 
-    public function hasExtendee()
-    {
-        return $this->has_extendee;
-    }
-
     /**
      * For numeric types, contains the original text representation of the value.
      * For booleans, "true" or "false".
@@ -384,7 +397,17 @@
      */
     public function getDefaultValue()
     {
-        return $this->default_value;
+        return isset($this->default_value) ? $this->default_value : '';
+    }
+
+    public function hasDefaultValue()
+    {
+        return isset($this->default_value);
+    }
+
+    public function clearDefaultValue()
+    {
+        unset($this->default_value);
     }
 
     /**
@@ -402,16 +425,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->default_value = $var;
-        $this->has_default_value = true;
 
         return $this;
     }
 
-    public function hasDefaultValue()
-    {
-        return $this->has_default_value;
-    }
-
     /**
      * If set, gives the index of a oneof in the containing type's oneof_decl
      * list.  This field is a member of that oneof.
@@ -421,7 +438,17 @@
      */
     public function getOneofIndex()
     {
-        return $this->oneof_index;
+        return isset($this->oneof_index) ? $this->oneof_index : 0;
+    }
+
+    public function hasOneofIndex()
+    {
+        return isset($this->oneof_index);
+    }
+
+    public function clearOneofIndex()
+    {
+        unset($this->oneof_index);
     }
 
     /**
@@ -436,16 +463,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->oneof_index = $var;
-        $this->has_oneof_index = true;
 
         return $this;
     }
 
-    public function hasOneofIndex()
-    {
-        return $this->has_oneof_index;
-    }
-
     /**
      * JSON name of this field. The value is set by protocol compiler. If the
      * user has set a "json_name" option on this field, that option's value
@@ -457,7 +478,17 @@
      */
     public function getJsonName()
     {
-        return $this->json_name;
+        return isset($this->json_name) ? $this->json_name : '';
+    }
+
+    public function hasJsonName()
+    {
+        return isset($this->json_name);
+    }
+
+    public function clearJsonName()
+    {
+        unset($this->json_name);
     }
 
     /**
@@ -474,25 +505,29 @@
     {
         GPBUtil::checkString($var, True);
         $this->json_name = $var;
-        $this->has_json_name = true;
 
         return $this;
     }
 
-    public function hasJsonName()
-    {
-        return $this->has_json_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
-     * @return \Google\Protobuf\Internal\FieldOptions
+     * @return \Google\Protobuf\Internal\FieldOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
      * @param \Google\Protobuf\Internal\FieldOptions $var
@@ -502,16 +537,10 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * If true, this is a proto3 "optional". When a proto3 field is optional, it
      * tracks presence regardless of field type.
@@ -537,7 +566,17 @@
      */
     public function getProto3Optional()
     {
-        return $this->proto3_optional;
+        return isset($this->proto3_optional) ? $this->proto3_optional : false;
+    }
+
+    public function hasProto3Optional()
+    {
+        return isset($this->proto3_optional);
+    }
+
+    public function clearProto3Optional()
+    {
+        unset($this->proto3_optional);
     }
 
     /**
@@ -568,15 +607,9 @@
     {
         GPBUtil::checkBool($var);
         $this->proto3_optional = $var;
-        $this->has_proto3_optional = true;
 
         return $this;
     }
 
-    public function hasProto3Optional()
-    {
-        return $this->has_proto3_optional;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions.php b/php/src/Google/Protobuf/Internal/FieldOptions.php
index 2ccc418..c6c63a9 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions.php
@@ -23,8 +23,7 @@
      *
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
      */
-    protected $ctype = 0;
-    private $has_ctype = false;
+    protected $ctype = null;
     /**
      * The packed option can be enabled for repeated primitive fields to enable
      * a more efficient representation on the wire. Rather than repeatedly
@@ -34,8 +33,7 @@
      *
      * Generated from protobuf field <code>optional bool packed = 2;</code>
      */
-    protected $packed = false;
-    private $has_packed = false;
+    protected $packed = null;
     /**
      * The jstype option determines the JavaScript type used for values of the
      * field.  The option is permitted only for 64 bit integral and fixed types
@@ -50,8 +48,7 @@
      *
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
      */
-    protected $jstype = 0;
-    private $has_jstype = false;
+    protected $jstype = null;
     /**
      * Should this field be parsed lazily?  Lazy applies only to message-type
      * fields.  It means that when the outer message is initially parsed, the
@@ -80,8 +77,7 @@
      *
      * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
      */
-    protected $lazy = false;
-    private $has_lazy = false;
+    protected $lazy = null;
     /**
      * Is this field deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -90,22 +86,19 @@
      *
      * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * For Google-internal migration only. Do not use.
      *
      * Generated from protobuf field <code>optional bool weak = 10 [default = false];</code>
      */
-    protected $weak = false;
-    private $has_weak = false;
+    protected $weak = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -187,7 +180,17 @@
      */
     public function getCtype()
     {
-        return $this->ctype;
+        return isset($this->ctype) ? $this->ctype : 0;
+    }
+
+    public function hasCtype()
+    {
+        return isset($this->ctype);
+    }
+
+    public function clearCtype()
+    {
+        unset($this->ctype);
     }
 
     /**
@@ -202,18 +205,12 @@
      */
     public function setCtype($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_CType::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\CType::class);
         $this->ctype = $var;
-        $this->has_ctype = true;
 
         return $this;
     }
 
-    public function hasCtype()
-    {
-        return $this->has_ctype;
-    }
-
     /**
      * The packed option can be enabled for repeated primitive fields to enable
      * a more efficient representation on the wire. Rather than repeatedly
@@ -226,7 +223,17 @@
      */
     public function getPacked()
     {
-        return $this->packed;
+        return isset($this->packed) ? $this->packed : false;
+    }
+
+    public function hasPacked()
+    {
+        return isset($this->packed);
+    }
+
+    public function clearPacked()
+    {
+        unset($this->packed);
     }
 
     /**
@@ -244,16 +251,10 @@
     {
         GPBUtil::checkBool($var);
         $this->packed = $var;
-        $this->has_packed = true;
 
         return $this;
     }
 
-    public function hasPacked()
-    {
-        return $this->has_packed;
-    }
-
     /**
      * The jstype option determines the JavaScript type used for values of the
      * field.  The option is permitted only for 64 bit integral and fixed types
@@ -271,7 +272,17 @@
      */
     public function getJstype()
     {
-        return $this->jstype;
+        return isset($this->jstype) ? $this->jstype : 0;
+    }
+
+    public function hasJstype()
+    {
+        return isset($this->jstype);
+    }
+
+    public function clearJstype()
+    {
+        unset($this->jstype);
     }
 
     /**
@@ -292,18 +303,12 @@
      */
     public function setJstype($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_JSType::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\JSType::class);
         $this->jstype = $var;
-        $this->has_jstype = true;
 
         return $this;
     }
 
-    public function hasJstype()
-    {
-        return $this->has_jstype;
-    }
-
     /**
      * Should this field be parsed lazily?  Lazy applies only to message-type
      * fields.  It means that when the outer message is initially parsed, the
@@ -335,7 +340,17 @@
      */
     public function getLazy()
     {
-        return $this->lazy;
+        return isset($this->lazy) ? $this->lazy : false;
+    }
+
+    public function hasLazy()
+    {
+        return isset($this->lazy);
+    }
+
+    public function clearLazy()
+    {
+        unset($this->lazy);
     }
 
     /**
@@ -372,16 +387,10 @@
     {
         GPBUtil::checkBool($var);
         $this->lazy = $var;
-        $this->has_lazy = true;
 
         return $this;
     }
 
-    public function hasLazy()
-    {
-        return $this->has_lazy;
-    }
-
     /**
      * Is this field deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -393,7 +402,17 @@
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -410,16 +429,10 @@
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * For Google-internal migration only. Do not use.
      *
@@ -428,7 +441,17 @@
      */
     public function getWeak()
     {
-        return $this->weak;
+        return isset($this->weak) ? $this->weak : false;
+    }
+
+    public function hasWeak()
+    {
+        return isset($this->weak);
+    }
+
+    public function clearWeak()
+    {
+        unset($this->weak);
     }
 
     /**
@@ -442,16 +465,10 @@
     {
         GPBUtil::checkBool($var);
         $this->weak = $var;
-        $this->has_weak = true;
 
         return $this;
     }
 
-    public function hasWeak()
-    {
-        return $this->has_weak;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -474,15 +491,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
index c9e3648..435bd5f 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
@@ -22,29 +22,25 @@
      *
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * e.g. "foo", "foo.bar", etc.
      *
      * Generated from protobuf field <code>optional string package = 2;</code>
      */
-    protected $package = '';
-    private $has_package = false;
+    protected $package = null;
     /**
      * Names of files imported by this file.
      *
      * Generated from protobuf field <code>repeated string dependency = 3;</code>
      */
     private $dependency;
-    private $has_dependency = false;
     /**
      * Indexes of the public imported files in the dependency list above.
      *
      * Generated from protobuf field <code>repeated int32 public_dependency = 10;</code>
      */
     private $public_dependency;
-    private $has_public_dependency = false;
     /**
      * Indexes of the weak imported files in the dependency list.
      * For Google-internal migration only. Do not use.
@@ -52,34 +48,28 @@
      * Generated from protobuf field <code>repeated int32 weak_dependency = 11;</code>
      */
     private $weak_dependency;
-    private $has_weak_dependency = false;
     /**
      * All top-level definitions in this file.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
      */
     private $message_type;
-    private $has_message_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
      */
     private $enum_type;
-    private $has_enum_type = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
      */
     private $service;
-    private $has_service = false;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
      */
     private $extension;
-    private $has_extension = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
@@ -89,15 +79,13 @@
      * Generated from protobuf field <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
      */
     protected $source_code_info = null;
-    private $has_source_code_info = false;
     /**
      * The syntax of the proto file.
      * The supported values are "proto2" and "proto3".
      *
      * Generated from protobuf field <code>optional string syntax = 12;</code>
      */
-    protected $syntax = '';
-    private $has_syntax = false;
+    protected $syntax = null;
 
     /**
      * Constructor.
@@ -145,7 +133,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -159,16 +157,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * e.g. "foo", "foo.bar", etc.
      *
@@ -177,7 +169,17 @@
      */
     public function getPackage()
     {
-        return $this->package;
+        return isset($this->package) ? $this->package : '';
+    }
+
+    public function hasPackage()
+    {
+        return isset($this->package);
+    }
+
+    public function clearPackage()
+    {
+        unset($this->package);
     }
 
     /**
@@ -191,16 +193,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->package = $var;
-        $this->has_package = true;
 
         return $this;
     }
 
-    public function hasPackage()
-    {
-        return $this->has_package;
-    }
-
     /**
      * Names of files imported by this file.
      *
@@ -223,16 +219,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->dependency = $arr;
-        $this->has_dependency = true;
 
         return $this;
     }
 
-    public function hasDependency()
-    {
-        return $this->has_dependency;
-    }
-
     /**
      * Indexes of the public imported files in the dependency list above.
      *
@@ -255,16 +245,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->public_dependency = $arr;
-        $this->has_public_dependency = true;
 
         return $this;
     }
 
-    public function hasPublicDependency()
-    {
-        return $this->has_public_dependency;
-    }
-
     /**
      * Indexes of the weak imported files in the dependency list.
      * For Google-internal migration only. Do not use.
@@ -289,16 +273,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->weak_dependency = $arr;
-        $this->has_weak_dependency = true;
 
         return $this;
     }
 
-    public function hasWeakDependency()
-    {
-        return $this->has_weak_dependency;
-    }
-
     /**
      * All top-level definitions in this file.
      *
@@ -321,16 +299,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
         $this->message_type = $arr;
-        $this->has_message_type = true;
 
         return $this;
     }
 
-    public function hasMessageType()
-    {
-        return $this->has_message_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -349,16 +321,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
         $this->enum_type = $arr;
-        $this->has_enum_type = true;
 
         return $this;
     }
 
-    public function hasEnumType()
-    {
-        return $this->has_enum_type;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -377,16 +343,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\ServiceDescriptorProto::class);
         $this->service = $arr;
-        $this->has_service = true;
 
         return $this;
     }
 
-    public function hasService()
-    {
-        return $this->has_service;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -405,25 +365,29 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->extension = $arr;
-        $this->has_extension = true;
 
         return $this;
     }
 
-    public function hasExtension()
-    {
-        return $this->has_extension;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
-     * @return \Google\Protobuf\Internal\FileOptions
+     * @return \Google\Protobuf\Internal\FileOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
      * @param \Google\Protobuf\Internal\FileOptions $var
@@ -433,16 +397,10 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FileOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
@@ -450,13 +408,23 @@
      * development tools.
      *
      * Generated from protobuf field <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
-     * @return \Google\Protobuf\Internal\SourceCodeInfo
+     * @return \Google\Protobuf\Internal\SourceCodeInfo|null
      */
     public function getSourceCodeInfo()
     {
         return $this->source_code_info;
     }
 
+    public function hasSourceCodeInfo()
+    {
+        return isset($this->source_code_info);
+    }
+
+    public function clearSourceCodeInfo()
+    {
+        unset($this->source_code_info);
+    }
+
     /**
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
@@ -471,16 +439,10 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\SourceCodeInfo::class);
         $this->source_code_info = $var;
-        $this->has_source_code_info = true;
 
         return $this;
     }
 
-    public function hasSourceCodeInfo()
-    {
-        return $this->has_source_code_info;
-    }
-
     /**
      * The syntax of the proto file.
      * The supported values are "proto2" and "proto3".
@@ -490,7 +452,17 @@
      */
     public function getSyntax()
     {
-        return $this->syntax;
+        return isset($this->syntax) ? $this->syntax : '';
+    }
+
+    public function hasSyntax()
+    {
+        return isset($this->syntax);
+    }
+
+    public function clearSyntax()
+    {
+        unset($this->syntax);
     }
 
     /**
@@ -505,15 +477,9 @@
     {
         GPBUtil::checkString($var, True);
         $this->syntax = $var;
-        $this->has_syntax = true;
 
         return $this;
     }
 
-    public function hasSyntax()
-    {
-        return $this->has_syntax;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
index 9907b17..794e634 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
@@ -22,7 +22,6 @@
      * Generated from protobuf field <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
      */
     private $file;
-    private $has_file = false;
 
     /**
      * Constructor.
@@ -56,15 +55,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FileDescriptorProto::class);
         $this->file = $arr;
-        $this->has_file = true;
 
         return $this;
     }
 
-    public function hasFile()
-    {
-        return $this->has_file;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php
index 892a6a8..3f2c3a4 100644
--- a/php/src/Google/Protobuf/Internal/FileOptions.php
+++ b/php/src/Google/Protobuf/Internal/FileOptions.php
@@ -23,38 +23,35 @@
      *
      * Generated from protobuf field <code>optional string java_package = 1;</code>
      */
-    protected $java_package = '';
-    private $has_java_package = false;
+    protected $java_package = null;
     /**
-     * If set, all the classes from the .proto file are wrapped in a single
-     * outer class with the given name.  This applies to both Proto1
-     * (equivalent to the old "--one_java_file" option) and Proto2 (where
-     * a .proto always translates to a single class, but you may want to
-     * explicitly choose the class name).
+     * Controls the name of the wrapper Java class generated for the .proto file.
+     * That class will always contain the .proto file's getDescriptor() method as
+     * well as any top-level extensions defined in the .proto file.
+     * If java_multiple_files is disabled, then all the other classes from the
+     * .proto file will be nested inside the single wrapper outer class.
      *
      * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      */
-    protected $java_outer_classname = '';
-    private $has_java_outer_classname = false;
+    protected $java_outer_classname = null;
     /**
-     * If set true, then the Java code generator will generate a separate .java
+     * If enabled, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
-     * file.  Thus, these types will *not* be nested inside the outer class
-     * named by java_outer_classname.  However, the outer class will still be
+     * file.  Thus, these types will *not* be nested inside the wrapper class
+     * named by java_outer_classname.  However, the wrapper class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
      *
      * Generated from protobuf field <code>optional bool java_multiple_files = 10 [default = false];</code>
      */
-    protected $java_multiple_files = false;
-    private $has_java_multiple_files = false;
+    protected $java_multiple_files = null;
     /**
      * This option does nothing.
      *
      * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
+     * @deprecated
      */
-    protected $java_generate_equals_and_hash = false;
-    private $has_java_generate_equals_and_hash = false;
+    protected $java_generate_equals_and_hash = null;
     /**
      * If set true, then the Java2 code generator will generate code that
      * throws an exception whenever an attempt is made to assign a non-UTF-8
@@ -65,13 +62,11 @@
      *
      * Generated from protobuf field <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
      */
-    protected $java_string_check_utf8 = false;
-    private $has_java_string_check_utf8 = false;
+    protected $java_string_check_utf8 = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
      */
-    protected $optimize_for = 0;
-    private $has_optimize_for = false;
+    protected $optimize_for = null;
     /**
      * Sets the Go package where structs generated from this .proto will be
      * placed. If omitted, the Go package will be derived from the following:
@@ -81,8 +76,7 @@
      *
      * Generated from protobuf field <code>optional string go_package = 11;</code>
      */
-    protected $go_package = '';
-    private $has_go_package = false;
+    protected $go_package = null;
     /**
      * Should generic services be generated in each language?  "Generic" services
      * are not specific to any particular RPC system.  They are generated by the
@@ -96,23 +90,19 @@
      *
      * Generated from protobuf field <code>optional bool cc_generic_services = 16 [default = false];</code>
      */
-    protected $cc_generic_services = false;
-    private $has_cc_generic_services = false;
+    protected $cc_generic_services = null;
     /**
      * Generated from protobuf field <code>optional bool java_generic_services = 17 [default = false];</code>
      */
-    protected $java_generic_services = false;
-    private $has_java_generic_services = false;
+    protected $java_generic_services = null;
     /**
      * Generated from protobuf field <code>optional bool py_generic_services = 18 [default = false];</code>
      */
-    protected $py_generic_services = false;
-    private $has_py_generic_services = false;
+    protected $py_generic_services = null;
     /**
      * Generated from protobuf field <code>optional bool php_generic_services = 42 [default = false];</code>
      */
-    protected $php_generic_services = false;
-    private $has_php_generic_services = false;
+    protected $php_generic_services = null;
     /**
      * Is this file deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -121,31 +111,27 @@
      *
      * Generated from protobuf field <code>optional bool deprecated = 23 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
      *
      * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = true];</code>
      */
-    protected $cc_enable_arenas = false;
-    private $has_cc_enable_arenas = false;
+    protected $cc_enable_arenas = null;
     /**
      * Sets the objective c class prefix which is prepended to all objective c
      * generated classes from this .proto. There is no default.
      *
      * Generated from protobuf field <code>optional string objc_class_prefix = 36;</code>
      */
-    protected $objc_class_prefix = '';
-    private $has_objc_class_prefix = false;
+    protected $objc_class_prefix = null;
     /**
      * Namespace for generated classes; defaults to the package.
      *
      * Generated from protobuf field <code>optional string csharp_namespace = 37;</code>
      */
-    protected $csharp_namespace = '';
-    private $has_csharp_namespace = false;
+    protected $csharp_namespace = null;
     /**
      * By default Swift generators will take the proto package and CamelCase it
      * replacing '.' with underscore and use that to prefix the types/symbols
@@ -154,16 +140,14 @@
      *
      * Generated from protobuf field <code>optional string swift_prefix = 39;</code>
      */
-    protected $swift_prefix = '';
-    private $has_swift_prefix = false;
+    protected $swift_prefix = null;
     /**
      * Sets the php class prefix which is prepended to all php generated classes
      * from this .proto. Default is empty.
      *
      * Generated from protobuf field <code>optional string php_class_prefix = 40;</code>
      */
-    protected $php_class_prefix = '';
-    private $has_php_class_prefix = false;
+    protected $php_class_prefix = null;
     /**
      * Use this option to change the namespace of php generated classes. Default
      * is empty. When this option is empty, the package name will be used for
@@ -171,8 +155,7 @@
      *
      * Generated from protobuf field <code>optional string php_namespace = 41;</code>
      */
-    protected $php_namespace = '';
-    private $has_php_namespace = false;
+    protected $php_namespace = null;
     /**
      * Use this option to change the namespace of php generated metadata classes.
      * Default is empty. When this option is empty, the proto file name will be
@@ -180,8 +163,7 @@
      *
      * Generated from protobuf field <code>optional string php_metadata_namespace = 44;</code>
      */
-    protected $php_metadata_namespace = '';
-    private $has_php_metadata_namespace = false;
+    protected $php_metadata_namespace = null;
     /**
      * Use this option to change the package of ruby generated classes. Default
      * is empty. When this option is not set, the package name will be used for
@@ -189,8 +171,7 @@
      *
      * Generated from protobuf field <code>optional string ruby_package = 45;</code>
      */
-    protected $ruby_package = '';
-    private $has_ruby_package = false;
+    protected $ruby_package = null;
     /**
      * The parser stores options it doesn't recognize here.
      * See the documentation for the "Options" section above.
@@ -198,7 +179,6 @@
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -212,16 +192,16 @@
      *           inappropriate because proto packages do not normally start with backwards
      *           domain names.
      *     @type string $java_outer_classname
-     *           If set, all the classes from the .proto file are wrapped in a single
-     *           outer class with the given name.  This applies to both Proto1
-     *           (equivalent to the old "--one_java_file" option) and Proto2 (where
-     *           a .proto always translates to a single class, but you may want to
-     *           explicitly choose the class name).
+     *           Controls the name of the wrapper Java class generated for the .proto file.
+     *           That class will always contain the .proto file's getDescriptor() method as
+     *           well as any top-level extensions defined in the .proto file.
+     *           If java_multiple_files is disabled, then all the other classes from the
+     *           .proto file will be nested inside the single wrapper outer class.
      *     @type bool $java_multiple_files
-     *           If set true, then the Java code generator will generate a separate .java
+     *           If enabled, then the Java code generator will generate a separate .java
      *           file for each top-level message, enum, and service defined in the .proto
-     *           file.  Thus, these types will *not* be nested inside the outer class
-     *           named by java_outer_classname.  However, the outer class will still be
+     *           file.  Thus, these types will *not* be nested inside the wrapper class
+     *           named by java_outer_classname.  However, the wrapper class will still be
      *           generated to contain the file's getDescriptor() method as well as any
      *           top-level extensions defined in the file.
      *     @type bool $java_generate_equals_and_hash
@@ -307,7 +287,17 @@
      */
     public function getJavaPackage()
     {
-        return $this->java_package;
+        return isset($this->java_package) ? $this->java_package : '';
+    }
+
+    public function hasJavaPackage()
+    {
+        return isset($this->java_package);
+    }
+
+    public function clearJavaPackage()
+    {
+        unset($this->java_package);
     }
 
     /**
@@ -324,37 +314,41 @@
     {
         GPBUtil::checkString($var, True);
         $this->java_package = $var;
-        $this->has_java_package = true;
 
         return $this;
     }
 
-    public function hasJavaPackage()
-    {
-        return $this->has_java_package;
-    }
-
     /**
-     * If set, all the classes from the .proto file are wrapped in a single
-     * outer class with the given name.  This applies to both Proto1
-     * (equivalent to the old "--one_java_file" option) and Proto2 (where
-     * a .proto always translates to a single class, but you may want to
-     * explicitly choose the class name).
+     * Controls the name of the wrapper Java class generated for the .proto file.
+     * That class will always contain the .proto file's getDescriptor() method as
+     * well as any top-level extensions defined in the .proto file.
+     * If java_multiple_files is disabled, then all the other classes from the
+     * .proto file will be nested inside the single wrapper outer class.
      *
      * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      * @return string
      */
     public function getJavaOuterClassname()
     {
-        return $this->java_outer_classname;
+        return isset($this->java_outer_classname) ? $this->java_outer_classname : '';
+    }
+
+    public function hasJavaOuterClassname()
+    {
+        return isset($this->java_outer_classname);
+    }
+
+    public function clearJavaOuterClassname()
+    {
+        unset($this->java_outer_classname);
     }
 
     /**
-     * If set, all the classes from the .proto file are wrapped in a single
-     * outer class with the given name.  This applies to both Proto1
-     * (equivalent to the old "--one_java_file" option) and Proto2 (where
-     * a .proto always translates to a single class, but you may want to
-     * explicitly choose the class name).
+     * Controls the name of the wrapper Java class generated for the .proto file.
+     * That class will always contain the .proto file's getDescriptor() method as
+     * well as any top-level extensions defined in the .proto file.
+     * If java_multiple_files is disabled, then all the other classes from the
+     * .proto file will be nested inside the single wrapper outer class.
      *
      * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      * @param string $var
@@ -364,21 +358,15 @@
     {
         GPBUtil::checkString($var, True);
         $this->java_outer_classname = $var;
-        $this->has_java_outer_classname = true;
 
         return $this;
     }
 
-    public function hasJavaOuterClassname()
-    {
-        return $this->has_java_outer_classname;
-    }
-
     /**
-     * If set true, then the Java code generator will generate a separate .java
+     * If enabled, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
-     * file.  Thus, these types will *not* be nested inside the outer class
-     * named by java_outer_classname.  However, the outer class will still be
+     * file.  Thus, these types will *not* be nested inside the wrapper class
+     * named by java_outer_classname.  However, the wrapper class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
      *
@@ -387,14 +375,24 @@
      */
     public function getJavaMultipleFiles()
     {
-        return $this->java_multiple_files;
+        return isset($this->java_multiple_files) ? $this->java_multiple_files : false;
+    }
+
+    public function hasJavaMultipleFiles()
+    {
+        return isset($this->java_multiple_files);
+    }
+
+    public function clearJavaMultipleFiles()
+    {
+        unset($this->java_multiple_files);
     }
 
     /**
-     * If set true, then the Java code generator will generate a separate .java
+     * If enabled, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
-     * file.  Thus, these types will *not* be nested inside the outer class
-     * named by java_outer_classname.  However, the outer class will still be
+     * file.  Thus, these types will *not* be nested inside the wrapper class
+     * named by java_outer_classname.  However, the wrapper class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
      *
@@ -406,25 +404,33 @@
     {
         GPBUtil::checkBool($var);
         $this->java_multiple_files = $var;
-        $this->has_java_multiple_files = true;
 
         return $this;
     }
 
-    public function hasJavaMultipleFiles()
-    {
-        return $this->has_java_multiple_files;
-    }
-
     /**
      * This option does nothing.
      *
      * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
      * @return bool
+     * @deprecated
      */
     public function getJavaGenerateEqualsAndHash()
     {
-        return $this->java_generate_equals_and_hash;
+        @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
+        return isset($this->java_generate_equals_and_hash) ? $this->java_generate_equals_and_hash : false;
+    }
+
+    public function hasJavaGenerateEqualsAndHash()
+    {
+        @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
+        return isset($this->java_generate_equals_and_hash);
+    }
+
+    public function clearJavaGenerateEqualsAndHash()
+    {
+        @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
+        unset($this->java_generate_equals_and_hash);
     }
 
     /**
@@ -433,21 +439,17 @@
      * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
      * @param bool $var
      * @return $this
+     * @deprecated
      */
     public function setJavaGenerateEqualsAndHash($var)
     {
+        @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
         GPBUtil::checkBool($var);
         $this->java_generate_equals_and_hash = $var;
-        $this->has_java_generate_equals_and_hash = true;
 
         return $this;
     }
 
-    public function hasJavaGenerateEqualsAndHash()
-    {
-        return $this->has_java_generate_equals_and_hash;
-    }
-
     /**
      * If set true, then the Java2 code generator will generate code that
      * throws an exception whenever an attempt is made to assign a non-UTF-8
@@ -461,7 +463,17 @@
      */
     public function getJavaStringCheckUtf8()
     {
-        return $this->java_string_check_utf8;
+        return isset($this->java_string_check_utf8) ? $this->java_string_check_utf8 : false;
+    }
+
+    public function hasJavaStringCheckUtf8()
+    {
+        return isset($this->java_string_check_utf8);
+    }
+
+    public function clearJavaStringCheckUtf8()
+    {
+        unset($this->java_string_check_utf8);
     }
 
     /**
@@ -480,23 +492,27 @@
     {
         GPBUtil::checkBool($var);
         $this->java_string_check_utf8 = $var;
-        $this->has_java_string_check_utf8 = true;
 
         return $this;
     }
 
-    public function hasJavaStringCheckUtf8()
-    {
-        return $this->has_java_string_check_utf8;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
      * @return int
      */
     public function getOptimizeFor()
     {
-        return $this->optimize_for;
+        return isset($this->optimize_for) ? $this->optimize_for : 0;
+    }
+
+    public function hasOptimizeFor()
+    {
+        return isset($this->optimize_for);
+    }
+
+    public function clearOptimizeFor()
+    {
+        unset($this->optimize_for);
     }
 
     /**
@@ -506,18 +522,12 @@
      */
     public function setOptimizeFor($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions\OptimizeMode::class);
         $this->optimize_for = $var;
-        $this->has_optimize_for = true;
 
         return $this;
     }
 
-    public function hasOptimizeFor()
-    {
-        return $this->has_optimize_for;
-    }
-
     /**
      * Sets the Go package where structs generated from this .proto will be
      * placed. If omitted, the Go package will be derived from the following:
@@ -530,7 +540,17 @@
      */
     public function getGoPackage()
     {
-        return $this->go_package;
+        return isset($this->go_package) ? $this->go_package : '';
+    }
+
+    public function hasGoPackage()
+    {
+        return isset($this->go_package);
+    }
+
+    public function clearGoPackage()
+    {
+        unset($this->go_package);
     }
 
     /**
@@ -548,16 +568,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->go_package = $var;
-        $this->has_go_package = true;
 
         return $this;
     }
 
-    public function hasGoPackage()
-    {
-        return $this->has_go_package;
-    }
-
     /**
      * Should generic services be generated in each language?  "Generic" services
      * are not specific to any particular RPC system.  They are generated by the
@@ -574,7 +588,17 @@
      */
     public function getCcGenericServices()
     {
-        return $this->cc_generic_services;
+        return isset($this->cc_generic_services) ? $this->cc_generic_services : false;
+    }
+
+    public function hasCcGenericServices()
+    {
+        return isset($this->cc_generic_services);
+    }
+
+    public function clearCcGenericServices()
+    {
+        unset($this->cc_generic_services);
     }
 
     /**
@@ -596,23 +620,27 @@
     {
         GPBUtil::checkBool($var);
         $this->cc_generic_services = $var;
-        $this->has_cc_generic_services = true;
 
         return $this;
     }
 
-    public function hasCcGenericServices()
-    {
-        return $this->has_cc_generic_services;
-    }
-
     /**
      * Generated from protobuf field <code>optional bool java_generic_services = 17 [default = false];</code>
      * @return bool
      */
     public function getJavaGenericServices()
     {
-        return $this->java_generic_services;
+        return isset($this->java_generic_services) ? $this->java_generic_services : false;
+    }
+
+    public function hasJavaGenericServices()
+    {
+        return isset($this->java_generic_services);
+    }
+
+    public function clearJavaGenericServices()
+    {
+        unset($this->java_generic_services);
     }
 
     /**
@@ -624,23 +652,27 @@
     {
         GPBUtil::checkBool($var);
         $this->java_generic_services = $var;
-        $this->has_java_generic_services = true;
 
         return $this;
     }
 
-    public function hasJavaGenericServices()
-    {
-        return $this->has_java_generic_services;
-    }
-
     /**
      * Generated from protobuf field <code>optional bool py_generic_services = 18 [default = false];</code>
      * @return bool
      */
     public function getPyGenericServices()
     {
-        return $this->py_generic_services;
+        return isset($this->py_generic_services) ? $this->py_generic_services : false;
+    }
+
+    public function hasPyGenericServices()
+    {
+        return isset($this->py_generic_services);
+    }
+
+    public function clearPyGenericServices()
+    {
+        unset($this->py_generic_services);
     }
 
     /**
@@ -652,23 +684,27 @@
     {
         GPBUtil::checkBool($var);
         $this->py_generic_services = $var;
-        $this->has_py_generic_services = true;
 
         return $this;
     }
 
-    public function hasPyGenericServices()
-    {
-        return $this->has_py_generic_services;
-    }
-
     /**
      * Generated from protobuf field <code>optional bool php_generic_services = 42 [default = false];</code>
      * @return bool
      */
     public function getPhpGenericServices()
     {
-        return $this->php_generic_services;
+        return isset($this->php_generic_services) ? $this->php_generic_services : false;
+    }
+
+    public function hasPhpGenericServices()
+    {
+        return isset($this->php_generic_services);
+    }
+
+    public function clearPhpGenericServices()
+    {
+        unset($this->php_generic_services);
     }
 
     /**
@@ -680,16 +716,10 @@
     {
         GPBUtil::checkBool($var);
         $this->php_generic_services = $var;
-        $this->has_php_generic_services = true;
 
         return $this;
     }
 
-    public function hasPhpGenericServices()
-    {
-        return $this->has_php_generic_services;
-    }
-
     /**
      * Is this file deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -701,7 +731,17 @@
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -718,16 +758,10 @@
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
@@ -737,7 +771,17 @@
      */
     public function getCcEnableArenas()
     {
-        return $this->cc_enable_arenas;
+        return isset($this->cc_enable_arenas) ? $this->cc_enable_arenas : false;
+    }
+
+    public function hasCcEnableArenas()
+    {
+        return isset($this->cc_enable_arenas);
+    }
+
+    public function clearCcEnableArenas()
+    {
+        unset($this->cc_enable_arenas);
     }
 
     /**
@@ -752,16 +796,10 @@
     {
         GPBUtil::checkBool($var);
         $this->cc_enable_arenas = $var;
-        $this->has_cc_enable_arenas = true;
 
         return $this;
     }
 
-    public function hasCcEnableArenas()
-    {
-        return $this->has_cc_enable_arenas;
-    }
-
     /**
      * Sets the objective c class prefix which is prepended to all objective c
      * generated classes from this .proto. There is no default.
@@ -771,7 +809,17 @@
      */
     public function getObjcClassPrefix()
     {
-        return $this->objc_class_prefix;
+        return isset($this->objc_class_prefix) ? $this->objc_class_prefix : '';
+    }
+
+    public function hasObjcClassPrefix()
+    {
+        return isset($this->objc_class_prefix);
+    }
+
+    public function clearObjcClassPrefix()
+    {
+        unset($this->objc_class_prefix);
     }
 
     /**
@@ -786,16 +834,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->objc_class_prefix = $var;
-        $this->has_objc_class_prefix = true;
 
         return $this;
     }
 
-    public function hasObjcClassPrefix()
-    {
-        return $this->has_objc_class_prefix;
-    }
-
     /**
      * Namespace for generated classes; defaults to the package.
      *
@@ -804,7 +846,17 @@
      */
     public function getCsharpNamespace()
     {
-        return $this->csharp_namespace;
+        return isset($this->csharp_namespace) ? $this->csharp_namespace : '';
+    }
+
+    public function hasCsharpNamespace()
+    {
+        return isset($this->csharp_namespace);
+    }
+
+    public function clearCsharpNamespace()
+    {
+        unset($this->csharp_namespace);
     }
 
     /**
@@ -818,16 +870,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->csharp_namespace = $var;
-        $this->has_csharp_namespace = true;
 
         return $this;
     }
 
-    public function hasCsharpNamespace()
-    {
-        return $this->has_csharp_namespace;
-    }
-
     /**
      * By default Swift generators will take the proto package and CamelCase it
      * replacing '.' with underscore and use that to prefix the types/symbols
@@ -839,7 +885,17 @@
      */
     public function getSwiftPrefix()
     {
-        return $this->swift_prefix;
+        return isset($this->swift_prefix) ? $this->swift_prefix : '';
+    }
+
+    public function hasSwiftPrefix()
+    {
+        return isset($this->swift_prefix);
+    }
+
+    public function clearSwiftPrefix()
+    {
+        unset($this->swift_prefix);
     }
 
     /**
@@ -856,16 +912,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->swift_prefix = $var;
-        $this->has_swift_prefix = true;
 
         return $this;
     }
 
-    public function hasSwiftPrefix()
-    {
-        return $this->has_swift_prefix;
-    }
-
     /**
      * Sets the php class prefix which is prepended to all php generated classes
      * from this .proto. Default is empty.
@@ -875,7 +925,17 @@
      */
     public function getPhpClassPrefix()
     {
-        return $this->php_class_prefix;
+        return isset($this->php_class_prefix) ? $this->php_class_prefix : '';
+    }
+
+    public function hasPhpClassPrefix()
+    {
+        return isset($this->php_class_prefix);
+    }
+
+    public function clearPhpClassPrefix()
+    {
+        unset($this->php_class_prefix);
     }
 
     /**
@@ -890,16 +950,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->php_class_prefix = $var;
-        $this->has_php_class_prefix = true;
 
         return $this;
     }
 
-    public function hasPhpClassPrefix()
-    {
-        return $this->has_php_class_prefix;
-    }
-
     /**
      * Use this option to change the namespace of php generated classes. Default
      * is empty. When this option is empty, the package name will be used for
@@ -910,7 +964,17 @@
      */
     public function getPhpNamespace()
     {
-        return $this->php_namespace;
+        return isset($this->php_namespace) ? $this->php_namespace : '';
+    }
+
+    public function hasPhpNamespace()
+    {
+        return isset($this->php_namespace);
+    }
+
+    public function clearPhpNamespace()
+    {
+        unset($this->php_namespace);
     }
 
     /**
@@ -926,16 +990,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->php_namespace = $var;
-        $this->has_php_namespace = true;
 
         return $this;
     }
 
-    public function hasPhpNamespace()
-    {
-        return $this->has_php_namespace;
-    }
-
     /**
      * Use this option to change the namespace of php generated metadata classes.
      * Default is empty. When this option is empty, the proto file name will be
@@ -946,7 +1004,17 @@
      */
     public function getPhpMetadataNamespace()
     {
-        return $this->php_metadata_namespace;
+        return isset($this->php_metadata_namespace) ? $this->php_metadata_namespace : '';
+    }
+
+    public function hasPhpMetadataNamespace()
+    {
+        return isset($this->php_metadata_namespace);
+    }
+
+    public function clearPhpMetadataNamespace()
+    {
+        unset($this->php_metadata_namespace);
     }
 
     /**
@@ -962,16 +1030,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->php_metadata_namespace = $var;
-        $this->has_php_metadata_namespace = true;
 
         return $this;
     }
 
-    public function hasPhpMetadataNamespace()
-    {
-        return $this->has_php_metadata_namespace;
-    }
-
     /**
      * Use this option to change the package of ruby generated classes. Default
      * is empty. When this option is not set, the package name will be used for
@@ -982,7 +1044,17 @@
      */
     public function getRubyPackage()
     {
-        return $this->ruby_package;
+        return isset($this->ruby_package) ? $this->ruby_package : '';
+    }
+
+    public function hasRubyPackage()
+    {
+        return isset($this->ruby_package);
+    }
+
+    public function clearRubyPackage()
+    {
+        unset($this->ruby_package);
     }
 
     /**
@@ -998,16 +1070,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->ruby_package = $var;
-        $this->has_ruby_package = true;
 
         return $this;
     }
 
-    public function hasRubyPackage()
-    {
-        return $this->has_ruby_package;
-    }
-
     /**
      * The parser stores options it doesn't recognize here.
      * See the documentation for the "Options" section above.
@@ -1032,15 +1098,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php
index c091fc6..1dd6645 100644
--- a/php/src/Google/Protobuf/Internal/GPBUtil.php
+++ b/php/src/Google/Protobuf/Internal/GPBUtil.php
@@ -168,7 +168,7 @@
     public static function checkFloat(&$var)
     {
         if (is_float($var) || is_numeric($var)) {
-            $var = floatval($var);
+            $var = unpack("f", pack("f", $var))[1];
         } else {
             throw new \Exception("Expect float.");
         }
@@ -279,15 +279,16 @@
             "do"=>0, "echo"=>0, "else"=>0, "elseif"=>0, "empty"=>0,
             "enddeclare"=>0, "endfor"=>0, "endforeach"=>0, "endif"=>0,
             "endswitch"=>0, "endwhile"=>0, "eval"=>0, "exit"=>0, "extends"=>0,
-            "final"=>0, "for"=>0, "foreach"=>0, "function"=>0, "global"=>0,
-            "goto"=>0, "if"=>0, "implements"=>0, "include"=>0,
-            "include_once"=>0, "instanceof"=>0, "insteadof"=>0, "interface"=>0,
-            "isset"=>0, "list"=>0, "namespace"=>0, "new"=>0, "or"=>0,
-            "print"=>0, "private"=>0, "protected"=>0, "public"=>0, "require"=>0,
-            "require_once"=>0, "return"=>0, "static"=>0, "switch"=>0,
-            "throw"=>0, "trait"=>0, "try"=>0, "unset"=>0, "use"=>0, "var"=>0,
-            "while"=>0, "xor"=>0, "int"=>0, "float"=>0, "bool"=>0, "string"=>0,
-            "true"=>0, "false"=>0, "null"=>0, "void"=>0, "iterable"=>0
+            "final"=>0, "finally"=>0, "fn"=>0, "for"=>0, "foreach"=>0,
+            "function"=>0, "global"=>0, "goto"=>0, "if"=>0, "implements"=>0,
+            "include"=>0, "include_once"=>0, "instanceof"=>0, "insteadof"=>0,
+            "interface"=>0, "isset"=>0, "list"=>0, "match"=>0, "namespace"=>0,
+            "new"=>0, "or"=>0, "print"=>0, "private"=>0, "protected"=>0,
+            "public"=>0, "require"=>0, "require_once"=>0, "return"=>0,
+            "static"=>0, "switch"=>0, "throw"=>0, "trait"=>0, "try"=>0,
+            "unset"=>0, "use"=>0, "var"=>0, "while"=>0, "xor"=>0, "yield"=>0,
+            "int"=>0, "float"=>0, "bool"=>0, "string"=>0, "true"=>0, "false"=>0,
+            "null"=>0, "void"=>0, "iterable"=>0
         );
 
         if (array_key_exists(strtolower($classname), $reserved_words)) {
@@ -338,9 +339,9 @@
 
         $package = $file_proto->getPackage();
         if ($package === "") {
-            $fullname = "." . $message_name_without_package;
+            $fullname = $message_name_without_package;
         } else {
-            $fullname = "." . $package . "." . $message_name_without_package;
+            $fullname = $package . "." . $message_name_without_package;
         }
 
         $class_name_without_package =
diff --git a/php/src/Google/Protobuf/Internal/GPBWire.php b/php/src/Google/Protobuf/Internal/GPBWire.php
index 7f1eab3..2956953 100644
--- a/php/src/Google/Protobuf/Internal/GPBWire.php
+++ b/php/src/Google/Protobuf/Internal/GPBWire.php
@@ -50,8 +50,8 @@
 
     public static function getTagFieldNumber($tag)
     {
-        return ($tag >> self::TAG_TYPE_BITS) &
-            (1 << ((PHP_INT_SIZE * 8) - self::TAG_TYPE_BITS)) - 1;
+        // We have to mask because PHP has no arithmetic shift.
+        return ($tag >> self::TAG_TYPE_BITS) & 0x1fffffff;
     }
 
     public static function getTagWireType($tag)
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
index f5a65be..c261ed6 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
@@ -26,7 +26,6 @@
      * Generated from protobuf field <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
      */
     private $annotation;
-    private $has_annotation = false;
 
     /**
      * Constructor.
@@ -68,15 +67,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class);
         $this->annotation = $arr;
-        $this->has_annotation = true;
 
         return $this;
     }
 
-    public function hasAnnotation()
-    {
-        return $this->has_annotation;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
index 369fea4..0b043d0 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
@@ -22,22 +22,19 @@
      * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
      */
     private $path;
-    private $has_path = false;
     /**
      * Identifies the filesystem path to the original source .proto.
      *
      * Generated from protobuf field <code>optional string source_file = 2;</code>
      */
-    protected $source_file = '';
-    private $has_source_file = false;
+    protected $source_file = null;
     /**
      * Identifies the starting offset in bytes in the generated code
      * that relates to the identified object.
      *
      * Generated from protobuf field <code>optional int32 begin = 3;</code>
      */
-    protected $begin = 0;
-    private $has_begin = false;
+    protected $begin = null;
     /**
      * Identifies the ending offset in bytes in the generated code that
      * relates to the identified offset. The end offset should be one past
@@ -45,8 +42,7 @@
      *
      * Generated from protobuf field <code>optional int32 end = 4;</code>
      */
-    protected $end = 0;
-    private $has_end = false;
+    protected $end = null;
 
     /**
      * Constructor.
@@ -97,16 +93,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->path = $arr;
-        $this->has_path = true;
 
         return $this;
     }
 
-    public function hasPath()
-    {
-        return $this->has_path;
-    }
-
     /**
      * Identifies the filesystem path to the original source .proto.
      *
@@ -115,7 +105,17 @@
      */
     public function getSourceFile()
     {
-        return $this->source_file;
+        return isset($this->source_file) ? $this->source_file : '';
+    }
+
+    public function hasSourceFile()
+    {
+        return isset($this->source_file);
+    }
+
+    public function clearSourceFile()
+    {
+        unset($this->source_file);
     }
 
     /**
@@ -129,16 +129,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->source_file = $var;
-        $this->has_source_file = true;
 
         return $this;
     }
 
-    public function hasSourceFile()
-    {
-        return $this->has_source_file;
-    }
-
     /**
      * Identifies the starting offset in bytes in the generated code
      * that relates to the identified object.
@@ -148,7 +142,17 @@
      */
     public function getBegin()
     {
-        return $this->begin;
+        return isset($this->begin) ? $this->begin : 0;
+    }
+
+    public function hasBegin()
+    {
+        return isset($this->begin);
+    }
+
+    public function clearBegin()
+    {
+        unset($this->begin);
     }
 
     /**
@@ -163,16 +167,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->begin = $var;
-        $this->has_begin = true;
 
         return $this;
     }
 
-    public function hasBegin()
-    {
-        return $this->has_begin;
-    }
-
     /**
      * Identifies the ending offset in bytes in the generated code that
      * relates to the identified offset. The end offset should be one past
@@ -183,7 +181,17 @@
      */
     public function getEnd()
     {
-        return $this->end;
+        return isset($this->end) ? $this->end : 0;
+    }
+
+    public function hasEnd()
+    {
+        return isset($this->end);
+    }
+
+    public function clearEnd()
+    {
+        unset($this->end);
     }
 
     /**
@@ -199,16 +207,10 @@
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
-        $this->has_end = true;
 
         return $this;
     }
 
-    public function hasEnd()
-    {
-        return $this->has_end;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.
diff --git a/php/src/Google/Protobuf/Internal/MapField.php b/php/src/Google/Protobuf/Internal/MapField.php
index 2c66aa0..719fb35 100644
--- a/php/src/Google/Protobuf/Internal/MapField.php
+++ b/php/src/Google/Protobuf/Internal/MapField.php
@@ -129,7 +129,7 @@
      *
      * This will also be called for: $ele = $arr[$key]
      *
-     * @param object $key The key of the element to be fetched.
+     * @param int|bool|string $key The key of the element to be fetched.
      * @return object The stored element at given key.
      * @throws \ErrorException Invalid type for index.
      * @throws \ErrorException Non-existing index.
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
index e292026..19b48f0 100644
--- a/php/src/Google/Protobuf/Internal/Message.php
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -93,8 +93,9 @@
         $pool = DescriptorPool::getGeneratedPool();
         $this->desc = $pool->getDescriptorByClassName(get_class($this));
         if (is_null($this->desc)) {
-            user_error(get_class($this) . " is not found in descriptor pool.");
-            return;
+          throw new \InvalidArgumentException(
+            get_class($this) ." is not found in descriptor pool. " .
+            'Only generated classes may derive from Message.');
         }
         foreach ($this->desc->getField() as $field) {
             $setter = $field->getSetter();
@@ -225,15 +226,28 @@
         }
     }
 
-    protected function writeOneof($number, $value)
+    protected function hasOneof($number)
     {
         $field = $this->desc->getFieldByNumber($number);
         $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
         $oneof_name = $oneof->getName();
         $oneof_field = $this->$oneof_name;
-        $oneof_field->setValue($value);
-        $oneof_field->setFieldName($field->getName());
-        $oneof_field->setNumber($number);
+        return $number === $oneof_field->getNumber();
+    }
+
+    protected function writeOneof($number, $value)
+    {
+        $field = $this->desc->getFieldByNumber($number);
+        $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+        $oneof_name = $oneof->getName();
+        if ($value === null) {
+            $this->$oneof_name = new OneofField($oneof);
+        } else {
+            $oneof_field = $this->$oneof_name;
+            $oneof_field->setValue($value);
+            $oneof_field->setFieldName($field->getName());
+            $oneof_field->setNumber($number);
+        }
     }
 
     protected function whichOneof($oneof_name)
@@ -773,10 +787,10 @@
      * @return null.
      * @throws \Exception Invalid data.
      */
-    public function mergeFromJsonString($data)
+    public function mergeFromJsonString($data, $ignore_unknown = false)
     {
         $input = new RawInputStream($data);
-        $this->parseFromJsonStream($input);
+        $this->parseFromJsonStream($input, $ignore_unknown);
     }
 
     /**
@@ -801,6 +815,7 @@
     private function convertJsonValueToProtoValue(
         $value,
         $field,
+        $ignore_unknown,
         $is_map_key = false)
     {
         switch ($field->getType()) {
@@ -849,7 +864,7 @@
                     } elseif (!is_object($value) && !is_array($value)) {
                         throw new GPBDecodeException("Expect message.");
                     }
-                    $submsg->mergeFromJsonArray($value);
+                    $submsg->mergeFromJsonArray($value, $ignore_unknown);
                 }
                 return $submsg;
             case GPBType::ENUM:
@@ -862,9 +877,12 @@
                 $enum_value = $field->getEnumType()->getValueByName($value);
                 if (!is_null($enum_value)) {
                     return $enum_value->getNumber();
+                } else if ($ignore_unknown) {
+                    return $this->defaultValue($field);
+                } else {
+                  throw new GPBDecodeException(
+                          "Enum field only accepts integer or enum value name");
                 }
-                throw new GPBDecodeException(
-                        "Enum field only accepts integer or enum value name");
             case GPBType::STRING:
                 if (is_null($value)) {
                     return $this->defaultValue($field);
@@ -1125,17 +1143,17 @@
         }
     }
 
-    protected function mergeFromJsonArray($array)
+    protected function mergeFromJsonArray($array, $ignore_unknown)
     {
         if (is_a($this, "Google\Protobuf\Any")) {
             $this->clear();
             $this->setTypeUrl($array["@type"]);
             $msg = $this->unpack();
             if (GPBUtil::hasSpecialJsonMapping($msg)) {
-                $msg->mergeFromJsonArray($array["value"]);
+                $msg->mergeFromJsonArray($array["value"], $ignore_unknown);
             } else {
                 unset($array["@type"]);
-                $msg->mergeFromJsonArray($array);
+                $msg->mergeFromJsonArray($array, $ignore_unknown);
             }
             $this->setValue($msg->serializeToString());
             return;
@@ -1171,9 +1189,10 @@
             $fields = $this->getFields();
             foreach($array as $key => $value) {
                 $v = new Value();
-                $v->mergeFromJsonArray($value);
+                $v->mergeFromJsonArray($value, $ignore_unknown);
                 $fields[$key] = $v;
             }
+            return;
         }
         if (is_a($this, "Google\Protobuf\Value")) {
             if (is_bool($array)) {
@@ -1194,7 +1213,7 @@
                     }
                     foreach ($array as $key => $v) {
                         $value = new Value();
-                        $value->mergeFromJsonArray($v);
+                        $value->mergeFromJsonArray($v, $ignore_unknown);
                         $values = $struct_value->getFields();
                         $values[$key]= $value;
                     }
@@ -1207,7 +1226,7 @@
                     }
                     foreach ($array as $v) {
                         $value = new Value();
-                        $value->mergeFromJsonArray($v);
+                        $value->mergeFromJsonArray($v, $ignore_unknown);
                         $values = $list_value->getValues();
                         $values[]= $value;
                     }
@@ -1217,17 +1236,23 @@
             }
             return;
         }
-        $this->mergeFromArrayJsonImpl($array);
+        $this->mergeFromArrayJsonImpl($array, $ignore_unknown);
     }
 
-    private function mergeFromArrayJsonImpl($array)
+    private function mergeFromArrayJsonImpl($array, $ignore_unknown)
     {
         foreach ($array as $key => $value) {
             $field = $this->desc->getFieldByJsonName($key);
             if (is_null($field)) {
                 $field = $this->desc->getFieldByName($key);
                 if (is_null($field)) {
-                    continue;
+                    if ($ignore_unknown) {
+                        continue;
+                    } else {
+                        throw new GPBDecodeException(
+                            $key . ' is unknown.'
+                        );
+                    }
                 }
             }
             if ($field->isMap()) {
@@ -1244,10 +1269,12 @@
                     $proto_key = $this->convertJsonValueToProtoValue(
                         $tmp_key,
                         $key_field,
+                        $ignore_unknown,
                         true);
                     $proto_value = $this->convertJsonValueToProtoValue(
                         $tmp_value,
-                        $value_field);
+                        $value_field,
+                        $ignore_unknown);
                     self::kvUpdateHelper($field, $proto_key, $proto_value);
                 }
             } else if ($field->isRepeated()) {
@@ -1261,14 +1288,16 @@
                     }
                     $proto_value = $this->convertJsonValueToProtoValue(
                         $tmp,
-                        $field);
+                        $field,
+                        $ignore_unknown);
                     self::appendHelper($field, $proto_value);
                 }
             } else {
                 $setter = $field->getSetter();
                 $proto_value = $this->convertJsonValueToProtoValue(
                     $value,
-                    $field);
+                    $field,
+                    $ignore_unknown);
                 if ($field->getType() === GPBType::MESSAGE) {
                     if (is_null($proto_value)) {
                         continue;
@@ -1288,7 +1317,7 @@
     /**
      * @ignore
      */
-    public function parseFromJsonStream($input)
+    public function parseFromJsonStream($input, $ignore_unknown)
     {
         $array = json_decode($input->getData(), true, 512, JSON_BIGINT_AS_STRING);
         if ($this instanceof \Google\Protobuf\ListValue) {
@@ -1304,7 +1333,7 @@
             }
         }
         try {
-            $this->mergeFromJsonArray($array);
+            $this->mergeFromJsonArray($array, $ignore_unknown);
         } catch (\Exception $e) {
             throw new GPBDecodeException($e->getMessage());
         }
@@ -1551,14 +1580,19 @@
      */
     private function existField($field)
     {
-        $oneof_index = $field->getOneofIndex();
-        if ($oneof_index !== -1) {
-            $oneof = $this->desc->getOneofDecl()[$oneof_index];
-            $oneof_name = $oneof->getName();
-            return $this->$oneof_name->getNumber() === $field->getNumber();
+        $getter = $field->getGetter();
+        $hazzer = "has" . substr($getter, 3);
+
+        if (method_exists($this, $hazzer)) {
+          return $this->$hazzer();
+        } else if ($field->getOneofIndex() !== -1) {
+          // For old generated code, which does not have hazzers for oneof
+          // fields.
+          $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+          $oneof_name = $oneof->getName();
+          return $this->$oneof_name->getNumber() === $field->getNumber();
         }
 
-        $getter = $field->getGetter();
         $values = $this->$getter();
         if ($field->isMap()) {
             return count($values) !== 0;
diff --git a/php/src/Google/Protobuf/Internal/MessageOptions.php b/php/src/Google/Protobuf/Internal/MessageOptions.php
index 95bb706a..2f4e3cb 100644
--- a/php/src/Google/Protobuf/Internal/MessageOptions.php
+++ b/php/src/Google/Protobuf/Internal/MessageOptions.php
@@ -34,8 +34,7 @@
      *
      * Generated from protobuf field <code>optional bool message_set_wire_format = 1 [default = false];</code>
      */
-    protected $message_set_wire_format = false;
-    private $has_message_set_wire_format = false;
+    protected $message_set_wire_format = null;
     /**
      * Disables the generation of the standard "descriptor()" accessor, which can
      * conflict with a field of the same name.  This is meant to make migration
@@ -43,8 +42,7 @@
      *
      * Generated from protobuf field <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
      */
-    protected $no_standard_descriptor_accessor = false;
-    private $has_no_standard_descriptor_accessor = false;
+    protected $no_standard_descriptor_accessor = null;
     /**
      * Is this message deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -53,8 +51,7 @@
      *
      * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * Whether the message is an automatically generated map entry type for the
      * maps field.
@@ -77,15 +74,13 @@
      *
      * Generated from protobuf field <code>optional bool map_entry = 7;</code>
      */
-    protected $map_entry = false;
-    private $has_map_entry = false;
+    protected $map_entry = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -168,7 +163,17 @@
      */
     public function getMessageSetWireFormat()
     {
-        return $this->message_set_wire_format;
+        return isset($this->message_set_wire_format) ? $this->message_set_wire_format : false;
+    }
+
+    public function hasMessageSetWireFormat()
+    {
+        return isset($this->message_set_wire_format);
+    }
+
+    public function clearMessageSetWireFormat()
+    {
+        unset($this->message_set_wire_format);
     }
 
     /**
@@ -196,16 +201,10 @@
     {
         GPBUtil::checkBool($var);
         $this->message_set_wire_format = $var;
-        $this->has_message_set_wire_format = true;
 
         return $this;
     }
 
-    public function hasMessageSetWireFormat()
-    {
-        return $this->has_message_set_wire_format;
-    }
-
     /**
      * Disables the generation of the standard "descriptor()" accessor, which can
      * conflict with a field of the same name.  This is meant to make migration
@@ -216,7 +215,17 @@
      */
     public function getNoStandardDescriptorAccessor()
     {
-        return $this->no_standard_descriptor_accessor;
+        return isset($this->no_standard_descriptor_accessor) ? $this->no_standard_descriptor_accessor : false;
+    }
+
+    public function hasNoStandardDescriptorAccessor()
+    {
+        return isset($this->no_standard_descriptor_accessor);
+    }
+
+    public function clearNoStandardDescriptorAccessor()
+    {
+        unset($this->no_standard_descriptor_accessor);
     }
 
     /**
@@ -232,16 +241,10 @@
     {
         GPBUtil::checkBool($var);
         $this->no_standard_descriptor_accessor = $var;
-        $this->has_no_standard_descriptor_accessor = true;
 
         return $this;
     }
 
-    public function hasNoStandardDescriptorAccessor()
-    {
-        return $this->has_no_standard_descriptor_accessor;
-    }
-
     /**
      * Is this message deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
@@ -253,7 +256,17 @@
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -270,16 +283,10 @@
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * Whether the message is an automatically generated map entry type for the
      * maps field.
@@ -305,7 +312,17 @@
      */
     public function getMapEntry()
     {
-        return $this->map_entry;
+        return isset($this->map_entry) ? $this->map_entry : false;
+    }
+
+    public function hasMapEntry()
+    {
+        return isset($this->map_entry);
+    }
+
+    public function clearMapEntry()
+    {
+        unset($this->map_entry);
     }
 
     /**
@@ -336,16 +353,10 @@
     {
         GPBUtil::checkBool($var);
         $this->map_entry = $var;
-        $this->has_map_entry = true;
 
         return $this;
     }
 
-    public function hasMapEntry()
-    {
-        return $this->has_map_entry;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -368,15 +379,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
index f40f20f..96efb02 100644
--- a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
@@ -20,40 +20,34 @@
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Input and output type names.  These are resolved in the same way as
      * FieldDescriptorProto.type_name, but must refer to a message type.
      *
      * Generated from protobuf field <code>optional string input_type = 2;</code>
      */
-    protected $input_type = '';
-    private $has_input_type = false;
+    protected $input_type = null;
     /**
      * Generated from protobuf field <code>optional string output_type = 3;</code>
      */
-    protected $output_type = '';
-    private $has_output_type = false;
+    protected $output_type = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
      */
     protected $options = null;
-    private $has_options = false;
     /**
      * Identifies if client streams multiple client messages
      *
      * Generated from protobuf field <code>optional bool client_streaming = 5 [default = false];</code>
      */
-    protected $client_streaming = false;
-    private $has_client_streaming = false;
+    protected $client_streaming = null;
     /**
      * Identifies if server streams multiple server messages
      *
      * Generated from protobuf field <code>optional bool server_streaming = 6 [default = false];</code>
      */
-    protected $server_streaming = false;
-    private $has_server_streaming = false;
+    protected $server_streaming = null;
 
     /**
      * Constructor.
@@ -84,7 +78,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -96,16 +100,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Input and output type names.  These are resolved in the same way as
      * FieldDescriptorProto.type_name, but must refer to a message type.
@@ -115,7 +113,17 @@
      */
     public function getInputType()
     {
-        return $this->input_type;
+        return isset($this->input_type) ? $this->input_type : '';
+    }
+
+    public function hasInputType()
+    {
+        return isset($this->input_type);
+    }
+
+    public function clearInputType()
+    {
+        unset($this->input_type);
     }
 
     /**
@@ -130,23 +138,27 @@
     {
         GPBUtil::checkString($var, True);
         $this->input_type = $var;
-        $this->has_input_type = true;
 
         return $this;
     }
 
-    public function hasInputType()
-    {
-        return $this->has_input_type;
-    }
-
     /**
      * Generated from protobuf field <code>optional string output_type = 3;</code>
      * @return string
      */
     public function getOutputType()
     {
-        return $this->output_type;
+        return isset($this->output_type) ? $this->output_type : '';
+    }
+
+    public function hasOutputType()
+    {
+        return isset($this->output_type);
+    }
+
+    public function clearOutputType()
+    {
+        unset($this->output_type);
     }
 
     /**
@@ -158,25 +170,29 @@
     {
         GPBUtil::checkString($var, True);
         $this->output_type = $var;
-        $this->has_output_type = true;
 
         return $this;
     }
 
-    public function hasOutputType()
-    {
-        return $this->has_output_type;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
-     * @return \Google\Protobuf\Internal\MethodOptions
+     * @return \Google\Protobuf\Internal\MethodOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
      * @param \Google\Protobuf\Internal\MethodOptions $var
@@ -186,16 +202,10 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MethodOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
     /**
      * Identifies if client streams multiple client messages
      *
@@ -204,7 +214,17 @@
      */
     public function getClientStreaming()
     {
-        return $this->client_streaming;
+        return isset($this->client_streaming) ? $this->client_streaming : false;
+    }
+
+    public function hasClientStreaming()
+    {
+        return isset($this->client_streaming);
+    }
+
+    public function clearClientStreaming()
+    {
+        unset($this->client_streaming);
     }
 
     /**
@@ -218,16 +238,10 @@
     {
         GPBUtil::checkBool($var);
         $this->client_streaming = $var;
-        $this->has_client_streaming = true;
 
         return $this;
     }
 
-    public function hasClientStreaming()
-    {
-        return $this->has_client_streaming;
-    }
-
     /**
      * Identifies if server streams multiple server messages
      *
@@ -236,7 +250,17 @@
      */
     public function getServerStreaming()
     {
-        return $this->server_streaming;
+        return isset($this->server_streaming) ? $this->server_streaming : false;
+    }
+
+    public function hasServerStreaming()
+    {
+        return isset($this->server_streaming);
+    }
+
+    public function clearServerStreaming()
+    {
+        unset($this->server_streaming);
     }
 
     /**
@@ -250,15 +274,9 @@
     {
         GPBUtil::checkBool($var);
         $this->server_streaming = $var;
-        $this->has_server_streaming = true;
 
         return $this;
     }
 
-    public function hasServerStreaming()
-    {
-        return $this->has_server_streaming;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/MethodOptions.php b/php/src/Google/Protobuf/Internal/MethodOptions.php
index 6a4c92d..a4595b7 100644
--- a/php/src/Google/Protobuf/Internal/MethodOptions.php
+++ b/php/src/Google/Protobuf/Internal/MethodOptions.php
@@ -23,20 +23,17 @@
      *
      * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
      */
-    protected $idempotency_level = 0;
-    private $has_idempotency_level = false;
+    protected $idempotency_level = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -70,7 +67,17 @@
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -87,23 +94,27 @@
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
      * @return int
      */
     public function getIdempotencyLevel()
     {
-        return $this->idempotency_level;
+        return isset($this->idempotency_level) ? $this->idempotency_level : 0;
+    }
+
+    public function hasIdempotencyLevel()
+    {
+        return isset($this->idempotency_level);
+    }
+
+    public function clearIdempotencyLevel()
+    {
+        unset($this->idempotency_level);
     }
 
     /**
@@ -113,18 +124,12 @@
      */
     public function setIdempotencyLevel($var)
     {
-        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions_IdempotencyLevel::class);
+        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions\IdempotencyLevel::class);
         $this->idempotency_level = $var;
-        $this->has_idempotency_level = true;
 
         return $this;
     }
 
-    public function hasIdempotencyLevel()
-    {
-        return $this->has_idempotency_level;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -147,15 +152,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
index 413b8e5..3cb9f25 100644
--- a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
@@ -20,13 +20,11 @@
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -49,7 +47,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -61,25 +69,29 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
-     * @return \Google\Protobuf\Internal\OneofOptions
+     * @return \Google\Protobuf\Internal\OneofOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
      * @param \Google\Protobuf\Internal\OneofOptions $var
@@ -89,15 +101,9 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\OneofOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/OneofOptions.php b/php/src/Google/Protobuf/Internal/OneofOptions.php
index 46b516f..8dde8f3 100644
--- a/php/src/Google/Protobuf/Internal/OneofOptions.php
+++ b/php/src/Google/Protobuf/Internal/OneofOptions.php
@@ -21,7 +21,6 @@
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -60,15 +59,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/RepeatedField.php b/php/src/Google/Protobuf/Internal/RepeatedField.php
index ec7a3a6..c0331ff 100644
--- a/php/src/Google/Protobuf/Internal/RepeatedField.php
+++ b/php/src/Google/Protobuf/Internal/RepeatedField.php
@@ -67,7 +67,7 @@
     /**
      * Constructs an instance of RepeatedField.
      *
-     * @param long $type Type of the stored element.
+     * @param integer $type Type of the stored element.
      * @param string $klass Message/Enum class name (message/enum fields only).
      * @ignore
      */
@@ -116,7 +116,7 @@
      *
      * This will also be called for: $ele = $arr[0]
      *
-     * @param long $offset The index of the element to be fetched.
+     * @param integer $offset The index of the element to be fetched.
      * @return object The stored element at given index.
      * @throws \ErrorException Invalid type for index.
      * @throws \ErrorException Non-existing index.
@@ -131,7 +131,7 @@
      *
      * This will also be called for: $arr []= $ele and $arr[0] = ele
      *
-     * @param long $offset The index of the element to be assigned.
+     * @param integer $offset The index of the element to be assigned.
      * @param object $value The element to be assigned.
      * @return void
      * @throws \ErrorException Invalid type for index.
@@ -177,8 +177,7 @@
                 break;
             case GPBType::MESSAGE:
                 if (is_null($value)) {
-                  trigger_error("RepeatedField element cannot be null.",
-                                E_USER_ERROR);
+                    throw new \TypeError("RepeatedField element cannot be null.");
                 }
                 GPBUtil::checkMessage($value, $this->klass);
                 break;
@@ -204,7 +203,7 @@
      *
      * This will also be called for: unset($arr)
      *
-     * @param long $offset The index of the element to be removed.
+     * @param integer $offset The index of the element to be removed.
      * @return void
      * @throws \ErrorException Invalid type for index.
      * @throws \ErrorException The element to be removed is not at the end of the
@@ -227,7 +226,7 @@
      *
      * This will also be called for: isset($arr)
      *
-     * @param long $offset The index of the element to be removed.
+     * @param integer $offset The index of the element to be removed.
      * @return bool True if the element at the given offset exists.
      * @throws \ErrorException Invalid type for index.
      */
diff --git a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
index aaeefbc..c511247 100644
--- a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
@@ -20,18 +20,15 @@
     /**
      * Generated from protobuf field <code>optional string name = 1;</code>
      */
-    protected $name = '';
-    private $has_name = false;
+    protected $name = null;
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
      */
     private $method;
-    private $has_method = false;
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
      */
     protected $options = null;
-    private $has_options = false;
 
     /**
      * Constructor.
@@ -55,7 +52,17 @@
      */
     public function getName()
     {
-        return $this->name;
+        return isset($this->name) ? $this->name : '';
+    }
+
+    public function hasName()
+    {
+        return isset($this->name);
+    }
+
+    public function clearName()
+    {
+        unset($this->name);
     }
 
     /**
@@ -67,16 +74,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -95,25 +96,29 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\MethodDescriptorProto::class);
         $this->method = $arr;
-        $this->has_method = true;
 
         return $this;
     }
 
-    public function hasMethod()
-    {
-        return $this->has_method;
-    }
-
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\ServiceOptions
+     * @return \Google\Protobuf\Internal\ServiceOptions|null
      */
     public function getOptions()
     {
         return $this->options;
     }
 
+    public function hasOptions()
+    {
+        return isset($this->options);
+    }
+
+    public function clearOptions()
+    {
+        unset($this->options);
+    }
+
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
      * @param \Google\Protobuf\Internal\ServiceOptions $var
@@ -123,15 +128,9 @@
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ServiceOptions::class);
         $this->options = $var;
-        $this->has_options = true;
 
         return $this;
     }
 
-    public function hasOptions()
-    {
-        return $this->has_options;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/ServiceOptions.php b/php/src/Google/Protobuf/Internal/ServiceOptions.php
index 0581efb..d15a36a 100644
--- a/php/src/Google/Protobuf/Internal/ServiceOptions.php
+++ b/php/src/Google/Protobuf/Internal/ServiceOptions.php
@@ -23,15 +23,13 @@
      *
      * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
      */
-    protected $deprecated = false;
-    private $has_deprecated = false;
+    protected $deprecated = null;
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
-    private $has_uninterpreted_option = false;
 
     /**
      * Constructor.
@@ -64,7 +62,17 @@
      */
     public function getDeprecated()
     {
-        return $this->deprecated;
+        return isset($this->deprecated) ? $this->deprecated : false;
+    }
+
+    public function hasDeprecated()
+    {
+        return isset($this->deprecated);
+    }
+
+    public function clearDeprecated()
+    {
+        unset($this->deprecated);
     }
 
     /**
@@ -81,16 +89,10 @@
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
-        $this->has_deprecated = true;
 
         return $this;
     }
 
-    public function hasDeprecated()
-    {
-        return $this->has_deprecated;
-    }
-
     /**
      * The parser stores options it doesn't recognize here. See above.
      *
@@ -113,15 +115,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
-        $this->has_uninterpreted_option = true;
 
         return $this;
     }
 
-    public function hasUninterpretedOption()
-    {
-        return $this->has_uninterpreted_option;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
index dfeb69f..1c572e7 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
@@ -64,7 +64,6 @@
      * Generated from protobuf field <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
      */
     private $location;
-    private $has_location = false;
 
     /**
      * Constructor.
@@ -223,15 +222,9 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo\Location::class);
         $this->location = $arr;
-        $this->has_location = true;
 
         return $this;
     }
 
-    public function hasLocation()
-    {
-        return $this->has_location;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
index 0aeea61..c4cc667 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
@@ -41,7 +41,6 @@
      * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
      */
     private $path;
-    private $has_path = false;
     /**
      * Always has exactly three or four elements: start line, start column,
      * end line (optional, otherwise assumed same as start line), end column.
@@ -52,7 +51,6 @@
      * Generated from protobuf field <code>repeated int32 span = 2 [packed = true];</code>
      */
     private $span;
-    private $has_span = false;
     /**
      * If this SourceCodeInfo represents a complete declaration, these are any
      * comments appearing before and after the declaration which appear to be
@@ -93,18 +91,15 @@
      *
      * Generated from protobuf field <code>optional string leading_comments = 3;</code>
      */
-    protected $leading_comments = '';
-    private $has_leading_comments = false;
+    protected $leading_comments = null;
     /**
      * Generated from protobuf field <code>optional string trailing_comments = 4;</code>
      */
-    protected $trailing_comments = '';
-    private $has_trailing_comments = false;
+    protected $trailing_comments = null;
     /**
      * Generated from protobuf field <code>repeated string leading_detached_comments = 6;</code>
      */
     private $leading_detached_comments;
-    private $has_leading_detached_comments = false;
 
     /**
      * Constructor.
@@ -248,16 +243,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->path = $arr;
-        $this->has_path = true;
 
         return $this;
     }
 
-    public function hasPath()
-    {
-        return $this->has_path;
-    }
-
     /**
      * Always has exactly three or four elements: start line, start column,
      * end line (optional, otherwise assumed same as start line), end column.
@@ -288,16 +277,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->span = $arr;
-        $this->has_span = true;
 
         return $this;
     }
 
-    public function hasSpan()
-    {
-        return $this->has_span;
-    }
-
     /**
      * If this SourceCodeInfo represents a complete declaration, these are any
      * comments appearing before and after the declaration which appear to be
@@ -341,7 +324,17 @@
      */
     public function getLeadingComments()
     {
-        return $this->leading_comments;
+        return isset($this->leading_comments) ? $this->leading_comments : '';
+    }
+
+    public function hasLeadingComments()
+    {
+        return isset($this->leading_comments);
+    }
+
+    public function clearLeadingComments()
+    {
+        unset($this->leading_comments);
     }
 
     /**
@@ -390,23 +383,27 @@
     {
         GPBUtil::checkString($var, True);
         $this->leading_comments = $var;
-        $this->has_leading_comments = true;
 
         return $this;
     }
 
-    public function hasLeadingComments()
-    {
-        return $this->has_leading_comments;
-    }
-
     /**
      * Generated from protobuf field <code>optional string trailing_comments = 4;</code>
      * @return string
      */
     public function getTrailingComments()
     {
-        return $this->trailing_comments;
+        return isset($this->trailing_comments) ? $this->trailing_comments : '';
+    }
+
+    public function hasTrailingComments()
+    {
+        return isset($this->trailing_comments);
+    }
+
+    public function clearTrailingComments()
+    {
+        unset($this->trailing_comments);
     }
 
     /**
@@ -418,16 +415,10 @@
     {
         GPBUtil::checkString($var, True);
         $this->trailing_comments = $var;
-        $this->has_trailing_comments = true;
 
         return $this;
     }
 
-    public function hasTrailingComments()
-    {
-        return $this->has_trailing_comments;
-    }
-
     /**
      * Generated from protobuf field <code>repeated string leading_detached_comments = 6;</code>
      * @return \Google\Protobuf\Internal\RepeatedField
@@ -446,16 +437,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->leading_detached_comments = $arr;
-        $this->has_leading_detached_comments = true;
 
         return $this;
     }
 
-    public function hasLeadingDetachedComments()
-    {
-        return $this->has_leading_detached_comments;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.
diff --git a/php/src/Google/Protobuf/Internal/TimestampBase.php b/php/src/Google/Protobuf/Internal/TimestampBase.php
new file mode 100644
index 0000000..653d1e9
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/TimestampBase.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Google\Protobuf\Internal;
+
+/**
+ * Base class for Google\Protobuf\Timestamp, this contains hand-written
+ * convenience methods.
+ */
+class TimestampBase extends \Google\Protobuf\Internal\Message
+{
+    /*
+     * Converts PHP DateTime to Timestamp.
+     *
+     * @param \DateTime $datetime
+     */
+    public function fromDateTime(\DateTime $datetime)
+    {
+        $this->seconds = $datetime->getTimestamp();
+        $this->nanos = 1000 * $datetime->format('u');
+    }
+
+    /**
+     * Converts Timestamp to PHP DateTime.
+     *
+     * @return \DateTime $datetime
+     */
+    public function toDateTime()
+    {
+        $time = sprintf('%s.%06d', $this->seconds, $this->nanos / 1000);
+        return \DateTime::createFromFormat('U.u', $time);
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption.php b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
index 6c871cc..a2aae3e 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
@@ -26,40 +26,33 @@
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
      */
     private $name;
-    private $has_name = false;
     /**
      * The value of the uninterpreted option, in whatever type the tokenizer
      * identified it as during parsing. Exactly one of these should be set.
      *
      * Generated from protobuf field <code>optional string identifier_value = 3;</code>
      */
-    protected $identifier_value = '';
-    private $has_identifier_value = false;
+    protected $identifier_value = null;
     /**
      * Generated from protobuf field <code>optional uint64 positive_int_value = 4;</code>
      */
-    protected $positive_int_value = 0;
-    private $has_positive_int_value = false;
+    protected $positive_int_value = null;
     /**
      * Generated from protobuf field <code>optional int64 negative_int_value = 5;</code>
      */
-    protected $negative_int_value = 0;
-    private $has_negative_int_value = false;
+    protected $negative_int_value = null;
     /**
      * Generated from protobuf field <code>optional double double_value = 6;</code>
      */
-    protected $double_value = 0.0;
-    private $has_double_value = false;
+    protected $double_value = null;
     /**
      * Generated from protobuf field <code>optional bytes string_value = 7;</code>
      */
-    protected $string_value = '';
-    private $has_string_value = false;
+    protected $string_value = null;
     /**
      * Generated from protobuf field <code>optional string aggregate_value = 8;</code>
      */
-    protected $aggregate_value = '';
-    private $has_aggregate_value = false;
+    protected $aggregate_value = null;
 
     /**
      * Constructor.
@@ -101,16 +94,10 @@
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption\NamePart::class);
         $this->name = $arr;
-        $this->has_name = true;
 
         return $this;
     }
 
-    public function hasName()
-    {
-        return $this->has_name;
-    }
-
     /**
      * The value of the uninterpreted option, in whatever type the tokenizer
      * identified it as during parsing. Exactly one of these should be set.
@@ -120,7 +107,17 @@
      */
     public function getIdentifierValue()
     {
-        return $this->identifier_value;
+        return isset($this->identifier_value) ? $this->identifier_value : '';
+    }
+
+    public function hasIdentifierValue()
+    {
+        return isset($this->identifier_value);
+    }
+
+    public function clearIdentifierValue()
+    {
+        unset($this->identifier_value);
     }
 
     /**
@@ -135,23 +132,27 @@
     {
         GPBUtil::checkString($var, True);
         $this->identifier_value = $var;
-        $this->has_identifier_value = true;
 
         return $this;
     }
 
-    public function hasIdentifierValue()
-    {
-        return $this->has_identifier_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional uint64 positive_int_value = 4;</code>
      * @return int|string
      */
     public function getPositiveIntValue()
     {
-        return $this->positive_int_value;
+        return isset($this->positive_int_value) ? $this->positive_int_value : 0;
+    }
+
+    public function hasPositiveIntValue()
+    {
+        return isset($this->positive_int_value);
+    }
+
+    public function clearPositiveIntValue()
+    {
+        unset($this->positive_int_value);
     }
 
     /**
@@ -163,23 +164,27 @@
     {
         GPBUtil::checkUint64($var);
         $this->positive_int_value = $var;
-        $this->has_positive_int_value = true;
 
         return $this;
     }
 
-    public function hasPositiveIntValue()
-    {
-        return $this->has_positive_int_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional int64 negative_int_value = 5;</code>
      * @return int|string
      */
     public function getNegativeIntValue()
     {
-        return $this->negative_int_value;
+        return isset($this->negative_int_value) ? $this->negative_int_value : 0;
+    }
+
+    public function hasNegativeIntValue()
+    {
+        return isset($this->negative_int_value);
+    }
+
+    public function clearNegativeIntValue()
+    {
+        unset($this->negative_int_value);
     }
 
     /**
@@ -191,23 +196,27 @@
     {
         GPBUtil::checkInt64($var);
         $this->negative_int_value = $var;
-        $this->has_negative_int_value = true;
 
         return $this;
     }
 
-    public function hasNegativeIntValue()
-    {
-        return $this->has_negative_int_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional double double_value = 6;</code>
      * @return float
      */
     public function getDoubleValue()
     {
-        return $this->double_value;
+        return isset($this->double_value) ? $this->double_value : 0.0;
+    }
+
+    public function hasDoubleValue()
+    {
+        return isset($this->double_value);
+    }
+
+    public function clearDoubleValue()
+    {
+        unset($this->double_value);
     }
 
     /**
@@ -219,23 +228,27 @@
     {
         GPBUtil::checkDouble($var);
         $this->double_value = $var;
-        $this->has_double_value = true;
 
         return $this;
     }
 
-    public function hasDoubleValue()
-    {
-        return $this->has_double_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional bytes string_value = 7;</code>
      * @return string
      */
     public function getStringValue()
     {
-        return $this->string_value;
+        return isset($this->string_value) ? $this->string_value : '';
+    }
+
+    public function hasStringValue()
+    {
+        return isset($this->string_value);
+    }
+
+    public function clearStringValue()
+    {
+        unset($this->string_value);
     }
 
     /**
@@ -247,23 +260,27 @@
     {
         GPBUtil::checkString($var, False);
         $this->string_value = $var;
-        $this->has_string_value = true;
 
         return $this;
     }
 
-    public function hasStringValue()
-    {
-        return $this->has_string_value;
-    }
-
     /**
      * Generated from protobuf field <code>optional string aggregate_value = 8;</code>
      * @return string
      */
     public function getAggregateValue()
     {
-        return $this->aggregate_value;
+        return isset($this->aggregate_value) ? $this->aggregate_value : '';
+    }
+
+    public function hasAggregateValue()
+    {
+        return isset($this->aggregate_value);
+    }
+
+    public function clearAggregateValue()
+    {
+        unset($this->aggregate_value);
     }
 
     /**
@@ -275,15 +292,9 @@
     {
         GPBUtil::checkString($var, True);
         $this->aggregate_value = $var;
-        $this->has_aggregate_value = true;
 
         return $this;
     }
 
-    public function hasAggregateValue()
-    {
-        return $this->has_aggregate_value;
-    }
-
 }
 
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
index 1956ba7..6212d1e 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
@@ -24,13 +24,11 @@
     /**
      * Generated from protobuf field <code>required string name_part = 1;</code>
      */
-    protected $name_part = '';
-    private $has_name_part = false;
+    protected $name_part = null;
     /**
      * Generated from protobuf field <code>required bool is_extension = 2;</code>
      */
-    protected $is_extension = false;
-    private $has_is_extension = false;
+    protected $is_extension = null;
 
     /**
      * Constructor.
@@ -53,7 +51,17 @@
      */
     public function getNamePart()
     {
-        return $this->name_part;
+        return isset($this->name_part) ? $this->name_part : '';
+    }
+
+    public function hasNamePart()
+    {
+        return isset($this->name_part);
+    }
+
+    public function clearNamePart()
+    {
+        unset($this->name_part);
     }
 
     /**
@@ -65,23 +73,27 @@
     {
         GPBUtil::checkString($var, True);
         $this->name_part = $var;
-        $this->has_name_part = true;
 
         return $this;
     }
 
-    public function hasNamePart()
-    {
-        return $this->has_name_part;
-    }
-
     /**
      * Generated from protobuf field <code>required bool is_extension = 2;</code>
      * @return bool
      */
     public function getIsExtension()
     {
-        return $this->is_extension;
+        return isset($this->is_extension) ? $this->is_extension : false;
+    }
+
+    public function hasIsExtension()
+    {
+        return isset($this->is_extension);
+    }
+
+    public function clearIsExtension()
+    {
+        unset($this->is_extension);
     }
 
     /**
@@ -93,16 +105,10 @@
     {
         GPBUtil::checkBool($var);
         $this->is_extension = $var;
-        $this->has_is_extension = true;
 
         return $this;
     }
 
-    public function hasIsExtension()
-    {
-        return $this->has_is_extension;
-    }
-
 }
 
 // Adding a class alias for backwards compatibility with the previous class name.
diff --git a/php/src/Google/Protobuf/Method.php b/php/src/Google/Protobuf/Method.php
index 8e80350..2755baa 100644
--- a/php/src/Google/Protobuf/Method.php
+++ b/php/src/Google/Protobuf/Method.php
@@ -20,31 +20,31 @@
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * A URL of the input message type.
      *
      * Generated from protobuf field <code>string request_type_url = 2;</code>
      */
-    private $request_type_url = '';
+    protected $request_type_url = '';
     /**
      * If true, the request is streamed.
      *
      * Generated from protobuf field <code>bool request_streaming = 3;</code>
      */
-    private $request_streaming = false;
+    protected $request_streaming = false;
     /**
      * The URL of the output message type.
      *
      * Generated from protobuf field <code>string response_type_url = 4;</code>
      */
-    private $response_type_url = '';
+    protected $response_type_url = '';
     /**
      * If true, the response is streamed.
      *
      * Generated from protobuf field <code>bool response_streaming = 5;</code>
      */
-    private $response_streaming = false;
+    protected $response_streaming = false;
     /**
      * Any metadata attached to the method.
      *
@@ -56,7 +56,7 @@
      *
      * Generated from protobuf field <code>.google.protobuf.Syntax syntax = 7;</code>
      */
-    private $syntax = 0;
+    protected $syntax = 0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Mixin.php b/php/src/Google/Protobuf/Mixin.php
index a2ea59c..4f7bf84 100644
--- a/php/src/Google/Protobuf/Mixin.php
+++ b/php/src/Google/Protobuf/Mixin.php
@@ -46,7 +46,7 @@
  * The mixin construct implies that all methods in `AccessControl` are
  * also declared with same name and request/response types in
  * `Storage`. A documentation generator or annotation processor will
- * see the effective `Storage.GetAcl` method after inherting
+ * see the effective `Storage.GetAcl` method after inheriting
  * documentation and annotations as follows:
  *     service Storage {
  *       // Get the underlying ACL object.
@@ -81,14 +81,14 @@
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * If non-empty specifies a path under which inherited HTTP paths
      * are rooted.
      *
      * Generated from protobuf field <code>string root = 2;</code>
      */
-    private $root = '';
+    protected $root = '';
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/NullValue.php b/php/src/Google/Protobuf/NullValue.php
index a72cbb2..61569f8 100644
--- a/php/src/Google/Protobuf/NullValue.php
+++ b/php/src/Google/Protobuf/NullValue.php
@@ -35,6 +35,7 @@
         return self::$valueToName[$value];
     }
 
+
     public static function value($name)
     {
         $const = __CLASS__ . '::' . strtoupper($name);
diff --git a/php/src/Google/Protobuf/OneofDescriptor.php b/php/src/Google/Protobuf/OneofDescriptor.php
index d973663..92b4e27 100644
--- a/php/src/Google/Protobuf/OneofDescriptor.php
+++ b/php/src/Google/Protobuf/OneofDescriptor.php
@@ -72,4 +72,9 @@
     {
         return count($this->internal_desc->getFields());
     }
+
+    public function isSynthetic()
+    {
+      return $this->internal_desc->isSynthetic();
+    }
 }
diff --git a/php/src/Google/Protobuf/Option.php b/php/src/Google/Protobuf/Option.php
index 22ecfc5..31249e5 100644
--- a/php/src/Google/Protobuf/Option.php
+++ b/php/src/Google/Protobuf/Option.php
@@ -24,7 +24,7 @@
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * The option's value packed in an Any message. If the value is a primitive,
      * the corresponding wrapper type defined in google/protobuf/wrappers.proto
@@ -33,7 +33,7 @@
      *
      * Generated from protobuf field <code>.google.protobuf.Any value = 2;</code>
      */
-    private $value = null;
+    protected $value = null;
 
     /**
      * Constructor.
@@ -97,13 +97,23 @@
      * value using the google.protobuf.Int32Value type.
      *
      * Generated from protobuf field <code>.google.protobuf.Any value = 2;</code>
-     * @return \Google\Protobuf\Any
+     * @return \Google\Protobuf\Any|null
      */
     public function getValue()
     {
         return $this->value;
     }
 
+    public function hasValue()
+    {
+        return isset($this->value);
+    }
+
+    public function clearValue()
+    {
+        unset($this->value);
+    }
+
     /**
      * The option's value packed in an Any message. If the value is a primitive,
      * the corresponding wrapper type defined in google/protobuf/wrappers.proto
diff --git a/php/src/Google/Protobuf/SourceContext.php b/php/src/Google/Protobuf/SourceContext.php
index cbc50c6..8b3ea11 100644
--- a/php/src/Google/Protobuf/SourceContext.php
+++ b/php/src/Google/Protobuf/SourceContext.php
@@ -22,7 +22,7 @@
      *
      * Generated from protobuf field <code>string file_name = 1;</code>
      */
-    private $file_name = '';
+    protected $file_name = '';
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/StringValue.php b/php/src/Google/Protobuf/StringValue.php
index 8fb354f..ad98316 100644
--- a/php/src/Google/Protobuf/StringValue.php
+++ b/php/src/Google/Protobuf/StringValue.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>string value = 1;</code>
      */
-    private $value = '';
+    protected $value = '';
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Syntax.php b/php/src/Google/Protobuf/Syntax.php
index 9812669..10952bf 100644
--- a/php/src/Google/Protobuf/Syntax.php
+++ b/php/src/Google/Protobuf/Syntax.php
@@ -40,6 +40,7 @@
         return self::$valueToName[$value];
     }
 
+
     public static function value($name)
     {
         $const = __CLASS__ . '::' . strtoupper($name);
diff --git a/php/src/Google/Protobuf/Timestamp.php b/php/src/Google/Protobuf/Timestamp.php
index 6d26f6c..a12f485 100644
--- a/php/src/Google/Protobuf/Timestamp.php
+++ b/php/src/Google/Protobuf/Timestamp.php
@@ -9,17 +9,17 @@
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * A Timestamp represents a point in time independent of any time zone
- * or calendar, represented as seconds and fractions of seconds at
- * nanosecond resolution in UTC Epoch time. It is encoded using the
- * Proleptic Gregorian Calendar which extends the Gregorian calendar
- * backwards to year one. It is encoded assuming all minutes are 60
- * seconds long, i.e. leap seconds are "smeared" so that no leap second
- * table is needed for interpretation. Range is from
- * 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
- * By restricting to that range, we ensure that we can convert to
- * and from  RFC 3339 date strings.
- * See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+ * A Timestamp represents a point in time independent of any time zone or local
+ * calendar, encoded as a count of seconds and fractions of seconds at
+ * nanosecond resolution. The count is relative to an epoch at UTC midnight on
+ * January 1, 1970, in the proleptic Gregorian calendar which extends the
+ * Gregorian calendar backwards to year one.
+ * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
+ * second table is needed for interpretation, using a [24-hour linear
+ * smear](https://developers.google.com/time/smear).
+ * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
+ * restricting to that range, we ensure that we can convert to and from [RFC
+ * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
  * # Examples
  * Example 1: Compute Timestamp from POSIX `time()`.
  *     Timestamp timestamp;
@@ -44,7 +44,12 @@
  *     long millis = System.currentTimeMillis();
  *     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
  *         .setNanos((int) ((millis % 1000) * 1000000)).build();
- * Example 5: Compute Timestamp from current time in Python.
+ * Example 5: Compute Timestamp from Java `Instant.now()`.
+ *     Instant now = Instant.now();
+ *     Timestamp timestamp =
+ *         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
+ *             .setNanos(now.getNano()).build();
+ * Example 6: Compute Timestamp from current time in Python.
  *     timestamp = Timestamp()
  *     timestamp.GetCurrentTime()
  * # JSON Mapping
@@ -61,17 +66,19 @@
  * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
  * 01:30 UTC on January 15, 2017.
  * In JavaScript, one can convert a Date object to this format using the
- * standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
+ * standard
+ * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
  * method. In Python, a standard `datetime.datetime` object can be converted
- * to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
- * with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
- * can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
- * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
+ * to this format using
+ * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
+ * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
+ * the Joda Time's [`ISODateTimeFormat.dateTime()`](
+ * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
  * ) to obtain a formatter capable of generating timestamps in this format.
  *
  * Generated from protobuf message <code>google.protobuf.Timestamp</code>
  */
-class Timestamp extends \Google\Protobuf\Internal\Message
+class Timestamp extends \Google\Protobuf\Internal\TimestampBase
 {
     /**
      * Represents seconds of UTC time since Unix epoch
@@ -80,7 +87,7 @@
      *
      * Generated from protobuf field <code>int64 seconds = 1;</code>
      */
-    private $seconds = 0;
+    protected $seconds = 0;
     /**
      * Non-negative fractions of a second at nanosecond resolution. Negative
      * second values with fractions must still have non-negative nanos values
@@ -89,7 +96,7 @@
      *
      * Generated from protobuf field <code>int32 nanos = 2;</code>
      */
-    private $nanos = 0;
+    protected $nanos = 0;
 
     /**
      * Constructor.
@@ -175,26 +182,5 @@
         return $this;
     }
 
-    /*
-     * Converts PHP DateTime to Timestamp.
-     *
-     * @param \DateTime $datetime
-     */
-    public function fromDateTime(\DateTime $datetime)
-    {
-        $this->seconds = $datetime->getTimestamp();
-        $this->nanos = 1000 * $datetime->format('u');
-    }
-
-    /**
-     * Converts Timestamp to PHP DateTime.
-     *
-     * @return \DateTime $datetime
-     */
-    public function toDateTime()
-    {
-        $time = sprintf('%s.%06d', $this->seconds, $this->nanos / 1000);
-        return \DateTime::createFromFormat('U.u', $time);
-    }
 }
 
diff --git a/php/src/Google/Protobuf/Type.php b/php/src/Google/Protobuf/Type.php
index 1b47811..41b9e36 100644
--- a/php/src/Google/Protobuf/Type.php
+++ b/php/src/Google/Protobuf/Type.php
@@ -20,7 +20,7 @@
      *
      * Generated from protobuf field <code>string name = 1;</code>
      */
-    private $name = '';
+    protected $name = '';
     /**
      * The list of fields.
      *
@@ -44,13 +44,13 @@
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
      */
-    private $source_context = null;
+    protected $source_context = null;
     /**
      * The source syntax.
      *
      * Generated from protobuf field <code>.google.protobuf.Syntax syntax = 6;</code>
      */
-    private $syntax = 0;
+    protected $syntax = 0;
 
     /**
      * Constructor.
@@ -185,13 +185,23 @@
      * The source context.
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
-     * @return \Google\Protobuf\SourceContext
+     * @return \Google\Protobuf\SourceContext|null
      */
     public function getSourceContext()
     {
         return $this->source_context;
     }
 
+    public function hasSourceContext()
+    {
+        return isset($this->source_context);
+    }
+
+    public function clearSourceContext()
+    {
+        unset($this->source_context);
+    }
+
     /**
      * The source context.
      *
diff --git a/php/src/Google/Protobuf/UInt32Value.php b/php/src/Google/Protobuf/UInt32Value.php
index f5a522d..ae5fc5b 100644
--- a/php/src/Google/Protobuf/UInt32Value.php
+++ b/php/src/Google/Protobuf/UInt32Value.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>uint32 value = 1;</code>
      */
-    private $value = 0;
+    protected $value = 0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/UInt64Value.php b/php/src/Google/Protobuf/UInt64Value.php
index 89e69cd..aa96867 100644
--- a/php/src/Google/Protobuf/UInt64Value.php
+++ b/php/src/Google/Protobuf/UInt64Value.php
@@ -21,7 +21,7 @@
      *
      * Generated from protobuf field <code>uint64 value = 1;</code>
      */
-    private $value = 0;
+    protected $value = 0;
 
     /**
      * Constructor.
diff --git a/php/src/Google/Protobuf/Value.php b/php/src/Google/Protobuf/Value.php
index 5c1e864..7bebb99 100644
--- a/php/src/Google/Protobuf/Value.php
+++ b/php/src/Google/Protobuf/Value.php
@@ -57,6 +57,11 @@
         return $this->readOneof(1);
     }
 
+    public function hasNullValue()
+    {
+        return $this->hasOneof(1);
+    }
+
     /**
      * Represents a null value.
      *
@@ -83,6 +88,11 @@
         return $this->readOneof(2);
     }
 
+    public function hasNumberValue()
+    {
+        return $this->hasOneof(2);
+    }
+
     /**
      * Represents a double value.
      *
@@ -109,6 +119,11 @@
         return $this->readOneof(3);
     }
 
+    public function hasStringValue()
+    {
+        return $this->hasOneof(3);
+    }
+
     /**
      * Represents a string value.
      *
@@ -135,6 +150,11 @@
         return $this->readOneof(4);
     }
 
+    public function hasBoolValue()
+    {
+        return $this->hasOneof(4);
+    }
+
     /**
      * Represents a boolean value.
      *
@@ -154,13 +174,18 @@
      * Represents a structured value.
      *
      * Generated from protobuf field <code>.google.protobuf.Struct struct_value = 5;</code>
-     * @return \Google\Protobuf\Struct
+     * @return \Google\Protobuf\Struct|null
      */
     public function getStructValue()
     {
         return $this->readOneof(5);
     }
 
+    public function hasStructValue()
+    {
+        return $this->hasOneof(5);
+    }
+
     /**
      * Represents a structured value.
      *
@@ -180,13 +205,18 @@
      * Represents a repeated `Value`.
      *
      * Generated from protobuf field <code>.google.protobuf.ListValue list_value = 6;</code>
-     * @return \Google\Protobuf\ListValue
+     * @return \Google\Protobuf\ListValue|null
      */
     public function getListValue()
     {
         return $this->readOneof(6);
     }
 
+    public function hasListValue()
+    {
+        return $this->hasOneof(6);
+    }
+
     /**
      * Represents a repeated `Value`.
      *
diff --git a/php/tests/array_test.php b/php/tests/ArrayTest.php
similarity index 83%
rename from php/tests/array_test.php
rename to php/tests/ArrayTest.php
index b251404..9e8fcb8 100644
--- a/php/tests/array_test.php
+++ b/php/tests/ArrayTest.php
@@ -1,5 +1,6 @@
 <?php
 
+require_once('test_base.php');
 require_once('test_util.php');
 
 use Google\Protobuf\Internal\RepeatedField;
@@ -7,7 +8,7 @@
 use Foo\TestMessage;
 use Foo\TestMessage\Sub;
 
-class RepeatedFieldTest extends \PHPUnit\Framework\TestCase
+class ArrayTest extends TestBase
 {
 
     #########################################################
@@ -296,15 +297,15 @@
 
         // Test append.
         $arr[] = 1;
-        $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF);
 
         $arr[] = 1.1;
-        $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF);
 
         $arr[] = '2';
-        $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF);
         $arr[] = '3.1';
-        $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF);
 
         $this->assertEquals(4, count($arr));
 
@@ -315,15 +316,15 @@
 
         // Test set.
         $arr[0] = 1;
-        $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF);
 
         $arr[1] = 1.1;
-        $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF);
 
         $arr[2] = '2';
-        $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF);
         $arr[3] = '3.1';
-        $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF);
     }
 
     #########################################################
@@ -336,15 +337,15 @@
 
         // Test append.
         $arr[] = 1;
-        $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF);
 
         $arr[] = 1.1;
-        $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF);
 
         $arr[] = '2';
-        $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF);
         $arr[] = '3.1';
-        $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF);
 
         $this->assertEquals(4, count($arr));
 
@@ -355,15 +356,15 @@
 
         // Test set.
         $arr[0] = 1;
-        $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF);
 
         $arr[1] = 1.1;
-        $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF);
 
         $arr[2] = '2';
-        $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF);
         $arr[3] = '3.1';
-        $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF);
     }
 
     #########################################################
@@ -566,6 +567,8 @@
             $sub = new Sub(['a' => $sub]);
         }
         $m->setRepeatedMessage($subs);
+
+        $this->assertTrue(true);
     }
 
     #########################################################
@@ -574,6 +577,14 @@
 
     public function testCycleLeak()
     {
+        if (getenv("USE_ZEND_ALLOC") === "0") {
+            // If we are disabling Zend's internal allocator (as we do for
+            // Valgrind tests, for example) then memory_get_usage() will not
+            // return a useful value.
+            $this->markTestSkipped();
+            return;
+        }
+
         gc_collect_cycles();
         $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
         $arr[] = new TestMessage;
@@ -590,4 +601,58 @@
         $end = memory_get_usage();
         $this->assertLessThan($start, $end);
     }
+
+    #########################################################
+    # Test incorrect types
+    #########################################################
+
+    public function testAppendNull()
+    {
+        $this->expectException(TypeError::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
+        $arr[] = null;
+    }
+
+    #########################################################
+    # Test equality
+    #########################################################
+
+    public function testEquality()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr2 = new RepeatedField(GPBType::INT32);
+
+        $this->assertTrue($arr == $arr2);
+
+        $arr[] = 0;
+        $arr[] = 1;
+        $arr[] = 2;
+
+        $this->assertFalse($arr == $arr2);
+
+        $arr2[] = 0;
+        $arr2[] = 1;
+        $arr2[] = 2;
+
+        $this->assertTrue($arr == $arr2);
+
+        // Arrays of different types always compare false.
+        $this->assertFalse(new RepeatedField(GPBType::INT32) ==
+                           new RepeatedField(GPBType::INT64));
+        $this->assertFalse(
+            new RepeatedField(GPBType::MESSAGE, TestMessage::class) ==
+            new RepeatedField(GPBType::MESSAGE, Sub::class));
+    }
+
+    #########################################################
+    # Test clone
+    #########################################################
+
+    public function testClone()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
+        $arr[] = new TestMessage;
+        $arr2 = clone $arr;
+        $this->assertSame($arr[0], $arr2[0]);
+    }
 }
diff --git a/php/tests/descriptors_test.php b/php/tests/DescriptorsTest.php
similarity index 96%
rename from php/tests/descriptors_test.php
rename to php/tests/DescriptorsTest.php
index 60a6292..4f17a49 100644
--- a/php/tests/descriptors_test.php
+++ b/php/tests/DescriptorsTest.php
@@ -1,7 +1,5 @@
 <?php
 
-require_once('generated/Descriptors/TestDescriptorsEnum.php');
-require_once('generated/Descriptors/TestDescriptorsMessage.php');
 require_once('test_base.php');
 require_once('test_util.php');
 
@@ -108,7 +106,7 @@
 
     public function testEnumDescriptor()
     {
-        // WARNINIG - we need to do this so that TestDescriptorsEnum is registered!!?
+        // WARNING - we need to do this so that TestDescriptorsEnum is registered!!?
         new TestDescriptorsMessage();
 
         $pool = DescriptorPool::getGeneratedPool();
@@ -205,22 +203,20 @@
         $this->assertSame(self::GPBTYPE_ENUM, $mapDesc->getField(1)->getType());
     }
 
-    /**
-     * @expectedException \Exception
-     */
     public function testFieldDescriptorEnumException()
     {
+        $this->expectException(Exception::class);
+
         $pool = DescriptorPool::getGeneratedPool();
         $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
         $fieldDesc = $desc->getField(0);
         $fieldDesc->getEnumType();
     }
 
-    /**
-     * @expectedException \Exception
-     */
     public function testFieldDescriptorMessageException()
     {
+        $this->expectException(Exception::class);
+
         $pool = DescriptorPool::getGeneratedPool();
         $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
         $fieldDesc = $desc->getField(0);
diff --git a/php/tests/encode_decode_test.php b/php/tests/EncodeDecodeTest.php
similarity index 92%
rename from php/tests/encode_decode_test.php
rename to php/tests/EncodeDecodeTest.php
index 319e332..ac01ca1 100644
--- a/php/tests/encode_decode_test.php
+++ b/php/tests/EncodeDecodeTest.php
@@ -14,6 +14,7 @@
 use Foo\TestBytesValue;
 use Foo\TestAny;
 use Foo\TestEnum;
+use Foo\TestLargeFieldNumber;
 use Foo\TestMessage;
 use Foo\TestMessage\Sub;
 use Foo\TestPackedMessage;
@@ -44,6 +45,21 @@
         $this->assertEquals(1, $m->getOptionalInt32());
     }
 
+    public function testDecodeJsonUnknown()
+    {
+        $this->expectException(Exception::class);
+
+        $m = new TestMessage();
+        $m->mergeFromJsonString("{\"unknown\":1}");
+    }
+
+    public function testDecodeJsonIgnoreUnknown()
+    {
+        $m = new TestMessage();
+        $m->mergeFromJsonString("{\"unknown\":1}", true);
+        $this->assertEquals("{}", $m->serializeToJsonString());
+    }
+
     public function testDecodeTopLevelBoolValue()
     {
         $m = new BoolValue();
@@ -212,7 +228,7 @@
     public function generateRandomString($length = 10) {
         $randomString = str_repeat("+", $length);
         for ($i = 0; $i < $length; $i++) {
-            $randomString[$i] = rand(0, 255);
+            $randomString[$i] = chr(rand(0, 255));
         }
         return $randomString;
     }
@@ -326,6 +342,42 @@
 
     }
 
+    public function testEncodeDecodeOptional()
+    {
+      $m = new TestMessage();
+      $this->assertFalse($m->hasTrueOptionalInt32());
+      $data = $m->serializeToString();
+      $this->assertSame("", $data);
+
+      $m->setTrueOptionalInt32(0);
+      $this->assertTrue($m->hasTrueOptionalInt32());
+      $data = $m->serializeToString();
+      $this->assertNotSame("", $data);
+
+      $m2 = new TestMessage();
+      $m2->mergeFromString($data);
+      $this->assertTrue($m2->hasTrueOptionalInt32());
+      $this->assertSame(0, $m2->getTrueOptionalInt32());
+    }
+
+    public function testJsonEncodeDecodeOptional()
+    {
+      $m = new TestMessage();
+      $this->assertFalse($m->hasTrueOptionalInt32());
+      $data = $m->serializeToJsonString();
+      $this->assertSame("{}", $data);
+
+      $m->setTrueOptionalInt32(0);
+      $this->assertTrue($m->hasTrueOptionalInt32());
+      $data = $m->serializeToJsonString();
+      $this->assertNotSame("{}", $data);
+
+      $m2 = new TestMessage();
+      $m2->mergeFromJsonString($data);
+      $this->assertTrue($m2->hasTrueOptionalInt32());
+      $this->assertSame(0, $m2->getTrueOptionalInt32());
+    }
+
     public function testJsonEncodeDecodeOneof()
     {
         $m = new TestMessage();
@@ -493,200 +545,187 @@
         $this->assertSame("", $data);
     }
 
-    /**
-     * @expectedException Exception
-     */
+    public function testLargeFieldNumber()
+    {
+        $m = new TestLargeFieldNumber(['large_field_number' => 5]);
+        $data = $m->serializeToString();
+        $m2 = new TestLargeFieldNumber();
+        $m2->mergeFromString($data);
+        $this->assertSame(5, $m2->getLargeFieldNumber());
+    }
+
     public function testDecodeInvalidInt32()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('08'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidSubMessage()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('9A010108'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidInt64()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('10'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidUInt32()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('18'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidUInt64()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('20'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidSInt32()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('28'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidSInt64()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('30'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidFixed32()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('3D'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidFixed64()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('41'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidSFixed32()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('4D'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidSFixed64()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('51'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidFloat()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('5D'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidDouble()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('61'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidBool()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('68'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidStringLengthMiss()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('72'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidStringDataMiss()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('7201'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidBytesLengthMiss()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('7A'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidBytesDataMiss()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('7A01'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidEnum()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('8001'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidMessageLengthMiss()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('8A01'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidMessageDataMiss()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage();
         $m->mergeFromString(hex2bin('8A0101'));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeInvalidPackedMessageLength()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestPackedMessage();
         $m->mergeFromString(hex2bin('D205'));
     }
@@ -884,6 +923,11 @@
         $m->mergeFromJsonString("{\"unknown\":{\"a\":1, \"b\":1},
                                 \"optionalInt32\":1}", true);
         $this->assertSame(1, $m->getOptionalInt32());
+
+        // Test unknown enum value
+        $m = new TestMessage();
+        $m->mergeFromJsonString("{\"optionalEnum\":\"UNKNOWN\"}", true);
+        $this->assertSame(0, $m->getOptionalEnum());
     }
 
     public function testJsonEncode()
@@ -896,6 +940,14 @@
         $this->expectFields($to);
     }
 
+    public function testJsonEncodeNullSubMessage()
+    {
+        $from = new TestMessage();
+        $from->setOptionalMessage(null);
+        $data = $from->serializeToJsonString();
+        $this->assertEquals("{}", $data);
+    }
+
     public function testDecodeDuration()
     {
         $m = new Google\Protobuf\Duration();
@@ -1102,11 +1154,10 @@
         $this->assertSame("0801", bin2hex($m1->getAny()->getValue()));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testDecodeAnyWithUnknownPacked()
     {
+        $this->expectException(Exception::class);
+
         $m = new TestAny();
         $m->mergeFromJsonString(
             "{\"any\":" .
diff --git a/php/tests/generated_class_test.php b/php/tests/GeneratedClassTest.php
similarity index 80%
rename from php/tests/generated_class_test.php
rename to php/tests/GeneratedClassTest.php
index 6af00ef..2b15e42 100644
--- a/php/tests/generated_class_test.php
+++ b/php/tests/GeneratedClassTest.php
@@ -1,7 +1,5 @@
 <?php
 
-require_once('generated/NoNamespaceEnum.php');
-require_once('generated/NoNamespaceMessage.php');
 require_once('test_base.php');
 require_once('test_util.php');
 
@@ -24,6 +22,13 @@
 use PBEmpty\PBEcho\TestEmptyPackage;
 use Php\Test\TestNamespace;
 
+# This is not allowed, but we at least shouldn't crash.
+class C extends \Google\Protobuf\Internal\Message {
+    public function __construct($data = null) {
+        parent::__construct($data);
+    }
+}
+
 class GeneratedClassTest extends TestBase
 {
 
@@ -72,6 +77,55 @@
     }
 
     #########################################################
+    # Test deprecated int32 field.
+    #########################################################
+
+    public function testDeprecatedInt32Field()
+    {
+        $m = new TestMessage();
+
+        // temporarily change error handler to capture the deprecated errors
+        $deprecationCount = 0;
+        set_error_handler(function ($errno, $errstr) use (&$deprecationCount) {
+            if ($errstr === 'deprecated_optional_int32 is deprecated.') {
+                $deprecationCount++;
+            }
+        }, E_USER_DEPRECATED);
+
+        // default test set
+        $m->setDeprecatedOptionalInt32(MAX_INT32);
+        $this->assertSame(MAX_INT32, $m->getDeprecatedOptionalInt32());
+        $m->setDeprecatedOptionalInt32(MIN_INT32);
+        $this->assertSame(MIN_INT32, $m->getDeprecatedOptionalInt32());
+
+        restore_error_handler();
+
+        $this->assertSame(4, $deprecationCount);
+    }
+
+    #########################################################
+    # Test optional int32 field.
+    #########################################################
+
+    public function testOptionalInt32Field()
+    {
+        $m = new TestMessage();
+
+        $this->assertFalse($m->hasTrueOptionalInt32());
+        $this->assertSame(0, $m->getTrueOptionalInt32());
+
+        // Set integer.
+        $m->setTrueOptionalInt32(MAX_INT32);
+        $this->assertTrue($m->hasTrueOptionalInt32());
+        $this->assertSame(MAX_INT32, $m->getTrueOptionalInt32());
+
+        // Clear integer.
+        $m->clearTrueOptionalInt32();
+        $this->assertFalse($m->hasTrueOptionalInt32());
+        $this->assertSame(0, $m->getTrueOptionalInt32());
+    }
+
+    #########################################################
     # Test uint32 field.
     #########################################################
 
@@ -238,21 +292,21 @@
         $this->assertEquals(1, TestEnum::value('ONE'));
     }
 
-    /**
-     * @expectedException UnexpectedValueException
-     * @expectedExceptionMessage Enum Foo\TestEnum has no name defined for value -1
-     */
     public function testInvalidEnumValueThrowsException()
     {
+        $this->expectException(UnexpectedValueException::class);
+        $this->expectExceptionMessage(
+            'Enum Foo\TestEnum has no name defined for value -1');
+
         TestEnum::name(-1);
     }
 
-    /**
-     * @expectedException UnexpectedValueException
-     * @expectedExceptionMessage Enum Foo\TestEnum has no value defined for name DOES_NOT_EXIST
-     */
     public function testInvalidEnumNameThrowsException()
     {
+        $this->expectException(UnexpectedValueException::class);
+        $this->expectExceptionMessage(
+            'Enum Foo\TestEnum has no value defined for name DOES_NOT_EXIST');
+
         TestEnum::value('DOES_NOT_EXIST');
     }
 
@@ -291,17 +345,17 @@
 
         // Set integer.
         $m->setOptionalFloat(1);
-        $this->assertEquals(1.0, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $m->getOptionalFloat(), MAX_FLOAT_DIFF);
 
         // Set float.
         $m->setOptionalFloat(1.1);
-        $this->assertEquals(1.1, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $m->getOptionalFloat(), MAX_FLOAT_DIFF);
 
         // Set string.
         $m->setOptionalFloat('2');
-        $this->assertEquals(2.0, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $m->getOptionalFloat(), MAX_FLOAT_DIFF);
         $m->setOptionalFloat('3.1');
-        $this->assertEquals(3.1, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $m->getOptionalFloat(), MAX_FLOAT_DIFF);
     }
 
     #########################################################
@@ -314,17 +368,17 @@
 
         // Set integer.
         $m->setOptionalDouble(1);
-        $this->assertEquals(1.0, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $m->getOptionalDouble(), MAX_FLOAT_DIFF);
 
         // Set float.
         $m->setOptionalDouble(1.1);
-        $this->assertEquals(1.1, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $m->getOptionalDouble(), MAX_FLOAT_DIFF);
 
         // Set string.
         $m->setOptionalDouble('2');
-        $this->assertEquals(2.0, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $m->getOptionalDouble(), MAX_FLOAT_DIFF);
         $m->setOptionalDouble('3.1');
-        $this->assertEquals(3.1, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $m->getOptionalDouble(), MAX_FLOAT_DIFF);
     }
 
     #########################################################
@@ -418,14 +472,18 @@
     {
         $m = new TestMessage();
 
+        $this->assertNull($m->getOptionalMessage());
+
         $sub_m = new Sub();
         $sub_m->setA(1);
         $m->setOptionalMessage($sub_m);
         $this->assertSame(1, $m->getOptionalMessage()->getA());
+        $this->assertTrue($m->hasOptionalMessage());
 
         $null = null;
         $m->setOptionalMessage($null);
         $this->assertNull($m->getOptionalMessage());
+        $this->assertFalse($m->hasOptionalMessage());
     }
 
     public function testLegacyMessageField()
@@ -703,10 +761,10 @@
     public function testMessageWithoutNamespace()
     {
         $m = new TestMessage();
-        $n = new NoNameSpaceMessage();
+        $n = new NoNamespaceMessage();
         $m->setOptionalNoNamespaceMessage($n);
         $repeatedNoNamespaceMessage = $m->getRepeatedNoNamespaceMessage();
-        $repeatedNoNamespaceMessage[] = new NoNameSpaceMessage();
+        $repeatedNoNamespaceMessage[] = new NoNamespaceMessage();
         $m->setRepeatedNoNamespaceMessage($repeatedNoNamespaceMessage);
 
         // test nested messages
@@ -719,9 +777,9 @@
     public function testEnumWithoutNamespace()
     {
         $m = new TestMessage();
-        $m->setOptionalNoNamespaceEnum(NoNameSpaceEnum::VALUE_A);
+        $m->setOptionalNoNamespaceEnum(NoNamespaceEnum::VALUE_A);
         $repeatedNoNamespaceEnum = $m->getRepeatedNoNamespaceEnum();
-        $repeatedNoNamespaceEnum[] = NoNameSpaceEnum::VALUE_A;
+        $repeatedNoNamespaceEnum[] = NoNamespaceEnum::VALUE_A;
         $m->setRepeatedNoNamespaceEnum($repeatedNoNamespaceEnum);
         $this->assertTrue(true);
     }
@@ -855,6 +913,8 @@
         $m = new \Lower\PBexit();
         $m = new \Lower\PBextends();
         $m = new \Lower\PBfinal();
+        $m = new \Lower\PBfinally();
+        $m = new \Lower\PBfn();
         $m = new \Lower\PBfor();
         $m = new \Lower\PBforeach();
         $m = new \Lower\PBfunction();
@@ -869,6 +929,7 @@
         $m = new \Lower\PBinterface();
         $m = new \Lower\PBisset();
         $m = new \Lower\PBlist();
+        $m = new \Lower\PBmatch();
         $m = new \Lower\PBnamespace();
         $m = new \Lower\PBnew();
         $m = new \Lower\PBor();
@@ -889,6 +950,7 @@
         $m = new \Lower\PBvar();
         $m = new \Lower\PBwhile();
         $m = new \Lower\PBxor();
+        $m = new \Lower\PByield();
         $m = new \Lower\PBint();
         $m = new \Lower\PBfloat();
         $m = new \Lower\PBbool();
@@ -929,6 +991,8 @@
         $m = new \Upper\PBEXIT();
         $m = new \Upper\PBEXTENDS();
         $m = new \Upper\PBFINAL();
+        $m = new \Upper\PBFINALLY();
+        $m = new \Upper\PBFN();
         $m = new \Upper\PBFOR();
         $m = new \Upper\PBFOREACH();
         $m = new \Upper\PBFUNCTION();
@@ -943,6 +1007,7 @@
         $m = new \Upper\PBINTERFACE();
         $m = new \Upper\PBISSET();
         $m = new \Upper\PBLIST();
+        $m = new \Upper\PBMATCH();
         $m = new \Upper\PBNAMESPACE();
         $m = new \Upper\PBNEW();
         $m = new \Upper\PBOR();
@@ -963,6 +1028,7 @@
         $m = new \Upper\PBVAR();
         $m = new \Upper\PBWHILE();
         $m = new \Upper\PBXOR();
+        $m = new \Upper\PBYIELD();
         $m = new \Upper\PBINT();
         $m = new \Upper\PBFLOAT();
         $m = new \Upper\PBBOOL();
@@ -1003,6 +1069,8 @@
         $m = new \Lower_enum\PBexit();
         $m = new \Lower_enum\PBextends();
         $m = new \Lower_enum\PBfinal();
+        $m = new \Lower_enum\PBfinally();
+        $m = new \Lower_enum\PBfn();
         $m = new \Lower_enum\PBfor();
         $m = new \Lower_enum\PBforeach();
         $m = new \Lower_enum\PBfunction();
@@ -1017,6 +1085,7 @@
         $m = new \Lower_enum\PBinterface();
         $m = new \Lower_enum\PBisset();
         $m = new \Lower_enum\PBlist();
+        $m = new \Lower_enum\PBmatch();
         $m = new \Lower_enum\PBnamespace();
         $m = new \Lower_enum\PBnew();
         $m = new \Lower_enum\PBor();
@@ -1037,6 +1106,7 @@
         $m = new \Lower_enum\PBvar();
         $m = new \Lower_enum\PBwhile();
         $m = new \Lower_enum\PBxor();
+        $m = new \Lower_enum\PByield();
         $m = new \Lower_enum\PBint();
         $m = new \Lower_enum\PBfloat();
         $m = new \Lower_enum\PBbool();
@@ -1077,6 +1147,8 @@
         $m = new \Upper_enum\PBEXIT();
         $m = new \Upper_enum\PBEXTENDS();
         $m = new \Upper_enum\PBFINAL();
+        $m = new \Upper_enum\PBFINALLY();
+        $m = new \Upper_enum\PBFN();
         $m = new \Upper_enum\PBFOR();
         $m = new \Upper_enum\PBFOREACH();
         $m = new \Upper_enum\PBFUNCTION();
@@ -1091,6 +1163,7 @@
         $m = new \Upper_enum\PBINTERFACE();
         $m = new \Upper_enum\PBISSET();
         $m = new \Upper_enum\PBLIST();
+        $m = new \Upper_enum\PBMATCH();
         $m = new \Upper_enum\PBNAMESPACE();
         $m = new \Upper_enum\PBNEW();
         $m = new \Upper_enum\PBOR();
@@ -1111,6 +1184,7 @@
         $m = new \Upper_enum\PBVAR();
         $m = new \Upper_enum\PBWHILE();
         $m = new \Upper_enum\PBXOR();
+        $m = new \Upper_enum\PBYIELD();
         $m = new \Upper_enum\PBINT();
         $m = new \Upper_enum\PBFLOAT();
         $m = new \Upper_enum\PBBOOL();
@@ -1151,6 +1225,8 @@
         $m = \Lower_enum_value\NotAllowed::PBexit;
         $m = \Lower_enum_value\NotAllowed::PBextends;
         $m = \Lower_enum_value\NotAllowed::PBfinal;
+        $m = \Lower_enum_value\NotAllowed::PBfinally;
+        $m = \Lower_enum_value\NotAllowed::PBfn;
         $m = \Lower_enum_value\NotAllowed::PBfor;
         $m = \Lower_enum_value\NotAllowed::PBforeach;
         $m = \Lower_enum_value\NotAllowed::PBfunction;
@@ -1165,6 +1241,7 @@
         $m = \Lower_enum_value\NotAllowed::PBinterface;
         $m = \Lower_enum_value\NotAllowed::PBisset;
         $m = \Lower_enum_value\NotAllowed::PBlist;
+        $m = \Lower_enum_value\NotAllowed::PBmatch;
         $m = \Lower_enum_value\NotAllowed::PBnamespace;
         $m = \Lower_enum_value\NotAllowed::PBnew;
         $m = \Lower_enum_value\NotAllowed::PBor;
@@ -1185,6 +1262,7 @@
         $m = \Lower_enum_value\NotAllowed::PBvar;
         $m = \Lower_enum_value\NotAllowed::PBwhile;
         $m = \Lower_enum_value\NotAllowed::PBxor;
+        $m = \Lower_enum_value\NotAllowed::PByield;
         $m = \Lower_enum_value\NotAllowed::int;
         $m = \Lower_enum_value\NotAllowed::float;
         $m = \Lower_enum_value\NotAllowed::bool;
@@ -1225,6 +1303,8 @@
         $m = \Upper_enum_value\NotAllowed::PBEXIT;
         $m = \Upper_enum_value\NotAllowed::PBEXTENDS;
         $m = \Upper_enum_value\NotAllowed::PBFINAL;
+        $m = \Upper_enum_value\NotAllowed::PBFINALLY;
+        $m = \Upper_enum_value\NotAllowed::PBFN;
         $m = \Upper_enum_value\NotAllowed::PBFOR;
         $m = \Upper_enum_value\NotAllowed::PBFOREACH;
         $m = \Upper_enum_value\NotAllowed::PBFUNCTION;
@@ -1239,6 +1319,7 @@
         $m = \Upper_enum_value\NotAllowed::PBINTERFACE;
         $m = \Upper_enum_value\NotAllowed::PBISSET;
         $m = \Upper_enum_value\NotAllowed::PBLIST;
+        $m = \Upper_enum_value\NotAllowed::PBMATCH;
         $m = \Upper_enum_value\NotAllowed::PBNAMESPACE;
         $m = \Upper_enum_value\NotAllowed::PBNEW;
         $m = \Upper_enum_value\NotAllowed::PBOR;
@@ -1259,6 +1340,7 @@
         $m = \Upper_enum_value\NotAllowed::PBVAR;
         $m = \Upper_enum_value\NotAllowed::PBWHILE;
         $m = \Upper_enum_value\NotAllowed::PBXOR;
+        $m = \Upper_enum_value\NotAllowed::PBYIELD;
         $m = \Upper_enum_value\NotAllowed::INT;
         $m = \Upper_enum_value\NotAllowed::FLOAT;
         $m = \Upper_enum_value\NotAllowed::BOOL;
@@ -1445,6 +1527,8 @@
             }
             $key = new TestMessage($key);
         }
+
+        $this->assertTrue(true);
     }
 
     public function testOneofMessageInArrayConstructor()
@@ -1454,6 +1538,8 @@
         ]);
         $this->assertSame('oneof_message', $m->getMyOneof());
         $this->assertNotNull($m->getOneofMessage());
+
+        $this->assertTrue(true);
     }
 
     public function testOneofStringInArrayConstructor()
@@ -1461,6 +1547,30 @@
         $m = new TestMessage([
             'oneof_string' => 'abc',
         ]);
+
+        $this->assertTrue(true);
+    }
+
+    #########################################################
+    # Test clone.
+    #########################################################
+
+    public function testClone()
+    {
+        $m = new TestMessage([
+            'optional_int32' => -42,
+            'optional_int64' => -43,
+            'optional_message' => new Sub([
+                'a' => 33
+            ]),
+            'map_int32_message' => [1 => new Sub(['a' => 36])],
+        ]);
+        $m2 = clone $m;
+        $this->assertEquals($m->getOptionalInt32(), $m2->getOptionalInt32());
+        $this->assertEquals($m->getOptionalInt64(), $m2->getOptionalInt64());
+        $this->assertSame($m->getOptionalMessage(), $m2->getOptionalMessage());
+        $this->assertSame($m->getMapInt32Message()[1], $m2->getMapInt32Message()[1]);
+        $this->assertEquals($m->serializeToJsonString(), $m2->serializeToJsonString());
     }
 
     #########################################################
@@ -1505,6 +1615,193 @@
         array_walk($values, function (&$value) {});
         $m = new TestMessage();
         $m->setOptionalString($values[0]);
+
+        $this->assertTrue(true);
+    }
+
+    #########################################################
+    # Test equality
+    #########################################################
+
+    public function testShallowEquality()
+    {
+        $m1 = new TestMessage([
+            'optional_int32' => -42,
+            'optional_int64' => -43,
+            'optional_uint32' => 42,
+            'optional_uint64' => 43,
+            'optional_sint32' => -44,
+            'optional_sint64' => -45,
+            'optional_fixed32' => 46,
+            'optional_fixed64' => 47,
+            'optional_sfixed32' => -46,
+            'optional_sfixed64' => -47,
+            'optional_float' => 1.5,
+            'optional_double' => 1.6,
+            'optional_bool' => true,
+            'optional_string' => 'a',
+            'optional_bytes' => 'bbbb',
+            'optional_enum' => TestEnum::ONE,
+            ]);
+        $data = $m1->serializeToString();
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $this->assertTrue($m1 == $m2);
+
+        $m1->setOptionalInt32(1234);
+        $this->assertTrue($m1 != $m2);
+    }
+
+    public function testDeepEquality()
+    {
+        $m1 = new TestMessage([
+            'optional_int32' => -42,
+            'optional_int64' => -43,
+            'optional_uint32' => 42,
+            'optional_uint64' => 43,
+            'optional_sint32' => -44,
+            'optional_sint64' => -45,
+            'optional_fixed32' => 46,
+            'optional_fixed64' => 47,
+            'optional_sfixed32' => -46,
+            'optional_sfixed64' => -47,
+            'optional_float' => 1.5,
+            'optional_double' => 1.6,
+            'optional_bool' => true,
+            'optional_string' => 'a',
+            'optional_bytes' => 'bbbb',
+            'optional_enum' => TestEnum::ONE,
+            'optional_message' => new Sub([
+                'a' => 33
+            ]),
+            'repeated_int32' => [-42, -52],
+            'repeated_int64' => [-43, -53],
+            'repeated_uint32' => [42, 52],
+            'repeated_uint64' => [43, 53],
+            'repeated_sint32' => [-44, -54],
+            'repeated_sint64' => [-45, -55],
+            'repeated_fixed32' => [46, 56],
+            'repeated_fixed64' => [47, 57],
+            'repeated_sfixed32' => [-46, -56],
+            'repeated_sfixed64' => [-47, -57],
+            'repeated_float' => [1.5, 2.5],
+            'repeated_double' => [1.6, 2.6],
+            'repeated_bool' => [true, false],
+            'repeated_string' => ['a', 'c'],
+            'repeated_bytes' => ['bbbb', 'dddd'],
+            'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
+            'repeated_message' => [new Sub(['a' => 34]),
+                                   new Sub(['a' => 35])],
+            'map_int32_int32' => [-62 => -62],
+            'map_int64_int64' => [-63 => -63],
+            'map_uint32_uint32' => [62 => 62],
+            'map_uint64_uint64' => [63 => 63],
+            'map_sint32_sint32' => [-64 => -64],
+            'map_sint64_sint64' => [-65 => -65],
+            'map_fixed32_fixed32' => [66 => 66],
+            'map_fixed64_fixed64' => [67 => 67],
+            'map_sfixed32_sfixed32' => [-68 => -68],
+            'map_sfixed64_sfixed64' => [-69 => -69],
+            'map_int32_float' => [1 => 3.5],
+            'map_int32_double' => [1 => 3.6],
+            'map_bool_bool' => [true => true],
+            'map_string_string' => ['e' => 'e'],
+            'map_int32_bytes' => [1 => 'ffff'],
+            'map_int32_enum' => [1 => TestEnum::ONE],
+            'map_int32_message' => [1 => new Sub(['a' => 36])],
+        ]);
+        $data = $m1->serializeToString();
+
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $this->assertTrue($m1 == $m2);
+
+        # Nested sub-message is checked.
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $m2->getOptionalMessage()->setA(1234);
+        $this->assertTrue($m1 != $m2);
+
+        # Repeated field element is checked.
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $m2->getRepeatedInt32()[0] = 1234;
+        $this->assertTrue($m1 != $m2);
+
+        # Repeated field length is checked.
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $m2->getRepeatedInt32()[] = 1234;
+        $this->assertTrue($m1 != $m2);
+
+        # SubMessage inside repeated field is checked.
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $m2->getRepeatedMessage()[0]->setA(1234);
+        $this->assertTrue($m1 != $m2);
+
+        # Map value is checked.
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $m2->getMapInt32Int32()[-62] = 1234;
+        $this->assertTrue($m1 != $m2);
+
+        # Map size is checked.
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $m2->getMapInt32Int32()[1234] = 1234;
+        $this->assertTrue($m1 != $m2);
+
+        # SubMessage inside map field is checked.
+        $m2 = new TestMessage();
+        $m2->mergeFromString($data);
+        $m2->getMapInt32Message()[1]->setA(1234);
+        $this->assertTrue($m1 != $m2);
+
+        # TODO: what about unknown fields?
+    }
+
+    #########################################################
+    # Test hasOneof<Field> methods exists and working
+    #########################################################
+
+    public function testHasOneof() {
+        $m = new TestMessage();
+        $this->assertFalse($m->hasOneofInt32());
+        $m->setOneofInt32(42);
+        $this->assertTrue($m->hasOneofInt32());
+        $m->setOneofString("bar");
+        $this->assertFalse($m->hasOneofInt32());
+        $this->assertTrue($m->hasOneofString());
+        $m->clear();
+        $this->assertFalse($m->hasOneofInt32());
+        $this->assertFalse($m->hasOneofString());
+
+        $sub_m = new Sub();
+        $sub_m->setA(1);
+        $m->setOneofMessage($sub_m);
+        $this->assertTrue($m->hasOneofMessage());
+        $m->setOneofMessage(null);
+        $this->assertFalse($m->hasOneofMessage());
+    }
+
+    #########################################################
+    # Test that we don't crash if users create their own messages.
+    #########################################################
+
+    public function testUserDefinedClass() {
+        if (getenv("USE_ZEND_ALLOC") === "0") {
+            // We're running a memory test. This test appears to leak in a way
+            // we cannot control, PHP bug?
+            //
+            // TODO: investigate further.
+            $this->markTestSkipped();
+            return;
+        }
+
+        # This is not allowed, but at least we shouldn't crash.
+        $this->expectException(Exception::class);
+        new C();
     }
 
     #########################################################
@@ -1515,18 +1812,41 @@
     {
         throw new Exception('Intended');
     }
-
-    /**
-     * @expectedException Exception
-     */
     public function testNoSegfaultWithError()
     {
+        if (getenv("USE_ZEND_ALLOC") === "0") {
+            // We're running a memory test. This test appears to leak in a way
+            // we cannot control, PHP bug?
+            //
+            // TODO: investigate further.
+            $this->markTestSkipped();
+            return;
+        }
+        $this->expectException(Exception::class);
+
         new TestMessage(['optional_int32' => $this->throwIntendedException()]);
     }
 
     public function testNoExceptionWithVarDump()
     {
         $m = new Sub(['a' => 1]);
-        var_dump($m);
+        /*
+         * This line currently segfaults on macOS with:
+         *
+         *    frame #0: 0x00000001029936cc xdebug.so`xdebug_zend_hash_is_recursive + 4
+         *    frame #1: 0x00000001029a6736 xdebug.so`xdebug_var_export_text_ansi + 1006
+         *    frame #2: 0x00000001029a715d xdebug.so`xdebug_get_zval_value_text_ansi + 273
+         *    frame #3: 0x000000010298a441 xdebug.so`zif_xdebug_var_dump + 297
+         *    frame #4: 0x000000010298d558 xdebug.so`xdebug_execute_internal + 640
+         *    frame #5: 0x000000010046d47f php`ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER + 364
+         *    frame #6: 0x000000010043cabc php`execute_ex + 44
+         *    frame #7: 0x000000010298d151 xdebug.so`xdebug_execute_ex + 1662
+         *    frame #8: 0x000000010046d865 php`ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER + 426
+         *
+         * The value we are passing to var_dump() appears to be corrupt somehow.
+         */
+        /* var_dump($m); */
+
+        $this->assertTrue(true);
     }
 }
diff --git a/php/tests/generated_phpdoc_test.php b/php/tests/GeneratedPhpdocTest.php
similarity index 95%
rename from php/tests/generated_phpdoc_test.php
rename to php/tests/GeneratedPhpdocTest.php
index 526927f..a0b912b 100644
--- a/php/tests/generated_phpdoc_test.php
+++ b/php/tests/GeneratedPhpdocTest.php
@@ -1,7 +1,5 @@
 <?php
 
-require_once('generated/NoNamespaceEnum.php');
-require_once('generated/NoNamespaceMessage.php');
 require_once('test_base.php');
 require_once('test_util.php');
 
@@ -13,15 +11,15 @@
     {
         $class = new ReflectionClass('Foo\TestMessage');
         $doc = $class->getDocComment();
-        $this->assertContains('foo.TestMessage', $doc);
+        $this->assertStringContains('foo.TestMessage', $doc);
     }
 
     public function testPhpDocForConstructor()
     {
         $class = new ReflectionClass('Foo\TestMessage');
         $doc = $class->getMethod('__construct')->getDocComment();
-        $this->assertContains('@param array $data', $doc);
-        $this->assertContains('@type int $optional_int32', $doc);
+        $this->assertStringContains('@param array $data', $doc);
+        $this->assertStringContains('@type int $optional_int32', $doc);
     }
 
     /**
@@ -32,7 +30,7 @@
         $class = new ReflectionClass('Foo\TestMessage');
         foreach ($methods as $method) {
             $doc = $class->getMethod($method)->getDocComment();
-            $this->assertContains($expectedDoc, $doc);
+            $this->assertStringContains($expectedDoc, $doc);
         }
     }
 
@@ -340,6 +338,13 @@
                 ],
                 '@param \NoNamespaceMessage $var'
             ],
+            [
+                [
+                    'setDeprecatedOptionalInt32',
+                    'getDeprecatedOptionalInt32',
+                ],
+                '@deprecated'
+            ],
         ];
     }
 }
diff --git a/php/tests/GeneratedServiceTest.php b/php/tests/GeneratedServiceTest.php
new file mode 100644
index 0000000..be9234c
--- /dev/null
+++ b/php/tests/GeneratedServiceTest.php
@@ -0,0 +1,127 @@
+<?php
+
+require_once('test_base.php');
+require_once('test_util.php');
+
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\MapField;
+use Google\Protobuf\Internal\GPBType;
+use Foo\Greeter;
+use Foo\HelloRequest;
+use Foo\HelloReply;
+
+class GeneratedServiceTest extends TestBase
+{
+    /**
+     * @var \ReflectionClass
+     */
+    private $serviceClass;
+
+    /**
+     * @var \ReflectionClass
+     */
+    private $namespacedServiceClass;
+
+    /**
+     * @var array
+     */
+    private $methodNames = [
+        'sayHello',
+        'sayHelloAgain'
+    ];
+
+    /**
+     * Avoid calling setUp, which has void return type (not avalialbe in php7.0).
+     *
+     * @before
+     */
+    public function setUpTest()
+    {
+        $this->serviceClass = new ReflectionClass('Foo\GreeterInterface');
+
+        $this->namespacedServiceClass = new ReflectionClass('Bar\OtherGreeterInterface');
+    }
+
+    public function testIsInterface()
+    {
+        $this->assertTrue($this->serviceClass->isInterface());
+    }
+
+    public function testPhpDocForClass()
+    {
+        $this->assertStringContains(
+            'foo.Greeter', $this->serviceClass->getDocComment());
+    }
+
+    public function testPhpDocForNamespacedClass()
+    {
+        $this->assertStringContains(
+            'foo.OtherGreeter', $this->namespacedServiceClass->getDocComment());
+    }
+
+    public function testServiceMethodsAreGenerated()
+    {
+        $this->assertCount(
+            count($this->methodNames), $this->serviceClass->getMethods());
+        foreach ($this->methodNames as $methodName) {
+            $this->assertTrue($this->serviceClass->hasMethod($methodName));
+        }
+    }
+
+    public function testPhpDocForServiceMethod()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $docComment =
+                $this->serviceClass->getMethod($methodName)->getDocComment();
+            $this->assertStringContains($methodName, $docComment);
+            $this->assertStringContains(
+                '@param \Foo\HelloRequest $request', $docComment);
+            $this->assertStringContains(
+                '@return \Foo\HelloReply', $docComment);
+        }
+    }
+
+    public function testPhpDocForServiceMethodInNamespacedClass()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $docComment =
+                $this->namespacedServiceClass->getMethod(
+                    $methodName)->getDocComment();
+            $this->assertStringContains($methodName, $docComment);
+            $this->assertStringContains(
+                '@param \Foo\HelloRequest $request', $docComment);
+            $this->assertStringContains(
+                '@return \Foo\HelloReply', $docComment);
+        }
+    }
+
+    public function testParamForServiceMethod()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $method = $this->serviceClass->getMethod($methodName);
+            $this->assertCount(1, $method->getParameters());
+            $param = $method->getParameters()[0];
+            $this->assertFalse($param->isOptional());
+            $this->assertSame('request', $param->getName());
+	    // ReflectionParameter::getType only exists in PHP 7+, so get the
+	    // type from __toString
+            $this->assertStringContains(
+                'Foo\HelloRequest $request', (string) $param);
+        }
+    }
+
+    public function testParamForServiceMethodInNamespacedClass()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $method = $this->serviceClass->getMethod($methodName);
+            $this->assertCount(1, $method->getParameters());
+            $param = $method->getParameters()[0];
+            $this->assertFalse($param->isOptional());
+            $this->assertSame('request', $param->getName());
+	    // ReflectionParameter::getType only exists in PHP 7+, so get the
+	    // type from __toString
+            $this->assertStringContains(
+                'Foo\HelloRequest $request', (string) $param);
+        }
+    }
+}
diff --git a/php/tests/map_field_test.php b/php/tests/MapFieldTest.php
similarity index 88%
rename from php/tests/map_field_test.php
rename to php/tests/MapFieldTest.php
index 577be68..2d8ae61 100644
--- a/php/tests/map_field_test.php
+++ b/php/tests/MapFieldTest.php
@@ -1,5 +1,6 @@
 <?php
 
+require_once('test_base.php');
 require_once('test_util.php');
 
 use Google\Protobuf\Internal\GPBType;
@@ -7,7 +8,7 @@
 use Foo\TestMessage;
 use Foo\TestMessage\Sub;
 
-class MapFieldTest extends \PHPUnit\Framework\TestCase {
+class MapFieldTest extends TestBase {
 
     #########################################################
     # Test int32 field.
@@ -257,15 +258,15 @@
 
         // Test set.
         $arr[0] = 1;
-        $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF);
 
         $arr[1] = 1.1;
-        $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF);
 
         $arr[2] = '2';
-        $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF);
         $arr[3] = '3.1';
-        $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF);
 
         $this->assertEquals(4, count($arr));
     }
@@ -279,15 +280,15 @@
 
         // Test set.
         $arr[0] = 1;
-        $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF);
 
         $arr[1] = 1.1;
-        $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF);
 
         $arr[2] = '2';
-        $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF);
         $arr[3] = '3.1';
-        $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+        $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF);
 
         $this->assertEquals(4, count($arr));
     }
@@ -477,6 +478,55 @@
         array_walk($values, function (&$value) {});
         $m = new TestMessage();
         $m->setMapInt32Message($values);
+
+        $this->assertTrue(true);
+    }
+
+    #########################################################
+    # Test equality
+    #########################################################
+
+    public function testEquality()
+    {
+        $map = new MapField(GPBType::INT32, GPBType::INT32);
+        $map2 = new MapField(GPBType::INT32, GPBType::INT32);
+
+        $this->assertTrue($map == $map2);
+
+        $map[1] = 2;
+
+        $this->assertFalse($map == $map2);
+
+        $map2[1] = 2;
+
+        $this->assertTrue($map == $map2);
+
+        // Arrays of different types always compare false.
+        $this->assertFalse(new MapField(GPBType::INT32, GPBType::INT32) ==
+                           new MapField(GPBType::INT32, GPBType::INT64));
+        $this->assertFalse(new MapField(GPBType::INT32, GPBType::INT32) ==
+                           new MapField(GPBType::INT64, GPBType::INT32));
+        $this->assertFalse(
+            new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class) ==
+            new MapField(GPBType::INT32, GPBType::MESSAGE, Sub::class));
+    }
+
+    #########################################################
+    # Test clone
+    #########################################################
+
+    public function testClone()
+    {
+        $map = new MapField(GPBType::INT32,
+            GPBType::MESSAGE, Sub::class);
+
+        // Test append.
+        $sub_m = new Sub();
+        $sub_m->setA(1);
+        $map[0] = $sub_m;
+
+        $map2 = clone $map;
+        $this->assertSame($map[0], $map2[0]);
     }
 
     #########################################################
diff --git a/php/tests/php_implementation_test.php b/php/tests/PhpImplementationTest.php
similarity index 96%
rename from php/tests/php_implementation_test.php
rename to php/tests/PhpImplementationTest.php
index 307b749..7187315 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/PhpImplementationTest.php
@@ -18,9 +18,13 @@
  * Please note, this test is only intended to be run without the protobuf C
  * extension.
  */
-class ImplementationTest extends TestBase
+class PhpImplementationTest extends TestBase
 {
-    public function setUp()
+    /**
+     * Avoid calling setUp, which has void return type (not avalialbe in php7.0).
+     * @before
+     */
+    public function skipTestsForExtension()
     {
         if (extension_loaded('protobuf')) {
             $this->markTestSkipped();
@@ -306,6 +310,8 @@
         $m = new TestMessage();
         $m->mergeFromString(TestUtil::getGoldenTestMessage());
         TestUtil::assertTestMessage($m);
+
+        $this->assertTrue(true);
     }
 
     public function testDescriptorDecode()
@@ -515,7 +521,7 @@
     {
         $m = new TestMessage();
         TestUtil::setTestMessage($m);
-        $this->assertSame(518, $m->byteSize());
+        $this->assertSame(504, $m->byteSize());
     }
 
     public function testPackedByteSize()
@@ -525,23 +531,23 @@
         $this->assertSame(166, $m->byteSize());
     }
 
-    /**
-     * @expectedException UnexpectedValueException
-     * @expectedExceptionMessage Invalid message property: optionalInt32
-     */
     public function testArrayConstructorJsonCaseThrowsException()
     {
+        $this->expectException(UnexpectedValueException::class);
+        $this->expectExceptionMessage(
+            'Invalid message property: optionalInt32');
+
         $m = new TestMessage([
             'optionalInt32' => -42,
         ]);
     }
 
-    /**
-     * @expectedException Exception
-     * @expectedExceptionMessage Expect Foo\TestMessage_Sub.
-     */
     public function testArraysForMessagesThrowsException()
     {
+        $this->expectException(Exception::class);
+        $this->expectExceptionMessage(
+            'Expect Foo\TestMessage\Sub.');
+
         $m = new TestMessage([
             'optional_message' => [
                 'a' => 33
@@ -568,10 +574,11 @@
 
     /**
      * @dataProvider provideArrayConstructorWithNullValuesThrowsException
-     * @expectedException Exception
      */
     public function testArrayConstructorWithNullValuesThrowsException($requestData)
     {
+        $this->expectException(Exception::class);
+
         $m = new TestMessage($requestData);
     }
 
diff --git a/php/tests/well_known_test.php b/php/tests/WellKnownTest.php
similarity index 97%
rename from php/tests/well_known_test.php
rename to php/tests/WellKnownTest.php
index a148fa4..486c65f 100644
--- a/php/tests/well_known_test.php
+++ b/php/tests/WellKnownTest.php
@@ -86,31 +86,28 @@
         $this->assertFalse($any->is(Any::class));
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testAnyUnpackInvalidTypeUrl()
     {
+        $this->expectException(Exception::class);
+
         $any = new Any();
         $any->setTypeUrl("invalid");
         $any->unpack();
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testAnyUnpackMessageNotAdded()
     {
+        $this->expectException(Exception::class);
+
         $any = new Any();
         $any->setTypeUrl("type.googleapis.com/MessageNotAdded");
         $any->unpack();
     }
 
-    /**
-     * @expectedException Exception
-     */
     public function testAnyUnpackDecodeError()
     {
+        $this->expectException(Exception::class);
+
         $any = new Any();
         $any->setTypeUrl("type.googleapis.com/foo.TestMessage");
         $any->setValue("abc");
@@ -273,6 +270,8 @@
 
         $m = new Value();
 
+        $this->assertNull($m->getStructValue());
+
         $m->setNullValue(NullValue::NULL_VALUE);
         $this->assertSame(NullValue::NULL_VALUE, $m->getNullValue());
         $this->assertSame("null_value", $m->getKind());
diff --git a/php/tests/wrapper_type_setters_test.php b/php/tests/WrapperTypeSettersTest.php
similarity index 98%
rename from php/tests/wrapper_type_setters_test.php
rename to php/tests/WrapperTypeSettersTest.php
index e4bdfcf..045fa66 100644
--- a/php/tests/wrapper_type_setters_test.php
+++ b/php/tests/WrapperTypeSettersTest.php
@@ -148,10 +148,10 @@
 
     /**
      * @dataProvider invalidSettersDataProvider
-     * @expectedException \Exception
      */
     public function testInvalidSetters($class, $setter, $value)
     {
+        $this->expectException(Exception::class);
         (new $class())->$setter($value);
     }
 
@@ -243,6 +243,8 @@
             }
             $this->assertEquals($expectedInnerValue, $actualInnerValue);
         }
+
+        $this->assertTrue(true);
     }
 
     public function constructorWithRepeatedWrapperTypeDataProvider()
@@ -286,6 +288,8 @@
             }
             $this->assertEquals($expectedInnerValue, $actualInnerValue);
         }
+
+        $this->assertTrue(true);
     }
 
     public function constructorWithMapWrapperTypeDataProvider()
diff --git a/php/tests/autoload.php b/php/tests/autoload.php
deleted file mode 100644
index b98b13a..0000000
--- a/php/tests/autoload.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-error_reporting(E_ALL);
-
-function getGeneratedFiles($dir, &$results = array())
-{
-    $files = scandir($dir);
-
-    foreach ($files as $key => $value) {
-        $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
-        if (!is_dir($path)) {
-            $results[] = $path;
-        } else if ($value != "." && $value != "..") {
-            getGeneratedFiles($path, $results);
-        }
-    }
-    return $results;
-}
-
-foreach (getGeneratedFiles("generated") as $filename)
-{
-    if (!is_dir($filename)) {
-        include_once $filename;
-    }
-
-}
-
diff --git a/php/tests/bootstrap_phpunit.php b/php/tests/bootstrap_phpunit.php
deleted file mode 100644
index 8452f15..0000000
--- a/php/tests/bootstrap_phpunit.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-
-require_once("vendor/autoload.php");
-
-error_reporting(E_ALL);
diff --git a/php/tests/compatibility_test.sh b/php/tests/compatibility_test.sh
index 2b5c6ab..7e44cce 100755
--- a/php/tests/compatibility_test.sh
+++ b/php/tests/compatibility_test.sh
@@ -1,17 +1,5 @@
 #!/bin/bash
 
-function use_php() {
-  VERSION=$1
-
-  OLD_PATH=$PATH
-  OLD_CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH
-  OLD_C_INCLUDE_PATH=$C_INCLUDE_PATH
-
-  export PATH=/usr/local/php-${VERSION}/bin:$OLD_PATH
-  export CPLUS_INCLUDE_PATH=/usr/local/php-${VERSION}/include/php/main:/usr/local/php-${VERSION}/include/php/:$OLD_CPLUS_INCLUDE_PATH
-  export C_INCLUDE_PATH=/usr/local/php-${VERSION}/include/php/main:/usr/local/php-${VERSION}/include/php/:$OLD_C_INCLUDE_PATH
-}
-
 function generate_proto() {
   PROTOC1=$1
   PROTOC2=$2
@@ -92,7 +80,6 @@
 popd
 
 # Build and copy the new runtime
-use_php 7.1
 pushd ../ext/google/protobuf
 make clean || true
 phpize && ./configure && make
@@ -113,11 +100,18 @@
 composer install
 
 # Remove implementation detail tests.
-tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php )
+# TODO(teboring): Temporarily disable encode_decode_test.php. In 3.13.0-rc1,
+# repeated primitive field encoding is changed to packed, which is a bug fix.
+# However, this fails the compatibility test which hard coded old encoding.
+# Will re-enable the test after making a release. After the version bump, the
+# compatibility test will use the updated test code.
+tests=( array_test.php generated_class_test.php map_field_test.php well_known_test.php )
 sed -i.bak '/php_implementation_test.php/d' phpunit.xml
 sed -i.bak '/generated_phpdoc_test.php/d' phpunit.xml
+sed -i.bak '/encode_decode_test.php/d' phpunit.xml
 sed -i.bak 's/generated_phpdoc_test.php//g' tests/test.sh
 sed -i.bak 's/generated_service_test.php//g' tests/test.sh
+sed -i.bak 's/encode_decode_test.php//g' tests/test.sh
 sed -i.bak '/memory_leak_test.php/d' tests/test.sh
 sed -i.bak '/^    public function testTimestamp()$/,/^    }$/d' tests/well_known_test.php
 sed -i.bak 's/PHPUnit_Framework_TestCase/\\PHPUnit\\Framework\\TestCase/g' tests/array_test.php
diff --git a/php/tests/compile_extension.sh b/php/tests/compile_extension.sh
index 2ffc51f..fce0469 100755
--- a/php/tests/compile_extension.sh
+++ b/php/tests/compile_extension.sh
@@ -1,14 +1,29 @@
 #!/bin/bash
 
-VERSION=$2
-
-export PATH=/usr/local/php-$VERSION/bin:$PATH
-export C_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$C_INCLUDE_PATH
-export CPLUS_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$CPLUS_INCLUDE_PATH
-
-pushd  ../ext/google/protobuf
-make clean || true
 set -e
-# Add following in configure for debug: --enable-debug CFLAGS='-g -O0'
-phpize && ./configure CFLAGS='-g -O0 -Wall' && make
-popd
+
+cd $(dirname $0)
+
+../prepare_c_extension.sh
+pushd  ../ext/google/protobuf > /dev/null
+
+CONFIGURE_OPTIONS=("./configure" "--with-php-config=$(which php-config)")
+
+if [ "$1" != "--release" ]; then
+  CONFIGURE_OPTIONS+=("CFLAGS=-g -O0 -Wall -DPBPHP_ENABLE_ASSERTS")
+fi
+
+FINGERPRINT="$(sha256sum $(which php)) ${CONFIGURE_OPTIONS[@]}"
+
+# If the PHP interpreter we are building against or the arguments
+# have changed, we must regenerated the Makefile.
+if [[ ! -f BUILD_STAMP ]] || [[ "$(cat BUILD_STAMP)" != "$FINGERPRINT" ]]; then
+  phpize --clean
+  rm -f configure.in configure.ac
+  phpize
+  "${CONFIGURE_OPTIONS[@]}"
+  echo "$FINGERPRINT" > BUILD_STAMP
+fi
+
+make
+popd > /dev/null
diff --git a/php/tests/force_c_ext.php b/php/tests/force_c_ext.php
new file mode 100644
index 0000000..afc63c5
--- /dev/null
+++ b/php/tests/force_c_ext.php
@@ -0,0 +1,14 @@
+<?php
+
+// We have to test this because the command-line argument will fail silently
+// if the extension could not be loaded:
+//    php -dextension=ext/google/protobuf/modules/protouf.so
+if (!extension_loaded("protobuf")) {
+    throw new Exception("Protobuf extension not loaded");
+}
+
+spl_autoload_register(function($class) {
+    if (strpos($class, "Google\\Protobuf") === 0) {
+        throw new Exception("When using the C extension, we should not load runtime class: " . $class);
+    }
+}, true, true);
diff --git a/php/tests/gdb_test.sh b/php/tests/gdb_test.sh
index da5f3f3..76a0fc3 100755
--- a/php/tests/gdb_test.sh
+++ b/php/tests/gdb_test.sh
@@ -1,11 +1,5 @@
 #!/bin/bash
 
-VERSION=$1
-
-export PATH=/usr/local/php-$VERSION/bin:$PATH
-export C_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$C_INCLUDE_PATH
-export CPLUS_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$CPLUS_INCLUDE_PATH
-
 php -i | grep "Configuration"
 
 # gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which
diff --git a/php/tests/generated_service_test.php b/php/tests/generated_service_test.php
deleted file mode 100644
index 5407db9..0000000
--- a/php/tests/generated_service_test.php
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-
-require_once('test_base.php');
-require_once('test_util.php');
-
-use Google\Protobuf\Internal\RepeatedField;
-use Google\Protobuf\Internal\MapField;
-use Google\Protobuf\Internal\GPBType;
-use Foo\Greeter;
-use Foo\HelloRequest;
-use Foo\HelloReply;
-
-class GeneratedServiceTest extends TestBase
-{
-    /**
-     * @var \ReflectionClass
-     */
-    private $serviceClass;
-
-    /**
-     * @var \ReflectionClass
-     */
-    private $namespacedServiceClass;
-
-    /**
-     * @var array
-     */
-    private $methodNames = [
-        'sayHello',
-        'sayHelloAgain'
-    ];
-
-    public function setUp()
-    {
-        parent::setUp();
-
-        $this->serviceClass = new ReflectionClass('Foo\GreeterInterface');
-
-        $this->namespacedServiceClass = new ReflectionClass('Bar\OtherGreeterInterface');
-    }
-
-    public function testIsInterface()
-    {
-        $this->assertTrue($this->serviceClass->isInterface());
-    }
-
-    public function testPhpDocForClass()
-    {
-        $this->assertContains('foo.Greeter', $this->serviceClass->getDocComment());
-    }
-
-    public function testPhpDocForNamespacedClass()
-    {
-        $this->assertContains('foo.OtherGreeter', $this->namespacedServiceClass->getDocComment());
-    }
-
-    public function testServiceMethodsAreGenerated()
-    {
-        $this->assertCount(count($this->methodNames), $this->serviceClass->getMethods());
-        foreach ($this->methodNames as $methodName) {
-            $this->assertTrue($this->serviceClass->hasMethod($methodName));
-        }
-    }
-
-    public function testPhpDocForServiceMethod()
-    {
-        foreach ($this->methodNames as $methodName) {
-            $docComment = $this->serviceClass->getMethod($methodName)->getDocComment();
-            $this->assertContains($methodName, $docComment);
-            $this->assertContains('@param \Foo\HelloRequest $request', $docComment);
-            $this->assertContains('@return \Foo\HelloReply', $docComment);
-        }
-    }
-
-    public function testPhpDocForServiceMethodInNamespacedClass()
-    {
-        foreach ($this->methodNames as $methodName) {
-            $docComment = $this->namespacedServiceClass->getMethod($methodName)->getDocComment();
-            $this->assertContains($methodName, $docComment);
-            $this->assertContains('@param \Foo\HelloRequest $request', $docComment);
-            $this->assertContains('@return \Foo\HelloReply', $docComment);
-        }
-    }
-
-    public function testParamForServiceMethod()
-    {
-        foreach ($this->methodNames as $methodName) {
-            $method = $this->serviceClass->getMethod($methodName);
-            $this->assertCount(1, $method->getParameters());
-            $param = $method->getParameters()[0];
-            $this->assertFalse($param->isOptional());
-            $this->assertSame('request', $param->getName());
-            // ReflectionParameter::getType only exists in PHP 7+, so get the type from __toString
-            $this->assertContains('Foo\HelloRequest $request', (string) $param);
-        }
-    }
-
-    public function testParamForServiceMethodInNamespacedClass()
-    {
-        foreach ($this->methodNames as $methodName) {
-            $method = $this->serviceClass->getMethod($methodName);
-            $this->assertCount(1, $method->getParameters());
-            $param = $method->getParameters()[0];
-            $this->assertFalse($param->isOptional());
-            $this->assertSame('request', $param->getName());
-            // ReflectionParameter::getType only exists in PHP 7+, so get the type from __toString
-            $this->assertContains('Foo\HelloRequest $request', (string) $param);
-        }
-    }
-}
diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php
index a9c292d..1f2d095 100644
--- a/php/tests/memory_leak_test.php
+++ b/php/tests/memory_leak_test.php
@@ -2,57 +2,7 @@
 
 # phpunit has memory leak by itself. Thus, it cannot be used to test memory leak.
 
-require_once('generated/NoNamespaceEnum.php');
-require_once('generated/NoNamespaceMessage.php');
-require_once('generated/NoNamespaceMessage/NestedEnum.php');
-require_once('generated/NoNamespaceMessage/NestedMessage.php');
-require_once('generated/PrefixEmpty.php');
-require_once('generated/PrefixTestPrefix.php');
-require_once('generated/PrefixTestPrefix/PrefixNestedEnum.php');
-require_once('generated/PrefixTestPrefix/PrefixNestedMessage.php');
-require_once('generated/TestEmptyNamespace.php');
-require_once('generated/TestEmptyNamespace/NestedEnum.php');
-require_once('generated/TestEmptyNamespace/NestedMessage.php');
-require_once('generated/Bar/TestInclude.php');
-require_once('generated/Bar/TestLegacyMessage.php');
-require_once('generated/Bar/TestLegacyMessage/NestedEnum.php');
-require_once('generated/Bar/TestLegacyMessage/NestedMessage.php');
-require_once('generated/Foo/PBARRAY.php');
-require_once('generated/Foo/PBEmpty.php');
-require_once('generated/Foo/TestAny.php');
-require_once('generated/Foo/TestBoolValue.php');
-require_once('generated/Foo/TestBytesValue.php');
-require_once('generated/Foo/TestEnum.php');
-require_once('generated/Foo/TestIncludeNamespaceMessage.php');
-require_once('generated/Foo/TestIncludePrefixMessage.php');
-require_once('generated/Foo/TestInt32Value.php');
-require_once('generated/Foo/TestInt64Value.php');
-require_once('generated/Foo/TestMessage.php');
-require_once('generated/Foo/TestMessage/PBEmpty.php');
-require_once('generated/Foo/TestMessage/NestedEnum.php');
-require_once('generated/Foo/TestMessage/Sub.php');
-require_once('generated/Foo/TestPackedMessage.php');
-require_once('generated/Foo/TestPhpDoc.php');
-require_once('generated/Foo/TestRandomFieldOrder.php');
-require_once('generated/Foo/TestReverseFieldOrder.php');
-require_once('generated/Foo/TestStringValue.php');
-require_once('generated/Foo/TestUInt32Value.php');
-require_once('generated/Foo/TestUInt64Value.php');
-require_once('generated/Foo/TestUnpackedMessage.php');
-require_once('generated/Foo/testLowerCaseMessage.php');
-require_once('generated/Foo/testLowerCaseEnum.php');
-require_once('generated/GPBMetadata/Proto/Test.php');
-require_once('generated/TestEmptyPhpNamespace.php');
-require_once('generated/GPBMetadata/Proto/TestInclude.php');
-require_once('generated/TestNoNamespace.php');
-require_once('generated/Metadata/Php/Test/TestPhpNamespace.php');
-require_once('generated/GPBMetadata/Proto/TestPrefix.php');
-require_once('generated/Php/Test/TestNamespace.php');
-require_once('generated/Php/Test/TestNamespace/PBEmpty.php');
-require_once('generated/Php/Test/TestNamespace/PBEmpty/NestedEnum.php');
-require_once('generated/Php/Test/TestNamespace/PBEmpty/NestedMessage.php');
-require_once('generated/Php/Test/TestNamespace/NestedEnum.php');
-require_once('generated/Php/Test/TestNamespace/NestedMessage.php');
+require_once('../vendor/autoload.php');
 require_once('test_util.php');
 
 use Google\Protobuf\Internal\RepeatedField;
diff --git a/php/tests/multirequest.sh b/php/tests/multirequest.sh
index 97535ea..ec4a1ae 100755
--- a/php/tests/multirequest.sh
+++ b/php/tests/multirequest.sh
@@ -1,14 +1,12 @@
 #!/bin/bash
+
+cd $(dirname $0)
+
 set -e
 
-# Compile c extension
-VERSION=7.4
 PORT=12345
 
-export PATH=/usr/local/php-$VERSION/bin:$PATH
-export C_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$C_INCLUDE_PATH
-export CPLUS_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$CPLUS_INCLUDE_PATH
-/bin/bash ./compile_extension.sh $VERSION
+./compile_extension.sh
 
 nohup php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so -S localhost:$PORT multirequest.php 2>&1 &
 
diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto
index 9505709..609b8cf 100644
--- a/php/tests/proto/test.proto
+++ b/php/tests/proto/test.proto
@@ -34,6 +34,27 @@
   bar.TestInclude optional_included_message = 18;
   TestMessage recursive = 19;
 
+  // True optional
+  optional int32 true_optional_int32 = 201;
+  optional int64 true_optional_int64 = 202;
+  optional uint32 true_optional_uint32 = 203;
+  optional uint64 true_optional_uint64 = 204;
+  optional sint32 true_optional_sint32 = 205;
+  optional sint64 true_optional_sint64 = 206;
+  optional fixed32 true_optional_fixed32 = 207;
+  optional fixed64 true_optional_fixed64 = 208;
+  optional sfixed32 true_optional_sfixed32 = 209;
+  optional sfixed64 true_optional_sfixed64 = 210;
+  optional float true_optional_float = 211;
+  optional double true_optional_double = 212;
+  optional bool true_optional_bool = 213;
+  optional string true_optional_string = 214;
+  optional bytes true_optional_bytes = 215;
+
+  optional TestEnum true_optional_enum = 216;
+  optional Sub true_optional_message = 217;
+  optional bar.TestInclude true_optional_included_message = 218;
+
   // Repeated
   repeated    int32 repeated_int32    = 31;
   repeated    int64 repeated_int64    = 32;
@@ -126,6 +147,9 @@
   map<string, google.protobuf.Any> map_string_any = 122;
   map<string, google.protobuf.ListValue> map_string_list = 123;
   map<string, google.protobuf.Struct> map_string_struct = 124;
+
+  // deprecated field
+  int32 deprecated_optional_int32 = 125 [deprecated=true];
 }
 
 enum TestEnum {
@@ -199,6 +223,10 @@
   string tag14 = 160;
 }
 
+message TestLargeFieldNumber {
+  int32 large_field_number = 536870911;
+}
+
 message TestReverseFieldOrder {
   repeated int32 a = 2;
   string b = 1;
diff --git a/php/tests/proto/test_reserved_enum_lower.proto b/php/tests/proto/test_reserved_enum_lower.proto
index d2daeaf..60807d9 100644
--- a/php/tests/proto/test_reserved_enum_lower.proto
+++ b/php/tests/proto/test_reserved_enum_lower.proto
@@ -32,46 +32,50 @@
 enum exit { ZERO28 = 0; }
 enum extends { ZERO29 = 0; }
 enum final { ZERO30 = 0; }
-enum for { ZERO31 = 0; }
-enum foreach { ZERO32 = 0; }
-enum function { ZERO33 = 0; }
-enum global { ZERO34 = 0; }
-enum goto { ZERO35 = 0; }
-enum if { ZERO36 = 0; }
-enum implements { ZERO37 = 0; }
-enum include { ZERO38 = 0; }
-enum include_once { ZERO39 = 0; }
-enum instanceof { ZERO40 = 0; }
-enum insteadof { ZERO41 = 0; }
-enum interface { ZERO42 = 0; }
-enum isset { ZERO43 = 0; }
-enum list { ZERO44 = 0; }
-enum namespace { ZERO45 = 0; }
-enum new { ZERO46 = 0; }
-enum or { ZERO47 = 0; }
-enum print { ZERO48 = 0; }
-enum private { ZERO49 = 0; }
-enum protected { ZERO50 = 0; }
-enum public { ZERO51 = 0; }
-enum require { ZERO52 = 0; }
-enum require_once { ZERO53 = 0; }
-enum return { ZERO54 = 0; }
-enum static { ZERO55 = 0; }
-enum switch { ZERO56 = 0; }
-enum throw { ZERO57 = 0; }
-enum trait { ZERO58 = 0; }
-enum try { ZERO59 = 0; }
-enum unset { ZERO60 = 0; }
-enum use { ZERO61 = 0; }
-enum var { ZERO62 = 0; }
-enum while { ZERO63 = 0; }
-enum xor { ZERO64 = 0; }
-enum int { ZERO65 = 0; }
-enum float { ZERO66 = 0; }
-enum bool { ZERO67 = 0; }
-enum string { ZERO68 = 0; }
-enum true { ZERO69 = 0; }
-enum false { ZERO70 = 0; }
-enum null { ZERO71 = 0; }
-enum void { ZERO72 = 0; }
-enum iterable { ZERO73 = 0; }
+enum finally { ZERO31 = 0; }
+enum fn { ZERO32 = 0; }
+enum for { ZERO33 = 0; }
+enum foreach { ZERO34 = 0; }
+enum function { ZERO35 = 0; }
+enum global { ZERO36 = 0; }
+enum goto { ZERO37 = 0; }
+enum if { ZERO38 = 0; }
+enum implements { ZERO39 = 0; }
+enum include { ZERO40 = 0; }
+enum include_once { ZERO41 = 0; }
+enum instanceof { ZERO42 = 0; }
+enum insteadof { ZERO43 = 0; }
+enum interface { ZERO44 = 0; }
+enum isset { ZERO45 = 0; }
+enum list { ZERO46 = 0; }
+enum match { ZERO47 = 0; }
+enum namespace { ZERO48 = 0; }
+enum new { ZERO49 = 0; }
+enum or { ZERO50 = 0; }
+enum print { ZERO51 = 0; }
+enum private { ZERO52 = 0; }
+enum protected { ZERO53 = 0; }
+enum public { ZERO54 = 0; }
+enum require { ZERO55 = 0; }
+enum require_once { ZERO56 = 0; }
+enum return { ZERO57 = 0; }
+enum static { ZERO58 = 0; }
+enum switch { ZERO59 = 0; }
+enum throw { ZERO60 = 0; }
+enum trait { ZERO61 = 0; }
+enum try { ZERO62 = 0; }
+enum unset { ZERO63 = 0; }
+enum use { ZERO64 = 0; }
+enum var { ZERO65 = 0; }
+enum while { ZERO66 = 0; }
+enum xor { ZERO67 = 0; }
+enum yield { ZERO68 = 0; }
+enum int { ZERO69 = 0; }
+enum float { ZERO70 = 0; }
+enum bool { ZERO71 = 0; }
+enum string { ZERO72 = 0; }
+enum true { ZERO73 = 0; }
+enum false { ZERO74 = 0; }
+enum null { ZERO75 = 0; }
+enum void { ZERO76 = 0; }
+enum iterable { ZERO77 = 0; }
diff --git a/php/tests/proto/test_reserved_enum_upper.proto b/php/tests/proto/test_reserved_enum_upper.proto
index a396fea..a107332 100644
--- a/php/tests/proto/test_reserved_enum_upper.proto
+++ b/php/tests/proto/test_reserved_enum_upper.proto
@@ -32,46 +32,50 @@
 enum EXIT { ZERO28 = 0; }
 enum EXTENDS { ZERO29 = 0; }
 enum FINAL { ZERO30 = 0; }
-enum FOR { ZERO31 = 0; }
-enum FOREACH { ZERO32 = 0; }
-enum FUNCTION { ZERO33 = 0; }
-enum GLOBAL { ZERO34 = 0; }
-enum GOTO { ZERO35 = 0; }
-enum IF { ZERO36 = 0; }
-enum IMPLEMENTS { ZERO37 = 0; }
-enum INCLUDE { ZERO38 = 0; }
-enum INCLUDE_ONCE { ZERO39 = 0; }
-enum INSTANCEOF { ZERO40 = 0; }
-enum INSTEADOF { ZERO41 = 0; }
-enum INTERFACE { ZERO42 = 0; }
-enum ISSET { ZERO43 = 0; }
-enum LIST { ZERO44 = 0; }
-enum NAMESPACE { ZERO45 = 0; }
-enum NEW { ZERO46 = 0; }
-enum OR { ZERO47 = 0; }
-enum PRINT { ZERO48 = 0; }
-enum PRIVATE { ZERO49 = 0; }
-enum PROTECTED { ZERO50 = 0; }
-enum PUBLIC { ZERO51 = 0; }
-enum REQUIRE { ZERO52 = 0; }
-enum REQUIRE_ONCE { ZERO53 = 0; }
-enum RETURN { ZERO54 = 0; }
-enum STATIC { ZERO55 = 0; }
-enum SWITCH { ZERO56 = 0; }
-enum THROW { ZERO57 = 0; }
-enum TRAIT { ZERO58 = 0; }
-enum TRY { ZERO59 = 0; }
-enum UNSET { ZERO60 = 0; }
-enum USE { ZERO61 = 0; }
-enum VAR { ZERO62 = 0; }
-enum WHILE { ZERO63 = 0; }
-enum XOR { ZERO64 = 0; }
-enum INT { ZERO65 = 0; }
-enum FLOAT { ZERO66 = 0; }
-enum BOOL { ZERO67 = 0; }
-enum STRING { ZERO68 = 0; }
-enum TRUE { ZERO69 = 0; }
-enum FALSE { ZERO70 = 0; }
-enum NULL { ZERO71 = 0; }
-enum VOID { ZERO72 = 0; }
-enum ITERABLE { ZERO73 = 0; }
+enum FINALLY { ZERO31 = 0; }
+enum FN { ZERO32 = 0; }
+enum FOR { ZERO33 = 0; }
+enum FOREACH { ZERO34 = 0; }
+enum FUNCTION { ZERO35 = 0; }
+enum GLOBAL { ZERO36 = 0; }
+enum GOTO { ZERO37 = 0; }
+enum IF { ZERO38 = 0; }
+enum IMPLEMENTS { ZERO39 = 0; }
+enum INCLUDE { ZERO40 = 0; }
+enum INCLUDE_ONCE { ZERO41 = 0; }
+enum INSTANCEOF { ZERO42 = 0; }
+enum INSTEADOF { ZERO43 = 0; }
+enum INTERFACE { ZERO44 = 0; }
+enum ISSET { ZERO45 = 0; }
+enum LIST { ZERO46 = 0; }
+enum MATCH { ZERO47 = 0; }
+enum NAMESPACE { ZERO48 = 0; }
+enum NEW { ZERO49 = 0; }
+enum OR { ZERO50 = 0; }
+enum PRINT { ZERO51 = 0; }
+enum PRIVATE { ZERO52 = 0; }
+enum PROTECTED { ZERO53 = 0; }
+enum PUBLIC { ZERO54 = 0; }
+enum REQUIRE { ZERO55 = 0; }
+enum REQUIRE_ONCE { ZERO56 = 0; }
+enum RETURN { ZERO57 = 0; }
+enum STATIC { ZERO58 = 0; }
+enum SWITCH { ZERO59 = 0; }
+enum THROW { ZERO60 = 0; }
+enum TRAIT { ZERO61 = 0; }
+enum TRY { ZERO62 = 0; }
+enum UNSET { ZERO63 = 0; }
+enum USE { ZERO64 = 0; }
+enum VAR { ZERO65 = 0; }
+enum WHILE { ZERO66 = 0; }
+enum XOR { ZERO67 = 0; }
+enum YIELD { ZERO68 = 0; }
+enum INT { ZERO69 = 0; }
+enum FLOAT { ZERO70 = 0; }
+enum BOOL { ZERO71 = 0; }
+enum STRING { ZERO72 = 0; }
+enum TRUE { ZERO73 = 0; }
+enum FALSE { ZERO74 = 0; }
+enum NULL { ZERO75 = 0; }
+enum VOID { ZERO76 = 0; }
+enum ITERABLE { ZERO77 = 0; }
diff --git a/php/tests/proto/test_reserved_enum_value_lower.proto b/php/tests/proto/test_reserved_enum_value_lower.proto
index 96da319..4682906 100644
--- a/php/tests/proto/test_reserved_enum_value_lower.proto
+++ b/php/tests/proto/test_reserved_enum_value_lower.proto
@@ -33,47 +33,51 @@
   exit = 27;
   extends = 28;
   final = 29;
-  for = 30;
-  foreach = 31;
-  function = 32;
-  global = 33;
-  goto = 34;
-  if = 35;
-  implements = 36;
-  include = 37;
-  include_once = 38;
-  instanceof = 39;
-  insteadof = 40;
-  interface = 41;
-  isset = 42;
-  list = 43;
-  namespace = 44;
-  new = 45;
-  or = 46;
-  print = 47;
-  private = 48;
-  protected = 49;
-  public = 50;
-  require = 51;
-  require_once = 52;
-  return = 53;
-  static = 54;
-  switch = 55;
-  throw = 56;
-  trait = 57;
-  try = 58;
-  unset = 59;
-  use = 60;
-  var = 61;
-  while = 62;
-  xor = 63;
-  int = 64;
-  float = 65;
-  bool = 66;
-  string = 67;
-  true = 68;
-  false = 69;
-  null = 70;
-  void = 71;
-  iterable = 72;
+  finally = 30;
+  fn = 31;
+  for = 32;
+  foreach = 33;
+  function = 34;
+  global = 35;
+  goto = 36;
+  if = 37;
+  implements = 38;
+  include = 39;
+  include_once = 40;
+  instanceof = 41;
+  insteadof = 42;
+  interface = 43;
+  isset = 44;
+  list = 45;
+  match = 46;
+  namespace = 47;
+  new = 48;
+  or = 49;
+  print = 50;
+  private = 51;
+  protected = 52;
+  public = 53;
+  require = 54;
+  require_once = 55;
+  return = 56;
+  static = 57;
+  switch = 58;
+  throw = 59;
+  trait = 60;
+  try = 61;
+  unset = 62;
+  use = 63;
+  var = 64;
+  while = 65;
+  xor = 66;
+  yield = 67;
+  int = 68;
+  float = 69;
+  bool = 70;
+  string = 71;
+  true = 72;
+  false = 73;
+  null = 74;
+  void = 75;
+  iterable = 76;
 }
diff --git a/php/tests/proto/test_reserved_enum_value_upper.proto b/php/tests/proto/test_reserved_enum_value_upper.proto
index b026a85..f30d7ff 100644
--- a/php/tests/proto/test_reserved_enum_value_upper.proto
+++ b/php/tests/proto/test_reserved_enum_value_upper.proto
@@ -33,47 +33,51 @@
   EXIT = 27;
   EXTENDS = 28;
   FINAL = 29;
-  FOR = 30;
-  FOREACH = 31;
-  FUNCTION = 32;
-  GLOBAL = 33;
-  GOTO = 34;
-  IF = 35;
-  IMPLEMENTS = 36;
-  INCLUDE = 37;
-  INCLUDE_ONCE = 38;
-  INSTANCEOF = 39;
-  INSTEADOF = 40;
-  INTERFACE = 41;
-  ISSET = 42;
-  LIST = 43;
-  NAMESPACE = 44;
-  NEW = 45;
-  OR = 46;
-  PRINT = 47;
-  PRIVATE = 48;
-  PROTECTED = 49;
-  PUBLIC = 50;
-  REQUIRE = 51;
-  REQUIRE_ONCE = 52;
-  RETURN = 53;
-  STATIC = 54;
-  SWITCH = 55;
-  THROW = 56;
-  TRAIT = 57;
-  TRY = 58;
-  UNSET = 59;
-  USE = 60;
-  VAR = 61;
-  WHILE = 62;
-  XOR = 63;
-  INT = 64;
-  FLOAT = 65;
-  BOOL = 66;
-  STRING = 67;
-  TRUE = 68;
-  FALSE = 69;
-  NULL = 70;
-  VOID = 71;
-  ITERABLE = 72;
+  FINALLY = 30;
+  FOR = 31;
+  FOREACH = 32;
+  FUNCTION = 33;
+  FN = 34;
+  GLOBAL = 35;
+  GOTO = 36;
+  IF = 37;
+  IMPLEMENTS = 38;
+  INCLUDE = 39;
+  INCLUDE_ONCE = 40;
+  INSTANCEOF = 41;
+  INSTEADOF = 42;
+  INTERFACE = 43;
+  ISSET = 44;
+  LIST = 45;
+  MATCH = 46;
+  NAMESPACE = 47;
+  NEW = 48;
+  OR = 49;
+  PRINT = 50;
+  PRIVATE = 51;
+  PROTECTED = 52;
+  PUBLIC = 53;
+  REQUIRE = 54;
+  REQUIRE_ONCE = 55;
+  RETURN = 56;
+  STATIC = 57;
+  SWITCH = 58;
+  THROW = 59;
+  TRAIT = 60;
+  TRY = 61;
+  UNSET = 62;
+  USE = 63;
+  VAR = 64;
+  WHILE = 65;
+  XOR = 66;
+  YIELD = 67;
+  INT = 68;
+  FLOAT = 69;
+  BOOL = 70;
+  STRING = 71;
+  TRUE = 72;
+  FALSE = 73;
+  NULL = 74;
+  VOID = 75;
+  ITERABLE = 76;
 }
diff --git a/php/tests/proto/test_reserved_message_lower.proto b/php/tests/proto/test_reserved_message_lower.proto
index ed12080..05344ff 100644
--- a/php/tests/proto/test_reserved_message_lower.proto
+++ b/php/tests/proto/test_reserved_message_lower.proto
@@ -32,6 +32,8 @@
 message exit {}
 message extends {}
 message final {}
+message finally {}
+message fn {}
 message for {}
 message foreach {}
 message function {}
@@ -46,6 +48,7 @@
 message interface {}
 message isset {}
 message list {}
+message match {}
 message namespace {}
 message new {}
 message or {}
@@ -66,6 +69,7 @@
 message var {}
 message while {}
 message xor {}
+message yield {}
 message int {}
 message float {}
 message bool {}
diff --git a/php/tests/proto/test_reserved_message_upper.proto b/php/tests/proto/test_reserved_message_upper.proto
index 2917fd1..853a17d 100644
--- a/php/tests/proto/test_reserved_message_upper.proto
+++ b/php/tests/proto/test_reserved_message_upper.proto
@@ -32,6 +32,8 @@
 message EXIT {}
 message EXTENDS {}
 message FINAL {}
+message FINALLY {}
+message FN {}
 message FOR {}
 message FOREACH {}
 message FUNCTION {}
@@ -46,6 +48,7 @@
 message INTERFACE {}
 message ISSET {}
 message LIST {}
+message MATCH {}
 message NAMESPACE {}
 message NEW {}
 message OR {}
@@ -66,6 +69,7 @@
 message VAR {}
 message WHILE {}
 message XOR {}
+message YIELD {}
 message INT {}
 message FLOAT {}
 message BOOL {}
diff --git a/php/tests/test.sh b/php/tests/test.sh
deleted file mode 100755
index 3c5e30d..0000000
--- a/php/tests/test.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-
-VERSION=$1
-
-export PATH=/usr/local/php-$VERSION/bin:$PATH
-export C_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$C_INCLUDE_PATH
-export CPLUS_INCLUDE_PATH=/usr/local/php-$VERSION/include/php/main:/usr/local/php-$VERSION/include/php:$CPLUS_INCLUDE_PATH
-
-# Compile c extension
-/bin/bash ./compile_extension.sh $VERSION
-
-tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php descriptors_test.php wrapper_type_setters_test.php)
-
-for t in "${tests[@]}"
-do
-  echo "****************************"
-  echo "* $t"
-  echo "****************************"
-  php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php $t
-  echo ""
-done
-
-for t in "${tests[@]}"
-do
-  echo "****************************"
-  echo "* $t persistent"
-  echo "****************************"
-  php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php $t
-  echo ""
-done
-
-# # Make sure to run the memory test in debug mode.
-# php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
-
-export ZEND_DONT_UNLOAD_MODULES=1
-export USE_ZEND_ALLOC=0
-valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
-valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
-
-# TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by
-# regresssion test.)
-
-# for t in "${tests[@]}"
-# do
-#   echo "****************************"
-#   echo "* $t (memory leak)"
-#   echo "****************************"
-#   valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php $t
-#   echo ""
-# done
diff --git a/php/tests/test_base.php b/php/tests/test_base.php
index a4d951b..db884a8 100644
--- a/php/tests/test_base.php
+++ b/php/tests/test_base.php
@@ -12,6 +12,30 @@
         TestUtil::setTestMessage($m);
     }
 
+    /**
+     * Polyfill for phpunit6.
+     */
+    static public function assertStringContains($needle, $haystack)
+    {
+        if (function_exists('PHPUnit\Framework\assertStringContainsString')) {
+            parent::assertStringContainsString($needle, $haystack);
+        } else {
+            parent::assertContains($needle, $haystack);
+        }
+    }
+
+    /**
+     * Polyfill for phpunit6.
+     */
+    static public function assertFloatEquals($expected, $actual, $delta)
+    {
+        if (function_exists('PHPUnit\Framework\assertEqualsWithDelta')) {
+            parent::assertEqualsWithDelta($expected, $actual, $delta);
+        } else {
+            parent::assertEquals($expected, $actual, '', $delta);
+        }
+    }
+
     public function setFields2(TestMessage $m)
     {
         TestUtil::setTestMessage2($m);
diff --git a/php/tests/test_util.php b/php/tests/test_util.php
index 2c5b595..c47bf58 100644
--- a/php/tests/test_util.php
+++ b/php/tests/test_util.php
@@ -338,38 +338,24 @@
             "800101" .
             "8A01020821" .
 
-            "F801D6FFFFFFFFFFFFFFFF01" .
-            "F801CCFFFFFFFFFFFFFFFF01" .
-            "8002D5FFFFFFFFFFFFFFFF01" .
-            "8002CBFFFFFFFFFFFFFFFF01" .
-            "88022A" .
-            "880234" .
-            "90022B" .
-            "900235" .
-            "980257" .
-            "98026B" .
-            "A00259" .
-            "A0026D" .
-            "AD022E000000" .
-            "AD0238000000" .
-            "B1022F00000000000000" .
-            "B1023900000000000000" .
-            "BD02D2FFFFFF" .
-            "BD02C8FFFFFF" .
-            "C102D1FFFFFFFFFFFFFF" .
-            "C102C7FFFFFFFFFFFFFF" .
-            "CD020000C03F" .
-            "CD0200002040" .
-            "D1029A9999999999F93F" .
-            "D102CDCCCCCCCCCC0440" .
-            "D80201" .
-            "D80200" .
+            "FA0114D6FFFFFFFFFFFFFFFF01CCFFFFFFFFFFFFFFFF01" .
+            "820214D5FFFFFFFFFFFFFFFF01CBFFFFFFFFFFFFFFFF01" .
+            "8A02022A34" .
+            "9202022B35" .
+            "9A0202576B" .
+            "A20202596D" .
+            "AA02082E00000038000000" .
+            "B202102F000000000000003900000000000000" .
+            "BA0208D2FFFFFFC8FFFFFF" .
+            "C20210D1FFFFFFFFFFFFFFC7FFFFFFFFFFFFFF" .
+            "CA02080000C03F00002040" .
+            "D202109A9999999999F93FCDCCCCCCCCCC0440" .
+            "DA02020100" .
             "E2020161" .
             "E2020163" .
             "EA020462626262" .
             "EA020464646464" .
-            "F00200" .
-            "F00201" .
+            "F202020001" .
             "FA02020822" .
             "FA02020823" .
 
diff --git a/php/tests/undefined_test.php b/php/tests/undefined_test.php
deleted file mode 100644
index 935d8be..0000000
--- a/php/tests/undefined_test.php
+++ /dev/null
@@ -1,920 +0,0 @@
-<?php
-
-require_once('test_util.php');
-
-use Google\Protobuf\Internal\RepeatedField;
-use Google\Protobuf\Internal\GPBType;
-use Foo\TestMessage;
-use Foo\TestMessage\Sub;
-
-class UndefinedTest extends PHPUnit_Framework_TestCase
-{
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = 0;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = 0;
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr[] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr[] = 0;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr[] = 0;
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr[] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr[] = 0;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr[] = 0;
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr[] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr[] = 0;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr[] = 0;
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatAppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr[] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatSetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr[] = 0.0;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr[] = 0.0;
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleAppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr[] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr[] = 0.0;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr[] = 0.0;
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::BOOL);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::BOOL);
-        $arr[] = true;
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $arr[] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $arr[] = 'abc';
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringAppendInvalidUTF8Fail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $hex = hex2bin("ff");
-        $arr[] = $hex;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetInvalidUTF8Fail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $arr[] = 'abc';
-        $hex = hex2bin("ff");
-        $arr[0] = $hex;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendIntFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
-        $arr[] = 1;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetIntFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
-        $arr[] = new Sub;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
-        $arr[] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
-        $arr[] = new Sub;
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendOtherMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
-        $arr[] = new TestMessage;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendNullFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
-        $null = null;
-        $arr[] = $null;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetNullFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
-        $arr[] = new Sub();
-        $null = null;
-        $arr[0] = $null;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRemoveMiddleFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-
-        $arr[] = 0;
-        $arr[] = 1;
-        $arr[] = 2;
-        $this->assertSame(3, count($arr));
-
-        unset($arr[1]);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRemoveEmptyFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-
-        unset($arr[0]);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageOffsetFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = 0;
-        $arr[new Sub()] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringOffsetFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = 0;
-        $arr['abc'] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testSetNonExistedOffsetFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr[0] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt32(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt32('abc');
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint32(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint32('abc');
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt64(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt64('abc');
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint64(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint64('abc');
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatFieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalFloat(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatFieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalFloat('abc');
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleFieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalDouble(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleFieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalDouble('abc');
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolFieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalBool(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringFieldInvalidUTF8Fail()
-    {
-        $m = new TestMessage();
-        $hex = hex2bin("ff");
-        $m->setOptionalString($hex);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageFieldWrongTypeFail()
-    {
-        $m = new TestMessage();
-        $a = 1;
-        $m->setOptionalMessage($a);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageFieldWrongClassFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalMessage(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongTypeFail()
-    {
-        $m = new TestMessage();
-        $a = 1;
-        $m->setRepeatedInt32($a);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongObjectFail()
-    {
-        $m = new TestMessage();
-        $m->setRepeatedInt32($m);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongRepeatedTypeFail()
-    {
-        $m = new TestMessage();
-
-        $repeated_int32 = new RepeatedField(GPBType::UINT32);
-        $m->setRepeatedInt32($repeated_int32);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongRepeatedMessageClassFail()
-    {
-        $m = new TestMessage();
-
-        $repeated_message = new RepeatedField(GPBType::MESSAGE,
-                                              TestMessage::class);
-        $m->setRepeatedMessage($repeated_message);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongTypeFail()
-    {
-        $m = new TestMessage();
-        $a = 1;
-        $m->setMapInt32Int32($a);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongObjectFail()
-    {
-        $m = new TestMessage();
-        $m->setMapInt32Int32($m);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongRepeatedTypeFail()
-    {
-        $m = new TestMessage();
-
-        $map_uint32_uint32 = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $m->setMapInt32Int32($map_uint32_uint32);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongRepeatedMessageClassFail()
-    {
-        $m = new TestMessage();
-
-        $map_int32_message = new MapField(GPBType::INT32,
-                                          GPBType::MESSAGE,
-                                          TestMessage::class);
-        $m->setMapInt32Message($map_int32_message);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageMergeFromInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $n = new Sub();
-        $m->mergeFrom($n);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetStringKeyFail()
-    {
-        $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr['abc'] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr[new Sub()] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetStringKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr['abc'] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr[new Sub()] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetStringKeyFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr['abc'] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr[new Sub()] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetStringKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr['abc'] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr[new Sub()] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetStringValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
-        $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
-        $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolSetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr[new Sub()] = true;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolSetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr[true] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetInvalidUTF8KeyFail()
-    {
-        $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr[hex2bin("ff")] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetInvalidUTF8ValueFail()
-    {
-        $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr['abc'] = hex2bin("ff");
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr[new Sub()] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr['abc'] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetIntValueFail()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetStringValueFail()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetOtherMessageValueFail()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = new Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetNullFailMap()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $null = NULL;
-       $arr[0] = $null;
-    }
-
-}
diff --git a/php/tests/valgrind.supp b/php/tests/valgrind.supp
new file mode 100644
index 0000000..e83b0a3
--- /dev/null
+++ b/php/tests/valgrind.supp
@@ -0,0 +1,12 @@
+{
+   PHP_Equal_Val
+   Memcheck:Cond
+   fun:zend_string_equal_val
+}
+
+{
+   PHP_ScanDir_Tail
+   Memcheck:Cond
+   obj:/usr/bin/php7.3
+   fun:__scandir64_tail
+}
diff --git a/protobuf.bzl b/protobuf.bzl
index e2821f5..9716128 100644
--- a/protobuf.bzl
+++ b/protobuf.bzl
@@ -76,18 +76,23 @@
 def _proto_gen_impl(ctx):
     """General implementation for generating protos"""
     srcs = ctx.files.srcs
-    deps = []
-    deps += ctx.files.srcs
+    deps = depset(direct=ctx.files.srcs)
     source_dir = _SourceDir(ctx)
     gen_dir = _GenDir(ctx).rstrip("/")
     if source_dir:
-        import_flags = ["-I" + source_dir, "-I" + gen_dir]
+        import_flags = depset(direct=["-I" + source_dir, "-I" + gen_dir])
     else:
-        import_flags = ["-I."]
+        import_flags = depset(direct=["-I."])
 
     for dep in ctx.attr.deps:
-        import_flags += dep.proto.import_flags
-        deps += dep.proto.deps
+        if type(dep.proto.import_flags) == "list":
+            import_flags = depset(transitive=[import_flags], direct=dep.proto.import_flags)
+        else:
+            import_flags = depset(transitive=[import_flags, dep.proto.import_flags])
+        if type(dep.proto.deps) == "list":
+            deps = depset(transitive=[deps], direct=dep.proto.deps)
+        else:
+            deps = depset(transitive=[deps, dep.proto.deps])
 
     if not ctx.attr.gen_cc and not ctx.attr.gen_py and not ctx.executable.plugin:
         return struct(
@@ -104,7 +109,7 @@
         in_gen_dir = src.root.path == gen_dir
         if in_gen_dir:
             import_flags_real = []
-            for f in depset(import_flags).to_list():
+            for f in import_flags.to_list():
                 path = f.replace("-I", "")
                 import_flags_real.append("-I$(realpath -s %s)" % path)
 
@@ -119,7 +124,7 @@
             outs.extend(_PyOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
 
         outs = [ctx.actions.declare_file(out, sibling = src) for out in outs]
-        inputs = [src] + deps
+        inputs = [src] + deps.to_list()
         tools = [ctx.executable.protoc]
         if ctx.executable.plugin:
             plugin = ctx.executable.plugin
@@ -142,7 +147,7 @@
                 inputs = inputs,
                 tools = tools,
                 outputs = outs,
-                arguments = args + import_flags + [src.path],
+                arguments = args + import_flags.to_list() + [src.path],
                 executable = ctx.executable.protoc,
                 mnemonic = "ProtoCompile",
                 use_default_shell_env = True,
@@ -185,13 +190,13 @@
         "deps": attr.label_list(providers = ["proto"]),
         "includes": attr.string_list(),
         "protoc": attr.label(
-            cfg = "host",
+            cfg = "exec",
             executable = True,
             allow_single_file = True,
             mandatory = True,
         ),
         "plugin": attr.label(
-            cfg = "host",
+            cfg = "exec",
             allow_files = True,
             executable = True,
         ),
@@ -323,7 +328,12 @@
     deps = [d[ProtoInfo] for d in ctx.attr.deps]
 
     srcjar = ctx.actions.declare_file("{}.srcjar".format(ctx.attr.name))
-    args.add("--java_out", srcjar)
+    if ctx.attr.javalite:
+        java_out = "lite:%s" % srcjar.path
+    else:
+        java_out = srcjar
+
+    args.add("--java_out", java_out)
 
     descriptors = depset(
         transitive = [dep.transitive_descriptor_sets for dep in deps],
@@ -347,6 +357,7 @@
         inputs = descriptors,
         outputs = [srcjar],
         arguments = [args],
+        use_default_shell_env = True,
     )
 
     return [
@@ -362,9 +373,12 @@
             mandatory = True,
             providers = [ProtoInfo],
         ),
+        "javalite": attr.bool(
+            default = False,
+        ),
         "_protoc": attr.label(
             executable = True,
-            cfg = "host",
+            cfg = "exec",
             default = "@com_google_protobuf//:protoc",
         ),
     },
@@ -432,7 +446,7 @@
       protoc: the label of the protocol compiler to generate the sources.
       use_grpc_plugin: a flag to indicate whether to call the Python C++ plugin
           when processing the proto files.
-      **kargs: other keyword arguments that are passed to cc_library.
+      **kargs: other keyword arguments that are passed to py_library.
 
     """
     outs = _PyOuts(srcs, use_grpc_plugin)
diff --git a/protobuf_deps.bzl b/protobuf_deps.bzl
index fb0c477..ec9d8e9 100644
--- a/protobuf_deps.bzl
+++ b/protobuf_deps.bzl
@@ -35,9 +35,9 @@
     if not native.existing_rule("rules_cc"):
         http_archive(
             name = "rules_cc",
-            sha256 = "29daf0159f0cf552fcff60b49d8bcd4f08f08506d2da6e41b07058ec50cfeaec",
-            strip_prefix = "rules_cc-b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e",
-            urls = ["https://github.com/bazelbuild/rules_cc/archive/b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e.tar.gz"],
+            sha256 = "9d48151ea71b3e225adfb6867e6d2c7d0dce46cbdc8710d9a9a628574dfd40a0",
+            strip_prefix = "rules_cc-818289e5613731ae410efb54218a4077fb9dbb03",
+            urls = ["https://github.com/bazelbuild/rules_cc/archive/818289e5613731ae410efb54218a4077fb9dbb03.tar.gz"],
         )
 
     if not native.existing_rule("rules_java"):
@@ -51,9 +51,9 @@
     if not native.existing_rule("rules_proto"):
         http_archive(
             name = "rules_proto",
-            sha256 = "602e7161d9195e50246177e7c55b2f39950a9cf7366f74ed5f22fd45750cd208",
-            strip_prefix = "rules_proto-97d8af4dc474595af3900dd85cb3a29ad28cc313",
-            urls = ["https://github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz"],
+            sha256 = "a4382f78723af788f0bc19fd4c8411f44ffe0a72723670a34692ffad56ada3ac",
+            strip_prefix = "rules_proto-f7a30f6f80006b591fa7c437fe5a951eb10bcbcf",
+            urls = ["https://github.com/bazelbuild/rules_proto/archive/f7a30f6f80006b591fa7c437fe5a951eb10bcbcf.zip"],
         )
 
     if not native.existing_rule("rules_python"):
@@ -63,3 +63,11 @@
             strip_prefix = "rules_python-4b84ad270387a7c439ebdccfd530e2339601ef27",
             urls = ["https://github.com/bazelbuild/rules_python/archive/4b84ad270387a7c439ebdccfd530e2339601ef27.tar.gz"],
         )
+
+    if not native.existing_rule("rules_jvm_external"):
+       http_archive(
+            name = "rules_jvm_external",
+            sha256 = "f36441aa876c4f6427bfb2d1f2d723b48e9d930b62662bf723ddfb8fc80f0140",
+            strip_prefix = "rules_jvm_external-4.1",
+            urls = ["https://github.com/bazelbuild/rules_jvm_external/archive/4.1.zip"],
+        )
diff --git a/protobuf_version.bzl b/protobuf_version.bzl
new file mode 100644
index 0000000..dd1f797
--- /dev/null
+++ b/protobuf_version.bzl
@@ -0,0 +1 @@
+PROTOBUF_VERSION = '3.17.3'
diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md
index 2c45fef..8fc3669 100644
--- a/protoc-artifacts/README.md
+++ b/protoc-artifacts/README.md
@@ -20,7 +20,7 @@
 ## Maven Location
 The published protoc artifacts are available on Maven here:
 
-    http://central.maven.org/maven2/com/google/protobuf/protoc/
+    https://repo.maven.apache.org/maven2/com/google/protobuf/protoc/
 
 ## Versioning
 The version of the ``protoc`` artifact must be the same as the version of the
@@ -123,7 +123,7 @@
           protoc.exe
         + ppcle_64
           protoc.exe
-        + s390x
+        + s390_64
           protoc.exe
       + osx
         + x86_64
diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh
index 7f65d37..4602842 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/protoc-artifacts/build-protoc.sh
@@ -93,7 +93,7 @@
         assertEq $format "elf64-x86-64" $LINENO
       elif [[ "$ARCH" == aarch_64 ]]; then
         assertEq $format "elf64-little" $LINENO
-      elif [[ "$ARCH" == s390x ]]; then
+      elif [[ "$ARCH" == s390_64 ]]; then
 	if [[ $host_machine == s390x ]];then
 	  assertEq $format "elf64-s390" $LINENO
 	else
@@ -149,7 +149,7 @@
       white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2"
     elif [[ "$ARCH" == x86_64 ]]; then
       white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-x86-64\.so\.2"
-    elif [[ "$ARCH" == s390x ]]; then
+    elif [[ "$ARCH" == s390_64 ]]; then
       if [[ $host_machine != s390x ]];then
         dump_cmd='objdump -p '"$1"' | grep NEEDED'
       fi
@@ -226,7 +226,7 @@
     elif [[ "$ARCH" == ppcle_64 ]]; then
       CXXFLAGS="$CXXFLAGS -m64"
       CONFIGURE_ARGS="$CONFIGURE_ARGS --host=powerpc64le-linux-gnu"
-    elif [[ "$ARCH" == s390x ]]; then
+    elif [[ "$ARCH" == s390_64 ]]; then
       CXXFLAGS="$CXXFLAGS -m64"
       CONFIGURE_ARGS="$CONFIGURE_ARGS --host=s390x-linux-gnu"
     else
diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh
index 2a25d3c..7d1923e 100755
--- a/protoc-artifacts/build-zip.sh
+++ b/protoc-artifacts/build-zip.sh
@@ -21,7 +21,7 @@
   dist/<TARGET>-<VERSION_NUMBER>-linux-x86_64.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-aarch_64.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-ppcle_64.zip
-  dist/<TARGET>-<VERSION_NUMBER>-linux-s390x.zip
+  dist/<TARGET>-<VERSION_NUMBER>-linux-s390_64.zip
 EOF
   exit 1
 fi
@@ -38,7 +38,7 @@
   linux-x86_64.zip linux-x86_64.exe \
   linux-aarch_64.zip linux-aarch_64.exe \
   linux-ppcle_64.zip linux-ppcle_64.exe \
-  linux-s390x.zip linux-s390x.exe \
+  linux-s390_64.zip linux-s390_64.exe \
 )
 
 # List of all well-known types to be included.
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index 327e3d7..4eec6e3 100644
--- a/protoc-artifacts/pom.xml
+++ b/protoc-artifacts/pom.xml
@@ -8,7 +8,7 @@
   </parent>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protoc</artifactId>
-  <version>3.11.4</version>
+  <version>3.17.3</version>
   <packaging>pom</packaging>
   <name>Protobuf Compiler</name>
   <description>
@@ -71,6 +71,15 @@
                   <type>exe</type>
                 </artifact>
                 <artifact>
+                  <!-- Reuse a compatible osx-x86_64 version until binary
+                       support for osx-aarch_64 is added. TODO: use
+                       <file>${basedir}/target/osx/aarch_64/protoc.exe</file>
+                       -->
+                  <file>${basedir}/target/osx/x86_64/protoc.exe</file>
+                  <classifier>osx-aarch_64</classifier>
+                  <type>exe</type>
+                </artifact>
+                <artifact>
                   <file>${basedir}/target/linux/aarch_64/protoc.exe</file>
                   <classifier>linux-aarch_64</classifier>
                   <type>exe</type>
@@ -81,8 +90,8 @@
                   <type>exe</type>
 	  	</artifact>
                 <artifact>
-                  <file>${basedir}/target/linux/s390x/protoc.exe</file>
-                  <classifier>linux-s390x</classifier>
+                  <file>${basedir}/target/linux/s390_64/protoc.exe</file>
+                  <classifier>linux-s390_64</classifier>
                   <type>exe</type>
                 </artifact>
               </artifacts>
diff --git a/python/README.md b/python/README.md
index a987c2d..cb8b7e9 100644
--- a/python/README.md
+++ b/python/README.md
@@ -22,7 +22,7 @@
 Development Warning
 ===================
 
-The pure python performance is slow. For better preformance please
+The pure python performance is slow. For better performance please
 use python c++ implementation.
 
 Installation
diff --git a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/factory_test1.proto b/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/factory_test1.proto
deleted file mode 100644
index 9f55e03..0000000
--- a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/factory_test1.proto
+++ /dev/null
@@ -1,55 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: matthewtoia@google.com (Matt Toia)
-
-
-package google.protobuf.python.internal;
-
-
-enum Factory1Enum {
-  FACTORY_1_VALUE_0 = 0;
-  FACTORY_1_VALUE_1 = 1;
-}
-
-message Factory1Message {
-  optional Factory1Enum factory_1_enum = 1;
-  enum NestedFactory1Enum {
-    NESTED_FACTORY_1_VALUE_0 = 0;
-    NESTED_FACTORY_1_VALUE_1 = 1;
-  }
-  optional NestedFactory1Enum nested_factory_1_enum = 2;
-  message NestedFactory1Message {
-    optional string value = 1;
-  }
-  optional NestedFactory1Message nested_factory_1_message = 3;
-  optional int32 scalar_value = 4;
-  repeated string list_value = 5;
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/factory_test2.proto b/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/factory_test2.proto
deleted file mode 100644
index d3ce4d7..0000000
--- a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/factory_test2.proto
+++ /dev/null
@@ -1,77 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: matthewtoia@google.com (Matt Toia)
-
-
-package google.protobuf.python.internal;
-
-import "google/protobuf/internal/factory_test1.proto";
-
-
-enum Factory2Enum {
-  FACTORY_2_VALUE_0 = 0;
-  FACTORY_2_VALUE_1 = 1;
-}
-
-message Factory2Message {
-  required int32 mandatory = 1;
-  optional Factory2Enum factory_2_enum = 2;
-  enum NestedFactory2Enum {
-    NESTED_FACTORY_2_VALUE_0 = 0;
-    NESTED_FACTORY_2_VALUE_1 = 1;
-  }
-  optional NestedFactory2Enum nested_factory_2_enum = 3;
-  message NestedFactory2Message {
-    optional string value = 1;
-  }
-  optional NestedFactory2Message nested_factory_2_message = 4;
-  optional Factory1Message factory_1_message = 5;
-  optional Factory1Enum factory_1_enum = 6;
-  optional Factory1Message.NestedFactory1Enum nested_factory_1_enum = 7;
-  optional Factory1Message.NestedFactory1Message nested_factory_1_message = 8;
-  optional Factory2Message circular_message = 9;
-  optional string scalar_value = 10;
-  repeated string list_value = 11;
-  repeated group Grouped = 12 {
-    optional string part_1 = 13;
-    optional string part_2 = 14;
-  }
-  optional LoopMessage loop = 15;
-  optional int32 int_with_default = 16 [default = 1776];
-  optional double double_with_default = 17 [default = 9.99];
-  optional string string_with_default = 18 [default = "hello world"];
-  optional bool bool_with_default = 19 [default = false];
-  optional Factory2Enum enum_with_default = 20 [default = FACTORY_2_VALUE_1];
-}
-
-message LoopMessage {
-  optional Factory2Message loop = 1;
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_extensions.proto b/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_extensions.proto
deleted file mode 100644
index e2d9701..0000000
--- a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_extensions.proto
+++ /dev/null
@@ -1,58 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: robinson@google.com (Will Robinson)
-
-
-package google.protobuf.internal;
-
-
-message TopLevelMessage {
-  optional ExtendedMessage submessage = 1;
-}
-
-
-message ExtendedMessage {
-  extensions 1 to max;
-}
-
-
-message ForeignMessage {
-  optional int32 foreign_message_int = 1;
-}
-
-
-extend ExtendedMessage {
-  optional int32 optional_int_extension = 1;
-  optional ForeignMessage optional_message_extension = 2;
-
-  repeated int32 repeated_int_extension = 3;
-  repeated ForeignMessage repeated_message_extension = 4;
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_extensions_dynamic.proto b/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_extensions_dynamic.proto
deleted file mode 100644
index df98ac4..0000000
--- a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_extensions_dynamic.proto
+++ /dev/null
@@ -1,49 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: jasonh@google.com (Jason Hsueh)
-//
-// This file is used to test a corner case in the CPP implementation where the
-// generated C++ type is available for the extendee, but the extension is
-// defined in a file whose C++ type is not in the binary.
-
-
-import "google/protobuf/internal/more_extensions.proto";
-
-package google.protobuf.internal;
-
-message DynamicMessageType {
-  optional int32 a = 1;
-}
-
-extend ExtendedMessage {
-  optional int32 dynamic_int32_extension = 100;
-  optional DynamicMessageType dynamic_message_extension = 101;
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_messages.proto b/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_messages.proto
deleted file mode 100644
index c701b44..0000000
--- a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/more_messages.proto
+++ /dev/null
@@ -1,51 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: robinson@google.com (Will Robinson)
-
-
-package google.protobuf.internal;
-
-// A message where tag numbers are listed out of order, to allow us to test our
-// canonicalization of serialized output, which should always be in tag order.
-// We also mix in some extensions for extra fun.
-message OutOfOrderFields {
-  optional   sint32 optional_sint32   =  5;
-  extensions 4 to 4;
-  optional   uint32 optional_uint32   =  3;
-  extensions 2 to 2;
-  optional    int32 optional_int32    =  1;
-};
-
-
-extend OutOfOrderFields {
-  optional   uint64 optional_uint64   =  4;
-  optional    int64 optional_int64    =  2;
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/test_bad_identifiers.proto b/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/test_bad_identifiers.proto
deleted file mode 100644
index 6a82299..0000000
--- a/python/compatibility_tests/v2.5.0/protos/python/google/protobuf/internal/test_bad_identifiers.proto
+++ /dev/null
@@ -1,52 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-
-
-package protobuf_unittest;
-
-option py_generic_services = true;
-
-message TestBadIdentifiers {
-  extensions 100 to max;
-}
-
-// Make sure these reasonable extension names don't conflict with internal
-// variables.
-extend TestBadIdentifiers {
-  optional string message = 100 [default="foo"];
-  optional string descriptor = 101 [default="bar"];
-  optional string reflection = 102 [default="baz"];
-  optional string service = 103 [default="qux"];
-}
-
-message AnotherMessage {}
-service AnotherService {}
diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto
deleted file mode 100644
index 031433e..0000000
--- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto
+++ /dev/null
@@ -1,620 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// The messages in this file describe the definitions found in .proto files.
-// A valid .proto file can be translated directly to a FileDescriptorProto
-// without any other information (e.g. without reading its imports).
-
-
-
-package google.protobuf;
-option java_package = "com.google.protobuf";
-option java_outer_classname = "DescriptorProtos";
-
-// descriptor.proto must be optimized for speed because reflection-based
-// algorithms don't work during bootstrapping.
-option optimize_for = SPEED;
-
-// The protocol compiler can output a FileDescriptorSet containing the .proto
-// files it parses.
-message FileDescriptorSet {
-  repeated FileDescriptorProto file = 1;
-}
-
-// Describes a complete .proto file.
-message FileDescriptorProto {
-  optional string name = 1;       // file name, relative to root of source tree
-  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
-
-  // Names of files imported by this file.
-  repeated string dependency = 3;
-  // Indexes of the public imported files in the dependency list above.
-  repeated int32 public_dependency = 10;
-  // Indexes of the weak imported files in the dependency list.
-  // For Google-internal migration only. Do not use.
-  repeated int32 weak_dependency = 11;
-
-  // All top-level definitions in this file.
-  repeated DescriptorProto message_type = 4;
-  repeated EnumDescriptorProto enum_type = 5;
-  repeated ServiceDescriptorProto service = 6;
-  repeated FieldDescriptorProto extension = 7;
-
-  optional FileOptions options = 8;
-
-  // This field contains optional information about the original source code.
-  // You may safely remove this entire field whithout harming runtime
-  // functionality of the descriptors -- the information is needed only by
-  // development tools.
-  optional SourceCodeInfo source_code_info = 9;
-}
-
-// Describes a message type.
-message DescriptorProto {
-  optional string name = 1;
-
-  repeated FieldDescriptorProto field = 2;
-  repeated FieldDescriptorProto extension = 6;
-
-  repeated DescriptorProto nested_type = 3;
-  repeated EnumDescriptorProto enum_type = 4;
-
-  message ExtensionRange {
-    optional int32 start = 1;
-    optional int32 end = 2;
-  }
-  repeated ExtensionRange extension_range = 5;
-
-  optional MessageOptions options = 7;
-}
-
-// Describes a field within a message.
-message FieldDescriptorProto {
-  enum Type {
-    // 0 is reserved for errors.
-    // Order is weird for historical reasons.
-    TYPE_DOUBLE         = 1;
-    TYPE_FLOAT          = 2;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
-    // negative values are likely.
-    TYPE_INT64          = 3;
-    TYPE_UINT64         = 4;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
-    // negative values are likely.
-    TYPE_INT32          = 5;
-    TYPE_FIXED64        = 6;
-    TYPE_FIXED32        = 7;
-    TYPE_BOOL           = 8;
-    TYPE_STRING         = 9;
-    TYPE_GROUP          = 10;  // Tag-delimited aggregate.
-    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
-
-    // New in version 2.
-    TYPE_BYTES          = 12;
-    TYPE_UINT32         = 13;
-    TYPE_ENUM           = 14;
-    TYPE_SFIXED32       = 15;
-    TYPE_SFIXED64       = 16;
-    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
-    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
-  };
-
-  enum Label {
-    // 0 is reserved for errors
-    LABEL_OPTIONAL      = 1;
-    LABEL_REQUIRED      = 2;
-    LABEL_REPEATED      = 3;
-    // TODO(sanjay): Should we add LABEL_MAP?
-  };
-
-  optional string name = 1;
-  optional int32 number = 3;
-  optional Label label = 4;
-
-  // If type_name is set, this need not be set.  If both this and type_name
-  // are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
-  optional Type type = 5;
-
-  // For message and enum types, this is the name of the type.  If the name
-  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
-  // rules are used to find the type (i.e. first the nested types within this
-  // message are searched, then within the parent, on up to the root
-  // namespace).
-  optional string type_name = 6;
-
-  // For extensions, this is the name of the type being extended.  It is
-  // resolved in the same manner as type_name.
-  optional string extendee = 2;
-
-  // For numeric types, contains the original text representation of the value.
-  // For booleans, "true" or "false".
-  // For strings, contains the default text contents (not escaped in any way).
-  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
-  // TODO(kenton):  Base-64 encode?
-  optional string default_value = 7;
-
-  optional FieldOptions options = 8;
-}
-
-// Describes an enum type.
-message EnumDescriptorProto {
-  optional string name = 1;
-
-  repeated EnumValueDescriptorProto value = 2;
-
-  optional EnumOptions options = 3;
-}
-
-// Describes a value within an enum.
-message EnumValueDescriptorProto {
-  optional string name = 1;
-  optional int32 number = 2;
-
-  optional EnumValueOptions options = 3;
-}
-
-// Describes a service.
-message ServiceDescriptorProto {
-  optional string name = 1;
-  repeated MethodDescriptorProto method = 2;
-
-  optional ServiceOptions options = 3;
-}
-
-// Describes a method of a service.
-message MethodDescriptorProto {
-  optional string name = 1;
-
-  // Input and output type names.  These are resolved in the same way as
-  // FieldDescriptorProto.type_name, but must refer to a message type.
-  optional string input_type = 2;
-  optional string output_type = 3;
-
-  optional MethodOptions options = 4;
-}
-
-
-// ===================================================================
-// Options
-
-// Each of the definitions above may have "options" attached.  These are
-// just annotations which may cause code to be generated slightly differently
-// or may contain hints for code that manipulates protocol messages.
-//
-// Clients may define custom options as extensions of the *Options messages.
-// These extensions may not yet be known at parsing time, so the parser cannot
-// store the values in them.  Instead it stores them in a field in the *Options
-// message called uninterpreted_option. This field must have the same name
-// across all *Options messages. We then use this field to populate the
-// extensions when we build a descriptor, at which point all protos have been
-// parsed and so all extensions are known.
-//
-// Extension numbers for custom options may be chosen as follows:
-// * For options which will only be used within a single application or
-//   organization, or for experimental options, use field numbers 50000
-//   through 99999.  It is up to you to ensure that you do not use the
-//   same number for multiple options.
-// * For options which will be published and used publicly by multiple
-//   independent entities, e-mail protobuf-global-extension-registry@google.com
-//   to reserve extension numbers. Simply provide your project name (e.g.
-//   Object-C plugin) and your project website (if available) -- there's no need
-//   to explain how you intend to use them. Usually you only need one extension
-//   number. You can declare multiple options with only one extension number by
-//   putting them in a sub-message. See the Custom Options section of the docs
-//   for examples:
-//   http://code.google.com/apis/protocolbuffers/docs/proto.html#options
-//   If this turns out to be popular, a web service will be set up
-//   to automatically assign option numbers.
-
-
-message FileOptions {
-
-  // Sets the Java package where classes generated from this .proto will be
-  // placed.  By default, the proto package is used, but this is often
-  // inappropriate because proto packages do not normally start with backwards
-  // domain names.
-  optional string java_package = 1;
-
-
-  // If set, all the classes from the .proto file are wrapped in a single
-  // outer class with the given name.  This applies to both Proto1
-  // (equivalent to the old "--one_java_file" option) and Proto2 (where
-  // a .proto always translates to a single class, but you may want to
-  // explicitly choose the class name).
-  optional string java_outer_classname = 8;
-
-  // If set true, then the Java code generator will generate a separate .java
-  // file for each top-level message, enum, and service defined in the .proto
-  // file.  Thus, these types will *not* be nested inside the outer class
-  // named by java_outer_classname.  However, the outer class will still be
-  // generated to contain the file's getDescriptor() method as well as any
-  // top-level extensions defined in the file.
-  optional bool java_multiple_files = 10 [default=false];
-
-  // If set true, then the Java code generator will generate equals() and
-  // hashCode() methods for all messages defined in the .proto file. This is
-  // purely a speed optimization, as the AbstractMessage base class includes
-  // reflection-based implementations of these methods.
-  optional bool java_generate_equals_and_hash = 20 [default=false];
-
-  // Generated classes can be optimized for speed or code size.
-  enum OptimizeMode {
-    SPEED = 1;        // Generate complete code for parsing, serialization,
-                      // etc.
-    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
-    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
-  }
-  optional OptimizeMode optimize_for = 9 [default=SPEED];
-
-  // Sets the Go package where structs generated from this .proto will be
-  // placed.  There is no default.
-  optional string go_package = 11;
-
-
-
-  // Should generic services be generated in each language?  "Generic" services
-  // are not specific to any particular RPC system.  They are generated by the
-  // main code generators in each language (without additional plugins).
-  // Generic services were the only kind of service generation supported by
-  // early versions of proto2.
-  //
-  // Generic services are now considered deprecated in favor of using plugins
-  // that generate code specific to your particular RPC system.  Therefore,
-  // these default to false.  Old code which depends on generic services should
-  // explicitly set them to true.
-  optional bool cc_generic_services = 16 [default=false];
-  optional bool java_generic_services = 17 [default=false];
-  optional bool py_generic_services = 18 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MessageOptions {
-  // Set true to use the old proto1 MessageSet wire format for extensions.
-  // This is provided for backwards-compatibility with the MessageSet wire
-  // format.  You should not use this for any other reason:  It's less
-  // efficient, has fewer features, and is more complicated.
-  //
-  // The message must be defined exactly as follows:
-  //   message Foo {
-  //     option message_set_wire_format = true;
-  //     extensions 4 to max;
-  //   }
-  // Note that the message cannot have any defined fields; MessageSets only
-  // have extensions.
-  //
-  // All extensions of your type must be singular messages; e.g. they cannot
-  // be int32s, enums, or repeated messages.
-  //
-  // Because this is an option, the above two restrictions are not enforced by
-  // the protocol compiler.
-  optional bool message_set_wire_format = 1 [default=false];
-
-  // Disables the generation of the standard "descriptor()" accessor, which can
-  // conflict with a field of the same name.  This is meant to make migration
-  // from proto1 easier; new code should avoid fields named "descriptor".
-  optional bool no_standard_descriptor_accessor = 2 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message FieldOptions {
-  // The ctype option instructs the C++ code generator to use a different
-  // representation of the field than it normally would.  See the specific
-  // options below.  This option is not yet implemented in the open source
-  // release -- sorry, we'll try to include it in a future version!
-  optional CType ctype = 1 [default = STRING];
-  enum CType {
-    // Default mode.
-    STRING = 0;
-
-    CORD = 1;
-
-    STRING_PIECE = 2;
-  }
-  // The packed option can be enabled for repeated primitive fields to enable
-  // a more efficient representation on the wire. Rather than repeatedly
-  // writing the tag and type for each element, the entire array is encoded as
-  // a single length-delimited blob.
-  optional bool packed = 2;
-
-
-
-  // Should this field be parsed lazily?  Lazy applies only to message-type
-  // fields.  It means that when the outer message is initially parsed, the
-  // inner message's contents will not be parsed but instead stored in encoded
-  // form.  The inner message will actually be parsed when it is first accessed.
-  //
-  // This is only a hint.  Implementations are free to choose whether to use
-  // eager or lazy parsing regardless of the value of this option.  However,
-  // setting this option true suggests that the protocol author believes that
-  // using lazy parsing on this field is worth the additional bookkeeping
-  // overhead typically needed to implement it.
-  //
-  // This option does not affect the public interface of any generated code;
-  // all method signatures remain the same.  Furthermore, thread-safety of the
-  // interface is not affected by this option; const methods remain safe to
-  // call from multiple threads concurrently, while non-const methods continue
-  // to require exclusive access.
-  //
-  //
-  // Note that implementations may choose not to check required fields within
-  // a lazy sub-message.  That is, calling IsInitialized() on the outher message
-  // may return true even if the inner message has missing required fields.
-  // This is necessary because otherwise the inner message would have to be
-  // parsed in order to perform the check, defeating the purpose of lazy
-  // parsing.  An implementation which chooses not to check required fields
-  // must be consistent about it.  That is, for any particular sub-message, the
-  // implementation must either *always* check its required fields, or *never*
-  // check its required fields, regardless of whether or not the message has
-  // been parsed.
-  optional bool lazy = 5 [default=false];
-
-  // Is this field deprecated?
-  // Depending on the target platform, this can emit Deprecated annotations
-  // for accessors, or it will be completely ignored; in the very least, this
-  // is a formalization for deprecating fields.
-  optional bool deprecated = 3 [default=false];
-
-  // EXPERIMENTAL.  DO NOT USE.
-  // For "map" fields, the name of the field in the enclosed type that
-  // is the key for this map.  For example, suppose we have:
-  //   message Item {
-  //     required string name = 1;
-  //     required string value = 2;
-  //   }
-  //   message Config {
-  //     repeated Item items = 1 [experimental_map_key="name"];
-  //   }
-  // In this situation, the map key for Item will be set to "name".
-  // TODO: Fully-implement this, then remove the "experimental_" prefix.
-  optional string experimental_map_key = 9;
-
-  // For Google-internal migration only. Do not use.
-  optional bool weak = 10 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumOptions {
-
-  // Set this option to false to disallow mapping different tag names to a same
-  // value.
-  optional bool allow_alias = 2 [default=true];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumValueOptions {
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message ServiceOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MethodOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-
-// A message representing a option the parser does not recognize. This only
-// appears in options protos created by the compiler::Parser class.
-// DescriptorPool resolves these when building Descriptor objects. Therefore,
-// options protos in descriptor objects (e.g. returned by Descriptor::options(),
-// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
-// in them.
-message UninterpretedOption {
-  // The name of the uninterpreted option.  Each string represents a segment in
-  // a dot-separated name.  is_extension is true iff a segment represents an
-  // extension (denoted with parentheses in options specs in .proto files).
-  // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
-  // "foo.(bar.baz).qux".
-  message NamePart {
-    required string name_part = 1;
-    required bool is_extension = 2;
-  }
-  repeated NamePart name = 2;
-
-  // The value of the uninterpreted option, in whatever type the tokenizer
-  // identified it as during parsing. Exactly one of these should be set.
-  optional string identifier_value = 3;
-  optional uint64 positive_int_value = 4;
-  optional int64 negative_int_value = 5;
-  optional double double_value = 6;
-  optional bytes string_value = 7;
-  optional string aggregate_value = 8;
-}
-
-// ===================================================================
-// Optional source code info
-
-// Encapsulates information about the original source file from which a
-// FileDescriptorProto was generated.
-message SourceCodeInfo {
-  // A Location identifies a piece of source code in a .proto file which
-  // corresponds to a particular definition.  This information is intended
-  // to be useful to IDEs, code indexers, documentation generators, and similar
-  // tools.
-  //
-  // For example, say we have a file like:
-  //   message Foo {
-  //     optional string foo = 1;
-  //   }
-  // Let's look at just the field definition:
-  //   optional string foo = 1;
-  //   ^       ^^     ^^  ^  ^^^
-  //   a       bc     de  f  ghi
-  // We have the following locations:
-  //   span   path               represents
-  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
-  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
-  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
-  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
-  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
-  //
-  // Notes:
-  // - A location may refer to a repeated field itself (i.e. not to any
-  //   particular index within it).  This is used whenever a set of elements are
-  //   logically enclosed in a single code segment.  For example, an entire
-  //   extend block (possibly containing multiple extension definitions) will
-  //   have an outer location whose path refers to the "extensions" repeated
-  //   field without an index.
-  // - Multiple locations may have the same path.  This happens when a single
-  //   logical declaration is spread out across multiple places.  The most
-  //   obvious example is the "extend" block again -- there may be multiple
-  //   extend blocks in the same scope, each of which will have the same path.
-  // - A location's span is not always a subset of its parent's span.  For
-  //   example, the "extendee" of an extension declaration appears at the
-  //   beginning of the "extend" block and is shared by all extensions within
-  //   the block.
-  // - Just because a location's span is a subset of some other location's span
-  //   does not mean that it is a descendent.  For example, a "group" defines
-  //   both a type and a field in a single declaration.  Thus, the locations
-  //   corresponding to the type and field and their components will overlap.
-  // - Code which tries to interpret locations should probably be designed to
-  //   ignore those that it doesn't understand, as more types of locations could
-  //   be recorded in the future.
-  repeated Location location = 1;
-  message Location {
-    // Identifies which part of the FileDescriptorProto was defined at this
-    // location.
-    //
-    // Each element is a field number or an index.  They form a path from
-    // the root FileDescriptorProto to the place where the definition.  For
-    // example, this path:
-    //   [ 4, 3, 2, 7, 1 ]
-    // refers to:
-    //   file.message_type(3)  // 4, 3
-    //       .field(7)         // 2, 7
-    //       .name()           // 1
-    // This is because FileDescriptorProto.message_type has field number 4:
-    //   repeated DescriptorProto message_type = 4;
-    // and DescriptorProto.field has field number 2:
-    //   repeated FieldDescriptorProto field = 2;
-    // and FieldDescriptorProto.name has field number 1:
-    //   optional string name = 1;
-    //
-    // Thus, the above path gives the location of a field name.  If we removed
-    // the last element:
-    //   [ 4, 3, 2, 7 ]
-    // this path refers to the whole field declaration (from the beginning
-    // of the label to the terminating semicolon).
-    repeated int32 path = 1 [packed=true];
-
-    // Always has exactly three or four elements: start line, start column,
-    // end line (optional, otherwise assumed same as start line), end column.
-    // These are packed into a single field for efficiency.  Note that line
-    // and column numbers are zero-based -- typically you will want to add
-    // 1 to each before displaying to a user.
-    repeated int32 span = 2 [packed=true];
-
-    // If this SourceCodeInfo represents a complete declaration, these are any
-    // comments appearing before and after the declaration which appear to be
-    // attached to the declaration.
-    //
-    // A series of line comments appearing on consecutive lines, with no other
-    // tokens appearing on those lines, will be treated as a single comment.
-    //
-    // Only the comment content is provided; comment markers (e.g. //) are
-    // stripped out.  For block comments, leading whitespace and an asterisk
-    // will be stripped from the beginning of each line other than the first.
-    // Newlines are included in the output.
-    //
-    // Examples:
-    //
-    //   optional int32 foo = 1;  // Comment attached to foo.
-    //   // Comment attached to bar.
-    //   optional int32 bar = 2;
-    //
-    //   optional string baz = 3;
-    //   // Comment attached to baz.
-    //   // Another line attached to baz.
-    //
-    //   // Comment attached to qux.
-    //   //
-    //   // Another line attached to qux.
-    //   optional double qux = 4;
-    //
-    //   optional string corge = 5;
-    //   /* Block comment attached
-    //    * to corge.  Leading asterisks
-    //    * will be removed. */
-    //   /* Block comment attached to
-    //    * grault. */
-    //   optional int32 grault = 6;
-    optional string leading_comments = 3;
-    optional string trailing_comments = 4;
-  }
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto
deleted file mode 100644
index 6eb2d86..0000000
--- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto
+++ /dev/null
@@ -1,719 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file we will use for unit testing.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;     // auto-added
-
-import "google/protobuf/unittest_import.proto";
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do "using namespace unittest = protobuf_unittest".
-package protobuf_unittest;
-
-// Protos optimized for SPEED use a strict superset of the generated code
-// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
-// tests for speed unless explicitly testing code size optimization.
-option optimize_for = SPEED;
-
-option java_outer_classname = "UnittestProto";
-
-// This proto includes every type of field in both singular and repeated
-// forms.
-message TestAllTypes {
-  message NestedMessage {
-    // The field name "b" fails to compile in proto1 because it conflicts with
-    // a local variable named "b" in one of the generated methods.  Doh.
-    // This file needs to compile in proto1 to test backwards-compatibility.
-    optional int32 bb = 1;
-  }
-
-  enum NestedEnum {
-    FOO = 1;
-    BAR = 2;
-    BAZ = 3;
-  }
-
-  // Singular
-  optional    int32 optional_int32    =  1;
-  optional    int64 optional_int64    =  2;
-  optional   uint32 optional_uint32   =  3;
-  optional   uint64 optional_uint64   =  4;
-  optional   sint32 optional_sint32   =  5;
-  optional   sint64 optional_sint64   =  6;
-  optional  fixed32 optional_fixed32  =  7;
-  optional  fixed64 optional_fixed64  =  8;
-  optional sfixed32 optional_sfixed32 =  9;
-  optional sfixed64 optional_sfixed64 = 10;
-  optional    float optional_float    = 11;
-  optional   double optional_double   = 12;
-  optional     bool optional_bool     = 13;
-  optional   string optional_string   = 14;
-  optional    bytes optional_bytes    = 15;
-
-  optional group OptionalGroup = 16 {
-    optional int32 a = 17;
-  }
-
-  optional NestedMessage                        optional_nested_message  = 18;
-  optional ForeignMessage                       optional_foreign_message = 19;
-  optional protobuf_unittest_import.ImportMessage optional_import_message  = 20;
-
-  optional NestedEnum                           optional_nested_enum     = 21;
-  optional ForeignEnum                          optional_foreign_enum    = 22;
-  optional protobuf_unittest_import.ImportEnum    optional_import_enum     = 23;
-
-  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
-  optional string optional_cord = 25 [ctype=CORD];
-
-  // Defined in unittest_import_public.proto
-  optional protobuf_unittest_import.PublicImportMessage
-      optional_public_import_message = 26;
-
-  optional NestedMessage optional_lazy_message = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32    = 31;
-  repeated    int64 repeated_int64    = 32;
-  repeated   uint32 repeated_uint32   = 33;
-  repeated   uint64 repeated_uint64   = 34;
-  repeated   sint32 repeated_sint32   = 35;
-  repeated   sint64 repeated_sint64   = 36;
-  repeated  fixed32 repeated_fixed32  = 37;
-  repeated  fixed64 repeated_fixed64  = 38;
-  repeated sfixed32 repeated_sfixed32 = 39;
-  repeated sfixed64 repeated_sfixed64 = 40;
-  repeated    float repeated_float    = 41;
-  repeated   double repeated_double   = 42;
-  repeated     bool repeated_bool     = 43;
-  repeated   string repeated_string   = 44;
-  repeated    bytes repeated_bytes    = 45;
-
-  repeated group RepeatedGroup = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated NestedMessage                        repeated_nested_message  = 48;
-  repeated ForeignMessage                       repeated_foreign_message = 49;
-  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
-
-  repeated NestedEnum                           repeated_nested_enum     = 51;
-  repeated ForeignEnum                          repeated_foreign_enum    = 52;
-  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
-
-  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord = 55 [ctype=CORD];
-
-  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32    = 61 [default =  41    ];
-  optional    int64 default_int64    = 62 [default =  42    ];
-  optional   uint32 default_uint32   = 63 [default =  43    ];
-  optional   uint64 default_uint64   = 64 [default =  44    ];
-  optional   sint32 default_sint32   = 65 [default = -45    ];
-  optional   sint64 default_sint64   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
-  optional    float default_float    = 71 [default =  51.5  ];
-  optional   double default_double   = 72 [default =  52e3  ];
-  optional     bool default_bool     = 73 [default = true   ];
-  optional   string default_string   = 74 [default = "hello"];
-  optional    bytes default_bytes    = 75 [default = "world"];
-
-  optional NestedEnum  default_nested_enum  = 81 [default = BAR        ];
-  optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
-  optional protobuf_unittest_import.ImportEnum
-      default_import_enum = 83 [default = IMPORT_BAR];
-
-  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
-  optional string default_cord = 85 [ctype=CORD,default="123"];
-}
-
-message TestDeprecatedFields {
-  optional int32 deprecated_int32 = 1 [deprecated=true];
-}
-
-// Define these after TestAllTypes to make sure the compiler can handle
-// that.
-message ForeignMessage {
-  optional int32 c = 1;
-}
-
-enum ForeignEnum {
-  FOREIGN_FOO = 4;
-  FOREIGN_BAR = 5;
-  FOREIGN_BAZ = 6;
-}
-
-message TestAllExtensions {
-  extensions 1 to max;
-}
-
-extend TestAllExtensions {
-  // Singular
-  optional    int32 optional_int32_extension    =  1;
-  optional    int64 optional_int64_extension    =  2;
-  optional   uint32 optional_uint32_extension   =  3;
-  optional   uint64 optional_uint64_extension   =  4;
-  optional   sint32 optional_sint32_extension   =  5;
-  optional   sint64 optional_sint64_extension   =  6;
-  optional  fixed32 optional_fixed32_extension  =  7;
-  optional  fixed64 optional_fixed64_extension  =  8;
-  optional sfixed32 optional_sfixed32_extension =  9;
-  optional sfixed64 optional_sfixed64_extension = 10;
-  optional    float optional_float_extension    = 11;
-  optional   double optional_double_extension   = 12;
-  optional     bool optional_bool_extension     = 13;
-  optional   string optional_string_extension   = 14;
-  optional    bytes optional_bytes_extension    = 15;
-
-  optional group OptionalGroup_extension = 16 {
-    optional int32 a = 17;
-  }
-
-  optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
-  optional ForeignMessage optional_foreign_message_extension = 19;
-  optional protobuf_unittest_import.ImportMessage
-    optional_import_message_extension = 20;
-
-  optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
-  optional ForeignEnum optional_foreign_enum_extension = 22;
-  optional protobuf_unittest_import.ImportEnum
-    optional_import_enum_extension = 23;
-
-  optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
-  optional string optional_cord_extension = 25 [ctype=CORD];
-
-  optional protobuf_unittest_import.PublicImportMessage
-    optional_public_import_message_extension = 26;
-
-  optional TestAllTypes.NestedMessage
-    optional_lazy_message_extension = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32_extension    = 31;
-  repeated    int64 repeated_int64_extension    = 32;
-  repeated   uint32 repeated_uint32_extension   = 33;
-  repeated   uint64 repeated_uint64_extension   = 34;
-  repeated   sint32 repeated_sint32_extension   = 35;
-  repeated   sint64 repeated_sint64_extension   = 36;
-  repeated  fixed32 repeated_fixed32_extension  = 37;
-  repeated  fixed64 repeated_fixed64_extension  = 38;
-  repeated sfixed32 repeated_sfixed32_extension = 39;
-  repeated sfixed64 repeated_sfixed64_extension = 40;
-  repeated    float repeated_float_extension    = 41;
-  repeated   double repeated_double_extension   = 42;
-  repeated     bool repeated_bool_extension     = 43;
-  repeated   string repeated_string_extension   = 44;
-  repeated    bytes repeated_bytes_extension    = 45;
-
-  repeated group RepeatedGroup_extension = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
-  repeated ForeignMessage repeated_foreign_message_extension = 49;
-  repeated protobuf_unittest_import.ImportMessage
-    repeated_import_message_extension = 50;
-
-  repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
-  repeated ForeignEnum repeated_foreign_enum_extension = 52;
-  repeated protobuf_unittest_import.ImportEnum
-    repeated_import_enum_extension = 53;
-
-  repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord_extension = 55 [ctype=CORD];
-
-  repeated TestAllTypes.NestedMessage
-    repeated_lazy_message_extension = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32_extension    = 61 [default =  41    ];
-  optional    int64 default_int64_extension    = 62 [default =  42    ];
-  optional   uint32 default_uint32_extension   = 63 [default =  43    ];
-  optional   uint64 default_uint64_extension   = 64 [default =  44    ];
-  optional   sint32 default_sint32_extension   = 65 [default = -45    ];
-  optional   sint64 default_sint64_extension   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32_extension  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64_extension  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32_extension = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64_extension = 70 [default = -50    ];
-  optional    float default_float_extension    = 71 [default =  51.5  ];
-  optional   double default_double_extension   = 72 [default =  52e3  ];
-  optional     bool default_bool_extension     = 73 [default = true   ];
-  optional   string default_string_extension   = 74 [default = "hello"];
-  optional    bytes default_bytes_extension    = 75 [default = "world"];
-
-  optional TestAllTypes.NestedEnum
-    default_nested_enum_extension = 81 [default = BAR];
-  optional ForeignEnum
-    default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
-  optional protobuf_unittest_import.ImportEnum
-    default_import_enum_extension = 83 [default = IMPORT_BAR];
-
-  optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
-                                                       default="abc"];
-  optional string default_cord_extension = 85 [ctype=CORD, default="123"];
-}
-
-message TestNestedExtension {
-  extend TestAllExtensions {
-    // Check for bug where string extensions declared in tested scope did not
-    // compile.
-    optional string test = 1002 [default="test"];
-  }
-}
-
-// We have separate messages for testing required fields because it's
-// annoying to have to fill in required fields in TestProto in order to
-// do anything with it.  Note that we don't need to test every type of
-// required filed because the code output is basically identical to
-// optional fields for all types.
-message TestRequired {
-  required int32 a = 1;
-  optional int32 dummy2 = 2;
-  required int32 b = 3;
-
-  extend TestAllExtensions {
-    optional TestRequired single = 1000;
-    repeated TestRequired multi  = 1001;
-  }
-
-  // Pad the field count to 32 so that we can test that IsInitialized()
-  // properly checks multiple elements of has_bits_.
-  optional int32 dummy4  =  4;
-  optional int32 dummy5  =  5;
-  optional int32 dummy6  =  6;
-  optional int32 dummy7  =  7;
-  optional int32 dummy8  =  8;
-  optional int32 dummy9  =  9;
-  optional int32 dummy10 = 10;
-  optional int32 dummy11 = 11;
-  optional int32 dummy12 = 12;
-  optional int32 dummy13 = 13;
-  optional int32 dummy14 = 14;
-  optional int32 dummy15 = 15;
-  optional int32 dummy16 = 16;
-  optional int32 dummy17 = 17;
-  optional int32 dummy18 = 18;
-  optional int32 dummy19 = 19;
-  optional int32 dummy20 = 20;
-  optional int32 dummy21 = 21;
-  optional int32 dummy22 = 22;
-  optional int32 dummy23 = 23;
-  optional int32 dummy24 = 24;
-  optional int32 dummy25 = 25;
-  optional int32 dummy26 = 26;
-  optional int32 dummy27 = 27;
-  optional int32 dummy28 = 28;
-  optional int32 dummy29 = 29;
-  optional int32 dummy30 = 30;
-  optional int32 dummy31 = 31;
-  optional int32 dummy32 = 32;
-
-  required int32 c = 33;
-}
-
-message TestRequiredForeign {
-  optional TestRequired optional_message = 1;
-  repeated TestRequired repeated_message = 2;
-  optional int32 dummy = 3;
-}
-
-// Test that we can use NestedMessage from outside TestAllTypes.
-message TestForeignNested {
-  optional TestAllTypes.NestedMessage foreign_nested = 1;
-}
-
-// TestEmptyMessage is used to test unknown field support.
-message TestEmptyMessage {
-}
-
-// Like above, but declare all field numbers as potential extensions.  No
-// actual extensions should ever be defined for this type.
-message TestEmptyMessageWithExtensions {
-  extensions 1 to max;
-}
-
-message TestMultipleExtensionRanges {
-  extensions 42;
-  extensions 4143 to 4243;
-  extensions 65536 to max;
-}
-
-// Test that really large tag numbers don't break anything.
-message TestReallyLargeTagNumber {
-  // The largest possible tag number is 2^28 - 1, since the wire format uses
-  // three bits to communicate wire type.
-  optional int32 a = 1;
-  optional int32 bb = 268435455;
-}
-
-message TestRecursiveMessage {
-  optional TestRecursiveMessage a = 1;
-  optional int32 i = 2;
-}
-
-// Test that mutual recursion works.
-message TestMutualRecursionA {
-  optional TestMutualRecursionB bb = 1;
-}
-
-message TestMutualRecursionB {
-  optional TestMutualRecursionA a = 1;
-  optional int32 optional_int32 = 2;
-}
-
-// Test that groups have disjoint field numbers from their siblings and
-// parents.  This is NOT possible in proto1; only proto2.  When attempting
-// to compile with proto1, this will emit an error; so we only include it
-// in protobuf_unittest_proto.
-message TestDupFieldNumber {                        // NO_PROTO1
-  optional int32 a = 1;                             // NO_PROTO1
-  optional group Foo = 2 { optional int32 a = 1; }  // NO_PROTO1
-  optional group Bar = 3 { optional int32 a = 1; }  // NO_PROTO1
-}                                                   // NO_PROTO1
-
-// Additional messages for testing lazy fields.
-message TestEagerMessage {
-  optional TestAllTypes sub_message = 1 [lazy=false];
-}
-message TestLazyMessage {
-  optional TestAllTypes sub_message = 1 [lazy=true];
-}
-
-// Needed for a Python test.
-message TestNestedMessageHasBits {
-  message NestedMessage {
-    repeated int32 nestedmessage_repeated_int32 = 1;
-    repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
-  }
-  optional NestedMessage optional_nested_message = 1;
-}
-
-
-// Test an enum that has multiple values with the same number.
-enum TestEnumWithDupValue {
-  option allow_alias = true;
-  FOO1 = 1;
-  BAR1 = 2;
-  BAZ = 3;
-  FOO2 = 1;
-  BAR2 = 2;
-}
-
-// Test an enum with large, unordered values.
-enum TestSparseEnum {
-  SPARSE_A = 123;
-  SPARSE_B = 62374;
-  SPARSE_C = 12589234;
-  SPARSE_D = -15;
-  SPARSE_E = -53452;
-  SPARSE_F = 0;
-  SPARSE_G = 2;
-}
-
-// Test message with CamelCase field names.  This violates Protocol Buffer
-// standard style.
-message TestCamelCaseFieldNames {
-  optional int32 PrimitiveField = 1;
-  optional string StringField = 2;
-  optional ForeignEnum EnumField = 3;
-  optional ForeignMessage MessageField = 4;
-  optional string StringPieceField = 5 [ctype=STRING_PIECE];
-  optional string CordField = 6 [ctype=CORD];
-
-  repeated int32 RepeatedPrimitiveField = 7;
-  repeated string RepeatedStringField = 8;
-  repeated ForeignEnum RepeatedEnumField = 9;
-  repeated ForeignMessage RepeatedMessageField = 10;
-  repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
-  repeated string RepeatedCordField = 12 [ctype=CORD];
-}
-
-
-// We list fields out of order, to ensure that we're using field number and not
-// field index to determine serialization order.
-message TestFieldOrderings {
-  optional string my_string = 11;
-  extensions 2 to 10;
-  optional int64 my_int = 1;
-  extensions 12 to 100;
-  optional float my_float = 101;
-}
-
-
-extend TestFieldOrderings {
-  optional string my_extension_string = 50;
-  optional int32 my_extension_int = 5;
-}
-
-
-message TestExtremeDefaultValues {
-  optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
-  optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
-  optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
-  optional  int32 small_int32  = 4 [default = -0x7FFFFFFF];
-  optional  int64 small_int64  = 5 [default = -0x7FFFFFFFFFFFFFFF];
-  optional  int32 really_small_int32 = 21 [default = -0x80000000];
-  optional  int64 really_small_int64 = 22 [default = -0x8000000000000000];
-
-  // The default value here is UTF-8 for "\u1234".  (We could also just type
-  // the UTF-8 text directly into this text file rather than escape it, but
-  // lots of people use editors that would be confused by this.)
-  optional string utf8_string = 6 [default = "\341\210\264"];
-
-  // Tests for single-precision floating-point values.
-  optional float zero_float = 7 [default = 0];
-  optional float one_float = 8 [default = 1];
-  optional float small_float = 9 [default = 1.5];
-  optional float negative_one_float = 10 [default = -1];
-  optional float negative_float = 11 [default = -1.5];
-  // Using exponents
-  optional float large_float = 12 [default = 2E8];
-  optional float small_negative_float = 13 [default = -8e-28];
-
-  // Text for nonfinite floating-point values.
-  optional double inf_double = 14 [default = inf];
-  optional double neg_inf_double = 15 [default = -inf];
-  optional double nan_double = 16 [default = nan];
-  optional float inf_float = 17 [default = inf];
-  optional float neg_inf_float = 18 [default = -inf];
-  optional float nan_float = 19 [default = nan];
-
-  // Tests for C++ trigraphs.
-  // Trigraphs should be escaped in C++ generated files, but they should not be
-  // escaped for other languages.
-  // Note that in .proto file, "\?" is a valid way to escape ? in string
-  // literals.
-  optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
-
-  // String defaults containing the character '\000'
-  optional string string_with_zero       = 23 [default = "hel\000lo"];
-  optional  bytes bytes_with_zero        = 24 [default = "wor\000ld"];
-  optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
-                                               default="ab\000c"];
-  optional string cord_with_zero         = 26 [ctype=CORD,
-                                               default="12\0003"];
-}
-
-message SparseEnumMessage {
-  optional TestSparseEnum sparse_enum = 1;
-}
-
-// Test String and Bytes: string is for valid UTF-8 strings
-message OneString {
-  optional string data = 1;
-}
-
-message MoreString {
-  repeated string data = 1;
-}
-
-message OneBytes {
-  optional bytes data = 1;
-}
-
-message MoreBytes {
-  repeated bytes data = 1;
-}
-
-
-// Test messages for packed fields
-
-message TestPackedTypes {
-  repeated    int32 packed_int32    =  90 [packed = true];
-  repeated    int64 packed_int64    =  91 [packed = true];
-  repeated   uint32 packed_uint32   =  92 [packed = true];
-  repeated   uint64 packed_uint64   =  93 [packed = true];
-  repeated   sint32 packed_sint32   =  94 [packed = true];
-  repeated   sint64 packed_sint64   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32 =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64 =  99 [packed = true];
-  repeated    float packed_float    = 100 [packed = true];
-  repeated   double packed_double   = 101 [packed = true];
-  repeated     bool packed_bool     = 102 [packed = true];
-  repeated ForeignEnum packed_enum  = 103 [packed = true];
-}
-
-// A message with the same fields as TestPackedTypes, but without packing. Used
-// to test packed <-> unpacked wire compatibility.
-message TestUnpackedTypes {
-  repeated    int32 unpacked_int32    =  90 [packed = false];
-  repeated    int64 unpacked_int64    =  91 [packed = false];
-  repeated   uint32 unpacked_uint32   =  92 [packed = false];
-  repeated   uint64 unpacked_uint64   =  93 [packed = false];
-  repeated   sint32 unpacked_sint32   =  94 [packed = false];
-  repeated   sint64 unpacked_sint64   =  95 [packed = false];
-  repeated  fixed32 unpacked_fixed32  =  96 [packed = false];
-  repeated  fixed64 unpacked_fixed64  =  97 [packed = false];
-  repeated sfixed32 unpacked_sfixed32 =  98 [packed = false];
-  repeated sfixed64 unpacked_sfixed64 =  99 [packed = false];
-  repeated    float unpacked_float    = 100 [packed = false];
-  repeated   double unpacked_double   = 101 [packed = false];
-  repeated     bool unpacked_bool     = 102 [packed = false];
-  repeated ForeignEnum unpacked_enum  = 103 [packed = false];
-}
-
-message TestPackedExtensions {
-  extensions 1 to max;
-}
-
-extend TestPackedExtensions {
-  repeated    int32 packed_int32_extension    =  90 [packed = true];
-  repeated    int64 packed_int64_extension    =  91 [packed = true];
-  repeated   uint32 packed_uint32_extension   =  92 [packed = true];
-  repeated   uint64 packed_uint64_extension   =  93 [packed = true];
-  repeated   sint32 packed_sint32_extension   =  94 [packed = true];
-  repeated   sint64 packed_sint64_extension   =  95 [packed = true];
-  repeated  fixed32 packed_fixed32_extension  =  96 [packed = true];
-  repeated  fixed64 packed_fixed64_extension  =  97 [packed = true];
-  repeated sfixed32 packed_sfixed32_extension =  98 [packed = true];
-  repeated sfixed64 packed_sfixed64_extension =  99 [packed = true];
-  repeated    float packed_float_extension    = 100 [packed = true];
-  repeated   double packed_double_extension   = 101 [packed = true];
-  repeated     bool packed_bool_extension     = 102 [packed = true];
-  repeated ForeignEnum packed_enum_extension  = 103 [packed = true];
-}
-
-// Used by ExtensionSetTest/DynamicExtensions.  The test actually builds
-// a set of extensions to TestAllExtensions dynamically, based on the fields
-// of this message type.
-message TestDynamicExtensions {
-  enum DynamicEnumType {
-    DYNAMIC_FOO = 2200;
-    DYNAMIC_BAR = 2201;
-    DYNAMIC_BAZ = 2202;
-  }
-  message DynamicMessageType {
-    optional int32 dynamic_field = 2100;
-  }
-
-  optional fixed32 scalar_extension = 2000;
-  optional ForeignEnum enum_extension = 2001;
-  optional DynamicEnumType dynamic_enum_extension = 2002;
-
-  optional ForeignMessage message_extension = 2003;
-  optional DynamicMessageType dynamic_message_extension = 2004;
-
-  repeated string repeated_extension = 2005;
-  repeated sint32 packed_extension = 2006 [packed = true];
-}
-
-message TestRepeatedScalarDifferentTagSizes {
-  // Parsing repeated fixed size values used to fail. This message needs to be
-  // used in order to get a tag of the right size; all of the repeated fields
-  // in TestAllTypes didn't trigger the check.
-  repeated fixed32 repeated_fixed32 = 12;
-  // Check for a varint type, just for good measure.
-  repeated int32   repeated_int32   = 13;
-
-  // These have two-byte tags.
-  repeated fixed64 repeated_fixed64 = 2046;
-  repeated int64   repeated_int64   = 2047;
-
-  // Three byte tags.
-  repeated float   repeated_float   = 262142;
-  repeated uint64  repeated_uint64  = 262143;
-}
-
-// Test that if an optional or required message/group field appears multiple
-// times in the input, they need to be merged.
-message TestParsingMerge {
-  // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
-  // except that all fields are repeated. In the tests, we will serialize the
-  // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
-  // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
-  // the corresponding required/optional fields in TestParsingMerge.
-  message RepeatedFieldsGenerator {
-    repeated TestAllTypes field1 = 1;
-    repeated TestAllTypes field2 = 2;
-    repeated TestAllTypes field3 = 3;
-    repeated group Group1 = 10 {
-      optional TestAllTypes field1 = 11;
-    }
-    repeated group Group2 = 20 {
-      optional TestAllTypes field1 = 21;
-    }
-    repeated TestAllTypes ext1 = 1000;
-    repeated TestAllTypes ext2 = 1001;
-  }
-  required TestAllTypes required_all_types = 1;
-  optional TestAllTypes optional_all_types = 2;
-  repeated TestAllTypes repeated_all_types = 3;
-  optional group OptionalGroup = 10 {
-    optional TestAllTypes optional_group_all_types = 11;
-  }
-  repeated group RepeatedGroup = 20 {
-    optional TestAllTypes repeated_group_all_types = 21;
-  }
-  extensions 1000 to max;
-  extend TestParsingMerge {
-    optional TestAllTypes optional_ext = 1000;
-    repeated TestAllTypes repeated_ext = 1001;
-  }
-}
-
-message TestCommentInjectionMessage {
-  // */ <- This should not close the generated doc comment
-  optional string a = 1 [default="*/ <- Neither should this."];
-}
-
-
-// Test that RPC services work.
-message FooRequest  {}
-message FooResponse {}
-
-message FooClientMessage {}
-message FooServerMessage{}
-
-service TestService {
-  rpc Foo(FooRequest) returns (FooResponse);
-  rpc Bar(BarRequest) returns (BarResponse);
-}
-
-
-message BarRequest  {}
-message BarResponse {}
diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto
deleted file mode 100644
index 2f4e3fd..0000000
--- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto
+++ /dev/null
@@ -1,387 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: benjy@google.com (Benjy Weinberger)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file used to test the "custom options" feature of proto2.
-
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;
-
-// A custom file option (defined below).
-option (file_opt1) = 9876543210;
-
-import "google/protobuf/descriptor.proto";
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-package protobuf_unittest;
-
-
-// Some simple test custom options of various types.
-
-extend google.protobuf.FileOptions {
-  optional uint64 file_opt1 = 7736974;
-}
-
-extend google.protobuf.MessageOptions {
-  optional int32 message_opt1 = 7739036;
-}
-
-extend google.protobuf.FieldOptions {
-  optional fixed64 field_opt1 = 7740936;
-  // This is useful for testing that we correctly register default values for
-  // extension options.
-  optional int32 field_opt2 = 7753913 [default=42];
-}
-
-extend google.protobuf.EnumOptions {
-  optional sfixed32 enum_opt1 = 7753576;
-}
-
-extend google.protobuf.EnumValueOptions {
-  optional int32 enum_value_opt1 = 1560678;
-}
-
-extend google.protobuf.ServiceOptions {
-  optional sint64 service_opt1 = 7887650;
-}
-
-enum MethodOpt1 {
-  METHODOPT1_VAL1 = 1;
-  METHODOPT1_VAL2 = 2;
-}
-
-extend google.protobuf.MethodOptions {
-  optional MethodOpt1 method_opt1 = 7890860;
-}
-
-// A test message with custom options at all possible locations (and also some
-// regular options, to make sure they interact nicely).
-message TestMessageWithCustomOptions {
-  option message_set_wire_format = false;
-
-  option (message_opt1) = -56;
-
-  optional string field1 = 1 [ctype=CORD,
-                              (field_opt1)=8765432109];
-
-  enum AnEnum {
-    option (enum_opt1) = -789;
-
-    ANENUM_VAL1 = 1;
-    ANENUM_VAL2 = 2 [(enum_value_opt1) = 123];
-  }
-}
-
-
-// A test RPC service with custom options at all possible locations (and also
-// some regular options, to make sure they interact nicely).
-message CustomOptionFooRequest {
-}
-
-message CustomOptionFooResponse {
-}
-
-message CustomOptionFooClientMessage {
-}
-
-message CustomOptionFooServerMessage {
-}
-
-service TestServiceWithCustomOptions {
-  option (service_opt1) = -9876543210;
-
-  rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) {
-    option (method_opt1) = METHODOPT1_VAL2;
-  }
-}
-
-
-
-// Options of every possible field type, so we can test them all exhaustively.
-
-message DummyMessageContainingEnum {
-  enum TestEnumType {
-    TEST_OPTION_ENUM_TYPE1 = 22;
-    TEST_OPTION_ENUM_TYPE2 = -23;
-  }
-}
-
-message DummyMessageInvalidAsOptionType {
-}
-
-extend google.protobuf.MessageOptions {
-  optional         bool     bool_opt = 7706090;
-  optional        int32    int32_opt = 7705709;
-  optional        int64    int64_opt = 7705542;
-  optional       uint32   uint32_opt = 7704880;
-  optional       uint64   uint64_opt = 7702367;
-  optional       sint32   sint32_opt = 7701568;
-  optional       sint64   sint64_opt = 7700863;
-  optional      fixed32  fixed32_opt = 7700307;
-  optional      fixed64  fixed64_opt = 7700194;
-  optional     sfixed32 sfixed32_opt = 7698645;
-  optional     sfixed64 sfixed64_opt = 7685475;
-  optional        float    float_opt = 7675390;
-  optional       double   double_opt = 7673293;
-  optional       string   string_opt = 7673285;
-  optional        bytes    bytes_opt = 7673238;
-  optional DummyMessageContainingEnum.TestEnumType enum_opt = 7673233;
-  optional DummyMessageInvalidAsOptionType message_type_opt = 7665967;
-}
-
-message CustomOptionMinIntegerValues {
-  option     (bool_opt) = false;
-  option    (int32_opt) = -0x80000000;
-  option    (int64_opt) = -0x8000000000000000;
-  option   (uint32_opt) = 0;
-  option   (uint64_opt) = 0;
-  option   (sint32_opt) = -0x80000000;
-  option   (sint64_opt) = -0x8000000000000000;
-  option  (fixed32_opt) = 0;
-  option  (fixed64_opt) = 0;
-  option (sfixed32_opt) = -0x80000000;
-  option (sfixed64_opt) = -0x8000000000000000;
-}
-
-message CustomOptionMaxIntegerValues {
-  option     (bool_opt) = true;
-  option    (int32_opt) = 0x7FFFFFFF;
-  option    (int64_opt) = 0x7FFFFFFFFFFFFFFF;
-  option   (uint32_opt) = 0xFFFFFFFF;
-  option   (uint64_opt) = 0xFFFFFFFFFFFFFFFF;
-  option   (sint32_opt) = 0x7FFFFFFF;
-  option   (sint64_opt) = 0x7FFFFFFFFFFFFFFF;
-  option  (fixed32_opt) = 0xFFFFFFFF;
-  option  (fixed64_opt) = 0xFFFFFFFFFFFFFFFF;
-  option (sfixed32_opt) = 0x7FFFFFFF;
-  option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF;
-}
-
-message CustomOptionOtherValues {
-  option  (int32_opt) = -100;  // To test sign-extension.
-  option  (float_opt) = 12.3456789;
-  option (double_opt) = 1.234567890123456789;
-  option (string_opt) = "Hello, \"World\"";
-  option  (bytes_opt) = "Hello\0World";
-  option   (enum_opt) = TEST_OPTION_ENUM_TYPE2;
-}
-
-message SettingRealsFromPositiveInts {
-  option  (float_opt) = 12;
-  option (double_opt) = 154;
-}
-
-message SettingRealsFromNegativeInts {
-  option  (float_opt) = -12;
-  option  (double_opt) = -154;
-}
-
-// Options of complex message types, themselves combined and extended in
-// various ways.
-
-message ComplexOptionType1 {
-  optional int32 foo = 1;
-  optional int32 foo2 = 2;
-  optional int32 foo3 = 3;
-
-  extensions 100 to max;
-}
-
-message ComplexOptionType2 {
-  optional ComplexOptionType1 bar = 1;
-  optional int32 baz = 2;
-
-  message ComplexOptionType4 {
-    optional int32 waldo = 1;
-
-    extend google.protobuf.MessageOptions {
-      optional ComplexOptionType4 complex_opt4 = 7633546;
-    }
-  }
-
-  optional ComplexOptionType4 fred = 3;
-
-  extensions 100 to max;
-}
-
-message ComplexOptionType3 {
-  optional int32 qux = 1;
-
-  optional group ComplexOptionType5 = 2 {
-    optional int32 plugh = 3;
-  }
-}
-
-extend ComplexOptionType1 {
-  optional int32 quux = 7663707;
-  optional ComplexOptionType3 corge = 7663442;
-}
-
-extend ComplexOptionType2 {
-  optional int32 grault = 7650927;
-  optional ComplexOptionType1 garply = 7649992;
-}
-
-extend google.protobuf.MessageOptions {
-  optional protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756;
-  optional ComplexOptionType2 complex_opt2 = 7636949;
-  optional ComplexOptionType3 complex_opt3 = 7636463;
-  optional group ComplexOpt6 = 7595468 {
-    optional int32 xyzzy = 7593951;
-  }
-}
-
-// Note that we try various different ways of naming the same extension.
-message VariousComplexOptions {
-  option (.protobuf_unittest.complex_opt1).foo = 42;
-  option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324;
-  option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876;
-  option (complex_opt2).baz = 987;
-  option (complex_opt2).(grault) = 654;
-  option (complex_opt2).bar.foo = 743;
-  option (complex_opt2).bar.(quux) = 1999;
-  option (complex_opt2).bar.(protobuf_unittest.corge).qux = 2008;
-  option (complex_opt2).(garply).foo = 741;
-  option (complex_opt2).(garply).(.protobuf_unittest.quux) = 1998;
-  option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121;
-  option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971;
-  option (complex_opt2).fred.waldo = 321;
-  option (protobuf_unittest.complex_opt3).qux = 9;
-  option (complex_opt3).complexoptiontype5.plugh = 22;
-  option (complexopt6).xyzzy = 24;
-}
-
-// ------------------------------------------------------
-// Definitions for testing aggregate option parsing.
-// See descriptor_unittest.cc.
-
-message AggregateMessageSet {
-  option message_set_wire_format = true;
-  extensions 4 to max;
-}
-
-message AggregateMessageSetElement {
-  extend AggregateMessageSet {
-    optional AggregateMessageSetElement message_set_extension = 15447542;
-  }
-  optional string s = 1;
-}
-
-// A helper type used to test aggregate option parsing
-message Aggregate {
-  optional int32 i = 1;
-  optional string s = 2;
-
-  // A nested object
-  optional Aggregate sub = 3;
-
-  // To test the parsing of extensions inside aggregate values
-  optional google.protobuf.FileOptions file = 4;
-  extend google.protobuf.FileOptions {
-    optional Aggregate nested = 15476903;
-  }
-
-  // An embedded message set
-  optional AggregateMessageSet mset = 5;
-}
-
-// Allow Aggregate to be used as an option at all possible locations
-// in the .proto grammar.
-extend google.protobuf.FileOptions      { optional Aggregate fileopt    = 15478479; }
-extend google.protobuf.MessageOptions   { optional Aggregate msgopt     = 15480088; }
-extend google.protobuf.FieldOptions     { optional Aggregate fieldopt   = 15481374; }
-extend google.protobuf.EnumOptions      { optional Aggregate enumopt    = 15483218; }
-extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
-extend google.protobuf.ServiceOptions   { optional Aggregate serviceopt = 15497145; }
-extend google.protobuf.MethodOptions    { optional Aggregate methodopt  = 15512713; }
-
-// Try using AggregateOption at different points in the proto grammar
-option (fileopt) = {
-  s: 'FileAnnotation'
-  // Also test the handling of comments
-  /* of both types */ i: 100
-
-  sub { s: 'NestedFileAnnotation' }
-
-  // Include a google.protobuf.FileOptions and recursively extend it with
-  // another fileopt.
-  file {
-    [protobuf_unittest.fileopt] {
-      s:'FileExtensionAnnotation'
-    }
-  }
-
-  // A message set inside an option value
-  mset {
-    [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
-      s: 'EmbeddedMessageSetElement'
-    }
-  }
-};
-
-message AggregateMessage {
-  option (msgopt) = { i:101 s:'MessageAnnotation' };
-  optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
-}
-
-service AggregateService {
-  option (serviceopt) = { s:'ServiceAnnotation' };
-  rpc Method (AggregateMessage) returns (AggregateMessage) {
-    option (methodopt) = { s:'MethodAnnotation' };
-  }
-}
-
-enum AggregateEnum {
-  option (enumopt) = { s:'EnumAnnotation' };
-  VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
-}
-
-// Test custom options for nested type.
-message NestedOptionType {
-  message NestedMessage {
-    option (message_opt1) = 1001;
-    optional int32 nested_field = 1 [(field_opt1) = 1002];
-  }
-  enum NestedEnum {
-    option (enum_opt1) = 1003;
-    NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
-  }
-  extend google.protobuf.FileOptions {
-    optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
-  }
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto
deleted file mode 100644
index ec36cca..0000000
--- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto
+++ /dev/null
@@ -1,64 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file which is imported by unittest.proto to test importing.
-
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do
-// "using namespace unittest_import = protobuf_unittest_import".
-package protobuf_unittest_import;
-
-option optimize_for = SPEED;
-
-// Exercise the java_package option.
-option java_package = "com.google.protobuf.test";
-
-// Do not set a java_outer_classname here to verify that Proto2 works without
-// one.
-
-// Test public import
-import public "google/protobuf/unittest_import_public.proto";
-
-message ImportMessage {
-  optional int32 d = 1;
-}
-
-enum ImportEnum {
-  IMPORT_FOO = 7;
-  IMPORT_BAR = 8;
-  IMPORT_BAZ = 9;
-}
-
diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto
deleted file mode 100644
index ea5d1b1..0000000
--- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto
+++ /dev/null
@@ -1,40 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: liujisi@google.com (Pherl Liu)
-
-
-package protobuf_unittest_import;
-
-option java_package = "com.google.protobuf.test";
-
-message PublicImportMessage {
-  optional int32 e = 1;
-}
diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto
deleted file mode 100644
index 3497f09..0000000
--- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto
+++ /dev/null
@@ -1,72 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// This file contains messages for testing message_set_wire_format.
-
-package protobuf_unittest;
-
-option optimize_for = SPEED;
-
-// A message with message_set_wire_format.
-message TestMessageSet {
-  option message_set_wire_format = true;
-  extensions 4 to max;
-}
-
-message TestMessageSetContainer {
-  optional TestMessageSet message_set = 1;
-}
-
-message TestMessageSetExtension1 {
-  extend TestMessageSet {
-    optional TestMessageSetExtension1 message_set_extension = 1545008;
-  }
-  optional int32 i = 15;
-}
-
-message TestMessageSetExtension2 {
-  extend TestMessageSet {
-    optional TestMessageSetExtension2 message_set_extension = 1547769;
-  }
-  optional string str = 25;
-}
-
-// MessageSet wire format is equivalent to this.
-message RawMessageSet {
-  repeated group Item = 1 {
-    required int32 type_id = 2;
-    required bytes message = 3;
-  }
-}
-
diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto
deleted file mode 100644
index cffb412..0000000
--- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto
+++ /dev/null
@@ -1,52 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-
-package google.protobuf.no_generic_services_test;
-
-// *_generic_services are false by default.
-
-message TestMessage {
-  optional int32 a = 1;
-  extensions 1000 to max;
-}
-
-enum TestEnum {
-  FOO = 1;
-}
-
-extend TestMessage {
-  optional int32 test_extension = 1000;
-}
-
-service TestService {
-  rpc Foo(TestMessage) returns(TestMessage);
-}
diff --git a/python/compatibility_tests/v2.5.0/setup.py b/python/compatibility_tests/v2.5.0/setup.py
deleted file mode 100755
index bf67536..0000000
--- a/python/compatibility_tests/v2.5.0/setup.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#! /usr/bin/env python
-#
-import glob
-import os
-import subprocess
-import sys
-
-from setuptools import setup, Extension, find_packages
-
-if sys.version_info[0] == 3:
-  # Python 3
-  from distutils.command.build_py import build_py_2to3 as _build_py
-else:
-  # Python 2
-  from distutils.command.build_py import build_py as _build_py
-from distutils.spawn import find_executable
-
-def generate_proto(source, code_gen):
-  """Invokes the Protocol Compiler to generate a _pb2.py from the given
-  .proto file."""
-  output = source.replace(".proto", "_pb2.py").replace("protos/src/proto/", "").replace("protos/python/", "")
-
-  if not os.path.exists(source):
-    sys.stderr.write("Can't find required file: %s\n" % source)
-    sys.exit(-1)
-
-  protoc_command = [ code_gen, "-Iprotos/src/proto", "-Iprotos/python", "--python_out=.", source ]
-  if subprocess.call(protoc_command) != 0:
-    sys.exit(-1)
-
-class build_py(_build_py):
-  def run(self):
-    # generate .proto file
-    protoc_1 = "./protoc_1"
-    protoc_2 = "./protoc_2"
-    generate_proto("protos/src/proto/google/protobuf/unittest.proto", protoc_2)
-    generate_proto("protos/src/proto/google/protobuf/unittest_custom_options.proto", protoc_1)
-    generate_proto("protos/src/proto/google/protobuf/unittest_import.proto", protoc_1)
-    generate_proto("protos/src/proto/google/protobuf/unittest_import_public.proto", protoc_1)
-    generate_proto("protos/src/proto/google/protobuf/unittest_mset.proto", protoc_1)
-    generate_proto("protos/src/proto/google/protobuf/unittest_no_generic_services.proto", protoc_1)
-    generate_proto("protos/python/google/protobuf/internal/factory_test1.proto", protoc_1)
-    generate_proto("protos/python/google/protobuf/internal/factory_test2.proto", protoc_1)
-    generate_proto("protos/python/google/protobuf/internal/more_extensions.proto", protoc_1)
-    generate_proto("protos/python/google/protobuf/internal/more_extensions_dynamic.proto", protoc_1)
-    generate_proto("protos/python/google/protobuf/internal/more_messages.proto", protoc_1)
-    generate_proto("protos/python/google/protobuf/internal/test_bad_identifiers.proto", protoc_1)
-
-    # _build_py is an old-style class, so super() doesn't work.
-    _build_py.run(self)
-
-if __name__ == '__main__':
-  # Keep this list of dependencies in sync with tox.ini.
-  install_requires = ['six>=1.9', 'setuptools']
-  if sys.version_info <= (2,7):
-    install_requires.append('ordereddict')
-    install_requires.append('unittest2')
-
-  setup(
-      name='protobuf',
-      description='Protocol Buffers',
-      download_url='https://github.com/protocolbuffers/protobuf/releases',
-      long_description="Protocol Buffers are Google's data interchange format",
-      url='https://developers.google.com/protocol-buffers/',
-      maintainer='protobuf@googlegroups.com',
-      maintainer_email='protobuf@googlegroups.com',
-      license='3-Clause BSD License',
-      classifiers=[
-        "Programming Language :: Python",
-        "Programming Language :: Python :: 2",
-        "Programming Language :: Python :: 2.6",
-        "Programming Language :: Python :: 2.7",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.3",
-        "Programming Language :: Python :: 3.4",
-        ],
-      packages=find_packages(
-          exclude=[
-              'import_test_package',
-          ],
-      ),
-      test_suite='tests.google.protobuf.internal',
-      cmdclass={
-          'build_py': build_py,
-      },
-      install_requires=install_requires,
-  )
diff --git a/python/compatibility_tests/v2.5.0/test.sh b/python/compatibility_tests/v2.5.0/test.sh
deleted file mode 100755
index 740c132..0000000
--- a/python/compatibility_tests/v2.5.0/test.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-# Change to the script's directory.
-cd $(dirname $0)
-
-# Version of the tests (i.e., the version of protobuf from where we extracted
-# these tests).
-TEST_VERSION=2.5.0
-
-# The old version of protobuf that we are testing compatibility against. This
-# is usually the same as TEST_VERSION (i.e., we use the tests extracted from
-# that version to test compatibility of the newest runtime against it), but it
-# is also possible to use this same test set to test the compatibility of the
-# latest version against other versions.
-OLD_VERSION=$1
-OLD_VERSION_PROTOC=https://repo1.maven.org/maven2/com/google/protobuf/protoc/$OLD_VERSION/protoc-$OLD_VERSION-linux-x86_64.exe
-
-# Extract the latest protobuf version number.
-VERSION_NUMBER=`grep "^__version__ = '.*'" ../../google/protobuf/__init__.py | sed "s|__version__ = '\(.*\)'|\1|"`
-
-echo "Running compatibility tests between current $VERSION_NUMBER and released $OLD_VERSION"
-
-# Check protoc
-[ -f ../../../src/protoc ] || {
-  echo "[ERROR]: Please build protoc first."
-  exit 1
-}
-
-# Test source compatibility. In these tests we recompile everything against
-# the new runtime (including old version generated code).
-rm google -f -r
-mkdir -p google/protobuf/internal
-# Build and copy the new runtime
-cd ../../
-python setup.py build
-cp google/protobuf/*.py compatibility_tests/v2.5.0/google/protobuf/
-cp google/protobuf/internal/*.py compatibility_tests/v2.5.0/google/protobuf/internal/
-cd compatibility_tests/v2.5.0
-cp tests/google/protobuf/internal/test_util.py google/protobuf/internal/
-cp google/protobuf/__init__.py google/
-
-# Download old version protoc compiler (for linux)
-wget $OLD_VERSION_PROTOC -O old_protoc
-chmod +x old_protoc
-
-# Test A.1:
-#   proto set 1: use old version
-#   proto set 2 which may import protos in set 1: use old version
-cp old_protoc protoc_1
-cp old_protoc protoc_2
-python setup.py build
-python setup.py test
-
-# Test A.2:
-#   proto set 1: use new version
-#   proto set 2 which may import protos in set 1: use old version
-cp ../../../src/protoc protoc_1
-cp old_protoc protoc_2
-python setup.py build
-python setup.py test
-
-# Test A.3:
-#   proto set 1: use old version
-#   proto set 2 which may import protos in set 1: use new version
-cp old_protoc protoc_1
-cp ../../../src/protoc protoc_2
-python setup.py build
-python setup.py test
-
-rm google -r -f
-rm build -r -f
-rm protoc_1
-rm protoc_2
-rm old_protoc
diff --git a/python/compatibility_tests/v2.5.0/tests/__init__.py b/python/compatibility_tests/v2.5.0/tests/__init__.py
deleted file mode 100644
index 5585614..0000000
--- a/python/compatibility_tests/v2.5.0/tests/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-try:
-  __import__('pkg_resources').declare_namespace(__name__)
-except ImportError:
-  __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/compatibility_tests/v2.5.0/tests/google/__init__.py b/python/compatibility_tests/v2.5.0/tests/google/__init__.py
deleted file mode 100644
index 5585614..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-try:
-  __import__('pkg_resources').declare_namespace(__name__)
-except ImportError:
-  __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/__init__.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/__init__.py
deleted file mode 100644
index 5585614..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-try:
-  __import__('pkg_resources').declare_namespace(__name__)
-except ImportError:
-  __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/__init__.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/__init__.py
deleted file mode 100644
index 64c6956..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/__init__.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# https://developers.google.com/protocol-buffers/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Copyright 2007 Google Inc. All Rights Reserved.
-
-if __name__ != '__main__':
-  try:
-    __import__('pkg_resources').declare_namespace(__name__)
-  except ImportError:
-    __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/descriptor_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/descriptor_test.py
deleted file mode 100755
index c74f882..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/descriptor_test.py
+++ /dev/null
@@ -1,613 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# http://code.google.com/p/protobuf/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unittest for google.protobuf.internal.descriptor."""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import unittest
-from google.protobuf import unittest_custom_options_pb2
-from google.protobuf import unittest_import_pb2
-from google.protobuf import unittest_pb2
-from google.protobuf import descriptor_pb2
-from google.protobuf import descriptor
-from google.protobuf import text_format
-
-
-TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
-name: 'TestEmptyMessage'
-"""
-
-
-class DescriptorTest(unittest.TestCase):
-
-  def setUp(self):
-    self.my_file = descriptor.FileDescriptor(
-        name='some/filename/some.proto',
-        package='protobuf_unittest'
-        )
-    self.my_enum = descriptor.EnumDescriptor(
-        name='ForeignEnum',
-        full_name='protobuf_unittest.ForeignEnum',
-        filename=None,
-        file=self.my_file,
-        values=[
-          descriptor.EnumValueDescriptor(name='FOREIGN_FOO', index=0, number=4),
-          descriptor.EnumValueDescriptor(name='FOREIGN_BAR', index=1, number=5),
-          descriptor.EnumValueDescriptor(name='FOREIGN_BAZ', index=2, number=6),
-        ])
-    self.my_message = descriptor.Descriptor(
-        name='NestedMessage',
-        full_name='protobuf_unittest.TestAllTypes.NestedMessage',
-        filename=None,
-        file=self.my_file,
-        containing_type=None,
-        fields=[
-          descriptor.FieldDescriptor(
-            name='bb',
-            full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb',
-            index=0, number=1,
-            type=5, cpp_type=1, label=1,
-            has_default_value=False, default_value=0,
-            message_type=None, enum_type=None, containing_type=None,
-            is_extension=False, extension_scope=None),
-        ],
-        nested_types=[],
-        enum_types=[
-          self.my_enum,
-        ],
-        extensions=[])
-    self.my_method = descriptor.MethodDescriptor(
-        name='Bar',
-        full_name='protobuf_unittest.TestService.Bar',
-        index=0,
-        containing_service=None,
-        input_type=None,
-        output_type=None)
-    self.my_service = descriptor.ServiceDescriptor(
-        name='TestServiceWithOptions',
-        full_name='protobuf_unittest.TestServiceWithOptions',
-        file=self.my_file,
-        index=0,
-        methods=[
-            self.my_method
-        ])
-
-  def testEnumValueName(self):
-    self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4),
-                     'FOREIGN_FOO')
-
-    self.assertEqual(
-        self.my_message.enum_types_by_name[
-            'ForeignEnum'].values_by_number[4].name,
-        self.my_message.EnumValueName('ForeignEnum', 4))
-
-  def testEnumFixups(self):
-    self.assertEqual(self.my_enum, self.my_enum.values[0].type)
-
-  def testContainingTypeFixups(self):
-    self.assertEqual(self.my_message, self.my_message.fields[0].containing_type)
-    self.assertEqual(self.my_message, self.my_enum.containing_type)
-
-  def testContainingServiceFixups(self):
-    self.assertEqual(self.my_service, self.my_method.containing_service)
-
-  def testGetOptions(self):
-    self.assertEqual(self.my_enum.GetOptions(),
-                     descriptor_pb2.EnumOptions())
-    self.assertEqual(self.my_enum.values[0].GetOptions(),
-                     descriptor_pb2.EnumValueOptions())
-    self.assertEqual(self.my_message.GetOptions(),
-                     descriptor_pb2.MessageOptions())
-    self.assertEqual(self.my_message.fields[0].GetOptions(),
-                     descriptor_pb2.FieldOptions())
-    self.assertEqual(self.my_method.GetOptions(),
-                     descriptor_pb2.MethodOptions())
-    self.assertEqual(self.my_service.GetOptions(),
-                     descriptor_pb2.ServiceOptions())
-
-  def testSimpleCustomOptions(self):
-    file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
-    message_descriptor =\
-        unittest_custom_options_pb2.TestMessageWithCustomOptions.DESCRIPTOR
-    field_descriptor = message_descriptor.fields_by_name["field1"]
-    enum_descriptor = message_descriptor.enum_types_by_name["AnEnum"]
-    enum_value_descriptor =\
-        message_descriptor.enum_values_by_name["ANENUM_VAL2"]
-    service_descriptor =\
-        unittest_custom_options_pb2.TestServiceWithCustomOptions.DESCRIPTOR
-    method_descriptor = service_descriptor.FindMethodByName("Foo")
-
-    file_options = file_descriptor.GetOptions()
-    file_opt1 = unittest_custom_options_pb2.file_opt1
-    self.assertEqual(9876543210, file_options.Extensions[file_opt1])
-    message_options = message_descriptor.GetOptions()
-    message_opt1 = unittest_custom_options_pb2.message_opt1
-    self.assertEqual(-56, message_options.Extensions[message_opt1])
-    field_options = field_descriptor.GetOptions()
-    field_opt1 = unittest_custom_options_pb2.field_opt1
-    self.assertEqual(8765432109, field_options.Extensions[field_opt1])
-    field_opt2 = unittest_custom_options_pb2.field_opt2
-    self.assertEqual(42, field_options.Extensions[field_opt2])
-    enum_options = enum_descriptor.GetOptions()
-    enum_opt1 = unittest_custom_options_pb2.enum_opt1
-    self.assertEqual(-789, enum_options.Extensions[enum_opt1])
-    enum_value_options = enum_value_descriptor.GetOptions()
-    enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1
-    self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1])
-
-    service_options = service_descriptor.GetOptions()
-    service_opt1 = unittest_custom_options_pb2.service_opt1
-    self.assertEqual(-9876543210, service_options.Extensions[service_opt1])
-    method_options = method_descriptor.GetOptions()
-    method_opt1 = unittest_custom_options_pb2.method_opt1
-    self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2,
-                     method_options.Extensions[method_opt1])
-
-  def testDifferentCustomOptionTypes(self):
-    kint32min = -2**31
-    kint64min = -2**63
-    kint32max = 2**31 - 1
-    kint64max = 2**63 - 1
-    kuint32max = 2**32 - 1
-    kuint64max = 2**64 - 1
-
-    message_descriptor =\
-        unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR
-    message_options = message_descriptor.GetOptions()
-    self.assertEqual(False, message_options.Extensions[
-        unittest_custom_options_pb2.bool_opt])
-    self.assertEqual(kint32min, message_options.Extensions[
-        unittest_custom_options_pb2.int32_opt])
-    self.assertEqual(kint64min, message_options.Extensions[
-        unittest_custom_options_pb2.int64_opt])
-    self.assertEqual(0, message_options.Extensions[
-        unittest_custom_options_pb2.uint32_opt])
-    self.assertEqual(0, message_options.Extensions[
-        unittest_custom_options_pb2.uint64_opt])
-    self.assertEqual(kint32min, message_options.Extensions[
-        unittest_custom_options_pb2.sint32_opt])
-    self.assertEqual(kint64min, message_options.Extensions[
-        unittest_custom_options_pb2.sint64_opt])
-    self.assertEqual(0, message_options.Extensions[
-        unittest_custom_options_pb2.fixed32_opt])
-    self.assertEqual(0, message_options.Extensions[
-        unittest_custom_options_pb2.fixed64_opt])
-    self.assertEqual(kint32min, message_options.Extensions[
-        unittest_custom_options_pb2.sfixed32_opt])
-    self.assertEqual(kint64min, message_options.Extensions[
-        unittest_custom_options_pb2.sfixed64_opt])
-
-    message_descriptor =\
-        unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR
-    message_options = message_descriptor.GetOptions()
-    self.assertEqual(True, message_options.Extensions[
-        unittest_custom_options_pb2.bool_opt])
-    self.assertEqual(kint32max, message_options.Extensions[
-        unittest_custom_options_pb2.int32_opt])
-    self.assertEqual(kint64max, message_options.Extensions[
-        unittest_custom_options_pb2.int64_opt])
-    self.assertEqual(kuint32max, message_options.Extensions[
-        unittest_custom_options_pb2.uint32_opt])
-    self.assertEqual(kuint64max, message_options.Extensions[
-        unittest_custom_options_pb2.uint64_opt])
-    self.assertEqual(kint32max, message_options.Extensions[
-        unittest_custom_options_pb2.sint32_opt])
-    self.assertEqual(kint64max, message_options.Extensions[
-        unittest_custom_options_pb2.sint64_opt])
-    self.assertEqual(kuint32max, message_options.Extensions[
-        unittest_custom_options_pb2.fixed32_opt])
-    self.assertEqual(kuint64max, message_options.Extensions[
-        unittest_custom_options_pb2.fixed64_opt])
-    self.assertEqual(kint32max, message_options.Extensions[
-        unittest_custom_options_pb2.sfixed32_opt])
-    self.assertEqual(kint64max, message_options.Extensions[
-        unittest_custom_options_pb2.sfixed64_opt])
-
-    message_descriptor =\
-        unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR
-    message_options = message_descriptor.GetOptions()
-    self.assertEqual(-100, message_options.Extensions[
-        unittest_custom_options_pb2.int32_opt])
-    self.assertAlmostEqual(12.3456789, message_options.Extensions[
-        unittest_custom_options_pb2.float_opt], 6)
-    self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[
-        unittest_custom_options_pb2.double_opt])
-    self.assertEqual("Hello, \"World\"", message_options.Extensions[
-        unittest_custom_options_pb2.string_opt])
-    self.assertEqual("Hello\0World", message_options.Extensions[
-        unittest_custom_options_pb2.bytes_opt])
-    dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum
-    self.assertEqual(
-        dummy_enum.TEST_OPTION_ENUM_TYPE2,
-        message_options.Extensions[unittest_custom_options_pb2.enum_opt])
-
-    message_descriptor =\
-        unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR
-    message_options = message_descriptor.GetOptions()
-    self.assertAlmostEqual(12, message_options.Extensions[
-        unittest_custom_options_pb2.float_opt], 6)
-    self.assertAlmostEqual(154, message_options.Extensions[
-        unittest_custom_options_pb2.double_opt])
-
-    message_descriptor =\
-        unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR
-    message_options = message_descriptor.GetOptions()
-    self.assertAlmostEqual(-12, message_options.Extensions[
-        unittest_custom_options_pb2.float_opt], 6)
-    self.assertAlmostEqual(-154, message_options.Extensions[
-        unittest_custom_options_pb2.double_opt])
-
-  def testComplexExtensionOptions(self):
-    descriptor =\
-        unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR
-    options = descriptor.GetOptions()
-    self.assertEqual(42, options.Extensions[
-        unittest_custom_options_pb2.complex_opt1].foo)
-    self.assertEqual(324, options.Extensions[
-        unittest_custom_options_pb2.complex_opt1].Extensions[
-            unittest_custom_options_pb2.quux])
-    self.assertEqual(876, options.Extensions[
-        unittest_custom_options_pb2.complex_opt1].Extensions[
-            unittest_custom_options_pb2.corge].qux)
-    self.assertEqual(987, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].baz)
-    self.assertEqual(654, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].Extensions[
-            unittest_custom_options_pb2.grault])
-    self.assertEqual(743, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].bar.foo)
-    self.assertEqual(1999, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].bar.Extensions[
-            unittest_custom_options_pb2.quux])
-    self.assertEqual(2008, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].bar.Extensions[
-            unittest_custom_options_pb2.corge].qux)
-    self.assertEqual(741, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].Extensions[
-            unittest_custom_options_pb2.garply].foo)
-    self.assertEqual(1998, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].Extensions[
-            unittest_custom_options_pb2.garply].Extensions[
-                unittest_custom_options_pb2.quux])
-    self.assertEqual(2121, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].Extensions[
-            unittest_custom_options_pb2.garply].Extensions[
-                unittest_custom_options_pb2.corge].qux)
-    self.assertEqual(1971, options.Extensions[
-        unittest_custom_options_pb2.ComplexOptionType2
-        .ComplexOptionType4.complex_opt4].waldo)
-    self.assertEqual(321, options.Extensions[
-        unittest_custom_options_pb2.complex_opt2].fred.waldo)
-    self.assertEqual(9, options.Extensions[
-        unittest_custom_options_pb2.complex_opt3].qux)
-    self.assertEqual(22, options.Extensions[
-        unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh)
-    self.assertEqual(24, options.Extensions[
-        unittest_custom_options_pb2.complexopt6].xyzzy)
-
-  # Check that aggregate options were parsed and saved correctly in
-  # the appropriate descriptors.
-  def testAggregateOptions(self):
-    file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
-    message_descriptor =\
-        unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR
-    field_descriptor = message_descriptor.fields_by_name["fieldname"]
-    enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR
-    enum_value_descriptor = enum_descriptor.values_by_name["VALUE"]
-    service_descriptor =\
-        unittest_custom_options_pb2.AggregateService.DESCRIPTOR
-    method_descriptor = service_descriptor.FindMethodByName("Method")
-
-    # Tests for the different types of data embedded in fileopt
-    file_options = file_descriptor.GetOptions().Extensions[
-        unittest_custom_options_pb2.fileopt]
-    self.assertEqual(100, file_options.i)
-    self.assertEqual("FileAnnotation", file_options.s)
-    self.assertEqual("NestedFileAnnotation", file_options.sub.s)
-    self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[
-        unittest_custom_options_pb2.fileopt].s)
-    self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[
-        unittest_custom_options_pb2.AggregateMessageSetElement
-        .message_set_extension].s)
-
-    # Simple tests for all the other types of annotations
-    self.assertEqual(
-        "MessageAnnotation",
-        message_descriptor.GetOptions().Extensions[
-            unittest_custom_options_pb2.msgopt].s)
-    self.assertEqual(
-        "FieldAnnotation",
-        field_descriptor.GetOptions().Extensions[
-            unittest_custom_options_pb2.fieldopt].s)
-    self.assertEqual(
-        "EnumAnnotation",
-        enum_descriptor.GetOptions().Extensions[
-            unittest_custom_options_pb2.enumopt].s)
-    self.assertEqual(
-        "EnumValueAnnotation",
-        enum_value_descriptor.GetOptions().Extensions[
-            unittest_custom_options_pb2.enumvalopt].s)
-    self.assertEqual(
-        "ServiceAnnotation",
-        service_descriptor.GetOptions().Extensions[
-            unittest_custom_options_pb2.serviceopt].s)
-    self.assertEqual(
-        "MethodAnnotation",
-        method_descriptor.GetOptions().Extensions[
-            unittest_custom_options_pb2.methodopt].s)
-
-  def testNestedOptions(self):
-    nested_message =\
-        unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR
-    self.assertEqual(1001, nested_message.GetOptions().Extensions[
-        unittest_custom_options_pb2.message_opt1])
-    nested_field = nested_message.fields_by_name["nested_field"]
-    self.assertEqual(1002, nested_field.GetOptions().Extensions[
-        unittest_custom_options_pb2.field_opt1])
-    outer_message =\
-        unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR
-    nested_enum = outer_message.enum_types_by_name["NestedEnum"]
-    self.assertEqual(1003, nested_enum.GetOptions().Extensions[
-        unittest_custom_options_pb2.enum_opt1])
-    nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"]
-    self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[
-        unittest_custom_options_pb2.enum_value_opt1])
-    nested_extension = outer_message.extensions_by_name["nested_extension"]
-    self.assertEqual(1005, nested_extension.GetOptions().Extensions[
-        unittest_custom_options_pb2.field_opt2])
-
-  def testFileDescriptorReferences(self):
-    self.assertEqual(self.my_enum.file, self.my_file)
-    self.assertEqual(self.my_message.file, self.my_file)
-
-  def testFileDescriptor(self):
-    self.assertEqual(self.my_file.name, 'some/filename/some.proto')
-    self.assertEqual(self.my_file.package, 'protobuf_unittest')
-
-
-class DescriptorCopyToProtoTest(unittest.TestCase):
-  """Tests for CopyTo functions of Descriptor."""
-
-  def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii):
-    expected_proto = expected_class()
-    text_format.Merge(expected_ascii, expected_proto)
-
-    self.assertEqual(
-        actual_proto, expected_proto,
-        'Not equal,\nActual:\n%s\nExpected:\n%s\n'
-        % (str(actual_proto), str(expected_proto)))
-
-  def _InternalTestCopyToProto(self, desc, expected_proto_class,
-                               expected_proto_ascii):
-    actual = expected_proto_class()
-    desc.CopyToProto(actual)
-    self._AssertProtoEqual(
-        actual, expected_proto_class, expected_proto_ascii)
-
-  def testCopyToProto_EmptyMessage(self):
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestEmptyMessage.DESCRIPTOR,
-        descriptor_pb2.DescriptorProto,
-        TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII)
-
-  def testCopyToProto_NestedMessage(self):
-    TEST_NESTED_MESSAGE_ASCII = """
-      name: 'NestedMessage'
-      field: <
-        name: 'bb'
-        number: 1
-        label: 1  # Optional
-        type: 5  # TYPE_INT32
-      >
-      """
-
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
-        descriptor_pb2.DescriptorProto,
-        TEST_NESTED_MESSAGE_ASCII)
-
-  def testCopyToProto_ForeignNestedMessage(self):
-    TEST_FOREIGN_NESTED_ASCII = """
-      name: 'TestForeignNested'
-      field: <
-        name: 'foreign_nested'
-        number: 1
-        label: 1  # Optional
-        type: 11  # TYPE_MESSAGE
-        type_name: '.protobuf_unittest.TestAllTypes.NestedMessage'
-      >
-      """
-
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestForeignNested.DESCRIPTOR,
-        descriptor_pb2.DescriptorProto,
-        TEST_FOREIGN_NESTED_ASCII)
-
-  def testCopyToProto_ForeignEnum(self):
-    TEST_FOREIGN_ENUM_ASCII = """
-      name: 'ForeignEnum'
-      value: <
-        name: 'FOREIGN_FOO'
-        number: 4
-      >
-      value: <
-        name: 'FOREIGN_BAR'
-        number: 5
-      >
-      value: <
-        name: 'FOREIGN_BAZ'
-        number: 6
-      >
-      """
-
-    self._InternalTestCopyToProto(
-        unittest_pb2._FOREIGNENUM,
-        descriptor_pb2.EnumDescriptorProto,
-        TEST_FOREIGN_ENUM_ASCII)
-
-  def testCopyToProto_Options(self):
-    TEST_DEPRECATED_FIELDS_ASCII = """
-      name: 'TestDeprecatedFields'
-      field: <
-        name: 'deprecated_int32'
-        number: 1
-        label: 1  # Optional
-        type: 5  # TYPE_INT32
-        options: <
-          deprecated: true
-        >
-      >
-      """
-
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestDeprecatedFields.DESCRIPTOR,
-        descriptor_pb2.DescriptorProto,
-        TEST_DEPRECATED_FIELDS_ASCII)
-
-  def testCopyToProto_AllExtensions(self):
-    TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """
-      name: 'TestEmptyMessageWithExtensions'
-      extension_range: <
-        start: 1
-        end: 536870912
-      >
-      """
-
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR,
-        descriptor_pb2.DescriptorProto,
-        TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII)
-
-  def testCopyToProto_SeveralExtensions(self):
-    TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """
-      name: 'TestMultipleExtensionRanges'
-      extension_range: <
-        start: 42
-        end: 43
-      >
-      extension_range: <
-        start: 4143
-        end: 4244
-      >
-      extension_range: <
-        start: 65536
-        end: 536870912
-      >
-      """
-
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR,
-        descriptor_pb2.DescriptorProto,
-        TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII)
-
-  def testCopyToProto_FileDescriptor(self):
-    UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = ("""
-      name: 'google/protobuf/unittest_import.proto'
-      package: 'protobuf_unittest_import'
-      dependency: 'google/protobuf/unittest_import_public.proto'
-      message_type: <
-        name: 'ImportMessage'
-        field: <
-          name: 'd'
-          number: 1
-          label: 1  # Optional
-          type: 5  # TYPE_INT32
-        >
-      >
-      """ +
-      """enum_type: <
-        name: 'ImportEnum'
-        value: <
-          name: 'IMPORT_FOO'
-          number: 7
-        >
-        value: <
-          name: 'IMPORT_BAR'
-          number: 8
-        >
-        value: <
-          name: 'IMPORT_BAZ'
-          number: 9
-        >
-      >
-      options: <
-        java_package: 'com.google.protobuf.test'
-        optimize_for: 1  # SPEED
-      >
-      public_dependency: 0
-      """)
-
-    self._InternalTestCopyToProto(
-        unittest_import_pb2.DESCRIPTOR,
-        descriptor_pb2.FileDescriptorProto,
-        UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII)
-
-  def testCopyToProto_ServiceDescriptor(self):
-    TEST_SERVICE_ASCII = """
-      name: 'TestService'
-      method: <
-        name: 'Foo'
-        input_type: '.protobuf_unittest.FooRequest'
-        output_type: '.protobuf_unittest.FooResponse'
-      >
-      method: <
-        name: 'Bar'
-        input_type: '.protobuf_unittest.BarRequest'
-        output_type: '.protobuf_unittest.BarResponse'
-      >
-      """
-
-    self._InternalTestCopyToProto(
-        unittest_pb2.TestService.DESCRIPTOR,
-        descriptor_pb2.ServiceDescriptorProto,
-        TEST_SERVICE_ASCII)
-
-
-class MakeDescriptorTest(unittest.TestCase):
-  def testMakeDescriptorWithUnsignedIntField(self):
-    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
-    file_descriptor_proto.name = 'Foo'
-    message_type = file_descriptor_proto.message_type.add()
-    message_type.name = file_descriptor_proto.name
-    field = message_type.field.add()
-    field.number = 1
-    field.name = 'uint64_field'
-    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
-    field.type = descriptor.FieldDescriptor.TYPE_UINT64
-    result = descriptor.MakeDescriptor(message_type)
-    self.assertEqual(result.fields[0].cpp_type,
-                     descriptor.FieldDescriptor.CPPTYPE_UINT64)
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/generator_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/generator_test.py
deleted file mode 100755
index feb7752..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/generator_test.py
+++ /dev/null
@@ -1,269 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# http://code.google.com/p/protobuf/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# TODO(robinson): Flesh this out considerably.  We focused on reflection_test.py
-# first, since it's testing the subtler code, and since it provides decent
-# indirect testing of the protocol compiler output.
-
-"""Unittest that directly tests the output of the pure-Python protocol
-compiler.  See //google/protobuf/reflection_test.py for a test which
-further ensures that we can use Python protocol message objects as we expect.
-"""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import unittest
-from google.protobuf.internal import test_bad_identifiers_pb2
-from google.protobuf import unittest_custom_options_pb2
-from google.protobuf import unittest_import_pb2
-from google.protobuf import unittest_import_public_pb2
-from google.protobuf import unittest_mset_pb2
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_no_generic_services_pb2
-from google.protobuf import service
-
-MAX_EXTENSION = 536870912
-
-
-class GeneratorTest(unittest.TestCase):
-
-  def testNestedMessageDescriptor(self):
-    field_name = 'optional_nested_message'
-    proto_type = unittest_pb2.TestAllTypes
-    self.assertEqual(
-        proto_type.NestedMessage.DESCRIPTOR,
-        proto_type.DESCRIPTOR.fields_by_name[field_name].message_type)
-
-  def testEnums(self):
-    # We test only module-level enums here.
-    # TODO(robinson): Examine descriptors directly to check
-    # enum descriptor output.
-    self.assertEqual(4, unittest_pb2.FOREIGN_FOO)
-    self.assertEqual(5, unittest_pb2.FOREIGN_BAR)
-    self.assertEqual(6, unittest_pb2.FOREIGN_BAZ)
-
-    proto = unittest_pb2.TestAllTypes()
-    self.assertEqual(1, proto.FOO)
-    self.assertEqual(1, unittest_pb2.TestAllTypes.FOO)
-    self.assertEqual(2, proto.BAR)
-    self.assertEqual(2, unittest_pb2.TestAllTypes.BAR)
-    self.assertEqual(3, proto.BAZ)
-    self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ)
-
-  def testExtremeDefaultValues(self):
-    message = unittest_pb2.TestExtremeDefaultValues()
-
-    # Python pre-2.6 does not have isinf() or isnan() functions, so we have
-    # to provide our own.
-    def isnan(val):
-      # NaN is never equal to itself.
-      return val != val
-    def isinf(val):
-      # Infinity times zero equals NaN.
-      return not isnan(val) and isnan(val * 0)
-
-    self.assertTrue(isinf(message.inf_double))
-    self.assertTrue(message.inf_double > 0)
-    self.assertTrue(isinf(message.neg_inf_double))
-    self.assertTrue(message.neg_inf_double < 0)
-    self.assertTrue(isnan(message.nan_double))
-
-    self.assertTrue(isinf(message.inf_float))
-    self.assertTrue(message.inf_float > 0)
-    self.assertTrue(isinf(message.neg_inf_float))
-    self.assertTrue(message.neg_inf_float < 0)
-    self.assertTrue(isnan(message.nan_float))
-    self.assertEqual("? ? ?? ?? ??? ??/ ??-", message.cpp_trigraph)
-
-  def testHasDefaultValues(self):
-    desc = unittest_pb2.TestAllTypes.DESCRIPTOR
-
-    expected_has_default_by_name = {
-        'optional_int32': False,
-        'repeated_int32': False,
-        'optional_nested_message': False,
-        'default_int32': True,
-    }
-
-    has_default_by_name = dict(
-        [(f.name, f.has_default_value)
-         for f in desc.fields
-         if f.name in expected_has_default_by_name])
-    self.assertEqual(expected_has_default_by_name, has_default_by_name)
-
-  def testContainingTypeBehaviorForExtensions(self):
-    self.assertEqual(unittest_pb2.optional_int32_extension.containing_type,
-                     unittest_pb2.TestAllExtensions.DESCRIPTOR)
-    self.assertEqual(unittest_pb2.TestRequired.single.containing_type,
-                     unittest_pb2.TestAllExtensions.DESCRIPTOR)
-
-  def testExtensionScope(self):
-    self.assertEqual(unittest_pb2.optional_int32_extension.extension_scope,
-                     None)
-    self.assertEqual(unittest_pb2.TestRequired.single.extension_scope,
-                     unittest_pb2.TestRequired.DESCRIPTOR)
-
-  def testIsExtension(self):
-    self.assertTrue(unittest_pb2.optional_int32_extension.is_extension)
-    self.assertTrue(unittest_pb2.TestRequired.single.is_extension)
-
-    message_descriptor = unittest_pb2.TestRequired.DESCRIPTOR
-    non_extension_descriptor = message_descriptor.fields_by_name['a']
-    self.assertTrue(not non_extension_descriptor.is_extension)
-
-  def testOptions(self):
-    proto = unittest_mset_pb2.TestMessageSet()
-    self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format)
-
-  def testMessageWithCustomOptions(self):
-    proto = unittest_custom_options_pb2.TestMessageWithCustomOptions()
-    enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions()
-    self.assertTrue(enum_options is not None)
-    # TODO(gps): We really should test for the presence of the enum_opt1
-    # extension and for its value to be set to -789.
-
-  def testNestedTypes(self):
-    self.assertEquals(
-        set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types),
-        set([
-            unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
-            unittest_pb2.TestAllTypes.OptionalGroup.DESCRIPTOR,
-            unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR,
-        ]))
-    self.assertEqual(unittest_pb2.TestEmptyMessage.DESCRIPTOR.nested_types, [])
-    self.assertEqual(
-        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.nested_types, [])
-
-  def testContainingType(self):
-    self.assertTrue(
-        unittest_pb2.TestEmptyMessage.DESCRIPTOR.containing_type is None)
-    self.assertTrue(
-        unittest_pb2.TestAllTypes.DESCRIPTOR.containing_type is None)
-    self.assertEqual(
-        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type,
-        unittest_pb2.TestAllTypes.DESCRIPTOR)
-    self.assertEqual(
-        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type,
-        unittest_pb2.TestAllTypes.DESCRIPTOR)
-    self.assertEqual(
-        unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR.containing_type,
-        unittest_pb2.TestAllTypes.DESCRIPTOR)
-
-  def testContainingTypeInEnumDescriptor(self):
-    self.assertTrue(unittest_pb2._FOREIGNENUM.containing_type is None)
-    self.assertEqual(unittest_pb2._TESTALLTYPES_NESTEDENUM.containing_type,
-                     unittest_pb2.TestAllTypes.DESCRIPTOR)
-
-  def testPackage(self):
-    self.assertEqual(
-        unittest_pb2.TestAllTypes.DESCRIPTOR.file.package,
-        'protobuf_unittest')
-    desc = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR
-    self.assertEqual(desc.file.package, 'protobuf_unittest')
-    self.assertEqual(
-        unittest_import_pb2.ImportMessage.DESCRIPTOR.file.package,
-        'protobuf_unittest_import')
-
-    self.assertEqual(
-        unittest_pb2._FOREIGNENUM.file.package, 'protobuf_unittest')
-    self.assertEqual(
-        unittest_pb2._TESTALLTYPES_NESTEDENUM.file.package,
-        'protobuf_unittest')
-    self.assertEqual(
-        unittest_import_pb2._IMPORTENUM.file.package,
-        'protobuf_unittest_import')
-
-  def testExtensionRange(self):
-    self.assertEqual(
-        unittest_pb2.TestAllTypes.DESCRIPTOR.extension_ranges, [])
-    self.assertEqual(
-        unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges,
-        [(1, MAX_EXTENSION)])
-    self.assertEqual(
-        unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges,
-        [(42, 43), (4143, 4244), (65536, MAX_EXTENSION)])
-
-  def testFileDescriptor(self):
-    self.assertEqual(unittest_pb2.DESCRIPTOR.name,
-                     'google/protobuf/unittest.proto')
-    self.assertEqual(unittest_pb2.DESCRIPTOR.package, 'protobuf_unittest')
-    self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None)
-
-  def testNoGenericServices(self):
-    self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage"))
-    self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO"))
-    self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension"))
-
-    # Make sure unittest_no_generic_services_pb2 has no services subclassing
-    # Proto2 Service class.
-    if hasattr(unittest_no_generic_services_pb2, "TestService"):
-      self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService,
-                                  service.Service))
-
-  def testMessageTypesByName(self):
-    file_type = unittest_pb2.DESCRIPTOR
-    self.assertEqual(
-        unittest_pb2._TESTALLTYPES,
-        file_type.message_types_by_name[unittest_pb2._TESTALLTYPES.name])
-
-    # Nested messages shouldn't be included in the message_types_by_name
-    # dictionary (like in the C++ API).
-    self.assertFalse(
-        unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in
-        file_type.message_types_by_name)
-
-  def testPublicImports(self):
-    # Test public imports as embedded message.
-    all_type_proto = unittest_pb2.TestAllTypes()
-    self.assertEqual(0, all_type_proto.optional_public_import_message.e)
-
-    # PublicImportMessage is actually defined in unittest_import_public_pb2
-    # module, and is public imported by unittest_import_pb2 module.
-    public_import_proto = unittest_import_pb2.PublicImportMessage()
-    self.assertEqual(0, public_import_proto.e)
-    self.assertTrue(unittest_import_public_pb2.PublicImportMessage is
-                    unittest_import_pb2.PublicImportMessage)
-
-  def testBadIdentifiers(self):
-    # We're just testing that the code was imported without problems.
-    message = test_bad_identifiers_pb2.TestBadIdentifiers()
-    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message],
-                     "foo")
-    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor],
-                     "bar")
-    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection],
-                     "baz")
-    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
-                     "qux")
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/golden_message b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/golden_message
deleted file mode 100644
index 4dd62cd..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/golden_message
+++ /dev/null
Binary files differ
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/golden_packed_fields_message b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/golden_packed_fields_message
deleted file mode 100644
index ee28d38..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/golden_packed_fields_message
+++ /dev/null
Binary files differ
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py
deleted file mode 100755
index e71b295..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py
+++ /dev/null
@@ -1,499 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# http://code.google.com/p/protobuf/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests python protocol buffers against the golden message.
-
-Note that the golden messages exercise every known field type, thus this
-test ends up exercising and verifying nearly all of the parsing and
-serialization code in the whole library.
-
-TODO(kenton):  Merge with wire_format_test?  It doesn't make a whole lot of
-sense to call this a test of the "message" module, which only declares an
-abstract interface.
-"""
-
-__author__ = 'gps@google.com (Gregory P. Smith)'
-
-import copy
-import math
-import operator
-import pickle
-
-import unittest
-from google.protobuf import unittest_import_pb2
-from google.protobuf import unittest_pb2
-from google.protobuf.internal import api_implementation
-from google.protobuf.internal import test_util
-from google.protobuf import message
-
-try:
-  cmp                                   # Python 2
-except NameError:
-  cmp = lambda x, y: (x > y) - (x < y)  # Python 3
-
-# Python pre-2.6 does not have isinf() or isnan() functions, so we have
-# to provide our own.
-def isnan(val):
-  # NaN is never equal to itself.
-  return val != val
-def isinf(val):
-  # Infinity times zero equals NaN.
-  return not isnan(val) and isnan(val * 0)
-def IsPosInf(val):
-  return isinf(val) and (val > 0)
-def IsNegInf(val):
-  return isinf(val) and (val < 0)
-
-class MessageTest(unittest.TestCase):
-
-  def testGoldenMessage(self):
-    golden_data = test_util.GoldenFile('golden_message').read()
-    golden_message = unittest_pb2.TestAllTypes()
-    golden_message.ParseFromString(golden_data)
-    test_util.ExpectAllFieldsSet(self, golden_message)
-    self.assertEqual(golden_data, golden_message.SerializeToString())
-    golden_copy = copy.deepcopy(golden_message)
-    self.assertEqual(golden_data, golden_copy.SerializeToString())
-
-  def testGoldenExtensions(self):
-    golden_data = test_util.GoldenFile('golden_message').read()
-    golden_message = unittest_pb2.TestAllExtensions()
-    golden_message.ParseFromString(golden_data)
-    all_set = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(all_set)
-    self.assertEquals(all_set, golden_message)
-    self.assertEqual(golden_data, golden_message.SerializeToString())
-    golden_copy = copy.deepcopy(golden_message)
-    self.assertEqual(golden_data, golden_copy.SerializeToString())
-
-  def testGoldenPackedMessage(self):
-    golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
-    golden_message = unittest_pb2.TestPackedTypes()
-    golden_message.ParseFromString(golden_data)
-    all_set = unittest_pb2.TestPackedTypes()
-    test_util.SetAllPackedFields(all_set)
-    self.assertEquals(all_set, golden_message)
-    self.assertEqual(golden_data, all_set.SerializeToString())
-    golden_copy = copy.deepcopy(golden_message)
-    self.assertEqual(golden_data, golden_copy.SerializeToString())
-
-  def testGoldenPackedExtensions(self):
-    golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
-    golden_message = unittest_pb2.TestPackedExtensions()
-    golden_message.ParseFromString(golden_data)
-    all_set = unittest_pb2.TestPackedExtensions()
-    test_util.SetAllPackedExtensions(all_set)
-    self.assertEquals(all_set, golden_message)
-    self.assertEqual(golden_data, all_set.SerializeToString())
-    golden_copy = copy.deepcopy(golden_message)
-    self.assertEqual(golden_data, golden_copy.SerializeToString())
-
-  def testPickleSupport(self):
-    golden_data = test_util.GoldenFile('golden_message').read()
-    golden_message = unittest_pb2.TestAllTypes()
-    golden_message.ParseFromString(golden_data)
-    pickled_message = pickle.dumps(golden_message)
-
-    unpickled_message = pickle.loads(pickled_message)
-    self.assertEquals(unpickled_message, golden_message)
-
-  def testPickleIncompleteProto(self):
-    golden_message = unittest_pb2.TestRequired(a=1)
-    pickled_message = pickle.dumps(golden_message)
-
-    unpickled_message = pickle.loads(pickled_message)
-    self.assertEquals(unpickled_message, golden_message)
-    self.assertEquals(unpickled_message.a, 1)
-    # This is still an incomplete proto - so serializing should fail
-    self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
-
-  def testPositiveInfinity(self):
-    golden_data = ('\x5D\x00\x00\x80\x7F'
-                   '\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
-                   '\xCD\x02\x00\x00\x80\x7F'
-                   '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F')
-    golden_message = unittest_pb2.TestAllTypes()
-    golden_message.ParseFromString(golden_data)
-    self.assertTrue(IsPosInf(golden_message.optional_float))
-    self.assertTrue(IsPosInf(golden_message.optional_double))
-    self.assertTrue(IsPosInf(golden_message.repeated_float[0]))
-    self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
-    self.assertEqual(golden_data, golden_message.SerializeToString())
-
-  def testNegativeInfinity(self):
-    golden_data = ('\x5D\x00\x00\x80\xFF'
-                   '\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
-                   '\xCD\x02\x00\x00\x80\xFF'
-                   '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
-    golden_message = unittest_pb2.TestAllTypes()
-    golden_message.ParseFromString(golden_data)
-    self.assertTrue(IsNegInf(golden_message.optional_float))
-    self.assertTrue(IsNegInf(golden_message.optional_double))
-    self.assertTrue(IsNegInf(golden_message.repeated_float[0]))
-    self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
-    self.assertEqual(golden_data, golden_message.SerializeToString())
-
-  def testNotANumber(self):
-    golden_data = ('\x5D\x00\x00\xC0\x7F'
-                   '\x61\x00\x00\x00\x00\x00\x00\xF8\x7F'
-                   '\xCD\x02\x00\x00\xC0\x7F'
-                   '\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F')
-    golden_message = unittest_pb2.TestAllTypes()
-    golden_message.ParseFromString(golden_data)
-    self.assertTrue(isnan(golden_message.optional_float))
-    self.assertTrue(isnan(golden_message.optional_double))
-    self.assertTrue(isnan(golden_message.repeated_float[0]))
-    self.assertTrue(isnan(golden_message.repeated_double[0]))
-
-    # The protocol buffer may serialize to any one of multiple different
-    # representations of a NaN.  Rather than verify a specific representation,
-    # verify the serialized string can be converted into a correctly
-    # behaving protocol buffer.
-    serialized = golden_message.SerializeToString()
-    message = unittest_pb2.TestAllTypes()
-    message.ParseFromString(serialized)
-    self.assertTrue(isnan(message.optional_float))
-    self.assertTrue(isnan(message.optional_double))
-    self.assertTrue(isnan(message.repeated_float[0]))
-    self.assertTrue(isnan(message.repeated_double[0]))
-
-  def testPositiveInfinityPacked(self):
-    golden_data = ('\xA2\x06\x04\x00\x00\x80\x7F'
-                   '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
-    golden_message = unittest_pb2.TestPackedTypes()
-    golden_message.ParseFromString(golden_data)
-    self.assertTrue(IsPosInf(golden_message.packed_float[0]))
-    self.assertTrue(IsPosInf(golden_message.packed_double[0]))
-    self.assertEqual(golden_data, golden_message.SerializeToString())
-
-  def testNegativeInfinityPacked(self):
-    golden_data = ('\xA2\x06\x04\x00\x00\x80\xFF'
-                   '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
-    golden_message = unittest_pb2.TestPackedTypes()
-    golden_message.ParseFromString(golden_data)
-    self.assertTrue(IsNegInf(golden_message.packed_float[0]))
-    self.assertTrue(IsNegInf(golden_message.packed_double[0]))
-    self.assertEqual(golden_data, golden_message.SerializeToString())
-
-  def testNotANumberPacked(self):
-    golden_data = ('\xA2\x06\x04\x00\x00\xC0\x7F'
-                   '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F')
-    golden_message = unittest_pb2.TestPackedTypes()
-    golden_message.ParseFromString(golden_data)
-    self.assertTrue(isnan(golden_message.packed_float[0]))
-    self.assertTrue(isnan(golden_message.packed_double[0]))
-
-    serialized = golden_message.SerializeToString()
-    message = unittest_pb2.TestPackedTypes()
-    message.ParseFromString(serialized)
-    self.assertTrue(isnan(message.packed_float[0]))
-    self.assertTrue(isnan(message.packed_double[0]))
-
-  def testExtremeFloatValues(self):
-    message = unittest_pb2.TestAllTypes()
-
-    # Most positive exponent, no significand bits set.
-    kMostPosExponentNoSigBits = math.pow(2, 127)
-    message.optional_float = kMostPosExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == kMostPosExponentNoSigBits)
-
-    # Most positive exponent, one significand bit set.
-    kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127)
-    message.optional_float = kMostPosExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == kMostPosExponentOneSigBit)
-
-    # Repeat last two cases with values of same magnitude, but negative.
-    message.optional_float = -kMostPosExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits)
-
-    message.optional_float = -kMostPosExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit)
-
-    # Most negative exponent, no significand bits set.
-    kMostNegExponentNoSigBits = math.pow(2, -127)
-    message.optional_float = kMostNegExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == kMostNegExponentNoSigBits)
-
-    # Most negative exponent, one significand bit set.
-    kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127)
-    message.optional_float = kMostNegExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == kMostNegExponentOneSigBit)
-
-    # Repeat last two cases with values of the same magnitude, but negative.
-    message.optional_float = -kMostNegExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits)
-
-    message.optional_float = -kMostNegExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
-
-  def testExtremeDoubleValues(self):
-    message = unittest_pb2.TestAllTypes()
-
-    # Most positive exponent, no significand bits set.
-    kMostPosExponentNoSigBits = math.pow(2, 1023)
-    message.optional_double = kMostPosExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == kMostPosExponentNoSigBits)
-
-    # Most positive exponent, one significand bit set.
-    kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023)
-    message.optional_double = kMostPosExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == kMostPosExponentOneSigBit)
-
-    # Repeat last two cases with values of same magnitude, but negative.
-    message.optional_double = -kMostPosExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits)
-
-    message.optional_double = -kMostPosExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit)
-
-    # Most negative exponent, no significand bits set.
-    kMostNegExponentNoSigBits = math.pow(2, -1023)
-    message.optional_double = kMostNegExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == kMostNegExponentNoSigBits)
-
-    # Most negative exponent, one significand bit set.
-    kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023)
-    message.optional_double = kMostNegExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == kMostNegExponentOneSigBit)
-
-    # Repeat last two cases with values of the same magnitude, but negative.
-    message.optional_double = -kMostNegExponentNoSigBits
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits)
-
-    message.optional_double = -kMostNegExponentOneSigBit
-    message.ParseFromString(message.SerializeToString())
-    self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit)
-
-  def testSortingRepeatedScalarFieldsDefaultComparator(self):
-    """Check some different types with the default comparator."""
-    message = unittest_pb2.TestAllTypes()
-
-    # TODO(mattp): would testing more scalar types strengthen test?
-    message.repeated_int32.append(1)
-    message.repeated_int32.append(3)
-    message.repeated_int32.append(2)
-    message.repeated_int32.sort()
-    self.assertEqual(message.repeated_int32[0], 1)
-    self.assertEqual(message.repeated_int32[1], 2)
-    self.assertEqual(message.repeated_int32[2], 3)
-
-    message.repeated_float.append(1.1)
-    message.repeated_float.append(1.3)
-    message.repeated_float.append(1.2)
-    message.repeated_float.sort()
-    self.assertAlmostEqual(message.repeated_float[0], 1.1)
-    self.assertAlmostEqual(message.repeated_float[1], 1.2)
-    self.assertAlmostEqual(message.repeated_float[2], 1.3)
-
-    message.repeated_string.append('a')
-    message.repeated_string.append('c')
-    message.repeated_string.append('b')
-    message.repeated_string.sort()
-    self.assertEqual(message.repeated_string[0], 'a')
-    self.assertEqual(message.repeated_string[1], 'b')
-    self.assertEqual(message.repeated_string[2], 'c')
-
-    message.repeated_bytes.append('a')
-    message.repeated_bytes.append('c')
-    message.repeated_bytes.append('b')
-    message.repeated_bytes.sort()
-    self.assertEqual(message.repeated_bytes[0], 'a')
-    self.assertEqual(message.repeated_bytes[1], 'b')
-    self.assertEqual(message.repeated_bytes[2], 'c')
-
-  def testSortingRepeatedScalarFieldsCustomComparator(self):
-    """Check some different types with custom comparator."""
-    message = unittest_pb2.TestAllTypes()
-
-    message.repeated_int32.append(-3)
-    message.repeated_int32.append(-2)
-    message.repeated_int32.append(-1)
-    message.repeated_int32.sort(lambda x,y: cmp(abs(x), abs(y)))
-    self.assertEqual(message.repeated_int32[0], -1)
-    self.assertEqual(message.repeated_int32[1], -2)
-    self.assertEqual(message.repeated_int32[2], -3)
-
-    message.repeated_string.append('aaa')
-    message.repeated_string.append('bb')
-    message.repeated_string.append('c')
-    message.repeated_string.sort(lambda x,y: cmp(len(x), len(y)))
-    self.assertEqual(message.repeated_string[0], 'c')
-    self.assertEqual(message.repeated_string[1], 'bb')
-    self.assertEqual(message.repeated_string[2], 'aaa')
-
-  def testSortingRepeatedCompositeFieldsCustomComparator(self):
-    """Check passing a custom comparator to sort a repeated composite field."""
-    message = unittest_pb2.TestAllTypes()
-
-    message.repeated_nested_message.add().bb = 1
-    message.repeated_nested_message.add().bb = 3
-    message.repeated_nested_message.add().bb = 2
-    message.repeated_nested_message.add().bb = 6
-    message.repeated_nested_message.add().bb = 5
-    message.repeated_nested_message.add().bb = 4
-    message.repeated_nested_message.sort(lambda x,y: cmp(x.bb, y.bb))
-    self.assertEqual(message.repeated_nested_message[0].bb, 1)
-    self.assertEqual(message.repeated_nested_message[1].bb, 2)
-    self.assertEqual(message.repeated_nested_message[2].bb, 3)
-    self.assertEqual(message.repeated_nested_message[3].bb, 4)
-    self.assertEqual(message.repeated_nested_message[4].bb, 5)
-    self.assertEqual(message.repeated_nested_message[5].bb, 6)
-
-  def testRepeatedCompositeFieldSortArguments(self):
-    """Check sorting a repeated composite field using list.sort() arguments."""
-    message = unittest_pb2.TestAllTypes()
-
-    get_bb = operator.attrgetter('bb')
-    cmp_bb = lambda a, b: cmp(a.bb, b.bb)
-    message.repeated_nested_message.add().bb = 1
-    message.repeated_nested_message.add().bb = 3
-    message.repeated_nested_message.add().bb = 2
-    message.repeated_nested_message.add().bb = 6
-    message.repeated_nested_message.add().bb = 5
-    message.repeated_nested_message.add().bb = 4
-    message.repeated_nested_message.sort(key=get_bb)
-    self.assertEqual([k.bb for k in message.repeated_nested_message],
-                     [1, 2, 3, 4, 5, 6])
-    message.repeated_nested_message.sort(key=get_bb, reverse=True)
-    self.assertEqual([k.bb for k in message.repeated_nested_message],
-                     [6, 5, 4, 3, 2, 1])
-    message.repeated_nested_message.sort(sort_function=cmp_bb)
-    self.assertEqual([k.bb for k in message.repeated_nested_message],
-                     [1, 2, 3, 4, 5, 6])
-    message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True)
-    self.assertEqual([k.bb for k in message.repeated_nested_message],
-                     [6, 5, 4, 3, 2, 1])
-
-  def testRepeatedScalarFieldSortArguments(self):
-    """Check sorting a scalar field using list.sort() arguments."""
-    message = unittest_pb2.TestAllTypes()
-
-    abs_cmp = lambda a, b: cmp(abs(a), abs(b))
-    message.repeated_int32.append(-3)
-    message.repeated_int32.append(-2)
-    message.repeated_int32.append(-1)
-    message.repeated_int32.sort(key=abs)
-    self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
-    message.repeated_int32.sort(key=abs, reverse=True)
-    self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
-    message.repeated_int32.sort(sort_function=abs_cmp)
-    self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
-    message.repeated_int32.sort(cmp=abs_cmp, reverse=True)
-    self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
-
-    len_cmp = lambda a, b: cmp(len(a), len(b))
-    message.repeated_string.append('aaa')
-    message.repeated_string.append('bb')
-    message.repeated_string.append('c')
-    message.repeated_string.sort(key=len)
-    self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
-    message.repeated_string.sort(key=len, reverse=True)
-    self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
-    message.repeated_string.sort(sort_function=len_cmp)
-    self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
-    message.repeated_string.sort(cmp=len_cmp, reverse=True)
-    self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
-
-  def testParsingMerge(self):
-    """Check the merge behavior when a required or optional field appears
-    multiple times in the input."""
-    messages = [
-        unittest_pb2.TestAllTypes(),
-        unittest_pb2.TestAllTypes(),
-        unittest_pb2.TestAllTypes() ]
-    messages[0].optional_int32 = 1
-    messages[1].optional_int64 = 2
-    messages[2].optional_int32 = 3
-    messages[2].optional_string = 'hello'
-
-    merged_message = unittest_pb2.TestAllTypes()
-    merged_message.optional_int32 = 3
-    merged_message.optional_int64 = 2
-    merged_message.optional_string = 'hello'
-
-    generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
-    generator.field1.extend(messages)
-    generator.field2.extend(messages)
-    generator.field3.extend(messages)
-    generator.ext1.extend(messages)
-    generator.ext2.extend(messages)
-    generator.group1.add().field1.MergeFrom(messages[0])
-    generator.group1.add().field1.MergeFrom(messages[1])
-    generator.group1.add().field1.MergeFrom(messages[2])
-    generator.group2.add().field1.MergeFrom(messages[0])
-    generator.group2.add().field1.MergeFrom(messages[1])
-    generator.group2.add().field1.MergeFrom(messages[2])
-
-    data = generator.SerializeToString()
-    parsing_merge = unittest_pb2.TestParsingMerge()
-    parsing_merge.ParseFromString(data)
-
-    # Required and optional fields should be merged.
-    self.assertEqual(parsing_merge.required_all_types, merged_message)
-    self.assertEqual(parsing_merge.optional_all_types, merged_message)
-    self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
-                     merged_message)
-    self.assertEqual(parsing_merge.Extensions[
-                     unittest_pb2.TestParsingMerge.optional_ext],
-                     merged_message)
-
-    # Repeated fields should not be merged.
-    self.assertEqual(len(parsing_merge.repeated_all_types), 3)
-    self.assertEqual(len(parsing_merge.repeatedgroup), 3)
-    self.assertEqual(len(parsing_merge.Extensions[
-        unittest_pb2.TestParsingMerge.repeated_ext]), 3)
-
-
-  def testSortEmptyRepeatedCompositeContainer(self):
-    """Exercise a scenario that has led to segfaults in the past.
-    """
-    m = unittest_pb2.TestAllTypes()
-    m.repeated_nested_message.sort()
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/service_reflection_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/service_reflection_test.py
deleted file mode 100755
index 9b7356f..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/service_reflection_test.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# http://code.google.com/p/protobuf/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests for google.protobuf.internal.service_reflection."""
-
-__author__ = 'petar@google.com (Petar Petrov)'
-
-import unittest
-from google.protobuf import unittest_pb2
-from google.protobuf import service_reflection
-from google.protobuf import service
-
-
-class FooUnitTest(unittest.TestCase):
-
-  def testService(self):
-    class MockRpcChannel(service.RpcChannel):
-      def CallMethod(self, method, controller, request, response, callback):
-        self.method = method
-        self.controller = controller
-        self.request = request
-        callback(response)
-
-    class MockRpcController(service.RpcController):
-      def SetFailed(self, msg):
-        self.failure_message = msg
-
-    self.callback_response = None
-
-    class MyService(unittest_pb2.TestService):
-      pass
-
-    self.callback_response = None
-
-    def MyCallback(response):
-      self.callback_response = response
-
-    rpc_controller = MockRpcController()
-    channel = MockRpcChannel()
-    srvc = MyService()
-    srvc.Foo(rpc_controller, unittest_pb2.FooRequest(), MyCallback)
-    self.assertEqual('Method Foo not implemented.',
-                     rpc_controller.failure_message)
-    self.assertEqual(None, self.callback_response)
-
-    rpc_controller.failure_message = None
-
-    service_descriptor = unittest_pb2.TestService.GetDescriptor()
-    srvc.CallMethod(service_descriptor.methods[1], rpc_controller,
-                    unittest_pb2.BarRequest(), MyCallback)
-    self.assertEqual('Method Bar not implemented.',
-                     rpc_controller.failure_message)
-    self.assertEqual(None, self.callback_response)
-
-    class MyServiceImpl(unittest_pb2.TestService):
-      def Foo(self, rpc_controller, request, done):
-        self.foo_called = True
-      def Bar(self, rpc_controller, request, done):
-        self.bar_called = True
-
-    srvc = MyServiceImpl()
-    rpc_controller.failure_message = None
-    srvc.Foo(rpc_controller, unittest_pb2.FooRequest(), MyCallback)
-    self.assertEqual(None, rpc_controller.failure_message)
-    self.assertEqual(True, srvc.foo_called)
-
-    rpc_controller.failure_message = None
-    srvc.CallMethod(service_descriptor.methods[1], rpc_controller,
-                    unittest_pb2.BarRequest(), MyCallback)
-    self.assertEqual(None, rpc_controller.failure_message)
-    self.assertEqual(True, srvc.bar_called)
-
-  def testServiceStub(self):
-    class MockRpcChannel(service.RpcChannel):
-      def CallMethod(self, method, controller, request,
-                     response_class, callback):
-        self.method = method
-        self.controller = controller
-        self.request = request
-        callback(response_class())
-
-    self.callback_response = None
-
-    def MyCallback(response):
-      self.callback_response = response
-
-    channel = MockRpcChannel()
-    stub = unittest_pb2.TestService_Stub(channel)
-    rpc_controller = 'controller'
-    request = 'request'
-
-    # GetDescriptor now static, still works as instance method for compatibility
-    self.assertEqual(unittest_pb2.TestService_Stub.GetDescriptor(),
-                     stub.GetDescriptor())
-
-    # Invoke method.
-    stub.Foo(rpc_controller, request, MyCallback)
-
-    self.assertTrue(isinstance(self.callback_response,
-                               unittest_pb2.FooResponse))
-    self.assertEqual(request, channel.request)
-    self.assertEqual(rpc_controller, channel.controller)
-    self.assertEqual(stub.GetDescriptor().methods[0], channel.method)
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/test_util.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/test_util.py
deleted file mode 100644
index e2c9db0..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/test_util.py
+++ /dev/null
@@ -1,651 +0,0 @@
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# http://code.google.com/p/protobuf/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Utilities for Python proto2 tests.
-
-This is intentionally modeled on C++ code in
-//google/protobuf/test_util.*.
-"""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import os.path
-
-from google.protobuf import unittest_import_pb2
-from google.protobuf import unittest_pb2
-
-
-def SetAllNonLazyFields(message):
-  """Sets every non-lazy field in the message to a unique value.
-
-  Args:
-    message: A unittest_pb2.TestAllTypes instance.
-  """
-
-  #
-  # Optional fields.
-  #
-
-  message.optional_int32    = 101
-  message.optional_int64    = 102
-  message.optional_uint32   = 103
-  message.optional_uint64   = 104
-  message.optional_sint32   = 105
-  message.optional_sint64   = 106
-  message.optional_fixed32  = 107
-  message.optional_fixed64  = 108
-  message.optional_sfixed32 = 109
-  message.optional_sfixed64 = 110
-  message.optional_float    = 111
-  message.optional_double   = 112
-  message.optional_bool     = True
-  # TODO(robinson): Firmly spec out and test how
-  # protos interact with unicode.  One specific example:
-  # what happens if we change the literal below to
-  # u'115'?  What *should* happen?  Still some discussion
-  # to finish with Kenton about bytes vs. strings
-  # and forcing everything to be utf8. :-/
-  message.optional_string   = '115'
-  message.optional_bytes    = '116'
-
-  message.optionalgroup.a = 117
-  message.optional_nested_message.bb = 118
-  message.optional_foreign_message.c = 119
-  message.optional_import_message.d = 120
-  message.optional_public_import_message.e = 126
-
-  message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ
-  message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ
-  message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ
-
-  message.optional_string_piece = '124'
-  message.optional_cord = '125'
-
-  #
-  # Repeated fields.
-  #
-
-  message.repeated_int32.append(201)
-  message.repeated_int64.append(202)
-  message.repeated_uint32.append(203)
-  message.repeated_uint64.append(204)
-  message.repeated_sint32.append(205)
-  message.repeated_sint64.append(206)
-  message.repeated_fixed32.append(207)
-  message.repeated_fixed64.append(208)
-  message.repeated_sfixed32.append(209)
-  message.repeated_sfixed64.append(210)
-  message.repeated_float.append(211)
-  message.repeated_double.append(212)
-  message.repeated_bool.append(True)
-  message.repeated_string.append('215')
-  message.repeated_bytes.append('216')
-
-  message.repeatedgroup.add().a = 217
-  message.repeated_nested_message.add().bb = 218
-  message.repeated_foreign_message.add().c = 219
-  message.repeated_import_message.add().d = 220
-  message.repeated_lazy_message.add().bb = 227
-
-  message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR)
-  message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR)
-  message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR)
-
-  message.repeated_string_piece.append('224')
-  message.repeated_cord.append('225')
-
-  # Add a second one of each field.
-  message.repeated_int32.append(301)
-  message.repeated_int64.append(302)
-  message.repeated_uint32.append(303)
-  message.repeated_uint64.append(304)
-  message.repeated_sint32.append(305)
-  message.repeated_sint64.append(306)
-  message.repeated_fixed32.append(307)
-  message.repeated_fixed64.append(308)
-  message.repeated_sfixed32.append(309)
-  message.repeated_sfixed64.append(310)
-  message.repeated_float.append(311)
-  message.repeated_double.append(312)
-  message.repeated_bool.append(False)
-  message.repeated_string.append('315')
-  message.repeated_bytes.append('316')
-
-  message.repeatedgroup.add().a = 317
-  message.repeated_nested_message.add().bb = 318
-  message.repeated_foreign_message.add().c = 319
-  message.repeated_import_message.add().d = 320
-  message.repeated_lazy_message.add().bb = 327
-
-  message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ)
-  message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ)
-  message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ)
-
-  message.repeated_string_piece.append('324')
-  message.repeated_cord.append('325')
-
-  #
-  # Fields that have defaults.
-  #
-
-  message.default_int32 = 401
-  message.default_int64 = 402
-  message.default_uint32 = 403
-  message.default_uint64 = 404
-  message.default_sint32 = 405
-  message.default_sint64 = 406
-  message.default_fixed32 = 407
-  message.default_fixed64 = 408
-  message.default_sfixed32 = 409
-  message.default_sfixed64 = 410
-  message.default_float = 411
-  message.default_double = 412
-  message.default_bool = False
-  message.default_string = '415'
-  message.default_bytes = '416'
-
-  message.default_nested_enum = unittest_pb2.TestAllTypes.FOO
-  message.default_foreign_enum = unittest_pb2.FOREIGN_FOO
-  message.default_import_enum = unittest_import_pb2.IMPORT_FOO
-
-  message.default_string_piece = '424'
-  message.default_cord = '425'
-
-
-def SetAllFields(message):
-  SetAllNonLazyFields(message)
-  message.optional_lazy_message.bb = 127
-
-
-def SetAllExtensions(message):
-  """Sets every extension in the message to a unique value.
-
-  Args:
-    message: A unittest_pb2.TestAllExtensions instance.
-  """
-
-  extensions = message.Extensions
-  pb2 = unittest_pb2
-  import_pb2 = unittest_import_pb2
-
-  #
-  # Optional fields.
-  #
-
-  extensions[pb2.optional_int32_extension] = 101
-  extensions[pb2.optional_int64_extension] = 102
-  extensions[pb2.optional_uint32_extension] = 103
-  extensions[pb2.optional_uint64_extension] = 104
-  extensions[pb2.optional_sint32_extension] = 105
-  extensions[pb2.optional_sint64_extension] = 106
-  extensions[pb2.optional_fixed32_extension] = 107
-  extensions[pb2.optional_fixed64_extension] = 108
-  extensions[pb2.optional_sfixed32_extension] = 109
-  extensions[pb2.optional_sfixed64_extension] = 110
-  extensions[pb2.optional_float_extension] = 111
-  extensions[pb2.optional_double_extension] = 112
-  extensions[pb2.optional_bool_extension] = True
-  extensions[pb2.optional_string_extension] = '115'
-  extensions[pb2.optional_bytes_extension] = '116'
-
-  extensions[pb2.optionalgroup_extension].a = 117
-  extensions[pb2.optional_nested_message_extension].bb = 118
-  extensions[pb2.optional_foreign_message_extension].c = 119
-  extensions[pb2.optional_import_message_extension].d = 120
-  extensions[pb2.optional_public_import_message_extension].e = 126
-  extensions[pb2.optional_lazy_message_extension].bb = 127
-
-  extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
-  extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
-  extensions[pb2.optional_foreign_enum_extension] = pb2.FOREIGN_BAZ
-  extensions[pb2.optional_import_enum_extension] = import_pb2.IMPORT_BAZ
-
-  extensions[pb2.optional_string_piece_extension] = '124'
-  extensions[pb2.optional_cord_extension] = '125'
-
-  #
-  # Repeated fields.
-  #
-
-  extensions[pb2.repeated_int32_extension].append(201)
-  extensions[pb2.repeated_int64_extension].append(202)
-  extensions[pb2.repeated_uint32_extension].append(203)
-  extensions[pb2.repeated_uint64_extension].append(204)
-  extensions[pb2.repeated_sint32_extension].append(205)
-  extensions[pb2.repeated_sint64_extension].append(206)
-  extensions[pb2.repeated_fixed32_extension].append(207)
-  extensions[pb2.repeated_fixed64_extension].append(208)
-  extensions[pb2.repeated_sfixed32_extension].append(209)
-  extensions[pb2.repeated_sfixed64_extension].append(210)
-  extensions[pb2.repeated_float_extension].append(211)
-  extensions[pb2.repeated_double_extension].append(212)
-  extensions[pb2.repeated_bool_extension].append(True)
-  extensions[pb2.repeated_string_extension].append('215')
-  extensions[pb2.repeated_bytes_extension].append('216')
-
-  extensions[pb2.repeatedgroup_extension].add().a = 217
-  extensions[pb2.repeated_nested_message_extension].add().bb = 218
-  extensions[pb2.repeated_foreign_message_extension].add().c = 219
-  extensions[pb2.repeated_import_message_extension].add().d = 220
-  extensions[pb2.repeated_lazy_message_extension].add().bb = 227
-
-  extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAR)
-  extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAR)
-  extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAR)
-
-  extensions[pb2.repeated_string_piece_extension].append('224')
-  extensions[pb2.repeated_cord_extension].append('225')
-
-  # Append a second one of each field.
-  extensions[pb2.repeated_int32_extension].append(301)
-  extensions[pb2.repeated_int64_extension].append(302)
-  extensions[pb2.repeated_uint32_extension].append(303)
-  extensions[pb2.repeated_uint64_extension].append(304)
-  extensions[pb2.repeated_sint32_extension].append(305)
-  extensions[pb2.repeated_sint64_extension].append(306)
-  extensions[pb2.repeated_fixed32_extension].append(307)
-  extensions[pb2.repeated_fixed64_extension].append(308)
-  extensions[pb2.repeated_sfixed32_extension].append(309)
-  extensions[pb2.repeated_sfixed64_extension].append(310)
-  extensions[pb2.repeated_float_extension].append(311)
-  extensions[pb2.repeated_double_extension].append(312)
-  extensions[pb2.repeated_bool_extension].append(False)
-  extensions[pb2.repeated_string_extension].append('315')
-  extensions[pb2.repeated_bytes_extension].append('316')
-
-  extensions[pb2.repeatedgroup_extension].add().a = 317
-  extensions[pb2.repeated_nested_message_extension].add().bb = 318
-  extensions[pb2.repeated_foreign_message_extension].add().c = 319
-  extensions[pb2.repeated_import_message_extension].add().d = 320
-  extensions[pb2.repeated_lazy_message_extension].add().bb = 327
-
-  extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAZ)
-  extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAZ)
-  extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAZ)
-
-  extensions[pb2.repeated_string_piece_extension].append('324')
-  extensions[pb2.repeated_cord_extension].append('325')
-
-  #
-  # Fields with defaults.
-  #
-
-  extensions[pb2.default_int32_extension] = 401
-  extensions[pb2.default_int64_extension] = 402
-  extensions[pb2.default_uint32_extension] = 403
-  extensions[pb2.default_uint64_extension] = 404
-  extensions[pb2.default_sint32_extension] = 405
-  extensions[pb2.default_sint64_extension] = 406
-  extensions[pb2.default_fixed32_extension] = 407
-  extensions[pb2.default_fixed64_extension] = 408
-  extensions[pb2.default_sfixed32_extension] = 409
-  extensions[pb2.default_sfixed64_extension] = 410
-  extensions[pb2.default_float_extension] = 411
-  extensions[pb2.default_double_extension] = 412
-  extensions[pb2.default_bool_extension] = False
-  extensions[pb2.default_string_extension] = '415'
-  extensions[pb2.default_bytes_extension] = '416'
-
-  extensions[pb2.default_nested_enum_extension] = pb2.TestAllTypes.FOO
-  extensions[pb2.default_foreign_enum_extension] = pb2.FOREIGN_FOO
-  extensions[pb2.default_import_enum_extension] = import_pb2.IMPORT_FOO
-
-  extensions[pb2.default_string_piece_extension] = '424'
-  extensions[pb2.default_cord_extension] = '425'
-
-
-def SetAllFieldsAndExtensions(message):
-  """Sets every field and extension in the message to a unique value.
-
-  Args:
-    message: A unittest_pb2.TestAllExtensions message.
-  """
-  message.my_int = 1
-  message.my_string = 'foo'
-  message.my_float = 1.0
-  message.Extensions[unittest_pb2.my_extension_int] = 23
-  message.Extensions[unittest_pb2.my_extension_string] = 'bar'
-
-
-def ExpectAllFieldsAndExtensionsInOrder(serialized):
-  """Ensures that serialized is the serialization we expect for a message
-  filled with SetAllFieldsAndExtensions().  (Specifically, ensures that the
-  serialization is in canonical, tag-number order).
-  """
-  my_extension_int = unittest_pb2.my_extension_int
-  my_extension_string = unittest_pb2.my_extension_string
-  expected_strings = []
-  message = unittest_pb2.TestFieldOrderings()
-  message.my_int = 1  # Field 1.
-  expected_strings.append(message.SerializeToString())
-  message.Clear()
-  message.Extensions[my_extension_int] = 23  # Field 5.
-  expected_strings.append(message.SerializeToString())
-  message.Clear()
-  message.my_string = 'foo'  # Field 11.
-  expected_strings.append(message.SerializeToString())
-  message.Clear()
-  message.Extensions[my_extension_string] = 'bar'  # Field 50.
-  expected_strings.append(message.SerializeToString())
-  message.Clear()
-  message.my_float = 1.0
-  expected_strings.append(message.SerializeToString())
-  message.Clear()
-  expected = ''.join(expected_strings)
-
-  if expected != serialized:
-    raise ValueError('Expected %r, found %r' % (expected, serialized))
-
-
-def ExpectAllFieldsSet(test_case, message):
-  """Check all fields for correct values have after Set*Fields() is called."""
-  test_case.assertTrue(message.HasField('optional_int32'))
-  test_case.assertTrue(message.HasField('optional_int64'))
-  test_case.assertTrue(message.HasField('optional_uint32'))
-  test_case.assertTrue(message.HasField('optional_uint64'))
-  test_case.assertTrue(message.HasField('optional_sint32'))
-  test_case.assertTrue(message.HasField('optional_sint64'))
-  test_case.assertTrue(message.HasField('optional_fixed32'))
-  test_case.assertTrue(message.HasField('optional_fixed64'))
-  test_case.assertTrue(message.HasField('optional_sfixed32'))
-  test_case.assertTrue(message.HasField('optional_sfixed64'))
-  test_case.assertTrue(message.HasField('optional_float'))
-  test_case.assertTrue(message.HasField('optional_double'))
-  test_case.assertTrue(message.HasField('optional_bool'))
-  test_case.assertTrue(message.HasField('optional_string'))
-  test_case.assertTrue(message.HasField('optional_bytes'))
-
-  test_case.assertTrue(message.HasField('optionalgroup'))
-  test_case.assertTrue(message.HasField('optional_nested_message'))
-  test_case.assertTrue(message.HasField('optional_foreign_message'))
-  test_case.assertTrue(message.HasField('optional_import_message'))
-
-  test_case.assertTrue(message.optionalgroup.HasField('a'))
-  test_case.assertTrue(message.optional_nested_message.HasField('bb'))
-  test_case.assertTrue(message.optional_foreign_message.HasField('c'))
-  test_case.assertTrue(message.optional_import_message.HasField('d'))
-
-  test_case.assertTrue(message.HasField('optional_nested_enum'))
-  test_case.assertTrue(message.HasField('optional_foreign_enum'))
-  test_case.assertTrue(message.HasField('optional_import_enum'))
-
-  test_case.assertTrue(message.HasField('optional_string_piece'))
-  test_case.assertTrue(message.HasField('optional_cord'))
-
-  test_case.assertEqual(101, message.optional_int32)
-  test_case.assertEqual(102, message.optional_int64)
-  test_case.assertEqual(103, message.optional_uint32)
-  test_case.assertEqual(104, message.optional_uint64)
-  test_case.assertEqual(105, message.optional_sint32)
-  test_case.assertEqual(106, message.optional_sint64)
-  test_case.assertEqual(107, message.optional_fixed32)
-  test_case.assertEqual(108, message.optional_fixed64)
-  test_case.assertEqual(109, message.optional_sfixed32)
-  test_case.assertEqual(110, message.optional_sfixed64)
-  test_case.assertEqual(111, message.optional_float)
-  test_case.assertEqual(112, message.optional_double)
-  test_case.assertEqual(True, message.optional_bool)
-  test_case.assertEqual('115', message.optional_string)
-  test_case.assertEqual('116', message.optional_bytes)
-
-  test_case.assertEqual(117, message.optionalgroup.a)
-  test_case.assertEqual(118, message.optional_nested_message.bb)
-  test_case.assertEqual(119, message.optional_foreign_message.c)
-  test_case.assertEqual(120, message.optional_import_message.d)
-  test_case.assertEqual(126, message.optional_public_import_message.e)
-  test_case.assertEqual(127, message.optional_lazy_message.bb)
-
-  test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
-                        message.optional_nested_enum)
-  test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
-                        message.optional_foreign_enum)
-  test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
-                        message.optional_import_enum)
-
-  # -----------------------------------------------------------------
-
-  test_case.assertEqual(2, len(message.repeated_int32))
-  test_case.assertEqual(2, len(message.repeated_int64))
-  test_case.assertEqual(2, len(message.repeated_uint32))
-  test_case.assertEqual(2, len(message.repeated_uint64))
-  test_case.assertEqual(2, len(message.repeated_sint32))
-  test_case.assertEqual(2, len(message.repeated_sint64))
-  test_case.assertEqual(2, len(message.repeated_fixed32))
-  test_case.assertEqual(2, len(message.repeated_fixed64))
-  test_case.assertEqual(2, len(message.repeated_sfixed32))
-  test_case.assertEqual(2, len(message.repeated_sfixed64))
-  test_case.assertEqual(2, len(message.repeated_float))
-  test_case.assertEqual(2, len(message.repeated_double))
-  test_case.assertEqual(2, len(message.repeated_bool))
-  test_case.assertEqual(2, len(message.repeated_string))
-  test_case.assertEqual(2, len(message.repeated_bytes))
-
-  test_case.assertEqual(2, len(message.repeatedgroup))
-  test_case.assertEqual(2, len(message.repeated_nested_message))
-  test_case.assertEqual(2, len(message.repeated_foreign_message))
-  test_case.assertEqual(2, len(message.repeated_import_message))
-  test_case.assertEqual(2, len(message.repeated_nested_enum))
-  test_case.assertEqual(2, len(message.repeated_foreign_enum))
-  test_case.assertEqual(2, len(message.repeated_import_enum))
-
-  test_case.assertEqual(2, len(message.repeated_string_piece))
-  test_case.assertEqual(2, len(message.repeated_cord))
-
-  test_case.assertEqual(201, message.repeated_int32[0])
-  test_case.assertEqual(202, message.repeated_int64[0])
-  test_case.assertEqual(203, message.repeated_uint32[0])
-  test_case.assertEqual(204, message.repeated_uint64[0])
-  test_case.assertEqual(205, message.repeated_sint32[0])
-  test_case.assertEqual(206, message.repeated_sint64[0])
-  test_case.assertEqual(207, message.repeated_fixed32[0])
-  test_case.assertEqual(208, message.repeated_fixed64[0])
-  test_case.assertEqual(209, message.repeated_sfixed32[0])
-  test_case.assertEqual(210, message.repeated_sfixed64[0])
-  test_case.assertEqual(211, message.repeated_float[0])
-  test_case.assertEqual(212, message.repeated_double[0])
-  test_case.assertEqual(True, message.repeated_bool[0])
-  test_case.assertEqual('215', message.repeated_string[0])
-  test_case.assertEqual('216', message.repeated_bytes[0])
-
-  test_case.assertEqual(217, message.repeatedgroup[0].a)
-  test_case.assertEqual(218, message.repeated_nested_message[0].bb)
-  test_case.assertEqual(219, message.repeated_foreign_message[0].c)
-  test_case.assertEqual(220, message.repeated_import_message[0].d)
-  test_case.assertEqual(227, message.repeated_lazy_message[0].bb)
-
-  test_case.assertEqual(unittest_pb2.TestAllTypes.BAR,
-                        message.repeated_nested_enum[0])
-  test_case.assertEqual(unittest_pb2.FOREIGN_BAR,
-                        message.repeated_foreign_enum[0])
-  test_case.assertEqual(unittest_import_pb2.IMPORT_BAR,
-                        message.repeated_import_enum[0])
-
-  test_case.assertEqual(301, message.repeated_int32[1])
-  test_case.assertEqual(302, message.repeated_int64[1])
-  test_case.assertEqual(303, message.repeated_uint32[1])
-  test_case.assertEqual(304, message.repeated_uint64[1])
-  test_case.assertEqual(305, message.repeated_sint32[1])
-  test_case.assertEqual(306, message.repeated_sint64[1])
-  test_case.assertEqual(307, message.repeated_fixed32[1])
-  test_case.assertEqual(308, message.repeated_fixed64[1])
-  test_case.assertEqual(309, message.repeated_sfixed32[1])
-  test_case.assertEqual(310, message.repeated_sfixed64[1])
-  test_case.assertEqual(311, message.repeated_float[1])
-  test_case.assertEqual(312, message.repeated_double[1])
-  test_case.assertEqual(False, message.repeated_bool[1])
-  test_case.assertEqual('315', message.repeated_string[1])
-  test_case.assertEqual('316', message.repeated_bytes[1])
-
-  test_case.assertEqual(317, message.repeatedgroup[1].a)
-  test_case.assertEqual(318, message.repeated_nested_message[1].bb)
-  test_case.assertEqual(319, message.repeated_foreign_message[1].c)
-  test_case.assertEqual(320, message.repeated_import_message[1].d)
-  test_case.assertEqual(327, message.repeated_lazy_message[1].bb)
-
-  test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
-                        message.repeated_nested_enum[1])
-  test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
-                        message.repeated_foreign_enum[1])
-  test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
-                        message.repeated_import_enum[1])
-
-  # -----------------------------------------------------------------
-
-  test_case.assertTrue(message.HasField('default_int32'))
-  test_case.assertTrue(message.HasField('default_int64'))
-  test_case.assertTrue(message.HasField('default_uint32'))
-  test_case.assertTrue(message.HasField('default_uint64'))
-  test_case.assertTrue(message.HasField('default_sint32'))
-  test_case.assertTrue(message.HasField('default_sint64'))
-  test_case.assertTrue(message.HasField('default_fixed32'))
-  test_case.assertTrue(message.HasField('default_fixed64'))
-  test_case.assertTrue(message.HasField('default_sfixed32'))
-  test_case.assertTrue(message.HasField('default_sfixed64'))
-  test_case.assertTrue(message.HasField('default_float'))
-  test_case.assertTrue(message.HasField('default_double'))
-  test_case.assertTrue(message.HasField('default_bool'))
-  test_case.assertTrue(message.HasField('default_string'))
-  test_case.assertTrue(message.HasField('default_bytes'))
-
-  test_case.assertTrue(message.HasField('default_nested_enum'))
-  test_case.assertTrue(message.HasField('default_foreign_enum'))
-  test_case.assertTrue(message.HasField('default_import_enum'))
-
-  test_case.assertEqual(401, message.default_int32)
-  test_case.assertEqual(402, message.default_int64)
-  test_case.assertEqual(403, message.default_uint32)
-  test_case.assertEqual(404, message.default_uint64)
-  test_case.assertEqual(405, message.default_sint32)
-  test_case.assertEqual(406, message.default_sint64)
-  test_case.assertEqual(407, message.default_fixed32)
-  test_case.assertEqual(408, message.default_fixed64)
-  test_case.assertEqual(409, message.default_sfixed32)
-  test_case.assertEqual(410, message.default_sfixed64)
-  test_case.assertEqual(411, message.default_float)
-  test_case.assertEqual(412, message.default_double)
-  test_case.assertEqual(False, message.default_bool)
-  test_case.assertEqual('415', message.default_string)
-  test_case.assertEqual('416', message.default_bytes)
-
-  test_case.assertEqual(unittest_pb2.TestAllTypes.FOO,
-                        message.default_nested_enum)
-  test_case.assertEqual(unittest_pb2.FOREIGN_FOO,
-                        message.default_foreign_enum)
-  test_case.assertEqual(unittest_import_pb2.IMPORT_FOO,
-                        message.default_import_enum)
-
-def GoldenFile(filename):
-  """Finds the given golden file and returns a file object representing it."""
-
-  # Search up the directory tree looking for the C++ protobuf source code.
-  path = '.'
-  while os.path.exists(path):
-    if os.path.exists(os.path.join(path, 'tests/google/protobuf/internal')):
-      # Found it.  Load the golden file from the testdata directory.
-      full_path = os.path.join(path, 'tests/google/protobuf/internal', filename)
-      return open(full_path, 'rb')
-    path = os.path.join(path, '..')
-
-  raise RuntimeError(
-    'Could not find golden files.  This test must be run from within the '
-    'protobuf source package so that it can read test data files from the '
-    'C++ source tree.')
-
-
-def SetAllPackedFields(message):
-  """Sets every field in the message to a unique value.
-
-  Args:
-    message: A unittest_pb2.TestPackedTypes instance.
-  """
-  message.packed_int32.extend([601, 701])
-  message.packed_int64.extend([602, 702])
-  message.packed_uint32.extend([603, 703])
-  message.packed_uint64.extend([604, 704])
-  message.packed_sint32.extend([605, 705])
-  message.packed_sint64.extend([606, 706])
-  message.packed_fixed32.extend([607, 707])
-  message.packed_fixed64.extend([608, 708])
-  message.packed_sfixed32.extend([609, 709])
-  message.packed_sfixed64.extend([610, 710])
-  message.packed_float.extend([611.0, 711.0])
-  message.packed_double.extend([612.0, 712.0])
-  message.packed_bool.extend([True, False])
-  message.packed_enum.extend([unittest_pb2.FOREIGN_BAR,
-                              unittest_pb2.FOREIGN_BAZ])
-
-
-def SetAllPackedExtensions(message):
-  """Sets every extension in the message to a unique value.
-
-  Args:
-    message: A unittest_pb2.TestPackedExtensions instance.
-  """
-  extensions = message.Extensions
-  pb2 = unittest_pb2
-
-  extensions[pb2.packed_int32_extension].extend([601, 701])
-  extensions[pb2.packed_int64_extension].extend([602, 702])
-  extensions[pb2.packed_uint32_extension].extend([603, 703])
-  extensions[pb2.packed_uint64_extension].extend([604, 704])
-  extensions[pb2.packed_sint32_extension].extend([605, 705])
-  extensions[pb2.packed_sint64_extension].extend([606, 706])
-  extensions[pb2.packed_fixed32_extension].extend([607, 707])
-  extensions[pb2.packed_fixed64_extension].extend([608, 708])
-  extensions[pb2.packed_sfixed32_extension].extend([609, 709])
-  extensions[pb2.packed_sfixed64_extension].extend([610, 710])
-  extensions[pb2.packed_float_extension].extend([611.0, 711.0])
-  extensions[pb2.packed_double_extension].extend([612.0, 712.0])
-  extensions[pb2.packed_bool_extension].extend([True, False])
-  extensions[pb2.packed_enum_extension].extend([unittest_pb2.FOREIGN_BAR,
-                                                unittest_pb2.FOREIGN_BAZ])
-
-
-def SetAllUnpackedFields(message):
-  """Sets every field in the message to a unique value.
-
-  Args:
-    message: A unittest_pb2.TestUnpackedTypes instance.
-  """
-  message.unpacked_int32.extend([601, 701])
-  message.unpacked_int64.extend([602, 702])
-  message.unpacked_uint32.extend([603, 703])
-  message.unpacked_uint64.extend([604, 704])
-  message.unpacked_sint32.extend([605, 705])
-  message.unpacked_sint64.extend([606, 706])
-  message.unpacked_fixed32.extend([607, 707])
-  message.unpacked_fixed64.extend([608, 708])
-  message.unpacked_sfixed32.extend([609, 709])
-  message.unpacked_sfixed64.extend([610, 710])
-  message.unpacked_float.extend([611.0, 711.0])
-  message.unpacked_double.extend([612.0, 712.0])
-  message.unpacked_bool.extend([True, False])
-  message.unpacked_enum.extend([unittest_pb2.FOREIGN_BAR,
-                                unittest_pb2.FOREIGN_BAZ])
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py
deleted file mode 100755
index 0bee668..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py
+++ /dev/null
@@ -1,622 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# http://code.google.com/p/protobuf/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Test for google.protobuf.text_format."""
-
-__author__ = 'kenton@google.com (Kenton Varda)'
-
-import difflib
-import re
-
-import unittest
-from google.protobuf import text_format
-from google.protobuf.internal import test_util
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_mset_pb2
-
-
-class TextFormatTest(unittest.TestCase):
-  def ReadGolden(self, golden_filename):
-    f = test_util.GoldenFile(golden_filename)
-    golden_lines = f.readlines()
-    f.close()
-    return golden_lines
-
-  def CompareToGoldenFile(self, text, golden_filename):
-    golden_lines = self.ReadGolden(golden_filename)
-    self.CompareToGoldenLines(text, golden_lines)
-
-  def CompareToGoldenText(self, text, golden_text):
-    self.CompareToGoldenLines(text, golden_text.splitlines(1))
-
-  def CompareToGoldenLines(self, text, golden_lines):
-    actual_lines = text.splitlines(1)
-    self.assertEqual(golden_lines, actual_lines,
-      "Text doesn't match golden.  Diff:\n" +
-      ''.join(difflib.ndiff(golden_lines, actual_lines)))
-
-  def testPrintAllFields(self):
-    message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    self.CompareToGoldenFile(
-      self.RemoveRedundantZeros(text_format.MessageToString(message)),
-      'text_format_unittest_data.txt')
-
-  def testPrintAllExtensions(self):
-    message = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(message)
-    self.CompareToGoldenFile(
-      self.RemoveRedundantZeros(text_format.MessageToString(message)),
-      'text_format_unittest_extensions_data.txt')
-
-  def testPrintMessageSet(self):
-    message = unittest_mset_pb2.TestMessageSetContainer()
-    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
-    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
-    message.message_set.Extensions[ext1].i = 23
-    message.message_set.Extensions[ext2].str = 'foo'
-    self.CompareToGoldenText(text_format.MessageToString(message),
-      'message_set {\n'
-      '  [protobuf_unittest.TestMessageSetExtension1] {\n'
-      '    i: 23\n'
-      '  }\n'
-      '  [protobuf_unittest.TestMessageSetExtension2] {\n'
-      '    str: \"foo\"\n'
-      '  }\n'
-      '}\n')
-
-  """
-  def testPrintBadEnumValue(self):
-    message = unittest_pb2.TestAllTypes()
-    message.optional_nested_enum = 100
-    message.optional_foreign_enum = 101
-    message.optional_import_enum = 102
-    self.CompareToGoldenText(
-        text_format.MessageToString(message),
-        'optional_nested_enum: 100\n'
-        'optional_foreign_enum: 101\n'
-        'optional_import_enum: 102\n')
-
-  def testPrintBadEnumValueExtensions(self):
-    message = unittest_pb2.TestAllExtensions()
-    message.Extensions[unittest_pb2.optional_nested_enum_extension] = 100
-    message.Extensions[unittest_pb2.optional_foreign_enum_extension] = 101
-    message.Extensions[unittest_pb2.optional_import_enum_extension] = 102
-    self.CompareToGoldenText(
-        text_format.MessageToString(message),
-        '[protobuf_unittest.optional_nested_enum_extension]: 100\n'
-        '[protobuf_unittest.optional_foreign_enum_extension]: 101\n'
-        '[protobuf_unittest.optional_import_enum_extension]: 102\n')
-  """
-
-  def testPrintExotic(self):
-    message = unittest_pb2.TestAllTypes()
-    message.repeated_int64.append(-9223372036854775808)
-    message.repeated_uint64.append(18446744073709551615)
-    message.repeated_double.append(123.456)
-    message.repeated_double.append(1.23e22)
-    message.repeated_double.append(1.23e-18)
-    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
-    message.repeated_string.append(u'\u00fc\ua71f')
-    self.CompareToGoldenText(
-      self.RemoveRedundantZeros(text_format.MessageToString(message)),
-      'repeated_int64: -9223372036854775808\n'
-      'repeated_uint64: 18446744073709551615\n'
-      'repeated_double: 123.456\n'
-      'repeated_double: 1.23e+22\n'
-      'repeated_double: 1.23e-18\n'
-      'repeated_string: '
-        '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
-      'repeated_string: "\\303\\274\\352\\234\\237"\n')
-
-  def testPrintNestedMessageAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
-    msg = message.repeated_nested_message.add()
-    msg.bb = 42;
-    self.CompareToGoldenText(
-        text_format.MessageToString(message, as_one_line=True),
-        'repeated_nested_message { bb: 42 }')
-
-  def testPrintRepeatedFieldsAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
-    message.repeated_int32.append(1)
-    message.repeated_int32.append(1)
-    message.repeated_int32.append(3)
-    message.repeated_string.append("Google")
-    message.repeated_string.append("Zurich")
-    self.CompareToGoldenText(
-        text_format.MessageToString(message, as_one_line=True),
-        'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 '
-        'repeated_string: "Google" repeated_string: "Zurich"')
-
-  def testPrintNestedNewLineInStringAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
-    message.optional_string = "a\nnew\nline"
-    self.CompareToGoldenText(
-        text_format.MessageToString(message, as_one_line=True),
-        'optional_string: "a\\nnew\\nline"')
-
-  def testPrintMessageSetAsOneLine(self):
-    message = unittest_mset_pb2.TestMessageSetContainer()
-    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
-    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
-    message.message_set.Extensions[ext1].i = 23
-    message.message_set.Extensions[ext2].str = 'foo'
-    self.CompareToGoldenText(
-        text_format.MessageToString(message, as_one_line=True),
-        'message_set {'
-        ' [protobuf_unittest.TestMessageSetExtension1] {'
-        ' i: 23'
-        ' }'
-        ' [protobuf_unittest.TestMessageSetExtension2] {'
-        ' str: \"foo\"'
-        ' }'
-        ' }')
-
-  def testPrintExoticAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
-    message.repeated_int64.append(-9223372036854775808)
-    message.repeated_uint64.append(18446744073709551615)
-    message.repeated_double.append(123.456)
-    message.repeated_double.append(1.23e22)
-    message.repeated_double.append(1.23e-18)
-    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
-    message.repeated_string.append(u'\u00fc\ua71f')
-    self.CompareToGoldenText(
-      self.RemoveRedundantZeros(
-          text_format.MessageToString(message, as_one_line=True)),
-      'repeated_int64: -9223372036854775808'
-      ' repeated_uint64: 18446744073709551615'
-      ' repeated_double: 123.456'
-      ' repeated_double: 1.23e+22'
-      ' repeated_double: 1.23e-18'
-      ' repeated_string: '
-      '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""'
-      ' repeated_string: "\\303\\274\\352\\234\\237"')
-
-  def testRoundTripExoticAsOneLine(self):
-    message = unittest_pb2.TestAllTypes()
-    message.repeated_int64.append(-9223372036854775808)
-    message.repeated_uint64.append(18446744073709551615)
-    message.repeated_double.append(123.456)
-    message.repeated_double.append(1.23e22)
-    message.repeated_double.append(1.23e-18)
-    message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
-    message.repeated_string.append(u'\u00fc\ua71f')
-
-    # Test as_utf8 = False.
-    wire_text = text_format.MessageToString(
-        message, as_one_line=True, as_utf8=False)
-    parsed_message = unittest_pb2.TestAllTypes()
-    text_format.Merge(wire_text, parsed_message)
-    self.assertEquals(message, parsed_message)
-
-    # Test as_utf8 = True.
-    wire_text = text_format.MessageToString(
-        message, as_one_line=True, as_utf8=True)
-    parsed_message = unittest_pb2.TestAllTypes()
-    text_format.Merge(wire_text, parsed_message)
-    self.assertEquals(message, parsed_message)
-
-  def testPrintRawUtf8String(self):
-    message = unittest_pb2.TestAllTypes()
-    message.repeated_string.append(u'\u00fc\ua71f')
-    text = text_format.MessageToString(message, as_utf8 = True)
-    self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n')
-    parsed_message = unittest_pb2.TestAllTypes()
-    text_format.Merge(text, parsed_message)
-    self.assertEquals(message, parsed_message)
-
-  def testMessageToString(self):
-    message = unittest_pb2.ForeignMessage()
-    message.c = 123
-    self.assertEqual('c: 123\n', str(message))
-
-  def RemoveRedundantZeros(self, text):
-    # Some platforms print 1e+5 as 1e+005.  This is fine, but we need to remove
-    # these zeros in order to match the golden file.
-    text = text.replace('e+0','e+').replace('e+0','e+') \
-               .replace('e-0','e-').replace('e-0','e-')
-    # Floating point fields are printed with .0 suffix even if they are
-    # actually integer numbers.
-    text = re.compile(r'\.0$', re.MULTILINE).sub('', text)
-    return text
-
-  def testMergeGolden(self):
-    golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
-    parsed_message = unittest_pb2.TestAllTypes()
-    text_format.Merge(golden_text, parsed_message)
-
-    message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    self.assertEquals(message, parsed_message)
-
-  def testMergeGoldenExtensions(self):
-    golden_text = '\n'.join(self.ReadGolden(
-        'text_format_unittest_extensions_data.txt'))
-    parsed_message = unittest_pb2.TestAllExtensions()
-    text_format.Merge(golden_text, parsed_message)
-
-    message = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(message)
-    self.assertEquals(message, parsed_message)
-
-  def testMergeAllFields(self):
-    message = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(message)
-    ascii_text = text_format.MessageToString(message)
-
-    parsed_message = unittest_pb2.TestAllTypes()
-    text_format.Merge(ascii_text, parsed_message)
-    self.assertEqual(message, parsed_message)
-    test_util.ExpectAllFieldsSet(self, message)
-
-  def testMergeAllExtensions(self):
-    message = unittest_pb2.TestAllExtensions()
-    test_util.SetAllExtensions(message)
-    ascii_text = text_format.MessageToString(message)
-
-    parsed_message = unittest_pb2.TestAllExtensions()
-    text_format.Merge(ascii_text, parsed_message)
-    self.assertEqual(message, parsed_message)
-
-  def testMergeMessageSet(self):
-    message = unittest_pb2.TestAllTypes()
-    text = ('repeated_uint64: 1\n'
-            'repeated_uint64: 2\n')
-    text_format.Merge(text, message)
-    self.assertEqual(1, message.repeated_uint64[0])
-    self.assertEqual(2, message.repeated_uint64[1])
-
-    message = unittest_mset_pb2.TestMessageSetContainer()
-    text = ('message_set {\n'
-            '  [protobuf_unittest.TestMessageSetExtension1] {\n'
-            '    i: 23\n'
-            '  }\n'
-            '  [protobuf_unittest.TestMessageSetExtension2] {\n'
-            '    str: \"foo\"\n'
-            '  }\n'
-            '}\n')
-    text_format.Merge(text, message)
-    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
-    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
-    self.assertEquals(23, message.message_set.Extensions[ext1].i)
-    self.assertEquals('foo', message.message_set.Extensions[ext2].str)
-
-  def testMergeExotic(self):
-    message = unittest_pb2.TestAllTypes()
-    text = ('repeated_int64: -9223372036854775808\n'
-            'repeated_uint64: 18446744073709551615\n'
-            'repeated_double: 123.456\n'
-            'repeated_double: 1.23e+22\n'
-            'repeated_double: 1.23e-18\n'
-            'repeated_string: \n'
-            '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
-            'repeated_string: "foo" \'corge\' "grault"\n'
-            'repeated_string: "\\303\\274\\352\\234\\237"\n'
-            'repeated_string: "\\xc3\\xbc"\n'
-            'repeated_string: "\xc3\xbc"\n')
-    text_format.Merge(text, message)
-
-    self.assertEqual(-9223372036854775808, message.repeated_int64[0])
-    self.assertEqual(18446744073709551615, message.repeated_uint64[0])
-    self.assertEqual(123.456, message.repeated_double[0])
-    self.assertEqual(1.23e22, message.repeated_double[1])
-    self.assertEqual(1.23e-18, message.repeated_double[2])
-    self.assertEqual(
-        '\000\001\a\b\f\n\r\t\v\\\'"', message.repeated_string[0])
-    self.assertEqual('foocorgegrault', message.repeated_string[1])
-    self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2])
-    self.assertEqual(u'\u00fc', message.repeated_string[3])
-
-  def testMergeEmptyText(self):
-    message = unittest_pb2.TestAllTypes()
-    text = ''
-    text_format.Merge(text, message)
-    self.assertEquals(unittest_pb2.TestAllTypes(), message)
-
-  def testMergeInvalidUtf8(self):
-    message = unittest_pb2.TestAllTypes()
-    text = 'repeated_string: "\\xc3\\xc3"'
-    self.assertRaises(text_format.ParseError, text_format.Merge, text, message)
-
-  def testMergeSingleWord(self):
-    message = unittest_pb2.TestAllTypes()
-    text = 'foo'
-    self.assertRaisesWithMessage(
-        text_format.ParseError,
-        ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
-         '"foo".'),
-        text_format.Merge, text, message)
-
-  def testMergeUnknownField(self):
-    message = unittest_pb2.TestAllTypes()
-    text = 'unknown_field: 8\n'
-    self.assertRaisesWithMessage(
-        text_format.ParseError,
-        ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
-         '"unknown_field".'),
-        text_format.Merge, text, message)
-
-  def testMergeBadExtension(self):
-    message = unittest_pb2.TestAllExtensions()
-    text = '[unknown_extension]: 8\n'
-    self.assertRaises(
-        text_format.ParseError,
-        text_format.Merge, text, message)
-    message = unittest_pb2.TestAllTypes()
-    self.assertRaisesWithMessage(
-        text_format.ParseError,
-        ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
-         'extensions.'),
-        text_format.Merge, text, message)
-
-  def testMergeGroupNotClosed(self):
-    message = unittest_pb2.TestAllTypes()
-    text = 'RepeatedGroup: <'
-    self.assertRaisesWithMessage(
-        text_format.ParseError, '1:16 : Expected ">".',
-        text_format.Merge, text, message)
-
-    text = 'RepeatedGroup: {'
-    self.assertRaisesWithMessage(
-        text_format.ParseError, '1:16 : Expected "}".',
-        text_format.Merge, text, message)
-
-  def testMergeEmptyGroup(self):
-    message = unittest_pb2.TestAllTypes()
-    text = 'OptionalGroup: {}'
-    text_format.Merge(text, message)
-    self.assertTrue(message.HasField('optionalgroup'))
-
-    message.Clear()
-
-    message = unittest_pb2.TestAllTypes()
-    text = 'OptionalGroup: <>'
-    text_format.Merge(text, message)
-    self.assertTrue(message.HasField('optionalgroup'))
-
-  def testMergeBadEnumValue(self):
-    message = unittest_pb2.TestAllTypes()
-    text = 'optional_nested_enum: BARR'
-    self.assertRaisesWithMessage(
-        text_format.ParseError,
-        ('1:23 : \'optional_nested_enum: BARR\': '
-         'Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
-         'has no value named BARR.'),
-        text_format.Merge, text, message)
-
-    message = unittest_pb2.TestAllTypes()
-    text = 'optional_nested_enum: 100'
-    self.assertRaisesWithMessage(
-        text_format.ParseError,
-        ('1:23 : \'optional_nested_enum: 100\': '
-         'Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
-         'has no value with number 100.'),
-        text_format.Merge, text, message)
-
-  def testMergeBadIntValue(self):
-    message = unittest_pb2.TestAllTypes()
-    text = 'optional_int32: bork'
-    self.assertRaisesWithMessage(
-        text_format.ParseError,
-        ('1:17 : \'optional_int32: bork\': '
-         'Couldn\'t parse integer: bork'),
-        text_format.Merge, text, message)
-
-  def testMergeStringFieldUnescape(self):
-    message = unittest_pb2.TestAllTypes()
-    text = r'''repeated_string: "\xf\x62"
-               repeated_string: "\\xf\\x62"
-               repeated_string: "\\\xf\\\x62"
-               repeated_string: "\\\\xf\\\\x62"
-               repeated_string: "\\\\\xf\\\\\x62"
-               repeated_string: "\x5cx20"'''
-    text_format.Merge(text, message)
-
-    SLASH = '\\'
-    self.assertEqual('\x0fb', message.repeated_string[0])
-    self.assertEqual(SLASH + 'xf' + SLASH + 'x62', message.repeated_string[1])
-    self.assertEqual(SLASH + '\x0f' + SLASH + 'b', message.repeated_string[2])
-    self.assertEqual(SLASH + SLASH + 'xf' + SLASH + SLASH + 'x62',
-                     message.repeated_string[3])
-    self.assertEqual(SLASH + SLASH + '\x0f' + SLASH + SLASH + 'b',
-                     message.repeated_string[4])
-    self.assertEqual(SLASH + 'x20', message.repeated_string[5])
-
-  def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs):
-    """Same as assertRaises, but also compares the exception message."""
-    if hasattr(e_class, '__name__'):
-      exc_name = e_class.__name__
-    else:
-      exc_name = str(e_class)
-
-    try:
-      func(*args, **kwargs)
-    except e_class as expr:
-      if str(expr) != e:
-        msg = '%s raised, but with wrong message: "%s" instead of "%s"'
-        raise self.failureException(msg % (exc_name,
-                                           str(expr).encode('string_escape'),
-                                           e.encode('string_escape')))
-      return
-    else:
-      raise self.failureException('%s not raised' % exc_name)
-
-
-class TokenizerTest(unittest.TestCase):
-  """
-  def testSimpleTokenCases(self):
-    text = ('identifier1:"string1"\n     \n\n'
-            'identifier2 : \n \n123  \n  identifier3 :\'string\'\n'
-            'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
-            'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
-            'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
-            'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f '
-            'false_bool:  0 true_BOOL:t \n true_bool1:  1 false_BOOL1:f ' )
-    tokenizer = text_format._Tokenizer(text)
-    methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
-               ':',
-               (tokenizer.ConsumeString, 'string1'),
-               (tokenizer.ConsumeIdentifier, 'identifier2'),
-               ':',
-               (tokenizer.ConsumeInt32, 123),
-               (tokenizer.ConsumeIdentifier, 'identifier3'),
-               ':',
-               (tokenizer.ConsumeString, 'string'),
-               (tokenizer.ConsumeIdentifier, 'identifiER_4'),
-               ':',
-               (tokenizer.ConsumeFloat, 1.1e+2),
-               (tokenizer.ConsumeIdentifier, 'ID5'),
-               ':',
-               (tokenizer.ConsumeFloat, -0.23),
-               (tokenizer.ConsumeIdentifier, 'ID6'),
-               ':',
-               (tokenizer.ConsumeString, 'aaaa\'bbbb'),
-               (tokenizer.ConsumeIdentifier, 'ID7'),
-               ':',
-               (tokenizer.ConsumeString, 'aa\"bb'),
-               (tokenizer.ConsumeIdentifier, 'ID8'),
-               ':',
-               '{',
-               (tokenizer.ConsumeIdentifier, 'A'),
-               ':',
-               (tokenizer.ConsumeFloat, float('inf')),
-               (tokenizer.ConsumeIdentifier, 'B'),
-               ':',
-               (tokenizer.ConsumeFloat, -float('inf')),
-               (tokenizer.ConsumeIdentifier, 'C'),
-               ':',
-               (tokenizer.ConsumeBool, True),
-               (tokenizer.ConsumeIdentifier, 'D'),
-               ':',
-               (tokenizer.ConsumeBool, False),
-               '}',
-               (tokenizer.ConsumeIdentifier, 'ID9'),
-               ':',
-               (tokenizer.ConsumeUint32, 22),
-               (tokenizer.ConsumeIdentifier, 'ID10'),
-               ':',
-               (tokenizer.ConsumeInt64, -111111111111111111),
-               (tokenizer.ConsumeIdentifier, 'ID11'),
-               ':',
-               (tokenizer.ConsumeInt32, -22),
-               (tokenizer.ConsumeIdentifier, 'ID12'),
-               ':',
-               (tokenizer.ConsumeUint64, 2222222222222222222),
-               (tokenizer.ConsumeIdentifier, 'ID13'),
-               ':',
-               (tokenizer.ConsumeFloat, 1.23456),
-               (tokenizer.ConsumeIdentifier, 'ID14'),
-               ':',
-               (tokenizer.ConsumeFloat, 1.2e+2),
-               (tokenizer.ConsumeIdentifier, 'false_bool'),
-               ':',
-               (tokenizer.ConsumeBool, False),
-               (tokenizer.ConsumeIdentifier, 'true_BOOL'),
-               ':',
-               (tokenizer.ConsumeBool, True),
-               (tokenizer.ConsumeIdentifier, 'true_bool1'),
-               ':',
-               (tokenizer.ConsumeBool, True),
-               (tokenizer.ConsumeIdentifier, 'false_BOOL1'),
-               ':',
-               (tokenizer.ConsumeBool, False)]
-
-    i = 0
-    while not tokenizer.AtEnd():
-      m = methods[i]
-      if type(m) == str:
-        token = tokenizer.token
-        self.assertEqual(token, m)
-        tokenizer.NextToken()
-      else:
-        self.assertEqual(m[1], m[0]())
-      i += 1
-
-  def testConsumeIntegers(self):
-    # This test only tests the failures in the integer parsing methods as well
-    # as the '0' special cases.
-    int64_max = (1 << 63) - 1
-    uint32_max = (1 << 32) - 1
-    text = '-1 %d %d' % (uint32_max + 1, int64_max + 1)
-    tokenizer = text_format._Tokenizer(text)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint64)
-    self.assertEqual(-1, tokenizer.ConsumeInt32())
-
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt32)
-    self.assertEqual(uint32_max + 1, tokenizer.ConsumeInt64())
-
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt64)
-    self.assertEqual(int64_max + 1, tokenizer.ConsumeUint64())
-    self.assertTrue(tokenizer.AtEnd())
-
-    text = '-0 -0 0 0'
-    tokenizer = text_format._Tokenizer(text)
-    self.assertEqual(0, tokenizer.ConsumeUint32())
-    self.assertEqual(0, tokenizer.ConsumeUint64())
-    self.assertEqual(0, tokenizer.ConsumeUint32())
-    self.assertEqual(0, tokenizer.ConsumeUint64())
-    self.assertTrue(tokenizer.AtEnd())
-    """
-
-  def testConsumeByteString(self):
-    text = '"string1\''
-    tokenizer = text_format._Tokenizer(text)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
-
-    text = 'string1"'
-    tokenizer = text_format._Tokenizer(text)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
-
-    text = '\n"\\xt"'
-    tokenizer = text_format._Tokenizer(text)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
-
-    text = '\n"\\"'
-    tokenizer = text_format._Tokenizer(text)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
-
-    text = '\n"\\x"'
-    tokenizer = text_format._Tokenizer(text)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
-
-  def testConsumeBool(self):
-    text = 'not-a-bool'
-    tokenizer = text_format._Tokenizer(text)
-    self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool)
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_unittest_data.txt b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_unittest_data.txt
deleted file mode 100644
index bbe5882..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_unittest_data.txt
+++ /dev/null
@@ -1,128 +0,0 @@
-optional_int32: 101
-optional_int64: 102
-optional_uint32: 103
-optional_uint64: 104
-optional_sint32: 105
-optional_sint64: 106
-optional_fixed32: 107
-optional_fixed64: 108
-optional_sfixed32: 109
-optional_sfixed64: 110
-optional_float: 111
-optional_double: 112
-optional_bool: true
-optional_string: "115"
-optional_bytes: "116"
-OptionalGroup {
-  a: 117
-}
-optional_nested_message {
-  bb: 118
-}
-optional_foreign_message {
-  c: 119
-}
-optional_import_message {
-  d: 120
-}
-optional_nested_enum: BAZ
-optional_foreign_enum: FOREIGN_BAZ
-optional_import_enum: IMPORT_BAZ
-optional_string_piece: "124"
-optional_cord: "125"
-optional_public_import_message {
-  e: 126
-}
-optional_lazy_message {
-  bb: 127
-}
-repeated_int32: 201
-repeated_int32: 301
-repeated_int64: 202
-repeated_int64: 302
-repeated_uint32: 203
-repeated_uint32: 303
-repeated_uint64: 204
-repeated_uint64: 304
-repeated_sint32: 205
-repeated_sint32: 305
-repeated_sint64: 206
-repeated_sint64: 306
-repeated_fixed32: 207
-repeated_fixed32: 307
-repeated_fixed64: 208
-repeated_fixed64: 308
-repeated_sfixed32: 209
-repeated_sfixed32: 309
-repeated_sfixed64: 210
-repeated_sfixed64: 310
-repeated_float: 211
-repeated_float: 311
-repeated_double: 212
-repeated_double: 312
-repeated_bool: true
-repeated_bool: false
-repeated_string: "215"
-repeated_string: "315"
-repeated_bytes: "216"
-repeated_bytes: "316"
-RepeatedGroup {
-  a: 217
-}
-RepeatedGroup {
-  a: 317
-}
-repeated_nested_message {
-  bb: 218
-}
-repeated_nested_message {
-  bb: 318
-}
-repeated_foreign_message {
-  c: 219
-}
-repeated_foreign_message {
-  c: 319
-}
-repeated_import_message {
-  d: 220
-}
-repeated_import_message {
-  d: 320
-}
-repeated_nested_enum: BAR
-repeated_nested_enum: BAZ
-repeated_foreign_enum: FOREIGN_BAR
-repeated_foreign_enum: FOREIGN_BAZ
-repeated_import_enum: IMPORT_BAR
-repeated_import_enum: IMPORT_BAZ
-repeated_string_piece: "224"
-repeated_string_piece: "324"
-repeated_cord: "225"
-repeated_cord: "325"
-repeated_lazy_message {
-  bb: 227
-}
-repeated_lazy_message {
-  bb: 327
-}
-default_int32: 401
-default_int64: 402
-default_uint32: 403
-default_uint64: 404
-default_sint32: 405
-default_sint64: 406
-default_fixed32: 407
-default_fixed64: 408
-default_sfixed32: 409
-default_sfixed64: 410
-default_float: 411
-default_double: 412
-default_bool: false
-default_string: "415"
-default_bytes: "416"
-default_nested_enum: FOO
-default_foreign_enum: FOREIGN_FOO
-default_import_enum: IMPORT_FOO
-default_string_piece: "424"
-default_cord: "425"
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_unittest_extensions_data.txt b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_unittest_extensions_data.txt
deleted file mode 100644
index 0a217f0..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_unittest_extensions_data.txt
+++ /dev/null
@@ -1,128 +0,0 @@
-[protobuf_unittest.optional_int32_extension]: 101
-[protobuf_unittest.optional_int64_extension]: 102
-[protobuf_unittest.optional_uint32_extension]: 103
-[protobuf_unittest.optional_uint64_extension]: 104
-[protobuf_unittest.optional_sint32_extension]: 105
-[protobuf_unittest.optional_sint64_extension]: 106
-[protobuf_unittest.optional_fixed32_extension]: 107
-[protobuf_unittest.optional_fixed64_extension]: 108
-[protobuf_unittest.optional_sfixed32_extension]: 109
-[protobuf_unittest.optional_sfixed64_extension]: 110
-[protobuf_unittest.optional_float_extension]: 111
-[protobuf_unittest.optional_double_extension]: 112
-[protobuf_unittest.optional_bool_extension]: true
-[protobuf_unittest.optional_string_extension]: "115"
-[protobuf_unittest.optional_bytes_extension]: "116"
-[protobuf_unittest.optionalgroup_extension] {
-  a: 117
-}
-[protobuf_unittest.optional_nested_message_extension] {
-  bb: 118
-}
-[protobuf_unittest.optional_foreign_message_extension] {
-  c: 119
-}
-[protobuf_unittest.optional_import_message_extension] {
-  d: 120
-}
-[protobuf_unittest.optional_nested_enum_extension]: BAZ
-[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ
-[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ
-[protobuf_unittest.optional_string_piece_extension]: "124"
-[protobuf_unittest.optional_cord_extension]: "125"
-[protobuf_unittest.optional_public_import_message_extension] {
-  e: 126
-}
-[protobuf_unittest.optional_lazy_message_extension] {
-  bb: 127
-}
-[protobuf_unittest.repeated_int32_extension]: 201
-[protobuf_unittest.repeated_int32_extension]: 301
-[protobuf_unittest.repeated_int64_extension]: 202
-[protobuf_unittest.repeated_int64_extension]: 302
-[protobuf_unittest.repeated_uint32_extension]: 203
-[protobuf_unittest.repeated_uint32_extension]: 303
-[protobuf_unittest.repeated_uint64_extension]: 204
-[protobuf_unittest.repeated_uint64_extension]: 304
-[protobuf_unittest.repeated_sint32_extension]: 205
-[protobuf_unittest.repeated_sint32_extension]: 305
-[protobuf_unittest.repeated_sint64_extension]: 206
-[protobuf_unittest.repeated_sint64_extension]: 306
-[protobuf_unittest.repeated_fixed32_extension]: 207
-[protobuf_unittest.repeated_fixed32_extension]: 307
-[protobuf_unittest.repeated_fixed64_extension]: 208
-[protobuf_unittest.repeated_fixed64_extension]: 308
-[protobuf_unittest.repeated_sfixed32_extension]: 209
-[protobuf_unittest.repeated_sfixed32_extension]: 309
-[protobuf_unittest.repeated_sfixed64_extension]: 210
-[protobuf_unittest.repeated_sfixed64_extension]: 310
-[protobuf_unittest.repeated_float_extension]: 211
-[protobuf_unittest.repeated_float_extension]: 311
-[protobuf_unittest.repeated_double_extension]: 212
-[protobuf_unittest.repeated_double_extension]: 312
-[protobuf_unittest.repeated_bool_extension]: true
-[protobuf_unittest.repeated_bool_extension]: false
-[protobuf_unittest.repeated_string_extension]: "215"
-[protobuf_unittest.repeated_string_extension]: "315"
-[protobuf_unittest.repeated_bytes_extension]: "216"
-[protobuf_unittest.repeated_bytes_extension]: "316"
-[protobuf_unittest.repeatedgroup_extension] {
-  a: 217
-}
-[protobuf_unittest.repeatedgroup_extension] {
-  a: 317
-}
-[protobuf_unittest.repeated_nested_message_extension] {
-  bb: 218
-}
-[protobuf_unittest.repeated_nested_message_extension] {
-  bb: 318
-}
-[protobuf_unittest.repeated_foreign_message_extension] {
-  c: 219
-}
-[protobuf_unittest.repeated_foreign_message_extension] {
-  c: 319
-}
-[protobuf_unittest.repeated_import_message_extension] {
-  d: 220
-}
-[protobuf_unittest.repeated_import_message_extension] {
-  d: 320
-}
-[protobuf_unittest.repeated_nested_enum_extension]: BAR
-[protobuf_unittest.repeated_nested_enum_extension]: BAZ
-[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR
-[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ
-[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR
-[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ
-[protobuf_unittest.repeated_string_piece_extension]: "224"
-[protobuf_unittest.repeated_string_piece_extension]: "324"
-[protobuf_unittest.repeated_cord_extension]: "225"
-[protobuf_unittest.repeated_cord_extension]: "325"
-[protobuf_unittest.repeated_lazy_message_extension] {
-  bb: 227
-}
-[protobuf_unittest.repeated_lazy_message_extension] {
-  bb: 327
-}
-[protobuf_unittest.default_int32_extension]: 401
-[protobuf_unittest.default_int64_extension]: 402
-[protobuf_unittest.default_uint32_extension]: 403
-[protobuf_unittest.default_uint64_extension]: 404
-[protobuf_unittest.default_sint32_extension]: 405
-[protobuf_unittest.default_sint64_extension]: 406
-[protobuf_unittest.default_fixed32_extension]: 407
-[protobuf_unittest.default_fixed64_extension]: 408
-[protobuf_unittest.default_sfixed32_extension]: 409
-[protobuf_unittest.default_sfixed64_extension]: 410
-[protobuf_unittest.default_float_extension]: 411
-[protobuf_unittest.default_double_extension]: 412
-[protobuf_unittest.default_bool_extension]: false
-[protobuf_unittest.default_string_extension]: "415"
-[protobuf_unittest.default_bytes_extension]: "416"
-[protobuf_unittest.default_nested_enum_extension]: FOO
-[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO
-[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO
-[protobuf_unittest.default_string_piece_extension]: "424"
-[protobuf_unittest.default_cord_extension]: "425"
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/wire_format_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/wire_format_test.py
deleted file mode 100755
index 7600778..0000000
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/wire_format_test.py
+++ /dev/null
@@ -1,253 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc.  All rights reserved.
-# http://code.google.com/p/protobuf/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Test for google.protobuf.internal.wire_format."""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import unittest
-from google.protobuf import message
-from google.protobuf.internal import wire_format
-
-
-class WireFormatTest(unittest.TestCase):
-
-  def testPackTag(self):
-    field_number = 0xabc
-    tag_type = 2
-    self.assertEqual((field_number << 3) | tag_type,
-                     wire_format.PackTag(field_number, tag_type))
-    PackTag = wire_format.PackTag
-    # Number too high.
-    self.assertRaises(message.EncodeError, PackTag, field_number, 6)
-    # Number too low.
-    self.assertRaises(message.EncodeError, PackTag, field_number, -1)
-
-  def testUnpackTag(self):
-    # Test field numbers that will require various varint sizes.
-    for expected_field_number in (1, 15, 16, 2047, 2048):
-      for expected_wire_type in range(6):  # Highest-numbered wiretype is 5.
-        field_number, wire_type = wire_format.UnpackTag(
-            wire_format.PackTag(expected_field_number, expected_wire_type))
-        self.assertEqual(expected_field_number, field_number)
-        self.assertEqual(expected_wire_type, wire_type)
-
-    self.assertRaises(TypeError, wire_format.UnpackTag, None)
-    self.assertRaises(TypeError, wire_format.UnpackTag, 'abc')
-    self.assertRaises(TypeError, wire_format.UnpackTag, 0.0)
-    self.assertRaises(TypeError, wire_format.UnpackTag, object())
-
-  def testZigZagEncode(self):
-    Z = wire_format.ZigZagEncode
-    self.assertEqual(0, Z(0))
-    self.assertEqual(1, Z(-1))
-    self.assertEqual(2, Z(1))
-    self.assertEqual(3, Z(-2))
-    self.assertEqual(4, Z(2))
-    self.assertEqual(0xfffffffe, Z(0x7fffffff))
-    self.assertEqual(0xffffffff, Z(-0x80000000))
-    self.assertEqual(0xfffffffffffffffe, Z(0x7fffffffffffffff))
-    self.assertEqual(0xffffffffffffffff, Z(-0x8000000000000000))
-
-    self.assertRaises(TypeError, Z, None)
-    self.assertRaises(TypeError, Z, 'abcd')
-    self.assertRaises(TypeError, Z, 0.0)
-    self.assertRaises(TypeError, Z, object())
-
-  def testZigZagDecode(self):
-    Z = wire_format.ZigZagDecode
-    self.assertEqual(0, Z(0))
-    self.assertEqual(-1, Z(1))
-    self.assertEqual(1, Z(2))
-    self.assertEqual(-2, Z(3))
-    self.assertEqual(2, Z(4))
-    self.assertEqual(0x7fffffff, Z(0xfffffffe))
-    self.assertEqual(-0x80000000, Z(0xffffffff))
-    self.assertEqual(0x7fffffffffffffff, Z(0xfffffffffffffffe))
-    self.assertEqual(-0x8000000000000000, Z(0xffffffffffffffff))
-
-    self.assertRaises(TypeError, Z, None)
-    self.assertRaises(TypeError, Z, 'abcd')
-    self.assertRaises(TypeError, Z, 0.0)
-    self.assertRaises(TypeError, Z, object())
-
-  def NumericByteSizeTestHelper(self, byte_size_fn, value, expected_value_size):
-    # Use field numbers that cause various byte sizes for the tag information.
-    for field_number, tag_bytes in ((15, 1), (16, 2), (2047, 2), (2048, 3)):
-      expected_size = expected_value_size + tag_bytes
-      actual_size = byte_size_fn(field_number, value)
-      self.assertEqual(expected_size, actual_size,
-                       'byte_size_fn: %s, field_number: %d, value: %r\n'
-                       'Expected: %d, Actual: %d'% (
-          byte_size_fn, field_number, value, expected_size, actual_size))
-
-  def testByteSizeFunctions(self):
-    # Test all numeric *ByteSize() functions.
-    NUMERIC_ARGS = [
-        # Int32ByteSize().
-        [wire_format.Int32ByteSize, 0, 1],
-        [wire_format.Int32ByteSize, 127, 1],
-        [wire_format.Int32ByteSize, 128, 2],
-        [wire_format.Int32ByteSize, -1, 10],
-        # Int64ByteSize().
-        [wire_format.Int64ByteSize, 0, 1],
-        [wire_format.Int64ByteSize, 127, 1],
-        [wire_format.Int64ByteSize, 128, 2],
-        [wire_format.Int64ByteSize, -1, 10],
-        # UInt32ByteSize().
-        [wire_format.UInt32ByteSize, 0, 1],
-        [wire_format.UInt32ByteSize, 127, 1],
-        [wire_format.UInt32ByteSize, 128, 2],
-        [wire_format.UInt32ByteSize, wire_format.UINT32_MAX, 5],
-        # UInt64ByteSize().
-        [wire_format.UInt64ByteSize, 0, 1],
-        [wire_format.UInt64ByteSize, 127, 1],
-        [wire_format.UInt64ByteSize, 128, 2],
-        [wire_format.UInt64ByteSize, wire_format.UINT64_MAX, 10],
-        # SInt32ByteSize().
-        [wire_format.SInt32ByteSize, 0, 1],
-        [wire_format.SInt32ByteSize, -1, 1],
-        [wire_format.SInt32ByteSize, 1, 1],
-        [wire_format.SInt32ByteSize, -63, 1],
-        [wire_format.SInt32ByteSize, 63, 1],
-        [wire_format.SInt32ByteSize, -64, 1],
-        [wire_format.SInt32ByteSize, 64, 2],
-        # SInt64ByteSize().
-        [wire_format.SInt64ByteSize, 0, 1],
-        [wire_format.SInt64ByteSize, -1, 1],
-        [wire_format.SInt64ByteSize, 1, 1],
-        [wire_format.SInt64ByteSize, -63, 1],
-        [wire_format.SInt64ByteSize, 63, 1],
-        [wire_format.SInt64ByteSize, -64, 1],
-        [wire_format.SInt64ByteSize, 64, 2],
-        # Fixed32ByteSize().
-        [wire_format.Fixed32ByteSize, 0, 4],
-        [wire_format.Fixed32ByteSize, wire_format.UINT32_MAX, 4],
-        # Fixed64ByteSize().
-        [wire_format.Fixed64ByteSize, 0, 8],
-        [wire_format.Fixed64ByteSize, wire_format.UINT64_MAX, 8],
-        # SFixed32ByteSize().
-        [wire_format.SFixed32ByteSize, 0, 4],
-        [wire_format.SFixed32ByteSize, wire_format.INT32_MIN, 4],
-        [wire_format.SFixed32ByteSize, wire_format.INT32_MAX, 4],
-        # SFixed64ByteSize().
-        [wire_format.SFixed64ByteSize, 0, 8],
-        [wire_format.SFixed64ByteSize, wire_format.INT64_MIN, 8],
-        [wire_format.SFixed64ByteSize, wire_format.INT64_MAX, 8],
-        # FloatByteSize().
-        [wire_format.FloatByteSize, 0.0, 4],
-        [wire_format.FloatByteSize, 1000000000.0, 4],
-        [wire_format.FloatByteSize, -1000000000.0, 4],
-        # DoubleByteSize().
-        [wire_format.DoubleByteSize, 0.0, 8],
-        [wire_format.DoubleByteSize, 1000000000.0, 8],
-        [wire_format.DoubleByteSize, -1000000000.0, 8],
-        # BoolByteSize().
-        [wire_format.BoolByteSize, False, 1],
-        [wire_format.BoolByteSize, True, 1],
-        # EnumByteSize().
-        [wire_format.EnumByteSize, 0, 1],
-        [wire_format.EnumByteSize, 127, 1],
-        [wire_format.EnumByteSize, 128, 2],
-        [wire_format.EnumByteSize, wire_format.UINT32_MAX, 5],
-        ]
-    for args in NUMERIC_ARGS:
-      self.NumericByteSizeTestHelper(*args)
-
-    # Test strings and bytes.
-    for byte_size_fn in (wire_format.StringByteSize, wire_format.BytesByteSize):
-      # 1 byte for tag, 1 byte for length, 3 bytes for contents.
-      self.assertEqual(5, byte_size_fn(10, 'abc'))
-      # 2 bytes for tag, 1 byte for length, 3 bytes for contents.
-      self.assertEqual(6, byte_size_fn(16, 'abc'))
-      # 2 bytes for tag, 2 bytes for length, 128 bytes for contents.
-      self.assertEqual(132, byte_size_fn(16, 'a' * 128))
-
-    # Test UTF-8 string byte size calculation.
-    # 1 byte for tag, 1 byte for length, 8 bytes for content.
-    self.assertEqual(10, wire_format.StringByteSize(
-        5, unicode('\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82', 'utf-8')))
-
-    class MockMessage(object):
-      def __init__(self, byte_size):
-        self.byte_size = byte_size
-      def ByteSize(self):
-        return self.byte_size
-
-    message_byte_size = 10
-    mock_message = MockMessage(byte_size=message_byte_size)
-    # Test groups.
-    # (2 * 1) bytes for begin and end tags, plus message_byte_size.
-    self.assertEqual(2 + message_byte_size,
-                     wire_format.GroupByteSize(1, mock_message))
-    # (2 * 2) bytes for begin and end tags, plus message_byte_size.
-    self.assertEqual(4 + message_byte_size,
-                     wire_format.GroupByteSize(16, mock_message))
-
-    # Test messages.
-    # 1 byte for tag, plus 1 byte for length, plus contents.
-    self.assertEqual(2 + mock_message.byte_size,
-                     wire_format.MessageByteSize(1, mock_message))
-    # 2 bytes for tag, plus 1 byte for length, plus contents.
-    self.assertEqual(3 + mock_message.byte_size,
-                     wire_format.MessageByteSize(16, mock_message))
-    # 2 bytes for tag, plus 2 bytes for length, plus contents.
-    mock_message.byte_size = 128
-    self.assertEqual(4 + mock_message.byte_size,
-                     wire_format.MessageByteSize(16, mock_message))
-
-
-    # Test message set item byte size.
-    # 4 bytes for tags, plus 1 byte for length, plus 1 byte for type_id,
-    # plus contents.
-    mock_message.byte_size = 10
-    self.assertEqual(mock_message.byte_size + 6,
-                     wire_format.MessageSetItemByteSize(1, mock_message))
-
-    # 4 bytes for tags, plus 2 bytes for length, plus 1 byte for type_id,
-    # plus contents.
-    mock_message.byte_size = 128
-    self.assertEqual(mock_message.byte_size + 7,
-                     wire_format.MessageSetItemByteSize(1, mock_message))
-
-    # 4 bytes for tags, plus 2 bytes for length, plus 2 byte for type_id,
-    # plus contents.
-    self.assertEqual(mock_message.byte_size + 8,
-                     wire_format.MessageSetItemByteSize(128, mock_message))
-
-    # Too-long varint.
-    self.assertRaises(message.EncodeError,
-                      wire_format.UInt64ByteSize, 1, 1 << 128)
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/python/docs/generate_docs.py b/python/docs/generate_docs.py
index 07debed..e024aaa 100755
--- a/python/docs/generate_docs.py
+++ b/python/docs/generate_docs.py
@@ -67,12 +67,22 @@
 PYTHON_DIR = DOCS_DIR.parent
 SOURCE_DIR = PYTHON_DIR / "google" / "protobuf"
 SOURCE_POSIX = SOURCE_DIR.as_posix()
+
+# Modules which are always included:
+INCLUDED_MODULES = (
+  "google.protobuf.internal.containers",
+)
+
+# Packages to ignore, including all modules (unless in INCLUDED_MODULES):
 IGNORED_PACKAGES = (
   "compiler",
+  "docs",
   "internal",
   "pyext",
   "util",
 )
+
+# Ignored module stems in all packages (unless in INCLUDED_MODULES):
 IGNORED_MODULES = (
   "any_test_pb2",
   "api_pb2",
@@ -81,6 +91,7 @@
   "test_messages_proto3_pb2",
   "test_messages_proto2",
 )
+
 TOC_REGEX = re.compile(
   r"\.\. START REFTOC.*\.\. END REFTOC\.\n",
   flags=re.DOTALL,
@@ -120,20 +131,28 @@
 def find_modules():
   modules = []
   for module_path in SOURCE_DIR.glob("**/*.py"):
-    package_posix = module_path.parent.as_posix()
-    if any(ignored in package_posix for ignored in IGNORED_PACKAGES):
+    # Determine the (dotted) relative package and module names.
+    package_path = module_path.parent.relative_to(PYTHON_DIR)
+    if package_path == SOURCE_DIR:
+      package_name = ""
+      module_name = module_path.stem
+    else:
+      package_name = package_path.as_posix().replace("/", ".")
+      module_name = package_name + "." + module_path.stem
+
+    # Filter: first, accept anything in the whitelist; then, reject anything
+    # at package level, then module name level.
+    if any(include == module_name for include in INCLUDED_MODULES):
+      pass
+    elif any(ignored in package_name for ignored in IGNORED_PACKAGES):
       continue
-    if any(ignored in module_path.stem for ignored in IGNORED_MODULES):
+    elif any(ignored in module_path.stem for ignored in IGNORED_MODULES):
       continue
 
-    package_name = "google.protobuf{}".format(
-      package_posix[len(SOURCE_POSIX) :].replace("/", ".")
-    )
     if module_path.name == "__init__.py":
       modules.append(package_name)
     else:
-      module_name = module_path.stem
-      modules.append("{}.{}".format(package_name, module_name))
+      modules.append(module_name)
 
   return modules
 
diff --git a/python/docs/google/protobuf/internal/containers.rst b/python/docs/google/protobuf/internal/containers.rst
new file mode 100644
index 0000000..c3b8e59
--- /dev/null
+++ b/python/docs/google/protobuf/internal/containers.rst
@@ -0,0 +1,21 @@
+.. DO NOT EDIT, generated by generate_docs.py.
+
+.. ifconfig:: build_env == 'readthedocs'
+
+   .. warning::
+
+      You are reading the documentation for the `latest committed changes
+      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      the `Protocol Buffers package for Python
+      <https://developers.google.com/protocol-buffers/docs/pythontutorial>`_.
+      Some features may not yet be released. Read the documentation for the
+      latest released package at `googleapis.dev
+      <https://googleapis.dev/python/protobuf/latest/>`_.
+
+google.protobuf.internal.containers
+===================================
+
+.. automodule:: google.protobuf.internal.containers
+   :members:
+   :inherited-members:
+   :undoc-members:
diff --git a/python/docs/index.rst b/python/docs/index.rst
index 57f7ce7..5535b39 100644
--- a/python/docs/index.rst
+++ b/python/docs/index.rst
@@ -38,6 +38,7 @@
    google/protobuf/duration_pb2
    google/protobuf/empty_pb2
    google/protobuf/field_mask_pb2
+   google/protobuf/internal/containers
    google/protobuf/json_format
    google/protobuf/message
    google/protobuf/message_factory
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index cc9a06a..496df6a 100644
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -30,10 +30,4 @@
 
 # Copyright 2007 Google Inc. All Rights Reserved.
 
-__version__ = '3.11.4'
-
-if __name__ != '__main__':
-  try:
-    __import__('pkg_resources').declare_namespace(__name__)
-  except ImportError:
-    __path__ = __import__('pkgutil').extend_path(__path__, __name__)
+__version__ = '3.17.3'
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index 5ef81a2..70fdae1 100644
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -227,7 +227,8 @@
       proto: An empty proto instance from descriptor_pb2.
 
     Raises:
-      Error: If self couldnt be serialized, due to to few constructor arguments.
+      Error: If self couldn't be serialized, due to to few constructor
+        arguments.
     """
     if (self.file is not None and
         self._serialized_start is not None and
@@ -286,12 +287,26 @@
   if _USE_C_DESCRIPTORS:
     _C_DESCRIPTOR_CLASS = _message.Descriptor
 
-    def __new__(cls, name, full_name, filename, containing_type, fields,
-                nested_types, enum_types, extensions, options=None,
-                serialized_options=None,
-                is_extendable=True, extension_ranges=None, oneofs=None,
-                file=None, serialized_start=None, serialized_end=None,  # pylint: disable=redefined-builtin
-                syntax=None, create_key=None):
+    def __new__(
+        cls,
+        name=None,
+        full_name=None,
+        filename=None,
+        containing_type=None,
+        fields=None,
+        nested_types=None,
+        enum_types=None,
+        extensions=None,
+        options=None,
+        serialized_options=None,
+        is_extendable=True,
+        extension_ranges=None,
+        oneofs=None,
+        file=None,  # pylint: disable=redefined-builtin
+        serialized_start=None,
+        serialized_end=None,
+        syntax=None,
+        create_key=None):
       _message.Message._CheckCalledFromGeneratedFile()
       return _message.default_pool.FindMessageTypeByName(full_name)
 
@@ -798,9 +813,18 @@
   if _USE_C_DESCRIPTORS:
     _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
 
-    def __new__(cls, name, full_name, index, methods, options=None,
-                serialized_options=None, file=None,  # pylint: disable=redefined-builtin
-                serialized_start=None, serialized_end=None, create_key=None):
+    def __new__(
+        cls,
+        name=None,
+        full_name=None,
+        index=None,
+        methods=None,
+        options=None,
+        serialized_options=None,
+        file=None,  # pylint: disable=redefined-builtin
+        serialized_start=None,
+        serialized_end=None,
+        create_key=None):
       _message.Message._CheckCalledFromGeneratedFile()  # pylint: disable=protected-access
       return _message.default_pool.FindServiceByName(full_name)
 
@@ -827,7 +851,7 @@
     Args:
       name (str): Name of the method.
     Returns:
-      MethodDescriptor or None: the desctiptor for the requested method, if
+      MethodDescriptor or None: the descriptor for the requested method, if
       found.
     """
     return self.methods_by_name.get(name, None)
@@ -889,6 +913,24 @@
     self.input_type = input_type
     self.output_type = output_type
 
+  def CopyToProto(self, proto):
+    """Copies this to a descriptor_pb2.MethodDescriptorProto.
+
+    Args:
+      proto (descriptor_pb2.MethodDescriptorProto): An empty descriptor proto.
+
+    Raises:
+      Error: If self couldn't be serialized, due to too few constructor
+        arguments.
+    """
+    if self.containing_service is not None:
+      from google.protobuf import descriptor_pb2
+      service_proto = descriptor_pb2.ServiceDescriptorProto()
+      self.containing_service.CopyToProto(service_proto)
+      proto.CopyFrom(service_proto.method[self.index])
+    else:
+      raise Error('Descriptor does not contain a service.')
+
 
 class FileDescriptor(DescriptorBase):
   """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py
index 5453f50..073eddc 100644
--- a/python/google/protobuf/descriptor_database.py
+++ b/python/google/protobuf/descriptor_database.py
@@ -58,7 +58,7 @@
     Raises:
       DescriptorDatabaseConflictingDefinitionError: if an attempt is made to
         add a proto with the same name but different definition than an
-        exisiting proto in the database.
+        existing proto in the database.
     """
     proto_name = file_desc_proto.name
     if proto_name not in self._file_desc_protos_by_file:
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
index e8448e8..be1af7d 100644
--- a/python/google/protobuf/internal/api_implementation.py
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -32,8 +32,8 @@
 """
 
 import os
-import warnings
 import sys
+import warnings
 
 try:
   # pylint: disable=g-import-not-at-top
@@ -60,11 +60,17 @@
       raise ImportError('_use_fast_cpp_protos import succeeded but was None')
     del _use_fast_cpp_protos
     _api_version = 2
+    from google.protobuf import use_pure_python
+    raise RuntimeError(
+        'Conflicting deps on both :use_fast_cpp_protos and :use_pure_python.\n'
+        ' go/build_deps_on_BOTH_use_fast_cpp_protos_AND_use_pure_python\n'
+        'This should be impossible via a link error at build time...')
   except ImportError:
     try:
       # pylint: disable=g-import-not-at-top
-      from google.protobuf.internal import use_pure_python
+      from google.protobuf import use_pure_python
       del use_pure_python  # Avoids a pylint error and namespace pollution.
+      _api_version = 0
     except ImportError:
       # TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default;
       # it can cause data loss if you have any Python-only extensions to any
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index ecd28ee..9279349 100644
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -231,6 +231,9 @@
       kwargs['cmp'] = kwargs.pop('sort_function')
     self._values.sort(*args, **kwargs)
 
+  def reverse(self):
+    self._values.reverse()
+
 
 collections_abc.MutableSequence.register(BaseContainer)
 
@@ -629,7 +632,8 @@
     return repr(self._values)
 
   def MergeFrom(self, other):
-    for key in other:
+    # pylint: disable=protected-access
+    for key in other._values:
       # According to documentation: "When parsing from the wire or when merging,
       # if there are duplicate map keys the last key seen is used".
       if key in self:
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index 092dab5..6804986 100644
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -209,7 +209,8 @@
         _DecodeVarint()
   """
 
-  def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default):
+  def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default,
+                      clear_if_default=False):
     if is_packed:
       local_DecodeVarint = _DecodeVarint
       def DecodePackedField(buffer, pos, end, message, field_dict):
@@ -249,10 +250,13 @@
       return DecodeRepeatedField
     else:
       def DecodeField(buffer, pos, end, message, field_dict):
-        (field_dict[key], pos) = decode_value(buffer, pos)
+        (new_value, pos) = decode_value(buffer, pos)
         if pos > end:
-          del field_dict[key]  # Discard corrupt value.
           raise _DecodeError('Truncated message.')
+        if clear_if_default and not new_value:
+          field_dict.pop(key, None)
+        else:
+          field_dict[key] = new_value
         return pos
       return DecodeField
 
@@ -383,7 +387,9 @@
   return _SimpleDecoder(wire_format.WIRETYPE_FIXED64, InnerDecode)
 
 
-def EnumDecoder(field_number, is_repeated, is_packed, key, new_default):
+def EnumDecoder(field_number, is_repeated, is_packed, key, new_default,
+                clear_if_default=False):
+  """Returns a decoder for enum field."""
   enum_type = key.enum_type
   if is_packed:
     local_DecodeVarint = _DecodeVarint
@@ -498,6 +504,9 @@
       (enum_value, pos) = _DecodeSignedVarint32(buffer, pos)
       if pos > end:
         raise _DecodeError('Truncated message.')
+      if clear_if_default and not enum_value:
+        field_dict.pop(key, None)
+        return pos
       # pylint: disable=protected-access
       if enum_value in enum_type.values_by_number:
         field_dict[key] = enum_value
@@ -550,7 +559,7 @@
 
 
 def StringDecoder(field_number, is_repeated, is_packed, key, new_default,
-                  is_strict_utf8=False):
+                  is_strict_utf8=False, clear_if_default=False):
   """Returns a decoder for a string field."""
 
   local_DecodeVarint = _DecodeVarint
@@ -604,12 +613,16 @@
       new_pos = pos + size
       if new_pos > end:
         raise _DecodeError('Truncated string.')
-      field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos])
+      if clear_if_default and not size:
+        field_dict.pop(key, None)
+      else:
+        field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos])
       return new_pos
     return DecodeField
 
 
-def BytesDecoder(field_number, is_repeated, is_packed, key, new_default):
+def BytesDecoder(field_number, is_repeated, is_packed, key, new_default,
+                 clear_if_default=False):
   """Returns a decoder for a bytes field."""
 
   local_DecodeVarint = _DecodeVarint
@@ -641,7 +654,10 @@
       new_pos = pos + size
       if new_pos > end:
         raise _DecodeError('Truncated string.')
-      field_dict[key] = buffer[pos:new_pos].tobytes()
+      if clear_if_default and not size:
+        field_dict.pop(key, None)
+      else:
+        field_dict[key] = buffer[pos:new_pos].tobytes()
       return new_pos
     return DecodeField
 
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 5e3b0a9..4fc8049 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -907,10 +907,6 @@
         descriptor_pb2.ServiceDescriptorProto,
         TEST_SERVICE_ASCII)
 
-  @unittest.skipIf(
-      api_implementation.Type() == 'python',
-      'It is not implemented in python.')
-  # TODO(jieluo): Add support for pure python or remove in c extension.
   def testCopyToProto_MethodDescriptor(self):
     expected_ascii = """
       name: 'Foo'
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
index 0d1f49d..0c016f3 100644
--- a/python/google/protobuf/internal/encoder.py
+++ b/python/google/protobuf/internal/encoder.py
@@ -372,14 +372,15 @@
 def _VarintEncoder():
   """Return an encoder for a basic varint value (does not include tag)."""
 
+  local_int2byte = six.int2byte
   def EncodeVarint(write, value, unused_deterministic=None):
     bits = value & 0x7f
     value >>= 7
     while value:
-      write(six.int2byte(0x80|bits))
+      write(local_int2byte(0x80|bits))
       bits = value & 0x7f
       value >>= 7
-    return write(six.int2byte(bits))
+    return write(local_int2byte(bits))
 
   return EncodeVarint
 
@@ -388,16 +389,17 @@
   """Return an encoder for a basic signed varint value (does not include
   tag)."""
 
+  local_int2byte = six.int2byte
   def EncodeSignedVarint(write, value, unused_deterministic=None):
     if value < 0:
       value += (1 << 64)
     bits = value & 0x7f
     value >>= 7
     while value:
-      write(six.int2byte(0x80|bits))
+      write(local_int2byte(0x80|bits))
       bits = value & 0x7f
       value >>= 7
-    return write(six.int2byte(bits))
+    return write(local_int2byte(bits))
 
   return EncodeSignedVarint
 
diff --git a/python/google/protobuf/internal/enum_type_wrapper.py b/python/google/protobuf/internal/enum_type_wrapper.py
index eeb2dae..9ae0066 100644
--- a/python/google/protobuf/internal/enum_type_wrapper.py
+++ b/python/google/protobuf/internal/enum_type_wrapper.py
@@ -48,32 +48,38 @@
   def __init__(self, enum_type):
     """Inits EnumTypeWrapper with an EnumDescriptor."""
     self._enum_type = enum_type
-    self.DESCRIPTOR = enum_type
+    self.DESCRIPTOR = enum_type  # pylint: disable=invalid-name
 
-  def Name(self, number):
+  def Name(self, number):  # pylint: disable=invalid-name
     """Returns a string containing the name of an enum value."""
-    if number in self._enum_type.values_by_number:
+    try:
       return self._enum_type.values_by_number[number].name
+    except KeyError:
+      pass  # fall out to break exception chaining
 
     if not isinstance(number, six.integer_types):
-      raise TypeError('Enum value for %s must be an int, but got %r.' % (
-          self._enum_type.name, number))
+      raise TypeError(
+          'Enum value for {} must be an int, but got {} {!r}.'.format(
+              self._enum_type.name, type(number), number))
     else:
-      # %r here to handle the odd case when you pass in a boolean.
-      raise ValueError('Enum %s has no name defined for value %r' % (
+      # repr here to handle the odd case when you pass in a boolean.
+      raise ValueError('Enum {} has no name defined for value {!r}'.format(
           self._enum_type.name, number))
 
-  def Value(self, name):
+  def Value(self, name):  # pylint: disable=invalid-name
     """Returns the value corresponding to the given enum name."""
-    if name in self._enum_type.values_by_name:
+    try:
       return self._enum_type.values_by_name[name].number
-    raise ValueError('Enum %s has no value defined for name %s' % (
+    except KeyError:
+      pass  # fall out to break exception chaining
+    raise ValueError('Enum {} has no value defined for name {!r}'.format(
         self._enum_type.name, name))
 
   def keys(self):
     """Return a list of the string names in the enum.
 
-    These are returned in the order they were defined in the .proto file.
+    Returns:
+      A list of strs, in the order they were defined in the .proto file.
     """
 
     return [value_descriptor.name
@@ -82,7 +88,8 @@
   def values(self):
     """Return a list of the integer values in the enum.
 
-    These are returned in the order they were defined in the .proto file.
+    Returns:
+      A list of ints, in the order they were defined in the .proto file.
     """
 
     return [value_descriptor.number
@@ -91,13 +98,20 @@
   def items(self):
     """Return a list of the (name, value) pairs of the enum.
 
-    These are returned in the order they were defined in the .proto file.
+    Returns:
+      A list of (str, int) pairs, in the order they were defined
+      in the .proto file.
     """
     return [(value_descriptor.name, value_descriptor.number)
             for value_descriptor in self._enum_type.values]
 
   def __getattr__(self, name):
     """Returns the value corresponding to the given enum name."""
-    if name in self._enum_type.values_by_name:
-      return self._enum_type.values_by_name[name].number
-    raise AttributeError
+    try:
+      return super(
+          EnumTypeWrapper,
+          self).__getattribute__('_enum_type').values_by_name[name].number
+    except KeyError:
+      pass  # fall out to break exception chaining
+    raise AttributeError('Enum {} has no value defined for name {!r}'.format(
+        self._enum_type.name, name))
diff --git a/python/google/protobuf/internal/factory_test1.proto b/python/google/protobuf/internal/factory_test1.proto
index f5bd038..5e729f5 100644
--- a/python/google/protobuf/internal/factory_test1.proto
+++ b/python/google/protobuf/internal/factory_test1.proto
@@ -34,7 +34,6 @@
 
 package google.protobuf.python.internal;
 
-
 enum Factory1Enum {
   FACTORY_1_VALUE_0 = 0;
   FACTORY_1_VALUE_1 = 1;
@@ -67,6 +66,5 @@
 
 service Factory1Service {
   // Dummy method for this dummy service.
-  rpc Factory1Method(Factory1MethodRequest) returns (Factory1MethodResponse) {
-  }
+  rpc Factory1Method(Factory1MethodRequest) returns (Factory1MethodResponse) {}
 }
diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py
index 1510228..672a9b4 100755
--- a/python/google/protobuf/internal/json_format_test.py
+++ b/python/google/protobuf/internal/json_format_test.py
@@ -239,16 +239,19 @@
     golden_dict = {
         'messageSet': {
             '[protobuf_unittest.'
-            'TestMessageSetExtension1.messageSetExtension]': {
+            'TestMessageSetExtension1.message_set_extension]': {
                 'i': 23,
             },
             '[protobuf_unittest.'
-            'TestMessageSetExtension2.messageSetExtension]': {
+            'TestMessageSetExtension2.message_set_extension]': {
                 'str': u'foo',
             },
         },
     }
     self.assertEqual(golden_dict, message_dict)
+    parsed_msg = unittest_mset_pb2.TestMessageSetContainer()
+    json_format.ParseDict(golden_dict, parsed_msg)
+    self.assertEqual(message, parsed_msg)
 
   def testExtensionSerializationDictMatchesProto3SpecMore(self):
     """See go/proto3-json-spec for spec.
@@ -266,7 +269,6 @@
     }
     self.assertEqual(expected_dict, message_dict)
 
-
   def testExtensionSerializationJsonMatchesProto3Spec(self):
     """See go/proto3-json-spec for spec.
     """
@@ -279,9 +281,9 @@
         message
     )
     ext1_text = ('protobuf_unittest.TestMessageSetExtension1.'
-                 'messageSetExtension')
+                 'message_set_extension')
     ext2_text = ('protobuf_unittest.TestMessageSetExtension2.'
-                 'messageSetExtension')
+                 'message_set_extension')
     golden_text = ('{"messageSet": {'
                    '    "[%s]": {'
                    '        "i": 23'
@@ -292,7 +294,6 @@
                    '}}') % (ext1_text, ext2_text)
     self.assertEqual(json.loads(golden_text), json.loads(message_text))
 
-
   def testJsonEscapeString(self):
     message = json_format_proto3_pb2.TestMessage()
     if sys.version_info[0] < 3:
@@ -635,6 +636,20 @@
     parsed_message = json_format_proto3_pb2.TestListValue()
     self.CheckParseBack(message, parsed_message)
 
+  def testNullValue(self):
+    message = json_format_proto3_pb2.TestOneof()
+    message.oneof_null_value = 0
+    self.assertEqual(json_format.MessageToJson(message),
+                     '{\n  "oneofNullValue": null\n}')
+    parsed_message = json_format_proto3_pb2.TestOneof()
+    self.CheckParseBack(message, parsed_message)
+    # Check old format is also accepted
+    new_message = json_format_proto3_pb2.TestOneof()
+    json_format.Parse('{\n  "oneofNullValue": "NULL_VALUE"\n}',
+                      new_message)
+    self.assertEqual(json_format.MessageToJson(new_message),
+                     '{\n  "oneofNullValue": null\n}')
+
   def testAnyMessage(self):
     message = json_format_proto3_pb2.TestAny()
     value1 = json_format_proto3_pb2.MessageType()
@@ -829,10 +844,14 @@
 
   def testParseDoubleToFloat(self):
     message = json_format_proto3_pb2.TestMessage()
-    text = ('{"repeatedFloatValue": [3.4028235e+39, 1.4028235e-39]\n}')
+    text = ('{"repeatedDoubleValue": [3.4028235e+39, 1.4028235e-39]\n}')
     json_format.Parse(text, message)
-    self.assertEqual(message.repeated_float_value[0], float('inf'))
-    self.assertAlmostEqual(message.repeated_float_value[1], 1.4028235e-39)
+    self.assertEqual(message.repeated_double_value[0], 3.4028235e+39)
+    self.assertEqual(message.repeated_double_value[1], 1.4028235e-39)
+    text = ('{"repeatedFloatValue": [3.4028235e+39, 1.4028235e-39]\n}')
+    self.CheckError(text,
+                    'Failed to parse repeatedFloatValue field: '
+                    'Float value too large.')
 
   def testFloatPrecision(self):
     message = json_format_proto3_pb2.TestMessage()
@@ -897,6 +916,23 @@
         'for enum type protobuf_unittest.TestAllTypes.NestedEnum.',
         json_format.Parse, '{"optionalNestedEnum": 12345}', message)
 
+  def testBytes(self):
+    message = json_format_proto3_pb2.TestMessage()
+    # Test url base64
+    text = '{"bytesValue": "-_"}'
+    json_format.Parse(text, message)
+    self.assertEqual(message.bytes_value, b'\xfb')
+    # Test padding
+    text = '{"bytesValue": "AQI="}'
+    json_format.Parse(text, message)
+    self.assertEqual(message.bytes_value, b'\x01\x02')
+    text = '{"bytesValue": "AQI"}'
+    json_format.Parse(text, message)
+    self.assertEqual(message.bytes_value, b'\x01\x02')
+    text = '{"bytesValue": "AQI*"}'
+    json_format.Parse(text, message)
+    self.assertEqual(message.bytes_value, b'\x01\x02')
+
   def testParseBadIdentifer(self):
     self.CheckError('{int32Value: 1}',
                     (r'Failed to load JSON: Expecting property name'
@@ -947,6 +983,9 @@
     self.CheckError('{"int32Value": "1 "}',
                     'Failed to parse int32Value field: '
                     'Couldn\'t parse integer: "1 ".')
+    self.CheckError('{"int32Value": false}',
+                    'Failed to parse int32Value field: Bool value False '
+                    'is not acceptable for integer field.')
     self.CheckError('{"int32Value": 12345678901234567890}',
                     'Failed to parse int32Value field: Value out of range: '
                     '12345678901234567890.')
@@ -958,12 +997,24 @@
     self.CheckError('{"floatValue": "nan"}',
                     'Failed to parse floatValue field: Couldn\'t '
                     'parse float "nan", use "NaN" instead.')
-
-  def testInvalidBytesValue(self):
-    self.CheckError('{"bytesValue": "AQI"}',
-                    'Failed to parse bytesValue field: Incorrect padding.')
-    self.CheckError('{"bytesValue": "AQI*"}',
-                    'Failed to parse bytesValue field: Incorrect padding.')
+    self.CheckError('{"floatValue": NaN}',
+                    'Failed to parse floatValue field: Couldn\'t '
+                    'parse NaN, use quoted "NaN" instead.')
+    self.CheckError('{"floatValue": Infinity}',
+                    'Failed to parse floatValue field: Couldn\'t parse Infinity'
+                    ' or value too large, use quoted "Infinity" instead.')
+    self.CheckError('{"floatValue": -Infinity}',
+                    'Failed to parse floatValue field: Couldn\'t parse '
+                    '-Infinity or value too small, '
+                    'use quoted "-Infinity" instead.')
+    self.CheckError('{"doubleValue": -1.89769e+308}',
+                    'Failed to parse doubleValue field: Couldn\'t parse '
+                    '-Infinity or value too small, '
+                    'use quoted "-Infinity" instead.')
+    self.CheckError('{"floatValue": 3.4028235e+39}',
+                    'Failed to parse floatValue field: Float value too large.')
+    self.CheckError('{"floatValue": -3.502823e+38}',
+                    'Failed to parse floatValue field: Float value too small.')
 
   def testInvalidRepeated(self):
     self.CheckError('{"repeatedInt32Value": 12345}',
@@ -1027,12 +1078,21 @@
         json_format.ParseError,
         'Failed to parse value field: year (0 )?is out of range.',
         json_format.Parse, text, message)
-    # Time bigger than maxinum time.
+    # Time bigger than maximum time.
     message.value.seconds = 253402300800
     self.assertRaisesRegexp(
         OverflowError,
         'date value out of range',
         json_format.MessageToJson, message)
+    # Lower case t does not accept.
+    text = '{"value": "0001-01-01t00:00:00Z"}'
+    with self.assertRaises(json_format.ParseError) as e:
+      json_format.Parse(text, message)
+    self.assertEqual(
+        'Failed to parse value field: '
+        'time data \'0001-01-01t00:00:00\' does not match format '
+        '\'%Y-%m-%dT%H:%M:%S\', lowercase \'t\' is not accepted.',
+        str(e.exception))
 
   def testInvalidOneof(self):
     message = json_format_proto3_pb2.TestOneof()
@@ -1059,6 +1119,30 @@
         'Failed to parse value field: Struct must be in a dict which is 1234',
         json_format.Parse, text, message)
 
+  def testTimestampInvalidStringValue(self):
+    message = json_format_proto3_pb2.TestTimestamp()
+    text = '{"value": {"foo": 123}}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        r"Timestamp JSON value not a string: {u?'foo': 123}",
+        json_format.Parse, text, message)
+
+  def testDurationInvalidStringValue(self):
+    message = json_format_proto3_pb2.TestDuration()
+    text = '{"value": {"foo": 123}}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        r"Duration JSON value not a string: {u?'foo': 123}",
+        json_format.Parse, text, message)
+
+  def testFieldMaskInvalidStringValue(self):
+    message = json_format_proto3_pb2.TestFieldMask()
+    text = '{"value": {"foo": 123}}'
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        r"FieldMask JSON value not a string: {u?'foo': 123}",
+        json_format.Parse, text, message)
+
   def testInvalidAny(self):
     message = any_pb2.Any()
     text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}'
@@ -1154,6 +1238,19 @@
         'Failed to parse any_value field: Can not find message descriptor by'
         ' type_url: type.googleapis.com/proto3.MessageType..')
 
+  def testParseDictUnknownValueType(self):
+    class UnknownClass(object):
+
+      def __repr__(self):
+        return 'v'
+    message = json_format_proto3_pb2.TestValue()
+    self.assertRaisesRegexp(
+        json_format.ParseError,
+        r"Value v has unexpected type <class '.*\.UnknownClass'>.",
+        json_format.ParseDict,
+        {'value': UnknownClass()},
+        message)
+
   def testMessageToDict(self):
     message = json_format_proto3_pb2.TestMessage()
     message.int32_value = 12345
diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py
index 24b79ec..42f91b2 100755
--- a/python/google/protobuf/internal/message_factory_test.py
+++ b/python/google/protobuf/internal/message_factory_test.py
@@ -106,6 +106,23 @@
         'google.protobuf.python.internal.Factory2Message'))
     self.assertTrue(cls is cls2)
 
+  def testCreatePrototypeOverride(self):
+    class MyMessageFactory(message_factory.MessageFactory):
+
+      def CreatePrototype(self, descriptor):
+        cls = super(MyMessageFactory, self).CreatePrototype(descriptor)
+        cls.additional_field = 'Some value'
+        return cls
+
+    db = descriptor_database.DescriptorDatabase()
+    pool = descriptor_pool.DescriptorPool(db)
+    db.Add(self.factory_test1_fd)
+    db.Add(self.factory_test2_fd)
+    factory = MyMessageFactory()
+    cls = factory.GetPrototype(pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory2Message'))
+    self.assertTrue(hasattr(cls, 'additional_field'))
+
   def testGetMessages(self):
     # performed twice because multiple calls with the same input must be allowed
     for _ in range(2):
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 0508bb2..77122a2 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -841,8 +841,7 @@
     m1.MergeFromString(m2.SerializeToString())
     self.assertEqual(1, m1.optional_nested_message.bb)
 
-  @unittest.skipIf(six.PY2, 'memoryview objects are not supported on py2')
-  def testMergeFromStringUsingMemoryViewWorksInPy3(self, message_module):
+  def testMergeFromStringUsingMemoryView(self, message_module):
     m2 = message_module.TestAllTypes()
     m2.optional_string = 'scalar string'
     m2.repeated_string.append('repeated string')
@@ -864,12 +863,6 @@
     self.assertIsInstance(m1.optional_string, six.text_type)
     self.assertIsInstance(m1.repeated_string[0], six.text_type)
 
-  @unittest.skipIf(six.PY3, 'memoryview is supported by py3')
-  def testMergeFromStringUsingMemoryViewIsPy2Error(self, message_module):
-    memview = memoryview(b'')
-    with self.assertRaises(TypeError):
-      message_module.TestAllTypes.FromString(memview)
-
   def testMergeFromEmpty(self, message_module):
     m1 = message_module.TestAllTypes()
     # Cpp extension will lazily create a sub message which is immutable.
@@ -1059,7 +1052,7 @@
     self.assertIsInstance(m.optional_string, six.text_type)
 
   def testLongValuedSlice(self, message_module):
-    """It should be possible to use long-valued indicies in slices
+    """It should be possible to use long-valued indices in slices.
 
     This didn't used to work in the v2 C++ implementation.
     """
@@ -1675,6 +1668,17 @@
     self.assertEqual(False, message.optional_bool)
     self.assertEqual(0, message.optional_nested_message.bb)
 
+  def testProto3ParserDropDefaultScalar(self):
+    message_proto2 = unittest_pb2.TestAllTypes()
+    message_proto2.optional_int32 = 0
+    message_proto2.optional_string = ''
+    message_proto2.optional_bytes = b''
+    self.assertEqual(len(message_proto2.ListFields()), 3)
+
+    message_proto3 = unittest_proto3_arena_pb2.TestAllTypes()
+    message_proto3.ParseFromString(message_proto2.SerializeToString())
+    self.assertEqual(len(message_proto3.ListFields()), 0)
+
   def testProto3Optional(self):
     msg = test_proto3_optional_pb2.TestProto3Optional()
     self.assertFalse(msg.HasField('optional_int32'))
@@ -2096,6 +2100,11 @@
     self.assertEqual(msg.map_int32_foreign_message[222].d, 20)
     self.assertNotEqual(msg.map_int32_foreign_message[222].c, 123)
 
+    # Merge a dict to map field is not accepted
+    with self.assertRaises(AttributeError):
+      m1.map_int32_all_types.MergeFrom(
+          {1: unittest_proto3_arena_pb2.TestAllTypes()})
+
   def testMergeFromBadType(self):
     msg = map_unittest_pb2.TestMap()
     with self.assertRaisesRegexp(
diff --git a/python/google/protobuf/internal/proto_builder_test.py b/python/google/protobuf/internal/proto_builder_test.py
index 36dfbfde..3ee14e4 100755
--- a/python/google/protobuf/internal/proto_builder_test.py
+++ b/python/google/protobuf/internal/proto_builder_test.py
@@ -42,6 +42,7 @@
   import unittest
 
 from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor
 from google.protobuf import descriptor_pool
 from google.protobuf import proto_builder
 from google.protobuf import text_format
@@ -91,6 +92,23 @@
         pool=pool)
     self.assertIs(proto_cls1.DESCRIPTOR, proto_cls2.DESCRIPTOR)
 
+  def testMakeLargeProtoClass(self):
+    """Test that large created protos don't use reserved field numbers."""
+    num_fields = 123456
+    fields = {
+        'foo%d' % i: descriptor_pb2.FieldDescriptorProto.TYPE_INT64
+        for i in range(num_fields)
+    }
+    proto_cls = proto_builder.MakeSimpleProtoClass(
+        fields,
+        full_name='net.proto2.python.public.proto_builder_test.LargeProtoTest')
+
+    reserved_field_numbers = set(
+        range(descriptor.FieldDescriptor.FIRST_RESERVED_FIELD_NUMBER,
+              descriptor.FieldDescriptor.LAST_RESERVED_FIELD_NUMBER + 1))
+    proto_field_numbers = set(proto_cls.DESCRIPTOR.fields_by_number)
+    self.assertFalse(reserved_field_numbers.intersection(proto_field_numbers))
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index beea894..99d2f07 100644
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -295,6 +295,7 @@
   is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
   is_packable = (is_repeated and
                  wire_format.IsTypePackable(field_descriptor.type))
+  is_proto3 = field_descriptor.containing_type.syntax == 'proto3'
   if not is_packable:
     is_packed = False
   elif field_descriptor.containing_type.syntax == 'proto2':
@@ -333,8 +334,12 @@
       decode_type = _FieldDescriptor.TYPE_INT32
 
     oneof_descriptor = None
+    clear_if_default = False
     if field_descriptor.containing_oneof is not None:
       oneof_descriptor = field_descriptor
+    elif (is_proto3 and not is_repeated and
+          field_descriptor.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE):
+      clear_if_default = True
 
     if is_map_entry:
       is_message_map = _IsMessageMapField(field_descriptor)
@@ -347,11 +352,17 @@
       field_decoder = decoder.StringDecoder(
           field_descriptor.number, is_repeated, is_packed,
           field_descriptor, field_descriptor._default_constructor,
-          is_strict_utf8_check)
-    else:
+          is_strict_utf8_check, clear_if_default)
+    elif field_descriptor.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
       field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
           field_descriptor.number, is_repeated, is_packed,
           field_descriptor, field_descriptor._default_constructor)
+    else:
+      field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
+          field_descriptor.number, is_repeated, is_packed,
+          # pylint: disable=protected-access
+          field_descriptor, field_descriptor._default_constructor,
+          clear_if_default)
 
     cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor)
 
@@ -1122,12 +1133,6 @@
 def _AddMergeFromStringMethod(message_descriptor, cls):
   """Helper for _AddMessageMethods()."""
   def MergeFromString(self, serialized):
-    if isinstance(serialized, memoryview) and six.PY2:
-      raise TypeError(
-          'memoryview not supported in Python 2 with the pure Python proto '
-          'implementation: this is to maintain compatibility with the C++ '
-          'implementation')
-
     serialized = memoryview(serialized)
     length = len(serialized)
     try:
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index e67248f..2b9ed1c 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -1311,6 +1311,38 @@
     # Remove a non-existent element.
     self.assertRaises(ValueError, proto.repeated_int32.remove, 123)
 
+  def testRepeatedScalarsReverse_Empty(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertFalse(proto.repeated_int32)
+    self.assertEqual(0, len(proto.repeated_int32))
+
+    self.assertIsNone(proto.repeated_int32.reverse())
+
+    self.assertFalse(proto.repeated_int32)
+    self.assertEqual(0, len(proto.repeated_int32))
+
+  def testRepeatedScalarsReverse_NonEmpty(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertFalse(proto.repeated_int32)
+    self.assertEqual(0, len(proto.repeated_int32))
+
+    proto.repeated_int32.append(1)
+    proto.repeated_int32.append(2)
+    proto.repeated_int32.append(3)
+    proto.repeated_int32.append(4)
+
+    self.assertEqual(4, len(proto.repeated_int32))
+
+    self.assertIsNone(proto.repeated_int32.reverse())
+
+    self.assertEqual(4, len(proto.repeated_int32))
+    self.assertEqual(4, proto.repeated_int32[0])
+    self.assertEqual(3, proto.repeated_int32[1])
+    self.assertEqual(2, proto.repeated_int32[2])
+    self.assertEqual(1, proto.repeated_int32[3])
+
   def testRepeatedComposites(self):
     proto = unittest_pb2.TestAllTypes()
     self.assertFalse(proto.repeated_nested_message)
@@ -1423,6 +1455,35 @@
     self.assertEqual(1, len(proto.repeated_nested_message))
     self.assertEqual(m1, proto.repeated_nested_message[0])
 
+  def testRepeatedCompositeReverse_Empty(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertFalse(proto.repeated_nested_message)
+    self.assertEqual(0, len(proto.repeated_nested_message))
+
+    self.assertIsNone(proto.repeated_nested_message.reverse())
+
+    self.assertFalse(proto.repeated_nested_message)
+    self.assertEqual(0, len(proto.repeated_nested_message))
+
+  def testRepeatedCompositeReverse_NonEmpty(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertFalse(proto.repeated_nested_message)
+    self.assertEqual(0, len(proto.repeated_nested_message))
+
+    m0 = proto.repeated_nested_message.add()
+    m0.bb = len(proto.repeated_nested_message)
+    m1 = proto.repeated_nested_message.add()
+    m1.bb = len(proto.repeated_nested_message)
+    m2 = proto.repeated_nested_message.add()
+    m2.bb = len(proto.repeated_nested_message)
+    self.assertListsEqual([m0, m1, m2], proto.repeated_nested_message)
+
+    self.assertIsNone(proto.repeated_nested_message.reverse())
+
+    self.assertListsEqual([m2, m1, m0], proto.repeated_nested_message)
+
   def testHandWrittenReflection(self):
     # Hand written extensions are only supported by the pure-Python
     # implementation of the API.
@@ -2813,7 +2874,7 @@
         proto2.MergeFromString(serialized))
 
   def _CheckRaises(self, exc_class, callable_obj, exception):
-    """This method checks if the excpetion type and message are as expected."""
+    """This method checks if the exception type and message are as expected."""
     try:
       callable_obj()
     except exc_class as ex:
@@ -3061,10 +3122,10 @@
       unittest_pb2.ForeignMessage.c.__get__(msg)
     except TypeError:
       pass  # The cpp implementation cannot mix fields from other messages.
-            # This test exercises a specific check that avoids a crash.
+      # This test exercises a specific check that avoids a crash.
     else:
       pass  # The python implementation allows fields from other messages.
-            # This is useless, but works.
+      # This is useless, but works.
 
   def testInitKwargs(self):
     proto = unittest_pb2.TestAllTypes(
@@ -3267,7 +3328,7 @@
   # conflicting message descriptors.
   def testParsingFlatClassWithExplicitClassDeclaration(self):
     """Test that the generated class can parse a flat message."""
-    # TODO(xiaofeng): This test fails with cpp implemetnation in the call
+    # TODO(xiaofeng): This test fails with cpp implementation in the call
     # of six.with_metaclass(). The other two callsites of with_metaclass
     # in this file are both excluded from cpp test, so it might be expected
     # to fail. Need someone more familiar with the python code to take a
diff --git a/python/google/protobuf/internal/test_proto3_optional.proto b/python/google/protobuf/internal/test_proto3_optional.proto
index a5abd19..f3e0a2e 100644
--- a/python/google/protobuf/internal/test_proto3_optional.proto
+++ b/python/google/protobuf/internal/test_proto3_optional.proto
@@ -30,10 +30,7 @@
 
 syntax = "proto3";
 
-package protobuf_unittest;
-
-option java_multiple_files = true;
-option java_package = "com.google.protobuf.testing.proto";
+package google.protobuf.python.internal;
 
 message TestProto3Optional {
   message NestedMessage {
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index cdf035b..6f75251 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -57,6 +57,7 @@
 from google.protobuf import descriptor_pb2
 from google.protobuf.internal import any_test_pb2 as test_extend_any
 from google.protobuf.internal import message_set_extensions_pb2
+from google.protobuf.internal import test_proto3_optional_pb2
 from google.protobuf.internal import test_util
 from google.protobuf import descriptor_pool
 from google.protobuf import text_format
@@ -141,6 +142,8 @@
     message.repeated_float.append(1.234e10)
     message.repeated_float.append(1.2345e10)
     message.repeated_float.append(1.23456e10)
+    message.repeated_float.append(float('NaN'))
+    message.repeated_float.append(float('inf'))
     message.repeated_double.append(0.0)
     message.repeated_double.append(0.8)
     message.repeated_double.append(1.0)
@@ -176,14 +179,12 @@
     self.CompareToGoldenText(
         self.RemoveRedundantZeros(text_format.MessageToString(message)),
         'repeated_float: 0\n'
-        # This should be 0.8
-        'repeated_float: 0.80000001\n'
+        'repeated_float: 0.8\n'
         'repeated_float: 1\n'
         'repeated_float: 1.2\n'
         'repeated_float: 1.23\n'
         'repeated_float: 1.234\n'
-        # This should be 1.2345
-        'repeated_float: 1.2345001\n'
+        'repeated_float: 1.2345\n'
         'repeated_float: 1.23456\n'
         # Note that these don't use scientific notation.
         'repeated_float: 12000000000\n'
@@ -191,6 +192,8 @@
         'repeated_float: 12340000000\n'
         'repeated_float: 12345000000\n'
         'repeated_float: 12345600000\n'
+        'repeated_float: nan\n'
+        'repeated_float: inf\n'
         'repeated_double: 0\n'
         'repeated_double: 0.8\n'
         'repeated_double: 1\n'
@@ -400,8 +403,7 @@
     # 32-bit 1.2 is noisy when extended to 64-bit:
     #  >>> struct.unpack('f', struct.pack('f', 1.2))[0]
     #  1.2000000476837158
-    # TODO(jieluo): change to 1.2 with cl/241634942.
-    message.payload.optional_float = 1.2000000476837158
+    message.payload.optional_float = 1.2
     formatted_fields = ['optional_float: 1.2',
                         'optional_double: -3.45678901234568e-6',
                         'repeated_float: -5642', 'repeated_double: 7.89e-5']
@@ -422,7 +424,7 @@
         'payload {{\n  {0}\n  {1}\n  {2}\n  {3}\n}}\n'.format(
             *formatted_fields))
 
-    # Test default float_format has 8 valid digits.
+    # Test default float_format will automatic print shortest float.
     message.payload.optional_float = 1.2345678912
     message.payload.optional_double = 1.2345678912
     formatted_fields = ['optional_float: 1.2345679',
@@ -434,6 +436,17 @@
         'payload {{\n  {0}\n  {1}\n  {2}\n  {3}\n}}\n'.format(
             *formatted_fields))
 
+    message.Clear()
+    message.payload.optional_float = 1.1000000000011
+    self.assertEqual(text_format.MessageToString(message),
+                     'payload {\n  optional_float: 1.1\n}\n')
+    message.payload.optional_float = 1.00000075e-36
+    self.assertEqual(text_format.MessageToString(message),
+                     'payload {\n  optional_float: 1.00000075e-36\n}\n')
+    message.payload.optional_float = 12345678912345e+11
+    self.assertEqual(text_format.MessageToString(message),
+                     'payload {\n  optional_float: 1.234568e+24\n}\n')
+
   def testMessageToString(self, message_module):
     message = message_module.ForeignMessage()
     message.c = 123
@@ -1163,6 +1176,54 @@
         '  }\n'
         '}\n')
 
+  def testDuplicateMapKey(self):
+    message = map_unittest_pb2.TestMap()
+    text = (
+        'map_uint64_uint64 {\n'
+        '  key: 123\n'
+        '  value: 17179869184\n'
+        '}\n'
+        'map_string_string {\n'
+        '  key: "abc"\n'
+        '  value: "first"\n'
+        '}\n'
+        'map_int32_foreign_message {\n'
+        '  key: 111\n'
+        '  value {\n'
+        '    c: 5\n'
+        '  }\n'
+        '}\n'
+        'map_uint64_uint64 {\n'
+        '  key: 123\n'
+        '  value: 321\n'
+        '}\n'
+        'map_string_string {\n'
+        '  key: "abc"\n'
+        '  value: "second"\n'
+        '}\n'
+        'map_int32_foreign_message {\n'
+        '  key: 111\n'
+        '  value {\n'
+        '    d: 5\n'
+        '  }\n'
+        '}\n')
+    text_format.Parse(text, message)
+    self.CompareToGoldenText(
+        text_format.MessageToString(message), 'map_uint64_uint64 {\n'
+        '  key: 123\n'
+        '  value: 321\n'
+        '}\n'
+        'map_string_string {\n'
+        '  key: "abc"\n'
+        '  value: "second"\n'
+        '}\n'
+        'map_int32_foreign_message {\n'
+        '  key: 111\n'
+        '  value {\n'
+        '    d: 5\n'
+        '  }\n'
+        '}\n')
+
   # In cpp implementation, __str__ calls the cpp implementation of text format.
   def testPrintMapUsingCppImplementation(self):
     message = map_unittest_pb2.TestMap()
@@ -1850,6 +1911,24 @@
       text_format.Merge(text, message)
     self.assertEqual(str(e.exception), '3:11 : Expected "}".')
 
+  def testProto3Optional(self):
+    msg = test_proto3_optional_pb2.TestProto3Optional()
+    self.assertEqual(text_format.MessageToString(msg), '')
+    msg.optional_int32 = 0
+    msg.optional_float = 0.0
+    msg.optional_string = ''
+    msg.optional_nested_message.bb = 0
+    text = ('optional_int32: 0\n'
+            'optional_float: 0.0\n'
+            'optional_string: ""\n'
+            'optional_nested_message {\n'
+            '  bb: 0\n'
+            '}\n')
+    self.assertEqual(text_format.MessageToString(msg), text)
+    msg2 = test_proto3_optional_pb2.TestProto3Optional()
+    text_format.Parse(text, msg2)
+    self.assertEqual(text_format.MessageToString(msg2), text)
+
 
 class TokenizerTest(unittest.TestCase):
 
@@ -2317,6 +2396,13 @@
                 '}\n')
     self.assertEqual(expected, output)
 
+  def testPrintShortFormatRepeatedFields(self):
+    message = unittest_pb2.TestAllTypes()
+    message.repeated_int32.append(1)
+    output = text_format.MessageToString(
+        message, use_short_repeated_primitives=True, force_colon=True)
+    self.assertEqual('repeated_int32: [1]\n', output)
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index 514a558..eb66f9f 100644
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -72,6 +72,21 @@
     return struct.unpack('<f', struct.pack('<f', original))[0]
 
 
+def ToShortestFloat(original):
+  """Returns the shortest float that has same value in wire."""
+  # All 4 byte floats have between 6 and 9 significant digits, so we
+  # start with 6 as the lower bound.
+  # It has to be iterative because use '.9g' directly can not get rid
+  # of the noises for most values. For example if set a float_field=0.9
+  # use '.9g' will print 0.899999976.
+  precision = 6
+  rounded = float('{0:.{1}g}'.format(original, precision))
+  while TruncateToFourByteFloat(rounded) != original:
+    precision += 1
+    rounded = float('{0:.{1}g}'.format(original, precision))
+  return rounded
+
+
 def SupportsOpenEnums(field_descriptor):
   return field_descriptor.containing_type.syntax == "proto3"
 
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index 277603d..d0ac5d9 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -39,6 +39,7 @@
   import unittest2 as unittest  #PY26
 except ImportError:
   import unittest
+import sys
 from google.protobuf import map_unittest_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
@@ -53,6 +54,12 @@
 from google.protobuf.internal import wire_format
 from google.protobuf import descriptor
 
+try:
+  import tracemalloc  # pylint: disable=g-import-not-at-top
+except ImportError:
+  # Requires python 3.4+
+  pass
+
 
 @testing_refleaks.TestCase
 class UnknownFieldsTest(unittest.TestCase):
@@ -312,6 +319,26 @@
     self.assertIn('UnknownFields does not exist.',
                   str(context.exception))
 
+  @unittest.skipIf((sys.version_info.major, sys.version_info.minor) < (3, 4),
+                   'tracemalloc requires python 3.4+')
+  def testUnknownFieldsNoMemoryLeak(self):
+    # Call to UnknownFields must not leak memory
+    nb_leaks = 1234
+
+    def leaking_function():
+      for _ in range(nb_leaks):
+        self.empty_message.UnknownFields()
+
+    tracemalloc.start()
+    snapshot1 = tracemalloc.take_snapshot()
+    leaking_function()
+    snapshot2 = tracemalloc.take_snapshot()
+    top_stats = snapshot2.compare_to(snapshot1, 'lineno')
+    tracemalloc.stop()
+    # There's no easy way to look for a precise leak source.
+    # Rely on a "marker" count value while checking allocated memory.
+    self.assertEqual([], [x for x in top_stats if x.count_diff == nb_leaks])
+
   def testSubUnknownFields(self):
     message = unittest_pb2.TestAllTypes()
     message.optionalgroup.a = 123
diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py
index 308fbfe..56659ac 100644
--- a/python/google/protobuf/internal/well_known_types.py
+++ b/python/google/protobuf/internal/well_known_types.py
@@ -143,6 +143,9 @@
     Raises:
       ValueError: On parsing problems.
     """
+    if not isinstance(value, six.string_types):
+      raise ValueError(
+          'Timestamp JSON value not a string: {!r}'.format(value))
     timezone_offset = value.find('Z')
     if timezone_offset == -1:
       timezone_offset = value.find('+')
@@ -160,6 +163,10 @@
     else:
       second_value = time_value[:point_position]
       nano_value = time_value[point_position + 1:]
+    if 't' in second_value:
+      raise ValueError(
+          'time data \'{0}\' does not match format \'%Y-%m-%dT%H:%M:%S\', '
+          'lowercase \'t\' is not accepted'.format(second_value))
     date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT)
     td = date_object - datetime(1970, 1, 1)
     seconds = td.seconds + td.days * _SECONDS_PER_DAY
@@ -299,6 +306,9 @@
     Raises:
       ValueError: On parsing problems.
     """
+    if not isinstance(value, six.string_types):
+      raise ValueError(
+          'Duration JSON value not a string: {!r}'.format(value))
     if len(value) < 1 or value[-1] != 's':
       raise ValueError(
           'Duration must end with letter "s": {0}.'.format(value))
@@ -397,7 +407,7 @@
 
 def _RoundTowardZero(value, divider):
   """Truncates the remainder part after division."""
-  # For some languanges, the sign of the remainder is implementation
+  # For some languages, the sign of the remainder is implementation
   # dependent if any of the operands is negative. Here we enforce
   # "rounded toward zero" semantics. For example, for (-5) / 2 an
   # implementation may give -3 as the result with the remainder being
@@ -424,6 +434,9 @@
 
   def FromJsonString(self, value):
     """Converts string to FieldMask according to proto3 JSON spec."""
+    if not isinstance(value, six.string_types):
+      raise ValueError(
+          'FieldMask JSON value not a string: {!r}'.format(value))
     self.Clear()
     if value:
       for path in value.split(','):
diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py
index b57837c..965614d 100644
--- a/python/google/protobuf/json_format.py
+++ b/python/google/protobuf/json_format.py
@@ -195,7 +195,6 @@
     self.preserving_proto_field_name = preserving_proto_field_name
     self.use_integers_for_enums = use_integers_for_enums
     self.descriptor_pool = descriptor_pool
-    # TODO(jieluo): change the float precision default to 8 valid digits.
     if float_precision:
       self.float_format = '.{}g'.format(float_precision)
     else:
@@ -246,8 +245,7 @@
           js[name] = [self._FieldToJsonObject(field, k)
                       for k in value]
         elif field.is_extension:
-          full_qualifier = field.full_name[:-len(field.name)]
-          name = '[%s%s]' % (full_qualifier, name)
+          name = '[%s]' % field.full_name
           js[name] = self._FieldToJsonObject(field, value)
         else:
           js[name] = self._FieldToJsonObject(field, value)
@@ -283,30 +281,13 @@
 
   def _FieldToJsonObject(self, field, value):
     """Converts field value according to Proto3 JSON Specification."""
-
-    def _ToShortestFloat(original):
-      """Returns the shortest float that has same value in wire."""
-      # Return the original value if it is not truncated. This may happen
-      # if someone mixes this code with an old protobuf runtime.
-      if type_checkers.TruncateToFourByteFloat(original) != original:
-        return original
-      # All 4 byte floats have between 6 and 9 significant digits, so we
-      # start with 6 as the lower bound.
-      # It has to be iterative because use '.9g' directly can not get rid
-      # of the noises for most values. For example if set a float_field=0.9
-      # use '.9g' will print 0.899999976.
-      precision = 6
-      rounded = float('{0:.{1}g}'.format(original, precision))
-      while type_checkers.TruncateToFourByteFloat(rounded) != original:
-        precision += 1
-        rounded = float('{0:.{1}g}'.format(original, precision))
-      return rounded
-
     if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
       return self._MessageToJsonObject(value)
     elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
       if self.use_integers_for_enums:
         return value
+      if field.enum_type.full_name == 'google.protobuf.NullValue':
+        return None
       enum_value = field.enum_type.values_by_number.get(value, None)
       if enum_value is not None:
         return enum_value.name
@@ -337,7 +318,7 @@
         if self.float_format:
           return float(format(value, self.float_format))
         else:
-          return _ToShortestFloat(value)
+          return type_checkers.ToShortestFloat(value)
 
     return value
 
@@ -550,8 +531,9 @@
                            '"{1}" fields.'.format(
                                message.DESCRIPTOR.full_name, name))
         names.append(name)
+        value = js[name]
         # Check no other oneof field is parsed.
-        if field.containing_oneof is not None:
+        if field.containing_oneof is not None and value is not None:
           oneof_name = field.containing_oneof.name
           if oneof_name in names:
             raise ParseError('Message type "{0}" should not have multiple '
@@ -559,12 +541,14 @@
                                  message.DESCRIPTOR.full_name, oneof_name))
           names.append(oneof_name)
 
-        value = js[name]
         if value is None:
           if (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE
               and field.message_type.full_name == 'google.protobuf.Value'):
             sub_message = getattr(message, field.name)
             sub_message.null_value = 0
+          elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM
+                and field.enum_type.full_name == 'google.protobuf.NullValue'):
+            setattr(message, field.name, 0)
           else:
             message.ClearField(field.name)
           continue
@@ -667,7 +651,8 @@
     elif isinstance(value, _INT_OR_FLOAT):
       message.number_value = value
     else:
-      raise ParseError('Unexpected type for Value message.')
+      raise ParseError('Value {0} has unexpected type {1}.'.format(
+          value, type(value)))
 
   def _ConvertListValueMessage(self, value, message):
     """Convert a JSON representation into ListValue message."""
@@ -739,12 +724,18 @@
   if field.cpp_type in _INT_TYPES:
     return _ConvertInteger(value)
   elif field.cpp_type in _FLOAT_TYPES:
-    return _ConvertFloat(value)
+    return _ConvertFloat(value, field)
   elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
     return _ConvertBool(value, require_str)
   elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
     if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
-      return base64.b64decode(value)
+      if isinstance(value, six.text_type):
+        encoded = value.encode('utf-8')
+      else:
+        encoded = value
+      # Add extra padding '='
+      padded_value = encoded + b'=' * (4 - len(encoded) % 4)
+      return base64.urlsafe_b64decode(padded_value)
     else:
       # Checking for unpaired surrogates appears to be unreliable,
       # depending on the specific Python version, so we check manually.
@@ -788,11 +779,32 @@
   if isinstance(value, six.text_type) and value.find(' ') != -1:
     raise ParseError('Couldn\'t parse integer: "{0}".'.format(value))
 
+  if isinstance(value, bool):
+    raise ParseError('Bool value {0} is not acceptable for '
+                     'integer field.'.format(value))
+
   return int(value)
 
 
-def _ConvertFloat(value):
+def _ConvertFloat(value, field):
   """Convert an floating point number."""
+  if isinstance(value, float):
+    if math.isnan(value):
+      raise ParseError('Couldn\'t parse NaN, use quoted "NaN" instead.')
+    if math.isinf(value):
+      if value > 0:
+        raise ParseError('Couldn\'t parse Infinity or value too large, '
+                         'use quoted "Infinity" instead.')
+      else:
+        raise ParseError('Couldn\'t parse -Infinity or value too small, '
+                         'use quoted "-Infinity" instead.')
+    if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
+      # pylint: disable=protected-access
+      if value > type_checkers._FLOAT_MAX:
+        raise ParseError('Float value too large')
+      # pylint: disable=protected-access
+      if value < type_checkers._FLOAT_MIN:
+        raise ParseError('Float value too small')
   if value == 'nan':
     raise ParseError('Couldn\'t parse float "nan", use "NaN" instead.')
   try:
diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py
index 24a524a..7dfaec8 100644
--- a/python/google/protobuf/message_factory.py
+++ b/python/google/protobuf/message_factory.py
@@ -64,7 +64,7 @@
     self._classes = {}
 
   def GetPrototype(self, descriptor):
-    """Builds a proto2 message class based on the passed in descriptor.
+    """Obtains a proto2 message class based on the passed in descriptor.
 
     Passing a descriptor with a fully qualified name matching a previous
     invocation will cause the same class to be returned.
@@ -76,27 +76,52 @@
       A class describing the passed in descriptor.
     """
     if descriptor not in self._classes:
-      descriptor_name = descriptor.name
-      if str is bytes:  # PY2
-        descriptor_name = descriptor.name.encode('ascii', 'ignore')
-      result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
-          descriptor_name,
-          (message.Message,),
-          {'DESCRIPTOR': descriptor, '__module__': None})
-      # pylint: disable=protected-access
-      result_class._FACTORY = self
-      # If module not set, it wrongly points to message_factory module.
+      result_class = self.CreatePrototype(descriptor)
+      # The assignment to _classes is redundant for the base implementation, but
+      # might avoid confusion in cases where CreatePrototype gets overridden and
+      # does not call the base implementation.
       self._classes[descriptor] = result_class
-      for field in descriptor.fields:
-        if field.message_type:
-          self.GetPrototype(field.message_type)
-      for extension in result_class.DESCRIPTOR.extensions:
-        if extension.containing_type not in self._classes:
-          self.GetPrototype(extension.containing_type)
-        extended_class = self._classes[extension.containing_type]
-        extended_class.RegisterExtension(extension)
+      return result_class
     return self._classes[descriptor]
 
+  def CreatePrototype(self, descriptor):
+    """Builds a proto2 message class based on the passed in descriptor.
+
+    Don't call this function directly, it always creates a new class. Call
+    GetPrototype() instead. This method is meant to be overridden in subblasses
+    to perform additional operations on the newly constructed class.
+
+    Args:
+      descriptor: The descriptor to build from.
+
+    Returns:
+      A class describing the passed in descriptor.
+    """
+    descriptor_name = descriptor.name
+    if str is bytes:  # PY2
+      descriptor_name = descriptor.name.encode('ascii', 'ignore')
+    result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
+        descriptor_name,
+        (message.Message,),
+        {
+            'DESCRIPTOR': descriptor,
+            # If module not set, it wrongly points to message_factory module.
+            '__module__': None,
+        })
+    result_class._FACTORY = self  # pylint: disable=protected-access
+    # Assign in _classes before doing recursive calls to avoid infinite
+    # recursion.
+    self._classes[descriptor] = result_class
+    for field in descriptor.fields:
+      if field.message_type:
+        self.GetPrototype(field.message_type)
+    for extension in result_class.DESCRIPTOR.extensions:
+      if extension.containing_type not in self._classes:
+        self.GetPrototype(extension.containing_type)
+      extended_class = self._classes[extension.containing_type]
+      extended_class.RegisterExtension(extension)
+    return result_class
+
   def GetMessages(self, files):
     """Gets all the messages from a specified file.
 
diff --git a/python/google/protobuf/proto_api.h b/python/google/protobuf/proto_api.h
index 75ee979..c869bce 100644
--- a/python/google/protobuf/proto_api.h
+++ b/python/google/protobuf/proto_api.h
@@ -82,6 +82,32 @@
   // to create Python-compatible message.
   virtual const DescriptorPool* GetDefaultDescriptorPool() const = 0;
   virtual MessageFactory* GetDefaultMessageFactory() const = 0;
+
+  // Allocate a new protocol buffer as a python object for the provided
+  // descriptor. This function works even if no Python module has been imported
+  // for the corresponding protocol buffer class.
+  // The factory is usually null; when provided, it is the MessageFactory which
+  // owns the Python class, and will be used to find and create Extensions for
+  // this message.
+  // When null is returned, a python error has already been set.
+  virtual PyObject* NewMessage(const Descriptor* descriptor,
+                               PyObject* py_message_factory) const = 0;
+
+  // Allocate a new protocol buffer where the underlying object is owned by C++.
+  // The factory must currently be null.  This function works even if no Python
+  // module has been imported for the corresponding protocol buffer class.
+  // When null is returned, a python error has already been set.
+  //
+  // Since this call returns a python object owned by C++, some operations
+  // are risky, and it must be used carefully. In particular:
+  // * Avoid modifying the returned object from the C++ side while there are
+  // existing python references to it or it's subobjects.
+  // * Avoid using python references to this object or any subobjects after the
+  // C++ object has been freed.
+  // * Calling this with the same C++ pointer will result in multiple distinct
+  // python objects referencing the same C++ object.
+  virtual PyObject* NewMessageOwnedExternally(
+      Message* msg, PyObject* py_message_factory) const = 0;
 };
 
 inline const char* PyProtoAPICapsuleName() {
diff --git a/python/google/protobuf/proto_builder.py b/python/google/protobuf/proto_builder.py
index 736caed..2b7dddc 100644
--- a/python/google/protobuf/proto_builder.py
+++ b/python/google/protobuf/proto_builder.py
@@ -31,13 +31,14 @@
 """Dynamic Protobuf class creator."""
 
 try:
-    from collections import OrderedDict
+  from collections import OrderedDict
 except ImportError:
-    from ordereddict import OrderedDict  #PY26
+  from ordereddict import OrderedDict  #PY26
 import hashlib
 import os
 
 from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor
 from google.protobuf import message_factory
 
 
@@ -124,6 +125,12 @@
   for f_number, (f_name, f_type) in enumerate(field_items, 1):
     field_proto = desc_proto.field.add()
     field_proto.name = f_name
+    # # If the number falls in the reserved range, reassign it to the correct
+    # # number after the range.
+    if f_number >= descriptor.FieldDescriptor.FIRST_RESERVED_FIELD_NUMBER:
+      f_number += (
+          descriptor.FieldDescriptor.LAST_RESERVED_FIELD_NUMBER -
+          descriptor.FieldDescriptor.FIRST_RESERVED_FIELD_NUMBER + 1)
     field_proto.number = f_number
     field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
     field_proto.type = f_type
diff --git a/python/google/protobuf/pyext/__init__.py b/python/google/protobuf/pyext/__init__.py
index 5585614..e69de29 100644
--- a/python/google/protobuf/pyext/__init__.py
+++ b/python/google/protobuf/pyext/__init__.py
@@ -1,4 +0,0 @@
-try:
-  __import__('pkg_resources').declare_namespace(__name__)
-except ImportError:
-  __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 24b2b46..eeb844c 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -30,15 +30,18 @@
 
 // Author: petar@google.com (Petar Petrov)
 
+#include <google/protobuf/pyext/descriptor.h>
+
 #include <Python.h>
 #include <frameobject.h>
+
+#include <cstdint>
 #include <string>
 #include <unordered_map>
 
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/pyext/descriptor.h>
 #include <google/protobuf/pyext/descriptor_containers.h>
 #include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
@@ -195,7 +198,7 @@
   std::string serialized;
   from.SerializeToString(&serialized);
   io::CodedInputStream input(
-      reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
+      reinterpret_cast<const uint8_t*>(serialized.c_str()), serialized.size());
   input.SetExtensionRegistry(message_factory->pool->pool,
                              message_factory->message_factory);
   bool success = to->ParseFromCodedStream(&input);
@@ -247,8 +250,9 @@
                  message_type->full_name().c_str());
     return NULL;
   }
+  ScopedPyObjectPtr args(PyTuple_New(0));
   ScopedPyObjectPtr value(
-      PyEval_CallObject(message_class->AsPyObject(), NULL));
+      PyObject_Call(message_class->AsPyObject(), args.get(), NULL));
   Py_DECREF(message_class);
   if (value == NULL) {
     return NULL;
@@ -804,22 +808,22 @@
 
   switch (_GetDescriptor(self)->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
-      int32 value = _GetDescriptor(self)->default_value_int32();
+      int32_t value = _GetDescriptor(self)->default_value_int32();
       result = PyInt_FromLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_INT64: {
-      int64 value = _GetDescriptor(self)->default_value_int64();
+      int64_t value = _GetDescriptor(self)->default_value_int64();
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT32: {
-      uint32 value = _GetDescriptor(self)->default_value_uint32();
+      uint32_t value = _GetDescriptor(self)->default_value_uint32();
       result = PyInt_FromSize_t(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT64: {
-      uint64 value = _GetDescriptor(self)->default_value_uint64();
+      uint64_t value = _GetDescriptor(self)->default_value_uint64();
       result = PyLong_FromUnsignedLongLong(value);
       break;
     }
@@ -1690,7 +1694,7 @@
   }
 
   const MethodDescriptor* method_descriptor =
-      _GetDescriptor(self)->FindMethodByName(std::string(name, name_size));
+      _GetDescriptor(self)->FindMethodByName(StringParam(name, name_size));
   if (method_descriptor == NULL) {
     PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
     return NULL;
diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h
index 327ba4b..b99209d 100644
--- a/python/google/protobuf/pyext/descriptor.h
+++ b/python/google/protobuf/pyext/descriptor.h
@@ -41,6 +41,9 @@
 namespace protobuf {
 namespace python {
 
+// Should match the type of ConstStringParam.
+using StringParam = std::string;
+
 extern PyTypeObject PyMessageDescriptor_Type;
 extern PyTypeObject PyFieldDescriptor_Type;
 extern PyTypeObject PyEnumDescriptor_Type;
diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc
index 865f0c0..c6ec258 100644
--- a/python/google/protobuf/pyext/descriptor_containers.cc
+++ b/python/google/protobuf/pyext/descriptor_containers.cc
@@ -81,9 +81,9 @@
 typedef int (*CountMethod)(PyContainer* self);
 typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
 typedef const void* (*GetByNameMethod)(PyContainer* self,
-                                       const std::string& name);
+                                       ConstStringParam name);
 typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self,
-                                                const std::string& name);
+                                                ConstStringParam name);
 typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
 typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
 typedef const std::string& (*GetItemNameMethod)(const void* descriptor);
@@ -183,7 +183,7 @@
           return false;
         }
         *item = self->container_def->get_by_name_fn(
-            self, std::string(name, name_size));
+            self, StringParam(name, name_size));
         return true;
       }
     case PyContainer::KIND_BYCAMELCASENAME:
@@ -200,7 +200,7 @@
           return false;
         }
         *item = self->container_def->get_by_camelcase_name_fn(
-            self, std::string(camelcase_name, name_size));
+            self, StringParam(camelcase_name, name_size));
         return true;
       }
     case PyContainer::KIND_BYNUMBER:
@@ -962,12 +962,12 @@
   return GetDescriptor(self)->field_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindFieldByName(name);
 }
 
 static const void* GetByCamelcaseName(PyContainer* self,
-                                      const std::string& name) {
+                                      ConstStringParam name) {
   return GetDescriptor(self)->FindFieldByCamelcaseName(name);
 }
 
@@ -1040,7 +1040,7 @@
   return GetDescriptor(self)->nested_type_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindNestedTypeByName(name);
 }
 
@@ -1092,7 +1092,7 @@
   return GetDescriptor(self)->enum_type_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindEnumTypeByName(name);
 }
 
@@ -1155,7 +1155,7 @@
   return count;
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindEnumValueByName(name);
 }
 
@@ -1215,7 +1215,7 @@
   return GetDescriptor(self)->extension_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindExtensionByName(name);
 }
 
@@ -1267,7 +1267,7 @@
   return GetDescriptor(self)->oneof_decl_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindOneofByName(name);
 }
 
@@ -1333,7 +1333,7 @@
   return GetDescriptor(self)->value(index);
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindValueByName(name);
 }
 
@@ -1454,7 +1454,7 @@
   return GetDescriptor(self)->method_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindMethodByName(name);
 }
 
@@ -1516,7 +1516,7 @@
   return GetDescriptor(self)->message_type_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindMessageTypeByName(name);
 }
 
@@ -1564,7 +1564,7 @@
   return GetDescriptor(self)->enum_type_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindEnumTypeByName(name);
 }
 
@@ -1612,7 +1612,7 @@
   return GetDescriptor(self)->extension_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindExtensionByName(name);
 }
 
@@ -1660,7 +1660,7 @@
   return GetDescriptor(self)->service_count();
 }
 
-static const void* GetByName(PyContainer* self, const std::string& name) {
+static const void* GetByName(PyContainer* self, ConstStringParam name) {
   return GetDescriptor(self)->FindServiceByName(name);
 }
 
diff --git a/python/google/protobuf/pyext/descriptor_database.cc b/python/google/protobuf/pyext/descriptor_database.cc
index 26f1b5f..da1c84a 100644
--- a/python/google/protobuf/pyext/descriptor_database.cc
+++ b/python/google/protobuf/pyext/descriptor_database.cc
@@ -33,6 +33,8 @@
 
 #include <google/protobuf/pyext/descriptor_database.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -164,7 +166,7 @@
     return false;
   }
   Py_ssize_t size = PyList_Size(py_list.get());
-  int64 item_value;
+  int64_t item_value;
   for (Py_ssize_t i = 0 ; i < size; ++i) {
     ScopedPyObjectPtr item(PySequence_GetItem(py_list.get(), i));
     item_value = PyLong_AsLong(item.get());
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index 2cffea3..b607956 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -176,9 +176,10 @@
 // The public DescriptorPool constructor.
 static PyObject* New(PyTypeObject* type,
                      PyObject* args, PyObject* kwargs) {
-  static char* kwlist[] = {"descriptor_db", 0};
+  static const char* kwlist[] = {"descriptor_db", 0};
   PyObject* py_database = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &py_database)) {
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
+                                   const_cast<char**>(kwlist), &py_database)) {
     return NULL;
   }
   DescriptorDatabase* database = NULL;
@@ -218,7 +219,7 @@
 }
 
 PyObject* SetErrorFromCollector(DescriptorPool::ErrorCollector* self,
-                                char* name, char* error_type) {
+                                const char* name, const char* error_type) {
   BuildFileErrorCollector* error_collector =
       reinterpret_cast<BuildFileErrorCollector*>(self);
   if (error_collector && !error_collector->error_message.empty()) {
@@ -240,7 +241,7 @@
 
   const Descriptor* message_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMessageTypeByName(
-          std::string(name, name_size));
+          StringParam(name, name_size));
 
   if (message_descriptor == NULL) {
     return SetErrorFromCollector(
@@ -264,7 +265,7 @@
 
   PyDescriptorPool* py_pool = reinterpret_cast<PyDescriptorPool*>(self);
   const FileDescriptor* file_descriptor =
-      py_pool->pool->FindFileByName(std::string(name, name_size));
+      py_pool->pool->FindFileByName(StringParam(name, name_size));
 
   if (file_descriptor == NULL) {
     return SetErrorFromCollector(py_pool->error_collector, name, "file");
@@ -280,7 +281,7 @@
   }
 
   const FieldDescriptor* field_descriptor =
-      self->pool->FindFieldByName(std::string(name, name_size));
+      self->pool->FindFieldByName(StringParam(name, name_size));
   if (field_descriptor == NULL) {
     return SetErrorFromCollector(self->error_collector, name, "field");
   }
@@ -301,7 +302,7 @@
   }
 
   const FieldDescriptor* field_descriptor =
-      self->pool->FindExtensionByName(std::string(name, name_size));
+      self->pool->FindExtensionByName(StringParam(name, name_size));
   if (field_descriptor == NULL) {
     return SetErrorFromCollector(self->error_collector, name,
                                  "extension field");
@@ -323,7 +324,7 @@
   }
 
   const EnumDescriptor* enum_descriptor =
-      self->pool->FindEnumTypeByName(std::string(name, name_size));
+      self->pool->FindEnumTypeByName(StringParam(name, name_size));
   if (enum_descriptor == NULL) {
     return SetErrorFromCollector(self->error_collector, name, "enum");
   }
@@ -344,7 +345,7 @@
   }
 
   const OneofDescriptor* oneof_descriptor =
-      self->pool->FindOneofByName(std::string(name, name_size));
+      self->pool->FindOneofByName(StringParam(name, name_size));
   if (oneof_descriptor == NULL) {
     return SetErrorFromCollector(self->error_collector, name, "oneof");
   }
@@ -366,7 +367,7 @@
 
   const ServiceDescriptor* service_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindServiceByName(
-          std::string(name, name_size));
+          StringParam(name, name_size));
   if (service_descriptor == NULL) {
     return SetErrorFromCollector(
         reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
@@ -386,7 +387,7 @@
 
   const MethodDescriptor* method_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMethodByName(
-          std::string(name, name_size));
+          StringParam(name, name_size));
   if (method_descriptor == NULL) {
     return SetErrorFromCollector(
         reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
@@ -406,7 +407,7 @@
 
   const FileDescriptor* file_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileContainingSymbol(
-          std::string(name, name_size));
+          StringParam(name, name_size));
   if (file_descriptor == NULL) {
     return SetErrorFromCollector(
         reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index d7226d0..37b414c 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -32,14 +32,16 @@
 // Author: tibell@google.com (Johan Tibell)
 
 #include <google/protobuf/pyext/extension_dict.h>
+
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/message.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/pyext/descriptor.h>
 #include <google/protobuf/pyext/message.h>
 #include <google/protobuf/pyext/message_factory.h>
@@ -240,11 +242,11 @@
 
   PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool;
   const FieldDescriptor* message_extension =
-      pool->pool->FindExtensionByName(std::string(name, name_size));
+      pool->pool->FindExtensionByName(StringParam(name, name_size));
   if (message_extension == NULL) {
     // Is is the name of a message set extension?
     const Descriptor* message_descriptor =
-        pool->pool->FindMessageTypeByName(std::string(name, name_size));
+        pool->pool->FindMessageTypeByName(StringParam(name, name_size));
     if (message_descriptor && message_descriptor->extension_count() > 0) {
       const FieldDescriptor* extension = message_descriptor->extension(0);
       if (extension->is_extension() &&
@@ -263,7 +265,7 @@
 }
 
 PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* arg) {
-  int64 number = PyLong_AsLong(arg);
+  int64_t number = PyLong_AsLong(arg);
   if (number == -1 && PyErr_Occurred()) {
     return NULL;
   }
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index ed0d31c..1c2c526 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -32,15 +32,16 @@
 
 #include <google/protobuf/pyext/map_container.h>
 
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/map_field.h>
 #include <google/protobuf/map.h>
+#include <google/protobuf/map_field.h>
 #include <google/protobuf/message.h>
-#include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/pyext/repeated_composite_container.h>
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
 #include <google/protobuf/stubs/map_util.h>
@@ -99,7 +100,7 @@
   //
   // We store this so that if the map is modified during iteration we can throw
   // an error.
-  uint64 version;
+  uint64_t version;
 };
 
 Message* MapContainer::GetMutableMessage() {
@@ -125,9 +126,9 @@
   }
 }
 
-static bool PythonToMapKey(PyObject* obj,
-                           const FieldDescriptor* field_descriptor,
-                           MapKey* key) {
+static bool PythonToMapKey(MapContainer* self, PyObject* obj, MapKey* key) {
+  const FieldDescriptor* field_descriptor =
+      self->parent_field_descriptor->message_type()->map_key();
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
       GOOGLE_CHECK_GET_INT32(obj, value, false);
@@ -171,8 +172,9 @@
   return true;
 }
 
-static PyObject* MapKeyToPython(const FieldDescriptor* field_descriptor,
-                                const MapKey& key) {
+static PyObject* MapKeyToPython(MapContainer* self, const MapKey& key) {
+  const FieldDescriptor* field_descriptor =
+      self->parent_field_descriptor->message_type()->map_key();
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
       return PyInt_FromLong(key.GetInt32Value());
@@ -196,8 +198,9 @@
 
 // This is only used for ScalarMap, so we don't need to handle the
 // CPPTYPE_MESSAGE case.
-PyObject* MapValueRefToPython(const FieldDescriptor* field_descriptor,
-                              const MapValueRef& value) {
+PyObject* MapValueRefToPython(MapContainer* self, const MapValueRef& value) {
+  const FieldDescriptor* field_descriptor =
+      self->parent_field_descriptor->message_type()->map_value();
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
       return PyInt_FromLong(value.GetInt32Value());
@@ -227,10 +230,11 @@
 
 // This is only used for ScalarMap, so we don't need to handle the
 // CPPTYPE_MESSAGE case.
-static bool PythonToMapValueRef(PyObject* obj,
-                                const FieldDescriptor* field_descriptor,
+static bool PythonToMapValueRef(MapContainer* self, PyObject* obj,
                                 bool allow_unknown_enum_values,
                                 MapValueRef* value_ref) {
+  const FieldDescriptor* field_descriptor =
+      self->parent_field_descriptor->message_type()->map_value();
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
       GOOGLE_CHECK_GET_INT32(obj, value, false);
@@ -336,6 +340,11 @@
 
 PyObject* MapReflectionFriend::MergeFrom(PyObject* _self, PyObject* arg) {
   MapContainer* self = GetMap(_self);
+  if (!PyObject_TypeCheck(arg, ScalarMapContainer_Type) &&
+      !PyObject_TypeCheck(arg, MessageMapContainer_Type)) {
+    PyErr_SetString(PyExc_AttributeError, "Not a map field");
+    return nullptr;
+  }
   MapContainer* other_map = GetMap(arg);
   Message* message = self->GetMutableMessage();
   const Message* other_message = other_map->parent->message;
@@ -357,7 +366,7 @@
   const Reflection* reflection = message->GetReflection();
   MapKey map_key;
 
-  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+  if (!PythonToMapKey(self, key, &map_key)) {
     return NULL;
   }
 
@@ -391,18 +400,6 @@
   self->parent_field_descriptor = parent_field_descriptor;
   self->version = 0;
 
-  self->key_field_descriptor =
-      parent_field_descriptor->message_type()->FindFieldByName("key");
-  self->value_field_descriptor =
-      parent_field_descriptor->message_type()->FindFieldByName("value");
-
-  if (self->key_field_descriptor == NULL ||
-      self->value_field_descriptor == NULL) {
-    PyErr_Format(PyExc_KeyError,
-                 "Map entry descriptor did not have key/value fields");
-    return NULL;
-  }
-
   return self;
 }
 
@@ -415,7 +412,7 @@
   MapKey map_key;
   MapValueRef value;
 
-  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+  if (!PythonToMapKey(self, key, &map_key)) {
     return NULL;
   }
 
@@ -424,7 +421,7 @@
     self->version++;
   }
 
-  return MapValueRefToPython(self->value_field_descriptor, value);
+  return MapValueRefToPython(self, value);
 }
 
 int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key,
@@ -436,7 +433,7 @@
   MapKey map_key;
   MapValueRef value;
 
-  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+  if (!PythonToMapKey(self, key, &map_key)) {
     return -1;
   }
 
@@ -447,10 +444,11 @@
     reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
                                        map_key, &value);
 
-    return PythonToMapValueRef(v, self->value_field_descriptor,
-                               reflection->SupportsUnknownEnumValues(), &value)
-               ? 0
-               : -1;
+    if (!PythonToMapValueRef(self, v, reflection->SupportsUnknownEnumValues(),
+                             &value)) {
+      return -1;
+    }
+    return 0;
   } else {
     // Delete key from map.
     if (reflection->DeleteMapValue(message, self->parent_field_descriptor,
@@ -465,10 +463,11 @@
 
 static PyObject* ScalarMapGet(PyObject* self, PyObject* args,
                               PyObject* kwargs) {
-  static char* kwlist[] = {"key", "default", nullptr};
+  static const char* kwlist[] = {"key", "default", nullptr};
   PyObject* key;
   PyObject* default_value = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
+                                   const_cast<char**>(kwlist), &key,
                                    &default_value)) {
     return NULL;
   }
@@ -505,13 +504,11 @@
            message, self->parent_field_descriptor);
        it != reflection->MapEnd(message, self->parent_field_descriptor);
        ++it) {
-    key.reset(MapKeyToPython(self->key_field_descriptor,
-                             it.GetKey()));
+    key.reset(MapKeyToPython(self, it.GetKey()));
     if (key == NULL) {
       return NULL;
     }
-    value.reset(MapValueRefToPython(self->value_field_descriptor,
-                                    it.GetValueRef()));
+    value.reset(MapValueRefToPython(self, it.GetValueRef()));
     if (value == NULL) {
       return NULL;
     }
@@ -655,22 +652,9 @@
   self->parent_field_descriptor = parent_field_descriptor;
   self->version = 0;
 
-  self->key_field_descriptor =
-      parent_field_descriptor->message_type()->FindFieldByName("key");
-  self->value_field_descriptor =
-      parent_field_descriptor->message_type()->FindFieldByName("value");
-
   Py_INCREF(message_class);
   self->message_class = message_class;
 
-  if (self->key_field_descriptor == NULL ||
-      self->value_field_descriptor == NULL) {
-    Py_DECREF(self);
-    PyErr_SetString(PyExc_KeyError,
-                    "Map entry descriptor did not have key/value fields");
-    return NULL;
-  }
-
   return self;
 }
 
@@ -692,7 +676,7 @@
 
   self->version++;
 
-  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+  if (!PythonToMapKey(self, key, &map_key)) {
     return -1;
   }
 
@@ -732,7 +716,7 @@
   MapKey map_key;
   MapValueRef value;
 
-  if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) {
+  if (!PythonToMapKey(self, key, &map_key)) {
     return NULL;
   }
 
@@ -759,8 +743,7 @@
            message, self->parent_field_descriptor);
        it != reflection->MapEnd(message, self->parent_field_descriptor);
        ++it) {
-    key.reset(MapKeyToPython(self->key_field_descriptor,
-                             it.GetKey()));
+    key.reset(MapKeyToPython(self, it.GetKey()));
     if (key == NULL) {
       return NULL;
     }
@@ -776,10 +759,11 @@
 }
 
 PyObject* MessageMapGet(PyObject* self, PyObject* args, PyObject* kwargs) {
-  static char* kwlist[] = {"key", "default", nullptr};
+  static const char* kwlist[] = {"key", "default", nullptr};
   PyObject* key;
   PyObject* default_value = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
+                                   const_cast<char**>(kwlist), &key,
                                    &default_value)) {
     return NULL;
   }
@@ -961,8 +945,7 @@
     return NULL;
   }
 
-  PyObject* ret = MapKeyToPython(self->container->key_field_descriptor,
-                                 self->iter->GetKey());
+  PyObject* ret = MapKeyToPython(self->container, self->iter->GetKey());
 
   ++(*self->iter);
 
diff --git a/python/google/protobuf/pyext/map_container.h b/python/google/protobuf/pyext/map_container.h
index 2c9b323..842602e 100644
--- a/python/google/protobuf/pyext/map_container.h
+++ b/python/google/protobuf/pyext/map_container.h
@@ -33,6 +33,7 @@
 
 #include <Python.h>
 
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/descriptor.h>
@@ -54,12 +55,9 @@
   // Use to get a mutable message when necessary.
   Message* GetMutableMessage();
 
-  // Cache some descriptors, used to convert keys and values.
-  const FieldDescriptor* key_field_descriptor;
-  const FieldDescriptor* value_field_descriptor;
   // We bump this whenever we perform a mutation, to invalidate existing
   // iterators.
-  uint64 version;
+  uint64_t version;
 };
 
 struct MessageMapContainer : public MapContainer {
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 8e9ed86..125df32 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -35,6 +35,7 @@
 
 #include <structmember.h>  // A Python header file.
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <string>
@@ -102,6 +103,15 @@
 namespace protobuf {
 namespace python {
 
+class MessageReflectionFriend {
+ public:
+  static void UnsafeShallowSwapFields(
+      Message* lhs, Message* rhs,
+      const std::vector<const FieldDescriptor*>& fields) {
+    lhs->GetReflection()->UnsafeShallowSwapFields(lhs, rhs, fields);
+  }
+};
+
 static PyObject* kDESCRIPTOR;
 PyObject* EnumTypeWrapper_class;
 static PyObject* PythonMessage_class;
@@ -121,7 +131,7 @@
     if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
   }
 }
-}
+}  // namespace
 
 // Finalize the creation of the Message class.
 static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
@@ -145,7 +155,7 @@
         PyEnumDescriptor_FromDescriptor(enum_descriptor));
     if (enum_type == NULL) {
       return -1;
-     }
+    }
     // Add wrapped enum type to message class.
     ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
         EnumTypeWrapper_class, enum_type.get(), NULL));
@@ -195,17 +205,15 @@
   return 0;
 }
 
-static PyObject* New(PyTypeObject* type,
-                     PyObject* args, PyObject* kwargs) {
-  static char *kwlist[] = {"name", "bases", "dict", 0};
+static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
+  static const char* kwlist[] = {"name", "bases", "dict", 0};
   PyObject *bases, *dict;
   const char* name;
 
   // Check arguments: (name, bases, dict)
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", kwlist,
-                                   &name,
-                                   &PyTuple_Type, &bases,
-                                   &PyDict_Type, &dict)) {
+  if (!PyArg_ParseTupleAndKeywords(
+          args, kwargs, "sO!O!:type", const_cast<char**>(kwlist), &name,
+          &PyTuple_Type, &bases, &PyDict_Type, &dict)) {
     return NULL;
   }
 
@@ -219,41 +227,20 @@
   }
 
   // Check dict['DESCRIPTOR']
-  PyObject* descriptor_or_name = PyDict_GetItem(dict, kDESCRIPTOR);
-  if (descriptor_or_name == nullptr) {
+  PyObject* py_descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
+  if (py_descriptor == nullptr) {
     PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
-    return NULL;
+    return nullptr;
   }
-
-  Py_ssize_t name_size;
-  char* full_name;
-  const Descriptor* message_descriptor;
-  PyObject* py_descriptor;
-
-  if (PyObject_TypeCheck(descriptor_or_name, &PyMessageDescriptor_Type)) {
-    py_descriptor = descriptor_or_name;
-    message_descriptor = PyMessageDescriptor_AsDescriptor(py_descriptor);
-    if (message_descriptor == nullptr) {
-      return nullptr;
-    }
-  } else {
-    if (PyString_AsStringAndSize(descriptor_or_name, &full_name, &name_size) <
-        0) {
-      return nullptr;
-    }
-    message_descriptor =
-        GetDefaultDescriptorPool()->pool->FindMessageTypeByName(
-            std::string(full_name, name_size));
-    if (message_descriptor == nullptr) {
-      PyErr_Format(PyExc_KeyError,
-                   "Can not find message descriptor %s "
-                   "from pool",
-                   full_name);
-      return nullptr;
-    }
-    py_descriptor = PyMessageDescriptor_FromDescriptor(message_descriptor);
-    // reset the dict['DESCRIPTOR'] to py_descriptor.
-    PyDict_SetItem(dict, kDESCRIPTOR, py_descriptor);
+  if (!PyObject_TypeCheck(py_descriptor, &PyMessageDescriptor_Type)) {
+    PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+                 py_descriptor->ob_type->tp_name);
+    return nullptr;
+  }
+  const Descriptor* message_descriptor =
+      PyMessageDescriptor_AsDescriptor(py_descriptor);
+  if (message_descriptor == nullptr) {
+    return nullptr;
   }
 
   // Messages have no __dict__
@@ -568,7 +555,7 @@
 
 // Format an error message for unexpected types.
 // Always return with an exception set.
-void FormatTypeError(PyObject* arg, char* expected_types) {
+void FormatTypeError(PyObject* arg, const char* expected_types) {
   // This function is often called with an exception set.
   // Clear it to call PyObject_Repr() in good conditions.
   PyErr_Clear();
@@ -603,15 +590,15 @@
       OutOfRangeError(arg);
     }  // Otherwise propagate existing error.
     return false;
-    }
-    if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) {
-      OutOfRangeError(arg);
-      return false;
-    }
+  }
+  if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) {
+    OutOfRangeError(arg);
+    return false;
+  }
   return true;
 }
 
-template<class T>
+template <class T>
 bool CheckAndGetInteger(PyObject* arg, T* value) {
   // The fast path.
 #if PY_MAJOR_VERSION < 3
@@ -631,10 +618,10 @@
   // an integer and can be used as an ordinal number".
   // This definition includes everything that implements numbers.Integral
   // and shouldn't cast the net too wide.
-    if (PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) {
-      FormatTypeError(arg, "int, long");
-      return false;
-    }
+  if (PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) {
+    FormatTypeError(arg, "int, long");
+    return false;
+  }
 
   // Now we have an integral number so we can safely use PyLong_ functions.
   // We need to treat the signed and unsigned cases differently in case arg is
@@ -651,7 +638,7 @@
       if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) {
         // Propagate existing error.
         return false;
-        }
+      }
       ulong_result = PyLong_AsUnsignedLongLong(casted);
       Py_DECREF(casted);
     }
@@ -676,7 +663,7 @@
       if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) {
         // Propagate existing error.
         return false;
-        }
+      }
       long_result = PyLong_AsLongLong(casted);
       Py_DECREF(casted);
     }
@@ -702,7 +689,7 @@
   if (PROTOBUF_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) {
     FormatTypeError(arg, "int, long, float");
     return false;
-    }
+  }
   return true;
 }
 
@@ -809,7 +796,7 @@
     return false;
   }
 
-  string value_string(value, value_len);
+  std::string value_string(value, value_len);
   if (append) {
     reflection->AddString(message, descriptor, std::move(value_string));
   } else if (index < 0) {
@@ -928,9 +915,9 @@
   // Toplevel messages are always mutable.
   GOOGLE_DCHECK(self->parent);
 
-  if (AssureWritable(self->parent) == -1)
+  if (AssureWritable(self->parent) == -1) {
     return -1;
-
+  }
   // If this message is part of a oneof, there might be a field to release in
   // the parent.
   if (MaybeReleaseOverlappingOneofField(self->parent,
@@ -984,7 +971,7 @@
       return NULL;
     }
     const EnumValueDescriptor* enum_value_descriptor =
-        enum_descriptor->FindValueByName(std::string(enum_label, size));
+        enum_descriptor->FindValueByName(StringParam(enum_label, size));
     if (enum_value_descriptor == NULL) {
       PyErr_Format(PyExc_ValueError, "unknown enum label \"%s\"", enum_label);
       return NULL;
@@ -1279,32 +1266,41 @@
 
 // The __new__ method of Message classes.
 // Creates a new C++ message and takes ownership.
-static PyObject* New(PyTypeObject* cls,
-                     PyObject* unused_args, PyObject* unused_kwargs) {
-  CMessageClass* type = CheckMessageClass(cls);
-  if (type == NULL) {
-    return NULL;
-  }
+static CMessage* NewCMessage(CMessageClass* type) {
   // Retrieve the message descriptor and the default instance (=prototype).
   const Descriptor* message_descriptor = type->message_descriptor;
-  if (message_descriptor == NULL) {
-    return NULL;
+  if (message_descriptor == nullptr) {
+    // This would be very unexpected since the CMessageClass has already
+    // been checked.
+    PyErr_Format(PyExc_TypeError,
+                 "CMessageClass object '%s' has no descriptor.",
+                 Py_TYPE(type)->tp_name);
+    return nullptr;
   }
   const Message* prototype =
       type->py_message_factory->message_factory->GetPrototype(
           message_descriptor);
-  if (prototype == NULL) {
+  if (prototype == nullptr) {
     PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
-    return NULL;
+    return nullptr;
   }
 
   CMessage* self = NewEmptyMessage(type);
-  if (self == NULL) {
-    return NULL;
+  if (self == nullptr) {
+    return nullptr;
   }
-  self->message = prototype->New();
+  self->message = prototype->New(nullptr);  // Ensures no arena is used.
   self->parent = nullptr;  // This message owns its data.
-  return reinterpret_cast<PyObject*>(self);
+  return self;
+}
+
+static PyObject* New(PyTypeObject* cls, PyObject* unused_args,
+                     PyObject* unused_kwargs) {
+  CMessageClass* type = CheckMessageClass(cls);
+  if (type == nullptr) {
+    return nullptr;
+  }
+  return reinterpret_cast<PyObject*>(NewCMessage(type));
 }
 
 // The __init__ method of Message classes.
@@ -1399,7 +1395,7 @@
 }
 
 const FieldDescriptor* FindFieldWithOneofs(const Message* message,
-                                           const std::string& field_name,
+                                           ConstStringParam field_name,
                                            bool* in_oneof) {
   *in_oneof = false;
   const Descriptor* descriptor = message->GetDescriptor();
@@ -1427,8 +1423,7 @@
     return false;
   }
 
-  if (field_descriptor->containing_oneof() == NULL &&
-      !field_descriptor->is_singular_with_presence()) {
+  if (!field_descriptor->has_presence()) {
     PyErr_Format(PyExc_ValueError,
                  "Can't test non-optional, non-submessage field \"%s.%s\" for "
                  "presence in proto3.",
@@ -1456,7 +1451,7 @@
   Message* message = self->message;
   bool is_in_oneof;
   const FieldDescriptor* field_descriptor =
-      FindFieldWithOneofs(message, std::string(field_name, size), &is_in_oneof);
+      FindFieldWithOneofs(message, StringParam(field_name, size), &is_in_oneof);
   if (field_descriptor == NULL) {
     if (!is_in_oneof) {
       PyErr_Format(PyExc_ValueError, "Protocol message %s has no field %s.",
@@ -1539,7 +1534,7 @@
   if (new_message == nullptr) {
     return -1;
   }
-  new_message->message = self->message->New();
+  new_message->message = self->message->New(nullptr);
   ScopedPyObjectPtr holder(reinterpret_cast<PyObject*>(new_message));
   new_message->child_submessages = new CMessage::SubMessagesMap();
   new_message->composite_fields = new CMessage::CompositeFieldsMap();
@@ -1569,10 +1564,17 @@
                                            to_release);
   }
 
-  self->message->GetReflection()->SwapFields(
-      self->message, new_message->message,
-      std::vector<const FieldDescriptor*>(fields_to_swap.begin(),
-                                          fields_to_swap.end()));
+  if (self->message->GetArena() == new_message->message->GetArena()) {
+    MessageReflectionFriend::UnsafeShallowSwapFields(
+        self->message, new_message->message,
+        std::vector<const FieldDescriptor*>(fields_to_swap.begin(),
+                                            fields_to_swap.end()));
+  } else {
+    self->message->GetReflection()->SwapFields(
+        self->message, new_message->message,
+        std::vector<const FieldDescriptor*>(fields_to_swap.begin(),
+                                            fields_to_swap.end()));
+  }
 
   // This might delete the Python message completely if all children were moved.
   Py_DECREF(self);
@@ -1633,7 +1635,7 @@
   AssureWritable(self);
   bool is_in_oneof;
   const FieldDescriptor* field_descriptor = FindFieldWithOneofs(
-      self->message, std::string(field_name, field_size), &is_in_oneof);
+      self->message, StringParam(field_name, field_size), &is_in_oneof);
   if (field_descriptor == NULL) {
     if (is_in_oneof) {
       // We gave the name of a oneof, and none of its fields are set.
@@ -1693,10 +1695,10 @@
     CMessage* self, PyObject* args, PyObject* kwargs,
     bool require_initialized) {
   // Parse the "deterministic" kwarg; defaults to False.
-  static char* kwlist[] = { "deterministic", 0 };
+  static const char* kwlist[] = {"deterministic", 0};
   PyObject* deterministic_obj = Py_None;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
-                                   &deterministic_obj)) {
+  if (!PyArg_ParseTupleAndKeywords(
+          args, kwargs, "|O", const_cast<char**>(kwlist), &deterministic_obj)) {
     return NULL;
   }
   // Preemptively convert to a bool first, so we don't need to back out of
@@ -1941,9 +1943,8 @@
 }
 
 static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
-  const void* data;
-  Py_ssize_t data_length;
-  if (PyObject_AsReadBuffer(arg, &data, &data_length) < 0) {
+  Py_buffer data;
+  if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) < 0) {
     return NULL;
   }
 
@@ -1956,7 +1957,8 @@
   const char* ptr;
   internal::ParseContext ctx(
       depth, false, &ptr,
-      StringPiece(static_cast<const char*>(data), data_length));
+      StringPiece(static_cast<const char*>(data.buf), data.len));
+  PyBuffer_Release(&data);
   ctx.data().pool = factory->pool->pool;
   ctx.data().factory = factory->message_factory;
 
@@ -1982,9 +1984,9 @@
     // TODO(jieluo): Raise error and return NULL instead.
     // b/27494216
     PyErr_Warn(nullptr, "Unexpected end-group tag: Not all data was converted");
-    return PyInt_FromLong(data_length - ctx.BytesUntilLimit(ptr));
+    return PyInt_FromLong(data.len - ctx.BytesUntilLimit(ptr));
   }
-  return PyInt_FromLong(data_length);
+  return PyInt_FromLong(data.len);
 }
 
 static PyObject* ParseFromString(CMessage* self, PyObject* arg) {
@@ -2034,13 +2036,12 @@
   char *name_data;
   if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0)
     return NULL;
-  std::string oneof_name = std::string(name_data, name_size);
   const OneofDescriptor* oneof_desc =
-      self->message->GetDescriptor()->FindOneofByName(oneof_name);
+      self->message->GetDescriptor()->FindOneofByName(
+          StringParam(name_data, name_size));
   if (oneof_desc == NULL) {
     PyErr_Format(PyExc_ValueError,
-                 "Protocol message has no oneof \"%s\" field.",
-                 oneof_name.c_str());
+                 "Protocol message has no oneof \"%s\" field.", name_data);
     return NULL;
   }
   const FieldDescriptor* field_in_oneof =
@@ -2171,19 +2172,21 @@
   // If other is not a message, it cannot be equal.
   if (!PyObject_TypeCheck(other, CMessage_Type)) {
     equals = false;
-  }
-  const google::protobuf::Message* other_message =
-      reinterpret_cast<CMessage*>(other)->message;
-  // If messages don't have the same descriptors, they are not equal.
-  if (equals &&
-      self->message->GetDescriptor() != other_message->GetDescriptor()) {
-    equals = false;
-  }
-  // Check the message contents.
-  if (equals && !google::protobuf::util::MessageDifferencer::Equals(
-          *self->message,
-          *reinterpret_cast<CMessage*>(other)->message)) {
-    equals = false;
+  } else {
+    // Otherwise, we have a CMessage whose message we can inspect.
+    const google::protobuf::Message* other_message =
+        reinterpret_cast<CMessage*>(other)->message;
+    // If messages don't have the same descriptors, they are not equal.
+    if (equals &&
+        self->message->GetDescriptor() != other_message->GetDescriptor()) {
+      equals = false;
+    }
+    // Check the message contents.
+    if (equals &&
+        !google::protobuf::util::MessageDifferencer::Equals(
+            *self->message, *reinterpret_cast<CMessage*>(other)->message)) {
+      equals = false;
+    }
   }
 
   if (equals ^ (opid == Py_EQ)) {
@@ -2204,22 +2207,22 @@
   PyObject* result = NULL;
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
-      int32 value = reflection->GetInt32(*message, field_descriptor);
+      int32_t value = reflection->GetInt32(*message, field_descriptor);
       result = PyInt_FromLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_INT64: {
-      int64 value = reflection->GetInt64(*message, field_descriptor);
+      int64_t value = reflection->GetInt64(*message, field_descriptor);
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT32: {
-      uint32 value = reflection->GetUInt32(*message, field_descriptor);
+      uint32_t value = reflection->GetUInt32(*message, field_descriptor);
       result = PyInt_FromSize_t(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT64: {
-      uint64 value = reflection->GetUInt64(*message, field_descriptor);
+      uint64_t value = reflection->GetUInt64(*message, field_descriptor);
       result = PyLong_FromUnsignedLongLong(value);
       break;
     }
@@ -2702,7 +2705,7 @@
 PyObject* ContainerBase::DeepCopy() {
   CMessage* new_parent =
       cmessage::NewEmptyMessage(this->parent->GetMessageClass());
-  new_parent->message = this->parent->message->New();
+  new_parent->message = this->parent->message->New(nullptr);
 
   // Copy the map field into the new message.
   this->parent->message->GetReflection()->SwapFields(
@@ -2866,28 +2869,57 @@
   return cmsg->message;
 }
 
+PyObject* PyMessage_New(const Descriptor* descriptor,
+                        PyObject* py_message_factory) {
+  PyMessageFactory* factory = nullptr;
+  if (py_message_factory == nullptr) {
+    factory = GetDescriptorPool_FromPool(descriptor->file()->pool())
+                  ->py_message_factory;
+  } else if (PyObject_TypeCheck(py_message_factory, &PyMessageFactory_Type)) {
+    factory = reinterpret_cast<PyMessageFactory*>(py_message_factory);
+  } else {
+    PyErr_SetString(PyExc_TypeError, "Expected a MessageFactory");
+    return nullptr;
+  }
+  auto* message_class =
+      message_factory::GetOrCreateMessageClass(factory, descriptor);
+  if (message_class == nullptr) {
+    return nullptr;
+  }
+
+  CMessage* self = cmessage::NewCMessage(message_class);
+  Py_DECREF(message_class);
+  if (self == nullptr) {
+    return nullptr;
+  }
+  return self->AsPyObject();
+}
+
 PyObject* PyMessage_NewMessageOwnedExternally(Message* message,
-                                              PyObject* message_factory) {
-  if (message_factory) {
+                                              PyObject* py_message_factory) {
+  if (py_message_factory) {
     PyErr_SetString(PyExc_NotImplementedError,
                     "Default message_factory=NULL is the only supported value");
-    return NULL;
+    return nullptr;
   }
   if (message->GetReflection()->GetMessageFactory() !=
       MessageFactory::generated_factory()) {
     PyErr_SetString(PyExc_TypeError,
                     "Message pointer was not created from the default factory");
-    return NULL;
+    return nullptr;
   }
 
   CMessageClass* message_class = message_factory::GetOrCreateMessageClass(
       GetDefaultDescriptorPool()->py_message_factory, message->GetDescriptor());
+  if (message_class == nullptr) {
+    return nullptr;
+  }
 
   CMessage* self = cmessage::NewEmptyMessage(message_class);
-  if (self == NULL) {
-    return NULL;
-  }
   Py_DECREF(message_class);
+  if (self == nullptr) {
+    return nullptr;
+  }
   self->message = message;
   Py_INCREF(Py_None);
   self->parent = reinterpret_cast<CMessage*>(Py_None);
@@ -2954,9 +2986,9 @@
       return false;
     }
 
-    PyModule_AddObject(m, "RepeatedScalarContainer",
-                       reinterpret_cast<PyObject*>(
-                           &RepeatedScalarContainer_Type));
+    PyModule_AddObject(
+        m, "RepeatedScalarContainer",
+        reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type));
 
     if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
       return false;
@@ -2964,8 +2996,7 @@
 
     PyModule_AddObject(
         m, "RepeatedCompositeContainer",
-        reinterpret_cast<PyObject*>(
-            &RepeatedCompositeContainer_Type));
+        reinterpret_cast<PyObject*>(&RepeatedCompositeContainer_Type));
 
     // Register them as MutableSequence.
 #if PY_MAJOR_VERSION >= 3
@@ -2998,16 +3029,14 @@
   }
 
   PyModule_AddObject(m, "UnknownFieldSet",
-                     reinterpret_cast<PyObject*>(
-                         &PyUnknownFields_Type));
+                     reinterpret_cast<PyObject*>(&PyUnknownFields_Type));
 
   if (PyType_Ready(&PyUnknownFieldRef_Type) < 0) {
     return false;
   }
 
   PyModule_AddObject(m, "UnknownField",
-                     reinterpret_cast<PyObject*>(
-                         &PyUnknownFieldRef_Type));
+                     reinterpret_cast<PyObject*>(&PyUnknownFieldRef_Type));
 
   // Initialize Map container types.
   if (!InitMapContainers()) {
@@ -3023,9 +3052,8 @@
   if (PyType_Ready(&ExtensionDict_Type) < 0) {
     return false;
   }
-  PyModule_AddObject(
-      m, "ExtensionDict",
-      reinterpret_cast<PyObject*>(&ExtensionDict_Type));
+  PyModule_AddObject(m, "ExtensionDict",
+                     reinterpret_cast<PyObject*>(&ExtensionDict_Type));
   if (PyType_Ready(&ExtensionIterator_Type) < 0) {
     return false;
   }
@@ -3039,25 +3067,24 @@
   PyModule_AddObject(m, "default_pool",
                      reinterpret_cast<PyObject*>(GetDefaultDescriptorPool()));
 
-  PyModule_AddObject(m, "DescriptorPool", reinterpret_cast<PyObject*>(
-      &PyDescriptorPool_Type));
-
-  PyModule_AddObject(m, "Descriptor", reinterpret_cast<PyObject*>(
-      &PyMessageDescriptor_Type));
-  PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast<PyObject*>(
-      &PyFieldDescriptor_Type));
-  PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast<PyObject*>(
-      &PyEnumDescriptor_Type));
-  PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast<PyObject*>(
-      &PyEnumValueDescriptor_Type));
-  PyModule_AddObject(m, "FileDescriptor", reinterpret_cast<PyObject*>(
-      &PyFileDescriptor_Type));
-  PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast<PyObject*>(
-      &PyOneofDescriptor_Type));
-  PyModule_AddObject(m, "ServiceDescriptor", reinterpret_cast<PyObject*>(
-      &PyServiceDescriptor_Type));
-  PyModule_AddObject(m, "MethodDescriptor", reinterpret_cast<PyObject*>(
-      &PyMethodDescriptor_Type));
+  PyModule_AddObject(m, "DescriptorPool",
+                     reinterpret_cast<PyObject*>(&PyDescriptorPool_Type));
+  PyModule_AddObject(m, "Descriptor",
+                     reinterpret_cast<PyObject*>(&PyMessageDescriptor_Type));
+  PyModule_AddObject(m, "FieldDescriptor",
+                     reinterpret_cast<PyObject*>(&PyFieldDescriptor_Type));
+  PyModule_AddObject(m, "EnumDescriptor",
+                     reinterpret_cast<PyObject*>(&PyEnumDescriptor_Type));
+  PyModule_AddObject(m, "EnumValueDescriptor",
+                     reinterpret_cast<PyObject*>(&PyEnumValueDescriptor_Type));
+  PyModule_AddObject(m, "FileDescriptor",
+                     reinterpret_cast<PyObject*>(&PyFileDescriptor_Type));
+  PyModule_AddObject(m, "OneofDescriptor",
+                     reinterpret_cast<PyObject*>(&PyOneofDescriptor_Type));
+  PyModule_AddObject(m, "ServiceDescriptor",
+                     reinterpret_cast<PyObject*>(&PyServiceDescriptor_Type));
+  PyModule_AddObject(m, "MethodDescriptor",
+                     reinterpret_cast<PyObject*>(&PyMethodDescriptor_Type));
 
   PyObject* enum_type_wrapper = PyImport_ImportModule(
       "google.protobuf.internal.enum_type_wrapper");
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index c5a635d..29af255 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -36,6 +36,7 @@
 
 #include <Python.h>
 
+#include <cstdint>
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -282,55 +283,54 @@
 /* Is 64bit */
 #define IS_64BIT (SIZEOF_LONG == 8)
 
-#define FIELD_IS_REPEATED(field_descriptor)                 \
-    ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
+#define FIELD_IS_REPEATED(field_descriptor) \
+  ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
 
-#define GOOGLE_CHECK_GET_INT32(arg, value, err)                        \
-    int32 value;                                            \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_INT32(arg, value, err)  \
+  int32_t value;                          \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_INT64(arg, value, err)                        \
-    int64 value;                                            \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_INT64(arg, value, err)  \
+  int64_t value;                          \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_UINT32(arg, value, err)                       \
-    uint32 value;                                           \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \
+  uint32_t value;                         \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_UINT64(arg, value, err)                       \
-    uint64 value;                                           \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \
+  uint64_t value;                         \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_FLOAT(arg, value, err)                        \
-    float value;                                            \
-    if (!CheckAndGetFloat(arg, &value)) {                   \
-      return err;                                          \
-    }                                                       \
+#define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \
+  float value;                           \
+  if (!CheckAndGetFloat(arg, &value)) {  \
+    return err;                          \
+  }
 
-#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err)                       \
-    double value;                                           \
-    if (!CheckAndGetDouble(arg, &value)) {                  \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \
+  double value;                           \
+  if (!CheckAndGetDouble(arg, &value)) {  \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_BOOL(arg, value, err)                         \
-    bool value;                                             \
-    if (!CheckAndGetBool(arg, &value)) {                    \
-      return err;                                          \
-    }
-
+#define GOOGLE_CHECK_GET_BOOL(arg, value, err) \
+  bool value;                           \
+  if (!CheckAndGetBool(arg, &value)) {  \
+    return err;                         \
+  }
 
 #define FULL_MODULE_NAME "google.protobuf.pyext._message"
 
-void FormatTypeError(PyObject* arg, char* expected_types);
+void FormatTypeError(PyObject* arg, const char* expected_types);
 template<class T>
 bool CheckAndGetInteger(PyObject* arg, T* value);
 bool CheckAndGetDouble(PyObject* arg, double* value);
@@ -353,10 +353,12 @@
 
 extern PyObject* PickleError_class;
 
+PyObject* PyMessage_New(const Descriptor* descriptor,
+                        PyObject* py_message_factory);
 const Message* PyMessage_GetMessagePointer(PyObject* msg);
 Message* PyMessage_GetMutableMessagePointer(PyObject* msg);
 PyObject* PyMessage_NewMessageOwnedExternally(Message* message,
-                                              PyObject* message_factory);
+                                              PyObject* py_message_factory);
 
 bool InitProto2MessageModule(PyObject *m);
 
diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc
index 5fed13b..7905be0 100644
--- a/python/google/protobuf/pyext/message_factory.cc
+++ b/python/google/protobuf/pyext/message_factory.cc
@@ -77,9 +77,10 @@
 }
 
 PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
-  static char* kwlist[] = {"pool", 0};
+  static const char* kwlist[] = {"pool", 0};
   PyObject* pool = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &pool)) {
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
+                                   const_cast<char**>(kwlist), &pool)) {
     return NULL;
   }
   ScopedPyObjectPtr owned_pool;
diff --git a/python/google/protobuf/pyext/message_module.cc b/python/google/protobuf/pyext/message_module.cc
index 63d60b7..b5975f7 100644
--- a/python/google/protobuf/pyext/message_module.cc
+++ b/python/google/protobuf/pyext/message_module.cc
@@ -30,13 +30,12 @@
 
 #include <Python.h>
 
+#include <google/protobuf/message_lite.h>
 #include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
 #include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/proto_api.h>
 
-#include <google/protobuf/message_lite.h>
-
 namespace {
 
 // C++ API.  Clients get at this via proto_api.h
@@ -55,6 +54,15 @@
     return google::protobuf::python::GetDefaultDescriptorPool()
         ->py_message_factory->message_factory;
   }
+  PyObject* NewMessage(const google::protobuf::Descriptor* descriptor,
+                       PyObject* py_message_factory) const override {
+    return google::protobuf::python::PyMessage_New(descriptor, py_message_factory);
+  }
+  PyObject* NewMessageOwnedExternally(
+      google::protobuf::Message* msg, PyObject* py_message_factory) const override {
+    return google::protobuf::python::PyMessage_NewMessageOwnedExternally(
+        msg, py_message_factory);
+  }
 };
 
 }  // namespace
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 4188b5f..f3d6fc3 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -77,8 +77,7 @@
 
 PyObject* Add(RepeatedCompositeContainer* self, PyObject* args,
               PyObject* kwargs) {
-  if (cmessage::AssureWritable(self->parent) == -1)
-    return NULL;
+  if (cmessage::AssureWritable(self->parent) == -1) return nullptr;
   Message* message = self->parent->message;
 
   Message* sub_message =
@@ -93,7 +92,7 @@
     message->GetReflection()->RemoveLast(
         message, self->parent_field_descriptor);
     Py_DECREF(cmsg);
-    return NULL;
+    return nullptr;
   }
 
   return cmsg->AsPyObject();
@@ -172,28 +171,28 @@
 PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) {
   cmessage::AssureWritable(self->parent);
   ScopedPyObjectPtr iter(PyObject_GetIter(value));
-  if (iter == NULL) {
+  if (iter == nullptr) {
     PyErr_SetString(PyExc_TypeError, "Value must be iterable");
-    return NULL;
+    return nullptr;
   }
   ScopedPyObjectPtr next;
-  while ((next.reset(PyIter_Next(iter.get()))) != NULL) {
+  while ((next.reset(PyIter_Next(iter.get()))) != nullptr) {
     if (!PyObject_TypeCheck(next.get(), CMessage_Type)) {
       PyErr_SetString(PyExc_TypeError, "Not a cmessage");
-      return NULL;
+      return nullptr;
     }
-    ScopedPyObjectPtr new_message(Add(self, NULL, NULL));
-    if (new_message == NULL) {
-      return NULL;
+    ScopedPyObjectPtr new_message(Add(self, nullptr, nullptr));
+    if (new_message == nullptr) {
+      return nullptr;
     }
     CMessage* new_cmessage = reinterpret_cast<CMessage*>(new_message.get());
     if (ScopedPyObjectPtr(cmessage::MergeFrom(new_cmessage, next.get())) ==
-        NULL) {
-      return NULL;
+        nullptr) {
+      return nullptr;
     }
   }
   if (PyErr_Occurred()) {
-    return NULL;
+    return nullptr;
   }
   Py_RETURN_NONE;
 }
@@ -220,7 +219,7 @@
   }
   if (index < 0 || index >= length) {
     PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
-    return NULL;
+    return nullptr;
   }
   Message* message = self->parent->message;
   Message* sub_message = message->GetReflection()->MutableRepeatedMessage(
@@ -240,7 +239,7 @@
   if (PyIndex_Check(item)) {
     Py_ssize_t index;
     index = PyNumber_AsSsize_t(item, PyExc_IndexError);
-    if (index == -1 && PyErr_Occurred()) return NULL;
+    if (index == -1 && PyErr_Occurred()) return nullptr;
     if (index < 0) index += length;
     return GetItem(self, index, length);
   } else if (PySlice_Check(item)) {
@@ -254,14 +253,14 @@
     if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(item),
                              length, &from, &to, &step, &slicelength) == -1) {
 #endif
-      return NULL;
+      return nullptr;
     }
 
     if (slicelength <= 0) {
       return PyList_New(0);
     } else {
       result = PyList_New(slicelength);
-      if (!result) return NULL;
+      if (!result) return nullptr;
 
       for (cur = from, i = 0; i < slicelength; cur += step, i++) {
         PyList_SET_ITEM(result, i, GetItem(self, cur, length));
@@ -272,7 +271,7 @@
   } else {
     PyErr_Format(PyExc_TypeError, "indices must be integers, not %.200s",
                  item->ob_type->tp_name);
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -283,7 +282,7 @@
 int AssignSubscript(RepeatedCompositeContainer* self,
                     PyObject* slice,
                     PyObject* value) {
-  if (value != NULL) {
+  if (value != nullptr) {
     PyErr_SetString(PyExc_TypeError, "does not support assignment");
     return -1;
   }
@@ -305,23 +304,23 @@
 
   for (Py_ssize_t i = 0; i < len; i++) {
     ScopedPyObjectPtr item(GetItem(self, i, len));
-    if (item == NULL) {
-      return NULL;
+    if (item == nullptr) {
+      return nullptr;
     }
     int result = PyObject_RichCompareBool(item.get(), value, Py_EQ);
     if (result < 0) {
-      return NULL;
+      return nullptr;
     }
     if (result) {
       ScopedPyObjectPtr py_index(PyLong_FromSsize_t(i));
-      if (AssignSubscript(self, py_index.get(), NULL) < 0) {
-        return NULL;
+      if (AssignSubscript(self, py_index.get(), nullptr) < 0) {
+        return nullptr;
       }
       Py_RETURN_NONE;
     }
   }
   PyErr_SetString(PyExc_ValueError, "Item to delete not in list");
-  return NULL;
+  return nullptr;
 }
 
 static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) {
@@ -332,23 +331,23 @@
     PyErr_SetString(PyExc_TypeError,
                     "Can only compare repeated composite fields "
                     "against other repeated composite fields.");
-    return NULL;
+    return nullptr;
   }
   if (opid == Py_EQ || opid == Py_NE) {
     // TODO(anuraag): Don't make new lists just for this...
-    ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
-    if (full_slice == NULL) {
-      return NULL;
+    ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
+    if (full_slice == nullptr) {
+      return nullptr;
     }
     ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
-    if (list == NULL) {
-      return NULL;
+    if (list == nullptr) {
+      return nullptr;
     }
     ScopedPyObjectPtr other_list(
         Subscript(reinterpret_cast<RepeatedCompositeContainer*>(other),
                   full_slice.get()));
-    if (other_list == NULL) {
-      return NULL;
+    if (other_list == nullptr) {
+      return nullptr;
     }
     return PyObject_RichCompare(list.get(), other_list.get(), opid);
   } else {
@@ -358,14 +357,14 @@
 }
 
 static PyObject* ToStr(PyObject* pself) {
-  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
-  if (full_slice == NULL) {
-    return NULL;
+  ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
+  if (full_slice == nullptr) {
+    return nullptr;
   }
   ScopedPyObjectPtr list(Subscript(
       reinterpret_cast<RepeatedCompositeContainer*>(pself), full_slice.get()));
-  if (list == NULL) {
-    return NULL;
+  if (list == nullptr) {
+    return nullptr;
   }
   return PyObject_Repr(list.get());
 }
@@ -380,16 +379,19 @@
   const FieldDescriptor* descriptor = self->parent_field_descriptor;
   const Py_ssize_t length = Length(reinterpret_cast<PyObject*>(self));
 
-  // Since Python protobuf objects are never arena-allocated, adding and
-  // removing message pointers to the underlying array is just updating
-  // pointers.
-  for (Py_ssize_t i = 0; i < length; ++i)
-    reflection->ReleaseLast(message, descriptor);
-
+  // We need to rearrange things to match python's sort order.  Because there
+  // was already an O(n*log(n)) step in python and a bunch of reflection, we
+  // expect an O(n**2) step in C++ won't hurt too much.
   for (Py_ssize_t i = 0; i < length; ++i) {
-    CMessage* py_cmsg = reinterpret_cast<CMessage*>(
-        PyList_GET_ITEM(child_list, i));
-    reflection->AddAllocatedMessage(message, descriptor, py_cmsg->message);
+    Message* child_message =
+        reinterpret_cast<CMessage*>(PyList_GET_ITEM(child_list, i))->message;
+    for (Py_ssize_t j = i; j < length; ++j) {
+      if (child_message ==
+          &reflection->GetRepeatedMessage(*message, descriptor, j)) {
+        reflection->SwapElements(message, descriptor, i, j);
+        break;
+      }
+    }
   }
 }
 
@@ -400,13 +402,12 @@
                                PyObject* kwds) {
   ScopedPyObjectPtr child_list(
       PySequence_List(reinterpret_cast<PyObject*>(self)));
-  if (child_list == NULL) {
+  if (child_list == nullptr) {
     return -1;
   }
   ScopedPyObjectPtr m(PyObject_GetAttrString(child_list.get(), "sort"));
-  if (m == NULL)
-    return -1;
-  if (ScopedPyObjectPtr(PyObject_Call(m.get(), args, kwds)) == NULL)
+  if (m == nullptr) return -1;
+  if (ScopedPyObjectPtr(PyObject_Call(m.get(), args, kwds)) == nullptr)
     return -1;
   ReorderAttached(self, child_list.get());
   return 0;
@@ -418,9 +419,9 @@
 
   // Support the old sort_function argument for backwards
   // compatibility.
-  if (kwds != NULL) {
+  if (kwds != nullptr) {
     PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
-    if (sort_func != NULL) {
+    if (sort_func != nullptr) {
       // Must set before deleting as sort_func is a borrowed reference
       // and kwds might be the only thing keeping it alive.
       PyDict_SetItemString(kwds, "cmp", sort_func);
@@ -429,7 +430,35 @@
   }
 
   if (SortPythonMessages(self, args, kwds) < 0) {
-    return NULL;
+    return nullptr;
+  }
+  Py_RETURN_NONE;
+}
+
+// ---------------------------------------------------------------------
+// reverse()
+
+// Returns 0 if successful; returns -1 and sets an exception if
+// unsuccessful.
+static int ReversePythonMessages(RepeatedCompositeContainer* self) {
+  ScopedPyObjectPtr child_list(
+      PySequence_List(reinterpret_cast<PyObject*>(self)));
+  if (child_list == nullptr) {
+    return -1;
+  }
+  if (ScopedPyObjectPtr(
+          PyObject_CallMethod(child_list.get(), "reverse", nullptr)) == nullptr)
+    return -1;
+  ReorderAttached(self, child_list.get());
+  return 0;
+}
+
+static PyObject* Reverse(PyObject* pself) {
+  RepeatedCompositeContainer* self =
+      reinterpret_cast<RepeatedCompositeContainer*>(pself);
+
+  if (ReversePythonMessages(self) < 0) {
+    return nullptr;
   }
   Py_RETURN_NONE;
 }
@@ -448,17 +477,17 @@
 
   Py_ssize_t index = -1;
   if (!PyArg_ParseTuple(args, "|n", &index)) {
-    return NULL;
+    return nullptr;
   }
   Py_ssize_t length = Length(pself);
   if (index < 0) index += length;
   PyObject* item = GetItem(self, index, length);
-  if (item == NULL) {
-    return NULL;
+  if (item == nullptr) {
+    return nullptr;
   }
   ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index));
-  if (AssignSubscript(self, py_index.get(), NULL) < 0) {
-    return NULL;
+  if (AssignSubscript(self, py_index.get(), nullptr) < 0) {
+    return nullptr;
   }
   return item;
 }
@@ -473,14 +502,14 @@
     const FieldDescriptor* parent_field_descriptor,
     CMessageClass* child_message_class) {
   if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
-    return NULL;
+    return nullptr;
   }
 
   RepeatedCompositeContainer* self =
       reinterpret_cast<RepeatedCompositeContainer*>(
           PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0));
-  if (self == NULL) {
-    return NULL;
+  if (self == nullptr) {
+    return nullptr;
   }
 
   Py_INCREF(parent);
@@ -500,10 +529,10 @@
 }
 
 static PySequenceMethods SqMethods = {
-  Length,                 /* sq_length */
-  0,                      /* sq_concat */
-  0,                      /* sq_repeat */
-  Item                    /* sq_item */
+    Length,  /* sq_length */
+    nullptr, /* sq_concat */
+    nullptr, /* sq_repeat */
+    Item     /* sq_item */
 };
 
 static PyMappingMethods MpMethods = {
@@ -513,66 +542,69 @@
 };
 
 static PyMethodDef Methods[] = {
-  { "__deepcopy__", DeepCopy, METH_VARARGS,
-    "Makes a deep copy of the class." },
-  { "add", (PyCFunction)AddMethod, METH_VARARGS | METH_KEYWORDS,
-    "Adds an object to the repeated container." },
-  { "append", AppendMethod, METH_O,
-    "Appends a message to the end of the repeated container."},
-  { "insert", Insert, METH_VARARGS,
-    "Inserts a message before the specified index." },
-  { "extend", ExtendMethod, METH_O,
-    "Adds objects to the repeated container." },
-  { "pop", Pop, METH_VARARGS,
-    "Removes an object from the repeated container and returns it." },
-  { "remove", Remove, METH_O,
-    "Removes an object from the repeated container." },
-  { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
-    "Sorts the repeated container." },
-  { "MergeFrom", MergeFromMethod, METH_O,
-    "Adds objects to the repeated container." },
-  { NULL, NULL }
-};
+    {"__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class."},
+    {"add", reinterpret_cast<PyCFunction>(AddMethod),
+     METH_VARARGS | METH_KEYWORDS, "Adds an object to the repeated container."},
+    {"append", AppendMethod, METH_O,
+     "Appends a message to the end of the repeated container."},
+    {"insert", Insert, METH_VARARGS,
+     "Inserts a message before the specified index."},
+    {"extend", ExtendMethod, METH_O, "Adds objects to the repeated container."},
+    {"pop", Pop, METH_VARARGS,
+     "Removes an object from the repeated container and returns it."},
+    {"remove", Remove, METH_O,
+     "Removes an object from the repeated container."},
+    {"sort", reinterpret_cast<PyCFunction>(Sort), METH_VARARGS | METH_KEYWORDS,
+     "Sorts the repeated container."},
+    {"reverse", reinterpret_cast<PyCFunction>(Reverse), METH_NOARGS,
+     "Reverses elements order of the repeated container."},
+    {"MergeFrom", MergeFromMethod, METH_O,
+     "Adds objects to the repeated container."},
+    {nullptr, nullptr}};
 
 }  // namespace repeated_composite_container
 
 PyTypeObject RepeatedCompositeContainer_Type = {
-  PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  FULL_MODULE_NAME ".RepeatedCompositeContainer",  // tp_name
-  sizeof(RepeatedCompositeContainer),  // tp_basicsize
-  0,                                   //  tp_itemsize
-  repeated_composite_container::Dealloc,  //  tp_dealloc
-  0,                                   //  tp_print
-  0,                                   //  tp_getattr
-  0,                                   //  tp_setattr
-  0,                                   //  tp_compare
-  repeated_composite_container::ToStr,      //  tp_repr
-  0,                                   //  tp_as_number
-  &repeated_composite_container::SqMethods,   //  tp_as_sequence
-  &repeated_composite_container::MpMethods,   //  tp_as_mapping
-  PyObject_HashNotImplemented,         //  tp_hash
-  0,                                   //  tp_call
-  0,                                   //  tp_str
-  0,                                   //  tp_getattro
-  0,                                   //  tp_setattro
-  0,                                   //  tp_as_buffer
-  Py_TPFLAGS_DEFAULT,                  //  tp_flags
-  "A Repeated scalar container",       //  tp_doc
-  0,                                   //  tp_traverse
-  0,                                   //  tp_clear
-  repeated_composite_container::RichCompare,  //  tp_richcompare
-  0,                                   //  tp_weaklistoffset
-  0,                                   //  tp_iter
-  0,                                   //  tp_iternext
-  repeated_composite_container::Methods,   //  tp_methods
-  0,                                   //  tp_members
-  0,                                   //  tp_getset
-  0,                                   //  tp_base
-  0,                                   //  tp_dict
-  0,                                   //  tp_descr_get
-  0,                                   //  tp_descr_set
-  0,                                   //  tp_dictoffset
-  0,                                   //  tp_init
+    PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
+    ".RepeatedCompositeContainer",              // tp_name
+    sizeof(RepeatedCompositeContainer),         // tp_basicsize
+    0,                                          //  tp_itemsize
+    repeated_composite_container::Dealloc,      //  tp_dealloc
+#if PY_VERSION_HEX >= 0x03080000
+    0,                                          //  tp_vectorcall_offset
+#else
+    nullptr,                                    //  tp_print
+#endif
+    nullptr,                                    //  tp_getattr
+    nullptr,                                    //  tp_setattr
+    nullptr,                                    //  tp_compare
+    repeated_composite_container::ToStr,        //  tp_repr
+    nullptr,                                    //  tp_as_number
+    &repeated_composite_container::SqMethods,   //  tp_as_sequence
+    &repeated_composite_container::MpMethods,   //  tp_as_mapping
+    PyObject_HashNotImplemented,                //  tp_hash
+    nullptr,                                    //  tp_call
+    nullptr,                                    //  tp_str
+    nullptr,                                    //  tp_getattro
+    nullptr,                                    //  tp_setattro
+    nullptr,                                    //  tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                         //  tp_flags
+    "A Repeated scalar container",              //  tp_doc
+    nullptr,                                    //  tp_traverse
+    nullptr,                                    //  tp_clear
+    repeated_composite_container::RichCompare,  //  tp_richcompare
+    0,                                          //  tp_weaklistoffset
+    nullptr,                                    //  tp_iter
+    nullptr,                                    //  tp_iternext
+    repeated_composite_container::Methods,      //  tp_methods
+    nullptr,                                    //  tp_members
+    nullptr,                                    //  tp_getset
+    nullptr,                                    //  tp_base
+    nullptr,                                    //  tp_dict
+    nullptr,                                    //  tp_descr_get
+    nullptr,                                    //  tp_descr_set
+    0,                                          //  tp_dictoffset
+    nullptr,                                    //  tp_init
 };
 
 }  // namespace python
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 712182b..d76114b 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -33,6 +33,7 @@
 
 #include <google/protobuf/pyext/repeated_scalar_container.h>
 
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/stubs/common.h>
@@ -46,13 +47,13 @@
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
 
 #if PY_MAJOR_VERSION >= 3
-  #define PyInt_FromLong PyLong_FromLong
-  #if PY_VERSION_HEX < 0x03030000
-    #error "Python 3.0 - 3.2 are not supported."
-  #else
-  #define PyString_AsString(ob) \
-    (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
-  #endif
+#define PyInt_FromLong PyLong_FromLong
+#if PY_VERSION_HEX < 0x03030000
+#error "Python 3.0 - 3.2 are not supported."
+#else
+#define PyString_AsString(ob) \
+  (PyUnicode_Check(ob) ? PyUnicode_AsUTF8(ob) : PyBytes_AsString(ob))
+#endif
 #endif
 
 namespace google {
@@ -61,13 +62,13 @@
 
 namespace repeated_scalar_container {
 
-static int InternalAssignRepeatedField(
-    RepeatedScalarContainer* self, PyObject* list) {
+static int InternalAssignRepeatedField(RepeatedScalarContainer* self,
+                                       PyObject* list) {
   Message* message = self->parent->message;
   message->GetReflection()->ClearField(message, self->parent_field_descriptor);
   for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
     PyObject* value = PyList_GET_ITEM(list, i);
-    if (ScopedPyObjectPtr(Append(self, value)) == NULL) {
+    if (ScopedPyObjectPtr(Append(self, value)) == nullptr) {
       return -1;
     }
   }
@@ -96,13 +97,12 @@
     index = field_size + index;
   }
   if (index < 0 || index >= field_size) {
-    PyErr_Format(PyExc_IndexError,
-                 "list assignment index (%d) out of range",
+    PyErr_Format(PyExc_IndexError, "list assignment index (%d) out of range",
                  static_cast<int>(index));
     return -1;
   }
 
-  if (arg == NULL) {
+  if (arg == nullptr) {
     ScopedPyObjectPtr py_index(PyLong_FromLong(index));
     return cmessage::DeleteRepeatedField(self->parent, field_descriptor,
                                          py_index.get());
@@ -150,8 +150,8 @@
       break;
     }
     case FieldDescriptor::CPPTYPE_STRING: {
-      if (!CheckAndSetString(
-          arg, message, field_descriptor, reflection, false, index)) {
+      if (!CheckAndSetString(arg, message, field_descriptor, reflection, false,
+                             index)) {
         return -1;
       }
       break;
@@ -165,12 +165,12 @@
         const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
         const EnumValueDescriptor* enum_value =
             enum_descriptor->FindValueByNumber(value);
-        if (enum_value != NULL) {
+        if (enum_value != nullptr) {
           reflection->SetRepeatedEnum(message, field_descriptor, index,
                                       enum_value);
         } else {
           ScopedPyObjectPtr s(PyObject_Str(arg));
-          if (s != NULL) {
+          if (s != nullptr) {
             PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
                          PyString_AsString(s.get()));
           }
@@ -180,9 +180,9 @@
       break;
     }
     default:
-      PyErr_Format(
-          PyExc_SystemError, "Adding value to a field of unknown type %d",
-          field_descriptor->cpp_type());
+      PyErr_Format(PyExc_SystemError,
+                   "Adding value to a field of unknown type %d",
+                   field_descriptor->cpp_type());
       return -1;
   }
   return 0;
@@ -201,60 +201,58 @@
     index = field_size + index;
   }
   if (index < 0 || index >= field_size) {
-    PyErr_Format(PyExc_IndexError,
-                 "list index (%zd) out of range",
-                 index);
-    return NULL;
+    PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
+    return nullptr;
   }
 
-  PyObject* result = NULL;
+  PyObject* result = nullptr;
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
-      int32 value = reflection->GetRepeatedInt32(
-          *message, field_descriptor, index);
+      int32_t value =
+          reflection->GetRepeatedInt32(*message, field_descriptor, index);
       result = PyInt_FromLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_INT64: {
-      int64 value = reflection->GetRepeatedInt64(
-          *message, field_descriptor, index);
+      int64_t value =
+          reflection->GetRepeatedInt64(*message, field_descriptor, index);
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT32: {
-      uint32 value = reflection->GetRepeatedUInt32(
-          *message, field_descriptor, index);
+      uint32_t value =
+          reflection->GetRepeatedUInt32(*message, field_descriptor, index);
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT64: {
-      uint64 value = reflection->GetRepeatedUInt64(
-          *message, field_descriptor, index);
+      uint64_t value =
+          reflection->GetRepeatedUInt64(*message, field_descriptor, index);
       result = PyLong_FromUnsignedLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
-      float value = reflection->GetRepeatedFloat(
-          *message, field_descriptor, index);
+      float value =
+          reflection->GetRepeatedFloat(*message, field_descriptor, index);
       result = PyFloat_FromDouble(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_DOUBLE: {
-      double value = reflection->GetRepeatedDouble(
-          *message, field_descriptor, index);
+      double value =
+          reflection->GetRepeatedDouble(*message, field_descriptor, index);
       result = PyFloat_FromDouble(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_BOOL: {
-      bool value = reflection->GetRepeatedBool(
-          *message, field_descriptor, index);
+      bool value =
+          reflection->GetRepeatedBool(*message, field_descriptor, index);
       result = PyBool_FromLong(value ? 1 : 0);
       break;
     }
     case FieldDescriptor::CPPTYPE_ENUM: {
       const EnumValueDescriptor* enum_value =
-          message->GetReflection()->GetRepeatedEnum(
-              *message, field_descriptor, index);
+          message->GetReflection()->GetRepeatedEnum(*message, field_descriptor,
+                                                    index);
       result = PyInt_FromLong(enum_value->number());
       break;
     }
@@ -266,10 +264,9 @@
       break;
     }
     default:
-      PyErr_Format(
-          PyExc_SystemError,
-          "Getting value from a repeated field of unknown type %d",
-          field_descriptor->cpp_type());
+      PyErr_Format(PyExc_SystemError,
+                   "Getting value from a repeated field of unknown type %d",
+                   field_descriptor->cpp_type());
   }
 
   return result;
@@ -287,23 +284,23 @@
     from = to = PyInt_AsLong(slice);
   } else  // NOLINT
 #endif
-  if (PyLong_Check(slice)) {
+      if (PyLong_Check(slice)) {
     from = to = PyLong_AsLong(slice);
   } else if (PySlice_Check(slice)) {
     length = Len(pself);
 #if PY_MAJOR_VERSION >= 3
-    if (PySlice_GetIndicesEx(slice,
-                             length, &from, &to, &step, &slicelength) == -1) {
+    if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
+        -1) {
 #else
-    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
-                             length, &from, &to, &step, &slicelength) == -1) {
+    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), length,
+                             &from, &to, &step, &slicelength) == -1) {
 #endif
-      return NULL;
+      return nullptr;
     }
     return_list = true;
   } else {
     PyErr_SetString(PyExc_TypeError, "list indices must be integers");
-    return NULL;
+    return nullptr;
   }
 
   if (!return_list) {
@@ -311,8 +308,8 @@
   }
 
   PyObject* list = PyList_New(0);
-  if (list == NULL) {
-    return NULL;
+  if (list == nullptr) {
+    return nullptr;
   }
   if (from <= to) {
     if (step < 0) {
@@ -348,73 +345,73 @@
   const Reflection* reflection = message->GetReflection();
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
-      GOOGLE_CHECK_GET_INT32(item, value, NULL);
+      GOOGLE_CHECK_GET_INT32(item, value, nullptr);
       reflection->AddInt32(message, field_descriptor, value);
       break;
     }
     case FieldDescriptor::CPPTYPE_INT64: {
-      GOOGLE_CHECK_GET_INT64(item, value, NULL);
+      GOOGLE_CHECK_GET_INT64(item, value, nullptr);
       reflection->AddInt64(message, field_descriptor, value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT32: {
-      GOOGLE_CHECK_GET_UINT32(item, value, NULL);
+      GOOGLE_CHECK_GET_UINT32(item, value, nullptr);
       reflection->AddUInt32(message, field_descriptor, value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT64: {
-      GOOGLE_CHECK_GET_UINT64(item, value, NULL);
+      GOOGLE_CHECK_GET_UINT64(item, value, nullptr);
       reflection->AddUInt64(message, field_descriptor, value);
       break;
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
-      GOOGLE_CHECK_GET_FLOAT(item, value, NULL);
+      GOOGLE_CHECK_GET_FLOAT(item, value, nullptr);
       reflection->AddFloat(message, field_descriptor, value);
       break;
     }
     case FieldDescriptor::CPPTYPE_DOUBLE: {
-      GOOGLE_CHECK_GET_DOUBLE(item, value, NULL);
+      GOOGLE_CHECK_GET_DOUBLE(item, value, nullptr);
       reflection->AddDouble(message, field_descriptor, value);
       break;
     }
     case FieldDescriptor::CPPTYPE_BOOL: {
-      GOOGLE_CHECK_GET_BOOL(item, value, NULL);
+      GOOGLE_CHECK_GET_BOOL(item, value, nullptr);
       reflection->AddBool(message, field_descriptor, value);
       break;
     }
     case FieldDescriptor::CPPTYPE_STRING: {
-      if (!CheckAndSetString(
-          item, message, field_descriptor, reflection, true, -1)) {
-        return NULL;
+      if (!CheckAndSetString(item, message, field_descriptor, reflection, true,
+                             -1)) {
+        return nullptr;
       }
       break;
     }
     case FieldDescriptor::CPPTYPE_ENUM: {
-      GOOGLE_CHECK_GET_INT32(item, value, NULL);
+      GOOGLE_CHECK_GET_INT32(item, value, nullptr);
       if (reflection->SupportsUnknownEnumValues()) {
         reflection->AddEnumValue(message, field_descriptor, value);
       } else {
         const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
         const EnumValueDescriptor* enum_value =
             enum_descriptor->FindValueByNumber(value);
-        if (enum_value != NULL) {
+        if (enum_value != nullptr) {
           reflection->AddEnum(message, field_descriptor, enum_value);
         } else {
           ScopedPyObjectPtr s(PyObject_Str(item));
-          if (s != NULL) {
+          if (s != nullptr) {
             PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
                          PyString_AsString(s.get()));
           }
-          return NULL;
+          return nullptr;
         }
       }
       break;
     }
     default:
-      PyErr_Format(
-          PyExc_SystemError, "Adding value to a field of unknown type %d",
-          field_descriptor->cpp_type());
-      return NULL;
+      PyErr_Format(PyExc_SystemError,
+                   "Adding value to a field of unknown type %d",
+                   field_descriptor->cpp_type());
+      return nullptr;
   }
 
   Py_RETURN_NONE;
@@ -437,25 +434,24 @@
 
   cmessage::AssureWritable(self->parent);
   Message* message = self->parent->message;
-  const FieldDescriptor* field_descriptor =
-      self->parent_field_descriptor;
+  const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
 
 #if PY_MAJOR_VERSION < 3
   if (PyInt_Check(slice)) {
     from = to = PyInt_AsLong(slice);
   } else  // NOLINT
 #endif
-  if (PyLong_Check(slice)) {
+      if (PyLong_Check(slice)) {
     from = to = PyLong_AsLong(slice);
   } else if (PySlice_Check(slice)) {
     const Reflection* reflection = message->GetReflection();
     length = reflection->FieldSize(*message, field_descriptor);
 #if PY_MAJOR_VERSION >= 3
-    if (PySlice_GetIndicesEx(slice,
-                             length, &from, &to, &step, &slicelength) == -1) {
+    if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
+        -1) {
 #else
-    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
-                             length, &from, &to, &step, &slicelength) == -1) {
+    if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), length,
+                             &from, &to, &step, &slicelength) == -1) {
 #endif
       return -1;
     }
@@ -465,7 +461,7 @@
     return -1;
   }
 
-  if (value == NULL) {
+  if (value == nullptr) {
     return cmessage::DeleteRepeatedField(self->parent, field_descriptor, slice);
   }
 
@@ -473,12 +469,12 @@
     return AssignItem(pself, from, value);
   }
 
-  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
-  if (full_slice == NULL) {
+  ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
+  if (full_slice == nullptr) {
     return -1;
   }
   ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
-  if (new_list == NULL) {
+  if (new_list == nullptr) {
     return -1;
   }
   if (PySequence_SetSlice(new_list.get(), from, to, value) < 0) {
@@ -495,23 +491,23 @@
   if (value == Py_None) {
     Py_RETURN_NONE;
   }
-  if ((Py_TYPE(value)->tp_as_sequence == NULL) && PyObject_Not(value)) {
+  if ((Py_TYPE(value)->tp_as_sequence == nullptr) && PyObject_Not(value)) {
     Py_RETURN_NONE;
   }
 
   ScopedPyObjectPtr iter(PyObject_GetIter(value));
-  if (iter == NULL) {
+  if (iter == nullptr) {
     PyErr_SetString(PyExc_TypeError, "Value must be iterable");
-    return NULL;
+    return nullptr;
   }
   ScopedPyObjectPtr next;
-  while ((next.reset(PyIter_Next(iter.get()))) != NULL) {
-    if (ScopedPyObjectPtr(Append(self, next.get())) == NULL) {
-      return NULL;
+  while ((next.reset(PyIter_Next(iter.get()))) != nullptr) {
+    if (ScopedPyObjectPtr(Append(self, next.get())) == nullptr) {
+      return nullptr;
     }
   }
   if (PyErr_Occurred()) {
-    return NULL;
+    return nullptr;
   }
   Py_RETURN_NONE;
 }
@@ -523,16 +519,16 @@
   Py_ssize_t index;
   PyObject* value;
   if (!PyArg_ParseTuple(args, "lO", &index, &value)) {
-    return NULL;
+    return nullptr;
   }
-  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
   ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
   if (PyList_Insert(new_list.get(), index, value) < 0) {
-    return NULL;
+    return nullptr;
   }
   int ret = InternalAssignRepeatedField(self, new_list.get());
   if (ret < 0) {
-    return NULL;
+    return nullptr;
   }
   Py_RETURN_NONE;
 }
@@ -548,10 +544,10 @@
   }
   if (match_index == -1) {
     PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
-    return NULL;
+    return nullptr;
   }
-  if (AssignItem(pself, match_index, NULL) < 0) {
-    return NULL;
+  if (AssignItem(pself, match_index, nullptr) < 0) {
+    return nullptr;
   }
   Py_RETURN_NONE;
 }
@@ -570,9 +566,9 @@
   // also a repeated scalar container, into Python lists so we can delegate
   // to the list's compare method.
 
-  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
-  if (full_slice == NULL) {
-    return NULL;
+  ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
+  if (full_slice == nullptr) {
+    return nullptr;
   }
 
   ScopedPyObjectPtr other_list_deleter;
@@ -582,54 +578,72 @@
   }
 
   ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
-  if (list == NULL) {
-    return NULL;
+  if (list == nullptr) {
+    return nullptr;
   }
   return PyObject_RichCompare(list.get(), other, opid);
 }
 
 PyObject* Reduce(PyObject* unused_self, PyObject* unused_other) {
-  PyErr_Format(
-      PickleError_class,
-      "can't pickle repeated message fields, convert to list first");
-  return NULL;
+  PyErr_Format(PickleError_class,
+               "can't pickle repeated message fields, convert to list first");
+  return nullptr;
 }
 
 static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) {
   // Support the old sort_function argument for backwards
   // compatibility.
-  if (kwds != NULL) {
+  if (kwds != nullptr) {
     PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
-    if (sort_func != NULL) {
+    if (sort_func != nullptr) {
       // Must set before deleting as sort_func is a borrowed reference
       // and kwds might be the only thing keeping it alive.
-      if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1)
-        return NULL;
-      if (PyDict_DelItemString(kwds, "sort_function") == -1)
-        return NULL;
+      if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) return nullptr;
+      if (PyDict_DelItemString(kwds, "sort_function") == -1) return nullptr;
     }
   }
 
-  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
-  if (full_slice == NULL) {
-    return NULL;
+  ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
+  if (full_slice == nullptr) {
+    return nullptr;
   }
   ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
-  if (list == NULL) {
-    return NULL;
+  if (list == nullptr) {
+    return nullptr;
   }
   ScopedPyObjectPtr m(PyObject_GetAttrString(list.get(), "sort"));
-  if (m == NULL) {
-    return NULL;
+  if (m == nullptr) {
+    return nullptr;
   }
   ScopedPyObjectPtr res(PyObject_Call(m.get(), args, kwds));
-  if (res == NULL) {
-    return NULL;
+  if (res == nullptr) {
+    return nullptr;
   }
   int ret = InternalAssignRepeatedField(
       reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
   if (ret < 0) {
-    return NULL;
+    return nullptr;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* Reverse(PyObject* pself) {
+  ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
+  if (full_slice == nullptr) {
+    return nullptr;
+  }
+  ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
+  if (list == nullptr) {
+    return nullptr;
+  }
+  ScopedPyObjectPtr res(PyObject_CallMethod(list.get(), "reverse", nullptr));
+  if (res == nullptr) {
+    return nullptr;
+  }
+  int ret = InternalAssignRepeatedField(
+      reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
+  if (ret < 0) {
+    return nullptr;
   }
   Py_RETURN_NONE;
 }
@@ -637,27 +651,27 @@
 static PyObject* Pop(PyObject* pself, PyObject* args) {
   Py_ssize_t index = -1;
   if (!PyArg_ParseTuple(args, "|n", &index)) {
-    return NULL;
+    return nullptr;
   }
   PyObject* item = Item(pself, index);
-  if (item == NULL) {
+  if (item == nullptr) {
     PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
-    return NULL;
+    return nullptr;
   }
-  if (AssignItem(pself, index, NULL) < 0) {
-    return NULL;
+  if (AssignItem(pself, index, nullptr) < 0) {
+    return nullptr;
   }
   return item;
 }
 
 static PyObject* ToStr(PyObject* pself) {
-  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
-  if (full_slice == NULL) {
-    return NULL;
+  ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
+  if (full_slice == nullptr) {
+    return nullptr;
   }
   ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
-  if (list == NULL) {
-    return NULL;
+  if (list == nullptr) {
+    return nullptr;
   }
   return PyObject_Repr(list.get());
 }
@@ -670,13 +684,13 @@
 RepeatedScalarContainer* NewContainer(
     CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
   if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
-    return NULL;
+    return nullptr;
   }
 
   RepeatedScalarContainer* self = reinterpret_cast<RepeatedScalarContainer*>(
       PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
-  if (self == NULL) {
-    return NULL;
+  if (self == nullptr) {
+    return nullptr;
   }
 
   Py_INCREF(parent);
@@ -696,81 +710,85 @@
 }
 
 static PySequenceMethods SqMethods = {
-  Len,        /* sq_length */
-  0,          /* sq_concat */
-  0,          /* sq_repeat */
-  Item,       /* sq_item */
-  0,          /* sq_slice */
-  AssignItem  /* sq_ass_item */
+    Len,       /* sq_length */
+    nullptr,   /* sq_concat */
+    nullptr,   /* sq_repeat */
+    Item,      /* sq_item */
+    nullptr,   /* sq_slice */
+    AssignItem /* sq_ass_item */
 };
 
 static PyMappingMethods MpMethods = {
-  Len,               /* mp_length */
-  Subscript,      /* mp_subscript */
-  AssSubscript, /* mp_ass_subscript */
+    Len,          /* mp_length */
+    Subscript,    /* mp_subscript */
+    AssSubscript, /* mp_ass_subscript */
 };
 
 static PyMethodDef Methods[] = {
-  { "__deepcopy__", DeepCopy, METH_VARARGS,
-    "Makes a deep copy of the class." },
-  { "__reduce__", Reduce, METH_NOARGS,
-    "Outputs picklable representation of the repeated field." },
-  { "append", AppendMethod, METH_O,
-    "Appends an object to the repeated container." },
-  { "extend", ExtendMethod, METH_O,
-    "Appends objects to the repeated container." },
-  { "insert", Insert, METH_VARARGS,
-    "Inserts an object at the specified position in the container." },
-  { "pop", Pop, METH_VARARGS,
-    "Removes an object from the repeated container and returns it." },
-  { "remove", Remove, METH_O,
-    "Removes an object from the repeated container." },
-  { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
-    "Sorts the repeated container."},
-  { "MergeFrom", (PyCFunction)MergeFrom, METH_O,
-    "Merges a repeated container into the current container." },
-  { NULL, NULL }
-};
+    {"__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class."},
+    {"__reduce__", Reduce, METH_NOARGS,
+     "Outputs picklable representation of the repeated field."},
+    {"append", AppendMethod, METH_O,
+     "Appends an object to the repeated container."},
+    {"extend", ExtendMethod, METH_O,
+     "Appends objects to the repeated container."},
+    {"insert", Insert, METH_VARARGS,
+     "Inserts an object at the specified position in the container."},
+    {"pop", Pop, METH_VARARGS,
+     "Removes an object from the repeated container and returns it."},
+    {"remove", Remove, METH_O,
+     "Removes an object from the repeated container."},
+    {"sort", reinterpret_cast<PyCFunction>(Sort), METH_VARARGS | METH_KEYWORDS,
+     "Sorts the repeated container."},
+    {"reverse", reinterpret_cast<PyCFunction>(Reverse), METH_NOARGS,
+     "Reverses elements order of the repeated container."},
+    {"MergeFrom", static_cast<PyCFunction>(MergeFrom), METH_O,
+     "Merges a repeated container into the current container."},
+    {nullptr, nullptr}};
 
 }  // namespace repeated_scalar_container
 
 PyTypeObject RepeatedScalarContainer_Type = {
-  PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  FULL_MODULE_NAME ".RepeatedScalarContainer",  // tp_name
-  sizeof(RepeatedScalarContainer),     // tp_basicsize
-  0,                                   //  tp_itemsize
-  repeated_scalar_container::Dealloc,  //  tp_dealloc
-  0,                                   //  tp_print
-  0,                                   //  tp_getattr
-  0,                                   //  tp_setattr
-  0,                                   //  tp_compare
-  repeated_scalar_container::ToStr,    //  tp_repr
-  0,                                   //  tp_as_number
-  &repeated_scalar_container::SqMethods,   //  tp_as_sequence
-  &repeated_scalar_container::MpMethods,   //  tp_as_mapping
-  PyObject_HashNotImplemented,         //  tp_hash
-  0,                                   //  tp_call
-  0,                                   //  tp_str
-  0,                                   //  tp_getattro
-  0,                                   //  tp_setattro
-  0,                                   //  tp_as_buffer
-  Py_TPFLAGS_DEFAULT,                  //  tp_flags
-  "A Repeated scalar container",       //  tp_doc
-  0,                                   //  tp_traverse
-  0,                                   //  tp_clear
-  repeated_scalar_container::RichCompare,  //  tp_richcompare
-  0,                                   //  tp_weaklistoffset
-  0,                                   //  tp_iter
-  0,                                   //  tp_iternext
-  repeated_scalar_container::Methods,      //  tp_methods
-  0,                                   //  tp_members
-  0,                                   //  tp_getset
-  0,                                   //  tp_base
-  0,                                   //  tp_dict
-  0,                                   //  tp_descr_get
-  0,                                   //  tp_descr_set
-  0,                                   //  tp_dictoffset
-  0,                                   //  tp_init
+    PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
+    ".RepeatedScalarContainer",              // tp_name
+    sizeof(RepeatedScalarContainer),         // tp_basicsize
+    0,                                       //  tp_itemsize
+    repeated_scalar_container::Dealloc,      //  tp_dealloc
+#if PY_VERSION_HEX >= 0x03080000
+    0,                                       //  tp_vectorcall_offset
+#else
+    nullptr,                                 //  tp_print
+#endif
+    nullptr,                                 //  tp_getattr
+    nullptr,                                 //  tp_setattr
+    nullptr,                                 //  tp_compare
+    repeated_scalar_container::ToStr,        //  tp_repr
+    nullptr,                                 //  tp_as_number
+    &repeated_scalar_container::SqMethods,   //  tp_as_sequence
+    &repeated_scalar_container::MpMethods,   //  tp_as_mapping
+    PyObject_HashNotImplemented,             //  tp_hash
+    nullptr,                                 //  tp_call
+    nullptr,                                 //  tp_str
+    nullptr,                                 //  tp_getattro
+    nullptr,                                 //  tp_setattro
+    nullptr,                                 //  tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                      //  tp_flags
+    "A Repeated scalar container",           //  tp_doc
+    nullptr,                                 //  tp_traverse
+    nullptr,                                 //  tp_clear
+    repeated_scalar_container::RichCompare,  //  tp_richcompare
+    0,                                       //  tp_weaklistoffset
+    nullptr,                                 //  tp_iter
+    nullptr,                                 //  tp_iternext
+    repeated_scalar_container::Methods,      //  tp_methods
+    nullptr,                                 //  tp_members
+    nullptr,                                 //  tp_getset
+    nullptr,                                 //  tp_base
+    nullptr,                                 //  tp_dict
+    nullptr,                                 //  tp_descr_get
+    nullptr,                                 //  tp_descr_set
+    0,                                       //  tp_dictoffset
+    nullptr,                                 //  tp_init
 };
 
 }  // namespace python
diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
index 9faaa4f..6f7fc29 100644
--- a/python/google/protobuf/pyext/scoped_pyobject_ptr.h
+++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
@@ -77,7 +77,7 @@
 
   PyObject* as_pyobject() const { return reinterpret_cast<PyObject*>(ptr_); }
 
-  // Increments the reference count fo the current object.
+  // Increments the reference count of the current object.
   // Should not be called when no object is held.
   void inc() const { Py_INCREF(ptr_); }
 
diff --git a/python/google/protobuf/pyext/unknown_fields.cc b/python/google/protobuf/pyext/unknown_fields.cc
index 8509213..deb86e6 100644
--- a/python/google/protobuf/pyext/unknown_fields.cc
+++ b/python/google/protobuf/pyext/unknown_fields.cc
@@ -142,6 +142,7 @@
   }
   Py_CLEAR(self->parent);
   self->~PyUnknownFields();
+  Py_TYPE(pself)->tp_free(pself);
 }
 
 static PySequenceMethods SqMethods = {
diff --git a/python/google/protobuf/service_reflection.py b/python/google/protobuf/service_reflection.py
index 8590e46..75c51ff 100644
--- a/python/google/protobuf/service_reflection.py
+++ b/python/google/protobuf/service_reflection.py
@@ -38,12 +38,6 @@
 
 __author__ = 'petar@google.com (Petar Petrov)'
 
-from google.protobuf.internal import api_implementation
-
-if api_implementation.Type() == 'cpp':
-  # pylint: disable=g-import-not-at-top
-  from google.protobuf.pyext import _message
-
 
 class GeneratedServiceType(type):
 
@@ -84,10 +78,6 @@
       return
 
     descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY]
-    if isinstance(descriptor, str):
-      descriptor = _message.default_pool.FindServiceByName(descriptor)
-      dictionary[GeneratedServiceType._DESCRIPTOR_KEY] = descriptor
-
     service_builder = _ServiceBuilder(descriptor)
     service_builder.BuildService(cls)
     cls.DESCRIPTOR = descriptor
@@ -113,16 +103,13 @@
         dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
         describing this protocol service type.
     """
-    descriptor = dictionary.get(cls._DESCRIPTOR_KEY)
-    if isinstance(descriptor, str):
-      descriptor = _message.default_pool.FindServiceByName(descriptor)
-      dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY] = descriptor
     super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary)
     # Don't do anything if this class doesn't have a descriptor. This happens
     # when a service stub is subclassed.
     if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary:
       return
 
+    descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY]
     service_stub_builder = _ServiceStubBuilder(descriptor)
     service_stub_builder.BuildServiceStub(cls)
 
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index 9c2b267..9c4ca90 100644
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -46,19 +46,19 @@
 import encodings.raw_unicode_escape  # pylint: disable=unused-import
 import encodings.unicode_escape  # pylint: disable=unused-import
 import io
+import math
 import re
-
 import six
 
-if six.PY3:
-  long = int  # pylint: disable=redefined-builtin,invalid-name
-
-# pylint: disable=g-import-not-at-top
 from google.protobuf.internal import decoder
 from google.protobuf.internal import type_checkers
 from google.protobuf import descriptor
 from google.protobuf import text_encoding
 
+if six.PY3:
+  long = int  # pylint: disable=redefined-builtin,invalid-name
+
+# pylint: disable=g-import-not-at-top
 __all__ = ['MessageToString', 'Parse', 'PrintMessage', 'PrintField',
            'PrintFieldValue', 'Merge', 'MessageToBytes']
 
@@ -120,20 +120,21 @@
     return self._writer.getvalue()
 
 
-def MessageToString(message,
-                    as_utf8=False,
-                    as_one_line=False,
-                    use_short_repeated_primitives=False,
-                    pointy_brackets=False,
-                    use_index_order=False,
-                    float_format=None,
-                    double_format=None,
-                    use_field_number=False,
-                    descriptor_pool=None,
-                    indent=0,
-                    message_formatter=None,
-                    print_unknown_fields=False,
-                    force_colon=False):
+def MessageToString(
+    message,
+    as_utf8=False,
+    as_one_line=False,
+    use_short_repeated_primitives=False,
+    pointy_brackets=False,
+    use_index_order=False,
+    float_format=None,
+    double_format=None,
+    use_field_number=False,
+    descriptor_pool=None,
+    indent=0,
+    message_formatter=None,
+    print_unknown_fields=False,
+    force_colon=False):
   # type: (...) -> str
   """Convert protobuf message to text format.
 
@@ -157,9 +158,9 @@
       determined by the extension number. By default, use the field number
       order.
     float_format (str): If set, use this to specify float field formatting
-      (per the "Format Specification Mini-Language"); otherwise, 8 valid
-      digits is used (default '.8g'). Also affect double field if
-      double_format is not set but float_format is set.
+      (per the "Format Specification Mini-Language"); otherwise, shortest float
+      that has same value in wire will be printed. Also affect double field
+      if double_format is not set but float_format is set.
     double_format (str): If set, use this to specify double field formatting
       (per the "Format Specification Mini-Language"); if it is not set but
       float_format is set, use float_format. Otherwise, use ``str()``
@@ -329,21 +330,22 @@
 class _Printer(object):
   """Text format printer for protocol message."""
 
-  def __init__(self,
-               out,
-               indent=0,
-               as_utf8=False,
-               as_one_line=False,
-               use_short_repeated_primitives=False,
-               pointy_brackets=False,
-               use_index_order=False,
-               float_format=None,
-               double_format=None,
-               use_field_number=False,
-               descriptor_pool=None,
-               message_formatter=None,
-               print_unknown_fields=False,
-               force_colon=False):
+  def __init__(
+      self,
+      out,
+      indent=0,
+      as_utf8=False,
+      as_one_line=False,
+      use_short_repeated_primitives=False,
+      pointy_brackets=False,
+      use_index_order=False,
+      float_format=None,
+      double_format=None,
+      use_field_number=False,
+      descriptor_pool=None,
+      message_formatter=None,
+      print_unknown_fields=False,
+      force_colon=False):
     """Initialize the Printer.
 
     Double values can be formatted compactly with 15 digits of precision
@@ -365,9 +367,9 @@
         defined in source code instead of the field number. By default, use the
         field number order.
       float_format: If set, use this to specify float field formatting
-        (per the "Format Specification Mini-Language"); otherwise, 8 valid
-        digits is used (default '.8g'). Also affect double field if
-        double_format is not set but float_format is set.
+        (per the "Format Specification Mini-Language"); otherwise, shortest
+        float that has same value in wire will be printed. Also affect double
+        field if double_format is not set but float_format is set.
       double_format: If set, use this to specify double field formatting
         (per the "Format Specification Mini-Language"); if it is not set but
         float_format is set, use float_format. Otherwise, str() is used.
@@ -539,7 +541,7 @@
         # For groups, use the capitalized name.
         out.write(field.message_type.name)
       else:
-        out.write(field.name)
+          out.write(field.name)
 
     if (self.force_colon or
         field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE):
@@ -565,8 +567,6 @@
       self.out.write(', ')
     self.PrintFieldValue(field, value[-1])
     self.out.write(']')
-    if self.force_colon:
-      self.out.write(':')
     self.out.write(' ' if self.as_one_line else '\n')
 
   def _PrintMessageFieldValue(self, value):
@@ -628,7 +628,10 @@
       if self.float_format is not None:
         out.write('{1:{0}}'.format(self.float_format, value))
       else:
-        out.write(str(float(format(value, '.8g'))))
+        if math.isnan(value):
+          out.write(str(value))
+        else:
+          out.write(str(type_checkers.ToShortestFloat(value)))
     elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and
           self.double_format is not None):
       out.write('{1:{0}}'.format(self.double_format, value))
@@ -877,8 +880,11 @@
           raise tokenizer.ParseErrorPreviousToken('Expected "%s".' %
                                                   (expanded_any_end_token,))
         self._MergeField(tokenizer, expanded_any_sub_message)
+      deterministic = False
+
       message.Pack(expanded_any_sub_message,
-                   type_url_prefix=type_url_prefix)
+                   type_url_prefix=type_url_prefix,
+                   deterministic=deterministic)
       return
 
     if tokenizer.TryConsume('['):
@@ -894,6 +900,8 @@
       # pylint: disable=protected-access
       field = message.Extensions._FindExtensionByName(name)
       # pylint: enable=protected-access
+
+
       if not field:
         if self.allow_unknown_extension:
           field = None
@@ -980,6 +988,7 @@
     if not tokenizer.TryConsume(','):
       tokenizer.TryConsume(';')
 
+
   def _ConsumeAnyTypeUrl(self, tokenizer):
     """Consumes a google.protobuf.Any type URL and returns the type name."""
     # Consume "type.googleapis.com/".
@@ -1049,7 +1058,7 @@
       value_cpptype = field.message_type.fields_by_name['value'].cpp_type
       if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
         value = getattr(message, field.name)[sub_message.key]
-        value.MergeFrom(sub_message.value)
+        value.CopyFrom(sub_message.value)
       else:
         getattr(message, field.name)[sub_message.key] = sub_message.value
 
diff --git a/python/protobuf_distutils/README.md b/python/protobuf_distutils/README.md
new file mode 100644
index 0000000..63d12b5
--- /dev/null
+++ b/python/protobuf_distutils/README.md
@@ -0,0 +1,121 @@
+# Python setuptools extension
+
+This is an extension for Python setuptools which uses an installed protobuf
+compiler (`protoc`) to generate Python sources.
+
+## Installing
+
+To use this extension, it needs to be installed so it can be imported by other
+projects' setup.py.
+
+```shell
+$ python setup.py build
+$ python -m pip install .
+```
+
+(If you want to test changes to the extension, you can use `python setup.py
+develop`.)
+
+## Usage
+
+### Example setup.py configuration
+
+```python
+from setuptools import setup
+setup(
+    # ...
+    name='example_project',
+
+    # Require this package, but only for setup (not installation):
+    setup_requires=['protobuf_distutils'],
+
+    options={
+        # See below for details.
+        'generate_py_protobufs': {
+            'source_dir':        'path/to/protos',
+            'extra_proto_paths': ['path/to/other/project/protos'],
+            'output_dir':        'path/to/project/sources',  # default '.'
+            'proto_files':       ['relative/path/to/just_this_file.proto'],
+            'protoc':            'path/to/protoc.exe',
+        },
+    },
+)
+```
+
+### Example build invocation
+
+These steps will generate protobuf sources so they are included when building
+and installing `example_project` (see above):
+
+```shell
+$ python setup.py generate_py_protobufs
+$ python setup.py build
+$ python -m pip install .
+```
+
+## Options
+
+- `source_dir`:
+
+  This is the directory holding .proto files to be processed.
+
+  The default behavior is to generate sources for all .proto files found under
+  `source_dir`, recursively. This behavior can be controlled with options below.
+
+- `proto_root_path`:
+
+  This is the root path for resolving imports in source .proto files.
+
+  The default is the shortest prefix of `source_dir` among `[source_dir] +
+  self.extra_proto_paths`.
+
+- `extra_proto_paths`:
+
+  Specifies additional paths that should be used to find imports, in
+  addition to `source_dir`.
+
+  This option can be used to specify the path to other protobuf sources,
+  which are imported by files under `source_dir`.  No Python code will
+  be generated for .proto files under `extra_proto_paths`.
+
+- `output_dir`:
+
+  Specifies where generated code should be placed.
+
+  Typically, this should be the root package that generated Python modules
+  should be below.
+
+  The generated files will be placed under `output_dir` according to the
+  relative source paths under `proto_root_path`. For example, the source file
+  `${proto_root_path}/subdir/message.proto` will be generated as the Python
+  module `${output_dir}/subdir/message_pb2.py`.
+
+- `proto_files`:
+
+  A list of strings, specific .proto file paths for generating code, instead of
+  searching for all .proto files under `source_path`.
+
+  These paths are relative to `source_dir`. For example, to generate code
+  for just `${source_dir}/subdir/message.proto`, specify
+  `['subdir/message.proto']`.
+
+- `protoc`:
+
+  By default, the protoc binary (the Protobuf compiler) is found by
+  searching the environment path. To use a specific protoc binary, its
+  path can be specified. Resolution of the `protoc` value is as follows:
+  1. If the `--protoc=VALUE` flag is passed to `generate_py_protobufs`,
+     then `VALUE` will be used.
+     For example:
+     ```shell
+     $ python setup.py generate_py_protobufs --protoc=/path/to/protoc
+     ```
+  2. Otherwise, if a value was set in the `options`, it will be used.
+     (See "Example setup.py configuration," above.)
+  3. Otherwise, if the `PROTOC` environment variable is set, it will be
+     used. For example:
+     For example:
+     ```shell
+     $ PROTOC=/path/to/protoc python setup.py generate_py_protobufs
+     ```
+  4. Otherwise, `$PATH` will be searched.
diff --git a/python/protobuf_distutils/protobuf_distutils/__init__.py b/python/protobuf_distutils/protobuf_distutils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/protobuf_distutils/protobuf_distutils/__init__.py
diff --git a/python/protobuf_distutils/protobuf_distutils/generate_py_protobufs.py b/python/protobuf_distutils/protobuf_distutils/generate_py_protobufs.py
new file mode 100644
index 0000000..515ded2
--- /dev/null
+++ b/python/protobuf_distutils/protobuf_distutils/generate_py_protobufs.py
@@ -0,0 +1,147 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc.  All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Implements the generate_py_protobufs command."""
+
+__author__ = 'dlj@google.com (David L. Jones)'
+
+import glob
+import sys
+import os
+import distutils.spawn as spawn
+from distutils.cmd import Command
+from distutils.errors import DistutilsOptionError, DistutilsExecError
+
+class generate_py_protobufs(Command):
+    """Generates Python sources for .proto files."""
+
+    description = 'Generate Python sources for .proto files'
+    user_options = [
+        ('extra-proto-paths=', None,
+         'Additional paths to resolve imports in .proto files.'),
+
+        ('protoc=', None,
+         'Path to a specific `protoc` command to use.'),
+    ]
+    boolean_options = ['recurse']
+
+    def initialize_options(self):
+        """Sets the defaults for the command options."""
+        self.source_dir = None
+        self.proto_root_path = None
+        self.extra_proto_paths = []
+        self.output_dir = '.'
+        self.proto_files = None
+        self.recurse = True
+        self.protoc = None
+
+    def finalize_options(self):
+        """Sets the final values for the command options.
+
+        Defaults were set in `initialize_options`, but could have been changed
+        by command-line options or by other commands.
+        """
+        self.ensure_dirname('source_dir')
+        self.ensure_string_list('extra_proto_paths')
+
+        if self.output_dir is None:
+            self.output_dir = '.'
+        self.ensure_dirname('output_dir')
+
+        # SUBTLE: if 'source_dir' is a subdirectory of any entry in
+        # 'extra_proto_paths', then in general, the shortest --proto_path prefix
+        # (and the longest relative .proto filenames) must be used for
+        # correctness. For example, consider:
+        #
+        #     source_dir = 'a/b/c'
+        #     extra_proto_paths = ['a/b', 'x/y']
+        #
+        # In this case, we must ensure that a/b/c/d/foo.proto resolves
+        # canonically as c/d/foo.proto, not just d/foo.proto. Otherwise, this
+        # import:
+        #
+        #     import "c/d/foo.proto";
+        #
+        # would result in different FileDescriptor.name keys from "d/foo.proto".
+        # That will cause all the definitions in the file to be flagged as
+        # duplicates, with an error similar to:
+        #
+        #     c/d/foo.proto: "packagename.MessageName" is already defined in file "d/foo.proto"
+        #
+        # For paths in self.proto_files, we transform them to be relative to
+        # self.proto_root_path, which may be different from self.source_dir.
+        #
+        # Although the order of --proto_paths is significant, shadowed filenames
+        # are errors: if 'a/b/c.proto' resolves to different files under two
+        # different --proto_path arguments, then the path is rejected as an
+        # error. (Implementation note: this is enforced in protoc's
+        # DiskSourceTree class.)
+
+        if self.proto_root_path is None:
+            self.proto_root_path = os.path.normpath(self.source_dir)
+            for root_candidate in self.extra_proto_paths:
+                root_candidate = os.path.normpath(root_candidate)
+                if self.proto_root_path.startswith(root_candidate):
+                    self.proto_root_path = root_candidate
+            if self.proto_root_path != self.source_dir:
+                self.announce('using computed proto_root_path: ' + self.proto_root_path, level=2)
+
+        if not self.source_dir.startswith(self.proto_root_path):
+            raise DistutilsOptionError('source_dir ' + self.source_dir +
+                                       ' is not under proto_root_path ' + self.proto_root_path)
+
+        if self.proto_files is None:
+            files = glob.glob(os.path.join(self.source_dir, '*.proto'))
+            if self.recurse:
+                files.extend(glob.glob(os.path.join(self.source_dir, '**', '*.proto')))
+            self.proto_files = [f.partition(self.proto_root_path + os.path.sep)[-1] for f in files]
+            if not self.proto_files:
+                raise DistutilsOptionError('no .proto files were found under ' + self.source_dir)
+
+        self.ensure_string_list('proto_files')
+
+        if self.protoc is None:
+            self.protoc = os.getenv('PROTOC')
+        if self.protoc is None:
+            self.protoc = spawn.find_executable('protoc')
+
+    def run(self):
+        # All proto file paths were adjusted in finalize_options to be relative
+        # to self.proto_root_path.
+        proto_paths = ['--proto_path=' + self.proto_root_path]
+        proto_paths.extend(['--proto_path=' + x for x in self.extra_proto_paths])
+
+        # Run protoc. It was already resolved, so don't try to resolve
+        # through PATH.
+        spawn.spawn(
+            [self.protoc,
+             '--python_out=' + self.output_dir,
+            ] + proto_paths + self.proto_files,
+            search_path=0)
diff --git a/python/protobuf_distutils/setup.py b/python/protobuf_distutils/setup.py
new file mode 100644
index 0000000..96259a9
--- /dev/null
+++ b/python/protobuf_distutils/setup.py
@@ -0,0 +1,77 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc.  All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Setuptools/distutils extension for generating Python protobuf code."""
+
+__author__ = 'dlj@google.com (David L. Jones)'
+
+from os import path
+from setuptools import setup, find_packages
+
+# Use README.md as the source for long_description.
+this_directory = path.abspath(path.dirname(__file__))
+with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
+    _readme = f.read()
+
+setup(
+    name='protobuf_distutils',
+    version='1.0',
+    packages=find_packages(),
+    maintainer='protobuf@googlegroups.com',
+    maintainer_email='protobuf@googlegroups.com',
+    license='3-Clause BSD License',
+    classifiers=[
+        "Framework :: Setuptools Plugin",
+        "Operating System :: OS Independent",
+        # These Python versions should match the protobuf package:
+        "Programming Language :: Python",
+        "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.3",
+        "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
+        "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: 3.7",
+        "Programming Language :: Python :: 3.8",
+        "Topic :: Software Development :: Code Generators",
+    ],
+    description=('This is a distutils extension to generate Python code for '
+                 '.proto files using an installed protoc binary.'),
+    long_description=_readme,
+    long_description_content_type='text/markdown',
+    url='https://github.com/protocolbuffers/protobuf/',
+    entry_points={
+        'distutils.commands': [
+            ('generate_py_protobufs = '
+             'protobuf_distutils.generate_py_protobufs:generate_py_protobufs'),
+        ],
+    },
+)
diff --git a/python/release.sh b/python/release.sh
index 8d35640..fc88b08 100755
--- a/python/release.sh
+++ b/python/release.sh
@@ -11,7 +11,10 @@
   local PYTHON=$2
   local PYPI=$3
 
-  virtualenv --no-site-packages -p `which $PYTHON` test-venv
+  # Setuptools 45.0 removed support for Python 2, so to test with Python 2 we
+  # pass --no-setuptools here and then install an older setuptools version
+  # below.
+  virtualenv -p `which $PYTHON` --no-setuptools test-venv
 
   # Intentionally put a broken protoc in the path to make sure installation
   # doesn't require protoc installed.
@@ -19,6 +22,7 @@
   chmod +x test-venv/bin/protoc
 
   source test-venv/bin/activate
+  pip install "setuptools<45"
   pip install -i ${PYPI} protobuf==${VERSION} --no-cache-dir
   deactivate
   rm -fr test-venv
@@ -76,18 +80,20 @@
 cd python
 
 # Run tests locally.
-python setup.py build
-python setup.py test
+python3 setup.py build
+python3 setup.py test
 
 # Deploy source package to testing PyPI
-python setup.py sdist upload -r https://test.pypi.org/legacy/
+python3 setup.py sdist
+twine upload --skip-existing -r testpypi -u protobuf-wheel-test dist/*
 
 # Test locally with different python versions.
 run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple
 run_install_test ${TESTING_VERSION} python3 https://test.pypi.org/simple
 
 # Deploy egg/wheel packages to testing PyPI and test again.
-python setup.py bdist_egg bdist_wheel upload -r https://test.pypi.org/legacy/
+python3 setup.py clean build bdist_wheel
+twine upload --skip-existing -r testpypi -u protobuf-wheel-test dist/*
 
 run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple
 run_install_test ${TESTING_VERSION} python3 https://test.pypi.org/simple
@@ -103,13 +109,15 @@
   echo "Publishing to PyPI..."
   # Be sure to run build before sdist, because otherwise sdist will not include
   # well-known types.
-  python setup.py clean build sdist upload
+  python3 setup.py clean build sdist
+  twine upload --skip-existing -u protobuf-packages dist/*
   # Be sure to run clean before bdist_xxx, because otherwise bdist_xxx will
   # include files you may not want in the package. E.g., if you have built
   # and tested with --cpp_implemenation, bdist_xxx will include the _message.so
   # file even when you no longer pass the --cpp_implemenation flag. See:
   #   https://github.com/protocolbuffers/protobuf/issues/3042
-  python setup.py clean build bdist_egg bdist_wheel upload
+  python3 setup.py clean build bdist_wheel
+  twine upload --skip-existing -u protobuf-packages dist/*
 else
   # Set the version number back (i.e., remove dev suffix).
   sed -i -r "s/__version__ = '.*'/__version__ = '${VERSION}'/" google/protobuf/__init__.py
diff --git a/python/release/wheel/Dockerfile b/python/release/wheel/Dockerfile
deleted file mode 100644
index f38ec2f..0000000
--- a/python/release/wheel/Dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-FROM quay.io/pypa/manylinux1_x86_64
-
-RUN yum install -y libtool
-RUN /opt/python/cp27-cp27mu/bin/pip install twine
-
-COPY protobuf_optimized_pip.sh /
diff --git a/python/release/wheel/README.md b/python/release/wheel/README.md
deleted file mode 100644
index edda2cd..0000000
--- a/python/release/wheel/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-Description
-------------------------------
-This directory is used to build released wheels according to PEP513 and upload
-them to pypi.
-
-Usage
-------------------------------
-For example, to release 3.3.0:
-    ./protobuf_optimized_pip.sh 3.3.0 PYPI_USERNAME PYPI_PASSWORD
-
-Structure
-------------------------------
-| Source                    | Source                                                       |
-|--------------------------------------|---------------------------------------------------|
-| protobuf_optimized_pip.sh | Entry point. Calling Dockerfile and build_wheel_manylinux.sh |
-| Dockerfile                | Build docker image according to PEP513.                      |
-| build_wheel_manylinux.sh  | Build wheel packages in the docker container.                |
diff --git a/python/release/wheel/build_wheel_manylinux.sh b/python/release/wheel/build_wheel_manylinux.sh
deleted file mode 100755
index 39fd8c1..0000000
--- a/python/release/wheel/build_wheel_manylinux.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash
-
-# Print usage and fail.
-function usage() {
-  echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION PYPI_USERNAME PYPI_PASSWORD" >&2
-  exit 1   # Causes caller to exit because we use -e.
-}
-
-# Validate arguments.
-if [ $0 != ./build_wheel_manylinux.sh ]; then
-  echo "Please run this script from the directory in which it is located." >&2
-  exit 1
-fi
-
-if [ $# -lt 3 ]; then
-  usage
-  exit 1
-fi
-
-PROTOBUF_VERSION=$1
-PYPI_USERNAME=$2
-PYPI_PASSWORD=$3
-
-docker rmi protobuf-python-wheel
-docker build . -t protobuf-python-wheel
-docker run --rm protobuf-python-wheel ./protobuf_optimized_pip.sh $PROTOBUF_VERSION $PYPI_USERNAME $PYPI_PASSWORD
-docker rmi protobuf-python-wheel
diff --git a/python/release/wheel/protobuf_optimized_pip.sh b/python/release/wheel/protobuf_optimized_pip.sh
deleted file mode 100755
index 07c2a09..0000000
--- a/python/release/wheel/protobuf_optimized_pip.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env bash
-
-# DO NOT use this script manually! Called by docker.
-
-set -ex
-
-# Print usage and fail.
-function usage() {
-  echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION" >&2
-  exit 1   # Causes caller to exit because we use -e.
-}
-
-# Build wheel
-function build_wheel() {
-  PYTHON_VERSION=$1
-  PYTHON_BIN=/opt/python/${PYTHON_VERSION}/bin/python
-
-  $PYTHON_BIN setup.py bdist_wheel --cpp_implementation --compile_static_extension
-  auditwheel repair dist/protobuf-${PROTOBUF_VERSION}-${PYTHON_VERSION}-linux_x86_64.whl
-}
-
-# Validate arguments.
-if [ $0 != ./protobuf_optimized_pip.sh ]; then
-  echo "Please run this script from the directory in which it is located." >&2
-  exit 1
-fi
-
-if [ $# -lt 1 ]; then
-  usage
-  exit 1
-fi
-
-PROTOBUF_VERSION=$1
-PYPI_USERNAME=$2
-PYPI_PASSWORD=$3
-
-DIR=${PWD}/'protobuf-python-build'
-PYTHON_VERSIONS=('cp27-cp27mu' 'cp33-cp33m' 'cp34-cp34m' 'cp35-cp35m' 'cp36-cp36m')
-
-mkdir -p ${DIR}
-cd ${DIR}
-curl -SsL -O https://github.com/protocolbuffers/protobuf/archive/v${PROTOBUF_VERSION}.tar.gz
-tar xzf v${PROTOBUF_VERSION}.tar.gz
-cd $DIR/protobuf-${PROTOBUF_VERSION}
-
-# Autoconf on centos 5.11 cannot recognize AC_PROG_OBJC.
-sed -i '/AC_PROG_OBJC/d' configure.ac
-sed -i 's/conformance\/Makefile//g' configure.ac
-
-# Use the /usr/bin/autoconf and related tools to pick the correct aclocal macros
-export PATH="/usr/bin:$PATH"
-
-# Build protoc
-./autogen.sh
-CXXFLAGS="-fPIC -g -O2" ./configure
-make -j8
-export PROTOC=$DIR/src/protoc
-
-cd python
-
-for PYTHON_VERSION in "${PYTHON_VERSIONS[@]}"
-do
-  build_wheel $PYTHON_VERSION
-done
-
-/opt/python/cp27-cp27mu/bin/twine upload wheelhouse/*
diff --git a/python/setup.py b/python/setup.py
index 7e462b1..696bde2 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -2,6 +2,7 @@
 #
 # See README for usage instructions.
 from distutils import util
+import fnmatch
 import glob
 import os
 import pkg_resources
@@ -17,6 +18,7 @@
 
 from distutils.command.build_py import build_py as _build_py
 from distutils.command.clean import clean as _clean
+from distutils.command.build_ext import build_ext as _build_ext
 from distutils.spawn import find_executable
 
 # Find the Protocol Compiler.
@@ -82,8 +84,6 @@
   generate_proto("../src/google/protobuf/test_messages_proto3.proto", False)
   generate_proto("../src/google/protobuf/test_messages_proto2.proto", False)
   generate_proto("../src/google/protobuf/unittest_arena.proto", False)
-  generate_proto("../src/google/protobuf/unittest_no_arena.proto", False)
-  generate_proto("../src/google/protobuf/unittest_no_arena_import.proto", False)
   generate_proto("../src/google/protobuf/unittest.proto", False)
   generate_proto("../src/google/protobuf/unittest_custom_options.proto", False)
   generate_proto("../src/google/protobuf/unittest_import.proto", False)
@@ -146,6 +146,34 @@
     # _build_py is an old-style class, so super() doesn't work.
     _build_py.run(self)
 
+  def find_package_modules(self, package, package_dir):
+    exclude = (
+        "*test*",
+        "google/protobuf/internal/*_pb2.py",
+        "google/protobuf/internal/_parameterized.py",
+        "google/protobuf/pyext/python_pb2.py",
+    )
+    modules = _build_py.find_package_modules(self, package, package_dir)
+    return [(pkg, mod, fil) for (pkg, mod, fil) in modules
+            if not any(fnmatch.fnmatchcase(fil, pat=pat) for pat in exclude)]
+
+
+class build_ext(_build_ext):
+  def get_ext_filename(self, ext_name):
+      # since python3.5, python extensions' shared libraries use a suffix that corresponds to the value
+      # of sysconfig.get_config_var('EXT_SUFFIX') and contains info about the architecture the library targets.
+      # E.g. on x64 linux the suffix is ".cpython-XYZ-x86_64-linux-gnu.so"
+      # When crosscompiling python wheels, we need to be able to override this suffix
+      # so that the resulting file name matches the target architecture and we end up with a well-formed
+      # wheel.
+      filename = _build_ext.get_ext_filename(self, ext_name)
+      orig_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
+      new_ext_suffix = os.getenv("PROTOCOL_BUFFERS_OVERRIDE_EXT_SUFFIX")
+      if new_ext_suffix and filename.endswith(orig_ext_suffix):
+        filename = filename[:-len(orig_ext_suffix)] + new_ext_suffix
+      return filename
+
+
 class test_conformance(_build_py):
   target = 'test_python'
   def run(self):
@@ -196,7 +224,7 @@
     # C++ projects must now migrate to libc++ and are recommended to set a
     # deployment target of macOS 10.9 or later, or iOS 7 or later.
     if sys.platform == 'darwin':
-      mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+      mac_target = str(sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET'))
       if mac_target and (pkg_resources.parse_version(mac_target) <
                        pkg_resources.parse_version('10.9.0')):
         os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
@@ -243,7 +271,7 @@
     os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
 
   # Keep this list of dependencies in sync with tox.ini.
-  install_requires = ['six>=1.9', 'setuptools']
+  install_requires = ['six>=1.9']
   if sys.version_info <= (2,7):
     install_requires.append('ordereddict')
     install_requires.append('unittest2')
@@ -273,12 +301,14 @@
       packages=find_packages(
           exclude=[
               'import_test_package',
+              'protobuf_distutils',
           ],
       ),
       test_suite='google.protobuf.internal',
       cmdclass={
           'clean': clean,
           'build_py': build_py,
+          'build_ext': build_ext,
           'test_conformance': test_conformance,
       },
       install_requires=install_requires,
diff --git a/python/tox.ini b/python/tox.ini
index 999f8ce..f9eee92 100644
--- a/python/tox.ini
+++ b/python/tox.ini
@@ -1,6 +1,6 @@
 [tox]
 envlist =
-    py{27,33,34,35,36}-{cpp,python}
+    py{27,33,34,35,36,37,38,39}-{cpp,python}
 
 [testenv]
 usedevelop=true
@@ -14,7 +14,9 @@
 commands =
     python setup.py -q build_py
     python: python setup.py -q build
-    cpp: python setup.py -q build --cpp_implementation --warnings_as_errors --compile_static_extension
+    # --warnings_as_errors disabled for Python 2.7 because _POSIX_C_SOURCE and _XOPEN_SOURCE are redefined
+    py27-cpp: python setup.py -q build --cpp_implementation --compile_static_extension
+    py{33,34,35,36,37,38,39}-cpp: python setup.py -q build --cpp_implementation --warnings_as_errors --compile_static_extension
     python: python setup.py -q test -q
     cpp: python setup.py -q test -q --cpp_implementation
     python: python setup.py -q test_conformance
diff --git a/ruby/Gemfile b/ruby/Gemfile
index fa75df1..76b23ad 100644
--- a/ruby/Gemfile
+++ b/ruby/Gemfile
@@ -1,3 +1,5 @@
 source 'https://rubygems.org'
 
 gemspec
+
+gem "irb", "~> 1.1", "< 1.2.0" if RUBY_VERSION < "2.5"
diff --git a/ruby/Rakefile b/ruby/Rakefile
index b0b803d..221e9b5 100644
--- a/ruby/Rakefile
+++ b/ruby/Rakefile
@@ -18,12 +18,30 @@
   google/protobuf/wrappers.proto
 ]
 
+test_protos = %w[
+  tests/basic_test.proto
+  tests/basic_test_proto2.proto
+  tests/generated_code.proto
+  tests/generated_code_proto2.proto
+  tests/multi_level_nesting_test.proto
+  tests/test_import.proto
+  tests/test_import_proto2.proto
+  tests/test_ruby_package.proto
+  tests/test_ruby_package_proto2.proto
+]
+
 # These are omitted for now because we don't support proto2.
 proto2_protos = %w[
   google/protobuf/descriptor.proto
   google/protobuf/compiler/plugin.proto
 ]
 
+if system('../src/protoc --version')
+  protoc_command = '../src/protoc' 
+else
+  protoc_command = 'protoc' 
+end
+
 genproto_output = []
 
 # We won't have access to .. from within docker, but the proto files
@@ -34,7 +52,15 @@
     output_file = "lib/" + proto_file.sub(/\.proto$/, "_pb.rb")
     genproto_output << output_file
     file output_file => input_file do |file_task|
-      sh "../src/protoc -I../src --ruby_out=lib #{input_file}"
+      sh "#{protoc_command} -I../src --ruby_out=lib #{input_file}"
+    end
+  end
+
+  test_protos.each do |proto_file|
+    output_file = proto_file.sub(/\.proto$/, "_pb.rb")
+    genproto_output << output_file
+    file output_file => proto_file do |file_task|
+      sh "#{protoc_command} -I../src -I. --ruby_out=. #{proto_file}"
     end
   end
 end
@@ -51,6 +77,12 @@
     system("mvn --batch-mode package")
   end
 else
+  unless ENV['IN_DOCKER'] == 'true'
+    # We need wyhash in-tree.
+    FileUtils.mkdir_p("ext/google/protobuf_c/third_party/wyhash")
+    FileUtils.cp("../third_party/wyhash/wyhash.h", "ext/google/protobuf_c/third_party/wyhash/wyhash.h")
+  end
+
   Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
     unless RUBY_PLATFORM =~ /darwin/
       # TODO: also set "no_native to true" for mac if possible. As is,
@@ -73,7 +105,7 @@
     ['x86-mingw32', 'x64-mingw32', 'x86_64-linux', 'x86-linux'].each do |plat|
       RakeCompilerDock.sh <<-"EOT", platform: plat
         bundle && \
-        IN_DOCKER=true rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.0:2.4.0:2.3.0
+        IN_DOCKER=true rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem RUBY_CC_VERSION=3.0.0:2.7.0:2.6.0:2.5.0:2.4.0:2.3.0
       EOT
     end
   end
@@ -81,60 +113,13 @@
   if RUBY_PLATFORM =~ /darwin/
     task 'gem:native' do
       system "rake genproto"
-      system "rake cross native gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.1:2.4.0:2.3.0"
+      system "rake cross native gem RUBY_CC_VERSION=3.0.0:2.7.0:2.6.0:2.5.1:2.4.0:2.3.0"
     end
   else
     task 'gem:native' => [:genproto, 'gem:windows']
   end
 end
 
-
-# Proto for tests.
-genproto_output << "tests/generated_code.rb"
-genproto_output << "tests/generated_code_proto2.rb"
-genproto_output << "tests/test_import.rb"
-genproto_output << "tests/test_import_proto2.rb"
-genproto_output << "tests/test_ruby_package.rb"
-genproto_output << "tests/test_ruby_package_proto2.rb"
-genproto_output << "tests/basic_test.rb"
-genproto_output << "tests/basic_test_proto2.rb"
-genproto_output << "tests/wrappers.rb"
-file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task|
-  sh "../src/protoc --ruby_out=. tests/generated_code.proto"
-end
-
-file "tests/generated_code_proto2.rb" => "tests/generated_code_proto2.proto" do |file_task|
-  sh "../src/protoc --ruby_out=. tests/generated_code_proto2.proto"
-end
-
-file "tests/test_import.rb" => "tests/test_import.proto" do |file_task|
-  sh "../src/protoc --ruby_out=. tests/test_import.proto"
-end
-
-file "tests/test_import_proto2.rb" => "tests/test_import_proto2.proto" do |file_task|
-  sh "../src/protoc --ruby_out=. tests/test_import_proto2.proto"
-end
-
-file "tests/test_ruby_package.rb" => "tests/test_ruby_package.proto" do |file_task|
-  sh "../src/protoc --ruby_out=. tests/test_ruby_package.proto"
-end
-
-file "tests/test_ruby_package_proto2.rb" => "tests/test_ruby_package_proto2.proto" do |file_task|
-  sh "../src/protoc --ruby_out=. tests/test_ruby_package_proto2.proto"
-end
-
-file "tests/basic_test.rb" => "tests/basic_test.proto" do |file_task|
-  sh "../src/protoc -I../src -I. --ruby_out=. tests/basic_test.proto"
-end
-
-file "tests/basic_test_proto2.rb" => "tests/basic_test_proto2.proto" do |file_task|
-  sh "../src/protoc -I../src -I. --ruby_out=. tests/basic_test_proto2.proto"
-end
-
-file "tests/wrappers.rb" => "../src/google/protobuf/wrappers.proto" do |file_task|
-  sh "../src/protoc -I../src -I. --ruby_out=tests ../src/google/protobuf/wrappers.proto"
-end
-
 task :genproto => genproto_output
 
 task :clean do
@@ -144,7 +129,7 @@
 Gem::PackageTask.new(spec) do |pkg|
 end
 
-Rake::TestTask.new(:test => :build) do |t|
+Rake::TestTask.new(:test => [:build, :genproto]) do |t|
   t.test_files = FileList["tests/*.rb"].exclude("tests/gc_test.rb", "tests/common_tests.rb")
 end
 
@@ -154,7 +139,7 @@
   t.test_files = FileList["tests/gc_test.rb"]
 end
 
-task :build => [:clean, :compile, :genproto]
+task :build => [:clean, :genproto, :compile]
 task :default => [:build]
 
 # vim:sw=2:et
diff --git a/ruby/compatibility_tests/v3.0.0/tests/basic.rb b/ruby/compatibility_tests/v3.0.0/tests/basic.rb
index bfe68ef..7228144 100755
--- a/ruby/compatibility_tests/v3.0.0/tests/basic.rb
+++ b/ruby/compatibility_tests/v3.0.0/tests/basic.rb
@@ -1264,10 +1264,10 @@
       m = MapMessage.new(:map_string_int32 => {"a" => 1})
       expected = '{"mapStringInt32":{"a":1},"mapStringMsg":{}}'
       expected_preserve = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
-      assert MapMessage.encode_json(m) == expected
+      assert_equal expected, MapMessage.encode_json(m, :emit_defaults => true)
 
-      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
-      assert json == expected_preserve
+      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults => true)
+      assert_equal expected_preserve, json
 
       m2 = MapMessage.decode_json(MapMessage.encode_json(m))
       assert m == m2
diff --git a/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb b/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb
index 4ebb731..4f70f52 100755
--- a/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb
+++ b/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb
@@ -20,6 +20,7 @@
       :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,
       :nitems, :iter_for_reverse_each, :indexes, :append, :prepend]
     arr_methods -= [:union, :difference, :filter!]
+    arr_methods -= [:intersection, :deconstruct] # ruby 2.7 methods we can ignore
     arr_methods.each do |method_name|
       assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
     end
@@ -325,18 +326,6 @@
     end
   end
 
-  def test_compact!
-    m = TestMessage.new
-    m.repeated_msg << TestMessage2.new(:foo => 1)
-    m.repeated_msg << nil
-    m.repeated_msg << TestMessage2.new(:foo => 2)
-    reference_arr = m.repeated_string.to_a
-
-    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
-      arr.compact!
-    end
-  end
-
   def test_delete
     m = TestMessage.new
     reference_arr = %w(foo bar baz)
diff --git a/ruby/ext/google/protobuf_c/convert.c b/ruby/ext/google/protobuf_c/convert.c
new file mode 100644
index 0000000..2fddc09
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/convert.c
@@ -0,0 +1,349 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// -----------------------------------------------------------------------------
+// Ruby <-> upb data conversion functions.
+//
+// This file Also contains a few other assorted algorithms on upb_msgval.
+//
+// None of the algorithms in this file require any access to the internal
+// representation of Ruby or upb objects.
+// -----------------------------------------------------------------------------
+
+#include "convert.h"
+
+#include "message.h"
+#include "protobuf.h"
+#include "third_party/wyhash/wyhash.h"
+
+static upb_strview Convert_StringData(VALUE str, upb_arena *arena) {
+  upb_strview ret;
+  if (arena) {
+    char *ptr = upb_arena_malloc(arena, RSTRING_LEN(str));
+    memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str));
+    ret.data = ptr;
+  } else {
+    // Data is only needed temporarily (within map lookup).
+    ret.data = RSTRING_PTR(str);
+  }
+  ret.size = RSTRING_LEN(str);
+  return ret;
+}
+
+static bool is_ruby_num(VALUE value) {
+  return (TYPE(value) == T_FLOAT ||
+          TYPE(value) == T_FIXNUM ||
+          TYPE(value) == T_BIGNUM);
+}
+
+static void Convert_CheckInt(const char* name, upb_fieldtype_t type,
+                             VALUE val) {
+  if (!is_ruby_num(val)) {
+    rb_raise(cTypeError,
+             "Expected number type for integral field '%s' (given %s).", name,
+             rb_class2name(CLASS_OF(val)));
+  }
+
+  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
+  // bound; we just need to do precision checks (i.e., disallow rounding) and
+  // check for < 0 on unsigned types.
+  if (TYPE(val) == T_FLOAT) {
+    double dbl_val = NUM2DBL(val);
+    if (floor(dbl_val) != dbl_val) {
+      rb_raise(rb_eRangeError,
+               "Non-integral floating point value assigned to integer field "
+               "'%s' (given %s).",
+               name, rb_class2name(CLASS_OF(val)));
+    }
+  }
+  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
+    if (NUM2DBL(val) < 0) {
+      rb_raise(
+          rb_eRangeError,
+          "Assigning negative value to unsigned integer field '%s' (given %s).",
+          name, rb_class2name(CLASS_OF(val)));
+    }
+  }
+}
+
+static int32_t Convert_ToEnum(VALUE value, const char* name,
+                              const upb_enumdef* e) {
+  int32_t val;
+
+  switch (TYPE(value)) {
+    case T_FLOAT:
+    case T_FIXNUM:
+    case T_BIGNUM:
+      Convert_CheckInt(name, UPB_TYPE_INT32, value);
+      val = NUM2INT(value);
+      break;
+    case T_STRING:
+      if (!upb_enumdef_ntoi(e, RSTRING_PTR(value), RSTRING_LEN(value), &val)) {
+        goto unknownval;
+      }
+      break;
+    case T_SYMBOL:
+      if (!upb_enumdef_ntoiz(e, rb_id2name(SYM2ID(value)), &val)) {
+        goto unknownval;
+      }
+      break;
+    default:
+      rb_raise(cTypeError,
+               "Expected number or symbol type for enum field '%s'.", name);
+  }
+
+  return val;
+
+unknownval:
+  rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
+}
+
+upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info,
+                             upb_arena* arena) {
+  upb_msgval ret;
+
+  switch (type_info.type) {
+    case UPB_TYPE_FLOAT:
+      if (!is_ruby_num(value)) {
+        rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+      ret.float_val = NUM2DBL(value);
+      break;
+    case UPB_TYPE_DOUBLE:
+      if (!is_ruby_num(value)) {
+        rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+      ret.double_val = NUM2DBL(value);
+      break;
+    case UPB_TYPE_BOOL: {
+      if (value == Qtrue) {
+        ret.bool_val = 1;
+      } else if (value == Qfalse) {
+        ret.bool_val = 0;
+      } else {
+        rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+      break;
+    }
+    case UPB_TYPE_STRING: {
+      VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
+      if (CLASS_OF(value) == rb_cSymbol) {
+        value = rb_funcall(value, rb_intern("to_s"), 0);
+      } else if (CLASS_OF(value) != rb_cString) {
+        rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+
+      if (rb_obj_encoding(value) != utf8) {
+        // Note: this will not duplicate underlying string data unless necessary.
+        value = rb_str_encode(value, utf8, 0, Qnil);
+
+        if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
+          rb_raise(rb_eEncodingError, "String is invalid UTF-8");
+        }
+      }
+
+      ret.str_val = Convert_StringData(value, arena);
+      break;
+    }
+    case UPB_TYPE_BYTES: {
+      VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding());
+      if (CLASS_OF(value) != rb_cString) {
+        rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+
+      if (rb_obj_encoding(value) != bytes) {
+        // Note: this will not duplicate underlying string data unless necessary.
+        // TODO(haberman): is this really necessary to get raw bytes?
+        value = rb_str_encode(value, bytes, 0, Qnil);
+      }
+
+      ret.str_val = Convert_StringData(value, arena);
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      ret.msg_val =
+          Message_GetUpbMessage(value, type_info.def.msgdef, name, arena);
+      break;
+    case UPB_TYPE_ENUM:
+      ret.int32_val = Convert_ToEnum(value, name, type_info.def.enumdef);
+      break;
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      Convert_CheckInt(name, type_info.type, value);
+      switch (type_info.type) {
+      case UPB_TYPE_INT32:
+        ret.int32_val = NUM2INT(value);
+        break;
+      case UPB_TYPE_INT64:
+        ret.int64_val = NUM2LL(value);
+        break;
+      case UPB_TYPE_UINT32:
+        ret.uint32_val = NUM2UINT(value);
+        break;
+      case UPB_TYPE_UINT64:
+        ret.uint64_val = NUM2ULL(value);
+        break;
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena) {
+  switch (type_info.type) {
+    case UPB_TYPE_FLOAT:
+      return DBL2NUM(upb_val.float_val);
+    case UPB_TYPE_DOUBLE:
+      return DBL2NUM(upb_val.double_val);
+    case UPB_TYPE_BOOL:
+      return upb_val.bool_val ? Qtrue : Qfalse;
+    case UPB_TYPE_INT32:
+      return INT2NUM(upb_val.int32_val);
+    case UPB_TYPE_INT64:
+      return LL2NUM(upb_val.int64_val);
+    case UPB_TYPE_UINT32:
+      return UINT2NUM(upb_val.uint32_val);
+    case UPB_TYPE_UINT64:
+      return ULL2NUM(upb_val.int64_val);
+    case UPB_TYPE_ENUM: {
+      const char* name =
+          upb_enumdef_iton(type_info.def.enumdef, upb_val.int32_val);
+      if (name) {
+        return ID2SYM(rb_intern(name));
+      } else {
+        return INT2NUM(upb_val.int32_val);
+      }
+    }
+    case UPB_TYPE_STRING: {
+      VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
+      rb_enc_associate(str_rb, rb_utf8_encoding());
+      rb_obj_freeze(str_rb);
+      return str_rb;
+    }
+    case UPB_TYPE_BYTES: {
+      VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
+      rb_enc_associate(str_rb, rb_ascii8bit_encoding());
+      rb_obj_freeze(str_rb);
+      return str_rb;
+    }
+    case UPB_TYPE_MESSAGE:
+      return Message_GetRubyWrapper((upb_msg*)upb_val.msg_val,
+                                    type_info.def.msgdef, arena);
+    default:
+      rb_raise(rb_eRuntimeError, "Convert_UpbToRuby(): Unexpected type %d",
+               (int)type_info.type);
+  }
+}
+
+upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
+                           upb_arena* arena) {
+  upb_msgval new_msgval;
+
+  switch (type_info.type) {
+    default:
+      memcpy(&new_msgval, &msgval, sizeof(msgval));
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      size_t n = msgval.str_val.size;
+      char *mem = upb_arena_malloc(arena, n);
+      new_msgval.str_val.data = mem;
+      new_msgval.str_val.size = n;
+      memcpy(mem, msgval.str_val.data, n);
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      new_msgval.msg_val =
+          Message_deep_copy(msgval.msg_val, type_info.def.msgdef, arena);
+      break;
+  }
+
+  return new_msgval;
+}
+
+bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info) {
+  switch (type_info.type) {
+    case UPB_TYPE_BOOL:
+      return memcmp(&val1, &val2, 1) == 0;
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return memcmp(&val1, &val2, 4) == 0;
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return memcmp(&val1, &val2, 8) == 0;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return val1.str_val.size == val2.str_val.size &&
+             memcmp(val1.str_val.data, val2.str_val.data,
+                    val1.str_val.size) == 0;
+    case UPB_TYPE_MESSAGE:
+      return Message_Equal(val1.msg_val, val2.msg_val, type_info.def.msgdef);
+    default:
+      rb_raise(rb_eRuntimeError, "Internal error, unexpected type");
+  }
+}
+
+uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed) {
+  switch (type_info.type) {
+    case UPB_TYPE_BOOL:
+      return wyhash(&val, 1, seed, _wyp);
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return wyhash(&val, 4, seed, _wyp);
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return wyhash(&val, 8, seed, _wyp);
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return wyhash(val.str_val.data, val.str_val.size, seed, _wyp);
+    case UPB_TYPE_MESSAGE:
+      return Message_Hash(val.msg_val, type_info.def.msgdef, seed);
+    default:
+      rb_raise(rb_eRuntimeError, "Internal error, unexpected type");
+  }
+}
diff --git a/ruby/ext/google/protobuf_c/convert.h b/ruby/ext/google/protobuf_c/convert.h
new file mode 100644
index 0000000..cda18a0
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/convert.h
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_CONVERT_H_
+#define RUBY_PROTOBUF_CONVERT_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Converts |ruby_val| to a upb_msgval according to |type_info|.
+//
+// The |arena| parameter indicates the lifetime of the container where this
+// value will be assigned. It is used as follows:
+// - If type is string or bytes, the string data will be copied into |arena|.
+// - If type is message, and we need to auto-construct a message due to implicit
+//   conversions (eg. Time -> Google::Protobuf::Timestamp), the new message
+//   will be created in |arena|.
+// - If type is message and the Ruby value is a message instance, we will fuse
+//   the message's arena into |arena|, to ensure that this message outlives the
+//   container.
+upb_msgval Convert_RubyToUpb(VALUE ruby_val, const char *name,
+                             TypeInfo type_info, upb_arena *arena);
+
+// Converts |upb_val| to a Ruby VALUE according to |type_info|. This may involve
+// creating a Ruby wrapper object.
+//
+// The |arena| parameter indicates the arena that owns the lifetime of
+// |upb_val|. Any Ruby wrapper object that is created will reference |arena|
+// and ensure it outlives the wrapper.
+VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena);
+
+// Creates a deep copy of |msgval| in |arena|.
+upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
+                           upb_arena *arena);
+
+// Returns true if |val1| and |val2| are equal. Their type is given by
+// |type_info|.
+bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info);
+
+// Returns a hash value for the given upb_msgval.
+uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed);
+
+#endif  // RUBY_PROTOBUF_CONVERT_H_
diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c
index 1e84984..88da610 100644
--- a/ruby/ext/google/protobuf_c/defs.c
+++ b/ruby/ext/google/protobuf_c/defs.c
@@ -30,8 +30,35 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <ruby/version.h>
+
+#include "convert.h"
+#include "message.h"
 #include "protobuf.h"
 
+static VALUE Builder_build(VALUE _self);
+
+static VALUE cMessageBuilderContext;
+static VALUE cOneofBuilderContext;
+static VALUE cEnumBuilderContext;
+static VALUE cBuilder;
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// -----------------------------------------------------------------------------
+
+static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def);
+static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def);
+static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def);
+static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def);
+static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def);
+
+// A distinct object that is not accessible from Ruby.  We use this as a
+// constructor argument to enforce that certain objects cannot be created from
+// Ruby.
+VALUE c_only_cookie = Qnil;
+
 // -----------------------------------------------------------------------------
 // Common utilities.
 // -----------------------------------------------------------------------------
@@ -48,6 +75,10 @@
   return rb_str_new2(s);
 }
 
+// -----------------------------------------------------------------------------
+// Backward compatibility code.
+// -----------------------------------------------------------------------------
+
 static void rewrite_enum_default(const upb_symtab* symtab,
                                  google_protobuf_FileDescriptorProto* file,
                                  google_protobuf_FieldDescriptorProto* field) {
@@ -205,6 +236,1280 @@
   }
 }
 
+// -----------------------------------------------------------------------------
+// DescriptorPool.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  VALUE def_to_descriptor;  // Hash table of def* -> Ruby descriptor.
+  upb_symtab* symtab;
+} DescriptorPool;
+
+VALUE cDescriptorPool = Qnil;
+
+// Global singleton DescriptorPool. The user is free to create others, but this
+// is used by generated code.
+VALUE generated_pool = Qnil;
+
+static void DescriptorPool_mark(void* _self) {
+  DescriptorPool* self = _self;
+  rb_gc_mark(self->def_to_descriptor);
+}
+
+static void DescriptorPool_free(void* _self) {
+  DescriptorPool* self = _self;
+  upb_symtab_free(self->symtab);
+  xfree(self);
+}
+
+static const rb_data_type_t DescriptorPool_type = {
+  "Google::Protobuf::DescriptorPool",
+  {DescriptorPool_mark, DescriptorPool_free, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
+  DescriptorPool* ret;
+  TypedData_Get_Struct(val, DescriptorPool, &DescriptorPool_type, ret);
+  return ret;
+}
+
+// Exposed to other modules in defs.h.
+const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb) {
+  DescriptorPool *pool = ruby_to_DescriptorPool(desc_pool_rb);
+  return pool->symtab;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.new => pool
+ *
+ * Creates a new, empty, descriptor pool.
+ */
+static VALUE DescriptorPool_alloc(VALUE klass) {
+  DescriptorPool* self = ALLOC(DescriptorPool);
+  VALUE ret;
+
+  self->def_to_descriptor = Qnil;
+  ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
+
+  self->def_to_descriptor = rb_hash_new();
+  self->symtab = upb_symtab_new();
+  ObjectCache_Add(self->symtab, ret);
+
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.build(&block)
+ *
+ * Invokes the block with a Builder instance as self. All message and enum types
+ * added within the block are committed to the pool atomically, and may refer
+ * (co)recursively to each other. The user should call Builder#add_message and
+ * Builder#add_enum within the block as appropriate.  This is the recommended,
+ * idiomatic way to define new message and enum types.
+ */
+static VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
+  VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
+  VALUE block = rb_block_proc();
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  Builder_build(ctx);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.build_file(serialized_file_proto)
+ *
+ * Adds the given serialized FileDescriptorProto to the pool.
+ */
+VALUE DescriptorPool_build(value _self, VALUE serialized_file_proto) {
+  DEFINE_SELF(DescriptorPool, self, _self);
+  Check_Type(serialized_file_proto, T_STRING);
+  upb_arena *arena = upb_arena_new();
+  google_protobuf_FileDescriptorProto* file_proto =
+      google_protobuf_FileDescriptorProto_parse(
+          RSTRING_PTR(serialized_file_proto),
+          RSTRING_LEN(serialized_file_proto), arena);
+  upb_status status;
+  upb_status_clear(&status);
+  if (!upb_symtab_addfile(self->symtab, file_proto, &status)) {
+    rb_raise(cTypeError, "Unable to build file to DescriptorPool: %s",
+             upb_status_errmsg(&status));
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.lookup(name) => descriptor
+ *
+ * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
+ * exists with the given name.
+ */
+static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
+  DescriptorPool* self = ruby_to_DescriptorPool(_self);
+  const char* name_str = get_str(name);
+  const upb_msgdef* msgdef;
+  const upb_enumdef* enumdef;
+
+  msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
+  if (msgdef) {
+    return get_msgdef_obj(_self, msgdef);
+  }
+
+  enumdef = upb_symtab_lookupenum(self->symtab, name_str);
+  if (enumdef) {
+    return get_enumdef_obj(_self, enumdef);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.generated_pool => descriptor_pool
+ *
+ * Class method that returns the global DescriptorPool. This is a singleton into
+ * which generated-code message and enum types are registered. The user may also
+ * register types in this pool for convenience so that they do not have to hold
+ * a reference to a private pool instance.
+ */
+static VALUE DescriptorPool_generated_pool(VALUE _self) {
+  return generated_pool;
+}
+
+static void DescriptorPool_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "DescriptorPool", rb_cObject);
+  rb_define_alloc_func(klass, DescriptorPool_alloc);
+  rb_define_method(klass, "build", DescriptorPool_build, -1);
+  rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
+  rb_define_singleton_method(klass, "generated_pool",
+                             DescriptorPool_generated_pool, 0);
+  rb_gc_register_address(&cDescriptorPool);
+  cDescriptorPool = klass;
+
+  rb_gc_register_address(&generated_pool);
+  generated_pool = rb_class_new_instance(0, NULL, klass);
+}
+
+// -----------------------------------------------------------------------------
+// Descriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_msgdef* msgdef;
+  VALUE klass;
+  VALUE descriptor_pool;
+} Descriptor;
+
+VALUE cDescriptor = Qnil;
+
+static void Descriptor_mark(void* _self) {
+  Descriptor* self = _self;
+  rb_gc_mark(self->klass);
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t Descriptor_type = {
+  "Google::Protobuf::Descriptor",
+  {Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static Descriptor* ruby_to_Descriptor(VALUE val) {
+  Descriptor* ret;
+  TypedData_Get_Struct(val, Descriptor, &Descriptor_type, ret);
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.new => descriptor
+ *
+ * Creates a new, empty, message type descriptor. At a minimum, its name must be
+ * set before it is added to a pool. It cannot be used to create messages until
+ * it is added to a pool, after which it becomes immutable (as part of a
+ * finalization process).
+ */
+static VALUE Descriptor_alloc(VALUE klass) {
+  Descriptor* self = ALLOC(Descriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &Descriptor_type, self);
+  self->msgdef = NULL;
+  self->klass = Qnil;
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *    Descriptor.new(c_only_cookie, ptr) => Descriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
+                                   VALUE descriptor_pool, VALUE ptr) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *    Descriptor.file_descriptor
+ *
+ * Returns the FileDescriptor object this message belongs to.
+ */
+static VALUE Descriptor_file_descriptor(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
+}
+
+/*
+ * call-seq:
+ *     Descriptor.name => name
+ *
+ * Returns the name of this message type as a fully-qualified string (e.g.,
+ * My.Package.MessageType).
+ */
+static VALUE Descriptor_name(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
+}
+
+/*
+ * call-seq:
+ *     Descriptor.each(&block)
+ *
+ * Iterates over fields in this message type, yielding to the block on each one.
+ */
+static VALUE Descriptor_each(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, self->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.lookup(name) => FieldDescriptor
+ *
+ * Returns the field descriptor for the field with the given name, if present,
+ * or nil if none.
+ */
+static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  const char* s = get_str(name);
+  const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
+  if (field == NULL) {
+    return Qnil;
+  }
+  return get_fielddef_obj(self->descriptor_pool, field);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.each_oneof(&block) => nil
+ *
+ * Invokes the given block for each oneof in this message type, passing the
+ * corresponding OneofDescriptor.
+ */
+static VALUE Descriptor_each_oneof(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+
+  upb_msg_oneof_iter it;
+  for (upb_msg_oneof_begin(&it, self->msgdef);
+       !upb_msg_oneof_done(&it);
+       upb_msg_oneof_next(&it)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
+    VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.lookup_oneof(name) => OneofDescriptor
+ *
+ * Returns the oneof descriptor for the oneof with the given name, if present,
+ * or nil if none.
+ */
+static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  const char* s = get_str(name);
+  const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
+  if (oneof == NULL) {
+    return Qnil;
+  }
+  return get_oneofdef_obj(self->descriptor_pool, oneof);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.msgclass => message_klass
+ *
+ * Returns the Ruby class created for this message type.
+ */
+static VALUE Descriptor_msgclass(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  if (self->klass == Qnil) {
+    self->klass = build_class_from_descriptor(_self);
+  }
+  return self->klass;
+}
+
+static void Descriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "Descriptor", rb_cObject);
+  rb_define_alloc_func(klass, Descriptor_alloc);
+  rb_define_method(klass, "initialize", Descriptor_initialize, 3);
+  rb_define_method(klass, "each", Descriptor_each, 0);
+  rb_define_method(klass, "lookup", Descriptor_lookup, 1);
+  rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
+  rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
+  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
+  rb_define_method(klass, "name", Descriptor_name, 0);
+  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  rb_gc_register_address(&cDescriptor);
+  cDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// FileDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_filedef* filedef;
+  VALUE descriptor_pool;  // Owns the upb_filedef.
+} FileDescriptor;
+
+static VALUE cFileDescriptor = Qnil;
+
+static void FileDescriptor_mark(void* _self) {
+  FileDescriptor* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t FileDescriptor_type = {
+  "Google::Protobuf::FileDescriptor",
+  {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
+  FileDescriptor* ret;
+  TypedData_Get_Struct(val, FileDescriptor, &FileDescriptor_type, ret);
+  return ret;
+}
+
+static VALUE FileDescriptor_alloc(VALUE klass) {
+  FileDescriptor* self = ALLOC(FileDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &FileDescriptor_type, self);
+  self->descriptor_pool = Qnil;
+  self->filedef = NULL;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     FileDescriptor.new => file
+ *
+ * Returns a new file descriptor. The syntax must be set before it's passed
+ * to a builder.
+ */
+static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
+                                VALUE descriptor_pool, VALUE ptr) {
+  FileDescriptor* self = ruby_to_FileDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->filedef = (const upb_filedef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FileDescriptor.name => name
+ *
+ * Returns the name of the file.
+ */
+static VALUE FileDescriptor_name(VALUE _self) {
+  FileDescriptor* self = ruby_to_FileDescriptor(_self);
+  const char* name = upb_filedef_name(self->filedef);
+  return name == NULL ? Qnil : rb_str_new2(name);
+}
+
+/*
+ * call-seq:
+ *     FileDescriptor.syntax => syntax
+ *
+ * Returns this file descriptors syntax.
+ *
+ * Valid syntax versions are:
+ *     :proto2 or :proto3.
+ */
+static VALUE FileDescriptor_syntax(VALUE _self) {
+  FileDescriptor* self = ruby_to_FileDescriptor(_self);
+
+  switch (upb_filedef_syntax(self->filedef)) {
+    case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3"));
+    case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2"));
+    default: return Qnil;
+  }
+}
+
+static void FileDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "FileDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, FileDescriptor_alloc);
+  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
+  rb_define_method(klass, "name", FileDescriptor_name, 0);
+  rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
+  rb_gc_register_address(&cFileDescriptor);
+  cFileDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// FieldDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_fielddef* fielddef;
+  VALUE descriptor_pool;  // Owns the upb_fielddef.
+} FieldDescriptor;
+
+static VALUE cFieldDescriptor = Qnil;
+
+static void FieldDescriptor_mark(void* _self) {
+  FieldDescriptor* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t FieldDescriptor_type = {
+  "Google::Protobuf::FieldDescriptor",
+  {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
+  FieldDescriptor* ret;
+  TypedData_Get_Struct(val, FieldDescriptor, &FieldDescriptor_type, ret);
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.new => field
+ *
+ * Returns a new field descriptor. Its name, type, etc. must be set before it is
+ * added to a message type.
+ */
+static VALUE FieldDescriptor_alloc(VALUE klass) {
+  FieldDescriptor* self = ALLOC(FieldDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &FieldDescriptor_type, self);
+  self->fielddef = NULL;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *    EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
+                                        VALUE descriptor_pool, VALUE ptr) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.name => name
+ *
+ * Returns the name of this field.
+ */
+static VALUE FieldDescriptor_name(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
+}
+
+// Non-static, exposed to other .c files.
+upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
+  if (TYPE(type) != T_SYMBOL) {
+    rb_raise(rb_eArgError, "Expected symbol for field type.");
+  }
+
+#define CONVERT(upb, ruby)                                           \
+  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
+    return UPB_TYPE_ ## upb;                                         \
+  }
+
+  CONVERT(FLOAT, float);
+  CONVERT(DOUBLE, double);
+  CONVERT(BOOL, bool);
+  CONVERT(STRING, string);
+  CONVERT(BYTES, bytes);
+  CONVERT(MESSAGE, message);
+  CONVERT(ENUM, enum);
+  CONVERT(INT32, int32);
+  CONVERT(INT64, int64);
+  CONVERT(UINT32, uint32);
+  CONVERT(UINT64, uint64);
+
+#undef CONVERT
+
+  rb_raise(rb_eArgError, "Unknown field type.");
+  return 0;
+}
+
+static upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
+  if (TYPE(type) != T_SYMBOL) {
+    rb_raise(rb_eArgError, "Expected symbol for field type.");
+  }
+
+#define CONVERT(upb, ruby)                                           \
+  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
+    return UPB_DESCRIPTOR_TYPE_ ## upb;                              \
+  }
+
+  CONVERT(FLOAT, float);
+  CONVERT(DOUBLE, double);
+  CONVERT(BOOL, bool);
+  CONVERT(STRING, string);
+  CONVERT(BYTES, bytes);
+  CONVERT(MESSAGE, message);
+  CONVERT(GROUP, group);
+  CONVERT(ENUM, enum);
+  CONVERT(INT32, int32);
+  CONVERT(INT64, int64);
+  CONVERT(UINT32, uint32);
+  CONVERT(UINT64, uint64);
+  CONVERT(SINT32, sint32);
+  CONVERT(SINT64, sint64);
+  CONVERT(FIXED32, fixed32);
+  CONVERT(FIXED64, fixed64);
+  CONVERT(SFIXED32, sfixed32);
+  CONVERT(SFIXED64, sfixed64);
+
+#undef CONVERT
+
+  rb_raise(rb_eArgError, "Unknown field type.");
+  return 0;
+}
+
+static VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
+  switch (type) {
+#define CONVERT(upb, ruby)                                           \
+    case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
+    CONVERT(FLOAT, float);
+    CONVERT(DOUBLE, double);
+    CONVERT(BOOL, bool);
+    CONVERT(STRING, string);
+    CONVERT(BYTES, bytes);
+    CONVERT(MESSAGE, message);
+    CONVERT(GROUP, group);
+    CONVERT(ENUM, enum);
+    CONVERT(INT32, int32);
+    CONVERT(INT64, int64);
+    CONVERT(UINT32, uint32);
+    CONVERT(UINT64, uint64);
+    CONVERT(SINT32, sint32);
+    CONVERT(SINT64, sint64);
+    CONVERT(FIXED32, fixed32);
+    CONVERT(FIXED64, fixed64);
+    CONVERT(SFIXED32, sfixed32);
+    CONVERT(SFIXED64, sfixed64);
+#undef CONVERT
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.type => type
+ *
+ * Returns this field's type, as a Ruby symbol, or nil if not yet set.
+ *
+ * Valid field types are:
+ *     :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
+ *     :bytes, :message.
+ */
+static VALUE FieldDescriptor__type(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.default => default
+ *
+ * Returns this field's default, as a Ruby object, or nil if not yet set.
+ */
+static VALUE FieldDescriptor_default(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_fielddef *f = self->fielddef;
+  upb_msgval default_val = {0};
+  if (upb_fielddef_issubmsg(f)) {
+    return Qnil;
+  } else if (!upb_fielddef_isseq(f)) {
+    default_val = upb_fielddef_default(f);
+  }
+  return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
+}
+
+
+/*
+ * call-seq:
+ *     FieldDescriptor.json_name => json_name
+ *
+ * Returns this field's json_name, as a Ruby string, or nil if not yet set.
+ */
+static VALUE FieldDescriptor_json_name(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_fielddef *f = self->fielddef;
+  const char *json_name = upb_fielddef_jsonname(f);
+  return rb_str_new2(json_name);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.label => label
+ *
+ * Returns this field's label (i.e., plurality), as a Ruby symbol.
+ *
+ * Valid field labels are:
+ *     :optional, :repeated
+ */
+static VALUE FieldDescriptor_label(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  switch (upb_fielddef_label(self->fielddef)) {
+#define CONVERT(upb, ruby)                                           \
+    case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
+
+    CONVERT(OPTIONAL, optional);
+    CONVERT(REQUIRED, required);
+    CONVERT(REPEATED, repeated);
+
+#undef CONVERT
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.number => number
+ *
+ * Returns the tag number for this field.
+ */
+static VALUE FieldDescriptor_number(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  return INT2NUM(upb_fielddef_number(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.submsg_name => submsg_name
+ *
+ * Returns the name of the message or enum type corresponding to this field, if
+ * it is a message or enum field (respectively), or nil otherwise. This type
+ * name will be resolved within the context of the pool to which the containing
+ * message type is added.
+ */
+static VALUE FieldDescriptor_submsg_name(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  switch (upb_fielddef_type(self->fielddef)) {
+    case UPB_TYPE_ENUM:
+      return rb_str_new2(
+          upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
+    case UPB_TYPE_MESSAGE:
+      return rb_str_new2(
+          upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
+    default:
+      return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.subtype => message_or_enum_descriptor
+ *
+ * Returns the message or enum descriptor corresponding to this field's type if
+ * it is a message or enum field, respectively, or nil otherwise. Cannot be
+ * called *until* the containing message type is added to a pool (and thus
+ * resolved).
+ */
+static VALUE FieldDescriptor_subtype(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  switch (upb_fielddef_type(self->fielddef)) {
+    case UPB_TYPE_ENUM:
+      return get_enumdef_obj(self->descriptor_pool,
+                             upb_fielddef_enumsubdef(self->fielddef));
+    case UPB_TYPE_MESSAGE:
+      return get_msgdef_obj(self->descriptor_pool,
+                            upb_fielddef_msgsubdef(self->fielddef));
+    default:
+      return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.get(message) => value
+ *
+ * Returns the value set for this field on the given message. Raises an
+ * exception if message is of the wrong type.
+ */
+static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+
+  Message_Get(msg_rb, &m);
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "get method called on wrong message type");
+  }
+
+  return Message_getfield(msg_rb, self->fielddef);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.has?(message) => boolean
+ *
+ * Returns whether the value is set on the given message. Raises an
+ * exception when calling for fields that do not have presence.
+ */
+static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+  const upb_msgdef *msg = Message_Get(msg_rb, &m);
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "has method called on wrong message type");
+  } else if (!upb_fielddef_haspresence(self->fielddef)) {
+    rb_raise(rb_eArgError, "does not track presence");
+  }
+
+  return upb_msg_has(msg, self->fielddef) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.clear(message)
+ *
+ * Clears the field from the message if it's set.
+ */
+static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+  upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "has method called on wrong message type");
+  }
+
+  upb_msg_clearfield(msg, self->fielddef);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.set(message, value)
+ *
+ * Sets the value corresponding to this field to the given value on the given
+ * message. Raises an exception if message is of the wrong type. Performs the
+ * ordinary type-checks for field setting.
+ */
+static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+  upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
+  upb_arena *arena = Arena_get(Message_GetArena(msg_rb));
+  upb_msgval msgval;
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "set method called on wrong message type");
+  }
+
+  msgval = Convert_RubyToUpb(value, upb_fielddef_name(self->fielddef),
+                             TypeInfo_get(self->fielddef), arena);
+  upb_msg_set(msg, self->fielddef, msgval, arena);
+  return Qnil;
+}
+
+static void FieldDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "FieldDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, FieldDescriptor_alloc);
+  rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
+  rb_define_method(klass, "name", FieldDescriptor_name, 0);
+  rb_define_method(klass, "type", FieldDescriptor__type, 0);
+  rb_define_method(klass, "default", FieldDescriptor_default, 0);
+  rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
+  rb_define_method(klass, "label", FieldDescriptor_label, 0);
+  rb_define_method(klass, "number", FieldDescriptor_number, 0);
+  rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
+  rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
+  rb_define_method(klass, "has?", FieldDescriptor_has, 1);
+  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
+  rb_define_method(klass, "get", FieldDescriptor_get, 1);
+  rb_define_method(klass, "set", FieldDescriptor_set, 2);
+  rb_gc_register_address(&cFieldDescriptor);
+  cFieldDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// OneofDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_oneofdef* oneofdef;
+  VALUE descriptor_pool;  // Owns the upb_oneofdef.
+} OneofDescriptor;
+
+static VALUE cOneofDescriptor = Qnil;
+
+static void OneofDescriptor_mark(void* _self) {
+  OneofDescriptor* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t OneofDescriptor_type = {
+    "Google::Protobuf::OneofDescriptor",
+    {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+    .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
+  OneofDescriptor* ret;
+  TypedData_Get_Struct(val, OneofDescriptor, &OneofDescriptor_type, ret);
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.new => oneof_descriptor
+ *
+ * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
+ * to being added to a message descriptor which is subsequently added to a pool.
+ */
+static VALUE OneofDescriptor_alloc(VALUE klass) {
+  OneofDescriptor* self = ALLOC(OneofDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &OneofDescriptor_type, self);
+  self->oneofdef = NULL;
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *    OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
+                                 VALUE descriptor_pool, VALUE ptr) {
+  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.name => name
+ *
+ * Returns the name of this oneof.
+ */
+static VALUE OneofDescriptor_name(VALUE _self) {
+  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
+  return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.each(&block) => nil
+ *
+ * Iterates through fields in this oneof, yielding to the block on each one.
+ */
+static VALUE OneofDescriptor_each(VALUE _self) {
+  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
+  upb_oneof_iter it;
+  for (upb_oneof_begin(&it, self->oneofdef);
+       !upb_oneof_done(&it);
+       upb_oneof_next(&it)) {
+    const upb_fielddef* f = upb_oneof_iter_field(&it);
+    VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+static void OneofDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, OneofDescriptor_alloc);
+  rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
+  rb_define_method(klass, "name", OneofDescriptor_name, 0);
+  rb_define_method(klass, "each", OneofDescriptor_each, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  rb_gc_register_address(&cOneofDescriptor);
+  cOneofDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// EnumDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_enumdef* enumdef;
+  VALUE module;  // begins as nil
+  VALUE descriptor_pool;  // Owns the upb_enumdef.
+} EnumDescriptor;
+
+static VALUE cEnumDescriptor = Qnil;
+
+static void EnumDescriptor_mark(void* _self) {
+  EnumDescriptor* self = _self;
+  rb_gc_mark(self->module);
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t EnumDescriptor_type = {
+  "Google::Protobuf::EnumDescriptor",
+  {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
+  EnumDescriptor* ret;
+  TypedData_Get_Struct(val, EnumDescriptor, &EnumDescriptor_type, ret);
+  return ret;
+}
+
+static VALUE EnumDescriptor_alloc(VALUE klass) {
+  EnumDescriptor* self = ALLOC(EnumDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &EnumDescriptor_type, self);
+  self->enumdef = NULL;
+  self->module = Qnil;
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+// Exposed to other modules in defs.h.
+const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) {
+  EnumDescriptor *desc = ruby_to_EnumDescriptor(enum_desc_rb);
+  return desc->enumdef;
+}
+
+/*
+ * call-seq:
+ *    EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
+                                       VALUE descriptor_pool, VALUE ptr) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *    EnumDescriptor.file_descriptor
+ *
+ * Returns the FileDescriptor object this enum belongs to.
+ */
+static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  return get_filedef_obj(self->descriptor_pool,
+                         upb_enumdef_file(self->enumdef));
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.name => name
+ *
+ * Returns the name of this enum type.
+ */
+static VALUE EnumDescriptor_name(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.lookup_name(name) => value
+ *
+ * Returns the numeric value corresponding to the given key name (as a Ruby
+ * symbol), or nil if none.
+ */
+static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  const char* name_str= rb_id2name(SYM2ID(name));
+  int32_t val = 0;
+  if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
+    return INT2NUM(val);
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.lookup_value(name) => value
+ *
+ * Returns the key name (as a Ruby symbol) corresponding to the integer value,
+ * or nil if none.
+ */
+static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  int32_t val = NUM2INT(number);
+  const char* name = upb_enumdef_iton(self->enumdef, val);
+  if (name != NULL) {
+    return ID2SYM(rb_intern(name));
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.each(&block)
+ *
+ * Iterates over key => value mappings in this enum's definition, yielding to
+ * the block with (key, value) arguments for each one.
+ */
+static VALUE EnumDescriptor_each(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+
+  upb_enum_iter it;
+  for (upb_enum_begin(&it, self->enumdef);
+       !upb_enum_done(&it);
+       upb_enum_next(&it)) {
+    VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it)));
+    VALUE number = INT2NUM(upb_enum_iter_number(&it));
+    rb_yield_values(2, key, number);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.enummodule => module
+ *
+ * Returns the Ruby module corresponding to this enum type.
+ */
+static VALUE EnumDescriptor_enummodule(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  if (self->module == Qnil) {
+    self->module = build_module_from_enumdesc(_self);
+  }
+  return self->module;
+}
+
+static void EnumDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "EnumDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, EnumDescriptor_alloc);
+  rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
+  rb_define_method(klass, "name", EnumDescriptor_name, 0);
+  rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
+  rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
+  rb_define_method(klass, "each", EnumDescriptor_each, 0);
+  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
+  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  rb_gc_register_address(&cEnumDescriptor);
+  cEnumDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// FileBuilderContext.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  upb_arena *arena;
+  google_protobuf_FileDescriptorProto* file_proto;
+  VALUE descriptor_pool;
+} FileBuilderContext;
+
+static VALUE cFileBuilderContext = Qnil;
+
+static void FileBuilderContext_mark(void* _self) {
+  FileBuilderContext* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static void FileBuilderContext_free(void* _self) {
+  FileBuilderContext* self = _self;
+  upb_arena_free(self->arena);
+  xfree(self);
+}
+
+static const rb_data_type_t FileBuilderContext_type = {
+  "Google::Protobuf::Internal::FileBuilderContext",
+  {FileBuilderContext_mark, FileBuilderContext_free, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static FileBuilderContext* ruby_to_FileBuilderContext(VALUE val) {
+  FileBuilderContext* ret;
+  TypedData_Get_Struct(val, FileBuilderContext, &FileBuilderContext_type, ret);
+  return ret;
+}
+
+static upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
+  FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
+  upb_strview ret;
+  char *data;
+
+  ret.size = strlen(str);
+  data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
+  ret.data = data;
+  memcpy(data, str, ret.size);
+  /* Null-terminate required by rewrite_enum_defaults() above. */
+  data[ret.size] = '\0';
+  return ret;
+}
+
+static upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
+  return FileBuilderContext_strdup2(_self, get_str(rb_str));
+}
+
+static upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
+  Check_Type(rb_sym, T_SYMBOL);
+  return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
+}
+
+static VALUE FileBuilderContext_alloc(VALUE klass) {
+  FileBuilderContext* self = ALLOC(FileBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &FileBuilderContext_type, self);
+  self->arena = upb_arena_new();
+  self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     FileBuilderContext.new(descriptor_pool) => context
+ *
+ * Create a new file builder context for the given file descriptor and
+ * builder context. This class is intended to serve as a DSL context to be used
+ * with #instance_eval.
+ */
+static VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
+                                           VALUE name, VALUE options) {
+  FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
+  self->descriptor_pool = descriptor_pool;
+
+  google_protobuf_FileDescriptorProto_set_name(
+      self->file_proto, FileBuilderContext_strdup(_self, name));
+
+  // Default syntax for Ruby is proto3.
+  google_protobuf_FileDescriptorProto_set_syntax(
+      self->file_proto,
+      FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
+
+  if (options != Qnil) {
+    VALUE syntax;
+
+    Check_Type(options, T_HASH);
+    syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
+
+    if (syntax != Qnil) {
+      VALUE syntax_str;
+
+      Check_Type(syntax, T_SYMBOL);
+      syntax_str = rb_id2str(SYM2ID(syntax));
+      google_protobuf_FileDescriptorProto_set_syntax(
+          self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
+    }
+  }
+
+  return Qnil;
+}
+
+<<<<<<< HEAD
+static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
+                           const VALUE* argv) {
+  DEFINE_SELF(MessageBuilderContext, message_builder, _message_builder);
+=======
+static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self);
+
+/*
+ * call-seq:
+ *     FileBuilderContext.add_message(name, &block)
+ *
+ * Creates a new, empty descriptor with the given name, and invokes the block in
+ * the context of a MessageBuilderContext on that descriptor. The block can then
+ * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
+ * methods to define the message fields.
+ *
+ * This is the recommended, idiomatic way to build message definitions.
+ */
+static VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
+  VALUE args[2] = { _self, name };
+  VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
+  VALUE block = rb_block_proc();
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  MessageBuilderContext_add_synthetic_oneofs(ctx);
+  return Qnil;
+}
+
 /* We have to do some relatively complicated logic here for backward
  * compatibility.
  *
@@ -334,1135 +1639,83 @@
       file_proto, RARRAY_LEN(enum_ents), arena);
 }
 
-// -----------------------------------------------------------------------------
-// DescriptorPool.
-// -----------------------------------------------------------------------------
-
-#define DEFINE_CLASS(name, string_name)                             \
-    VALUE c ## name = Qnil;                                         \
-    const rb_data_type_t _ ## name ## _type = {                     \
-      string_name,                                                  \
-      { name ## _mark, name ## _free, NULL },                       \
-    };                                                              \
-    name* ruby_to_ ## name(VALUE val) {                             \
-      name* ret;                                                    \
-      TypedData_Get_Struct(val, name, &_ ## name ## _type, ret);    \
-      return ret;                                                   \
-    }                                                               \
-
-#define DEFINE_SELF(type, var, rb_var)                              \
-    type* var = ruby_to_ ## type(rb_var)
-
-// Global singleton DescriptorPool. The user is free to create others, but this
-// is used by generated code.
-VALUE generated_pool = Qnil;
-
-DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool");
-
-void DescriptorPool_mark(void* _self) {
-  DescriptorPool* self = _self;
-  rb_gc_mark(self->def_to_descriptor);
-}
-
-void DescriptorPool_free(void* _self) {
-  DescriptorPool* self = _self;
-
-  upb_symtab_free(self->symtab);
-  upb_handlercache_free(self->fill_handler_cache);
-  upb_handlercache_free(self->pb_serialize_handler_cache);
-  upb_handlercache_free(self->json_serialize_handler_cache);
-  upb_handlercache_free(self->json_serialize_handler_preserve_cache);
-  upb_pbcodecache_free(self->fill_method_cache);
-  upb_json_codecache_free(self->json_fill_method_cache);
-
-  xfree(self);
-}
-
 /*
  * call-seq:
- *     DescriptorPool.new => pool
+ *     FileBuilderContext.add_enum(name, &block)
  *
- * Creates a new, empty, descriptor pool.
- */
-VALUE DescriptorPool_alloc(VALUE klass) {
-  DescriptorPool* self = ALLOC(DescriptorPool);
-  VALUE ret;
-
-  self->def_to_descriptor = Qnil;
-  ret = TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
-
-  self->def_to_descriptor = rb_hash_new();
-  self->symtab = upb_symtab_new();
-  self->fill_handler_cache =
-      upb_handlercache_new(add_handlers_for_message, (void*)ret);
-  self->pb_serialize_handler_cache = upb_pb_encoder_newcache();
-  self->json_serialize_handler_cache = upb_json_printer_newcache(false);
-  self->json_serialize_handler_preserve_cache =
-      upb_json_printer_newcache(true);
-  self->fill_method_cache = upb_pbcodecache_new(self->fill_handler_cache);
-  self->json_fill_method_cache = upb_json_codecache_new();
-
-  return ret;
-}
-
-void DescriptorPool_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "DescriptorPool", rb_cObject);
-  rb_define_alloc_func(klass, DescriptorPool_alloc);
-  rb_define_method(klass, "build", DescriptorPool_build, -1);
-  rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
-  rb_define_singleton_method(klass, "generated_pool",
-                             DescriptorPool_generated_pool, 0);
-  rb_gc_register_address(&cDescriptorPool);
-  cDescriptorPool = klass;
-
-  rb_gc_register_address(&generated_pool);
-  generated_pool = rb_class_new_instance(0, NULL, klass);
-}
-
-/*
- * call-seq:
- *     DescriptorPool.build(&block)
+ * Creates a new, empty enum descriptor with the given name, and invokes the
+ * block in the context of an EnumBuilderContext on that descriptor. The block
+ * can then call EnumBuilderContext#add_value to define the enum values.
  *
- * Invokes the block with a Builder instance as self. All message and enum types
- * added within the block are committed to the pool atomically, and may refer
- * (co)recursively to each other. The user should call Builder#add_message and
- * Builder#add_enum within the block as appropriate.  This is the recommended,
- * idiomatic way to define new message and enum types.
+ * This is the recommended, idiomatic way to build enum definitions.
  */
-VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
-  VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
+static VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
+  VALUE args[2] = { _self, name };
+  VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
   VALUE block = rb_block_proc();
   rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
-  Builder_build(ctx);
   return Qnil;
 }
 
-/*
- * call-seq:
- *     DescriptorPool.build_file(serialized_file_proto)
- *
- * Adds the given serialized FileDescriptorProto to the pool.
- */
-VALUE DescriptorPool_build(value _self, VALUE serialized_file_proto) {
-  DEFINE_SELF(DescriptorPool, self, _self);
-  Check_Type(serialized_file_proto, T_STRING);
-  upb_arena *arena = upb_arena_new();
-  google_protobuf_FileDescriptorProto* file_proto =
-      google_protobuf_FileDescriptorProto_parse(
-          RSTRING_PTR(serialized_file_proto),
-          RSTRING_LEN(serialized_file_proto), arena);
+static void FileBuilderContext_build(VALUE _self) {
+  FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
+  DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
   upb_status status;
+
+  rewrite_enum_defaults(pool->symtab, self->file_proto);
+  rewrite_names(_self, self->file_proto);
+
   upb_status_clear(&status);
-  if (!upb_symtab_addfile(self->symtab, file_proto, &status)) {
-    rb_raise(cTypeError, "Unable to build file to DescriptorPool: %s",
+  if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
+    rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
              upb_status_errmsg(&status));
   }
-  return Qnil;
 }
 
-/*
- * call-seq:
- *     DescriptorPool.lookup(name) => descriptor
- *
- * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
- * exists with the given name.
- */
-VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
-  DEFINE_SELF(DescriptorPool, self, _self);
-  const char* name_str = get_str(name);
-  const upb_msgdef* msgdef;
-  const upb_enumdef* enumdef;
-
-  msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
-  if (msgdef) {
-    return get_msgdef_obj(_self, msgdef);
-  }
-
-  enumdef = upb_symtab_lookupenum(self->symtab, name_str);
-  if (enumdef) {
-    return get_enumdef_obj(_self, enumdef);
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     DescriptorPool.generated_pool => descriptor_pool
- *
- * Class method that returns the global DescriptorPool. This is a singleton into
- * which generated-code message and enum types are registered. The user may also
- * register types in this pool for convenience so that they do not have to hold
- * a reference to a private pool instance.
- */
-VALUE DescriptorPool_generated_pool(VALUE _self) {
-  return generated_pool;
-}
-
-// -----------------------------------------------------------------------------
-// Descriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
-
-void Descriptor_mark(void* _self) {
-  Descriptor* self = _self;
-  rb_gc_mark(self->klass);
-  rb_gc_mark(self->descriptor_pool);
-  if (self->layout && self->layout->empty_template) {
-    layout_mark(self->layout, self->layout->empty_template);
-  }
-}
-
-void Descriptor_free(void* _self) {
-  Descriptor* self = _self;
-  if (self->layout) {
-    free_layout(self->layout);
-  }
-  xfree(self);
-}
-
-/*
- * call-seq:
- *     Descriptor.new => descriptor
- *
- * Creates a new, empty, message type descriptor. At a minimum, its name must be
- * set before it is added to a pool. It cannot be used to create messages until
- * it is added to a pool, after which it becomes immutable (as part of a
- * finalization process).
- */
-VALUE Descriptor_alloc(VALUE klass) {
-  Descriptor* self = ALLOC(Descriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self);
-  self->msgdef = NULL;
-  self->klass = Qnil;
-  self->descriptor_pool = Qnil;
-  self->layout = NULL;
-  return ret;
-}
-
-void Descriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "Descriptor", rb_cObject);
-  rb_define_alloc_func(klass, Descriptor_alloc);
-  rb_define_method(klass, "initialize", Descriptor_initialize, 3);
-  rb_define_method(klass, "each", Descriptor_each, 0);
-  rb_define_method(klass, "lookup", Descriptor_lookup, 1);
-  rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
-  rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
-  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
-  rb_define_method(klass, "name", Descriptor_name, 0);
-  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
-  rb_include_module(klass, rb_mEnumerable);
-  rb_gc_register_address(&cDescriptor);
-  cDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    Descriptor.new(c_only_cookie, ptr) => Descriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
-                            VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(Descriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *    Descriptor.file_descriptor
- *
- * Returns the FileDescriptor object this message belongs to.
- */
-VALUE Descriptor_file_descriptor(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-  return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
-}
-
-/*
- * call-seq:
- *     Descriptor.name => name
- *
- * Returns the name of this message type as a fully-qualified string (e.g.,
- * My.Package.MessageType).
- */
-VALUE Descriptor_name(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-  return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
-}
-
-/*
- * call-seq:
- *     Descriptor.each(&block)
- *
- * Iterates over fields in this message type, yielding to the block on each one.
- */
-VALUE Descriptor_each(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, self->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
-    rb_yield(obj);
-  }
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     Descriptor.lookup(name) => FieldDescriptor
- *
- * Returns the field descriptor for the field with the given name, if present,
- * or nil if none.
- */
-VALUE Descriptor_lookup(VALUE _self, VALUE name) {
-  DEFINE_SELF(Descriptor, self, _self);
-  const char* s = get_str(name);
-  const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
-  if (field == NULL) {
-    return Qnil;
-  }
-  return get_fielddef_obj(self->descriptor_pool, field);
-}
-
-/*
- * call-seq:
- *     Descriptor.each_oneof(&block) => nil
- *
- * Invokes the given block for each oneof in this message type, passing the
- * corresponding OneofDescriptor.
- */
-VALUE Descriptor_each_oneof(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-
-  upb_msg_oneof_iter it;
-  for (upb_msg_oneof_begin(&it, self->msgdef);
-       !upb_msg_oneof_done(&it);
-       upb_msg_oneof_next(&it)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
-    VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
-    rb_yield(obj);
-  }
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     Descriptor.lookup_oneof(name) => OneofDescriptor
- *
- * Returns the oneof descriptor for the oneof with the given name, if present,
- * or nil if none.
- */
-VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
-  DEFINE_SELF(Descriptor, self, _self);
-  const char* s = get_str(name);
-  const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
-  if (oneof == NULL) {
-    return Qnil;
-  }
-  return get_oneofdef_obj(self->descriptor_pool, oneof);
-}
-
-/*
- * call-seq:
- *     Descriptor.msgclass => message_klass
- *
- * Returns the Ruby class created for this message type.
- */
-VALUE Descriptor_msgclass(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-  if (self->klass == Qnil) {
-    self->klass = build_class_from_descriptor(_self);
-  }
-  return self->klass;
-}
-
-// -----------------------------------------------------------------------------
-// FileDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(FileDescriptor, "Google::Protobuf::FileDescriptor");
-
-void FileDescriptor_mark(void* _self) {
-  FileDescriptor* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void FileDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-VALUE FileDescriptor_alloc(VALUE klass) {
-  FileDescriptor* self = ALLOC(FileDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_FileDescriptor_type, self);
-  self->descriptor_pool = Qnil;
-  self->filedef = NULL;
-  return ret;
-}
-
-/*
- * call-seq:
- *     FileDescriptor.new => file
- *
- * Returns a new file descriptor. The syntax must be set before it's passed
- * to a builder.
- */
-VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(FileDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->filedef = (const upb_filedef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-void FileDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "FileDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, FileDescriptor_alloc);
-  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
-  rb_define_method(klass, "name", FileDescriptor_name, 0);
-  rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
-  rb_gc_register_address(&cFileDescriptor);
-  cFileDescriptor = klass;
-}
-
-/*
- * call-seq:
- *     FileDescriptor.name => name
- *
- * Returns the name of the file.
- */
-VALUE FileDescriptor_name(VALUE _self) {
-  DEFINE_SELF(FileDescriptor, self, _self);
-  const char* name = upb_filedef_name(self->filedef);
-  return name == NULL ? Qnil : rb_str_new2(name);
-}
-
-/*
- * call-seq:
- *     FileDescriptor.syntax => syntax
- *
- * Returns this file descriptors syntax.
- *
- * Valid syntax versions are:
- *     :proto2 or :proto3.
- */
-VALUE FileDescriptor_syntax(VALUE _self) {
-  DEFINE_SELF(FileDescriptor, self, _self);
-
-  switch (upb_filedef_syntax(self->filedef)) {
-    case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3"));
-    case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2"));
-    default: return Qnil;
-  }
-}
-
-// -----------------------------------------------------------------------------
-// FieldDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor");
-
-void FieldDescriptor_mark(void* _self) {
-  FieldDescriptor* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void FieldDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.new => field
- *
- * Returns a new field descriptor. Its name, type, etc. must be set before it is
- * added to a message type.
- */
-VALUE FieldDescriptor_alloc(VALUE klass) {
-  FieldDescriptor* self = ALLOC(FieldDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self);
-  self->fielddef = NULL;
-  return ret;
-}
-
-void FieldDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "FieldDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, FieldDescriptor_alloc);
-  rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
-  rb_define_method(klass, "name", FieldDescriptor_name, 0);
-  rb_define_method(klass, "type", FieldDescriptor_type, 0);
-  rb_define_method(klass, "default", FieldDescriptor_default, 0);
-  rb_define_method(klass, "label", FieldDescriptor_label, 0);
-  rb_define_method(klass, "number", FieldDescriptor_number, 0);
-  rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
-  rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
-  rb_define_method(klass, "has?", FieldDescriptor_has, 1);
-  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
-  rb_define_method(klass, "get", FieldDescriptor_get, 1);
-  rb_define_method(klass, "set", FieldDescriptor_set, 2);
-  rb_gc_register_address(&cFieldDescriptor);
-  cFieldDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.name => name
- *
- * Returns the name of this field.
- */
-VALUE FieldDescriptor_name(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
-}
-
-upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
-  if (TYPE(type) != T_SYMBOL) {
-    rb_raise(rb_eArgError, "Expected symbol for field type.");
-  }
-
-#define CONVERT(upb, ruby)                                           \
-  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
-    return UPB_TYPE_ ## upb;                                         \
-  }
-
-  CONVERT(FLOAT, float);
-  CONVERT(DOUBLE, double);
-  CONVERT(BOOL, bool);
-  CONVERT(STRING, string);
-  CONVERT(BYTES, bytes);
-  CONVERT(MESSAGE, message);
-  CONVERT(ENUM, enum);
-  CONVERT(INT32, int32);
-  CONVERT(INT64, int64);
-  CONVERT(UINT32, uint32);
-  CONVERT(UINT64, uint64);
-
-#undef CONVERT
-
-  rb_raise(rb_eArgError, "Unknown field type.");
-  return 0;
-}
-
-VALUE fieldtype_to_ruby(upb_fieldtype_t type) {
-  switch (type) {
-#define CONVERT(upb, ruby)                                           \
-    case UPB_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
-    CONVERT(FLOAT, float);
-    CONVERT(DOUBLE, double);
-    CONVERT(BOOL, bool);
-    CONVERT(STRING, string);
-    CONVERT(BYTES, bytes);
-    CONVERT(MESSAGE, message);
-    CONVERT(ENUM, enum);
-    CONVERT(INT32, int32);
-    CONVERT(INT64, int64);
-    CONVERT(UINT32, uint32);
-    CONVERT(UINT64, uint64);
-#undef CONVERT
-  }
-  return Qnil;
-}
-
-upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
-  if (TYPE(type) != T_SYMBOL) {
-    rb_raise(rb_eArgError, "Expected symbol for field type.");
-  }
-
-#define CONVERT(upb, ruby)                                           \
-  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
-    return UPB_DESCRIPTOR_TYPE_ ## upb;                              \
-  }
-
-  CONVERT(FLOAT, float);
-  CONVERT(DOUBLE, double);
-  CONVERT(BOOL, bool);
-  CONVERT(STRING, string);
-  CONVERT(BYTES, bytes);
-  CONVERT(MESSAGE, message);
-  CONVERT(GROUP, group);
-  CONVERT(ENUM, enum);
-  CONVERT(INT32, int32);
-  CONVERT(INT64, int64);
-  CONVERT(UINT32, uint32);
-  CONVERT(UINT64, uint64);
-  CONVERT(SINT32, sint32);
-  CONVERT(SINT64, sint64);
-  CONVERT(FIXED32, fixed32);
-  CONVERT(FIXED64, fixed64);
-  CONVERT(SFIXED32, sfixed32);
-  CONVERT(SFIXED64, sfixed64);
-
-#undef CONVERT
-
-  rb_raise(rb_eArgError, "Unknown field type.");
-  return 0;
-}
-
-VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
-  switch (type) {
-#define CONVERT(upb, ruby)                                           \
-    case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
-    CONVERT(FLOAT, float);
-    CONVERT(DOUBLE, double);
-    CONVERT(BOOL, bool);
-    CONVERT(STRING, string);
-    CONVERT(BYTES, bytes);
-    CONVERT(MESSAGE, message);
-    CONVERT(GROUP, group);
-    CONVERT(ENUM, enum);
-    CONVERT(INT32, int32);
-    CONVERT(INT64, int64);
-    CONVERT(UINT32, uint32);
-    CONVERT(UINT64, uint64);
-    CONVERT(SINT32, sint32);
-    CONVERT(SINT64, sint64);
-    CONVERT(FIXED32, fixed32);
-    CONVERT(FIXED64, fixed64);
-    CONVERT(SFIXED32, sfixed32);
-    CONVERT(SFIXED64, sfixed64);
-#undef CONVERT
-  }
-  return Qnil;
-}
-
-VALUE ruby_to_label(VALUE label) {
-  upb_label_t upb_label;
-  bool converted = false;
-
-#define CONVERT(upb, ruby)                                           \
-  if (SYM2ID(label) == rb_intern( # ruby )) {                        \
-    upb_label = UPB_LABEL_ ## upb;                                   \
-    converted = true;                                                \
-  }
-
-  CONVERT(OPTIONAL, optional);
-  CONVERT(REQUIRED, required);
-  CONVERT(REPEATED, repeated);
-
-#undef CONVERT
-
-  if (!converted) {
-    rb_raise(rb_eArgError, "Unknown field label.");
-  }
-
-  return upb_label;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.type => type
- *
- * Returns this field's type, as a Ruby symbol, or nil if not yet set.
- *
- * Valid field types are:
- *     :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
- *     :bytes, :message.
- */
-VALUE FieldDescriptor_type(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.default => default
- *
- * Returns this field's default, as a Ruby object, or nil if not yet set.
- */
-VALUE FieldDescriptor_default(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return layout_get_default(self->fielddef);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.label => label
- *
- * Returns this field's label (i.e., plurality), as a Ruby symbol.
- *
- * Valid field labels are:
- *     :optional, :repeated
- */
-VALUE FieldDescriptor_label(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  switch (upb_fielddef_label(self->fielddef)) {
-#define CONVERT(upb, ruby)                                           \
-    case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
-
-    CONVERT(OPTIONAL, optional);
-    CONVERT(REQUIRED, required);
-    CONVERT(REPEATED, repeated);
-
-#undef CONVERT
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.number => number
- *
- * Returns the tag number for this field.
- */
-VALUE FieldDescriptor_number(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return INT2NUM(upb_fielddef_number(self->fielddef));
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.submsg_name => submsg_name
- *
- * Returns the name of the message or enum type corresponding to this field, if
- * it is a message or enum field (respectively), or nil otherwise. This type
- * name will be resolved within the context of the pool to which the containing
- * message type is added.
- */
-VALUE FieldDescriptor_submsg_name(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  switch (upb_fielddef_type(self->fielddef)) {
-    case UPB_TYPE_ENUM:
-      return rb_str_new2(
-          upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
-    case UPB_TYPE_MESSAGE:
-      return rb_str_new2(
-          upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
-    default:
-      return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.subtype => message_or_enum_descriptor
- *
- * Returns the message or enum descriptor corresponding to this field's type if
- * it is a message or enum field, respectively, or nil otherwise. Cannot be
- * called *until* the containing message type is added to a pool (and thus
- * resolved).
- */
-VALUE FieldDescriptor_subtype(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  switch (upb_fielddef_type(self->fielddef)) {
-    case UPB_TYPE_ENUM:
-      return get_enumdef_obj(self->descriptor_pool,
-                             upb_fielddef_enumsubdef(self->fielddef));
-    case UPB_TYPE_MESSAGE:
-      return get_msgdef_obj(self->descriptor_pool,
-                            upb_fielddef_msgsubdef(self->fielddef));
-    default:
-      return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.get(message) => value
- *
- * Returns the value set for this field on the given message. Raises an
- * exception if message is of the wrong type.
- */
-VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "get method called on wrong message type");
-  }
-  return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.has?(message) => boolean
- *
- * Returns whether the value is set on the given message. Raises an
- * exception when calling with proto syntax 3.
- */
-VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "has method called on wrong message type");
-  } else if (!upb_fielddef_haspresence(self->fielddef)) {
-    rb_raise(rb_eArgError, "does not track presence");
-  }
-
-  return layout_has(msg->descriptor->layout, Message_data(msg), self->fielddef);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.clear(message)
- *
- * Clears the field from the message if it's set.
- */
-VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "has method called on wrong message type");
-  }
-
-  layout_clear(msg->descriptor->layout, Message_data(msg), self->fielddef);
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.set(message, value)
- *
- * Sets the value corresponding to this field to the given value on the given
- * message. Raises an exception if message is of the wrong type. Performs the
- * ordinary type-checks for field setting.
- */
-VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "set method called on wrong message type");
-  }
-  layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value);
-  return Qnil;
-}
-
-// -----------------------------------------------------------------------------
-// OneofDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
-
-void OneofDescriptor_mark(void* _self) {
-  OneofDescriptor* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void OneofDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-/*
- * call-seq:
- *     OneofDescriptor.new => oneof_descriptor
- *
- * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
- * to being added to a message descriptor which is subsequently added to a pool.
- */
-VALUE OneofDescriptor_alloc(VALUE klass) {
-  OneofDescriptor* self = ALLOC(OneofDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
-  self->oneofdef = NULL;
-  self->descriptor_pool = Qnil;
-  return ret;
-}
-
-void OneofDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "OneofDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, OneofDescriptor_alloc);
-  rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
-  rb_define_method(klass, "name", OneofDescriptor_name, 0);
-  rb_define_method(klass, "each", OneofDescriptor_each, 0);
-  rb_include_module(klass, rb_mEnumerable);
-  rb_gc_register_address(&cOneofDescriptor);
-  cOneofDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(OneofDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     OneofDescriptor.name => name
- *
- * Returns the name of this oneof.
- */
-VALUE OneofDescriptor_name(VALUE _self) {
-  DEFINE_SELF(OneofDescriptor, self, _self);
-  return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
-}
-
-/*
- * call-seq:
- *     OneofDescriptor.each(&block) => nil
- *
- * Iterates through fields in this oneof, yielding to the block on each one.
- */
-VALUE OneofDescriptor_each(VALUE _self) {
-  DEFINE_SELF(OneofDescriptor, self, _self);
-  upb_oneof_iter it;
-  for (upb_oneof_begin(&it, self->oneofdef);
-       !upb_oneof_done(&it);
-       upb_oneof_next(&it)) {
-    const upb_fielddef* f = upb_oneof_iter_field(&it);
-    VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
-    rb_yield(obj);
-  }
-  return Qnil;
-}
-
-// -----------------------------------------------------------------------------
-// EnumDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor");
-
-void EnumDescriptor_mark(void* _self) {
-  EnumDescriptor* self = _self;
-  rb_gc_mark(self->module);
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void EnumDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-VALUE EnumDescriptor_alloc(VALUE klass) {
-  EnumDescriptor* self = ALLOC(EnumDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self);
-  self->enumdef = NULL;
-  self->module = Qnil;
-  self->descriptor_pool = Qnil;
-  return ret;
-}
-
-/*
- * call-seq:
- *    EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-void EnumDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "EnumDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, EnumDescriptor_alloc);
-  rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
-  rb_define_method(klass, "name", EnumDescriptor_name, 0);
-  rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
-  rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
-  rb_define_method(klass, "each", EnumDescriptor_each, 0);
-  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
-  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
-  rb_include_module(klass, rb_mEnumerable);
-  rb_gc_register_address(&cEnumDescriptor);
-  cEnumDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    EnumDescriptor.file_descriptor
- *
- * Returns the FileDescriptor object this enum belongs to.
- */
-VALUE EnumDescriptor_file_descriptor(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  return get_filedef_obj(self->descriptor_pool,
-                         upb_enumdef_file(self->enumdef));
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.name => name
- *
- * Returns the name of this enum type.
- */
-VALUE EnumDescriptor_name(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.lookup_name(name) => value
- *
- * Returns the numeric value corresponding to the given key name (as a Ruby
- * symbol), or nil if none.
- */
-VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  const char* name_str= rb_id2name(SYM2ID(name));
-  int32_t val = 0;
-  if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
-    return INT2NUM(val);
-  } else {
-    return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.lookup_value(name) => value
- *
- * Returns the key name (as a Ruby symbol) corresponding to the integer value,
- * or nil if none.
- */
-VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  int32_t val = NUM2INT(number);
-  const char* name = upb_enumdef_iton(self->enumdef, val);
-  if (name != NULL) {
-    return ID2SYM(rb_intern(name));
-  } else {
-    return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.each(&block)
- *
- * Iterates over key => value mappings in this enum's definition, yielding to
- * the block with (key, value) arguments for each one.
- */
-VALUE EnumDescriptor_each(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-
-  upb_enum_iter it;
-  for (upb_enum_begin(&it, self->enumdef);
-       !upb_enum_done(&it);
-       upb_enum_next(&it)) {
-    VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it)));
-    VALUE number = INT2NUM(upb_enum_iter_number(&it));
-    rb_yield_values(2, key, number);
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.enummodule => module
- *
- * Returns the Ruby module corresponding to this enum type.
- */
-VALUE EnumDescriptor_enummodule(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  if (self->module == Qnil) {
-    self->module = build_module_from_enumdesc(_self);
-  }
-  return self->module;
+static void FileBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, FileBuilderContext_alloc);
+  rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
+  rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
+  rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
+  rb_gc_register_address(&cFileBuilderContext);
+  cFileBuilderContext = klass;
 }
 
 // -----------------------------------------------------------------------------
 // MessageBuilderContext.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(MessageBuilderContext,
-    "Google::Protobuf::Internal::MessageBuilderContext");
+typedef struct {
+  google_protobuf_DescriptorProto* msg_proto;
+  VALUE file_builder;
+} MessageBuilderContext;
 
-void MessageBuilderContext_mark(void* _self) {
+static VALUE cMessageBuilderContext = Qnil;
+
+static void MessageBuilderContext_mark(void* _self) {
   MessageBuilderContext* self = _self;
   rb_gc_mark(self->file_builder);
 }
 
-void MessageBuilderContext_free(void* _self) {
-  MessageBuilderContext* self = _self;
-  xfree(self);
-}
+static const rb_data_type_t MessageBuilderContext_type = {
+  "Google::Protobuf::Internal::MessageBuilderContext",
+  {MessageBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE MessageBuilderContext_alloc(VALUE klass) {
-  MessageBuilderContext* self = ALLOC(MessageBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_MessageBuilderContext_type, self);
-  self->file_builder = Qnil;
+static MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE val) {
+  MessageBuilderContext* ret;
+  TypedData_Get_Struct(val, MessageBuilderContext, &MessageBuilderContext_type,
+                       ret);
   return ret;
 }
 
-void MessageBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "MessageBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, MessageBuilderContext_alloc);
-  rb_define_method(klass, "initialize",
-                   MessageBuilderContext_initialize, 2);
-  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
-  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
-  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
-  rb_define_method(klass, "map", MessageBuilderContext_map, -1);
-  rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
-  rb_gc_register_address(&cMessageBuilderContext);
-  cMessageBuilderContext = klass;
+static VALUE MessageBuilderContext_alloc(VALUE klass) {
+  MessageBuilderContext* self = ALLOC(MessageBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &MessageBuilderContext_type, self);
+  self->file_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -1473,10 +1726,9 @@
  * builder context. This class is intended to serve as a DSL context to be used
  * with #instance_eval.
  */
-VALUE MessageBuilderContext_initialize(VALUE _self,
-                                       VALUE _file_builder,
-                                       VALUE name) {
-  DEFINE_SELF(MessageBuilderContext, self, _self);
+static VALUE MessageBuilderContext_initialize(VALUE _self, VALUE _file_builder,
+                                              VALUE name) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
   FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
   google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
 
@@ -1492,8 +1744,9 @@
 
 static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
                              VALUE type, VALUE number, VALUE type_class,
-                             VALUE options, int oneof_index) {
-  DEFINE_SELF(MessageBuilderContext, self, msgbuilder_rb);
+                             VALUE options, int oneof_index,
+                             bool proto3_optional) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(msgbuilder_rb);
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(self->file_builder);
   google_protobuf_FieldDescriptorProto* field_proto;
@@ -1512,6 +1765,10 @@
   google_protobuf_FieldDescriptorProto_set_type(
       field_proto, (int)ruby_to_descriptortype(type));
 
+  if (proto3_optional) {
+    google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true);
+  }
+
   if (type_class != Qnil) {
     Check_Type(type_class, T_STRING);
 
@@ -1536,6 +1793,16 @@
           field_proto,
           FileBuilderContext_strdup(self->file_builder, default_value));
     }
+
+    if (rb_funcall(options, rb_intern("key?"), 1,
+                   ID2SYM(rb_intern("json_name"))) == Qtrue) {
+      VALUE json_name =
+          rb_hash_lookup(options, ID2SYM(rb_intern("json_name")));
+
+      google_protobuf_FieldDescriptorProto_set_json_name(
+          field_proto,
+          FileBuilderContext_strdup(self->file_builder, json_name));
+    }
   }
 
   if (oneof_index >= 0) {
@@ -1544,9 +1811,17 @@
   }
 }
 
+#if RUBY_API_VERSION_CODE >= 20700
 static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
-                           const VALUE* argv) {
-  DEFINE_SELF(MessageBuilderContext, message_builder, _message_builder);
+                           const VALUE* argv, VALUE blockarg) {
+  (void)blockarg;
+#else
+static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
+                           VALUE* argv) {
+#endif
+  MessageBuilderContext* message_builder =
+      ruby_to_MessageBuilderContext(_message_builder);
+>>>>>>> master
   VALUE type_class = rb_ary_entry(types, 2);
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(message_builder->file_builder);
@@ -1597,7 +1872,38 @@
   }
 
   msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
-                   options, -1);
+                   options, -1, false);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     MessageBuilderContext.proto3_optional(name, type, number,
+ *                                           type_class = nil, options = nil)
+ *
+ * Defines a true proto3 optional field (that tracks presence) on this message
+ * type with the given type, tag number, and type class (for message and enum
+ * fields). The type must be a Ruby symbol (as accepted by
+ * FieldDescriptor#type=) and the type_class must be a string, if present (as
+ * accepted by FieldDescriptor#submsg_name=).
+ */
+static VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
+                                                   VALUE _self) {
+  VALUE name, type, number;
+  VALUE type_class, options = Qnil;
+
+  rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
+
+  // Allow passing (name, type, number, options) or
+  // (name, type, number, type_class, options)
+  if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
+    options = type_class;
+    type_class = Qnil;
+  }
+
+  msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
+                   options, -1, true);
 
   return Qnil;
 }
@@ -1616,7 +1922,8 @@
  * completeness. Any attempt to add a message type with required fields to a
  * pool will currently result in an error.
  */
-VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
+static VALUE MessageBuilderContext_required(int argc, VALUE* argv,
+                                            VALUE _self) {
   VALUE name, type, number;
   VALUE type_class, options = Qnil;
 
@@ -1630,7 +1937,7 @@
   }
 
   msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class,
-                   options, -1);
+                   options, -1, false);
 
   return Qnil;
 }
@@ -1644,19 +1951,22 @@
  * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
  * string, if present (as accepted by FieldDescriptor#submsg_name=).
  */
-VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
-  VALUE name, type, number, type_class;
+static VALUE MessageBuilderContext_repeated(int argc, VALUE* argv,
+                                            VALUE _self) {
+  VALUE name, type, number;
+  VALUE type_class, options = Qnil;
 
-  if (argc < 3) {
-    rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+  rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
+
+  // Allow passing (name, type, number, options) or
+  // (name, type, number, type_class, options)
+  if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
+    options = type_class;
+    type_class = Qnil;
   }
-  name = argv[0];
-  type = argv[1];
-  number = argv[2];
-  type_class = (argc > 3) ? argv[3] : Qnil;
 
   msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class,
-                   Qnil, -1);
+                   options, -1, false);
 
   return Qnil;
 }
@@ -1673,8 +1983,8 @@
  * type_class must be a string, if present (as accepted by
  * FieldDescriptor#submsg_name=).
  */
-VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
-  DEFINE_SELF(MessageBuilderContext, self, _self);
+static VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
   VALUE name, key_type, value_type, number, type_class;
   VALUE mapentry_desc_name;
   FileBuilderContext* file_builder;
@@ -1703,14 +2013,6 @@
 
   file_builder = ruby_to_FileBuilderContext(self->file_builder);
 
-  // TODO(haberman): remove this restriction, maps are supported in proto2.
-  if (upb_strview_eql(
-          google_protobuf_FileDescriptorProto_syntax(file_builder->file_proto),
-          upb_strview_makez("proto2"))) {
-    rb_raise(rb_eArgError,
-             "Cannot add a native map field using proto2 syntax.");
-  }
-
   // Create a new message descriptor for the map entry message, and create a
   // repeated submessage field here with that type.
   msg_name = google_protobuf_DescriptorProto_name(self->msg_proto);
@@ -1754,8 +2056,8 @@
  *
  * This is the recommended, idiomatic way to build oneof definitions.
  */
-VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
-  DEFINE_SELF(MessageBuilderContext, self, _self);
+static VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
   size_t oneof_count;
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(self->file_builder);
@@ -1781,40 +2083,107 @@
   return Qnil;
 }
 
+static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
+  FileBuilderContext* file_context =
+      ruby_to_FileBuilderContext(self->file_builder);
+  size_t field_count, oneof_count;
+  google_protobuf_FieldDescriptorProto** fields =
+      google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count);
+  const google_protobuf_OneofDescriptorProto*const* oneofs =
+      google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
+  VALUE names = rb_hash_new();
+  VALUE underscore = rb_str_new2("_");
+  size_t i;
+
+  // We have to build a set of all names, to ensure that synthetic oneofs are
+  // not creating conflicts.
+  for (i = 0; i < field_count; i++) {
+    upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]);
+    rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
+  }
+  for (i = 0; i < oneof_count; i++) {
+    upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]);
+    rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
+  }
+
+  for (i = 0; i < field_count; i++) {
+    google_protobuf_OneofDescriptorProto* oneof_proto;
+    VALUE oneof_name;
+    upb_strview field_name;
+
+    if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) {
+      continue;
+    }
+
+    // Prepend '_' until we are no longer conflicting.
+    field_name = google_protobuf_FieldDescriptorProto_name(fields[i]);
+    oneof_name = rb_str_new(field_name.data, field_name.size);
+    while (rb_hash_lookup(names, oneof_name) != Qnil) {
+      oneof_name = rb_str_plus(underscore, oneof_name);
+    }
+
+    rb_hash_aset(names, oneof_name, Qtrue);
+    google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i],
+                                                         oneof_count++);
+    oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
+        self->msg_proto, file_context->arena);
+    google_protobuf_OneofDescriptorProto_set_name(
+        oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name));
+  }
+}
+
+static void MessageBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "MessageBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, MessageBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   MessageBuilderContext_initialize, 2);
+  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
+  rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
+  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
+  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
+  rb_define_method(klass, "map", MessageBuilderContext_map, -1);
+  rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
+  rb_gc_register_address(&cMessageBuilderContext);
+  cMessageBuilderContext = klass;
+}
+
 // -----------------------------------------------------------------------------
 // OneofBuilderContext.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(OneofBuilderContext,
-    "Google::Protobuf::Internal::OneofBuilderContext");
+typedef struct {
+  int oneof_index;
+  VALUE message_builder;
+} OneofBuilderContext;
+
+static VALUE cOneofBuilderContext = Qnil;
 
 void OneofBuilderContext_mark(void* _self) {
   OneofBuilderContext* self = _self;
   rb_gc_mark(self->message_builder);
 }
 
-void OneofBuilderContext_free(void* _self) {
-  xfree(_self);
-}
+static const rb_data_type_t OneofBuilderContext_type = {
+  "Google::Protobuf::Internal::OneofBuilderContext",
+  {OneofBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE OneofBuilderContext_alloc(VALUE klass) {
-  OneofBuilderContext* self = ALLOC(OneofBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_OneofBuilderContext_type, self);
-  self->oneof_index = 0;
-  self->message_builder = Qnil;
+static OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE val) {
+  OneofBuilderContext* ret;
+  TypedData_Get_Struct(val, OneofBuilderContext, &OneofBuilderContext_type,
+                       ret);
   return ret;
 }
 
-void OneofBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "OneofBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, OneofBuilderContext_alloc);
-  rb_define_method(klass, "initialize",
-                   OneofBuilderContext_initialize, 2);
-  rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
-  rb_gc_register_address(&cOneofBuilderContext);
-  cOneofBuilderContext = klass;
+static VALUE OneofBuilderContext_alloc(VALUE klass) {
+  OneofBuilderContext* self = ALLOC(OneofBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &OneofBuilderContext_type, self);
+  self->oneof_index = 0;
+  self->message_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -1825,10 +2194,9 @@
  * builder context. This class is intended to serve as a DSL context to be used
  * with #instance_eval.
  */
-VALUE OneofBuilderContext_initialize(VALUE _self,
-                                     VALUE oneof_index,
-                                     VALUE message_builder) {
-  DEFINE_SELF(OneofBuilderContext, self, _self);
+static VALUE OneofBuilderContext_initialize(VALUE _self, VALUE oneof_index,
+                                            VALUE message_builder) {
+  OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
   self->oneof_index = NUM2INT(oneof_index);
   self->message_builder = message_builder;
   return Qnil;
@@ -1844,52 +2212,64 @@
  * (as accepted by FieldDescriptor#type=) and the type_class must be a string,
  * if present (as accepted by FieldDescriptor#submsg_name=).
  */
-VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
-  DEFINE_SELF(OneofBuilderContext, self, _self);
+static VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
+  OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
   VALUE name, type, number;
   VALUE type_class, options = Qnil;
 
   rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
 
   msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type,
-                   number, type_class, options, self->oneof_index);
+                   number, type_class, options, self->oneof_index, false);
 
   return Qnil;
 }
 
+static void OneofBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, OneofBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   OneofBuilderContext_initialize, 2);
+  rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
+  rb_gc_register_address(&cOneofBuilderContext);
+  cOneofBuilderContext = klass;
+}
+
 // -----------------------------------------------------------------------------
 // EnumBuilderContext.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(EnumBuilderContext,
-    "Google::Protobuf::Internal::EnumBuilderContext");
+typedef struct {
+  google_protobuf_EnumDescriptorProto* enum_proto;
+  VALUE file_builder;
+} EnumBuilderContext;
+
+static VALUE cEnumBuilderContext = Qnil;
 
 void EnumBuilderContext_mark(void* _self) {
   EnumBuilderContext* self = _self;
   rb_gc_mark(self->file_builder);
 }
 
-void EnumBuilderContext_free(void* _self) {
-  xfree(_self);
-}
+static const rb_data_type_t EnumBuilderContext_type = {
+  "Google::Protobuf::Internal::EnumBuilderContext",
+  {EnumBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE EnumBuilderContext_alloc(VALUE klass) {
-  EnumBuilderContext* self = ALLOC(EnumBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_EnumBuilderContext_type, self);
-  self->enum_proto = NULL;
-  self->file_builder = Qnil;
+static EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE val) {
+  EnumBuilderContext* ret;
+  TypedData_Get_Struct(val, EnumBuilderContext, &EnumBuilderContext_type, ret);
   return ret;
 }
 
-void EnumBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "EnumBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, EnumBuilderContext_alloc);
-  rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
-  rb_define_method(klass, "value", EnumBuilderContext_value, 2);
-  rb_gc_register_address(&cEnumBuilderContext);
-  cEnumBuilderContext = klass;
+static VALUE EnumBuilderContext_alloc(VALUE klass) {
+  EnumBuilderContext* self = ALLOC(EnumBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &EnumBuilderContext_type, self);
+  self->enum_proto = NULL;
+  self->file_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -1899,9 +2279,9 @@
  * Create a new builder context around the given enum descriptor. This class is
  * intended to serve as a DSL context to be used with #instance_eval.
  */
-VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
-                                    VALUE name) {
-  DEFINE_SELF(EnumBuilderContext, self, _self);
+static VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
+                                           VALUE name) {
+  EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
   FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
   google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
 
@@ -1922,8 +2302,8 @@
  * Adds the given name => number mapping to the enum type. Name must be a Ruby
  * symbol.
  */
-VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
-  DEFINE_SELF(EnumBuilderContext, self, _self);
+static VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
+  EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
   FileBuilderContext* file_builder =
       ruby_to_FileBuilderContext(self->file_builder);
   google_protobuf_EnumValueDescriptorProto* enum_value;
@@ -1939,193 +2319,51 @@
   return Qnil;
 }
 
-
-// -----------------------------------------------------------------------------
-// FileBuilderContext.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(FileBuilderContext,
-             "Google::Protobuf::Internal::FileBuilderContext");
-
-void FileBuilderContext_mark(void* _self) {
-  FileBuilderContext* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void FileBuilderContext_free(void* _self) {
-  FileBuilderContext* self = _self;
-  upb_arena_free(self->arena);
-  xfree(self);
-}
-
-upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
-  DEFINE_SELF(FileBuilderContext, self, _self);
-  upb_strview ret;
-  char *data;
-
-  ret.size = strlen(str);
-  data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
-  ret.data = data;
-  memcpy(data, str, ret.size);
-  /* Null-terminate required by rewrite_enum_defaults() above. */
-  data[ret.size] = '\0';
-  return ret;
-}
-
-upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
-  return FileBuilderContext_strdup2(_self, get_str(rb_str));
-}
-
-upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
-  Check_Type(rb_sym, T_SYMBOL);
-  return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
-}
-
-VALUE FileBuilderContext_alloc(VALUE klass) {
-  FileBuilderContext* self = ALLOC(FileBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_FileBuilderContext_type, self);
-  self->arena = upb_arena_new();
-  self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
-  self->descriptor_pool = Qnil;
-  return ret;
-}
-
-void FileBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, FileBuilderContext_alloc);
-  rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
-  rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
-  rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
-  rb_gc_register_address(&cFileBuilderContext);
-  cFileBuilderContext = klass;
-}
-
-/*
- * call-seq:
- *     FileBuilderContext.new(descriptor_pool) => context
- *
- * Create a new file builder context for the given file descriptor and
- * builder context. This class is intended to serve as a DSL context to be used
- * with #instance_eval.
- */
-VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
-                                    VALUE name, VALUE options) {
-  DEFINE_SELF(FileBuilderContext, self, _self);
-  self->descriptor_pool = descriptor_pool;
-
-  google_protobuf_FileDescriptorProto_set_name(
-      self->file_proto, FileBuilderContext_strdup(_self, name));
-
-  // Default syntax for Ruby is proto3.
-  google_protobuf_FileDescriptorProto_set_syntax(
-      self->file_proto,
-      FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
-
-  if (options != Qnil) {
-    VALUE syntax;
-
-    Check_Type(options, T_HASH);
-    syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
-
-    if (syntax != Qnil) {
-      VALUE syntax_str;
-
-      Check_Type(syntax, T_SYMBOL);
-      syntax_str = rb_id2str(SYM2ID(syntax));
-      google_protobuf_FileDescriptorProto_set_syntax(
-          self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
-    }
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FileBuilderContext.add_message(name, &block)
- *
- * Creates a new, empty descriptor with the given name, and invokes the block in
- * the context of a MessageBuilderContext on that descriptor. The block can then
- * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
- * methods to define the message fields.
- *
- * This is the recommended, idiomatic way to build message definitions.
- */
-VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
-  VALUE args[2] = { _self, name };
-  VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
-  VALUE block = rb_block_proc();
-  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FileBuilderContext.add_enum(name, &block)
- *
- * Creates a new, empty enum descriptor with the given name, and invokes the
- * block in the context of an EnumBuilderContext on that descriptor. The block
- * can then call EnumBuilderContext#add_value to define the enum values.
- *
- * This is the recommended, idiomatic way to build enum definitions.
- */
-VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
-  VALUE args[2] = { _self, name };
-  VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
-  VALUE block = rb_block_proc();
-  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
-  return Qnil;
-}
-
-void FileBuilderContext_build(VALUE _self) {
-  DEFINE_SELF(FileBuilderContext, self, _self);
-  DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
-  upb_status status;
-
-  rewrite_enum_defaults(pool->symtab, self->file_proto);
-  rewrite_names(_self, self->file_proto);
-
-  upb_status_clear(&status);
-  if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
-    rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
-             upb_status_errmsg(&status));
-  }
+static void EnumBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "EnumBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, EnumBuilderContext_alloc);
+  rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
+  rb_define_method(klass, "value", EnumBuilderContext_value, 2);
+  rb_gc_register_address(&cEnumBuilderContext);
+  cEnumBuilderContext = klass;
 }
 
 // -----------------------------------------------------------------------------
 // Builder.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
+typedef struct {
+  VALUE descriptor_pool;
+  VALUE default_file_builder;
+} Builder;
 
-void Builder_mark(void* _self) {
+static VALUE cBuilder = Qnil;
+
+static void Builder_mark(void* _self) {
   Builder* self = _self;
   rb_gc_mark(self->descriptor_pool);
   rb_gc_mark(self->default_file_builder);
 }
 
-void Builder_free(void* _self) {
-  xfree(_self);
-}
+static const rb_data_type_t Builder_type = {
+  "Google::Protobuf::Internal::Builder",
+  {Builder_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE Builder_alloc(VALUE klass) {
-  Builder* self = ALLOC(Builder);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_Builder_type, self);
-  self->descriptor_pool = Qnil;
-  self->default_file_builder = Qnil;
+static Builder* ruby_to_Builder(VALUE val) {
+  Builder* ret;
+  TypedData_Get_Struct(val, Builder, &Builder_type, ret);
   return ret;
 }
 
-void Builder_register(VALUE module) {
-  VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
-  rb_define_alloc_func(klass, Builder_alloc); 
-  rb_define_method(klass, "initialize", Builder_initialize, 1);
-  rb_define_method(klass, "add_file", Builder_add_file, -1);
-  rb_define_method(klass, "add_message", Builder_add_message, 1);
-  rb_define_method(klass, "add_enum", Builder_add_enum, 1);
-  rb_gc_register_address(&cBuilder);
-  cBuilder = klass;
+static VALUE Builder_alloc(VALUE klass) {
+  Builder* self = ALLOC(Builder);
+  VALUE ret = TypedData_Wrap_Struct(klass, &Builder_type, self);
+  self->descriptor_pool = Qnil;
+  self->default_file_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -2136,8 +2374,8 @@
  * descriptors and atomically register them into a pool in a way that allows for
  * (co)recursive type references.
  */
-VALUE Builder_initialize(VALUE _self, VALUE pool) {
-  DEFINE_SELF(Builder, self, _self);
+static VALUE Builder_initialize(VALUE _self, VALUE pool) {
+  Builder* self = ruby_to_Builder(_self);
   self->descriptor_pool = pool;
   self->default_file_builder = Qnil;  // Created lazily if needed.
   return Qnil;
@@ -2154,8 +2392,8 @@
  *
  * This is the recommended, idiomatic way to build file descriptors.
  */
-VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
-  DEFINE_SELF(Builder, self, _self);
+static VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
+  Builder* self = ruby_to_Builder(_self);
   VALUE name, options;
   VALUE ctx;
   VALUE block;
@@ -2175,7 +2413,7 @@
 }
 
 static VALUE Builder_get_default_file(VALUE _self) {
-  DEFINE_SELF(Builder, self, _self);
+  Builder* self = ruby_to_Builder(_self);
 
   /* Lazily create only if legacy builder-level methods are called. */
   if (self->default_file_builder == Qnil) {
@@ -2199,7 +2437,7 @@
  * files generated by protoc which don't add messages within "add_file" block.
  * Descriptors created this way get assigned to a default empty FileDescriptor.
  */
-VALUE Builder_add_message(VALUE _self, VALUE name) {
+static VALUE Builder_add_message(VALUE _self, VALUE name) {
   VALUE file_builder = Builder_get_default_file(_self);
   rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name,
                         rb_block_proc());
@@ -2218,7 +2456,7 @@
  * Enum descriptors created this way get assigned to a default empty
  * FileDescriptor.
  */
-VALUE Builder_add_enum(VALUE _self, VALUE name) {
+static VALUE Builder_add_enum(VALUE _self, VALUE name) {
   VALUE file_builder = Builder_get_default_file(_self);
   rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name,
                         rb_block_proc());
@@ -2227,8 +2465,8 @@
 
 /* This method is hidden from Ruby, and only called directly from
  * DescriptorPool_build(). */
-VALUE Builder_build(VALUE _self) {
-  DEFINE_SELF(Builder, self, _self);
+static VALUE Builder_build(VALUE _self) {
+  Builder* self = ruby_to_Builder(_self);
 
   if (self->default_file_builder != Qnil) {
     FileBuilderContext_build(self->default_file_builder);
@@ -2238,8 +2476,19 @@
   return Qnil;
 }
 
+static void Builder_register(VALUE module) {
+  VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
+  rb_define_alloc_func(klass, Builder_alloc); 
+  rb_define_method(klass, "initialize", Builder_initialize, 1);
+  rb_define_method(klass, "add_file", Builder_add_file, -1);
+  rb_define_method(klass, "add_message", Builder_add_message, 1);
+  rb_define_method(klass, "add_enum", Builder_add_enum, 1);
+  rb_gc_register_address(&cBuilder);
+  cBuilder = klass;
+}
+
 static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
-  DEFINE_SELF(DescriptorPool, descriptor_pool, _descriptor_pool);
+  DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
   VALUE key = ULL2NUM((intptr_t)ptr);
   VALUE def;
 
@@ -2254,48 +2503,111 @@
     VALUE args[3] = { c_only_cookie, _descriptor_pool, key };
     def = rb_class_new_instance(3, args, klass);
     rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);
-
-    // For message defs, we now eagerly get/create descriptors for all
-    // submessages.  We will need these anyway to parse or serialize this
-    // message type.  But more importantly, we must do this now so that
-    // add_handlers_for_message() (which calls get_msgdef_obj()) does *not*
-    // need to create a Ruby object or insert into a Ruby Hash.  We need to
-    // avoid triggering GC, which can switch Ruby threads and re-enter our
-    // C extension from a different thread.  This wreaks havoc on our state
-    // if we were in the middle of building handlers.
-    if (klass == cDescriptor) {
-      const upb_msgdef *m = ptr;
-      upb_msg_field_iter it;
-      for (upb_msg_field_begin(&it, m);
-           !upb_msg_field_done(&it);
-           upb_msg_field_next(&it)) {
-        const upb_fielddef* f = upb_msg_iter_field(&it);
-        if (upb_fielddef_issubmsg(f)) {
-          get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f));
-        }
-      }
-    }
   }
 
   return def;
 }
 
-VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
+static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
   return get_def_obj(descriptor_pool, def, cDescriptor);
 }
 
-VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
+static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
   return get_def_obj(descriptor_pool, def, cEnumDescriptor);
 }
 
-VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
+static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
   return get_def_obj(descriptor_pool, def, cFieldDescriptor);
 }
 
-VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
+static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
   return get_def_obj(descriptor_pool, def, cFileDescriptor);
 }
 
-VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
+static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
   return get_def_obj(descriptor_pool, def, cOneofDescriptor);
 }
+
+// -----------------------------------------------------------------------------
+// Shared functions
+// -----------------------------------------------------------------------------
+
+// Functions exposed to other modules in defs.h.
+
+VALUE Descriptor_DefToClass(const upb_msgdef *m) {
+  const upb_symtab *symtab = upb_filedef_symtab(upb_msgdef_file(m));
+  VALUE pool = ObjectCache_Get(symtab);
+  PBRUBY_ASSERT(pool != Qnil);
+  VALUE desc_rb = get_msgdef_obj(pool, m);
+  const Descriptor* desc = ruby_to_Descriptor(desc_rb);
+  return desc->klass;
+}
+
+const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb) {
+  const Descriptor* desc = ruby_to_Descriptor(desc_rb);
+  return desc->msgdef;
+}
+
+VALUE TypeInfo_InitArg(int argc, VALUE *argv, int skip_arg) {
+  if (argc > skip_arg) {
+    if (argc > 1 + skip_arg) {
+      rb_raise(rb_eArgError, "Expected a maximum of %d arguments.", skip_arg + 1);
+    }
+    return argv[skip_arg];
+  } else {
+    return Qnil;
+  }
+}
+
+TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
+                            VALUE* type_class, VALUE* init_arg) {
+  TypeInfo ret = {ruby_to_fieldtype(argv[skip_arg])};
+
+  if (ret.type == UPB_TYPE_MESSAGE || ret.type == UPB_TYPE_ENUM) {
+    *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 2);
+
+    if (argc < 2 + skip_arg) {
+      rb_raise(rb_eArgError, "Expected at least %d arguments for message/enum.",
+               2 + skip_arg);
+    }
+
+    VALUE klass = argv[1 + skip_arg];
+    VALUE desc = MessageOrEnum_GetDescriptor(klass);
+    *type_class = klass;
+
+    if (desc == Qnil) {
+      rb_raise(rb_eArgError,
+               "Type class has no descriptor. Please pass a "
+               "class or enum as returned by the DescriptorPool.");
+    }
+
+    if (ret.type == UPB_TYPE_MESSAGE) {
+      ret.def.msgdef = ruby_to_Descriptor(desc)->msgdef;
+      Message_CheckClass(klass);
+    } else {
+      PBRUBY_ASSERT(ret.type == UPB_TYPE_ENUM);
+      ret.def.enumdef = ruby_to_EnumDescriptor(desc)->enumdef;
+    }
+  } else {
+    *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 1);
+  }
+
+  return ret;
+}
+
+void Defs_register(VALUE module) {
+  DescriptorPool_register(module);
+  Descriptor_register(module);
+  FileDescriptor_register(module);
+  FieldDescriptor_register(module);
+  OneofDescriptor_register(module);
+  EnumDescriptor_register(module);
+  FileBuilderContext_register(module);
+  MessageBuilderContext_register(module);
+  OneofBuilderContext_register(module);
+  EnumBuilderContext_register(module);
+  Builder_register(module);
+
+  rb_gc_register_address(&c_only_cookie);
+  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
+}
diff --git a/ruby/ext/google/protobuf_c/defs.h b/ruby/ext/google/protobuf_c/defs.h
new file mode 100644
index 0000000..97a94bb
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/defs.h
@@ -0,0 +1,107 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_DEFS_H_
+#define RUBY_PROTOBUF_DEFS_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// -----------------------------------------------------------------------------
+// TypeInfo
+// -----------------------------------------------------------------------------
+
+// This bundles a upb_fieldtype_t and msgdef/enumdef when appropriate. This is
+// convenient for functions that need type information but cannot necessarily
+// assume a upb_fielddef will be available.
+//
+// For example, Google::Protobuf::Map and Google::Protobuf::RepeatedField can
+// be constructed with type information alone:
+//
+//   # RepeatedField will internally store the type information in a TypeInfo.
+//   Google::Protobuf::RepeatedField.new(:message, FooMessage)
+
+typedef struct {
+  upb_fieldtype_t type;
+  union {
+    const upb_msgdef* msgdef;      // When type == UPB_TYPE_MESSAGE
+    const upb_enumdef* enumdef;    // When type == UPB_TYPE_ENUM
+  } def;
+} TypeInfo;
+
+static inline TypeInfo TypeInfo_get(const upb_fielddef *f) {
+  TypeInfo ret = {upb_fielddef_type(f), {NULL}};
+  switch (ret.type) {
+    case UPB_TYPE_MESSAGE:
+      ret.def.msgdef = upb_fielddef_msgsubdef(f);
+      break;
+    case UPB_TYPE_ENUM:
+      ret.def.enumdef = upb_fielddef_enumsubdef(f);
+      break;
+    default:
+      break;
+  }
+  return ret;
+}
+
+TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
+                            VALUE* type_class, VALUE* init_arg);
+
+static inline TypeInfo TypeInfo_from_type(upb_fieldtype_t type) {
+  TypeInfo ret = {type};
+  assert(type != UPB_TYPE_MESSAGE && type != UPB_TYPE_ENUM);
+  return ret;
+}
+
+// -----------------------------------------------------------------------------
+// Other utilities
+// -----------------------------------------------------------------------------
+
+VALUE Descriptor_DefToClass(const upb_msgdef *m);
+
+// Returns the underlying msgdef, enumdef, or symtab (respectively) for the
+// given Descriptor, EnumDescriptor, or DescriptorPool Ruby object.
+const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb);
+const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb);
+const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb);
+
+// Returns a upb field type for the given Ruby symbol
+// (eg. :float => UPB_TYPE_FLOAT).
+upb_fieldtype_t ruby_to_fieldtype(VALUE type);
+
+// The singleton generated pool (a DescriptorPool object).
+extern VALUE generated_pool;
+
+// Call at startup to register all types in this module.
+void Defs_register(VALUE module);
+
+#endif  // RUBY_PROTOBUF_DEFS_H_
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
deleted file mode 100644
index 4a1d724..0000000
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ /dev/null
@@ -1,1795 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2014 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "protobuf.h"
-
-VALUE initialize_rb_class_with_no_args(VALUE klass) {
-  return rb_funcall(klass, rb_intern("new"), 0);
-}
-
-// This function is equivalent to rb_str_cat(), but unlike the real
-// rb_str_cat(), it doesn't leak memory in some versions of Ruby.
-// For more information, see:
-//   https://bugs.ruby-lang.org/issues/11328
-VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
-  char *p;
-  size_t oldlen = RSTRING_LEN(rb_str);
-  rb_str_modify_expand(rb_str, len);
-  p = RSTRING_PTR(rb_str);
-  memcpy(p + oldlen, str, len);
-  rb_str_set_len(rb_str, oldlen + len);
-  return rb_str;
-}
-
-bool is_wrapper(const upb_msgdef* m) {
-  switch (upb_msgdef_wellknowntype(m)) {
-    case UPB_WELLKNOWN_DOUBLEVALUE:
-    case UPB_WELLKNOWN_FLOATVALUE:
-    case UPB_WELLKNOWN_INT64VALUE:
-    case UPB_WELLKNOWN_UINT64VALUE:
-    case UPB_WELLKNOWN_INT32VALUE:
-    case UPB_WELLKNOWN_UINT32VALUE:
-    case UPB_WELLKNOWN_STRINGVALUE:
-    case UPB_WELLKNOWN_BYTESVALUE:
-    case UPB_WELLKNOWN_BOOLVALUE:
-      return true;
-    default:
-      return false;
-  }
-}
-
-// The code below also comes from upb's prototype Ruby binding, developed by
-// haberman@.
-
-/* stringsink *****************************************************************/
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
-  stringsink *sink = _sink;
-  sink->len = 0;
-  return sink;
-}
-
-static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
-                                size_t len, const upb_bufhandle *handle) {
-  stringsink *sink = _sink;
-  size_t new_size = sink->size;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  while (sink->len + len > new_size) {
-    new_size *= 2;
-  }
-
-  if (new_size != sink->size) {
-    sink->ptr = realloc(sink->ptr, new_size);
-    sink->size = new_size;
-  }
-
-  memcpy(sink->ptr + sink->len, ptr, len);
-  sink->len += len;
-
-  return len;
-}
-
-void stringsink_init(stringsink *sink) {
-  upb_byteshandler_init(&sink->handler);
-  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
-  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
-  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
-  sink->size = 32;
-  sink->ptr = malloc(sink->size);
-  sink->len = 0;
-}
-
-void stringsink_uninit(stringsink *sink) {
-  free(sink->ptr);
-}
-
-// -----------------------------------------------------------------------------
-// Parsing.
-// -----------------------------------------------------------------------------
-
-#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
-
-typedef struct {
-  size_t ofs;
-  int32_t hasbit;
-} field_handlerdata_t;
-
-// Creates a handlerdata that contains the offset and the hasbit for the field
-static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit) {
-  field_handlerdata_t *hd = ALLOC(field_handlerdata_t);
-  hd->ofs = ofs;
-  hd->hasbit = hasbit;
-  upb_handlers_addcleanup(h, hd, xfree);
-  return hd;
-}
-
-typedef struct {
-  size_t ofs;
-  int32_t hasbit;
-  upb_fieldtype_t wrapped_type;  // Only for wrappers.
-  VALUE subklass;
-} submsg_handlerdata_t;
-
-// Creates a handlerdata that contains offset and submessage type information.
-static const void *newsubmsghandlerdata(upb_handlers* h,
-                                        const upb_fielddef *f,
-                                        uint32_t ofs,
-                                        int32_t hasbit,
-                                        VALUE subklass) {
-  submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
-  const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
-  hd->ofs = ofs;
-  hd->hasbit = hasbit;
-  hd->subklass = subklass;
-  upb_handlers_addcleanup(h, hd, xfree);
-  if (is_wrapper(subm)) {
-    const upb_fielddef *value_f = upb_msgdef_itof(subm, 1);
-    hd->wrapped_type = upb_fielddef_type(value_f);
-  }
-  return hd;
-}
-
-typedef struct {
-  size_t ofs;              // union data slot
-  size_t case_ofs;         // oneof_case field
-  uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
-  VALUE subklass;
-} oneof_handlerdata_t;
-
-static const void *newoneofhandlerdata(upb_handlers *h,
-                                       uint32_t ofs,
-                                       uint32_t case_ofs,
-                                       const upb_fielddef *f,
-                                       const Descriptor* desc) {
-  oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
-  hd->ofs = ofs;
-  hd->case_ofs = case_ofs;
-  // We reuse the field tag number as a oneof union discriminant tag. Note that
-  // we don't expose these numbers to the user, so the only requirement is that
-  // we have some unique ID for each union case/possibility. The field tag
-  // numbers are already present and are easy to use so there's no reason to
-  // create a separate ID space. In addition, using the field tag number here
-  // lets us easily look up the field in the oneof accessor.
-  hd->oneof_case_num = upb_fielddef_number(f);
-  if (is_value_field(f)) {
-    hd->oneof_case_num |= ONEOF_CASE_MASK;
-  }
-  hd->subklass = field_type_class(desc->layout, f);
-  upb_handlers_addcleanup(h, hd, xfree);
-  return hd;
-}
-
-// A handler that starts a repeated field.  Gets the Repeated*Field instance for
-// this field (such an instance always exists even in an empty message).
-static void *startseq_handler(void* closure, const void* hd) {
-  MessageHeader* msg = closure;
-  const size_t *ofs = hd;
-  return (void*)DEREF(msg, *ofs, VALUE);
-}
-
-// Handlers that append primitive values to a repeated field.
-#define DEFINE_APPEND_HANDLER(type, ctype)                 \
-  static bool append##type##_handler(void *closure, const void *hd, \
-                                     ctype val) {                   \
-    VALUE ary = (VALUE)closure;                                     \
-    RepeatedField_push_native(ary, &val);                           \
-    return true;                                                    \
-  }
-
-DEFINE_APPEND_HANDLER(bool,   bool)
-DEFINE_APPEND_HANDLER(int32,  int32_t)
-DEFINE_APPEND_HANDLER(uint32, uint32_t)
-DEFINE_APPEND_HANDLER(float,  float)
-DEFINE_APPEND_HANDLER(int64,  int64_t)
-DEFINE_APPEND_HANDLER(uint64, uint64_t)
-DEFINE_APPEND_HANDLER(double, double)
-
-// Appends a string to a repeated field.
-static void* appendstr_handler(void *closure,
-                               const void *hd,
-                               size_t size_hint) {
-  VALUE ary = (VALUE)closure;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyStringUtf8Encoding);
-  RepeatedField_push_native(ary, &str);
-  return (void*)str;
-}
-
-static void set_hasbit(void *closure, int32_t hasbit) {
-  if (hasbit > 0) {
-    uint8_t* storage = closure;
-    storage[hasbit/8] |= 1 << (hasbit % 8);
-  }
-}
-
-// Appends a 'bytes' string to a repeated field.
-static void* appendbytes_handler(void *closure,
-                                 const void *hd,
-                                 size_t size_hint) {
-  VALUE ary = (VALUE)closure;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyString8bitEncoding);
-  RepeatedField_push_native(ary, &str);
-  return (void*)str;
-}
-
-// Sets a non-repeated string field in a message.
-static void* str_handler(void *closure,
-                         const void *hd,
-                         size_t size_hint) {
-  MessageHeader* msg = closure;
-  const field_handlerdata_t *fieldhandler = hd;
-
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyStringUtf8Encoding);
-  DEREF(msg, fieldhandler->ofs, VALUE) = str;
-  set_hasbit(closure, fieldhandler->hasbit);
-  return (void*)str;
-}
-
-// Sets a non-repeated 'bytes' field in a message.
-static void* bytes_handler(void *closure,
-                           const void *hd,
-                           size_t size_hint) {
-  MessageHeader* msg = closure;
-  const field_handlerdata_t *fieldhandler = hd;
-
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyString8bitEncoding);
-  DEREF(msg, fieldhandler->ofs, VALUE) = str;
-  set_hasbit(closure, fieldhandler->hasbit);
-  return (void*)str;
-}
-
-static size_t stringdata_handler(void* closure, const void* hd,
-                                 const char* str, size_t len,
-                                 const upb_bufhandle* handle) {
-  VALUE rb_str = (VALUE)closure;
-  noleak_rb_str_cat(rb_str, str, len);
-  return len;
-}
-
-static bool stringdata_end_handler(void* closure, const void* hd) {
-  VALUE rb_str = (VALUE)closure;
-  rb_obj_freeze(rb_str);
-  return true;
-}
-
-static bool appendstring_end_handler(void* closure, const void* hd) {
-  VALUE rb_str = (VALUE)closure;
-  rb_obj_freeze(rb_str);
-  return true;
-}
-
-// Appends a submessage to a repeated field (a regular Ruby array for now).
-static void *appendsubmsg_handler(void *closure, const void *hd) {
-  VALUE ary = (VALUE)closure;
-  const submsg_handlerdata_t *submsgdata = hd;
-  MessageHeader* submsg;
-
-  VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass);
-  RepeatedField_push(ary, submsg_rb);
-
-  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
-  return submsg;
-}
-
-// Appends a wrapper to a repeated field (a regular Ruby array for now).
-static void *appendwrapper_handler(void *closure, const void *hd) {
-  VALUE ary = (VALUE)closure;
-  int size = RepeatedField_size(ary);
-  (void)hd;
-
-  RepeatedField_push(ary, Qnil);
-
-  return RepeatedField_index_native(ary, size);
-}
-
-// Sets a non-repeated submessage field in a message.
-static void *submsg_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const submsg_handlerdata_t* submsgdata = hd;
-  VALUE submsg_rb;
-  MessageHeader* submsg;
-
-  if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
-    DEREF(msg, submsgdata->ofs, VALUE) =
-        initialize_rb_class_with_no_args(submsgdata->subklass);
-  }
-
-  set_hasbit(closure, submsgdata->hasbit);
-
-  submsg_rb = DEREF(msg, submsgdata->ofs, VALUE);
-  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
-
-  return submsg;
-}
-
-static void* startwrapper(void* closure, const void* hd) {
-  const submsg_handlerdata_t* submsgdata = hd;
-  char* msg = closure;
-  VALUE* field = (VALUE*)(msg + submsgdata->ofs);
-
-  set_hasbit(closure, submsgdata->hasbit);
-
-  switch (submsgdata->wrapped_type) {
-    case UPB_TYPE_FLOAT:
-    case UPB_TYPE_DOUBLE:
-      *field = DBL2NUM(0);
-      break;
-    case UPB_TYPE_BOOL:
-      *field = Qfalse;
-      break;
-    case UPB_TYPE_STRING:
-      *field = get_frozen_string(NULL, 0, false);
-      break;
-    case UPB_TYPE_BYTES:
-      *field = get_frozen_string(NULL, 0, true);
-      break;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      *field = INT2NUM(0);
-      break;
-    case UPB_TYPE_MESSAGE:
-      rb_raise(rb_eRuntimeError,
-               "Internal logic error with well-known types.");
-  }
-
-  return field;
-}
-
-// Handler data for startmap/endmap handlers.
-typedef struct {
-  size_t ofs;
-  upb_fieldtype_t key_field_type;
-  upb_fieldtype_t value_field_type;
-  VALUE subklass;
-} map_handlerdata_t;
-
-// Temporary frame for map parsing: at the beginning of a map entry message, a
-// submsg handler allocates a frame to hold (i) a reference to the Map object
-// into which this message will be inserted and (ii) storage slots to
-// temporarily hold the key and value for this map entry until the end of the
-// submessage. When the submessage ends, another handler is called to insert the
-// value into the map.
-typedef struct {
-  VALUE map;
-  const map_handlerdata_t* handlerdata;
-  char key_storage[NATIVE_SLOT_MAX_SIZE];
-  char value_storage[NATIVE_SLOT_MAX_SIZE];
-} map_parse_frame_t;
-
-static void MapParseFrame_mark(void* _self) {
-  map_parse_frame_t* frame = _self;
-
-  // This shouldn't strictly be necessary since this should be rooted by the
-  // message itself, but it can't hurt.
-  rb_gc_mark(frame->map);
-
-  native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage);
-  native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage);
-}
-
-void MapParseFrame_free(void* self) {
-  xfree(self);
-}
-
-rb_data_type_t MapParseFrame_type = {
-  "MapParseFrame",
-  { MapParseFrame_mark, MapParseFrame_free, NULL },
-};
-
-// Handler to begin a map entry: allocates a temporary frame. This is the
-// 'startsubmsg' handler on the msgdef that contains the map field.
-static void *startmap_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const map_handlerdata_t* mapdata = hd;
-  map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
-  VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
-
-  frame->handlerdata = mapdata;
-  frame->map = map_rb;
-  native_slot_init(mapdata->key_field_type, &frame->key_storage);
-  native_slot_init(mapdata->value_field_type, &frame->value_storage);
-
-  Map_set_frame(map_rb,
-                TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
-
-  return frame;
-}
-
-static bool endmap_handler(void *closure, const void *hd) {
-  map_parse_frame_t* frame = closure;
-  Map_set_frame(frame->map, Qnil);
-  return true;
-}
-
-// Handler to end a map entry: inserts the value defined during the message into
-// the map. This is the 'endmsg' handler on the map entry msgdef.
-static bool endmapentry_handler(void* closure, const void* hd, upb_status* s) {
-  map_parse_frame_t* frame = closure;
-  const map_handlerdata_t* mapdata = hd;
-
-  VALUE key = native_slot_get(
-      mapdata->key_field_type, Qnil,
-      &frame->key_storage);
-
-  VALUE value = native_slot_get(
-      mapdata->value_field_type, mapdata->subklass,
-      &frame->value_storage);
-
-  Map_index_set(frame->map, key, value);
-
-  return true;
-}
-
-// Allocates a new map_handlerdata_t given the map entry message definition. If
-// the offset of the field within the parent message is also given, that is
-// added to the handler data as well. Note that this is called *twice* per map
-// field: once in the parent message handler setup when setting the startsubmsg
-// handler and once in the map entry message handler setup when setting the
-// key/value and endmsg handlers. The reason is that there is no easy way to
-// pass the handlerdata down to the sub-message handler setup.
-static map_handlerdata_t* new_map_handlerdata(
-    size_t ofs,
-    const upb_msgdef* mapentry_def,
-    const Descriptor* desc) {
-  const upb_fielddef* key_field;
-  const upb_fielddef* value_field;
-  map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
-  hd->ofs = ofs;
-  key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
-  assert(key_field != NULL);
-  hd->key_field_type = upb_fielddef_type(key_field);
-  value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
-  assert(value_field != NULL);
-  hd->value_field_type = upb_fielddef_type(value_field);
-  hd->subklass = field_type_class(desc->layout, value_field);
-
-  return hd;
-}
-
-// Handlers that set primitive values in oneofs.
-#define DEFINE_ONEOF_HANDLER(type, ctype)                           \
-  static bool oneof##type##_handler(void *closure, const void *hd,  \
-                                     ctype val) {                   \
-    const oneof_handlerdata_t *oneofdata = hd;                      \
-    DEREF(closure, oneofdata->case_ofs, uint32_t) =                 \
-        oneofdata->oneof_case_num;                                  \
-    DEREF(closure, oneofdata->ofs, ctype) = val;                    \
-    return true;                                                    \
-  }
-
-DEFINE_ONEOF_HANDLER(bool,   bool)
-DEFINE_ONEOF_HANDLER(int32,  int32_t)
-DEFINE_ONEOF_HANDLER(uint32, uint32_t)
-DEFINE_ONEOF_HANDLER(float,  float)
-DEFINE_ONEOF_HANDLER(int64,  int64_t)
-DEFINE_ONEOF_HANDLER(uint64, uint64_t)
-DEFINE_ONEOF_HANDLER(double, double)
-
-#undef DEFINE_ONEOF_HANDLER
-
-// Handlers for strings in a oneof.
-static void *oneofstr_handler(void *closure,
-                              const void *hd,
-                              size_t size_hint) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyStringUtf8Encoding);
-  DEREF(msg, oneofdata->case_ofs, uint32_t) =
-      oneofdata->oneof_case_num;
-  DEREF(msg, oneofdata->ofs, VALUE) = str;
-  return (void*)str;
-}
-
-static void *oneofbytes_handler(void *closure,
-                                const void *hd,
-                                size_t size_hint) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyString8bitEncoding);
-  DEREF(msg, oneofdata->case_ofs, uint32_t) =
-      oneofdata->oneof_case_num;
-  DEREF(msg, oneofdata->ofs, VALUE) = str;
-  return (void*)str;
-}
-
-static bool oneofstring_end_handler(void* closure, const void* hd) {
-  VALUE rb_str = rb_str_new2("");
-  rb_obj_freeze(rb_str);
-  return true;
-}
-
-// Handler for a submessage field in a oneof.
-static void *oneofsubmsg_handler(void *closure,
-                                 const void *hd) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
-
-  VALUE submsg_rb;
-  MessageHeader* submsg;
-
-  if (oldcase != oneofdata->oneof_case_num ||
-      DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
-    DEREF(msg, oneofdata->ofs, VALUE) =
-        initialize_rb_class_with_no_args(oneofdata->subklass);
-  }
-  // Set the oneof case *after* allocating the new class instance -- otherwise,
-  // if the Ruby GC is invoked as part of a call into the VM, it might invoke
-  // our mark routines, and our mark routines might see the case value
-  // indicating a VALUE is present and expect a valid VALUE. See comment in
-  // layout_set() for more detail: basically, the change to the value and the
-  // case must be atomic w.r.t. the Ruby VM.
-  DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
-
-  submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
-  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
-  return submsg;
-}
-
-static void* oneof_startwrapper(void* closure, const void* hd) {
-  char* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-
-  DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
-
-  return msg + oneofdata->ofs;
-}
-
-// Set up handlers for a repeated field.
-static void add_handlers_for_repeated_field(upb_handlers *h,
-                                            const Descriptor* desc,
-                                            const upb_fielddef *f,
-                                            size_t offset) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  attr.handler_data = newhandlerdata(h, offset, -1);
-  upb_handlers_setstartseq(h, f, startseq_handler, &attr);
-
-  switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype)                                 \
-  case utype:                                                     \
-    upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
-    break;
-
-    SET_HANDLER(UPB_TYPE_BOOL,   bool);
-    SET_HANDLER(UPB_TYPE_INT32,  int32);
-    SET_HANDLER(UPB_TYPE_UINT32, uint32);
-    SET_HANDLER(UPB_TYPE_ENUM,   int32);
-    SET_HANDLER(UPB_TYPE_FLOAT,  float);
-    SET_HANDLER(UPB_TYPE_INT64,  int64);
-    SET_HANDLER(UPB_TYPE_UINT64, uint64);
-    SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
-      upb_handlers_setstartstr(h, f, is_bytes ?
-                               appendbytes_handler : appendstr_handler,
-                               NULL);
-      upb_handlers_setstring(h, f, stringdata_handler, NULL);
-      upb_handlers_setendstr(h, f, appendstring_end_handler, NULL);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      VALUE subklass = field_type_class(desc->layout, f);
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newsubmsghandlerdata(h, f, 0, -1, subklass);
-      if (is_wrapper(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, appendwrapper_handler, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
-      }
-      break;
-    }
-  }
-}
-
-static bool doublewrapper_handler(void* closure, const void* hd, double val) {
-  VALUE* rbval = closure;
-  *rbval = DBL2NUM(val);
-  return true;
-}
-
-static bool floatwrapper_handler(void* closure, const void* hd, float val) {
-  VALUE* rbval = closure;
-  *rbval = DBL2NUM(val);
-  return true;
-}
-
-static bool int64wrapper_handler(void* closure, const void* hd, int64_t val) {
-  VALUE* rbval = closure;
-  *rbval = LL2NUM(val);
-  return true;
-}
-
-static bool uint64wrapper_handler(void* closure, const void* hd, uint64_t val) {
-  VALUE* rbval = closure;
-  *rbval = ULL2NUM(val);
-  return true;
-}
-
-static bool int32wrapper_handler(void* closure, const void* hd, int32_t val) {
-  VALUE* rbval = closure;
-  *rbval = INT2NUM(val);
-  return true;
-}
-
-static bool uint32wrapper_handler(void* closure, const void* hd, uint32_t val) {
-  VALUE* rbval = closure;
-  *rbval = UINT2NUM(val);
-  return true;
-}
-
-static void* startstringwrapper_handler(void* closure, const void* hd,
-                                        size_t size_hint) {
-  VALUE* rbval = closure;
-  (void)size_hint;
-  *rbval = rb_str_new(NULL, 0);
-  rb_enc_associate(*rbval, kRubyStringUtf8Encoding);
-  return closure;
-}
-
-static size_t stringwrapper_handler(void* closure, const void* hd,
-                                    const char* ptr, size_t len,
-                                    const upb_bufhandle* handle) {
-  VALUE* rbval = closure;
-  *rbval = noleak_rb_str_cat(*rbval, ptr, len);
-  return len;
-}
-
-static void* startbyteswrapper_handler(void* closure, const void* hd,
-                                       size_t size_hint) {
-  VALUE* rbval = closure;
-  (void)size_hint;
-  *rbval = rb_str_new(NULL, 0);
-  rb_enc_associate(*rbval, kRubyString8bitEncoding);
-  return closure;
-}
-
-static size_t byteswrapper_handler(void* closure, const void* hd,
-                                   const char* ptr, size_t len,
-                                   const upb_bufhandle* handle) {
-  VALUE* rbval = closure;
-  *rbval = noleak_rb_str_cat(*rbval, ptr, len);
-  return len;
-}
-
-static bool boolwrapper_handler(void* closure, const void* hd, bool val) {
-  VALUE* rbval = closure;
-  if (val) {
-    *rbval = Qtrue;
-  } else {
-    *rbval = Qfalse;
-  }
-  return true;
-}
-
-// Set up handlers for a singular field.
-static void add_handlers_for_singular_field(const Descriptor* desc,
-                                            upb_handlers* h,
-                                            const upb_fielddef* f,
-                                            size_t offset, size_t hasbit_off) {
-  // The offset we pass to UPB points to the start of the Message,
-  // rather than the start of where our data is stored.
-  int32_t hasbit = -1;
-  if (hasbit_off != MESSAGE_FIELD_NO_HASBIT) {
-    hasbit = hasbit_off + sizeof(MessageHeader) * 8;
-  }
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_BOOL:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_FLOAT:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-      upb_msg_setscalarhandler(h, f, offset, hasbit);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newhandlerdata(h, offset, hasbit);
-      upb_handlers_setstartstr(h, f,
-                               is_bytes ? bytes_handler : str_handler,
-                               &attr);
-      upb_handlers_setstring(h, f, stringdata_handler, &attr);
-      upb_handlers_setendstr(h, f, stringdata_end_handler, &attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newsubmsghandlerdata(
-          h, f, offset, hasbit, field_type_class(desc->layout, f));
-      if (is_wrapper(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, startwrapper, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
-      }
-    }
-  }
-}
-
-// Adds handlers to a map field.
-static void add_handlers_for_mapfield(upb_handlers* h,
-                                      const upb_fielddef* fielddef,
-                                      size_t offset,
-                                      const Descriptor* desc) {
-  const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
-  map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_addcleanup(h, hd, xfree);
-  attr.handler_data = hd;
-  upb_handlers_setstartsubmsg(h, fielddef, startmap_handler, &attr);
-  upb_handlers_setendsubmsg(h, fielddef, endmap_handler, &attr);
-}
-
-// Adds handlers to a map-entry msgdef.
-static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
-                                      const Descriptor* desc) {
-  const upb_fielddef* key_field = map_entry_key(msgdef);
-  const upb_fielddef* value_field = map_entry_value(msgdef);
-  map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_addcleanup(h, hd, xfree);
-  attr.handler_data = hd;
-  upb_handlers_setendmsg(h, endmapentry_handler, &attr);
-
-  add_handlers_for_singular_field(
-      desc, h, key_field,
-      offsetof(map_parse_frame_t, key_storage),
-      MESSAGE_FIELD_NO_HASBIT);
-  add_handlers_for_singular_field(
-      desc, h, value_field,
-      offsetof(map_parse_frame_t, value_storage),
-      MESSAGE_FIELD_NO_HASBIT);
-}
-
-static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
-                                     upb_handlers* h) {
-  const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
-  switch (upb_msgdef_wellknowntype(msgdef)) {
-    case UPB_WELLKNOWN_DOUBLEVALUE:
-      upb_handlers_setdouble(h, f, doublewrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_FLOATVALUE:
-      upb_handlers_setfloat(h, f, floatwrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_INT64VALUE:
-      upb_handlers_setint64(h, f, int64wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_UINT64VALUE:
-      upb_handlers_setuint64(h, f, uint64wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_INT32VALUE:
-      upb_handlers_setint32(h, f, int32wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_UINT32VALUE:
-      upb_handlers_setuint32(h, f, uint32wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_STRINGVALUE:
-      upb_handlers_setstartstr(h, f, startstringwrapper_handler, NULL);
-      upb_handlers_setstring(h, f, stringwrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_BYTESVALUE:
-      upb_handlers_setstartstr(h, f, startbyteswrapper_handler, NULL);
-      upb_handlers_setstring(h, f, byteswrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_BOOLVALUE:
-      upb_handlers_setbool(h, f, boolwrapper_handler, NULL);
-      return;
-    default:
-      rb_raise(rb_eRuntimeError,
-               "Internal logic error with well-known types.");
-  }
-}
-
-// Set up handlers for a oneof field.
-static void add_handlers_for_oneof_field(upb_handlers *h,
-                                         const upb_fielddef *f,
-                                         size_t offset,
-                                         size_t oneof_case_offset,
-                                         const Descriptor* desc) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  attr.handler_data =
-      newoneofhandlerdata(h, offset, oneof_case_offset, f, desc);
-
-  switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype)                                 \
-  case utype:                                                     \
-    upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
-    break;
-
-    SET_HANDLER(UPB_TYPE_BOOL,   bool);
-    SET_HANDLER(UPB_TYPE_INT32,  int32);
-    SET_HANDLER(UPB_TYPE_UINT32, uint32);
-    SET_HANDLER(UPB_TYPE_ENUM,   int32);
-    SET_HANDLER(UPB_TYPE_FLOAT,  float);
-    SET_HANDLER(UPB_TYPE_INT64,  int64);
-    SET_HANDLER(UPB_TYPE_UINT64, uint64);
-    SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
-      upb_handlers_setstartstr(h, f, is_bytes ?
-                               oneofbytes_handler : oneofstr_handler,
-                               &attr);
-      upb_handlers_setstring(h, f, stringdata_handler, NULL);
-      upb_handlers_setendstr(h, f, oneofstring_end_handler, &attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (is_wrapper(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, oneof_startwrapper, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
-      }
-      break;
-    }
-  }
-}
-
-static bool unknown_field_handler(void* closure, const void* hd,
-                                  const char* buf, size_t size) {
-  MessageHeader* msg = (MessageHeader*)closure;
-  UPB_UNUSED(hd);
-
-  if (msg->unknown_fields == NULL) {
-    msg->unknown_fields = malloc(sizeof(stringsink));
-    stringsink_init(msg->unknown_fields);
-  }
-
-  stringsink_string(msg->unknown_fields, NULL, buf, size, NULL);
-
-  return true;
-}
-
-size_t get_field_offset(MessageLayout* layout, const upb_fielddef* f) {
-  return layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader);
-}
-
-void add_handlers_for_message(const void *closure, upb_handlers *h) {
-  const VALUE descriptor_pool = (VALUE)closure;
-  const upb_msgdef* msgdef = upb_handlers_msgdef(h);
-  Descriptor* desc =
-      ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef));
-  upb_msg_field_iter i;
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  // Ensure layout exists. We may be invoked to create handlers for a given
-  // message if we are included as a submsg of another message type before our
-  // class is actually built, so to work around this, we just create the layout
-  // (and handlers, in the class-building function) on-demand.
-  if (desc->layout == NULL) {
-    create_layout(desc);
-  }
-
-  // If this is a mapentry message type, set up a special set of handlers and
-  // bail out of the normal (user-defined) message type handling.
-  if (upb_msgdef_mapentry(msgdef)) {
-    add_handlers_for_mapentry(msgdef, h, desc);
-    return;
-  }
-
-  // If this is a wrapper type, use special handlers and bail.
-  if (is_wrapper(msgdef)) {
-    add_handlers_for_wrapper(msgdef, h);
-    return;
-  }
-
-  upb_handlers_setunknown(h, unknown_field_handler, &attr);
-
-  for (upb_msg_field_begin(&i, desc->msgdef);
-       !upb_msg_field_done(&i);
-       upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
-    size_t offset = get_field_offset(desc->layout, f);
-
-    if (oneof) {
-      size_t oneof_case_offset =
-          desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset +
-          sizeof(MessageHeader);
-      add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc);
-    } else if (is_map_field(f)) {
-      add_handlers_for_mapfield(h, f, offset, desc);
-    } else if (upb_fielddef_isseq(f)) {
-      add_handlers_for_repeated_field(h, desc, f, offset);
-    } else {
-      add_handlers_for_singular_field(
-          desc, h, f, offset,
-          desc->layout->fields[upb_fielddef_index(f)].hasbit);
-    }
-  }
-}
-
-// Constructs the handlers for filling a message's data into an in-memory
-// object.
-const upb_handlers* get_fill_handlers(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef);
-}
-
-static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_pbcodecache_get(pool->fill_method_cache, desc->msgdef);
-}
-
-static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_json_codecache_get(pool->json_fill_method_cache, desc->msgdef);
-}
-
-static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_handlercache_get(pool->pb_serialize_handler_cache, desc->msgdef);
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
-    Descriptor* desc, bool preserve_proto_fieldnames) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  if (preserve_proto_fieldnames) {
-    return upb_handlercache_get(pool->json_serialize_handler_preserve_cache,
-                                desc->msgdef);
-  } else {
-    return upb_handlercache_get(pool->json_serialize_handler_cache,
-                                desc->msgdef);
-  }
-}
-
-
-// Stack-allocated context during an encode/decode operation. Contains the upb
-// environment and its stack-based allocator, an initial buffer for allocations
-// to avoid malloc() when possible, and a template for Ruby exception messages
-// if any error occurs.
-#define STACK_ENV_STACKBYTES 4096
-typedef struct {
-  upb_arena *arena;
-  upb_status status;
-  const char* ruby_error_template;
-  char allocbuf[STACK_ENV_STACKBYTES];
-} stackenv;
-
-static void stackenv_init(stackenv* se, const char* errmsg);
-static void stackenv_uninit(stackenv* se);
-
-static void stackenv_init(stackenv* se, const char* errmsg) {
-  se->ruby_error_template = errmsg;
-  se->arena =
-      upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global);
-  upb_status_clear(&se->status);
-}
-
-static void stackenv_uninit(stackenv* se) {
-  upb_arena_free(se->arena);
-
-  if (!upb_ok(&se->status)) {
-    // TODO(haberman): have a way to verify that this is actually a parse error,
-    // instead of just throwing "parse error" unconditionally.
-    VALUE errmsg = rb_str_new2(upb_status_errmsg(&se->status));
-    rb_raise(cParseError, se->ruby_error_template, errmsg);
-  }
-}
-
-/*
- * call-seq:
- *     MessageClass.decode(data) => message
- *
- * Decodes the given data (as a string containing bytes in protocol buffers wire
- * format) under the interpretration given by this message class's definition
- * and returns a message object with the corresponding field values.
- */
-VALUE Message_decode(VALUE klass, VALUE data) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  VALUE msgklass = Descriptor_msgclass(descriptor);
-  VALUE msg_rb;
-  MessageHeader* msg;
-
-  if (TYPE(data) != T_STRING) {
-    rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
-  }
-
-  msg_rb = initialize_rb_class_with_no_args(msgklass);
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  {
-    const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
-    const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
-    const upb_msgdef* m = upb_handlers_msgdef(h);
-    VALUE wrapper = Qnil;
-    void* ptr = msg;
-    stackenv se;
-    upb_sink sink;
-    upb_pbdecoder* decoder;
-    stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
-
-    if (is_wrapper(m)) {
-      ptr = &wrapper;
-    }
-
-    upb_sink_reset(&sink, h, ptr);
-    decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
-    upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
-                      upb_pbdecoder_input(decoder));
-
-    stackenv_uninit(&se);
-
-    if (is_wrapper(m)) {
-      msg_rb = ruby_wrapper_type(msgklass, wrapper);
-    }
-  }
-
-  return msg_rb;
-}
-
-/*
- * call-seq:
- *     MessageClass.decode_json(data, options = {}) => message
- *
- * Decodes the given data (as a string containing bytes in protocol buffers wire
- * format) under the interpretration given by this message class's definition
- * and returns a message object with the corresponding field values.
- *
- *  @param options [Hash] options for the decoder
- *   ignore_unknown_fields: set true to ignore unknown fields (default is to
- *   raise an error)
- */
-VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  VALUE msgklass = Descriptor_msgclass(descriptor);
-  VALUE msg_rb;
-  VALUE data = argv[0];
-  VALUE ignore_unknown_fields = Qfalse;
-  MessageHeader* msg;
-
-  if (argc < 1 || argc > 2) {
-    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
-  }
-
-  if (argc == 2) {
-    VALUE hash_args = argv[1];
-    if (TYPE(hash_args) != T_HASH) {
-      rb_raise(rb_eArgError, "Expected hash arguments.");
-    }
-
-    ignore_unknown_fields = rb_hash_lookup2(
-        hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse);
-  }
-
-  if (TYPE(data) != T_STRING) {
-    rb_raise(rb_eArgError, "Expected string for JSON data.");
-  }
-
-  // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
-  // convert, because string handlers pass data directly to message string
-  // fields.
-
-  msg_rb = initialize_rb_class_with_no_args(msgklass);
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  {
-    const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
-    const upb_handlers* h = get_fill_handlers(desc);
-    const upb_msgdef* m = upb_handlers_msgdef(h);
-    stackenv se;
-    upb_sink sink;
-    upb_json_parser* parser;
-    DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
-    stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
-
-    if (is_wrapper(m)) {
-      rb_raise(
-          rb_eRuntimeError,
-          "Parsing a wrapper type from JSON at the top level does not work.");
-    }
-
-    upb_sink_reset(&sink, h, msg);
-    parser = upb_json_parser_create(se.arena, method, pool->symtab, sink,
-                                    &se.status, RTEST(ignore_unknown_fields));
-    upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
-                      upb_json_parser_input(parser));
-
-    stackenv_uninit(&se);
-  }
-
-  return msg_rb;
-}
-
-// -----------------------------------------------------------------------------
-// Serializing.
-// -----------------------------------------------------------------------------
-
-/* msgvisitor *****************************************************************/
-
-static void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth,
-                   bool emit_defaults, bool is_json, bool open_msg);
-
-static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
-  upb_selector_t ret;
-  bool ok = upb_handlers_getselector(f, type, &ret);
-  UPB_ASSERT(ok);
-  return ret;
-}
-
-static void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) {
-  upb_sink subsink;
-
-  if (str == Qnil) return;
-
-  assert(BUILTIN_TYPE(str) == RUBY_T_STRING);
-
-  // We should be guaranteed that the string has the correct encoding because
-  // we ensured this at assignment time and then froze the string.
-  if (upb_fielddef_type(f) == UPB_TYPE_STRING) {
-    assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyStringUtf8Encoding);
-  } else {
-    assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyString8bitEncoding);
-  }
-
-  upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
-                    &subsink);
-  upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
-                     RSTRING_LEN(str), NULL);
-  upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
-}
-
-static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink,
-                      int depth, bool emit_defaults, bool is_json) {
-  upb_sink subsink;
-  VALUE descriptor;
-  Descriptor* subdesc;
-
-  if (submsg == Qnil) return;
-
-  descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-  subdesc = ruby_to_Descriptor(descriptor);
-
-  upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
-  putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true);
-  upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-}
-
-static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
-                   bool emit_defaults, bool is_json) {
-  upb_sink subsink;
-  upb_fieldtype_t type = upb_fielddef_type(f);
-  upb_selector_t sel = 0;
-  int size;
-  int i;
-  VALUE type_class = ruby_to_RepeatedField(ary)->field_type_class;
-
-  if (ary == Qnil) return;
-  if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return;
-
-  size = NUM2INT(RepeatedField_length(ary));
-  if (size == 0 && !emit_defaults) return;
-
-  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
-  if (upb_fielddef_isprimitive(f)) {
-    sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  }
-
-  for (i = 0; i < size; i++) {
-    void* memory = RepeatedField_index_native(ary, i);
-    switch (type) {
-#define T(upbtypeconst, upbtype, ctype)                     \
-  case upbtypeconst:                                        \
-    upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
-    break;
-
-      T(UPB_TYPE_FLOAT,  float,  float)
-      T(UPB_TYPE_DOUBLE, double, double)
-      T(UPB_TYPE_BOOL,   bool,   int8_t)
-      case UPB_TYPE_ENUM:
-      T(UPB_TYPE_INT32,  int32,  int32_t)
-      T(UPB_TYPE_UINT32, uint32, uint32_t)
-      T(UPB_TYPE_INT64,  int64,  int64_t)
-      T(UPB_TYPE_UINT64, uint64, uint64_t)
-
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        putstr(*((VALUE *)memory), f, subsink);
-        break;
-      case UPB_TYPE_MESSAGE: {
-        VALUE val = native_slot_get(UPB_TYPE_MESSAGE, type_class, memory);
-        putsubmsg(val, f, subsink, depth, emit_defaults, is_json);
-        break;
-      }
-
-#undef T
-
-    }
-  }
-  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class,
-                           int depth, upb_sink sink, bool emit_defaults,
-                           bool is_json) {
-  upb_selector_t sel = 0;
-
-  if (depth > ENCODE_MAX_NESTING) {
-    rb_raise(rb_eRuntimeError,
-             "Maximum recursion depth exceeded during encoding.");
-  }
-
-  if (upb_fielddef_isprimitive(f)) {
-    sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  }
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-      upb_sink_putint32(sink, sel, NUM2INT(value));
-      break;
-    case UPB_TYPE_INT64:
-      upb_sink_putint64(sink, sel, NUM2LL(value));
-      break;
-    case UPB_TYPE_UINT32:
-      upb_sink_putuint32(sink, sel, NUM2UINT(value));
-      break;
-    case UPB_TYPE_UINT64:
-      upb_sink_putuint64(sink, sel, NUM2ULL(value));
-      break;
-    case UPB_TYPE_FLOAT:
-      upb_sink_putfloat(sink, sel, NUM2DBL(value));
-      break;
-    case UPB_TYPE_DOUBLE:
-      upb_sink_putdouble(sink, sel, NUM2DBL(value));
-      break;
-    case UPB_TYPE_ENUM: {
-      if (TYPE(value) == T_SYMBOL) {
-        value = rb_funcall(type_class, rb_intern("resolve"), 1, value);
-      }
-      upb_sink_putint32(sink, sel, NUM2INT(value));
-      break;
-    }
-    case UPB_TYPE_BOOL:
-      upb_sink_putbool(sink, sel, value == Qtrue);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      putstr(value, f, sink);
-      break;
-    case UPB_TYPE_MESSAGE:
-      putsubmsg(value, f, sink, depth, emit_defaults, is_json);
-  }
-}
-
-static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth,
-                   bool emit_defaults, bool is_json) {
-  Map* self;
-  upb_sink subsink;
-  const upb_fielddef* key_field;
-  const upb_fielddef* value_field;
-  Map_iter it;
-
-  if (map == Qnil) return;
-  if (!emit_defaults && Map_length(map) == 0) return;
-
-  self = ruby_to_Map(map);
-
-  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
-  assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
-  key_field = map_field_key(f);
-  value_field = map_field_value(f);
-
-  for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) {
-    VALUE key = Map_iter_key(&it);
-    VALUE value = Map_iter_value(&it);
-    upb_status status;
-
-    upb_sink entry_sink;
-    upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
-                         &entry_sink);
-    upb_sink_startmsg(entry_sink);
-
-    put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults,
-                   is_json);
-    put_ruby_value(value, value_field, self->value_type_class, depth + 1,
-                   entry_sink, emit_defaults, is_json);
-
-    upb_sink_endmsg(entry_sink, &status);
-    upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-  }
-
-  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
-    Descriptor* desc, bool preserve_proto_fieldnames);
-
-static void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink,
-                       int depth, bool emit_defaults) {
-  upb_status status;
-  MessageHeader* msg = NULL;
-  const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
-  const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
-
-  size_t type_url_offset;
-  VALUE type_url_str_rb;
-  const upb_msgdef *payload_type = NULL;
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  upb_sink_startmsg(sink);
-
-  /* Handle type url */
-  type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset;
-  type_url_str_rb = DEREF(Message_data(msg), type_url_offset, VALUE);
-  if (RSTRING_LEN(type_url_str_rb) > 0) {
-    putstr(type_url_str_rb, type_field, sink);
-  }
-
-  {
-    const char* type_url_str = RSTRING_PTR(type_url_str_rb);
-    size_t type_url_len = RSTRING_LEN(type_url_str_rb);
-    DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
-
-    if (type_url_len <= 20 ||
-        strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
-      rb_raise(rb_eRuntimeError, "Invalid type url: %s", type_url_str);
-      return;
-    }
-
-    /* Resolve type url */
-    type_url_str += 20;
-    type_url_len -= 20;
-
-    payload_type = upb_symtab_lookupmsg2(
-        pool->symtab, type_url_str, type_url_len);
-    if (payload_type == NULL) {
-      rb_raise(rb_eRuntimeError, "Unknown type: %s", type_url_str);
-      return;
-    }
-  }
-
-  {
-    uint32_t value_offset;
-    VALUE value_str_rb;
-    size_t value_len;
-
-    value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
-    value_str_rb = DEREF(Message_data(msg), value_offset, VALUE);
-    value_len = RSTRING_LEN(value_str_rb);
-
-    if (value_len > 0) {
-      VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type);
-      Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb);
-      VALUE payload_class = Descriptor_msgclass(payload_desc_rb);
-      upb_sink subsink;
-      bool is_wellknown;
-
-      VALUE payload_msg_rb = Message_decode(payload_class, value_str_rb);
-
-      is_wellknown =
-          upb_msgdef_wellknowntype(payload_desc->msgdef) !=
-              UPB_WELLKNOWN_UNSPECIFIED;
-      if (is_wellknown) {
-        upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
-                          &subsink);
-      }
-
-      subsink.handlers =
-          msgdef_json_serialize_handlers(payload_desc, true);
-      subsink.closure = sink.closure;
-      putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true,
-             is_wellknown);
-    }
-  }
-
-  upb_sink_endmsg(sink, &status);
-}
-
-static void putjsonlistvalue(
-    VALUE msg_rb, const Descriptor* desc,
-    upb_sink sink, int depth, bool emit_defaults) {
-  upb_status status;
-  upb_sink subsink;
-  MessageHeader* msg = NULL;
-  const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
-  uint32_t offset =
-      desc->layout->fields[upb_fielddef_index(f)].offset +
-      sizeof(MessageHeader);
-  VALUE ary;
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  upb_sink_startmsg(sink);
-
-  ary = DEREF(msg, offset, VALUE);
-
-  if (ary == Qnil || RepeatedField_size(ary) == 0) {
-    upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-    upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-  } else {
-    putary(ary, f, sink, depth, emit_defaults, true);
-  }
-
-  upb_sink_endmsg(sink, &status);
-}
-
-static void putmsg(VALUE msg_rb, const Descriptor* desc,
-                   upb_sink sink, int depth, bool emit_defaults,
-                   bool is_json, bool open_msg) {
-  MessageHeader* msg;
-  upb_msg_field_iter i;
-  upb_status status;
-  bool json_wrapper = is_wrapper(desc->msgdef) && is_json;
-
-  if (is_json &&
-      upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
-    putjsonany(msg_rb, desc, sink, depth, emit_defaults);
-    return;
-  }
-
-  if (is_json &&
-      upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
-    putjsonlistvalue(msg_rb, desc, sink, depth, emit_defaults);
-    return;
-  }
-
-  if (open_msg) {
-    upb_sink_startmsg(sink);
-  }
-
-  // Protect against cycles (possible because users may freely reassign message
-  // and repeated fields) by imposing a maximum recursion depth.
-  if (depth > ENCODE_MAX_NESTING) {
-    rb_raise(rb_eRuntimeError,
-             "Maximum recursion depth exceeded during encoding.");
-  }
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  if (desc != msg->descriptor) {
-    rb_raise(rb_eArgError,
-             "The type of given msg is '%s', expect '%s'.",
-             upb_msgdef_fullname(msg->descriptor->msgdef),
-             upb_msgdef_fullname(desc->msgdef));
-  }
-
-  for (upb_msg_field_begin(&i, desc->msgdef);
-       !upb_msg_field_done(&i);
-       upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-    const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
-    bool is_matching_oneof = false;
-    uint32_t offset =
-        desc->layout->fields[upb_fielddef_index(f)].offset +
-        sizeof(MessageHeader);
-
-    if (oneof) {
-      uint32_t oneof_case =
-          slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
-      // For a oneof, check that this field is actually present -- skip all the
-      // below if not.
-      if (oneof_case != upb_fielddef_number(f)) {
-        continue;
-      }
-      // Otherwise, fall through to the appropriate singular-field handler
-      // below.
-      is_matching_oneof = true;
-    }
-
-    if (is_map_field(f)) {
-      VALUE map = DEREF(msg, offset, VALUE);
-      if (map != Qnil || emit_defaults) {
-        putmap(map, f, sink, depth, emit_defaults, is_json);
-      }
-    } else if (upb_fielddef_isseq(f)) {
-      VALUE ary = DEREF(msg, offset, VALUE);
-      if (ary != Qnil) {
-        putary(ary, f, sink, depth, emit_defaults, is_json);
-      }
-    } else if (upb_fielddef_isstring(f)) {
-      VALUE str = DEREF(msg, offset, VALUE);
-      bool is_default = false;
-
-      if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO2) {
-        is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse;
-      } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {
-        is_default = RSTRING_LEN(str) == 0;
-      }
-
-      if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) {
-        putstr(str, f, sink);
-      }
-    } else if (upb_fielddef_issubmsg(f)) {
-      // OPT: could try to avoid the layout_get() (which will expand lazy
-      // wrappers).
-      VALUE val = layout_get(desc->layout, Message_data(msg), f);
-      putsubmsg(val, f, sink, depth, emit_defaults, is_json);
-    } else {
-      upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-
-#define T(upbtypeconst, upbtype, ctype, default_value)                       \
-  case upbtypeconst: {                                                       \
-    ctype value = DEREF(msg, offset, ctype);                                 \
-    bool is_default = false;                                                 \
-    if (upb_fielddef_haspresence(f)) {                                       \
-      is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \
-    } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {       \
-      is_default = default_value == value;                                   \
-    }                                                                        \
-    if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { \
-      upb_sink_put##upbtype(sink, sel, value);                               \
-    }                                                                        \
-  } break;
-
-      switch (upb_fielddef_type(f)) {
-        T(UPB_TYPE_FLOAT,  float,  float, 0.0)
-        T(UPB_TYPE_DOUBLE, double, double, 0.0)
-        T(UPB_TYPE_BOOL,   bool,   uint8_t, 0)
-        case UPB_TYPE_ENUM:
-        T(UPB_TYPE_INT32,  int32,  int32_t, 0)
-        T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
-        T(UPB_TYPE_INT64,  int64,  int64_t, 0)
-        T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
-
-        case UPB_TYPE_STRING:
-        case UPB_TYPE_BYTES:
-        case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error.");
-      }
-
-#undef T
-    }
-  }
-
-  {
-    stringsink* unknown = msg->unknown_fields;
-    if (unknown != NULL) {
-      upb_sink_putunknown(sink, unknown->ptr, unknown->len);
-    }
-  }
-
-  if (open_msg) {
-    upb_sink_endmsg(sink, &status);
-  }
-}
-
-/*
- * call-seq:
- *     MessageClass.encode(msg) => bytes
- *
- * Encodes the given message object to its serialized form in protocol buffers
- * wire format.
- */
-VALUE Message_encode(VALUE klass, VALUE msg_rb) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-
-  stringsink sink;
-  stringsink_init(&sink);
-
-  {
-    const upb_handlers* serialize_handlers =
-        msgdef_pb_serialize_handlers(desc);
-
-    stackenv se;
-    upb_pb_encoder* encoder;
-    VALUE ret;
-
-    stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
-    encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
-
-    putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true);
-
-    ret = rb_str_new(sink.ptr, sink.len);
-
-    stackenv_uninit(&se);
-    stringsink_uninit(&sink);
-
-    return ret;
-  }
-}
-
-/*
- * call-seq:
- *     MessageClass.encode_json(msg, options = {}) => json_string
- *
- * Encodes the given message object into its serialized JSON representation.
- * @param options [Hash] options for the decoder
- *  preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
- *  emit_defaults: set true to emit 0/false values (default is to omit them)
- */
-VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  VALUE msg_rb;
-  VALUE preserve_proto_fieldnames = Qfalse;
-  VALUE emit_defaults = Qfalse;
-  stringsink sink;
-
-  if (argc < 1 || argc > 2) {
-    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
-  }
-
-  msg_rb = argv[0];
-
-  if (argc == 2) {
-    VALUE hash_args = argv[1];
-    if (TYPE(hash_args) != T_HASH) {
-      rb_raise(rb_eArgError, "Expected hash arguments.");
-    }
-    preserve_proto_fieldnames = rb_hash_lookup2(
-        hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse);
-
-    emit_defaults = rb_hash_lookup2(
-        hash_args, ID2SYM(rb_intern("emit_defaults")), Qfalse);
-  }
-
-  stringsink_init(&sink);
-
-  {
-    const upb_handlers* serialize_handlers =
-        msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames));
-    upb_json_printer* printer;
-    stackenv se;
-    VALUE ret;
-
-    stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
-    printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
-
-    putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
-           RTEST(emit_defaults), true, true);
-
-    ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding());
-
-    stackenv_uninit(&se);
-    stringsink_uninit(&sink);
-
-    return ret;
-  }
-}
-
-static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
-  MessageHeader* msg;
-  upb_msg_field_iter it;
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  {
-    stringsink* unknown = msg->unknown_fields;
-    if (unknown != NULL) {
-      stringsink_uninit(unknown);
-      msg->unknown_fields = NULL;
-    }
-  }
-
-  for (upb_msg_field_begin(&it, desc->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    upb_fielddef *f = upb_msg_iter_field(&it);
-    const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
-    uint32_t offset =
-        desc->layout->fields[upb_fielddef_index(f)].offset +
-        sizeof(MessageHeader);
-
-    if (oneof) {
-      uint32_t oneof_case =
-          slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
-      // For a oneof, check that this field is actually present -- skip all the
-      // below if not.
-      if (oneof_case != upb_fielddef_number(f)) {
-        continue;
-      }
-      // Otherwise, fall through to the appropriate singular-field handler
-      // below.
-    }
-
-    if (!upb_fielddef_issubmsg(f)) {
-      continue;
-    }
-
-    if (is_map_field(f)) {
-      VALUE map;
-      Map_iter map_it;
-
-      if (!upb_fielddef_issubmsg(map_field_value(f))) continue;
-      map = DEREF(msg, offset, VALUE);
-      if (map == Qnil) continue;
-      for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) {
-        VALUE submsg = Map_iter_value(&map_it);
-        VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-        const Descriptor* subdesc = ruby_to_Descriptor(descriptor);
-        discard_unknown(submsg, subdesc);
-      }
-    } else if (upb_fielddef_isseq(f)) {
-      VALUE ary = DEREF(msg, offset, VALUE);
-      int size;
-      int i;
-
-      if (ary == Qnil) continue;
-      size = NUM2INT(RepeatedField_length(ary));
-      for (i = 0; i < size; i++) {
-        void* memory = RepeatedField_index_native(ary, i);
-        VALUE submsg = *((VALUE *)memory);
-        VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-        const Descriptor* subdesc = ruby_to_Descriptor(descriptor);
-        discard_unknown(submsg, subdesc);
-      }
-    } else {
-      VALUE submsg = DEREF(msg, offset, VALUE);
-      VALUE descriptor;
-      const Descriptor* subdesc;
-
-      if (submsg == Qnil) continue;
-      descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-      subdesc = ruby_to_Descriptor(descriptor);
-      discard_unknown(submsg, subdesc);
-    }
-  }
-}
-
-/*
- * call-seq:
- *     Google::Protobuf.discard_unknown(msg)
- *
- * Discard unknown fields in the given message object and recursively discard
- * unknown fields in submessages.
- */
-VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) {
-  VALUE klass = CLASS_OF(msg_rb);
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  if (klass == cRepeatedField || klass == cMap) {
-    rb_raise(rb_eArgError, "Expected proto msg for discard unknown.");
-  } else {
-    discard_unknown(msg_rb, desc);
-  }
-  return Qnil;
-}
diff --git a/ruby/ext/google/protobuf_c/extconf.rb b/ruby/ext/google/protobuf_c/extconf.rb
index 80b7985..eaab4db 100755
--- a/ruby/ext/google/protobuf_c/extconf.rb
+++ b/ruby/ext/google/protobuf_c/extconf.rb
@@ -3,9 +3,9 @@
 require 'mkmf'
 
 if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
-  $CFLAGS += " -std=gnu90 -O3 -DNDEBUG -Wall -Wdeclaration-after-statement -Wsign-compare"
+  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG -fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement"
 else
-  $CFLAGS += " -std=gnu90 -O3 -DNDEBUG"
+  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG"
 end
 
 
@@ -14,8 +14,8 @@
   $LDFLAGS += " -Wl,-wrap,memcpy"
 end
 
-$objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
-         "repeated_field.o", "map.o", "encode_decode.o", "upb.o",
-         "wrap_memcpy.o"]
+$objs = ["protobuf.o", "convert.o", "defs.o", "message.o",
+         "repeated_field.o", "map.o", "ruby-upb.o", "wrap_memcpy.o"]
 
+find_header('third_party/wyhash/wyhash.h', '../../../..')
 create_makefile("google/protobuf_c")
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 00d23a7..d5b47e4 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -28,170 +28,233 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "convert.h"
+#include "defs.h"
+#include "message.h"
 #include "protobuf.h"
 
 // -----------------------------------------------------------------------------
-// Basic map operations on top of upb's strtable.
+// Basic map operations on top of upb_map.
 //
 // Note that we roll our own `Map` container here because, as for
 // `RepeatedField`, we want a strongly-typed container. This is so that any user
 // errors due to incorrect map key or value types are raised as close as
 // possible to the error site, rather than at some deferred point (e.g.,
 // serialization).
-//
-// We build our `Map` on top of upb_strtable so that we're able to take
-// advantage of the native_slot storage abstraction, as RepeatedField does.
-// (This is not quite a perfect mapping -- see the key conversions below -- but
-// gives us full support and error-checking for all value types for free.)
 // -----------------------------------------------------------------------------
 
-// Map values are stored using the native_slot abstraction (as with repeated
-// field values), but keys are a bit special. Since we use a strtable, we need
-// to store keys as sequences of bytes such that equality of those bytes maps
-// one-to-one to equality of keys. We store strings directly (i.e., they map to
-// their own bytes) and integers as native integers (using the native_slot
-// abstraction).
-
-// Note that there is another tradeoff here in keeping string keys as native
-// strings rather than Ruby strings: traversing the Map requires conversion to
-// Ruby string values on every traversal, potentially creating more garbage. We
-// should consider ways to cache a Ruby version of the key if this becomes an
-// issue later.
-
-// Forms a key to use with the underlying strtable from a Ruby key value. |buf|
-// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to
-// construct a key byte sequence if needed. |out_key| and |out_length| provide
-// the resulting key data/length.
-#define TABLE_KEY_BUF_LENGTH 8  // sizeof(uint64_t)
-static VALUE table_key(Map* self, VALUE key,
-                       char* buf,
-                       const char** out_key,
-                       size_t* out_length) {
-  switch (self->key_type) {
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_STRING:
-      // Strings: use string content directly.
-      if (TYPE(key) == T_SYMBOL) {
-        key = rb_id2str(SYM2ID(key));
-      }
-      Check_Type(key, T_STRING);
-      key = native_slot_encode_and_freeze_string(self->key_type, key);
-      *out_key = RSTRING_PTR(key);
-      *out_length = RSTRING_LEN(key);
-      break;
-
-    case UPB_TYPE_BOOL:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      native_slot_set("", self->key_type, Qnil, buf, key);
-      *out_key = buf;
-      *out_length = native_slot_size(self->key_type);
-      break;
-
-    default:
-      // Map constructor should not allow a Map with another key type to be
-      // constructed.
-      assert(false);
-      break;
-  }
-
-  return key;
-}
-
-static VALUE table_key_to_ruby(Map* self, upb_strview key) {
-  switch (self->key_type) {
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_STRING: {
-      VALUE ret = rb_str_new(key.data, key.size);
-      rb_enc_associate(ret,
-                       (self->key_type == UPB_TYPE_BYTES) ?
-                       kRubyString8bitEncoding : kRubyStringUtf8Encoding);
-      return ret;
-    }
-
-    case UPB_TYPE_BOOL:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      return native_slot_get(self->key_type, Qnil, key.data);
-
-    default:
-      assert(false);
-      return Qnil;
-  }
-}
-
-static void* value_memory(upb_value* v) {
-  return (void*)(&v->val);
-}
-
 // -----------------------------------------------------------------------------
 // Map container type.
 // -----------------------------------------------------------------------------
 
+typedef struct {
+  const upb_map *map;  // Can convert to mutable when non-frozen.
+  upb_fieldtype_t key_type;
+  TypeInfo value_type_info;
+  VALUE value_type_class;
+  VALUE arena;
+} Map;
+
+static void Map_mark(void* _self) {
+  Map* self = _self;
+  rb_gc_mark(self->value_type_class);
+  rb_gc_mark(self->arena);
+}
+
 const rb_data_type_t Map_type = {
   "Google::Protobuf::Map",
-  { Map_mark, Map_free, NULL },
+  { Map_mark, RUBY_DEFAULT_FREE, NULL },
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
 };
 
 VALUE cMap;
 
-Map* ruby_to_Map(VALUE _self) {
+static Map* ruby_to_Map(VALUE _self) {
   Map* self;
   TypedData_Get_Struct(_self, Map, &Map_type, self);
   return self;
 }
 
-void Map_mark(void* _self) {
-  Map* self = _self;
-
-  rb_gc_mark(self->value_type_class);
-  rb_gc_mark(self->parse_frame);
-
-  if (self->value_type == UPB_TYPE_STRING ||
-      self->value_type == UPB_TYPE_BYTES ||
-      self->value_type == UPB_TYPE_MESSAGE) {
-    upb_strtable_iter it;
-    for (upb_strtable_begin(&it, &self->table);
-         !upb_strtable_done(&it);
-         upb_strtable_next(&it)) {
-      upb_value v = upb_strtable_iter_value(&it);
-      void* mem = value_memory(&v);
-      native_slot_mark(self->value_type, mem);
-    }
-  }
-}
-
-void Map_free(void* _self) {
-  Map* self = _self;
-  upb_strtable_uninit(&self->table);
-  xfree(self);
-}
-
-VALUE Map_alloc(VALUE klass) {
+static VALUE Map_alloc(VALUE klass) {
   Map* self = ALLOC(Map);
-  memset(self, 0, sizeof(Map));
+  self->map = NULL;
   self->value_type_class = Qnil;
+  self->value_type_info.def.msgdef = NULL;
+  self->arena = Qnil;
   return TypedData_Wrap_Struct(klass, &Map_type, self);
 }
 
-VALUE Map_set_frame(VALUE map, VALUE val) {
-  Map* self = ruby_to_Map(map);
-  self->parse_frame = val;
+VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
+                         TypeInfo value_type, VALUE arena) {
+  PBRUBY_ASSERT(map);
+
+  VALUE val = ObjectCache_Get(map);
+
+  if (val == Qnil) {
+    val = Map_alloc(cMap);
+    Map* self;
+    ObjectCache_Add(map, val);
+    TypedData_Get_Struct(val, Map, &Map_type, self);
+    self->map = map;
+    self->arena = arena;
+    self->key_type = key_type;
+    self->value_type_info = value_type;
+    if (self->value_type_info.type == UPB_TYPE_MESSAGE) {
+      const upb_msgdef *val_m = self->value_type_info.def.msgdef;
+      self->value_type_class = Descriptor_DefToClass(val_m);
+    }
+  }
+
   return val;
 }
 
-static bool needs_typeclass(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_MESSAGE:
-    case UPB_TYPE_ENUM:
-      return true;
-    default:
-      return false;
+static VALUE Map_new_this_type(Map *from) {
+  VALUE arena_rb = Arena_new();
+  upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type,
+                             from->value_type_info.type);
+  VALUE ret =
+      Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
+  PBRUBY_ASSERT(ruby_to_Map(ret)->value_type_class == from->value_type_class);
+  return ret;
+}
+
+static TypeInfo Map_keyinfo(Map* self) {
+  TypeInfo ret;
+  ret.type = self->key_type;
+  ret.def.msgdef = NULL;
+  return ret;
+}
+
+static upb_map *Map_GetMutable(VALUE _self) {
+  rb_check_frozen(_self);
+  return (upb_map*)ruby_to_Map(_self)->map;
+}
+
+VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
+                     TypeInfo val_info) {
+  VALUE hash = rb_hash_new();
+  size_t iter = UPB_MAP_BEGIN;
+  TypeInfo key_info = TypeInfo_from_type(key_type);
+
+  if (!map) return hash;
+
+  while (upb_mapiter_next(map, &iter)) {
+    upb_msgval key = upb_mapiter_key(map, iter);
+    upb_msgval val = upb_mapiter_value(map, iter);
+    VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
+    VALUE val_val = Scalar_CreateHash(val, val_info);
+    rb_hash_aset(hash, key_val, val_val);
   }
+
+  return hash;
+}
+
+VALUE Map_deep_copy(VALUE obj) {
+  Map* self = ruby_to_Map(obj);
+  VALUE new_arena_rb = Arena_new();
+  upb_arena *arena = Arena_get(new_arena_rb);
+  upb_map* new_map =
+      upb_map_new(arena, self->key_type, self->value_type_info.type);
+  size_t iter = UPB_MAP_BEGIN;
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    upb_msgval val_copy = Msgval_DeepCopy(val, self->value_type_info, arena);
+    upb_map_set(new_map, key, val_copy, arena);
+  }
+
+  return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
+                            new_arena_rb);
+}
+
+const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
+                             upb_arena* arena) {
+  const upb_fielddef* key_field = map_field_key(field);
+  const upb_fielddef* value_field = map_field_value(field);
+  TypeInfo value_type_info = TypeInfo_get(value_field);
+  Map* self;
+
+  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
+      RTYPEDDATA_TYPE(val) != &Map_type) {
+    rb_raise(cTypeError, "Expected Map instance");
+  }
+
+  self = ruby_to_Map(val);
+  if (self->key_type != upb_fielddef_type(key_field)) {
+    rb_raise(cTypeError, "Map key type does not match field's key type");
+  }
+  if (self->value_type_info.type != value_type_info.type) {
+    rb_raise(cTypeError, "Map value type does not match field's value type");
+  }
+  if (self->value_type_info.def.msgdef != value_type_info.def.msgdef) {
+    rb_raise(cTypeError, "Map value type has wrong message/enum class");
+  }
+
+  Arena_fuse(self->arena, arena);
+  return self->map;
+}
+
+void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
+                 TypeInfo val_type) {
+  bool first = true;
+  TypeInfo key_type_info = {key_type};
+  StringBuilder_Printf(b, "{");
+  if (map) {
+    size_t iter = UPB_MAP_BEGIN;
+    while (upb_mapiter_next(map, &iter)) {
+      upb_msgval key = upb_mapiter_key(map, iter);
+      upb_msgval val = upb_mapiter_value(map, iter);
+      if (first) {
+        first = false;
+      } else {
+        StringBuilder_Printf(b, ", ");
+      }
+      StringBuilder_PrintMsgval(b, key, key_type_info);
+      StringBuilder_Printf(b, "=>");
+      StringBuilder_PrintMsgval(b, val, val_type);
+    }
+  }
+  StringBuilder_Printf(b, "}");
+}
+
+static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  upb_arena *arena = Arena_get(self->arena);
+  upb_msgval key_val = Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
+  upb_msgval val_val = Convert_RubyToUpb(val, "", self->value_type_info, arena);
+  upb_map_set(Map_GetMutable(_self), key_val, val_val, arena);
+  return ST_CONTINUE;
+}
+
+// Used only internally -- shared by #merge and #initialize.
+static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
+  if (TYPE(hashmap) == T_HASH) {
+    rb_hash_foreach(hashmap, merge_into_self_callback, _self);
+  } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
+             RTYPEDDATA_TYPE(hashmap) == &Map_type) {
+    Map* self = ruby_to_Map(_self);
+    Map* other = ruby_to_Map(hashmap);
+    upb_arena *arena = Arena_get(self->arena);
+    upb_msg *self_msg = Map_GetMutable(_self);
+    size_t iter = UPB_MAP_BEGIN;
+
+    Arena_fuse(other->arena, arena);
+
+    if (self->key_type != other->key_type ||
+        self->value_type_info.type != other->value_type_info.type ||
+        self->value_type_class != other->value_type_class) {
+      rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
+    }
+
+    while (upb_mapiter_next(other->map, &iter)) {
+      upb_msgval key = upb_mapiter_key(other->map, iter);
+      upb_msgval val = upb_mapiter_value(other->map, iter);
+      upb_map_set(self_msg, key, val, arena);
+    }
+  } else {
+    rb_raise(rb_eArgError, "Unknown type merging into Map");
+  }
+  return _self;
 }
 
 /*
@@ -224,9 +287,9 @@
  * references to underlying objects will be shared if the value type is a
  * message type.
  */
-VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
+static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  int init_value_arg;
+  VALUE init_arg;
 
   // We take either two args (:key_type, :value_type), three args (:key_type,
   // :value_type, "ValueMessageType"), or four args (the above plus an initial
@@ -236,8 +299,9 @@
   }
 
   self->key_type = ruby_to_fieldtype(argv[0]);
-  self->value_type = ruby_to_fieldtype(argv[1]);
-  self->parse_frame = Qnil;
+  self->value_type_info =
+      TypeInfo_FromClass(argc, argv, 1, &self->value_type_class, &init_arg);
+  self->arena = Arena_new();
 
   // Check that the key type is an allowed type.
   switch (self->key_type) {
@@ -254,21 +318,12 @@
       rb_raise(rb_eArgError, "Invalid key type for map.");
   }
 
-  init_value_arg = 2;
-  if (needs_typeclass(self->value_type) && argc > 2) {
-    self->value_type_class = argv[2];
-    validate_type_class(self->value_type, self->value_type_class);
-    init_value_arg = 3;
-  }
+  self->map = upb_map_new(Arena_get(self->arena), self->key_type,
+                          self->value_type_info.type);
+  ObjectCache_Add(self->map, _self);
 
-  // Table value type is always UINT64: this ensures enough space to store the
-  // native_slot value.
-  if (!upb_strtable_init(&self->table, UPB_CTYPE_UINT64)) {
-    rb_raise(rb_eRuntimeError, "Could not allocate table.");
-  }
-
-  if (argc > init_value_arg) {
-    Map_merge_into_self(_self, argv[init_value_arg]);
+  if (init_arg != Qnil) {
+    Map_merge_into_self(_self, init_arg);
   }
 
   return Qnil;
@@ -282,22 +337,16 @@
  * Note that Map also includes Enumerable; map thus acts like a normal Ruby
  * sequence.
  */
-VALUE Map_each(VALUE _self) {
+static VALUE Map_each(VALUE _self) {
   Map* self = ruby_to_Map(_self);
+  size_t iter = UPB_MAP_BEGIN;
 
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    rb_yield_values(2, key, value);
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
+    VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
+    rb_yield_values(2, key_val, val_val);
   }
 
   return Qnil;
@@ -309,17 +358,15 @@
  *
  * Returns the list of keys contained in the map, in unspecified order.
  */
-VALUE Map_keys(VALUE _self) {
+static VALUE Map_keys(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-
+  size_t iter = UPB_MAP_BEGIN;
   VALUE ret = rb_ary_new();
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
 
-    rb_ary_push(ret, key);
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
+    rb_ary_push(ret, key_val);
   }
 
   return ret;
@@ -331,22 +378,15 @@
  *
  * Returns the list of values contained in the map, in unspecified order.
  */
-VALUE Map_values(VALUE _self) {
+static VALUE Map_values(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-
+  size_t iter = UPB_MAP_BEGIN;
   VALUE ret = rb_ary_new();
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
 
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    rb_ary_push(ret, value);
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
+    rb_ary_push(ret, val_val);
   }
 
   return ret;
@@ -359,18 +399,13 @@
  * Accesses the element at the given key. Throws an exception if the key type is
  * incorrect. Returns nil when the key is not present in the map.
  */
-VALUE Map_index(VALUE _self, VALUE key) {
+static VALUE Map_index(VALUE _self, VALUE key) {
   Map* self = ruby_to_Map(_self);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
+  upb_msgval val;
 
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-  key = table_key(self, key, keybuf, &keyval, &length);
-
-  if (upb_strtable_lookup2(&self->table, keyval, length, &v)) {
-    void* mem = value_memory(&v);
-    return native_slot_get(self->value_type, self->value_type_class, mem);
+  if (upb_map_get(self->map, key_upb, &val)) {
+    return Convert_UpbToRuby(val, self->value_type_info, self->arena);
   } else {
     return Qnil;
   }
@@ -384,33 +419,15 @@
  * Throws an exception if the key type is incorrect. Returns the new value that
  * was just inserted.
  */
-VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
+static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
   Map* self = ruby_to_Map(_self);
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-  void* mem;
-  key = table_key(self, key, keybuf, &keyval, &length);
+  upb_arena *arena = Arena_get(self->arena);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
+  upb_msgval val_upb = Convert_RubyToUpb(val, "", self->value_type_info, arena);
 
-  rb_check_frozen(_self);
+  upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena);
 
-  if (TYPE(value) == T_HASH) {
-    VALUE args[1] = { value };
-    value = rb_class_new_instance(1, args, self->value_type_class);
-  }
-
-  mem = value_memory(&v);
-  native_slot_set("", self->value_type, self->value_type_class, mem, value);
-
-  // Replace any existing value by issuing a 'remove' operation first.
-  upb_strtable_remove2(&self->table, keyval, length, NULL);
-  if (!upb_strtable_insert2(&self->table, keyval, length, v)) {
-    rb_raise(rb_eRuntimeError, "Could not insert into table");
-  }
-
-  // Ruby hashmap's :[]= method also returns the inserted value.
-  return value;
+  return val;
 }
 
 /*
@@ -420,15 +437,11 @@
  * Returns true if the given key is present in the map. Throws an exception if
  * the key has the wrong type.
  */
-VALUE Map_has_key(VALUE _self, VALUE key) {
+static VALUE Map_has_key(VALUE _self, VALUE key) {
   Map* self = ruby_to_Map(_self);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
 
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  key = table_key(self, key, keybuf, &keyval, &length);
-
-  if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) {
+  if (upb_map_get(self->map, key_upb, NULL)) {
     return Qtrue;
   } else {
     return Qfalse;
@@ -442,22 +455,25 @@
  * Deletes the value at the given key, if any, returning either the old value or
  * nil if none was present. Throws an exception if the key is of the wrong type.
  */
-VALUE Map_delete(VALUE _self, VALUE key) {
+static VALUE Map_delete(VALUE _self, VALUE key) {
   Map* self = ruby_to_Map(_self);
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-  key = table_key(self, key, keybuf, &keyval, &length);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
+  upb_msgval val_upb;
+  VALUE ret;
 
   rb_check_frozen(_self);
 
-  if (upb_strtable_remove2(&self->table, keyval, length, &v)) {
-    void* mem = value_memory(&v);
-    return native_slot_get(self->value_type, self->value_type_class, mem);
+  // TODO(haberman): make upb_map_delete() also capable of returning the deleted
+  // value.
+  if (upb_map_get(self->map, key_upb, &val_upb)) {
+    ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
   } else {
-    return Qnil;
+    ret = Qnil;
   }
+
+  upb_map_delete(Map_GetMutable(_self), key_upb);
+
+  return ret;
 }
 
 /*
@@ -466,17 +482,8 @@
  *
  * Removes all entries from the map.
  */
-VALUE Map_clear(VALUE _self) {
-  Map* self = ruby_to_Map(_self);
-
-  rb_check_frozen(_self);
-
-  // Uninit and reinit the table -- this is faster than iterating and doing a
-  // delete-lookup on each key.
-  upb_strtable_uninit(&self->table);
-  if (!upb_strtable_init(&self->table, UPB_CTYPE_INT64)) {
-    rb_raise(rb_eRuntimeError, "Unable to re-initialize table");
-  }
+static VALUE Map_clear(VALUE _self) {
+  upb_map_clear(Map_GetMutable(_self));
   return Qnil;
 }
 
@@ -486,24 +493,9 @@
  *
  * Returns the number of entries (key-value pairs) in the map.
  */
-VALUE Map_length(VALUE _self) {
+static VALUE Map_length(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  return ULL2NUM(upb_strtable_count(&self->table));
-}
-
-VALUE Map_new_this_type(VALUE _self) {
-  Map* self = ruby_to_Map(_self);
-  VALUE new_map = Qnil;
-  VALUE key_type = fieldtype_to_ruby(self->key_type);
-  VALUE value_type = fieldtype_to_ruby(self->value_type);
-  if (self->value_type_class != Qnil) {
-    new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 3,
-                         key_type, value_type, self->value_type_class);
-  } else {
-    new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
-                         key_type, value_type);
-  }
-  return new_map;
+  return ULL2NUM(upb_map_size(self->map));
 }
 
 /*
@@ -513,54 +505,23 @@
  * Duplicates this map with a shallow copy. References to all non-primitive
  * element objects (e.g., submessages) are shared.
  */
-VALUE Map_dup(VALUE _self) {
+static VALUE Map_dup(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  VALUE new_map = Map_new_this_type(_self);
-  Map* new_self = ruby_to_Map(new_map);
+  VALUE new_map_rb = Map_new_this_type(self);
+  Map* new_self = ruby_to_Map(new_map_rb);
+  size_t iter = UPB_MAP_BEGIN;
+  upb_arena *arena = Arena_get(new_self->arena);
+  upb_map *new_map = Map_GetMutable(new_map_rb);
 
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    upb_strview k = upb_strtable_iter_key(&it);
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    upb_value dup;
-    void* dup_mem = value_memory(&dup);
-    native_slot_dup(self->value_type, dup_mem, mem);
+  Arena_fuse(self->arena, arena);
 
-    if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) {
-      rb_raise(rb_eRuntimeError, "Error inserting value into new table");
-    }
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    upb_map_set(new_map, key, val, arena);
   }
 
-  return new_map;
-}
-
-// Used by Google::Protobuf.deep_copy but not exposed directly.
-VALUE Map_deep_copy(VALUE _self) {
-  Map* self = ruby_to_Map(_self);
-  VALUE new_map = Map_new_this_type(_self);
-  Map* new_self = ruby_to_Map(new_map);
-
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    upb_strview k = upb_strtable_iter_key(&it);
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    upb_value dup;
-    void* dup_mem = value_memory(&dup);
-    native_slot_deep_copy(self->value_type, self->value_type_class, dup_mem,
-                          mem);
-
-    if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) {
-      rb_raise(rb_eRuntimeError, "Error inserting value into new table");
-    }
-  }
-
-  return new_map;
+  return new_map_rb;
 }
 
 /*
@@ -579,12 +540,11 @@
 VALUE Map_eq(VALUE _self, VALUE _other) {
   Map* self = ruby_to_Map(_self);
   Map* other;
-  upb_strtable_iter it;
 
   // Allow comparisons to Ruby hashmaps by converting to a temporary Map
   // instance. Slow, but workable.
   if (TYPE(_other) == T_HASH) {
-    VALUE other_map = Map_new_this_type(_self);
+    VALUE other_map = Map_new_this_type(self);
     Map_merge_into_self(other_map, _other);
     _other = other_map;
   }
@@ -595,33 +555,27 @@
     return Qtrue;
   }
   if (self->key_type != other->key_type ||
-      self->value_type != other->value_type ||
+      self->value_type_info.type != other->value_type_info.type ||
       self->value_type_class != other->value_type_class) {
     return Qfalse;
   }
-  if (upb_strtable_count(&self->table) != upb_strtable_count(&other->table)) {
+  if (upb_map_size(self->map) != upb_map_size(other->map)) {
     return Qfalse;
   }
 
   // For each member of self, check that an equal member exists at the same key
   // in other.
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    upb_strview k = upb_strtable_iter_key(&it);
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    upb_value other_v;
-    void* other_mem = value_memory(&other_v);
-
-    if (!upb_strtable_lookup2(&other->table, k.data, k.size, &other_v)) {
+  size_t iter = UPB_MAP_BEGIN;
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    upb_msgval other_val;
+    if (!upb_map_get(other->map, key, &other_val)) {
       // Not present in other map.
       return Qfalse;
     }
-
-    if (!native_slot_eq(self->value_type, self->value_type_class, mem,
-                        other_mem)) {
-      // Present, but value not equal.
+    if (!Msgval_IsEqual(val, other_val, self->value_type_info)) {
+      // Present but different value.
       return Qfalse;
     }
   }
@@ -631,32 +585,40 @@
 
 /*
  * call-seq:
+ *     Message.freeze => self
+ *
+ * Freezes the message object. We have to intercept this so we can pin the
+ * Ruby object into memory so we don't forget it's frozen.
+ */
+static VALUE Map_freeze(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  if (!RB_OBJ_FROZEN(_self)) {
+    Arena_Pin(self->arena, _self);
+    RB_OBJ_FREEZE(_self);
+  }
+  return _self;
+}
+
+/*
+ * call-seq:
  *     Map.hash => hash_value
  *
  * Returns a hash value based on this map's contents.
  */
 VALUE Map_hash(VALUE _self) {
   Map* self = ruby_to_Map(_self);
+  uint64_t hash = 0;
 
-  st_index_t h = rb_hash_start(0);
-  VALUE hash_sym = rb_intern("hash");
-
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(key, hash_sym, 0)));
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(value, hash_sym, 0)));
+  size_t iter = UPB_MAP_BEGIN;
+  TypeInfo key_info = {self->key_type};
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    hash = Msgval_GetHash(key, key_info, hash);
+    hash = Msgval_GetHash(val, self->value_type_info, hash);
   }
 
-  return INT2FIX(h);
+  return LL2NUM(hash);
 }
 
 /*
@@ -667,24 +629,7 @@
  */
 VALUE Map_to_h(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  VALUE hash = rb_hash_new();
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    if (self->value_type == UPB_TYPE_MESSAGE) {
-      value = Message_to_h(value);
-    }
-    rb_hash_aset(hash, key, value);
-  }
-  return hash;
+  return Map_CreateHash(self->map, self->key_type, self->value_type_info);
 }
 
 /*
@@ -698,34 +643,11 @@
 VALUE Map_inspect(VALUE _self) {
   Map* self = ruby_to_Map(_self);
 
-  VALUE str = rb_str_new2("{");
-
-  bool first = true;
-  VALUE inspect_sym = rb_intern("inspect");
-
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    if (!first) {
-      str = rb_str_cat2(str, ", ");
-    } else {
-      first = false;
-    }
-    str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
-    str = rb_str_cat2(str, "=>");
-    str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
-  }
-
-  str = rb_str_cat2(str, "}");
-  return str;
+  StringBuilder* builder = StringBuilder_New();
+  Map_Inspect(builder, self->map, self->key_type, self->value_type_info);
+  VALUE ret = StringBuilder_ToRubyString(builder);
+  StringBuilder_Free(builder);
+  return ret;
 }
 
 /*
@@ -737,79 +659,11 @@
  * in the new copy of this map. Returns the new copy of this map with merged
  * contents.
  */
-VALUE Map_merge(VALUE _self, VALUE hashmap) {
+static VALUE Map_merge(VALUE _self, VALUE hashmap) {
   VALUE dupped = Map_dup(_self);
   return Map_merge_into_self(dupped, hashmap);
 }
 
-static int merge_into_self_callback(VALUE key, VALUE value, VALUE self) {
-  Map_index_set(self, key, value);
-  return ST_CONTINUE;
-}
-
-// Used only internally -- shared by #merge and #initialize.
-VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
-  if (TYPE(hashmap) == T_HASH) {
-    rb_hash_foreach(hashmap, merge_into_self_callback, _self);
-  } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
-             RTYPEDDATA_TYPE(hashmap) == &Map_type) {
-
-    Map* self = ruby_to_Map(_self);
-    Map* other = ruby_to_Map(hashmap);
-    upb_strtable_iter it;
-
-    if (self->key_type != other->key_type ||
-        self->value_type != other->value_type ||
-        self->value_type_class != other->value_type_class) {
-      rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
-    }
-
-    for (upb_strtable_begin(&it, &other->table);
-         !upb_strtable_done(&it);
-         upb_strtable_next(&it)) {
-      upb_strview k = upb_strtable_iter_key(&it);
-
-      // Replace any existing value by issuing a 'remove' operation first.
-      upb_value v;
-      upb_value oldv;
-      upb_strtable_remove2(&self->table, k.data, k.size, &oldv);
-
-      v = upb_strtable_iter_value(&it);
-      upb_strtable_insert2(&self->table, k.data, k.size, v);
-    }
-  } else {
-    rb_raise(rb_eArgError, "Unknown type merging into Map");
-  }
-  return _self;
-}
-
-// Internal method: map iterator initialization (used for serialization).
-void Map_begin(VALUE _self, Map_iter* iter) {
-  Map* self = ruby_to_Map(_self);
-  iter->self = self;
-  upb_strtable_begin(&iter->it, &self->table);
-}
-
-void Map_next(Map_iter* iter) {
-  upb_strtable_next(&iter->it);
-}
-
-bool Map_done(Map_iter* iter) {
-  return upb_strtable_done(&iter->it);
-}
-
-VALUE Map_iter_key(Map_iter* iter) {
-  return table_key_to_ruby(iter->self, upb_strtable_iter_key(&iter->it));
-}
-
-VALUE Map_iter_value(Map_iter* iter) {
-  upb_value v = upb_strtable_iter_value(&iter->it);
-  void* mem = value_memory(&v);
-  return native_slot_get(iter->self->value_type,
-                         iter->self->value_type_class,
-                         mem);
-}
-
 void Map_register(VALUE module) {
   VALUE klass = rb_define_class_under(module, "Map", rb_cObject);
   rb_define_alloc_func(klass, Map_alloc);
@@ -828,6 +682,7 @@
   rb_define_method(klass, "length", Map_length, 0);
   rb_define_method(klass, "dup", Map_dup, 0);
   rb_define_method(klass, "==", Map_eq, 1);
+  rb_define_method(klass, "freeze", Map_freeze, 0);
   rb_define_method(klass, "hash", Map_hash, 0);
   rb_define_method(klass, "to_h", Map_to_h, 0);
   rb_define_method(klass, "inspect", Map_inspect, 0);
diff --git a/ruby/ext/google/protobuf_c/map.h b/ruby/ext/google/protobuf_c/map.h
new file mode 100644
index 0000000..411362c
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/map.h
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_MAP_H_
+#define RUBY_PROTOBUF_MAP_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Returns a Ruby wrapper object for the given map, which will be created if
+// one does not exist already.
+VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type,
+                         TypeInfo value_type, VALUE arena);
+
+// Gets the underlying upb_map for this Ruby map object, which must have
+// key/value type that match |field|. If this is not a map or the type doesn't
+// match, raises an exception.
+const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field,
+                             upb_arena *arena);
+
+// Implements #inspect for this map by appending its contents to |b|.
+void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type,
+                 TypeInfo val_type);
+
+// Returns a new Hash object containing the contents of this Map.
+VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
+                     TypeInfo val_info);
+
+// Returns a deep copy of this Map object.
+VALUE Map_deep_copy(VALUE obj);
+
+// Ruby class of Google::Protobuf::Map.
+extern VALUE cMap;
+
+// Call at startup to register all types in this module.
+void Map_register(VALUE module);
+
+#endif  // RUBY_PROTOBUF_MAP_H_
diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index f57501c..98f89e8 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -28,49 +28,61 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "message.h"
+
+#include "convert.h"
+#include "defs.h"
+#include "map.h"
 #include "protobuf.h"
+#include "repeated_field.h"
+#include "third_party/wyhash/wyhash.h"
+
+static VALUE cParseError = Qnil;
+static ID descriptor_instancevar_interned;
+
+static VALUE initialize_rb_class_with_no_args(VALUE klass) {
+    return rb_funcall(klass, rb_intern("new"), 0);
+}
+
+VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
+  return rb_ivar_get(klass, descriptor_instancevar_interned);
+}
 
 // -----------------------------------------------------------------------------
 // Class/module creation from msgdefs and enumdefs, respectively.
 // -----------------------------------------------------------------------------
 
-void* Message_data(void* msg) {
-  return ((uint8_t *)msg) + sizeof(MessageHeader);
+typedef struct {
+  VALUE arena;
+  const upb_msg* msg;        // Can get as mutable when non-frozen.
+  const upb_msgdef* msgdef;  // kept alive by self.class.descriptor reference.
+} Message;
+
+static void Message_mark(void* _self) {
+  Message* self = (Message *)_self;
+  rb_gc_mark(self->arena);
 }
 
-void Message_mark(void* _self) {
-  MessageHeader* self = (MessageHeader *)_self;
-  layout_mark(self->descriptor->layout, Message_data(self));
-}
-
-void Message_free(void* self) {
-  stringsink* unknown = ((MessageHeader *)self)->unknown_fields;
-  if (unknown != NULL) {
-    stringsink_uninit(unknown);
-    free(unknown);
-  }
-  xfree(self);
-}
-
-rb_data_type_t Message_type = {
+static rb_data_type_t Message_type = {
   "Message",
-  { Message_mark, Message_free, NULL },
+  { Message_mark, RUBY_DEFAULT_FREE, NULL },
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
 };
 
-VALUE Message_alloc(VALUE klass) {
+static Message* ruby_to_Message(VALUE msg_rb) {
+  Message* msg;
+  TypedData_Get_Struct(msg_rb, Message, &Message_type, msg);
+  return msg;
+}
+
+static VALUE Message_alloc(VALUE klass) {
   VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  MessageHeader* msg;
+  Message* msg = ALLOC(Message);
   VALUE ret;
 
-  if (desc->layout == NULL) {
-    create_layout(desc);
-  }
-
-  msg = (void*)ALLOC_N(uint8_t, sizeof(MessageHeader) + desc->layout->size);
-  msg->descriptor = desc;
-  msg->unknown_fields = NULL;
-  memcpy(Message_data(msg), desc->layout->empty_template, desc->layout->size);
+  msg->msgdef = Descriptor_GetMsgDef(descriptor);
+  msg->arena = Qnil;
+  msg->msg = NULL;
 
   ret = TypedData_Wrap_Struct(klass, &Message_type, msg);
   rb_ivar_set(ret, descriptor_instancevar_interned, descriptor);
@@ -78,24 +90,92 @@
   return ret;
 }
 
-static const upb_fielddef* which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
-  uint32_t oneof_case;
-  const upb_fielddef* f;
+const upb_msg *Message_Get(VALUE msg_rb, const upb_msgdef **m) {
+  Message* msg = ruby_to_Message(msg_rb);
+  if (m) *m = msg->msgdef;
+  return msg->msg;
+}
 
-  oneof_case =
-      slot_read_oneof_case(self->descriptor->layout, Message_data(self), o);
+upb_msg *Message_GetMutable(VALUE msg_rb, const upb_msgdef **m) {
+  rb_check_frozen(msg_rb);
+  return (upb_msg*)Message_Get(msg_rb, m);
+}
 
-  if (oneof_case == ONEOF_CASE_NONE) {
-    return NULL;
+void Message_InitPtr(VALUE self_, upb_msg *msg, VALUE arena) {
+  Message* self = ruby_to_Message(self_);
+  self->msg = msg;
+  self->arena = arena;
+  ObjectCache_Add(msg, self_);
+}
+
+VALUE Message_GetArena(VALUE msg_rb) {
+  Message* msg = ruby_to_Message(msg_rb);
+  return msg->arena;
+}
+
+void Message_CheckClass(VALUE klass) {
+  if (rb_get_alloc_func(klass) != &Message_alloc) {
+    rb_raise(rb_eArgError,
+             "Message class was not returned by the DescriptorPool.");
+  }
+}
+
+VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) {
+  if (msg == NULL) return Qnil;
+
+  VALUE val = ObjectCache_Get(msg);
+
+  if (val == Qnil) {
+    VALUE klass = Descriptor_DefToClass(m);
+    val = Message_alloc(klass);
+    Message_InitPtr(val, msg, arena);
   }
 
-  // oneof_case is a field index, so find that field.
-  f = upb_oneofdef_itof(o, oneof_case);
-  assert(f != NULL);
-
-  return f;
+  return val;
 }
 
+void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
+                          const upb_msgdef* m) {
+  bool first = true;
+  int n = upb_msgdef_fieldcount(m);
+  VALUE klass = Descriptor_DefToClass(m);
+  StringBuilder_Printf(b, "<%s: ", rb_class2name(klass));
+
+  for (int i = 0; i < n; i++) {
+    const upb_fielddef* field = upb_msgdef_field(m, i);
+
+    if (upb_fielddef_haspresence(field) && !upb_msg_has(msg, field)) {
+      continue;
+    }
+
+    if (!first) {
+      StringBuilder_Printf(b, ", ");
+    } else {
+      first = false;
+    }
+
+    upb_msgval msgval = upb_msg_get(msg, field);
+
+    StringBuilder_Printf(b, "%s: ", upb_fielddef_name(field));
+
+    if (upb_fielddef_ismap(field)) {
+      const upb_msgdef* entry_m = upb_fielddef_msgsubdef(field);
+      const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1);
+      const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2);
+      TypeInfo val_info = TypeInfo_get(val_f);
+      Map_Inspect(b, msgval.map_val, upb_fielddef_type(key_f), val_info);
+    } else if (upb_fielddef_isseq(field)) {
+      RepeatedField_Inspect(b, msgval.array_val, TypeInfo_get(field));
+    } else {
+      StringBuilder_PrintMsgval(b, msgval, TypeInfo_get(field));
+    }
+  }
+
+  StringBuilder_Printf(b, ">");
+}
+
+// Helper functions for #method_missing ////////////////////////////////////////
+
 enum {
   METHOD_UNKNOWN = 0,
   METHOD_GETTER = 1,
@@ -108,148 +188,203 @@
 };
 
 // Check if the field is a well known wrapper type
-bool is_wrapper_type_field(const upb_fielddef* field) {
-  const upb_msgdef *m;
-  if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
+static bool IsWrapper(const upb_fielddef* f) {
+  return upb_fielddef_issubmsg(f) &&
+         upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f));
+}
+
+static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f,
+                  const upb_oneofdef** o, const char* prefix,
+                  const char* suffix) {
+  size_t sp = strlen(prefix);
+  size_t ss = strlen(suffix);
+  size_t sn = strlen(name);
+
+  if (sn <= sp + ss) return false;
+
+  if (memcmp(name, prefix, sp) != 0 ||
+      memcmp(name + sn - ss, suffix, ss) != 0) {
     return false;
   }
-  m = upb_fielddef_msgsubdef(field);
-  switch (upb_msgdef_wellknowntype(m)) {
-    case UPB_WELLKNOWN_DOUBLEVALUE:
-    case UPB_WELLKNOWN_FLOATVALUE:
-    case UPB_WELLKNOWN_INT64VALUE:
-    case UPB_WELLKNOWN_UINT64VALUE:
-    case UPB_WELLKNOWN_INT32VALUE:
-    case UPB_WELLKNOWN_UINT32VALUE:
-    case UPB_WELLKNOWN_STRINGVALUE:
-    case UPB_WELLKNOWN_BYTESVALUE:
-    case UPB_WELLKNOWN_BOOLVALUE:
-      return true;
-    default:
-      return false;
-  }
+
+  return upb_msgdef_lookupname(m, name + sp, sn - sp - ss, f, o);
 }
 
-// Get a new Ruby wrapper type and set the initial value
-VALUE ruby_wrapper_type(VALUE type_class, VALUE value) {
-  if (value != Qnil) {
-    VALUE hash = rb_hash_new();
-    rb_hash_aset(hash, rb_str_new2("value"), value);
-    {
-      VALUE args[1] = {hash};
-      return rb_class_new_instance(1, args, type_class);
-    }
-  }
-  return Qnil;
-}
-
-static int extract_method_call(VALUE method_name, MessageHeader* self,
-                            const upb_fielddef **f, const upb_oneofdef **o) {
-  VALUE method_str;
-  char* name;
-  size_t name_len;
-  int accessor_type;
-  const upb_oneofdef* test_o;
-  const upb_fielddef* test_f;
-  bool has_field;
+static int extract_method_call(VALUE method_name, Message* self,
+                               const upb_fielddef** f, const upb_oneofdef** o) {
+  const upb_msgdef* m = self->msgdef;
+  const char* name;
 
   Check_Type(method_name, T_SYMBOL);
+  name = rb_id2name(SYM2ID(method_name));
 
-  method_str = rb_id2str(SYM2ID(method_name));
-  name = RSTRING_PTR(method_str);
-  name_len = RSTRING_LEN(method_str);
-
-  if (name[name_len - 1] == '=') {
-    accessor_type = METHOD_SETTER;
-    name_len--;
-    // We want to ensure if the proto has something named clear_foo or has_foo?,
-    // we don't strip the prefix.
-  } else if (strncmp("clear_", name, 6) == 0 &&
-             !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
-                                    &test_f, &test_o)) {
-    accessor_type = METHOD_CLEAR;
-    name = name + 6;
-    name_len = name_len - 6;
-  } else if (strncmp("has_", name, 4) == 0 && name[name_len - 1] == '?' &&
-             !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
-                                    &test_f, &test_o)) {
-    accessor_type = METHOD_PRESENCE;
-    name = name + 4;
-    name_len = name_len - 5;
-  } else {
-    accessor_type = METHOD_GETTER;
+  if (Match(m, name, f, o, "", "")) return METHOD_GETTER;
+  if (Match(m, name, f, o, "", "=")) return METHOD_SETTER;
+  if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
+  if (Match(m, name, f, o, "has_", "?") &&
+      (*o || (*f && upb_fielddef_haspresence(*f)))) {
+    // Disallow oneof hazzers for proto3.
+    // TODO(haberman): remove this test when we are enabling oneof hazzers for
+    // proto3.
+    if (*f && !upb_fielddef_issubmsg(*f) &&
+        upb_fielddef_realcontainingoneof(*f) &&
+        upb_msgdef_syntax(upb_fielddef_containingtype(*f)) !=
+            UPB_SYNTAX_PROTO2) {
+      return METHOD_UNKNOWN;
+    }
+    return METHOD_PRESENCE;
+  }
+  if (Match(m, name, f, o, "", "_as_value") && *f && !upb_fielddef_isseq(*f) &&
+      IsWrapper(*f)) {
+    return METHOD_WRAPPER_GETTER;
+  }
+  if (Match(m, name, f, o, "", "_as_value=") && *f && !upb_fielddef_isseq(*f) &&
+      IsWrapper(*f)) {
+    return METHOD_WRAPPER_SETTER;
+  }
+  if (Match(m, name, f, o, "", "_const") && *f &&
+      upb_fielddef_type(*f) == UPB_TYPE_ENUM) {
+    return METHOD_ENUM_GETTER;
   }
 
-  has_field = upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
-                                    &test_f, &test_o);
+  return METHOD_UNKNOWN;
+}
 
-  // Look for wrapper type accessor of the form <field_name>_as_value
-  if (!has_field &&
-      (accessor_type == METHOD_GETTER || accessor_type == METHOD_SETTER) &&
-      name_len > 9 && strncmp(name + name_len - 9, "_as_value", 9) == 0) {
-    const upb_oneofdef* test_o_wrapper;
-    const upb_fielddef* test_f_wrapper;
-    char wrapper_field_name[name_len - 8];
+static VALUE Message_oneof_accessor(VALUE _self, const upb_oneofdef* o,
+                                    int accessor_type) {
+  Message* self = ruby_to_Message(_self);
+  const upb_fielddef* oneof_field = upb_msg_whichoneof(self->msg, o);
 
-    // Find the field name
-    strncpy(wrapper_field_name, name, name_len - 9);
-    wrapper_field_name[name_len - 9] = '\0';
-
-    // Check if field exists and is a wrapper type
-    if (upb_msgdef_lookupname(self->descriptor->msgdef, wrapper_field_name,
-                              name_len - 9, &test_f_wrapper, &test_o_wrapper) &&
-        is_wrapper_type_field(test_f_wrapper)) {
-      // It does exist!
-      has_field = true;
-      if (accessor_type == METHOD_SETTER) {
-        accessor_type = METHOD_WRAPPER_SETTER;
-      } else {
-        accessor_type = METHOD_WRAPPER_GETTER;
+  switch (accessor_type) {
+    case METHOD_PRESENCE:
+      return oneof_field == NULL ? Qfalse : Qtrue;
+    case METHOD_CLEAR:
+      if (oneof_field != NULL) {
+        upb_msg_clearfield(Message_GetMutable(_self, NULL), oneof_field);
       }
-      test_o = test_o_wrapper;
-      test_f = test_f_wrapper;
+      return Qnil;
+    case METHOD_GETTER:
+      return oneof_field == NULL
+                 ? Qnil
+                 : ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
+    case METHOD_SETTER:
+      rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
+  }
+  rb_raise(rb_eRuntimeError, "Invalid access of oneof field.");
+}
+
+static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val,
+                             upb_arena* arena) {
+  upb_msgval msgval;
+  if (upb_fielddef_ismap(f)) {
+    msgval.map_val = Map_GetUpbMap(val, f, arena);
+  } else if (upb_fielddef_isseq(f)) {
+    msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
+  } else {
+    if (val == Qnil &&
+        (upb_fielddef_issubmsg(f) || upb_fielddef_realcontainingoneof(f))) {
+      upb_msg_clearfield(msg, f);
+      return;
     }
+    msgval =
+        Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena);
   }
+  upb_msg_set(msg, f, msgval, arena);
+}
 
-  // Look for enum accessor of the form <enum_name>_const
-  if (!has_field && accessor_type == METHOD_GETTER &&
-      name_len > 6 && strncmp(name + name_len - 6, "_const", 6) == 0) {
-    const upb_oneofdef* test_o_enum;
-    const upb_fielddef* test_f_enum;
-    char enum_name[name_len - 5];
+VALUE Message_getfield(VALUE _self, const upb_fielddef* f) {
+  Message* self = ruby_to_Message(_self);
+  // This is a special-case: upb_msg_mutable() for map & array are logically
+  // const (they will not change what is serialized) but physically
+  // non-const, as they do allocate a repeated field or map. The logical
+  // constness means it's ok to do even if the message is frozen.
+  upb_msg *msg = (upb_msg*)self->msg;
+  upb_arena *arena = Arena_get(self->arena);
+  if (upb_fielddef_ismap(f)) {
+    upb_map *map = upb_msg_mutable(msg, f, arena).map;
+    const upb_fielddef *key_f = map_field_key(f);
+    const upb_fielddef *val_f = map_field_value(f);
+    upb_fieldtype_t key_type = upb_fielddef_type(key_f);
+    TypeInfo value_type_info = TypeInfo_get(val_f);
+    return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
+  } else if (upb_fielddef_isseq(f)) {
+    upb_array *arr = upb_msg_mutable(msg, f, arena).array;
+    return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
+  } else if (upb_fielddef_issubmsg(f)) {
+    if (!upb_msg_has(self->msg, f)) return Qnil;
+    upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
+    const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+    return Message_GetRubyWrapper(submsg, m, self->arena);
+  } else {
+    upb_msgval msgval = upb_msg_get(self->msg, f);
+    return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
+  }
+}
 
-    // Find enum field name
-    strncpy(enum_name, name, name_len - 6);
-    enum_name[name_len - 6] = '\0';
+static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
+                                    int accessor_type, int argc, VALUE* argv) {
+  upb_arena *arena = Arena_get(Message_GetArena(_self));
 
-    // Check if enum field exists
-    if (upb_msgdef_lookupname(self->descriptor->msgdef, enum_name, name_len - 6,
-                                             &test_f_enum, &test_o_enum) &&
-        upb_fielddef_type(test_f_enum) == UPB_TYPE_ENUM) {
-      // It does exist!
-      has_field = true;
-      accessor_type = METHOD_ENUM_GETTER;
-      test_o = test_o_enum;
-      test_f = test_f_enum;
+  switch (accessor_type) {
+    case METHOD_SETTER:
+      Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
+      return Qnil;
+    case METHOD_CLEAR:
+      upb_msg_clearfield(Message_GetMutable(_self, NULL), f);
+      return Qnil;
+    case METHOD_PRESENCE:
+      if (!upb_fielddef_haspresence(f)) {
+        rb_raise(rb_eRuntimeError, "Field does not have presence.");
+      }
+      return upb_msg_has(Message_Get(_self, NULL), f);
+    case METHOD_WRAPPER_GETTER: {
+      Message* self = ruby_to_Message(_self);
+      if (upb_msg_has(self->msg, f)) {
+        PBRUBY_ASSERT(upb_fielddef_issubmsg(f) && !upb_fielddef_isseq(f));
+        upb_msgval wrapper = upb_msg_get(self->msg, f);
+        const upb_msgdef *wrapper_m = upb_fielddef_msgsubdef(f);
+        const upb_fielddef *value_f = upb_msgdef_itof(wrapper_m, 1);
+        upb_msgval value = upb_msg_get(wrapper.msg_val, value_f);
+        return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
+      } else {
+        return Qnil;
+      }
     }
-  }
+    case METHOD_WRAPPER_SETTER: {
+      upb_msg *msg = Message_GetMutable(_self, NULL);
+      if (argv[1] == Qnil) {
+        upb_msg_clearfield(msg, f);
+      } else {
+        const upb_fielddef *val_f = upb_msgdef_itof(upb_fielddef_msgsubdef(f), 1);
+        upb_msgval msgval = Convert_RubyToUpb(argv[1], upb_fielddef_name(f),
+                                              TypeInfo_get(val_f), arena);
+        upb_msg *wrapper = upb_msg_mutable(msg, f, arena).msg;
+        upb_msg_set(wrapper, val_f, msgval, arena);
+      }
+      return Qnil;
+    }
+    case METHOD_ENUM_GETTER: {
+      upb_msgval msgval = upb_msg_get(Message_Get(_self, NULL), f);
 
-  // Verify the name corresponds to a oneof or field in this message.
-  if (!has_field) {
-    return METHOD_UNKNOWN;
+      if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
+        // Map repeated fields to a new type with ints
+        VALUE arr = rb_ary_new();
+        size_t i, n = upb_array_size(msgval.array_val);
+        for (i = 0; i < n; i++) {
+          upb_msgval elem = upb_array_get(msgval.array_val, i);
+          rb_ary_push(arr, INT2NUM(elem.int32_val));
+        }
+        return arr;
+      } else {
+        return INT2NUM(msgval.int32_val);
+      }
+    }
+    case METHOD_GETTER:
+      return Message_getfield(_self, f);
+    default:
+      rb_raise(rb_eRuntimeError, "Internal error, no such accessor: %d",
+               accessor_type);
   }
-
-  // Method calls like 'has_foo?' are not allowed if field "foo" does not have
-  // a hasbit (e.g. repeated fields or non-message type fields for proto3
-  // syntax).
-  if (accessor_type == METHOD_PRESENCE && test_f != NULL &&
-      !upb_fielddef_haspresence(test_f)) {
-    return METHOD_UNKNOWN;
-  }
-
-  *o = test_o;
-  *f = test_f;
-  return accessor_type;
 }
 
 /*
@@ -279,111 +414,56 @@
  * true if the field 'fieldname' is set in the message object, else false. For
  * 'proto3' syntax, calling this for a basic type field will result in an error.
  */
-VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
-  MessageHeader* self;
+static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
+  Message* self = ruby_to_Message(_self);
   const upb_oneofdef* o;
   const upb_fielddef* f;
   int accessor_type;
 
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
   if (argc < 1) {
     rb_raise(rb_eArgError, "Expected method name as first argument.");
   }
 
   accessor_type = extract_method_call(argv[0], self, &f, &o);
-  if (accessor_type == METHOD_UNKNOWN || (o == NULL && f == NULL) ) {
-    return rb_call_super(argc, argv);
-  } else if (accessor_type == METHOD_SETTER || accessor_type == METHOD_WRAPPER_SETTER) {
-    if (argc != 2) {
-      rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
-    }
-    rb_check_frozen(_self);
-  } else if (argc != 1) {
-    rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc);
+
+  if (accessor_type == METHOD_UNKNOWN) return rb_call_super(argc, argv);
+
+  // Validate argument count.
+  switch (accessor_type) {
+    case METHOD_SETTER:
+    case METHOD_WRAPPER_SETTER:
+      if (argc != 2) {
+        rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
+      }
+      rb_check_frozen(_self);
+      break;
+    default:
+      if (argc != 1) {
+        rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc);
+      }
+      break;
   }
 
-  // Return which of the oneof fields are set
+  // Dispatch accessor.
   if (o != NULL) {
-    const upb_fielddef* oneof_field = which_oneof_field(self, o);
-
-    if (accessor_type == METHOD_SETTER) {
-      rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
-    }
-
-    if (accessor_type == METHOD_PRESENCE) {
-      return oneof_field == NULL ? Qfalse : Qtrue;
-    } else if (accessor_type == METHOD_CLEAR) {
-      if (oneof_field != NULL) {
-        layout_clear(self->descriptor->layout, Message_data(self), oneof_field);
-      }
-      return Qnil;
-    } else {
-      // METHOD_ACCESSOR
-      return oneof_field == NULL ? Qnil :
-        ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
-    }
-  // Otherwise we're operating on a single proto field
-  } else if (accessor_type == METHOD_SETTER) {
-    layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
-    return Qnil;
-  } else if (accessor_type == METHOD_CLEAR) {
-    layout_clear(self->descriptor->layout, Message_data(self), f);
-    return Qnil;
-  } else if (accessor_type == METHOD_PRESENCE) {
-    return layout_has(self->descriptor->layout, Message_data(self), f);
-  } else if (accessor_type == METHOD_WRAPPER_GETTER) {
-    VALUE value = layout_get(self->descriptor->layout, Message_data(self), f);
-    switch (TYPE(value)) {
-      case T_DATA:
-        return rb_funcall(value, rb_intern("value"), 0);
-      case T_NIL:
-        return Qnil;
-      default:
-        return value;
-    }
-  } else if (accessor_type == METHOD_WRAPPER_SETTER) {
-    VALUE wrapper = ruby_wrapper_type(
-        field_type_class(self->descriptor->layout, f), argv[1]);
-    layout_set(self->descriptor->layout, Message_data(self), f, wrapper);
-    return Qnil;
-  } else if (accessor_type == METHOD_ENUM_GETTER) {
-    VALUE enum_type = field_type_class(self->descriptor->layout, f);
-    VALUE method = rb_intern("const_get");
-    VALUE raw_value = layout_get(self->descriptor->layout, Message_data(self), f);
-
-    // Map repeated fields to a new type with ints
-    if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
-      int array_size = FIX2INT(rb_funcall(raw_value, rb_intern("length"), 0));
-      int i;
-      VALUE array_args[1] = { ID2SYM(rb_intern("int64")) };
-      VALUE array = rb_class_new_instance(1, array_args, CLASS_OF(raw_value));
-      for (i = 0; i < array_size; i++) {
-        VALUE entry = rb_funcall(enum_type, method, 1, rb_funcall(raw_value,
-                                 rb_intern("at"), 1, INT2NUM(i)));
-        rb_funcall(array, rb_intern("push"), 1, entry);
-      }
-      return array;
-    }
-    // Convert the value for singular fields
-    return rb_funcall(enum_type, method, 1, raw_value);
+    return Message_oneof_accessor(_self, o, accessor_type);
   } else {
-    return layout_get(self->descriptor->layout, Message_data(self), f);
+    return Message_field_accessor(_self, f, accessor_type, argc, argv);
   }
 }
 
-
-VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
-  MessageHeader* self;
+static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
+  Message* self = ruby_to_Message(_self);
   const upb_oneofdef* o;
   const upb_fielddef* f;
   int accessor_type;
 
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
   if (argc < 1) {
     rb_raise(rb_eArgError, "Expected method name as first argument.");
   }
 
   accessor_type = extract_method_call(argv[0], self, &f, &o);
+
   if (accessor_type == METHOD_UNKNOWN) {
     return rb_call_super(argc, argv);
   } else if (o != NULL) {
@@ -393,17 +473,116 @@
   }
 }
 
-VALUE create_submsg_from_hash(const MessageLayout* layout,
-                              const upb_fielddef* f, VALUE hash) {
-  VALUE args[1] = { hash };
-  return rb_class_new_instance(1, args, field_type_class(layout, f));
+void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
+                           upb_arena* arena);
+
+typedef struct {
+  upb_map *map;
+  TypeInfo key_type;
+  TypeInfo val_type;
+  upb_arena *arena;
+} MapInit;
+
+static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
+  MapInit *map_init = (MapInit*)_self;
+  upb_msgval k, v;
+  k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
+
+  if (map_init->val_type.type == UPB_TYPE_MESSAGE && TYPE(val) == T_HASH) {
+    upb_msg *msg = upb_msg_new(map_init->val_type.def.msgdef, map_init->arena);
+    Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
+                          map_init->arena);
+    v.msg_val = msg;
+  } else {
+    v = Convert_RubyToUpb(val, "", map_init->val_type, map_init->arena);
+  }
+  upb_map_set(map_init->map, k, v, map_init->arena);
+  return ST_CONTINUE;
 }
 
-int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
-  MessageHeader* self;
-  char *name;
-  const upb_fielddef* f;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static void Map_InitFromValue(upb_map* map, const upb_fielddef* f, VALUE val,
+                       upb_arena* arena) {
+  const upb_msgdef* entry_m = upb_fielddef_msgsubdef(f);
+  const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1);
+  const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2);
+  if (TYPE(val) != T_HASH) {
+    rb_raise(rb_eArgError,
+             "Expected Hash object as initializer value for map field '%s' "
+             "(given %s).",
+             upb_fielddef_name(f), rb_class2name(CLASS_OF(val)));
+  }
+  MapInit map_init = {map, TypeInfo_get(key_f), TypeInfo_get(val_f), arena};
+  rb_hash_foreach(val, Map_initialize_kwarg, (VALUE)&map_init);
+}
+
+static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info,
+                                         upb_arena* arena) {
+  if (info.type == UPB_TYPE_MESSAGE) {
+    upb_msgval msgval;
+    upb_msg* msg = upb_msg_new(info.def.msgdef, arena);
+    Message_InitFromValue(msg, info.def.msgdef, val, arena);
+    msgval.msg_val = msg;
+    return msgval;
+  } else {
+    return Convert_RubyToUpb(val, "", info, arena);
+  }
+}
+
+static void RepeatedField_InitFromValue(upb_array* arr, const upb_fielddef* f,
+                                        VALUE val, upb_arena* arena) {
+  TypeInfo type_info = TypeInfo_get(f);
+
+  if (TYPE(val) != T_ARRAY) {
+    rb_raise(rb_eArgError,
+             "Expected array as initializer value for repeated field '%s' (given %s).",
+             upb_fielddef_name(f), rb_class2name(CLASS_OF(val)));
+  }
+
+  for (int i = 0; i < RARRAY_LEN(val); i++) {
+    VALUE entry = rb_ary_entry(val, i);
+    upb_msgval msgval;
+    if (upb_fielddef_issubmsg(f) && TYPE(entry) == T_HASH) {
+      msgval = MessageValue_FromValue(entry, type_info, arena);
+    } else {
+      msgval = Convert_RubyToUpb(entry, upb_fielddef_name(f), type_info, arena);
+    }
+    upb_array_append(arr, msgval, arena);
+  }
+}
+
+static void Message_InitFieldFromValue(upb_msg* msg, const upb_fielddef* f,
+                                       VALUE val, upb_arena* arena) {
+  if (TYPE(val) == T_NIL) return;
+
+  if (upb_fielddef_ismap(f)) {
+    upb_map *map = upb_msg_mutable(msg, f, arena).map;
+    Map_InitFromValue(map, f, val, arena);
+  } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
+    upb_array *arr = upb_msg_mutable(msg, f, arena).array;
+    RepeatedField_InitFromValue(arr, f, val, arena);
+  } else if (upb_fielddef_issubmsg(f)) {
+    if (TYPE(val) == T_HASH) {
+      upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
+      Message_InitFromValue(submsg, upb_fielddef_msgsubdef(f), val, arena);
+    } else {
+      Message_setfield(msg, f, val, arena);
+    }
+  } else {
+    upb_msgval msgval =
+        Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena);
+    upb_msg_set(msg, f, msgval, arena);
+  }
+}
+
+typedef struct {
+  upb_msg *msg;
+  const upb_msgdef *msgdef;
+  upb_arena *arena;
+} MsgInit;
+
+static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
+  MsgInit *msg_init = (MsgInit*)_self;
+  const char *name;
 
   if (TYPE(key) == T_STRING) {
     name = RSTRING_PTR(key);
@@ -414,52 +593,26 @@
              "Expected string or symbols as hash keys when initializing proto from hash.");
   }
 
-  f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
+  const upb_fielddef* f = upb_msgdef_ntofz(msg_init->msgdef, name);
+
   if (f == NULL) {
     rb_raise(rb_eArgError,
              "Unknown field name '%s' in initialization map entry.", name);
   }
 
-  if (TYPE(val) == T_NIL) {
-    return 0;
-  }
+  Message_InitFieldFromValue(msg_init->msg, f, val, msg_init->arena);
+  return ST_CONTINUE;
+}
 
-  if (is_map_field(f)) {
-    VALUE map;
-
-    if (TYPE(val) != T_HASH) {
-      rb_raise(rb_eArgError,
-               "Expected Hash object as initializer value for map field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-    map = layout_get(self->descriptor->layout, Message_data(self), f);
-    Map_merge_into_self(map, val);
-  } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
-    VALUE ary;
-    int i;
-
-    if (TYPE(val) != T_ARRAY) {
-      rb_raise(rb_eArgError,
-               "Expected array as initializer value for repeated field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-    ary = layout_get(self->descriptor->layout, Message_data(self), f);
-    for (i = 0; i < RARRAY_LEN(val); i++) {
-      VALUE entry = rb_ary_entry(val, i);
-      if (TYPE(entry) == T_HASH && upb_fielddef_issubmsg(f)) {
-        entry = create_submsg_from_hash(self->descriptor->layout, f, entry);
-      }
-
-      RepeatedField_push(ary, entry);
-    }
+void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
+                           upb_arena* arena) {
+  MsgInit msg_init = {msg, m, arena};
+  if (TYPE(val) == T_HASH) {
+    rb_hash_foreach(val, Message_initialize_kwarg, (VALUE)&msg_init);
   } else {
-    if (TYPE(val) == T_HASH && upb_fielddef_issubmsg(f)) {
-      val = create_submsg_from_hash(self->descriptor->layout, f, val);
-    }
-
-    layout_set(self->descriptor->layout, Message_data(self), f, val);
+    rb_raise(rb_eArgError, "Expected hash arguments or message, not %s",
+             rb_class2name(CLASS_OF(val)));
   }
-  return 0;
 }
 
 /*
@@ -474,12 +627,13 @@
  * have been added to a pool. The method definitions described here on the
  * Message class are provided on each concrete message class.
  */
-VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
-  MessageHeader* self;
-  VALUE hash_args;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  VALUE arena_rb = Arena_new();
+  upb_arena *arena = Arena_get(arena_rb);
+  upb_msg *msg = upb_msg_new(self->msgdef, arena);
 
-  layout_init(self->descriptor->layout, Message_data(self));
+  Message_InitPtr(_self, msg, arena_rb);
 
   if (argc == 0) {
     return Qnil;
@@ -487,12 +641,7 @@
   if (argc != 1) {
     rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
   }
-  hash_args = argv[0];
-  if (TYPE(hash_args) != T_HASH) {
-    rb_raise(rb_eArgError, "Expected hash arguments.");
-  }
-
-  rb_hash_foreach(hash_args, Message_initialize_kwarg, _self);
+  Message_InitFromValue((upb_msg*)self->msg, self->msgdef, argv[0], arena);
   return Qnil;
 }
 
@@ -502,37 +651,40 @@
  *
  * Performs a shallow copy of this message and returns the new copy.
  */
-VALUE Message_dup(VALUE _self) {
-  MessageHeader* self;
-  VALUE new_msg;
-  MessageHeader* new_msg_self;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_dup(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
+  Message* new_msg_self = ruby_to_Message(new_msg);
+  size_t size = upb_msgdef_layout(self->msgdef)->size;
 
-  new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
-  TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
-
-  layout_dup(self->descriptor->layout,
-             Message_data(new_msg_self),
-             Message_data(self));
-
+  // TODO(copy unknown fields?)
+  // TODO(use official upb msg copy function)
+  memcpy((upb_msg*)new_msg_self->msg, self->msg, size);
+  Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
   return new_msg;
 }
 
-// Internal only; used by Google::Protobuf.deep_copy.
-VALUE Message_deep_copy(VALUE _self) {
-  MessageHeader* self;
-  MessageHeader* new_msg_self;
-  VALUE new_msg;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+// Support function for Message_eq, and also used by other #eq functions.
+bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) {
+  if (m1 == m2) return true;
 
-  new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
-  TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
+  size_t size1, size2;
+  int encode_opts = UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC;
+  upb_arena *arena_tmp = upb_arena_new();
+  const upb_msglayout *layout = upb_msgdef_layout(m);
 
-  layout_deep_copy(self->descriptor->layout,
-                   Message_data(new_msg_self),
-                   Message_data(self));
+  // Compare deterministically serialized payloads with no unknown fields.
+  char *data1 = upb_encode_ex(m1, layout, encode_opts, arena_tmp, &size1);
+  char *data2 = upb_encode_ex(m2, layout, encode_opts, arena_tmp, &size2);
 
-  return new_msg;
+  if (data1 && data2) {
+    bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
+    upb_arena_free(arena_tmp);
+    return ret;
+  } else {
+    upb_arena_free(arena_tmp);
+    rb_raise(cParseError, "Error comparing messages");
+  }
 }
 
 /*
@@ -544,22 +696,34 @@
  * method's semantics (a more efficient comparison may actually be done if the
  * field is of a primitive type).
  */
-VALUE Message_eq(VALUE _self, VALUE _other) {
-  MessageHeader* self;
-  MessageHeader* other;
-  if (TYPE(_self) != TYPE(_other)) {
-    return Qfalse;
-  }
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
-  TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
+static VALUE Message_eq(VALUE _self, VALUE _other) {
+  if (CLASS_OF(_self) != CLASS_OF(_other)) return Qfalse;
 
-  if (self->descriptor != other->descriptor) {
-    return Qfalse;
-  }
+  Message* self = ruby_to_Message(_self);
+  Message* other = ruby_to_Message(_other);
+  assert(self->msgdef == other->msgdef);
 
-  return layout_eq(self->descriptor->layout,
-                   Message_data(self),
-                   Message_data(other));
+  return Message_Equal(self->msg, other->msg, self->msgdef) ? Qtrue : Qfalse;
+}
+
+uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
+  upb_arena *arena = upb_arena_new();
+  const char *data;
+  size_t size;
+
+  // Hash a deterministically serialized payloads with no unknown fields.
+  data = upb_encode_ex(msg, upb_msgdef_layout(m),
+                       UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC, arena,
+                       &size);
+
+  if (data) {
+    uint64_t ret = wyhash(data, size, seed, _wyp);
+    upb_arena_free(arena);
+    return ret;
+  } else {
+    upb_arena_free(arena);
+    rb_raise(cParseError, "Error calculating hash");
+  }
 }
 
 /*
@@ -568,11 +732,12 @@
  *
  * Returns a hash value that represents this message's field values.
  */
-VALUE Message_hash(VALUE _self) {
-  MessageHeader* self;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
-
-  return layout_hash(self->descriptor->layout, Message_data(self));
+static VALUE Message_hash(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  uint64_t hash_value = Message_Hash(self->msg, self->msgdef, 0);
+  // RUBY_FIXNUM_MAX should be one less than a power of 2.
+  assert((RUBY_FIXNUM_MAX & (RUBY_FIXNUM_MAX + 1)) == 0);
+  return INT2FIX(hash_value & RUBY_FIXNUM_MAX);
 }
 
 /*
@@ -583,18 +748,99 @@
  * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
  * field's value is represented according to its own #inspect method.
  */
-VALUE Message_inspect(VALUE _self) {
-  MessageHeader* self;
-  VALUE str;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_inspect(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
 
-  str = rb_str_new2("<");
-  str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
-  str = rb_str_cat2(str, ": ");
-  str = rb_str_append(str, layout_inspect(
-      self->descriptor->layout, Message_data(self)));
-  str = rb_str_cat2(str, ">");
-  return str;
+  StringBuilder* builder = StringBuilder_New();
+  Message_PrintMessage(builder, self->msg, self->msgdef);
+  VALUE ret = StringBuilder_ToRubyString(builder);
+  StringBuilder_Free(builder);
+  return ret;
+}
+
+// Support functions for Message_to_h //////////////////////////////////////////
+
+static VALUE RepeatedField_CreateArray(const upb_array* arr,
+                                       TypeInfo type_info) {
+  int size = arr ? upb_array_size(arr) : 0;
+  VALUE ary = rb_ary_new2(size);
+
+  for (int i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(arr, i);
+    VALUE val = Scalar_CreateHash(msgval, type_info);
+    rb_ary_push(ary, val);
+  }
+
+  return ary;
+}
+
+static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
+  if (!msg) return Qnil;
+
+  VALUE hash = rb_hash_new();
+  int n = upb_msgdef_fieldcount(m);
+  bool is_proto2;
+
+  // We currently have a few behaviors that are specific to proto2.
+  // This is unfortunate, we should key behaviors off field attributes (like
+  // whether a field has presence), not proto2 vs. proto3. We should see if we
+  // can change this without breaking users.
+  is_proto2 = upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2;
+
+  for (int i = 0; i < n; i++) {
+    const upb_fielddef* field = upb_msgdef_field(m, i);
+    TypeInfo type_info = TypeInfo_get(field);
+    upb_msgval msgval;
+    VALUE msg_value;
+    VALUE msg_key;
+
+    if (!is_proto2 && upb_fielddef_issubmsg(field) &&
+        !upb_fielddef_isseq(field) && !upb_msg_has(msg, field)) {
+      // TODO: Legacy behavior, remove when we fix the is_proto2 differences.
+      msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
+      rb_hash_aset(hash, msg_key, Qnil);
+      continue;
+    }
+
+    // Do not include fields that are not present (oneof or optional fields).
+    if (is_proto2 && upb_fielddef_haspresence(field) &&
+        !upb_msg_has(msg, field)) {
+      continue;
+    }
+
+    msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
+    msgval = upb_msg_get(msg, field);
+
+    // Proto2 omits empty map/repeated filds also.
+
+    if (upb_fielddef_ismap(field)) {
+      const upb_msgdef *entry_m = upb_fielddef_msgsubdef(field);
+      const upb_fielddef *key_f = upb_msgdef_itof(entry_m, 1);
+      const upb_fielddef *val_f = upb_msgdef_itof(entry_m, 2);
+      upb_fieldtype_t key_type = upb_fielddef_type(key_f);
+      msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f));
+    } else if (upb_fielddef_isseq(field)) {
+      if (is_proto2 &&
+          (!msgval.array_val || upb_array_size(msgval.array_val) == 0)) {
+        continue;
+      }
+      msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
+    } else {
+      msg_value = Scalar_CreateHash(msgval, type_info);
+    }
+
+    rb_hash_aset(hash, msg_key, msg_value);
+  }
+
+  return hash;
+}
+
+VALUE Scalar_CreateHash(upb_msgval msgval, TypeInfo type_info) {
+  if (type_info.type == UPB_TYPE_MESSAGE) {
+    return Message_CreateHash(msgval.msg_val, type_info.def.msgdef);
+  } else {
+    return Convert_UpbToRuby(msgval, type_info, Qnil);
+  }
 }
 
 /*
@@ -603,57 +849,26 @@
  *
  * Returns the message as a Ruby Hash object, with keys as symbols.
  */
-VALUE Message_to_h(VALUE _self) {
-  MessageHeader* self;
-  VALUE hash;
-  upb_msg_field_iter it;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
-
-  hash = rb_hash_new();
-
-  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE msg_value;
-    VALUE msg_key;
-
-    // For proto2, do not include fields which are not set.
-    if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
-       field_contains_hasbit(self->descriptor->layout, field) &&
-       !layout_has(self->descriptor->layout, Message_data(self), field)) {
-      continue;
-    }
-
-    msg_value = layout_get(self->descriptor->layout, Message_data(self), field);
-    msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
-    if (is_map_field(field)) {
-      msg_value = Map_to_h(msg_value);
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      msg_value = RepeatedField_to_ary(msg_value);
-      if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
-          RARRAY_LEN(msg_value) == 0) {
-        continue;
-      }
-
-      if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-        int i;
-        for (i = 0; i < RARRAY_LEN(msg_value); i++) {
-          VALUE elem = rb_ary_entry(msg_value, i);
-          rb_ary_store(msg_value, i, Message_to_h(elem));
-        }
-      }
-
-    } else if (msg_value != Qnil &&
-               upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-      msg_value = Message_to_h(msg_value);
-    }
-    rb_hash_aset(hash, msg_key, msg_value);
-  }
-  return hash;
+static VALUE Message_to_h(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  return Message_CreateHash(self->msg, self->msgdef);
 }
 
-
+/*
+ * call-seq:
+ *     Message.freeze => self
+ *
+ * Freezes the message object. We have to intercept this so we can pin the
+ * Ruby object into memory so we don't forget it's frozen.
+ */
+static VALUE Message_freeze(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  if (!RB_OBJ_FROZEN(_self)) {
+    Arena_Pin(self->arena, _self);
+    RB_OBJ_FREEZE(_self);
+  }
+  return _self;
+}
 
 /*
  * call-seq:
@@ -662,16 +877,18 @@
  * Accesses a field's value by field name. The provided field name should be a
  * string.
  */
-VALUE Message_index(VALUE _self, VALUE field_name) {
-  MessageHeader* self;
+static VALUE Message_index(VALUE _self, VALUE field_name) {
+  Message* self = ruby_to_Message(_self);
   const upb_fielddef* field;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
   Check_Type(field_name, T_STRING);
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
+  field = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name));
+
   if (field == NULL) {
     return Qnil;
   }
-  return layout_get(self->descriptor->layout, Message_data(self), field);
+
+  return Message_getfield(_self, field);
 }
 
 /*
@@ -681,36 +898,224 @@
  * Sets a field's value by field name. The provided field name should be a
  * string.
  */
-VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
-  MessageHeader* self;
-  const upb_fielddef* field;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
+  Message* self = ruby_to_Message(_self);
+  const upb_fielddef* f;
+  upb_msgval val;
+  upb_arena *arena = Arena_get(self->arena);
+
   Check_Type(field_name, T_STRING);
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
-  if (field == NULL) {
+  f = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name));
+
+  if (f == NULL) {
     rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
   }
-  layout_set(self->descriptor->layout, Message_data(self), field, value);
+
+  val = Convert_RubyToUpb(value, upb_fielddef_name(f), TypeInfo_get(f), arena);
+  upb_msg_set(Message_GetMutable(_self, NULL), f, val, arena);
+
   return Qnil;
 }
 
 /*
  * call-seq:
+ *     MessageClass.decode(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+static VALUE Message_decode(VALUE klass, VALUE data) {
+  if (TYPE(data) != T_STRING) {
+    rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
+  }
+
+  VALUE msg_rb = initialize_rb_class_with_no_args(klass);
+  Message* msg = ruby_to_Message(msg_rb);
+
+  if (!upb_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg,
+                 upb_msgdef_layout(msg->msgdef),
+                 Arena_get(msg->arena))) {
+    rb_raise(cParseError, "Error occurred during parsing");
+  }
+
+  return msg_rb;
+}
+
+/*
+ * call-seq:
+ *     MessageClass.decode_json(data, options = {}) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ *
+ *  @param options [Hash] options for the decoder
+ *   ignore_unknown_fields: set true to ignore unknown fields (default is to
+ *   raise an error)
+ */
+static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
+  VALUE data = argv[0];
+  int options = 0;
+  upb_status status;
+
+  // TODO(haberman): use this message's pool instead.
+  const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
+
+  if (argc < 1 || argc > 2) {
+    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
+  }
+
+  if (argc == 2) {
+    VALUE hash_args = argv[1];
+    if (TYPE(hash_args) != T_HASH) {
+      rb_raise(rb_eArgError, "Expected hash arguments.");
+    }
+
+    if (RTEST(rb_hash_lookup2( hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) {
+      options |= UPB_JSONDEC_IGNOREUNKNOWN;
+    }
+  }
+
+  if (TYPE(data) != T_STRING) {
+    rb_raise(rb_eArgError, "Expected string for JSON data.");
+  }
+
+  // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
+  // convert, because string handlers pass data directly to message string
+  // fields.
+
+  VALUE msg_rb = initialize_rb_class_with_no_args(klass);
+  Message* msg = ruby_to_Message(msg_rb);
+
+  // We don't allow users to decode a wrapper type directly.
+  if (upb_msgdef_iswrapper(msg->msgdef)) {
+    rb_raise(rb_eRuntimeError, "Cannot parse a wrapper directly.");
+  }
+
+  upb_status_clear(&status);
+  if (!upb_json_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg,
+                       msg->msgdef, symtab, options,
+                       Arena_get(msg->arena), &status)) {
+    rb_raise(cParseError, "Error occurred during parsing: %s",
+             upb_status_errmsg(&status));
+  }
+
+  return msg_rb;
+}
+
+/*
+ * call-seq:
+ *     MessageClass.encode(msg) => bytes
+ *
+ * Encodes the given message object to its serialized form in protocol buffers
+ * wire format.
+ */
+static VALUE Message_encode(VALUE klass, VALUE msg_rb) {
+  Message* msg = ruby_to_Message(msg_rb);
+  upb_arena *arena = upb_arena_new();
+  const char *data;
+  size_t size;
+
+  if (CLASS_OF(msg_rb) != klass) {
+    rb_raise(rb_eArgError, "Message of wrong type.");
+  }
+
+  data = upb_encode(msg->msg, upb_msgdef_layout(msg->msgdef), arena,
+                    &size);
+
+  if (data) {
+    VALUE ret = rb_str_new(data, size);
+    rb_enc_associate(ret, rb_ascii8bit_encoding());
+    upb_arena_free(arena);
+    return ret;
+  } else {
+    upb_arena_free(arena);
+    rb_raise(rb_eRuntimeError, "Exceeded maximum depth (possibly cycle)");
+  }
+}
+
+/*
+ * call-seq:
+ *     MessageClass.encode_json(msg, options = {}) => json_string
+ *
+ * Encodes the given message object into its serialized JSON representation.
+ * @param options [Hash] options for the decoder
+ *  preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
+ *  emit_defaults: set true to emit 0/false values (default is to omit them)
+ */
+static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
+  Message* msg = ruby_to_Message(argv[0]);
+  int options = 0;
+  char buf[1024];
+  size_t size;
+  upb_status status;
+
+  // TODO(haberman): use this message's pool instead.
+  const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
+
+  if (argc < 1 || argc > 2) {
+    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
+  }
+
+  if (argc == 2) {
+    VALUE hash_args = argv[1];
+    if (TYPE(hash_args) != T_HASH) {
+      rb_raise(rb_eArgError, "Expected hash arguments.");
+    }
+
+    if (RTEST(rb_hash_lookup2(hash_args,
+                              ID2SYM(rb_intern("preserve_proto_fieldnames")),
+                              Qfalse))) {
+      options |= UPB_JSONENC_PROTONAMES;
+    }
+
+    if (RTEST(rb_hash_lookup2(hash_args, ID2SYM(rb_intern("emit_defaults")),
+                              Qfalse))) {
+      options |= UPB_JSONENC_EMITDEFAULTS;
+    }
+  }
+
+  upb_status_clear(&status);
+  size = upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf,
+                         sizeof(buf), &status);
+
+  if (!upb_ok(&status)) {
+    rb_raise(cParseError, "Error occurred during encoding: %s",
+             upb_status_errmsg(&status));
+  }
+
+  VALUE ret;
+  if (size >= sizeof(buf)) {
+    char* buf2 = malloc(size + 1);
+    upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1,
+                    &status);
+    ret = rb_str_new(buf2, size);
+    free(buf2);
+  } else {
+    ret = rb_str_new(buf, size);
+  }
+
+  rb_enc_associate(ret, rb_utf8_encoding());
+  return ret;
+}
+
+/*
+ * call-seq:
  *     Message.descriptor => descriptor
  *
  * Class method that returns the Descriptor instance corresponding to this
  * message class's type.
  */
-VALUE Message_descriptor(VALUE klass) {
+static VALUE Message_descriptor(VALUE klass) {
   return rb_ivar_get(klass, descriptor_instancevar_interned);
 }
 
 VALUE build_class_from_descriptor(VALUE descriptor) {
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
   const char *name;
   VALUE klass;
 
-  name = upb_msgdef_fullname(desc->msgdef);
+  name = upb_msgdef_fullname(Descriptor_GetMsgDef(descriptor));
   if (name == NULL) {
     rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
   }
@@ -737,6 +1142,7 @@
   rb_define_method(klass, "clone", Message_dup, 0);
   rb_define_method(klass, "==", Message_eq, 1);
   rb_define_method(klass, "eql?", Message_eq, 1);
+  rb_define_method(klass, "freeze", Message_freeze, 0);
   rb_define_method(klass, "hash", Message_hash, 0);
   rb_define_method(klass, "to_h", Message_to_h, 0);
   rb_define_method(klass, "inspect", Message_inspect, 0);
@@ -759,12 +1165,12 @@
  * This module method, provided on each generated enum module, looks up an enum
  * value by number and returns its name as a Ruby symbol, or nil if not found.
  */
-VALUE enum_lookup(VALUE self, VALUE number) {
+static VALUE enum_lookup(VALUE self, VALUE number) {
   int32_t num = NUM2INT(number);
   VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
-  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+  const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc);
 
-  const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
+  const char* name = upb_enumdef_iton(e, num);
   if (name == NULL) {
     return Qnil;
   } else {
@@ -779,13 +1185,13 @@
  * This module method, provided on each generated enum module, looks up an enum
  * value by name (as a Ruby symbol) and returns its name, or nil if not found.
  */
-VALUE enum_resolve(VALUE self, VALUE sym) {
+static VALUE enum_resolve(VALUE self, VALUE sym) {
   const char* name = rb_id2name(SYM2ID(sym));
   VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
-  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+  const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc);
 
   int32_t num = 0;
-  bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num);
+  bool found = upb_enumdef_ntoiz(e, name, &num);
   if (!found) {
     return Qnil;
   } else {
@@ -800,17 +1206,16 @@
  * This module method, provided on each generated enum module, returns the
  * EnumDescriptor corresponding to this enum type.
  */
-VALUE enum_descriptor(VALUE self) {
+static VALUE enum_descriptor(VALUE self) {
   return rb_ivar_get(self, descriptor_instancevar_interned);
 }
 
 VALUE build_module_from_enumdesc(VALUE _enumdesc) {
-  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(_enumdesc);
-  VALUE mod = rb_define_module_id(
-      rb_intern(upb_enumdef_fullname(enumdesc->enumdef)));
+  const upb_enumdef *e = EnumDescriptor_GetEnumDef(_enumdesc);
+  VALUE mod = rb_define_module_id(rb_intern(upb_enumdef_fullname(e)));
 
   upb_enum_iter it;
-  for (upb_enum_begin(&it, enumdesc->enumdef);
+  for (upb_enum_begin(&it, e);
        !upb_enum_done(&it);
        upb_enum_next(&it)) {
     const char* name = upb_enum_iter_name(&it);
@@ -831,20 +1236,94 @@
   return mod;
 }
 
-/*
- * call-seq:
- *     Google::Protobuf.deep_copy(obj) => copy_of_obj
- *
- * Performs a deep copy of a RepeatedField instance, a Map instance, or a
- * message object, recursively copying its members.
- */
-VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
-  VALUE klass = CLASS_OF(obj);
-  if (klass == cRepeatedField) {
-    return RepeatedField_deep_copy(obj);
-  } else if (klass == cMap) {
-    return Map_deep_copy(obj);
-  } else {
-    return Message_deep_copy(obj);
+// Internal only; used by Google::Protobuf.deep_copy.
+upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
+                           upb_arena *arena) {
+  // Serialize and parse.
+  upb_arena *tmp_arena = upb_arena_new();
+  const upb_msglayout *layout = upb_msgdef_layout(m);
+  size_t size;
+
+  char* data = upb_encode_ex(msg, layout, 0, tmp_arena, &size);
+  upb_msg* new_msg = upb_msg_new(m, arena);
+
+  if (!data || !upb_decode(data, size, new_msg, layout, arena)) {
+    upb_arena_free(tmp_arena);
+    rb_raise(cParseError, "Error occurred copying proto");
   }
+
+  upb_arena_free(tmp_arena);
+  return new_msg;
+}
+
+const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
+                                     const char* name, upb_arena* arena) {
+  if (value == Qnil) {
+    rb_raise(cTypeError, "nil message not allowed here.");
+  }
+
+  VALUE klass = CLASS_OF(value);
+  VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned);
+  const upb_msgdef* val_m =
+      desc_rb == Qnil ? NULL : Descriptor_GetMsgDef(desc_rb);
+
+  if (val_m != m) {
+    // Check for possible implicit conversions
+    // TODO: hash conversion?
+
+    switch (upb_msgdef_wellknowntype(m)) {
+      case UPB_WELLKNOWN_TIMESTAMP: {
+        // Time -> Google::Protobuf::Timestamp
+        upb_msg *msg = upb_msg_new(m, arena);
+        upb_msgval sec, nsec;
+        struct timespec time;
+        const upb_fielddef *sec_f = upb_msgdef_itof(m, 1);
+        const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2);
+
+        if (!rb_obj_is_kind_of(value, rb_cTime)) goto badtype;
+
+        time = rb_time_timespec(value);
+        sec.int64_val = time.tv_sec;
+        nsec.int32_val = time.tv_nsec;
+        upb_msg_set(msg, sec_f, sec, arena);
+        upb_msg_set(msg, nsec_f, nsec, arena);
+        return msg;
+      }
+      case UPB_WELLKNOWN_DURATION: {
+        // Numeric -> Google::Protobuf::Duration
+        upb_msg *msg = upb_msg_new(m, arena);
+        upb_msgval sec, nsec;
+        const upb_fielddef *sec_f = upb_msgdef_itof(m, 1);
+        const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2);
+
+        if (!rb_obj_is_kind_of(value, rb_cNumeric)) goto badtype;
+
+        sec.int64_val = NUM2LL(value);
+        nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
+        upb_msg_set(msg, sec_f, sec, arena);
+        upb_msg_set(msg, nsec_f, nsec, arena);
+        return msg;
+      }
+      default:
+      badtype:
+        rb_raise(cTypeError,
+                 "Invalid type %s to assign to submessage field '%s'.",
+                rb_class2name(CLASS_OF(value)), name);
+    }
+
+  }
+
+  Message* self = ruby_to_Message(value);
+  Arena_fuse(self->arena, arena);
+
+  return self->msg;
+}
+
+void Message_register(VALUE protobuf) {
+  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
+
+  // Ruby-interned string: "descriptor". We use this identifier to store an
+  // instance variable on message classes we create in order to link them back
+  // to their descriptors.
+  descriptor_instancevar_interned = rb_intern("descriptor");
 }
diff --git a/ruby/ext/google/protobuf_c/message.h b/ruby/ext/google/protobuf_c/message.h
new file mode 100644
index 0000000..2ec440c
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/message.h
@@ -0,0 +1,101 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_MESSAGE_H_
+#define RUBY_PROTOBUF_MESSAGE_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Gets the underlying upb_msg* and upb_msgdef for the given Ruby message
+// wrapper. Requires that |value| is indeed a message object.
+const upb_msg *Message_Get(VALUE value, const upb_msgdef **m);
+
+// Like Message_Get(), but checks that the object is not frozen and returns a
+// mutable pointer.
+upb_msg *Message_GetMutable(VALUE value, const upb_msgdef **m);
+
+// Returns the Arena object for this message.
+VALUE Message_GetArena(VALUE value);
+
+// Converts |value| into a upb_msg value of the expected upb_msgdef type,
+// raising an error if this is not possible. Used when assigning |value| to a
+// field of another message, which means the message must be of a particular
+// type.
+//
+// This will perform automatic conversions in some cases (for example, Time ->
+// Google::Protobuf::Timestamp). If any new message is created, it will be
+// created on |arena|, and any existing message will have its arena fused with
+// |arena|.
+const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
+                                     const char* name, upb_arena* arena);
+
+// Gets or constructs a Ruby wrapper object for the given message. The wrapper
+// object will reference |arena| and ensure that it outlives this object.
+VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena);
+
+// Gets the given field from this message.
+VALUE Message_getfield(VALUE _self, const upb_fielddef* f);
+
+// Implements #inspect for this message, printing the text to |b|.
+void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
+                          const upb_msgdef* m);
+
+// Returns a hash value for the given message.
+uint64_t Message_Hash(const upb_msg *msg, const upb_msgdef *m, uint64_t seed);
+
+// Returns a deep copy of the given message.
+upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
+                           upb_arena *arena);
+
+// Returns true if these two messages are equal.
+bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
+
+// Checks that this Ruby object is a message, and raises an exception if not.
+void Message_CheckClass(VALUE klass);
+
+// Returns a new Hash object containing the contents of this message.
+VALUE Scalar_CreateHash(upb_msgval val, TypeInfo type_info);
+
+// Creates a message class or enum module for this descriptor, respectively.
+VALUE build_class_from_descriptor(VALUE descriptor);
+VALUE build_module_from_enumdesc(VALUE _enumdesc);
+
+// Returns the Descriptor/EnumDescriptor for the given message class or enum
+// module, respectively. Returns nil if this is not a message class or enum
+// module.
+VALUE MessageOrEnum_GetDescriptor(VALUE klass);
+
+// Call at startup to register all types in this module.
+void Message_register(VALUE protobuf);
+
+#endif  // RUBY_PROTOBUF_MESSAGE_H_
diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index 60c1e2a..a61328b 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -30,62 +30,414 @@
 
 #include "protobuf.h"
 
-VALUE cError;
+#include <ruby/version.h>
+
+#include "defs.h"
+#include "map.h"
+#include "message.h"
+#include "repeated_field.h"
+
 VALUE cParseError;
 VALUE cTypeError;
-VALUE c_only_cookie = Qnil;
 
-static VALUE cached_empty_string = Qnil;
-static VALUE cached_empty_bytes = Qnil;
-
-static VALUE create_frozen_string(const char* str, size_t size, bool binary) {
-  VALUE str_rb = rb_str_new(str, size);
-
-  rb_enc_associate(str_rb,
-                   binary ? kRubyString8bitEncoding : kRubyStringUtf8Encoding);
-  rb_obj_freeze(str_rb);
-  return str_rb;
+const upb_fielddef* map_field_key(const upb_fielddef* field) {
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(field);
+  return upb_msgdef_itof(entry, 1);
 }
 
-VALUE get_frozen_string(const char* str, size_t size, bool binary) {
-  if (size == 0) {
-    return binary ? cached_empty_bytes : cached_empty_string;
+const upb_fielddef* map_field_value(const upb_fielddef* field) {
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(field);
+  return upb_msgdef_itof(entry, 2);
+}
+
+// -----------------------------------------------------------------------------
+// StringBuilder, for inspect
+// -----------------------------------------------------------------------------
+
+struct StringBuilder {
+  size_t size;
+  size_t cap;
+  char *data;
+};
+
+typedef struct StringBuilder StringBuilder;
+
+static size_t StringBuilder_SizeOf(size_t cap) {
+  return sizeof(StringBuilder) + cap;
+}
+
+StringBuilder* StringBuilder_New() {
+  const size_t cap = 128;
+  StringBuilder* builder = malloc(sizeof(*builder));
+  builder->size = 0;
+  builder->cap = cap;
+  builder->data = malloc(builder->cap);
+  return builder;
+}
+
+void StringBuilder_Free(StringBuilder* b) {
+  free(b->data);
+  free(b);
+}
+
+void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...) {
+  size_t have = b->cap - b->size;
+  size_t n;
+  va_list args;
+
+  va_start(args, fmt);
+  n = vsnprintf(&b->data[b->size], have, fmt, args);
+  va_end(args);
+
+  if (have <= n) {
+    while (have <= n) {
+      b->cap *= 2;
+      have = b->cap - b->size;
+    }
+    b->data = realloc(b->data, StringBuilder_SizeOf(b->cap));
+    va_start(args, fmt);
+    n = vsnprintf(&b->data[b->size], have, fmt, args);
+    va_end(args);
+    PBRUBY_ASSERT(n < have);
+  }
+
+  b->size += n;
+}
+
+VALUE StringBuilder_ToRubyString(StringBuilder* b) {
+  VALUE ret = rb_str_new(b->data, b->size);
+  rb_enc_associate(ret, rb_utf8_encoding());
+  return ret;
+}
+
+static void StringBuilder_PrintEnum(StringBuilder* b, int32_t val,
+                                    const upb_enumdef* e) {
+  const char *name = upb_enumdef_iton(e, val);
+  if (name) {
+    StringBuilder_Printf(b, ":%s", name);
   } else {
-    // It is harder to memoize non-empty strings.  The obvious approach would be
-    // to use a Ruby hash keyed by string as memo table, but looking up in such a table
-    // requires constructing a string (the very thing we're trying to avoid).
-    //
-    // Since few fields have defaults, we will just optimize the empty string
-    // case for now.
-    return create_frozen_string(str, size, binary);
+    StringBuilder_Printf(b, "%" PRId32, val);
+  }
+}
+
+void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val,
+                               TypeInfo info) {
+  switch (info.type) {
+    case UPB_TYPE_BOOL:
+      StringBuilder_Printf(b, "%s", val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_FLOAT: {
+      VALUE str = rb_inspect(DBL2NUM(val.float_val));
+      StringBuilder_Printf(b, "%s", RSTRING_PTR(str));
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      VALUE str = rb_inspect(DBL2NUM(val.double_val));
+      StringBuilder_Printf(b, "%s", RSTRING_PTR(str));
+      break;
+    }
+    case UPB_TYPE_INT32:
+      StringBuilder_Printf(b, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      StringBuilder_Printf(b, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      StringBuilder_Printf(b, "%" PRId64, val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      StringBuilder_Printf(b, "%" PRIu64, val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data);
+      break;
+    case UPB_TYPE_BYTES:
+      StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data);
+      break;
+    case UPB_TYPE_ENUM:
+      StringBuilder_PrintEnum(b, val.int32_val, info.def.enumdef);
+      break;
+    case UPB_TYPE_MESSAGE:
+      Message_PrintMessage(b, val.msg_val, info.def.msgdef);
+      break;
   }
 }
 
 // -----------------------------------------------------------------------------
-// Utilities.
+// Arena
 // -----------------------------------------------------------------------------
 
-// Raises a Ruby error if |status| is not OK, using its error message.
-void check_upb_status(const upb_status* status, const char* msg) {
-  if (!upb_ok(status)) {
-    rb_raise(rb_eRuntimeError, "%s: %s\n", msg, upb_status_errmsg(status));
+typedef struct {
+  upb_arena *arena;
+  VALUE pinned_objs;
+} Arena;
+
+static void Arena_mark(void *data) {
+  Arena *arena = data;
+  rb_gc_mark(arena->pinned_objs);
+}
+
+static void Arena_free(void *data) {
+  Arena *arena = data;
+  upb_arena_free(arena->arena);
+  xfree(arena);
+}
+
+static VALUE cArena;
+
+const rb_data_type_t Arena_type = {
+  "Google::Protobuf::Internal::Arena",
+  { Arena_mark, Arena_free, NULL },
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static VALUE Arena_alloc(VALUE klass) {
+  Arena *arena = ALLOC(Arena);
+  arena->arena = upb_arena_new();
+  arena->pinned_objs = Qnil;
+  return TypedData_Wrap_Struct(klass, &Arena_type, arena);
+}
+
+upb_arena *Arena_get(VALUE _arena) {
+  Arena *arena;
+  TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
+  return arena->arena;
+}
+
+void Arena_fuse(VALUE _arena, upb_arena *other) {
+  Arena *arena;
+  TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
+  if (!upb_arena_fuse(arena->arena, other)) {
+    rb_raise(rb_eRuntimeError,
+             "Unable to fuse arenas. This should never happen since Ruby does "
+             "not use initial blocks");
   }
 }
 
-// String encodings: we look these up once, at load time, and then cache them
-// here.
-rb_encoding* kRubyStringUtf8Encoding;
-rb_encoding* kRubyStringASCIIEncoding;
-rb_encoding* kRubyString8bitEncoding;
+VALUE Arena_new() {
+  return Arena_alloc(cArena);
+}
 
-// Ruby-interned string: "descriptor". We use this identifier to store an
-// instance variable on message classes we create in order to link them back to
-// their descriptors.
+void Arena_Pin(VALUE _arena, VALUE obj) {
+  Arena *arena;
+  TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
+  if (arena->pinned_objs == Qnil) {
+    arena->pinned_objs = rb_ary_new();
+  }
+  rb_ary_push(arena->pinned_objs, obj);
+}
+
+void Arena_register(VALUE module) {
+  VALUE internal = rb_define_module_under(module, "Internal");
+  VALUE klass = rb_define_class_under(internal, "Arena", rb_cObject);
+  rb_define_alloc_func(klass, Arena_alloc);
+  rb_gc_register_address(&cArena);
+  cArena = klass;
+}
+
+// -----------------------------------------------------------------------------
+// Object Cache
+// -----------------------------------------------------------------------------
+
+// A pointer -> Ruby Object cache that keeps references to Ruby wrapper
+// objects.  This allows us to look up any Ruby wrapper object by the address
+// of the object it is wrapping. That way we can avoid ever creating two
+// different wrapper objects for the same C object, which saves memory and
+// preserves object identity.
 //
-// We intern this once at module load time then use the interned identifier at
-// runtime in order to avoid the cost of repeatedly interning in hot paths.
-const char* kDescriptorInstanceVar = "descriptor";
-ID descriptor_instancevar_interned;
+// We use WeakMap for the cache. For Ruby <2.7 we also need a secondary Hash
+// to store WeakMap keys because Ruby <2.7 WeakMap doesn't allow non-finalizable
+// keys.
+//
+// We also need the secondary Hash if sizeof(long) < sizeof(VALUE), because this
+// means it may not be possible to fit a pointer into a Fixnum. Keys are
+// pointers, and if they fit into a Fixnum, Ruby doesn't collect them, but if
+// they overflow and require allocating a Bignum, they could get collected
+// prematurely, thus removing the cache entry. This happens on 64-bit Windows,
+// on which pointers are 64 bits but longs are 32 bits. In this case, we enable
+// the secondary Hash to hold the keys and prevent them from being collected.
+
+#if RUBY_API_VERSION_CODE >= 20700 && SIZEOF_LONG >= SIZEOF_VALUE
+#define USE_SECONDARY_MAP 0
+#else
+#define USE_SECONDARY_MAP 1
+#endif
+
+#if USE_SECONDARY_MAP
+
+// Maps Numeric -> Object. The object is then used as a key into the WeakMap.
+// This is needed for Ruby <2.7 where a number cannot be a key to WeakMap.
+// The object is used only for its identity; it does not contain any data.
+VALUE secondary_map = Qnil;
+
+// Mutations to the map are under a mutex, because SeconaryMap_MaybeGC()
+// iterates over the map which cannot happen in parallel with insertions, or
+// Ruby will throw:
+//   can't add a new key into hash during iteration (RuntimeError)
+VALUE secondary_map_mutex = Qnil;
+
+// Lambda that will GC entries from the secondary map that are no longer present
+// in the primary map.
+VALUE gc_secondary_map_lambda = Qnil;
+ID length;
+
+extern VALUE weak_obj_cache;
+
+static void SecondaryMap_Init() {
+  rb_gc_register_address(&secondary_map);
+  rb_gc_register_address(&gc_secondary_map_lambda);
+  rb_gc_register_address(&secondary_map_mutex);
+  secondary_map = rb_hash_new();
+  gc_secondary_map_lambda = rb_eval_string(
+      "->(secondary, weak) {\n"
+      "  secondary.delete_if { |k, v| !weak.key?(v) }\n"
+      "}\n");
+  secondary_map_mutex = rb_mutex_new();
+  length = rb_intern("length");
+}
+
+// The secondary map is a regular Hash, and will never shrink on its own.
+// The main object cache is a WeakMap that will automatically remove entries
+// when the target object is no longer reachable, but unless we manually
+// remove the corresponding entries from the secondary map, it will grow
+// without bound.
+//
+// To avoid this unbounded growth we periodically remove entries from the
+// secondary map that are no longer present in the WeakMap. The logic of
+// how often to perform this GC is an artbirary tuning parameter that
+// represents a straightforward CPU/memory tradeoff.
+//
+// Requires: secondary_map_mutex is held.
+static void SecondaryMap_MaybeGC() {
+  PBRUBY_ASSERT(rb_mutex_locked_p(secondary_map_mutex) == Qtrue);
+  size_t weak_len = NUM2ULL(rb_funcall(weak_obj_cache, length, 0));
+  size_t secondary_len = RHASH_SIZE(secondary_map);
+  if (secondary_len < weak_len) {
+    // Logically this case should not be possible: a valid entry cannot exist in
+    // the weak table unless there is a corresponding entry in the secondary
+    // table. It should *always* be the case that secondary_len >= weak_len.
+    //
+    // However ObjectSpace::WeakMap#length (and therefore weak_len) is
+    // unreliable: it overreports its true length by including non-live objects.
+    // However these non-live objects are not yielded in iteration, so we may
+    // have previously deleted them from the secondary map in a previous
+    // invocation of SecondaryMap_MaybeGC().
+    //
+    // In this case, we can't measure any waste, so we just return.
+    return;
+  }
+  size_t waste = secondary_len - weak_len;
+  // GC if we could remove at least 2000 entries or 20% of the table size
+  // (whichever is greater).  Since the cost of the GC pass is O(N), we
+  // want to make sure that we condition this on overall table size, to
+  // avoid O(N^2) CPU costs.
+  size_t threshold = PBRUBY_MAX(secondary_len * 0.2, 2000);
+  if (waste > threshold) {
+    rb_funcall(gc_secondary_map_lambda, rb_intern("call"), 2,
+               secondary_map, weak_obj_cache);
+  }
+}
+
+// Requires: secondary_map_mutex is held by this thread iff create == true.
+static VALUE SecondaryMap_Get(VALUE key, bool create) {
+  PBRUBY_ASSERT(!create || rb_mutex_locked_p(secondary_map_mutex) == Qtrue);
+  VALUE ret = rb_hash_lookup(secondary_map, key);
+  if (ret == Qnil && create) {
+    SecondaryMap_MaybeGC();
+    ret = rb_class_new_instance(0, NULL, rb_cObject);
+    rb_hash_aset(secondary_map, key, ret);
+  }
+  return ret;
+}
+
+#endif
+
+// Requires: secondary_map_mutex is held by this thread iff create == true.
+static VALUE ObjectCache_GetKey(const void* key, bool create) {
+  VALUE key_val = (VALUE)key;
+  PBRUBY_ASSERT((key_val & 3) == 0);
+  VALUE ret = LL2NUM(key_val >> 2);
+#if USE_SECONDARY_MAP
+  ret = SecondaryMap_Get(ret, create);
+#endif
+  return ret;
+}
+
+// Public ObjectCache API.
+
+VALUE weak_obj_cache = Qnil;
+ID item_get;
+ID item_set;
+
+static void ObjectCache_Init() {
+  rb_gc_register_address(&weak_obj_cache);
+  VALUE klass = rb_eval_string("ObjectSpace::WeakMap");
+  weak_obj_cache = rb_class_new_instance(0, NULL, klass);
+  item_get = rb_intern("[]");
+  item_set = rb_intern("[]=");
+#if USE_SECONDARY_MAP
+  SecondaryMap_Init();
+#endif
+}
+
+void ObjectCache_Add(const void* key, VALUE val) {
+  PBRUBY_ASSERT(ObjectCache_Get(key) == Qnil);
+#if USE_SECONDARY_MAP
+  rb_mutex_lock(secondary_map_mutex);
+#endif
+  VALUE key_rb = ObjectCache_GetKey(key, true);
+  rb_funcall(weak_obj_cache, item_set, 2, key_rb, val);
+#if USE_SECONDARY_MAP
+  rb_mutex_unlock(secondary_map_mutex);
+#endif
+  PBRUBY_ASSERT(ObjectCache_Get(key) == val);
+}
+
+// Returns the cached object for this key, if any. Otherwise returns Qnil.
+VALUE ObjectCache_Get(const void* key) {
+  VALUE key_rb = ObjectCache_GetKey(key, false);
+  return rb_funcall(weak_obj_cache, item_get, 1, key_rb);
+}
+
+/*
+ * call-seq:
+ *     Google::Protobuf.discard_unknown(msg)
+ *
+ * Discard unknown fields in the given message object and recursively discard
+ * unknown fields in submessages.
+ */
+static VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) {
+  const upb_msgdef *m;
+  upb_msg *msg = Message_GetMutable(msg_rb, &m);
+  if (!upb_msg_discardunknown(msg, m, 128)) {
+    rb_raise(rb_eRuntimeError, "Messages nested too deeply.");
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Google::Protobuf.deep_copy(obj) => copy_of_obj
+ *
+ * Performs a deep copy of a RepeatedField instance, a Map instance, or a
+ * message object, recursively copying its members.
+ */
+VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
+  VALUE klass = CLASS_OF(obj);
+  if (klass == cRepeatedField) {
+    return RepeatedField_deep_copy(obj);
+  } else if (klass == cMap) {
+    return Map_deep_copy(obj);
+  } else {
+    VALUE new_arena_rb = Arena_new();
+    upb_arena *new_arena = Arena_get(new_arena_rb);
+    const upb_msgdef *m;
+    const upb_msg *msg = Message_Get(obj, &m);
+    upb_msg* new_msg = Message_deep_copy(msg, m, new_arena);
+    return Message_GetRubyWrapper(new_msg, m, new_arena_rb);
+  }
+}
 
 // -----------------------------------------------------------------------------
 // Initialization/entry point.
@@ -93,44 +445,26 @@
 
 // This must be named "Init_protobuf_c" because the Ruby module is named
 // "protobuf_c" -- the VM looks for this symbol in our .so.
+__attribute__ ((visibility ("default")))
 void Init_protobuf_c() {
+  ObjectCache_Init();
+
   VALUE google = rb_define_module("Google");
   VALUE protobuf = rb_define_module_under(google, "Protobuf");
-  VALUE internal = rb_define_module_under(protobuf, "Internal");
 
-  descriptor_instancevar_interned = rb_intern(kDescriptorInstanceVar);
-  DescriptorPool_register(protobuf);
-  Descriptor_register(protobuf);
-  FileDescriptor_register(protobuf);
-  FieldDescriptor_register(protobuf);
-  OneofDescriptor_register(protobuf);
-  EnumDescriptor_register(protobuf);
-  MessageBuilderContext_register(internal);
-  OneofBuilderContext_register(internal);
-  EnumBuilderContext_register(internal);
-  FileBuilderContext_register(internal);
-  Builder_register(internal);
+  Arena_register(protobuf);
+  Defs_register(protobuf);
   RepeatedField_register(protobuf);
   Map_register(protobuf);
+  Message_register(protobuf);
 
-  cError = rb_const_get(protobuf, rb_intern("Error"));
   cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
+  rb_gc_register_mark_object(cParseError);
   cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
+  rb_gc_register_mark_object(cTypeError);
 
   rb_define_singleton_method(protobuf, "discard_unknown",
                              Google_Protobuf_discard_unknown, 1);
   rb_define_singleton_method(protobuf, "deep_copy",
                              Google_Protobuf_deep_copy, 1);
-
-  kRubyStringUtf8Encoding = rb_utf8_encoding();
-  kRubyStringASCIIEncoding = rb_usascii_encoding();
-  kRubyString8bitEncoding = rb_ascii8bit_encoding();
-
-  rb_gc_register_address(&c_only_cookie);
-  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
-
-  rb_gc_register_address(&cached_empty_string);
-  rb_gc_register_address(&cached_empty_bytes);
-  cached_empty_string = create_frozen_string("", 0, false);
-  cached_empty_bytes = create_frozen_string("", 0, true);
 }
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index ae9895c..f7ac204 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -35,632 +35,83 @@
 #include <ruby/vm.h>
 #include <ruby/encoding.h>
 
-#include "upb.h"
-
-// Forward decls.
-struct DescriptorPool;
-struct Descriptor;
-struct FileDescriptor;
-struct FieldDescriptor;
-struct EnumDescriptor;
-struct MessageLayout;
-struct MessageField;
-struct MessageHeader;
-struct MessageBuilderContext;
-struct EnumBuilderContext;
-struct FileBuilderContext;
-struct Builder;
-
-typedef struct DescriptorPool DescriptorPool;
-typedef struct Descriptor Descriptor;
-typedef struct FileDescriptor FileDescriptor;
-typedef struct FieldDescriptor FieldDescriptor;
-typedef struct OneofDescriptor OneofDescriptor;
-typedef struct EnumDescriptor EnumDescriptor;
-typedef struct MessageLayout MessageLayout;
-typedef struct MessageField MessageField;
-typedef struct MessageOneof MessageOneof;
-typedef struct MessageHeader MessageHeader;
-typedef struct MessageBuilderContext MessageBuilderContext;
-typedef struct OneofBuilderContext OneofBuilderContext;
-typedef struct EnumBuilderContext EnumBuilderContext;
-typedef struct FileBuilderContext FileBuilderContext;
-typedef struct Builder Builder;
-
-/*
- It can be a bit confusing how the C structs defined below and the Ruby
- objects interact and hold references to each other. First, a few principles:
-
- - Ruby's "TypedData" abstraction lets a Ruby VALUE hold a pointer to a C
-   struct (or arbitrary memory chunk), own it, and free it when collected.
-   Thus, each struct below will have a corresponding Ruby object
-   wrapping/owning it.
-
- - To get back from an underlying upb {msg,enum}def to the Ruby object, we
-   keep a global hashmap, accessed by get_def_obj/add_def_obj below.
-
- The in-memory structure is then something like:
-
-   Ruby                        |      upb
-                               |
-   DescriptorPool  ------------|-----------> upb_symtab____________________
-                               |                | (message types)          \
-                               |                v                           \
-   Descriptor   ---------------|-----------> upb_msgdef         (enum types)|
-    |--> msgclass              |                |   ^                       |
-    |    (dynamically built)   |                |   | (submsg fields)       |
-    |--> MessageLayout         |                |   |                       /
-    |--------------------------|> decoder method|   |                      /
-    \--------------------------|> serialize     |   |                     /
-                               |  handlers      v   |                    /
-   FieldDescriptor  -----------|-----------> upb_fielddef               /
-                               |                    |                  /
-                               |                    v (enum fields)   /
-   EnumDescriptor  ------------|-----------> upb_enumdef  <----------'
-                               |
-                               |
-               ^               |               \___/
-               `---------------|-----------------'    (get_def_obj map)
- */
-
-// -----------------------------------------------------------------------------
-// Ruby class structure definitions.
-// -----------------------------------------------------------------------------
-
-struct DescriptorPool {
-  VALUE def_to_descriptor;  // Hash table of def* -> Ruby descriptor.
-  upb_symtab* symtab;
-  upb_handlercache* fill_handler_cache;
-  upb_handlercache* pb_serialize_handler_cache;
-  upb_handlercache* json_serialize_handler_cache;
-  upb_handlercache* json_serialize_handler_preserve_cache;
-  upb_pbcodecache* fill_method_cache;
-  upb_json_codecache* json_fill_method_cache;
-};
-
-struct Descriptor {
-  const upb_msgdef* msgdef;
-  MessageLayout* layout;
-  VALUE klass;
-  VALUE descriptor_pool;
-};
-
-struct FileDescriptor {
-  const upb_filedef* filedef;
-  VALUE descriptor_pool;  // Owns the upb_filedef.
-};
-
-struct FieldDescriptor {
-  const upb_fielddef* fielddef;
-  VALUE descriptor_pool;  // Owns the upb_fielddef.
-};
-
-struct OneofDescriptor {
-  const upb_oneofdef* oneofdef;
-  VALUE descriptor_pool;  // Owns the upb_oneofdef.
-};
-
-struct EnumDescriptor {
-  const upb_enumdef* enumdef;
-  VALUE module;  // begins as nil
-  VALUE descriptor_pool;  // Owns the upb_enumdef.
-};
-
-struct MessageBuilderContext {
-  google_protobuf_DescriptorProto* msg_proto;
-  VALUE file_builder;
-};
-
-struct OneofBuilderContext {
-  int oneof_index;
-  VALUE message_builder;
-};
-
-struct EnumBuilderContext {
-  google_protobuf_EnumDescriptorProto* enum_proto;
-  VALUE file_builder;
-};
-
-struct FileBuilderContext {
-  upb_arena *arena;
-  google_protobuf_FileDescriptorProto* file_proto;
-  VALUE descriptor_pool;
-};
-
-struct Builder {
-  VALUE descriptor_pool;
-  VALUE default_file_builder;
-};
-
-extern VALUE cDescriptorPool;
-extern VALUE cDescriptor;
-extern VALUE cFileDescriptor;
-extern VALUE cFieldDescriptor;
-extern VALUE cEnumDescriptor;
-extern VALUE cMessageBuilderContext;
-extern VALUE cOneofBuilderContext;
-extern VALUE cEnumBuilderContext;
-extern VALUE cFileBuilderContext;
-extern VALUE cBuilder;
-
-extern VALUE cError;
-extern VALUE cParseError;
-extern VALUE cTypeError;
-
-// We forward-declare all of the Ruby method implementations here because we
-// sometimes call the methods directly across .c files, rather than going
-// through Ruby's method dispatching (e.g. during message parse). It's cleaner
-// to keep the list of object methods together than to split them between
-// static-in-file definitions and header declarations.
-
-void DescriptorPool_mark(void* _self);
-void DescriptorPool_free(void* _self);
-VALUE DescriptorPool_alloc(VALUE klass);
-void DescriptorPool_register(VALUE module);
-DescriptorPool* ruby_to_DescriptorPool(VALUE value);
-VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self);
-VALUE DescriptorPool_lookup(VALUE _self, VALUE name);
-VALUE DescriptorPool_generated_pool(VALUE _self);
-
-extern VALUE generated_pool;
-
-void Descriptor_mark(void* _self);
-void Descriptor_free(void* _self);
-VALUE Descriptor_alloc(VALUE klass);
-void Descriptor_register(VALUE module);
-Descriptor* ruby_to_Descriptor(VALUE value);
-VALUE Descriptor_initialize(VALUE _self, VALUE cookie, VALUE descriptor_pool,
-                            VALUE ptr);
-VALUE Descriptor_name(VALUE _self);
-VALUE Descriptor_each(VALUE _self);
-VALUE Descriptor_lookup(VALUE _self, VALUE name);
-VALUE Descriptor_each_oneof(VALUE _self);
-VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
-VALUE Descriptor_msgclass(VALUE _self);
-VALUE Descriptor_file_descriptor(VALUE _self);
-extern const rb_data_type_t _Descriptor_type;
-
-void FileDescriptor_mark(void* _self);
-void FileDescriptor_free(void* _self);
-VALUE FileDescriptor_alloc(VALUE klass);
-void FileDescriptor_register(VALUE module);
-FileDescriptor* ruby_to_FileDescriptor(VALUE value);
-VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr);
-VALUE FileDescriptor_name(VALUE _self);
-VALUE FileDescriptor_syntax(VALUE _self);
-
-void FieldDescriptor_mark(void* _self);
-void FieldDescriptor_free(void* _self);
-VALUE FieldDescriptor_alloc(VALUE klass);
-void FieldDescriptor_register(VALUE module);
-FieldDescriptor* ruby_to_FieldDescriptor(VALUE value);
-VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr);
-VALUE FieldDescriptor_name(VALUE _self);
-VALUE FieldDescriptor_type(VALUE _self);
-VALUE FieldDescriptor_default(VALUE _self);
-VALUE FieldDescriptor_label(VALUE _self);
-VALUE FieldDescriptor_number(VALUE _self);
-VALUE FieldDescriptor_submsg_name(VALUE _self);
-VALUE FieldDescriptor_subtype(VALUE _self);
-VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb);
-VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb);
-VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb);
-VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
-upb_fieldtype_t ruby_to_fieldtype(VALUE type);
-VALUE fieldtype_to_ruby(upb_fieldtype_t type);
-
-void OneofDescriptor_mark(void* _self);
-void OneofDescriptor_free(void* _self);
-VALUE OneofDescriptor_alloc(VALUE klass);
-void OneofDescriptor_register(VALUE module);
-OneofDescriptor* ruby_to_OneofDescriptor(VALUE value);
-VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr);
-VALUE OneofDescriptor_name(VALUE _self);
-VALUE OneofDescriptor_each(VALUE _self);
-
-void EnumDescriptor_mark(void* _self);
-void EnumDescriptor_free(void* _self);
-VALUE EnumDescriptor_alloc(VALUE klass);
-VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr);
-void EnumDescriptor_register(VALUE module);
-EnumDescriptor* ruby_to_EnumDescriptor(VALUE value);
-VALUE EnumDescriptor_file_descriptor(VALUE _self);
-VALUE EnumDescriptor_name(VALUE _self);
-VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name);
-VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number);
-VALUE EnumDescriptor_each(VALUE _self);
-VALUE EnumDescriptor_enummodule(VALUE _self);
-extern const rb_data_type_t _EnumDescriptor_type;
-
-void MessageBuilderContext_mark(void* _self);
-void MessageBuilderContext_free(void* _self);
-VALUE MessageBuilderContext_alloc(VALUE klass);
-void MessageBuilderContext_register(VALUE module);
-MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE value);
-VALUE MessageBuilderContext_initialize(VALUE _self,
-                                       VALUE _file_builder,
-                                       VALUE name);
-VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name);
-
-void OneofBuilderContext_mark(void* _self);
-void OneofBuilderContext_free(void* _self);
-VALUE OneofBuilderContext_alloc(VALUE klass);
-void OneofBuilderContext_register(VALUE module);
-OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE value);
-VALUE OneofBuilderContext_initialize(VALUE _self,
-                                     VALUE descriptor,
-                                     VALUE builder);
-VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
-
-void EnumBuilderContext_mark(void* _self);
-void EnumBuilderContext_free(void* _self);
-VALUE EnumBuilderContext_alloc(VALUE klass);
-void EnumBuilderContext_register(VALUE module);
-EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value);
-VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
-                                    VALUE name);
-VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number);
-
-void FileBuilderContext_mark(void* _self);
-void FileBuilderContext_free(void* _self);
-VALUE FileBuilderContext_alloc(VALUE klass);
-void FileBuilderContext_register(VALUE module);
-FileBuilderContext* ruby_to_FileBuilderContext(VALUE _self);
-upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str);
-upb_strview FileBuilderContext_strdup_name(VALUE _self, VALUE rb_str);
-upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym);
-VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
-                                    VALUE name, VALUE options);
-VALUE FileBuilderContext_add_message(VALUE _self, VALUE name);
-VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name);
-VALUE FileBuilderContext_pending_descriptors(VALUE _self);
-
-void Builder_mark(void* _self);
-void Builder_free(void* _self);
-VALUE Builder_alloc(VALUE klass);
-void Builder_register(VALUE module);
-Builder* ruby_to_Builder(VALUE value);
-VALUE Builder_build(VALUE _self);
-VALUE Builder_initialize(VALUE _self, VALUE descriptor_pool);
-VALUE Builder_add_file(int argc, VALUE *argv, VALUE _self);
-VALUE Builder_add_message(VALUE _self, VALUE name);
-VALUE Builder_add_enum(VALUE _self, VALUE name);
-VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
-
-// -----------------------------------------------------------------------------
-// Native slot storage abstraction.
-// -----------------------------------------------------------------------------
-
-#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
-
-size_t native_slot_size(upb_fieldtype_t type);
-void native_slot_set(const char* name,
-                     upb_fieldtype_t type,
-                     VALUE type_class,
-                     void* memory,
-                     VALUE value);
-// Atomically (with respect to Ruby VM calls) either update the value and set a
-// oneof case, or do neither. If |case_memory| is null, then no case value is
-// set.
-void native_slot_set_value_and_case(const char* name,
-                                    upb_fieldtype_t type,
-                                    VALUE type_class,
-                                    void* memory,
-                                    VALUE value,
-                                    uint32_t* case_memory,
-                                    uint32_t case_number);
-VALUE native_slot_get(upb_fieldtype_t type,
-                      VALUE type_class,
-                      const void* memory);
-void native_slot_init(upb_fieldtype_t type, void* memory);
-void native_slot_mark(upb_fieldtype_t type, void* memory);
-void native_slot_dup(upb_fieldtype_t type, void* to, void* from);
-void native_slot_deep_copy(upb_fieldtype_t type, VALUE type_class, void* to,
-                           void* from);
-bool native_slot_eq(upb_fieldtype_t type, VALUE type_class, void* mem1,
-                    void* mem2);
-
-VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
-void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value);
-uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
-                              const upb_oneofdef* oneof);
-bool is_value_field(const upb_fielddef* f);
-
-extern rb_encoding* kRubyStringUtf8Encoding;
-extern rb_encoding* kRubyStringASCIIEncoding;
-extern rb_encoding* kRubyString8bitEncoding;
-
-VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field);
-
-#define MAP_KEY_FIELD 1
-#define MAP_VALUE_FIELD 2
-
-// Oneof case slot value to indicate that no oneof case is set. The value `0` is
-// safe because field numbers are used as case identifiers, and no field can
-// have a number of 0.
-#define ONEOF_CASE_NONE 0
+#include "ruby-upb.h"
+#include "defs.h"
 
 // These operate on a map field (i.e., a repeated field of submessages whose
 // submessage type is a map-entry msgdef).
-bool is_map_field(const upb_fielddef* field);
 const upb_fielddef* map_field_key(const upb_fielddef* field);
 const upb_fielddef* map_field_value(const upb_fielddef* field);
 
-// These operate on a map-entry msgdef.
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
-
 // -----------------------------------------------------------------------------
-// Repeated field container type.
+// Arena
 // -----------------------------------------------------------------------------
 
-typedef struct {
-  upb_fieldtype_t field_type;
-  VALUE field_type_class;
-  void* elements;
-  int size;
-  int capacity;
-} RepeatedField;
+// A Ruby object that wraps an underlying upb_arena.  Any objects that are
+// allocated from this arena should reference the Arena in rb_gc_mark(), to
+// ensure that the object's underlying memory outlives any Ruby object that can
+// reach it.
 
-void RepeatedField_mark(void* self);
-void RepeatedField_free(void* self);
-VALUE RepeatedField_alloc(VALUE klass);
-VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self);
-void RepeatedField_register(VALUE module);
+VALUE Arena_new();
+upb_arena *Arena_get(VALUE arena);
 
-extern const rb_data_type_t RepeatedField_type;
-extern VALUE cRepeatedField;
+// Fuses this arena to another, throwing a Ruby exception if this is not
+// possible.
+void Arena_fuse(VALUE arena, upb_arena *other);
 
-RepeatedField* ruby_to_RepeatedField(VALUE value);
-
-VALUE RepeatedField_new_this_type(VALUE _self);
-VALUE RepeatedField_each(VALUE _self);
-VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self);
-void* RepeatedField_index_native(VALUE _self, int index);
-int RepeatedField_size(VALUE _self);
-VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val);
-void RepeatedField_reserve(RepeatedField* self, int new_size);
-VALUE RepeatedField_push(VALUE _self, VALUE val);
-void RepeatedField_push_native(VALUE _self, void* data);
-VALUE RepeatedField_pop_one(VALUE _self);
-VALUE RepeatedField_insert(int argc, VALUE* argv, VALUE _self);
-VALUE RepeatedField_replace(VALUE _self, VALUE list);
-VALUE RepeatedField_clear(VALUE _self);
-VALUE RepeatedField_length(VALUE _self);
-VALUE RepeatedField_dup(VALUE _self);
-VALUE RepeatedField_deep_copy(VALUE _self);
-VALUE RepeatedField_to_ary(VALUE _self);
-VALUE RepeatedField_eq(VALUE _self, VALUE _other);
-VALUE RepeatedField_hash(VALUE _self);
-VALUE RepeatedField_inspect(VALUE _self);
-VALUE RepeatedField_plus(VALUE _self, VALUE list);
-
-// Defined in repeated_field.c; also used by Map.
-void validate_type_class(upb_fieldtype_t type, VALUE klass);
+// Pins this Ruby object to the lifetime of this arena, so that as long as the
+// arena is alive this object will not be collected.
+//
+// We use this to guarantee that the "frozen" bit on the object will be
+// remembered, even if the user drops their reference to this precise object.
+void Arena_Pin(VALUE arena, VALUE obj);
 
 // -----------------------------------------------------------------------------
-// Map container type.
+// ObjectCache
 // -----------------------------------------------------------------------------
 
-typedef struct {
-  upb_fieldtype_t key_type;
-  upb_fieldtype_t value_type;
-  VALUE value_type_class;
-  VALUE parse_frame;
-  upb_strtable table;
-} Map;
+// Global object cache from upb array/map/message/symtab to wrapper object.
+//
+// This is a conceptually "weak" cache, in that it does not prevent "val" from
+// being collected (though in Ruby <2.7 is it effectively strong, due to
+// implementation limitations).
 
-void Map_mark(void* self);
-void Map_free(void* self);
-VALUE Map_alloc(VALUE klass);
-VALUE Map_init(int argc, VALUE* argv, VALUE self);
-void Map_register(VALUE module);
-VALUE Map_set_frame(VALUE self, VALUE val);
+// Adds an entry to the cache. The "arena" parameter must give the arena that
+// "key" was allocated from.  In Ruby <2.7.0, it will be used to remove the key
+// from the cache when the arena is destroyed.
+void ObjectCache_Add(const void* key, VALUE val);
 
-extern const rb_data_type_t Map_type;
-extern VALUE cMap;
-
-Map* ruby_to_Map(VALUE value);
-
-VALUE Map_new_this_type(VALUE _self);
-VALUE Map_each(VALUE _self);
-VALUE Map_keys(VALUE _self);
-VALUE Map_values(VALUE _self);
-VALUE Map_index(VALUE _self, VALUE key);
-VALUE Map_index_set(VALUE _self, VALUE key, VALUE value);
-VALUE Map_has_key(VALUE _self, VALUE key);
-VALUE Map_delete(VALUE _self, VALUE key);
-VALUE Map_clear(VALUE _self);
-VALUE Map_length(VALUE _self);
-VALUE Map_dup(VALUE _self);
-VALUE Map_deep_copy(VALUE _self);
-VALUE Map_eq(VALUE _self, VALUE _other);
-VALUE Map_hash(VALUE _self);
-VALUE Map_to_h(VALUE _self);
-VALUE Map_inspect(VALUE _self);
-VALUE Map_merge(VALUE _self, VALUE hashmap);
-VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
-
-typedef struct {
-  Map* self;
-  upb_strtable_iter it;
-} Map_iter;
-
-void Map_begin(VALUE _self, Map_iter* iter);
-void Map_next(Map_iter* iter);
-bool Map_done(Map_iter* iter);
-VALUE Map_iter_key(Map_iter* iter);
-VALUE Map_iter_value(Map_iter* iter);
+// Returns the cached object for this key, if any. Otherwise returns Qnil.
+VALUE ObjectCache_Get(const void* key);
 
 // -----------------------------------------------------------------------------
-// Message layout / storage.
+// StringBuilder, for inspect
 // -----------------------------------------------------------------------------
 
-#define MESSAGE_FIELD_NO_HASBIT ((uint32_t)-1)
+struct StringBuilder;
+typedef struct StringBuilder StringBuilder;
 
-struct MessageField {
-  uint32_t offset;
-  uint32_t hasbit;
-};
+StringBuilder* StringBuilder_New();
+void StringBuilder_Free(StringBuilder* b);
+void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...);
+VALUE StringBuilder_ToRubyString(StringBuilder* b);
 
-struct MessageOneof {
-  uint32_t offset;
-  uint32_t case_offset;
-};
-
-// MessageLayout is owned by the enclosing Descriptor, which must outlive us.
-struct MessageLayout {
-  const Descriptor* desc;
-  const upb_msgdef* msgdef;
-  void* empty_template;  // Can memcpy() onto a layout to clear it.
-  MessageField* fields;
-  MessageOneof* oneofs;
-  uint32_t size;
-  uint32_t value_offset;
-  int value_count;
-  int repeated_count;
-  int map_count;
-};
-
-#define ONEOF_CASE_MASK 0x80000000
-
-void create_layout(Descriptor* desc);
-void free_layout(MessageLayout* layout);
-bool field_contains_hasbit(MessageLayout* layout,
-                 const upb_fielddef* field);
-VALUE layout_get_default(const upb_fielddef* field);
-VALUE layout_get(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field);
-void layout_set(MessageLayout* layout,
-                void* storage,
-                const upb_fielddef* field,
-                VALUE val);
-VALUE layout_has(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field);
-void layout_clear(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field);
-void layout_init(MessageLayout* layout, void* storage);
-void layout_mark(MessageLayout* layout, void* storage);
-void layout_dup(MessageLayout* layout, void* to, void* from);
-void layout_deep_copy(MessageLayout* layout, void* to, void* from);
-VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2);
-VALUE layout_hash(MessageLayout* layout, void* storage);
-VALUE layout_inspect(MessageLayout* layout, void* storage);
-
-bool is_wrapper_type_field(const upb_fielddef* field);
-VALUE ruby_wrapper_type(VALUE type_class, VALUE value);
-
-// -----------------------------------------------------------------------------
-// Message class creation.
-// -----------------------------------------------------------------------------
-
-// This should probably be factored into a common upb component.
-
-typedef struct {
-  upb_byteshandler handler;
-  upb_bytessink sink;
-  char *ptr;
-  size_t len, size;
-} stringsink;
-
-void stringsink_uninit(stringsink *sink);
-
-struct MessageHeader {
-  Descriptor* descriptor;      // kept alive by self.class.descriptor reference.
-  stringsink* unknown_fields;  // store unknown fields in decoding.
-  // Data comes after this.
-};
-
-extern rb_data_type_t Message_type;
-
-VALUE build_class_from_descriptor(VALUE descriptor);
-void* Message_data(void* msg);
-void Message_mark(void* self);
-void Message_free(void* self);
-VALUE Message_alloc(VALUE klass);
-VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self);
-VALUE Message_initialize(int argc, VALUE* argv, VALUE _self);
-VALUE Message_dup(VALUE _self);
-VALUE Message_deep_copy(VALUE _self);
-VALUE Message_eq(VALUE _self, VALUE _other);
-VALUE Message_hash(VALUE _self);
-VALUE Message_inspect(VALUE _self);
-VALUE Message_to_h(VALUE _self);
-VALUE Message_index(VALUE _self, VALUE field_name);
-VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
-VALUE Message_descriptor(VALUE klass);
-VALUE Message_decode(VALUE klass, VALUE data);
-VALUE Message_encode(VALUE klass, VALUE msg_rb);
-VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass);
-VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass);
-
-VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb);
-VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj);
-
-VALUE build_module_from_enumdesc(VALUE _enumdesc);
-VALUE enum_lookup(VALUE self, VALUE number);
-VALUE enum_resolve(VALUE self, VALUE sym);
-VALUE enum_descriptor(VALUE self);
-
-const upb_pbdecodermethod *new_fillmsg_decodermethod(
-    Descriptor* descriptor, const void *owner);
-void add_handlers_for_message(const void *closure, upb_handlers *h);
-
-// Maximum depth allowed during encoding, to avoid stack overflows due to
-// cycles.
-#define ENCODE_MAX_NESTING 63
-
-// -----------------------------------------------------------------------------
-// A cache of frozen string objects to use as field defaults.
-// -----------------------------------------------------------------------------
-VALUE get_frozen_string(const char* data, size_t size, bool binary);
-
-// -----------------------------------------------------------------------------
-// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
-// instances.
-// -----------------------------------------------------------------------------
-VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def);
-VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def);
-VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def);
-VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def);
-VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def);
+void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val, TypeInfo info);
 
 // -----------------------------------------------------------------------------
 // Utilities.
 // -----------------------------------------------------------------------------
 
-void check_upb_status(const upb_status* status, const char* msg);
-
-#define CHECK_UPB(code, msg) do {                                             \
-    upb_status status = UPB_STATUS_INIT;                                      \
-    code;                                                                     \
-    check_upb_status(&status, msg);                                           \
-} while (0)
-
-extern ID descriptor_instancevar_interned;
-
-// A distinct object that is not accessible from Ruby.  We use this as a
-// constructor argument to enforce that certain objects cannot be created from
-// Ruby.
-extern VALUE c_only_cookie;
+extern VALUE cTypeError;
 
 #ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
+#define PBRUBY_ASSERT(expr) do {} while (false && (expr))
 #else
-#define UPB_ASSERT(expr) assert(expr)
+#define PBRUBY_ASSERT(expr) assert(expr)
 #endif
 
+#define PBRUBY_MAX(x, y) (((x) > (y)) ? (x) : (y))
+
 #define UPB_UNUSED(var) (void)var
 
 #endif  // __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index e3afb28..1cc4915 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -28,49 +28,164 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "repeated_field.h"
+
+#include "convert.h"
+#include "defs.h"
+#include "message.h"
 #include "protobuf.h"
+#include "third_party/wyhash/wyhash.h"
 
 // -----------------------------------------------------------------------------
 // Repeated field container type.
 // -----------------------------------------------------------------------------
 
-const rb_data_type_t RepeatedField_type = {
-  "Google::Protobuf::RepeatedField",
-  { RepeatedField_mark, RepeatedField_free, NULL },
-};
+typedef struct {
+  const upb_array *array;   // Can get as mutable when non-frozen.
+  TypeInfo type_info;
+  VALUE type_class;  // To GC-root the msgdef/enumdef in type_info.
+  VALUE arena;       // To GC-root the upb_array.
+} RepeatedField;
 
 VALUE cRepeatedField;
 
-RepeatedField* ruby_to_RepeatedField(VALUE _self) {
+static void RepeatedField_mark(void* _self) {
+  RepeatedField* self = (RepeatedField*)_self;
+  rb_gc_mark(self->type_class);
+  rb_gc_mark(self->arena);
+}
+
+const rb_data_type_t RepeatedField_type = {
+  "Google::Protobuf::RepeatedField",
+  { RepeatedField_mark, RUBY_DEFAULT_FREE, NULL },
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static RepeatedField* ruby_to_RepeatedField(VALUE _self) {
   RepeatedField* self;
   TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self);
   return self;
 }
 
-void* RepeatedField_memoryat(RepeatedField* self, int index, int element_size) {
-  return ((uint8_t *)self->elements) + index * element_size;
+static upb_array *RepeatedField_GetMutable(VALUE _self) {
+  rb_check_frozen(_self);
+  return (upb_array*)ruby_to_RepeatedField(_self)->array;
+}
+
+VALUE RepeatedField_alloc(VALUE klass) {
+  RepeatedField* self = ALLOC(RepeatedField);
+  self->arena = Qnil;
+  self->type_class = Qnil;
+  self->array = NULL;
+  return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
+}
+
+VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info,
+                                   VALUE arena) {
+  PBRUBY_ASSERT(array);
+  VALUE val = ObjectCache_Get(array);
+
+  if (val == Qnil) {
+    val = RepeatedField_alloc(cRepeatedField);
+    RepeatedField* self;
+    ObjectCache_Add(array, val);
+    TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self);
+    self->array = array;
+    self->arena = arena;
+    self->type_info = type_info;
+    if (self->type_info.type == UPB_TYPE_MESSAGE) {
+      self->type_class = Descriptor_DefToClass(type_info.def.msgdef);
+    }
+  }
+
+  PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.type == type_info.type);
+  PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef ==
+                type_info.def.msgdef);
+  return val;
+}
+
+static VALUE RepeatedField_new_this_type(RepeatedField* from) {
+  VALUE arena_rb = Arena_new();
+  upb_array *array = upb_array_new(Arena_get(arena_rb), from->type_info.type);
+  VALUE ret = RepeatedField_GetRubyWrapper(array, from->type_info, arena_rb);
+  PBRUBY_ASSERT(ruby_to_RepeatedField(ret)->type_class == from->type_class);
+  return ret;
+}
+
+void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
+                           TypeInfo info) {
+  bool first = true;
+  StringBuilder_Printf(b, "[");
+  size_t n = array ? upb_array_size(array) : 0;
+  for (size_t i = 0; i < n; i++) {
+    if (first) {
+      first = false;
+    } else {
+      StringBuilder_Printf(b, ", ");
+    }
+    StringBuilder_PrintMsgval(b, upb_array_get(array, i), info);
+  }
+  StringBuilder_Printf(b, "]");
+}
+
+VALUE RepeatedField_deep_copy(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  VALUE new_rptfield = RepeatedField_new_this_type(self);
+  RepeatedField* new_self = ruby_to_RepeatedField(new_rptfield);
+  VALUE arena_rb = new_self->arena;
+  upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
+  upb_arena *arena = Arena_get(arena_rb);
+  size_t elements = upb_array_size(self->array);
+
+  upb_array_resize(new_array, elements, arena);
+
+  size_t size = upb_array_size(self->array);
+  for (size_t i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    upb_msgval copy = Msgval_DeepCopy(msgval, self->type_info, arena);
+    upb_array_set(new_array, i, copy);
+  }
+
+  return new_rptfield;
+}
+
+const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef* field,
+                                           upb_arena* arena) {
+  RepeatedField* self;
+  TypeInfo type_info = TypeInfo_get(field);
+
+  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
+      RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
+    rb_raise(cTypeError, "Expected repeated field array");
+  }
+
+  self = ruby_to_RepeatedField(val);
+  if (self->type_info.type != type_info.type) {
+    rb_raise(cTypeError, "Repeated field array has wrong element type");
+  }
+
+  if (self->type_info.def.msgdef != type_info.def.msgdef) {
+    rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
+  }
+
+  Arena_fuse(self->arena, arena);
+  return self->array;
 }
 
 static int index_position(VALUE _index, RepeatedField* repeated_field) {
   int index = NUM2INT(_index);
-  if (index < 0 && repeated_field->size > 0) {
-    index = repeated_field->size + index;
-  }
+  if (index < 0) index += upb_array_size(repeated_field->array);
   return index;
 }
 
-VALUE RepeatedField_subarray(VALUE _self, long beg, long len) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  int element_size = native_slot_size(self->field_type);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  size_t off = beg * element_size;
-  VALUE ary = rb_ary_new2(len);
-  int i;
+static VALUE RepeatedField_subarray(RepeatedField* self, long beg, long len) {
+  size_t size = upb_array_size(self->array);
+  VALUE ary = rb_ary_new2(size);
+  long i;
 
-  for (i = beg; i < beg + len; i++, off += element_size) {
-    void* mem = ((uint8_t *)self->elements) + off;
-    VALUE elem = native_slot_get(field_type, field_type_class, mem);
+  for (i = beg; i < beg + len; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    VALUE elem = Convert_UpbToRuby(msgval, self->type_info, self->arena);
     rb_ary_push(ary, elem);
   }
   return ary;
@@ -84,17 +199,14 @@
  * also includes Enumerable; combined with this method, the repeated field thus
  * acts like an ordinary Ruby sequence.
  */
-VALUE RepeatedField_each(VALUE _self) {
+static VALUE RepeatedField_each(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  int element_size = native_slot_size(field_type);
-  size_t off = 0;
+  int size = upb_array_size(self->array);
   int i;
 
-  for (i = 0; i < self->size; i++, off += element_size) {
-    void* memory = (void *) (((uint8_t *)self->elements) + off);
-    VALUE val = native_slot_get(field_type, field_type_class, memory);
+  for (i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
     rb_yield(val);
   }
   return _self;
@@ -107,11 +219,9 @@
  *
  * Accesses the element at the given index. Returns nil on out-of-bounds
  */
-VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
+static VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  int element_size = native_slot_size(self->field_type);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
+  long size = upb_array_size(self->array);
 
   VALUE arg = argv[0];
   long beg, len;
@@ -119,35 +229,36 @@
   if (argc == 1){
     if (FIXNUM_P(arg)) {
       /* standard case */
-      void* memory;
+      upb_msgval msgval;
       int index = index_position(argv[0], self);
-      if (index < 0 || index >= self->size) {
+      if (index < 0 || (size_t)index >= upb_array_size(self->array)) {
         return Qnil;
       }
-      memory = RepeatedField_memoryat(self, index, element_size);
-      return native_slot_get(field_type, field_type_class, memory);
-    }else{
+      msgval = upb_array_get(self->array, index);
+      return Convert_UpbToRuby(msgval, self->type_info, self->arena);
+    } else {
       /* check if idx is Range */
-      switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) {
+      switch (rb_range_beg_len(arg, &beg, &len, size, 0)) {
         case Qfalse:
           break;
         case Qnil:
           return Qnil;
         default:
-          return RepeatedField_subarray(_self, beg, len);
+          return RepeatedField_subarray(self, beg, len);
       }
     }
   }
+
   /* assume 2 arguments */
   beg = NUM2LONG(argv[0]);
   len = NUM2LONG(argv[1]);
   if (beg < 0) {
-    beg += self->size;
+    beg += size;
   }
-  if (beg >= self->size) {
+  if (beg >= size) {
     return Qnil;
   }
-  return RepeatedField_subarray(_self, beg, len);
+  return RepeatedField_subarray(self, beg, len);
 }
 
 /*
@@ -157,128 +268,88 @@
  * Sets the element at the given index. On out-of-bounds assignments, extends
  * the array and fills the hole (if any) with default values.
  */
-VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
+static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  int element_size = native_slot_size(field_type);
-  void* memory;
+  int size = upb_array_size(self->array);
+  upb_array *array = RepeatedField_GetMutable(_self);
+  upb_arena *arena = Arena_get(self->arena);
+  upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
 
   int index = index_position(_index, self);
   if (index < 0 || index >= (INT_MAX - 1)) {
     return Qnil;
   }
-  if (index >= self->size) {
-    upb_fieldtype_t field_type = self->field_type;
-    int element_size = native_slot_size(field_type);
-    int i;
 
-    RepeatedField_reserve(self, index + 1);
-    for (i = self->size; i <= index; i++) {
-      void* elem = RepeatedField_memoryat(self, i, element_size);
-      native_slot_init(field_type, elem);
+  if (index >= size) {
+    upb_array_resize(array, index + 1, arena);
+    upb_msgval fill;
+    memset(&fill, 0, sizeof(fill));
+    for (int i = size; i < index; i++) {
+      // Fill default values.
+      // TODO(haberman): should this happen at the upb level?
+      upb_array_set(array, i, fill);
     }
-    self->size = index + 1;
   }
 
-  memory = RepeatedField_memoryat(self, index, element_size);
-  native_slot_set("", field_type, field_type_class, memory, val);
+  upb_array_set(array, index, msgval);
   return Qnil;
 }
 
-static int kInitialSize = 8;
-
-void RepeatedField_reserve(RepeatedField* self, int new_size) {
-  void* old_elems = self->elements;
-  int elem_size = native_slot_size(self->field_type);
-  if (new_size <= self->capacity) {
-    return;
-  }
-  if (self->capacity == 0) {
-    self->capacity = kInitialSize;
-  }
-  while (self->capacity < new_size) {
-    self->capacity *= 2;
-  }
-  self->elements = ALLOC_N(uint8_t, elem_size * self->capacity);
-  if (old_elems != NULL) {
-    memcpy(self->elements, old_elems, self->size * elem_size);
-    xfree(old_elems);
-  }
-}
-
 /*
  * call-seq:
- *     RepeatedField.push(value)
+ *     RepeatedField.push(value, ...)
  *
  * Adds a new element to the repeated field.
  */
-VALUE RepeatedField_push(VALUE _self, VALUE val) {
+static VALUE RepeatedField_push_vararg(int argc, VALUE* argv, VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  void* memory;
-
-  RepeatedField_reserve(self, self->size + 1);
-  memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
-  native_slot_set("", field_type, self->field_type_class, memory, val);
-  // native_slot_set may raise an error; bump size only after set.
-  self->size++;
-  return _self;
-}
-
-VALUE RepeatedField_push_vararg(VALUE _self, VALUE args) {
+  upb_arena *arena = Arena_get(self->arena);
+  upb_array *array = RepeatedField_GetMutable(_self);
   int i;
-  for (i = 0; i < RARRAY_LEN(args); i++) {
-    RepeatedField_push(_self, rb_ary_entry(args, i));
+
+  for (i = 0; i < argc; i++) {
+    upb_msgval msgval = Convert_RubyToUpb(argv[i], "", self->type_info, arena);
+    upb_array_append(array, msgval, arena);
   }
+
   return _self;
 }
 
-// Used by parsing handlers.
-void RepeatedField_push_native(VALUE _self, void* data) {
+/*
+ * call-seq:
+ *     RepeatedField.<<(value)
+ *
+ * Adds a new element to the repeated field.
+ */
+static VALUE RepeatedField_push(VALUE _self, VALUE val) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  void* memory;
+  upb_arena *arena = Arena_get(self->arena);
+  upb_array *array = RepeatedField_GetMutable(_self);
 
-  RepeatedField_reserve(self, self->size + 1);
-  memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
-  memcpy(memory, data, element_size);
-  self->size++;
-}
+  upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
+  upb_array_append(array, msgval, arena);
 
-void* RepeatedField_index_native(VALUE _self, int index) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  return RepeatedField_memoryat(self, index, element_size);
-}
-
-int RepeatedField_size(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  return self->size;
+  return _self;
 }
 
 /*
  * Private ruby method, used by RepeatedField.pop
  */
-VALUE RepeatedField_pop_one(VALUE _self) {
+static VALUE RepeatedField_pop_one(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  int element_size = native_slot_size(field_type);
-  int index;
-  void* memory;
+  size_t size = upb_array_size(self->array);
+  upb_array *array = RepeatedField_GetMutable(_self);
+  upb_msgval last;
   VALUE ret;
 
-  if (self->size == 0) {
+  if (size == 0) {
     return Qnil;
   }
-  index = self->size - 1;
-  memory = RepeatedField_memoryat(self, index, element_size);
-  ret = native_slot_get(field_type, field_type_class, memory);
-  self->size--;
+
+  last = upb_array_get(self->array, size - 1);
+  ret = Convert_UpbToRuby(last, self->type_info, self->arena);
+
+  upb_array_resize(array, size - 1, Arena_get(self->arena));
   return ret;
 }
 
@@ -288,15 +359,18 @@
  *
  * Replaces the contents of the repeated field with the given list of elements.
  */
-VALUE RepeatedField_replace(VALUE _self, VALUE list) {
+static VALUE RepeatedField_replace(VALUE _self, VALUE list) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_array *array = RepeatedField_GetMutable(_self);
   int i;
 
   Check_Type(list, T_ARRAY);
-  self->size = 0;
+  upb_array_resize(array, 0, Arena_get(self->arena));
+
   for (i = 0; i < RARRAY_LEN(list); i++) {
     RepeatedField_push(_self, rb_ary_entry(list, i));
   }
+
   return list;
 }
 
@@ -306,9 +380,10 @@
  *
  * Clears (removes all elements from) this repeated field.
  */
-VALUE RepeatedField_clear(VALUE _self) {
+static VALUE RepeatedField_clear(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  self->size = 0;
+  upb_array *array = RepeatedField_GetMutable(_self);
+  upb_array_resize(array, 0, Arena_get(self->arena));
   return _self;
 }
 
@@ -318,23 +393,9 @@
  *
  * Returns the length of this repeated field.
  */
-VALUE RepeatedField_length(VALUE _self) {
+static VALUE RepeatedField_length(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  return INT2NUM(self->size);
-}
-
-VALUE RepeatedField_new_this_type(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE new_rptfield = Qnil;
-  VALUE element_type = fieldtype_to_ruby(self->field_type);
-  if (self->field_type_class != Qnil) {
-    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
-                              element_type, self->field_type_class);
-  } else {
-    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1,
-                              element_type);
-  }
-  return new_rptfield;
+  return INT2NUM(upb_array_size(self->array));
 }
 
 /*
@@ -344,42 +405,20 @@
  * Duplicates this repeated field with a shallow copy. References to all
  * non-primitive element objects (e.g., submessages) are shared.
  */
-VALUE RepeatedField_dup(VALUE _self) {
+static VALUE RepeatedField_dup(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE new_rptfield = RepeatedField_new_this_type(_self);
+  VALUE new_rptfield = RepeatedField_new_this_type(self);
   RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
-  upb_fieldtype_t field_type = self->field_type;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
+  upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
+  upb_arena* arena = Arena_get(new_rptfield_self->arena);
+  int size = upb_array_size(self->array);
   int i;
 
-  RepeatedField_reserve(new_rptfield_self, self->size);
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
-    void* from_mem = (uint8_t *)self->elements + off;
-    native_slot_dup(field_type, to_mem, from_mem);
-    new_rptfield_self->size++;
-  }
+  Arena_fuse(self->arena, arena);
 
-  return new_rptfield;
-}
-
-// Internal only: used by Google::Protobuf.deep_copy.
-VALUE RepeatedField_deep_copy(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE new_rptfield = RepeatedField_new_this_type(_self);
-  RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
-  upb_fieldtype_t field_type = self->field_type;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
-  int i;
-
-  RepeatedField_reserve(new_rptfield_self, self->size);
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
-    void* from_mem = (uint8_t *)self->elements + off;
-    native_slot_deep_copy(field_type, self->field_type_class, to_mem, from_mem);
-    new_rptfield_self->size++;
+  for (i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    upb_array_append(new_array, msgval, arena);
   }
 
   return new_rptfield;
@@ -394,17 +433,16 @@
  */
 VALUE RepeatedField_to_ary(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
-  VALUE ary = rb_ary_new2(self->size);
+  int size = upb_array_size(self->array);
+  VALUE ary = rb_ary_new2(size);
   int i;
 
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* mem = ((uint8_t *)self->elements) + off;
-    VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
-    rb_ary_push(ary, elem);
+  for (i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
+    rb_ary_push(ary, val);
   }
+
   return ary;
 }
 
@@ -436,28 +474,39 @@
 
   self = ruby_to_RepeatedField(_self);
   other = ruby_to_RepeatedField(_other);
-  if (self->field_type != other->field_type ||
-      self->field_type_class != other->field_type_class ||
-      self->size != other->size) {
+  size_t n = upb_array_size(self->array);
+
+  if (self->type_info.type != other->type_info.type ||
+      self->type_class != other->type_class ||
+      upb_array_size(other->array) != n) {
     return Qfalse;
   }
 
-  {
-    upb_fieldtype_t field_type = self->field_type;
-    size_t elem_size = native_slot_size(field_type);
-    size_t off = 0;
-    int i;
-
-    for (i = 0; i < self->size; i++, off += elem_size) {
-      void* self_mem = ((uint8_t *)self->elements) + off;
-      void* other_mem = ((uint8_t *)other->elements) + off;
-      if (!native_slot_eq(field_type, self->field_type_class, self_mem,
-                          other_mem)) {
-        return Qfalse;
-      }
+  for (size_t i = 0; i < n; i++) {
+    upb_msgval val1 = upb_array_get(self->array, i);
+    upb_msgval val2 = upb_array_get(other->array, i);
+    if (!Msgval_IsEqual(val1, val2, self->type_info)) {
+      return Qfalse;
     }
-    return Qtrue;
   }
+
+  return Qtrue;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.freeze => self
+ *
+ * Freezes the repeated field. We have to intercept this so we can pin the Ruby
+ * object into memory so we don't forget it's frozen.
+ */
+static VALUE RepeatedField_freeze(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  if (!RB_OBJ_FROZEN(_self)) {
+    Arena_Pin(self->arena, _self);
+    RB_OBJ_FREEZE(_self);
+  }
+  return _self;
 }
 
 /*
@@ -468,22 +517,15 @@
  */
 VALUE RepeatedField_hash(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  st_index_t h = rb_hash_start(0);
-  VALUE hash_sym = rb_intern("hash");
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
-  int i;
+  uint64_t hash = 0;
+  size_t n = upb_array_size(self->array);
 
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* mem = ((uint8_t *)self->elements) + off;
-    VALUE elem = native_slot_get(field_type, field_type_class, mem);
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0)));
+  for (size_t i = 0; i < n; i++) {
+    upb_msgval val = upb_array_get(self->array, i);
+    hash = Msgval_GetHash(val, self->type_info, hash);
   }
-  h = rb_hash_end(h);
 
-  return INT2FIX(h);
+  return LL2NUM(hash);
 }
 
 /*
@@ -495,34 +537,39 @@
  * be either another repeated field or a Ruby array.
  */
 VALUE RepeatedField_plus(VALUE _self, VALUE list) {
-  VALUE dupped = RepeatedField_dup(_self);
+  VALUE dupped_ = RepeatedField_dup(_self);
 
   if (TYPE(list) == T_ARRAY) {
     int i;
     for (i = 0; i < RARRAY_LEN(list); i++) {
       VALUE elem = rb_ary_entry(list, i);
-      RepeatedField_push(dupped, elem);
+      RepeatedField_push(dupped_, elem);
     }
   } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
              RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
     RepeatedField* self = ruby_to_RepeatedField(_self);
     RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
+    RepeatedField* dupped = ruby_to_RepeatedField(dupped_);
+    upb_array *dupped_array = RepeatedField_GetMutable(dupped_);
+    upb_arena* arena = Arena_get(dupped->arena);
+    int size = upb_array_size(list_rptfield->array);
     int i;
 
-    if (self->field_type != list_rptfield->field_type ||
-        self->field_type_class != list_rptfield->field_type_class) {
+    if (self->type_info.type != list_rptfield->type_info.type ||
+        self->type_class != list_rptfield->type_class) {
       rb_raise(rb_eArgError,
                "Attempt to append RepeatedField with different element type.");
     }
-    for (i = 0; i < list_rptfield->size; i++) {
-      void* mem = RepeatedField_index_native(list, i);
-      RepeatedField_push_native(dupped, mem);
+
+    for (i = 0; i < size; i++) {
+      upb_msgval msgval = upb_array_get(list_rptfield->array, i);
+      upb_array_append(dupped_array, msgval, arena);
     }
   } else {
     rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
   }
 
-  return dupped;
+  return dupped_;
 }
 
 /*
@@ -541,93 +588,6 @@
   return _self;
 }
 
-
-void validate_type_class(upb_fieldtype_t type, VALUE klass) {
-  if (rb_ivar_get(klass, descriptor_instancevar_interned) == Qnil) {
-    rb_raise(rb_eArgError,
-             "Type class has no descriptor. Please pass a "
-             "class or enum as returned by the DescriptorPool.");
-  }
-  if (type == UPB_TYPE_MESSAGE) {
-    VALUE desc = rb_ivar_get(klass, descriptor_instancevar_interned);
-    if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) ||
-        RTYPEDDATA_TYPE(desc) != &_Descriptor_type) {
-      rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
-    }
-    if (rb_get_alloc_func(klass) != &Message_alloc) {
-      rb_raise(rb_eArgError,
-               "Message class was not returned by the DescriptorPool.");
-    }
-  } else if (type == UPB_TYPE_ENUM) {
-    VALUE enumdesc = rb_ivar_get(klass, descriptor_instancevar_interned);
-    if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) ||
-        RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) {
-      rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
-    }
-  }
-}
-
-void RepeatedField_init_args(int argc, VALUE* argv,
-                             VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE ary = Qnil;
-  if (argc < 1) {
-    rb_raise(rb_eArgError, "Expected at least 1 argument.");
-  }
-  self->field_type = ruby_to_fieldtype(argv[0]);
-
-  if (self->field_type == UPB_TYPE_MESSAGE ||
-      self->field_type == UPB_TYPE_ENUM) {
-    if (argc < 2) {
-      rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
-    }
-    self->field_type_class = argv[1];
-    if (argc > 2) {
-      ary = argv[2];
-    }
-    validate_type_class(self->field_type, self->field_type_class);
-  } else {
-    if (argc > 2) {
-      rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
-    }
-    if (argc > 1) {
-      ary = argv[1];
-    }
-  }
-
-  if (ary != Qnil) {
-    int i;
-
-    if (!RB_TYPE_P(ary, T_ARRAY)) {
-      rb_raise(rb_eArgError, "Expected array as initialize argument");
-    }
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
-      RepeatedField_push(_self, rb_ary_entry(ary, i));
-    }
-  }
-}
-
-// Mark, free, alloc, init and class setup functions.
-
-void RepeatedField_mark(void* _self) {
-  RepeatedField* self = (RepeatedField*)_self;
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  int i;
-
-  rb_gc_mark(self->field_type_class);
-  for (i = 0; i < self->size; i++) {
-    void* memory = (((uint8_t *)self->elements) + i * element_size);
-    native_slot_mark(self->field_type, memory);
-  }
-}
-
-void RepeatedField_free(void* _self) {
-  RepeatedField* self = (RepeatedField*)_self;
-  xfree(self->elements);
-  xfree(self);
-}
-
 /*
  * call-seq:
  *     RepeatedField.new(type, type_class = nil, initial_elems = [])
@@ -639,18 +599,30 @@
  * EnumDescriptor#enummodule, respectively. An initial list of elements may also
  * be provided.
  */
-VALUE RepeatedField_alloc(VALUE klass) {
-  RepeatedField* self = ALLOC(RepeatedField);
-  self->elements = NULL;
-  self->size = 0;
-  self->capacity = 0;
-  self->field_type = -1;
-  self->field_type_class = Qnil;
-  return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
-}
+VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_arena *arena;
+  VALUE ary = Qnil;
 
-VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) {
-  RepeatedField_init_args(argc, argv, self);
+  self->arena = Arena_new();
+  arena = Arena_get(self->arena);
+
+  if (argc < 1) {
+    rb_raise(rb_eArgError, "Expected at least 1 argument.");
+  }
+
+  self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary);
+  self->array = upb_array_new(arena, self->type_info.type);
+  ObjectCache_Add(self->array, _self);
+
+  if (ary != Qnil) {
+    if (!RB_TYPE_P(ary, T_ARRAY)) {
+      rb_raise(rb_eArgError, "Expected array as initialize argument");
+    }
+    for (int i = 0; i < RARRAY_LEN(ary); i++) {
+      RepeatedField_push(_self, rb_ary_entry(ary, i));
+    }
+  }
   return Qnil;
 }
 
@@ -667,7 +639,7 @@
   rb_define_method(klass, "[]", RepeatedField_index, -1);
   rb_define_method(klass, "at", RepeatedField_index, -1);
   rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
-  rb_define_method(klass, "push", RepeatedField_push_vararg, -2);
+  rb_define_method(klass, "push", RepeatedField_push_vararg, -1);
   rb_define_method(klass, "<<", RepeatedField_push, 1);
   rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
   rb_define_method(klass, "replace", RepeatedField_replace, 1);
@@ -679,6 +651,7 @@
   rb_define_method(klass, "clone", RepeatedField_dup, 0);
   rb_define_method(klass, "==", RepeatedField_eq, 1);
   rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
+  rb_define_method(klass, "freeze", RepeatedField_freeze, 0);
   rb_define_method(klass, "hash", RepeatedField_hash, 0);
   rb_define_method(klass, "+", RepeatedField_plus, 1);
   rb_define_method(klass, "concat", RepeatedField_concat, 1);
diff --git a/ruby/ext/google/protobuf_c/repeated_field.h b/ruby/ext/google/protobuf_c/repeated_field.h
new file mode 100644
index 0000000..e4ef252
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/repeated_field.h
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_REPEATED_FIELD_H_
+#define RUBY_PROTOBUF_REPEATED_FIELD_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Returns a Ruby wrapper object for the given upb_array, which will be created
+// if one does not exist already.
+VALUE RepeatedField_GetRubyWrapper(upb_array* msg, TypeInfo type_info,
+                                   VALUE arena);
+
+// Gets the underlying upb_array for this Ruby RepeatedField object, which must
+// have a type that matches |f|. If this is not a repeated field or the type
+// doesn't match, raises an exception.
+const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f,
+                                           upb_arena* arena);
+
+// Implements #inspect for this repeated field by appending its contents to |b|.
+void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
+                           TypeInfo info);
+
+// Returns a deep copy of this RepeatedField object.
+VALUE RepeatedField_deep_copy(VALUE obj);
+
+// Ruby class of Google::Protobuf::RepeatedField.
+extern VALUE cRepeatedField;
+
+// Call at startup to register all types in this module.
+void RepeatedField_register(VALUE module);
+
+#endif  // RUBY_PROTOBUF_REPEATED_FIELD_H_
diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c
new file mode 100755
index 0000000..b1b701b
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/ruby-upb.c
@@ -0,0 +1,8858 @@
+/* Amalgamated source file */
+#include "ruby-upb.h"
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google LLC nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is where we define macros used across upb.
+ *
+ * All of these macros are undef'd in port_undef.inc to avoid leaking them to
+ * users.
+ *
+ * The correct usage is:
+ *
+ *   #include "upb/foobar.h"
+ *   #include "upb/baz.h"
+ *
+ *   // MUST be last included header.
+ *   #include "upb/port_def.inc"
+ *
+ *   // Code for this file.
+ *   // <...>
+ *
+ *   // Can be omitted for .c files, required for .h.
+ *   #include "upb/port_undef.inc"
+ *
+ * This file is private and must not be included by users!
+ */
+
+#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+      (defined(__cplusplus) && __cplusplus >= 201103L) ||           \
+      (defined(_MSC_VER) && _MSC_VER >= 1900))
+#error upb requires C99 or C++11 or MSVC >= 2015.
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#if UINTPTR_MAX == 0xffffffff
+#define UPB_SIZE(size32, size64) size32
+#else
+#define UPB_SIZE(size32, size64) size64
+#endif
+
+/* If we always read/write as a consistent type to each address, this shouldn't
+ * violate aliasing.
+ */
+#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
+
+#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
+  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
+      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
+      : default
+
+#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
+  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
+  *UPB_PTR_AT(msg, offset, fieldtype) = value;
+
+#define UPB_MAPTYPE_STRING 0
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__) || defined(__clang__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
+#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
+#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
+#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
+
+/* Hints to the compiler about likely/unlikely branches. */
+#if defined (__GNUC__) || defined(__clang__)
+#define UPB_LIKELY(x) __builtin_expect((x),1)
+#define UPB_UNLIKELY(x) __builtin_expect((x),0)
+#else
+#define UPB_LIKELY(x) (x)
+#define UPB_UNLIKELY(x) (x)
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg)))
+#elif defined(_MSC_VER)
+#define UPB_NOINLINE
+#define UPB_FORCEINLINE
+#define UPB_NORETURN __declspec(noreturn)
+#define UPB_PRINTF(str, first_vararg)
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#define UPB_PRINTF(str, first_vararg)
+#endif
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
+ */
+#ifdef NDEBUG
+#ifdef __GNUC__
+#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
+#elif defined _MSC_VER
+#define UPB_ASSUME(expr) if (!(expr)) __assume(0)
+#else
+#define UPB_ASSUME(expr) do {} while (false && (expr))
+#endif
+#else
+#define UPB_ASSUME(expr) assert(expr)
+#endif
+
+/* UPB_ASSERT(): in release mode, we use the expression without letting it be
+ * evaluated.  This prevents "unused variable" warnings. */
+#ifdef NDEBUG
+#define UPB_ASSERT(expr) do {} while (false && (expr))
+#else
+#define UPB_ASSERT(expr) assert(expr)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
+#else
+#define UPB_UNREACHABLE() do { assert(0); } while(0)
+#endif
+
+/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
+#ifdef __APPLE__
+#define UPB_SETJMP(buf) _setjmp(buf)
+#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
+#else
+#define UPB_SETJMP(buf) setjmp(buf)
+#define UPB_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */
+#define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr))
+
+/* Configure whether fasttable is switched on or not. *************************/
+
+#ifdef __has_attribute
+#define UPB_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define UPB_HAS_ATTRIBUTE(x) 0
+#endif
+
+#if UPB_HAS_ATTRIBUTE(musttail)
+#define UPB_MUSTTAIL __attribute__((musttail))
+#else
+#define UPB_MUSTTAIL
+#endif
+
+#undef UPB_HAS_ATTRIBUTE
+
+/* This check is not fully robust: it does not require that we have "musttail"
+ * support available. We need tail calls to avoid consuming arbitrary amounts
+ * of stack space.
+ *
+ * GCC/Clang can mostly be trusted to generate tail calls as long as
+ * optimization is enabled, but, debug builds will not generate tail calls
+ * unless "musttail" is available.
+ *
+ * We should probably either:
+ *   1. require that the compiler supports musttail.
+ *   2. add some fallback code for when musttail isn't available (ie. return
+ *      instead of tail calling). This is safe and portable, but this comes at
+ *      a CPU cost.
+ */
+#if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__)
+#define UPB_FASTTABLE_SUPPORTED 1
+#else
+#define UPB_FASTTABLE_SUPPORTED 0
+#endif
+
+/* define UPB_ENABLE_FASTTABLE to force fast table support.
+ * This is useful when we want to ensure we are really getting fasttable,
+ * for example for testing or benchmarking. */
+#if defined(UPB_ENABLE_FASTTABLE)
+#if !UPB_FASTTABLE_SUPPORTED
+#error fasttable is x86-64/ARM64 only and requires GCC or Clang.
+#endif
+#define UPB_FASTTABLE 1
+/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
+ * This is useful for releasing code that might be used on multiple platforms,
+ * for example the PHP or Ruby C extensions. */
+#elif defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
+#else
+#define UPB_FASTTABLE 0
+#endif
+
+/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
+ * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */
+#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE_INIT(...)
+#else
+#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
+#endif
+
+#undef UPB_FASTTABLE_SUPPORTED
+
+/* ASAN poisoning (for arena) *************************************************/
+
+#if defined(__SANITIZE_ADDRESS__)
+#define UPB_ASAN 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  __asan_poison_memory_region((addr), (size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  __asan_unpoison_memory_region((addr), (size))
+#else
+#define UPB_ASAN 0
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#endif
+
+/** upb/decode.c ************************************************************/
+
+#include <setjmp.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+/* Maps descriptor type -> elem_size_lg2.  */
+static const uint8_t desctype_to_elem_size_lg2[] = {
+    -1,               /* invalid descriptor type */
+    3,  /* DOUBLE */
+    2,   /* FLOAT */
+    3,   /* INT64 */
+    3,  /* UINT64 */
+    2,   /* INT32 */
+    3,  /* FIXED64 */
+    2,  /* FIXED32 */
+    0,    /* BOOL */
+    UPB_SIZE(3, 4),  /* STRING */
+    UPB_SIZE(2, 3),  /* GROUP */
+    UPB_SIZE(2, 3),  /* MESSAGE */
+    UPB_SIZE(3, 4),  /* BYTES */
+    2,  /* UINT32 */
+    2,    /* ENUM */
+    2,   /* SFIXED32 */
+    3,   /* SFIXED64 */
+    2,   /* SINT32 */
+    3,   /* SINT64 */
+};
+
+/* Maps descriptor type -> upb map size.  */
+static const uint8_t desctype_to_mapsize[] = {
+    -1,                 /* invalid descriptor type */
+    8,                  /* DOUBLE */
+    4,                  /* FLOAT */
+    8,                  /* INT64 */
+    8,                  /* UINT64 */
+    4,                  /* INT32 */
+    8,                  /* FIXED64 */
+    4,                  /* FIXED32 */
+    1,                  /* BOOL */
+    UPB_MAPTYPE_STRING, /* STRING */
+    sizeof(void *),     /* GROUP */
+    sizeof(void *),     /* MESSAGE */
+    UPB_MAPTYPE_STRING, /* BYTES */
+    4,                  /* UINT32 */
+    4,                  /* ENUM */
+    4,                  /* SFIXED32 */
+    8,                  /* SFIXED64 */
+    4,                  /* SINT32 */
+    8,                  /* SINT64 */
+};
+
+static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) |
+                                   (1 << UPB_DTYPE_FIXED32) |
+                                   (1 << UPB_DTYPE_SFIXED32);
+
+static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
+                                   (1 << UPB_DTYPE_FIXED64) |
+                                   (1 << UPB_DTYPE_SFIXED64);
+
+/* Op: an action to be performed for a wire-type/field-type combination. */
+#define OP_SCALAR_LG2(n) (n)      /* n in [0, 2, 3] => op in [0, 2, 3] */
+#define OP_STRING 4
+#define OP_BYTES 5
+#define OP_SUBMSG 6
+/* Ops above are scalar-only. Repeated fields can use any op.  */
+#define OP_FIXPCK_LG2(n) (n + 5)  /* n in [2, 3] => op in [7, 8] */
+#define OP_VARPCK_LG2(n) (n + 9)  /* n in [0, 2, 3] => op in [9, 11, 12] */
+
+static const int8_t varint_ops[19] = {
+    -1,               /* field not found */
+    -1,               /* DOUBLE */
+    -1,               /* FLOAT */
+    OP_SCALAR_LG2(3), /* INT64 */
+    OP_SCALAR_LG2(3), /* UINT64 */
+    OP_SCALAR_LG2(2), /* INT32 */
+    -1,               /* FIXED64 */
+    -1,               /* FIXED32 */
+    OP_SCALAR_LG2(0), /* BOOL */
+    -1,               /* STRING */
+    -1,               /* GROUP */
+    -1,               /* MESSAGE */
+    -1,               /* BYTES */
+    OP_SCALAR_LG2(2), /* UINT32 */
+    OP_SCALAR_LG2(2), /* ENUM */
+    -1,               /* SFIXED32 */
+    -1,               /* SFIXED64 */
+    OP_SCALAR_LG2(2), /* SINT32 */
+    OP_SCALAR_LG2(3), /* SINT64 */
+};
+
+static const int8_t delim_ops[37] = {
+    /* For non-repeated field type. */
+    -1,        /* field not found */
+    -1,        /* DOUBLE */
+    -1,        /* FLOAT */
+    -1,        /* INT64 */
+    -1,        /* UINT64 */
+    -1,        /* INT32 */
+    -1,        /* FIXED64 */
+    -1,        /* FIXED32 */
+    -1,        /* BOOL */
+    OP_STRING, /* STRING */
+    -1,        /* GROUP */
+    OP_SUBMSG, /* MESSAGE */
+    OP_BYTES,  /* BYTES */
+    -1,        /* UINT32 */
+    -1,        /* ENUM */
+    -1,        /* SFIXED32 */
+    -1,        /* SFIXED64 */
+    -1,        /* SINT32 */
+    -1,        /* SINT64 */
+    /* For repeated field type. */
+    OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
+    OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
+    OP_VARPCK_LG2(3), /* REPEATED INT64 */
+    OP_VARPCK_LG2(3), /* REPEATED UINT64 */
+    OP_VARPCK_LG2(2), /* REPEATED INT32 */
+    OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */
+    OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */
+    OP_VARPCK_LG2(0), /* REPEATED BOOL */
+    OP_STRING,        /* REPEATED STRING */
+    OP_SUBMSG,        /* REPEATED GROUP */
+    OP_SUBMSG,        /* REPEATED MESSAGE */
+    OP_BYTES,         /* REPEATED BYTES */
+    OP_VARPCK_LG2(2), /* REPEATED UINT32 */
+    OP_VARPCK_LG2(2), /* REPEATED ENUM */
+    OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
+    OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */
+    OP_VARPCK_LG2(2), /* REPEATED SINT32 */
+    OP_VARPCK_LG2(3), /* REPEATED SINT64 */
+};
+
+typedef union {
+  bool bool_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  uint32_t size;
+} wireval;
+
+static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                              const upb_msglayout *layout);
+
+UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); }
+
+// We don't want to mark this NORETURN, see comment in .h.
+// Unfortunately this code to suppress the warning doesn't appear to be working.
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-warning-option"
+#pragma clang diagnostic ignored "-Wsuggest-attribute"
+#endif
+
+const char *fastdecode_err(upb_decstate *d) {
+  longjmp(d->err, 1);
+  return NULL;
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+const uint8_t upb_utf8_offsets[] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) {
+  if (!decode_verifyutf8_inl(buf, len)) decode_err(d);
+}
+
+static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) {
+  bool need_realloc = arr->size - arr->len < elem;
+  if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, &d->arena)) {
+    decode_err(d);
+  }
+  return need_realloc;
+}
+
+typedef struct {
+  const char *ptr;
+  uint64_t val;
+} decode_vret;
+
+UPB_NOINLINE
+static decode_vret decode_longvarint64(const char *ptr, uint64_t val) {
+  decode_vret ret = {NULL, 0};
+  uint64_t byte;
+  int i;
+  for (i = 1; i < 10; i++) {
+    byte = (uint8_t)ptr[i];
+    val += (byte - 1) << (i * 7);
+    if (!(byte & 0x80)) {
+      ret.ptr = ptr + i + 1;
+      ret.val = val;
+      return ret;
+    }
+  }
+  return ret;
+}
+
+UPB_FORCEINLINE
+static const char *decode_varint64(upb_decstate *d, const char *ptr,
+                                   uint64_t *val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = byte;
+    return ptr + 1;
+  } else {
+    decode_vret res = decode_longvarint64(ptr, byte);
+    if (!res.ptr) decode_err(d);
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char *decode_tag(upb_decstate *d, const char *ptr,
+                                   uint32_t *val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = byte;
+    return ptr + 1;
+  } else {
+    const char *start = ptr;
+    decode_vret res = decode_longvarint64(ptr, byte);
+    ptr = res.ptr;
+    *val = res.val;
+    if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d);
+    return ptr;
+  }
+}
+
+static void decode_munge(int type, wireval *val) {
+  switch (type) {
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      val->bool_val = val->uint64_val != 0;
+      break;
+    case UPB_DESCRIPTOR_TYPE_SINT32: {
+      uint32_t n = val->uint32_val;
+      val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_SINT64: {
+      uint64_t n = val->uint64_val;
+      val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      if (!_upb_isle()) {
+        /* The next stage will memcpy(dst, &val, 4) */
+        val->uint32_val = val->uint64_val;
+      }
+      break;
+  }
+}
+
+static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
+                                                 uint32_t field_number) {
+  static upb_msglayout_field none = {0, 0, 0, 0, 0, 0};
+
+  /* Lots of optimization opportunities here. */
+  int i;
+  if (l == NULL) return &none;
+  for (i = 0; i < l->field_count; i++) {
+    if (l->fields[i].number == field_number) {
+      return &l->fields[i];
+    }
+  }
+
+  return &none; /* Unknown field. */
+}
+
+static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
+                                 const upb_msglayout_field *field) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  return _upb_msg_new_inl(subl, &d->arena);
+}
+
+UPB_NOINLINE
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+                                  int overrun) {
+  ptr = decode_isdonefallback_inl(d, ptr, overrun);
+  if (ptr == NULL) {
+    decode_err(d);
+  }
+  return ptr;
+}
+
+static const char *decode_readstr(upb_decstate *d, const char *ptr, int size,
+                                  upb_strview *str) {
+  if (d->alias) {
+    str->data = ptr;
+  } else {
+    char *data =  upb_arena_malloc(&d->arena, size);
+    if (!data) decode_err(d);
+    memcpy(data, ptr, size);
+    str->data = data;
+  }
+  str->size = size;
+  return ptr + size;
+}
+
+UPB_FORCEINLINE
+static const char *decode_tosubmsg(upb_decstate *d, const char *ptr,
+                                   upb_msg *submsg, const upb_msglayout *layout,
+                                   const upb_msglayout_field *field, int size) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  int saved_delta = decode_pushlimit(d, ptr, size);
+  if (--d->depth < 0) decode_err(d);
+  if (!decode_isdone(d, &ptr)) {
+    ptr = decode_msg(d, ptr, submsg, subl);
+  }
+  if (d->end_group != DECODE_NOGROUP) decode_err(d);
+  decode_poplimit(d, ptr, saved_delta);
+  d->depth++;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *decode_group(upb_decstate *d, const char *ptr,
+                                upb_msg *submsg, const upb_msglayout *subl,
+                                uint32_t number) {
+  if (--d->depth < 0) decode_err(d);
+  if (decode_isdone(d, &ptr)) {
+    decode_err(d);
+  }
+  ptr = decode_msg(d, ptr, submsg, subl);
+  if (d->end_group != number) decode_err(d);
+  d->end_group = DECODE_NOGROUP;
+  d->depth++;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *decode_togroup(upb_decstate *d, const char *ptr,
+                                  upb_msg *submsg, const upb_msglayout *layout,
+                                  const upb_msglayout_field *field) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  return decode_group(d, ptr, submsg, subl, field->number);
+}
+
+static const char *decode_toarray(upb_decstate *d, const char *ptr,
+                                  upb_msg *msg, const upb_msglayout *layout,
+                                  const upb_msglayout_field *field, wireval val,
+                                  int op) {
+  upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
+  upb_array *arr = *arrp;
+  void *mem;
+
+  if (arr) {
+    decode_reserve(d, arr, 1);
+  } else {
+    size_t lg2 = desctype_to_elem_size_lg2[field->descriptortype];
+    arr = _upb_array_new(&d->arena, 4, lg2);
+    if (!arr) decode_err(d);
+    *arrp = arr;
+  }
+
+  switch (op) {
+    case OP_SCALAR_LG2(0):
+    case OP_SCALAR_LG2(2):
+    case OP_SCALAR_LG2(3):
+      /* Append scalar value. */
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
+      arr->len++;
+      memcpy(mem, &val, 1 << op);
+      return ptr;
+    case OP_STRING:
+      decode_verifyutf8(d, ptr, val.size);
+      /* Fallthrough. */
+    case OP_BYTES: {
+      /* Append bytes. */
+      upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len;
+      arr->len++;
+      return decode_readstr(d, ptr, val.size, str);
+    }
+    case OP_SUBMSG: {
+      /* Append submessage / group. */
+      upb_msg *submsg = decode_newsubmsg(d, layout, field);
+      *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
+          submsg;
+      arr->len++;
+      if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
+        return decode_togroup(d, ptr, submsg, layout, field);
+      } else {
+        return decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
+      }
+    }
+    case OP_FIXPCK_LG2(2):
+    case OP_FIXPCK_LG2(3): {
+      /* Fixed packed. */
+      int lg2 = op - OP_FIXPCK_LG2(0);
+      int mask = (1 << lg2) - 1;
+      size_t count = val.size >> lg2;
+      if ((val.size & mask) != 0) {
+        decode_err(d); /* Length isn't a round multiple of elem size. */
+      }
+      decode_reserve(d, arr, count);
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+      arr->len += count;
+      memcpy(mem, ptr, val.size);  /* XXX: ptr boundary. */
+      return ptr + val.size;
+    }
+    case OP_VARPCK_LG2(0):
+    case OP_VARPCK_LG2(2):
+    case OP_VARPCK_LG2(3): {
+      /* Varint packed. */
+      int lg2 = op - OP_VARPCK_LG2(0);
+      int scale = 1 << lg2;
+      int saved_limit = decode_pushlimit(d, ptr, val.size);
+      char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+      while (!decode_isdone(d, &ptr)) {
+        wireval elem;
+        ptr = decode_varint64(d, ptr, &elem.uint64_val);
+        decode_munge(field->descriptortype, &elem);
+        if (decode_reserve(d, arr, 1)) {
+          out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+        }
+        arr->len++;
+        memcpy(out, &elem, scale);
+        out += scale;
+      }
+      decode_poplimit(d, ptr, saved_limit);
+      return ptr;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                const upb_msglayout *layout,
+                                const upb_msglayout_field *field, wireval val) {
+  upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
+  upb_map *map = *map_p;
+  upb_map_entry ent;
+  const upb_msglayout *entry = layout->submsgs[field->submsg_index];
+
+  if (!map) {
+    /* Lazily create map. */
+    const upb_msglayout *entry = layout->submsgs[field->submsg_index];
+    const upb_msglayout_field *key_field = &entry->fields[0];
+    const upb_msglayout_field *val_field = &entry->fields[1];
+    char key_size = desctype_to_mapsize[key_field->descriptortype];
+    char val_size = desctype_to_mapsize[val_field->descriptortype];
+    UPB_ASSERT(key_field->offset == 0);
+    UPB_ASSERT(val_field->offset == sizeof(upb_strview));
+    map = _upb_map_new(&d->arena, key_size, val_size);
+    *map_p = map;
+  }
+
+  /* Parse map entry. */
+  memset(&ent, 0, sizeof(ent));
+
+  if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
+      entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
+    /* Create proactively to handle the case where it doesn't appear. */
+    ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena));
+  }
+
+  ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size);
+  _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
+  return ptr;
+}
+
+static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                const upb_msglayout *layout,
+                                const upb_msglayout_field *field, wireval val,
+                                int op) {
+  void *mem = UPB_PTR_AT(msg, field->offset, void);
+  int type = field->descriptortype;
+
+  /* Set presence if necessary. */
+  if (field->presence < 0) {
+    /* Oneof case */
+    uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
+    if (op == OP_SUBMSG && *oneof_case != field->number) {
+      memset(mem, 0, sizeof(void*));
+    }
+    *oneof_case = field->number;
+  } else if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  }
+
+  /* Store into message. */
+  switch (op) {
+    case OP_SUBMSG: {
+      upb_msg **submsgp = mem;
+      upb_msg *submsg = *submsgp;
+      if (!submsg) {
+        submsg = decode_newsubmsg(d, layout, field);
+        *submsgp = submsg;
+      }
+      if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
+        ptr = decode_togroup(d, ptr, submsg, layout, field);
+      } else {
+        ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
+      }
+      break;
+    }
+    case OP_STRING:
+      decode_verifyutf8(d, ptr, val.size);
+      /* Fallthrough. */
+    case OP_BYTES:
+      return decode_readstr(d, ptr, val.size, mem);
+    case OP_SCALAR_LG2(3):
+      memcpy(mem, &val, 8);
+      break;
+    case OP_SCALAR_LG2(2):
+      memcpy(mem, &val, 4);
+      break;
+    case OP_SCALAR_LG2(0):
+      memcpy(mem, &val, 1);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr,
+                                   upb_msg *msg, const upb_msglayout *layout) {
+#if UPB_FASTTABLE
+  if (layout && layout->table_mask != (unsigned char)-1) {
+    uint16_t tag = fastdecode_loadtag(*ptr);
+    intptr_t table = decode_totable(layout);
+    *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag);
+    return true;
+  }
+#endif
+  return false;
+}
+
+UPB_NOINLINE
+static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                              const upb_msglayout *layout) {
+  while (true) {
+    uint32_t tag;
+    const upb_msglayout_field *field;
+    int field_number;
+    int wire_type;
+    const char *field_start = ptr;
+    wireval val;
+    int op;
+
+    UPB_ASSERT(ptr < d->limit_ptr);
+    ptr = decode_tag(d, ptr, &tag);
+    field_number = tag >> 3;
+    wire_type = tag & 7;
+
+    field = upb_find_field(layout, field_number);
+
+    switch (wire_type) {
+      case UPB_WIRE_TYPE_VARINT:
+        ptr = decode_varint64(d, ptr, &val.uint64_val);
+        op = varint_ops[field->descriptortype];
+        decode_munge(field->descriptortype, &val);
+        break;
+      case UPB_WIRE_TYPE_32BIT:
+        memcpy(&val.uint32_val, ptr, 4);
+        val.uint32_val = _upb_be_swap32(val.uint32_val);
+        ptr += 4;
+        op = OP_SCALAR_LG2(2);
+        if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_64BIT:
+        memcpy(&val.uint64_val, ptr, 8);
+        val.uint64_val = _upb_be_swap64(val.uint64_val);
+        ptr += 8;
+        op = OP_SCALAR_LG2(3);
+        if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_DELIMITED: {
+        int ndx = field->descriptortype;
+        uint64_t size;
+        if (_upb_isrepeated(field)) ndx += 18;
+        ptr = decode_varint64(d, ptr, &size);
+        if (size >= INT32_MAX ||
+            ptr - d->end + (int32_t)size > d->limit) {
+          decode_err(d); /* Length overflow. */
+        }
+        op = delim_ops[ndx];
+        val.size = size;
+        break;
+      }
+      case UPB_WIRE_TYPE_START_GROUP:
+        val.uint32_val = field_number;
+        op = OP_SUBMSG;
+        if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_END_GROUP:
+        d->end_group = field_number;
+        return ptr;
+      default:
+        decode_err(d);
+    }
+
+    if (op >= 0) {
+      /* Parse, using op for dispatch. */
+      switch (field->label) {
+        case UPB_LABEL_REPEATED:
+        case _UPB_LABEL_PACKED:
+          ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
+          break;
+        case _UPB_LABEL_MAP:
+          ptr = decode_tomap(d, ptr, msg, layout, field, val);
+          break;
+        default:
+          ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
+          break;
+      }
+    } else {
+    unknown:
+      /* Skip unknown field. */
+      if (field_number == 0) decode_err(d);
+      if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size;
+      if (msg) {
+        if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+          d->unknown = field_start;
+          d->unknown_msg = msg;
+          ptr = decode_group(d, ptr, NULL, NULL, field_number);
+          d->unknown_msg = NULL;
+          field_start = d->unknown;
+        }
+        if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
+                                 &d->arena)) {
+          decode_err(d);
+        }
+      } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+        ptr = decode_group(d, ptr, NULL, NULL, field_number);
+      }
+    }
+
+    if (decode_isdone(d, &ptr)) return ptr;
+    if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr;
+  }
+}
+
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+                               upb_msg *msg, intptr_t table, uint64_t hasbits,
+                               uint64_t data) {
+  (void)data;
+  *(uint32_t*)msg |= hasbits;
+  return decode_msg(d, ptr, msg, decode_totablep(table));
+}
+
+static bool decode_top(struct upb_decstate *d, const char *buf, void *msg,
+                       const upb_msglayout *l) {
+  if (!decode_tryfastdispatch(d, &buf, msg, l)) {
+    decode_msg(d, buf, msg, l);
+  }
+  return d->end_group == DECODE_NOGROUP;
+}
+
+bool _upb_decode(const char *buf, size_t size, void *msg,
+                 const upb_msglayout *l, upb_arena *arena, int options) {
+  bool ok;
+  upb_decstate state;
+  unsigned depth = (unsigned)options >> 16;
+
+  if (size == 0) {
+    return true;
+  } else if (size <= 16) {
+    memset(&state.patch, 0, 32);
+    memcpy(&state.patch, buf, size);
+    buf = state.patch;
+    state.end = buf + size;
+    state.limit = 0;
+    state.alias = false;
+  } else {
+    state.end = buf + size - 16;
+    state.limit = 16;
+    state.alias = options & UPB_DECODE_ALIAS;
+  }
+
+  state.limit_ptr = state.end;
+  state.unknown_msg = NULL;
+  state.depth = depth ? depth : 64;
+  state.end_group = DECODE_NOGROUP;
+  state.arena.head = arena->head;
+  state.arena.last_size = arena->last_size;
+  state.arena.cleanup_metadata = arena->cleanup_metadata;
+  state.arena.parent = arena;
+
+  if (UPB_UNLIKELY(UPB_SETJMP(state.err))) {
+    ok = false;
+  } else {
+    ok = decode_top(&state, buf, msg, l);
+  }
+
+  arena->head.ptr = state.arena.head.ptr;
+  arena->head.end = state.arena.head.end;
+  arena->cleanup_metadata = state.arena.cleanup_metadata;
+  return ok;
+}
+
+#undef OP_SCALAR_LG2
+#undef OP_FIXPCK_LG2
+#undef OP_VARPCK_LG2
+#undef OP_STRING
+#undef OP_SUBMSG
+
+/** upb/encode.c ************************************************************/
+/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
+
+
+#include <setjmp.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+#define UPB_PB_VARINT_MAX_LEN 10
+
+UPB_NOINLINE
+static size_t encode_varint64(uint64_t val, char *buf) {
+  size_t i = 0;
+  do {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    buf[i++] = byte;
+  } while (val);
+  return i;
+}
+
+static uint32_t encode_zz32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
+static uint64_t encode_zz64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
+
+typedef struct {
+  jmp_buf err;
+  upb_alloc *alloc;
+  char *buf, *ptr, *limit;
+  int options;
+  int depth;
+  _upb_mapsorter sorter;
+} upb_encstate;
+
+static size_t upb_roundup_pow2(size_t bytes) {
+  size_t ret = 128;
+  while (ret < bytes) {
+    ret *= 2;
+  }
+  return ret;
+}
+
+UPB_NORETURN static void encode_err(upb_encstate *e) {
+  UPB_LONGJMP(e->err, 1);
+}
+
+UPB_NOINLINE
+static void encode_growbuffer(upb_encstate *e, size_t bytes) {
+  size_t old_size = e->limit - e->buf;
+  size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
+  char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
+
+  if (!new_buf) encode_err(e);
+
+  /* We want previous data at the end, realloc() put it at the beginning. */
+  if (old_size > 0) {
+    memmove(new_buf + new_size - old_size, e->buf, old_size);
+  }
+
+  e->ptr = new_buf + new_size - (e->limit - e->ptr);
+  e->limit = new_buf + new_size;
+  e->buf = new_buf;
+
+  e->ptr -= bytes;
+}
+
+/* Call to ensure that at least "bytes" bytes are available for writing at
+ * e->ptr.  Returns false if the bytes could not be allocated. */
+UPB_FORCEINLINE
+static void encode_reserve(upb_encstate *e, size_t bytes) {
+  if ((size_t)(e->ptr - e->buf) < bytes) {
+    encode_growbuffer(e, bytes);
+    return;
+  }
+
+  e->ptr -= bytes;
+}
+
+/* Writes the given bytes to the buffer, handling reserve/advance. */
+static void encode_bytes(upb_encstate *e, const void *data, size_t len) {
+  if (len == 0) return;  /* memcpy() with zero size is UB */
+  encode_reserve(e, len);
+  memcpy(e->ptr, data, len);
+}
+
+static void encode_fixed64(upb_encstate *e, uint64_t val) {
+  val = _upb_be_swap64(val);
+  encode_bytes(e, &val, sizeof(uint64_t));
+}
+
+static void encode_fixed32(upb_encstate *e, uint32_t val) {
+  val = _upb_be_swap32(val);
+  encode_bytes(e, &val, sizeof(uint32_t));
+}
+
+UPB_NOINLINE
+static void encode_longvarint(upb_encstate *e, uint64_t val) {
+  size_t len;
+  char *start;
+
+  encode_reserve(e, UPB_PB_VARINT_MAX_LEN);
+  len = encode_varint64(val, e->ptr);
+  start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
+  memmove(start, e->ptr, len);
+  e->ptr = start;
+}
+
+UPB_FORCEINLINE
+static void encode_varint(upb_encstate *e, uint64_t val) {
+  if (val < 128 && e->ptr != e->buf) {
+    --e->ptr;
+    *e->ptr = val;
+  } else {
+    encode_longvarint(e, val);
+  }
+}
+
+static void encode_double(upb_encstate *e, double d) {
+  uint64_t u64;
+  UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
+  memcpy(&u64, &d, sizeof(uint64_t));
+  encode_fixed64(e, u64);
+}
+
+static void encode_float(upb_encstate *e, float d) {
+  uint32_t u32;
+  UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
+  memcpy(&u32, &d, sizeof(uint32_t));
+  encode_fixed32(e, u32);
+}
+
+static void encode_tag(upb_encstate *e, uint32_t field_number,
+                       uint8_t wire_type) {
+  encode_varint(e, (field_number << 3) | wire_type);
+}
+
+static void encode_fixedarray(upb_encstate *e, const upb_array *arr,
+                               size_t elem_size, uint32_t tag) {
+  size_t bytes = arr->len * elem_size;
+  const char* data = _upb_array_constptr(arr);
+  const char* ptr = data + bytes - elem_size;
+  if (tag) {
+    while (true) {
+      encode_bytes(e, ptr, elem_size);
+      encode_varint(e, tag);
+      if (ptr == data) break;
+      ptr -= elem_size;
+    }
+  } else {
+    encode_bytes(e, data, bytes);
+  }
+}
+
+static void encode_message(upb_encstate *e, const char *msg,
+                           const upb_msglayout *m, size_t *size);
+
+static void encode_scalar(upb_encstate *e, const void *_field_mem,
+                          const upb_msglayout *m, const upb_msglayout_field *f,
+                          bool skip_zero_value) {
+  const char *field_mem = _field_mem;
+  int wire_type;
+
+#define CASE(ctype, type, wtype, encodeval) \
+  {                                         \
+    ctype val = *(ctype *)field_mem;        \
+    if (skip_zero_value && val == 0) {      \
+      return;                               \
+    }                                       \
+    encode_##type(e, encodeval);            \
+    wire_type = wtype;                      \
+    break;                                  \
+  }
+
+  switch (f->descriptortype) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+      CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+      CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz32(val));
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz64(val));
+    case UPB_DESCRIPTOR_TYPE_STRING:
+    case UPB_DESCRIPTOR_TYPE_BYTES: {
+      upb_strview view = *(upb_strview*)field_mem;
+      if (skip_zero_value && view.size == 0) {
+        return;
+      }
+      encode_bytes(e, view.data, view.size);
+      encode_varint(e, view.size);
+      wire_type = UPB_WIRE_TYPE_DELIMITED;
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_GROUP: {
+      size_t size;
+      void *submsg = *(void **)field_mem;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e);
+      encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+      encode_message(e, submsg, subm, &size);
+      wire_type = UPB_WIRE_TYPE_START_GROUP;
+      e->depth++;
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
+      size_t size;
+      void *submsg = *(void **)field_mem;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e);
+      encode_message(e, submsg, subm, &size);
+      encode_varint(e, size);
+      wire_type = UPB_WIRE_TYPE_DELIMITED;
+      e->depth++;
+      break;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+#undef CASE
+
+  encode_tag(e, f->number, wire_type);
+}
+
+static void encode_array(upb_encstate *e, const char *field_mem,
+                         const upb_msglayout *m, const upb_msglayout_field *f) {
+  const upb_array *arr = *(const upb_array**)field_mem;
+  bool packed = f->label == _UPB_LABEL_PACKED;
+  size_t pre_len = e->limit - e->ptr;
+
+  if (arr == NULL || arr->len == 0) {
+    return;
+  }
+
+#define VARINT_CASE(ctype, encode)                                       \
+  {                                                                      \
+    const ctype *start = _upb_array_constptr(arr);                       \
+    const ctype *ptr = start + arr->len;                                 \
+    uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
+    do {                                                                 \
+      ptr--;                                                             \
+      encode_varint(e, encode);                                          \
+      if (tag) encode_varint(e, tag);                                    \
+    } while (ptr != start);                                              \
+  }                                                                      \
+  break;
+
+#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
+
+  switch (f->descriptortype) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      encode_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      encode_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      encode_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+      encode_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+      VARINT_CASE(uint64_t, *ptr);
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      VARINT_CASE(uint32_t, *ptr);
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      VARINT_CASE(int32_t, (int64_t)*ptr);
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      VARINT_CASE(bool, *ptr);
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      VARINT_CASE(int32_t, encode_zz32(*ptr));
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      VARINT_CASE(int64_t, encode_zz64(*ptr));
+    case UPB_DESCRIPTOR_TYPE_STRING:
+    case UPB_DESCRIPTOR_TYPE_BYTES: {
+      const upb_strview *start = _upb_array_constptr(arr);
+      const upb_strview *ptr = start + arr->len;
+      do {
+        ptr--;
+        encode_bytes(e, ptr->data, ptr->size);
+        encode_varint(e, ptr->size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+      } while (ptr != start);
+      return;
+    }
+    case UPB_DESCRIPTOR_TYPE_GROUP: {
+      const void *const*start = _upb_array_constptr(arr);
+      const void *const*ptr = start + arr->len;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (--e->depth == 0) encode_err(e);
+      do {
+        size_t size;
+        ptr--;
+        encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+        encode_message(e, *ptr, subm, &size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
+      const void *const*start = _upb_array_constptr(arr);
+      const void *const*ptr = start + arr->len;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (--e->depth == 0) encode_err(e);
+      do {
+        size_t size;
+        ptr--;
+        encode_message(e, *ptr, subm, &size);
+        encode_varint(e, size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+  }
+#undef VARINT_CASE
+
+  if (packed) {
+    encode_varint(e, e->limit - e->ptr - pre_len);
+    encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+  }
+}
+
+static void encode_mapentry(upb_encstate *e, uint32_t number,
+                            const upb_msglayout *layout,
+                            const upb_map_entry *ent) {
+  const upb_msglayout_field *key_field = &layout->fields[0];
+  const upb_msglayout_field *val_field = &layout->fields[1];
+  size_t pre_len = e->limit - e->ptr;
+  size_t size;
+  encode_scalar(e, &ent->v, layout, val_field, false);
+  encode_scalar(e, &ent->k, layout, key_field, false);
+  size = (e->limit - e->ptr) - pre_len;
+  encode_varint(e, size);
+  encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED);
+}
+
+static void encode_map(upb_encstate *e, const char *field_mem,
+                       const upb_msglayout *m, const upb_msglayout_field *f) {
+  const upb_map *map = *(const upb_map**)field_mem;
+  const upb_msglayout *layout = m->submsgs[f->submsg_index];
+  UPB_ASSERT(layout->field_count == 2);
+
+  if (map == NULL) return;
+
+  if (e->options & UPB_ENCODE_DETERMINISTIC) {
+    _upb_sortedmap sorted;
+    _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
+                           &sorted);
+    upb_map_entry ent;
+    while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+    _upb_mapsorter_popmap(&e->sorter, &sorted);
+  } else {
+    upb_strtable_iter i;
+    upb_strtable_begin(&i, &map->table);
+    for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+      upb_strview key = upb_strtable_iter_key(&i);
+      const upb_value val = upb_strtable_iter_value(&i);
+      upb_map_entry ent;
+      _upb_map_fromkey(key, &ent.k, map->key_size);
+      _upb_map_fromvalue(val, &ent.v, map->val_size);
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+  }
+}
+
+static void encode_scalarfield(upb_encstate *e, const char *msg,
+                               const upb_msglayout *m,
+                               const upb_msglayout_field *f) {
+  bool skip_empty = false;
+  if (f->presence == 0) {
+    /* Proto3 presence. */
+    skip_empty = true;
+  } else if (f->presence > 0) {
+    /* Proto2 presence: hasbit. */
+    if (!_upb_hasbit_field(msg, f)) return;
+  } else {
+    /* Field is in a oneof. */
+    if (_upb_getoneofcase_field(msg, f) != f->number) return;
+  }
+  encode_scalar(e, msg + f->offset, m, f, skip_empty);
+}
+
+static void encode_message(upb_encstate *e, const char *msg,
+                           const upb_msglayout *m, size_t *size) {
+  size_t pre_len = e->limit - e->ptr;
+  const upb_msglayout_field *f = &m->fields[m->field_count];
+  const upb_msglayout_field *first = &m->fields[0];
+
+  if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) {
+    size_t unknown_size;
+    const char *unknown = upb_msg_getunknown(msg, &unknown_size);
+
+    if (unknown) {
+      encode_bytes(e, unknown, unknown_size);
+    }
+  }
+
+  while (f != first) {
+    f--;
+    if (_upb_isrepeated(f)) {
+      encode_array(e, msg + f->offset, m, f);
+    } else if (f->label == _UPB_LABEL_MAP) {
+      encode_map(e, msg + f->offset, m, f);
+    } else {
+      encode_scalarfield(e, msg, m, f);
+    }
+  }
+
+  *size = (e->limit - e->ptr) - pre_len;
+}
+
+char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
+                    upb_arena *arena, size_t *size) {
+  upb_encstate e;
+  unsigned depth = (unsigned)options >> 16;
+
+  e.alloc = upb_arena_alloc(arena);
+  e.buf = NULL;
+  e.limit = NULL;
+  e.ptr = NULL;
+  e.depth = depth ? depth : 64;
+  e.options = options;
+  _upb_mapsorter_init(&e.sorter);
+  char *ret = NULL;
+
+  if (UPB_SETJMP(e.err)) {
+    *size = 0;
+    ret = NULL;
+  } else {
+    encode_message(&e, msg, l, size);
+    *size = e.limit - e.ptr;
+    if (*size == 0) {
+      static char ch;
+      ret = &ch;
+    } else {
+      UPB_ASSERT(e.ptr);
+      ret = e.ptr;
+    }
+  }
+
+  _upb_mapsorter_destroy(&e.sorter);
+  return ret;
+}
+
+/** upb/msg.c ************************************************************/
+
+
+/** upb_msg *******************************************************************/
+
+static const size_t overhead = sizeof(upb_msg_internal);
+
+static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
+  ptrdiff_t size = sizeof(upb_msg_internal);
+  return (upb_msg_internal*)((char*)msg - size);
+}
+
+upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
+  return _upb_msg_new_inl(l, a);
+}
+
+void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) {
+  void *mem = UPB_PTR_AT(msg, -sizeof(upb_msg_internal), char);
+  memset(mem, 0, upb_msg_sizeof(l));
+}
+
+bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                         upb_arena *arena) {
+
+  upb_msg_internal *in = upb_msg_getinternal(msg);
+  if (!in->unknown) {
+    size_t size = 128;
+    while (size < len) size *= 2;
+    in->unknown = upb_arena_malloc(arena, size + overhead);
+    if (!in->unknown) return false;
+    in->unknown->size = size;
+    in->unknown->len = 0;
+  } else if (in->unknown->size - in->unknown->len < len) {
+    size_t need = in->unknown->len + len;
+    size_t size = in->unknown->size;
+    while (size < need)  size *= 2;
+    in->unknown = upb_arena_realloc(
+        arena, in->unknown, in->unknown->size + overhead, size + overhead);
+    if (!in->unknown) return false;
+    in->unknown->size = size;
+  }
+  memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len);
+  in->unknown->len += len;
+  return true;
+}
+
+void _upb_msg_discardunknown_shallow(upb_msg *msg) {
+  upb_msg_internal *in = upb_msg_getinternal(msg);
+  if (in->unknown) {
+    in->unknown->len = 0;
+  }
+}
+
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
+  const upb_msg_internal *in = upb_msg_getinternal_const(msg);
+  if (in->unknown) {
+    *len = in->unknown->len;
+    return (char*)(in->unknown + 1);
+  } else {
+    *len = 0;
+    return NULL;
+  }
+}
+
+/** upb_array *****************************************************************/
+
+bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
+  size_t new_size = UPB_MAX(arr->size, 4);
+  int elem_size_lg2 = arr->data & 7;
+  size_t old_bytes = arr->size << elem_size_lg2;
+  size_t new_bytes;
+  void* ptr = _upb_array_ptr(arr);
+
+  /* Log2 ceiling of size. */
+  while (new_size < min_size) new_size *= 2;
+
+  new_bytes = new_size << elem_size_lg2;
+  ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes);
+
+  if (!ptr) {
+    return false;
+  }
+
+  arr->data = _upb_tag_arrptr(ptr, elem_size_lg2);
+  arr->size = new_size;
+  return true;
+}
+
+static upb_array *getorcreate_array(upb_array **arr_ptr, int elem_size_lg2,
+                                    upb_arena *arena) {
+  upb_array *arr = *arr_ptr;
+  if (!arr) {
+    arr = _upb_array_new(arena, 4, elem_size_lg2);
+    if (!arr) return NULL;
+    *arr_ptr = arr;
+  }
+  return arr;
+}
+
+void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
+                                 int elem_size_lg2, upb_arena *arena) {
+  upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+  return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr)
+                                                    : NULL;
+}
+
+bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
+                                int elem_size_lg2, upb_arena *arena) {
+  upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+  if (!arr) return false;
+
+  size_t elems = arr->len;
+
+  if (!_upb_array_resize(arr, elems + 1, arena)) {
+    return false;
+  }
+
+  char *data = _upb_array_ptr(arr);
+  memcpy(data + (elems << elem_size_lg2), value, 1 << elem_size_lg2);
+  return true;
+}
+
+/** upb_map *******************************************************************/
+
+upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
+  upb_map *map = upb_arena_malloc(a, sizeof(upb_map));
+
+  if (!map) {
+    return NULL;
+  }
+
+  upb_strtable_init(&map->table, 4, a);
+  map->key_size = key_size;
+  map->val_size = value_size;
+
+  return map;
+}
+
+static void _upb_mapsorter_getkeys(const void *_a, const void *_b, void *a_key,
+                                   void *b_key, size_t size) {
+  const upb_tabent *const*a = _a;
+  const upb_tabent *const*b = _b;
+  upb_strview a_tabkey = upb_tabstrview((*a)->key);
+  upb_strview b_tabkey = upb_tabstrview((*b)->key);
+  _upb_map_fromkey(a_tabkey, a_key, size);
+  _upb_map_fromkey(b_tabkey, b_key, size);
+}
+
+static int _upb_mapsorter_cmpi64(const void *_a, const void *_b) {
+  int64_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpu64(const void *_a, const void *_b) {
+  uint64_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpi32(const void *_a, const void *_b) {
+  int32_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpu32(const void *_a, const void *_b) {
+  uint32_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpbool(const void *_a, const void *_b) {
+  bool a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 1);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpstr(const void *_a, const void *_b) {
+  upb_strview a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING);
+  size_t common_size = UPB_MIN(a.size, b.size);
+  int cmp = memcmp(a.data, b.data, common_size);
+  if (cmp) return cmp;
+  return a.size - b.size;
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+                            const upb_map *map, _upb_sortedmap *sorted) {
+  int map_size = _upb_map_size(map);
+  sorted->start = s->size;
+  sorted->pos = sorted->start;
+  sorted->end = sorted->start + map_size;
+
+  /* Grow s->entries if necessary. */
+  if (sorted->end > s->cap) {
+    s->cap = _upb_lg2ceilsize(sorted->end);
+    s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
+    if (!s->entries) return false;
+  }
+
+  s->size = sorted->end;
+
+  /* Copy non-empty entries from the table to s->entries. */
+  upb_tabent const**dst = &s->entries[sorted->start];
+  const upb_tabent *src = map->table.t.entries;
+  const upb_tabent *end = src + upb_table_size(&map->table.t);
+  for (; src < end; src++) {
+    if (!upb_tabent_isempty(src)) {
+      *dst = src;
+      dst++;
+    }
+  }
+  UPB_ASSERT(dst == &s->entries[sorted->end]);
+
+  /* Sort entries according to the key type. */
+
+  int (*compar)(const void *, const void *);
+
+  switch (key_type) {
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      compar = _upb_mapsorter_cmpi64;
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      compar = _upb_mapsorter_cmpu64;
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      compar = _upb_mapsorter_cmpi32;
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      compar = _upb_mapsorter_cmpu32;
+      break;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      compar = _upb_mapsorter_cmpbool;
+      break;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      compar = _upb_mapsorter_cmpstr;
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
+  return true;
+}
+
+/** upb/table.c ************************************************************/
+/*
+ * upb_table Implementation
+ *
+ * Implementation is heavily inspired by Lua's ltable.c.
+ */
+
+#include <string.h>
+
+#include "third_party/wyhash/wyhash.h"
+
+/* Must be last. */
+
+#define UPB_MAXARRSIZE 16  /* 64k. */
+
+/* From Chromium. */
+#define ARRAY_SIZE(x) \
+    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
+
+static const double MAX_LOAD = 0.85;
+
+/* The minimum utilization of the array part of a mixed hash/array table.  This
+ * is a speed/memory-usage tradeoff (though it's not straightforward because of
+ * cache effects).  The lower this is, the more memory we'll use. */
+static const double MIN_DENSITY = 0.1;
+
+static bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
+
+static upb_value _upb_value_val(uint64_t val) {
+  upb_value ret;
+  _upb_value_setval(&ret, val);
+  return ret;
+}
+
+static int log2ceil(uint64_t v) {
+  int ret = 0;
+  bool pow2 = is_pow2(v);
+  while (v >>= 1) ret++;
+  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
+  return UPB_MIN(UPB_MAXARRSIZE, ret);
+}
+
+char *upb_strdup2(const char *s, size_t len, upb_arena *a) {
+  size_t n;
+  char *p;
+
+  /* Prevent overflow errors. */
+  if (len == SIZE_MAX) return NULL;
+  /* Always null-terminate, even if binary data; but don't rely on the input to
+   * have a null-terminating byte since it may be a raw binary buffer. */
+  n = len + 1;
+  p = upb_arena_malloc(a, n);
+  if (p) {
+    memcpy(p, s, len);
+    p[len] = 0;
+  }
+  return p;
+}
+
+/* A type to represent the lookup key of either a strtable or an inttable. */
+typedef union {
+  uintptr_t num;
+  struct {
+    const char *str;
+    size_t len;
+  } str;
+} lookupkey_t;
+
+static lookupkey_t strkey2(const char *str, size_t len) {
+  lookupkey_t k;
+  k.str.str = str;
+  k.str.len = len;
+  return k;
+}
+
+static lookupkey_t intkey(uintptr_t key) {
+  lookupkey_t k;
+  k.num = key;
+  return k;
+}
+
+typedef uint32_t hashfunc_t(upb_tabkey key);
+typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
+
+/* Base table (shared code) ***************************************************/
+
+static uint32_t upb_inthash(uintptr_t key) {
+  return (uint32_t)key;
+}
+
+static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
+  return t->entries + (hash & t->mask);
+}
+
+static bool upb_arrhas(upb_tabval key) {
+  return key.val != (uint64_t)-1;
+}
+
+
+static bool isfull(upb_table *t) {
+  return t->count == t->max_count;
+}
+
+static bool init(upb_table *t, uint8_t size_lg2, upb_arena *a) {
+  size_t bytes;
+
+  t->count = 0;
+  t->size_lg2 = size_lg2;
+  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
+  t->max_count = upb_table_size(t) * MAX_LOAD;
+  bytes = upb_table_size(t) * sizeof(upb_tabent);
+  if (bytes > 0) {
+    t->entries = upb_arena_malloc(a, bytes);
+    if (!t->entries) return false;
+    memset(t->entries, 0, bytes);
+  } else {
+    t->entries = NULL;
+  }
+  return true;
+}
+
+static upb_tabent *emptyent(upb_table *t, upb_tabent *e) {
+  upb_tabent *begin = t->entries;
+  upb_tabent *end = begin + upb_table_size(t);
+  for (e = e + 1; e < end; e++) {
+    if (upb_tabent_isempty(e)) return e;
+  }
+  for (e = begin; e < end; e++) {
+    if (upb_tabent_isempty(e)) return e;
+  }
+  UPB_ASSERT(false);
+  return NULL;
+}
+
+static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
+  return (upb_tabent*)upb_getentry(t, hash);
+}
+
+static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
+                                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e;
+
+  if (t->size_lg2 == 0) return NULL;
+  e = upb_getentry(t, hash);
+  if (upb_tabent_isempty(e)) return NULL;
+  while (1) {
+    if (eql(e->key, key)) return e;
+    if ((e = e->next) == NULL) return NULL;
+  }
+}
+
+static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
+                                     uint32_t hash, eqlfunc_t *eql) {
+  return (upb_tabent*)findentry(t, key, hash, eql);
+}
+
+static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
+                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e = findentry(t, key, hash, eql);
+  if (e) {
+    if (v) {
+      _upb_value_setval(v, e->val.val);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* The given key must not already exist in the table. */
+static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
+                   upb_value val, uint32_t hash,
+                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
+  upb_tabent *mainpos_e;
+  upb_tabent *our_e;
+
+  UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
+
+  t->count++;
+  mainpos_e = getentry_mutable(t, hash);
+  our_e = mainpos_e;
+
+  if (upb_tabent_isempty(mainpos_e)) {
+    /* Our main position is empty; use it. */
+    our_e->next = NULL;
+  } else {
+    /* Collision. */
+    upb_tabent *new_e = emptyent(t, mainpos_e);
+    /* Head of collider's chain. */
+    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
+    if (chain == mainpos_e) {
+      /* Existing ent is in its main position (it has the same hash as us, and
+       * is the head of our chain).  Insert to new ent and append to this chain. */
+      new_e->next = mainpos_e->next;
+      mainpos_e->next = new_e;
+      our_e = new_e;
+    } else {
+      /* Existing ent is not in its main position (it is a node in some other
+       * chain).  This implies that no existing ent in the table has our hash.
+       * Evict it (updating its chain) and use its ent for head of our chain. */
+      *new_e = *mainpos_e;  /* copies next. */
+      while (chain->next != mainpos_e) {
+        chain = (upb_tabent*)chain->next;
+        UPB_ASSERT(chain);
+      }
+      chain->next = new_e;
+      our_e = mainpos_e;
+      our_e->next = NULL;
+    }
+  }
+  our_e->key = tabkey;
+  our_e->val.val = val.val;
+  UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
+}
+
+static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
+               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
+  upb_tabent *chain = getentry_mutable(t, hash);
+  if (upb_tabent_isempty(chain)) return false;
+  if (eql(chain->key, key)) {
+    /* Element to remove is at the head of its chain. */
+    t->count--;
+    if (val) _upb_value_setval(val, chain->val.val);
+    if (removed) *removed = chain->key;
+    if (chain->next) {
+      upb_tabent *move = (upb_tabent*)chain->next;
+      *chain = *move;
+      move->key = 0;  /* Make the slot empty. */
+    } else {
+      chain->key = 0;  /* Make the slot empty. */
+    }
+    return true;
+  } else {
+    /* Element to remove is either in a non-head position or not in the
+     * table. */
+    while (chain->next && !eql(chain->next->key, key)) {
+      chain = (upb_tabent*)chain->next;
+    }
+    if (chain->next) {
+      /* Found element to remove. */
+      upb_tabent *rm = (upb_tabent*)chain->next;
+      t->count--;
+      if (val) _upb_value_setval(val, chain->next->val.val);
+      if (removed) *removed = rm->key;
+      rm->key = 0;  /* Make the slot empty. */
+      chain->next = rm->next;
+      return true;
+    } else {
+      /* Element to remove is not in the table. */
+      return false;
+    }
+  }
+}
+
+static size_t next(const upb_table *t, size_t i) {
+  do {
+    if (++i >= upb_table_size(t))
+      return SIZE_MAX - 1;  /* Distinct from -1. */
+  } while(upb_tabent_isempty(&t->entries[i]));
+
+  return i;
+}
+
+static size_t begin(const upb_table *t) {
+  return next(t, -1);
+}
+
+
+/* upb_strtable ***************************************************************/
+
+/* A simple "subclass" of upb_table that only adds a hash function for strings. */
+
+static upb_tabkey strcopy(lookupkey_t k2, upb_arena *a) {
+  uint32_t len = (uint32_t) k2.str.len;
+  char *str = upb_arena_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
+  if (str == NULL) return 0;
+  memcpy(str, &len, sizeof(uint32_t));
+  if (k2.str.len) memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
+  str[sizeof(uint32_t) + k2.str.len] = '\0';
+  return (uintptr_t)str;
+}
+
+static uint32_t table_hash(const char *p, size_t n) {
+  return wyhash(p, n, 0, _wyp);
+}
+
+static uint32_t strhash(upb_tabkey key) {
+  uint32_t len;
+  char *str = upb_tabstr(key, &len);
+  return table_hash(str, len);
+}
+
+static bool streql(upb_tabkey k1, lookupkey_t k2) {
+  uint32_t len;
+  char *str = upb_tabstr(k1, &len);
+  return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0);
+}
+
+bool upb_strtable_init(upb_strtable *t, size_t expected_size, upb_arena *a) {
+  // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2 denominator.
+  size_t need_entries = (expected_size + 1) * 1204 / 1024;
+  UPB_ASSERT(need_entries >= expected_size * 0.85);
+  int size_lg2 = _upb_lg2ceil(need_entries);
+  return init(&t->t, size_lg2, a);
+}
+
+void upb_strtable_clear(upb_strtable *t) {
+  size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
+  t->t.count = 0;
+  memset((char*)t->t.entries, 0, bytes);
+}
+
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_arena *a) {
+  upb_strtable new_table;
+  upb_strtable_iter i;
+
+  if (!init(&new_table.t, size_lg2, a))
+    return false;
+  upb_strtable_begin(&i, t);
+  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+    upb_strview key = upb_strtable_iter_key(&i);
+    upb_strtable_insert(&new_table, key.data, key.size,
+                        upb_strtable_iter_value(&i), a);
+  }
+  *t = new_table;
+  return true;
+}
+
+bool upb_strtable_insert(upb_strtable *t, const char *k, size_t len,
+                         upb_value v, upb_arena *a) {
+  lookupkey_t key;
+  upb_tabkey tabkey;
+  uint32_t hash;
+
+  if (isfull(&t->t)) {
+    /* Need to resize.  New table of double the size, add old elements to it. */
+    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
+      return false;
+    }
+  }
+
+  key = strkey2(k, len);
+  tabkey = strcopy(key, a);
+  if (tabkey == 0) return false;
+
+  hash = table_hash(key.str.str, key.str.len);
+  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
+  return true;
+}
+
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v) {
+  uint32_t hash = table_hash(key, len);
+  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
+}
+
+bool upb_strtable_remove(upb_strtable *t, const char *key, size_t len,
+                         upb_value *val) {
+  uint32_t hash = table_hash(key, len);
+  upb_tabkey tabkey;
+  return rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql);
+}
+
+/* Iteration */
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
+  i->t = t;
+  i->index = begin(&t->t);
+}
+
+void upb_strtable_next(upb_strtable_iter *i) {
+  i->index = next(&i->t->t, i->index);
+}
+
+bool upb_strtable_done(const upb_strtable_iter *i) {
+  if (!i->t) return true;
+  return i->index >= upb_table_size(&i->t->t) ||
+         upb_tabent_isempty(str_tabent(i));
+}
+
+upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) {
+  upb_strview key;
+  uint32_t len;
+  UPB_ASSERT(!upb_strtable_done(i));
+  key.data = upb_tabstr(str_tabent(i)->key, &len);
+  key.size = len;
+  return key;
+}
+
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
+  UPB_ASSERT(!upb_strtable_done(i));
+  return _upb_value_val(str_tabent(i)->val.val);
+}
+
+void upb_strtable_iter_setdone(upb_strtable_iter *i) {
+  i->t = NULL;
+  i->index = SIZE_MAX;
+}
+
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2) {
+  if (upb_strtable_done(i1) && upb_strtable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index;
+}
+
+
+/* upb_inttable ***************************************************************/
+
+/* For inttables we use a hybrid structure where small keys are kept in an
+ * array and large keys are put in the hash table. */
+
+static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
+
+static bool inteql(upb_tabkey k1, lookupkey_t k2) {
+  return k1 == k2.num;
+}
+
+static upb_tabval *mutable_array(upb_inttable *t) {
+  return (upb_tabval*)t->array;
+}
+
+static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
+  if (key < t->array_size) {
+    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
+  } else {
+    upb_tabent *e =
+        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
+    return e ? &e->val : NULL;
+  }
+}
+
+static const upb_tabval *inttable_val_const(const upb_inttable *t,
+                                            uintptr_t key) {
+  return inttable_val((upb_inttable*)t, key);
+}
+
+size_t upb_inttable_count(const upb_inttable *t) {
+  return t->t.count + t->array_count;
+}
+
+static void check(upb_inttable *t) {
+  UPB_UNUSED(t);
+#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
+  {
+    /* This check is very expensive (makes inserts/deletes O(N)). */
+    size_t count = 0;
+    upb_inttable_iter i;
+    upb_inttable_begin(&i, t);
+    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
+      UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
+    }
+    UPB_ASSERT(count == upb_inttable_count(t));
+  }
+#endif
+}
+
+bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
+                            upb_arena *a) {
+  size_t array_bytes;
+
+  if (!init(&t->t, hsize_lg2, a)) return false;
+  /* Always make the array part at least 1 long, so that we know key 0
+   * won't be in the hash part, which simplifies things. */
+  t->array_size = UPB_MAX(1, asize);
+  t->array_count = 0;
+  array_bytes = t->array_size * sizeof(upb_value);
+  t->array = upb_arena_malloc(a, array_bytes);
+  if (!t->array) {
+    return false;
+  }
+  memset(mutable_array(t), 0xff, array_bytes);
+  check(t);
+  return true;
+}
+
+bool upb_inttable_init(upb_inttable *t, upb_arena *a) {
+  return upb_inttable_sizedinit(t, 0, 4, a);
+}
+
+bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val,
+                         upb_arena *a) {
+  upb_tabval tabval;
+  tabval.val = val.val;
+  UPB_ASSERT(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
+
+  if (key < t->array_size) {
+    UPB_ASSERT(!upb_arrhas(t->array[key]));
+    t->array_count++;
+    mutable_array(t)[key].val = val.val;
+  } else {
+    if (isfull(&t->t)) {
+      /* Need to resize the hash part, but we re-use the array part. */
+      size_t i;
+      upb_table new_table;
+
+      if (!init(&new_table, t->t.size_lg2 + 1, a)) {
+        return false;
+      }
+
+      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
+        const upb_tabent *e = &t->t.entries[i];
+        uint32_t hash;
+        upb_value v;
+
+        _upb_value_setval(&v, e->val.val);
+        hash = upb_inthash(e->key);
+        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
+      }
+
+      UPB_ASSERT(t->t.count == new_table.count);
+
+      t->t = new_table;
+    }
+    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
+  }
+  check(t);
+  return true;
+}
+
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
+  const upb_tabval *table_v = inttable_val_const(t, key);
+  if (!table_v) return false;
+  if (v) _upb_value_setval(v, table_v->val);
+  return true;
+}
+
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
+  upb_tabval *table_v = inttable_val(t, key);
+  if (!table_v) return false;
+  table_v->val = val.val;
+  return true;
+}
+
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
+  bool success;
+  if (key < t->array_size) {
+    if (upb_arrhas(t->array[key])) {
+      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
+      t->array_count--;
+      if (val) {
+        _upb_value_setval(val, t->array[key].val);
+      }
+      mutable_array(t)[key] = empty;
+      success = true;
+    } else {
+      success = false;
+    }
+  } else {
+    success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
+  }
+  check(t);
+  return success;
+}
+
+void upb_inttable_compact(upb_inttable *t, upb_arena *a) {
+  /* A power-of-two histogram of the table keys. */
+  size_t counts[UPB_MAXARRSIZE + 1] = {0};
+
+  /* The max key in each bucket. */
+  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
+
+  upb_inttable_iter i;
+  size_t arr_count;
+  int size_lg2;
+  upb_inttable new_t;
+
+  upb_inttable_begin(&i, t);
+  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    uintptr_t key = upb_inttable_iter_key(&i);
+    int bucket = log2ceil(key);
+    max[bucket] = UPB_MAX(max[bucket], key);
+    counts[bucket]++;
+  }
+
+  /* Find the largest power of two that satisfies the MIN_DENSITY
+   * definition (while actually having some keys). */
+  arr_count = upb_inttable_count(t);
+
+  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
+    if (counts[size_lg2] == 0) {
+      /* We can halve again without losing any entries. */
+      continue;
+    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
+      break;
+    }
+
+    arr_count -= counts[size_lg2];
+  }
+
+  UPB_ASSERT(arr_count <= upb_inttable_count(t));
+
+  {
+    /* Insert all elements into new, perfectly-sized table. */
+    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
+    size_t hash_count = upb_inttable_count(t) - arr_count;
+    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
+    int hashsize_lg2 = log2ceil(hash_size);
+
+    upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a);
+    upb_inttable_begin(&i, t);
+    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+      uintptr_t k = upb_inttable_iter_key(&i);
+      upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i), a);
+    }
+    UPB_ASSERT(new_t.array_size == arr_size);
+    UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
+  }
+  *t = new_t;
+}
+
+/* Iteration. */
+
+static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
+  UPB_ASSERT(!i->array_part);
+  return &i->t->t.entries[i->index];
+}
+
+static upb_tabval int_arrent(const upb_inttable_iter *i) {
+  UPB_ASSERT(i->array_part);
+  return i->t->array[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
+  i->t = t;
+  i->index = -1;
+  i->array_part = true;
+  upb_inttable_next(i);
+}
+
+void upb_inttable_next(upb_inttable_iter *iter) {
+  const upb_inttable *t = iter->t;
+  if (iter->array_part) {
+    while (++iter->index < t->array_size) {
+      if (upb_arrhas(int_arrent(iter))) {
+        return;
+      }
+    }
+    iter->array_part = false;
+    iter->index = begin(&t->t);
+  } else {
+    iter->index = next(&t->t, iter->index);
+  }
+}
+
+bool upb_inttable_done(const upb_inttable_iter *i) {
+  if (!i->t) return true;
+  if (i->array_part) {
+    return i->index >= i->t->array_size ||
+           !upb_arrhas(int_arrent(i));
+  } else {
+    return i->index >= upb_table_size(&i->t->t) ||
+           upb_tabent_isempty(int_tabent(i));
+  }
+}
+
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
+  UPB_ASSERT(!upb_inttable_done(i));
+  return i->array_part ? i->index : int_tabent(i)->key;
+}
+
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
+  UPB_ASSERT(!upb_inttable_done(i));
+  return _upb_value_val(
+      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val);
+}
+
+void upb_inttable_iter_setdone(upb_inttable_iter *i) {
+  i->t = NULL;
+  i->index = SIZE_MAX;
+  i->array_part = false;
+}
+
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                                          const upb_inttable_iter *i2) {
+  if (upb_inttable_done(i1) && upb_inttable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index &&
+         i1->array_part == i2->array_part;
+}
+
+/** upb/upb.c ************************************************************/
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* upb_status *****************************************************************/
+
+void upb_status_clear(upb_status *status) {
+  if (!status) return;
+  status->ok = true;
+  status->msg[0] = '\0';
+}
+
+bool upb_ok(const upb_status *status) { return status->ok; }
+
+const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
+
+void upb_status_seterrmsg(upb_status *status, const char *msg) {
+  if (!status) return;
+  status->ok = false;
+  strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_status_vseterrf(status, fmt, args);
+  va_end(args);
+}
+
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
+  if (!status) return;
+  status->ok = false;
+  vsnprintf(status->msg, sizeof(status->msg), fmt, args);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) {
+  size_t len;
+  if (!status) return;
+  status->ok = false;
+  len = strlen(status->msg);
+  vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+/* upb_alloc ******************************************************************/
+
+static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                                  size_t size) {
+  UPB_UNUSED(alloc);
+  UPB_UNUSED(oldsize);
+  if (size == 0) {
+    free(ptr);
+    return NULL;
+  } else {
+    return realloc(ptr, size);
+  }
+}
+
+static uint32_t *upb_cleanup_pointer(uintptr_t cleanup_metadata) {
+  return (uint32_t *)(cleanup_metadata & ~0x1);
+}
+
+static bool upb_cleanup_has_initial_block(uintptr_t cleanup_metadata) {
+  return cleanup_metadata & 0x1;
+}
+
+static uintptr_t upb_cleanup_metadata(uint32_t *cleanup,
+                                      bool has_initial_block) {
+  return (uintptr_t)cleanup | has_initial_block;
+}
+
+upb_alloc upb_alloc_global = {&upb_global_allocfunc};
+
+/* upb_arena ******************************************************************/
+
+/* Be conservative and choose 16 in case anyone is using SSE. */
+
+struct mem_block {
+  struct mem_block *next;
+  uint32_t size;
+  uint32_t cleanups;
+  /* Data follows. */
+};
+
+typedef struct cleanup_ent {
+  upb_cleanup_func *cleanup;
+  void *ud;
+} cleanup_ent;
+
+static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16);
+
+static upb_arena *arena_findroot(upb_arena *a) {
+  /* Path splitting keeps time complexity down, see:
+   *   https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
+  while (a->parent != a) {
+    upb_arena *next = a->parent;
+    a->parent = next->parent;
+    a = next;
+  }
+  return a;
+}
+
+static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr,
+                               size_t size) {
+  mem_block *block = ptr;
+
+  /* The block is for arena |a|, but should appear in the freelist of |root|. */
+  block->next = root->freelist;
+  block->size = (uint32_t)size;
+  block->cleanups = 0;
+  root->freelist = block;
+  a->last_size = block->size;
+  if (!root->freelist_tail) root->freelist_tail = block;
+
+  a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
+  a->head.end = UPB_PTR_AT(block, size, char);
+  a->cleanup_metadata = upb_cleanup_metadata(
+      &block->cleanups, upb_cleanup_has_initial_block(a->cleanup_metadata));
+
+  UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr);
+}
+
+static bool upb_arena_allocblock(upb_arena *a, size_t size) {
+  upb_arena *root = arena_findroot(a);
+  size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve;
+  mem_block *block = upb_malloc(root->block_alloc, block_size);
+
+  if (!block) return false;
+  upb_arena_addblock(a, root, block, block_size);
+  return true;
+}
+
+void *_upb_arena_slowmalloc(upb_arena *a, size_t size) {
+  if (!upb_arena_allocblock(a, size)) return NULL;  /* Out of memory. */
+  UPB_ASSERT(_upb_arenahas(a) >= size);
+  return upb_arena_malloc(a, size);
+}
+
+static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                               size_t size) {
+  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
+  return upb_arena_realloc(a, ptr, oldsize, size);
+}
+
+/* Public Arena API ***********************************************************/
+
+upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) {
+  const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve;
+  upb_arena *a;
+
+  /* We need to malloc the initial block. */
+  n = first_block_overhead + 256;
+  if (!alloc || !(mem = upb_malloc(alloc, n))) {
+    return NULL;
+  }
+
+  a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
+  n -= sizeof(*a);
+
+  a->head.alloc.func = &upb_arena_doalloc;
+  a->block_alloc = alloc;
+  a->parent = a;
+  a->refcount = 1;
+  a->freelist = NULL;
+  a->freelist_tail = NULL;
+  a->cleanup_metadata = upb_cleanup_metadata(NULL, false);
+
+  upb_arena_addblock(a, a, mem, n);
+
+  return a;
+}
+
+upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
+  upb_arena *a;
+
+  /* Round block size down to alignof(*a) since we will allocate the arena
+   * itself at the end. */
+  n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena));
+
+  if (UPB_UNLIKELY(n < sizeof(upb_arena))) {
+    return arena_initslow(mem, n, alloc);
+  }
+
+  a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
+
+  a->head.alloc.func = &upb_arena_doalloc;
+  a->block_alloc = alloc;
+  a->parent = a;
+  a->refcount = 1;
+  a->last_size = UPB_MAX(128, n);
+  a->head.ptr = mem;
+  a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char);
+  a->freelist = NULL;
+  a->cleanup_metadata = upb_cleanup_metadata(NULL, true);
+
+  return a;
+}
+
+static void arena_dofree(upb_arena *a) {
+  mem_block *block = a->freelist;
+  UPB_ASSERT(a->parent == a);
+  UPB_ASSERT(a->refcount == 0);
+
+  while (block) {
+    /* Load first since we are deleting block. */
+    mem_block *next = block->next;
+
+    if (block->cleanups > 0) {
+      cleanup_ent *end = UPB_PTR_AT(block, block->size, void);
+      cleanup_ent *ptr = end - block->cleanups;
+
+      for (; ptr < end; ptr++) {
+        ptr->cleanup(ptr->ud);
+      }
+    }
+
+    upb_free(a->block_alloc, block);
+    block = next;
+  }
+}
+
+void upb_arena_free(upb_arena *a) {
+  a = arena_findroot(a);
+  if (--a->refcount == 0) arena_dofree(a);
+}
+
+bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
+  cleanup_ent *ent;
+  uint32_t* cleanups = upb_cleanup_pointer(a->cleanup_metadata);
+
+  if (!cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) {
+    if (!upb_arena_allocblock(a, 128)) return false;  /* Out of memory. */
+    UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent));
+    cleanups = upb_cleanup_pointer(a->cleanup_metadata);
+  }
+
+  a->head.end -= sizeof(cleanup_ent);
+  ent = (cleanup_ent*)a->head.end;
+  (*cleanups)++;
+  UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent));
+
+  ent->cleanup = func;
+  ent->ud = ud;
+
+  return true;
+}
+
+bool upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
+  upb_arena *r1 = arena_findroot(a1);
+  upb_arena *r2 = arena_findroot(a2);
+
+  if (r1 == r2) return true;  /* Already fused. */
+
+  /* Do not fuse initial blocks since we cannot lifetime extend them. */
+  if (upb_cleanup_has_initial_block(r1->cleanup_metadata)) return false;
+  if (upb_cleanup_has_initial_block(r2->cleanup_metadata)) return false;
+
+  /* Only allow fuse with a common allocator */
+  if (r1->block_alloc != r2->block_alloc) return false;
+
+  /* We want to join the smaller tree to the larger tree.
+   * So swap first if they are backwards. */
+  if (r1->refcount < r2->refcount) {
+    upb_arena *tmp = r1;
+    r1 = r2;
+    r2 = tmp;
+  }
+
+  /* r1 takes over r2's freelist and refcount. */
+  r1->refcount += r2->refcount;
+  if (r2->freelist_tail) {
+    UPB_ASSERT(r2->freelist_tail->next == NULL);
+    r2->freelist_tail->next = r1->freelist;
+    r1->freelist = r2->freelist;
+  }
+  r2->parent = r1;
+  return true;
+}
+
+/** upb/decode_fast.c ************************************************************/
+// Fast decoder: ~3x the speed of decode.c, but requires x86-64/ARM64.
+// Also the table size grows by 2x.
+//
+// Could potentially be ported to other 64-bit archs that pass at least six
+// arguments in registers and have 8 unused high bits in pointers.
+//
+// The overall design is to create specialized functions for every possible
+// field type (eg. oneof boolean field with a 1 byte tag) and then dispatch
+// to the specialized function as quickly as possible.
+
+
+
+/* Must be last. */
+
+#if UPB_FASTTABLE
+
+// The standard set of arguments passed to each parsing function.
+// Thanks to x86-64 calling conventions, these will stay in registers.
+#define UPB_PARSE_PARAMS                                          \
+  upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+      uint64_t hasbits, uint64_t data
+
+#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
+
+#define RETURN_GENERIC(m)                                                      \
+  /* Uncomment either of these for debugging purposes. */                      \
+  /* fprintf(stderr, m); */                                                    \
+  /*__builtin_trap(); */                                                       \
+  return fastdecode_generic(d, ptr, msg, table, hasbits, 0);
+
+typedef enum {
+  CARD_s = 0,  /* Singular (optional, non-repeated) */
+  CARD_o = 1,  /* Oneof */
+  CARD_r = 2,  /* Repeated */
+  CARD_p = 3   /* Packed Repeated */
+} upb_card;
+
+UPB_NOINLINE
+static const char *fastdecode_isdonefallback(UPB_PARSE_PARAMS) {
+  int overrun = data;
+  ptr = decode_isdonefallback_inl(d, ptr, overrun);
+  if (ptr == NULL) {
+    return fastdecode_err(d);
+  }
+  data = fastdecode_loadtag(ptr);
+  UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_dispatch(UPB_PARSE_PARAMS) {
+  if (UPB_UNLIKELY(ptr >= d->limit_ptr)) {
+    int overrun = ptr - d->end;
+    if (UPB_LIKELY(overrun == d->limit)) {
+      // Parse is finished.
+      *(uint32_t*)msg |= hasbits;  // Sync hasbits.
+      return ptr;
+    } else {
+      data = overrun;
+      UPB_MUSTTAIL return fastdecode_isdonefallback(UPB_PARSE_ARGS);
+    }
+  }
+
+  // Read two bytes of tag data (for a one-byte tag, the high byte is junk).
+  data = fastdecode_loadtag(ptr);
+  UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_checktag(uint16_t data, int tagbytes) {
+  if (tagbytes == 1) {
+    return (data & 0xff) == 0;
+  } else {
+    return data == 0;
+  }
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_longsize(const char *ptr, int *size) {
+  int i;
+  UPB_ASSERT(*size & 0x80);
+  *size &= 0xff;
+  for (i = 0; i < 3; i++) {
+    ptr++;
+    size_t byte = (uint8_t)ptr[-1];
+    *size += (byte - 1) << (7 + 7 * i);
+    if (UPB_LIKELY((byte & 0x80) == 0)) return ptr;
+  }
+  ptr++;
+  size_t byte = (uint8_t)ptr[-1];
+  // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected
+  // for a 32 bit varint.
+  if (UPB_UNLIKELY(byte >= 8)) return NULL;
+  *size += (byte - 1) << 28;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck(const char *ptr, size_t len,
+                                   const char *end) {
+  uintptr_t uptr = (uintptr_t)ptr;
+  uintptr_t uend = (uintptr_t)end + 16;
+  uintptr_t res = uptr + len;
+  return res < uptr || res > uend;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck2(const char *ptr, size_t len,
+                                    const char *end) {
+  // This is one extra branch compared to the more normal:
+  //   return (size_t)(end - ptr) < size;
+  // However it is one less computation if we are just about to use "ptr + len":
+  //   https://godbolt.org/z/35YGPz
+  // In microbenchmarks this shows an overall 4% improvement.
+  uintptr_t uptr = (uintptr_t)ptr;
+  uintptr_t uend = (uintptr_t)end;
+  uintptr_t res = uptr + len;
+  return res < uptr || res > uend;
+}
+
+typedef const char *fastdecode_delimfunc(upb_decstate *d, const char *ptr,
+                                         void *ctx);
+
+UPB_FORCEINLINE
+static const char *fastdecode_delimited(upb_decstate *d, const char *ptr,
+                                        fastdecode_delimfunc *func, void *ctx) {
+  ptr++;
+  int len = (int8_t)ptr[-1];
+  if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) {
+    // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer.
+    // If it exceeds the buffer limit, limit/limit_ptr will change during
+    // sub-message parsing, so we need to preserve delta, not limit.
+    if (UPB_UNLIKELY(len & 0x80)) {
+      // Size varint >1 byte (length >= 128).
+      ptr = fastdecode_longsize(ptr, &len);
+      if (!ptr) {
+        // Corrupt wire format: size exceeded INT_MAX.
+        return NULL;
+      }
+    }
+    if (ptr - d->end + (int)len > d->limit) {
+      // Corrupt wire format: invalid limit.
+      return NULL;
+    }
+    int delta = decode_pushlimit(d, ptr, len);
+    ptr = func(d, ptr, ctx);
+    decode_poplimit(d, ptr, delta);
+  } else {
+    // Fast case: Sub-message is <128 bytes and fits in the current buffer.
+    // This means we can preserve limit/limit_ptr verbatim.
+    const char *saved_limit_ptr = d->limit_ptr;
+    int saved_limit = d->limit;
+    d->limit_ptr = ptr + len;
+    d->limit = d->limit_ptr - d->end;
+    UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+    ptr = func(d, ptr, ctx);
+    d->limit_ptr = saved_limit_ptr;
+    d->limit = saved_limit;
+    UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+  }
+  return ptr;
+}
+
+/* singular, oneof, repeated field handling ***********************************/
+
+typedef struct {
+  upb_array *arr;
+  void *end;
+} fastdecode_arr;
+
+typedef enum {
+  FD_NEXT_ATLIMIT,
+  FD_NEXT_SAMEFIELD,
+  FD_NEXT_OTHERFIELD
+} fastdecode_next;
+
+typedef struct {
+  void *dst;
+  fastdecode_next next;
+  uint32_t tag;
+} fastdecode_nextret;
+
+UPB_FORCEINLINE
+static void *fastdecode_resizearr(upb_decstate *d, void *dst,
+                                  fastdecode_arr *farr, int valbytes) {
+  if (UPB_UNLIKELY(dst == farr->end)) {
+    size_t old_size = farr->arr->size;
+    size_t old_bytes = old_size * valbytes;
+    size_t new_size = old_size * 2;
+    size_t new_bytes = new_size * valbytes;
+    char *old_ptr = _upb_array_ptr(farr->arr);
+    char *new_ptr = upb_arena_realloc(&d->arena, old_ptr, old_bytes, new_bytes);
+    uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+    farr->arr->size = new_size;
+    farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2);
+    dst = (void*)(new_ptr + (old_size * valbytes));
+    farr->end = (void*)(new_ptr + (new_size * valbytes));
+  }
+  return dst;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) {
+  if (tagbytes == 1) {
+    return (uint8_t)tag == (uint8_t)data;
+  } else {
+    return (uint16_t)tag == (uint16_t)data;
+  }
+}
+
+UPB_FORCEINLINE
+static void fastdecode_commitarr(void *dst, fastdecode_arr *farr,
+                                 int valbytes) {
+  farr->arr->len =
+      (size_t)((char *)dst - (char *)_upb_array_ptr(farr->arr)) / valbytes;
+}
+
+UPB_FORCEINLINE
+static fastdecode_nextret fastdecode_nextrepeated(upb_decstate *d, void *dst,
+                                                  const char **ptr,
+                                                  fastdecode_arr *farr,
+                                                  uint64_t data, int tagbytes,
+                                                  int valbytes) {
+  fastdecode_nextret ret;
+  dst = (char *)dst + valbytes;
+
+  if (UPB_LIKELY(!decode_isdone(d, ptr))) {
+    ret.tag = fastdecode_loadtag(*ptr);
+    if (fastdecode_tagmatch(ret.tag, data, tagbytes)) {
+      ret.next = FD_NEXT_SAMEFIELD;
+    } else {
+      fastdecode_commitarr(dst, farr, valbytes);
+      ret.next = FD_NEXT_OTHERFIELD;
+    }
+  } else {
+    fastdecode_commitarr(dst, farr, valbytes);
+    ret.next = FD_NEXT_ATLIMIT;
+  }
+
+  ret.dst = dst;
+  return ret;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_fieldmem(upb_msg *msg, uint64_t data) {
+  size_t ofs = data >> 48;
+  return (char *)msg + ofs;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                 uint64_t *data, uint64_t *hasbits,
+                                 fastdecode_arr *farr, int valbytes,
+                                 upb_card card) {
+  switch (card) {
+    case CARD_s: {
+      uint8_t hasbit_index = *data >> 24;
+      // Set hasbit and return pointer to scalar field.
+      *hasbits |= 1ull << hasbit_index;
+      return fastdecode_fieldmem(msg, *data);
+    }
+    case CARD_o: {
+      uint16_t case_ofs = *data >> 32;
+      uint32_t *oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t);
+      uint8_t field_number = *data >> 24;
+      *oneof_case = field_number;
+      return fastdecode_fieldmem(msg, *data);
+    }
+    case CARD_r: {
+      // Get pointer to upb_array and allocate/expand if necessary.
+      uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+      upb_array **arr_p = fastdecode_fieldmem(msg, *data);
+      char *begin;
+      *(uint32_t*)msg |= *hasbits;
+      *hasbits = 0;
+      if (UPB_LIKELY(!*arr_p)) {
+        farr->arr = _upb_array_new(&d->arena, 8, elem_size_lg2);
+        *arr_p = farr->arr;
+      } else {
+        farr->arr = *arr_p;
+      }
+      begin = _upb_array_ptr(farr->arr);
+      farr->end = begin + (farr->arr->size * valbytes);
+      *data = fastdecode_loadtag(ptr);
+      return begin + (farr->arr->len * valbytes);
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_flippacked(uint64_t *data, int tagbytes) {
+  *data ^= (0x2 ^ 0x0);  // Patch data to match packed wiretype.
+  return fastdecode_checktag(*data, tagbytes);
+}
+
+#define FASTDECODE_CHECKPACKED(tagbytes, card, func)                           \
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {                    \
+    if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {            \
+      UPB_MUSTTAIL return func(UPB_PARSE_ARGS);                                \
+    }                                                                          \
+    RETURN_GENERIC("packed check tag mismatch\n");                             \
+  }
+
+/* varint fields **************************************************************/
+
+UPB_FORCEINLINE
+static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) {
+  if (valbytes == 1) {
+    return val != 0;
+  } else if (zigzag) {
+    if (valbytes == 4) {
+      uint32_t n = val;
+      return (n >> 1) ^ -(int32_t)(n & 1);
+    } else if (valbytes == 8) {
+      return (val >> 1) ^ -(int64_t)(val & 1);
+    }
+    UPB_UNREACHABLE();
+  }
+  return val;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_varint64(const char *ptr, uint64_t *val) {
+  ptr++;
+  *val = (uint8_t)ptr[-1];
+  if (UPB_UNLIKELY(*val & 0x80)) {
+    int i;
+    for (i = 0; i < 8; i++) {
+      ptr++;
+      uint64_t byte = (uint8_t)ptr[-1];
+      *val += (byte - 1) << (7 + 7 * i);
+      if (UPB_LIKELY((byte & 0x80) == 0)) goto done;
+    }
+    ptr++;
+    uint64_t byte = (uint8_t)ptr[-1];
+    if (byte > 1) {
+      return NULL;
+    }
+    *val += (byte - 1) << 63;
+  }
+done:
+  UPB_ASSUME(ptr != NULL);
+  return ptr;
+}
+
+#define FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
+                                  valbytes, card, zigzag, packed)              \
+  uint64_t val;                                                                \
+  void *dst;                                                                   \
+  fastdecode_arr farr;                                                         \
+                                                                               \
+  FASTDECODE_CHECKPACKED(tagbytes, card, packed);                              \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes,     \
+                            card);                                             \
+  if (card == CARD_r) {                                                        \
+    if (UPB_UNLIKELY(!dst)) {                                                  \
+      RETURN_GENERIC("need array resize\n");                                   \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, valbytes);                       \
+  }                                                                            \
+                                                                               \
+  ptr += tagbytes;                                                             \
+  ptr = fastdecode_varint64(ptr, &val);                                        \
+  if (ptr == NULL)                                                             \
+    return fastdecode_err(d);                                                  \
+  val = fastdecode_munge(val, valbytes, zigzag);                               \
+  memcpy(dst, &val, valbytes);                                                 \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, valbytes);                        \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+typedef struct {
+  uint8_t valbytes;
+  bool zigzag;
+  void *dst;
+  fastdecode_arr farr;
+} fastdecode_varintdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr,
+                                             void *ctx) {
+  fastdecode_varintdata *data = ctx;
+  void *dst = data->dst;
+  uint64_t val;
+
+  while (!decode_isdone(d, &ptr)) {
+    dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes);
+    ptr = fastdecode_varint64(ptr, &val);
+    if (ptr == NULL) return NULL;
+    val = fastdecode_munge(val, data->valbytes, data->zigzag);
+    memcpy(dst, &val, data->valbytes);
+    dst = (char *)dst + data->valbytes;
+  }
+
+  fastdecode_commitarr(dst, &data->farr, data->valbytes);
+  return ptr;
+}
+
+#define FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes,   \
+                                valbytes, zigzag, unpacked)                    \
+  fastdecode_varintdata ctx = {valbytes, zigzag};                              \
+                                                                               \
+  FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked);                          \
+                                                                               \
+  ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr,       \
+                                valbytes, CARD_r);                             \
+  if (UPB_UNLIKELY(!ctx.dst)) {                                                \
+    RETURN_GENERIC("need array resize\n");                                     \
+  }                                                                            \
+                                                                               \
+  ptr += tagbytes;                                                             \
+  ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx);        \
+                                                                               \
+  if (UPB_UNLIKELY(ptr == NULL)) {                                             \
+    return fastdecode_err(d);                                                  \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(d, ptr, msg, table, hasbits, 0);
+
+#define FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                          valbytes, card, zigzag, unpacked, packed)        \
+  if (card == CARD_p) {                                                    \
+    FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes,   \
+                            valbytes, zigzag, unpacked);                   \
+  } else {                                                                 \
+    FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
+                              valbytes, card, zigzag, packed);             \
+  }
+
+#define z_ZZ true
+#define b_ZZ false
+#define v_ZZ false
+
+/* Generate all combinations:
+ * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */
+
+#define F(card, type, valbytes, tagbytes)                                      \
+  UPB_NOINLINE                                                                 \
+  const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+    FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, valbytes,   \
+                      CARD_##card, type##_ZZ,                                  \
+                      upb_pr##type##valbytes##_##tagbytes##bt,                 \
+                      upb_pp##type##valbytes##_##tagbytes##bt);                \
+  }
+
+#define TYPES(card, tagbytes) \
+  F(card, b, 1, tagbytes)     \
+  F(card, v, 4, tagbytes)     \
+  F(card, v, 8, tagbytes)     \
+  F(card, z, 4, tagbytes)     \
+  F(card, z, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef z_ZZ
+#undef b_ZZ
+#undef v_ZZ
+#undef o_ONEOF
+#undef s_ONEOF
+#undef r_ONEOF
+#undef F
+#undef TYPES
+#undef TAGBYTES
+#undef FASTDECODE_UNPACKEDVARINT
+#undef FASTDECODE_PACKEDVARINT
+#undef FASTDECODE_VARINT
+
+
+/* fixed fields ***************************************************************/
+
+#define FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes,  \
+                                 valbytes, card, packed)                       \
+  void *dst;                                                                   \
+  fastdecode_arr farr;                                                         \
+                                                                               \
+  FASTDECODE_CHECKPACKED(tagbytes, card, packed)                               \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes,     \
+                            card);                                             \
+  if (card == CARD_r) {                                                        \
+    if (UPB_UNLIKELY(!dst)) {                                                  \
+      RETURN_GENERIC("couldn't allocate array in arena\n");                    \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, valbytes);                       \
+  }                                                                            \
+                                                                               \
+  ptr += tagbytes;                                                             \
+  memcpy(dst, ptr, valbytes);                                                  \
+  ptr += valbytes;                                                             \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, valbytes);                        \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+#define FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
+                               valbytes, unpacked)                          \
+  FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked)                        \
+                                                                            \
+  ptr += tagbytes;                                                          \
+  int size = (uint8_t)ptr[0];                                               \
+  ptr++;                                                                    \
+  if (size & 0x80) {                                                        \
+    ptr = fastdecode_longsize(ptr, &size);                                  \
+  }                                                                         \
+                                                                            \
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr) ||       \
+                   (size % valbytes) != 0)) {                               \
+    return fastdecode_err(d);                                               \
+  }                                                                         \
+                                                                            \
+  upb_array **arr_p = fastdecode_fieldmem(msg, data);                       \
+  upb_array *arr = *arr_p;                                                  \
+  uint8_t elem_size_lg2 = __builtin_ctz(valbytes);                          \
+  int elems = size / valbytes;                                              \
+                                                                            \
+  if (UPB_LIKELY(!arr)) {                                                   \
+    *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2);         \
+    if (!arr) {                                                             \
+      return fastdecode_err(d);                                             \
+    }                                                                       \
+  } else {                                                                  \
+    _upb_array_resize(arr, elems, &d->arena);                               \
+  }                                                                         \
+                                                                            \
+  char *dst = _upb_array_ptr(arr);                                          \
+  memcpy(dst, ptr, size);                                                   \
+  arr->len = elems;                                                         \
+                                                                            \
+  ptr += size;                                                              \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+#define FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                         valbytes, card, unpacked, packed)                \
+  if (card == CARD_p) {                                                   \
+    FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes,   \
+                           valbytes, unpacked);                           \
+  } else {                                                                \
+    FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
+                             valbytes, card, packed);                     \
+  }
+
+/* Generate all combinations:
+ * {s,o,r,p} x {f4,f8} x {1bt,2bt} */
+
+#define F(card, valbytes, tagbytes)                                         \
+  UPB_NOINLINE                                                              \
+  const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+    FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
+                     CARD_##card, upb_ppf##valbytes##_##tagbytes##bt,       \
+                     upb_prf##valbytes##_##tagbytes##bt);                   \
+  }
+
+#define TYPES(card, tagbytes) \
+  F(card, 4, tagbytes)        \
+  F(card, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+#undef FASTDECODE_UNPACKEDFIXED
+#undef FASTDECODE_PACKEDFIXED
+
+/* string fields **************************************************************/
+
+typedef const char *fastdecode_copystr_func(struct upb_decstate *d,
+                                            const char *ptr, upb_msg *msg,
+                                            const upb_msglayout *table,
+                                            uint64_t hasbits, upb_strview *dst);
+
+UPB_NOINLINE
+static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr,
+                                         upb_msg *msg, intptr_t table,
+                                         uint64_t hasbits, uint64_t data) {
+  upb_strview *dst = (upb_strview*)data;
+  if (!decode_verifyutf8_inl(dst->data, dst->size)) {
+    return fastdecode_err(d);
+  }
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+}
+
+#define FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, validate_utf8) \
+  int size = (uint8_t)ptr[0]; /* Could plumb through hasbits. */               \
+  ptr++;                                                                       \
+  if (size & 0x80) {                                                           \
+    ptr = fastdecode_longsize(ptr, &size);                                     \
+  }                                                                            \
+                                                                               \
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) {         \
+    dst->size = 0;                                                             \
+    return fastdecode_err(d);                                                  \
+  }                                                                            \
+                                                                               \
+  if (d->alias) {                                                              \
+    dst->data = ptr;                                                           \
+    dst->size = size;                                                          \
+  } else {                                                                     \
+    char *data = upb_arena_malloc(&d->arena, size);                            \
+    if (!data) {                                                               \
+      return fastdecode_err(d);                                                \
+    }                                                                          \
+    memcpy(data, ptr, size);                                                   \
+    dst->data = data;                                                          \
+    dst->size = size;                                                          \
+  }                                                                            \
+                                                                               \
+  ptr += size;                                                                 \
+  if (validate_utf8) {                                                         \
+    data = (uint64_t)dst;                                                      \
+    UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS);                 \
+  } else {                                                                     \
+    UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);                   \
+  }
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_utf8(struct upb_decstate *d,
+                                              const char *ptr, upb_msg *msg,
+                                              intptr_t table, uint64_t hasbits,
+                                              uint64_t data) {
+  upb_strview *dst = (upb_strview*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
+}
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_noutf8(struct upb_decstate *d,
+                                                const char *ptr, upb_msg *msg,
+                                                intptr_t table,
+                                                uint64_t hasbits,
+                                                uint64_t data) {
+  upb_strview *dst = (upb_strview*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
+}
+
+UPB_FORCEINLINE
+static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size,
+                              int copy, char *data, upb_strview *dst) {
+  d->arena.head.ptr += copy;
+  dst->data = data;
+  UPB_UNPOISON_MEMORY_REGION(data, copy);
+  memcpy(data, ptr, copy);
+  UPB_POISON_MEMORY_REGION(data + size, copy - size);
+}
+
+#define FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                              card, validate_utf8)                             \
+  upb_strview *dst;                                                            \
+  fastdecode_arr farr;                                                         \
+  int64_t size;                                                                \
+  size_t arena_has;                                                            \
+  size_t common_has;                                                           \
+  char *buf;                                                                   \
+                                                                               \
+  UPB_ASSERT(!d->alias);                                                       \
+  UPB_ASSERT(fastdecode_checktag(data, tagbytes));                             \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
+                            sizeof(upb_strview), card);                        \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));            \
+  }                                                                            \
+                                                                               \
+  size = (uint8_t)ptr[tagbytes];                                               \
+  ptr += tagbytes + 1;                                                         \
+  dst->size = size;                                                            \
+                                                                               \
+  buf = d->arena.head.ptr;                                                     \
+  arena_has = _upb_arenahas(&d->arena);                                        \
+  common_has = UPB_MIN(arena_has, (d->end - ptr) + 16);                        \
+                                                                               \
+  if (UPB_LIKELY(size <= 15 - tagbytes)) {                                     \
+    if (arena_has < 16)                                                        \
+      goto longstr;                                                            \
+    d->arena.head.ptr += 16;                                                   \
+    memcpy(buf, ptr - tagbytes - 1, 16);                                       \
+    dst->data = buf + tagbytes + 1;                                            \
+  } else if (UPB_LIKELY(size <= 32)) {                                         \
+    if (UPB_UNLIKELY(common_has < 32))                                         \
+      goto longstr;                                                            \
+    fastdecode_docopy(d, ptr, size, 32, buf, dst);                             \
+  } else if (UPB_LIKELY(size <= 64)) {                                         \
+    if (UPB_UNLIKELY(common_has < 64))                                         \
+      goto longstr;                                                            \
+    fastdecode_docopy(d, ptr, size, 64, buf, dst);                             \
+  } else if (UPB_LIKELY(size < 128)) {                                         \
+    if (UPB_UNLIKELY(common_has < 128))                                        \
+      goto longstr;                                                            \
+    fastdecode_docopy(d, ptr, size, 128, buf, dst);                            \
+  } else {                                                                     \
+    goto longstr;                                                              \
+  }                                                                            \
+                                                                               \
+  ptr += size;                                                                 \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {       \
+      return fastdecode_err(d);                                                \
+    }                                                                          \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));             \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  if (card != CARD_r && validate_utf8) {                                       \
+    data = (uint64_t)dst;                                                      \
+    UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS);                 \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);                     \
+                                                                               \
+  longstr:                                                                     \
+  ptr--;                                                                       \
+  if (validate_utf8) {                                                         \
+    UPB_MUSTTAIL return fastdecode_longstring_utf8(d, ptr, msg, table,         \
+                                                   hasbits, (uint64_t)dst);    \
+  } else {                                                                     \
+    UPB_MUSTTAIL return fastdecode_longstring_noutf8(d, ptr, msg, table,       \
+                                                     hasbits, (uint64_t)dst);  \
+  }
+
+#define FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, card,   \
+                          copyfunc, validate_utf8)                             \
+  upb_strview *dst;                                                            \
+  fastdecode_arr farr;                                                         \
+  int64_t size;                                                                \
+                                                                               \
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {                    \
+    RETURN_GENERIC("string field tag mismatch\n");                             \
+  }                                                                            \
+                                                                               \
+  if (UPB_UNLIKELY(!d->alias)) {                                               \
+    UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS);                              \
+  }                                                                            \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
+                            sizeof(upb_strview), card);                        \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));            \
+  }                                                                            \
+                                                                               \
+  size = (int8_t)ptr[tagbytes];                                                \
+  ptr += tagbytes + 1;                                                         \
+  dst->data = ptr;                                                             \
+  dst->size = size;                                                            \
+                                                                               \
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) {               \
+    ptr--;                                                                     \
+    if (validate_utf8) {                                                       \
+      return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits,           \
+                                        (uint64_t)dst);                        \
+    } else {                                                                   \
+      return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits,         \
+                                          (uint64_t)dst);                      \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  ptr += size;                                                                 \
+                                                                               \
+  if (card == CARD_r) {                                                        \
+    if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {       \
+      return fastdecode_err(d);                                                \
+    }                                                                          \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));             \
+    switch (ret.next) {                                                        \
+    case FD_NEXT_SAMEFIELD:                                                    \
+      dst = ret.dst;                                                           \
+      if (UPB_UNLIKELY(!d->alias)) {                                           \
+        /* Buffer flipped and we can't alias any more. Bounce to */            \
+        /* copyfunc(), but via dispatch since we need to reload table */       \
+        /* data also. */                                                       \
+        fastdecode_commitarr(dst, &farr, sizeof(upb_strview));                 \
+        data = ret.tag;                                                        \
+        UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);            \
+      }                                                                        \
+      goto again;                                                              \
+    case FD_NEXT_OTHERFIELD:                                                   \
+      data = ret.tag;                                                          \
+      UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);              \
+    case FD_NEXT_ATLIMIT:                                                      \
+      return ptr;                                                              \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  if (card != CARD_r && validate_utf8) {                                       \
+    data = (uint64_t)dst;                                                      \
+    UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS);                 \
+  }                                                                            \
+                                                                               \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+/* Generate all combinations:
+ * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */
+
+#define s_VALIDATE true
+#define b_VALIDATE false
+
+#define F(card, tagbytes, type)                                        \
+  UPB_NOINLINE                                                         \
+  const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) {   \
+    FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
+                          CARD_##card, type##_VALIDATE);               \
+  }                                                                    \
+  const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) {   \
+    FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes,     \
+                      CARD_##card, upb_c##card##type##_##tagbytes##bt, \
+                      type##_VALIDATE);                                \
+  }
+
+#define UTF8(card, tagbytes) \
+  F(card, tagbytes, s)       \
+  F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+  UTF8(card, 1)        \
+  UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef s_VALIDATE
+#undef b_VALIDATE
+#undef F
+#undef TAGBYTES
+#undef FASTDECODE_LONGSTRING
+#undef FASTDECODE_COPYSTRING
+#undef FASTDECODE_STRING
+
+/* message fields *************************************************************/
+
+UPB_INLINE
+upb_msg *decode_newmsg_ceil(upb_decstate *d, const upb_msglayout *l,
+                            int msg_ceil_bytes) {
+  size_t size = l->size + sizeof(upb_msg_internal);
+  char *msg_data;
+  if (UPB_LIKELY(msg_ceil_bytes > 0 &&
+                 _upb_arenahas(&d->arena) >= msg_ceil_bytes)) {
+    UPB_ASSERT(size <= (size_t)msg_ceil_bytes);
+    msg_data = d->arena.head.ptr;
+    d->arena.head.ptr += size;
+    UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes);
+    memset(msg_data, 0, msg_ceil_bytes);
+    UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size);
+  } else {
+    msg_data = (char*)upb_arena_malloc(&d->arena, size);
+    memset(msg_data, 0, size);
+  }
+  return msg_data + sizeof(upb_msg_internal);
+}
+
+typedef struct {
+  intptr_t table;
+  upb_msg *msg;
+} fastdecode_submsgdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr,
+                                       void *ctx) {
+  fastdecode_submsgdata *submsg = ctx;
+  ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0);
+  UPB_ASSUME(ptr != NULL);
+  return ptr;
+}
+
+#define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes,    \
+                          msg_ceil_bytes, card)                           \
+                                                                          \
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {               \
+    RETURN_GENERIC("submessage field tag mismatch\n");                    \
+  }                                                                       \
+                                                                          \
+  if (--d->depth == 0) return fastdecode_err(d);                          \
+                                                                          \
+  upb_msg **dst;                                                          \
+  uint32_t submsg_idx = (data >> 16) & 0xff;                              \
+  const upb_msglayout *tablep = decode_totablep(table);                   \
+  const upb_msglayout *subtablep = tablep->submsgs[submsg_idx];           \
+  fastdecode_submsgdata submsg = {decode_totable(subtablep)};             \
+  fastdecode_arr farr;                                                    \
+                                                                          \
+  if (subtablep->table_mask == (uint8_t)-1) {                             \
+    RETURN_GENERIC("submessage doesn't have fast tables.");               \
+  }                                                                       \
+                                                                          \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,          \
+                            sizeof(upb_msg *), card);                     \
+                                                                          \
+  if (card == CARD_s) {                                                   \
+    *(uint32_t *)msg |= hasbits;                                          \
+    hasbits = 0;                                                          \
+  }                                                                       \
+                                                                          \
+  again:                                                                  \
+  if (card == CARD_r) {                                                   \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg *));         \
+  }                                                                       \
+                                                                          \
+  submsg.msg = *dst;                                                      \
+                                                                          \
+  if (card == CARD_r || UPB_LIKELY(!submsg.msg)) {                        \
+    *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \
+  }                                                                       \
+                                                                          \
+  ptr += tagbytes;                                                        \
+  ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg);       \
+                                                                          \
+  if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) {      \
+    return fastdecode_err(d);                                             \
+  }                                                                       \
+                                                                          \
+  if (card == CARD_r) {                                                   \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                     \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *));          \
+    switch (ret.next) {                                                   \
+      case FD_NEXT_SAMEFIELD:                                             \
+        dst = ret.dst;                                                    \
+        goto again;                                                       \
+      case FD_NEXT_OTHERFIELD:                                            \
+        d->depth++;                                                       \
+        data = ret.tag;                                                   \
+        UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);       \
+      case FD_NEXT_ATLIMIT:                                               \
+        d->depth++;                                                       \
+        return ptr;                                                       \
+    }                                                                     \
+  }                                                                       \
+                                                                          \
+  d->depth++;                                                             \
+  UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
+
+#define F(card, tagbytes, size_ceil, ceil_arg)                               \
+  const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(               \
+      UPB_PARSE_PARAMS) {                                                    \
+    FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \
+                      CARD_##card);                                          \
+  }
+
+#define SIZES(card, tagbytes) \
+  F(card, tagbytes, 64, 64) \
+  F(card, tagbytes, 128, 128) \
+  F(card, tagbytes, 192, 192) \
+  F(card, tagbytes, 256, 256) \
+  F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+  SIZES(card, 1) \
+  SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+#undef FASTDECODE_SUBMSG
+
+#endif  /* UPB_FASTTABLE */
+
+/** bazel-out/k8-fastbuild/bin/external/com_google_protobuf/google/protobuf/descriptor.upb.c ************************************************************//* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+
+
+static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = {
+  &google_protobuf_FileDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
+  &google_protobuf_FileDescriptorSet_submsgs[0],
+  &google_protobuf_FileDescriptorSet__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
+  &google_protobuf_DescriptorProto_msginit,
+  &google_protobuf_EnumDescriptorProto_msginit,
+  &google_protobuf_FieldDescriptorProto_msginit,
+  &google_protobuf_FileOptions_msginit,
+  &google_protobuf_ServiceDescriptorProto_msginit,
+  &google_protobuf_SourceCodeInfo_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {3, UPB_SIZE(36, 72), 0, 0, 12, 3},
+  {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
+  {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
+  {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
+  {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
+  {8, UPB_SIZE(28, 56), 3, 3, 11, 1},
+  {9, UPB_SIZE(32, 64), 4, 5, 11, 1},
+  {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
+  {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
+  {12, UPB_SIZE(20, 40), 5, 0, 12, 1},
+};
+
+const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
+  &google_protobuf_FileDescriptorProto_submsgs[0],
+  &google_protobuf_FileDescriptorProto__fields[0],
+  UPB_SIZE(64, 128), 12, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = {
+  &google_protobuf_DescriptorProto_msginit,
+  &google_protobuf_DescriptorProto_ExtensionRange_msginit,
+  &google_protobuf_DescriptorProto_ReservedRange_msginit,
+  &google_protobuf_EnumDescriptorProto_msginit,
+  &google_protobuf_FieldDescriptorProto_msginit,
+  &google_protobuf_MessageOptions_msginit,
+  &google_protobuf_OneofDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
+  {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
+  {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
+  {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
+  {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
+  {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
+  {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
+  {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
+  {10, UPB_SIZE(44, 88), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_msginit = {
+  &google_protobuf_DescriptorProto_submsgs[0],
+  &google_protobuf_DescriptorProto__fields[0],
+  UPB_SIZE(48, 96), 10, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
+  &google_protobuf_ExtensionRangeOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+  {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
+  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
+  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
+  UPB_SIZE(16, 24), 3, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
+  NULL,
+  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
+  UPB_SIZE(16, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
+  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
+  &google_protobuf_ExtensionRangeOptions_submsgs[0],
+  &google_protobuf_ExtensionRangeOptions__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
+  &google_protobuf_FieldOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
+  {1, UPB_SIZE(24, 24), 1, 0, 12, 1},
+  {2, UPB_SIZE(32, 40), 2, 0, 12, 1},
+  {3, UPB_SIZE(12, 12), 3, 0, 5, 1},
+  {4, UPB_SIZE(4, 4), 4, 0, 14, 1},
+  {5, UPB_SIZE(8, 8), 5, 0, 14, 1},
+  {6, UPB_SIZE(40, 56), 6, 0, 12, 1},
+  {7, UPB_SIZE(48, 72), 7, 0, 12, 1},
+  {8, UPB_SIZE(64, 104), 8, 0, 11, 1},
+  {9, UPB_SIZE(16, 16), 9, 0, 5, 1},
+  {10, UPB_SIZE(56, 88), 10, 0, 12, 1},
+  {17, UPB_SIZE(20, 20), 11, 0, 8, 1},
+};
+
+const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
+  &google_protobuf_FieldDescriptorProto_submsgs[0],
+  &google_protobuf_FieldDescriptorProto__fields[0],
+  UPB_SIZE(72, 112), 11, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
+  &google_protobuf_OneofOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
+  &google_protobuf_OneofDescriptorProto_submsgs[0],
+  &google_protobuf_OneofDescriptorProto__fields[0],
+  UPB_SIZE(16, 32), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
+  &google_protobuf_EnumOptions_msginit,
+  &google_protobuf_EnumValueDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
+  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
+  {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
+  {5, UPB_SIZE(24, 48), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
+  &google_protobuf_EnumDescriptorProto_submsgs[0],
+  &google_protobuf_EnumDescriptorProto__fields[0],
+  UPB_SIZE(32, 64), 5, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
+  NULL,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
+  UPB_SIZE(16, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
+  &google_protobuf_EnumValueOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(8, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(4, 4), 2, 0, 5, 1},
+  {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
+  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
+  &google_protobuf_EnumValueDescriptorProto__fields[0],
+  UPB_SIZE(24, 32), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
+  &google_protobuf_MethodDescriptorProto_msginit,
+  &google_protobuf_ServiceOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
+  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
+};
+
+const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
+  &google_protobuf_ServiceDescriptorProto_submsgs[0],
+  &google_protobuf_ServiceDescriptorProto__fields[0],
+  UPB_SIZE(24, 48), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
+  &google_protobuf_MethodOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {3, UPB_SIZE(20, 40), 3, 0, 12, 1},
+  {4, UPB_SIZE(28, 56), 4, 0, 11, 1},
+  {5, UPB_SIZE(1, 1), 5, 0, 8, 1},
+  {6, UPB_SIZE(2, 2), 6, 0, 8, 1},
+};
+
+const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
+  &google_protobuf_MethodDescriptorProto_submsgs[0],
+  &google_protobuf_MethodDescriptorProto__fields[0],
+  UPB_SIZE(32, 64), 6, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
+  {1, UPB_SIZE(20, 24), 1, 0, 12, 1},
+  {8, UPB_SIZE(28, 40), 2, 0, 12, 1},
+  {9, UPB_SIZE(4, 4), 3, 0, 14, 1},
+  {10, UPB_SIZE(8, 8), 4, 0, 8, 1},
+  {11, UPB_SIZE(36, 56), 5, 0, 12, 1},
+  {16, UPB_SIZE(9, 9), 6, 0, 8, 1},
+  {17, UPB_SIZE(10, 10), 7, 0, 8, 1},
+  {18, UPB_SIZE(11, 11), 8, 0, 8, 1},
+  {20, UPB_SIZE(12, 12), 9, 0, 8, 1},
+  {23, UPB_SIZE(13, 13), 10, 0, 8, 1},
+  {27, UPB_SIZE(14, 14), 11, 0, 8, 1},
+  {31, UPB_SIZE(15, 15), 12, 0, 8, 1},
+  {36, UPB_SIZE(44, 72), 13, 0, 12, 1},
+  {37, UPB_SIZE(52, 88), 14, 0, 12, 1},
+  {39, UPB_SIZE(60, 104), 15, 0, 12, 1},
+  {40, UPB_SIZE(68, 120), 16, 0, 12, 1},
+  {41, UPB_SIZE(76, 136), 17, 0, 12, 1},
+  {42, UPB_SIZE(16, 16), 18, 0, 8, 1},
+  {44, UPB_SIZE(84, 152), 19, 0, 12, 1},
+  {45, UPB_SIZE(92, 168), 20, 0, 12, 1},
+  {999, UPB_SIZE(100, 184), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FileOptions_msginit = {
+  &google_protobuf_FileOptions_submsgs[0],
+  &google_protobuf_FileOptions__fields[0],
+  UPB_SIZE(104, 192), 21, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
+  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
+  {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
+  {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
+  {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_MessageOptions_msginit = {
+  &google_protobuf_MessageOptions_submsgs[0],
+  &google_protobuf_MessageOptions__fields[0],
+  UPB_SIZE(16, 16), 5, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 14, 1},
+  {2, UPB_SIZE(12, 12), 2, 0, 8, 1},
+  {3, UPB_SIZE(13, 13), 3, 0, 8, 1},
+  {5, UPB_SIZE(14, 14), 4, 0, 8, 1},
+  {6, UPB_SIZE(8, 8), 5, 0, 14, 1},
+  {10, UPB_SIZE(15, 15), 6, 0, 8, 1},
+  {999, UPB_SIZE(16, 16), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FieldOptions_msginit = {
+  &google_protobuf_FieldOptions_submsgs[0],
+  &google_protobuf_FieldOptions__fields[0],
+  UPB_SIZE(24, 24), 7, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
+  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_OneofOptions_msginit = {
+  &google_protobuf_OneofOptions_submsgs[0],
+  &google_protobuf_OneofOptions__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
+  {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_EnumOptions_msginit = {
+  &google_protobuf_EnumOptions_submsgs[0],
+  &google_protobuf_EnumOptions__fields[0],
+  UPB_SIZE(8, 16), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
+  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
+  &google_protobuf_EnumValueOptions_submsgs[0],
+  &google_protobuf_EnumValueOptions__fields[0],
+  UPB_SIZE(8, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
+  {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_ServiceOptions_msginit = {
+  &google_protobuf_ServiceOptions_submsgs[0],
+  &google_protobuf_ServiceOptions__fields[0],
+  UPB_SIZE(8, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
+  {33, UPB_SIZE(8, 8), 1, 0, 8, 1},
+  {34, UPB_SIZE(4, 4), 2, 0, 14, 1},
+  {999, UPB_SIZE(12, 16), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_MethodOptions_msginit = {
+  &google_protobuf_MethodOptions_submsgs[0],
+  &google_protobuf_MethodOptions__fields[0],
+  UPB_SIZE(16, 24), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_NamePart_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
+  {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
+  {3, UPB_SIZE(32, 32), 1, 0, 12, 1},
+  {4, UPB_SIZE(8, 8), 2, 0, 4, 1},
+  {5, UPB_SIZE(16, 16), 3, 0, 3, 1},
+  {6, UPB_SIZE(24, 24), 4, 0, 1, 1},
+  {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
+  {8, UPB_SIZE(48, 64), 6, 0, 12, 1},
+};
+
+const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
+  &google_protobuf_UninterpretedOption_submsgs[0],
+  &google_protobuf_UninterpretedOption__fields[0],
+  UPB_SIZE(64, 96), 7, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 2},
+  {2, UPB_SIZE(1, 1), 2, 0, 8, 2},
+};
+
+const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
+  NULL,
+  &google_protobuf_UninterpretedOption_NamePart__fields[0],
+  UPB_SIZE(16, 32), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
+  &google_protobuf_SourceCodeInfo_Location_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
+  &google_protobuf_SourceCodeInfo_submsgs[0],
+  &google_protobuf_SourceCodeInfo__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
+  {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
+  {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
+  {3, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {4, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {6, UPB_SIZE(28, 56), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
+  NULL,
+  &google_protobuf_SourceCodeInfo_Location__fields[0],
+  UPB_SIZE(32, 64), 5, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
+  &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
+  &google_protobuf_GeneratedCodeInfo_submsgs[0],
+  &google_protobuf_GeneratedCodeInfo__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
+  {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
+  {2, UPB_SIZE(12, 16), 1, 0, 12, 1},
+  {3, UPB_SIZE(4, 4), 2, 0, 5, 1},
+  {4, UPB_SIZE(8, 8), 3, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
+  NULL,
+  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
+  UPB_SIZE(24, 48), 4, false, 255,
+};
+
+
+
+/** upb/def.c ************************************************************/
+
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+typedef struct {
+  size_t len;
+  char str[1];  /* Null-terminated string data follows. */
+} str_t;
+
+struct upb_fielddef {
+  const upb_filedef *file;
+  const upb_msgdef *msgdef;
+  const char *full_name;
+  const char *json_name;
+  union {
+    int64_t sint;
+    uint64_t uint;
+    double dbl;
+    float flt;
+    bool boolean;
+    str_t *str;
+  } defaultval;
+  const upb_oneofdef *oneof;
+  union {
+    const upb_msgdef *msgdef;
+    const upb_enumdef *enumdef;
+    const google_protobuf_FieldDescriptorProto *unresolved;
+  } sub;
+  uint32_t number_;
+  uint16_t index_;
+  uint16_t layout_index;
+  bool is_extension_;
+  bool lazy_;
+  bool packed_;
+  bool proto3_optional_;
+  upb_descriptortype_t type_;
+  upb_label_t label_;
+};
+
+struct upb_msgdef {
+  const upb_msglayout *layout;
+  const upb_filedef *file;
+  const char *full_name;
+
+  /* Tables for looking up fields by number and name. */
+  upb_inttable itof;
+  upb_strtable ntof;
+
+  const upb_fielddef *fields;
+  const upb_oneofdef *oneofs;
+  int field_count;
+  int oneof_count;
+  int real_oneof_count;
+
+  /* Is this a map-entry message? */
+  bool map_entry;
+  upb_wellknowntype_t well_known_type;
+
+  /* TODO(haberman): proper extension ranges (there can be multiple). */
+};
+
+struct upb_enumdef {
+  const upb_filedef *file;
+  const char *full_name;
+  upb_strtable ntoi;
+  upb_inttable iton;
+  int32_t defaultval;
+};
+
+struct upb_oneofdef {
+  const upb_msgdef *parent;
+  const char *full_name;
+  int field_count;
+  bool synthetic;
+  const upb_fielddef **fields;
+  upb_strtable ntof;
+  upb_inttable itof;
+};
+
+struct upb_filedef {
+  const char *name;
+  const char *package;
+  const char *phpprefix;
+  const char *phpnamespace;
+
+  const upb_filedef **deps;
+  const upb_msgdef *msgs;
+  const upb_enumdef *enums;
+  const upb_fielddef *exts;
+  const upb_symtab *symtab;
+
+  int dep_count;
+  int msg_count;
+  int enum_count;
+  int ext_count;
+  upb_syntax_t syntax;
+};
+
+struct upb_symtab {
+  upb_arena *arena;
+  upb_strtable syms;  /* full_name -> packed def ptr */
+  upb_strtable files;  /* file_name -> upb_filedef* */
+  size_t bytes_loaded;
+};
+
+/* Inside a symtab we store tagged pointers to specific def types. */
+typedef enum {
+  UPB_DEFTYPE_FIELD = 0,
+
+  /* Only inside symtab table. */
+  UPB_DEFTYPE_MSG = 1,
+  UPB_DEFTYPE_ENUM = 2,
+
+  /* Only inside message table. */
+  UPB_DEFTYPE_ONEOF = 1,
+  UPB_DEFTYPE_FIELD_JSONNAME = 2
+} upb_deftype_t;
+
+static const void *unpack_def(upb_value v, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+  return (num & 3) == type ? (const void*)(num & ~3) : NULL;
+}
+
+static upb_value pack_def(const void *ptr, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)ptr | type;
+  return upb_value_constptr((const void*)num);
+}
+
+/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
+static bool upb_isbetween(char c, char low, char high) {
+  return c >= low && c <= high;
+}
+
+static bool upb_isletter(char c) {
+  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+  return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static const char *shortdefname(const char *fullname) {
+  const char *p;
+
+  if (fullname == NULL) {
+    return NULL;
+  } else if ((p = strrchr(fullname, '.')) == NULL) {
+    /* No '.' in the name, return the full string. */
+    return fullname;
+  } else {
+    /* Return one past the last '.'. */
+    return p + 1;
+  }
+}
+
+/* All submessage fields are lower than all other fields.
+ * Secondly, fields are increasing in order. */
+uint32_t field_rank(const upb_fielddef *f) {
+  uint32_t ret = upb_fielddef_number(f);
+  const uint32_t high_bit = 1 << 30;
+  UPB_ASSERT(ret < high_bit);
+  if (!upb_fielddef_issubmsg(f))
+    ret |= high_bit;
+  return ret;
+}
+
+int cmp_fields(const void *p1, const void *p2) {
+  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
+  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
+  return field_rank(f1) - field_rank(f2);
+}
+
+static void upb_status_setoom(upb_status *status) {
+  upb_status_seterrmsg(status, "out of memory");
+}
+
+static void assign_msg_wellknowntype(upb_msgdef *m) {
+  const char *name = upb_msgdef_fullname(m);
+  if (name == NULL) {
+    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+    return;
+  }
+  if (!strcmp(name, "google.protobuf.Any")) {
+    m->well_known_type = UPB_WELLKNOWN_ANY;
+  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
+    m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
+  } else if (!strcmp(name, "google.protobuf.Duration")) {
+    m->well_known_type = UPB_WELLKNOWN_DURATION;
+  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
+    m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
+  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
+    m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
+  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
+    m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
+  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
+    m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
+  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
+    m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
+  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
+    m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
+  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
+    m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
+  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
+    m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
+  } else if (!strcmp(name, "google.protobuf.StringValue")) {
+    m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
+  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
+    m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
+  } else if (!strcmp(name, "google.protobuf.Value")) {
+    m->well_known_type = UPB_WELLKNOWN_VALUE;
+  } else if (!strcmp(name, "google.protobuf.ListValue")) {
+    m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
+  } else if (!strcmp(name, "google.protobuf.Struct")) {
+    m->well_known_type = UPB_WELLKNOWN_STRUCT;
+  } else {
+    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+  }
+}
+
+
+/* upb_enumdef ****************************************************************/
+
+const char *upb_enumdef_fullname(const upb_enumdef *e) {
+  return e->full_name;
+}
+
+const char *upb_enumdef_name(const upb_enumdef *e) {
+  return shortdefname(e->full_name);
+}
+
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
+  return e->file;
+}
+
+int32_t upb_enumdef_default(const upb_enumdef *e) {
+  UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
+  return e->defaultval;
+}
+
+int upb_enumdef_numvals(const upb_enumdef *e) {
+  return (int)upb_strtable_count(&e->ntoi);
+}
+
+void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
+  /* We iterate over the ntoi table, to account for duplicate numbers. */
+  upb_strtable_begin(i, &e->ntoi);
+}
+
+void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
+bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
+
+bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
+                      size_t len, int32_t *num) {
+  upb_value v;
+  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
+    return false;
+  }
+  if (num) *num = upb_value_getint32(v);
+  return true;
+}
+
+const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
+  upb_value v;
+  return upb_inttable_lookup(&def->iton, num, &v) ? upb_value_getcstr(v) : NULL;
+}
+
+const char *upb_enum_iter_name(upb_enum_iter *iter) {
+  return upb_strtable_iter_key(iter).data;
+}
+
+int32_t upb_enum_iter_number(upb_enum_iter *iter) {
+  return upb_value_getint32(upb_strtable_iter_value(iter));
+}
+
+
+/* upb_fielddef ***************************************************************/
+
+const char *upb_fielddef_fullname(const upb_fielddef *f) {
+  return f->full_name;
+}
+
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
+  switch (f->type_) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      return UPB_TYPE_DOUBLE;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      return UPB_TYPE_FLOAT;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+      return UPB_TYPE_INT64;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      return UPB_TYPE_INT32;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      return UPB_TYPE_UINT64;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      return UPB_TYPE_UINT32;
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      return UPB_TYPE_ENUM;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      return UPB_TYPE_BOOL;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      return UPB_TYPE_STRING;
+    case UPB_DESCRIPTOR_TYPE_BYTES:
+      return UPB_TYPE_BYTES;
+    case UPB_DESCRIPTOR_TYPE_GROUP:
+    case UPB_DESCRIPTOR_TYPE_MESSAGE:
+      return UPB_TYPE_MESSAGE;
+  }
+  UPB_UNREACHABLE();
+}
+
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
+  return f->type_;
+}
+
+uint32_t upb_fielddef_index(const upb_fielddef *f) {
+  return f->index_;
+}
+
+upb_label_t upb_fielddef_label(const upb_fielddef *f) {
+  return f->label_;
+}
+
+uint32_t upb_fielddef_number(const upb_fielddef *f) {
+  return f->number_;
+}
+
+bool upb_fielddef_isextension(const upb_fielddef *f) {
+  return f->is_extension_;
+}
+
+bool upb_fielddef_lazy(const upb_fielddef *f) {
+  return f->lazy_;
+}
+
+bool upb_fielddef_packed(const upb_fielddef *f) {
+  return f->packed_;
+}
+
+const char *upb_fielddef_name(const upb_fielddef *f) {
+  return shortdefname(f->full_name);
+}
+
+const char *upb_fielddef_jsonname(const upb_fielddef *f) {
+  return f->json_name;
+}
+
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
+  return f->file;
+}
+
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
+  return f->msgdef;
+}
+
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
+  return f->oneof;
+}
+
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) {
+  if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL;
+  return f->oneof;
+}
+
+upb_msgval upb_fielddef_default(const upb_fielddef *f) {
+  UPB_ASSERT(!upb_fielddef_issubmsg(f));
+  upb_msgval ret;
+  if (upb_fielddef_isstring(f)) {
+    str_t *str = f->defaultval.str;
+    if (str) {
+      ret.str_val.data = str->str;
+      ret.str_val.size = str->len;
+    } else {
+      ret.str_val.size = 0;
+    }
+  } else {
+    memcpy(&ret, &f->defaultval, 8);
+  }
+  return ret;
+}
+
+static void chkdefaulttype(const upb_fielddef *f, int ctype) {
+  UPB_UNUSED(f);
+  UPB_UNUSED(ctype);
+}
+
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT64);
+  return f->defaultval.sint;
+}
+
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT32);
+  return (int32_t)f->defaultval.sint;
+}
+
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT64);
+  return f->defaultval.uint;
+}
+
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT32);
+  return (uint32_t)f->defaultval.uint;
+}
+
+bool upb_fielddef_defaultbool(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_BOOL);
+  return f->defaultval.boolean;
+}
+
+float upb_fielddef_defaultfloat(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_FLOAT);
+  return f->defaultval.flt;
+}
+
+double upb_fielddef_defaultdouble(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_DOUBLE);
+  return f->defaultval.dbl;
+}
+
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
+  str_t *str = f->defaultval.str;
+  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
+         upb_fielddef_type(f) == UPB_TYPE_ENUM);
+  if (str) {
+    if (len) *len = str->len;
+    return str->str;
+  } else {
+    if (len) *len = 0;
+    return NULL;
+  }
+}
+
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE ? f->sub.msgdef : NULL;
+}
+
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_ENUM ? f->sub.enumdef : NULL;
+}
+
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) {
+  return &f->msgdef->layout->fields[f->layout_index];
+}
+
+bool upb_fielddef_issubmsg(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
+}
+
+bool upb_fielddef_isstring(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES;
+}
+
+bool upb_fielddef_isseq(const upb_fielddef *f) {
+  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
+}
+
+bool upb_fielddef_isprimitive(const upb_fielddef *f) {
+  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
+}
+
+bool upb_fielddef_ismap(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
+         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
+}
+
+bool upb_fielddef_hassubdef(const upb_fielddef *f) {
+  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
+}
+
+bool upb_fielddef_haspresence(const upb_fielddef *f) {
+  if (upb_fielddef_isseq(f)) return false;
+  return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) ||
+         f->file->syntax == UPB_SYNTAX_PROTO2;
+}
+
+static bool between(int32_t x, int32_t low, int32_t high) {
+  return x >= low && x <= high;
+}
+
+bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
+bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
+bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
+
+bool upb_fielddef_checkdescriptortype(int32_t type) {
+  return between(type, 1, 18);
+}
+
+/* upb_msgdef *****************************************************************/
+
+const char *upb_msgdef_fullname(const upb_msgdef *m) {
+  return m->full_name;
+}
+
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
+  return m->file;
+}
+
+const char *upb_msgdef_name(const upb_msgdef *m) {
+  return shortdefname(m->full_name);
+}
+
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
+  return m->file->syntax;
+}
+
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
+  upb_value val;
+  return upb_inttable_lookup(&m->itof, i, &val) ? upb_value_getconstptr(val)
+                                                : NULL;
+}
+
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return unpack_def(val, UPB_DEFTYPE_FIELD);
+}
+
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return unpack_def(val, UPB_DEFTYPE_ONEOF);
+}
+
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return false;
+  }
+
+  *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
+  *f = unpack_def(val, UPB_DEFTYPE_FIELD);
+  return *o || *f;  /* False if this was a JSON name. */
+}
+
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+                                              const char *name, size_t len) {
+  upb_value val;
+  const upb_fielddef* f;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  f = unpack_def(val, UPB_DEFTYPE_FIELD);
+  if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME);
+
+  return f;
+}
+
+int upb_msgdef_numfields(const upb_msgdef *m) {
+  return m->field_count;
+}
+
+int upb_msgdef_numoneofs(const upb_msgdef *m) {
+  return m->oneof_count;
+}
+
+int upb_msgdef_numrealoneofs(const upb_msgdef *m) {
+  return m->real_oneof_count;
+}
+
+int upb_msgdef_fieldcount(const upb_msgdef *m) {
+  return m->field_count;
+}
+
+int upb_msgdef_oneofcount(const upb_msgdef *m) {
+  return m->oneof_count;
+}
+
+int upb_msgdef_realoneofcount(const upb_msgdef *m) {
+  return m->real_oneof_count;
+}
+
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) {
+  return m->layout;
+}
+
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i) {
+  UPB_ASSERT(i >= 0 && i < m->field_count);
+  return &m->fields[i];
+}
+
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i) {
+  UPB_ASSERT(i >= 0 && i < m->oneof_count);
+  return &m->oneofs[i];
+}
+
+bool upb_msgdef_mapentry(const upb_msgdef *m) {
+  return m->map_entry;
+}
+
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
+  return m->well_known_type;
+}
+
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
+  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+         type <= UPB_WELLKNOWN_UINT32VALUE;
+}
+
+bool upb_msgdef_iswrapper(const upb_msgdef *m) {
+  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+         type <= UPB_WELLKNOWN_BOOLVALUE;
+}
+
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
+  upb_inttable_begin(iter, &m->itof);
+}
+
+void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
+
+bool upb_msg_field_done(const upb_msg_field_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
+  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+                                const upb_msg_field_iter * iter2) {
+  return upb_inttable_iter_isequal(iter1, iter2);
+}
+
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
+  upb_strtable_begin(iter, &m->ntof);
+  /* We need to skip past any initial fields. */
+  while (!upb_strtable_done(iter) &&
+         !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
+    upb_strtable_next(iter);
+  }
+}
+
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
+  /* We need to skip past fields to return only oneofs. */
+  do {
+    upb_strtable_next(iter);
+  } while (!upb_strtable_done(iter) &&
+           !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
+}
+
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
+  return upb_strtable_done(iter);
+}
+
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
+  return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
+}
+
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
+  upb_strtable_iter_setdone(iter);
+}
+
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+                                const upb_msg_oneof_iter *iter2) {
+  return upb_strtable_iter_isequal(iter1, iter2);
+}
+
+/* upb_oneofdef ***************************************************************/
+
+const char *upb_oneofdef_name(const upb_oneofdef *o) {
+  return shortdefname(o->full_name);
+}
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
+  return o->parent;
+}
+
+int upb_oneofdef_fieldcount(const upb_oneofdef *o) {
+  return o->field_count;
+}
+
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i) {
+  UPB_ASSERT(i < o->field_count);
+  return o->fields[i];
+}
+
+int upb_oneofdef_numfields(const upb_oneofdef *o) {
+  return o->field_count;
+}
+
+uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
+  return o - o->parent->oneofs;
+}
+
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o) {
+  return o->synthetic;
+}
+
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup(&o->itof, num, &val) ? upb_value_getptr(val)
+                                                  : NULL;
+}
+
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
+  upb_inttable_begin(iter, &o->itof);
+}
+
+void upb_oneof_next(upb_oneof_iter *iter) {
+  upb_inttable_next(iter);
+}
+
+bool upb_oneof_done(upb_oneof_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
+  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f) {
+  return f->name;
+}
+
+const char *upb_filedef_package(const upb_filedef *f) {
+  return f->package;
+}
+
+const char *upb_filedef_phpprefix(const upb_filedef *f) {
+  return f->phpprefix;
+}
+
+const char *upb_filedef_phpnamespace(const upb_filedef *f) {
+  return f->phpnamespace;
+}
+
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
+  return f->syntax;
+}
+
+int upb_filedef_msgcount(const upb_filedef *f) {
+  return f->msg_count;
+}
+
+int upb_filedef_depcount(const upb_filedef *f) {
+  return f->dep_count;
+}
+
+int upb_filedef_enumcount(const upb_filedef *f) {
+  return f->enum_count;
+}
+
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
+}
+
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
+}
+
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
+}
+
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f) {
+  return f->symtab;
+}
+
+void upb_symtab_free(upb_symtab *s) {
+  upb_arena_free(s->arena);
+  upb_gfree(s);
+}
+
+upb_symtab *upb_symtab_new(void) {
+  upb_symtab *s = upb_gmalloc(sizeof(*s));
+
+  if (!s) {
+    return NULL;
+  }
+
+  s->arena = upb_arena_new();
+  s->bytes_loaded = 0;
+
+  if (!upb_strtable_init(&s->syms, 32, s->arena) ||
+      !upb_strtable_init(&s->files, 4, s->arena)) {
+    upb_arena_free(s->arena);
+    upb_gfree(s);
+    s = NULL;
+  }
+  return s;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  return upb_strtable_lookup(&s->syms, sym, &v) ?
+      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
+                                        size_t len) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
+      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  return upb_strtable_lookup(&s->syms, sym, &v) ?
+      unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
+  upb_value v;
+  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
+                                                  : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile2(
+    const upb_symtab *s, const char *name, size_t len) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->files, name, len, &v) ?
+      upb_value_getconstptr(v) : NULL;
+}
+
+int upb_symtab_filecount(const upb_symtab *s) {
+  return (int)upb_strtable_count(&s->files);
+}
+
+/* Code to build defs from descriptor protos. *********************************/
+
+/* There is a question of how much validation to do here.  It will be difficult
+ * to perfectly match the amount of validation performed by proto2.  But since
+ * this code is used to directly build defs from Ruby (for example) we do need
+ * to validate important constraints like uniqueness of names and numbers. */
+
+#define CHK_OOM(x) if (!(x)) { symtab_oomerr(ctx); }
+
+typedef struct {
+  upb_symtab *symtab;
+  upb_filedef *file;              /* File we are building. */
+  upb_arena *arena;               /* Allocate defs here. */
+  const upb_msglayout **layouts;  /* NULL if we should build layouts. */
+  upb_status *status;             /* Record errors here. */
+  jmp_buf err;                    /* longjmp() on error. */
+} symtab_addctx;
+
+UPB_NORETURN UPB_NOINLINE UPB_PRINTF(2, 3)
+static void symtab_errf(symtab_addctx *ctx, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_status_vseterrf(ctx->status, fmt, argp);
+  va_end(argp);
+  UPB_LONGJMP(ctx->err, 1);
+}
+
+UPB_NORETURN UPB_NOINLINE
+static void symtab_oomerr(symtab_addctx *ctx) {
+  upb_status_setoom(ctx->status);
+  UPB_LONGJMP(ctx->err, 1);
+}
+
+void *symtab_alloc(symtab_addctx *ctx, size_t bytes) {
+  void *ret = upb_arena_malloc(ctx->arena, bytes);
+  if (!ret) symtab_oomerr(ctx);
+  return ret;
+}
+
+static void check_ident(symtab_addctx *ctx, upb_strview name, bool full) {
+  const char *str = name.data;
+  size_t len = name.size;
+  bool start = true;
+  size_t i;
+  for (i = 0; i < len; i++) {
+    char c = str[i];
+    if (c == '.') {
+      if (start || !full) {
+        symtab_errf(ctx, "invalid name: unexpected '.' (%.*s)", (int)len, str);
+      }
+      start = true;
+    } else if (start) {
+      if (!upb_isletter(c)) {
+        symtab_errf(
+            ctx,
+            "invalid name: path components must start with a letter (%.*s)",
+            (int)len, str);
+      }
+      start = false;
+    } else {
+      if (!upb_isalphanum(c)) {
+        symtab_errf(ctx, "invalid name: non-alphanumeric character (%.*s)",
+                    (int)len, str);
+      }
+    }
+  }
+  if (start) {
+    symtab_errf(ctx, "invalid name: empty part (%.*s)", (int)len, str);
+  }
+}
+
+static size_t div_round_up(size_t n, size_t d) {
+  return (n + d - 1) / d;
+}
+
+static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return 8;
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_FLOAT:
+      return 4;
+    case UPB_TYPE_BOOL:
+      return 1;
+    case UPB_TYPE_MESSAGE:
+      return sizeof(void*);
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_STRING:
+      return sizeof(upb_strview);
+  }
+  UPB_UNREACHABLE();
+}
+
+static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
+  if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) {
+    upb_map_entry ent;
+    UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
+    return sizeof(ent.k);
+  } else if (upb_fielddef_isseq(f)) {
+    return sizeof(void*);
+  } else {
+    return upb_msgval_sizeof(upb_fielddef_type(f));
+  }
+}
+
+static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) {
+  uint32_t ret;
+
+  l->size = UPB_ALIGN_UP(l->size, size);
+  ret = l->size;
+  l->size += size;
+  return ret;
+}
+
+static int field_number_cmp(const void *p1, const void *p2) {
+  const upb_msglayout_field *f1 = p1;
+  const upb_msglayout_field *f2 = p2;
+  return f1->number - f2->number;
+}
+
+static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) {
+  int i;
+  int n = upb_msgdef_numfields(m);
+  for (i = 0; i < n; i++) {
+    upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number);
+    UPB_ASSERT(f);
+    f->layout_index = i;
+  }
+}
+
+/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
+ * It computes a dynamic layout for all of the fields in |m|. */
+static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
+  upb_msglayout *l = (upb_msglayout*)m->layout;
+  upb_msg_field_iter it;
+  upb_msg_oneof_iter oit;
+  size_t hasbit;
+  size_t field_count = upb_msgdef_numfields(m);
+  size_t submsg_count = 0;
+  const upb_msglayout **submsgs;
+  upb_msglayout_field *fields;
+
+  memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry));
+
+  /* Count sub-messages. */
+  for (size_t i = 0; i < field_count; i++) {
+    if (upb_fielddef_issubmsg(&m->fields[i])) {
+      submsg_count++;
+    }
+  }
+
+  fields = symtab_alloc(ctx, field_count * sizeof(*fields));
+  submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs));
+
+  l->field_count = upb_msgdef_numfields(m);
+  l->fields = fields;
+  l->submsgs = submsgs;
+  l->table_mask = 0;
+
+  /* TODO(haberman): initialize fast tables so that reflection-based parsing
+   * can get the same speeds as linked-in types. */
+  l->fasttable[0].field_parser = &fastdecode_generic;
+  l->fasttable[0].field_data = 0;
+
+  if (upb_msgdef_mapentry(m)) {
+    /* TODO(haberman): refactor this method so this special case is more
+     * elegant. */
+    const upb_fielddef *key = upb_msgdef_itof(m, 1);
+    const upb_fielddef *val = upb_msgdef_itof(m, 2);
+    fields[0].number = 1;
+    fields[1].number = 2;
+    fields[0].label = UPB_LABEL_OPTIONAL;
+    fields[1].label = UPB_LABEL_OPTIONAL;
+    fields[0].presence = 0;
+    fields[1].presence = 0;
+    fields[0].descriptortype = upb_fielddef_descriptortype(key);
+    fields[1].descriptortype = upb_fielddef_descriptortype(val);
+    fields[0].offset = 0;
+    fields[1].offset = sizeof(upb_strview);
+    fields[1].submsg_index = 0;
+
+    if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) {
+      submsgs[0] = upb_fielddef_msgsubdef(val)->layout;
+    }
+
+    l->field_count = 2;
+    l->size = 2 * sizeof(upb_strview);
+    l->size = UPB_ALIGN_UP(l->size, 8);
+    return;
+  }
+
+  /* Allocate data offsets in three stages:
+   *
+   * 1. hasbits.
+   * 2. regular fields.
+   * 3. oneof fields.
+   *
+   * OPT: There is a lot of room for optimization here to minimize the size.
+   */
+
+  /* Allocate hasbits and set basic field attributes. */
+  submsg_count = 0;
+  for (upb_msg_field_begin(&it, m), hasbit = 0;
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    upb_fielddef* f = upb_msg_iter_field(&it);
+    upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
+
+    field->number = upb_fielddef_number(f);
+    field->descriptortype = upb_fielddef_descriptortype(f);
+    field->label = upb_fielddef_label(f);
+
+    if (field->descriptortype == UPB_DTYPE_STRING &&
+        f->file->syntax == UPB_SYNTAX_PROTO2) {
+      /* See TableDescriptorType() in upbc/generator.cc for details and
+       * rationale. */
+      field->descriptortype = UPB_DTYPE_BYTES;
+    }
+
+    if (upb_fielddef_ismap(f)) {
+      field->label = _UPB_LABEL_MAP;
+    } else if (upb_fielddef_packed(f)) {
+      field->label = _UPB_LABEL_PACKED;
+    }
+
+    if (upb_fielddef_issubmsg(f)) {
+      const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+      field->submsg_index = submsg_count++;
+      submsgs[field->submsg_index] = subm->layout;
+    }
+
+    if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) {
+      /* We don't use hasbit 0, so that 0 can indicate "no presence" in the
+       * table. This wastes one hasbit, but we don't worry about it for now. */
+      field->presence = ++hasbit;
+    } else {
+      field->presence = 0;
+    }
+  }
+
+  /* Account for space used by hasbits. */
+  l->size = div_round_up(hasbit, 8);
+
+  /* Allocate non-oneof fields. */
+  for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* f = upb_msg_iter_field(&it);
+    size_t field_size = upb_msg_fielddefsize(f);
+    size_t index = upb_fielddef_index(f);
+
+    if (upb_fielddef_realcontainingoneof(f)) {
+      /* Oneofs are handled separately below. */
+      continue;
+    }
+
+    fields[index].offset = upb_msglayout_place(l, field_size);
+  }
+
+  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
+   * and space for the actual data. */
+  for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
+    upb_oneof_iter fit;
+
+    size_t case_size = sizeof(uint32_t);  /* Could potentially optimize this. */
+    size_t field_size = 0;
+    uint32_t case_offset;
+    uint32_t data_offset;
+
+    if (upb_oneofdef_issynthetic(o)) continue;
+
+    /* Calculate field size: the max of all field sizes. */
+    for (upb_oneof_begin(&fit, o);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* f = upb_oneof_iter_field(&fit);
+      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
+    }
+
+    /* Align and allocate case offset. */
+    case_offset = upb_msglayout_place(l, case_size);
+    data_offset = upb_msglayout_place(l, field_size);
+
+    for (upb_oneof_begin(&fit, o);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* f = upb_oneof_iter_field(&fit);
+      fields[upb_fielddef_index(f)].offset = data_offset;
+      fields[upb_fielddef_index(f)].presence = ~case_offset;
+    }
+  }
+
+  /* Size of the entire structure should be a multiple of its greatest
+   * alignment.  TODO: track overall alignment for real? */
+  l->size = UPB_ALIGN_UP(l->size, 8);
+
+  /* Sort fields by number. */
+  qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp);
+  assign_layout_indices(m, fields);
+}
+
+static char *strviewdup(symtab_addctx *ctx, upb_strview view) {
+  return upb_strdup2(view.data, view.size, ctx->arena);
+}
+
+static bool streql2(const char *a, size_t n, const char *b) {
+  return n == strlen(b) && memcmp(a, b, n) == 0;
+}
+
+static bool streql_view(upb_strview view, const char *b) {
+  return streql2(view.data, view.size, b);
+}
+
+static const char *makefullname(symtab_addctx *ctx, const char *prefix,
+                                upb_strview name) {
+  if (prefix) {
+    /* ret = prefix + '.' + name; */
+    size_t n = strlen(prefix);
+    char *ret = symtab_alloc(ctx, n + name.size + 2);
+    strcpy(ret, prefix);
+    ret[n] = '.';
+    memcpy(&ret[n + 1], name.data, name.size);
+    ret[n + 1 + name.size] = '\0';
+    return ret;
+  } else {
+    return strviewdup(ctx, name);
+  }
+}
+
+static void finalize_oneofs(symtab_addctx *ctx, upb_msgdef *m) {
+  int i;
+  int synthetic_count = 0;
+  upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs;
+
+  for (i = 0; i < m->oneof_count; i++) {
+    upb_oneofdef *o = &mutable_oneofs[i];
+
+    if (o->synthetic && o->field_count != 1) {
+      symtab_errf(ctx, "Synthetic oneofs must have one field, not %d: %s",
+                  o->field_count, upb_oneofdef_name(o));
+    }
+
+    if (o->synthetic) {
+      synthetic_count++;
+    } else if (synthetic_count != 0) {
+      symtab_errf(ctx, "Synthetic oneofs must be after all other oneofs: %s",
+                  upb_oneofdef_name(o));
+    }
+
+    o->fields = symtab_alloc(ctx, sizeof(upb_fielddef *) * o->field_count);
+    o->field_count = 0;
+  }
+
+  for (i = 0; i < m->field_count; i++) {
+    const upb_fielddef *f = &m->fields[i];
+    upb_oneofdef *o = (upb_oneofdef*)f->oneof;
+    if (o) {
+      o->fields[o->field_count++] = f;
+    }
+  }
+
+  m->real_oneof_count = m->oneof_count - synthetic_count;
+}
+
+size_t getjsonname(const char *name, char *buf, size_t len) {
+  size_t src, dst = 0;
+  bool ucase_next = false;
+
+#define WRITE(byte) \
+  ++dst; \
+  if (dst < len) buf[dst - 1] = byte; \
+  else if (dst == len) buf[dst - 1] = '\0'
+
+  if (!name) {
+    WRITE('\0');
+    return 0;
+  }
+
+  /* Implement the transformation as described in the spec:
+   *   1. upper case all letters after an underscore.
+   *   2. remove all underscores.
+   */
+  for (src = 0; name[src]; src++) {
+    if (name[src] == '_') {
+      ucase_next = true;
+      continue;
+    }
+
+    if (ucase_next) {
+      WRITE(toupper(name[src]));
+      ucase_next = false;
+    } else {
+      WRITE(name[src]);
+    }
+  }
+
+  WRITE('\0');
+  return dst;
+
+#undef WRITE
+}
+
+static char* makejsonname(symtab_addctx *ctx, const char* name) {
+  size_t size = getjsonname(name, NULL, 0);
+  char* json_name = symtab_alloc(ctx, size);
+  getjsonname(name, json_name, size);
+  return json_name;
+}
+
+static void symtab_add(symtab_addctx *ctx, const char *name, upb_value v) {
+  if (upb_strtable_lookup(&ctx->symtab->syms, name, NULL)) {
+    symtab_errf(ctx, "duplicate symbol '%s'", name);
+  }
+  size_t len = strlen(name);
+  CHK_OOM(upb_strtable_insert(&ctx->symtab->syms, name, len, v,
+                              ctx->symtab->arena));
+}
+
+/* Given a symbol and the base symbol inside which it is defined, find the
+ * symbol's definition in t. */
+static const void *symtab_resolve(symtab_addctx *ctx, const upb_fielddef *f,
+                                  const char *base, upb_strview sym,
+                                  upb_deftype_t type) {
+  const upb_strtable *t = &ctx->symtab->syms;
+  if(sym.size == 0) goto notfound;
+  if(sym.data[0] == '.') {
+    /* Symbols starting with '.' are absolute, so we do a single lookup.
+     * Slice to omit the leading '.' */
+    upb_value v;
+    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
+      goto notfound;
+    }
+
+    const void *ret = unpack_def(v, type);
+    if (!ret) {
+      symtab_errf(ctx, "type mismatch when resolving field %s, name %s",
+                  f->full_name, sym.data);
+    }
+    return ret;
+  } else {
+    /* Remove components from base until we find an entry or run out.
+     * TODO: This branch is totally broken, but currently not used. */
+    (void)base;
+    UPB_ASSERT(false);
+    goto notfound;
+  }
+
+notfound:
+  symtab_errf(ctx, "couldn't resolve name '" UPB_STRVIEW_FORMAT "'",
+              UPB_STRVIEW_ARGS(sym));
+}
+
+static void create_oneofdef(
+    symtab_addctx *ctx, upb_msgdef *m,
+    const google_protobuf_OneofDescriptorProto *oneof_proto) {
+  upb_oneofdef *o;
+  upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
+  upb_value v;
+
+  o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
+  o->parent = m;
+  o->full_name = makefullname(ctx, m->full_name, name);
+  o->field_count = 0;
+  o->synthetic = false;
+
+  v = pack_def(o, UPB_DEFTYPE_ONEOF);
+  symtab_add(ctx, o->full_name, v);
+  CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, v, ctx->arena));
+
+  CHK_OOM(upb_inttable_init(&o->itof, ctx->arena));
+  CHK_OOM(upb_strtable_init(&o->ntof, 4, ctx->arena));
+}
+
+static str_t *newstr(symtab_addctx *ctx, const char *data, size_t len) {
+  str_t *ret = symtab_alloc(ctx, sizeof(*ret) + len);
+  if (!ret) return NULL;
+  ret->len = len;
+  if (len) memcpy(ret->str, data, len);
+  ret->str[len] = '\0';
+  return ret;
+}
+
+static void parse_default(symtab_addctx *ctx, const char *str, size_t len,
+                          upb_fielddef *f) {
+  char *end;
+  char nullz[64];
+  errno = 0;
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_FLOAT:
+      /* Standard C number parsing functions expect null-terminated strings. */
+      if (len >= sizeof(nullz) - 1) {
+        symtab_errf(ctx, "Default too long: %.*s", (int)len, str);
+      }
+      memcpy(nullz, str, len);
+      nullz[len] = '\0';
+      str = nullz;
+      break;
+    default:
+      break;
+  }
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32: {
+      long val = strtol(str, &end, 0);
+      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_ENUM: {
+      const upb_enumdef *e = f->sub.enumdef;
+      int32_t val;
+      if (!upb_enumdef_ntoi(e, str, len, &val)) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_INT64: {
+      long long val = strtoll(str, &end, 0);
+      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(str, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case UPB_TYPE_UINT64: {
+      unsigned long long val = strtoull(str, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      double val = strtod(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.dbl = val;
+      break;
+    }
+    case UPB_TYPE_FLOAT: {
+      float val = strtof(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.flt = val;
+      break;
+    }
+    case UPB_TYPE_BOOL: {
+      if (streql2(str, len, "false")) {
+        f->defaultval.boolean = false;
+      } else if (streql2(str, len, "true")) {
+        f->defaultval.boolean = true;
+      } else {
+      }
+      break;
+    }
+    case UPB_TYPE_STRING:
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case UPB_TYPE_BYTES:
+      /* XXX: need to interpret the C-escaped value. */
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case UPB_TYPE_MESSAGE:
+      /* Should not have a default value. */
+      symtab_errf(ctx, "Message should not have a default (%s)",
+                  upb_fielddef_fullname(f));
+  }
+
+  return;
+
+invalid:
+  symtab_errf(ctx, "Invalid default '%.*s' for field %s", (int)len, str,
+              upb_fielddef_fullname(f));
+}
+
+static void set_default_default(symtab_addctx *ctx, upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_ENUM:
+      f->defaultval.sint = 0;
+      break;
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_UINT32:
+      f->defaultval.uint = 0;
+      break;
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_FLOAT:
+      f->defaultval.dbl = 0;
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      f->defaultval.str = newstr(ctx, NULL, 0);
+      break;
+    case UPB_TYPE_BOOL:
+      f->defaultval.boolean = false;
+      break;
+    case UPB_TYPE_MESSAGE:
+      break;
+  }
+}
+
+static void create_fielddef(
+    symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
+    const google_protobuf_FieldDescriptorProto *field_proto) {
+  upb_fielddef *f;
+  const google_protobuf_FieldOptions *options;
+  upb_strview name;
+  const char *full_name;
+  const char *json_name;
+  const char *shortname;
+  uint32_t field_number;
+
+  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
+    symtab_errf(ctx, "field has no name (%s)", upb_msgdef_fullname(m));
+  }
+
+  name = google_protobuf_FieldDescriptorProto_name(field_proto);
+  check_ident(ctx, name, false);
+  full_name = makefullname(ctx, prefix, name);
+  shortname = shortdefname(full_name);
+
+  if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
+    json_name = strviewdup(
+        ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
+  } else {
+    json_name = makejsonname(ctx, shortname);
+  }
+
+  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
+
+  if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
+    symtab_errf(ctx, "invalid field number (%u)", field_number);
+  }
+
+  if (m) {
+    /* direct message field. */
+    upb_value v, field_v, json_v;
+    size_t json_size;
+
+    f = (upb_fielddef*)&m->fields[m->field_count];
+    f->index_ = m->field_count++;
+    f->msgdef = m;
+    f->is_extension_ = false;
+
+    if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
+      symtab_errf(ctx, "duplicate field name (%s)", shortname);
+    }
+
+    if (upb_strtable_lookup(&m->ntof, json_name, NULL)) {
+      symtab_errf(ctx, "duplicate json_name (%s)", json_name);
+    }
+
+    if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
+      symtab_errf(ctx, "duplicate field number (%u)", field_number);
+    }
+
+    field_v = pack_def(f, UPB_DEFTYPE_FIELD);
+    json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME);
+    v = upb_value_constptr(f);
+    json_size = strlen(json_name);
+
+    CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, field_v,
+                                ctx->arena));
+    CHK_OOM(upb_inttable_insert(&m->itof, field_number, v, ctx->arena));
+
+    if (strcmp(shortname, json_name) != 0) {
+      upb_strtable_insert(&m->ntof, json_name, json_size, json_v, ctx->arena);
+    }
+
+    if (ctx->layouts) {
+      const upb_msglayout_field *fields = m->layout->fields;
+      int count = m->layout->field_count;
+      bool found = false;
+      int i;
+      for (i = 0; i < count; i++) {
+        if (fields[i].number == field_number) {
+          f->layout_index = i;
+          found = true;
+          break;
+        }
+      }
+      UPB_ASSERT(found);
+    }
+  } else {
+    /* extension field. */
+    f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++];
+    f->is_extension_ = true;
+    symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD));
+  }
+
+  f->full_name = full_name;
+  f->json_name = json_name;
+  f->file = ctx->file;
+  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
+  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
+  f->number_ = field_number;
+  f->oneof = NULL;
+  f->proto3_optional_ =
+      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
+
+  /* We can't resolve the subdef or (in the case of extensions) the containing
+   * message yet, because it may not have been defined yet.  We stash a pointer
+   * to the field_proto until later when we can properly resolve it. */
+  f->sub.unresolved = field_proto;
+
+  if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
+    symtab_errf(ctx, "proto3 fields cannot be required (%s)", f->full_name);
+  }
+
+  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    int oneof_index =
+        google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
+    upb_oneofdef *oneof;
+    upb_value v = upb_value_constptr(f);
+
+    if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
+      symtab_errf(ctx, "fields in oneof must have OPTIONAL label (%s)",
+                  f->full_name);
+    }
+
+    if (!m) {
+      symtab_errf(ctx, "oneof_index provided for extension field (%s)",
+                  f->full_name);
+    }
+
+    if (oneof_index >= m->oneof_count) {
+      symtab_errf(ctx, "oneof_index out of range (%s)", f->full_name);
+    }
+
+    oneof = (upb_oneofdef *)&m->oneofs[oneof_index];
+    f->oneof = oneof;
+
+    oneof->field_count++;
+    if (f->proto3_optional_) {
+      oneof->synthetic = true;
+    }
+    CHK_OOM(upb_inttable_insert(&oneof->itof, f->number_, v, ctx->arena));
+    CHK_OOM(
+        upb_strtable_insert(&oneof->ntof, name.data, name.size, v, ctx->arena));
+  } else {
+    f->oneof = NULL;
+    if (f->proto3_optional_) {
+      symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)",
+                  f->full_name);
+    }
+  }
+
+  options = google_protobuf_FieldDescriptorProto_has_options(field_proto) ?
+    google_protobuf_FieldDescriptorProto_options(field_proto) : NULL;
+
+  if (options && google_protobuf_FieldOptions_has_packed(options)) {
+    f->packed_ = google_protobuf_FieldOptions_packed(options);
+  } else {
+    /* Repeated fields default to packed for proto3 only. */
+    f->packed_ = upb_fielddef_isprimitive(f) &&
+        f->label_ == UPB_LABEL_REPEATED && f->file->syntax == UPB_SYNTAX_PROTO3;
+  }
+
+  if (options) {
+    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
+  } else {
+    f->lazy_ = false;
+  }
+}
+
+static void create_enumdef(
+    symtab_addctx *ctx, const char *prefix,
+    const google_protobuf_EnumDescriptorProto *enum_proto) {
+  upb_enumdef *e;
+  const google_protobuf_EnumValueDescriptorProto *const *values;
+  upb_strview name;
+  size_t i, n;
+
+  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
+  check_ident(ctx, name, false);
+
+  e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
+  e->full_name = makefullname(ctx, prefix, name);
+  symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM));
+
+  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
+  CHK_OOM(upb_strtable_init(&e->ntoi, n, ctx->arena));
+  CHK_OOM(upb_inttable_init(&e->iton, ctx->arena));
+
+  e->file = ctx->file;
+  e->defaultval = 0;
+
+  if (n == 0) {
+    symtab_errf(ctx, "enums must contain at least one value (%s)",
+                e->full_name);
+  }
+
+  for (i = 0; i < n; i++) {
+    const google_protobuf_EnumValueDescriptorProto *value = values[i];
+    upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
+    char *name2 = strviewdup(ctx, name);
+    int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
+    upb_value v = upb_value_int32(num);
+
+    if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
+      symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)",
+                  e->full_name);
+    }
+
+    if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
+      symtab_errf(ctx, "duplicate enum label '%s'", name2);
+    }
+
+    CHK_OOM(name2)
+    CHK_OOM(upb_strtable_insert(&e->ntoi, name2, strlen(name2), v, ctx->arena));
+
+    if (!upb_inttable_lookup(&e->iton, num, NULL)) {
+      upb_value v = upb_value_cstr(name2);
+      CHK_OOM(upb_inttable_insert(&e->iton, num, v, ctx->arena));
+    }
+  }
+
+  upb_inttable_compact(&e->iton, ctx->arena);
+}
+
+static void create_msgdef(symtab_addctx *ctx, const char *prefix,
+                          const google_protobuf_DescriptorProto *msg_proto) {
+  upb_msgdef *m;
+  const google_protobuf_MessageOptions *options;
+  const google_protobuf_OneofDescriptorProto *const *oneofs;
+  const google_protobuf_FieldDescriptorProto *const *fields;
+  const google_protobuf_EnumDescriptorProto *const *enums;
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n_oneof, n_field, n;
+  upb_strview name;
+
+  name = google_protobuf_DescriptorProto_name(msg_proto);
+  check_ident(ctx, name, false);
+
+  m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
+  m->full_name = makefullname(ctx, prefix, name);
+  symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG));
+
+  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof);
+  fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field);
+
+  CHK_OOM(upb_inttable_init(&m->itof, ctx->arena));
+  CHK_OOM(upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena));
+
+  m->file = ctx->file;
+  m->map_entry = false;
+
+  options = google_protobuf_DescriptorProto_options(msg_proto);
+
+  if (options) {
+    m->map_entry = google_protobuf_MessageOptions_map_entry(options);
+  }
+
+  if (ctx->layouts) {
+    m->layout = *ctx->layouts;
+    ctx->layouts++;
+  } else {
+    /* Allocate now (to allow cross-linking), populate later. */
+    m->layout = symtab_alloc(
+        ctx, sizeof(*m->layout) + sizeof(_upb_fasttable_entry));
+  }
+
+  m->oneof_count = 0;
+  m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof);
+  for (i = 0; i < n_oneof; i++) {
+    create_oneofdef(ctx, m, oneofs[i]);
+  }
+
+  m->field_count = 0;
+  m->fields = symtab_alloc(ctx, sizeof(*m->fields) * n_field);
+  for (i = 0; i < n_field; i++) {
+    create_fielddef(ctx, m->full_name, m, fields[i]);
+  }
+
+  finalize_oneofs(ctx, m);
+  assign_msg_wellknowntype(m);
+  upb_inttable_compact(&m->itof, ctx->arena);
+
+  /* This message is built.  Now build nested messages and enums. */
+
+  enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_enumdef(ctx, m->full_name, enums[i]);
+  }
+
+  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_msgdef(ctx, m->full_name, msgs[i]);
+  }
+}
+
+static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
+                               upb_filedef *file) {
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n;
+
+  file->msg_count++;
+
+  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    count_types_in_msg(msgs[i], file);
+  }
+
+  google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+  file->enum_count += n;
+
+  google_protobuf_DescriptorProto_extension(msg_proto, &n);
+  file->ext_count += n;
+}
+
+static void count_types_in_file(
+    const google_protobuf_FileDescriptorProto *file_proto,
+    upb_filedef *file) {
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n;
+
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    count_types_in_msg(msgs[i], file);
+  }
+
+  google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  file->enum_count += n;
+
+  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->ext_count += n;
+}
+
+static void resolve_fielddef(symtab_addctx *ctx, const char *prefix,
+                             upb_fielddef *f) {
+  upb_strview name;
+  const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
+
+  if (f->is_extension_) {
+    if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
+      symtab_errf(ctx, "extension for field '%s' had no extendee",
+                  f->full_name);
+    }
+
+    name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
+    f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+  }
+
+  if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
+      !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
+    symtab_errf(ctx, "field '%s' is missing type name", f->full_name);
+  }
+
+  name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
+
+  if (upb_fielddef_issubmsg(f)) {
+    f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+  } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
+    f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
+  }
+
+  /* Have to delay resolving of the default value until now because of the enum
+   * case, since enum defaults are specified with a label. */
+  if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
+    upb_strview defaultval =
+        google_protobuf_FieldDescriptorProto_default_value(field_proto);
+
+    if (f->file->syntax == UPB_SYNTAX_PROTO3) {
+      symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)",
+                  f->full_name);
+    }
+
+    if (upb_fielddef_issubmsg(f)) {
+      symtab_errf(ctx, "message fields cannot have explicit defaults (%s)",
+                  f->full_name);
+    }
+
+    parse_default(ctx, defaultval.data, defaultval.size, f);
+  } else {
+    set_default_default(ctx, f);
+  }
+}
+
+static void build_filedef(
+    symtab_addctx *ctx, upb_filedef *file,
+    const google_protobuf_FileDescriptorProto *file_proto) {
+  const google_protobuf_FileOptions *file_options_proto;
+  const google_protobuf_DescriptorProto *const *msgs;
+  const google_protobuf_EnumDescriptorProto *const *enums;
+  const google_protobuf_FieldDescriptorProto *const *exts;
+  const upb_strview* strs;
+  size_t i, n;
+
+  count_types_in_file(file_proto, file);
+
+  file->msgs = symtab_alloc(ctx, sizeof(*file->msgs) * file->msg_count);
+  file->enums = symtab_alloc(ctx, sizeof(*file->enums) * file->enum_count);
+  file->exts = symtab_alloc(ctx, sizeof(*file->exts) * file->ext_count);
+
+  /* We increment these as defs are added. */
+  file->msg_count = 0;
+  file->enum_count = 0;
+  file->ext_count = 0;
+
+  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
+    symtab_errf(ctx, "File has no name");
+  }
+
+  file->name =
+      strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
+  file->phpprefix = NULL;
+  file->phpnamespace = NULL;
+
+  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
+    upb_strview package =
+        google_protobuf_FileDescriptorProto_package(file_proto);
+    check_ident(ctx, package, true);
+    file->package = strviewdup(ctx, package);
+  } else {
+    file->package = NULL;
+  }
+
+  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
+    upb_strview syntax =
+        google_protobuf_FileDescriptorProto_syntax(file_proto);
+
+    if (streql_view(syntax, "proto2")) {
+      file->syntax = UPB_SYNTAX_PROTO2;
+    } else if (streql_view(syntax, "proto3")) {
+      file->syntax = UPB_SYNTAX_PROTO3;
+    } else {
+      symtab_errf(ctx, "Invalid syntax '" UPB_STRVIEW_FORMAT "'",
+                  UPB_STRVIEW_ARGS(syntax));
+    }
+  } else {
+    file->syntax = UPB_SYNTAX_PROTO2;
+  }
+
+  /* Read options. */
+  file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
+  if (file_options_proto) {
+    if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
+      file->phpprefix = strviewdup(
+          ctx,
+          google_protobuf_FileOptions_php_class_prefix(file_options_proto));
+    }
+    if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
+      file->phpnamespace = strviewdup(
+          ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
+    }
+  }
+
+  /* Verify dependencies. */
+  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
+  file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n);
+
+  for (i = 0; i < n; i++) {
+    upb_strview dep_name = strs[i];
+    upb_value v;
+    if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
+                              dep_name.size, &v)) {
+      symtab_errf(ctx,
+                  "Depends on file '" UPB_STRVIEW_FORMAT
+                  "', but it has not been loaded",
+                  UPB_STRVIEW_ARGS(dep_name));
+    }
+    file->deps[i] = upb_value_getconstptr(v);
+  }
+
+  /* Create messages. */
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_msgdef(ctx, file->package, msgs[i]);
+  }
+
+  /* Create enums. */
+  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_enumdef(ctx, file->package, enums[i]);
+  }
+
+  /* Create extensions. */
+  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->exts = symtab_alloc(ctx, sizeof(*file->exts) * n);
+  for (i = 0; i < n; i++) {
+    create_fielddef(ctx, file->package, NULL, exts[i]);
+  }
+
+  /* Now that all names are in the table, build layouts and resolve refs. */
+  for (i = 0; i < (size_t)file->ext_count; i++) {
+    resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]);
+  }
+
+  for (i = 0; i < (size_t)file->msg_count; i++) {
+    const upb_msgdef *m = &file->msgs[i];
+    int j;
+    for (j = 0; j < m->field_count; j++) {
+      resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]);
+    }
+  }
+
+  if (!ctx->layouts) {
+    for (i = 0; i < (size_t)file->msg_count; i++) {
+      const upb_msgdef *m = &file->msgs[i];
+      make_layout(ctx, m);
+    }
+  }
+}
+
+static void remove_filedef(upb_symtab *s, upb_filedef *file) {
+  int i;
+  for (i = 0; i < file->msg_count; i++) {
+    const char *name = file->msgs[i].full_name;
+    upb_strtable_remove(&s->syms, name, strlen(name), NULL);
+  }
+  for (i = 0; i < file->enum_count; i++) {
+    const char *name = file->enums[i].full_name;
+    upb_strtable_remove(&s->syms, name, strlen(name), NULL);
+  }
+  for (i = 0; i < file->ext_count; i++) {
+    const char *name = file->exts[i].full_name;
+    upb_strtable_remove(&s->syms, name, strlen(name), NULL);
+  }
+}
+
+static const upb_filedef *_upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+    const upb_msglayout **layouts, upb_status *status) {
+  upb_arena *file_arena = upb_arena_new();
+  upb_filedef *file;
+  symtab_addctx ctx;
+
+  if (!file_arena) return NULL;
+
+  file = upb_arena_malloc(file_arena, sizeof(*file));
+  if (!file) goto done;
+
+  ctx.file = file;
+  ctx.symtab = s;
+  ctx.arena = file_arena;
+  ctx.layouts = layouts;
+  ctx.status = status;
+
+  file->msg_count = 0;
+  file->enum_count = 0;
+  file->ext_count = 0;
+  file->symtab = s;
+
+  if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) {
+    UPB_ASSERT(!upb_ok(status));
+    remove_filedef(s, file);
+    file = NULL;
+  } else {
+    build_filedef(&ctx, file, file_proto);
+    upb_strtable_insert(&s->files, file->name, strlen(file->name),
+                        upb_value_constptr(file), ctx.arena);
+    UPB_ASSERT(upb_ok(status));
+    upb_arena_fuse(s->arena, file_arena);
+  }
+
+done:
+  upb_arena_free(file_arena);
+  return file;
+}
+
+const upb_filedef *upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+    upb_status *status) {
+  return _upb_symtab_addfile(s, file_proto, NULL, status);
+}
+
+/* Include here since we want most of this file to be stdio-free. */
+#include <stdio.h>
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
+  /* Since this function should never fail (it would indicate a bug in upb) we
+   * print errors to stderr instead of returning error status to the user. */
+  upb_def_init **deps = init->deps;
+  google_protobuf_FileDescriptorProto *file;
+  upb_arena *arena;
+  upb_status status;
+
+  upb_status_clear(&status);
+
+  if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
+    return true;
+  }
+
+  arena = upb_arena_new();
+
+  for (; *deps; deps++) {
+    if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
+  }
+
+  file = google_protobuf_FileDescriptorProto_parse_ex(
+      init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS);
+  s->bytes_loaded += init->descriptor.size;
+
+  if (!file) {
+    upb_status_seterrf(
+        &status,
+        "Failed to parse compiled-in descriptor for file '%s'. This should "
+        "never happen.",
+        init->filename);
+    goto err;
+  }
+
+  if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err;
+
+  upb_arena_free(arena);
+  return true;
+
+err:
+  fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
+          upb_status_errmsg(&status));
+  upb_arena_free(arena);
+  return false;
+}
+
+size_t _upb_symtab_bytesloaded(const upb_symtab *s) {
+  return s->bytes_loaded;
+}
+
+upb_arena *_upb_symtab_arena(const upb_symtab *s) {
+  return s->arena;
+}
+
+#undef CHK_OOM
+
+/** upb/reflection.c ************************************************************/
+
+#include <string.h>
+
+
+static size_t get_field_size(const upb_msglayout_field *f) {
+  static unsigned char sizes[] = {
+    0,/* 0 */
+    8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
+    4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
+    8, /* UPB_DESCRIPTOR_TYPE_INT64 */
+    8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
+    4, /* UPB_DESCRIPTOR_TYPE_INT32 */
+    8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
+    4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
+    1, /* UPB_DESCRIPTOR_TYPE_BOOL */
+    sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
+    sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
+    sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
+    sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
+    4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
+    4, /* UPB_DESCRIPTOR_TYPE_ENUM */
+    4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
+    8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
+    4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
+    8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
+  };
+  return _upb_repeated_or_map(f) ? sizeof(void *) : sizes[f->descriptortype];
+}
+
+/* Strings/bytes are special-cased in maps. */
+static char _upb_fieldtype_to_mapsize[12] = {
+  0,
+  1,  /* UPB_TYPE_BOOL */
+  4,  /* UPB_TYPE_FLOAT */
+  4,  /* UPB_TYPE_INT32 */
+  4,  /* UPB_TYPE_UINT32 */
+  4,  /* UPB_TYPE_ENUM */
+  sizeof(void*),  /* UPB_TYPE_MESSAGE */
+  8,  /* UPB_TYPE_DOUBLE */
+  8,  /* UPB_TYPE_INT64 */
+  8,  /* UPB_TYPE_UINT64 */
+  0,  /* UPB_TYPE_STRING */
+  0,  /* UPB_TYPE_BYTES */
+};
+
+static const char _upb_fieldtype_to_sizelg2[12] = {
+  0,
+  0,  /* UPB_TYPE_BOOL */
+  2,  /* UPB_TYPE_FLOAT */
+  2,  /* UPB_TYPE_INT32 */
+  2,  /* UPB_TYPE_UINT32 */
+  2,  /* UPB_TYPE_ENUM */
+  UPB_SIZE(2, 3),  /* UPB_TYPE_MESSAGE */
+  3,  /* UPB_TYPE_DOUBLE */
+  3,  /* UPB_TYPE_INT64 */
+  3,  /* UPB_TYPE_UINT64 */
+  UPB_SIZE(3, 4),  /* UPB_TYPE_STRING */
+  UPB_SIZE(3, 4),  /* UPB_TYPE_BYTES */
+};
+
+/** upb_msg *******************************************************************/
+
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
+  return _upb_msg_new(upb_msgdef_layout(m), a);
+}
+
+static bool in_oneof(const upb_msglayout_field *field) {
+  return field->presence < 0;
+}
+
+static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  const char *mem = UPB_PTR_AT(msg, field->offset, char);
+  upb_msgval val = {0};
+  memcpy(&val, mem, get_field_size(field));
+  return val;
+}
+
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  if (in_oneof(field)) {
+    return _upb_getoneofcase_field(msg, field) == field->number;
+  } else if (field->presence > 0) {
+    return _upb_hasbit_field(msg, field);
+  } else {
+    UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
+               field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
+    return _upb_msg_getraw(msg, f).msg_val != NULL;
+  }
+}
+
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+                                       const upb_oneofdef *o) {
+  const upb_fielddef *f = upb_oneofdef_field(o, 0);
+  if (upb_oneofdef_issynthetic(o)) {
+    UPB_ASSERT(upb_oneofdef_fieldcount(o) == 1);
+    return upb_msg_has(msg, f) ? f : NULL;
+  } else {
+    const upb_msglayout_field *field = upb_fielddef_layout(f);
+    uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
+    f = oneof_case ? upb_oneofdef_itof(o, oneof_case) : NULL;
+    UPB_ASSERT((f != NULL) == (oneof_case != 0));
+    return f;
+  }
+}
+
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
+  if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
+    return _upb_msg_getraw(msg, f);
+  } else {
+    return upb_fielddef_default(f);
+  }
+}
+
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
+                              upb_arena *a) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  upb_mutmsgval ret;
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+  bool wrong_oneof =
+      in_oneof(field) && _upb_getoneofcase_field(msg, field) != field->number;
+
+  memcpy(&ret, mem, sizeof(void*));
+
+  if (a && (!ret.msg || wrong_oneof)) {
+    if (upb_fielddef_ismap(f)) {
+      const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+      const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
+      const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
+      ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
+    } else if (upb_fielddef_isseq(f)) {
+      ret.array = upb_array_new(a, upb_fielddef_type(f));
+    } else {
+      UPB_ASSERT(upb_fielddef_issubmsg(f));
+      ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
+    }
+
+    memcpy(mem, &ret, sizeof(void*));
+
+    if (wrong_oneof) {
+      *_upb_oneofcase_field(msg, field) = field->number;
+    } else if (field->presence > 0) {
+      _upb_sethas_field(msg, field);
+    }
+  }
+  return ret;
+}
+
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+                 upb_arena *a) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+  UPB_UNUSED(a);  /* We reserve the right to make set insert into a map. */
+  memcpy(mem, &val, get_field_size(field));
+  if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  } else if (in_oneof(field)) {
+    *_upb_oneofcase_field(msg, field) = field->number;
+  }
+}
+
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+
+  if (field->presence > 0) {
+    _upb_clearhas_field(msg, field);
+  } else if (in_oneof(field)) {
+    uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
+    if (*oneof_case != field->number) return;
+    *oneof_case = 0;
+  }
+
+  memset(mem, 0, get_field_size(field));
+}
+
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m) {
+  _upb_msg_clear(msg, upb_msgdef_layout(m));
+}
+
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+                  const upb_symtab *ext_pool, const upb_fielddef **out_f,
+                  upb_msgval *out_val, size_t *iter) {
+  int i = *iter;
+  int n = upb_msgdef_fieldcount(m);
+  const upb_msgval zero = {0};
+  UPB_UNUSED(ext_pool);
+  while (++i < n) {
+    const upb_fielddef *f = upb_msgdef_field(m, i);
+    upb_msgval val = _upb_msg_getraw(msg, f);
+
+    /* Skip field if unset or empty. */
+    if (upb_fielddef_haspresence(f)) {
+      if (!upb_msg_has(msg, f)) continue;
+    } else {
+      upb_msgval test = val;
+      if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
+        /* Clear string pointer, only size matters (ptr could be non-NULL). */
+        test.str_val.data = NULL;
+      }
+      /* Continue if NULL or 0. */
+      if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
+
+      /* Continue on empty array or map. */
+      if (upb_fielddef_ismap(f)) {
+        if (upb_map_size(test.map_val) == 0) continue;
+      } else if (upb_fielddef_isseq(f)) {
+        if (upb_array_size(test.array_val) == 0) continue;
+      }
+    }
+
+    *out_val = val;
+    *out_f = f;
+    *iter = i;
+    return true;
+  }
+  *iter = i;
+  return false;
+}
+
+bool _upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int depth) {
+  size_t iter = UPB_MSG_BEGIN;
+  const upb_fielddef *f;
+  upb_msgval val;
+  bool ret = true;
+
+  if (--depth == 0) return false;
+
+  _upb_msg_discardunknown_shallow(msg);
+
+  while (upb_msg_next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
+    const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+    if (!subm) continue;
+    if (upb_fielddef_ismap(f)) {
+      const upb_fielddef *val_f = upb_msgdef_itof(subm, 2);
+      const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f);
+      upb_map *map = (upb_map*)val.map_val;
+      size_t iter = UPB_MAP_BEGIN;
+
+      if (!val_m) continue;
+
+      while (upb_mapiter_next(map, &iter)) {
+        upb_msgval map_val = upb_mapiter_value(map, iter);
+        if (!_upb_msg_discardunknown((upb_msg*)map_val.msg_val, val_m, depth)) {
+          ret = false;
+        }
+      }
+    } else if (upb_fielddef_isseq(f)) {
+      const upb_array *arr = val.array_val;
+      size_t i, n = upb_array_size(arr);
+      for (i = 0; i < n; i++) {
+        upb_msgval elem = upb_array_get(arr, i);
+        if (!_upb_msg_discardunknown((upb_msg*)elem.msg_val, subm, depth)) {
+          ret = false;
+        }
+      }
+    } else {
+      if (!_upb_msg_discardunknown((upb_msg*)val.msg_val, subm, depth)) {
+        ret = false;
+      }
+    }
+  }
+
+  return ret;
+}
+
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth) {
+  return _upb_msg_discardunknown(msg, m, maxdepth);
+}
+
+/** upb_array *****************************************************************/
+
+upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
+  return _upb_array_new(a, 4, _upb_fieldtype_to_sizelg2[type]);
+}
+
+size_t upb_array_size(const upb_array *arr) {
+  return arr->len;
+}
+
+upb_msgval upb_array_get(const upb_array *arr, size_t i) {
+  upb_msgval ret;
+  const char* data = _upb_array_constptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->len);
+  memcpy(&ret, data + (i << lg2), 1 << lg2);
+  return ret;
+}
+
+void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
+  char* data = _upb_array_ptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->len);
+  memcpy(data + (i << lg2), &val, 1 << lg2);
+}
+
+bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
+  if (!upb_array_resize(arr, arr->len + 1, arena)) {
+    return false;
+  }
+  upb_array_set(arr, arr->len - 1, val);
+  return true;
+}
+
+bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) {
+  return _upb_array_resize(arr, size, arena);
+}
+
+/** upb_map *******************************************************************/
+
+upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
+                     upb_fieldtype_t value_type) {
+  return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
+                      _upb_fieldtype_to_mapsize[value_type]);
+}
+
+size_t upb_map_size(const upb_map *map) {
+  return _upb_map_size(map);
+}
+
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
+  return _upb_map_get(map, &key, map->key_size, val, map->val_size);
+}
+
+void upb_map_clear(upb_map *map) {
+  _upb_map_clear(map);
+}
+
+bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
+                 upb_arena *arena) {
+  return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena);
+}
+
+bool upb_map_delete(upb_map *map, upb_msgval key) {
+  return _upb_map_delete(map, &key, map->key_size);
+}
+
+bool upb_mapiter_next(const upb_map *map, size_t *iter) {
+  return _upb_map_next(map, iter);
+}
+
+bool upb_mapiter_done(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  UPB_ASSERT(iter != UPB_MAP_BEGIN);
+  i.t = &map->table;
+  i.index = iter;
+  return upb_strtable_done(&i);
+}
+
+/* Returns the key and value for this entry of the map. */
+upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  upb_msgval ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
+  return ret;
+}
+
+upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  upb_msgval ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
+  return ret;
+}
+
+/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
+
+/** upb/json_decode.c ************************************************************/
+
+#include <errno.h>
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Special header, must be included last. */
+
+typedef struct {
+  const char *ptr, *end;
+  upb_arena *arena;  /* TODO: should we have a tmp arena for tmp data? */
+  const upb_symtab *any_pool;
+  int depth;
+  upb_status *status;
+  jmp_buf err;
+  int line;
+  const char *line_begin;
+  bool is_first;
+  int options;
+  const upb_fielddef *debug_field;
+} jsondec;
+
+enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL };
+
+/* Forward declarations of mutually-recursive functions. */
+static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m);
+static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f);
+static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg,
+                                   const upb_msgdef *m);
+static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m);
+
+static bool jsondec_streql(upb_strview str, const char *lit) {
+  return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0;
+}
+
+static bool jsondec_isnullvalue(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_ENUM &&
+         strcmp(upb_enumdef_fullname(upb_fielddef_enumsubdef(f)),
+                "google.protobuf.NullValue") == 0;
+}
+
+static bool jsondec_isvalue(const upb_fielddef *f) {
+  return (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+          upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(f)) ==
+              UPB_WELLKNOWN_VALUE) ||
+         jsondec_isnullvalue(f);
+}
+
+UPB_NORETURN static void jsondec_err(jsondec *d, const char *msg) {
+  upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: %s", d->line,
+                     (int)(d->ptr - d->line_begin), msg);
+  UPB_LONGJMP(d->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsondec_errf(jsondec *d, const char *fmt, ...) {
+  va_list argp;
+  upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: ", d->line,
+                     (int)(d->ptr - d->line_begin));
+  va_start(argp, fmt);
+  upb_status_vappenderrf(d->status, fmt, argp);
+  va_end(argp);
+  UPB_LONGJMP(d->err, 1);
+}
+
+static void jsondec_skipws(jsondec *d) {
+  while (d->ptr != d->end) {
+    switch (*d->ptr) {
+      case '\n':
+        d->line++;
+        d->line_begin = d->ptr;
+        /* Fallthrough. */
+      case '\r':
+      case '\t':
+      case ' ':
+        d->ptr++;
+        break;
+      default:
+        return;
+    }
+  }
+  jsondec_err(d, "Unexpected EOF");
+}
+
+static bool jsondec_tryparsech(jsondec *d, char ch) {
+  if (d->ptr == d->end || *d->ptr != ch) return false;
+  d->ptr++;
+  return true;
+}
+
+static void jsondec_parselit(jsondec *d, const char *lit) {
+  size_t avail = d->end - d->ptr;
+  size_t len = strlen(lit);
+  if (avail < len || memcmp(d->ptr, lit, len) != 0) {
+    jsondec_errf(d, "Expected: '%s'", lit);
+  }
+  d->ptr += len;
+}
+
+static void jsondec_wsch(jsondec *d, char ch) {
+  jsondec_skipws(d);
+  if (!jsondec_tryparsech(d, ch)) {
+    jsondec_errf(d, "Expected: '%c'", ch);
+  }
+}
+
+static void jsondec_true(jsondec *d) { jsondec_parselit(d, "true"); }
+static void jsondec_false(jsondec *d) { jsondec_parselit(d, "false"); }
+static void jsondec_null(jsondec *d) { jsondec_parselit(d, "null"); }
+
+static void jsondec_entrysep(jsondec *d) {
+  jsondec_skipws(d);
+  jsondec_parselit(d, ":");
+}
+
+static int jsondec_rawpeek(jsondec *d) {
+  switch (*d->ptr) {
+    case '{':
+      return JD_OBJECT;
+    case '[':
+      return JD_ARRAY;
+    case '"':
+      return JD_STRING;
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      return JD_NUMBER;
+    case 't':
+      return JD_TRUE;
+    case 'f':
+      return JD_FALSE;
+    case 'n':
+      return JD_NULL;
+    default:
+      jsondec_errf(d, "Unexpected character: '%c'", *d->ptr);
+  }
+}
+
+/* JSON object/array **********************************************************/
+
+/* These are used like so:
+ *
+ * jsondec_objstart(d);
+ * while (jsondec_objnext(d)) {
+ *   ...
+ * }
+ * jsondec_objend(d) */
+
+static int jsondec_peek(jsondec *d) {
+  jsondec_skipws(d);
+  return jsondec_rawpeek(d);
+}
+
+static void jsondec_push(jsondec *d) {
+  if (--d->depth < 0) {
+    jsondec_err(d, "Recursion limit exceeded");
+  }
+  d->is_first = true;
+}
+
+static bool jsondec_seqnext(jsondec *d, char end_ch) {
+  bool is_first = d->is_first;
+  d->is_first = false;
+  jsondec_skipws(d);
+  if (*d->ptr == end_ch) return false;
+  if (!is_first) jsondec_parselit(d, ",");
+  return true;
+}
+
+static void jsondec_arrstart(jsondec *d) {
+  jsondec_push(d);
+  jsondec_wsch(d, '[');
+}
+
+static void jsondec_arrend(jsondec *d) {
+  d->depth++;
+  jsondec_wsch(d, ']');
+}
+
+static bool jsondec_arrnext(jsondec *d) {
+  return jsondec_seqnext(d, ']');
+}
+
+static void jsondec_objstart(jsondec *d) {
+  jsondec_push(d);
+  jsondec_wsch(d, '{');
+}
+
+static void jsondec_objend(jsondec *d) {
+  d->depth++;
+  jsondec_wsch(d, '}');
+}
+
+static bool jsondec_objnext(jsondec *d) {
+  if (!jsondec_seqnext(d, '}')) return false;
+  if (jsondec_peek(d) != JD_STRING) {
+    jsondec_err(d, "Object must start with string");
+  }
+  return true;
+}
+
+/* JSON number ****************************************************************/
+
+static bool jsondec_tryskipdigits(jsondec *d) {
+  const char *start = d->ptr;
+
+  while (d->ptr < d->end) {
+    if (*d->ptr < '0' || *d->ptr > '9') {
+      break;
+    }
+    d->ptr++;
+  }
+
+  return d->ptr != start;
+}
+
+static void jsondec_skipdigits(jsondec *d) {
+  if (!jsondec_tryskipdigits(d)) {
+    jsondec_err(d, "Expected one or more digits");
+  }
+}
+
+static double jsondec_number(jsondec *d) {
+  const char *start = d->ptr;
+
+  assert(jsondec_rawpeek(d) == JD_NUMBER);
+
+  /* Skip over the syntax of a number, as specified by JSON. */
+  if (*d->ptr == '-') d->ptr++;
+
+  if (jsondec_tryparsech(d, '0')) {
+    if (jsondec_tryskipdigits(d)) {
+      jsondec_err(d, "number cannot have leading zero");
+    }
+  } else {
+    jsondec_skipdigits(d);
+  }
+
+  if (d->ptr == d->end) goto parse;
+  if (jsondec_tryparsech(d, '.')) {
+    jsondec_skipdigits(d);
+  }
+  if (d->ptr == d->end) goto parse;
+
+  if (*d->ptr == 'e' || *d->ptr == 'E') {
+    d->ptr++;
+    if (d->ptr == d->end) {
+      jsondec_err(d, "Unexpected EOF in number");
+    }
+    if (*d->ptr == '+' || *d->ptr == '-') {
+      d->ptr++;
+    }
+    jsondec_skipdigits(d);
+  }
+
+parse:
+  /* Having verified the syntax of a JSON number, use strtod() to parse
+   * (strtod() accepts a superset of JSON syntax). */
+  errno = 0;
+  {
+    char* end;
+    double val = strtod(start, &end);
+    assert(end == d->ptr);
+
+    /* Currently the min/max-val conformance tests fail if we check this.  Does
+     * this mean the conformance tests are wrong or strtod() is wrong, or
+     * something else?  Investigate further. */
+    /*
+    if (errno == ERANGE) {
+      jsondec_err(d, "Number out of range");
+    }
+    */
+
+    if (val > DBL_MAX || val < -DBL_MAX) {
+      jsondec_err(d, "Number out of range");
+    }
+
+    return val;
+  }
+}
+
+/* JSON string ****************************************************************/
+
+static char jsondec_escape(jsondec *d) {
+  switch (*d->ptr++) {
+    case '"':
+      return '\"';
+    case '\\':
+      return '\\';
+    case '/':
+      return '/';
+    case 'b':
+      return '\b';
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    default:
+      jsondec_err(d, "Invalid escape char");
+  }
+}
+
+static uint32_t jsondec_codepoint(jsondec *d) {
+  uint32_t cp = 0;
+  const char *end;
+
+  if (d->end - d->ptr < 4) {
+    jsondec_err(d, "EOF inside string");
+  }
+
+  end = d->ptr + 4;
+  while (d->ptr < end) {
+    char ch = *d->ptr++;
+    if (ch >= '0' && ch <= '9') {
+      ch -= '0';
+    } else if (ch >= 'a' && ch <= 'f') {
+      ch = ch - 'a' + 10;
+    } else if (ch >= 'A' && ch <= 'F') {
+      ch = ch - 'A' + 10;
+    } else {
+      jsondec_err(d, "Invalid hex digit");
+    }
+    cp = (cp << 4) | ch;
+  }
+
+  return cp;
+}
+
+/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */
+static size_t jsondec_unicode(jsondec *d, char* out) {
+  uint32_t cp = jsondec_codepoint(d);
+  if (cp >= 0xd800 && cp <= 0xdbff) {
+    /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */
+    uint32_t high = cp;
+    uint32_t low;
+    jsondec_parselit(d, "\\u");
+    low = jsondec_codepoint(d);
+    if (low < 0xdc00 || low > 0xdfff) {
+      jsondec_err(d, "Invalid low surrogate");
+    }
+    cp = (high & 0x3ff) << 10;
+    cp |= (low & 0x3ff);
+    cp += 0x10000;
+  } else if (cp >= 0xdc00 && cp <= 0xdfff) {
+    jsondec_err(d, "Unpaired low surrogate");
+  }
+
+  /* Write to UTF-8 */
+  if (cp <= 0x7f) {
+    out[0] = cp;
+    return 1;
+  } else if (cp <= 0x07FF) {
+    out[0] = ((cp >> 6) & 0x1F) | 0xC0;
+    out[1] = ((cp >> 0) & 0x3F) | 0x80;
+    return 2;
+  } else if (cp <= 0xFFFF) {
+    out[0] = ((cp >> 12) & 0x0F) | 0xE0;
+    out[1] = ((cp >> 6) & 0x3F) | 0x80;
+    out[2] = ((cp >> 0) & 0x3F) | 0x80;
+    return 3;
+  } else if (cp < 0x10FFFF) {
+    out[0] = ((cp >> 18) & 0x07) | 0xF0;
+    out[1] = ((cp >> 12) & 0x3f) | 0x80;
+    out[2] = ((cp >> 6) & 0x3f) | 0x80;
+    out[3] = ((cp >> 0) & 0x3f) | 0x80;
+    return 4;
+  } else {
+    jsondec_err(d, "Invalid codepoint");
+  }
+}
+
+static void jsondec_resize(jsondec *d, char **buf, char **end, char **buf_end) {
+  size_t oldsize = *buf_end - *buf;
+  size_t len = *end - *buf;
+  size_t size = UPB_MAX(8, 2 * oldsize);
+
+  *buf = upb_arena_realloc(d->arena, *buf, len, size);
+  if (!*buf) jsondec_err(d, "Out of memory");
+
+  *end = *buf + len;
+  *buf_end = *buf + size;
+}
+
+static upb_strview jsondec_string(jsondec *d) {
+  char *buf = NULL;
+  char *end = NULL;
+  char *buf_end = NULL;
+
+  jsondec_skipws(d);
+
+  if (*d->ptr++ != '"') {
+    jsondec_err(d, "Expected string");
+  }
+
+  while (d->ptr < d->end) {
+    char ch = *d->ptr++;
+
+    if (end == buf_end) {
+      jsondec_resize(d, &buf, &end, &buf_end);
+    }
+
+    switch (ch) {
+      case '"': {
+        upb_strview ret;
+        ret.data = buf;
+        ret.size = end - buf;
+        *end = '\0';  /* Needed for possible strtod(). */
+        return ret;
+      }
+      case '\\':
+        if (d->ptr == d->end) goto eof;
+        if (*d->ptr == 'u') {
+          d->ptr++;
+          if (buf_end - end < 4) {
+            /* Allow space for maximum-sized code point (4 bytes). */
+            jsondec_resize(d, &buf, &end, &buf_end);
+          }
+          end += jsondec_unicode(d, end);
+        } else {
+          *end++ = jsondec_escape(d);
+        }
+        break;
+      default:
+        if ((unsigned char)*d->ptr < 0x20) {
+          jsondec_err(d, "Invalid char in JSON string");
+        }
+        *end++ = ch;
+        break;
+    }
+  }
+
+eof:
+  jsondec_err(d, "EOF inside string");
+}
+
+static void jsondec_skipval(jsondec *d) {
+  switch (jsondec_peek(d)) {
+    case JD_OBJECT:
+      jsondec_objstart(d);
+      while (jsondec_objnext(d)) {
+        jsondec_string(d);
+        jsondec_entrysep(d);
+        jsondec_skipval(d);
+      }
+      jsondec_objend(d);
+      break;
+    case JD_ARRAY:
+      jsondec_arrstart(d);
+      while (jsondec_arrnext(d)) {
+        jsondec_skipval(d);
+      }
+      jsondec_arrend(d);
+      break;
+    case JD_TRUE:
+      jsondec_true(d);
+      break;
+    case JD_FALSE:
+      jsondec_false(d);
+      break;
+    case JD_NULL:
+      jsondec_null(d);
+      break;
+    case JD_STRING:
+      jsondec_string(d);
+      break;
+    case JD_NUMBER:
+      jsondec_number(d);
+      break;
+  }
+}
+
+/* Base64 decoding for bytes fields. ******************************************/
+
+static unsigned int jsondec_base64_tablelookup(const char ch) {
+  /* Table includes the normal base64 chars plus the URL-safe variant. */
+  const signed char table[256] = {
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       62 /*+*/, -1,       62 /*-*/, -1,       63 /*/ */, 52 /*0*/,
+      53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/,  59 /*7*/,
+      60 /*8*/, 61 /*9*/, -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       0 /*A*/,  1 /*B*/,  2 /*C*/,  3 /*D*/,   4 /*E*/,
+      5 /*F*/,  6 /*G*/,  07 /*H*/, 8 /*I*/,  9 /*J*/,  10 /*K*/,  11 /*L*/,
+      12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/,  18 /*S*/,
+      19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/,  25 /*Z*/,
+      -1,       -1,       -1,       -1,       63 /*_*/, -1,        26 /*a*/,
+      27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/,  33 /*h*/,
+      34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/,  40 /*o*/,
+      41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/,  47 /*v*/,
+      48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1};
+
+  /* Sign-extend return value so high bit will be set on any unexpected char. */
+  return table[(unsigned)ch];
+}
+
+static char *jsondec_partialbase64(jsondec *d, const char *ptr, const char *end,
+                                   char *out) {
+  int32_t val = -1;
+
+  switch (end - ptr) {
+    case 2:
+      val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+            jsondec_base64_tablelookup(ptr[1]) << 12;
+      out[0] = val >> 16;
+      out += 1;
+      break;
+    case 3:
+      val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+            jsondec_base64_tablelookup(ptr[1]) << 12 |
+            jsondec_base64_tablelookup(ptr[2]) << 6;
+      out[0] = val >> 16;
+      out[1] = (val >> 8) & 0xff;
+      out += 2;
+      break;
+  }
+
+  if (val < 0) {
+    jsondec_err(d, "Corrupt base64");
+  }
+
+  return out;
+}
+
+static size_t jsondec_base64(jsondec *d, upb_strview str) {
+  /* We decode in place. This is safe because this is a new buffer (not
+   * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */
+  char *out = (char*)str.data;
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  const char *end4 = ptr + (str.size & -4);  /* Round down to multiple of 4. */
+
+  for (; ptr < end4; ptr += 4, out += 3) {
+    int val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+              jsondec_base64_tablelookup(ptr[1]) << 12 |
+              jsondec_base64_tablelookup(ptr[2]) << 6 |
+              jsondec_base64_tablelookup(ptr[3]) << 0;
+
+    if (val < 0) {
+      /* Junk chars or padding. Remove trailing padding, if any. */
+      if (end - ptr == 4 && ptr[3] == '=') {
+        if (ptr[2] == '=') {
+          end -= 2;
+        } else {
+          end -= 1;
+        }
+      }
+      break;
+    }
+
+    out[0] = val >> 16;
+    out[1] = (val >> 8) & 0xff;
+    out[2] = val & 0xff;
+  }
+
+  if (ptr < end) {
+    /* Process remaining chars. We do not require padding. */
+    out = jsondec_partialbase64(d, ptr, end, out);
+  }
+
+  return out - str.data;
+}
+
+/* Low-level integer parsing **************************************************/
+
+/* We use these hand-written routines instead of strto[u]l() because the "long
+ * long" variants aren't in c89. Also our version allows setting a ptr limit. */
+
+static const char *jsondec_buftouint64(jsondec *d, const char *ptr,
+                                       const char *end, uint64_t *val) {
+  uint64_t u64 = 0;
+  while (ptr < end) {
+    unsigned ch = *ptr - '0';
+    if (ch >= 10) break;
+    if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) {
+      jsondec_err(d, "Integer overflow");
+    }
+    u64 *= 10;
+    u64 += ch;
+    ptr++;
+  }
+
+  *val = u64;
+  return ptr;
+}
+
+static const char *jsondec_buftoint64(jsondec *d, const char *ptr,
+                                      const char *end, int64_t *val) {
+  bool neg = false;
+  uint64_t u64;
+
+  if (ptr != end && *ptr == '-') {
+    ptr++;
+    neg = true;
+  }
+
+  ptr = jsondec_buftouint64(d, ptr, end, &u64);
+  if (u64 > (uint64_t)INT64_MAX + neg) {
+    jsondec_err(d, "Integer overflow");
+  }
+
+  *val = neg ? -u64 : u64;
+  return ptr;
+}
+
+static uint64_t jsondec_strtouint64(jsondec *d, upb_strview str) {
+  const char *end = str.data + str.size;
+  uint64_t ret;
+  if (jsondec_buftouint64(d, str.data, end, &ret) != end) {
+    jsondec_err(d, "Non-number characters in quoted integer");
+  }
+  return ret;
+}
+
+static int64_t jsondec_strtoint64(jsondec *d, upb_strview str) {
+  const char *end = str.data + str.size;
+  int64_t ret;
+  if (jsondec_buftoint64(d, str.data, end, &ret) != end) {
+    jsondec_err(d, "Non-number characters in quoted integer");
+  }
+  return ret;
+}
+
+/* Primitive value types ******************************************************/
+
+/* Parse INT32 or INT64 value. */
+static upb_msgval jsondec_int(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val;
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER: {
+      double dbl = jsondec_number(d);
+      if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) {
+        jsondec_err(d, "JSON number is out of range.");
+      }
+      val.int64_val = dbl;  /* must be guarded, overflow here is UB */
+      if (val.int64_val != dbl) {
+        jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl,
+                     val.int64_val);
+      }
+      break;
+    }
+    case JD_STRING: {
+      upb_strview str = jsondec_string(d);
+      val.int64_val = jsondec_strtoint64(d, str);
+      break;
+    }
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_INT32) {
+    if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) {
+      jsondec_err(d, "Integer out of range.");
+    }
+    val.int32_val = (int32_t)val.int64_val;
+  }
+
+  return val;
+}
+
+/* Parse UINT32 or UINT64 value. */
+static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val = {0};
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER: {
+      double dbl = jsondec_number(d);
+      if (dbl > 18446744073709549568.0 || dbl < 0) {
+        jsondec_err(d, "JSON number is out of range.");
+      }
+      val.uint64_val = dbl;  /* must be guarded, overflow here is UB */
+      if (val.uint64_val != dbl) {
+        jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl,
+                     val.uint64_val);
+      }
+      break;
+    }
+    case JD_STRING: {
+      upb_strview str = jsondec_string(d);
+      val.uint64_val = jsondec_strtouint64(d, str);
+      break;
+    }
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_UINT32) {
+    if (val.uint64_val > UINT32_MAX) {
+      jsondec_err(d, "Integer out of range.");
+    }
+    val.uint32_val = (uint32_t)val.uint64_val;
+  }
+
+  return val;
+}
+
+/* Parse DOUBLE or FLOAT value. */
+static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) {
+  upb_strview str;
+  upb_msgval val = {0};
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER:
+      val.double_val = jsondec_number(d);
+      break;
+    case JD_STRING:
+      str = jsondec_string(d);
+      if (jsondec_streql(str, "NaN")) {
+        val.double_val = NAN;
+      } else if (jsondec_streql(str, "Infinity")) {
+        val.double_val = INFINITY;
+      } else if (jsondec_streql(str, "-Infinity")) {
+        val.double_val = -INFINITY;
+      } else {
+        val.double_val = strtod(str.data, NULL);
+      }
+      break;
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_FLOAT) {
+    if (val.double_val != INFINITY && val.double_val != -INFINITY &&
+        (val.double_val > FLT_MAX || val.double_val < -FLT_MAX)) {
+      jsondec_err(d, "Float out of range");
+    }
+    val.float_val = val.double_val;
+  }
+
+  return val;
+}
+
+/* Parse STRING or BYTES value. */
+static upb_msgval jsondec_strfield(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val;
+  val.str_val = jsondec_string(d);
+  if (upb_fielddef_type(f) == UPB_TYPE_BYTES) {
+    val.str_val.size = jsondec_base64(d, val.str_val);
+  }
+  return val;
+}
+
+static upb_msgval jsondec_enum(jsondec *d, const upb_fielddef *f) {
+  switch (jsondec_peek(d)) {
+    case JD_STRING: {
+      const upb_enumdef *e = upb_fielddef_enumsubdef(f);
+      upb_strview str = jsondec_string(d);
+      upb_msgval val;
+      if (!upb_enumdef_ntoi(e, str.data, str.size, &val.int32_val)) {
+        if (d->options & UPB_JSONDEC_IGNOREUNKNOWN) {
+          val.int32_val = 0;
+        } else {
+          jsondec_errf(d, "Unknown enumerator: '" UPB_STRVIEW_FORMAT "'",
+                       UPB_STRVIEW_ARGS(str));
+        }
+      }
+      return val;
+    }
+    case JD_NULL: {
+      if (jsondec_isnullvalue(f)) {
+        upb_msgval val;
+        jsondec_null(d);
+        val.int32_val = 0;
+        return val;
+      }
+    }
+      /* Fallthrough. */
+    default:
+      return jsondec_int(d, f);
+  }
+}
+
+static upb_msgval jsondec_bool(jsondec *d, const upb_fielddef *f) {
+  bool is_map_key = upb_fielddef_number(f) == 1 &&
+                    upb_msgdef_mapentry(upb_fielddef_containingtype(f));
+  upb_msgval val;
+
+  if (is_map_key) {
+    upb_strview str = jsondec_string(d);
+    if (jsondec_streql(str, "true")) {
+      val.bool_val = true;
+    } else if (jsondec_streql(str, "false")) {
+      val.bool_val = false;
+    } else {
+      jsondec_err(d, "Invalid boolean map key");
+    }
+  } else {
+    switch (jsondec_peek(d)) {
+      case JD_TRUE:
+        val.bool_val = true;
+        jsondec_true(d);
+        break;
+      case JD_FALSE:
+        val.bool_val = false;
+        jsondec_false(d);
+        break;
+      default:
+        jsondec_err(d, "Expected true or false");
+    }
+  }
+
+  return val;
+}
+
+/* Composite types (array/message/map) ****************************************/
+
+static void jsondec_array(jsondec *d, upb_msg *msg, const upb_fielddef *f) {
+  upb_array *arr = upb_msg_mutable(msg, f, d->arena).array;
+
+  jsondec_arrstart(d);
+  while (jsondec_arrnext(d)) {
+    upb_msgval elem = jsondec_value(d, f);
+    upb_array_append(arr, elem, d->arena);
+  }
+  jsondec_arrend(d);
+}
+
+static void jsondec_map(jsondec *d, upb_msg *msg, const upb_fielddef *f) {
+  upb_map *map = upb_msg_mutable(msg, f, d->arena).map;
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+  const upb_fielddef *key_f = upb_msgdef_itof(entry, 1);
+  const upb_fielddef *val_f = upb_msgdef_itof(entry, 2);
+
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    upb_msgval key, val;
+    key = jsondec_value(d, key_f);
+    jsondec_entrysep(d);
+    val = jsondec_value(d, val_f);
+    upb_map_set(map, key, val, d->arena);
+  }
+  jsondec_objend(d);
+}
+
+static void jsondec_tomsg(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    jsondec_object(d, msg, m);
+  } else {
+    jsondec_wellknown(d, msg, m);
+  }
+}
+
+static upb_msgval jsondec_msg(jsondec *d, const upb_fielddef *f) {
+  const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+  upb_msg *msg = upb_msg_new(m, d->arena);
+  upb_msgval val;
+
+  jsondec_tomsg(d, msg, m);
+  val.msg_val = msg;
+  return val;
+}
+
+static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_strview name;
+  const upb_fielddef *f;
+  const upb_fielddef *preserved;
+
+  name = jsondec_string(d);
+  jsondec_entrysep(d);
+  f = upb_msgdef_lookupjsonname(m, name.data, name.size);
+
+  if (!f) {
+    if ((d->options & UPB_JSONDEC_IGNOREUNKNOWN) == 0) {
+      jsondec_errf(d, "No such field: " UPB_STRVIEW_FORMAT,
+                   UPB_STRVIEW_ARGS(name));
+    }
+    jsondec_skipval(d);
+    return;
+  }
+
+  if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) {
+    /* JSON "null" indicates a default value, so no need to set anything. */
+    jsondec_null(d);
+    return;
+  }
+
+  if (upb_fielddef_realcontainingoneof(f) &&
+      upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) {
+    jsondec_err(d, "More than one field for this oneof.");
+  }
+
+  preserved = d->debug_field;
+  d->debug_field = f;
+
+  if (upb_fielddef_ismap(f)) {
+    jsondec_map(d, msg, f);
+  } else if (upb_fielddef_isseq(f)) {
+    jsondec_array(d, msg, f);
+  } else if (upb_fielddef_issubmsg(f)) {
+    upb_msg *submsg = upb_msg_mutable(msg, f, d->arena).msg;
+    const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+    jsondec_tomsg(d, submsg, subm);
+  } else {
+    upb_msgval val = jsondec_value(d, f);
+    upb_msg_set(msg, f, val, d->arena);
+  }
+
+  d->debug_field = preserved;
+}
+
+static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    jsondec_field(d, msg, m);
+  }
+  jsondec_objend(d);
+}
+
+static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      return jsondec_bool(d, f);
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_DOUBLE:
+      return jsondec_double(d, f);
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      return jsondec_uint(d, f);
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+      return jsondec_int(d, f);
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return jsondec_strfield(d, f);
+    case UPB_TYPE_ENUM:
+      return jsondec_enum(d, f);
+    case UPB_TYPE_MESSAGE:
+      return jsondec_msg(d, f);
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+/* Well-known types ***********************************************************/
+
+static int jsondec_tsdigits(jsondec *d, const char **ptr, size_t digits,
+                            const char *after) {
+  uint64_t val;
+  const char *p = *ptr;
+  const char *end = p + digits;
+  size_t after_len = after ? strlen(after) : 0;
+
+  UPB_ASSERT(digits <= 9);  /* int can't overflow. */
+
+  if (jsondec_buftouint64(d, p, end, &val) != end ||
+      (after_len && memcmp(end, after, after_len) != 0)) {
+    jsondec_err(d, "Malformed timestamp");
+  }
+
+  UPB_ASSERT(val < INT_MAX);
+
+  *ptr = end + after_len;
+  return (int)val;
+}
+
+static int jsondec_nanos(jsondec *d, const char **ptr, const char *end) {
+  uint64_t nanos = 0;
+  const char *p = *ptr;
+
+  if (p != end && *p == '.') {
+    const char *nano_end = jsondec_buftouint64(d, p + 1, end, &nanos);
+    int digits = (int)(nano_end - p - 1);
+    int exp_lg10 = 9 - digits;
+    if (digits > 9) {
+      jsondec_err(d, "Too many digits for partial seconds");
+    }
+    while (exp_lg10--) nanos *= 10;
+    *ptr = nano_end;
+  }
+
+  UPB_ASSERT(nanos < INT_MAX);
+
+  return (int)nanos;
+}
+
+/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */
+int jsondec_epochdays(int y, int m, int d) {
+  const uint32_t year_base = 4800;    /* Before min year, multiple of 400. */
+  const uint32_t m_adj = m - 3;       /* March-based month. */
+  const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0;
+  const uint32_t adjust = carry ? 12 : 0;
+  const uint32_t y_adj = y + year_base - carry;
+  const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048;
+  const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400;
+  return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632;
+}
+
+static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) {
+  return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s;
+}
+
+static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_msgval seconds;
+  upb_msgval nanos;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+
+  if (str.size < 20) goto malformed;
+
+  {
+    /* 1972-01-01T01:00:00 */
+    int year = jsondec_tsdigits(d, &ptr, 4, "-");
+    int mon = jsondec_tsdigits(d, &ptr, 2, "-");
+    int day = jsondec_tsdigits(d, &ptr, 2, "T");
+    int hour = jsondec_tsdigits(d, &ptr, 2, ":");
+    int min = jsondec_tsdigits(d, &ptr, 2, ":");
+    int sec = jsondec_tsdigits(d, &ptr, 2, NULL);
+
+    seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec);
+  }
+
+  nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+  {
+    /* [+-]08:00 or Z */
+    int ofs_hour = 0;
+    int ofs_min = 0;
+    bool neg = false;
+
+    if (ptr == end) goto malformed;
+
+    switch (*ptr++) {
+      case '-':
+        neg = true;
+        /* fallthrough */
+      case '+':
+        if ((end - ptr) != 5) goto malformed;
+        ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":");
+        ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL);
+        ofs_min = ((ofs_hour * 60) + ofs_min) * 60;
+        seconds.int64_val += (neg ? ofs_min : -ofs_min);
+        break;
+      case 'Z':
+        if (ptr != end) goto malformed;
+        break;
+      default:
+        goto malformed;
+    }
+  }
+
+  if (seconds.int64_val < -62135596800) {
+    jsondec_err(d, "Timestamp out of range");
+  }
+
+  upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena);
+  upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena);
+  return;
+
+malformed:
+  jsondec_err(d, "Malformed timestamp");
+}
+
+static void jsondec_duration(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_msgval seconds;
+  upb_msgval nanos;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  const int64_t max = (uint64_t)3652500 * 86400;
+
+  /* "3.000000001s", "3s", etc. */
+  ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val);
+  nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+  if (end - ptr != 1 || *ptr != 's') {
+    jsondec_err(d, "Malformed duration");
+  }
+
+  if (seconds.int64_val < -max || seconds.int64_val > max) {
+    jsondec_err(d, "Duration out of range");
+  }
+
+  if (seconds.int64_val < 0) {
+    nanos.int32_val = - nanos.int32_val;
+  }
+
+  upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena);
+  upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena);
+}
+
+static void jsondec_listvalue(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *values_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *value_m = upb_fielddef_msgsubdef(values_f);
+  upb_array *values = upb_msg_mutable(msg, values_f, d->arena).array;
+
+  jsondec_arrstart(d);
+  while (jsondec_arrnext(d)) {
+    upb_msg *value_msg = upb_msg_new(value_m, d->arena);
+    upb_msgval value;
+    value.msg_val = value_msg;
+    upb_array_append(values, value, d->arena);
+    jsondec_wellknownvalue(d, value_msg, value_m);
+  }
+  jsondec_arrend(d);
+}
+
+static void jsondec_struct(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *fields_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f);
+  const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2);
+  const upb_msgdef *value_m = upb_fielddef_msgsubdef(value_f);
+  upb_map *fields = upb_msg_mutable(msg, fields_f, d->arena).map;
+
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    upb_msgval key, value;
+    upb_msg *value_msg = upb_msg_new(value_m, d->arena);
+    key.str_val = jsondec_string(d);
+    value.msg_val = value_msg;
+    upb_map_set(fields, key, value, d->arena);
+    jsondec_entrysep(d);
+    jsondec_wellknownvalue(d, value_msg, value_m);
+  }
+  jsondec_objend(d);
+}
+
+static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg,
+                                   const upb_msgdef *m) {
+  upb_msgval val;
+  const upb_fielddef *f;
+  upb_msg *submsg;
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER:
+      /* double number_value = 2; */
+      f = upb_msgdef_itof(m, 2);
+      val.double_val = jsondec_number(d);
+      break;
+    case JD_STRING:
+      /* string string_value = 3; */
+      f = upb_msgdef_itof(m, 3);
+      val.str_val = jsondec_string(d);
+      break;
+    case JD_FALSE:
+      /* bool bool_value = 4; */
+      f = upb_msgdef_itof(m, 4);
+      val.bool_val = false;
+      jsondec_false(d);
+      break;
+    case JD_TRUE:
+      /* bool bool_value = 4; */
+      f = upb_msgdef_itof(m, 4);
+      val.bool_val = true;
+      jsondec_true(d);
+      break;
+    case JD_NULL:
+      /* NullValue null_value = 1; */
+      f = upb_msgdef_itof(m, 1);
+      val.int32_val = 0;
+      jsondec_null(d);
+      break;
+    /* Note: these cases return, because upb_msg_mutable() is enough. */
+    case JD_OBJECT:
+      /* Struct struct_value = 5; */
+      f = upb_msgdef_itof(m, 5);
+      submsg = upb_msg_mutable(msg, f, d->arena).msg;
+      jsondec_struct(d, submsg, upb_fielddef_msgsubdef(f));
+      return;
+    case JD_ARRAY:
+      /* ListValue list_value = 6; */
+      f = upb_msgdef_itof(m, 6);
+      submsg = upb_msg_mutable(msg, f, d->arena).msg;
+      jsondec_listvalue(d, submsg, upb_fielddef_msgsubdef(f));
+      return;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  upb_msg_set(msg, f, val, d->arena);
+}
+
+static upb_strview jsondec_mask(jsondec *d, const char *buf, const char *end) {
+  /* FieldMask fields grow due to inserted '_' characters, so we can't do the
+   * transform in place. */
+  const char *ptr = buf;
+  upb_strview ret;
+  char *out;
+
+  ret.size = end - ptr;
+  while (ptr < end) {
+    ret.size += (*ptr >= 'A' && *ptr <= 'Z');
+    ptr++;
+  }
+
+  out = upb_arena_malloc(d->arena, ret.size);
+  ptr = buf;
+  ret.data = out;
+
+  while (ptr < end) {
+    char ch = *ptr++;
+    if (ch >= 'A' && ch <= 'Z') {
+      *out++ = '_';
+      *out++ = ch + 32;
+    } else if (ch == '_') {
+      jsondec_err(d, "field mask may not contain '_'");
+    } else {
+      *out++ = ch;
+    }
+  }
+
+  return ret;
+}
+
+static void jsondec_fieldmask(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  /* repeated string paths = 1; */
+  const upb_fielddef *paths_f = upb_msgdef_itof(m, 1);
+  upb_array *arr = upb_msg_mutable(msg, paths_f, d->arena).array;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  upb_msgval val;
+
+  while (ptr < end) {
+    const char *elem_end = memchr(ptr, ',', end - ptr);
+    if (elem_end) {
+      val.str_val = jsondec_mask(d, ptr, elem_end);
+      ptr = elem_end + 1;
+    } else {
+      val.str_val = jsondec_mask(d, ptr, end);
+      ptr = end;
+    }
+    upb_array_append(arr, val, d->arena);
+  }
+}
+
+static void jsondec_anyfield(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    /* For regular types: {"@type": "[user type]", "f1": <V1>, "f2": <V2>}
+     * where f1, f2, etc. are the normal fields of this type. */
+    jsondec_field(d, msg, m);
+  } else {
+    /* For well-known types: {"@type": "[well-known type]", "value": <X>}
+     * where <X> is whatever encoding the WKT normally uses. */
+    upb_strview str = jsondec_string(d);
+    jsondec_entrysep(d);
+    if (!jsondec_streql(str, "value")) {
+      jsondec_err(d, "Key for well-known type must be 'value'");
+    }
+    jsondec_wellknown(d, msg, m);
+  }
+}
+
+static const upb_msgdef *jsondec_typeurl(jsondec *d, upb_msg *msg,
+                                         const upb_msgdef *m) {
+  const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *type_m;
+  upb_strview type_url = jsondec_string(d);
+  const char *end = type_url.data + type_url.size;
+  const char *ptr = end;
+  upb_msgval val;
+
+  val.str_val = type_url;
+  upb_msg_set(msg, type_url_f, val, d->arena);
+
+  /* Find message name after the last '/' */
+  while (ptr > type_url.data && *--ptr != '/') {}
+
+  if (ptr == type_url.data || ptr == end) {
+    jsondec_err(d, "Type url must have at least one '/' and non-empty host");
+  }
+
+  ptr++;
+  type_m = upb_symtab_lookupmsg2(d->any_pool, ptr, end - ptr);
+
+  if (!type_m) {
+    jsondec_err(d, "Type was not found");
+  }
+
+  return type_m;
+}
+
+static void jsondec_any(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  /* string type_url = 1;
+   * bytes value = 2; */
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 2);
+  upb_msg *any_msg;
+  const upb_msgdef *any_m = NULL;
+  const char *pre_type_data = NULL;
+  const char *pre_type_end = NULL;
+  upb_msgval encoded;
+
+  jsondec_objstart(d);
+
+  /* Scan looking for "@type", which is not necessarily first. */
+  while (!any_m && jsondec_objnext(d)) {
+    const char *start = d->ptr;
+    upb_strview name = jsondec_string(d);
+    jsondec_entrysep(d);
+    if (jsondec_streql(name, "@type")) {
+      any_m = jsondec_typeurl(d, msg, m);
+      if (pre_type_data) {
+        pre_type_end = start;
+        while (*pre_type_end != ',') pre_type_end--;
+      }
+    } else {
+      if (!pre_type_data) pre_type_data = start;
+      jsondec_skipval(d);
+    }
+  }
+
+  if (!any_m) {
+    jsondec_err(d, "Any object didn't contain a '@type' field");
+  }
+
+  any_msg = upb_msg_new(any_m, d->arena);
+
+  if (pre_type_data) {
+    size_t len = pre_type_end - pre_type_data + 1;
+    char *tmp = upb_arena_malloc(d->arena, len);
+    const char *saved_ptr = d->ptr;
+    const char *saved_end = d->end;
+    memcpy(tmp, pre_type_data, len - 1);
+    tmp[len - 1] = '}';
+    d->ptr = tmp;
+    d->end = tmp + len;
+    d->is_first = true;
+    while (jsondec_objnext(d)) {
+      jsondec_anyfield(d, any_msg, any_m);
+    }
+    d->ptr = saved_ptr;
+    d->end = saved_end;
+  }
+
+  while (jsondec_objnext(d)) {
+    jsondec_anyfield(d, any_msg, any_m);
+  }
+
+  jsondec_objend(d);
+
+  encoded.str_val.data = upb_encode(any_msg, upb_msgdef_layout(any_m), d->arena,
+                                    &encoded.str_val.size);
+  upb_msg_set(msg, value_f, encoded, d->arena);
+}
+
+static void jsondec_wrapper(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 1);
+  upb_msgval val = jsondec_value(d, value_f);
+  upb_msg_set(msg, value_f, val, d->arena);
+}
+
+static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  switch (upb_msgdef_wellknowntype(m)) {
+    case UPB_WELLKNOWN_ANY:
+      jsondec_any(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_FIELDMASK:
+      jsondec_fieldmask(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_DURATION:
+      jsondec_duration(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_TIMESTAMP:
+      jsondec_timestamp(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_VALUE:
+      jsondec_wellknownvalue(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_LISTVALUE:
+      jsondec_listvalue(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_STRUCT:
+      jsondec_struct(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_DOUBLEVALUE:
+    case UPB_WELLKNOWN_FLOATVALUE:
+    case UPB_WELLKNOWN_INT64VALUE:
+    case UPB_WELLKNOWN_UINT64VALUE:
+    case UPB_WELLKNOWN_INT32VALUE:
+    case UPB_WELLKNOWN_UINT32VALUE:
+    case UPB_WELLKNOWN_STRINGVALUE:
+    case UPB_WELLKNOWN_BYTESVALUE:
+    case UPB_WELLKNOWN_BOOLVALUE:
+      jsondec_wrapper(d, msg, m);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
+                     const upb_msgdef *m, const upb_symtab *any_pool,
+                     int options, upb_arena *arena, upb_status *status) {
+  jsondec d;
+
+  if (size == 0) return true;
+
+  d.ptr = buf;
+  d.end = buf + size;
+  d.arena = arena;
+  d.any_pool = any_pool;
+  d.status = status;
+  d.options = options;
+  d.depth = 64;
+  d.line = 1;
+  d.line_begin = d.ptr;
+  d.debug_field = NULL;
+  d.is_first = false;
+
+  if (UPB_SETJMP(d.err)) return false;
+
+  jsondec_tomsg(&d, msg, m);
+  return true;
+}
+
+/** upb/json_encode.c ************************************************************/
+
+#include <ctype.h>
+#include <float.h>
+#include <inttypes.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+typedef struct {
+  char *buf, *ptr, *end;
+  size_t overflow;
+  int indent_depth;
+  int options;
+  const upb_symtab *ext_pool;
+  jmp_buf err;
+  upb_status *status;
+  upb_arena *arena;
+} jsonenc;
+
+static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
+static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f);
+static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg,
+                             const upb_msgdef *m);
+static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m, bool first);
+static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
+
+UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) {
+  upb_status_seterrmsg(e->status, msg);
+  longjmp(e->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsonenc_errf(jsonenc *e, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_status_vseterrf(e->status, fmt, argp);
+  va_end(argp);
+  longjmp(e->err, 1);
+}
+
+static upb_arena *jsonenc_arena(jsonenc *e) {
+  /* Create lazily, since it's only needed for Any */
+  if (!e->arena) {
+    e->arena = upb_arena_new();
+  }
+  return e->arena;
+}
+
+static void jsonenc_putbytes(jsonenc *e, const void *data, size_t len) {
+  size_t have = e->end - e->ptr;
+  if (UPB_LIKELY(have >= len)) {
+    memcpy(e->ptr, data, len);
+    e->ptr += len;
+  } else {
+    if (have) {
+      memcpy(e->ptr, data, have);
+      e->ptr += have;
+    }
+    e->overflow += (len - have);
+  }
+}
+
+static void jsonenc_putstr(jsonenc *e, const char *str) {
+  jsonenc_putbytes(e, str, strlen(str));
+}
+
+UPB_PRINTF(2, 3)
+static void jsonenc_printf(jsonenc *e, const char *fmt, ...) {
+  size_t n;
+  size_t have = e->end - e->ptr;
+  va_list args;
+
+  va_start(args, fmt);
+  n = vsnprintf(e->ptr, have, fmt, args);
+  va_end(args);
+
+  if (UPB_LIKELY(have > n)) {
+    e->ptr += n;
+  } else {
+    e->ptr = UPB_PTRADD(e->ptr, have);
+    e->overflow += (n - have);
+  }
+}
+
+static void jsonenc_nanos(jsonenc *e, int32_t nanos) {
+  int digits = 9;
+
+  if (nanos == 0) return;
+  if (nanos < 0 || nanos >= 1000000000) {
+    jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos");
+  }
+
+  while (nanos % 1000 == 0) {
+    nanos /= 1000;
+    digits -= 3;
+  }
+
+  jsonenc_printf(e, ".%.*" PRId32, digits, nanos);
+}
+
+static void jsonenc_timestamp(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2);
+  int64_t seconds = upb_msg_get(msg, seconds_f).int64_val;
+  int32_t nanos = upb_msg_get(msg, nanos_f).int32_val;
+  int L, N, I, J, K, hour, min, sec;
+
+  if (seconds < -62135596800) {
+    jsonenc_err(e,
+                "error formatting timestamp as JSON: minimum acceptable value "
+                "is 0001-01-01T00:00:00Z");
+  } else if (seconds > 253402300799) {
+    jsonenc_err(e,
+                "error formatting timestamp as JSON: maximum acceptable value "
+                "is 9999-12-31T23:59:59Z");
+  }
+
+  /* Julian Day -> Y/M/D, Algorithm from:
+   * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
+   *   Processing Calendar Dates," Communications of the Association of
+   *   Computing Machines, vol. 11 (1968), p. 657.  */
+  L = (int)(seconds / 86400) + 68569 + 2440588;
+  N = 4 * L / 146097;
+  L = L - (146097 * N + 3) / 4;
+  I = 4000 * (L + 1) / 1461001;
+  L = L - 1461 * I / 4 + 31;
+  J = 80 * L / 2447;
+  K = L - 2447 * J / 80;
+  L = J / 11;
+  J = J + 2 - 12 * L;
+  I = 100 * (N - 49) + I + L;
+
+  sec = seconds % 60;
+  min = (seconds / 60) % 60;
+  hour = (seconds / 3600) % 24;
+
+  jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec);
+  jsonenc_nanos(e, nanos);
+  jsonenc_putstr(e, "Z\"");
+}
+
+static void jsonenc_duration(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2);
+  int64_t seconds = upb_msg_get(msg, seconds_f).int64_val;
+  int32_t nanos = upb_msg_get(msg, nanos_f).int32_val;
+
+  if (seconds > 315576000000 || seconds < -315576000000 ||
+      (seconds < 0) != (nanos < 0)) {
+    jsonenc_err(e, "bad duration");
+  }
+
+  if (nanos < 0) {
+    nanos = -nanos;
+  }
+
+  jsonenc_printf(e, "\"%" PRId64, seconds);
+  jsonenc_nanos(e, nanos);
+  jsonenc_putstr(e, "s\"");
+}
+
+static void jsonenc_enum(int32_t val, const upb_fielddef *f, jsonenc *e) {
+  const upb_enumdef *e_def = upb_fielddef_enumsubdef(f);
+
+  if (strcmp(upb_enumdef_fullname(e_def), "google.protobuf.NullValue") == 0) {
+    jsonenc_putstr(e, "null");
+  } else {
+    const char *name = upb_enumdef_iton(e_def, val);
+
+    if (name) {
+      jsonenc_printf(e, "\"%s\"", name);
+    } else {
+      jsonenc_printf(e, "%" PRId32, val);
+    }
+  }
+}
+
+static void jsonenc_bytes(jsonenc *e, upb_strview str) {
+  /* This is the regular base64, not the "web-safe" version. */
+  static const char base64[] =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  const unsigned char *ptr = (unsigned char*)str.data;
+  const unsigned char *end = UPB_PTRADD(ptr, str.size);
+  char buf[4];
+
+  jsonenc_putstr(e, "\"");
+
+  while (end - ptr >= 3) {
+    buf[0] = base64[ptr[0] >> 2];
+    buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+    buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)];
+    buf[3] = base64[ptr[2] & 0x3f];
+    jsonenc_putbytes(e, buf, 4);
+    ptr += 3;
+  }
+
+  switch (end - ptr) {
+    case 2:
+      buf[0] = base64[ptr[0] >> 2];
+      buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+      buf[2] = base64[(ptr[1] & 0xf) << 2];
+      buf[3] = '=';
+      jsonenc_putbytes(e, buf, 4);
+      break;
+    case 1:
+      buf[0] = base64[ptr[0] >> 2];
+      buf[1] = base64[((ptr[0] & 0x3) << 4)];
+      buf[2] = '=';
+      buf[3] = '=';
+      jsonenc_putbytes(e, buf, 4);
+      break;
+  }
+
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_stringbody(jsonenc *e, upb_strview str) {
+  const char *ptr = str.data;
+  const char *end = UPB_PTRADD(ptr, str.size);
+
+  while (ptr < end) {
+    switch (*ptr) {
+      case '\n':
+        jsonenc_putstr(e, "\\n");
+        break;
+      case '\r':
+        jsonenc_putstr(e, "\\r");
+        break;
+      case '\t':
+        jsonenc_putstr(e, "\\t");
+        break;
+      case '\"':
+        jsonenc_putstr(e, "\\\"");
+        break;
+      case '\f':
+        jsonenc_putstr(e, "\\f");
+        break;
+      case '\b':
+        jsonenc_putstr(e, "\\b");
+        break;
+      case '\\':
+        jsonenc_putstr(e, "\\\\");
+        break;
+      default:
+        if ((uint8_t)*ptr < 0x20) {
+          jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr);
+        } else {
+          /* This could be a non-ASCII byte.  We rely on the string being valid
+           * UTF-8. */
+          jsonenc_putbytes(e, ptr, 1);
+        }
+        break;
+    }
+    ptr++;
+  }
+}
+
+static void jsonenc_string(jsonenc *e, upb_strview str) {
+  jsonenc_putstr(e, "\"");
+  jsonenc_stringbody(e, str);
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_double(jsonenc *e, const char *fmt, double val) {
+  if (val == INFINITY) {
+    jsonenc_putstr(e, "\"Infinity\"");
+  } else if (val == -INFINITY) {
+    jsonenc_putstr(e, "\"-Infinity\"");
+  } else if (val != val) {
+    jsonenc_putstr(e, "\"NaN\"");
+  } else {
+    jsonenc_printf(e, fmt, val);
+  }
+}
+
+static void jsonenc_wrapper(jsonenc *e, const upb_msg *msg,
+                            const upb_msgdef *m) {
+  const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
+  upb_msgval val = upb_msg_get(msg, val_f);
+  jsonenc_scalar(e, val, val_f);
+}
+
+static const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) {
+  /* Find last '/', if any. */
+  const char *end = type_url.data + type_url.size;
+  const char *ptr = end;
+  const upb_msgdef *ret;
+
+  if (!e->ext_pool) {
+    jsonenc_err(e, "Tried to encode Any, but no symtab was provided");
+  }
+
+  if (type_url.size == 0) goto badurl;
+
+  while (true) {
+    if (--ptr == type_url.data) {
+      /* Type URL must contain at least one '/', with host before. */
+      goto badurl;
+    }
+    if (*ptr == '/') {
+      ptr++;
+      break;
+    }
+  }
+
+  ret = upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr);
+
+  if (!ret) {
+    jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr);
+  }
+
+  return ret;
+
+badurl:
+  jsonenc_errf(
+      e, "Bad type URL: " UPB_STRVIEW_FORMAT, UPB_STRVIEW_ARGS(type_url));
+}
+
+static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 2);
+  upb_strview type_url = upb_msg_get(msg, type_url_f).str_val;
+  upb_strview value = upb_msg_get(msg, value_f).str_val;
+  const upb_msgdef *any_m = jsonenc_getanymsg(e, type_url);
+  const upb_msglayout *any_layout = upb_msgdef_layout(any_m);
+  upb_arena *arena = jsonenc_arena(e);
+  upb_msg *any = upb_msg_new(any_m, arena);
+
+  if (!upb_decode(value.data, value.size, any, any_layout, arena)) {
+    jsonenc_err(e, "Error decoding message in Any");
+  }
+
+  jsonenc_putstr(e, "{\"@type\":");
+  jsonenc_string(e, type_url);
+
+  if (upb_msgdef_wellknowntype(any_m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */
+    jsonenc_msgfields(e, any, any_m, false);
+  } else {
+    /* Well-known type: {"@type": "...","value": <well-known encoding>} */
+    jsonenc_putstr(e, ",\"value\":");
+    jsonenc_msgfield(e, any, any_m);
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_putsep(jsonenc *e, const char *str, bool *first) {
+  if (*first) {
+    *first = false;
+  } else {
+    jsonenc_putstr(e, str);
+  }
+}
+
+static void jsonenc_fieldpath(jsonenc *e, upb_strview path) {
+  const char *ptr = path.data;
+  const char *end = ptr + path.size;
+
+  while (ptr < end) {
+    char ch = *ptr;
+
+    if (ch >= 'A' && ch <= 'Z') {
+      jsonenc_err(e, "Field mask element may not have upper-case letter.");
+    } else if (ch == '_') {
+      if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') {
+        jsonenc_err(e, "Underscore must be followed by a lowercase letter.");
+      }
+      ch = *++ptr - 32;
+    }
+
+    jsonenc_putbytes(e, &ch, 1);
+    ptr++;
+  }
+}
+
+static void jsonenc_fieldmask(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *paths_f = upb_msgdef_itof(m, 1);
+  const upb_array *paths = upb_msg_get(msg, paths_f).array_val;
+  bool first = true;
+  size_t i, n = 0;
+
+  if (paths) n = upb_array_size(paths);
+
+  jsonenc_putstr(e, "\"");
+
+  for (i = 0; i < n; i++) {
+    jsonenc_putsep(e, ",", &first);
+    jsonenc_fieldpath(e, upb_array_get(paths, i).str_val);
+  }
+
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_struct(jsonenc *e, const upb_msg *msg,
+                           const upb_msgdef *m) {
+  const upb_fielddef *fields_f = upb_msgdef_itof(m, 1);
+  const upb_map *fields = upb_msg_get(msg, fields_f).map_val;
+  const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f);
+  const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2);
+  size_t iter = UPB_MAP_BEGIN;
+  bool first = true;
+
+  jsonenc_putstr(e, "{");
+
+  if (fields) {
+    while (upb_mapiter_next(fields, &iter)) {
+      upb_msgval key = upb_mapiter_key(fields, iter);
+      upb_msgval val = upb_mapiter_value(fields, iter);
+
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_string(e, key.str_val);
+      jsonenc_putstr(e, ":");
+      jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f));
+    }
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_listvalue(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *values_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *values_m = upb_fielddef_msgsubdef(values_f);
+  const upb_array *values = upb_msg_get(msg, values_f).array_val;
+  size_t i;
+  bool first = true;
+
+  jsonenc_putstr(e, "[");
+
+  if (values) {
+    const size_t size = upb_array_size(values);
+    for (i = 0; i < size; i++) {
+      upb_msgval elem = upb_array_get(values, i);
+
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_value(e, elem.msg_val, values_m);
+    }
+  }
+
+  jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  /* TODO(haberman): do we want a reflection method to get oneof case? */
+  size_t iter = UPB_MSG_BEGIN;
+  const upb_fielddef *f;
+  upb_msgval val;
+
+  if (!upb_msg_next(msg, m, NULL,  &f, &val, &iter)) {
+    jsonenc_err(e, "No value set in Value proto");
+  }
+
+  switch (upb_fielddef_number(f)) {
+    case 1:
+      jsonenc_putstr(e, "null");
+      break;
+    case 2:
+      jsonenc_double(e, "%.17g", val.double_val);
+      break;
+    case 3:
+      jsonenc_string(e, val.str_val);
+      break;
+    case 4:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case 5:
+      jsonenc_struct(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+    case 6:
+      jsonenc_listvalue(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+  }
+}
+
+static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg,
+                             const upb_msgdef *m) {
+  switch (upb_msgdef_wellknowntype(m)) {
+    case UPB_WELLKNOWN_UNSPECIFIED:
+      jsonenc_msg(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_ANY:
+      jsonenc_any(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_FIELDMASK:
+      jsonenc_fieldmask(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_DURATION:
+      jsonenc_duration(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_TIMESTAMP:
+      jsonenc_timestamp(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_DOUBLEVALUE:
+    case UPB_WELLKNOWN_FLOATVALUE:
+    case UPB_WELLKNOWN_INT64VALUE:
+    case UPB_WELLKNOWN_UINT64VALUE:
+    case UPB_WELLKNOWN_INT32VALUE:
+    case UPB_WELLKNOWN_UINT32VALUE:
+    case UPB_WELLKNOWN_STRINGVALUE:
+    case UPB_WELLKNOWN_BYTESVALUE:
+    case UPB_WELLKNOWN_BOOLVALUE:
+      jsonenc_wrapper(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_VALUE:
+      jsonenc_value(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_LISTVALUE:
+      jsonenc_listvalue(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_STRUCT:
+      jsonenc_struct(e, msg, m);
+      break;
+  }
+}
+
+static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_FLOAT:
+      jsonenc_double(e, "%.9g", val.float_val);
+      break;
+    case UPB_TYPE_DOUBLE:
+      jsonenc_double(e, "%.17g", val.double_val);
+      break;
+    case UPB_TYPE_INT32:
+      jsonenc_printf(e, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      jsonenc_string(e, val.str_val);
+      break;
+    case UPB_TYPE_BYTES:
+      jsonenc_bytes(e, val.str_val);
+      break;
+    case UPB_TYPE_ENUM:
+      jsonenc_enum(val.int32_val, f, e);
+      break;
+    case UPB_TYPE_MESSAGE:
+      jsonenc_msgfield(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+  }
+}
+
+static void jsonenc_mapkey(jsonenc *e, upb_msgval val, const upb_fielddef *f) {
+  jsonenc_putstr(e, "\"");
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_INT32:
+      jsonenc_printf(e, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      jsonenc_printf(e, "%" PRId64, val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      jsonenc_printf(e, "%" PRIu64, val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      jsonenc_stringbody(e, val.str_val);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  jsonenc_putstr(e, "\":");
+}
+
+static void jsonenc_array(jsonenc *e, const upb_array *arr,
+                         const upb_fielddef *f) {
+  size_t i;
+  size_t size = arr ? upb_array_size(arr) : 0;
+  bool first = true;
+
+  jsonenc_putstr(e, "[");
+
+  for (i = 0; i < size; i++) {
+    jsonenc_putsep(e, ",", &first);
+    jsonenc_scalar(e, upb_array_get(arr, i), f);
+  }
+
+  jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_map(jsonenc *e, const upb_map *map, const upb_fielddef *f) {
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+  const upb_fielddef *key_f = upb_msgdef_itof(entry, 1);
+  const upb_fielddef *val_f = upb_msgdef_itof(entry, 2);
+  size_t iter = UPB_MAP_BEGIN;
+  bool first = true;
+
+  jsonenc_putstr(e, "{");
+
+  if (map) {
+    while (upb_mapiter_next(map, &iter)) {
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f);
+      jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f);
+    }
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_fieldval(jsonenc *e, const upb_fielddef *f,
+                             upb_msgval val, bool *first) {
+  const char *name;
+
+  if (e->options & UPB_JSONENC_PROTONAMES) {
+    name = upb_fielddef_name(f);
+  } else {
+    name = upb_fielddef_jsonname(f);
+  }
+
+  jsonenc_putsep(e, ",", first);
+  jsonenc_printf(e, "\"%s\":", name);
+
+  if (upb_fielddef_ismap(f)) {
+    jsonenc_map(e, val.map_val, f);
+  } else if (upb_fielddef_isseq(f)) {
+    jsonenc_array(e, val.array_val, f);
+  } else {
+    jsonenc_scalar(e, val, f);
+  }
+}
+
+static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m, bool first) {
+  upb_msgval val;
+  const upb_fielddef *f;
+
+  if (e->options & UPB_JSONENC_EMITDEFAULTS) {
+    /* Iterate over all fields. */
+    int i = 0;
+    int n = upb_msgdef_fieldcount(m);
+    for (i = 0; i < n; i++) {
+      f = upb_msgdef_field(m, i);
+      if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
+        jsonenc_fieldval(e, f, upb_msg_get(msg, f), &first);
+      }
+    }
+  } else {
+    /* Iterate over non-empty fields. */
+    size_t iter = UPB_MSG_BEGIN;
+    while (upb_msg_next(msg, m, e->ext_pool, &f, &val, &iter)) {
+      jsonenc_fieldval(e, f, val, &first);
+    }
+  }
+}
+
+static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  jsonenc_putstr(e, "{");
+  jsonenc_msgfields(e, msg, m, true);
+  jsonenc_putstr(e, "}");
+}
+
+static size_t jsonenc_nullz(jsonenc *e, size_t size) {
+  size_t ret = e->ptr - e->buf + e->overflow;
+
+  if (size > 0) {
+    if (e->ptr == e->end) e->ptr--;
+    *e->ptr = '\0';
+  }
+
+  return ret;
+}
+
+size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
+                       const upb_symtab *ext_pool, int options, char *buf,
+                       size_t size, upb_status *status) {
+  jsonenc e;
+
+  e.buf = buf;
+  e.ptr = buf;
+  e.end = UPB_PTRADD(buf, size);
+  e.overflow = 0;
+  e.options = options;
+  e.ext_pool = ext_pool;
+  e.status = status;
+  e.arena = NULL;
+
+  if (setjmp(e.err)) return -1;
+
+  jsonenc_msgfield(&e, msg, m);
+  if (e.arena) upb_arena_free(e.arena);
+  return jsonenc_nullz(&e, size);
+}
+
+/** upb/port_undef.inc ************************************************************/
+/* See port_def.inc.  This should #undef all macros #defined there. */
+
+#undef UPB_SIZE
+#undef UPB_PTR_AT
+#undef UPB_READ_ONEOF
+#undef UPB_WRITE_ONEOF
+#undef UPB_MAPTYPE_STRING
+#undef UPB_INLINE
+#undef UPB_ALIGN_UP
+#undef UPB_ALIGN_DOWN
+#undef UPB_ALIGN_MALLOC
+#undef UPB_ALIGN_OF
+#undef UPB_LIKELY
+#undef UPB_UNLIKELY
+#undef UPB_FORCEINLINE
+#undef UPB_NOINLINE
+#undef UPB_NORETURN
+#undef UPB_PRINTF
+#undef UPB_MAX
+#undef UPB_MIN
+#undef UPB_UNUSED
+#undef UPB_ASSUME
+#undef UPB_ASSERT
+#undef UPB_UNREACHABLE
+#undef UPB_SETJMP
+#undef UPB_LONGJMP
+#undef UPB_PTRADD
+#undef UPB_MUSTTAIL
+#undef UPB_FASTTABLE_SUPPORTED
+#undef UPB_FASTTABLE
+#undef UPB_FASTTABLE_INIT
+#undef UPB_POISON_MEMORY_REGION
+#undef UPB_UNPOISON_MEMORY_REGION
+#undef UPB_ASAN
diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h
new file mode 100755
index 0000000..68d6345
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/ruby-upb.h
@@ -0,0 +1,4411 @@
+/* Amalgamated source file */
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google LLC nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is where we define macros used across upb.
+ *
+ * All of these macros are undef'd in port_undef.inc to avoid leaking them to
+ * users.
+ *
+ * The correct usage is:
+ *
+ *   #include "upb/foobar.h"
+ *   #include "upb/baz.h"
+ *
+ *   // MUST be last included header.
+ *   #include "upb/port_def.inc"
+ *
+ *   // Code for this file.
+ *   // <...>
+ *
+ *   // Can be omitted for .c files, required for .h.
+ *   #include "upb/port_undef.inc"
+ *
+ * This file is private and must not be included by users!
+ */
+
+#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+      (defined(__cplusplus) && __cplusplus >= 201103L) ||           \
+      (defined(_MSC_VER) && _MSC_VER >= 1900))
+#error upb requires C99 or C++11 or MSVC >= 2015.
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#if UINTPTR_MAX == 0xffffffff
+#define UPB_SIZE(size32, size64) size32
+#else
+#define UPB_SIZE(size32, size64) size64
+#endif
+
+/* If we always read/write as a consistent type to each address, this shouldn't
+ * violate aliasing.
+ */
+#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
+
+#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
+  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
+      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
+      : default
+
+#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
+  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
+  *UPB_PTR_AT(msg, offset, fieldtype) = value;
+
+#define UPB_MAPTYPE_STRING 0
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__) || defined(__clang__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
+#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
+#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
+#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
+
+/* Hints to the compiler about likely/unlikely branches. */
+#if defined (__GNUC__) || defined(__clang__)
+#define UPB_LIKELY(x) __builtin_expect((x),1)
+#define UPB_UNLIKELY(x) __builtin_expect((x),0)
+#else
+#define UPB_LIKELY(x) (x)
+#define UPB_UNLIKELY(x) (x)
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg)))
+#elif defined(_MSC_VER)
+#define UPB_NOINLINE
+#define UPB_FORCEINLINE
+#define UPB_NORETURN __declspec(noreturn)
+#define UPB_PRINTF(str, first_vararg)
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#define UPB_PRINTF(str, first_vararg)
+#endif
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
+ */
+#ifdef NDEBUG
+#ifdef __GNUC__
+#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
+#elif defined _MSC_VER
+#define UPB_ASSUME(expr) if (!(expr)) __assume(0)
+#else
+#define UPB_ASSUME(expr) do {} while (false && (expr))
+#endif
+#else
+#define UPB_ASSUME(expr) assert(expr)
+#endif
+
+/* UPB_ASSERT(): in release mode, we use the expression without letting it be
+ * evaluated.  This prevents "unused variable" warnings. */
+#ifdef NDEBUG
+#define UPB_ASSERT(expr) do {} while (false && (expr))
+#else
+#define UPB_ASSERT(expr) assert(expr)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
+#else
+#define UPB_UNREACHABLE() do { assert(0); } while(0)
+#endif
+
+/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
+#ifdef __APPLE__
+#define UPB_SETJMP(buf) _setjmp(buf)
+#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
+#else
+#define UPB_SETJMP(buf) setjmp(buf)
+#define UPB_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */
+#define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr))
+
+/* Configure whether fasttable is switched on or not. *************************/
+
+#ifdef __has_attribute
+#define UPB_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define UPB_HAS_ATTRIBUTE(x) 0
+#endif
+
+#if UPB_HAS_ATTRIBUTE(musttail)
+#define UPB_MUSTTAIL __attribute__((musttail))
+#else
+#define UPB_MUSTTAIL
+#endif
+
+#undef UPB_HAS_ATTRIBUTE
+
+/* This check is not fully robust: it does not require that we have "musttail"
+ * support available. We need tail calls to avoid consuming arbitrary amounts
+ * of stack space.
+ *
+ * GCC/Clang can mostly be trusted to generate tail calls as long as
+ * optimization is enabled, but, debug builds will not generate tail calls
+ * unless "musttail" is available.
+ *
+ * We should probably either:
+ *   1. require that the compiler supports musttail.
+ *   2. add some fallback code for when musttail isn't available (ie. return
+ *      instead of tail calling). This is safe and portable, but this comes at
+ *      a CPU cost.
+ */
+#if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__)
+#define UPB_FASTTABLE_SUPPORTED 1
+#else
+#define UPB_FASTTABLE_SUPPORTED 0
+#endif
+
+/* define UPB_ENABLE_FASTTABLE to force fast table support.
+ * This is useful when we want to ensure we are really getting fasttable,
+ * for example for testing or benchmarking. */
+#if defined(UPB_ENABLE_FASTTABLE)
+#if !UPB_FASTTABLE_SUPPORTED
+#error fasttable is x86-64/ARM64 only and requires GCC or Clang.
+#endif
+#define UPB_FASTTABLE 1
+/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
+ * This is useful for releasing code that might be used on multiple platforms,
+ * for example the PHP or Ruby C extensions. */
+#elif defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
+#else
+#define UPB_FASTTABLE 0
+#endif
+
+/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
+ * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */
+#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE_INIT(...)
+#else
+#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
+#endif
+
+#undef UPB_FASTTABLE_SUPPORTED
+
+/* ASAN poisoning (for arena) *************************************************/
+
+#if defined(__SANITIZE_ADDRESS__)
+#define UPB_ASAN 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  __asan_poison_memory_region((addr), (size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  __asan_unpoison_memory_region((addr), (size))
+#else
+#define UPB_ASAN 0
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#endif
+
+/** upb/decode.h ************************************************************/
+/*
+ * upb_decode: parsing into a upb_msg using a upb_msglayout.
+ */
+
+#ifndef UPB_DECODE_H_
+#define UPB_DECODE_H_
+
+
+/** upb/msg.h ************************************************************/
+/*
+ * Public APIs for message operations that do not require descriptors.
+ * These functions can be used even in build that does not want to depend on
+ * reflection or descriptors.
+ *
+ * Descriptor-based reflection functionality lives in reflection.h.
+ */
+
+#ifndef UPB_MSG_H_
+#define UPB_MSG_H_
+
+#include <stddef.h>
+
+
+/** upb/upb.h ************************************************************/
+/*
+ * This file contains shared definitions that are widely used across upb.
+ */
+
+#ifndef UPB_H_
+#define UPB_H_
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* upb_status *****************************************************************/
+
+#define UPB_STATUS_MAX_MESSAGE 127
+
+typedef struct {
+  bool ok;
+  char msg[UPB_STATUS_MAX_MESSAGE];  /* Error message; NULL-terminated. */
+} upb_status;
+
+const char *upb_status_errmsg(const upb_status *status);
+bool upb_ok(const upb_status *status);
+
+/* These are no-op if |status| is NULL. */
+void upb_status_clear(upb_status *status);
+void upb_status_seterrmsg(upb_status *status, const char *msg);
+void upb_status_seterrf(upb_status *status, const char *fmt, ...)
+    UPB_PRINTF(2, 3);
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args)
+    UPB_PRINTF(2, 0);
+void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args)
+    UPB_PRINTF(2, 0);
+
+/** upb_strview ************************************************************/
+
+typedef struct {
+  const char *data;
+  size_t size;
+} upb_strview;
+
+UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
+  upb_strview ret;
+  ret.data = data;
+  ret.size = size;
+  return ret;
+}
+
+UPB_INLINE upb_strview upb_strview_makez(const char *data) {
+  return upb_strview_make(data, strlen(data));
+}
+
+UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
+  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
+}
+
+#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
+
+#define UPB_STRVIEW_FORMAT "%.*s"
+#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
+
+/** upb_alloc *****************************************************************/
+
+/* A upb_alloc is a possibly-stateful allocator object.
+ *
+ * It could either be an arena allocator (which doesn't require individual
+ * free() calls) or a regular malloc() (which does).  The client must therefore
+ * free memory unless it knows that the allocator is an arena allocator. */
+
+struct upb_alloc;
+typedef struct upb_alloc upb_alloc;
+
+/* A malloc()/free() function.
+ * If "size" is 0 then the function acts like free(), otherwise it acts like
+ * realloc().  Only "oldsize" bytes from a previous allocation are preserved. */
+typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size);
+
+struct upb_alloc {
+  upb_alloc_func *func;
+};
+
+UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
+  UPB_ASSERT(alloc);
+  return alloc->func(alloc, NULL, 0, size);
+}
+
+UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size) {
+  UPB_ASSERT(alloc);
+  return alloc->func(alloc, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
+  assert(alloc);
+  alloc->func(alloc, ptr, 0, 0);
+}
+
+/* The global allocator used by upb.  Uses the standard malloc()/free(). */
+
+extern upb_alloc upb_alloc_global;
+
+/* Functions that hard-code the global malloc.
+ *
+ * We still get benefit because we can put custom logic into our global
+ * allocator, like injecting out-of-memory faults in debug/testing builds. */
+
+UPB_INLINE void *upb_gmalloc(size_t size) {
+  return upb_malloc(&upb_alloc_global, size);
+}
+
+UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
+  return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_gfree(void *ptr) {
+  upb_free(&upb_alloc_global, ptr);
+}
+
+/* upb_arena ******************************************************************/
+
+/* upb_arena is a specific allocator implementation that uses arena allocation.
+ * The user provides an allocator that will be used to allocate the underlying
+ * arena blocks.  Arenas by nature do not require the individual allocations
+ * to be freed.  However the Arena does allow users to register cleanup
+ * functions that will run when the arena is destroyed.
+ *
+ * A upb_arena is *not* thread-safe.
+ *
+ * You could write a thread-safe arena allocator that satisfies the
+ * upb_alloc interface, but it would not be as efficient for the
+ * single-threaded case. */
+
+typedef void upb_cleanup_func(void *ud);
+
+struct upb_arena;
+typedef struct upb_arena upb_arena;
+
+typedef struct {
+  /* We implement the allocator interface.
+   * This must be the first member of upb_arena!
+   * TODO(haberman): remove once handlers are gone. */
+  upb_alloc alloc;
+
+  char *ptr, *end;
+} _upb_arena_head;
+
+/* Creates an arena from the given initial block (if any -- n may be 0).
+ * Additional blocks will be allocated from |alloc|.  If |alloc| is NULL, this
+ * is a fixed-size arena and cannot grow. */
+upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
+void upb_arena_free(upb_arena *a);
+bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
+bool upb_arena_fuse(upb_arena *a, upb_arena *b);
+void *_upb_arena_slowmalloc(upb_arena *a, size_t size);
+
+UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
+
+UPB_INLINE size_t _upb_arenahas(upb_arena *a) {
+  _upb_arena_head *h = (_upb_arena_head*)a;
+  return (size_t)(h->end - h->ptr);
+}
+
+UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
+  _upb_arena_head *h = (_upb_arena_head*)a;
+  void* ret;
+  size = UPB_ALIGN_MALLOC(size);
+
+  if (UPB_UNLIKELY(_upb_arenahas(a) < size)) {
+    return _upb_arena_slowmalloc(a, size);
+  }
+
+  ret = h->ptr;
+  h->ptr += size;
+  UPB_UNPOISON_MEMORY_REGION(ret, size);
+
+#if UPB_ASAN
+  {
+    size_t guard_size = 32;
+    if (_upb_arenahas(a) >= guard_size) {
+      h->ptr += guard_size;
+    } else {
+      h->ptr = h->end;
+    }
+  }
+#endif
+
+  return ret;
+}
+
+UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
+                                   size_t size) {
+  void *ret = upb_arena_malloc(a, size);
+
+  if (ret && oldsize > 0) {
+    memcpy(ret, ptr, oldsize);
+  }
+
+  return ret;
+}
+
+UPB_INLINE upb_arena *upb_arena_new(void) {
+  return upb_arena_init(NULL, 0, &upb_alloc_global);
+}
+
+/* Constants ******************************************************************/
+
+/* Generic function type. */
+typedef void upb_func(void);
+
+/* A list of types as they are encoded on-the-wire. */
+typedef enum {
+  UPB_WIRE_TYPE_VARINT      = 0,
+  UPB_WIRE_TYPE_64BIT       = 1,
+  UPB_WIRE_TYPE_DELIMITED   = 2,
+  UPB_WIRE_TYPE_START_GROUP = 3,
+  UPB_WIRE_TYPE_END_GROUP   = 4,
+  UPB_WIRE_TYPE_32BIT       = 5
+} upb_wiretype_t;
+
+/* The types a field can have.  Note that this list is not identical to the
+ * types defined in descriptor.proto, which gives INT32 and SINT32 separate
+ * types (we distinguish the two with the "integer encoding" enum below). */
+typedef enum {
+  UPB_TYPE_BOOL     = 1,
+  UPB_TYPE_FLOAT    = 2,
+  UPB_TYPE_INT32    = 3,
+  UPB_TYPE_UINT32   = 4,
+  UPB_TYPE_ENUM     = 5,  /* Enum values are int32. */
+  UPB_TYPE_MESSAGE  = 6,
+  UPB_TYPE_DOUBLE   = 7,
+  UPB_TYPE_INT64    = 8,
+  UPB_TYPE_UINT64   = 9,
+  UPB_TYPE_STRING   = 10,
+  UPB_TYPE_BYTES    = 11
+} upb_fieldtype_t;
+
+/* The repeated-ness of each field; this matches descriptor.proto. */
+typedef enum {
+  UPB_LABEL_OPTIONAL = 1,
+  UPB_LABEL_REQUIRED = 2,
+  UPB_LABEL_REPEATED = 3
+} upb_label_t;
+
+/* Descriptor types, as defined in descriptor.proto. */
+typedef enum {
+  /* Old (long) names.  TODO(haberman): remove */
+  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
+  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
+  UPB_DESCRIPTOR_TYPE_INT64    = 3,
+  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
+  UPB_DESCRIPTOR_TYPE_INT32    = 5,
+  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
+  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
+  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
+  UPB_DESCRIPTOR_TYPE_STRING   = 9,
+  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
+  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
+  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
+  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
+  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
+  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
+  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
+  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
+  UPB_DESCRIPTOR_TYPE_SINT64   = 18,
+
+  UPB_DTYPE_DOUBLE   = 1,
+  UPB_DTYPE_FLOAT    = 2,
+  UPB_DTYPE_INT64    = 3,
+  UPB_DTYPE_UINT64   = 4,
+  UPB_DTYPE_INT32    = 5,
+  UPB_DTYPE_FIXED64  = 6,
+  UPB_DTYPE_FIXED32  = 7,
+  UPB_DTYPE_BOOL     = 8,
+  UPB_DTYPE_STRING   = 9,
+  UPB_DTYPE_GROUP    = 10,
+  UPB_DTYPE_MESSAGE  = 11,
+  UPB_DTYPE_BYTES    = 12,
+  UPB_DTYPE_UINT32   = 13,
+  UPB_DTYPE_ENUM     = 14,
+  UPB_DTYPE_SFIXED32 = 15,
+  UPB_DTYPE_SFIXED64 = 16,
+  UPB_DTYPE_SINT32   = 17,
+  UPB_DTYPE_SINT64   = 18
+} upb_descriptortype_t;
+
+#define UPB_MAP_BEGIN ((size_t)-1)
+
+UPB_INLINE bool _upb_isle(void) {
+  int x = 1;
+  return *(char*)&x == 1;
+}
+
+UPB_INLINE uint32_t _upb_be_swap32(uint32_t val) {
+  if (_upb_isle()) {
+    return val;
+  } else {
+    return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+           ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
+  }
+}
+
+UPB_INLINE uint64_t _upb_be_swap64(uint64_t val) {
+  if (_upb_isle()) {
+    return val;
+  } else {
+    return ((uint64_t)_upb_be_swap32(val) << 32) | _upb_be_swap32(val >> 32);
+  }
+}
+
+UPB_INLINE int _upb_lg2ceil(int x) {
+  if (x <= 1) return 0;
+#ifdef __GNUC__
+  return 32 - __builtin_clz(x - 1);
+#else
+  int lg2 = 0;
+  while (1 << lg2 < x) lg2++;
+  return lg2;
+#endif
+}
+
+UPB_INLINE int _upb_lg2ceilsize(int x) {
+  return 1 << _upb_lg2ceil(x);
+}
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_H_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void upb_msg;
+
+/* For users these are opaque. They can be obtained from upb_msgdef_layout()
+ * but users cannot access any of the members. */
+struct upb_msglayout;
+typedef struct upb_msglayout upb_msglayout;
+
+/* Adds unknown data (serialized protobuf data) to the given message.  The data
+ * is copied into the message instance. */
+void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                        upb_arena *arena);
+
+/* Returns a reference to the message's unknown data. */
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* UPB_MSG_INT_H_ */
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* If set, strings will alias the input buffer instead of copying into the
+   * arena. */
+  UPB_DECODE_ALIAS = 1,
+};
+
+#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
+
+bool _upb_decode(const char *buf, size_t size, upb_msg *msg,
+                 const upb_msglayout *l, upb_arena *arena, int options);
+
+UPB_INLINE
+bool upb_decode(const char *buf, size_t size, upb_msg *msg,
+                const upb_msglayout *l, upb_arena *arena) {
+  return _upb_decode(buf, size, msg, l, arena, 0);
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* UPB_DECODE_H_ */
+
+/** upb/decode_internal.h ************************************************************/
+/*
+ * Internal implementation details of the decoder that are shared between
+ * decode.c and decode_fast.c.
+ */
+
+#ifndef UPB_DECODE_INT_H_
+#define UPB_DECODE_INT_H_
+
+#include <setjmp.h>
+
+
+/** upb/msg_internal.h ************************************************************//*
+** Our memory representation for parsing tables and messages themselves.
+** Functions in this file are used by generated code and possibly reflection.
+**
+** The definitions in this file are internal to upb.
+**/
+
+#ifndef UPB_MSG_INT_H_
+#define UPB_MSG_INT_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/** upb/table_internal.h ************************************************************/
+/*
+ * upb_table
+ *
+ * This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
+ * This file defines very fast int->upb_value (inttable) and string->upb_value
+ * (strtable) hash tables.
+ *
+ * The table uses chained scatter with Brent's variation (inspired by the Lua
+ * implementation of hash tables).  The hash function for strings is Austin
+ * Appleby's "MurmurHash."
+ *
+ * The inttable uses uintptr_t as its key, which guarantees it can be used to
+ * store pointers or integers of at least 32 bits (upb isn't really useful on
+ * systems where sizeof(void*) < 4).
+ *
+ * The table must be homogeneous (all values of the same type).  In debug
+ * mode, we check this on insert and lookup.
+ */
+
+#ifndef UPB_TABLE_H_
+#define UPB_TABLE_H_
+
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* upb_value ******************************************************************/
+
+typedef struct {
+  uint64_t val;
+} upb_value;
+
+/* Variant that works with a length-delimited rather than NULL-delimited string,
+ * as supported by strtable. */
+char *upb_strdup2(const char *s, size_t len, upb_arena *a);
+
+UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) {
+  v->val = val;
+}
+
+/* For each value ctype, define the following set of functions:
+ *
+ * // Get/set an int32 from a upb_value.
+ * int32_t upb_value_getint32(upb_value val);
+ * void upb_value_setint32(upb_value *val, int32_t cval);
+ *
+ * // Construct a new upb_value from an int32.
+ * upb_value upb_value_int32(int32_t val); */
+#define FUNCS(name, membername, type_t, converter, proto_type) \
+  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
+    val->val = (converter)cval; \
+  } \
+  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
+    upb_value ret; \
+    upb_value_set ## name(&ret, val); \
+    return ret; \
+  } \
+  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
+    return (type_t)(converter)val.val; \
+  }
+
+FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
+FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
+FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
+FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
+FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
+FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
+FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
+FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
+FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
+
+#undef FUNCS
+
+UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
+  memcpy(&val->val, &cval, sizeof(cval));
+}
+
+UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
+  memcpy(&val->val, &cval, sizeof(cval));
+}
+
+UPB_INLINE upb_value upb_value_float(float cval) {
+  upb_value ret;
+  upb_value_setfloat(&ret, cval);
+  return ret;
+}
+
+UPB_INLINE upb_value upb_value_double(double cval) {
+  upb_value ret;
+  upb_value_setdouble(&ret, cval);
+  return ret;
+}
+
+#undef SET_TYPE
+
+
+/* upb_tabkey *****************************************************************/
+
+/* Either:
+ *   1. an actual integer key, or
+ *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
+ *
+ * ...depending on whether this is a string table or an int table.  We would
+ * make this a union of those two types, but C89 doesn't support statically
+ * initializing a non-first union member. */
+typedef uintptr_t upb_tabkey;
+
+UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
+  char* mem = (char*)key;
+  if (len) memcpy(len, mem, sizeof(*len));
+  return mem + sizeof(*len);
+}
+
+UPB_INLINE upb_strview upb_tabstrview(upb_tabkey key) {
+  upb_strview ret;
+  uint32_t len;
+  ret.data = upb_tabstr(key, &len);
+  ret.size = len;
+  return ret;
+}
+
+/* upb_tabval *****************************************************************/
+
+typedef struct upb_tabval {
+  uint64_t val;
+} upb_tabval;
+
+#define UPB_TABVALUE_EMPTY_INIT  {-1}
+
+/* upb_table ******************************************************************/
+
+typedef struct _upb_tabent {
+  upb_tabkey key;
+  upb_tabval val;
+
+  /* Internal chaining.  This is const so we can create static initializers for
+   * tables.  We cast away const sometimes, but *only* when the containing
+   * upb_table is known to be non-const.  This requires a bit of care, but
+   * the subtlety is confined to table.c. */
+  const struct _upb_tabent *next;
+} upb_tabent;
+
+typedef struct {
+  size_t count;          /* Number of entries in the hash part. */
+  uint32_t mask;         /* Mask to turn hash value -> bucket. */
+  uint32_t max_count;    /* Max count before we hit our load limit. */
+  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
+  upb_tabent *entries;
+} upb_table;
+
+typedef struct {
+  upb_table t;
+} upb_strtable;
+
+typedef struct {
+  upb_table t;              /* For entries that don't fit in the array part. */
+  const upb_tabval *array;  /* Array part of the table. See const note above. */
+  size_t array_size;        /* Array part size. */
+  size_t array_count;       /* Array part number of elements. */
+} upb_inttable;
+
+UPB_INLINE size_t upb_table_size(const upb_table *t) {
+  if (t->size_lg2 == 0)
+    return 0;
+  else
+    return 1 << t->size_lg2;
+}
+
+/* Internal-only functions, in .h file only out of necessity. */
+UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
+  return e->key == 0;
+}
+
+/* Initialize and uninitialize a table, respectively.  If memory allocation
+ * failed, false is returned that the table is uninitialized. */
+bool upb_inttable_init(upb_inttable *table, upb_arena *a);
+bool upb_strtable_init(upb_strtable *table, size_t expected_size, upb_arena *a);
+
+/* Returns the number of values in the table. */
+size_t upb_inttable_count(const upb_inttable *t);
+UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
+  return t->t.count;
+}
+
+void upb_strtable_clear(upb_strtable *t);
+
+/* Inserts the given key into the hashtable with the given value.  The key must
+ * not already exist in the hash table.  For string tables, the key must be
+ * NULL-terminated, and the table will make an internal copy of the key.
+ * Inttables must not insert a value of UINTPTR_MAX.
+ *
+ * If a table resize was required but memory allocation failed, false is
+ * returned and the table is unchanged. */
+bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val,
+                         upb_arena *a);
+bool upb_strtable_insert(upb_strtable *t, const char *key, size_t len,
+                         upb_value val, upb_arena *a);
+
+/* Looks up key in this table, returning "true" if the key was found.
+ * If v is non-NULL, copies the value for this key into *v. */
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v);
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_lookup2(t, key, strlen(key), v);
+}
+
+/* Removes an item from the table.  Returns true if the remove was successful,
+ * and stores the removed item in *val if non-NULL. */
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
+bool upb_strtable_remove(upb_strtable *t, const char *key, size_t len,
+                          upb_value *val);
+
+/* Updates an existing entry in an inttable.  If the entry does not exist,
+ * returns false and does nothing.  Unlike insert/remove, this does not
+ * invalidate iterators. */
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
+
+/* Optimizes the table for the current set of entries, for both memory use and
+ * lookup time.  Client should call this after all entries have been inserted;
+ * inserting more entries is legal, but will likely require a table resize. */
+void upb_inttable_compact(upb_inttable *t, upb_arena *a);
+
+/* Exposed for testing only. */
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_arena *a);
+
+/* Iterators ******************************************************************/
+
+/* Iterators for int and string tables.  We are subject to some kind of unusual
+ * design constraints:
+ *
+ * For high-level languages:
+ *  - we must be able to guarantee that we don't crash or corrupt memory even if
+ *    the program accesses an invalidated iterator.
+ *
+ * For C++11 range-based for:
+ *  - iterators must be copyable
+ *  - iterators must be comparable
+ *  - it must be possible to construct an "end" value.
+ *
+ * Iteration order is undefined.
+ *
+ * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
+ * guaranteed to work even on an invalidated iterator, as long as the table it
+ * is iterating over has not been freed.  Calling next() or accessing data from
+ * an invalidated iterator yields unspecified elements from the table, but it is
+ * guaranteed not to crash and to return real table elements (except when done()
+ * is true). */
+
+
+/* upb_strtable_iter **********************************************************/
+
+/*   upb_strtable_iter i;
+ *   upb_strtable_begin(&i, t);
+ *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+ *     const char *key = upb_strtable_iter_key(&i);
+ *     const upb_value val = upb_strtable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_strtable *t;
+  size_t index;
+} upb_strtable_iter;
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
+void upb_strtable_next(upb_strtable_iter *i);
+bool upb_strtable_done(const upb_strtable_iter *i);
+upb_strview upb_strtable_iter_key(const upb_strtable_iter *i);
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
+void upb_strtable_iter_setdone(upb_strtable_iter *i);
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2);
+
+
+/* upb_inttable_iter **********************************************************/
+
+/*   upb_inttable_iter i;
+ *   upb_inttable_begin(&i, t);
+ *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ *     uintptr_t key = upb_inttable_iter_key(&i);
+ *     upb_value val = upb_inttable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_inttable *t;
+  size_t index;
+  bool array_part;
+} upb_inttable_iter;
+
+UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) {
+  return &i->t->t.entries[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
+void upb_inttable_next(upb_inttable_iter *i);
+bool upb_inttable_done(const upb_inttable_iter *i);
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
+void upb_inttable_iter_setdone(upb_inttable_iter *i);
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                               const upb_inttable_iter *i2);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* UPB_TABLE_H_ */
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** upb_msglayout *************************************************************/
+
+/* upb_msglayout represents the memory layout of a given upb_msgdef.  The
+ * members are public so generated code can initialize them, but users MUST NOT
+ * read or write any of its members. */
+
+/* These aren't real labels according to descriptor.proto, but in the table we
+ * use these for map/packed fields instead of UPB_LABEL_REPEATED. */
+enum {
+  _UPB_LABEL_MAP = 4,
+  _UPB_LABEL_PACKED = 7  /* Low 3 bits are common with UPB_LABEL_REPEATED. */
+};
+
+typedef struct {
+  uint32_t number;
+  uint16_t offset;
+  int16_t presence;       /* If >0, hasbit_index.  If <0, ~oneof_index. */
+  uint16_t submsg_index;  /* undefined if descriptortype != MESSAGE or GROUP. */
+  uint8_t descriptortype;
+  uint8_t label;          /* google.protobuf.Label or _UPB_LABEL_* above. */
+} upb_msglayout_field;
+
+struct upb_decstate;
+struct upb_msglayout;
+
+typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr,
+                                      upb_msg *msg, intptr_t table,
+                                      uint64_t hasbits, uint64_t data);
+
+typedef struct {
+  uint64_t field_data;
+  _upb_field_parser *field_parser;
+} _upb_fasttable_entry;
+
+struct upb_msglayout {
+  const struct upb_msglayout *const* submsgs;
+  const upb_msglayout_field *fields;
+  /* Must be aligned to sizeof(void*).  Doesn't include internal members like
+   * unknown fields, extension dict, pointer to msglayout, etc. */
+  uint16_t size;
+  uint16_t field_count;
+  bool extendable;
+  uint8_t table_mask;
+  /* To constant-initialize the tables of variable length, we need a flexible
+   * array member, and we need to compile in C99 mode. */
+  _upb_fasttable_entry fasttable[];
+};
+
+/** upb_msg *******************************************************************/
+
+/* Internal members of a upb_msg.  We can change this without breaking binary
+ * compatibility.  We put these before the user's data.  The user's upb_msg*
+ * points after the upb_msg_internal. */
+
+typedef struct {
+  uint32_t len;
+  uint32_t size;
+  /* Data follows. */
+} upb_msg_unknowndata;
+
+/* Used when a message is not extendable. */
+typedef struct {
+  upb_msg_unknowndata *unknown;
+} upb_msg_internal;
+
+/* Maps upb_fieldtype_t -> memory size. */
+extern char _upb_fieldtype_to_size[12];
+
+UPB_INLINE size_t upb_msg_sizeof(const upb_msglayout *l) {
+  return l->size + sizeof(upb_msg_internal);
+}
+
+UPB_INLINE upb_msg *_upb_msg_new_inl(const upb_msglayout *l, upb_arena *a) {
+  size_t size = upb_msg_sizeof(l);
+  void *mem = upb_arena_malloc(a, size);
+  upb_msg *msg;
+  if (UPB_UNLIKELY(!mem)) return NULL;
+  msg = UPB_PTR_AT(mem, sizeof(upb_msg_internal), upb_msg);
+  memset(mem, 0, size);
+  return msg;
+}
+
+/* Creates a new messages with the given layout on the given arena. */
+upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a);
+
+UPB_INLINE upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
+  ptrdiff_t size = sizeof(upb_msg_internal);
+  return (upb_msg_internal*)((char*)msg - size);
+}
+
+/* Clears the given message. */
+void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l);
+
+/* Discards the unknown fields for this message only. */
+void _upb_msg_discardunknown_shallow(upb_msg *msg);
+
+/* Adds unknown data (serialized protobuf data) to the given message.  The data
+ * is copied into the message instance. */
+bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                         upb_arena *arena);
+
+/** Hasbit access *************************************************************/
+
+UPB_INLINE bool _upb_hasbit(const upb_msg *msg, size_t idx) {
+  return (*UPB_PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
+}
+
+UPB_INLINE void _upb_sethas(const upb_msg *msg, size_t idx) {
+  (*UPB_PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
+}
+
+UPB_INLINE void _upb_clearhas(const upb_msg *msg, size_t idx) {
+  (*UPB_PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
+}
+
+UPB_INLINE size_t _upb_msg_hasidx(const upb_msglayout_field *f) {
+  UPB_ASSERT(f->presence > 0);
+  return f->presence;
+}
+
+UPB_INLINE bool _upb_hasbit_field(const upb_msg *msg,
+                                  const upb_msglayout_field *f) {
+  return _upb_hasbit(msg, _upb_msg_hasidx(f));
+}
+
+UPB_INLINE void _upb_sethas_field(const upb_msg *msg,
+                                  const upb_msglayout_field *f) {
+  _upb_sethas(msg, _upb_msg_hasidx(f));
+}
+
+UPB_INLINE void _upb_clearhas_field(const upb_msg *msg,
+                                    const upb_msglayout_field *f) {
+  _upb_clearhas(msg, _upb_msg_hasidx(f));
+}
+
+/** Oneof case access *********************************************************/
+
+UPB_INLINE uint32_t *_upb_oneofcase(upb_msg *msg, size_t case_ofs) {
+  return UPB_PTR_AT(msg, case_ofs, uint32_t);
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase(const void *msg, size_t case_ofs) {
+  return *UPB_PTR_AT(msg, case_ofs, uint32_t);
+}
+
+UPB_INLINE size_t _upb_oneofcase_ofs(const upb_msglayout_field *f) {
+  UPB_ASSERT(f->presence < 0);
+  return ~(ptrdiff_t)f->presence;
+}
+
+UPB_INLINE uint32_t *_upb_oneofcase_field(upb_msg *msg,
+                                          const upb_msglayout_field *f) {
+  return _upb_oneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_msg *msg,
+                                            const upb_msglayout_field *f) {
+  return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_msg *msg, size_t ofs) {
+  return *UPB_PTR_AT(msg, ofs, const upb_msg*) != NULL;
+}
+
+UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) {
+  return (field->label & 3) == UPB_LABEL_REPEATED;
+}
+
+UPB_INLINE bool _upb_repeated_or_map(const upb_msglayout_field *field) {
+  return field->label >= UPB_LABEL_REPEATED;
+}
+
+/** upb_array *****************************************************************/
+
+/* Our internal representation for repeated fields.  */
+typedef struct {
+  uintptr_t data;   /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
+  size_t len;   /* Measured in elements. */
+  size_t size;  /* Measured in elements. */
+  uint64_t junk;
+} upb_array;
+
+UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) {
+  UPB_ASSERT((arr->data & 7) <= 4);
+  return (void*)(arr->data & ~(uintptr_t)7);
+}
+
+UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) {
+  UPB_ASSERT(elem_size_lg2 <= 4);
+  return (uintptr_t)ptr | elem_size_lg2;
+}
+
+UPB_INLINE void *_upb_array_ptr(upb_array *arr) {
+  return (void*)_upb_array_constptr(arr);
+}
+
+UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) {
+  UPB_ASSERT(elem_size_lg2 <= 4);
+  UPB_ASSERT(((uintptr_t)ptr & 7) == 0);
+  return (uintptr_t)ptr | (unsigned)elem_size_lg2;
+}
+
+UPB_INLINE upb_array *_upb_array_new(upb_arena *a, size_t init_size,
+                                     int elem_size_lg2) {
+  const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_array), 8);
+  const size_t bytes = sizeof(upb_array) + (init_size << elem_size_lg2);
+  upb_array *arr = (upb_array*)upb_arena_malloc(a, bytes);
+  if (!arr) return NULL;
+  arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2);
+  arr->len = 0;
+  arr->size = init_size;
+  return arr;
+}
+
+/* Resizes the capacity of the array to be at least min_size. */
+bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena);
+
+/* Fallback functions for when the accessors require a resize. */
+void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
+                                 int elem_size_lg2, upb_arena *arena);
+bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
+                                int elem_size_lg2, upb_arena *arena);
+
+UPB_INLINE bool _upb_array_reserve(upb_array *arr, size_t size,
+                                   upb_arena *arena) {
+  if (arr->size < size) return _upb_array_realloc(arr, size, arena);
+  return true;
+}
+
+UPB_INLINE bool _upb_array_resize(upb_array *arr, size_t size,
+                                  upb_arena *arena) {
+  if (!_upb_array_reserve(arr, size, arena)) return false;
+  arr->len = size;
+  return true;
+}
+
+UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
+                                           size_t *size) {
+  const upb_array *arr = *UPB_PTR_AT(msg, ofs, const upb_array*);
+  if (arr) {
+    if (size) *size = arr->len;
+    return _upb_array_constptr(arr);
+  } else {
+    if (size) *size = 0;
+    return NULL;
+  }
+}
+
+UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
+                                             size_t *size) {
+  upb_array *arr = *UPB_PTR_AT(msg, ofs, upb_array*);
+  if (arr) {
+    if (size) *size = arr->len;
+    return _upb_array_ptr(arr);
+  } else {
+    if (size) *size = 0;
+    return NULL;
+  }
+}
+
+UPB_INLINE void *_upb_array_resize_accessor2(void *msg, size_t ofs, size_t size,
+                                             int elem_size_lg2,
+                                             upb_arena *arena) {
+  upb_array **arr_ptr = UPB_PTR_AT(msg, ofs, upb_array *);
+  upb_array *arr = *arr_ptr;
+  if (!arr || arr->size < size) {
+    return _upb_array_resize_fallback(arr_ptr, size, elem_size_lg2, arena);
+  }
+  arr->len = size;
+  return _upb_array_ptr(arr);
+}
+
+UPB_INLINE bool _upb_array_append_accessor2(void *msg, size_t ofs,
+                                            int elem_size_lg2,
+                                            const void *value,
+                                            upb_arena *arena) {
+  upb_array **arr_ptr = UPB_PTR_AT(msg, ofs, upb_array *);
+  size_t elem_size = 1 << elem_size_lg2;
+  upb_array *arr = *arr_ptr;
+  void *ptr;
+  if (!arr || arr->len == arr->size) {
+    return _upb_array_append_fallback(arr_ptr, value, elem_size_lg2, arena);
+  }
+  ptr = _upb_array_ptr(arr);
+  memcpy(UPB_PTR_AT(ptr, arr->len * elem_size, char), value, elem_size);
+  arr->len++;
+  return true;
+}
+
+/* Used by old generated code, remove once all code has been regenerated. */
+UPB_INLINE int _upb_sizelg2(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_BOOL:
+      return 0;
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return 2;
+    case UPB_TYPE_MESSAGE:
+      return UPB_SIZE(2, 3);
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return 3;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return UPB_SIZE(3, 4);
+  }
+  UPB_UNREACHABLE();
+}
+UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
+                                             upb_fieldtype_t type,
+                                             upb_arena *arena) {
+  return _upb_array_resize_accessor2(msg, ofs, size, _upb_sizelg2(type), arena);
+}
+UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
+                                            size_t elem_size, upb_fieldtype_t type,
+                                            const void *value,
+                                            upb_arena *arena) {
+  (void)elem_size;
+  return _upb_array_append_accessor2(msg, ofs, _upb_sizelg2(type), value,
+                                     arena);
+}
+
+/** upb_map *******************************************************************/
+
+/* Right now we use strmaps for everything.  We'll likely want to use
+ * integer-specific maps for integer-keyed maps.*/
+typedef struct {
+  /* Size of key and val, based on the map type.  Strings are represented as '0'
+   * because they must be handled specially. */
+  char key_size;
+  char val_size;
+
+  upb_strtable table;
+} upb_map;
+
+/* Map entries aren't actually stored, they are only used during parsing.  For
+ * parsing, it helps a lot if all map entry messages have the same layout.
+ * The compiler and def.c must ensure that all map entries have this layout. */
+typedef struct {
+  upb_msg_internal internal;
+  union {
+    upb_strview str;  /* For str/bytes. */
+    upb_value val;    /* For all other types. */
+  } k;
+  union {
+    upb_strview str;  /* For str/bytes. */
+    upb_value val;    /* For all other types. */
+  } v;
+} upb_map_entry;
+
+/* Creates a new map on the given arena with this key/value type. */
+upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size);
+
+/* Converting between internal table representation and user values.
+ *
+ * _upb_map_tokey() and _upb_map_fromkey() are inverses.
+ * _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
+ *
+ * These functions account for the fact that strings are treated differently
+ * from other types when stored in a map.
+ */
+
+UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    return *(upb_strview*)key;
+  } else {
+    return upb_strview_make((const char*)key, size);
+  }
+}
+
+UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    memcpy(out, &key, sizeof(key));
+  } else {
+    memcpy(out, key.data, size);
+  }
+}
+
+UPB_INLINE bool _upb_map_tovalue(const void *val, size_t size, upb_value *msgval,
+                                 upb_arena *a) {
+  if (size == UPB_MAPTYPE_STRING) {
+    upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp));
+    if (!strp) return false;
+    *strp = *(upb_strview*)val;
+    *msgval = upb_value_ptr(strp);
+  } else {
+    memcpy(msgval, val, size);
+  }
+  return true;
+}
+
+UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    const upb_strview *strp = (const upb_strview*)upb_value_getptr(val);
+    memcpy(out, strp, sizeof(upb_strview));
+  } else {
+    memcpy(out, &val, size);
+  }
+}
+
+/* Map operations, shared by reflection and generated code. */
+
+UPB_INLINE size_t _upb_map_size(const upb_map *map) {
+  return map->table.t.count;
+}
+
+UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key,
+                             size_t key_size, void *val, size_t val_size) {
+  upb_value tabval;
+  upb_strview k = _upb_map_tokey(key, key_size);
+  bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
+  if (ret && val) {
+    _upb_map_fromvalue(tabval, val, val_size);
+  }
+  return ret;
+}
+
+UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) {
+  upb_strtable_iter it;
+  it.t = &map->table;
+  it.index = *iter;
+  upb_strtable_next(&it);
+  *iter = it.index;
+  if (upb_strtable_done(&it)) return NULL;
+  return (void*)str_tabent(&it);
+}
+
+UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size,
+                             void *val, size_t val_size, upb_arena *a) {
+  upb_strview strkey = _upb_map_tokey(key, key_size);
+  upb_value tabval = {0};
+  if (!_upb_map_tovalue(val, val_size, &tabval, a)) return false;
+
+  /* TODO(haberman): add overwrite operation to minimize number of lookups. */
+  upb_strtable_remove(&map->table, strkey.data, strkey.size, NULL);
+  return upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a);
+}
+
+UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) {
+  upb_strview k = _upb_map_tokey(key, key_size);
+  return upb_strtable_remove(&map->table, k.data, k.size, NULL);
+}
+
+UPB_INLINE void _upb_map_clear(upb_map *map) {
+  upb_strtable_clear(&map->table);
+}
+
+/* Message map operations, these get the map from the message first. */
+
+UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  return map ? _upb_map_size(map) : 0;
+}
+
+UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs,
+                                 const void *key, size_t key_size, void *val,
+                                 size_t val_size) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return false;
+  return _upb_map_get(map, key, key_size, val, val_size);
+}
+
+UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs,
+                                   size_t *iter) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return NULL;
+  return _upb_map_next(map, iter);
+}
+
+UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key,
+                                 size_t key_size, void *val, size_t val_size,
+                                 upb_arena *arena) {
+  upb_map **map = UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!*map) {
+    *map = _upb_map_new(arena, key_size, val_size);
+  }
+  return _upb_map_set(*map, key, key_size, val, val_size, arena);
+}
+
+UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key,
+                                    size_t key_size) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return false;
+  return _upb_map_delete(map, key, key_size);
+}
+
+UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return;
+  _upb_map_clear(map);
+}
+
+/* Accessing map key/value from a pointer, used by generated code only. */
+
+UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) {
+  const upb_tabent *ent = (const upb_tabent*)msg;
+  uint32_t u32len;
+  upb_strview k;
+  k.data = upb_tabstr(ent->key, &u32len);
+  k.size = u32len;
+  _upb_map_fromkey(k, key, size);
+}
+
+UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) {
+  const upb_tabent *ent = (const upb_tabent*)msg;
+  upb_value v = {ent->val.val};
+  _upb_map_fromvalue(v, val, size);
+}
+
+UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) {
+  upb_tabent *ent = (upb_tabent*)msg;
+  /* This is like _upb_map_tovalue() except the entry already exists so we can
+   * reuse the allocated upb_strview for string fields. */
+  if (size == UPB_MAPTYPE_STRING) {
+    upb_strview *strp = (upb_strview*)(uintptr_t)ent->val.val;
+    memcpy(strp, val, sizeof(*strp));
+  } else {
+    memcpy(&ent->val.val, val, size);
+  }
+}
+
+/** _upb_mapsorter *************************************************************/
+
+/* _upb_mapsorter sorts maps and provides ordered iteration over the entries.
+ * Since maps can be recursive (map values can be messages which contain other maps).
+ * _upb_mapsorter can contain a stack of maps. */
+
+typedef struct {
+  upb_tabent const**entries;
+  int size;
+  int cap;
+} _upb_mapsorter;
+
+typedef struct {
+  int start;
+  int pos;
+  int end;
+} _upb_sortedmap;
+
+UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter *s) {
+  s->entries = NULL;
+  s->size = 0;
+  s->cap = 0;
+}
+
+UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter *s) {
+  if (s->entries) free(s->entries);
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+                            const upb_map *map, _upb_sortedmap *sorted);
+
+UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter *s, _upb_sortedmap *sorted) {
+  s->size = sorted->start;
+}
+
+UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter *s, const upb_map *map,
+                                    _upb_sortedmap *sorted,
+                                    upb_map_entry *ent) {
+  if (sorted->pos == sorted->end) return false;
+  const upb_tabent *tabent = s->entries[sorted->pos++];
+  upb_strview key = upb_tabstrview(tabent->key);
+  _upb_map_fromkey(key, &ent->k, map->key_size);
+  upb_value val = {tabent->val.val};
+  _upb_map_fromvalue(val, &ent->v, map->val_size);
+  return true;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif /* UPB_MSG_INT_H_ */
+
+/** upb/upb_internal.h ************************************************************/
+#ifndef UPB_INT_H_
+#define UPB_INT_H_
+
+
+struct mem_block;
+typedef struct mem_block mem_block;
+
+struct upb_arena {
+  _upb_arena_head head;
+  /* Stores cleanup metadata for this arena.
+   * - a pointer to the current cleanup counter.
+   * - a boolean indicating if there is an unowned initial block.  */
+  uintptr_t cleanup_metadata;
+
+  /* Allocator to allocate arena blocks.  We are responsible for freeing these
+   * when we are destroyed. */
+  upb_alloc *block_alloc;
+  uint32_t last_size;
+
+  /* When multiple arenas are fused together, each arena points to a parent
+   * arena (root points to itself). The root tracks how many live arenas
+   * reference it. */
+  uint32_t refcount;  /* Only used when a->parent == a */
+  struct upb_arena *parent;
+
+  /* Linked list of blocks to free/cleanup. */
+  mem_block *freelist, *freelist_tail;
+};
+
+#endif  /* UPB_INT_H_ */
+
+/* Must be last. */
+
+#define DECODE_NOGROUP (uint32_t)-1
+
+typedef struct upb_decstate {
+  const char *end;         /* Can read up to 16 bytes slop beyond this. */
+  const char *limit_ptr;   /* = end + UPB_MIN(limit, 0) */
+  upb_msg *unknown_msg;    /* If non-NULL, add unknown data at buffer flip. */
+  const char *unknown;     /* Start of unknown data. */
+  int limit;               /* Submessage limit relative to end. */
+  int depth;
+  uint32_t end_group;   /* field number of END_GROUP tag, else DECODE_NOGROUP */
+  bool alias;
+  char patch[32];
+  upb_arena arena;
+  jmp_buf err;
+} upb_decstate;
+
+/* Error function that will abort decoding with longjmp(). We can't declare this
+ * UPB_NORETURN, even though it is appropriate, because if we do then compilers
+ * will "helpfully" refuse to tailcall to it
+ * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal
+ * of our optimizations. That is also why we must declare it in a separate file,
+ * otherwise the compiler will see that it calls longjmp() and deduce that it is
+ * noreturn. */
+const char *fastdecode_err(upb_decstate *d);
+
+extern const uint8_t upb_utf8_offsets[];
+
+UPB_INLINE
+bool decode_verifyutf8_inl(const char *buf, int len) {
+  int i, j;
+  uint8_t offset;
+
+  i = 0;
+  while (i < len) {
+    offset = upb_utf8_offsets[(uint8_t)buf[i]];
+    if (offset == 0 || i + offset > len) {
+      return false;
+    }
+    for (j = i + 1; j < i + offset; j++) {
+      if ((buf[j] & 0xc0) != 0x80) {
+        return false;
+      }
+    }
+    i += offset;
+  }
+  return i == len;
+}
+
+/* x86-64 pointers always have the high 16 bits matching. So we can shift
+ * left 8 and right 8 without loss of information. */
+UPB_INLINE intptr_t decode_totable(const upb_msglayout *tablep) {
+  return ((intptr_t)tablep << 8) | tablep->table_mask;
+}
+
+UPB_INLINE const upb_msglayout *decode_totablep(intptr_t table) {
+  return (const upb_msglayout*)(table >> 8);
+}
+
+UPB_INLINE
+const char *decode_isdonefallback_inl(upb_decstate *d, const char *ptr,
+                                      int overrun) {
+  if (overrun < d->limit) {
+    /* Need to copy remaining data into patch buffer. */
+    UPB_ASSERT(overrun < 16);
+    if (d->unknown_msg) {
+      if (!_upb_msg_addunknown(d->unknown_msg, d->unknown, ptr - d->unknown,
+                               &d->arena)) {
+        return NULL;
+      }
+      d->unknown = &d->patch[0] + overrun;
+    }
+    memset(d->patch + 16, 0, 16);
+    memcpy(d->patch, d->end, 16);
+    ptr = &d->patch[0] + overrun;
+    d->end = &d->patch[16];
+    d->limit -= 16;
+    d->limit_ptr = d->end + d->limit;
+    d->alias = false;
+    UPB_ASSERT(ptr < d->limit_ptr);
+    return ptr;
+  } else {
+    return NULL;
+  }
+}
+
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+                                  int overrun);
+
+UPB_INLINE
+bool decode_isdone(upb_decstate *d, const char **ptr) {
+  int overrun = *ptr - d->end;
+  if (UPB_LIKELY(*ptr < d->limit_ptr)) {
+    return false;
+  } else if (UPB_LIKELY(overrun == d->limit)) {
+    return true;
+  } else {
+    *ptr = decode_isdonefallback(d, *ptr, overrun);
+    return false;
+  }
+}
+
+#if UPB_FASTTABLE
+UPB_INLINE
+const char *fastdecode_tagdispatch(upb_decstate *d, const char *ptr,
+                                    upb_msg *msg, intptr_t table,
+                                    uint64_t hasbits, uint64_t tag) {
+  const upb_msglayout *table_p = decode_totablep(table);
+  uint8_t mask = table;
+  uint64_t data;
+  size_t idx = tag & mask;
+  UPB_ASSUME((idx & 7) == 0);
+  idx >>= 3;
+  data = table_p->fasttable[idx].field_data ^ tag;
+  UPB_MUSTTAIL return table_p->fasttable[idx].field_parser(d, ptr, msg, table,
+                                                           hasbits, data);
+}
+#endif
+
+UPB_INLINE uint32_t fastdecode_loadtag(const char* ptr) {
+  uint16_t tag;
+  memcpy(&tag, ptr, 2);
+  return tag;
+}
+
+UPB_INLINE void decode_checklimit(upb_decstate *d) {
+  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+}
+
+UPB_INLINE int decode_pushlimit(upb_decstate *d, const char *ptr, int size) {
+  int limit = size + (int)(ptr - d->end);
+  int delta = d->limit - limit;
+  decode_checklimit(d);
+  d->limit = limit;
+  d->limit_ptr = d->end + UPB_MIN(0, limit);
+  decode_checklimit(d);
+  return delta;
+}
+
+UPB_INLINE void decode_poplimit(upb_decstate *d, const char *ptr,
+                                int saved_delta) {
+  UPB_ASSERT(ptr - d->end == d->limit);
+  decode_checklimit(d);
+  d->limit += saved_delta;
+  d->limit_ptr = d->end + UPB_MIN(0, d->limit);
+  decode_checklimit(d);
+}
+
+
+#endif  /* UPB_DECODE_INT_H_ */
+
+/** upb/encode.h ************************************************************/
+/*
+ * upb_encode: parsing into a upb_msg using a upb_msglayout.
+ */
+
+#ifndef UPB_ENCODE_H_
+#define UPB_ENCODE_H_
+
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* If set, the results of serializing will be deterministic across all
+   * instances of this binary. There are no guarantees across different
+   * binary builds.
+   *
+   * If your proto contains maps, the encoder will need to malloc()/free()
+   * memory during encode. */
+  UPB_ENCODE_DETERMINISTIC = 1,
+
+  /* When set, unknown fields are not printed. */
+  UPB_ENCODE_SKIPUNKNOWN = 2,
+};
+
+#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+
+char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
+                    upb_arena *arena, size_t *size);
+
+UPB_INLINE char *upb_encode(const void *msg, const upb_msglayout *l,
+                            upb_arena *arena, size_t *size) {
+  return upb_encode_ex(msg, l, 0, arena, size);
+}
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_ENCODE_H_ */
+
+/** upb/decode_fast.h ************************************************************/
+// These are the specialized field parser functions for the fast parser.
+// Generated tables will refer to these by name.
+//
+// The function names are encoded with names like:
+//
+//   //  123 4
+//   upb_pss_1bt();   // Parse singular string, 1 byte tag.
+//
+// In position 1:
+//   - 'p' for parse, most function use this
+//   - 'c' for copy, for when we are copying strings instead of aliasing
+//
+// In position 2 (cardinality):
+//   - 's' for singular, with or without hasbit
+//   - 'o' for oneof
+//   - 'r' for non-packed repeated
+//   - 'p' for packed repeated
+//
+// In position 3 (type):
+//   - 'b1' for bool
+//   - 'v4' for 4-byte varint
+//   - 'v8' for 8-byte varint
+//   - 'z4' for zig-zag-encoded 4-byte varint
+//   - 'z8' for zig-zag-encoded 8-byte varint
+//   - 'f4' for 4-byte fixed
+//   - 'f8' for 8-byte fixed
+//   - 'm' for sub-message
+//   - 's' for string (validate UTF-8)
+//   - 'b' for bytes
+//
+// In position 4 (tag length):
+//   - '1' for one-byte tags (field numbers 1-15)
+//   - '2' for two-byte tags (field numbers 16-2048)
+
+#ifndef UPB_DECODE_FAST_H_
+#define UPB_DECODE_FAST_H_
+
+
+struct upb_decstate;
+
+// The fallback, generic parsing function that can handle any field type.
+// This just uses the regular (non-fast) parser to parse a single field.
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+                               upb_msg *msg, intptr_t table, uint64_t hasbits,
+                               uint64_t data);
+
+#define UPB_PARSE_PARAMS                                                 \
+  struct upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+      uint64_t hasbits, uint64_t data
+
+/* primitive fields ***********************************************************/
+
+#define F(card, type, valbytes, tagbytes) \
+  const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define TYPES(card, tagbytes) \
+  F(card, b, 1, tagbytes)     \
+  F(card, v, 4, tagbytes)     \
+  F(card, v, 8, tagbytes)     \
+  F(card, z, 4, tagbytes)     \
+  F(card, z, 8, tagbytes)     \
+  F(card, f, 4, tagbytes)     \
+  F(card, f, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+/* string fields **************************************************************/
+
+#define F(card, tagbytes, type)                                     \
+  const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \
+  const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define UTF8(card, tagbytes) \
+  F(card, tagbytes, s)       \
+  F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+  UTF8(card, 1)        \
+  UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef F
+#undef TAGBYTES
+
+/* sub-message fields *********************************************************/
+
+#define F(card, tagbytes, size_ceil, ceil_arg) \
+  const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS);
+
+#define SIZES(card, tagbytes) \
+  F(card, tagbytes, 64, 64) \
+  F(card, tagbytes, 128, 128) \
+  F(card, tagbytes, 192, 192) \
+  F(card, tagbytes, 256, 256) \
+  F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+  SIZES(card, 1) \
+  SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+
+#undef UPB_PARSE_PARAMS
+
+#endif  /* UPB_DECODE_FAST_H_ */
+
+/** google/protobuf/descriptor.upb.h ************************************************************//* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
+#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct google_protobuf_FileDescriptorSet;
+struct google_protobuf_FileDescriptorProto;
+struct google_protobuf_DescriptorProto;
+struct google_protobuf_DescriptorProto_ExtensionRange;
+struct google_protobuf_DescriptorProto_ReservedRange;
+struct google_protobuf_ExtensionRangeOptions;
+struct google_protobuf_FieldDescriptorProto;
+struct google_protobuf_OneofDescriptorProto;
+struct google_protobuf_EnumDescriptorProto;
+struct google_protobuf_EnumDescriptorProto_EnumReservedRange;
+struct google_protobuf_EnumValueDescriptorProto;
+struct google_protobuf_ServiceDescriptorProto;
+struct google_protobuf_MethodDescriptorProto;
+struct google_protobuf_FileOptions;
+struct google_protobuf_MessageOptions;
+struct google_protobuf_FieldOptions;
+struct google_protobuf_OneofOptions;
+struct google_protobuf_EnumOptions;
+struct google_protobuf_EnumValueOptions;
+struct google_protobuf_ServiceOptions;
+struct google_protobuf_MethodOptions;
+struct google_protobuf_UninterpretedOption;
+struct google_protobuf_UninterpretedOption_NamePart;
+struct google_protobuf_SourceCodeInfo;
+struct google_protobuf_SourceCodeInfo_Location;
+struct google_protobuf_GeneratedCodeInfo;
+struct google_protobuf_GeneratedCodeInfo_Annotation;
+typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet;
+typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto;
+typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto;
+typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange;
+typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange;
+typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions;
+typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto;
+typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto;
+typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto;
+typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange;
+typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto;
+typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto;
+typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto;
+typedef struct google_protobuf_FileOptions google_protobuf_FileOptions;
+typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions;
+typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions;
+typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions;
+typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions;
+typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions;
+typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions;
+typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions;
+typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption;
+typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart;
+typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo;
+typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location;
+typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo;
+typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation;
+extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
+extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
+extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
+extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_FileOptions_msginit;
+extern const upb_msglayout google_protobuf_MessageOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldOptions_msginit;
+extern const upb_msglayout google_protobuf_OneofOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
+extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
+extern const upb_msglayout google_protobuf_MethodOptions_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
+  google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
+  google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
+} google_protobuf_FieldDescriptorProto_Label;
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
+  google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
+  google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
+  google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
+  google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
+  google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
+  google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
+  google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
+  google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
+  google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
+} google_protobuf_FieldDescriptorProto_Type;
+
+typedef enum {
+  google_protobuf_FieldOptions_STRING = 0,
+  google_protobuf_FieldOptions_CORD = 1,
+  google_protobuf_FieldOptions_STRING_PIECE = 2
+} google_protobuf_FieldOptions_CType;
+
+typedef enum {
+  google_protobuf_FieldOptions_JS_NORMAL = 0,
+  google_protobuf_FieldOptions_JS_STRING = 1,
+  google_protobuf_FieldOptions_JS_NUMBER = 2
+} google_protobuf_FieldOptions_JSType;
+
+typedef enum {
+  google_protobuf_FileOptions_SPEED = 1,
+  google_protobuf_FileOptions_CODE_SIZE = 2,
+  google_protobuf_FileOptions_LITE_RUNTIME = 3
+} google_protobuf_FileOptions_OptimizeMode;
+
+typedef enum {
+  google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
+  google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
+  google_protobuf_MethodOptions_IDEMPOTENT = 2
+} google_protobuf_MethodOptions_IdempotencyLevel;
+
+
+/* google.protobuf.FileDescriptorSet */
+
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) {
+  return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) {
+  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) {
+  struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FileDescriptorProto */
+
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
+UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); }
+UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); }
+UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); }
+UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
+
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+}
+UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(36, 72), UPB_SIZE(3, 4), &val,
+      arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(44, 88), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 96), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(48, 96), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(52, 104), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(52, 104), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FileDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value;
+}
+UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 112), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(56, 112), 2, &val,
+      arena);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(60, 120), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(60, 120), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
+}
+
+/* google.protobuf.DescriptorProto */
+
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); }
+UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); }
+UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
+UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
+UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(32, 64), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(32, 64), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_DescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(36, 72), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+}
+UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.DescriptorProto.ExtensionRange */
+
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) {
+  struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.DescriptorProto.ReservedRange */
+
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+/* google.protobuf.ExtensionRangeOptions */
+
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) {
+  return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FieldDescriptorProto */
+
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); }
+UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(64, 104), const google_protobuf_FieldOptions*); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 11); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); }
+
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 7);
+  *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
+  _upb_sethas(msg, 8);
+  *UPB_PTR_AT(msg, UPB_SIZE(64, 104), google_protobuf_FieldOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 9);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 10);
+  *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 11);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value;
+}
+
+/* google.protobuf.OneofDescriptorProto */
+
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); }
+
+UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.EnumDescriptorProto */
+
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+
+UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.EnumDescriptorProto.EnumReservedRange */
+
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+/* google.protobuf.EnumValueDescriptorProto */
+
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); }
+
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.ServiceDescriptorProto */
+
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); }
+
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.MethodDescriptorProto */
+
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+
+/* google.protobuf.FileOptions */
+
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) {
+  return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 8); }
+UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 9); }
+UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 11); }
+UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 12); }
+UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 18); }
+UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 19); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 20); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(100, 184)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(100, 184), len); }
+
+UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 7);
+  *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 8);
+  *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 9);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 10);
+  *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 11);
+  *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 12);
+  *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 13);
+  *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 14);
+  *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 15);
+  *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 16);
+  *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 17);
+  *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 18);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 19);
+  *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 20);
+  *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(100, 184), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(100, 184), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(100, 184), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.MessageOptions */
+
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) {
+  return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); }
+
+UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(8, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FieldOptions */
+
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) {
+  return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 16)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(16, 16), len); }
+
+UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 16), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 16), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 16), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.OneofOptions */
+
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) {
+  return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.EnumOptions */
+
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) {
+  return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.EnumValueOptions */
+
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) {
+  return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.ServiceOptions */
+
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) {
+  return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.MethodOptions */
+
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) {
+  return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); }
+UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 16)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(12, 16), len); }
+
+UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value;
+}
+UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 16), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 16), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(12, 16), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.UninterpretedOption */
+
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+}
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); }
+UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); }
+
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(56, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value;
+}
+
+/* google.protobuf.UninterpretedOption.NamePart */
+
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+
+/* google.protobuf.SourceCodeInfo */
+
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) {
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) {
+  struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.SourceCodeInfo.Location */
+
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
+}
+
+UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
+
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(20, 40), 2, &val,
+      arena);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
+}
+UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.GeneratedCodeInfo */
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) {
+  struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.GeneratedCodeInfo.Annotation */
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
+}
+
+UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len);
+}
+UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 32), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(20, 32), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
+
+/** upb/def.h ************************************************************/
+/*
+ * Defs are upb's internal representation of the constructs that can appear
+ * in a .proto file:
+ *
+ * - upb_msgdef: describes a "message" construct.
+ * - upb_fielddef: describes a message field.
+ * - upb_filedef: describes a .proto file and its defs.
+ * - upb_enumdef: describes an enum.
+ * - upb_oneofdef: describes a oneof.
+ *
+ * TODO: definitions of services.
+ */
+
+#ifndef UPB_DEF_H_
+#define UPB_DEF_H_
+
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* __cplusplus */
+
+struct upb_enumdef;
+typedef struct upb_enumdef upb_enumdef;
+struct upb_fielddef;
+typedef struct upb_fielddef upb_fielddef;
+struct upb_filedef;
+typedef struct upb_filedef upb_filedef;
+struct upb_msgdef;
+typedef struct upb_msgdef upb_msgdef;
+struct upb_oneofdef;
+typedef struct upb_oneofdef upb_oneofdef;
+struct upb_symtab;
+typedef struct upb_symtab upb_symtab;
+
+typedef enum {
+  UPB_SYNTAX_PROTO2 = 2,
+  UPB_SYNTAX_PROTO3 = 3
+} upb_syntax_t;
+
+/* All the different kind of well known type messages. For simplicity of check,
+ * number wrappers and string wrappers are grouped together. Make sure the
+ * order and merber of these groups are not changed.
+ */
+typedef enum {
+  UPB_WELLKNOWN_UNSPECIFIED,
+  UPB_WELLKNOWN_ANY,
+  UPB_WELLKNOWN_FIELDMASK,
+  UPB_WELLKNOWN_DURATION,
+  UPB_WELLKNOWN_TIMESTAMP,
+  /* number wrappers */
+  UPB_WELLKNOWN_DOUBLEVALUE,
+  UPB_WELLKNOWN_FLOATVALUE,
+  UPB_WELLKNOWN_INT64VALUE,
+  UPB_WELLKNOWN_UINT64VALUE,
+  UPB_WELLKNOWN_INT32VALUE,
+  UPB_WELLKNOWN_UINT32VALUE,
+  /* string wrappers */
+  UPB_WELLKNOWN_STRINGVALUE,
+  UPB_WELLKNOWN_BYTESVALUE,
+  UPB_WELLKNOWN_BOOLVALUE,
+  UPB_WELLKNOWN_VALUE,
+  UPB_WELLKNOWN_LISTVALUE,
+  UPB_WELLKNOWN_STRUCT
+} upb_wellknowntype_t;
+
+/* upb_fielddef ***************************************************************/
+
+/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
+ * protobuf wire format. */
+#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
+
+const char *upb_fielddef_fullname(const upb_fielddef *f);
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
+upb_label_t upb_fielddef_label(const upb_fielddef *f);
+uint32_t upb_fielddef_number(const upb_fielddef *f);
+const char *upb_fielddef_name(const upb_fielddef *f);
+const char *upb_fielddef_jsonname(const upb_fielddef *f);
+bool upb_fielddef_isextension(const upb_fielddef *f);
+bool upb_fielddef_lazy(const upb_fielddef *f);
+bool upb_fielddef_packed(const upb_fielddef *f);
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f);
+uint32_t upb_fielddef_index(const upb_fielddef *f);
+bool upb_fielddef_issubmsg(const upb_fielddef *f);
+bool upb_fielddef_isstring(const upb_fielddef *f);
+bool upb_fielddef_isseq(const upb_fielddef *f);
+bool upb_fielddef_isprimitive(const upb_fielddef *f);
+bool upb_fielddef_ismap(const upb_fielddef *f);
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
+bool upb_fielddef_defaultbool(const upb_fielddef *f);
+float upb_fielddef_defaultfloat(const upb_fielddef *f);
+double upb_fielddef_defaultdouble(const upb_fielddef *f);
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
+bool upb_fielddef_hassubdef(const upb_fielddef *f);
+bool upb_fielddef_haspresence(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f);
+
+/* upb_oneofdef ***************************************************************/
+
+typedef upb_inttable_iter upb_oneof_iter;
+
+const char *upb_oneofdef_name(const upb_oneofdef *o);
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
+uint32_t upb_oneofdef_index(const upb_oneofdef *o);
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o);
+int upb_oneofdef_fieldcount(const upb_oneofdef *o);
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i);
+
+/* Oneof lookups:
+ * - ntof:  look up a field by name.
+ * - ntofz: look up a field by name (as a null-terminated string).
+ * - itof:  look up a field by number. */
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length);
+UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
+                                                  const char *name) {
+  return upb_oneofdef_ntof(o, name, strlen(name));
+}
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
+
+/* DEPRECATED, slated for removal. */
+int upb_oneofdef_numfields(const upb_oneofdef *o);
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
+void upb_oneof_next(upb_oneof_iter *iter);
+bool upb_oneof_done(upb_oneof_iter *iter);
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
+void upb_oneof_iter_setdone(upb_oneof_iter *iter);
+bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
+                            const upb_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_msgdef *****************************************************************/
+
+typedef upb_inttable_iter upb_msg_field_iter;
+typedef upb_strtable_iter upb_msg_oneof_iter;
+
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY   1
+#define UPB_MAPENTRY_VALUE 2
+
+/* Well-known field tag numbers for Any messages. */
+#define UPB_ANY_TYPE 1
+#define UPB_ANY_VALUE 2
+
+/* Well-known field tag numbers for timestamp messages. */
+#define UPB_DURATION_SECONDS 1
+#define UPB_DURATION_NANOS 2
+
+/* Well-known field tag numbers for duration messages. */
+#define UPB_TIMESTAMP_SECONDS 1
+#define UPB_TIMESTAMP_NANOS 2
+
+const char *upb_msgdef_fullname(const upb_msgdef *m);
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
+const char *upb_msgdef_name(const upb_msgdef *m);
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
+bool upb_msgdef_iswrapper(const upb_msgdef *m);
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
+int upb_msgdef_fieldcount(const upb_msgdef *m);
+int upb_msgdef_oneofcount(const upb_msgdef *m);
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i);
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i);
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len);
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len);
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m);
+
+UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
+                                               const char *name) {
+  return upb_msgdef_ntoo(m, name, strlen(name));
+}
+
+UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
+                                                const char *name) {
+  return upb_msgdef_ntof(m, name, strlen(name));
+}
+
+/* Lookup of either field or oneof by name.  Returns whether either was found.
+ * If the return is true, then the found def will be set, and the non-found
+ * one set to NULL. */
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o);
+
+UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
+                                       const upb_fielddef **f,
+                                       const upb_oneofdef **o) {
+  return upb_msgdef_lookupname(m, name, strlen(name), f, o);
+}
+
+/* Returns a field by either JSON name or regular proto name. */
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+                                              const char *name, size_t len);
+
+/* DEPRECATED, slated for removal */
+int upb_msgdef_numfields(const upb_msgdef *m);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+int upb_msgdef_numrealoneofs(const upb_msgdef *m);
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
+void upb_msg_field_next(upb_msg_field_iter *iter);
+bool upb_msg_field_done(const upb_msg_field_iter *iter);
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+                                const upb_msg_field_iter * iter2);
+void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
+void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+                                const upb_msg_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_enumdef ****************************************************************/
+
+typedef upb_strtable_iter upb_enum_iter;
+
+const char *upb_enumdef_fullname(const upb_enumdef *e);
+const char *upb_enumdef_name(const upb_enumdef *e);
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
+int32_t upb_enumdef_default(const upb_enumdef *e);
+int upb_enumdef_numvals(const upb_enumdef *e);
+
+/* Enum lookups:
+ * - ntoi:  look up a name with specified length.
+ * - ntoiz: look up a name provided as a null-terminated string.
+ * - iton:  look up an integer, returning the name as a null-terminated
+ *          string. */
+bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
+                      int32_t *num);
+UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
+                                  const char *name, int32_t *num) {
+  return upb_enumdef_ntoi(e, name, strlen(name), num);
+}
+const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
+
+void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
+void upb_enum_next(upb_enum_iter *iter);
+bool upb_enum_done(upb_enum_iter *iter);
+const char *upb_enum_iter_name(upb_enum_iter *iter);
+int32_t upb_enum_iter_number(upb_enum_iter *iter);
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f);
+const char *upb_filedef_package(const upb_filedef *f);
+const char *upb_filedef_phpprefix(const upb_filedef *f);
+const char *upb_filedef_phpnamespace(const upb_filedef *f);
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
+int upb_filedef_depcount(const upb_filedef *f);
+int upb_filedef_msgcount(const upb_filedef *f);
+int upb_filedef_enumcount(const upb_filedef *f);
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f);
+
+/* upb_symtab *****************************************************************/
+
+upb_symtab *upb_symtab_new(void);
+void upb_symtab_free(upb_symtab* s);
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
+const upb_msgdef *upb_symtab_lookupmsg2(
+    const upb_symtab *s, const char *sym, size_t len);
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
+const upb_filedef *upb_symtab_lookupfile2(
+    const upb_symtab *s, const char *name, size_t len);
+int upb_symtab_filecount(const upb_symtab *s);
+const upb_filedef *upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
+    upb_status *status);
+size_t _upb_symtab_bytesloaded(const upb_symtab *s);
+upb_arena *_upb_symtab_arena(const upb_symtab *s);
+
+/* For generated code only: loads a generated descriptor. */
+typedef struct upb_def_init {
+  struct upb_def_init **deps;     /* Dependencies of this file. */
+  const upb_msglayout **layouts;  /* Pre-order layouts of all messages. */
+  const char *filename;
+  upb_strview descriptor;         /* Serialized descriptor. */
+} upb_def_init;
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif  /* __cplusplus */
+
+#endif /* UPB_DEF_H_ */
+
+/** upb/reflection.h ************************************************************/
+#ifndef UPB_REFLECTION_H_
+#define UPB_REFLECTION_H_
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef union {
+  bool bool_val;
+  float float_val;
+  double double_val;
+  int32_t int32_val;
+  int64_t int64_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  const upb_map* map_val;
+  const upb_msg* msg_val;
+  const upb_array* array_val;
+  upb_strview str_val;
+} upb_msgval;
+
+typedef union {
+  upb_map* map;
+  upb_msg* msg;
+  upb_array* array;
+} upb_mutmsgval;
+
+upb_msgval upb_fielddef_default(const upb_fielddef *f);
+
+/** upb_msg *******************************************************************/
+
+/* Creates a new message of the given type in the given arena. */
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a);
+
+/* Returns the value associated with this field. */
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns a mutable pointer to a map, array, or submessage value.  If the given
+ * arena is non-NULL this will construct a new object if it was not previously
+ * present.  May not be called for primitive fields. */
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a);
+
+/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns the field that is set in the oneof, or NULL if none are set. */
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+                                       const upb_oneofdef *o);
+
+/* Sets the given field to the given value.  For a msg/array/map/string, the
+ * value must be in the same arena.  */
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+                 upb_arena *a);
+
+/* Clears any field presence and sets the value back to its default. */
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f);
+
+/* Clear all data and unknown fields. */
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m);
+
+/* Iterate over present fields.
+ *
+ * size_t iter = UPB_MSG_BEGIN;
+ * const upb_fielddef *f;
+ * upb_msgval val;
+ * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) {
+ *   process_field(f, val);
+ * }
+ *
+ * If ext_pool is NULL, no extensions will be returned.  If the given symtab
+ * returns extensions that don't match what is in this message, those extensions
+ * will be skipped.
+ */
+
+#define UPB_MSG_BEGIN -1
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+                  const upb_symtab *ext_pool, const upb_fielddef **f,
+                  upb_msgval *val, size_t *iter);
+
+/* Clears all unknown field data from this message and all submessages. */
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth);
+
+/** upb_array *****************************************************************/
+
+/* Creates a new array on the given arena that holds elements of this type. */
+upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type);
+
+/* Returns the size of the array. */
+size_t upb_array_size(const upb_array *arr);
+
+/* Returns the given element, which must be within the array's current size. */
+upb_msgval upb_array_get(const upb_array *arr, size_t i);
+
+/* Sets the given element, which must be within the array's current size. */
+void upb_array_set(upb_array *arr, size_t i, upb_msgval val);
+
+/* Appends an element to the array.  Returns false on allocation failure. */
+bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena);
+
+/* Changes the size of a vector.  New elements are initialized to empty/0.
+ * Returns false on allocation failure. */
+bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena);
+
+/** upb_map *******************************************************************/
+
+/* Creates a new map on the given arena with the given key/value size. */
+upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
+                     upb_fieldtype_t value_type);
+
+/* Returns the number of entries in the map. */
+size_t upb_map_size(const upb_map *map);
+
+/* Stores a value for the given key into |*val| (or the zero value if the key is
+ * not present).  Returns whether the key was present.  The |val| pointer may be
+ * NULL, in which case the function tests whether the given key is present.  */
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
+
+/* Removes all entries in the map. */
+void upb_map_clear(upb_map *map);
+
+/* Sets the given key to the given value.  Returns true if this was a new key in
+ * the map, or false if an existing key was replaced. */
+bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
+                 upb_arena *arena);
+
+/* Deletes this key from the table.  Returns true if the key was present. */
+bool upb_map_delete(upb_map *map, upb_msgval key);
+
+/* Map iteration:
+ *
+ * size_t iter = UPB_MAP_BEGIN;
+ * while (upb_mapiter_next(map, &iter)) {
+ *   upb_msgval key = upb_mapiter_key(map, iter);
+ *   upb_msgval val = upb_mapiter_value(map, iter);
+ *
+ *   // If mutating is desired.
+ *   upb_mapiter_setvalue(map, iter, value2);
+ * }
+ */
+
+/* Advances to the next entry.  Returns false if no more entries are present. */
+bool upb_mapiter_next(const upb_map *map, size_t *iter);
+
+/* Returns true if the iterator still points to a valid entry, or false if the
+ * iterator is past the last element. It is an error to call this function with
+ * UPB_MAP_BEGIN (you must call next() at least once first). */
+bool upb_mapiter_done(const upb_map *map, size_t iter);
+
+/* Returns the key and value for this entry of the map. */
+upb_msgval upb_mapiter_key(const upb_map *map, size_t iter);
+upb_msgval upb_mapiter_value(const upb_map *map, size_t iter);
+
+/* Sets the value for this entry.  The iterator must not be done, and the
+ * iterator must not have been initialized const. */
+void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_H_ */
+
+/** upb/json_decode.h ************************************************************/
+#ifndef UPB_JSONDECODE_H_
+#define UPB_JSONDECODE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  UPB_JSONDEC_IGNOREUNKNOWN = 1
+};
+
+bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
+                     const upb_msgdef *m, const upb_symtab *any_pool,
+                     int options, upb_arena *arena, upb_status *status);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_JSONDECODE_H_ */
+
+/** upb/json_encode.h ************************************************************/
+#ifndef UPB_JSONENCODE_H_
+#define UPB_JSONENCODE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* When set, emits 0/default values.  TODO(haberman): proto3 only? */
+  UPB_JSONENC_EMITDEFAULTS = 1,
+
+  /* When set, use normal (snake_caes) field names instead of JSON (camelCase)
+     names. */
+  UPB_JSONENC_PROTONAMES = 2
+};
+
+/* Encodes the given |msg| to JSON format.  The message's reflection is given in
+ * |m|.  The symtab in |symtab| is used to find extensions (if NULL, extensions
+ * will not be printed).
+ *
+ * Output is placed in the given buffer, and always NULL-terminated.  The output
+ * size (excluding NULL) is returned.  This means that a return value >= |size|
+ * implies that the output was truncated.  (These are the same semantics as
+ * snprintf()). */
+size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
+                       const upb_symtab *ext_pool, int options, char *buf,
+                       size_t size, upb_status *status);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_JSONENCODE_H_ */
+
+/** upb/port_undef.inc ************************************************************/
+/* See port_def.inc.  This should #undef all macros #defined there. */
+
+#undef UPB_SIZE
+#undef UPB_PTR_AT
+#undef UPB_READ_ONEOF
+#undef UPB_WRITE_ONEOF
+#undef UPB_MAPTYPE_STRING
+#undef UPB_INLINE
+#undef UPB_ALIGN_UP
+#undef UPB_ALIGN_DOWN
+#undef UPB_ALIGN_MALLOC
+#undef UPB_ALIGN_OF
+#undef UPB_LIKELY
+#undef UPB_UNLIKELY
+#undef UPB_FORCEINLINE
+#undef UPB_NOINLINE
+#undef UPB_NORETURN
+#undef UPB_PRINTF
+#undef UPB_MAX
+#undef UPB_MIN
+#undef UPB_UNUSED
+#undef UPB_ASSUME
+#undef UPB_ASSERT
+#undef UPB_UNREACHABLE
+#undef UPB_SETJMP
+#undef UPB_LONGJMP
+#undef UPB_PTRADD
+#undef UPB_MUSTTAIL
+#undef UPB_FASTTABLE_SUPPORTED
+#undef UPB_FASTTABLE
+#undef UPB_FASTTABLE_INIT
+#undef UPB_POISON_MEMORY_REGION
+#undef UPB_UNPOISON_MEMORY_REGION
+#undef UPB_ASAN
diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c
deleted file mode 100644
index 739c0a7..0000000
--- a/ruby/ext/google/protobuf_c/storage.c
+++ /dev/null
@@ -1,1149 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2014 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "protobuf.h"
-
-#include <math.h>
-
-#include <ruby/encoding.h>
-
-// -----------------------------------------------------------------------------
-// Ruby <-> native slot management.
-// -----------------------------------------------------------------------------
-
-#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs)
-#define DEREF_OFFSET(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs)
-#define DEREF(memory, type) *(type*)(memory)
-
-size_t native_slot_size(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_FLOAT:   return 4;
-    case UPB_TYPE_DOUBLE:  return 8;
-    case UPB_TYPE_BOOL:    return 1;
-    case UPB_TYPE_STRING:  return sizeof(VALUE);
-    case UPB_TYPE_BYTES:   return sizeof(VALUE);
-    case UPB_TYPE_MESSAGE: return sizeof(VALUE);
-    case UPB_TYPE_ENUM:    return 4;
-    case UPB_TYPE_INT32:   return 4;
-    case UPB_TYPE_INT64:   return 8;
-    case UPB_TYPE_UINT32:  return 4;
-    case UPB_TYPE_UINT64:  return 8;
-    default: return 0;
-  }
-}
-
-static bool is_ruby_num(VALUE value) {
-  return (TYPE(value) == T_FLOAT ||
-          TYPE(value) == T_FIXNUM ||
-          TYPE(value) == T_BIGNUM);
-}
-
-void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE val) {
-  if (!is_ruby_num(val)) {
-    rb_raise(cTypeError, "Expected number type for integral field '%s' (given %s).",
-             name, rb_class2name(CLASS_OF(val)));
-  }
-
-  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
-  // bound; we just need to do precision checks (i.e., disallow rounding) and
-  // check for < 0 on unsigned types.
-  if (TYPE(val) == T_FLOAT) {
-    double dbl_val = NUM2DBL(val);
-    if (floor(dbl_val) != dbl_val) {
-      rb_raise(rb_eRangeError,
-               "Non-integral floating point value assigned to integer field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-  }
-  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
-    if (NUM2DBL(val) < 0) {
-      rb_raise(rb_eRangeError,
-               "Assigning negative value to unsigned integer field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-  }
-}
-
-VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
-  rb_encoding* desired_encoding = (type == UPB_TYPE_STRING) ?
-      kRubyStringUtf8Encoding : kRubyString8bitEncoding;
-  VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding);
-
-  if (rb_obj_encoding(value) != desired_encoding_value || !OBJ_FROZEN(value)) {
-    // Note: this will not duplicate underlying string data unless necessary.
-    value = rb_str_encode(value, desired_encoding_value, 0, Qnil);
-
-    if (type == UPB_TYPE_STRING &&
-        rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
-      rb_raise(rb_eEncodingError, "String is invalid UTF-8");
-    }
-
-    // Ensure the data remains valid.  Since we called #encode a moment ago,
-    // this does not freeze the string the user assigned.
-    rb_obj_freeze(value);
-  }
-
-  return value;
-}
-
-void native_slot_set(const char* name,
-                     upb_fieldtype_t type, VALUE type_class,
-                     void* memory, VALUE value) {
-  native_slot_set_value_and_case(name, type, type_class, memory, value, NULL, 0);
-}
-
-void native_slot_set_value_and_case(const char* name,
-                                    upb_fieldtype_t type, VALUE type_class,
-                                    void* memory, VALUE value,
-                                    uint32_t* case_memory,
-                                    uint32_t case_number) {
-  // Note that in order to atomically change the value in memory and the case
-  // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after
-  // all Ruby VM calls are complete. The case is then set at the bottom of this
-  // function.
-  switch (type) {
-    case UPB_TYPE_FLOAT:
-      if (!is_ruby_num(value)) {
-        rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-      DEREF(memory, float) = NUM2DBL(value);
-      break;
-    case UPB_TYPE_DOUBLE:
-      if (!is_ruby_num(value)) {
-        rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-      DEREF(memory, double) = NUM2DBL(value);
-      break;
-    case UPB_TYPE_BOOL: {
-      int8_t val = -1;
-      if (value == Qtrue) {
-        val = 1;
-      } else if (value == Qfalse) {
-        val = 0;
-      } else {
-        rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-      DEREF(memory, int8_t) = val;
-      break;
-    }
-    case UPB_TYPE_STRING:
-      if (CLASS_OF(value) == rb_cSymbol) {
-        value = rb_funcall(value, rb_intern("to_s"), 0);
-      } else if (CLASS_OF(value) != rb_cString) {
-        rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-
-      DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
-      break;
-
-    case UPB_TYPE_BYTES: {
-      if (CLASS_OF(value) != rb_cString) {
-        rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-
-      DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (CLASS_OF(value) == CLASS_OF(Qnil)) {
-        value = Qnil;
-      } else if (CLASS_OF(value) != type_class) {
-        // check for possible implicit conversions
-        VALUE converted_value = Qnil;
-        const char* field_type_name = rb_class2name(type_class);
-
-        if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
-            rb_obj_is_kind_of(value, rb_cTime)) {
-          // Time -> Google::Protobuf::Timestamp
-          VALUE hash = rb_hash_new();
-          rb_hash_aset(hash, rb_str_new2("seconds"),
-                       rb_funcall(value, rb_intern("to_i"), 0));
-          rb_hash_aset(hash, rb_str_new2("nanos"),
-                       rb_funcall(value, rb_intern("nsec"), 0));
-          {
-            VALUE args[1] = {hash};
-            converted_value = rb_class_new_instance(1, args, type_class);
-          }
-        } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
-                   rb_obj_is_kind_of(value, rb_cNumeric)) {
-          // Numeric -> Google::Protobuf::Duration
-          VALUE hash = rb_hash_new();
-          rb_hash_aset(hash, rb_str_new2("seconds"),
-                       rb_funcall(value, rb_intern("to_i"), 0));
-          {
-            VALUE n_value =
-                rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
-            n_value =
-                rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
-            n_value = rb_funcall(n_value, rb_intern("round"), 0);
-            rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
-          }
-          {
-            VALUE args[1] = { hash };
-            converted_value = rb_class_new_instance(1, args, type_class);
-          }
-        }
-
-        // raise if no suitable conversaion could be found
-        if (converted_value == Qnil) {
-          rb_raise(cTypeError,
-                   "Invalid type %s to assign to submessage field '%s'.",
-                  rb_class2name(CLASS_OF(value)), name);
-        } else {
-          value = converted_value;
-        }
-      }
-      DEREF(memory, VALUE) = value;
-      break;
-    }
-    case UPB_TYPE_ENUM: {
-      int32_t int_val = 0;
-      if (TYPE(value) == T_STRING) {
-        value = rb_funcall(value, rb_intern("to_sym"), 0);
-      } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
-        rb_raise(cTypeError,
-                 "Expected number or symbol type for enum field '%s'.", name);
-      }
-      if (TYPE(value) == T_SYMBOL) {
-        // Ensure that the given symbol exists in the enum module.
-        VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
-        if (lookup == Qnil) {
-          rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
-        } else {
-          int_val = NUM2INT(lookup);
-        }
-      } else {
-        native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value);
-        int_val = NUM2INT(value);
-      }
-      DEREF(memory, int32_t) = int_val;
-      break;
-    }
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      native_slot_check_int_range_precision(name, type, value);
-      switch (type) {
-      case UPB_TYPE_INT32:
-        DEREF(memory, int32_t) = NUM2INT(value);
-        break;
-      case UPB_TYPE_INT64:
-        DEREF(memory, int64_t) = NUM2LL(value);
-        break;
-      case UPB_TYPE_UINT32:
-        DEREF(memory, uint32_t) = NUM2UINT(value);
-        break;
-      case UPB_TYPE_UINT64:
-        DEREF(memory, uint64_t) = NUM2ULL(value);
-        break;
-      default:
-        break;
-      }
-      break;
-    default:
-      break;
-  }
-
-  if (case_memory != NULL) {
-    *case_memory = case_number;
-  }
-}
-
-VALUE native_slot_get(upb_fieldtype_t type,
-                      VALUE type_class,
-                      const void* memory) {
-  switch (type) {
-    case UPB_TYPE_FLOAT:
-      return DBL2NUM(DEREF(memory, float));
-    case UPB_TYPE_DOUBLE:
-      return DBL2NUM(DEREF(memory, double));
-    case UPB_TYPE_BOOL:
-      return DEREF(memory, int8_t) ? Qtrue : Qfalse;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      return DEREF(memory, VALUE);
-    case UPB_TYPE_MESSAGE: {
-      VALUE val = DEREF(memory, VALUE);
-
-      // Lazily expand wrapper type if necessary.
-      int type = TYPE(val);
-      if (type != T_DATA && type != T_NIL) {
-        // This must be a wrapper type.
-        val = ruby_wrapper_type(type_class, val);
-        DEREF(memory, VALUE) = val;
-      }
-
-      return val;
-    }
-    case UPB_TYPE_ENUM: {
-      int32_t val = DEREF(memory, int32_t);
-      VALUE symbol = enum_lookup(type_class, INT2NUM(val));
-      if (symbol == Qnil) {
-        return INT2NUM(val);
-      } else {
-        return symbol;
-      }
-    }
-    case UPB_TYPE_INT32:
-      return INT2NUM(DEREF(memory, int32_t));
-    case UPB_TYPE_INT64:
-      return LL2NUM(DEREF(memory, int64_t));
-    case UPB_TYPE_UINT32:
-      return UINT2NUM(DEREF(memory, uint32_t));
-    case UPB_TYPE_UINT64:
-      return ULL2NUM(DEREF(memory, uint64_t));
-    default:
-      return Qnil;
-  }
-}
-
-void native_slot_init(upb_fieldtype_t type, void* memory) {
-  switch (type) {
-    case UPB_TYPE_FLOAT:
-      DEREF(memory, float) = 0.0;
-      break;
-    case UPB_TYPE_DOUBLE:
-      DEREF(memory, double) = 0.0;
-      break;
-    case UPB_TYPE_BOOL:
-      DEREF(memory, int8_t) = 0;
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      DEREF(memory, VALUE) = rb_str_new2("");
-      rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ?
-                       kRubyString8bitEncoding : kRubyStringUtf8Encoding);
-      break;
-    case UPB_TYPE_MESSAGE:
-      DEREF(memory, VALUE) = Qnil;
-      break;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-      DEREF(memory, int32_t) = 0;
-      break;
-    case UPB_TYPE_INT64:
-      DEREF(memory, int64_t) = 0;
-      break;
-    case UPB_TYPE_UINT32:
-      DEREF(memory, uint32_t) = 0;
-      break;
-    case UPB_TYPE_UINT64:
-      DEREF(memory, uint64_t) = 0;
-      break;
-    default:
-      break;
-  }
-}
-
-void native_slot_mark(upb_fieldtype_t type, void* memory) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_MESSAGE:
-      rb_gc_mark(DEREF(memory, VALUE));
-      break;
-    default:
-      break;
-  }
-}
-
-void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
-  memcpy(to, from, native_slot_size(type));
-}
-
-void native_slot_deep_copy(upb_fieldtype_t type, VALUE type_class, void* to,
-                           void* from) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      VALUE from_val = DEREF(from, VALUE);
-      DEREF(to, VALUE) = (from_val != Qnil) ?
-          rb_funcall(from_val, rb_intern("dup"), 0) : Qnil;
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      VALUE from_val = native_slot_get(type, type_class, from);
-      DEREF(to, VALUE) = (from_val != Qnil) ?
-          Message_deep_copy(from_val) : Qnil;
-      break;
-    }
-    default:
-      memcpy(to, from, native_slot_size(type));
-  }
-}
-
-bool native_slot_eq(upb_fieldtype_t type, VALUE type_class, void* mem1,
-                    void* mem2) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_MESSAGE: {
-      VALUE val1 = native_slot_get(type, type_class, mem1);
-      VALUE val2 = native_slot_get(type, type_class, mem2);
-      VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
-      return ret == Qtrue;
-    }
-    default:
-      return !memcmp(mem1, mem2, native_slot_size(type));
-  }
-}
-
-// -----------------------------------------------------------------------------
-// Map field utilities.
-// -----------------------------------------------------------------------------
-
-const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
-  const upb_msgdef* subdef;
-  if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
-      upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
-    return NULL;
-  }
-  subdef = upb_fielddef_msgsubdef(field);
-  return upb_msgdef_mapentry(subdef) ? subdef : NULL;
-}
-
-const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
-  const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
-  assert(subdef);
-  return subdef;
-}
-
-bool is_map_field(const upb_fielddef *field) {
-  const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
-  if (subdef == NULL) return false;
-
-  // Map fields are a proto3 feature.
-  // If we're using proto2 syntax we need to fallback to the repeated field.
-  return upb_msgdef_syntax(subdef) == UPB_SYNTAX_PROTO3;
-}
-
-const upb_fielddef* map_field_key(const upb_fielddef* field) {
-  const upb_msgdef* subdef = map_entry_msgdef(field);
-  return map_entry_key(subdef);
-}
-
-const upb_fielddef* map_field_value(const upb_fielddef* field) {
-  const upb_msgdef* subdef = map_entry_msgdef(field);
-  return map_entry_value(subdef);
-}
-
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
-  const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
-  assert(key_field != NULL);
-  return key_field;
-}
-
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
-  const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
-  assert(value_field != NULL);
-  return value_field;
-}
-
-// -----------------------------------------------------------------------------
-// Memory layout management.
-// -----------------------------------------------------------------------------
-
-bool field_contains_hasbit(MessageLayout* layout,
-                            const upb_fielddef* field) {
-  return layout->fields[upb_fielddef_index(field)].hasbit !=
-      MESSAGE_FIELD_NO_HASBIT;
-}
-
-static size_t align_up_to(size_t offset, size_t granularity) {
-  // Granularity must be a power of two.
-  return (offset + granularity - 1) & ~(granularity - 1);
-}
-
-bool is_value_field(const upb_fielddef* f) {
-  return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) ||
-         upb_fielddef_isstring(f);
-}
-
-void create_layout(Descriptor* desc) {
-  const upb_msgdef *msgdef = desc->msgdef;
-  MessageLayout* layout = ALLOC(MessageLayout);
-  int nfields = upb_msgdef_numfields(msgdef);
-  int noneofs = upb_msgdef_numoneofs(msgdef);
-  upb_msg_field_iter it;
-  upb_msg_oneof_iter oit;
-  size_t off = 0;
-  size_t hasbit = 0;
-
-  layout->empty_template = NULL;
-  layout->desc = desc;
-  desc->layout = layout;
-
-  layout->fields = ALLOC_N(MessageField, nfields);
-  layout->oneofs = NULL;
-
-  if (noneofs > 0) {
-    layout->oneofs = ALLOC_N(MessageOneof, noneofs);
-  }
-
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_haspresence(field)) {
-      layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
-    } else {
-      layout->fields[upb_fielddef_index(field)].hasbit =
-          MESSAGE_FIELD_NO_HASBIT;
-    }
-  }
-
-  if (hasbit != 0) {
-    off += (hasbit + 8 - 1) / 8;
-  }
-
-  off = align_up_to(off, sizeof(VALUE));
-  layout->value_offset = off;
-  layout->repeated_count = 0;
-  layout->map_count = 0;
-  layout->value_count = 0;
-
-  // Place all VALUE fields for repeated fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
-        upb_fielddef_ismap(field)) {
-      continue;
-    }
-
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += sizeof(VALUE);
-    layout->repeated_count++;
-  }
-
-  // Place all VALUE fields for map fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
-        !upb_fielddef_ismap(field)) {
-      continue;
-    }
-
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += sizeof(VALUE);
-    layout->map_count++;
-  }
-
-  layout->value_count = layout->repeated_count + layout->map_count;
-
-  // Next place all other (non-oneof) VALUE fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_containingoneof(field) || !is_value_field(field) ||
-        upb_fielddef_isseq(field)) {
-      continue;
-    }
-
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += sizeof(VALUE);
-    layout->value_count++;
-  }
-
-  // Now place all other (non-oneof) fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    size_t field_size;
-
-    if (upb_fielddef_containingoneof(field) || is_value_field(field)) {
-      continue;
-    }
-
-    // Allocate |field_size| bytes for this field in the layout.
-    field_size = native_slot_size(upb_fielddef_type(field));
-
-    // Align current offset up to |size| granularity.
-    off = align_up_to(off, field_size);
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += field_size;
-  }
-
-  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
-  // one slot per oneof.
-  //
-  // We assign all value slots first, then pack the 'case' fields at the end,
-  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
-  // bytes respectively and we want to avoid alignment overhead.
-  //
-  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
-  // space for oneof cases is conceptually as wide as field tag numbers. In
-  // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
-  // members (8 or 16 bits respectively), so conceivably we could assign
-  // consecutive case numbers and then pick a smaller oneof case slot size, but
-  // the complexity to implement this indirection is probably not worthwhile.
-  for (upb_msg_oneof_begin(&oit, msgdef);
-       !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
-    upb_oneof_iter fit;
-
-    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
-    // all fields.
-    size_t field_size = NATIVE_SLOT_MAX_SIZE;
-    // Align the offset.
-    off = align_up_to(off, field_size);
-    // Assign all fields in the oneof this same offset.
-    for (upb_oneof_begin(&fit, oneof);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* field = upb_oneof_iter_field(&fit);
-      layout->fields[upb_fielddef_index(field)].offset = off;
-      layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
-    }
-    off += field_size;
-  }
-
-  // Now the case fields.
-  for (upb_msg_oneof_begin(&oit, msgdef);
-       !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
-    size_t field_size = sizeof(uint32_t);
-    // Align the offset.
-    off = (off + field_size - 1) & ~(field_size - 1);
-    layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
-    off += field_size;
-  }
-
-  layout->size = off;
-  layout->msgdef = msgdef;
-
-  // Create the empty message template.
-  layout->empty_template = ALLOC_N(char, layout->size);
-  memset(layout->empty_template, 0, layout->size);
-
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it));
-  }
-}
-
-void free_layout(MessageLayout* layout) {
-  xfree(layout->empty_template);
-  xfree(layout->fields);
-  xfree(layout->oneofs);
-  xfree(layout);
-}
-
-VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
-  VALUE type_class = Qnil;
-  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-    VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
-                                      upb_fielddef_msgsubdef(field));
-    type_class = Descriptor_msgclass(submsgdesc);
-  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
-    VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
-                                        upb_fielddef_enumsubdef(field));
-    type_class = EnumDescriptor_enummodule(subenumdesc);
-  }
-  return type_class;
-}
-
-static void* slot_memory(MessageLayout* layout,
-                         const void* storage,
-                         const upb_fielddef* field) {
-  return ((uint8_t *)storage) +
-      layout->fields[upb_fielddef_index(field)].offset;
-}
-
-static uint32_t* slot_oneof_case(MessageLayout* layout,
-                                 const void* storage,
-                                 const upb_oneofdef* oneof) {
-  return (uint32_t*)(((uint8_t*)storage) +
-                     layout->oneofs[upb_oneofdef_index(oneof)].case_offset);
-}
-
-uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
-                              const upb_oneofdef* oneof) {
-  uint32_t* ptr = slot_oneof_case(layout, storage, oneof);
-  return *ptr & ~ONEOF_CASE_MASK;
-}
-
-static void slot_set_hasbit(MessageLayout* layout,
-                            const void* storage,
-                            const upb_fielddef* field) {
-  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
-  assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
-
-  ((uint8_t*)storage)[hasbit / 8] |= 1 << (hasbit % 8);
-}
-
-static void slot_clear_hasbit(MessageLayout* layout,
-                              const void* storage,
-                              const upb_fielddef* field) {
-  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
-  assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
-  ((uint8_t*)storage)[hasbit / 8] &= ~(1 << (hasbit % 8));
-}
-
-static bool slot_is_hasbit_set(MessageLayout* layout,
-                            const void* storage,
-                            const upb_fielddef* field) {
-  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
-  if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
-    return false;
-  }
-
-  return DEREF_OFFSET(
-      (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
-}
-
-VALUE layout_has(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field) {
-  assert(field_contains_hasbit(layout, field));
-  return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
-}
-
-void layout_clear(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field) {
-  void* memory = slot_memory(layout, storage, field);
-  const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
-
-  if (field_contains_hasbit(layout, field)) {
-    slot_clear_hasbit(layout, storage, field);
-  }
-
-  if (oneof) {
-    uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
-    memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
-    *oneof_case = ONEOF_CASE_NONE;
-  } else if (is_map_field(field)) {
-    VALUE map = Qnil;
-
-    const upb_fielddef* key_field = map_field_key(field);
-    const upb_fielddef* value_field = map_field_value(field);
-    VALUE type_class = field_type_class(layout, value_field);
-
-    if (type_class != Qnil) {
-      VALUE args[3] = {
-        fieldtype_to_ruby(upb_fielddef_type(key_field)),
-        fieldtype_to_ruby(upb_fielddef_type(value_field)),
-        type_class,
-      };
-      map = rb_class_new_instance(3, args, cMap);
-    } else {
-      VALUE args[2] = {
-        fieldtype_to_ruby(upb_fielddef_type(key_field)),
-        fieldtype_to_ruby(upb_fielddef_type(value_field)),
-      };
-      map = rb_class_new_instance(2, args, cMap);
-    }
-
-    DEREF(memory, VALUE) = map;
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    VALUE ary = Qnil;
-
-    VALUE type_class = field_type_class(layout, field);
-
-    if (type_class != Qnil) {
-      VALUE args[2] = {
-        fieldtype_to_ruby(upb_fielddef_type(field)),
-        type_class,
-      };
-      ary = rb_class_new_instance(2, args, cRepeatedField);
-    } else {
-      VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
-      ary = rb_class_new_instance(1, args, cRepeatedField);
-    }
-
-    DEREF(memory, VALUE) = ary;
-  } else {
-    native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
-                    field_type_class(layout, field), memory,
-                    layout_get_default(field));
-  }
-}
-
-VALUE layout_get_default(const upb_fielddef *field) {
-  switch (upb_fielddef_type(field)) {
-    case UPB_TYPE_FLOAT:   return DBL2NUM(upb_fielddef_defaultfloat(field));
-    case UPB_TYPE_DOUBLE:  return DBL2NUM(upb_fielddef_defaultdouble(field));
-    case UPB_TYPE_BOOL:
-      return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
-    case UPB_TYPE_MESSAGE: return Qnil;
-    case UPB_TYPE_ENUM: {
-      const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
-      int32_t num = upb_fielddef_defaultint32(field);
-      const char *label = upb_enumdef_iton(enumdef, num);
-      if (label) {
-        return ID2SYM(rb_intern(label));
-      } else {
-        return INT2NUM(num);
-      }
-    }
-    case UPB_TYPE_INT32:   return INT2NUM(upb_fielddef_defaultint32(field));
-    case UPB_TYPE_INT64:   return LL2NUM(upb_fielddef_defaultint64(field));;
-    case UPB_TYPE_UINT32:  return UINT2NUM(upb_fielddef_defaultuint32(field));
-    case UPB_TYPE_UINT64:  return ULL2NUM(upb_fielddef_defaultuint64(field));
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      size_t size;
-      const char *str = upb_fielddef_defaultstr(field, &size);
-      return get_frozen_string(str, size,
-                               upb_fielddef_type(field) == UPB_TYPE_BYTES);
-    }
-    default: return Qnil;
-  }
-}
-
-VALUE layout_get(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field) {
-  void* memory = slot_memory(layout, storage, field);
-  const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
-  bool field_set;
-  if (field_contains_hasbit(layout, field)) {
-    field_set = slot_is_hasbit_set(layout, storage, field);
-  } else {
-    field_set = true;
-  }
-
-  if (oneof) {
-    uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
-    if (oneof_case != upb_fielddef_number(field)) {
-      return layout_get_default(field);
-    }
-    return native_slot_get(upb_fielddef_type(field),
-                           field_type_class(layout, field), memory);
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    return *((VALUE *)memory);
-  } else if (!field_set) {
-    return layout_get_default(field);
-  } else {
-    return native_slot_get(upb_fielddef_type(field),
-                           field_type_class(layout, field), memory);
-  }
-}
-
-static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
-                                      const upb_fielddef* field) {
-  RepeatedField* self;
-  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
-
-  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
-      RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
-    rb_raise(cTypeError, "Expected repeated field array");
-  }
-
-  self = ruby_to_RepeatedField(val);
-  if (self->field_type != upb_fielddef_type(field)) {
-    rb_raise(cTypeError, "Repeated field array has wrong element type");
-  }
-
-  if (self->field_type_class != field_type_class(layout, field)) {
-    rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
-  }
-}
-
-static void check_map_field_type(const MessageLayout* layout, VALUE val,
-                                 const upb_fielddef* field) {
-  const upb_fielddef* key_field = map_field_key(field);
-  const upb_fielddef* value_field = map_field_value(field);
-  Map* self;
-
-  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
-      RTYPEDDATA_TYPE(val) != &Map_type) {
-    rb_raise(cTypeError, "Expected Map instance");
-  }
-
-  self = ruby_to_Map(val);
-  if (self->key_type != upb_fielddef_type(key_field)) {
-    rb_raise(cTypeError, "Map key type does not match field's key type");
-  }
-  if (self->value_type != upb_fielddef_type(value_field)) {
-    rb_raise(cTypeError, "Map value type does not match field's value type");
-  }
-  if (self->value_type_class != field_type_class(layout, value_field)) {
-    rb_raise(cTypeError, "Map value type has wrong message/enum class");
-  }
-}
-
-void layout_set(MessageLayout* layout,
-                void* storage,
-                const upb_fielddef* field,
-                VALUE val) {
-  void* memory = slot_memory(layout, storage, field);
-  const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
-
-  if (oneof) {
-    uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
-    if (val == Qnil) {
-      // Assigning nil to a oneof field clears the oneof completely.
-      *oneof_case = ONEOF_CASE_NONE;
-      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
-    } else {
-      // The transition between field types for a single oneof (union) slot is
-      // somewhat complex because we need to ensure that a GC triggered at any
-      // point by a call into the Ruby VM sees a valid state for this field and
-      // does not either go off into the weeds (following what it thinks is a
-      // VALUE but is actually a different field type) or miss an object (seeing
-      // what it thinks is a primitive field but is actually a VALUE for the new
-      // field type).
-      //
-      // In order for the transition to be safe, the oneof case slot must be in
-      // sync with the value slot whenever the Ruby VM has been called. Thus, we
-      // use native_slot_set_value_and_case(), which ensures that both the value
-      // and case number are altered atomically (w.r.t. the Ruby VM).
-      uint32_t case_value = upb_fielddef_number(field);
-      if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) {
-        case_value |= ONEOF_CASE_MASK;
-      }
-
-      native_slot_set_value_and_case(
-          upb_fielddef_name(field), upb_fielddef_type(field),
-          field_type_class(layout, field), memory, val, oneof_case, case_value);
-    }
-  } else if (is_map_field(field)) {
-    check_map_field_type(layout, val, field);
-    DEREF(memory, VALUE) = val;
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    check_repeated_field_type(layout, val, field);
-    DEREF(memory, VALUE) = val;
-  } else {
-    native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
-                    field_type_class(layout, field), memory, val);
-  }
-
-  if (layout->fields[upb_fielddef_index(field)].hasbit !=
-      MESSAGE_FIELD_NO_HASBIT) {
-    slot_set_hasbit(layout, storage, field);
-  }
-}
-
-void layout_init(MessageLayout* layout, void* storage) {
-  VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
-  int i;
-
-  for (i = 0; i < layout->repeated_count; i++, value++) {
-    *value = RepeatedField_new_this_type(*value);
-  }
-
-  for (i = 0; i < layout->map_count; i++, value++) {
-    *value = Map_new_this_type(*value);
-  }
-}
-
-void layout_mark(MessageLayout* layout, void* storage) {
-  VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
-  int noneofs = upb_msgdef_numoneofs(layout->msgdef);
-  int i;
-
-  for (i = 0; i < layout->value_count; i++) {
-    rb_gc_mark(values[i]);
-  }
-
-  for (i = 0; i < noneofs; i++) {
-    MessageOneof* oneof = &layout->oneofs[i];
-    uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset);
-    if (*case_ptr & ONEOF_CASE_MASK) {
-      rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE));
-    }
-  }
-}
-
-void layout_dup(MessageLayout* layout, void* to, void* from) {
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
-
-    void* to_memory = slot_memory(layout, to, field);
-    void* from_memory = slot_memory(layout, from, field);
-
-    if (oneof) {
-      uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
-      uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
-      if (slot_read_oneof_case(layout, from, oneof) ==
-          upb_fielddef_number(field)) {
-        *to_oneof_case = *from_oneof_case;
-        native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
-      }
-    } else if (is_map_field(field)) {
-      DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
-    } else {
-      if (field_contains_hasbit(layout, field)) {
-        if (!slot_is_hasbit_set(layout, from, field)) continue;
-        slot_set_hasbit(layout, to, field);
-      }
-
-      native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
-    }
-  }
-}
-
-void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
-
-    void* to_memory = slot_memory(layout, to, field);
-    void* from_memory = slot_memory(layout, from, field);
-
-    if (oneof) {
-      uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
-      uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
-      if (slot_read_oneof_case(layout, from, oneof) ==
-          upb_fielddef_number(field)) {
-        *to_oneof_case = *from_oneof_case;
-        native_slot_deep_copy(upb_fielddef_type(field),
-                              field_type_class(layout, field), to_memory,
-                              from_memory);
-      }
-    } else if (is_map_field(field)) {
-      DEREF(to_memory, VALUE) =
-          Map_deep_copy(DEREF(from_memory, VALUE));
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      DEREF(to_memory, VALUE) =
-          RepeatedField_deep_copy(DEREF(from_memory, VALUE));
-    } else {
-      if (field_contains_hasbit(layout, field)) {
-        if (!slot_is_hasbit_set(layout, from, field)) continue;
-        slot_set_hasbit(layout, to, field);
-      }
-
-      native_slot_deep_copy(upb_fielddef_type(field),
-                            field_type_class(layout, field), to_memory,
-                            from_memory);
-    }
-  }
-}
-
-VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
-
-    void* msg1_memory = slot_memory(layout, msg1, field);
-    void* msg2_memory = slot_memory(layout, msg2, field);
-
-    if (oneof) {
-      uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof);
-      uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof);
-      if (*msg1_oneof_case != *msg2_oneof_case ||
-          (slot_read_oneof_case(layout, msg1, oneof) ==
-               upb_fielddef_number(field) &&
-           !native_slot_eq(upb_fielddef_type(field),
-                           field_type_class(layout, field), msg1_memory,
-                           msg2_memory))) {
-        return Qfalse;
-      }
-    } else if (is_map_field(field)) {
-      if (!Map_eq(DEREF(msg1_memory, VALUE),
-                  DEREF(msg2_memory, VALUE))) {
-        return Qfalse;
-      }
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
-                            DEREF(msg2_memory, VALUE))) {
-        return Qfalse;
-      }
-    } else {
-      if (slot_is_hasbit_set(layout, msg1, field) !=
-              slot_is_hasbit_set(layout, msg2, field) ||
-          !native_slot_eq(upb_fielddef_type(field),
-                          field_type_class(layout, field), msg1_memory,
-                          msg2_memory)) {
-        return Qfalse;
-      }
-    }
-  }
-  return Qtrue;
-}
-
-VALUE layout_hash(MessageLayout* layout, void* storage) {
-  upb_msg_field_iter it;
-  st_index_t h = rb_hash_start(0);
-  VALUE hash_sym = rb_intern("hash");
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE field_val = layout_get(layout, storage, field);
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
-  }
-  h = rb_hash_end(h);
-
-  return INT2FIX(h);
-}
-
-VALUE layout_inspect(MessageLayout* layout, void* storage) {
-  VALUE str = rb_str_new2("");
-
-  upb_msg_field_iter it;
-  bool first = true;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE field_val = layout_get(layout, storage, field);
-
-    if (!first) {
-      str = rb_str_cat2(str, ", ");
-    } else {
-      first = false;
-    }
-    str = rb_str_cat2(str, upb_fielddef_name(field));
-    str = rb_str_cat2(str, ": ");
-
-    str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0));
-  }
-
-  return str;
-}
diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c
deleted file mode 100644
index ffa55fb..0000000
--- a/ruby/ext/google/protobuf_c/upb.c
+++ /dev/null
@@ -1,13774 +0,0 @@
-/* Amalgamated source file */
-#include "upb.h"
-/*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-*   #include "upb/foobar.h"
-*   #include "upb/baz.h"
-*
-*   // MUST be last included header.
-*   #include "upb/port_def.inc"
-*
-*   // Code for this file.
-*   // <...>
-*
-*   // Can be omitted for .c files, required for .h.
-*   #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#include <stdint.h>
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-/* If we always read/write as a consistent type to each address, this shouldn't
- * violate aliasing.
- */
-#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
-  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
-      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
-      : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
-  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
-  *UPB_PTR_AT(msg, offset, fieldtype) = value;
-
-#define UPB_MAPTYPE_STRING 0
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else  /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include <stdio.h>
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include <stdarg.h>
-#include <stdio.h>
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
-    (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
-#ifdef NDEBUG
-#ifdef __GNUC__
-#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
-#else
-#define UPB_ASSUME(expr) do {} if (false && (expr))
-#endif
-#else
-#define UPB_ASSUME(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated.  This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode.  This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include <math.h>
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-
-#include <setjmp.h>
-#include <string.h>
-
-
-
-/* Maps descriptor type -> upb field type.  */
-static const uint8_t desctype_to_fieldtype[] = {
-    -1,               /* invalid descriptor type */
-    UPB_TYPE_DOUBLE,  /* DOUBLE */
-    UPB_TYPE_FLOAT,   /* FLOAT */
-    UPB_TYPE_INT64,   /* INT64 */
-    UPB_TYPE_UINT64,  /* UINT64 */
-    UPB_TYPE_INT32,   /* INT32 */
-    UPB_TYPE_UINT64,  /* FIXED64 */
-    UPB_TYPE_UINT32,  /* FIXED32 */
-    UPB_TYPE_BOOL,    /* BOOL */
-    UPB_TYPE_STRING,  /* STRING */
-    UPB_TYPE_MESSAGE, /* GROUP */
-    UPB_TYPE_MESSAGE, /* MESSAGE */
-    UPB_TYPE_BYTES,   /* BYTES */
-    UPB_TYPE_UINT32,  /* UINT32 */
-    UPB_TYPE_ENUM,    /* ENUM */
-    UPB_TYPE_INT32,   /* SFIXED32 */
-    UPB_TYPE_INT64,   /* SFIXED64 */
-    UPB_TYPE_INT32,   /* SINT32 */
-    UPB_TYPE_INT64,   /* SINT64 */
-};
-
-/* Maps descriptor type -> upb map size.  */
-static const uint8_t desctype_to_mapsize[] = {
-    -1,                 /* invalid descriptor type */
-    8,                  /* DOUBLE */
-    4,                  /* FLOAT */
-    8,                  /* INT64 */
-    8,                  /* UINT64 */
-    4,                  /* INT32 */
-    8,                  /* FIXED64 */
-    4,                  /* FIXED32 */
-    1,                  /* BOOL */
-    UPB_MAPTYPE_STRING, /* STRING */
-    sizeof(void *),     /* GROUP */
-    sizeof(void *),     /* MESSAGE */
-    UPB_MAPTYPE_STRING, /* BYTES */
-    4,                  /* UINT32 */
-    4,                  /* ENUM */
-    4,                  /* SFIXED32 */
-    8,                  /* SFIXED64 */
-    4,                  /* SINT32 */
-    8,                  /* SINT64 */
-};
-
-static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) |
-                                   (1 << UPB_DTYPE_FIXED32) |
-                                   (1 << UPB_DTYPE_SFIXED32);
-
-static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
-                                   (1 << UPB_DTYPE_FIXED64) |
-                                   (1 << UPB_DTYPE_SFIXED64);
-
-/* Op: an action to be performed for a wire-type/field-type combination. */
-#define OP_SCALAR_LG2(n) (n)
-#define OP_FIXPCK_LG2(n) (n + 4)
-#define OP_VARPCK_LG2(n) (n + 8)
-#define OP_STRING 4
-#define OP_SUBMSG 5
-
-static const int8_t varint_ops[19] = {
-    -1,               /* field not found */
-    -1,               /* DOUBLE */
-    -1,               /* FLOAT */
-    OP_SCALAR_LG2(3), /* INT64 */
-    OP_SCALAR_LG2(3), /* UINT64 */
-    OP_SCALAR_LG2(2), /* INT32 */
-    -1,               /* FIXED64 */
-    -1,               /* FIXED32 */
-    OP_SCALAR_LG2(0), /* BOOL */
-    -1,               /* STRING */
-    -1,               /* GROUP */
-    -1,               /* MESSAGE */
-    -1,               /* BYTES */
-    OP_SCALAR_LG2(2), /* UINT32 */
-    OP_SCALAR_LG2(2), /* ENUM */
-    -1,               /* SFIXED32 */
-    -1,               /* SFIXED64 */
-    OP_SCALAR_LG2(2), /* SINT32 */
-    OP_SCALAR_LG2(3), /* SINT64 */
-};
-
-static const int8_t delim_ops[37] = {
-    /* For non-repeated field type. */
-    -1,        /* field not found */
-    -1,        /* DOUBLE */
-    -1,        /* FLOAT */
-    -1,        /* INT64 */
-    -1,        /* UINT64 */
-    -1,        /* INT32 */
-    -1,        /* FIXED64 */
-    -1,        /* FIXED32 */
-    -1,        /* BOOL */
-    OP_STRING, /* STRING */
-    -1,        /* GROUP */
-    OP_SUBMSG, /* MESSAGE */
-    OP_STRING, /* BYTES */
-    -1,        /* UINT32 */
-    -1,        /* ENUM */
-    -1,        /* SFIXED32 */
-    -1,        /* SFIXED64 */
-    -1,        /* SINT32 */
-    -1,        /* SINT64 */
-    /* For repeated field type. */
-    OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
-    OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
-    OP_VARPCK_LG2(3), /* REPEATED INT64 */
-    OP_VARPCK_LG2(3), /* REPEATED UINT64 */
-    OP_VARPCK_LG2(2), /* REPEATED INT32 */
-    OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */
-    OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */
-    OP_VARPCK_LG2(0), /* REPEATED BOOL */
-    OP_STRING,        /* REPEATED STRING */
-    OP_SUBMSG,        /* REPEATED GROUP */
-    OP_SUBMSG,        /* REPEATED MESSAGE */
-    OP_STRING,        /* REPEATED BYTES */
-    OP_VARPCK_LG2(2), /* REPEATED UINT32 */
-    OP_VARPCK_LG2(2), /* REPEATED ENUM */
-    OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
-    OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */
-    OP_VARPCK_LG2(2), /* REPEATED SINT32 */
-    OP_VARPCK_LG2(3), /* REPEATED SINT64 */
-};
-
-/* Data pertaining to the parse. */
-typedef struct {
-  const char *limit;       /* End of delimited region or end of buffer. */
-  upb_arena *arena;
-  int depth;
-  uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */
-  jmp_buf err;
-} upb_decstate;
-
-typedef union {
-  bool bool_val;
-  int32_t int32_val;
-  int64_t int64_val;
-  uint32_t uint32_val;
-  uint64_t uint64_val;
-  upb_strview str_val;
-} wireval;
-
-static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
-                              const upb_msglayout *layout);
-
-UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); }
-
-static bool decode_reserve(upb_decstate *d, upb_array *arr, int elem) {
-  bool need_realloc = arr->size - arr->len < elem;
-  if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, d->arena)) {
-    decode_err(d);
-  }
-  return need_realloc;
-}
-
-UPB_NOINLINE
-static const char *decode_longvarint64(upb_decstate *d, const char *ptr,
-                                       const char *limit, uint64_t *val) {
-  uint8_t byte;
-  int bitpos = 0;
-  uint64_t out = 0;
-
-  do {
-    if (bitpos >= 70 || ptr == limit) decode_err(d);
-    byte = *ptr;
-    out |= (uint64_t)(byte & 0x7F) << bitpos;
-    ptr++;
-    bitpos += 7;
-  } while (byte & 0x80);
-
-  *val = out;
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char *decode_varint64(upb_decstate *d, const char *ptr,
-                                   const char *limit, uint64_t *val) {
-  if (UPB_LIKELY(ptr < limit && (*ptr & 0x80) == 0)) {
-    *val = (uint8_t)*ptr;
-    return ptr + 1;
-  } else {
-    return decode_longvarint64(d, ptr, limit, val);
-  }
-}
-
-static const char *decode_varint32(upb_decstate *d, const char *ptr,
-                                   const char *limit, uint32_t *val) {
-  uint64_t u64;
-  ptr = decode_varint64(d, ptr, limit, &u64);
-  if (u64 > UINT32_MAX) decode_err(d);
-  *val = (uint32_t)u64;
-  return ptr;
-}
-
-static void decode_munge(int type, wireval *val) {
-  switch (type) {
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      val->bool_val = val->uint64_val != 0;
-      break;
-    case UPB_DESCRIPTOR_TYPE_SINT32: {
-      uint32_t n = val->uint32_val;
-      val->int32_val = (n >> 1) ^ -(int32_t)(n & 1);
-      break;
-    }
-    case UPB_DESCRIPTOR_TYPE_SINT64: {
-      uint64_t n = val->uint64_val;
-      val->int64_val = (n >> 1) ^ -(int64_t)(n & 1);
-      break;
-    }
-  }
-}
-
-static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
-                                                 uint32_t field_number) {
-  static upb_msglayout_field none = {0};
-
-  /* Lots of optimization opportunities here. */
-  int i;
-  if (l == NULL) return &none;
-  for (i = 0; i < l->field_count; i++) {
-    if (l->fields[i].number == field_number) {
-      return &l->fields[i];
-    }
-  }
-
-  return &none; /* Unknown field. */
-}
-
-static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
-                                 const upb_msglayout_field *field) {
-  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
-  return _upb_msg_new(subl, d->arena);
-}
-
-static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg,
-                            const upb_msglayout *layout,
-                            const upb_msglayout_field *field, upb_strview val) {
-  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
-  const char *saved_limit = d->limit;
-  if (--d->depth < 0) decode_err(d);
-  d->limit = val.data + val.size;
-  decode_msg(d, val.data, submsg, subl);
-  d->limit = saved_limit;
-  if (d->end_group != 0) decode_err(d);
-  d->depth++;
-}
-
-static const char *decode_group(upb_decstate *d, const char *ptr,
-                                upb_msg *submsg, const upb_msglayout *subl,
-                                uint32_t number) {
-  if (--d->depth < 0) decode_err(d);
-  ptr = decode_msg(d, ptr, submsg, subl);
-  if (d->end_group != number) decode_err(d);
-  d->end_group = 0;
-  d->depth++;
-  return ptr;
-}
-
-static const char *decode_togroup(upb_decstate *d, const char *ptr,
-                                  upb_msg *submsg, const upb_msglayout *layout,
-                                  const upb_msglayout_field *field) {
-  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
-  return decode_group(d, ptr, submsg, subl, field->number);
-}
-
-static const char *decode_toarray(upb_decstate *d, const char *ptr,
-                                  upb_msg *msg, const upb_msglayout *layout,
-                                  const upb_msglayout_field *field, wireval val,
-                                  int op) {
-  upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
-  upb_array *arr = *arrp;
-  void *mem;
-
-  if (!arr) {
-    upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype];
-    arr = _upb_array_new(d->arena, type);
-    if (!arr) decode_err(d);
-    *arrp = arr;
-  }
-
-  decode_reserve(d, arr, 1);
-
-  switch (op) {
-    case OP_SCALAR_LG2(0):
-    case OP_SCALAR_LG2(2):
-    case OP_SCALAR_LG2(3):
-      /* Append scalar value. */
-      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
-      arr->len++;
-      memcpy(mem, &val, 1 << op);
-      return ptr;
-    case OP_STRING:
-      /* Append string. */
-      mem =
-          UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void);
-      arr->len++;
-      memcpy(mem, &val, sizeof(upb_strview));
-      return ptr;
-    case OP_SUBMSG: {
-      /* Append submessage / group. */
-      upb_msg *submsg = decode_newsubmsg(d, layout, field);
-      *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
-          submsg;
-      arr->len++;
-      if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
-        ptr = decode_togroup(d, ptr, submsg, layout, field);
-      } else {
-        decode_tosubmsg(d, submsg, layout, field, val.str_val);
-      }
-      return ptr;
-    }
-    case OP_FIXPCK_LG2(2):
-    case OP_FIXPCK_LG2(3): {
-      /* Fixed packed. */
-      int lg2 = op - OP_FIXPCK_LG2(0);
-      int mask = (1 << lg2) - 1;
-      int count = val.str_val.size >> lg2;
-      if ((val.str_val.size & mask) != 0) {
-        decode_err(d); /* Length isn't a round multiple of elem size. */
-      }
-      decode_reserve(d, arr, count);
-      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-      arr->len += count;
-      memcpy(mem, val.str_val.data, count << op);
-      return ptr;
-    }
-    case OP_VARPCK_LG2(0):
-    case OP_VARPCK_LG2(2):
-    case OP_VARPCK_LG2(3): {
-      /* Varint packed. */
-      int lg2 = op - OP_VARPCK_LG2(0);
-      int scale = 1 << lg2;
-      const char *ptr = val.str_val.data;
-      const char *end = ptr + val.str_val.size;
-      char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-      while (ptr < end) {
-        wireval elem;
-        ptr = decode_varint64(d, ptr, end, &elem.uint64_val);
-        decode_munge(field->descriptortype, &elem);
-        if (decode_reserve(d, arr, 1)) {
-          out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-        }
-        arr->len++;
-        memcpy(out, &elem, scale);
-        out += scale;
-      }
-      if (ptr != end) decode_err(d);
-      return ptr;
-    }
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-static void decode_tomap(upb_decstate *d, upb_msg *msg,
-                         const upb_msglayout *layout,
-                         const upb_msglayout_field *field, wireval val) {
-  upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
-  upb_map *map = *map_p;
-  upb_map_entry ent;
-  const upb_msglayout *entry = layout->submsgs[field->submsg_index];
-
-  if (!map) {
-    /* Lazily create map. */
-    const upb_msglayout *entry = layout->submsgs[field->submsg_index];
-    const upb_msglayout_field *key_field = &entry->fields[0];
-    const upb_msglayout_field *val_field = &entry->fields[1];
-    char key_size = desctype_to_mapsize[key_field->descriptortype];
-    char val_size = desctype_to_mapsize[val_field->descriptortype];
-    UPB_ASSERT(key_field->offset == 0);
-    UPB_ASSERT(val_field->offset == sizeof(upb_strview));
-    map = _upb_map_new(d->arena, key_size, val_size);
-    *map_p = map;
-  }
-
-  /* Parse map entry. */
-  memset(&ent, 0, sizeof(ent));
-
-  if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
-      entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
-    /* Create proactively to handle the case where it doesn't appear. */
-    ent.v.val.val = (uint64_t)_upb_msg_new(entry->submsgs[0], d->arena);
-  }
-
-  decode_tosubmsg(d, &ent.k, layout, field, val.str_val);
-
-  /* Insert into map. */
-  _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena);
-}
-
-static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
-                                const upb_msglayout *layout,
-                                const upb_msglayout_field *field, wireval val,
-                                int op) {
-  void *mem = UPB_PTR_AT(msg, field->offset, void);
-  int type = field->descriptortype;
-
-  /* Set presence if necessary. */
-  if (field->presence < 0) {
-    /* Oneof case */
-    *UPB_PTR_AT(msg, -field->presence, int32_t) = field->number;
-  } else if (field->presence > 0) {
-    /* Hasbit */
-    uint32_t hasbit = field->presence;
-    *UPB_PTR_AT(msg, hasbit / 8, uint8_t) |= (1 << (hasbit % 8));
-  }
-
-  /* Store into message. */
-  switch (op) {
-    case OP_SUBMSG: {
-      upb_msg **submsgp = mem;
-      upb_msg *submsg = *submsgp;
-      if (!submsg) {
-        submsg = decode_newsubmsg(d, layout, field);
-        *submsgp = submsg;
-      }
-      if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
-        ptr = decode_togroup(d, ptr, submsg, layout, field);
-      } else {
-        decode_tosubmsg(d, submsg, layout, field, val.str_val);
-      }
-      break;
-    }
-    case OP_STRING:
-      memcpy(mem, &val, sizeof(upb_strview));
-      break;
-    case OP_SCALAR_LG2(3):
-      memcpy(mem, &val, 8);
-      break;
-    case OP_SCALAR_LG2(2):
-      memcpy(mem, &val, 4);
-      break;
-    case OP_SCALAR_LG2(0):
-      memcpy(mem, &val, 1);
-      break;
-    default:
-      UPB_UNREACHABLE();
-  }
-
-  return ptr;
-}
-
-static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
-                              const upb_msglayout *layout) {
-  while (ptr < d->limit) {
-    uint32_t tag;
-    const upb_msglayout_field *field;
-    int field_number;
-    int wire_type;
-    const char *field_start = ptr;
-    wireval val;
-    int op;
-
-    ptr = decode_varint32(d, ptr, d->limit, &tag);
-    field_number = tag >> 3;
-    wire_type = tag & 7;
-
-    field = upb_find_field(layout, field_number);
-
-    switch (wire_type) {
-      case UPB_WIRE_TYPE_VARINT:
-        ptr = decode_varint64(d, ptr, d->limit, &val.uint64_val);
-        op = varint_ops[field->descriptortype];
-        decode_munge(field->descriptortype, &val);
-        break;
-      case UPB_WIRE_TYPE_32BIT:
-        if (d->limit - ptr < 4) decode_err(d);
-        memcpy(&val, ptr, 4);
-        ptr += 4;
-        op = OP_SCALAR_LG2(2);
-        if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
-        break;
-      case UPB_WIRE_TYPE_64BIT:
-        if (d->limit - ptr < 8) decode_err(d);
-        memcpy(&val, ptr, 8);
-        ptr += 8;
-        op = OP_SCALAR_LG2(3);
-        if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
-        break;
-      case UPB_WIRE_TYPE_DELIMITED: {
-        uint32_t size;
-        int ndx = field->descriptortype;
-        if (_upb_isrepeated(field)) ndx += 18;
-        ptr = decode_varint32(d, ptr, d->limit, &size);
-        if (size >= INT32_MAX || (size_t)(d->limit - ptr) < size) {
-          decode_err(d); /* Length overflow. */
-        }
-        val.str_val.data = ptr;
-        val.str_val.size = size;
-        ptr += size;
-        op = delim_ops[ndx];
-        break;
-      }
-      case UPB_WIRE_TYPE_START_GROUP:
-        val.int32_val = field_number;
-        op = OP_SUBMSG;
-        if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown;
-        break;
-      case UPB_WIRE_TYPE_END_GROUP:
-        d->end_group = field_number;
-        return ptr;
-      default:
-        decode_err(d);
-    }
-
-    if (op >= 0) {
-      /* Parse, using op for dispatch. */
-      switch (field->label) {
-        case UPB_LABEL_REPEATED:
-        case _UPB_LABEL_PACKED:
-          ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
-          break;
-        case _UPB_LABEL_MAP:
-          decode_tomap(d, msg, layout, field, val);
-          break;
-        default:
-          ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
-          break;
-      }
-    } else {
-    unknown:
-      /* Skip unknown field. */
-      if (field_number == 0) decode_err(d);
-      if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
-        ptr = decode_group(d, ptr, NULL, NULL, field_number);
-      }
-      if (msg) {
-        if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
-                                 d->arena)) {
-          decode_err(d);
-        }
-      }
-    }
-  }
-
-  if (ptr != d->limit) decode_err(d);
-  return ptr;
-}
-
-bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l,
-                upb_arena *arena) {
-  upb_decstate state;
-  state.limit = buf + size;
-  state.arena = arena;
-  state.depth = 64;
-  state.end_group = 0;
-
-  if (setjmp(state.err)) return false;
-
-  if (size == 0) return true;
-  decode_msg(&state, buf, msg, l);
-
-  return state.end_group == 0;
-}
-
-#undef OP_SCALAR_LG2
-#undef OP_FIXPCK_LG2
-#undef OP_VARPCK_LG2
-#undef OP_STRING
-#undef OP_SUBMSG
-/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
-
-
-#include <string.h>
-
-
-
-#define UPB_PB_VARINT_MAX_LEN 10
-#define CHK(x) do { if (!(x)) { return false; } } while(0)
-
-static size_t upb_encode_varint(uint64_t val, char *buf) {
-  size_t i;
-  if (val < 128) { buf[0] = val; return 1; }
-  i = 0;
-  while (val) {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    buf[i++] = byte;
-  }
-  return i;
-}
-
-static uint32_t upb_zzencode_32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
-static uint64_t upb_zzencode_64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
-
-typedef struct {
-  upb_alloc *alloc;
-  char *buf, *ptr, *limit;
-} upb_encstate;
-
-static size_t upb_roundup_pow2(size_t bytes) {
-  size_t ret = 128;
-  while (ret < bytes) {
-    ret *= 2;
-  }
-  return ret;
-}
-
-static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) {
-  size_t old_size = e->limit - e->buf;
-  size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
-  char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
-  CHK(new_buf);
-
-  /* We want previous data at the end, realloc() put it at the beginning. */
-  if (old_size > 0) {
-    memmove(new_buf + new_size - old_size, e->buf, old_size);
-  }
-
-  e->ptr = new_buf + new_size - (e->limit - e->ptr);
-  e->limit = new_buf + new_size;
-  e->buf = new_buf;
-  return true;
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr.  Returns false if the bytes could not be allocated. */
-static bool upb_encode_reserve(upb_encstate *e, size_t bytes) {
-  CHK(UPB_LIKELY((size_t)(e->ptr - e->buf) >= bytes) ||
-      upb_encode_growbuffer(e, bytes));
-
-  e->ptr -= bytes;
-  return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) {
-  if (len == 0) return true;
-  CHK(upb_encode_reserve(e, len));
-  memcpy(e->ptr, data, len);
-  return true;
-}
-
-static bool upb_put_fixed64(upb_encstate *e, uint64_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return upb_put_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool upb_put_fixed32(upb_encstate *e, uint32_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return upb_put_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool upb_put_varint(upb_encstate *e, uint64_t val) {
-  size_t len;
-  char *start;
-  CHK(upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN));
-  len = upb_encode_varint(val, e->ptr);
-  start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
-  memmove(start, e->ptr, len);
-  e->ptr = start;
-  return true;
-}
-
-static bool upb_put_double(upb_encstate *e, double d) {
-  uint64_t u64;
-  UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
-  memcpy(&u64, &d, sizeof(uint64_t));
-  return upb_put_fixed64(e, u64);
-}
-
-static bool upb_put_float(upb_encstate *e, float d) {
-  uint32_t u32;
-  UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
-  memcpy(&u32, &d, sizeof(uint32_t));
-  return upb_put_fixed32(e, u32);
-}
-
-static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) {
-  uint32_t ret;
-  memcpy(&ret, msg - f->presence, sizeof(ret));
-  return ret;
-}
-
-static bool upb_readhasbit(const char *msg, const upb_msglayout_field *f) {
-  uint32_t hasbit = f->presence;
-  UPB_ASSERT(f->presence > 0);
-  return (*UPB_PTR_AT(msg, hasbit / 8, uint8_t)) & (1 << (hasbit % 8));
-}
-
-static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) {
-  return upb_put_varint(e, (field_number << 3) | wire_type);
-}
-
-static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr,
-                               size_t elem_size, uint32_t tag) {
-  size_t bytes = arr->len * elem_size;
-  const char* data = _upb_array_constptr(arr);
-  const char* ptr = data + bytes - elem_size;
-  if (tag) {
-    while (true) {
-      CHK(upb_put_bytes(e, ptr, elem_size) && upb_put_varint(e, tag));
-      if (ptr == data) break;
-      ptr -= elem_size;
-    }
-    return true;
-  } else {
-    return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes);
-  }
-}
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
-                        const upb_msglayout *m, size_t *size);
-
-static bool upb_encode_scalarfield(upb_encstate *e, const void *_field_mem,
-                                   const upb_msglayout *m,
-                                   const upb_msglayout_field *f,
-                                   bool skip_zero_value) {
-  const char *field_mem = _field_mem;
-#define CASE(ctype, type, wire_type, encodeval) do { \
-  ctype val = *(ctype*)field_mem; \
-  if (skip_zero_value && val == 0) { \
-    return true; \
-  } \
-  return upb_put_ ## type(e, encodeval) && \
-      upb_put_tag(e, f->number, wire_type); \
-} while(0)
-
-  switch (f->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-      CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val));
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-      CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val));
-    case UPB_DESCRIPTOR_TYPE_STRING:
-    case UPB_DESCRIPTOR_TYPE_BYTES: {
-      upb_strview view = *(upb_strview*)field_mem;
-      if (skip_zero_value && view.size == 0) {
-        return true;
-      }
-      return upb_put_bytes(e, view.data, view.size) &&
-          upb_put_varint(e, view.size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
-    }
-    case UPB_DESCRIPTOR_TYPE_GROUP: {
-      size_t size;
-      void *submsg = *(void **)field_mem;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      if (submsg == NULL) {
-        return true;
-      }
-      return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
-          upb_encode_message(e, submsg, subm, &size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
-    }
-    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-      size_t size;
-      void *submsg = *(void **)field_mem;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      if (submsg == NULL) {
-        return true;
-      }
-      return upb_encode_message(e, submsg, subm, &size) &&
-          upb_put_varint(e, size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
-    }
-  }
-#undef CASE
-  UPB_UNREACHABLE();
-}
-
-static bool upb_encode_array(upb_encstate *e, const char *field_mem,
-                             const upb_msglayout *m,
-                             const upb_msglayout_field *f) {
-  const upb_array *arr = *(const upb_array**)field_mem;
-  bool packed = f->label == _UPB_LABEL_PACKED;
-
-  if (arr == NULL || arr->len == 0) {
-    return true;
-  }
-
-#define VARINT_CASE(ctype, encode)                                       \
-  {                                                                      \
-    const ctype *start = _upb_array_constptr(arr);                       \
-    const ctype *ptr = start + arr->len;                                 \
-    size_t pre_len = e->limit - e->ptr;                                  \
-    uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
-    do {                                                                 \
-      ptr--;                                                             \
-      CHK(upb_put_varint(e, encode));                                    \
-      if (tag) CHK(upb_put_varint(e, tag));                              \
-    } while (ptr != start);                                              \
-    if (!tag) CHK(upb_put_varint(e, e->limit - e->ptr - pre_len));       \
-  }                                                                      \
-  break;                                                                 \
-  do {                                                                   \
-    ;                                                                    \
-  } while (0)
-
-#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
-
-  switch (f->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      CHK(upb_put_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      CHK(upb_put_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      VARINT_CASE(uint64_t, *ptr);
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-      VARINT_CASE(uint32_t, *ptr);
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      VARINT_CASE(int32_t, (int64_t)*ptr);
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      VARINT_CASE(bool, *ptr);
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      VARINT_CASE(int32_t, upb_zzencode_32(*ptr));
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-      VARINT_CASE(int64_t, upb_zzencode_64(*ptr));
-    case UPB_DESCRIPTOR_TYPE_STRING:
-    case UPB_DESCRIPTOR_TYPE_BYTES: {
-      const upb_strview *start = _upb_array_constptr(arr);
-      const upb_strview *ptr = start + arr->len;
-      do {
-        ptr--;
-        CHK(upb_put_bytes(e, ptr->data, ptr->size) &&
-            upb_put_varint(e, ptr->size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-      } while (ptr != start);
-      return true;
-    }
-    case UPB_DESCRIPTOR_TYPE_GROUP: {
-      const void *const*start = _upb_array_constptr(arr);
-      const void *const*ptr = start + arr->len;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      do {
-        size_t size;
-        ptr--;
-        CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
-            upb_encode_message(e, *ptr, subm, &size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP));
-      } while (ptr != start);
-      return true;
-    }
-    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-      const void *const*start = _upb_array_constptr(arr);
-      const void *const*ptr = start + arr->len;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      do {
-        size_t size;
-        ptr--;
-        CHK(upb_encode_message(e, *ptr, subm, &size) &&
-            upb_put_varint(e, size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-      } while (ptr != start);
-      return true;
-    }
-  }
-#undef VARINT_CASE
-
-  if (packed) {
-    CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-  }
-  return true;
-}
-
-static bool upb_encode_map(upb_encstate *e, const char *field_mem,
-                           const upb_msglayout *m,
-                           const upb_msglayout_field *f) {
-  const upb_map *map = *(const upb_map**)field_mem;
-  const upb_msglayout *entry = m->submsgs[f->submsg_index];
-  const upb_msglayout_field *key_field = &entry->fields[0];
-  const upb_msglayout_field *val_field = &entry->fields[1];
-  upb_strtable_iter i;
-  if (map == NULL) {
-    return true;
-  }
-
-  upb_strtable_begin(&i, &map->table);
-  for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
-    size_t pre_len = e->limit - e->ptr;
-    size_t size;
-    upb_strview key = upb_strtable_iter_key(&i);
-    const upb_value val = upb_strtable_iter_value(&i);
-    const void *keyp =
-        map->key_size == UPB_MAPTYPE_STRING ? (void *)&key : key.data;
-    const void *valp =
-        map->val_size == UPB_MAPTYPE_STRING ? upb_value_getptr(val) : &val;
-
-    CHK(upb_encode_scalarfield(e, valp, entry, val_field, false));
-    CHK(upb_encode_scalarfield(e, keyp, entry, key_field, false));
-    size = (e->limit - e->ptr) - pre_len;
-    CHK(upb_put_varint(e, size));
-    CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-  }
-
-  return true;
-}
-
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
-                        const upb_msglayout *m, size_t *size) {
-  int i;
-  size_t pre_len = e->limit - e->ptr;
-  const char *unknown;
-  size_t unknown_size;
-
-  unknown = upb_msg_getunknown(msg, &unknown_size);
-
-  if (unknown) {
-    upb_put_bytes(e, unknown, unknown_size);
-  }
-
-  for (i = m->field_count - 1; i >= 0; i--) {
-    const upb_msglayout_field *f = &m->fields[i];
-
-    if (_upb_isrepeated(f)) {
-      CHK(upb_encode_array(e, msg + f->offset, m, f));
-    } else if (f->label == _UPB_LABEL_MAP) {
-      CHK(upb_encode_map(e, msg + f->offset, m, f));
-    } else {
-      bool skip_empty = false;
-      if (f->presence == 0) {
-        /* Proto3 presence. */
-        skip_empty = true;
-      } else if (f->presence > 0) {
-        /* Proto2 presence: hasbit. */
-        if (!upb_readhasbit(msg, f)) {
-          continue;
-        }
-      } else {
-        /* Field is in a oneof. */
-        if (upb_readcase(msg, f) != f->number) {
-          continue;
-        }
-      }
-      CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, skip_empty));
-    }
-  }
-
-  *size = (e->limit - e->ptr) - pre_len;
-  return true;
-}
-
-char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena,
-                 size_t *size) {
-  upb_encstate e;
-  e.alloc = upb_arena_alloc(arena);
-  e.buf = NULL;
-  e.limit = NULL;
-  e.ptr = NULL;
-
-  if (!upb_encode_message(&e, msg, m, size)) {
-    *size = 0;
-    return NULL;
-  }
-
-  *size = e.limit - e.ptr;
-
-  if (*size == 0) {
-    static char ch;
-    return &ch;
-  } else {
-    UPB_ASSERT(e.ptr);
-    return e.ptr;
-  }
-}
-
-#undef CHK
-
-
-
-
-/** upb_msg *******************************************************************/
-
-static const char _upb_fieldtype_to_sizelg2[12] = {
-  0,
-  0,  /* UPB_TYPE_BOOL */
-  2,  /* UPB_TYPE_FLOAT */
-  2,  /* UPB_TYPE_INT32 */
-  2,  /* UPB_TYPE_UINT32 */
-  2,  /* UPB_TYPE_ENUM */
-  UPB_SIZE(2, 3),  /* UPB_TYPE_MESSAGE */
-  3,  /* UPB_TYPE_DOUBLE */
-  3,  /* UPB_TYPE_INT64 */
-  3,  /* UPB_TYPE_UINT64 */
-  UPB_SIZE(3, 4),  /* UPB_TYPE_STRING */
-  UPB_SIZE(3, 4),  /* UPB_TYPE_BYTES */
-};
-
-static uintptr_t tag_arrptr(void* ptr, int elem_size_lg2) {
-  UPB_ASSERT(elem_size_lg2 <= 4);
-  return (uintptr_t)ptr | elem_size_lg2;
-}
-
-static int upb_msg_internalsize(const upb_msglayout *l) {
-  return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
-}
-
-static size_t upb_msg_sizeof(const upb_msglayout *l) {
-  return l->size + upb_msg_internalsize(l);
-}
-
-static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
-  return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal);
-}
-
-static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
-  return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal);
-}
-
-static upb_msg_internal_withext *upb_msg_getinternalwithext(
-    upb_msg *msg, const upb_msglayout *l) {
-  UPB_ASSERT(l->extendable);
-  return UPB_PTR_AT(msg, -sizeof(upb_msg_internal_withext),
-                    upb_msg_internal_withext);
-}
-
-upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
-  void *mem = upb_arena_malloc(a, upb_msg_sizeof(l));
-  upb_msg_internal *in;
-  upb_msg *msg;
-
-  if (!mem) {
-    return NULL;
-  }
-
-  msg = UPB_PTR_AT(mem, upb_msg_internalsize(l), upb_msg);
-
-  /* Initialize normal members. */
-  memset(msg, 0, l->size);
-
-  /* Initialize internal members. */
-  in = upb_msg_getinternal(msg);
-  in->unknown = NULL;
-  in->unknown_len = 0;
-  in->unknown_size = 0;
-
-  if (l->extendable) {
-    upb_msg_getinternalwithext(msg, l)->extdict = NULL;
-  }
-
-  return msg;
-}
-
-bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                         upb_arena *arena) {
-  upb_msg_internal *in = upb_msg_getinternal(msg);
-  if (len > in->unknown_size - in->unknown_len) {
-    upb_alloc *alloc = upb_arena_alloc(arena);
-    size_t need = in->unknown_size + len;
-    size_t newsize = UPB_MAX(in->unknown_size * 2, need);
-    void *mem = upb_realloc(alloc, in->unknown, in->unknown_size, newsize);
-    if (!mem) return false;
-    in->unknown = mem;
-    in->unknown_size = newsize;
-  }
-  memcpy(in->unknown + in->unknown_len, data, len);
-  in->unknown_len += len;
-  return true;
-}
-
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
-  const upb_msg_internal *in = upb_msg_getinternal_const(msg);
-  *len = in->unknown_len;
-  return in->unknown;
-}
-
-/** upb_array *****************************************************************/
-
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type) {
-  upb_array *arr = upb_arena_malloc(a, sizeof(upb_array));
-
-  if (!arr) {
-    return NULL;
-  }
-
-  arr->data = tag_arrptr(NULL, _upb_fieldtype_to_sizelg2[type]);
-  arr->len = 0;
-  arr->size = 0;
-
-  return arr;
-}
-
-bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
-  size_t new_size = UPB_MAX(arr->size, 4);
-  int elem_size_lg2 = arr->data & 7;
-  size_t old_bytes = arr->size << elem_size_lg2;
-  size_t new_bytes;
-  void* ptr = _upb_array_ptr(arr);
-
-  /* Log2 ceiling of size. */
-  while (new_size < min_size) new_size *= 2;
-
-  new_bytes = new_size << elem_size_lg2;
-  ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes);
-
-  if (!ptr) {
-    return false;
-  }
-
-  arr->data = tag_arrptr(ptr, elem_size_lg2);
-  arr->size = new_size;
-  return true;
-}
-
-static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type,
-                                    upb_arena *arena) {
-  upb_array *arr = *arr_ptr;
-  if (!arr) {
-    arr = _upb_array_new(arena, type);
-    if (!arr) return NULL;
-    *arr_ptr = arr;
-  }
-  return arr;
-}
-
-static bool resize_array(upb_array *arr, size_t size, upb_arena *arena) {
-  if (size > arr->size && !_upb_array_realloc(arr, size, arena)) {
-    return false;
-  }
-
-  arr->len = size;
-  return true;
-}
-
-void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
-                                 upb_fieldtype_t type, upb_arena *arena) {
-  upb_array *arr = getorcreate_array(arr_ptr, type, arena);
-  return arr && resize_array(arr, size, arena) ? _upb_array_ptr(arr) : NULL;
-}
-
-bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
-                                upb_fieldtype_t type, upb_arena *arena) {
-  upb_array *arr = getorcreate_array(arr_ptr, type, arena);
-  size_t elem = arr->len;
-  int lg2 = _upb_fieldtype_to_sizelg2[type];
-  char *data;
-
-  if (!arr || !resize_array(arr, elem + 1, arena)) return false;
-
-  data = _upb_array_ptr(arr);
-  memcpy(data + (elem << lg2), value, 1 << lg2);
-  return true;
-}
-
-/** upb_map *******************************************************************/
-
-upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
-  upb_map *map = upb_arena_malloc(a, sizeof(upb_map));
-
-  if (!map) {
-    return NULL;
-  }
-
-  upb_strtable_init2(&map->table, UPB_CTYPE_INT32, upb_arena_alloc(a));
-  map->key_size = key_size;
-  map->val_size = value_size;
-
-  return map;
-}
-/*
-** upb_table Implementation
-**
-** Implementation is heavily inspired by Lua's ltable.c.
-*/
-
-
-#include <string.h>
-
-
-#define UPB_MAXARRSIZE 16  /* 64k. */
-
-/* From Chromium. */
-#define ARRAY_SIZE(x) \
-    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
-
-static const double MAX_LOAD = 0.85;
-
-/* The minimum utilization of the array part of a mixed hash/array table.  This
- * is a speed/memory-usage tradeoff (though it's not straightforward because of
- * cache effects).  The lower this is, the more memory we'll use. */
-static const double MIN_DENSITY = 0.1;
-
-bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
-
-int log2ceil(uint64_t v) {
-  int ret = 0;
-  bool pow2 = is_pow2(v);
-  while (v >>= 1) ret++;
-  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
-  return UPB_MIN(UPB_MAXARRSIZE, ret);
-}
-
-char *upb_strdup(const char *s, upb_alloc *a) {
-  return upb_strdup2(s, strlen(s), a);
-}
-
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
-  size_t n;
-  char *p;
-
-  /* Prevent overflow errors. */
-  if (len == SIZE_MAX) return NULL;
-  /* Always null-terminate, even if binary data; but don't rely on the input to
-   * have a null-terminating byte since it may be a raw binary buffer. */
-  n = len + 1;
-  p = upb_malloc(a, n);
-  if (p) {
-    memcpy(p, s, len);
-    p[len] = 0;
-  }
-  return p;
-}
-
-/* A type to represent the lookup key of either a strtable or an inttable. */
-typedef union {
-  uintptr_t num;
-  struct {
-    const char *str;
-    size_t len;
-  } str;
-} lookupkey_t;
-
-static lookupkey_t strkey2(const char *str, size_t len) {
-  lookupkey_t k;
-  k.str.str = str;
-  k.str.len = len;
-  return k;
-}
-
-static lookupkey_t intkey(uintptr_t key) {
-  lookupkey_t k;
-  k.num = key;
-  return k;
-}
-
-typedef uint32_t hashfunc_t(upb_tabkey key);
-typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
-
-/* Base table (shared code) ***************************************************/
-
-/* For when we need to cast away const. */
-static upb_tabent *mutable_entries(upb_table *t) {
-  return (upb_tabent*)t->entries;
-}
-
-static bool isfull(upb_table *t) {
-  if (upb_table_size(t) == 0) {
-    return true;
-  } else {
-    return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
-  }
-}
-
-static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
-  size_t bytes;
-
-  t->count = 0;
-  t->size_lg2 = size_lg2;
-  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
-  bytes = upb_table_size(t) * sizeof(upb_tabent);
-  if (bytes > 0) {
-    t->entries = upb_malloc(a, bytes);
-    if (!t->entries) return false;
-    memset(mutable_entries(t), 0, bytes);
-  } else {
-    t->entries = NULL;
-  }
-  return true;
-}
-
-static void uninit(upb_table *t, upb_alloc *a) {
-  upb_free(a, mutable_entries(t));
-}
-
-static upb_tabent *emptyent(upb_table *t) {
-  upb_tabent *e = mutable_entries(t) + upb_table_size(t);
-  while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); }
-}
-
-static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
-  return (upb_tabent*)upb_getentry(t, hash);
-}
-
-static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
-                                   uint32_t hash, eqlfunc_t *eql) {
-  const upb_tabent *e;
-
-  if (t->size_lg2 == 0) return NULL;
-  e = upb_getentry(t, hash);
-  if (upb_tabent_isempty(e)) return NULL;
-  while (1) {
-    if (eql(e->key, key)) return e;
-    if ((e = e->next) == NULL) return NULL;
-  }
-}
-
-static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
-                                     uint32_t hash, eqlfunc_t *eql) {
-  return (upb_tabent*)findentry(t, key, hash, eql);
-}
-
-static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
-                   uint32_t hash, eqlfunc_t *eql) {
-  const upb_tabent *e = findentry(t, key, hash, eql);
-  if (e) {
-    if (v) {
-      _upb_value_setval(v, e->val.val);
-    }
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* The given key must not already exist in the table. */
-static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
-                   upb_value val, uint32_t hash,
-                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
-  upb_tabent *mainpos_e;
-  upb_tabent *our_e;
-
-  UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
-
-  t->count++;
-  mainpos_e = getentry_mutable(t, hash);
-  our_e = mainpos_e;
-
-  if (upb_tabent_isempty(mainpos_e)) {
-    /* Our main position is empty; use it. */
-    our_e->next = NULL;
-  } else {
-    /* Collision. */
-    upb_tabent *new_e = emptyent(t);
-    /* Head of collider's chain. */
-    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
-    if (chain == mainpos_e) {
-      /* Existing ent is in its main posisiton (it has the same hash as us, and
-       * is the head of our chain).  Insert to new ent and append to this chain. */
-      new_e->next = mainpos_e->next;
-      mainpos_e->next = new_e;
-      our_e = new_e;
-    } else {
-      /* Existing ent is not in its main position (it is a node in some other
-       * chain).  This implies that no existing ent in the table has our hash.
-       * Evict it (updating its chain) and use its ent for head of our chain. */
-      *new_e = *mainpos_e;  /* copies next. */
-      while (chain->next != mainpos_e) {
-        chain = (upb_tabent*)chain->next;
-        UPB_ASSERT(chain);
-      }
-      chain->next = new_e;
-      our_e = mainpos_e;
-      our_e->next = NULL;
-    }
-  }
-  our_e->key = tabkey;
-  our_e->val.val = val.val;
-  UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
-}
-
-static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
-               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
-  upb_tabent *chain = getentry_mutable(t, hash);
-  if (upb_tabent_isempty(chain)) return false;
-  if (eql(chain->key, key)) {
-    /* Element to remove is at the head of its chain. */
-    t->count--;
-    if (val) _upb_value_setval(val, chain->val.val);
-    if (removed) *removed = chain->key;
-    if (chain->next) {
-      upb_tabent *move = (upb_tabent*)chain->next;
-      *chain = *move;
-      move->key = 0;  /* Make the slot empty. */
-    } else {
-      chain->key = 0;  /* Make the slot empty. */
-    }
-    return true;
-  } else {
-    /* Element to remove is either in a non-head position or not in the
-     * table. */
-    while (chain->next && !eql(chain->next->key, key)) {
-      chain = (upb_tabent*)chain->next;
-    }
-    if (chain->next) {
-      /* Found element to remove. */
-      upb_tabent *rm = (upb_tabent*)chain->next;
-      t->count--;
-      if (val) _upb_value_setval(val, chain->next->val.val);
-      if (removed) *removed = rm->key;
-      rm->key = 0;  /* Make the slot empty. */
-      chain->next = rm->next;
-      return true;
-    } else {
-      /* Element to remove is not in the table. */
-      return false;
-    }
-  }
-}
-
-static size_t next(const upb_table *t, size_t i) {
-  do {
-    if (++i >= upb_table_size(t))
-      return SIZE_MAX;
-  } while(upb_tabent_isempty(&t->entries[i]));
-
-  return i;
-}
-
-static size_t begin(const upb_table *t) {
-  return next(t, -1);
-}
-
-
-/* upb_strtable ***************************************************************/
-
-/* A simple "subclass" of upb_table that only adds a hash function for strings. */
-
-static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
-  uint32_t len = (uint32_t) k2.str.len;
-  char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
-  if (str == NULL) return 0;
-  memcpy(str, &len, sizeof(uint32_t));
-  memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
-  str[sizeof(uint32_t) + k2.str.len] = '\0';
-  return (uintptr_t)str;
-}
-
-static uint32_t strhash(upb_tabkey key) {
-  uint32_t len;
-  char *str = upb_tabstr(key, &len);
-  return upb_murmur_hash2(str, len, 0);
-}
-
-static bool streql(upb_tabkey k1, lookupkey_t k2) {
-  uint32_t len;
-  char *str = upb_tabstr(k1, &len);
-  return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
-}
-
-bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
-  return init(&t->t, 2, a);
-}
-
-void upb_strtable_clear(upb_strtable *t) {
-  size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
-  t->t.count = 0;
-  memset((char*)t->t.entries, 0, bytes);
-}
-
-void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
-  size_t i;
-  for (i = 0; i < upb_table_size(&t->t); i++)
-    upb_free(a, (void*)t->t.entries[i].key);
-  uninit(&t->t, a);
-}
-
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
-  upb_strtable new_table;
-  upb_strtable_iter i;
-
-  if (!init(&new_table.t, size_lg2, a))
-    return false;
-  upb_strtable_begin(&i, t);
-  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
-    upb_strview key = upb_strtable_iter_key(&i);
-    upb_strtable_insert3(
-        &new_table, key.data, key.size,
-        upb_strtable_iter_value(&i), a);
-  }
-  upb_strtable_uninit2(t, a);
-  *t = new_table;
-  return true;
-}
-
-bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
-                          upb_value v, upb_alloc *a) {
-  lookupkey_t key;
-  upb_tabkey tabkey;
-  uint32_t hash;
-
-  if (isfull(&t->t)) {
-    /* Need to resize.  New table of double the size, add old elements to it. */
-    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
-      return false;
-    }
-  }
-
-  key = strkey2(k, len);
-  tabkey = strcopy(key, a);
-  if (tabkey == 0) return false;
-
-  hash = upb_murmur_hash2(key.str.str, key.str.len, 0);
-  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
-  return true;
-}
-
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
-                          upb_value *v) {
-  uint32_t hash = upb_murmur_hash2(key, len, 0);
-  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
-}
-
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
-                         upb_value *val, upb_alloc *alloc) {
-  uint32_t hash = upb_murmur_hash2(key, len, 0);
-  upb_tabkey tabkey;
-  if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
-    if (alloc) {
-      /* Arena-based allocs don't need to free and won't pass this. */
-      upb_free(alloc, (void*)tabkey);
-    }
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* Iteration */
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
-  i->t = t;
-  i->index = begin(&t->t);
-}
-
-void upb_strtable_next(upb_strtable_iter *i) {
-  i->index = next(&i->t->t, i->index);
-}
-
-bool upb_strtable_done(const upb_strtable_iter *i) {
-  if (!i->t) return true;
-  return i->index >= upb_table_size(&i->t->t) ||
-         upb_tabent_isempty(str_tabent(i));
-}
-
-upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) {
-  upb_strview key;
-  uint32_t len;
-  UPB_ASSERT(!upb_strtable_done(i));
-  key.data = upb_tabstr(str_tabent(i)->key, &len);
-  key.size = len;
-  return key;
-}
-
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
-  UPB_ASSERT(!upb_strtable_done(i));
-  return _upb_value_val(str_tabent(i)->val.val);
-}
-
-void upb_strtable_iter_setdone(upb_strtable_iter *i) {
-  i->t = NULL;
-  i->index = SIZE_MAX;
-}
-
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
-                               const upb_strtable_iter *i2) {
-  if (upb_strtable_done(i1) && upb_strtable_done(i2))
-    return true;
-  return i1->t == i2->t && i1->index == i2->index;
-}
-
-
-/* upb_inttable ***************************************************************/
-
-/* For inttables we use a hybrid structure where small keys are kept in an
- * array and large keys are put in the hash table. */
-
-static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
-
-static bool inteql(upb_tabkey k1, lookupkey_t k2) {
-  return k1 == k2.num;
-}
-
-static upb_tabval *mutable_array(upb_inttable *t) {
-  return (upb_tabval*)t->array;
-}
-
-static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
-  if (key < t->array_size) {
-    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
-  } else {
-    upb_tabent *e =
-        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
-    return e ? &e->val : NULL;
-  }
-}
-
-static const upb_tabval *inttable_val_const(const upb_inttable *t,
-                                            uintptr_t key) {
-  return inttable_val((upb_inttable*)t, key);
-}
-
-size_t upb_inttable_count(const upb_inttable *t) {
-  return t->t.count + t->array_count;
-}
-
-static void check(upb_inttable *t) {
-  UPB_UNUSED(t);
-#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
-  {
-    /* This check is very expensive (makes inserts/deletes O(N)). */
-    size_t count = 0;
-    upb_inttable_iter i;
-    upb_inttable_begin(&i, t);
-    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
-      UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
-    }
-    UPB_ASSERT(count == upb_inttable_count(t));
-  }
-#endif
-}
-
-bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
-                            upb_alloc *a) {
-  size_t array_bytes;
-
-  if (!init(&t->t, hsize_lg2, a)) return false;
-  /* Always make the array part at least 1 long, so that we know key 0
-   * won't be in the hash part, which simplifies things. */
-  t->array_size = UPB_MAX(1, asize);
-  t->array_count = 0;
-  array_bytes = t->array_size * sizeof(upb_value);
-  t->array = upb_malloc(a, array_bytes);
-  if (!t->array) {
-    uninit(&t->t, a);
-    return false;
-  }
-  memset(mutable_array(t), 0xff, array_bytes);
-  check(t);
-  return true;
-}
-
-bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
-  return upb_inttable_sizedinit(t, 0, 4, a);
-}
-
-void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
-  uninit(&t->t, a);
-  upb_free(a, mutable_array(t));
-}
-
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
-                          upb_alloc *a) {
-  upb_tabval tabval;
-  tabval.val = val.val;
-  UPB_ASSERT(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
-
-  if (key < t->array_size) {
-    UPB_ASSERT(!upb_arrhas(t->array[key]));
-    t->array_count++;
-    mutable_array(t)[key].val = val.val;
-  } else {
-    if (isfull(&t->t)) {
-      /* Need to resize the hash part, but we re-use the array part. */
-      size_t i;
-      upb_table new_table;
-
-      if (!init(&new_table, t->t.size_lg2 + 1, a)) {
-        return false;
-      }
-
-      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
-        const upb_tabent *e = &t->t.entries[i];
-        uint32_t hash;
-        upb_value v;
-
-        _upb_value_setval(&v, e->val.val);
-        hash = upb_inthash(e->key);
-        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
-      }
-
-      UPB_ASSERT(t->t.count == new_table.count);
-
-      uninit(&t->t, a);
-      t->t = new_table;
-    }
-    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
-  }
-  check(t);
-  return true;
-}
-
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
-  const upb_tabval *table_v = inttable_val_const(t, key);
-  if (!table_v) return false;
-  if (v) _upb_value_setval(v, table_v->val);
-  return true;
-}
-
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
-  upb_tabval *table_v = inttable_val(t, key);
-  if (!table_v) return false;
-  table_v->val = val.val;
-  return true;
-}
-
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
-  bool success;
-  if (key < t->array_size) {
-    if (upb_arrhas(t->array[key])) {
-      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
-      t->array_count--;
-      if (val) {
-        _upb_value_setval(val, t->array[key].val);
-      }
-      mutable_array(t)[key] = empty;
-      success = true;
-    } else {
-      success = false;
-    }
-  } else {
-    success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
-  }
-  check(t);
-  return success;
-}
-
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
-  return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
-}
-
-upb_value upb_inttable_pop(upb_inttable *t) {
-  upb_value val;
-  bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
-  UPB_ASSERT(ok);
-  return val;
-}
-
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
-                             upb_alloc *a) {
-  return upb_inttable_insert2(t, (uintptr_t)key, val, a);
-}
-
-bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
-                            upb_value *v) {
-  return upb_inttable_lookup(t, (uintptr_t)key, v);
-}
-
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
-  return upb_inttable_remove(t, (uintptr_t)key, val);
-}
-
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
-  /* A power-of-two histogram of the table keys. */
-  size_t counts[UPB_MAXARRSIZE + 1] = {0};
-
-  /* The max key in each bucket. */
-  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
-
-  upb_inttable_iter i;
-  size_t arr_count;
-  int size_lg2;
-  upb_inttable new_t;
-
-  upb_inttable_begin(&i, t);
-  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    uintptr_t key = upb_inttable_iter_key(&i);
-    int bucket = log2ceil(key);
-    max[bucket] = UPB_MAX(max[bucket], key);
-    counts[bucket]++;
-  }
-
-  /* Find the largest power of two that satisfies the MIN_DENSITY
-   * definition (while actually having some keys). */
-  arr_count = upb_inttable_count(t);
-
-  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
-    if (counts[size_lg2] == 0) {
-      /* We can halve again without losing any entries. */
-      continue;
-    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
-      break;
-    }
-
-    arr_count -= counts[size_lg2];
-  }
-
-  UPB_ASSERT(arr_count <= upb_inttable_count(t));
-
-  {
-    /* Insert all elements into new, perfectly-sized table. */
-    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
-    size_t hash_count = upb_inttable_count(t) - arr_count;
-    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
-    int hashsize_lg2 = log2ceil(hash_size);
-
-    upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a);
-    upb_inttable_begin(&i, t);
-    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-      uintptr_t k = upb_inttable_iter_key(&i);
-      upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
-    }
-    UPB_ASSERT(new_t.array_size == arr_size);
-    UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
-  }
-  upb_inttable_uninit2(t, a);
-  *t = new_t;
-}
-
-/* Iteration. */
-
-static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
-  UPB_ASSERT(!i->array_part);
-  return &i->t->t.entries[i->index];
-}
-
-static upb_tabval int_arrent(const upb_inttable_iter *i) {
-  UPB_ASSERT(i->array_part);
-  return i->t->array[i->index];
-}
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
-  i->t = t;
-  i->index = -1;
-  i->array_part = true;
-  upb_inttable_next(i);
-}
-
-void upb_inttable_next(upb_inttable_iter *iter) {
-  const upb_inttable *t = iter->t;
-  if (iter->array_part) {
-    while (++iter->index < t->array_size) {
-      if (upb_arrhas(int_arrent(iter))) {
-        return;
-      }
-    }
-    iter->array_part = false;
-    iter->index = begin(&t->t);
-  } else {
-    iter->index = next(&t->t, iter->index);
-  }
-}
-
-bool upb_inttable_done(const upb_inttable_iter *i) {
-  if (!i->t) return true;
-  if (i->array_part) {
-    return i->index >= i->t->array_size ||
-           !upb_arrhas(int_arrent(i));
-  } else {
-    return i->index >= upb_table_size(&i->t->t) ||
-           upb_tabent_isempty(int_tabent(i));
-  }
-}
-
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
-  UPB_ASSERT(!upb_inttable_done(i));
-  return i->array_part ? i->index : int_tabent(i)->key;
-}
-
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
-  UPB_ASSERT(!upb_inttable_done(i));
-  return _upb_value_val(
-      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val);
-}
-
-void upb_inttable_iter_setdone(upb_inttable_iter *i) {
-  i->t = NULL;
-  i->index = SIZE_MAX;
-  i->array_part = false;
-}
-
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
-                                          const upb_inttable_iter *i2) {
-  if (upb_inttable_done(i1) && upb_inttable_done(i2))
-    return true;
-  return i1->t == i2->t && i1->index == i2->index &&
-         i1->array_part == i2->array_part;
-}
-
-#if defined(UPB_UNALIGNED_READS_OK) || defined(__s390x__)
-/* -----------------------------------------------------------------------------
- * MurmurHash2, by Austin Appleby (released as public domain).
- * Reformatted and C99-ified by Joshua Haberman.
- * Note - This code makes a few assumptions about how your machine behaves -
- *   1. We can read a 4-byte value from any address without crashing
- *   2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
- * And it has a few limitations -
- *   1. It will not work incrementally.
- *   2. It will not produce the same results on little-endian and big-endian
- *      machines. */
-uint32_t upb_murmur_hash2(const void *key, size_t len, uint32_t seed) {
-  /* 'm' and 'r' are mixing constants generated offline.
-   * They're not really 'magic', they just happen to work well. */
-  const uint32_t m = 0x5bd1e995;
-  const int32_t r = 24;
-
-  /* Initialize the hash to a 'random' value */
-  uint32_t h = seed ^ len;
-
-  /* Mix 4 bytes at a time into the hash */
-  const uint8_t * data = (const uint8_t *)key;
-  while(len >= 4) {
-    uint32_t k;
-    memcpy(&k, data, sizeof(k));
-
-    k *= m;
-    k ^= k >> r;
-    k *= m;
-
-    h *= m;
-    h ^= k;
-
-    data += 4;
-    len -= 4;
-  }
-
-  /* Handle the last few bytes of the input array */
-  switch(len) {
-    case 3: h ^= data[2] << 16;
-    case 2: h ^= data[1] << 8;
-    case 1: h ^= data[0]; h *= m;
-  };
-
-  /* Do a few final mixes of the hash to ensure the last few
-   * bytes are well-incorporated. */
-  h ^= h >> 13;
-  h *= m;
-  h ^= h >> 15;
-
-  return h;
-}
-
-#else /* !UPB_UNALIGNED_READS_OK */
-
-/* -----------------------------------------------------------------------------
- * MurmurHashAligned2, by Austin Appleby
- * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
- * on certain platforms.
- * Performance will be lower than MurmurHash2 */
-
-#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
-
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed) {
-  const uint32_t m = 0x5bd1e995;
-  const int32_t r = 24;
-  const uint8_t * data = (const uint8_t *)key;
-  uint32_t h = (uint32_t)(seed ^ len);
-  uint8_t align = (uintptr_t)data & 3;
-
-  if(align && (len >= 4)) {
-    /* Pre-load the temp registers */
-    uint32_t t = 0, d = 0;
-    int32_t sl;
-    int32_t sr;
-
-    switch(align) {
-      case 1: t |= data[2] << 16;
-      case 2: t |= data[1] << 8;
-      case 3: t |= data[0];
-    }
-
-    t <<= (8 * align);
-
-    data += 4-align;
-    len -= 4-align;
-
-    sl = 8 * (4-align);
-    sr = 8 * align;
-
-    /* Mix */
-
-    while(len >= 4) {
-      uint32_t k;
-
-      d = *(uint32_t *)data;
-      t = (t >> sr) | (d << sl);
-
-      k = t;
-
-      MIX(h,k,m);
-
-      t = d;
-
-      data += 4;
-      len -= 4;
-    }
-
-    /* Handle leftover data in temp registers */
-
-    d = 0;
-
-    if(len >= align) {
-      uint32_t k;
-
-      switch(align) {
-        case 3: d |= data[2] << 16;
-        case 2: d |= data[1] << 8;
-        case 1: d |= data[0];
-      }
-
-      k = (t >> sr) | (d << sl);
-      MIX(h,k,m);
-
-      data += align;
-      len -= align;
-
-      /* ----------
-       * Handle tail bytes */
-
-      switch(len) {
-        case 3: h ^= data[2] << 16;
-        case 2: h ^= data[1] << 8;
-        case 1: h ^= data[0]; h *= m;
-      };
-    } else {
-      switch(len) {
-        case 3: d |= data[2] << 16;
-        case 2: d |= data[1] << 8;
-        case 1: d |= data[0];
-        case 0: h ^= (t >> sr) | (d << sl); h *= m;
-      }
-    }
-
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-  } else {
-    while(len >= 4) {
-      uint32_t k = *(uint32_t *)data;
-
-      MIX(h,k,m);
-
-      data += 4;
-      len -= 4;
-    }
-
-    /* ----------
-     * Handle tail bytes */
-
-    switch(len) {
-      case 3: h ^= data[2] << 16;
-      case 2: h ^= data[1] << 8;
-      case 1: h ^= data[0]; h *= m;
-    };
-
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-  }
-}
-#undef MIX
-
-#endif /* UPB_UNALIGNED_READS_OK */
-
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-/* upb_status *****************************************************************/
-
-void upb_status_clear(upb_status *status) {
-  if (!status) return;
-  status->ok = true;
-  status->msg[0] = '\0';
-}
-
-bool upb_ok(const upb_status *status) { return status->ok; }
-
-const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
-
-void upb_status_seterrmsg(upb_status *status, const char *msg) {
-  if (!status) return;
-  status->ok = false;
-  strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1);
-  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
-}
-
-void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  upb_status_vseterrf(status, fmt, args);
-  va_end(args);
-}
-
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
-  if (!status) return;
-  status->ok = false;
-  _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
-  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
-}
-
-/* upb_alloc ******************************************************************/
-
-static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                                  size_t size) {
-  UPB_UNUSED(alloc);
-  UPB_UNUSED(oldsize);
-  if (size == 0) {
-    free(ptr);
-    return NULL;
-  } else {
-    return realloc(ptr, size);
-  }
-}
-
-upb_alloc upb_alloc_global = {&upb_global_allocfunc};
-
-/* upb_arena ******************************************************************/
-
-/* Be conservative and choose 16 in case anyone is using SSE. */
-
-struct upb_arena {
-  _upb_arena_head head;
-  char *start;
-
-  /* Allocator to allocate arena blocks.  We are responsible for freeing these
-   * when we are destroyed. */
-  upb_alloc *block_alloc;
-
-  size_t bytes_allocated;
-  size_t next_block_size;
-  size_t max_block_size;
-
-  /* Linked list of blocks.  Points to an arena_block, defined in env.c */
-  void *block_head;
-
-  /* Cleanup entries.  Pointer to a cleanup_ent, defined in env.c */
-  void *cleanup_head;
-};
-
-typedef struct mem_block {
-  struct mem_block *next;
-  bool owned;
-  /* Data follows. */
-} mem_block;
-
-typedef struct cleanup_ent {
-  struct cleanup_ent *next;
-  upb_cleanup_func *cleanup;
-  void *ud;
-} cleanup_ent;
-
-static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size,
-                               bool owned) {
-  mem_block *block = ptr;
-
-  if (a->block_head) {
-    a->bytes_allocated += a->head.ptr - a->start;
-  }
-
-  block->next = a->block_head;
-  block->owned = owned;
-
-  a->block_head = block;
-  a->start = (char*)block + _upb_arena_alignup(sizeof(mem_block));
-  a->head.ptr = a->start;
-  a->head.end = (char*)block + size;
-
-  /* TODO(haberman): ASAN poison. */
-}
-
-static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) {
-  size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block);
-  mem_block *block = upb_malloc(a->block_alloc, block_size);
-
-  if (!block) {
-    return NULL;
-  }
-
-  upb_arena_addblock(a, block, block_size, true);
-  a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size);
-
-  return block;
-}
-
-void *_upb_arena_slowmalloc(upb_arena *a, size_t size) {
-  mem_block *block = upb_arena_allocblock(a, size);
-  if (!block) return NULL;  /* Out of memory. */
-  return upb_arena_malloc(a, size);
-}
-
-static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                               size_t size) {
-  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
-  void *ret;
-
-  if (size == 0) {
-    return NULL;  /* We are an arena, don't need individual frees. */
-  }
-
-  ret = upb_arena_malloc(a, size);
-  if (!ret) return NULL;
-
-  /* TODO(haberman): special-case if this is a realloc of the last alloc? */
-
-  if (oldsize > 0) {
-    memcpy(ret, ptr, oldsize);  /* Preserve existing data. */
-  }
-
-  /* TODO(haberman): ASAN unpoison. */
-  return ret;
-}
-
-/* Public Arena API ***********************************************************/
-
-#define upb_alignof(type) offsetof (struct { char c; type member; }, member)
-
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
-  const size_t first_block_overhead = sizeof(upb_arena) + sizeof(mem_block);
-  upb_arena *a;
-  bool owned = false;
-
-  /* Round block size down to alignof(*a) since we will allocate the arena
-   * itself at the end. */
-  n &= ~(upb_alignof(upb_arena) - 1);
-
-  if (n < first_block_overhead) {
-    /* We need to malloc the initial block. */
-    n = first_block_overhead + 256;
-    owned = true;
-    if (!alloc || !(mem = upb_malloc(alloc, n))) {
-      return NULL;
-    }
-  }
-
-  a = (void*)((char*)mem + n - sizeof(*a));
-  n -= sizeof(*a);
-
-  a->head.alloc.func = &upb_arena_doalloc;
-  a->head.ptr = NULL;
-  a->head.end = NULL;
-  a->start = NULL;
-  a->block_alloc = &upb_alloc_global;
-  a->bytes_allocated = 0;
-  a->next_block_size = 256;
-  a->max_block_size = 16384;
-  a->cleanup_head = NULL;
-  a->block_head = NULL;
-  a->block_alloc = alloc;
-
-  upb_arena_addblock(a, mem, n, owned);
-
-  return a;
-}
-
-#undef upb_alignof
-
-void upb_arena_free(upb_arena *a) {
-  cleanup_ent *ent = a->cleanup_head;
-  mem_block *block = a->block_head;
-
-  while (ent) {
-    ent->cleanup(ent->ud);
-    ent = ent->next;
-  }
-
-  /* Must do this after running cleanup functions, because this will delete
-   * the memory we store our cleanup entries in! */
-  while (block) {
-    /* Load first since we are deleting block. */
-    mem_block *next = block->next;
-
-    if (block->owned) {
-      upb_free(a->block_alloc, block);
-    }
-
-    block = next;
-  }
-}
-
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
-  cleanup_ent *ent = upb_malloc(&a->head.alloc, sizeof(cleanup_ent));
-  if (!ent) {
-    return false;  /* Out of memory. */
-  }
-
-  ent->cleanup = func;
-  ent->ud = ud;
-  ent->next = a->cleanup_head;
-  a->cleanup_head = ent;
-
-  return true;
-}
-
-size_t upb_arena_bytesallocated(const upb_arena *a) {
-  return a->bytes_allocated + (a->head.ptr - a->start);
-}
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include <stddef.h>
-
-
-static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = {
-  &google_protobuf_FileDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
-  &google_protobuf_FileDescriptorSet_submsgs[0],
-  &google_protobuf_FileDescriptorSet__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
-  &google_protobuf_DescriptorProto_msginit,
-  &google_protobuf_EnumDescriptorProto_msginit,
-  &google_protobuf_FieldDescriptorProto_msginit,
-  &google_protobuf_FileOptions_msginit,
-  &google_protobuf_ServiceDescriptorProto_msginit,
-  &google_protobuf_SourceCodeInfo_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {3, UPB_SIZE(36, 72), 0, 0, 9, 3},
-  {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
-  {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
-  {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
-  {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
-  {8, UPB_SIZE(28, 56), 4, 3, 11, 1},
-  {9, UPB_SIZE(32, 64), 5, 5, 11, 1},
-  {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
-  {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
-  {12, UPB_SIZE(20, 40), 3, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
-  &google_protobuf_FileDescriptorProto_submsgs[0],
-  &google_protobuf_FileDescriptorProto__fields[0],
-  UPB_SIZE(64, 128), 12, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[8] = {
-  &google_protobuf_DescriptorProto_msginit,
-  &google_protobuf_DescriptorProto_ExtensionRange_msginit,
-  &google_protobuf_DescriptorProto_ReservedRange_msginit,
-  &google_protobuf_EnumDescriptorProto_msginit,
-  &google_protobuf_FieldDescriptorProto_msginit,
-  &google_protobuf_MessageOptions_msginit,
-  &google_protobuf_OneofDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
-  {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
-  {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
-  {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
-  {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
-  {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
-  {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
-  {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
-  {10, UPB_SIZE(44, 88), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_msginit = {
-  &google_protobuf_DescriptorProto_submsgs[0],
-  &google_protobuf_DescriptorProto__fields[0],
-  UPB_SIZE(48, 96), 10, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
-  &google_protobuf_ExtensionRangeOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-  {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
-  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
-  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
-  UPB_SIZE(16, 24), 3, false,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
-  NULL,
-  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
-  UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
-  &google_protobuf_ExtensionRangeOptions_submsgs[0],
-  &google_protobuf_ExtensionRangeOptions__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
-  &google_protobuf_FieldOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
-  {1, UPB_SIZE(36, 40), 6, 0, 9, 1},
-  {2, UPB_SIZE(44, 56), 7, 0, 9, 1},
-  {3, UPB_SIZE(24, 24), 3, 0, 5, 1},
-  {4, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {5, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {6, UPB_SIZE(52, 72), 8, 0, 9, 1},
-  {7, UPB_SIZE(60, 88), 9, 0, 9, 1},
-  {8, UPB_SIZE(76, 120), 11, 0, 11, 1},
-  {9, UPB_SIZE(28, 28), 4, 0, 5, 1},
-  {10, UPB_SIZE(68, 104), 10, 0, 9, 1},
-  {17, UPB_SIZE(32, 32), 5, 0, 8, 1},
-};
-
-const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
-  &google_protobuf_FieldDescriptorProto_submsgs[0],
-  &google_protobuf_FieldDescriptorProto__fields[0],
-  UPB_SIZE(80, 128), 11, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
-  &google_protobuf_OneofOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
-  &google_protobuf_OneofDescriptorProto_submsgs[0],
-  &google_protobuf_OneofDescriptorProto__fields[0],
-  UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
-  &google_protobuf_EnumOptions_msginit,
-  &google_protobuf_EnumValueDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
-  {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
-  {5, UPB_SIZE(24, 48), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
-  &google_protobuf_EnumDescriptorProto_submsgs[0],
-  &google_protobuf_EnumDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
-  NULL,
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
-  UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
-  &google_protobuf_EnumValueOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(8, 8), 2, 0, 9, 1},
-  {2, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
-  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
-  &google_protobuf_EnumValueDescriptorProto__fields[0],
-  UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
-  &google_protobuf_MethodDescriptorProto_msginit,
-  &google_protobuf_ServiceOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
-};
-
-const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
-  &google_protobuf_ServiceDescriptorProto_submsgs[0],
-  &google_protobuf_ServiceDescriptorProto__fields[0],
-  UPB_SIZE(24, 48), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
-  &google_protobuf_MethodOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
-  {1, UPB_SIZE(4, 8), 3, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 4, 0, 9, 1},
-  {3, UPB_SIZE(20, 40), 5, 0, 9, 1},
-  {4, UPB_SIZE(28, 56), 6, 0, 11, 1},
-  {5, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {6, UPB_SIZE(2, 2), 2, 0, 8, 1},
-};
-
-const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
-  &google_protobuf_MethodDescriptorProto_submsgs[0],
-  &google_protobuf_MethodDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 6, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
-  {1, UPB_SIZE(28, 32), 11, 0, 9, 1},
-  {8, UPB_SIZE(36, 48), 12, 0, 9, 1},
-  {9, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {10, UPB_SIZE(16, 16), 2, 0, 8, 1},
-  {11, UPB_SIZE(44, 64), 13, 0, 9, 1},
-  {16, UPB_SIZE(17, 17), 3, 0, 8, 1},
-  {17, UPB_SIZE(18, 18), 4, 0, 8, 1},
-  {18, UPB_SIZE(19, 19), 5, 0, 8, 1},
-  {20, UPB_SIZE(20, 20), 6, 0, 8, 1},
-  {23, UPB_SIZE(21, 21), 7, 0, 8, 1},
-  {27, UPB_SIZE(22, 22), 8, 0, 8, 1},
-  {31, UPB_SIZE(23, 23), 9, 0, 8, 1},
-  {36, UPB_SIZE(52, 80), 14, 0, 9, 1},
-  {37, UPB_SIZE(60, 96), 15, 0, 9, 1},
-  {39, UPB_SIZE(68, 112), 16, 0, 9, 1},
-  {40, UPB_SIZE(76, 128), 17, 0, 9, 1},
-  {41, UPB_SIZE(84, 144), 18, 0, 9, 1},
-  {42, UPB_SIZE(24, 24), 10, 0, 8, 1},
-  {44, UPB_SIZE(92, 160), 19, 0, 9, 1},
-  {45, UPB_SIZE(100, 176), 20, 0, 9, 1},
-  {999, UPB_SIZE(108, 192), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileOptions_msginit = {
-  &google_protobuf_FileOptions_submsgs[0],
-  &google_protobuf_FileOptions__fields[0],
-  UPB_SIZE(112, 208), 21, false,
-};
-
-static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
-  {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
-  {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
-  {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MessageOptions_msginit = {
-  &google_protobuf_MessageOptions_submsgs[0],
-  &google_protobuf_MessageOptions__fields[0],
-  UPB_SIZE(12, 16), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
-  {1, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {2, UPB_SIZE(24, 24), 3, 0, 8, 1},
-  {3, UPB_SIZE(25, 25), 4, 0, 8, 1},
-  {5, UPB_SIZE(26, 26), 5, 0, 8, 1},
-  {6, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {10, UPB_SIZE(27, 27), 6, 0, 8, 1},
-  {999, UPB_SIZE(28, 32), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FieldOptions_msginit = {
-  &google_protobuf_FieldOptions_submsgs[0],
-  &google_protobuf_FieldOptions__fields[0],
-  UPB_SIZE(32, 40), 7, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_OneofOptions_msginit = {
-  &google_protobuf_OneofOptions_submsgs[0],
-  &google_protobuf_OneofOptions__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
-  {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumOptions_msginit = {
-  &google_protobuf_EnumOptions_submsgs[0],
-  &google_protobuf_EnumOptions__fields[0],
-  UPB_SIZE(8, 16), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
-  &google_protobuf_EnumValueOptions_submsgs[0],
-  &google_protobuf_EnumValueOptions__fields[0],
-  UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
-  {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ServiceOptions_msginit = {
-  &google_protobuf_ServiceOptions_submsgs[0],
-  &google_protobuf_ServiceOptions__fields[0],
-  UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
-  {33, UPB_SIZE(16, 16), 2, 0, 8, 1},
-  {34, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {999, UPB_SIZE(20, 24), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MethodOptions_msginit = {
-  &google_protobuf_MethodOptions_submsgs[0],
-  &google_protobuf_MethodOptions__fields[0],
-  UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_NamePart_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
-  {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
-  {3, UPB_SIZE(32, 32), 4, 0, 9, 1},
-  {4, UPB_SIZE(8, 8), 1, 0, 4, 1},
-  {5, UPB_SIZE(16, 16), 2, 0, 3, 1},
-  {6, UPB_SIZE(24, 24), 3, 0, 1, 1},
-  {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
-  {8, UPB_SIZE(48, 64), 6, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
-  &google_protobuf_UninterpretedOption_submsgs[0],
-  &google_protobuf_UninterpretedOption__fields[0],
-  UPB_SIZE(64, 96), 7, false,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
-  {1, UPB_SIZE(4, 8), 2, 0, 9, 2},
-  {2, UPB_SIZE(1, 1), 1, 0, 8, 2},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
-  NULL,
-  &google_protobuf_UninterpretedOption_NamePart__fields[0],
-  UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
-  &google_protobuf_SourceCodeInfo_Location_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
-  &google_protobuf_SourceCodeInfo_submsgs[0],
-  &google_protobuf_SourceCodeInfo__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
-  {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
-  {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
-  {3, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {4, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {6, UPB_SIZE(28, 56), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
-  NULL,
-  &google_protobuf_SourceCodeInfo_Location__fields[0],
-  UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
-  &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
-  &google_protobuf_GeneratedCodeInfo_submsgs[0],
-  &google_protobuf_GeneratedCodeInfo__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
-  {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
-  {2, UPB_SIZE(12, 16), 3, 0, 9, 1},
-  {3, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {4, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
-  NULL,
-  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
-  UPB_SIZE(24, 48), 4, false,
-};
-
-
-
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-typedef struct {
-  size_t len;
-  char str[1];  /* Null-terminated string data follows. */
-} str_t;
-
-static str_t *newstr(upb_alloc *alloc, const char *data, size_t len) {
-  str_t *ret = upb_malloc(alloc, sizeof(*ret) + len);
-  if (!ret) return NULL;
-  ret->len = len;
-  memcpy(ret->str, data, len);
-  ret->str[len] = '\0';
-  return ret;
-}
-
-struct upb_fielddef {
-  const upb_filedef *file;
-  const upb_msgdef *msgdef;
-  const char *full_name;
-  const char *json_name;
-  union {
-    int64_t sint;
-    uint64_t uint;
-    double dbl;
-    float flt;
-    bool boolean;
-    str_t *str;
-  } defaultval;
-  const upb_oneofdef *oneof;
-  union {
-    const upb_msgdef *msgdef;
-    const upb_enumdef *enumdef;
-    const google_protobuf_FieldDescriptorProto *unresolved;
-  } sub;
-  uint32_t number_;
-  uint16_t index_;
-  uint16_t layout_index;
-  uint32_t selector_base;  /* Used to index into a upb::Handlers table. */
-  bool is_extension_;
-  bool lazy_;
-  bool packed_;
-  bool proto3_optional_;
-  upb_descriptortype_t type_;
-  upb_label_t label_;
-};
-
-struct upb_msgdef {
-  const upb_msglayout *layout;
-  const upb_filedef *file;
-  const char *full_name;
-  uint32_t selector_count;
-  uint32_t submsg_field_count;
-
-  /* Tables for looking up fields by number and name. */
-  upb_inttable itof;
-  upb_strtable ntof;
-
-  const upb_fielddef *fields;
-  const upb_oneofdef *oneofs;
-  int field_count;
-  int oneof_count;
-
-  /* Is this a map-entry message? */
-  bool map_entry;
-  upb_wellknowntype_t well_known_type;
-
-  /* TODO(haberman): proper extension ranges (there can be multiple). */
-};
-
-struct upb_enumdef {
-  const upb_filedef *file;
-  const char *full_name;
-  upb_strtable ntoi;
-  upb_inttable iton;
-  int32_t defaultval;
-};
-
-struct upb_oneofdef {
-  const upb_msgdef *parent;
-  const char *full_name;
-  uint32_t index;
-  upb_strtable ntof;
-  upb_inttable itof;
-};
-
-struct upb_filedef {
-  const char *name;
-  const char *package;
-  const char *phpprefix;
-  const char *phpnamespace;
-  upb_syntax_t syntax;
-
-  const upb_filedef **deps;
-  const upb_msgdef *msgs;
-  const upb_enumdef *enums;
-  const upb_fielddef *exts;
-
-  int dep_count;
-  int msg_count;
-  int enum_count;
-  int ext_count;
-};
-
-struct upb_symtab {
-  upb_arena *arena;
-  upb_strtable syms;  /* full_name -> packed def ptr */
-  upb_strtable files;  /* file_name -> upb_filedef* */
-};
-
-/* Inside a symtab we store tagged pointers to specific def types. */
-typedef enum {
-  UPB_DEFTYPE_FIELD = 0,
-
-  /* Only inside symtab table. */
-  UPB_DEFTYPE_MSG = 1,
-  UPB_DEFTYPE_ENUM = 2,
-
-  /* Only inside message table. */
-  UPB_DEFTYPE_ONEOF = 1,
-  UPB_DEFTYPE_FIELD_JSONNAME = 2
-} upb_deftype_t;
-
-static const void *unpack_def(upb_value v, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
-  return (num & 3) == type ? (const void*)(num & ~3) : NULL;
-}
-
-static upb_value pack_def(const void *ptr, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)ptr | type;
-  return upb_value_constptr((const void*)num);
-}
-
-/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
-static bool upb_isbetween(char c, char low, char high) {
-  return c >= low && c <= high;
-}
-
-static bool upb_isletter(char c) {
-  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
-}
-
-static bool upb_isalphanum(char c) {
-  return upb_isletter(c) || upb_isbetween(c, '0', '9');
-}
-
-static bool upb_isident(upb_strview name, bool full, upb_status *s) {
-  const char *str = name.data;
-  size_t len = name.size;
-  bool start = true;
-  size_t i;
-  for (i = 0; i < len; i++) {
-    char c = str[i];
-    if (c == '.') {
-      if (start || !full) {
-        upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
-        return false;
-      }
-      start = true;
-    } else if (start) {
-      if (!upb_isletter(c)) {
-        upb_status_seterrf(
-            s, "invalid name: path components must start with a letter (%s)",
-            str);
-        return false;
-      }
-      start = false;
-    } else {
-      if (!upb_isalphanum(c)) {
-        upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
-                           str);
-        return false;
-      }
-    }
-  }
-  return !start;
-}
-
-static const char *shortdefname(const char *fullname) {
-  const char *p;
-
-  if (fullname == NULL) {
-    return NULL;
-  } else if ((p = strrchr(fullname, '.')) == NULL) {
-    /* No '.' in the name, return the full string. */
-    return fullname;
-  } else {
-    /* Return one past the last '.'. */
-    return p + 1;
-  }
-}
-
-/* All submessage fields are lower than all other fields.
- * Secondly, fields are increasing in order. */
-uint32_t field_rank(const upb_fielddef *f) {
-  uint32_t ret = upb_fielddef_number(f);
-  const uint32_t high_bit = 1 << 30;
-  UPB_ASSERT(ret < high_bit);
-  if (!upb_fielddef_issubmsg(f))
-    ret |= high_bit;
-  return ret;
-}
-
-int cmp_fields(const void *p1, const void *p2) {
-  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
-  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
-  return field_rank(f1) - field_rank(f2);
-}
-
-/* A few implementation details of handlers.  We put these here to avoid
- * a def -> handlers dependency. */
-
-#define UPB_STATIC_SELECTOR_COUNT 3  /* Warning: also in upb/handlers.h. */
-
-static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
-  return upb_fielddef_isseq(f) ? 2 : 0;
-}
-
-static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
-  uint32_t ret = 1;
-  if (upb_fielddef_isseq(f)) ret += 2;    /* STARTSEQ/ENDSEQ */
-  if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
-  if (upb_fielddef_issubmsg(f)) {
-    /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
-    ret += 0;
-    if (upb_fielddef_lazy(f)) {
-      /* STARTSTR/ENDSTR/STRING (for lazy) */
-      ret += 3;
-    }
-  }
-  return ret;
-}
-
-static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
-  /* Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
-   * lowest indexes, but we do not publicly guarantee this. */
-  upb_msg_field_iter j;
-  upb_msg_oneof_iter k;
-  int i;
-  uint32_t selector;
-  int n = upb_msgdef_numfields(m);
-  upb_fielddef **fields;
-
-  if (n == 0) {
-    m->selector_count = UPB_STATIC_SELECTOR_COUNT;
-    m->submsg_field_count = 0;
-    return true;
-  }
-
-  fields = upb_gmalloc(n * sizeof(*fields));
-  if (!fields) {
-    upb_status_setoom(s);
-    return false;
-  }
-
-  m->submsg_field_count = 0;
-  for(i = 0, upb_msg_field_begin(&j, m);
-      !upb_msg_field_done(&j);
-      upb_msg_field_next(&j), i++) {
-    upb_fielddef *f = upb_msg_iter_field(&j);
-    UPB_ASSERT(f->msgdef == m);
-    if (upb_fielddef_issubmsg(f)) {
-      m->submsg_field_count++;
-    }
-    fields[i] = f;
-  }
-
-  qsort(fields, n, sizeof(*fields), cmp_fields);
-
-  selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
-  for (i = 0; i < n; i++) {
-    upb_fielddef *f = fields[i];
-    f->index_ = i;
-    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
-    selector += upb_handlers_selectorcount(f);
-  }
-  m->selector_count = selector;
-
-  for(upb_msg_oneof_begin(&k, m), i = 0;
-      !upb_msg_oneof_done(&k);
-      upb_msg_oneof_next(&k), i++) {
-    upb_oneofdef *o = (upb_oneofdef*)upb_msg_iter_oneof(&k);
-    o->index = i;
-  }
-
-  upb_gfree(fields);
-  return true;
-}
-
-static void assign_msg_wellknowntype(upb_msgdef *m) {
-  const char *name = upb_msgdef_fullname(m);
-  if (name == NULL) {
-    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
-    return;
-  }
-  if (!strcmp(name, "google.protobuf.Any")) {
-    m->well_known_type = UPB_WELLKNOWN_ANY;
-  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
-    m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
-  } else if (!strcmp(name, "google.protobuf.Duration")) {
-    m->well_known_type = UPB_WELLKNOWN_DURATION;
-  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
-    m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
-  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
-    m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
-  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
-    m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
-  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
-    m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
-  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
-    m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
-  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
-    m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
-  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
-    m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
-  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
-    m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
-  } else if (!strcmp(name, "google.protobuf.StringValue")) {
-    m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
-  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
-    m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
-  } else if (!strcmp(name, "google.protobuf.Value")) {
-    m->well_known_type = UPB_WELLKNOWN_VALUE;
-  } else if (!strcmp(name, "google.protobuf.ListValue")) {
-    m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
-  } else if (!strcmp(name, "google.protobuf.Struct")) {
-    m->well_known_type = UPB_WELLKNOWN_STRUCT;
-  } else {
-    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
-  }
-}
-
-
-/* upb_enumdef ****************************************************************/
-
-const char *upb_enumdef_fullname(const upb_enumdef *e) {
-  return e->full_name;
-}
-
-const char *upb_enumdef_name(const upb_enumdef *e) {
-  return shortdefname(e->full_name);
-}
-
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
-  return e->file;
-}
-
-int32_t upb_enumdef_default(const upb_enumdef *e) {
-  UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
-  return e->defaultval;
-}
-
-int upb_enumdef_numvals(const upb_enumdef *e) {
-  return (int)upb_strtable_count(&e->ntoi);
-}
-
-void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
-  /* We iterate over the ntoi table, to account for duplicate numbers. */
-  upb_strtable_begin(i, &e->ntoi);
-}
-
-void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
-bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
-
-bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
-                      size_t len, int32_t *num) {
-  upb_value v;
-  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
-    return false;
-  }
-  if (num) *num = upb_value_getint32(v);
-  return true;
-}
-
-const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
-  upb_value v;
-  return upb_inttable_lookup32(&def->iton, num, &v) ?
-      upb_value_getcstr(v) : NULL;
-}
-
-const char *upb_enum_iter_name(upb_enum_iter *iter) {
-  return upb_strtable_iter_key(iter).data;
-}
-
-int32_t upb_enum_iter_number(upb_enum_iter *iter) {
-  return upb_value_getint32(upb_strtable_iter_value(iter));
-}
-
-
-/* upb_fielddef ***************************************************************/
-
-const char *upb_fielddef_fullname(const upb_fielddef *f) {
-  return f->full_name;
-}
-
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
-  switch (f->type_) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      return UPB_TYPE_DOUBLE;
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      return UPB_TYPE_FLOAT;
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-      return UPB_TYPE_INT64;
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      return UPB_TYPE_INT32;
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      return UPB_TYPE_UINT64;
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-      return UPB_TYPE_UINT32;
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      return UPB_TYPE_ENUM;
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      return UPB_TYPE_BOOL;
-    case UPB_DESCRIPTOR_TYPE_STRING:
-      return UPB_TYPE_STRING;
-    case UPB_DESCRIPTOR_TYPE_BYTES:
-      return UPB_TYPE_BYTES;
-    case UPB_DESCRIPTOR_TYPE_GROUP:
-    case UPB_DESCRIPTOR_TYPE_MESSAGE:
-      return UPB_TYPE_MESSAGE;
-  }
-  UPB_UNREACHABLE();
-}
-
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
-  return f->type_;
-}
-
-uint32_t upb_fielddef_index(const upb_fielddef *f) {
-  return f->index_;
-}
-
-upb_label_t upb_fielddef_label(const upb_fielddef *f) {
-  return f->label_;
-}
-
-uint32_t upb_fielddef_number(const upb_fielddef *f) {
-  return f->number_;
-}
-
-bool upb_fielddef_isextension(const upb_fielddef *f) {
-  return f->is_extension_;
-}
-
-bool upb_fielddef_lazy(const upb_fielddef *f) {
-  return f->lazy_;
-}
-
-bool upb_fielddef_packed(const upb_fielddef *f) {
-  return f->packed_;
-}
-
-const char *upb_fielddef_name(const upb_fielddef *f) {
-  return shortdefname(f->full_name);
-}
-
-const char *upb_fielddef_jsonname(const upb_fielddef *f) {
-  return f->json_name;
-}
-
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) {
-  return f->selector_base;
-}
-
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
-  return f->msgdef;
-}
-
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
-  return f->oneof;
-}
-
-static void chkdefaulttype(const upb_fielddef *f, int ctype) {
-  UPB_UNUSED(f);
-  UPB_UNUSED(ctype);
-}
-
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_INT64);
-  return f->defaultval.sint;
-}
-
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_INT32);
-  return (int32_t)f->defaultval.sint;
-}
-
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_UINT64);
-  return f->defaultval.uint;
-}
-
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_UINT32);
-  return (uint32_t)f->defaultval.uint;
-}
-
-bool upb_fielddef_defaultbool(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_BOOL);
-  return f->defaultval.boolean;
-}
-
-float upb_fielddef_defaultfloat(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_FLOAT);
-  return f->defaultval.flt;
-}
-
-double upb_fielddef_defaultdouble(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_DOUBLE);
-  return f->defaultval.dbl;
-}
-
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
-  str_t *str = f->defaultval.str;
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
-         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
-         upb_fielddef_type(f) == UPB_TYPE_ENUM);
-  if (str) {
-    if (len) *len = str->len;
-    return str->str;
-  } else {
-    if (len) *len = 0;
-    return NULL;
-  }
-}
-
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
-  return f->sub.msgdef;
-}
-
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_ENUM);
-  return f->sub.enumdef;
-}
-
-const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) {
-  return &f->msgdef->layout->fields[f->layout_index];
-}
-
-bool upb_fielddef_issubmsg(const upb_fielddef *f) {
-  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
-}
-
-bool upb_fielddef_isstring(const upb_fielddef *f) {
-  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
-         upb_fielddef_type(f) == UPB_TYPE_BYTES;
-}
-
-bool upb_fielddef_isseq(const upb_fielddef *f) {
-  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
-}
-
-bool upb_fielddef_isprimitive(const upb_fielddef *f) {
-  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
-}
-
-bool upb_fielddef_ismap(const upb_fielddef *f) {
-  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
-         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
-}
-
-bool upb_fielddef_hassubdef(const upb_fielddef *f) {
-  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
-}
-
-bool upb_fielddef_haspresence(const upb_fielddef *f) {
-  if (upb_fielddef_isseq(f)) return false;
-  if (upb_fielddef_issubmsg(f)) return true;
-  if (f->proto3_optional_) return true;
-  return f->file->syntax == UPB_SYNTAX_PROTO2;
-}
-
-static bool between(int32_t x, int32_t low, int32_t high) {
-  return x >= low && x <= high;
-}
-
-bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
-bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
-bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
-
-bool upb_fielddef_checkdescriptortype(int32_t type) {
-  return between(type, 1, 18);
-}
-
-/* upb_msgdef *****************************************************************/
-
-const char *upb_msgdef_fullname(const upb_msgdef *m) {
-  return m->full_name;
-}
-
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
-  return m->file;
-}
-
-const char *upb_msgdef_name(const upb_msgdef *m) {
-  return shortdefname(m->full_name);
-}
-
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
-  return m->file->syntax;
-}
-
-size_t upb_msgdef_selectorcount(const upb_msgdef *m) {
-  return m->selector_count;
-}
-
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) {
-  return m->submsg_field_count;
-}
-
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
-  upb_value val;
-  return upb_inttable_lookup32(&m->itof, i, &val) ?
-      upb_value_getconstptr(val) : NULL;
-}
-
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
-                                    size_t len) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  return unpack_def(val, UPB_DEFTYPE_FIELD);
-}
-
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
-                                    size_t len) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  return unpack_def(val, UPB_DEFTYPE_ONEOF);
-}
-
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
-                           const upb_fielddef **f, const upb_oneofdef **o) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return false;
-  }
-
-  *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
-  *f = unpack_def(val, UPB_DEFTYPE_FIELD);
-  return *o || *f;  /* False if this was a JSON name. */
-}
-
-const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
-                                              const char *name, size_t len) {
-  upb_value val;
-  const upb_fielddef* f;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  f = unpack_def(val, UPB_DEFTYPE_FIELD);
-  if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME);
-
-  return f;
-}
-
-int upb_msgdef_numfields(const upb_msgdef *m) {
-  return m->field_count;
-}
-
-int upb_msgdef_numoneofs(const upb_msgdef *m) {
-  return m->oneof_count;
-}
-
-const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) {
-  return m->layout;
-}
-
-const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i) {
-  if (i >= m->field_count) return NULL;
-  return &m->fields[i];
-}
-
-bool upb_msgdef_mapentry(const upb_msgdef *m) {
-  return m->map_entry;
-}
-
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
-  return m->well_known_type;
-}
-
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
-         type <= UPB_WELLKNOWN_UINT32VALUE;
-}
-
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
-  upb_inttable_begin(iter, &m->itof);
-}
-
-void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
-
-bool upb_msg_field_done(const upb_msg_field_iter *iter) {
-  return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
-  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
-  upb_inttable_iter_setdone(iter);
-}
-
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
-                                const upb_msg_field_iter * iter2) {
-  return upb_inttable_iter_isequal(iter1, iter2);
-}
-
-void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
-  upb_strtable_begin(iter, &m->ntof);
-  /* We need to skip past any initial fields. */
-  while (!upb_strtable_done(iter) &&
-         !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
-    upb_strtable_next(iter);
-  }
-}
-
-void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
-  /* We need to skip past fields to return only oneofs. */
-  do {
-    upb_strtable_next(iter);
-  } while (!upb_strtable_done(iter) &&
-           !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
-}
-
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
-  return upb_strtable_done(iter);
-}
-
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
-  return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
-}
-
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
-  upb_strtable_iter_setdone(iter);
-}
-
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
-                                const upb_msg_oneof_iter *iter2) {
-  return upb_strtable_iter_isequal(iter1, iter2);
-}
-
-/* upb_oneofdef ***************************************************************/
-
-const char *upb_oneofdef_name(const upb_oneofdef *o) {
-  return shortdefname(o->full_name);
-}
-
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
-  return o->parent;
-}
-
-int upb_oneofdef_numfields(const upb_oneofdef *o) {
-  return (int)upb_strtable_count(&o->ntof);
-}
-
-uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
-  return o->index;
-}
-
-bool upb_oneofdef_synthetic(const upb_oneofdef *o) {
-  upb_inttable_iter iter;
-  const upb_fielddef *f;
-  upb_inttable_begin(&iter, &o->itof);
-  if (upb_oneofdef_numfields(o) != 1) return false;
-  f = upb_value_getptr(upb_inttable_iter_value(&iter));
-  UPB_ASSERT(f);
-  return f->proto3_optional_;
-}
-
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
-                                      const char *name, size_t length) {
-  upb_value val;
-  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
-      upb_value_getptr(val) : NULL;
-}
-
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
-  upb_value val;
-  return upb_inttable_lookup32(&o->itof, num, &val) ?
-      upb_value_getptr(val) : NULL;
-}
-
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
-  upb_inttable_begin(iter, &o->itof);
-}
-
-void upb_oneof_next(upb_oneof_iter *iter) {
-  upb_inttable_next(iter);
-}
-
-bool upb_oneof_done(upb_oneof_iter *iter) {
-  return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
-  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
-  upb_inttable_iter_setdone(iter);
-}
-
-/* Dynamic Layout Generation. *************************************************/
-
-static bool is_power_of_two(size_t val) {
-  return (val & (val - 1)) == 0;
-}
-
-/* Align up to the given power of 2. */
-static size_t align_up(size_t val, size_t align) {
-  UPB_ASSERT(is_power_of_two(align));
-  return (val + align - 1) & ~(align - 1);
-}
-
-static size_t div_round_up(size_t n, size_t d) {
-  return (n + d - 1) / d;
-}
-
-static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT64:
-      return 8;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_FLOAT:
-      return 4;
-    case UPB_TYPE_BOOL:
-      return 1;
-    case UPB_TYPE_MESSAGE:
-      return sizeof(void*);
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_STRING:
-      return sizeof(upb_strview);
-  }
-  UPB_UNREACHABLE();
-}
-
-static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
-  if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) {
-    upb_map_entry ent;
-    UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
-    return sizeof(ent.k);
-  } else if (upb_fielddef_isseq(f)) {
-    return sizeof(void*);
-  } else {
-    return upb_msgval_sizeof(upb_fielddef_type(f));
-  }
-}
-
-static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) {
-  uint32_t ret;
-
-  l->size = align_up(l->size, size);
-  ret = l->size;
-  l->size += size;
-  return ret;
-}
-
-/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
- * It computes a dynamic layout for all of the fields in |m|. */
-static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) {
-  upb_msglayout *l = (upb_msglayout*)m->layout;
-  upb_msg_field_iter it;
-  upb_msg_oneof_iter oit;
-  size_t hasbit;
-  size_t submsg_count = m->submsg_field_count;
-  const upb_msglayout **submsgs;
-  upb_msglayout_field *fields;
-  upb_alloc *alloc = upb_arena_alloc(symtab->arena);
-
-  memset(l, 0, sizeof(*l));
-
-  fields = upb_malloc(alloc, upb_msgdef_numfields(m) * sizeof(*fields));
-  submsgs = upb_malloc(alloc, submsg_count * sizeof(*submsgs));
-
-  if ((!fields && upb_msgdef_numfields(m)) ||
-      (!submsgs && submsg_count)) {
-    /* OOM. */
-    return false;
-  }
-
-  l->field_count = upb_msgdef_numfields(m);
-  l->fields = fields;
-  l->submsgs = submsgs;
-
-  if (upb_msgdef_mapentry(m)) {
-    /* TODO(haberman): refactor this method so this special case is more
-     * elegant. */
-    const upb_fielddef *key = upb_msgdef_itof(m, 1);
-    const upb_fielddef *val = upb_msgdef_itof(m, 2);
-    fields[0].number = 1;
-    fields[1].number = 2;
-    fields[0].label = UPB_LABEL_OPTIONAL;
-    fields[1].label = UPB_LABEL_OPTIONAL;
-    fields[0].presence = 0;
-    fields[1].presence = 0;
-    fields[0].descriptortype = upb_fielddef_descriptortype(key);
-    fields[1].descriptortype = upb_fielddef_descriptortype(val);
-    fields[0].offset = 0;
-    fields[1].offset = sizeof(upb_strview);
-    fields[1].submsg_index = 0;
-
-    if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) {
-      submsgs[0] = upb_fielddef_msgsubdef(val)->layout;
-    }
-
-    l->field_count = 2;
-    l->size = 2 * sizeof(upb_strview);align_up(l->size, 8);
-    return true;
-  }
-
-  /* Allocate data offsets in three stages:
-   *
-   * 1. hasbits.
-   * 2. regular fields.
-   * 3. oneof fields.
-   *
-   * OPT: There is a lot of room for optimization here to minimize the size.
-   */
-
-  /* Allocate hasbits and set basic field attributes. */
-  submsg_count = 0;
-  for (upb_msg_field_begin(&it, m), hasbit = 0;
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    upb_fielddef* f = upb_msg_iter_field(&it);
-    upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
-
-    field->number = upb_fielddef_number(f);
-    field->descriptortype = upb_fielddef_descriptortype(f);
-    field->label = upb_fielddef_label(f);
-
-    if (upb_fielddef_ismap(f)) {
-      field->label = _UPB_LABEL_MAP;
-    } else if (upb_fielddef_packed(f)) {
-      field->label = _UPB_LABEL_PACKED;
-    }
-
-    /* TODO: we probably should sort the fields by field number to match the
-     * output of upbc, and to improve search speed for the table parser. */
-    f->layout_index = f->index_;
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
-      field->submsg_index = submsg_count++;
-      submsgs[field->submsg_index] = subm->layout;
-    }
-
-    if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) {
-      /* We don't use hasbit 0, so that 0 can indicate "no presence" in the
-       * table. This wastes one hasbit, but we don't worry about it for now. */
-      field->presence = ++hasbit;
-    } else {
-      field->presence = 0;
-    }
-  }
-
-  /* Account for space used by hasbits. */
-  l->size = div_round_up(hasbit, 8);
-
-  /* Allocate non-oneof fields. */
-  for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* f = upb_msg_iter_field(&it);
-    size_t field_size = upb_msg_fielddefsize(f);
-    size_t index = upb_fielddef_index(f);
-
-    if (upb_fielddef_containingoneof(f)) {
-      /* Oneofs are handled separately below. */
-      continue;
-    }
-
-    fields[index].offset = upb_msglayout_place(l, field_size);
-  }
-
-  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
-   * and space for the actual data. */
-  for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
-    upb_oneof_iter fit;
-
-    size_t case_size = sizeof(uint32_t);  /* Could potentially optimize this. */
-    size_t field_size = 0;
-    uint32_t case_offset;
-    uint32_t data_offset;
-
-    /* Calculate field size: the max of all field sizes. */
-    for (upb_oneof_begin(&fit, o);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* f = upb_oneof_iter_field(&fit);
-      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
-    }
-
-    /* Align and allocate case offset. */
-    case_offset = upb_msglayout_place(l, case_size);
-    data_offset = upb_msglayout_place(l, field_size);
-
-    for (upb_oneof_begin(&fit, o);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* f = upb_oneof_iter_field(&fit);
-      fields[upb_fielddef_index(f)].offset = data_offset;
-      fields[upb_fielddef_index(f)].presence = ~case_offset;
-    }
-  }
-
-  /* Size of the entire structure should be a multiple of its greatest
-   * alignment.  TODO: track overall alignment for real? */
-  l->size = align_up(l->size, 8);
-
-  return true;
-}
-
-/* Code to build defs from descriptor protos. *********************************/
-
-/* There is a question of how much validation to do here.  It will be difficult
- * to perfectly match the amount of validation performed by proto2.  But since
- * this code is used to directly build defs from Ruby (for example) we do need
- * to validate important constraints like uniqueness of names and numbers. */
-
-#define CHK(x) if (!(x)) { return false; }
-#define CHK_OOM(x) if (!(x)) { upb_status_setoom(ctx->status); return false; }
-
-typedef struct {
-  const upb_symtab *symtab;
-  upb_filedef *file;              /* File we are building. */
-  upb_alloc *alloc;               /* Allocate defs here. */
-  upb_alloc *tmp;                 /* Alloc for addtab and any other tmp data. */
-  upb_strtable *addtab;           /* full_name -> packed def ptr for new defs */
-  const upb_msglayout **layouts;  /* NULL if we should build layouts. */
-  upb_status *status;             /* Record errors here. */
-} symtab_addctx;
-
-static char* strviewdup(const symtab_addctx *ctx, upb_strview view) {
-  return upb_strdup2(view.data, view.size, ctx->alloc);
-}
-
-static bool streql2(const char *a, size_t n, const char *b) {
-  return n == strlen(b) && memcmp(a, b, n) == 0;
-}
-
-static bool streql_view(upb_strview view, const char *b) {
-  return streql2(view.data, view.size, b);
-}
-
-static const char *makefullname(const symtab_addctx *ctx, const char *prefix,
-                                upb_strview name) {
-  if (prefix) {
-    /* ret = prefix + '.' + name; */
-    size_t n = strlen(prefix);
-    char *ret = upb_malloc(ctx->alloc, n + name.size + 2);
-    CHK_OOM(ret);
-    strcpy(ret, prefix);
-    ret[n] = '.';
-    memcpy(&ret[n + 1], name.data, name.size);
-    ret[n + 1 + name.size] = '\0';
-    return ret;
-  } else {
-    return strviewdup(ctx, name);
-  }
-}
-
-size_t getjsonname(const char *name, char *buf, size_t len) {
-  size_t src, dst = 0;
-  bool ucase_next = false;
-
-#define WRITE(byte) \
-  ++dst; \
-  if (dst < len) buf[dst - 1] = byte; \
-  else if (dst == len) buf[dst - 1] = '\0'
-
-  if (!name) {
-    WRITE('\0');
-    return 0;
-  }
-
-  /* Implement the transformation as described in the spec:
-   *   1. upper case all letters after an underscore.
-   *   2. remove all underscores.
-   */
-  for (src = 0; name[src]; src++) {
-    if (name[src] == '_') {
-      ucase_next = true;
-      continue;
-    }
-
-    if (ucase_next) {
-      WRITE(toupper(name[src]));
-      ucase_next = false;
-    } else {
-      WRITE(name[src]);
-    }
-  }
-
-  WRITE('\0');
-  return dst;
-
-#undef WRITE
-}
-
-static char* makejsonname(const char* name, upb_alloc *alloc) {
-  size_t size = getjsonname(name, NULL, 0);
-  char* json_name = upb_malloc(alloc, size);
-  getjsonname(name, json_name, size);
-  return json_name;
-}
-
-static bool symtab_add(const symtab_addctx *ctx, const char *name,
-                       upb_value v) {
-  upb_value tmp;
-  if (upb_strtable_lookup(ctx->addtab, name, &tmp) ||
-      upb_strtable_lookup(&ctx->symtab->syms, name, &tmp)) {
-    upb_status_seterrf(ctx->status, "duplicate symbol '%s'", name);
-    return false;
-  }
-
-  CHK_OOM(upb_strtable_insert3(ctx->addtab, name, strlen(name), v, ctx->tmp));
-  return true;
-}
-
-/* Given a symbol and the base symbol inside which it is defined, find the
- * symbol's definition in t. */
-static bool resolvename(const upb_strtable *t, const upb_fielddef *f,
-                        const char *base, upb_strview sym,
-                        upb_deftype_t type, upb_status *status,
-                        const void **def) {
-  if(sym.size == 0) return NULL;
-  if(sym.data[0] == '.') {
-    /* Symbols starting with '.' are absolute, so we do a single lookup.
-     * Slice to omit the leading '.' */
-    upb_value v;
-    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
-      return false;
-    }
-
-    *def = unpack_def(v, type);
-
-    if (!*def) {
-      upb_status_seterrf(status,
-                         "type mismatch when resolving field %s, name %s",
-                         f->full_name, sym.data);
-      return false;
-    }
-
-    return true;
-  } else {
-    /* Remove components from base until we find an entry or run out.
-     * TODO: This branch is totally broken, but currently not used. */
-    (void)base;
-    UPB_ASSERT(false);
-    return false;
-  }
-}
-
-const void *symtab_resolve(const symtab_addctx *ctx, const upb_fielddef *f,
-                           const char *base, upb_strview sym,
-                           upb_deftype_t type) {
-  const void *ret;
-  if (!resolvename(ctx->addtab, f, base, sym, type, ctx->status, &ret) &&
-      !resolvename(&ctx->symtab->syms, f, base, sym, type, ctx->status, &ret)) {
-    if (upb_ok(ctx->status)) {
-      upb_status_seterrf(ctx->status, "couldn't resolve name '%s'", sym.data);
-    }
-    return false;
-  }
-  return ret;
-}
-
-static bool create_oneofdef(
-    const symtab_addctx *ctx, upb_msgdef *m,
-    const google_protobuf_OneofDescriptorProto *oneof_proto) {
-  upb_oneofdef *o;
-  upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
-  upb_value v;
-
-  o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
-  o->parent = m;
-  o->full_name = makefullname(ctx, m->full_name, name);
-
-  v = pack_def(o, UPB_DEFTYPE_ONEOF);
-  CHK_OOM(symtab_add(ctx, o->full_name, v));
-  CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc));
-
-  CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-  CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
-  return true;
-}
-
-static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len,
-                          upb_fielddef *f) {
-  char *end;
-  char nullz[64];
-  errno = 0;
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      /* Standard C number parsing functions expect null-terminated strings. */
-      if (len >= sizeof(nullz) - 1) {
-        return false;
-      }
-      memcpy(nullz, str, len);
-      nullz[len] = '\0';
-      str = nullz;
-      break;
-    default:
-      break;
-  }
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32: {
-      long val = strtol(str, &end, 0);
-      CHK(val <= INT32_MAX && val >= INT32_MIN && errno != ERANGE && !*end);
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_ENUM: {
-      const upb_enumdef *e = f->sub.enumdef;
-      int32_t val;
-      CHK(upb_enumdef_ntoi(e, str, len, &val));
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_INT64: {
-      /* XXX: Need to write our own strtoll, since it's not available in c89. */
-      int64_t val = strtol(str, &end, 0);
-      CHK(val <= INT64_MAX && val >= INT64_MIN && errno != ERANGE && !*end);
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_UINT32: {
-      unsigned long val = strtoul(str, &end, 0);
-      CHK(val <= UINT32_MAX && errno != ERANGE && !*end);
-      f->defaultval.uint = val;
-      break;
-    }
-    case UPB_TYPE_UINT64: {
-      /* XXX: Need to write our own strtoull, since it's not available in c89. */
-      uint64_t val = strtoul(str, &end, 0);
-      CHK(val <= UINT64_MAX && errno != ERANGE && !*end);
-      f->defaultval.uint = val;
-      break;
-    }
-    case UPB_TYPE_DOUBLE: {
-      double val = strtod(str, &end);
-      CHK(errno != ERANGE && !*end);
-      f->defaultval.dbl = val;
-      break;
-    }
-    case UPB_TYPE_FLOAT: {
-      /* XXX: Need to write our own strtof, since it's not available in c89. */
-      float val = strtod(str, &end);
-      CHK(errno != ERANGE && !*end);
-      f->defaultval.flt = val;
-      break;
-    }
-    case UPB_TYPE_BOOL: {
-      if (streql2(str, len, "false")) {
-        f->defaultval.boolean = false;
-      } else if (streql2(str, len, "true")) {
-        f->defaultval.boolean = true;
-      } else {
-        return false;
-      }
-      break;
-    }
-    case UPB_TYPE_STRING:
-      f->defaultval.str = newstr(ctx->alloc, str, len);
-      break;
-    case UPB_TYPE_BYTES:
-      /* XXX: need to interpret the C-escaped value. */
-      f->defaultval.str = newstr(ctx->alloc, str, len);
-      break;
-    case UPB_TYPE_MESSAGE:
-      /* Should not have a default value. */
-      return false;
-  }
-  return true;
-}
-
-static void set_default_default(const symtab_addctx *ctx, upb_fielddef *f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_ENUM:
-      f->defaultval.sint = 0;
-      break;
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_UINT32:
-      f->defaultval.uint = 0;
-      break;
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      f->defaultval.dbl = 0;
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      f->defaultval.str = newstr(ctx->alloc, NULL, 0);
-      break;
-    case UPB_TYPE_BOOL:
-      f->defaultval.boolean = false;
-      break;
-    case UPB_TYPE_MESSAGE:
-      break;
-  }
-}
-
-static bool create_fielddef(
-    const symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
-    const google_protobuf_FieldDescriptorProto *field_proto) {
-  upb_alloc *alloc = ctx->alloc;
-  upb_fielddef *f;
-  const google_protobuf_FieldOptions *options;
-  upb_strview name;
-  const char *full_name;
-  const char *json_name;
-  const char *shortname;
-  uint32_t field_number;
-
-  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
-    upb_status_seterrmsg(ctx->status, "field has no name");
-    return false;
-  }
-
-  name = google_protobuf_FieldDescriptorProto_name(field_proto);
-  CHK(upb_isident(name, false, ctx->status));
-  full_name = makefullname(ctx, prefix, name);
-  shortname = shortdefname(full_name);
-
-  if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
-    json_name = strviewdup(
-        ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
-  } else {
-    json_name = makejsonname(shortname, ctx->alloc);
-  }
-
-  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
-
-  if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
-    upb_status_seterrf(ctx->status, "invalid field number (%u)", field_number);
-    return false;
-  }
-
-  if (m) {
-    /* direct message field. */
-    upb_value v, field_v, json_v;
-    size_t json_size;
-
-    f = (upb_fielddef*)&m->fields[m->field_count++];
-    f->msgdef = m;
-    f->is_extension_ = false;
-
-    if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate field name (%s)", shortname);
-      return false;
-    }
-
-    if (upb_strtable_lookup(&m->ntof, json_name, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate json_name (%s)", json_name);
-      return false;
-    }
-
-    if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate field number (%u)",
-                         field_number);
-      return false;
-    }
-
-    field_v = pack_def(f, UPB_DEFTYPE_FIELD);
-    json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME);
-    v = upb_value_constptr(f);
-    json_size = strlen(json_name);
-
-    CHK_OOM(
-        upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc));
-    CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc));
-
-    if (strcmp(shortname, json_name) != 0) {
-      upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc);
-    }
-
-    if (ctx->layouts) {
-      const upb_msglayout_field *fields = m->layout->fields;
-      int count = m->layout->field_count;
-      bool found = false;
-      int i;
-      for (i = 0; i < count; i++) {
-        if (fields[i].number == field_number) {
-          f->layout_index = i;
-          found = true;
-          break;
-        }
-      }
-      UPB_ASSERT(found);
-    }
-  } else {
-    /* extension field. */
-    f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++];
-    f->is_extension_ = true;
-    CHK_OOM(symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD)));
-  }
-
-  f->full_name = full_name;
-  f->json_name = json_name;
-  f->file = ctx->file;
-  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
-  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
-  f->number_ = field_number;
-  f->oneof = NULL;
-  f->proto3_optional_ =
-      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
-
-  /* We can't resolve the subdef or (in the case of extensions) the containing
-   * message yet, because it may not have been defined yet.  We stash a pointer
-   * to the field_proto until later when we can properly resolve it. */
-  f->sub.unresolved = field_proto;
-
-  if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
-    upb_status_seterrf(ctx->status, "proto3 fields cannot be required (%s)",
-                       f->full_name);
-    return false;
-  }
-
-  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
-    int oneof_index =
-        google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
-    upb_oneofdef *oneof;
-    upb_value v = upb_value_constptr(f);
-
-    if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
-      upb_status_seterrf(ctx->status,
-                         "fields in oneof must have OPTIONAL label (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (!m) {
-      upb_status_seterrf(ctx->status,
-                         "oneof_index provided for extension field (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (oneof_index >= m->oneof_count) {
-      upb_status_seterrf(ctx->status, "oneof_index out of range (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    oneof = (upb_oneofdef*)&m->oneofs[oneof_index];
-    f->oneof = oneof;
-
-    CHK(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc));
-    CHK(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc));
-  } else {
-    f->oneof = NULL;
-  }
-
-  if (google_protobuf_FieldDescriptorProto_has_options(field_proto)) {
-    options = google_protobuf_FieldDescriptorProto_options(field_proto);
-    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
-    f->packed_ = google_protobuf_FieldOptions_packed(options);
-  } else {
-    f->lazy_ = false;
-    f->packed_ = false;
-  }
-
-  return true;
-}
-
-static bool create_enumdef(
-    const symtab_addctx *ctx, const char *prefix,
-    const google_protobuf_EnumDescriptorProto *enum_proto) {
-  upb_enumdef *e;
-  const google_protobuf_EnumValueDescriptorProto *const *values;
-  upb_strview name;
-  size_t i, n;
-
-  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
-  CHK(upb_isident(name, false, ctx->status));
-
-  e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
-  e->full_name = makefullname(ctx, prefix, name);
-  CHK_OOM(symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM)));
-
-  CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, ctx->alloc));
-  CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc));
-
-  e->file = ctx->file;
-  e->defaultval = 0;
-
-  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
-
-  if (n == 0) {
-    upb_status_seterrf(ctx->status,
-                       "enums must contain at least one value (%s)",
-                       e->full_name);
-    return false;
-  }
-
-  for (i = 0; i < n; i++) {
-    const google_protobuf_EnumValueDescriptorProto *value = values[i];
-    upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
-    char *name2 = strviewdup(ctx, name);
-    int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
-    upb_value v = upb_value_int32(num);
-
-    if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
-      upb_status_seterrf(ctx->status,
-                         "for proto3, the first enum value must be zero (%s)",
-                         e->full_name);
-      return false;
-    }
-
-    if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate enum label '%s'", name2);
-      return false;
-    }
-
-    CHK_OOM(name2)
-    CHK_OOM(
-        upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc));
-
-    if (!upb_inttable_lookup(&e->iton, num, NULL)) {
-      upb_value v = upb_value_cstr(name2);
-      CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc));
-    }
-  }
-
-  upb_inttable_compact2(&e->iton, ctx->alloc);
-
-  return true;
-}
-
-static bool create_msgdef(symtab_addctx *ctx, const char *prefix,
-                          const google_protobuf_DescriptorProto *msg_proto) {
-  upb_msgdef *m;
-  const google_protobuf_MessageOptions *options;
-  const google_protobuf_OneofDescriptorProto *const *oneofs;
-  const google_protobuf_FieldDescriptorProto *const *fields;
-  const google_protobuf_EnumDescriptorProto *const *enums;
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-  upb_strview name;
-
-  name = google_protobuf_DescriptorProto_name(msg_proto);
-  CHK(upb_isident(name, false, ctx->status));
-
-  m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
-  m->full_name = makefullname(ctx, prefix, name);
-  CHK_OOM(symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG)));
-
-  CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-  CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
-  m->file = ctx->file;
-  m->map_entry = false;
-
-  options = google_protobuf_DescriptorProto_options(msg_proto);
-
-  if (options) {
-    m->map_entry = google_protobuf_MessageOptions_map_entry(options);
-  }
-
-  if (ctx->layouts) {
-    m->layout = *ctx->layouts;
-    ctx->layouts++;
-  } else {
-    /* Allocate now (to allow cross-linking), populate later. */
-    m->layout = upb_malloc(ctx->alloc, sizeof(*m->layout));
-  }
-
-  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n);
-  m->oneof_count = 0;
-  m->oneofs = upb_malloc(ctx->alloc, sizeof(*m->oneofs) * n);
-  for (i = 0; i < n; i++) {
-    CHK(create_oneofdef(ctx, m, oneofs[i]));
-  }
-
-  fields = google_protobuf_DescriptorProto_field(msg_proto, &n);
-  m->field_count = 0;
-  m->fields = upb_malloc(ctx->alloc, sizeof(*m->fields) * n);
-  for (i = 0; i < n; i++) {
-    CHK(create_fielddef(ctx, m->full_name, m, fields[i]));
-  }
-
-  CHK(assign_msg_indices(m, ctx->status));
-  assign_msg_wellknowntype(m);
-  upb_inttable_compact2(&m->itof, ctx->alloc);
-
-  /* This message is built.  Now build nested messages and enums. */
-
-  enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_enumdef(ctx, m->full_name, enums[i]));
-  }
-
-  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_msgdef(ctx, m->full_name, msgs[i]));
-  }
-
-  return true;
-}
-
-typedef struct {
-  int msg_count;
-  int enum_count;
-  int ext_count;
-} decl_counts;
-
-static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
-                               decl_counts *counts) {
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-
-  counts->msg_count++;
-
-  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    count_types_in_msg(msgs[i], counts);
-  }
-
-  google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  counts->enum_count += n;
-
-  google_protobuf_DescriptorProto_extension(msg_proto, &n);
-  counts->ext_count += n;
-}
-
-static void count_types_in_file(
-    const google_protobuf_FileDescriptorProto *file_proto,
-    decl_counts *counts) {
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    count_types_in_msg(msgs[i], counts);
-  }
-
-  google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  counts->enum_count += n;
-
-  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  counts->ext_count += n;
-}
-
-static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix,
-                             upb_fielddef *f) {
-  upb_strview name;
-  const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
-
-  if (f->is_extension_) {
-    if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
-      upb_status_seterrf(ctx->status,
-                         "extension for field '%s' had no extendee",
-                         f->full_name);
-      return false;
-    }
-
-    name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
-    f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
-    CHK(f->msgdef);
-  }
-
-  if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
-      !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
-    upb_status_seterrf(ctx->status, "field '%s' is missing type name",
-                       f->full_name);
-    return false;
-  }
-
-  name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
-
-  if (upb_fielddef_issubmsg(f)) {
-    f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
-    CHK(f->sub.msgdef);
-  } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
-    f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
-    CHK(f->sub.enumdef);
-  }
-
-  /* Have to delay resolving of the default value until now because of the enum
-   * case, since enum defaults are specified with a label. */
-  if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
-    upb_strview defaultval =
-        google_protobuf_FieldDescriptorProto_default_value(field_proto);
-
-    if (f->file->syntax == UPB_SYNTAX_PROTO3) {
-      upb_status_seterrf(ctx->status,
-                         "proto3 fields cannot have explicit defaults (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (upb_fielddef_issubmsg(f)) {
-      upb_status_seterrf(ctx->status,
-                         "message fields cannot have explicit defaults (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (!parse_default(ctx, defaultval.data, defaultval.size, f)) {
-      upb_status_seterrf(ctx->status,
-                         "couldn't parse default '" UPB_STRVIEW_FORMAT
-                         "' for field (%s)",
-                         UPB_STRVIEW_ARGS(defaultval), f->full_name);
-      return false;
-    }
-  } else {
-    set_default_default(ctx, f);
-  }
-
-  return true;
-}
-
-static bool build_filedef(
-    symtab_addctx *ctx, upb_filedef *file,
-    const google_protobuf_FileDescriptorProto *file_proto) {
-  upb_alloc *alloc = ctx->alloc;
-  const google_protobuf_FileOptions *file_options_proto;
-  const google_protobuf_DescriptorProto *const *msgs;
-  const google_protobuf_EnumDescriptorProto *const *enums;
-  const google_protobuf_FieldDescriptorProto *const *exts;
-  const upb_strview* strs;
-  size_t i, n;
-  decl_counts counts = {0};
-
-  count_types_in_file(file_proto, &counts);
-
-  file->msgs = upb_malloc(alloc, sizeof(*file->msgs) * counts.msg_count);
-  file->enums = upb_malloc(alloc, sizeof(*file->enums) * counts.enum_count);
-  file->exts = upb_malloc(alloc, sizeof(*file->exts) * counts.ext_count);
-
-  CHK_OOM(counts.msg_count == 0 || file->msgs);
-  CHK_OOM(counts.enum_count == 0 || file->enums);
-  CHK_OOM(counts.ext_count == 0 || file->exts);
-
-  /* We increment these as defs are added. */
-  file->msg_count = 0;
-  file->enum_count = 0;
-  file->ext_count = 0;
-
-  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
-    upb_status_seterrmsg(ctx->status, "File has no name");
-    return false;
-  }
-
-  file->name =
-      strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
-  file->phpprefix = NULL;
-  file->phpnamespace = NULL;
-
-  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
-    upb_strview package =
-        google_protobuf_FileDescriptorProto_package(file_proto);
-    CHK(upb_isident(package, true, ctx->status));
-    file->package = strviewdup(ctx, package);
-  } else {
-    file->package = NULL;
-  }
-
-  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
-    upb_strview syntax =
-        google_protobuf_FileDescriptorProto_syntax(file_proto);
-
-    if (streql_view(syntax, "proto2")) {
-      file->syntax = UPB_SYNTAX_PROTO2;
-    } else if (streql_view(syntax, "proto3")) {
-      file->syntax = UPB_SYNTAX_PROTO3;
-    } else {
-      upb_status_seterrf(ctx->status, "Invalid syntax '" UPB_STRVIEW_FORMAT "'",
-                         UPB_STRVIEW_ARGS(syntax));
-      return false;
-    }
-  } else {
-    file->syntax = UPB_SYNTAX_PROTO2;
-  }
-
-  /* Read options. */
-  file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
-  if (file_options_proto) {
-    if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
-      file->phpprefix = strviewdup(
-          ctx,
-          google_protobuf_FileOptions_php_class_prefix(file_options_proto));
-    }
-    if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
-      file->phpnamespace = strviewdup(
-          ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
-    }
-  }
-
-  /* Verify dependencies. */
-  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
-  file->deps = upb_malloc(alloc, sizeof(*file->deps) * n) ;
-  CHK_OOM(n == 0 || file->deps);
-
-  for (i = 0; i < n; i++) {
-    upb_strview dep_name = strs[i];
-    upb_value v;
-    if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
-                              dep_name.size, &v)) {
-      upb_status_seterrf(ctx->status,
-                         "Depends on file '" UPB_STRVIEW_FORMAT
-                         "', but it has not been loaded",
-                         UPB_STRVIEW_ARGS(dep_name));
-      return false;
-    }
-    file->deps[i] = upb_value_getconstptr(v);
-  }
-
-  /* Create messages. */
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_msgdef(ctx, file->package, msgs[i]));
-  }
-
-  /* Create enums. */
-  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_enumdef(ctx, file->package, enums[i]));
-  }
-
-  /* Create extensions. */
-  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  file->exts = upb_malloc(alloc, sizeof(*file->exts) * n);
-  CHK_OOM(n == 0 || file->exts);
-  for (i = 0; i < n; i++) {
-    CHK(create_fielddef(ctx, file->package, NULL, exts[i]));
-  }
-
-  /* Now that all names are in the table, build layouts and resolve refs. */
-  for (i = 0; i < file->ext_count; i++) {
-    CHK(resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]));
-  }
-
-  for (i = 0; i < file->msg_count; i++) {
-    const upb_msgdef *m = &file->msgs[i];
-    int j;
-    for (j = 0; j < m->field_count; j++) {
-      CHK(resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]));
-    }
-  }
-
-  if (!ctx->layouts) {
-    for (i = 0; i < file->msg_count; i++) {
-      const upb_msgdef *m = &file->msgs[i];
-      make_layout(ctx->symtab, m);
-    }
-  }
-
-  return true;
- }
-
-static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx,
-                                 upb_status *status) {
-  const upb_filedef *file = ctx->file;
-  upb_alloc *alloc = upb_arena_alloc(s->arena);
-  upb_strtable_iter iter;
-
-  CHK_OOM(upb_strtable_insert3(&s->files, file->name, strlen(file->name),
-                               upb_value_constptr(file), alloc));
-
-  upb_strtable_begin(&iter, ctx->addtab);
-  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
-    upb_strview key = upb_strtable_iter_key(&iter);
-    upb_value value = upb_strtable_iter_value(&iter);
-    CHK_OOM(upb_strtable_insert3(&s->syms, key.data, key.size, value, alloc));
-  }
-
-  return true;
-}
-
-/* upb_filedef ****************************************************************/
-
-const char *upb_filedef_name(const upb_filedef *f) {
-  return f->name;
-}
-
-const char *upb_filedef_package(const upb_filedef *f) {
-  return f->package;
-}
-
-const char *upb_filedef_phpprefix(const upb_filedef *f) {
-  return f->phpprefix;
-}
-
-const char *upb_filedef_phpnamespace(const upb_filedef *f) {
-  return f->phpnamespace;
-}
-
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
-  return f->syntax;
-}
-
-int upb_filedef_msgcount(const upb_filedef *f) {
-  return f->msg_count;
-}
-
-int upb_filedef_depcount(const upb_filedef *f) {
-  return f->dep_count;
-}
-
-int upb_filedef_enumcount(const upb_filedef *f) {
-  return f->enum_count;
-}
-
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
-}
-
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
-}
-
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
-}
-
-void upb_symtab_free(upb_symtab *s) {
-  upb_arena_free(s->arena);
-  upb_gfree(s);
-}
-
-upb_symtab *upb_symtab_new(void) {
-  upb_symtab *s = upb_gmalloc(sizeof(*s));
-  upb_alloc *alloc;
-
-  if (!s) {
-    return NULL;
-  }
-
-  s->arena = upb_arena_new();
-  alloc = upb_arena_alloc(s->arena);
-
-  if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, alloc) ||
-      !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, alloc)) {
-    upb_arena_free(s->arena);
-    upb_gfree(s);
-    s = NULL;
-  }
-  return s;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ?
-      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
-                                        size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
-      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ?
-      unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
-}
-
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
-  upb_value v;
-  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
-                                                  : NULL;
-}
-
-int upb_symtab_filecount(const upb_symtab *s) {
-  return (int)upb_strtable_count(&s->files);
-}
-
-static const upb_filedef *_upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
-    const upb_msglayout **layouts, upb_status *status) {
-  upb_arena *tmparena = upb_arena_new();
-  upb_strtable addtab;
-  upb_alloc *alloc = upb_arena_alloc(s->arena);
-  upb_filedef *file = upb_malloc(alloc, sizeof(*file));
-  bool ok;
-  symtab_addctx ctx;
-
-  ctx.file = file;
-  ctx.symtab = s;
-  ctx.alloc = alloc;
-  ctx.tmp = upb_arena_alloc(tmparena);
-  ctx.addtab = &addtab;
-  ctx.layouts = layouts;
-  ctx.status = status;
-
-  ok = file &&
-      upb_strtable_init2(&addtab, UPB_CTYPE_CONSTPTR, ctx.tmp) &&
-      build_filedef(&ctx, file, file_proto) &&
-      upb_symtab_addtotabs(s, &ctx, status);
-
-  upb_arena_free(tmparena);
-  return ok ? file : NULL;
-}
-
-const upb_filedef *upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
-    upb_status *status) {
-  return _upb_symtab_addfile(s, file_proto, NULL, status);
-}
-
-/* Include here since we want most of this file to be stdio-free. */
-#include <stdio.h>
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
-  /* Since this function should never fail (it would indicate a bug in upb) we
-   * print errors to stderr instead of returning error status to the user. */
-  upb_def_init **deps = init->deps;
-  google_protobuf_FileDescriptorProto *file;
-  upb_arena *arena;
-  upb_status status;
-
-  upb_status_clear(&status);
-
-  if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
-    return true;
-  }
-
-  arena = upb_arena_new();
-
-  for (; *deps; deps++) {
-    if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
-  }
-
-  file = google_protobuf_FileDescriptorProto_parse(
-      init->descriptor.data, init->descriptor.size, arena);
-
-  if (!file) {
-    upb_status_seterrf(
-        &status,
-        "Failed to parse compiled-in descriptor for file '%s'. This should "
-        "never happen.",
-        init->filename);
-    goto err;
-  }
-
-  if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err;
-
-  upb_arena_free(arena);
-  return true;
-
-err:
-  fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
-          upb_status_errmsg(&status));
-  upb_arena_free(arena);
-  return false;
-}
-
-#undef CHK
-#undef CHK_OOM
-
-
-#include <string.h>
-
-
-static char field_size[] = {
-  0,/* 0 */
-  8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
-  4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
-  8, /* UPB_DESCRIPTOR_TYPE_INT64 */
-  8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
-  4, /* UPB_DESCRIPTOR_TYPE_INT32 */
-  8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
-  4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
-  1, /* UPB_DESCRIPTOR_TYPE_BOOL */
-  sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
-  sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
-  sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
-  sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
-  4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
-  4, /* UPB_DESCRIPTOR_TYPE_ENUM */
-  4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
-  8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
-  4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
-  8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
-};
-
-/* Strings/bytes are special-cased in maps. */
-static char _upb_fieldtype_to_mapsize[12] = {
-  0,
-  1,  /* UPB_TYPE_BOOL */
-  4,  /* UPB_TYPE_FLOAT */
-  4,  /* UPB_TYPE_INT32 */
-  4,  /* UPB_TYPE_UINT32 */
-  4,  /* UPB_TYPE_ENUM */
-  sizeof(void*),  /* UPB_TYPE_MESSAGE */
-  8,  /* UPB_TYPE_DOUBLE */
-  8,  /* UPB_TYPE_INT64 */
-  8,  /* UPB_TYPE_UINT64 */
-  0,  /* UPB_TYPE_STRING */
-  0,  /* UPB_TYPE_BYTES */
-};
-
-/** upb_msg *******************************************************************/
-
-upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
-  return _upb_msg_new(upb_msgdef_layout(m), a);
-}
-
-static bool in_oneof(const upb_msglayout_field *field) {
-  return field->presence < 0;
-}
-
-static uint32_t *oneofcase(const upb_msg *msg,
-                           const upb_msglayout_field *field) {
-  UPB_ASSERT(in_oneof(field));
-  return UPB_PTR_AT(msg, -field->presence, uint32_t);
-}
-
-static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  const char *mem = UPB_PTR_AT(msg, field->offset, char);
-  upb_msgval val = {0};
-  int size = upb_fielddef_isseq(f) ? sizeof(void *)
-                                   : field_size[field->descriptortype];
-  memcpy(&val, mem, size);
-  return val;
-}
-
-bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  if (in_oneof(field)) {
-    return *oneofcase(msg, field) == field->number;
-  } else if (field->presence > 0) {
-    uint32_t hasbit = field->presence;
-    return *UPB_PTR_AT(msg, hasbit / 8, uint8_t) & (1 << (hasbit % 8));
-  } else {
-    UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
-               field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
-    return _upb_msg_getraw(msg, f).msg_val != NULL;
-  }
-}
-
-bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o) {
-  upb_oneof_iter i;
-  const upb_fielddef *f;
-  const upb_msglayout_field *field;
-
-  upb_oneof_begin(&i, o);
-  if (upb_oneof_done(&i)) return false;
-  f = upb_oneof_iter_field(&i);
-  field = upb_fielddef_layout(f);
-  return *oneofcase(msg, field) != 0;
-}
-
-upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
-  if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
-    return _upb_msg_getraw(msg, f);
-  } else {
-    /* TODO(haberman): change upb_fielddef to not require this switch(). */
-    upb_msgval val = {0};
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_INT32:
-      case UPB_TYPE_ENUM:
-        val.int32_val = upb_fielddef_defaultint32(f);
-        break;
-      case UPB_TYPE_INT64:
-        val.int64_val = upb_fielddef_defaultint64(f);
-        break;
-      case UPB_TYPE_UINT32:
-        val.uint32_val = upb_fielddef_defaultuint32(f);
-        break;
-      case UPB_TYPE_UINT64:
-        val.uint64_val = upb_fielddef_defaultuint64(f);
-        break;
-      case UPB_TYPE_FLOAT:
-        val.float_val = upb_fielddef_defaultfloat(f);
-        break;
-      case UPB_TYPE_DOUBLE:
-        val.double_val = upb_fielddef_defaultdouble(f);
-        break;
-      case UPB_TYPE_BOOL:
-        val.double_val = upb_fielddef_defaultbool(f);
-        break;
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size);
-        break;
-      case UPB_TYPE_MESSAGE:
-        val.msg_val = NULL;
-        break;
-    }
-    return val;
-  }
-}
-
-upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
-                              upb_arena *a) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  upb_mutmsgval ret;
-  char *mem = UPB_PTR_AT(msg, field->offset, char);
-  bool wrong_oneof = in_oneof(field) && *oneofcase(msg, field) != field->number;
-
-  memcpy(&ret, mem, sizeof(void*));
-
-  if (a && (!ret.msg || wrong_oneof)) {
-    if (upb_fielddef_ismap(f)) {
-      const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
-      const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
-      const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
-      ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
-    } else if (upb_fielddef_isseq(f)) {
-      ret.array = upb_array_new(a, upb_fielddef_type(f));
-    } else {
-      UPB_ASSERT(upb_fielddef_issubmsg(f));
-      ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
-    }
-
-    memcpy(mem, &ret, sizeof(void*));
-
-    if (wrong_oneof) {
-      *oneofcase(msg, field) = field->number;
-    }
-  }
-  return ret;
-}
-
-void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
-                 upb_arena *a) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  char *mem = UPB_PTR_AT(msg, field->offset, char);
-  int size = upb_fielddef_isseq(f) ? sizeof(void *)
-                                   : field_size[field->descriptortype];
-  memcpy(mem, &val, size);
-  if (in_oneof(field)) {
-    *oneofcase(msg, field) = field->number;
-  }
-}
-
-bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
-                  const upb_symtab *ext_pool, const upb_fielddef **out_f,
-                  upb_msgval *out_val, size_t *iter) {
-  size_t i = *iter;
-  const upb_msgval zero = {0};
-  const upb_fielddef *f;
-  while ((f = _upb_msgdef_field(m, (int)++i)) != NULL) {
-    upb_msgval val = _upb_msg_getraw(msg, f);
-
-    /* Skip field if unset or empty. */
-    if (upb_fielddef_haspresence(f)) {
-      if (!upb_msg_has(msg, f)) continue;
-    } else {
-      upb_msgval test = val;
-      if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
-        /* Clear string pointer, only size matters (ptr could be non-NULL). */
-        test.str_val.data = NULL;
-      }
-      /* Continue if NULL or 0. */
-      if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
-
-      /* Continue on empty array or map. */
-      if (upb_fielddef_ismap(f)) {
-        if (upb_map_size(test.map_val) == 0) continue;
-      } else if (upb_fielddef_isseq(f)) {
-        if (upb_array_size(test.array_val) == 0) continue;
-      }
-    }
-
-    *out_val = val;
-    *out_f = f;
-    *iter = i;
-    return true;
-  }
-  *iter = i;
-  return false;
-}
-
-/** upb_array *****************************************************************/
-
-upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
-  return _upb_array_new(a, type);
-}
-
-size_t upb_array_size(const upb_array *arr) {
-  return arr->len;
-}
-
-upb_msgval upb_array_get(const upb_array *arr, size_t i) {
-  upb_msgval ret;
-  const char* data = _upb_array_constptr(arr);
-  int lg2 = arr->data & 7;
-  UPB_ASSERT(i < arr->len);
-  memcpy(&ret, data + (i << lg2), 1 << lg2);
-  return ret;
-}
-
-void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
-  char* data = _upb_array_ptr(arr);
-  int lg2 = arr->data & 7;
-  UPB_ASSERT(i < arr->len);
-  memcpy(data + (i << lg2), &val, 1 << lg2);
-}
-
-bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
-  if (!_upb_array_realloc(arr, arr->len + 1, arena)) {
-    return false;
-  }
-  arr->len++;
-  upb_array_set(arr, arr->len - 1, val);
-  return true;
-}
-
-/* Resizes the array to the given size, reallocating if necessary, and returns a
- * pointer to the new array elements. */
-bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) {
-  return _upb_array_realloc(arr, size, arena);
-}
-
-/** upb_map *******************************************************************/
-
-upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
-                     upb_fieldtype_t value_type) {
-  return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
-                      _upb_fieldtype_to_mapsize[value_type]);
-}
-
-size_t upb_map_size(const upb_map *map) {
-  return _upb_map_size(map);
-}
-
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
-  return _upb_map_get(map, &key, map->key_size, val, map->val_size);
-}
-
-bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
-                 upb_arena *arena) {
-  return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena);
-}
-
-bool upb_map_delete(upb_map *map, upb_msgval key) {
-  return _upb_map_delete(map, &key, map->key_size);
-}
-
-bool upb_mapiter_next(const upb_map *map, size_t *iter) {
-  return _upb_map_next(map, iter);
-}
-
-/* Returns the key and value for this entry of the map. */
-upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
-  upb_strtable_iter i;
-  upb_msgval ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
-  return ret;
-}
-
-upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
-  upb_strtable_iter i;
-  upb_msgval ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
-  return ret;
-}
-
-/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
-/*
-** TODO(haberman): it's unclear whether a lot of the consistency checks should
-** UPB_ASSERT() or return false.
-*/
-
-
-#include <string.h>
-
-
-
-struct upb_handlers {
-  upb_handlercache *cache;
-  const upb_msgdef *msg;
-  const upb_handlers **sub;
-  const void *top_closure_type;
-  upb_handlers_tabent table[1];  /* Dynamically-sized field handler array. */
-};
-
-static void *upb_calloc(upb_arena *arena, size_t size) {
-  void *mem = upb_malloc(upb_arena_alloc(arena), size);
-  if (mem) {
-    memset(mem, 0, size);
-  }
-  return mem;
-}
-
-/* Defined for the sole purpose of having a unique pointer value for
- * UPB_NO_CLOSURE. */
-char _upb_noclosure;
-
-/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
- * subhandlers for this submessage field. */
-#define SUBH(h, selector) (h->sub[selector])
-
-/* The selector for a submessage field is the field index. */
-#define SUBH_F(h, f) SUBH(h, upb_fielddef_index(f))
-
-static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
-                         upb_handlertype_t type) {
-  upb_selector_t sel;
-  bool ok;
-
-  ok = upb_handlers_getselector(f, type, &sel);
-
-  UPB_ASSERT(upb_handlers_msgdef(h) == upb_fielddef_containingtype(f));
-  UPB_ASSERT(ok);
-
-  return sel;
-}
-
-static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
-                             upb_handlertype_t type) {
-  int32_t sel = trygetsel(h, f, type);
-  UPB_ASSERT(sel >= 0);
-  return sel;
-}
-
-static const void **returntype(upb_handlers *h, const upb_fielddef *f,
-                               upb_handlertype_t type) {
-  return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type;
-}
-
-static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
-                  upb_handlertype_t type, upb_func *func,
-                  const upb_handlerattr *attr) {
-  upb_handlerattr set_attr = UPB_HANDLERATTR_INIT;
-  const void *closure_type;
-  const void **context_closure_type;
-
-  UPB_ASSERT(!h->table[sel].func);
-
-  if (attr) {
-    set_attr = *attr;
-  }
-
-  /* Check that the given closure type matches the closure type that has been
-   * established for this context (if any). */
-  closure_type = set_attr.closure_type;
-
-  if (type == UPB_HANDLER_STRING) {
-    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
-  } else if (f && upb_fielddef_isseq(f) &&
-             type != UPB_HANDLER_STARTSEQ &&
-             type != UPB_HANDLER_ENDSEQ) {
-    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
-  } else {
-    context_closure_type = &h->top_closure_type;
-  }
-
-  if (closure_type && *context_closure_type &&
-      closure_type != *context_closure_type) {
-    return false;
-  }
-
-  if (closure_type)
-    *context_closure_type = closure_type;
-
-  /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
-   * matches any pre-existing expectations about what type is expected. */
-  if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
-    const void *return_type = set_attr.return_closure_type;
-    const void *table_return_type = h->table[sel].attr.return_closure_type;
-    if (return_type && table_return_type && return_type != table_return_type) {
-      return false;
-    }
-
-    if (table_return_type && !return_type) {
-      set_attr.return_closure_type = table_return_type;
-    }
-  }
-
-  h->table[sel].func = (upb_func*)func;
-  h->table[sel].attr = set_attr;
-  return true;
-}
-
-/* Returns the effective closure type for this handler (which will propagate
- * from outer frames if this frame has no START* handler).  Not implemented for
- * UPB_HANDLER_STRING at the moment since this is not needed.  Returns NULL is
- * the effective closure type is unspecified (either no handler was registered
- * to specify it or the handler that was registered did not specify the closure
- * type). */
-const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
-                                   upb_handlertype_t type) {
-  const void *ret;
-  upb_selector_t sel;
-
-  UPB_ASSERT(type != UPB_HANDLER_STRING);
-  ret = h->top_closure_type;
-
-  if (upb_fielddef_isseq(f) &&
-      type != UPB_HANDLER_STARTSEQ &&
-      type != UPB_HANDLER_ENDSEQ &&
-      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
-    ret = h->table[sel].attr.return_closure_type;
-  }
-
-  if (type == UPB_HANDLER_STRING &&
-      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
-    ret = h->table[sel].attr.return_closure_type;
-  }
-
-  /* The effective type of the submessage; not used yet.
-   * if (type == SUBMESSAGE &&
-   *     h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
-   *   ret = h->table[sel].attr.return_closure_type;
-   * } */
-
-  return ret;
-}
-
-/* Checks whether the START* handler specified by f & type is missing even
- * though it is required to convert the established type of an outer frame
- * ("closure_type") into the established type of an inner frame (represented in
- * the return closure type of this handler's attr. */
-bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
-                upb_status *status) {
-  const void *closure_type;
-  const upb_handlerattr *attr;
-  const void *return_closure_type;
-
-  upb_selector_t sel = handlers_getsel(h, f, type);
-  if (h->table[sel].func) return true;
-  closure_type = effective_closure_type(h, f, type);
-  attr = &h->table[sel].attr;
-  return_closure_type = attr->return_closure_type;
-  if (closure_type && return_closure_type &&
-      closure_type != return_closure_type) {
-    return false;
-  }
-  return true;
-}
-
-static upb_handlers *upb_handlers_new(const upb_msgdef *md,
-                                      upb_handlercache *cache,
-                                      upb_arena *arena) {
-  int extra;
-  upb_handlers *h;
-
-  extra =
-      (int)(sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1));
-  h = upb_calloc(arena, sizeof(*h) + extra);
-  if (!h) return NULL;
-
-  h->cache = cache;
-  h->msg = md;
-
-  if (upb_msgdef_submsgfieldcount(md) > 0) {
-    size_t bytes = upb_msgdef_submsgfieldcount(md) * sizeof(*h->sub);
-    h->sub = upb_calloc(arena, bytes);
-    if (!h->sub) return NULL;
-  } else {
-    h->sub = 0;
-  }
-
-  /* calloc() above initialized all handlers to NULL. */
-  return h;
-}
-
-/* Public interface ***********************************************************/
-
-#define SETTER(name, handlerctype, handlertype)                       \
-  bool upb_handlers_set##name(upb_handlers *h, const upb_fielddef *f, \
-                              handlerctype func,                      \
-                              const upb_handlerattr *attr) {          \
-    int32_t sel = trygetsel(h, f, handlertype);                       \
-    return doset(h, sel, f, handlertype, (upb_func *)func, attr);     \
-  }
-
-SETTER(int32,       upb_int32_handlerfunc*,       UPB_HANDLER_INT32)
-SETTER(int64,       upb_int64_handlerfunc*,       UPB_HANDLER_INT64)
-SETTER(uint32,      upb_uint32_handlerfunc*,      UPB_HANDLER_UINT32)
-SETTER(uint64,      upb_uint64_handlerfunc*,      UPB_HANDLER_UINT64)
-SETTER(float,       upb_float_handlerfunc*,       UPB_HANDLER_FLOAT)
-SETTER(double,      upb_double_handlerfunc*,      UPB_HANDLER_DOUBLE)
-SETTER(bool,        upb_bool_handlerfunc*,        UPB_HANDLER_BOOL)
-SETTER(startstr,    upb_startstr_handlerfunc*,    UPB_HANDLER_STARTSTR)
-SETTER(string,      upb_string_handlerfunc*,      UPB_HANDLER_STRING)
-SETTER(endstr,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSTR)
-SETTER(startseq,    upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSEQ)
-SETTER(startsubmsg, upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSUBMSG)
-SETTER(endsubmsg,   upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSUBMSG)
-SETTER(endseq,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSEQ)
-
-#undef SETTER
-
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
-                             const upb_handlerattr *attr) {
-  return doset(h, UPB_UNKNOWN_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
-                              const upb_handlerattr *attr) {
-  return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
-                            const upb_handlerattr *attr) {
-  return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
-                                 const upb_handlers *sub) {
-  UPB_ASSERT(sub);
-  UPB_ASSERT(upb_fielddef_issubmsg(f));
-  if (SUBH_F(h, f)) return false;  /* Can't reset. */
-  if (upb_handlers_msgdef(sub) != upb_fielddef_msgsubdef(f)) {
-    return false;
-  }
-  SUBH_F(h, f) = sub;
-  return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
-                                                const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_issubmsg(f));
-  return SUBH_F(h, f);
-}
-
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
-                                  const void **handler_data) {
-  upb_func *ret = (upb_func *)h->table[s].func;
-  if (ret && handler_data) {
-    *handler_data = h->table[s].attr.handler_data;
-  }
-  return ret;
-}
-
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
-                          upb_handlerattr *attr) {
-  if (!upb_handlers_gethandler(h, sel, NULL))
-    return false;
-  *attr = h->table[sel].attr;
-  return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
-                                                    upb_selector_t sel) {
-  /* STARTSUBMSG selector in sel is the field's selector base. */
-  return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
-}
-
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
-
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
-  return upb_handlercache_addcleanup(h->cache, p, func);
-}
-
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
-    case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
-    case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
-    case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
-    case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
-    case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
-    case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
-    default: UPB_ASSERT(false); return -1;  /* Invalid input. */
-  }
-}
-
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
-                              upb_selector_t *s) {
-  uint32_t selector_base = upb_fielddef_selectorbase(f);
-  switch (type) {
-    case UPB_HANDLER_INT32:
-    case UPB_HANDLER_INT64:
-    case UPB_HANDLER_UINT32:
-    case UPB_HANDLER_UINT64:
-    case UPB_HANDLER_FLOAT:
-    case UPB_HANDLER_DOUBLE:
-    case UPB_HANDLER_BOOL:
-      if (!upb_fielddef_isprimitive(f) ||
-          upb_handlers_getprimitivehandlertype(f) != type)
-        return false;
-      *s = selector_base;
-      break;
-    case UPB_HANDLER_STRING:
-      if (upb_fielddef_isstring(f)) {
-        *s = selector_base;
-      } else if (upb_fielddef_lazy(f)) {
-        *s = selector_base + 3;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_STARTSTR:
-      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
-        *s = selector_base + 1;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_ENDSTR:
-      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
-        *s = selector_base + 2;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_STARTSEQ:
-      if (!upb_fielddef_isseq(f)) return false;
-      *s = selector_base - 2;
-      break;
-    case UPB_HANDLER_ENDSEQ:
-      if (!upb_fielddef_isseq(f)) return false;
-      *s = selector_base - 1;
-      break;
-    case UPB_HANDLER_STARTSUBMSG:
-      if (!upb_fielddef_issubmsg(f)) return false;
-      /* Selectors for STARTSUBMSG are at the beginning of the table so that the
-       * selector can also be used as an index into the "sub" array of
-       * subhandlers.  The indexes for the two into these two tables are the
-       * same, except that in the handler table the static selectors come first. */
-      *s = upb_fielddef_index(f) + UPB_STATIC_SELECTOR_COUNT;
-      break;
-    case UPB_HANDLER_ENDSUBMSG:
-      if (!upb_fielddef_issubmsg(f)) return false;
-      *s = selector_base;
-      break;
-  }
-  UPB_ASSERT((size_t)*s < upb_msgdef_selectorcount(upb_fielddef_containingtype(f)));
-  return true;
-}
-
-/* upb_handlercache ***********************************************************/
-
-struct upb_handlercache {
-  upb_arena *arena;
-  upb_inttable tab;  /* maps upb_msgdef* -> upb_handlers*. */
-  upb_handlers_callback *callback;
-  const void *closure;
-};
-
-const upb_handlers *upb_handlercache_get(upb_handlercache *c,
-                                         const upb_msgdef *md) {
-  upb_msg_field_iter i;
-  upb_value v;
-  upb_handlers *h;
-
-  if (upb_inttable_lookupptr(&c->tab, md, &v)) {
-    return upb_value_getptr(v);
-  }
-
-  h = upb_handlers_new(md, c, c->arena);
-  v = upb_value_ptr(h);
-
-  if (!h) return NULL;
-  if (!upb_inttable_insertptr(&c->tab, md, v)) return NULL;
-
-  c->callback(c->closure, h);
-
-  /* For each submessage field, get or create a handlers object and set it as
-   * the subhandlers. */
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
-      const upb_handlers *sub_mh = upb_handlercache_get(c, subdef);
-
-      if (!sub_mh) return NULL;
-
-      upb_handlers_setsubhandlers(h, f, sub_mh);
-    }
-  }
-
-  return h;
-}
-
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
-                                       const void *closure) {
-  upb_handlercache *cache = upb_gmalloc(sizeof(*cache));
-
-  if (!cache) return NULL;
-
-  cache->arena = upb_arena_new();
-
-  cache->callback = callback;
-  cache->closure = closure;
-
-  if (!upb_inttable_init(&cache->tab, UPB_CTYPE_PTR)) goto oom;
-
-  return cache;
-
-oom:
-  upb_gfree(cache);
-  return NULL;
-}
-
-void upb_handlercache_free(upb_handlercache *cache) {
-  upb_inttable_uninit(&cache->tab);
-  upb_arena_free(cache->arena);
-  upb_gfree(cache);
-}
-
-bool upb_handlercache_addcleanup(upb_handlercache *c, void *p,
-                                 upb_handlerfree *func) {
-  return upb_arena_addcleanup(c->arena, p, func);
-}
-
-/* upb_byteshandler ***********************************************************/
-
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
-                                  upb_startstr_handlerfunc *func, void *d) {
-  h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_STARTSTR_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-bool upb_byteshandler_setstring(upb_byteshandler *h,
-                                upb_string_handlerfunc *func, void *d) {
-  h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_STRING_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
-                                upb_endfield_handlerfunc *func, void *d) {
-  h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_ENDSTR_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-/** Handlers for upb_msg ******************************************************/
-
-typedef struct {
-  size_t offset;
-  int32_t hasbit;
-} upb_msg_handlerdata;
-
-/* Fallback implementation if the handler is not specialized by the producer. */
-#define MSG_WRITER(type, ctype)                                               \
-  bool upb_msg_set ## type (void *c, const void *hd, ctype val) {             \
-    uint8_t *m = c;                                                           \
-    const upb_msg_handlerdata *d = hd;                                        \
-    if (d->hasbit > 0)                                                        \
-      *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8);                   \
-    *(ctype*)&m[d->offset] = val;                                             \
-    return true;                                                              \
-  }                                                                           \
-
-MSG_WRITER(double, double)
-MSG_WRITER(float,  float)
-MSG_WRITER(int32,  int32_t)
-MSG_WRITER(int64,  int64_t)
-MSG_WRITER(uint32, uint32_t)
-MSG_WRITER(uint64, uint64_t)
-MSG_WRITER(bool,   bool)
-
-bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f,
-                              size_t offset, int32_t hasbit) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  bool ok;
-
-  upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d));
-  if (!d) return false;
-  d->offset = offset;
-  d->hasbit = hasbit;
-
-  attr.handler_data = d;
-  attr.alwaysok = true;
-  upb_handlers_addcleanup(h, d, upb_gfree);
-
-#define TYPE(u, l) \
-  case UPB_TYPE_##u: \
-    ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break;
-
-  ok = false;
-
-  switch (upb_fielddef_type(f)) {
-    TYPE(INT64,  int64);
-    TYPE(INT32,  int32);
-    TYPE(ENUM,   int32);
-    TYPE(UINT64, uint64);
-    TYPE(UINT32, uint32);
-    TYPE(DOUBLE, double);
-    TYPE(FLOAT,  float);
-    TYPE(BOOL,   bool);
-    default: UPB_ASSERT(false); break;
-  }
-#undef TYPE
-
-  return ok;
-}
-
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
-                                  upb_selector_t s,
-                                  upb_fieldtype_t *type,
-                                  size_t *offset,
-                                  int32_t *hasbit) {
-  const upb_msg_handlerdata *d;
-  const void *p;
-  upb_func *f = upb_handlers_gethandler(h, s, &p);
-
-  if ((upb_int64_handlerfunc*)f == upb_msg_setint64) {
-    *type = UPB_TYPE_INT64;
-  } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) {
-    *type = UPB_TYPE_INT32;
-  } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) {
-    *type = UPB_TYPE_UINT64;
-  } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) {
-    *type = UPB_TYPE_UINT32;
-  } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) {
-    *type = UPB_TYPE_DOUBLE;
-  } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) {
-    *type = UPB_TYPE_FLOAT;
-  } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) {
-    *type = UPB_TYPE_BOOL;
-  } else {
-    return false;
-  }
-
-  d = p;
-  *offset = d->offset;
-  *hasbit = d->hasbit;
-  return true;
-}
-
-
-bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) {
-  void *subc;
-  bool ret;
-  upb_bufhandle handle = UPB_BUFHANDLE_INIT;
-  handle.buf = buf;
-  ret = upb_bytessink_start(sink, len, &subc);
-  if (ret && len != 0) {
-    ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len);
-  }
-  if (ret) {
-    ret = upb_bytessink_end(sink);
-  }
-  return ret;
-}
-
-
-#ifdef UPB_MSVC_VSNPRINTF
-/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and
- * vsnprintf. To support them, missing functions are manually implemented
- * using the existing secure functions. */
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) {
-  if (!s) {
-    return _vscprintf(format, arg);
-  }
-  int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg);
-  if (ret < 0) {
-	ret = _vscprintf(format, arg);
-  }
-  return ret;
-}
-
-int msvc_snprintf(char* s, size_t n, const char* format, ...) {
-  va_list arg;
-  va_start(arg, format);
-  int ret = msvc_vsnprintf(s, n, format, arg);
-  va_end(arg);
-  return ret;
-}
-#endif
-/*
-** protobuf decoder bytecode compiler
-**
-** Code to compile a upb::Handlers into bytecode for decoding a protobuf
-** according to that specific schema and destination handlers.
-**
-** Bytecode definition is in decoder.int.h.
-*/
-
-#include <stdarg.h>
-
-#ifdef UPB_DUMP_BYTECODE
-#include <stdio.h>
-#endif
-
-
-#define MAXLABEL 5
-#define EMPTYLABEL -1
-
-/* upb_pbdecodermethod ********************************************************/
-
-static void freemethod(upb_pbdecodermethod *method) {
-  upb_inttable_uninit(&method->dispatch);
-  upb_gfree(method);
-}
-
-static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
-                                      mgroup *group) {
-  upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret));
-  upb_byteshandler_init(&ret->input_handler_);
-
-  ret->group = group;
-  ret->dest_handlers_ = dest_handlers;
-  upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
-
-  return ret;
-}
-
-const upb_handlers *upb_pbdecodermethod_desthandlers(
-    const upb_pbdecodermethod *m) {
-  return m->dest_handlers_;
-}
-
-const upb_byteshandler *upb_pbdecodermethod_inputhandler(
-    const upb_pbdecodermethod *m) {
-  return &m->input_handler_;
-}
-
-bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
-  return m->is_native_;
-}
-
-
-/* mgroup *********************************************************************/
-
-static void freegroup(mgroup *g) {
-  upb_inttable_iter i;
-
-  upb_inttable_begin(&i, &g->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    freemethod(upb_value_getptr(upb_inttable_iter_value(&i)));
-  }
-
-  upb_inttable_uninit(&g->methods);
-  upb_gfree(g->bytecode);
-  upb_gfree(g);
-}
-
-mgroup *newgroup(void) {
-  mgroup *g = upb_gmalloc(sizeof(*g));
-  upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
-  g->bytecode = NULL;
-  g->bytecode_end = NULL;
-  return g;
-}
-
-
-/* bytecode compiler **********************************************************/
-
-/* Data used only at compilation time. */
-typedef struct {
-  mgroup *group;
-
-  uint32_t *pc;
-  int fwd_labels[MAXLABEL];
-  int back_labels[MAXLABEL];
-
-  /* For fields marked "lazy", parse them lazily or eagerly? */
-  bool lazy;
-} compiler;
-
-static compiler *newcompiler(mgroup *group, bool lazy) {
-  compiler *ret = upb_gmalloc(sizeof(*ret));
-  int i;
-
-  ret->group = group;
-  ret->lazy = lazy;
-  for (i = 0; i < MAXLABEL; i++) {
-    ret->fwd_labels[i] = EMPTYLABEL;
-    ret->back_labels[i] = EMPTYLABEL;
-  }
-  return ret;
-}
-
-static void freecompiler(compiler *c) {
-  upb_gfree(c);
-}
-
-const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
-
-/* How many words an instruction is. */
-static int instruction_len(uint32_t instr) {
-  switch (getop(instr)) {
-    case OP_SETDISPATCH: return 1 + ptr_words;
-    case OP_TAGN: return 3;
-    case OP_SETBIGGROUPNUM: return 2;
-    default: return 1;
-  }
-}
-
-bool op_has_longofs(int32_t instruction) {
-  switch (getop(instruction)) {
-    case OP_CALL:
-    case OP_BRANCH:
-    case OP_CHECKDELIM:
-      return true;
-    /* The "tag" instructions only have 8 bytes available for the jump target,
-     * but that is ok because these opcodes only require short jumps. */
-    case OP_TAG1:
-    case OP_TAG2:
-    case OP_TAGN:
-      return false;
-    default:
-      UPB_ASSERT(false);
-      return false;
-  }
-}
-
-static int32_t getofs(uint32_t instruction) {
-  if (op_has_longofs(instruction)) {
-    return (int32_t)instruction >> 8;
-  } else {
-    return (int8_t)(instruction >> 8);
-  }
-}
-
-static void setofs(uint32_t *instruction, int32_t ofs) {
-  if (op_has_longofs(*instruction)) {
-    *instruction = getop(*instruction) | (uint32_t)ofs << 8;
-  } else {
-    *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
-  }
-  UPB_ASSERT(getofs(*instruction) == ofs);  /* Would fail in cases of overflow. */
-}
-
-static uint32_t pcofs(compiler *c) {
-  return (uint32_t)(c->pc - c->group->bytecode);
-}
-
-/* Defines a local label at the current PC location.  All previous forward
- * references are updated to point to this location.  The location is noted
- * for any future backward references. */
-static void label(compiler *c, unsigned int label) {
-  int val;
-  uint32_t *codep;
-
-  UPB_ASSERT(label < MAXLABEL);
-  val = c->fwd_labels[label];
-  codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
-  while (codep) {
-    int ofs = getofs(*codep);
-    setofs(codep, (int32_t)(c->pc - codep - instruction_len(*codep)));
-    codep = ofs ? codep + ofs : NULL;
-  }
-  c->fwd_labels[label] = EMPTYLABEL;
-  c->back_labels[label] = pcofs(c);
-}
-
-/* Creates a reference to a numbered label; either a forward reference
- * (positive arg) or backward reference (negative arg).  For forward references
- * the value returned now is actually a "next" pointer into a linked list of all
- * instructions that use this label and will be patched later when the label is
- * defined with label().
- *
- * The returned value is the offset that should be written into the instruction.
- */
-static int32_t labelref(compiler *c, int label) {
-  UPB_ASSERT(label < MAXLABEL);
-  if (label == LABEL_DISPATCH) {
-    /* No resolving required. */
-    return 0;
-  } else if (label < 0) {
-    /* Backward local label.  Relative to the next instruction. */
-    uint32_t from = (uint32_t)((c->pc + 1) - c->group->bytecode);
-    return c->back_labels[-label] - from;
-  } else {
-    /* Forward local label: prepend to (possibly-empty) linked list. */
-    int *lptr = &c->fwd_labels[label];
-    int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
-    *lptr = pcofs(c);
-    return ret;
-  }
-}
-
-static void put32(compiler *c, uint32_t v) {
-  mgroup *g = c->group;
-  if (c->pc == g->bytecode_end) {
-    int ofs = pcofs(c);
-    size_t oldsize = g->bytecode_end - g->bytecode;
-    size_t newsize = UPB_MAX(oldsize * 2, 64);
-    /* TODO(haberman): handle OOM. */
-    g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t),
-                                            newsize * sizeof(uint32_t));
-    g->bytecode_end = g->bytecode + newsize;
-    c->pc = g->bytecode + ofs;
-  }
-  *c->pc++ = v;
-}
-
-static void putop(compiler *c, int op, ...) {
-  va_list ap;
-  va_start(ap, op);
-
-  switch (op) {
-    case OP_SETDISPATCH: {
-      uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
-      put32(c, OP_SETDISPATCH);
-      put32(c, (uint32_t)ptr);
-      if (sizeof(uintptr_t) > sizeof(uint32_t))
-        put32(c, (uint64_t)ptr >> 32);
-      break;
-    }
-    case OP_STARTMSG:
-    case OP_ENDMSG:
-    case OP_PUSHLENDELIM:
-    case OP_POP:
-    case OP_SETDELIM:
-    case OP_HALT:
-    case OP_RET:
-    case OP_DISPATCH:
-      put32(c, op);
-      break;
-    case OP_PARSE_DOUBLE:
-    case OP_PARSE_FLOAT:
-    case OP_PARSE_INT64:
-    case OP_PARSE_UINT64:
-    case OP_PARSE_INT32:
-    case OP_PARSE_FIXED64:
-    case OP_PARSE_FIXED32:
-    case OP_PARSE_BOOL:
-    case OP_PARSE_UINT32:
-    case OP_PARSE_SFIXED32:
-    case OP_PARSE_SFIXED64:
-    case OP_PARSE_SINT32:
-    case OP_PARSE_SINT64:
-    case OP_STARTSEQ:
-    case OP_ENDSEQ:
-    case OP_STARTSUBMSG:
-    case OP_ENDSUBMSG:
-    case OP_STARTSTR:
-    case OP_STRING:
-    case OP_ENDSTR:
-    case OP_PUSHTAGDELIM:
-      put32(c, op | va_arg(ap, upb_selector_t) << 8);
-      break;
-    case OP_SETBIGGROUPNUM:
-      put32(c, op);
-      put32(c, va_arg(ap, int));
-      break;
-    case OP_CALL: {
-      const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
-      put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
-      break;
-    }
-    case OP_CHECKDELIM:
-    case OP_BRANCH: {
-      uint32_t instruction = op;
-      int label = va_arg(ap, int);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      break;
-    }
-    case OP_TAG1:
-    case OP_TAG2: {
-      int label = va_arg(ap, int);
-      uint64_t tag = va_arg(ap, uint64_t);
-      uint32_t instruction = (uint32_t)(op | (tag << 16));
-      UPB_ASSERT(tag <= 0xffff);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      break;
-    }
-    case OP_TAGN: {
-      int label = va_arg(ap, int);
-      uint64_t tag = va_arg(ap, uint64_t);
-      uint32_t instruction = op | (upb_value_size(tag) << 16);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      put32(c, (uint32_t)tag);
-      put32(c, tag >> 32);
-      break;
-    }
-  }
-
-  va_end(ap);
-}
-
-#if defined(UPB_DUMP_BYTECODE)
-
-const char *upb_pbdecoder_getopname(unsigned int op) {
-#define QUOTE(x) #x
-#define EXPAND_AND_QUOTE(x) QUOTE(x)
-#define OPNAME(x) OP_##x
-#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
-#define T(x) OP(PARSE_##x)
-  /* Keep in sync with list in decoder.int.h. */
-  switch ((opcode)op) {
-    T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
-    T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
-    OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
-    OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
-    OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
-    OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
-    OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
-  }
-  return "<unknown op>";
-#undef OP
-#undef T
-}
-
-#endif
-
-#ifdef UPB_DUMP_BYTECODE
-
-static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
-
-  uint32_t *begin = p;
-
-  while (p < end) {
-    fprintf(f, "%p  %8tx", p, p - begin);
-    uint32_t instr = *p++;
-    uint8_t op = getop(instr);
-    fprintf(f, " %s", upb_pbdecoder_getopname(op));
-    switch ((opcode)op) {
-      case OP_SETDISPATCH: {
-        const upb_inttable *dispatch;
-        memcpy(&dispatch, p, sizeof(void*));
-        p += ptr_words;
-        const upb_pbdecodermethod *method =
-            (void *)((char *)dispatch -
-                     offsetof(upb_pbdecodermethod, dispatch));
-        fprintf(f, " %s", upb_msgdef_fullname(
-                              upb_handlers_msgdef(method->dest_handlers_)));
-        break;
-      }
-      case OP_DISPATCH:
-      case OP_STARTMSG:
-      case OP_ENDMSG:
-      case OP_PUSHLENDELIM:
-      case OP_POP:
-      case OP_SETDELIM:
-      case OP_HALT:
-      case OP_RET:
-        break;
-      case OP_PARSE_DOUBLE:
-      case OP_PARSE_FLOAT:
-      case OP_PARSE_INT64:
-      case OP_PARSE_UINT64:
-      case OP_PARSE_INT32:
-      case OP_PARSE_FIXED64:
-      case OP_PARSE_FIXED32:
-      case OP_PARSE_BOOL:
-      case OP_PARSE_UINT32:
-      case OP_PARSE_SFIXED32:
-      case OP_PARSE_SFIXED64:
-      case OP_PARSE_SINT32:
-      case OP_PARSE_SINT64:
-      case OP_STARTSEQ:
-      case OP_ENDSEQ:
-      case OP_STARTSUBMSG:
-      case OP_ENDSUBMSG:
-      case OP_STARTSTR:
-      case OP_STRING:
-      case OP_ENDSTR:
-      case OP_PUSHTAGDELIM:
-        fprintf(f, " %d", instr >> 8);
-        break;
-      case OP_SETBIGGROUPNUM:
-        fprintf(f, " %d", *p++);
-        break;
-      case OP_CHECKDELIM:
-      case OP_CALL:
-      case OP_BRANCH:
-        fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        break;
-      case OP_TAG1:
-      case OP_TAG2: {
-        fprintf(f, " tag:0x%x", instr >> 16);
-        if (getofs(instr)) {
-          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        }
-        break;
-      }
-      case OP_TAGN: {
-        uint64_t tag = *p++;
-        tag |= (uint64_t)*p++ << 32;
-        fprintf(f, " tag:0x%llx", (long long)tag);
-        fprintf(f, " n:%d", instr >> 16);
-        if (getofs(instr)) {
-          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        }
-        break;
-      }
-    }
-    fputs("\n", f);
-  }
-}
-
-#endif
-
-static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
-  uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
-  uint64_t encoded_tag = upb_vencode32(tag);
-  /* No tag should be greater than 5 bytes. */
-  UPB_ASSERT(encoded_tag <= 0xffffffffff);
-  return encoded_tag;
-}
-
-static void putchecktag(compiler *c, const upb_fielddef *f,
-                        int wire_type, int dest) {
-  uint64_t tag = get_encoded_tag(f, wire_type);
-  switch (upb_value_size(tag)) {
-    case 1:
-      putop(c, OP_TAG1, dest, tag);
-      break;
-    case 2:
-      putop(c, OP_TAG2, dest, tag);
-      break;
-    default:
-      putop(c, OP_TAGN, dest, tag);
-      break;
-  }
-}
-
-static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
-  upb_selector_t selector;
-  bool ok = upb_handlers_getselector(f, type, &selector);
-  UPB_ASSERT(ok);
-  return selector;
-}
-
-/* Takes an existing, primary dispatch table entry and repacks it with a
- * different alternate wire type.  Called when we are inserting a secondary
- * dispatch table entry for an alternate wire type. */
-static uint64_t repack(uint64_t dispatch, int new_wt2) {
-  uint64_t ofs;
-  uint8_t wt1;
-  uint8_t old_wt2;
-  upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
-  UPB_ASSERT(old_wt2 == NO_WIRE_TYPE);  /* wt2 should not be set yet. */
-  return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
-}
-
-/* Marks the current bytecode position as the dispatch target for this message,
- * field, and wire type. */
-static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
-                           const upb_fielddef *f, int wire_type) {
-  /* Offset is relative to msg base. */
-  uint64_t ofs = pcofs(c) - method->code_base.ofs;
-  uint32_t fn = upb_fielddef_number(f);
-  upb_inttable *d = &method->dispatch;
-  upb_value v;
-  if (upb_inttable_remove(d, fn, &v)) {
-    /* TODO: prioritize based on packed setting in .proto file. */
-    uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
-    upb_inttable_insert(d, fn, upb_value_uint64(repacked));
-    upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
-  } else {
-    uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
-    upb_inttable_insert(d, fn, upb_value_uint64(val));
-  }
-}
-
-static void putpush(compiler *c, const upb_fielddef *f) {
-  if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
-    putop(c, OP_PUSHLENDELIM);
-  } else {
-    uint32_t fn = upb_fielddef_number(f);
-    if (fn >= 1 << 24) {
-      putop(c, OP_PUSHTAGDELIM, 0);
-      putop(c, OP_SETBIGGROUPNUM, fn);
-    } else {
-      putop(c, OP_PUSHTAGDELIM, fn);
-    }
-  }
-}
-
-static upb_pbdecodermethod *find_submethod(const compiler *c,
-                                           const upb_pbdecodermethod *method,
-                                           const upb_fielddef *f) {
-  const upb_handlers *sub =
-      upb_handlers_getsubhandlers(method->dest_handlers_, f);
-  upb_value v;
-  return upb_inttable_lookupptr(&c->group->methods, sub, &v)
-             ? upb_value_getptr(v)
-             : NULL;
-}
-
-static void putsel(compiler *c, opcode op, upb_selector_t sel,
-                   const upb_handlers *h) {
-  if (upb_handlers_gethandler(h, sel, NULL)) {
-    putop(c, op, sel);
-  }
-}
-
-/* Puts an opcode to call a callback, but only if a callback actually exists for
- * this field and handler type. */
-static void maybeput(compiler *c, opcode op, const upb_handlers *h,
-                     const upb_fielddef *f, upb_handlertype_t type) {
-  putsel(c, op, getsel(f, type), h);
-}
-
-static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
-  if (!upb_fielddef_lazy(f))
-    return false;
-
-  return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR), NULL) ||
-         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING), NULL) ||
-         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR), NULL);
-}
-
-
-/* bytecode compiler code generation ******************************************/
-
-/* Symbolic names for our local labels. */
-#define LABEL_LOOPSTART 1  /* Top of a repeated field loop. */
-#define LABEL_LOOPBREAK 2  /* To jump out of a repeated loop */
-#define LABEL_FIELD     3  /* Jump backward to find the most recent field. */
-#define LABEL_ENDMSG    4  /* To reach the OP_ENDMSG instr for this msg. */
-
-/* Generates bytecode to parse a single non-lazy message field. */
-static void generate_msgfield(compiler *c, const upb_fielddef *f,
-                              upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-  const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
-  int wire_type;
-
-  if (!sub_m) {
-    /* Don't emit any code for this field at all; it will be parsed as an
-     * unknown field.
-     *
-     * TODO(haberman): we should change this to parse it as a string field
-     * instead.  It will probably be faster, but more importantly, once we
-     * start vending unknown fields, a field shouldn't be treated as unknown
-     * just because it doesn't have subhandlers registered. */
-    return;
-  }
-
-  label(c, LABEL_FIELD);
-
-  wire_type =
-      (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
-          ? UPB_WIRE_TYPE_DELIMITED
-          : UPB_WIRE_TYPE_START_GROUP;
-
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
-   label(c, LABEL_LOOPSTART);
-    putpush(c, f);
-    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
-    putop(c, OP_CALL, sub_m);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
-    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
-      putop(c, OP_SETDELIM);
-    }
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putpush(c, f);
-    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
-    putop(c, OP_CALL, sub_m);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
-    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
-      putop(c, OP_SETDELIM);
-    }
-  }
-}
-
-/* Generates bytecode to parse a single string or lazy submessage field. */
-static void generate_delimfield(compiler *c, const upb_fielddef *f,
-                                upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-
-  label(c, LABEL_FIELD);
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
-   label(c, LABEL_LOOPSTART);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
-    /* Need to emit even if no handler to skip past the string. */
-    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
-    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
-    putop(c, OP_POP);
-    putop(c, OP_SETDELIM);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
-    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
-    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
-    putop(c, OP_POP);
-    putop(c, OP_SETDELIM);
-  }
-}
-
-/* Generates bytecode to parse a single primitive field. */
-static void generate_primitivefield(compiler *c, const upb_fielddef *f,
-                                    upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-  upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
-  opcode parse_type;
-  upb_selector_t sel;
-  int wire_type;
-
-  label(c, LABEL_FIELD);
-
-  /* From a decoding perspective, ENUM is the same as INT32. */
-  if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
-    descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
-
-  parse_type = (opcode)descriptor_type;
-
-  /* TODO(haberman): generate packed or non-packed first depending on "packed"
-   * setting in the fielddef.  This will favor (in speed) whichever was
-   * specified. */
-
-  UPB_ASSERT((int)parse_type >= 0 && parse_type <= OP_MAX);
-  sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Packed */
-   label(c, LABEL_LOOPSTART);
-    putop(c, parse_type, sel);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Non-packed */
-   label(c, LABEL_LOOPSTART);
-    putop(c, parse_type, sel);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);  /* Packed and non-packed join. */
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-    putop(c, OP_SETDELIM);  /* Could remove for non-packed by dup ENDSEQ. */
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, parse_type, sel);
-  }
-}
-
-/* Adds bytecode for parsing the given message to the given decoderplan,
- * while adding all dispatch targets to this message's dispatch table. */
-static void compile_method(compiler *c, upb_pbdecodermethod *method) {
-  const upb_handlers *h;
-  const upb_msgdef *md;
-  uint32_t* start_pc;
-  upb_msg_field_iter i;
-  upb_value val;
-
-  UPB_ASSERT(method);
-
-  /* Clear all entries in the dispatch table. */
-  upb_inttable_uninit(&method->dispatch);
-  upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
-
-  h = upb_pbdecodermethod_desthandlers(method);
-  md = upb_handlers_msgdef(h);
-
- method->code_base.ofs = pcofs(c);
-  putop(c, OP_SETDISPATCH, &method->dispatch);
-  putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
- label(c, LABEL_FIELD);
-  start_pc = c->pc;
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_fieldtype_t type = upb_fielddef_type(f);
-
-    if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
-      generate_msgfield(c, f, method);
-    } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
-               type == UPB_TYPE_MESSAGE) {
-      generate_delimfield(c, f, method);
-    } else {
-      generate_primitivefield(c, f, method);
-    }
-  }
-
-  /* If there were no fields, or if no handlers were defined, we need to
-   * generate a non-empty loop body so that we can at least dispatch for unknown
-   * fields and check for the end of the message. */
-  if (c->pc == start_pc) {
-    /* Check for end-of-message. */
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    /* Unconditionally dispatch. */
-    putop(c, OP_DISPATCH, 0);
-  }
-
-  /* For now we just loop back to the last field of the message (or if none,
-   * the DISPATCH opcode for the message). */
-  putop(c, OP_BRANCH, -LABEL_FIELD);
-
-  /* Insert both a label and a dispatch table entry for this end-of-msg. */
- label(c, LABEL_ENDMSG);
-  val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
-  upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
-
-  putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
-  putop(c, OP_RET);
-
-  upb_inttable_compact(&method->dispatch);
-}
-
-/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
- * Returns the method for these handlers.
- *
- * Generates a new method for every destination handlers reachable from "h". */
-static void find_methods(compiler *c, const upb_handlers *h) {
-  upb_value v;
-  upb_msg_field_iter i;
-  const upb_msgdef *md;
-  upb_pbdecodermethod *method;
-
-  if (upb_inttable_lookupptr(&c->group->methods, h, &v))
-    return;
-
-  method = newmethod(h, c->group);
-  upb_inttable_insertptr(&c->group->methods, h, upb_value_ptr(method));
-
-  /* Find submethods. */
-  md = upb_handlers_msgdef(h);
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    const upb_handlers *sub_h;
-    if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
-        (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
-      /* We only generate a decoder method for submessages with handlers.
-       * Others will be parsed as unknown fields. */
-      find_methods(c, sub_h);
-    }
-  }
-}
-
-/* (Re-)compile bytecode for all messages in "msgs."
- * Overwrites any existing bytecode in "c". */
-static void compile_methods(compiler *c) {
-  upb_inttable_iter i;
-
-  /* Start over at the beginning of the bytecode. */
-  c->pc = c->group->bytecode;
-
-  upb_inttable_begin(&i, &c->group->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
-    compile_method(c, method);
-  }
-}
-
-static void set_bytecode_handlers(mgroup *g) {
-  upb_inttable_iter i;
-  upb_inttable_begin(&i, &g->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
-    upb_byteshandler *h = &m->input_handler_;
-
-    m->code_base.ptr = g->bytecode + m->code_base.ofs;
-
-    upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
-    upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
-    upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
-  }
-}
-
-
-/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
- * handlers and other mgroups (but verify we have a transitive closure). */
-const mgroup *mgroup_new(const upb_handlers *dest, bool lazy) {
-  mgroup *g;
-  compiler *c;
-
-  g = newgroup();
-  c = newcompiler(g, lazy);
-  find_methods(c, dest);
-
-  /* We compile in two passes:
-   * 1. all messages are assigned relative offsets from the beginning of the
-   *    bytecode (saved in method->code_base).
-   * 2. forwards OP_CALL instructions can be correctly linked since message
-   *    offsets have been previously assigned.
-   *
-   * Could avoid the second pass by linking OP_CALL instructions somehow. */
-  compile_methods(c);
-  compile_methods(c);
-  g->bytecode_end = c->pc;
-  freecompiler(c);
-
-#ifdef UPB_DUMP_BYTECODE
-  {
-    FILE *f = fopen("/tmp/upb-bytecode", "w");
-    UPB_ASSERT(f);
-    dumpbc(g->bytecode, g->bytecode_end, stderr);
-    dumpbc(g->bytecode, g->bytecode_end, f);
-    fclose(f);
-
-    f = fopen("/tmp/upb-bytecode.bin", "wb");
-    UPB_ASSERT(f);
-    fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
-    fclose(f);
-  }
-#endif
-
-  set_bytecode_handlers(g);
-  return g;
-}
-
-
-/* upb_pbcodecache ************************************************************/
-
-upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest) {
-  upb_pbcodecache *c = upb_gmalloc(sizeof(*c));
-
-  if (!c) return NULL;
-
-  c->dest = dest;
-  c->lazy = false;
-
-  c->arena = upb_arena_new();
-  if (!upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR)) return NULL;
-
-  return c;
-}
-
-void upb_pbcodecache_free(upb_pbcodecache *c) {
-  upb_inttable_iter i;
-
-  upb_inttable_begin(&i, &c->groups);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_value val = upb_inttable_iter_value(&i);
-    freegroup((void*)upb_value_getconstptr(val));
-  }
-
-  upb_inttable_uninit(&c->groups);
-  upb_arena_free(c->arena);
-  upb_gfree(c);
-}
-
-void upb_pbdecodermethodopts_setlazy(upb_pbcodecache *c, bool lazy) {
-  UPB_ASSERT(upb_inttable_count(&c->groups) == 0);
-  c->lazy = lazy;
-}
-
-const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
-                                               const upb_msgdef *md) {
-  upb_value v;
-  bool ok;
-  const upb_handlers *h;
-  const mgroup *g;
-
-  h = upb_handlercache_get(c->dest, md);
-  if (upb_inttable_lookupptr(&c->groups, md, &v)) {
-    g = upb_value_getconstptr(v);
-  } else {
-    g = mgroup_new(h, c->lazy);
-    ok = upb_inttable_insertptr(&c->groups, md, upb_value_constptr(g));
-    UPB_ASSUME(ok);
-  }
-
-  ok = upb_inttable_lookupptr(&g->methods, h, &v);
-  UPB_ASSUME(ok);
-  return upb_value_getptr(v);
-}
-/*
-** upb::Decoder (Bytecode Decoder VM)
-**
-** Bytecode must previously have been generated using the bytecode compiler in
-** compile_decoder.c.  This decoder then walks through the bytecode op-by-op to
-** parse the input.
-**
-** Decoding is fully resumable; we just keep a pointer to the current bytecode
-** instruction and resume from there.  A fair amount of the logic here is to
-** handle the fact that values can span buffer seams and we have to be able to
-** be capable of suspending/resuming from any byte in the stream.  This
-** sometimes requires keeping a few trailing bytes from the last buffer around
-** in the "residual" buffer.
-*/
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#ifdef UPB_DUMP_BYTECODE
-#include <stdio.h>
-#endif
-
-
-#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
-
-/* Error messages that are shared between the bytecode and JIT decoders. */
-const char *kPbDecoderStackOverflow = "Nesting too deep.";
-const char *kPbDecoderSubmessageTooLong =
-    "Submessage end extends past enclosing submessage.";
-
-/* Error messages shared within this file. */
-static const char *kUnterminatedVarint = "Unterminated varint.";
-
-/* upb_pbdecoder **************************************************************/
-
-static opcode halt = OP_HALT;
-
-/* A dummy character we can point to when the user passes us a NULL buffer.
- * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
- * behavior, which would invalidate functions like curbufleft(). */
-static const char dummy_char;
-
-/* Whether an op consumes any of the input buffer. */
-static bool consumes_input(opcode op) {
-  switch (op) {
-    case OP_SETDISPATCH:
-    case OP_STARTMSG:
-    case OP_ENDMSG:
-    case OP_STARTSEQ:
-    case OP_ENDSEQ:
-    case OP_STARTSUBMSG:
-    case OP_ENDSUBMSG:
-    case OP_STARTSTR:
-    case OP_ENDSTR:
-    case OP_PUSHTAGDELIM:
-    case OP_POP:
-    case OP_SETDELIM:
-    case OP_SETBIGGROUPNUM:
-    case OP_CHECKDELIM:
-    case OP_CALL:
-    case OP_RET:
-    case OP_BRANCH:
-      return false;
-    default:
-      return true;
-  }
-}
-
-static size_t stacksize(upb_pbdecoder *d, size_t entries) {
-  UPB_UNUSED(d);
-  return entries * sizeof(upb_pbdecoder_frame);
-}
-
-static size_t callstacksize(upb_pbdecoder *d, size_t entries) {
-  UPB_UNUSED(d);
-
-  return entries * sizeof(uint32_t*);
-}
-
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
-
-/* It's unfortunate that we have to micro-manage the compiler with
- * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
- * specific to one hardware configuration.  But empirically on a Core i7,
- * performance increases 30-50% with these annotations.  Every instance where
- * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
- * benchmarks. */
-
-static void seterr(upb_pbdecoder *d, const char *msg) {
-  upb_status_seterrmsg(d->status, msg);
-}
-
-void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
-  seterr(d, msg);
-}
-
-
-/* Buffering ******************************************************************/
-
-/* We operate on one buffer at a time, which is either the user's buffer passed
- * to our "decode" callback or some residual bytes from the previous buffer. */
-
-/* How many bytes can be safely read from d->ptr without reading past end-of-buf
- * or past the current delimited end. */
-static size_t curbufleft(const upb_pbdecoder *d) {
-  UPB_ASSERT(d->data_end >= d->ptr);
-  return d->data_end - d->ptr;
-}
-
-/* How many bytes are available before end-of-buffer. */
-static size_t bufleft(const upb_pbdecoder *d) {
-  return d->end - d->ptr;
-}
-
-/* Overall stream offset of d->ptr. */
-uint64_t offset(const upb_pbdecoder *d) {
-  return d->bufstart_ofs + (d->ptr - d->buf);
-}
-
-/* How many bytes are available before the end of this delimited region. */
-size_t delim_remaining(const upb_pbdecoder *d) {
-  return d->top->end_ofs - offset(d);
-}
-
-/* Advances d->ptr. */
-static void advance(upb_pbdecoder *d, size_t len) {
-  UPB_ASSERT(curbufleft(d) >= len);
-  d->ptr += len;
-}
-
-static bool in_buf(const char *p, const char *buf, const char *end) {
-  return p >= buf && p <= end;
-}
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
-  return in_buf(p, d->residual, d->residual_end);
-}
-
-/* Calculates the delim_end value, which is affected by both the current buffer
- * and the parsing stack, so must be called whenever either is updated. */
-static void set_delim_end(upb_pbdecoder *d) {
-  size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
-  if (delim_ofs <= (size_t)(d->end - d->buf)) {
-    d->delim_end = d->buf + delim_ofs;
-    d->data_end = d->delim_end;
-  } else {
-    d->data_end = d->end;
-    d->delim_end = NULL;
-  }
-}
-
-static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
-  d->ptr = buf;
-  d->buf = buf;
-  d->end = end;
-  set_delim_end(d);
-}
-
-static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
-  UPB_ASSERT(curbufleft(d) == 0);
-  d->bufstart_ofs += (d->end - d->buf);
-  switchtobuf(d, buf, buf + len);
-}
-
-static void checkpoint(upb_pbdecoder *d) {
-  /* The assertion here is in the interests of efficiency, not correctness.
-   * We are trying to ensure that we don't checkpoint() more often than
-   * necessary. */
-  UPB_ASSERT(d->checkpoint != d->ptr);
-  d->checkpoint = d->ptr;
-}
-
-/* Skips "bytes" bytes in the stream, which may be more than available.  If we
- * skip more bytes than are available, we return a long read count to the caller
- * indicating how many bytes can be skipped over before passing actual data
- * again.  Skipped bytes can pass a NULL buffer and the decoder guarantees they
- * won't actually be read.
- */
-static int32_t skip(upb_pbdecoder *d, size_t bytes) {
-  UPB_ASSERT(!in_residual_buf(d, d->ptr) || d->size_param == 0);
-  UPB_ASSERT(d->skip == 0);
-  if (bytes > delim_remaining(d)) {
-    seterr(d, "Skipped value extended beyond enclosing submessage.");
-    return (int32_t)upb_pbdecoder_suspend(d);
-  } else if (bufleft(d) >= bytes) {
-    /* Skipped data is all in current buffer, and more is still available. */
-    advance(d, bytes);
-    d->skip = 0;
-    return DECODE_OK;
-  } else {
-    /* Skipped data extends beyond currently available buffers. */
-    d->pc = d->last;
-    d->skip = bytes - curbufleft(d);
-    d->bufstart_ofs += (d->end - d->buf);
-    d->residual_end = d->residual;
-    switchtobuf(d, d->residual, d->residual_end);
-    return (int32_t)(d->size_param + d->skip);
-  }
-}
-
-
-/* Resumes the decoder from an initial state or from a previous suspend. */
-int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
-                             size_t size, const upb_bufhandle *handle) {
-  UPB_UNUSED(p);  /* Useless; just for the benefit of the JIT. */
-
-  /* d->skip and d->residual_end could probably elegantly be represented
-   * as a single variable, to more easily represent this invariant. */
-  UPB_ASSERT(!(d->skip && d->residual_end > d->residual));
-
-  /* We need to remember the original size_param, so that the value we return
-   * is relative to it, even if we do some skipping first. */
-  d->size_param = size;
-  d->handle = handle;
-
-  /* Have to handle this case specially (ie. not with skip()) because the user
-   * is allowed to pass a NULL buffer here, which won't allow us to safely
-   * calculate a d->end or use our normal functions like curbufleft(). */
-  if (d->skip && d->skip >= size) {
-    d->skip -= size;
-    d->bufstart_ofs += size;
-    buf = &dummy_char;
-    size = 0;
-
-    /* We can't just return now, because we might need to execute some ops
-     * like CHECKDELIM, which could call some callbacks and pop the stack. */
-  }
-
-  /* We need to pretend that this was the actual buffer param, since some of the
-   * calculations assume that d->ptr/d->buf is relative to this. */
-  d->buf_param = buf;
-
-  if (!buf) {
-    /* NULL buf is ok if its entire span is covered by the "skip" above, but
-     * by this point we know that "skip" doesn't cover the buffer. */
-    seterr(d, "Passed NULL buffer over non-skippable region.");
-    return (int32_t)upb_pbdecoder_suspend(d);
-  }
-
-  if (d->residual_end > d->residual) {
-    /* We have residual bytes from the last buffer. */
-    UPB_ASSERT(d->ptr == d->residual);
-  } else {
-    switchtobuf(d, buf, buf + size);
-  }
-
-  d->checkpoint = d->ptr;
-
-  /* Handle skips that don't cover the whole buffer (as above). */
-  if (d->skip) {
-    size_t skip_bytes = d->skip;
-    d->skip = 0;
-    CHECK_RETURN(skip(d, skip_bytes));
-    checkpoint(d);
-  }
-
-  /* If we're inside an unknown group, continue to parse unknown values. */
-  if (d->top->groupnum < 0) {
-    CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
-    checkpoint(d);
-  }
-
-  return DECODE_OK;
-}
-
-/* Suspends the decoder at the last checkpoint, without saving any residual
- * bytes.  If there are any unconsumed bytes, returns a short byte count. */
-size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
-  d->pc = d->last;
-  if (d->checkpoint == d->residual) {
-    /* Checkpoint was in residual buf; no user bytes were consumed. */
-    d->ptr = d->residual;
-    return 0;
-  } else {
-    size_t ret = d->size_param - (d->end - d->checkpoint);
-    UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
-    UPB_ASSERT(d->buf == d->buf_param || d->buf == &dummy_char);
-
-    d->bufstart_ofs += (d->checkpoint - d->buf);
-    d->residual_end = d->residual;
-    switchtobuf(d, d->residual, d->residual_end);
-    return ret;
-  }
-}
-
-/* Suspends the decoder at the last checkpoint, and saves any unconsumed
- * bytes in our residual buffer.  This is necessary if we need more user
- * bytes to form a complete value, which might not be contiguous in the
- * user's buffers.  Always consumes all user bytes. */
-static size_t suspend_save(upb_pbdecoder *d) {
-  /* We hit end-of-buffer before we could parse a full value.
-   * Save any unconsumed bytes (if any) to the residual buffer. */
-  d->pc = d->last;
-
-  if (d->checkpoint == d->residual) {
-    /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
-    UPB_ASSERT((d->residual_end - d->residual) + d->size_param <=
-           sizeof(d->residual));
-    if (!in_residual_buf(d, d->ptr)) {
-      d->bufstart_ofs -= (d->residual_end - d->residual);
-    }
-    memcpy(d->residual_end, d->buf_param, d->size_param);
-    d->residual_end += d->size_param;
-  } else {
-    /* Checkpoint was in user buf; old residual bytes not needed. */
-    size_t save;
-    UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
-
-    d->ptr = d->checkpoint;
-    save = curbufleft(d);
-    UPB_ASSERT(save <= sizeof(d->residual));
-    memcpy(d->residual, d->ptr, save);
-    d->residual_end = d->residual + save;
-    d->bufstart_ofs = offset(d);
-  }
-
-  switchtobuf(d, d->residual, d->residual_end);
-  return d->size_param;
-}
-
-/* Copies the next "bytes" bytes into "buf" and advances the stream.
- * Requires that this many bytes are available in the current buffer. */
-UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
-                                         size_t bytes) {
-  UPB_ASSERT(bytes <= curbufleft(d));
-  memcpy(buf, d->ptr, bytes);
-  advance(d, bytes);
-}
-
-/* Slow path for getting the next "bytes" bytes, regardless of whether they are
- * available in the current buffer or not.  Returns a status code as described
- * in decoder.int.h. */
-UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
-                                          size_t bytes) {
-  const size_t avail = curbufleft(d);
-  consumebytes(d, buf, avail);
-  bytes -= avail;
-  UPB_ASSERT(bytes > 0);
-  if (in_residual_buf(d, d->ptr)) {
-    advancetobuf(d, d->buf_param, d->size_param);
-  }
-  if (curbufleft(d) >= bytes) {
-    consumebytes(d, (char *)buf + avail, bytes);
-    return DECODE_OK;
-  } else if (d->data_end == d->delim_end) {
-    seterr(d, "Submessage ended in the middle of a value or group");
-    return (int32_t)upb_pbdecoder_suspend(d);
-  } else {
-    return (int32_t)suspend_save(d);
-  }
-}
-
-/* Gets the next "bytes" bytes, regardless of whether they are available in the
- * current buffer or not.  Returns a status code as described in decoder.int.h.
- */
-UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
-                                        size_t bytes) {
-  if (curbufleft(d) >= bytes) {
-    /* Buffer has enough data to satisfy. */
-    consumebytes(d, buf, bytes);
-    return DECODE_OK;
-  } else {
-    return getbytes_slow(d, buf, bytes);
-  }
-}
-
-UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
-                                          size_t bytes) {
-  size_t ret = curbufleft(d);
-  memcpy(buf, d->ptr, ret);
-  if (in_residual_buf(d, d->ptr)) {
-    size_t copy = UPB_MIN(bytes - ret, d->size_param);
-    memcpy((char *)buf + ret, d->buf_param, copy);
-    ret += copy;
-  }
-  return ret;
-}
-
-UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
-                                        size_t bytes) {
-  if (curbufleft(d) >= bytes) {
-    memcpy(buf, d->ptr, bytes);
-    return bytes;
-  } else {
-    return peekbytes_slow(d, buf, bytes);
-  }
-}
-
-
-/* Decoding of wire types *****************************************************/
-
-/* Slow path for decoding a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
-                                                      uint64_t *u64) {
-  uint8_t byte = 0x80;
-  int bitpos;
-  *u64 = 0;
-  for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
-    CHECK_RETURN(getbytes(d, &byte, 1));
-    *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
-  }
-  if(bitpos == 70 && (byte & 0x80)) {
-    seterr(d, kUnterminatedVarint);
-    return (int32_t)upb_pbdecoder_suspend(d);
-  }
-  return DECODE_OK;
-}
-
-/* Decodes a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
-  if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
-    *u64 = *d->ptr;
-    advance(d, 1);
-    return DECODE_OK;
-  } else if (curbufleft(d) >= 10) {
-    /* Fast case. */
-    upb_decoderet r = upb_vdecode_fast(d->ptr);
-    if (r.p == NULL) {
-      seterr(d, kUnterminatedVarint);
-      return (int32_t)upb_pbdecoder_suspend(d);
-    }
-    advance(d, r.p - d->ptr);
-    *u64 = r.val;
-    return DECODE_OK;
-  } else {
-    /* Slow case -- varint spans buffer seam. */
-    return upb_pbdecoder_decode_varint_slow(d, u64);
-  }
-}
-
-/* Decodes a 32-bit varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
-  uint64_t u64;
-  int32_t ret = decode_varint(d, &u64);
-  if (ret >= 0) return ret;
-  if (u64 > UINT32_MAX) {
-    seterr(d, "Unterminated 32-bit varint");
-    /* TODO(haberman) guarantee that this function return is >= 0 somehow,
-     * so we know this path will always be treated as error by our caller.
-     * Right now the size_t -> int32_t can overflow and produce negative values.
-     */
-    *u32 = 0;
-    return (int32_t)upb_pbdecoder_suspend(d);
-  }
-  *u32 = (uint32_t)u64;
-  return DECODE_OK;
-}
-
-/* Decodes a fixed32 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
-  return getbytes(d, u32, 4);
-}
-
-/* Decodes a fixed64 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
-  return getbytes(d, u64, 8);
-}
-
-/* Non-static versions of the above functions.
- * These are called by the JIT for fallback paths. */
-int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
-  return decode_fixed32(d, u32);
-}
-
-int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
-  return decode_fixed64(d, u64);
-}
-
-static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
-static float  as_float(uint32_t n)  { float  f; memcpy(&f, &n, 4); return f; }
-
-/* Pushes a frame onto the decoder stack. */
-static bool decoder_push(upb_pbdecoder *d, uint64_t end) {
-  upb_pbdecoder_frame *fr = d->top;
-
-  if (end > fr->end_ofs) {
-    seterr(d, kPbDecoderSubmessageTooLong);
-    return false;
-  } else if (fr == d->limit) {
-    seterr(d, kPbDecoderStackOverflow);
-    return false;
-  }
-
-  fr++;
-  fr->end_ofs = end;
-  fr->dispatch = NULL;
-  fr->groupnum = 0;
-  d->top = fr;
-  return true;
-}
-
-static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
-  /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
-   * field number) prior to hitting any enclosing submessage end, pushing our
-   * existing delim end prevents us from continuing to parse values from a
-   * corrupt proto that doesn't give us an END tag in time. */
-  if (!decoder_push(d, d->top->end_ofs))
-    return false;
-  d->top->groupnum = arg;
-  return true;
-}
-
-/* Pops a frame from the decoder stack. */
-static void decoder_pop(upb_pbdecoder *d) { d->top--; }
-
-UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
-                                                 uint64_t expected) {
-  uint64_t data = 0;
-  size_t bytes = upb_value_size(expected);
-  size_t read = peekbytes(d, &data, bytes);
-  if (read == bytes && data == expected) {
-    /* Advance past matched bytes. */
-    int32_t ok = getbytes(d, &data, read);
-    UPB_ASSERT(ok < 0);
-    return DECODE_OK;
-  } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
-    return (int32_t)suspend_save(d);
-  } else {
-    return DECODE_MISMATCH;
-  }
-}
-
-int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
-                                  uint8_t wire_type) {
-  if (fieldnum >= 0)
-    goto have_tag;
-
-  while (true) {
-    uint32_t tag;
-    CHECK_RETURN(decode_v32(d, &tag));
-    wire_type = tag & 0x7;
-    fieldnum = tag >> 3;
-
-have_tag:
-    if (fieldnum == 0) {
-      seterr(d, "Saw invalid field number (0)");
-      return (int32_t)upb_pbdecoder_suspend(d);
-    }
-
-    switch (wire_type) {
-      case UPB_WIRE_TYPE_32BIT:
-        CHECK_RETURN(skip(d, 4));
-        break;
-      case UPB_WIRE_TYPE_64BIT:
-        CHECK_RETURN(skip(d, 8));
-        break;
-      case UPB_WIRE_TYPE_VARINT: {
-        uint64_t u64;
-        CHECK_RETURN(decode_varint(d, &u64));
-        break;
-      }
-      case UPB_WIRE_TYPE_DELIMITED: {
-        uint32_t len;
-        CHECK_RETURN(decode_v32(d, &len));
-        CHECK_RETURN(skip(d, len));
-        break;
-      }
-      case UPB_WIRE_TYPE_START_GROUP:
-        if (!pushtagdelim(d, -fieldnum)) {
-          return (int32_t)upb_pbdecoder_suspend(d);
-        }
-        break;
-      case UPB_WIRE_TYPE_END_GROUP:
-        if (fieldnum == -d->top->groupnum) {
-          decoder_pop(d);
-        } else if (fieldnum == d->top->groupnum) {
-          return DECODE_ENDGROUP;
-        } else {
-          seterr(d, "Unmatched ENDGROUP tag.");
-          return (int32_t)upb_pbdecoder_suspend(d);
-        }
-        break;
-      default:
-        seterr(d, "Invalid wire type");
-        return (int32_t)upb_pbdecoder_suspend(d);
-    }
-
-    if (d->top->groupnum >= 0) {
-      /* TODO: More code needed for handling unknown groups. */
-      upb_sink_putunknown(d->top->sink, d->checkpoint, d->ptr - d->checkpoint);
-      return DECODE_OK;
-    }
-
-    /* Unknown group -- continue looping over unknown fields. */
-    checkpoint(d);
-  }
-}
-
-static void goto_endmsg(upb_pbdecoder *d) {
-  upb_value v;
-  bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
-  UPB_ASSERT(found);
-  d->pc = d->top->base + upb_value_getuint64(v);
-}
-
-/* Parses a tag and jumps to the corresponding bytecode instruction for this
- * field.
- *
- * If the tag is unknown (or the wire type doesn't match), parses the field as
- * unknown.  If the tag is a valid ENDGROUP tag, jumps to the bytecode
- * instruction for the end of message. */
-static int32_t dispatch(upb_pbdecoder *d) {
-  upb_inttable *dispatch = d->top->dispatch;
-  uint32_t tag;
-  uint8_t wire_type;
-  uint32_t fieldnum;
-  upb_value val;
-  int32_t retval;
-
-  /* Decode tag. */
-  CHECK_RETURN(decode_v32(d, &tag));
-  wire_type = tag & 0x7;
-  fieldnum = tag >> 3;
-
-  /* Lookup tag.  Because of packed/non-packed compatibility, we have to
-   * check the wire type against two possibilities. */
-  if (fieldnum != DISPATCH_ENDMSG &&
-      upb_inttable_lookup32(dispatch, fieldnum, &val)) {
-    uint64_t v = upb_value_getuint64(val);
-    if (wire_type == (v & 0xff)) {
-      d->pc = d->top->base + (v >> 16);
-      return DECODE_OK;
-    } else if (wire_type == ((v >> 8) & 0xff)) {
-      bool found =
-          upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
-      UPB_ASSERT(found);
-      d->pc = d->top->base + upb_value_getuint64(val);
-      return DECODE_OK;
-    }
-  }
-
-  /* We have some unknown fields (or ENDGROUP) to parse.  The DISPATCH or TAG
-   * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
-   * we need to back up to, so that when we're done skipping unknown data we
-   * can re-check the delimited end. */
-  d->last--;  /* Necessary if we get suspended */
-  d->pc = d->last;
-  UPB_ASSERT(getop(*d->last) == OP_CHECKDELIM);
-
-  /* Unknown field or ENDGROUP. */
-  retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
-
-  CHECK_RETURN(retval);
-
-  if (retval == DECODE_ENDGROUP) {
-    goto_endmsg(d);
-    return DECODE_OK;
-  }
-
-  return DECODE_OK;
-}
-
-/* Callers know that the stack is more than one deep because the opcodes that
- * call this only occur after PUSH operations. */
-upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
-  UPB_ASSERT(d->top != d->stack);
-  return d->top - 1;
-}
-
-
-/* The main decoding loop *****************************************************/
-
-/* The main decoder VM function.  Uses traditional bytecode dispatch loop with a
- * switch() statement. */
-size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
-                      const upb_bufhandle* handle) {
-
-#define VMCASE(op, code) \
-  case op: { code; if (consumes_input(op)) checkpoint(d); break; }
-#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
-  VMCASE(OP_PARSE_ ## type, { \
-    ctype val; \
-    CHECK_RETURN(decode_ ## wt(d, &val)); \
-    upb_sink_put ## name(d->top->sink, arg, (convfunc)(val)); \
-  })
-
-  while(1) {
-    int32_t instruction;
-    opcode op;
-    uint32_t arg;
-    int32_t longofs;
-
-    d->last = d->pc;
-    instruction = *d->pc++;
-    op = getop(instruction);
-    arg = instruction >> 8;
-    longofs = arg;
-    UPB_ASSERT(d->ptr != d->residual_end);
-    UPB_UNUSED(group);
-#ifdef UPB_DUMP_BYTECODE
-    fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
-                    "%x %s (%d)\n",
-            (int)offset(d),
-            (int)(d->ptr - d->buf),
-            (int)(d->data_end - d->ptr),
-            (int)(d->end - d->ptr),
-            (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
-            (int)(d->pc - 1 - group->bytecode),
-            upb_pbdecoder_getopname(op),
-            arg);
-#endif
-    switch (op) {
-      /* Technically, we are losing data if we see a 32-bit varint that is not
-       * properly sign-extended.  We could detect this and error about the data
-       * loss, but proto2 does not do this, so we pass. */
-      PRIMITIVE_OP(INT32,    varint,  int32,  int32_t,      uint64_t)
-      PRIMITIVE_OP(INT64,    varint,  int64,  int64_t,      uint64_t)
-      PRIMITIVE_OP(UINT32,   varint,  uint32, uint32_t,     uint64_t)
-      PRIMITIVE_OP(UINT64,   varint,  uint64, uint64_t,     uint64_t)
-      PRIMITIVE_OP(FIXED32,  fixed32, uint32, uint32_t,     uint32_t)
-      PRIMITIVE_OP(FIXED64,  fixed64, uint64, uint64_t,     uint64_t)
-      PRIMITIVE_OP(SFIXED32, fixed32, int32,  int32_t,      uint32_t)
-      PRIMITIVE_OP(SFIXED64, fixed64, int64,  int64_t,      uint64_t)
-      PRIMITIVE_OP(BOOL,     varint,  bool,   bool,         uint64_t)
-      PRIMITIVE_OP(DOUBLE,   fixed64, double, as_double,    uint64_t)
-      PRIMITIVE_OP(FLOAT,    fixed32, float,  as_float,     uint32_t)
-      PRIMITIVE_OP(SINT32,   varint,  int32,  upb_zzdec_32, uint64_t)
-      PRIMITIVE_OP(SINT64,   varint,  int64,  upb_zzdec_64, uint64_t)
-
-      VMCASE(OP_SETDISPATCH,
-        d->top->base = d->pc - 1;
-        memcpy(&d->top->dispatch, d->pc, sizeof(void*));
-        d->pc += sizeof(void*) / sizeof(uint32_t);
-      )
-      VMCASE(OP_STARTMSG,
-        CHECK_SUSPEND(upb_sink_startmsg(d->top->sink));
-      )
-      VMCASE(OP_ENDMSG,
-        CHECK_SUSPEND(upb_sink_endmsg(d->top->sink, d->status));
-      )
-      VMCASE(OP_STARTSEQ,
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startseq(outer->sink, arg, &d->top->sink));
-      )
-      VMCASE(OP_ENDSEQ,
-        CHECK_SUSPEND(upb_sink_endseq(d->top->sink, arg));
-      )
-      VMCASE(OP_STARTSUBMSG,
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startsubmsg(outer->sink, arg, &d->top->sink));
-      )
-      VMCASE(OP_ENDSUBMSG,
-        upb_sink subsink = (d->top + 1)->sink;
-        CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, subsink, arg));
-      )
-      VMCASE(OP_STARTSTR,
-        uint32_t len = (uint32_t)delim_remaining(d);
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startstr(outer->sink, arg, len, &d->top->sink));
-        if (len == 0) {
-          d->pc++;  /* Skip OP_STRING. */
-        }
-      )
-      VMCASE(OP_STRING,
-        uint32_t len = (uint32_t)curbufleft(d);
-        size_t n = upb_sink_putstring(d->top->sink, arg, d->ptr, len, handle);
-        if (n > len) {
-          if (n > delim_remaining(d)) {
-            seterr(d, "Tried to skip past end of string.");
-            return upb_pbdecoder_suspend(d);
-          } else {
-            int32_t ret = skip(d, n);
-            /* This shouldn't return DECODE_OK, because n > len. */
-            UPB_ASSERT(ret >= 0);
-            return ret;
-          }
-        }
-        advance(d, n);
-        if (n < len || d->delim_end == NULL) {
-          /* We aren't finished with this string yet. */
-          d->pc--;  /* Repeat OP_STRING. */
-          if (n > 0) checkpoint(d);
-          return upb_pbdecoder_suspend(d);
-        }
-      )
-      VMCASE(OP_ENDSTR,
-        CHECK_SUSPEND(upb_sink_endstr(d->top->sink, arg));
-      )
-      VMCASE(OP_PUSHTAGDELIM,
-        CHECK_SUSPEND(pushtagdelim(d, arg));
-      )
-      VMCASE(OP_SETBIGGROUPNUM,
-        d->top->groupnum = *d->pc++;
-      )
-      VMCASE(OP_POP,
-        UPB_ASSERT(d->top > d->stack);
-        decoder_pop(d);
-      )
-      VMCASE(OP_PUSHLENDELIM,
-        uint32_t len;
-        CHECK_RETURN(decode_v32(d, &len));
-        CHECK_SUSPEND(decoder_push(d, offset(d) + len));
-        set_delim_end(d);
-      )
-      VMCASE(OP_SETDELIM,
-        set_delim_end(d);
-      )
-      VMCASE(OP_CHECKDELIM,
-        /* We are guaranteed of this assert because we never allow ourselves to
-         * consume bytes beyond data_end, which covers delim_end when non-NULL.
-         */
-        UPB_ASSERT(!(d->delim_end && d->ptr > d->delim_end));
-        if (d->ptr == d->delim_end)
-          d->pc += longofs;
-      )
-      VMCASE(OP_CALL,
-        d->callstack[d->call_len++] = d->pc;
-        d->pc += longofs;
-      )
-      VMCASE(OP_RET,
-        UPB_ASSERT(d->call_len > 0);
-        d->pc = d->callstack[--d->call_len];
-      )
-      VMCASE(OP_BRANCH,
-        d->pc += longofs;
-      )
-      VMCASE(OP_TAG1,
-        uint8_t expected;
-        CHECK_SUSPEND(curbufleft(d) > 0);
-        expected = (arg >> 8) & 0xff;
-        if (*d->ptr == expected) {
-          advance(d, 1);
-        } else {
-          int8_t shortofs;
-         badtag:
-          shortofs = arg;
-          if (shortofs == LABEL_DISPATCH) {
-            CHECK_RETURN(dispatch(d));
-          } else {
-            d->pc += shortofs;
-            break; /* Avoid checkpoint(). */
-          }
-        }
-      )
-      VMCASE(OP_TAG2,
-        uint16_t expected;
-        CHECK_SUSPEND(curbufleft(d) > 0);
-        expected = (arg >> 8) & 0xffff;
-        if (curbufleft(d) >= 2) {
-          uint16_t actual;
-          memcpy(&actual, d->ptr, 2);
-          if (expected == actual) {
-            advance(d, 2);
-          } else {
-            goto badtag;
-          }
-        } else {
-          int32_t result = upb_pbdecoder_checktag_slow(d, expected);
-          if (result == DECODE_MISMATCH) goto badtag;
-          if (result >= 0) return result;
-        }
-      )
-      VMCASE(OP_TAGN, {
-        uint64_t expected;
-        int32_t result;
-        memcpy(&expected, d->pc, 8);
-        d->pc += 2;
-        result = upb_pbdecoder_checktag_slow(d, expected);
-        if (result == DECODE_MISMATCH) goto badtag;
-        if (result >= 0) return result;
-      })
-      VMCASE(OP_DISPATCH, {
-        CHECK_RETURN(dispatch(d));
-      })
-      VMCASE(OP_HALT, {
-        return d->size_param;
-      })
-    }
-  }
-}
-
-
-/* BytesHandler handlers ******************************************************/
-
-void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
-  upb_pbdecoder *d = closure;
-  UPB_UNUSED(size_hint);
-  d->top->end_ofs = UINT64_MAX;
-  d->bufstart_ofs = 0;
-  d->call_len = 1;
-  d->callstack[0] = &halt;
-  d->pc = pc;
-  d->skip = 0;
-  return d;
-}
-
-bool upb_pbdecoder_end(void *closure, const void *handler_data) {
-  upb_pbdecoder *d = closure;
-  const upb_pbdecodermethod *method = handler_data;
-  uint64_t end;
-  char dummy;
-
-  if (d->residual_end > d->residual) {
-    seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
-    return false;
-  }
-
-  if (d->skip) {
-    seterr(d, "Unexpected EOF inside skipped data");
-    return false;
-  }
-
-  if (d->top->end_ofs != UINT64_MAX) {
-    seterr(d, "Unexpected EOF inside delimited string");
-    return false;
-  }
-
-  /* The user's end() call indicates that the message ends here. */
-  end = offset(d);
-  d->top->end_ofs = end;
-
-  {
-    const uint32_t *p = d->pc;
-    d->stack->end_ofs = end;
-    /* Check the previous bytecode, but guard against beginning. */
-    if (p != method->code_base.ptr) p--;
-    if (getop(*p) == OP_CHECKDELIM) {
-      /* Rewind from OP_TAG* to OP_CHECKDELIM. */
-      UPB_ASSERT(getop(*d->pc) == OP_TAG1 ||
-             getop(*d->pc) == OP_TAG2 ||
-             getop(*d->pc) == OP_TAGN ||
-             getop(*d->pc) == OP_DISPATCH);
-      d->pc = p;
-    }
-    upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
-  }
-
-  if (d->call_len != 0) {
-    seterr(d, "Unexpected EOF inside submessage or group");
-    return false;
-  }
-
-  return true;
-}
-
-size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
-                            size_t size, const upb_bufhandle *handle) {
-  int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
-
-  if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
-  CHECK_RETURN(result);
-
-  return run_decoder_vm(decoder, group, handle);
-}
-
-
-/* Public API *****************************************************************/
-
-void upb_pbdecoder_reset(upb_pbdecoder *d) {
-  d->top = d->stack;
-  d->top->groupnum = 0;
-  d->ptr = d->residual;
-  d->buf = d->residual;
-  d->end = d->residual;
-  d->residual_end = d->residual;
-}
-
-upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m,
-                                    upb_sink sink, upb_status *status) {
-  const size_t default_max_nesting = 64;
-#ifndef NDEBUG
-  size_t size_before = upb_arena_bytesallocated(a);
-#endif
-
-  upb_pbdecoder *d = upb_arena_malloc(a, sizeof(upb_pbdecoder));
-  if (!d) return NULL;
-
-  d->method_ = m;
-  d->callstack = upb_arena_malloc(a, callstacksize(d, default_max_nesting));
-  d->stack = upb_arena_malloc(a, stacksize(d, default_max_nesting));
-  if (!d->stack || !d->callstack) {
-    return NULL;
-  }
-
-  d->arena = a;
-  d->limit = d->stack + default_max_nesting - 1;
-  d->stack_size = default_max_nesting;
-  d->status = status;
-
-  upb_pbdecoder_reset(d);
-  upb_bytessink_reset(&d->input_, &m->input_handler_, d);
-
-  if (d->method_->dest_handlers_) {
-    if (sink.handlers != d->method_->dest_handlers_)
-      return NULL;
-  }
-  d->top->sink = sink;
-
-  /* If this fails, increase the value in decoder.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
-                      UPB_PB_DECODER_SIZE);
-  return d;
-}
-
-uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
-  return offset(d);
-}
-
-const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
-  return d->method_;
-}
-
-upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d) {
-  return d->input_;
-}
-
-size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
-  return d->stack_size;
-}
-
-bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
-  UPB_ASSERT(d->top >= d->stack);
-
-  if (max < (size_t)(d->top - d->stack)) {
-    /* Can't set a limit smaller than what we are currently at. */
-    return false;
-  }
-
-  if (max > d->stack_size) {
-    /* Need to reallocate stack and callstack to accommodate. */
-    size_t old_size = stacksize(d, d->stack_size);
-    size_t new_size = stacksize(d, max);
-    void *p = upb_arena_realloc(d->arena, d->stack, old_size, new_size);
-    if (!p) {
-      return false;
-    }
-    d->stack = p;
-
-    old_size = callstacksize(d, d->stack_size);
-    new_size = callstacksize(d, max);
-    p = upb_arena_realloc(d->arena, d->callstack, old_size, new_size);
-    if (!p) {
-      return false;
-    }
-    d->callstack = p;
-
-    d->stack_size = max;
-  }
-
-  d->limit = d->stack + max - 1;
-  return true;
-}
-/*
-** upb::Encoder
-**
-** Since we are implementing pure handlers (ie. without any out-of-band access
-** to pre-computed lengths), we have to buffer all submessages before we can
-** emit even their first byte.
-**
-** Not knowing the size of submessages also means we can't write a perfect
-** zero-copy implementation, even with buffering.  Lengths are stored as
-** varints, which means that we don't know how many bytes to reserve for the
-** length until we know what the length is.
-**
-** This leaves us with three main choices:
-**
-** 1. buffer all submessage data in a temporary buffer, then copy it exactly
-**    once into the output buffer.
-**
-** 2. attempt to buffer data directly into the output buffer, estimating how
-**    many bytes each length will take.  When our guesses are wrong, use
-**    memmove() to grow or shrink the allotted space.
-**
-** 3. buffer directly into the output buffer, allocating a max length
-**    ahead-of-time for each submessage length.  If we overallocated, we waste
-**    space, but no memcpy() or memmove() is required.  This approach requires
-**    defining a maximum size for submessages and rejecting submessages that
-**    exceed that size.
-**
-** (2) and (3) have the potential to have better performance, but they are more
-** complicated and subtle to implement:
-**
-**   (3) requires making an arbitrary choice of the maximum message size; it
-**       wastes space when submessages are shorter than this and fails
-**       completely when they are longer.  This makes it more finicky and
-**       requires configuration based on the input.  It also makes it impossible
-**       to perfectly match the output of reference encoders that always use the
-**       optimal amount of space for each length.
-**
-**   (2) requires guessing the the size upfront, and if multiple lengths are
-**       guessed wrong the minimum required number of memmove() operations may
-**       be complicated to compute correctly.  Implemented properly, it may have
-**       a useful amortized or average cost, but more investigation is required
-**       to determine this and what the optimal algorithm is to achieve it.
-**
-**   (1) makes you always pay for exactly one copy, but its implementation is
-**       the simplest and its performance is predictable.
-**
-** So for now, we implement (1) only.  If we wish to optimize later, we should
-** be able to do it without affecting users.
-**
-** The strategy is to buffer the segments of data that do *not* depend on
-** unknown lengths in one buffer, and keep a separate buffer of segment pointers
-** and lengths.  When the top-level submessage ends, we can go beginning to end,
-** alternating the writing of lengths with memcpy() of the rest of the data.
-** At the top level though, no buffering is required.
-*/
-
-
-
-/* The output buffer is divided into segments; a segment is a string of data
- * that is "ready to go" -- it does not need any varint lengths inserted into
- * the middle.  The seams between segments are where varints will be inserted
- * once they are known.
- *
- * We also use the concept of a "run", which is a range of encoded bytes that
- * occur at a single submessage level.  Every segment contains one or more runs.
- *
- * A segment can span messages.  Consider:
- *
- *                  .--Submessage lengths---------.
- *                  |       |                     |
- *                  |       V                     V
- *                  V      | |---------------    | |-----------------
- * Submessages:    | |-----------------------------------------------
- * Top-level msg: ------------------------------------------------------------
- *
- * Segments:          -----   -------------------   -----------------
- * Runs:              *----   *--------------*---   *----------------
- * (* marks the start)
- *
- * Note that the top-level menssage is not in any segment because it does not
- * have any length preceding it.
- *
- * A segment is only interrupted when another length needs to be inserted.  So
- * observe how the second segment spans both the inner submessage and part of
- * the next enclosing message. */
-typedef struct {
-  uint32_t msglen;  /* The length to varint-encode before this segment. */
-  uint32_t seglen;  /* Length of the segment. */
-} upb_pb_encoder_segment;
-
-struct upb_pb_encoder {
-  upb_arena *arena;
-
-  /* Our input and output. */
-  upb_sink input_;
-  upb_bytessink output_;
-
-  /* The "subclosure" -- used as the inner closure as part of the bytessink
-   * protocol. */
-  void *subc;
-
-  /* The output buffer and limit, and our current write position.  "buf"
-   * initially points to "initbuf", but is dynamically allocated if we need to
-   * grow beyond the initial size. */
-  char *buf, *ptr, *limit;
-
-  /* The beginning of the current run, or undefined if we are at the top
-   * level. */
-  char *runbegin;
-
-  /* The list of segments we are accumulating. */
-  upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
-
-  /* The stack of enclosing submessages.  Each entry in the stack points to the
-   * segment where this submessage's length is being accumulated. */
-  int *stack, *top, *stacklimit;
-
-  /* Depth of startmsg/endmsg calls. */
-  int depth;
-};
-
-/* low-level buffering ********************************************************/
-
-/* Low-level functions for interacting with the output buffer. */
-
-/* TODO(haberman): handle pushback */
-static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
-  size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
-  UPB_ASSERT(n == len);
-}
-
-static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
-  return &e->segbuf[*e->top];
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr.  Returns false if the bytes could not be allocated. */
-static bool reserve(upb_pb_encoder *e, size_t bytes) {
-  if ((size_t)(e->limit - e->ptr) < bytes) {
-    /* Grow buffer. */
-    char *new_buf;
-    size_t needed = bytes + (e->ptr - e->buf);
-    size_t old_size = e->limit - e->buf;
-
-    size_t new_size = old_size;
-
-    while (new_size < needed) {
-      new_size *= 2;
-    }
-
-    new_buf = upb_arena_realloc(e->arena, e->buf, old_size, new_size);
-
-    if (new_buf == NULL) {
-      return false;
-    }
-
-    e->ptr = new_buf + (e->ptr - e->buf);
-    e->runbegin = new_buf + (e->runbegin - e->buf);
-    e->limit = new_buf + new_size;
-    e->buf = new_buf;
-  }
-
-  return true;
-}
-
-/* Call when "bytes" bytes have been writte at e->ptr.  The caller *must* have
- * previously called reserve() with at least this many bytes. */
-static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
-  UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes);
-  e->ptr += bytes;
-}
-
-/* Call when all of the bytes for a handler have been written.  Flushes the
- * bytes if possible and necessary, returning false if this failed. */
-static bool commit(upb_pb_encoder *e) {
-  if (!e->top) {
-    /* We aren't inside a delimited region.  Flush our accumulated bytes to
-     * the output.
-     *
-     * TODO(haberman): in the future we may want to delay flushing for
-     * efficiency reasons. */
-    putbuf(e, e->buf, e->ptr - e->buf);
-    e->ptr = e->buf;
-  }
-
-  return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
-  if (!reserve(e, len)) {
-    return false;
-  }
-
-  memcpy(e->ptr, data, len);
-  encoder_advance(e, len);
-  return true;
-}
-
-/* Finish the current run by adding the run totals to the segment and message
- * length. */
-static void accumulate(upb_pb_encoder *e) {
-  size_t run_len;
-  UPB_ASSERT(e->ptr >= e->runbegin);
-  run_len = e->ptr - e->runbegin;
-  e->segptr->seglen += run_len;
-  top(e)->msglen += run_len;
-  e->runbegin = e->ptr;
-}
-
-/* Call to indicate the start of delimited region for which the full length is
- * not yet known.  All data will be buffered until the length is known.
- * Delimited regions may be nested; their lengths will all be tracked properly. */
-static bool start_delim(upb_pb_encoder *e) {
-  if (e->top) {
-    /* We are already buffering, advance to the next segment and push it on the
-     * stack. */
-    accumulate(e);
-
-    if (++e->top == e->stacklimit) {
-      /* TODO(haberman): grow stack? */
-      return false;
-    }
-
-    if (++e->segptr == e->seglimit) {
-      /* Grow segment buffer. */
-      size_t old_size =
-          (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
-      size_t new_size = old_size * 2;
-      upb_pb_encoder_segment *new_buf =
-          upb_arena_realloc(e->arena, e->segbuf, old_size, new_size);
-
-      if (new_buf == NULL) {
-        return false;
-      }
-
-      e->segptr = new_buf + (e->segptr - e->segbuf);
-      e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
-      e->segbuf = new_buf;
-    }
-  } else {
-    /* We were previously at the top level, start buffering. */
-    e->segptr = e->segbuf;
-    e->top = e->stack;
-    e->runbegin = e->ptr;
-  }
-
-  *e->top = (int)(e->segptr - e->segbuf);
-  e->segptr->seglen = 0;
-  e->segptr->msglen = 0;
-
-  return true;
-}
-
-/* Call to indicate the end of a delimited region.  We now know the length of
- * the delimited region.  If we are not nested inside any other delimited
- * regions, we can now emit all of the buffered data we accumulated. */
-static bool end_delim(upb_pb_encoder *e) {
-  size_t msglen;
-  accumulate(e);
-  msglen = top(e)->msglen;
-
-  if (e->top == e->stack) {
-    /* All lengths are now available, emit all buffered data. */
-    char buf[UPB_PB_VARINT_MAX_LEN];
-    upb_pb_encoder_segment *s;
-    const char *ptr = e->buf;
-    for (s = e->segbuf; s <= e->segptr; s++) {
-      size_t lenbytes = upb_vencode64(s->msglen, buf);
-      putbuf(e, buf, lenbytes);
-      putbuf(e, ptr, s->seglen);
-      ptr += s->seglen;
-    }
-
-    e->ptr = e->buf;
-    e->top = NULL;
-  } else {
-    /* Need to keep buffering; propagate length info into enclosing
-     * submessages. */
-    --e->top;
-    top(e)->msglen += msglen + upb_varint_size(msglen);
-  }
-
-  return true;
-}
-
-
-/* tag_t **********************************************************************/
-
-/* A precomputed (pre-encoded) tag and length. */
-
-typedef struct {
-  uint8_t bytes;
-  char tag[7];
-} tag_t;
-
-/* Allocates a new tag for this field, and sets it in these handlerattr. */
-static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
-                    upb_handlerattr *attr) {
-  uint32_t n = upb_fielddef_number(f);
-
-  tag_t *tag = upb_gmalloc(sizeof(tag_t));
-  tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
-
-  attr->handler_data = tag;
-  upb_handlers_addcleanup(h, tag, upb_gfree);
-}
-
-static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
-  return encode_bytes(e, tag->tag, tag->bytes);
-}
-
-
-/* encoding of wire types *****************************************************/
-
-static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return encode_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return encode_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool encode_varint(upb_pb_encoder *e, uint64_t val) {
-  if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
-    return false;
-  }
-
-  encoder_advance(e, upb_vencode64(val, e->ptr));
-  return true;
-}
-
-static uint64_t dbl2uint64(double d) {
-  uint64_t ret;
-  memcpy(&ret, &d, sizeof(uint64_t));
-  return ret;
-}
-
-static uint32_t flt2uint32(float d) {
-  uint32_t ret;
-  memcpy(&ret, &d, sizeof(uint32_t));
-  return ret;
-}
-
-
-/* encoding of proto types ****************************************************/
-
-static bool startmsg(void *c, const void *hd) {
-  upb_pb_encoder *e = c;
-  UPB_UNUSED(hd);
-  if (e->depth++ == 0) {
-    upb_bytessink_start(e->output_, 0, &e->subc);
-  }
-  return true;
-}
-
-static bool endmsg(void *c, const void *hd, upb_status *status) {
-  upb_pb_encoder *e = c;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(status);
-  if (--e->depth == 0) {
-    upb_bytessink_end(e->output_);
-  }
-  return true;
-}
-
-static void *encode_startdelimfield(void *c, const void *hd) {
-  bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
-  return ok ? c : UPB_BREAK;
-}
-
-static bool encode_unknown(void *c, const void *hd, const char *buf,
-                           size_t len) {
-  UPB_UNUSED(hd);
-  return encode_bytes(c, buf, len) && commit(c);
-}
-
-static bool encode_enddelimfield(void *c, const void *hd) {
-  UPB_UNUSED(hd);
-  return end_delim(c);
-}
-
-static void *encode_startgroup(void *c, const void *hd) {
-  return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
-}
-
-static bool encode_endgroup(void *c, const void *hd) {
-  return encode_tag(c, hd) && commit(c);
-}
-
-static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
-  UPB_UNUSED(size_hint);
-  return encode_startdelimfield(c, hd);
-}
-
-static size_t encode_strbuf(void *c, const void *hd, const char *buf,
-                            size_t len, const upb_bufhandle *h) {
-  UPB_UNUSED(hd);
-  UPB_UNUSED(h);
-  return encode_bytes(c, buf, len) ? len : 0;
-}
-
-#define T(type, ctype, convert, encode)                                  \
-  static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
-    return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e);  \
-  }                                                                      \
-  static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
-    UPB_UNUSED(hd);                                                      \
-    return encode(e, (convert)(val));                                    \
-  }
-
-T(double,   double,   dbl2uint64,   encode_fixed64)
-T(float,    float,    flt2uint32,   encode_fixed32)
-T(int64,    int64_t,  uint64_t,     encode_varint)
-T(int32,    int32_t,  int64_t,      encode_varint)
-T(fixed64,  uint64_t, uint64_t,     encode_fixed64)
-T(fixed32,  uint32_t, uint32_t,     encode_fixed32)
-T(bool,     bool,     bool,         encode_varint)
-T(uint32,   uint32_t, uint32_t,     encode_varint)
-T(uint64,   uint64_t, uint64_t,     encode_varint)
-T(enum,     int32_t,  uint32_t,     encode_varint)
-T(sfixed32, int32_t,  uint32_t,     encode_fixed32)
-T(sfixed64, int64_t,  uint64_t,     encode_fixed64)
-T(sint32,   int32_t,  upb_zzenc_32, encode_varint)
-T(sint64,   int64_t,  upb_zzenc_64, encode_varint)
-
-#undef T
-
-
-/* code to build the handlers *************************************************/
-
-#include <stdio.h>
-static void newhandlers_callback(const void *closure, upb_handlers *h) {
-  const upb_msgdef *m;
-  upb_msg_field_iter i;
-
-  UPB_UNUSED(closure);
-
-  upb_handlers_setstartmsg(h, startmsg, NULL);
-  upb_handlers_setendmsg(h, endmsg, NULL);
-  upb_handlers_setunknown(h, encode_unknown, NULL);
-
-  m = upb_handlers_msgdef(h);
-  for(upb_msg_field_begin(&i, m);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
-                  upb_fielddef_packed(f);
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-    upb_wiretype_t wt =
-        packed ? UPB_WIRE_TYPE_DELIMITED
-               : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
-
-    /* Pre-encode the tag for this field. */
-    new_tag(h, f, wt, &attr);
-
-    if (packed) {
-      upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
-      upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
-    }
-
-#define T(upper, lower, upbtype)                                     \
-  case UPB_DESCRIPTOR_TYPE_##upper:                                  \
-    if (packed) {                                                    \
-      upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
-    } else {                                                         \
-      upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
-    }                                                                \
-    break;
-
-    switch (upb_fielddef_descriptortype(f)) {
-      T(DOUBLE,   double,   double);
-      T(FLOAT,    float,    float);
-      T(INT64,    int64,    int64);
-      T(INT32,    int32,    int32);
-      T(FIXED64,  fixed64,  uint64);
-      T(FIXED32,  fixed32,  uint32);
-      T(BOOL,     bool,     bool);
-      T(UINT32,   uint32,   uint32);
-      T(UINT64,   uint64,   uint64);
-      T(ENUM,     enum,     int32);
-      T(SFIXED32, sfixed32, int32);
-      T(SFIXED64, sfixed64, int64);
-      T(SINT32,   sint32,   int32);
-      T(SINT64,   sint64,   int64);
-      case UPB_DESCRIPTOR_TYPE_STRING:
-      case UPB_DESCRIPTOR_TYPE_BYTES:
-        upb_handlers_setstartstr(h, f, encode_startstr, &attr);
-        upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
-        upb_handlers_setstring(h, f, encode_strbuf, &attr);
-        break;
-      case UPB_DESCRIPTOR_TYPE_MESSAGE:
-        upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
-        upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
-        break;
-      case UPB_DESCRIPTOR_TYPE_GROUP: {
-        /* Endgroup takes a different tag (wire_type = END_GROUP). */
-        upb_handlerattr attr2 = UPB_HANDLERATTR_INIT;
-        new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
-
-        upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
-        upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
-
-        break;
-      }
-    }
-
-#undef T
-  }
-}
-
-void upb_pb_encoder_reset(upb_pb_encoder *e) {
-  e->segptr = NULL;
-  e->top = NULL;
-  e->depth = 0;
-}
-
-
-/* public API *****************************************************************/
-
-upb_handlercache *upb_pb_encoder_newcache(void) {
-  return upb_handlercache_new(newhandlers_callback, NULL);
-}
-
-upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h,
-                                      upb_bytessink output) {
-  const size_t initial_bufsize = 256;
-  const size_t initial_segbufsize = 16;
-  /* TODO(haberman): make this configurable. */
-  const size_t stack_size = 64;
-#ifndef NDEBUG
-  const size_t size_before = upb_arena_bytesallocated(arena);
-#endif
-
-  upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder));
-  if (!e) return NULL;
-
-  e->buf = upb_arena_malloc(arena, initial_bufsize);
-  e->segbuf = upb_arena_malloc(arena, initial_segbufsize * sizeof(*e->segbuf));
-  e->stack = upb_arena_malloc(arena, stack_size * sizeof(*e->stack));
-
-  if (!e->buf || !e->segbuf || !e->stack) {
-    return NULL;
-  }
-
-  e->limit = e->buf + initial_bufsize;
-  e->seglimit = e->segbuf + initial_segbufsize;
-  e->stacklimit = e->stack + stack_size;
-
-  upb_pb_encoder_reset(e);
-  upb_sink_reset(&e->input_, h, e);
-
-  e->arena = arena;
-  e->output_ = output;
-  e->subc = output.closure;
-  e->ptr = e->buf;
-
-  /* If this fails, increase the value in encoder.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
-                      UPB_PB_ENCODER_SIZE);
-  return e;
-}
-
-upb_sink upb_pb_encoder_input(upb_pb_encoder *e) { return e->input_; }
-/*
- * upb::pb::TextPrinter
- *
- * OPT: This is not optimized at all.  It uses printf() which parses the format
- * string every time, and it allocates memory for every put.
- */
-
-
-#include <ctype.h>
-#include <float.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-
-
-struct upb_textprinter {
-  upb_sink input_;
-  upb_bytessink output_;
-  int indent_depth_;
-  bool single_line_;
-  void *subc;
-};
-
-#define CHECK(x) if ((x) < 0) goto err;
-
-static const char *shortname(const char *longname) {
-  const char *last = strrchr(longname, '.');
-  return last ? last + 1 : longname;
-}
-
-static int indent(upb_textprinter *p) {
-  int i;
-  if (!p->single_line_)
-    for (i = 0; i < p->indent_depth_; i++)
-      upb_bytessink_putbuf(p->output_, p->subc, "  ", 2, NULL);
-  return 0;
-}
-
-static int endfield(upb_textprinter *p) {
-  const char ch = (p->single_line_ ? ' ' : '\n');
-  upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
-  return 0;
-}
-
-static int putescaped(upb_textprinter *p, const char *buf, size_t len,
-                      bool preserve_utf8) {
-  /* Based on CEscapeInternal() from Google's protobuf release. */
-  char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
-  const char *end = buf + len;
-
-  /* I think hex is prettier and more useful, but proto2 uses octal; should
-   * investigate whether it can parse hex also. */
-  const bool use_hex = false;
-  bool last_hex_escape = false; /* true if last output char was \xNN */
-
-  for (; buf < end; buf++) {
-    bool is_hex_escape;
-
-    if (dstend - dst < 4) {
-      upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
-      dst = dstbuf;
-    }
-
-    is_hex_escape = false;
-    switch (*buf) {
-      case '\n': *(dst++) = '\\'; *(dst++) = 'n';  break;
-      case '\r': *(dst++) = '\\'; *(dst++) = 'r';  break;
-      case '\t': *(dst++) = '\\'; *(dst++) = 't';  break;
-      case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
-      case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
-      case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
-      default:
-        /* Note that if we emit \xNN and the buf character after that is a hex
-         * digit then that digit must be escaped too to prevent it being
-         * interpreted as part of the character code by C. */
-        if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
-            (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
-          sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
-          is_hex_escape = use_hex;
-          dst += 4;
-        } else {
-          *(dst++) = *buf; break;
-        }
-    }
-    last_hex_escape = is_hex_escape;
-  }
-  /* Flush remaining data. */
-  upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
-  return 0;
-}
-
-bool putf(upb_textprinter *p, const char *fmt, ...) {
-  va_list args;
-  va_list args_copy;
-  char *str;
-  int written;
-  int len;
-  bool ok;
-
-  va_start(args, fmt);
-
-  /* Run once to get the length of the string. */
-  _upb_va_copy(args_copy, args);
-  len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
-  va_end(args_copy);
-
-  /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
-  str = upb_gmalloc(len + 1);
-  if (!str) return false;
-  written = vsprintf(str, fmt, args);
-  va_end(args);
-  UPB_ASSERT(written == len);
-
-  ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
-  upb_gfree(str);
-  return ok;
-}
-
-
-/* handlers *******************************************************************/
-
-static bool textprinter_startmsg(void *c, const void *hd) {
-  upb_textprinter *p = c;
-  UPB_UNUSED(hd);
-  if (p->indent_depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc);
-  }
-  return true;
-}
-
-static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
-  upb_textprinter *p = c;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(s);
-  if (p->indent_depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-#define TYPE(name, ctype, fmt) \
-  static bool textprinter_put ## name(void *closure, const void *handler_data, \
-                                      ctype val) {                             \
-    upb_textprinter *p = closure;                                              \
-    const upb_fielddef *f = handler_data;                                      \
-    CHECK(indent(p));                                                          \
-    putf(p, "%s: " fmt, upb_fielddef_name(f), val);                            \
-    CHECK(endfield(p));                                                        \
-    return true;                                                               \
-  err:                                                                         \
-    return false;                                                              \
-}
-
-static bool textprinter_putbool(void *closure, const void *handler_data,
-                                bool val) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  CHECK(indent(p));
-  putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
-  CHECK(endfield(p));
-  return true;
-err:
-  return false;
-}
-
-#define STRINGIFY_HELPER(x) #x
-#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
-
-TYPE(int32,  int32_t,  "%" PRId32)
-TYPE(int64,  int64_t,  "%" PRId64)
-TYPE(uint32, uint32_t, "%" PRIu32)
-TYPE(uint64, uint64_t, "%" PRIu64)
-TYPE(float,  float,    "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
-TYPE(double, double,   "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
-
-#undef TYPE
-
-/* Output a symbolic value from the enum if found, else just print as int32. */
-static bool textprinter_putenum(void *closure, const void *handler_data,
-                                int32_t val) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  const upb_enumdef *enum_def = upb_fielddef_enumsubdef(f);
-  const char *label = upb_enumdef_iton(enum_def, val);
-  if (label) {
-    indent(p);
-    putf(p, "%s: %s", upb_fielddef_name(f), label);
-    endfield(p);
-  } else {
-    if (!textprinter_putint32(closure, handler_data, val))
-      return false;
-  }
-  return true;
-}
-
-static void *textprinter_startstr(void *closure, const void *handler_data,
-                      size_t size_hint) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  UPB_UNUSED(size_hint);
-  indent(p);
-  putf(p, "%s: \"", upb_fielddef_name(f));
-  return p;
-}
-
-static bool textprinter_endstr(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  UPB_UNUSED(handler_data);
-  putf(p, "\"");
-  endfield(p);
-  return true;
-}
-
-static size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
-                                 size_t len, const upb_bufhandle *handle) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = hd;
-  UPB_UNUSED(handle);
-  CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
-  return len;
-err:
-  return 0;
-}
-
-static void *textprinter_startsubmsg(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  const char *name = handler_data;
-  CHECK(indent(p));
-  putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
-  p->indent_depth_++;
-  return p;
-err:
-  return UPB_BREAK;
-}
-
-static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  UPB_UNUSED(handler_data);
-  p->indent_depth_--;
-  CHECK(indent(p));
-  upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
-  CHECK(endfield(p));
-  return true;
-err:
-  return false;
-}
-
-static void onmreg(const void *c, upb_handlers *h) {
-  const upb_msgdef *m = upb_handlers_msgdef(h);
-  upb_msg_field_iter i;
-  UPB_UNUSED(c);
-
-  upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
-  upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
-
-  for(upb_msg_field_begin(&i, m);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-    attr.handler_data = f;
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_INT32:
-        upb_handlers_setint32(h, f, textprinter_putint32, &attr);
-        break;
-      case UPB_TYPE_INT64:
-        upb_handlers_setint64(h, f, textprinter_putint64, &attr);
-        break;
-      case UPB_TYPE_UINT32:
-        upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
-        break;
-      case UPB_TYPE_UINT64:
-        upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
-        break;
-      case UPB_TYPE_FLOAT:
-        upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
-        break;
-      case UPB_TYPE_DOUBLE:
-        upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
-        break;
-      case UPB_TYPE_BOOL:
-        upb_handlers_setbool(h, f, textprinter_putbool, &attr);
-        break;
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
-        upb_handlers_setstring(h, f, textprinter_putstr, &attr);
-        upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
-        break;
-      case UPB_TYPE_MESSAGE: {
-        const char *name =
-            upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_GROUP
-                ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
-                : upb_fielddef_name(f);
-        attr.handler_data = name;
-        upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
-        upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
-        break;
-      }
-      case UPB_TYPE_ENUM:
-        upb_handlers_setint32(h, f, textprinter_putenum, &attr);
-        break;
-    }
-  }
-}
-
-static void textprinter_reset(upb_textprinter *p, bool single_line) {
-  p->single_line_ = single_line;
-  p->indent_depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
-                                        upb_bytessink output) {
-  upb_textprinter *p = upb_arena_malloc(arena, sizeof(upb_textprinter));
-  if (!p) return NULL;
-
-  p->output_ = output;
-  upb_sink_reset(&p->input_, h, p);
-  textprinter_reset(p, false);
-
-  return p;
-}
-
-upb_handlercache *upb_textprinter_newcache(void) {
-  return upb_handlercache_new(&onmreg, NULL);
-}
-
-upb_sink upb_textprinter_input(upb_textprinter *p) { return p->input_; }
-
-void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
-  p->single_line_ = single_line;
-}
-
-
-/* Index is descriptor type. */
-const uint8_t upb_pb_native_wire_types[] = {
-  UPB_WIRE_TYPE_END_GROUP,     /* ENDGROUP */
-  UPB_WIRE_TYPE_64BIT,         /* DOUBLE */
-  UPB_WIRE_TYPE_32BIT,         /* FLOAT */
-  UPB_WIRE_TYPE_VARINT,        /* INT64 */
-  UPB_WIRE_TYPE_VARINT,        /* UINT64 */
-  UPB_WIRE_TYPE_VARINT,        /* INT32 */
-  UPB_WIRE_TYPE_64BIT,         /* FIXED64 */
-  UPB_WIRE_TYPE_32BIT,         /* FIXED32 */
-  UPB_WIRE_TYPE_VARINT,        /* BOOL */
-  UPB_WIRE_TYPE_DELIMITED,     /* STRING */
-  UPB_WIRE_TYPE_START_GROUP,   /* GROUP */
-  UPB_WIRE_TYPE_DELIMITED,     /* MESSAGE */
-  UPB_WIRE_TYPE_DELIMITED,     /* BYTES */
-  UPB_WIRE_TYPE_VARINT,        /* UINT32 */
-  UPB_WIRE_TYPE_VARINT,        /* ENUM */
-  UPB_WIRE_TYPE_32BIT,         /* SFIXED32 */
-  UPB_WIRE_TYPE_64BIT,         /* SFIXED64 */
-  UPB_WIRE_TYPE_VARINT,        /* SINT32 */
-  UPB_WIRE_TYPE_VARINT,        /* SINT64 */
-};
-
-/* A basic branch-based decoder, uses 32-bit values to get good performance
- * on 32-bit architectures (but performs well on 64-bits also).
- * This scheme comes from the original Google Protobuf implementation
- * (proto2). */
-upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
-  upb_decoderet err = {NULL, 0};
-  const char *p = r.p;
-  uint32_t low = (uint32_t)r.val;
-  uint32_t high = 0;
-  uint32_t b;
-  b = *(p++); low  |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
-  b = *(p++); low  |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
-  b = *(p++); low  |= (b & 0x7fU) << 28;
-              high  = (b & 0x7fU) >>  4; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) <<  3; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
-  return err;
-
-done:
-  r.val = ((uint64_t)high << 32) | low;
-  r.p = p;
-  return r;
-}
-
-/* Like the previous, but uses 64-bit values. */
-upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
-  const char *p = r.p;
-  uint64_t val = r.val;
-  uint64_t b;
-  upb_decoderet err = {NULL, 0};
-  b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
-  return err;
-
-done:
-  r.val = val;
-  r.p = p;
-  return r;
-}
-
-#line 1 "upb/json/parser.rl"
-/*
-** upb::json::Parser (upb_json_parser)
-**
-** A parser that uses the Ragel State Machine Compiler to generate
-** the finite automata.
-**
-** Ragel only natively handles regular languages, but we can manually
-** program it a bit to handle context-free languages like JSON, by using
-** the "fcall" and "fret" constructs.
-**
-** This parser can handle the basics, but needs several things to be fleshed
-** out:
-**
-** - handling of unicode escape sequences (including high surrogate pairs).
-** - properly check and report errors for unknown fields, stack overflow,
-**   improper array nesting (or lack of nesting).
-** - handling of base64 sequences with padding characters.
-** - handling of push-back (non-success returns from sink functions).
-** - handling of keys/escape-sequences/etc that span input buffers.
-*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <float.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <time.h>
-
-
-
-#define UPB_JSON_MAX_DEPTH 64
-
-/* Type of value message */
-enum {
-  VALUE_NULLVALUE   = 0,
-  VALUE_NUMBERVALUE = 1,
-  VALUE_STRINGVALUE = 2,
-  VALUE_BOOLVALUE   = 3,
-  VALUE_STRUCTVALUE = 4,
-  VALUE_LISTVALUE   = 5
-};
-
-/* Forward declare */
-static bool is_top_level(upb_json_parser *p);
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type);
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type);
-
-static bool is_number_wrapper_object(upb_json_parser *p);
-static bool does_number_wrapper_start(upb_json_parser *p);
-static bool does_number_wrapper_end(upb_json_parser *p);
-
-static bool is_string_wrapper_object(upb_json_parser *p);
-static bool does_string_wrapper_start(upb_json_parser *p);
-static bool does_string_wrapper_end(upb_json_parser *p);
-
-static bool does_fieldmask_start(upb_json_parser *p);
-static bool does_fieldmask_end(upb_json_parser *p);
-static void start_fieldmask_object(upb_json_parser *p);
-static void end_fieldmask_object(upb_json_parser *p);
-
-static void start_wrapper_object(upb_json_parser *p);
-static void end_wrapper_object(upb_json_parser *p);
-
-static void start_value_object(upb_json_parser *p, int value_type);
-static void end_value_object(upb_json_parser *p);
-
-static void start_listvalue_object(upb_json_parser *p);
-static void end_listvalue_object(upb_json_parser *p);
-
-static void start_structvalue_object(upb_json_parser *p);
-static void end_structvalue_object(upb_json_parser *p);
-
-static void start_object(upb_json_parser *p);
-static void end_object(upb_json_parser *p);
-
-static void start_any_object(upb_json_parser *p, const char *ptr);
-static bool end_any_object(upb_json_parser *p, const char *ptr);
-
-static bool start_subobject(upb_json_parser *p);
-static void end_subobject(upb_json_parser *p);
-
-static void start_member(upb_json_parser *p);
-static void end_member(upb_json_parser *p);
-static bool end_membername(upb_json_parser *p);
-
-static void start_any_member(upb_json_parser *p, const char *ptr);
-static void end_any_member(upb_json_parser *p, const char *ptr);
-static bool end_any_membername(upb_json_parser *p);
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
-             const upb_bufhandle *handle);
-static bool end(void *closure, const void *hd);
-
-static const char eof_ch = 'e';
-
-/* stringsink */
-typedef struct {
-  upb_byteshandler handler;
-  upb_bytessink sink;
-  char *ptr;
-  size_t len, size;
-} upb_stringsink;
-
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
-  upb_stringsink *sink = _sink;
-  sink->len = 0;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(size_hint);
-  return sink;
-}
-
-static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
-                                size_t len, const upb_bufhandle *handle) {
-  upb_stringsink *sink = _sink;
-  size_t new_size = sink->size;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  while (sink->len + len > new_size) {
-    new_size *= 2;
-  }
-
-  if (new_size != sink->size) {
-    sink->ptr = realloc(sink->ptr, new_size);
-    sink->size = new_size;
-  }
-
-  memcpy(sink->ptr + sink->len, ptr, len);
-  sink->len += len;
-
-  return len;
-}
-
-void upb_stringsink_init(upb_stringsink *sink) {
-  upb_byteshandler_init(&sink->handler);
-  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
-  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
-  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
-  sink->size = 32;
-  sink->ptr = malloc(sink->size);
-  sink->len = 0;
-}
-
-void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); }
-
-typedef struct {
-  /* For encoding Any value field in binary format. */
-  upb_handlercache *encoder_handlercache;
-  upb_stringsink stringsink;
-
-  /* For decoding Any value field in json format. */
-  upb_json_codecache *parser_codecache;
-  upb_sink sink;
-  upb_json_parser *parser;
-
-  /* Mark the range of uninterpreted values in json input before type url. */
-  const char *before_type_url_start;
-  const char *before_type_url_end;
-
-  /* Mark the range of uninterpreted values in json input after type url. */
-  const char *after_type_url_start;
-} upb_jsonparser_any_frame;
-
-typedef struct {
-  upb_sink sink;
-
-  /* The current message in which we're parsing, and the field whose value we're
-   * expecting next. */
-  const upb_msgdef *m;
-  const upb_fielddef *f;
-
-  /* The table mapping json name to fielddef for this message. */
-  const upb_strtable *name_table;
-
-  /* We are in a repeated-field context. We need this flag to decide whether to
-   * handle the array as a normal repeated field or a
-   * google.protobuf.ListValue/google.protobuf.Value. */
-  bool is_repeated;
-
-  /* We are in a repeated-field context, ready to emit mapentries as
-   * submessages. This flag alters the start-of-object (open-brace) behavior to
-   * begin a sequence of mapentry messages rather than a single submessage. */
-  bool is_map;
-
-  /* We are in a map-entry message context. This flag is set when parsing the
-   * value field of a single map entry and indicates to all value-field parsers
-   * (subobjects, strings, numbers, and bools) that the map-entry submessage
-   * should end as soon as the value is parsed. */
-  bool is_mapentry;
-
-  /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
-   * message's map field that we're currently parsing. This differs from |f|
-   * because |f| is the field in the *current* message (i.e., the map-entry
-   * message itself), not the parent's field that leads to this map. */
-  const upb_fielddef *mapfield;
-
-  /* We are in an Any message context. This flag is set when parsing the Any
-   * message and indicates to all field parsers (subobjects, strings, numbers,
-   * and bools) that the parsed field should be serialized as binary data or
-   * cached (type url not found yet). */
-  bool is_any;
-
-  /* The type of packed message in Any. */
-  upb_jsonparser_any_frame *any_frame;
-
-  /* True if the field to be parsed is unknown. */
-  bool is_unknown_field;
-} upb_jsonparser_frame;
-
-static void init_frame(upb_jsonparser_frame* frame) {
-  frame->m = NULL;
-  frame->f = NULL;
-  frame->name_table = NULL;
-  frame->is_repeated = false;
-  frame->is_map = false;
-  frame->is_mapentry = false;
-  frame->mapfield = NULL;
-  frame->is_any = false;
-  frame->any_frame = NULL;
-  frame->is_unknown_field = false;
-}
-
-struct upb_json_parser {
-  upb_arena *arena;
-  const upb_json_parsermethod *method;
-  upb_bytessink input_;
-
-  /* Stack to track the JSON scopes we are in. */
-  upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
-  upb_jsonparser_frame *top;
-  upb_jsonparser_frame *limit;
-
-  upb_status *status;
-
-  /* Ragel's internal parsing stack for the parsing state machine. */
-  int current_state;
-  int parser_stack[UPB_JSON_MAX_DEPTH];
-  int parser_top;
-
-  /* The handle for the current buffer. */
-  const upb_bufhandle *handle;
-
-  /* Accumulate buffer.  See details in parser.rl. */
-  const char *accumulated;
-  size_t accumulated_len;
-  char *accumulate_buf;
-  size_t accumulate_buf_size;
-
-  /* Multi-part text data.  See details in parser.rl. */
-  int multipart_state;
-  upb_selector_t string_selector;
-
-  /* Input capture.  See details in parser.rl. */
-  const char *capture;
-
-  /* Intermediate result of parsing a unicode escape sequence. */
-  uint32_t digit;
-
-  /* For resolve type url in Any. */
-  const upb_symtab *symtab;
-
-  /* Whether to proceed if unknown field is met. */
-  bool ignore_json_unknown;
-
-  /* Cache for parsing timestamp due to base and zone are handled in different
-   * handlers. */
-  struct tm tm;
-};
-
-static upb_jsonparser_frame* start_jsonparser_frame(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  inner = p->top + 1;
-  init_frame(inner);
-  return inner;
-}
-
-struct upb_json_codecache {
-  upb_arena *arena;
-  upb_inttable methods;   /* upb_msgdef* -> upb_json_parsermethod* */
-};
-
-struct upb_json_parsermethod {
-  const upb_json_codecache *cache;
-  upb_byteshandler input_handler_;
-
-  /* Maps json_name -> fielddef */
-  upb_strtable name_table;
-};
-
-#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-
-static upb_jsonparser_any_frame *json_parser_any_frame_new(
-    upb_json_parser *p) {
-  upb_jsonparser_any_frame *frame;
-
-  frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
-
-  frame->encoder_handlercache = upb_pb_encoder_newcache();
-  frame->parser_codecache = upb_json_codecache_new();
-  frame->parser = NULL;
-  frame->before_type_url_start = NULL;
-  frame->before_type_url_end = NULL;
-  frame->after_type_url_start = NULL;
-
-  upb_stringsink_init(&frame->stringsink);
-
-  return frame;
-}
-
-static void json_parser_any_frame_set_payload_type(
-    upb_json_parser *p,
-    upb_jsonparser_any_frame *frame,
-    const upb_msgdef *payload_type) {
-  const upb_handlers *h;
-  const upb_json_parsermethod *parser_method;
-  upb_pb_encoder *encoder;
-
-  /* Initialize encoder. */
-  h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
-  encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
-
-  /* Initialize parser. */
-  parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
-  upb_sink_reset(&frame->sink, h, encoder);
-  frame->parser =
-      upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink,
-                             p->status, p->ignore_json_unknown);
-}
-
-static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) {
-  upb_handlercache_free(frame->encoder_handlercache);
-  upb_json_codecache_free(frame->parser_codecache);
-  upb_stringsink_uninit(&frame->stringsink);
-}
-
-static bool json_parser_any_frame_has_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->parser != NULL;
-}
-
-static bool json_parser_any_frame_has_value_before_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->before_type_url_start != frame->before_type_url_end;
-}
-
-static bool json_parser_any_frame_has_value_after_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->after_type_url_start != NULL;
-}
-
-static bool json_parser_any_frame_has_value(
-  upb_jsonparser_any_frame *frame) {
-  return json_parser_any_frame_has_value_before_type_url(frame) ||
-         json_parser_any_frame_has_value_after_type_url(frame);
-}
-
-static void json_parser_any_frame_set_before_type_url_end(
-    upb_jsonparser_any_frame *frame,
-    const char *ptr) {
-  if (frame->parser == NULL) {
-    frame->before_type_url_end = ptr;
-  }
-}
-
-static void json_parser_any_frame_set_after_type_url_start_once(
-    upb_jsonparser_any_frame *frame,
-    const char *ptr) {
-  if (json_parser_any_frame_has_type_url(frame) &&
-      frame->after_type_url_start == NULL) {
-    frame->after_type_url_start = ptr;
-  }
-}
-
-/* Used to signal that a capture has been suspended. */
-static char suspend_capture;
-
-static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
-                                             upb_handlertype_t type) {
-  upb_selector_t sel;
-  bool ok = upb_handlers_getselector(p->top->f, type, &sel);
-  UPB_ASSUME(ok);
-  return sel;
-}
-
-static upb_selector_t parser_getsel(upb_json_parser *p) {
-  return getsel_for_handlertype(
-      p, upb_handlers_getprimitivehandlertype(p->top->f));
-}
-
-static bool check_stack(upb_json_parser *p) {
-  if ((p->top + 1) == p->limit) {
-    upb_status_seterrmsg(p->status, "Nesting too deep");
-    return false;
-  }
-
-  return true;
-}
-
-static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
-  upb_value v;
-  const upb_json_codecache *cache = p->method->cache;
-  bool ok;
-  const upb_json_parsermethod *method;
-
-  ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
-  UPB_ASSUME(ok);
-  method = upb_value_getconstptr(v);
-
-  frame->name_table = &method->name_table;
-}
-
-/* There are GCC/Clang built-ins for overflow checking which we could start
- * using if there was any performance benefit to it. */
-
-static bool checked_add(size_t a, size_t b, size_t *c) {
-  if (SIZE_MAX - a < b) return false;
-  *c = a + b;
-  return true;
-}
-
-static size_t saturating_multiply(size_t a, size_t b) {
-  /* size_t is unsigned, so this is defined behavior even on overflow. */
-  size_t ret = a * b;
-  if (b != 0 && ret / b != a) {
-    ret = SIZE_MAX;
-  }
-  return ret;
-}
-
-
-/* Base64 decoding ************************************************************/
-
-/* TODO(haberman): make this streaming. */
-
-static const signed char b64table[] = {
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,
-  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
-  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
-  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
-  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
-  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
-  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,
-  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
-  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
-  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
-  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
-};
-
-/* Returns the table value sign-extended to 32 bits.  Knowing that the upper
- * bits will be 1 for unrecognized characters makes it easier to check for
- * this error condition later (see below). */
-int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
-
-/* Returns true if the given character is not a valid base64 character or
- * padding. */
-bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
-
-static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
-                        size_t len) {
-  const char *limit = ptr + len;
-  for (; ptr < limit; ptr += 4) {
-    uint32_t val;
-    char output[3];
-
-    if (limit - ptr < 4) {
-      upb_status_seterrf(p->status,
-                         "Base64 input for bytes field not a multiple of 4: %s",
-                         upb_fielddef_name(p->top->f));
-      return false;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12 |
-          b64lookup(ptr[2]) << 6  |
-          b64lookup(ptr[3]);
-
-    /* Test the upper bit; returns true if any of the characters returned -1. */
-    if (val & 0x80000000) {
-      goto otherchar;
-    }
-
-    output[0] = val >> 16;
-    output[1] = (val >> 8) & 0xff;
-    output[2] = val & 0xff;
-    upb_sink_putstring(p->top->sink, sel, output, 3, NULL);
-  }
-  return true;
-
-otherchar:
-  if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
-      nonbase64(ptr[3]) ) {
-    upb_status_seterrf(p->status,
-                       "Non-base64 characters in bytes field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  } if (ptr[2] == '=') {
-    uint32_t val;
-    char output;
-
-    /* Last group contains only two input bytes, one output byte. */
-    if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
-      goto badpadding;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12;
-
-    UPB_ASSERT(!(val & 0x80000000));
-    output = val >> 16;
-    upb_sink_putstring(p->top->sink, sel, &output, 1, NULL);
-    return true;
-  } else {
-    uint32_t val;
-    char output[2];
-
-    /* Last group contains only three input bytes, two output bytes. */
-    if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
-      goto badpadding;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12 |
-          b64lookup(ptr[2]) << 6;
-
-    output[0] = val >> 16;
-    output[1] = (val >> 8) & 0xff;
-    upb_sink_putstring(p->top->sink, sel, output, 2, NULL);
-    return true;
-  }
-
-badpadding:
-  upb_status_seterrf(p->status,
-                     "Incorrect base64 padding for field: %s (%.*s)",
-                     upb_fielddef_name(p->top->f),
-                     4, ptr);
-  return false;
-}
-
-
-/* Accumulate buffer **********************************************************/
-
-/* Functionality for accumulating a buffer.
- *
- * Some parts of the parser need an entire value as a contiguous string.  For
- * example, to look up a member name in a hash table, or to turn a string into
- * a number, the relevant library routines need the input string to be in
- * contiguous memory, even if the value spanned two or more buffers in the
- * input.  These routines handle that.
- *
- * In the common case we can just point to the input buffer to get this
- * contiguous string and avoid any actual copy.  So we optimistically begin
- * this way.  But there are a few cases where we must instead copy into a
- * separate buffer:
- *
- *   1. The string was not contiguous in the input (it spanned buffers).
- *
- *   2. The string included escape sequences that need to be interpreted to get
- *      the true value in a contiguous buffer. */
-
-static void assert_accumulate_empty(upb_json_parser *p) {
-  UPB_ASSERT(p->accumulated == NULL);
-  UPB_ASSERT(p->accumulated_len == 0);
-}
-
-static void accumulate_clear(upb_json_parser *p) {
-  p->accumulated = NULL;
-  p->accumulated_len = 0;
-}
-
-/* Used internally by accumulate_append(). */
-static bool accumulate_realloc(upb_json_parser *p, size_t need) {
-  void *mem;
-  size_t old_size = p->accumulate_buf_size;
-  size_t new_size = UPB_MAX(old_size, 128);
-  while (new_size < need) {
-    new_size = saturating_multiply(new_size, 2);
-  }
-
-  mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
-  if (!mem) {
-    upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
-    return false;
-  }
-
-  p->accumulate_buf = mem;
-  p->accumulate_buf_size = new_size;
-  return true;
-}
-
-/* Logically appends the given data to the append buffer.
- * If "can_alias" is true, we will try to avoid actually copying, but the buffer
- * must be valid until the next accumulate_append() call (if any). */
-static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
-                              bool can_alias) {
-  size_t need;
-
-  if (!p->accumulated && can_alias) {
-    p->accumulated = buf;
-    p->accumulated_len = len;
-    return true;
-  }
-
-  if (!checked_add(p->accumulated_len, len, &need)) {
-    upb_status_seterrmsg(p->status, "Integer overflow.");
-    return false;
-  }
-
-  if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
-    return false;
-  }
-
-  if (p->accumulated != p->accumulate_buf) {
-    memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
-    p->accumulated = p->accumulate_buf;
-  }
-
-  memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
-  p->accumulated_len += len;
-  return true;
-}
-
-/* Returns a pointer to the data accumulated since the last accumulate_clear()
- * call, and writes the length to *len.  This with point either to the input
- * buffer or a temporary accumulate buffer. */
-static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
-  UPB_ASSERT(p->accumulated);
-  *len = p->accumulated_len;
-  return p->accumulated;
-}
-
-
-/* Mult-part text data ********************************************************/
-
-/* When we have text data in the input, it can often come in multiple segments.
- * For example, there may be some raw string data followed by an escape
- * sequence.  The two segments are processed with different logic.  Also buffer
- * seams in the input can cause multiple segments.
- *
- * As we see segments, there are two main cases for how we want to process them:
- *
- *  1. we want to push the captured input directly to string handlers.
- *
- *  2. we need to accumulate all the parts into a contiguous buffer for further
- *     processing (field name lookup, string->number conversion, etc). */
-
-/* This is the set of states for p->multipart_state. */
-enum {
-  /* We are not currently processing multipart data. */
-  MULTIPART_INACTIVE = 0,
-
-  /* We are processing multipart data by accumulating it into a contiguous
-   * buffer. */
-  MULTIPART_ACCUMULATE = 1,
-
-  /* We are processing multipart data by pushing each part directly to the
-   * current string handlers. */
-  MULTIPART_PUSHEAGERLY = 2
-};
-
-/* Start a multi-part text value where we accumulate the data for processing at
- * the end. */
-static void multipart_startaccum(upb_json_parser *p) {
-  assert_accumulate_empty(p);
-  UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_ACCUMULATE;
-}
-
-/* Start a multi-part text value where we immediately push text data to a string
- * value with the given selector. */
-static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
-  assert_accumulate_empty(p);
-  UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_PUSHEAGERLY;
-  p->string_selector = sel;
-}
-
-static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
-                           bool can_alias) {
-  switch (p->multipart_state) {
-    case MULTIPART_INACTIVE:
-      upb_status_seterrmsg(
-          p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
-      return false;
-
-    case MULTIPART_ACCUMULATE:
-      if (!accumulate_append(p, buf, len, can_alias)) {
-        return false;
-      }
-      break;
-
-    case MULTIPART_PUSHEAGERLY: {
-      const upb_bufhandle *handle = can_alias ? p->handle : NULL;
-      upb_sink_putstring(p->top->sink, p->string_selector, buf, len, handle);
-      break;
-    }
-  }
-
-  return true;
-}
-
-/* Note: this invalidates the accumulate buffer!  Call only after reading its
- * contents. */
-static void multipart_end(upb_json_parser *p) {
-  UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_INACTIVE;
-  accumulate_clear(p);
-}
-
-
-/* Input capture **************************************************************/
-
-/* Functionality for capturing a region of the input as text.  Gracefully
- * handles the case where a buffer seam occurs in the middle of the captured
- * region. */
-
-static void capture_begin(upb_json_parser *p, const char *ptr) {
-  UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
-  UPB_ASSERT(p->capture == NULL);
-  p->capture = ptr;
-}
-
-static bool capture_end(upb_json_parser *p, const char *ptr) {
-  UPB_ASSERT(p->capture);
-  if (multipart_text(p, p->capture, ptr - p->capture, true)) {
-    p->capture = NULL;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* This is called at the end of each input buffer (ie. when we have hit a
- * buffer seam).  If we are in the middle of capturing the input, this
- * processes the unprocessed capture region. */
-static void capture_suspend(upb_json_parser *p, const char **ptr) {
-  if (!p->capture) return;
-
-  if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
-    /* We use this as a signal that we were in the middle of capturing, and
-     * that capturing should resume at the beginning of the next buffer.
-     * 
-     * We can't use *ptr here, because we have no guarantee that this pointer
-     * will be valid when we resume (if the underlying memory is freed, then
-     * using the pointer at all, even to compare to NULL, is likely undefined
-     * behavior). */
-    p->capture = &suspend_capture;
-  } else {
-    /* Need to back up the pointer to the beginning of the capture, since
-     * we were not able to actually preserve it. */
-    *ptr = p->capture;
-  }
-}
-
-static void capture_resume(upb_json_parser *p, const char *ptr) {
-  if (p->capture) {
-    UPB_ASSERT(p->capture == &suspend_capture);
-    p->capture = ptr;
-  }
-}
-
-
-/* Callbacks from the parser **************************************************/
-
-/* These are the functions called directly from the parser itself.
- * We define these in the same order as their declarations in the parser. */
-
-static char escape_char(char in) {
-  switch (in) {
-    case 'r': return '\r';
-    case 't': return '\t';
-    case 'n': return '\n';
-    case 'f': return '\f';
-    case 'b': return '\b';
-    case '/': return '/';
-    case '"': return '"';
-    case '\\': return '\\';
-    default:
-      UPB_ASSERT(0);
-      return 'x';
-  }
-}
-
-static bool escape(upb_json_parser *p, const char *ptr) {
-  char ch = escape_char(*ptr);
-  return multipart_text(p, &ch, 1, false);
-}
-
-static void start_hex(upb_json_parser *p) {
-  p->digit = 0;
-}
-
-static void hexdigit(upb_json_parser *p, const char *ptr) {
-  char ch = *ptr;
-
-  p->digit <<= 4;
-
-  if (ch >= '0' && ch <= '9') {
-    p->digit += (ch - '0');
-  } else if (ch >= 'a' && ch <= 'f') {
-    p->digit += ((ch - 'a') + 10);
-  } else {
-    UPB_ASSERT(ch >= 'A' && ch <= 'F');
-    p->digit += ((ch - 'A') + 10);
-  }
-}
-
-static bool end_hex(upb_json_parser *p) {
-  uint32_t codepoint = p->digit;
-
-  /* emit the codepoint as UTF-8. */
-  char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
-  int length = 0;
-  if (codepoint <= 0x7F) {
-    utf8[0] = codepoint;
-    length = 1;
-  } else if (codepoint <= 0x07FF) {
-    utf8[1] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[0] = (codepoint & 0x1F) | 0xC0;
-    length = 2;
-  } else /* codepoint <= 0xFFFF */ {
-    utf8[2] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[1] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[0] = (codepoint & 0x0F) | 0xE0;
-    length = 3;
-  }
-  /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
-   * we have to wait for the next escape to get the full code point). */
-
-  return multipart_text(p, utf8, length, false);
-}
-
-static void start_text(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_text(upb_json_parser *p, const char *ptr) {
-  return capture_end(p, ptr);
-}
-
-static bool start_number(upb_json_parser *p, const char *ptr) {
-  if (is_top_level(p)) {
-    if (is_number_wrapper_object(p)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_NUMBERVALUE);
-    } else {
-      return false;
-    }
-  } else if (does_number_wrapper_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_NUMBERVALUE);
-  }
-
-  multipart_startaccum(p);
-  capture_begin(p, ptr);
-  return true;
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted);
-
-static bool end_number_nontop(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  if (p->top->f == NULL) {
-    multipart_end(p);
-    return true;
-  }
-
-  return parse_number(p, false);
-}
-
-static bool end_number(upb_json_parser *p, const char *ptr) {
-  if (!end_number_nontop(p, ptr)) {
-    return false;
-  }
-
-  if (does_number_wrapper_end(p)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-/* |buf| is NULL-terminated. |buf| itself will never include quotes;
- * |is_quoted| tells us whether this text originally appeared inside quotes. */
-static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
-                                     bool is_quoted) {
-  size_t len = strlen(buf);
-  const char *bufend = buf + len;
-  char *end;
-  upb_fieldtype_t type = upb_fielddef_type(p->top->f);
-  double val;
-  double dummy;
-  double inf = UPB_INFINITY;
-
-  errno = 0;
-
-  if (len == 0 || buf[0] == ' ') {
-    return false;
-  }
-
-  /* For integer types, first try parsing with integer-specific routines.
-   * If these succeed, they will be more accurate for int64/uint64 than
-   * strtod().
-   */
-  switch (type) {
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32: {
-      long val = strtol(buf, &end, 0);
-      if (errno == ERANGE || end != bufend) {
-        break;
-      } else if (val > INT32_MAX || val < INT32_MIN) {
-        return false;
-      } else {
-        upb_sink_putint32(p->top->sink, parser_getsel(p), (int32_t)val);
-        return true;
-      }
-    }
-    case UPB_TYPE_UINT32: {
-      unsigned long val = strtoul(buf, &end, 0);
-      if (end != bufend) {
-        break;
-      } else if (val > UINT32_MAX || errno == ERANGE) {
-        return false;
-      } else {
-        upb_sink_putuint32(p->top->sink, parser_getsel(p), (uint32_t)val);
-        return true;
-      }
-    }
-    /* XXX: We can't handle [u]int64 properly on 32-bit machines because
-     * strto[u]ll isn't in C89. */
-    case UPB_TYPE_INT64: {
-      long val = strtol(buf, &end, 0);
-      if (errno == ERANGE || end != bufend) {
-        break;
-      } else {
-        upb_sink_putint64(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    case UPB_TYPE_UINT64: {
-      unsigned long val = strtoul(p->accumulated, &end, 0);
-      if (end != bufend) {
-        break;
-      } else if (errno == ERANGE) {
-        return false;
-      } else {
-        upb_sink_putuint64(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    default:
-      break;
-  }
-
-  if (type != UPB_TYPE_DOUBLE && type != UPB_TYPE_FLOAT && is_quoted) {
-    /* Quoted numbers for integer types are not allowed to be in double form. */
-    return false;
-  }
-
-  if (len == strlen("Infinity") && strcmp(buf, "Infinity") == 0) {
-    /* C89 does not have an INFINITY macro. */
-    val = inf;
-  } else if (len == strlen("-Infinity") && strcmp(buf, "-Infinity") == 0) {
-    val = -inf;
-  } else {
-    val = strtod(buf, &end);
-    if (errno == ERANGE || end != bufend) {
-      return false;
-    }
-  }
-
-  switch (type) {
-#define CASE(capitaltype, smalltype, ctype, min, max)                     \
-    case UPB_TYPE_ ## capitaltype: {                                      \
-      if (modf(val, &dummy) != 0 || val > max || val < min) {             \
-        return false;                                                     \
-      } else {                                                            \
-        upb_sink_put ## smalltype(p->top->sink, parser_getsel(p),        \
-                                  (ctype)val);                            \
-        return true;                                                      \
-      }                                                                   \
-      break;                                                              \
-    }
-    case UPB_TYPE_ENUM:
-    CASE(INT32, int32, int32_t, INT32_MIN, INT32_MAX);
-    CASE(INT64, int64, int64_t, INT64_MIN, INT64_MAX);
-    CASE(UINT32, uint32, uint32_t, 0, UINT32_MAX);
-    CASE(UINT64, uint64, uint64_t, 0, UINT64_MAX);
-#undef CASE
-
-    case UPB_TYPE_DOUBLE:
-      upb_sink_putdouble(p->top->sink, parser_getsel(p), val);
-      return true;
-    case UPB_TYPE_FLOAT:
-      if ((val > FLT_MAX || val < -FLT_MAX) && val != inf && val != -inf) {
-        return false;
-      } else {
-        upb_sink_putfloat(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    default:
-      return false;
-  }
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted) {
-  size_t len;
-  const char *buf;
-
-  /* strtol() and friends unfortunately do not support specifying the length of
-   * the input string, so we need to force a copy into a NULL-terminated buffer. */
-  if (!multipart_text(p, "\0", 1, false)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (parse_number_from_buffer(p, buf, is_quoted)) {
-    multipart_end(p);
-    return true;
-  } else {
-    upb_status_seterrf(p->status, "error parsing number: %s", buf);
-    multipart_end(p);
-    return false;
-  }
-}
-
-static bool parser_putbool(upb_json_parser *p, bool val) {
-  bool ok;
-
-  if (p->top->f == NULL) {
-    return true;
-  }
-
-  if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
-    upb_status_seterrf(p->status,
-                       "Boolean value specified for non-bool field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-
-  ok = upb_sink_putbool(p->top->sink, parser_getsel(p), val);
-  UPB_ASSERT(ok);
-
-  return true;
-}
-
-static bool end_bool(upb_json_parser *p, bool val) {
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_BOOLVALUE);
-    } else {
-      return false;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_BOOLVALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_BOOLVALUE);
-  }
-
-  if (p->top->is_unknown_field) {
-    return true;
-  }
-
-  if (!parser_putbool(p, val)) {
-    return false;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-static bool end_null(upb_json_parser *p) {
-  const char *zero_ptr = "0";
-
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_NULLVALUE);
-    } else {
-      return true;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_NULLVALUE);
-  } else {
-    return true;
-  }
-
-  /* Fill null_value field. */
-  multipart_startaccum(p);
-  capture_begin(p, zero_ptr);
-  capture_end(p, zero_ptr + 1);
-  parse_number(p, false);
-
-  end_value_object(p);
-  if (!is_top_level(p)) {
-    end_subobject(p);
-  }
-
-  return true;
-}
-
-static bool start_any_stringval(upb_json_parser *p) {
-  multipart_startaccum(p);
-  return true;
-}
-
-static bool start_stringval(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    if (is_string_wrapper_object(p) ||
-        is_number_wrapper_object(p)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
-      start_fieldmask_object(p);
-      return true;
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-               is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
-      start_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_STRINGVALUE);
-    } else {
-      return false;
-    }
-  } else if (does_string_wrapper_start(p) ||
-             does_number_wrapper_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (does_fieldmask_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_fieldmask_object(p);
-    return true;
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_TIMESTAMP) ||
-             is_wellknown_field(p, UPB_WELLKNOWN_DURATION)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_STRINGVALUE);
-  }
-
-  if (p->top->f == NULL) {
-    multipart_startaccum(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return start_any_stringval(p);
-  }
-
-  if (upb_fielddef_isstring(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    if (!check_stack(p)) return false;
-
-    /* Start a new parser frame: parser frames correspond one-to-one with
-     * handler frames, and string events occur in a sub-frame. */
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-    upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-    inner->m = p->top->m;
-    inner->f = p->top->f;
-    p->top = inner;
-
-    if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
-      /* For STRING fields we push data directly to the handlers as it is
-       * parsed.  We don't do this yet for BYTES fields, because our base64
-       * decoder is not streaming.
-       *
-       * TODO(haberman): make base64 decoding streaming also. */
-      multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
-      return true;
-    } else {
-      multipart_startaccum(p);
-      return true;
-    }
-  } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL &&
-             upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) {
-    /* No need to push a frame -- numeric values in quotes remain in the
-     * current parser frame.  These values must accmulate so we can convert
-     * them all at once at the end. */
-    multipart_startaccum(p);
-    return true;
-  } else {
-    upb_status_seterrf(p->status,
-                       "String specified for bool or submessage field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-}
-
-static bool end_any_stringval(upb_json_parser *p) {
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-
-  /* Set type_url */
-  upb_selector_t sel;
-  upb_jsonparser_frame *inner;
-  if (!check_stack(p)) return false;
-  inner = p->top + 1;
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-  upb_sink_putstring(inner->sink, sel, buf, len, NULL);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(inner->sink, sel);
-
-  multipart_end(p);
-
-  /* Resolve type url */
-  if (strncmp(buf, "type.googleapis.com/", 20) == 0 && len > 20) {
-    const upb_msgdef *payload_type = NULL;
-    buf += 20;
-    len -= 20;
-
-    payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
-    if (payload_type == NULL) {
-      upb_status_seterrf(
-          p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
-      return false;
-    }
-
-    json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type);
-
-    return true;
-  } else {
-    upb_status_seterrf(
-        p->status, "Invalid type url: %.*s\n", (int)len, buf);
-    return false;
-  }
-}
-
-static bool end_stringval_nontop(upb_json_parser *p) {
-  bool ok = true;
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->f == NULL) {
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return end_any_stringval(p);
-  }
-
-  switch (upb_fielddef_type(p->top->f)) {
-    case UPB_TYPE_BYTES:
-      if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
-                       p->accumulated, p->accumulated_len)) {
-        return false;
-      }
-      /* Fall through. */
-
-    case UPB_TYPE_STRING: {
-      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-      upb_sink_endstr(p->top->sink, sel);
-      p->top--;
-      break;
-    }
-
-    case UPB_TYPE_ENUM: {
-      /* Resolve enum symbolic name to integer value. */
-      const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f);
-
-      size_t len;
-      const char *buf = accumulate_getptr(p, &len);
-
-      int32_t int_val = 0;
-      ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
-
-      if (ok) {
-        upb_selector_t sel = parser_getsel(p);
-        upb_sink_putint32(p->top->sink, sel, int_val);
-      } else {
-        upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
-      }
-
-      break;
-    }
-
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      ok = parse_number(p, true);
-      break;
-
-    default:
-      UPB_ASSERT(false);
-      upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
-      ok = false;
-      break;
-  }
-
-  multipart_end(p);
-
-  return ok;
-}
-
-static bool end_stringval(upb_json_parser *p) {
-  /* FieldMask's stringvals have been ended when handling them. Only need to
-   * close FieldMask here.*/
-  if (does_fieldmask_end(p)) {
-    end_fieldmask_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (!end_stringval_nontop(p)) {
-    return false;
-  }
-
-  if (does_string_wrapper_end(p) ||
-      does_number_wrapper_end(p)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_DURATION) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
-    end_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-static void start_duration_base(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_duration_base(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  char seconds_buf[14];
-  char nanos_buf[12];
-  char *end;
-  int64_t seconds = 0;
-  int32_t nanos = 0;
-  double val = 0.0;
-  const char *seconds_membername = "seconds";
-  const char *nanos_membername = "nanos";
-  size_t fraction_start;
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  memset(seconds_buf, 0, 14);
-  memset(nanos_buf, 0, 12);
-
-  /* Find out base end. The maximus duration is 315576000000, which cannot be
-   * represented by double without losing precision. Thus, we need to handle
-   * fraction and base separately. */
-  for (fraction_start = 0; fraction_start < len && buf[fraction_start] != '.';
-       fraction_start++);
-
-  /* Parse base */
-  memcpy(seconds_buf, buf, fraction_start);
-  seconds = strtol(seconds_buf, &end, 10);
-  if (errno == ERANGE || end != seconds_buf + fraction_start) {
-    upb_status_seterrf(p->status, "error parsing duration: %s",
-                       seconds_buf);
-    return false;
-  }
-
-  if (seconds > 315576000000) {
-    upb_status_seterrf(p->status, "error parsing duration: "
-                                   "maximum acceptable value is "
-                                   "315576000000");
-    return false;
-  }
-
-  if (seconds < -315576000000) {
-    upb_status_seterrf(p->status, "error parsing duration: "
-                                   "minimum acceptable value is "
-                                   "-315576000000");
-    return false;
-  }
-
-  /* Parse fraction */
-  nanos_buf[0] = '0';
-  memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
-  val = strtod(nanos_buf, &end);
-  if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
-    upb_status_seterrf(p->status, "error parsing duration: %s",
-                       nanos_buf);
-    return false;
-  }
-
-  nanos = val * 1000000000;
-  if (seconds < 0) nanos = -nanos;
-
-  /* Clean up buffer */
-  multipart_end(p);
-
-  /* Set seconds */
-  start_member(p);
-  capture_begin(p, seconds_membername);
-  capture_end(p, seconds_membername + 7);
-  end_membername(p);
-  upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
-  end_member(p);
-
-  /* Set nanos */
-  start_member(p);
-  capture_begin(p, nanos_membername);
-  capture_end(p, nanos_membername + 5);
-  end_membername(p);
-  upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
-  end_member(p);
-
-  /* Continue previous arena */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static int parse_timestamp_number(upb_json_parser *p) {
-  size_t len;
-  const char *buf;
-  int val;
-
-  /* atoi() and friends unfortunately do not support specifying the length of
-   * the input string, so we need to force a copy into a NULL-terminated buffer. */
-  multipart_text(p, "\0", 1, false);
-
-  buf = accumulate_getptr(p, &len);
-  val = atoi(buf);
-  multipart_end(p);
-  multipart_startaccum(p);
-
-  return val;
-}
-
-static void start_year(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_year(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_year = parse_timestamp_number(p) - 1900;
-  return true;
-}
-
-static void start_month(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_month(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_mon = parse_timestamp_number(p) - 1;
-  return true;
-}
-
-static void start_day(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_day(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_mday = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_hour(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_hour(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_hour = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_minute(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_minute(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_min = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_second(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_second(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_sec = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_timestamp_base(upb_json_parser *p) {
-  memset(&p->tm, 0, sizeof(struct tm));
-}
-
-static void start_timestamp_fraction(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  char nanos_buf[12];
-  char *end;
-  double val = 0.0;
-  int32_t nanos;
-  const char *nanos_membername = "nanos";
-
-  memset(nanos_buf, 0, 12);
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (len > 10) {
-    upb_status_seterrf(p->status,
-        "error parsing timestamp: at most 9-digit fraction.");
-    return false;
-  }
-
-  /* Parse nanos */
-  nanos_buf[0] = '0';
-  memcpy(nanos_buf + 1, buf, len);
-  val = strtod(nanos_buf, &end);
-
-  if (errno == ERANGE || end != nanos_buf + len + 1) {
-    upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
-                       nanos_buf);
-    return false;
-  }
-
-  nanos = val * 1000000000;
-
-  /* Clean up previous environment */
-  multipart_end(p);
-
-  /* Set nanos */
-  start_member(p);
-  capture_begin(p, nanos_membername);
-  capture_end(p, nanos_membername + 5);
-  end_membername(p);
-  upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
-  end_member(p);
-
-  /* Continue previous environment */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static int div_round_up2(int n, int d) {
-  return (n + d - 1) / d;
-}
-
-/* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */
-static int epoch_days(int year, int month, int day) {
-  static const uint16_t month_yday[12] = {0,   31,  59,  90,  120, 151,
-                                          181, 212, 243, 273, 304, 334};
-  int febs_since_0 = month > 2 ? year + 1 : year;
-  int leap_days_since_0 = div_round_up2(febs_since_0, 4) -
-                          div_round_up2(febs_since_0, 100) +
-                          div_round_up2(febs_since_0, 400);
-  int days_since_0 =
-      365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0;
-
-  /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD).
-   * Since the "BC" system does not have a year zero, 1 BC == year zero. */
-  return days_since_0 - 719528;
-}
-
-static int64_t upb_timegm(const struct tm *tp) {
-  int64_t ret = epoch_days(tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday);
-  ret = (ret * 24) + tp->tm_hour;
-  ret = (ret * 60) + tp->tm_min;
-  ret = (ret * 60) + tp->tm_sec;
-  return ret;
-}
-
-static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  int hours;
-  int64_t seconds;
-  const char *seconds_membername = "seconds";
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (buf[0] != 'Z') {
-    if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
-      upb_status_seterrf(p->status, "error parsing timestamp offset");
-      return false;
-    }
-
-    if (buf[0] == '+') {
-      hours = -hours;
-    }
-
-    p->tm.tm_hour += hours;
-  }
-
-  /* Normalize tm */
-  seconds = upb_timegm(&p->tm);
-
-  /* Check timestamp boundary */
-  if (seconds < -62135596800) {
-    upb_status_seterrf(p->status, "error parsing timestamp: "
-                                   "minimum acceptable value is "
-                                   "0001-01-01T00:00:00Z");
-    return false;
-  }
-
-  /* Clean up previous environment */
-  multipart_end(p);
-
-  /* Set seconds */
-  start_member(p);
-  capture_begin(p, seconds_membername);
-  capture_end(p, seconds_membername + 7);
-  end_membername(p);
-  upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
-  end_member(p);
-
-  /* Continue previous environment */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
-  return capture_end(p, ptr);
-}
-
-static bool start_fieldmask_path(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  if (!check_stack(p)) return false;
-
-  /* Start a new parser frame: parser frames correspond one-to-one with
-   * handler frames, and string events occur in a sub-frame. */
-  inner = start_jsonparser_frame(p);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  inner->m = p->top->m;
-  inner->f = p->top->f;
-  p->top = inner;
-
-  multipart_startaccum(p);
-  return true;
-}
-
-static bool lower_camel_push(
-    upb_json_parser *p, upb_selector_t sel, const char *ptr, size_t len) {
-  const char *limit = ptr + len;
-  bool first = true;
-  for (;ptr < limit; ptr++) {
-    if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
-      char lower = tolower(*ptr);
-      upb_sink_putstring(p->top->sink, sel, "_", 1, NULL);
-      upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL);
-    } else {
-      upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL);
-    }
-    first = false;
-  }
-  return true;
-}
-
-static bool end_fieldmask_path(upb_json_parser *p) {
-  upb_selector_t sel;
-
-  if (!lower_camel_push(
-           p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
-           p->accumulated, p->accumulated_len)) {
-    return false;
-  }
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(p->top->sink, sel);
-  p->top--;
-
-  multipart_end(p);
-  return true;
-}
-
-static void start_member(upb_json_parser *p) {
-  UPB_ASSERT(!p->top->f);
-  multipart_startaccum(p);
-}
-
-/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
- * field based on the current contents of the accumulate buffer. */
-static bool parse_mapentry_key(upb_json_parser *p) {
-
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-
-  /* Emit the key field. We do a bit of ad-hoc parsing here because the
-   * parser state machine has already decided that this is a string field
-   * name, and we are reinterpreting it as some arbitrary key type. In
-   * particular, integer and bool keys are quoted, so we need to parse the
-   * quoted string contents here. */
-
-  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
-  if (p->top->f == NULL) {
-    upb_status_seterrmsg(p->status, "mapentry message has no key");
-    return false;
-  }
-  switch (upb_fielddef_type(p->top->f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      /* Invoke end_number. The accum buffer has the number's text already. */
-      if (!parse_number(p, true)) {
-        return false;
-      }
-      break;
-    case UPB_TYPE_BOOL:
-      if (len == 4 && !strncmp(buf, "true", 4)) {
-        if (!parser_putbool(p, true)) {
-          return false;
-        }
-      } else if (len == 5 && !strncmp(buf, "false", 5)) {
-        if (!parser_putbool(p, false)) {
-          return false;
-        }
-      } else {
-        upb_status_seterrmsg(p->status,
-                             "Map bool key not 'true' or 'false'");
-        return false;
-      }
-      multipart_end(p);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      upb_sink subsink;
-      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-      upb_sink_startstr(p->top->sink, sel, len, &subsink);
-      sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-      upb_sink_putstring(subsink, sel, buf, len, NULL);
-      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-      upb_sink_endstr(subsink, sel);
-      multipart_end(p);
-      break;
-    }
-    default:
-      upb_status_seterrmsg(p->status, "Invalid field type for map key");
-      return false;
-  }
-
-  return true;
-}
-
-/* Helper: emit one map entry (as a submessage in the map field sequence). This
- * is invoked from end_membername(), at the end of the map entry's key string,
- * with the map key in the accumulate buffer. It parses the key from that
- * buffer, emits the handler calls to start the mapentry submessage (setting up
- * its subframe in the process), and sets up state in the subframe so that the
- * value parser (invoked next) will emit the mapentry's value field and then
- * end the mapentry message. */
-
-static bool handle_mapentry(upb_json_parser *p) {
-  const upb_fielddef *mapfield;
-  const upb_msgdef *mapentrymsg;
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  /* Map entry: p->top->sink is the seq frame, so we need to start a frame
-   * for the mapentry itself, and then set |f| in that frame so that the map
-   * value field is parsed, and also set a flag to end the frame after the
-   * map-entry value is parsed. */
-  if (!check_stack(p)) return false;
-
-  mapfield = p->top->mapfield;
-  mapentrymsg = upb_fielddef_msgsubdef(mapfield);
-
-  inner = start_jsonparser_frame(p);
-  p->top->f = mapfield;
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
-  upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
-  inner->m = mapentrymsg;
-  inner->mapfield = mapfield;
-
-  /* Don't set this to true *yet* -- we reuse parsing handlers below to push
-   * the key field value to the sink, and these handlers will pop the frame
-   * if they see is_mapentry (when invoked by the parser state machine, they
-   * would have just seen the map-entry value, not key). */
-  inner->is_mapentry = false;
-  p->top = inner;
-
-  /* send STARTMSG in submsg frame. */
-  upb_sink_startmsg(p->top->sink);
-
-  parse_mapentry_key(p);
-
-  /* Set up the value field to receive the map-entry value. */
-  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
-  p->top->is_mapentry = true;  /* set up to pop frame after value is parsed. */
-  p->top->mapfield = mapfield;
-  if (p->top->f == NULL) {
-    upb_status_seterrmsg(p->status, "mapentry message has no value");
-    return false;
-  }
-
-  return true;
-}
-
-static bool end_membername(upb_json_parser *p) {
-  UPB_ASSERT(!p->top->f);
-
-  if (!p->top->m) {
-    p->top->is_unknown_field = true;
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return end_any_membername(p);
-  } else if (p->top->is_map) {
-    return handle_mapentry(p);
-  } else {
-    size_t len;
-    const char *buf = accumulate_getptr(p, &len);
-    upb_value v;
-
-    if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
-      p->top->f = upb_value_getconstptr(v);
-      multipart_end(p);
-
-      return true;
-    } else if (p->ignore_json_unknown) {
-      p->top->is_unknown_field = true;
-      multipart_end(p);
-      return true;
-    } else {
-      upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
-      return false;
-    }
-  }
-}
-
-static bool end_any_membername(upb_json_parser *p) {
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-  upb_value v;
-
-  if (len == 5 && strncmp(buf, "@type", len) == 0) {
-    upb_strtable_lookup2(p->top->name_table, "type_url", 8, &v);
-    p->top->f = upb_value_getconstptr(v);
-    multipart_end(p);
-    return true;
-  } else {
-    p->top->is_unknown_field = true;
-    multipart_end(p);
-    return true;
-  }
-}
-
-static void end_member(upb_json_parser *p) {
-  /* If we just parsed a map-entry value, end that frame too. */
-  if (p->top->is_mapentry) {
-    upb_selector_t sel;
-    bool ok;
-    const upb_fielddef *mapfield;
-
-    UPB_ASSERT(p->top > p->stack);
-    /* send ENDMSG on submsg. */
-    upb_sink_endmsg(p->top->sink, p->status);
-    mapfield = p->top->mapfield;
-
-    /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
-    p->top--;
-    ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
-    UPB_ASSUME(ok);
-    upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
-  }
-
-  p->top->f = NULL;
-  p->top->is_unknown_field = false;
-}
-
-static void start_any_member(upb_json_parser *p, const char *ptr) {
-  start_member(p);
-  json_parser_any_frame_set_after_type_url_start_once(p->top->any_frame, ptr);
-}
-
-static void end_any_member(upb_json_parser *p, const char *ptr) {
-  json_parser_any_frame_set_before_type_url_end(p->top->any_frame, ptr);
-  end_member(p);
-}
-
-static bool start_subobject(upb_json_parser *p) {
-  if (p->top->is_unknown_field) {
-    if (!check_stack(p)) return false;
-
-    p->top = start_jsonparser_frame(p);
-    return true;
-  }
-
-  if (upb_fielddef_ismap(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    /* Beginning of a map. Start a new parser frame in a repeated-field
-     * context. */
-    if (!check_stack(p)) return false;
-
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
-    upb_sink_startseq(p->top->sink, sel, &inner->sink);
-    inner->m = upb_fielddef_msgsubdef(p->top->f);
-    inner->mapfield = p->top->f;
-    inner->is_map = true;
-    p->top = inner;
-
-    return true;
-  } else if (upb_fielddef_issubmsg(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    /* Beginning of a subobject. Start a new parser frame in the submsg
-     * context. */
-    if (!check_stack(p)) return false;
-
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
-    upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
-    inner->m = upb_fielddef_msgsubdef(p->top->f);
-    set_name_table(p, inner);
-    p->top = inner;
-
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
-      p->top->is_any = true;
-      p->top->any_frame = json_parser_any_frame_new(p);
-    } else {
-      p->top->is_any = false;
-      p->top->any_frame = NULL;
-    }
-
-    return true;
-  } else {
-    upb_status_seterrf(p->status,
-                       "Object specified for non-message/group field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-}
-
-static bool start_subobject_full(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_STRUCTVALUE);
-      if (!start_subobject(p)) return false;
-      start_structvalue_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
-      start_structvalue_object(p);
-    } else {
-      return true;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_STRUCT)) {
-    if (!start_subobject(p)) return false;
-    start_structvalue_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) return false;
-    start_value_object(p, VALUE_STRUCTVALUE);
-    if (!start_subobject(p)) return false;
-    start_structvalue_object(p);
-  }
-
-  return start_subobject(p);
-}
-
-static void end_subobject(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    return;
-  }
-
-  if (p->top->is_map) {
-    upb_selector_t sel;
-    p->top--;
-    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
-    upb_sink_endseq(p->top->sink, sel);
-  } else {
-    upb_selector_t sel;
-    bool is_unknown = p->top->m == NULL;
-    p->top--;
-    if (!is_unknown) {
-      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
-      upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
-    }
-  }
-}
-
-static void end_subobject_full(upb_json_parser *p) {
-  end_subobject(p);
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
-    end_structvalue_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-}
-
-static bool start_array(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_LISTVALUE);
-      if (!start_subobject(p)) return false;
-      start_listvalue_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
-      start_listvalue_object(p);
-    } else {
-      return false;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_LISTVALUE) &&
-             (!upb_fielddef_isseq(p->top->f) ||
-              p->top->is_repeated)) {
-    if (!start_subobject(p)) return false;
-    start_listvalue_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE) &&
-             (!upb_fielddef_isseq(p->top->f) ||
-              p->top->is_repeated)) {
-    if (!start_subobject(p)) return false;
-    start_value_object(p, VALUE_LISTVALUE);
-    if (!start_subobject(p)) return false;
-    start_listvalue_object(p);
-  }
-
-  if (p->top->is_unknown_field) {
-    inner = start_jsonparser_frame(p);
-    inner->is_unknown_field = true;
-    p->top = inner;
-
-    return true;
-  }
-
-  if (!upb_fielddef_isseq(p->top->f)) {
-    upb_status_seterrf(p->status,
-                       "Array specified for non-repeated field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-
-  if (!check_stack(p)) return false;
-
-  inner = start_jsonparser_frame(p);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
-  upb_sink_startseq(p->top->sink, sel, &inner->sink);
-  inner->m = p->top->m;
-  inner->f = p->top->f;
-  inner->is_repeated = true;
-  p->top = inner;
-
-  return true;
-}
-
-static void end_array(upb_json_parser *p) {
-  upb_selector_t sel;
-
-  UPB_ASSERT(p->top > p->stack);
-
-  p->top--;
-
-  if (p->top->is_unknown_field) {
-    return;
-  }
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
-  upb_sink_endseq(p->top->sink, sel);
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
-    end_listvalue_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-}
-
-static void start_object(upb_json_parser *p) {
-  if (!p->top->is_map && p->top->m != NULL) {
-    upb_sink_startmsg(p->top->sink);
-  }
-}
-
-static void end_object(upb_json_parser *p) {
-  if (!p->top->is_map && p->top->m != NULL) {
-    upb_sink_endmsg(p->top->sink, p->status);
-  }
-}
-
-static void start_any_object(upb_json_parser *p, const char *ptr) {
-  start_object(p);
-  p->top->any_frame->before_type_url_start = ptr;
-  p->top->any_frame->before_type_url_end = ptr;
-}
-
-static bool end_any_object(upb_json_parser *p, const char *ptr) {
-  const char *value_membername = "value";
-  bool is_well_known_packed = false;
-  const char *packed_end = ptr + 1;
-  upb_selector_t sel;
-  upb_jsonparser_frame *inner;
-
-  if (json_parser_any_frame_has_value(p->top->any_frame) &&
-      !json_parser_any_frame_has_type_url(p->top->any_frame)) {
-    upb_status_seterrmsg(p->status, "No valid type url");
-    return false;
-  }
-
-  /* Well known types data is represented as value field. */
-  if (upb_msgdef_wellknowntype(p->top->any_frame->parser->top->m) !=
-          UPB_WELLKNOWN_UNSPECIFIED) {
-    is_well_known_packed = true;
-
-    if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
-      p->top->any_frame->before_type_url_start =
-          memchr(p->top->any_frame->before_type_url_start, ':',
-                 p->top->any_frame->before_type_url_end -
-                 p->top->any_frame->before_type_url_start);
-      if (p->top->any_frame->before_type_url_start == NULL) {
-        upb_status_seterrmsg(p->status, "invalid data for well known type.");
-        return false;
-      }
-      p->top->any_frame->before_type_url_start++;
-    }
-
-    if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-      p->top->any_frame->after_type_url_start =
-          memchr(p->top->any_frame->after_type_url_start, ':',
-                 (ptr + 1) -
-                 p->top->any_frame->after_type_url_start);
-      if (p->top->any_frame->after_type_url_start == NULL) {
-        upb_status_seterrmsg(p->status, "Invalid data for well known type.");
-        return false;
-      }
-      p->top->any_frame->after_type_url_start++;
-      packed_end = ptr;
-    }
-  }
-
-  if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL,
-               p->top->any_frame->before_type_url_start,
-               p->top->any_frame->before_type_url_end -
-               p->top->any_frame->before_type_url_start, NULL)) {
-      return false;
-    }
-  } else {
-    if (!is_well_known_packed) {
-      if (!parse(p->top->any_frame->parser, NULL, "{", 1, NULL)) {
-        return false;
-      }
-    }
-  }
-
-  if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame) &&
-      json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL, ",", 1, NULL)) {
-      return false;
-    }
-  }
-
-  if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL,
-               p->top->any_frame->after_type_url_start,
-               packed_end - p->top->any_frame->after_type_url_start, NULL)) {
-      return false;
-    }
-  } else {
-    if (!is_well_known_packed) {
-      if (!parse(p->top->any_frame->parser, NULL, "}", 1, NULL)) {
-        return false;
-      }
-    }
-  }
-
-  if (!end(p->top->any_frame->parser, NULL)) {
-    return false;
-  }
-
-  p->top->is_any = false;
-
-  /* Set value */
-  start_member(p);
-  capture_begin(p, value_membername);
-  capture_end(p, value_membername + 5);
-  end_membername(p);
-
-  if (!check_stack(p)) return false;
-  inner = p->top + 1;
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-  upb_sink_putstring(inner->sink, sel, p->top->any_frame->stringsink.ptr,
-                     p->top->any_frame->stringsink.len, NULL);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(inner->sink, sel);
-
-  end_member(p);
-
-  end_object(p);
-
-  /* Deallocate any parse frame. */
-  json_parser_any_frame_free(p->top->any_frame);
-
-  return true;
-}
-
-static bool is_string_wrapper(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type == UPB_WELLKNOWN_STRINGVALUE ||
-         type == UPB_WELLKNOWN_BYTESVALUE;
-}
-
-static bool is_fieldmask(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type == UPB_WELLKNOWN_FIELDMASK;
-}
-
-static void start_fieldmask_object(upb_json_parser *p) {
-  const char *membername = "paths";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + 5);
-  end_membername(p);
-
-  start_array(p);
-}
-
-static void end_fieldmask_object(upb_json_parser *p) {
-  end_array(p);
-  end_member(p);
-  end_object(p);
-}
-
-static void start_wrapper_object(upb_json_parser *p) {
-  const char *membername = "value";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + 5);
-  end_membername(p);
-}
-
-static void end_wrapper_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_value_object(upb_json_parser *p, int value_type) {
-  const char *nullmember = "null_value";
-  const char *numbermember = "number_value";
-  const char *stringmember = "string_value";
-  const char *boolmember = "bool_value";
-  const char *structmember = "struct_value";
-  const char *listmember = "list_value";
-  const char *membername = "";
-
-  switch (value_type) {
-    case VALUE_NULLVALUE:
-      membername = nullmember;
-      break;
-    case VALUE_NUMBERVALUE:
-      membername = numbermember;
-      break;
-    case VALUE_STRINGVALUE:
-      membername = stringmember;
-      break;
-    case VALUE_BOOLVALUE:
-      membername = boolmember;
-      break;
-    case VALUE_STRUCTVALUE:
-      membername = structmember;
-      break;
-    case VALUE_LISTVALUE:
-      membername = listmember;
-      break;
-  }
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_value_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_listvalue_object(upb_json_parser *p) {
-  const char *membername = "values";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_listvalue_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_structvalue_object(upb_json_parser *p) {
-  const char *membername = "fields";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_structvalue_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static bool is_top_level(upb_json_parser *p) {
-  return p->top == p->stack && p->top->f == NULL && !p->top->is_unknown_field;
-}
-
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type) {
-  return p->top->m != NULL && upb_msgdef_wellknowntype(p->top->m) == type;
-}
-
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         (upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(p->top->f))
-              == type);
-}
-
-static bool does_number_wrapper_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         upb_msgdef_isnumberwrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_number_wrapper_end(upb_json_parser *p) {
-  return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool is_number_wrapper_object(upb_json_parser *p) {
-  return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool does_string_wrapper_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         is_string_wrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_string_wrapper_end(upb_json_parser *p) {
-  return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool is_string_wrapper_object(upb_json_parser *p) {
-  return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool does_fieldmask_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         is_fieldmask(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_fieldmask_end(upb_json_parser *p) {
-  return p->top->m != NULL && is_fieldmask(p->top->m);
-}
-
-#define CHECK_RETURN_TOP(x) if (!(x)) goto error
-
-
-/* The actual parser **********************************************************/
-
-/* What follows is the Ragel parser itself.  The language is specified in Ragel
- * and the actions call our C functions above.
- *
- * Ragel has an extensive set of functionality, and we use only a small part of
- * it.  There are many action types but we only use a few:
- *
- *   ">" -- transition into a machine
- *   "%" -- transition out of a machine
- *   "@" -- transition into a final state of a machine.
- *
- * "@" transitions are tricky because a machine can transition into a final
- * state repeatedly.  But in some cases we know this can't happen, for example
- * a string which is delimited by a final '"' can only transition into its
- * final state once, when the closing '"' is seen. */
-
-
-#line 2780 "upb/json/parser.rl"
-
-
-
-#line 2583 "upb/json/parser.c"
-static const char _json_actions[] = {
-	0, 1, 0, 1, 1, 1, 3, 1, 
-	4, 1, 6, 1, 7, 1, 8, 1, 
-	9, 1, 11, 1, 12, 1, 13, 1, 
-	14, 1, 15, 1, 16, 1, 17, 1, 
-	18, 1, 19, 1, 20, 1, 22, 1, 
-	23, 1, 24, 1, 35, 1, 37, 1, 
-	39, 1, 40, 1, 42, 1, 43, 1, 
-	44, 1, 46, 1, 48, 1, 49, 1, 
-	50, 1, 51, 1, 53, 1, 54, 2, 
-	4, 9, 2, 5, 6, 2, 7, 3, 
-	2, 7, 9, 2, 21, 26, 2, 25, 
-	10, 2, 27, 28, 2, 29, 30, 2, 
-	32, 34, 2, 33, 31, 2, 38, 36, 
-	2, 40, 42, 2, 45, 2, 2, 46, 
-	54, 2, 47, 36, 2, 49, 54, 2, 
-	50, 54, 2, 51, 54, 2, 52, 41, 
-	2, 53, 54, 3, 32, 34, 35, 4, 
-	21, 26, 27, 28
-};
-
-static const short _json_key_offsets[] = {
-	0, 0, 12, 13, 18, 23, 28, 29, 
-	30, 31, 32, 33, 34, 35, 36, 37, 
-	38, 43, 44, 48, 53, 58, 63, 67, 
-	71, 74, 77, 79, 83, 87, 89, 91, 
-	96, 98, 100, 109, 115, 121, 127, 133, 
-	135, 139, 142, 144, 146, 149, 150, 154, 
-	156, 158, 160, 162, 163, 165, 167, 168, 
-	170, 172, 173, 175, 177, 178, 180, 182, 
-	183, 185, 187, 191, 193, 195, 196, 197, 
-	198, 199, 201, 206, 208, 210, 212, 221, 
-	222, 222, 222, 227, 232, 237, 238, 239, 
-	240, 241, 241, 242, 243, 244, 244, 245, 
-	246, 247, 247, 252, 253, 257, 262, 267, 
-	272, 276, 276, 279, 282, 285, 288, 291, 
-	294, 294, 294, 294, 294, 294
-};
-
-static const char _json_trans_keys[] = {
-	32, 34, 45, 91, 102, 110, 116, 123, 
-	9, 13, 48, 57, 34, 32, 93, 125, 
-	9, 13, 32, 44, 93, 9, 13, 32, 
-	93, 125, 9, 13, 97, 108, 115, 101, 
-	117, 108, 108, 114, 117, 101, 32, 34, 
-	125, 9, 13, 34, 32, 58, 9, 13, 
-	32, 93, 125, 9, 13, 32, 44, 125, 
-	9, 13, 32, 44, 125, 9, 13, 32, 
-	34, 9, 13, 45, 48, 49, 57, 48, 
-	49, 57, 46, 69, 101, 48, 57, 69, 
-	101, 48, 57, 43, 45, 48, 57, 48, 
-	57, 48, 57, 46, 69, 101, 48, 57, 
-	34, 92, 34, 92, 34, 47, 92, 98, 
-	102, 110, 114, 116, 117, 48, 57, 65, 
-	70, 97, 102, 48, 57, 65, 70, 97, 
-	102, 48, 57, 65, 70, 97, 102, 48, 
-	57, 65, 70, 97, 102, 34, 92, 45, 
-	48, 49, 57, 48, 49, 57, 46, 115, 
-	48, 57, 115, 48, 57, 34, 46, 115, 
-	48, 57, 48, 57, 48, 57, 48, 57, 
-	48, 57, 45, 48, 57, 48, 57, 45, 
-	48, 57, 48, 57, 84, 48, 57, 48, 
-	57, 58, 48, 57, 48, 57, 58, 48, 
-	57, 48, 57, 43, 45, 46, 90, 48, 
-	57, 48, 57, 58, 48, 48, 34, 48, 
-	57, 43, 45, 90, 48, 57, 34, 44, 
-	34, 44, 34, 44, 34, 45, 91, 102, 
-	110, 116, 123, 48, 57, 34, 32, 93, 
-	125, 9, 13, 32, 44, 93, 9, 13, 
-	32, 93, 125, 9, 13, 97, 108, 115, 
-	101, 117, 108, 108, 114, 117, 101, 32, 
-	34, 125, 9, 13, 34, 32, 58, 9, 
-	13, 32, 93, 125, 9, 13, 32, 44, 
-	125, 9, 13, 32, 44, 125, 9, 13, 
-	32, 34, 9, 13, 32, 9, 13, 32, 
-	9, 13, 32, 9, 13, 32, 9, 13, 
-	32, 9, 13, 32, 9, 13, 0
-};
-
-static const char _json_single_lengths[] = {
-	0, 8, 1, 3, 3, 3, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	3, 1, 2, 3, 3, 3, 2, 2, 
-	1, 3, 0, 2, 2, 0, 0, 3, 
-	2, 2, 9, 0, 0, 0, 0, 2, 
-	2, 1, 2, 0, 1, 1, 2, 0, 
-	0, 0, 0, 1, 0, 0, 1, 0, 
-	0, 1, 0, 0, 1, 0, 0, 1, 
-	0, 0, 4, 0, 0, 1, 1, 1, 
-	1, 0, 3, 2, 2, 2, 7, 1, 
-	0, 0, 3, 3, 3, 1, 1, 1, 
-	1, 0, 1, 1, 1, 0, 1, 1, 
-	1, 0, 3, 1, 2, 3, 3, 3, 
-	2, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const char _json_range_lengths[] = {
-	0, 2, 0, 1, 1, 1, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 3, 3, 3, 3, 0, 
-	1, 1, 0, 1, 1, 0, 1, 1, 
-	1, 1, 1, 0, 1, 1, 0, 1, 
-	1, 0, 1, 1, 0, 1, 1, 0, 
-	1, 1, 0, 1, 1, 0, 0, 0, 
-	0, 1, 1, 0, 0, 0, 1, 0, 
-	0, 0, 1, 1, 1, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 1, 0, 1, 1, 1, 1, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const short _json_index_offsets[] = {
-	0, 0, 11, 13, 18, 23, 28, 30, 
-	32, 34, 36, 38, 40, 42, 44, 46, 
-	48, 53, 55, 59, 64, 69, 74, 78, 
-	82, 85, 89, 91, 95, 99, 101, 103, 
-	108, 111, 114, 124, 128, 132, 136, 140, 
-	143, 147, 150, 153, 155, 158, 160, 164, 
-	166, 168, 170, 172, 174, 176, 178, 180, 
-	182, 184, 186, 188, 190, 192, 194, 196, 
-	198, 200, 202, 207, 209, 211, 213, 215, 
-	217, 219, 221, 226, 229, 232, 235, 244, 
-	246, 247, 248, 253, 258, 263, 265, 267, 
-	269, 271, 272, 274, 276, 278, 279, 281, 
-	283, 285, 286, 291, 293, 297, 302, 307, 
-	312, 316, 317, 320, 323, 326, 329, 332, 
-	335, 336, 337, 338, 339, 340
-};
-
-static const unsigned char _json_indicies[] = {
-	0, 2, 3, 4, 5, 6, 7, 8, 
-	0, 3, 1, 9, 1, 11, 12, 1, 
-	11, 10, 13, 14, 12, 13, 1, 14, 
-	1, 1, 14, 10, 15, 1, 16, 1, 
-	17, 1, 18, 1, 19, 1, 20, 1, 
-	21, 1, 22, 1, 23, 1, 24, 1, 
-	25, 26, 27, 25, 1, 28, 1, 29, 
-	30, 29, 1, 30, 1, 1, 30, 31, 
-	32, 33, 34, 32, 1, 35, 36, 27, 
-	35, 1, 36, 26, 36, 1, 37, 38, 
-	39, 1, 38, 39, 1, 41, 42, 42, 
-	40, 43, 1, 42, 42, 43, 40, 44, 
-	44, 45, 1, 45, 1, 45, 40, 41, 
-	42, 42, 39, 40, 47, 48, 46, 50, 
-	51, 49, 52, 52, 52, 52, 52, 52, 
-	52, 52, 53, 1, 54, 54, 54, 1, 
-	55, 55, 55, 1, 56, 56, 56, 1, 
-	57, 57, 57, 1, 59, 60, 58, 61, 
-	62, 63, 1, 64, 65, 1, 66, 67, 
-	1, 68, 1, 67, 68, 1, 69, 1, 
-	66, 67, 65, 1, 70, 1, 71, 1, 
-	72, 1, 73, 1, 74, 1, 75, 1, 
-	76, 1, 77, 1, 78, 1, 79, 1, 
-	80, 1, 81, 1, 82, 1, 83, 1, 
-	84, 1, 85, 1, 86, 1, 87, 1, 
-	88, 1, 89, 89, 90, 91, 1, 92, 
-	1, 93, 1, 94, 1, 95, 1, 96, 
-	1, 97, 1, 98, 1, 99, 99, 100, 
-	98, 1, 102, 1, 101, 104, 105, 103, 
-	1, 1, 101, 106, 107, 108, 109, 110, 
-	111, 112, 107, 1, 113, 1, 114, 115, 
-	117, 118, 1, 117, 116, 119, 120, 118, 
-	119, 1, 120, 1, 1, 120, 116, 121, 
-	1, 122, 1, 123, 1, 124, 1, 125, 
-	126, 1, 127, 1, 128, 1, 129, 130, 
-	1, 131, 1, 132, 1, 133, 134, 135, 
-	136, 134, 1, 137, 1, 138, 139, 138, 
-	1, 139, 1, 1, 139, 140, 141, 142, 
-	143, 141, 1, 144, 145, 136, 144, 1, 
-	145, 135, 145, 1, 146, 147, 147, 1, 
-	148, 148, 1, 149, 149, 1, 150, 150, 
-	1, 151, 151, 1, 152, 152, 1, 1, 
-	1, 1, 1, 1, 1, 0
-};
-
-static const char _json_trans_targs[] = {
-	1, 0, 2, 107, 3, 6, 10, 13, 
-	16, 106, 4, 3, 106, 4, 5, 7, 
-	8, 9, 108, 11, 12, 109, 14, 15, 
-	110, 16, 17, 111, 18, 18, 19, 20, 
-	21, 22, 111, 21, 22, 24, 25, 31, 
-	112, 26, 28, 27, 29, 30, 33, 113, 
-	34, 33, 113, 34, 32, 35, 36, 37, 
-	38, 39, 33, 113, 34, 41, 42, 46, 
-	42, 46, 43, 45, 44, 114, 48, 49, 
-	50, 51, 52, 53, 54, 55, 56, 57, 
-	58, 59, 60, 61, 62, 63, 64, 65, 
-	66, 67, 73, 72, 68, 69, 70, 71, 
-	72, 115, 74, 67, 72, 76, 116, 76, 
-	116, 77, 79, 81, 82, 85, 90, 94, 
-	98, 80, 117, 117, 83, 82, 80, 83, 
-	84, 86, 87, 88, 89, 117, 91, 92, 
-	93, 117, 95, 96, 97, 117, 98, 99, 
-	105, 100, 100, 101, 102, 103, 104, 105, 
-	103, 104, 117, 106, 106, 106, 106, 106, 
-	106
-};
-
-static const unsigned char _json_trans_actions[] = {
-	0, 0, 113, 107, 53, 0, 0, 0, 
-	125, 59, 45, 0, 55, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 101, 51, 47, 0, 0, 45, 
-	49, 49, 104, 0, 0, 0, 0, 0, 
-	3, 0, 0, 0, 0, 0, 5, 15, 
-	0, 0, 71, 7, 13, 0, 74, 9, 
-	9, 9, 77, 80, 11, 37, 37, 37, 
-	0, 0, 0, 39, 0, 41, 86, 0, 
-	0, 0, 17, 19, 0, 21, 23, 0, 
-	25, 27, 0, 29, 31, 0, 33, 35, 
-	0, 135, 83, 135, 0, 0, 0, 0, 
-	0, 92, 0, 89, 89, 98, 43, 0, 
-	131, 95, 113, 107, 53, 0, 0, 0, 
-	125, 59, 69, 110, 45, 0, 55, 0, 
-	0, 0, 0, 0, 0, 119, 0, 0, 
-	0, 122, 0, 0, 0, 116, 0, 101, 
-	51, 47, 0, 0, 45, 49, 49, 104, 
-	0, 0, 128, 0, 57, 63, 65, 61, 
-	67
-};
-
-static const unsigned char _json_eof_actions[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 1, 0, 1, 0, 0, 1, 1, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 57, 63, 65, 61, 67, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const int json_start = 1;
-
-static const int json_en_number_machine = 23;
-static const int json_en_string_machine = 32;
-static const int json_en_duration_machine = 40;
-static const int json_en_timestamp_machine = 47;
-static const int json_en_fieldmask_machine = 75;
-static const int json_en_value_machine = 78;
-static const int json_en_main = 1;
-
-
-#line 2783 "upb/json/parser.rl"
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
-             const upb_bufhandle *handle) {
-  upb_json_parser *parser = closure;
-
-  /* Variables used by Ragel's generated code. */
-  int cs = parser->current_state;
-  int *stack = parser->parser_stack;
-  int top = parser->parser_top;
-
-  const char *p = buf;
-  const char *pe = buf + size;
-  const char *eof = &eof_ch;
-
-  parser->handle = handle;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  capture_resume(parser, buf);
-
-  
-#line 2861 "upb/json/parser.c"
-	{
-	int _klen;
-	unsigned int _trans;
-	const char *_acts;
-	unsigned int _nacts;
-	const char *_keys;
-
-	if ( p == pe )
-		goto _test_eof;
-	if ( cs == 0 )
-		goto _out;
-_resume:
-	_keys = _json_trans_keys + _json_key_offsets[cs];
-	_trans = _json_index_offsets[cs];
-
-	_klen = _json_single_lengths[cs];
-	if ( _klen > 0 ) {
-		const char *_lower = _keys;
-		const char *_mid;
-		const char *_upper = _keys + _klen - 1;
-		while (1) {
-			if ( _upper < _lower )
-				break;
-
-			_mid = _lower + ((_upper-_lower) >> 1);
-			if ( (*p) < *_mid )
-				_upper = _mid - 1;
-			else if ( (*p) > *_mid )
-				_lower = _mid + 1;
-			else {
-				_trans += (unsigned int)(_mid - _keys);
-				goto _match;
-			}
-		}
-		_keys += _klen;
-		_trans += _klen;
-	}
-
-	_klen = _json_range_lengths[cs];
-	if ( _klen > 0 ) {
-		const char *_lower = _keys;
-		const char *_mid;
-		const char *_upper = _keys + (_klen<<1) - 2;
-		while (1) {
-			if ( _upper < _lower )
-				break;
-
-			_mid = _lower + (((_upper-_lower) >> 1) & ~1);
-			if ( (*p) < _mid[0] )
-				_upper = _mid - 2;
-			else if ( (*p) > _mid[1] )
-				_lower = _mid + 2;
-			else {
-				_trans += (unsigned int)((_mid - _keys)>>1);
-				goto _match;
-			}
-		}
-		_trans += _klen;
-	}
-
-_match:
-	_trans = _json_indicies[_trans];
-	cs = _json_trans_targs[_trans];
-
-	if ( _json_trans_actions[_trans] == 0 )
-		goto _again;
-
-	_acts = _json_actions + _json_trans_actions[_trans];
-	_nacts = (unsigned int) *_acts++;
-	while ( _nacts-- > 0 )
-	{
-		switch ( *_acts++ )
-		{
-	case 1:
-#line 2588 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 2:
-#line 2590 "upb/json/parser.rl"
-	{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
-	break;
-	case 3:
-#line 2594 "upb/json/parser.rl"
-	{ start_text(parser, p); }
-	break;
-	case 4:
-#line 2595 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_text(parser, p)); }
-	break;
-	case 5:
-#line 2601 "upb/json/parser.rl"
-	{ start_hex(parser); }
-	break;
-	case 6:
-#line 2602 "upb/json/parser.rl"
-	{ hexdigit(parser, p); }
-	break;
-	case 7:
-#line 2603 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_hex(parser)); }
-	break;
-	case 8:
-#line 2609 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(escape(parser, p)); }
-	break;
-	case 9:
-#line 2615 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 10:
-#line 2620 "upb/json/parser.rl"
-	{ start_year(parser, p); }
-	break;
-	case 11:
-#line 2621 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_year(parser, p)); }
-	break;
-	case 12:
-#line 2625 "upb/json/parser.rl"
-	{ start_month(parser, p); }
-	break;
-	case 13:
-#line 2626 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_month(parser, p)); }
-	break;
-	case 14:
-#line 2630 "upb/json/parser.rl"
-	{ start_day(parser, p); }
-	break;
-	case 15:
-#line 2631 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_day(parser, p)); }
-	break;
-	case 16:
-#line 2635 "upb/json/parser.rl"
-	{ start_hour(parser, p); }
-	break;
-	case 17:
-#line 2636 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_hour(parser, p)); }
-	break;
-	case 18:
-#line 2640 "upb/json/parser.rl"
-	{ start_minute(parser, p); }
-	break;
-	case 19:
-#line 2641 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_minute(parser, p)); }
-	break;
-	case 20:
-#line 2645 "upb/json/parser.rl"
-	{ start_second(parser, p); }
-	break;
-	case 21:
-#line 2646 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_second(parser, p)); }
-	break;
-	case 22:
-#line 2651 "upb/json/parser.rl"
-	{ start_duration_base(parser, p); }
-	break;
-	case 23:
-#line 2652 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
-	break;
-	case 24:
-#line 2654 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 25:
-#line 2659 "upb/json/parser.rl"
-	{ start_timestamp_base(parser); }
-	break;
-	case 26:
-#line 2661 "upb/json/parser.rl"
-	{ start_timestamp_fraction(parser, p); }
-	break;
-	case 27:
-#line 2662 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
-	break;
-	case 28:
-#line 2664 "upb/json/parser.rl"
-	{ start_timestamp_zone(parser, p); }
-	break;
-	case 29:
-#line 2665 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
-	break;
-	case 30:
-#line 2667 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 31:
-#line 2672 "upb/json/parser.rl"
-	{ start_fieldmask_path_text(parser, p); }
-	break;
-	case 32:
-#line 2673 "upb/json/parser.rl"
-	{ end_fieldmask_path_text(parser, p); }
-	break;
-	case 33:
-#line 2678 "upb/json/parser.rl"
-	{ start_fieldmask_path(parser); }
-	break;
-	case 34:
-#line 2679 "upb/json/parser.rl"
-	{ end_fieldmask_path(parser); }
-	break;
-	case 35:
-#line 2685 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 36:
-#line 2690 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
-          {stack[top++] = cs; cs = 47;goto _again;}
-        } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_DURATION)) {
-          {stack[top++] = cs; cs = 40;goto _again;}
-        } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_FIELDMASK)) {
-          {stack[top++] = cs; cs = 75;goto _again;}
-        } else {
-          {stack[top++] = cs; cs = 32;goto _again;}
-        }
-      }
-	break;
-	case 37:
-#line 2703 "upb/json/parser.rl"
-	{ p--; {stack[top++] = cs; cs = 78;goto _again;} }
-	break;
-	case 38:
-#line 2708 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          start_any_member(parser, p);
-        } else {
-          start_member(parser);
-        }
-      }
-	break;
-	case 39:
-#line 2715 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_membername(parser)); }
-	break;
-	case 40:
-#line 2718 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          end_any_member(parser, p);
-        } else {
-          end_member(parser);
-        }
-      }
-	break;
-	case 41:
-#line 2729 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          start_any_object(parser, p);
-        } else {
-          start_object(parser);
-        }
-      }
-	break;
-	case 42:
-#line 2738 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          CHECK_RETURN_TOP(end_any_object(parser, p));
-        } else {
-          end_object(parser);
-        }
-      }
-	break;
-	case 43:
-#line 2750 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_array(parser)); }
-	break;
-	case 44:
-#line 2754 "upb/json/parser.rl"
-	{ end_array(parser); }
-	break;
-	case 45:
-#line 2759 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_number(parser, p)); }
-	break;
-	case 46:
-#line 2760 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_number(parser, p)); }
-	break;
-	case 47:
-#line 2762 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_stringval(parser)); }
-	break;
-	case 48:
-#line 2763 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_stringval(parser)); }
-	break;
-	case 49:
-#line 2765 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
-	break;
-	case 50:
-#line 2767 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
-	break;
-	case 51:
-#line 2769 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_null(parser)); }
-	break;
-	case 52:
-#line 2771 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
-	break;
-	case 53:
-#line 2772 "upb/json/parser.rl"
-	{ end_subobject_full(parser); }
-	break;
-	case 54:
-#line 2777 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-#line 3185 "upb/json/parser.c"
-		}
-	}
-
-_again:
-	if ( cs == 0 )
-		goto _out;
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	const char *__acts = _json_actions + _json_eof_actions[cs];
-	unsigned int __nacts = (unsigned int) *__acts++;
-	while ( __nacts-- > 0 ) {
-		switch ( *__acts++ ) {
-	case 0:
-#line 2586 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; 	if ( p == pe )
-		goto _test_eof;
-goto _again;} }
-	break;
-	case 46:
-#line 2760 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_number(parser, p)); }
-	break;
-	case 49:
-#line 2765 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
-	break;
-	case 50:
-#line 2767 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
-	break;
-	case 51:
-#line 2769 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_null(parser)); }
-	break;
-	case 53:
-#line 2772 "upb/json/parser.rl"
-	{ end_subobject_full(parser); }
-	break;
-#line 3227 "upb/json/parser.c"
-		}
-	}
-	}
-
-	_out: {}
-	}
-
-#line 2805 "upb/json/parser.rl"
-
-  if (p != pe) {
-    upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
-  } else {
-    capture_suspend(parser, &p);
-  }
-
-error:
-  /* Save parsing state back to parser. */
-  parser->current_state = cs;
-  parser->parser_top = top;
-
-  return p - buf;
-}
-
-static bool end(void *closure, const void *hd) {
-  upb_json_parser *parser = closure;
-
-  /* Prevent compile warning on unused static constants. */
-  UPB_UNUSED(json_start);
-  UPB_UNUSED(json_en_duration_machine);
-  UPB_UNUSED(json_en_fieldmask_machine);
-  UPB_UNUSED(json_en_number_machine);
-  UPB_UNUSED(json_en_string_machine);
-  UPB_UNUSED(json_en_timestamp_machine);
-  UPB_UNUSED(json_en_value_machine);
-  UPB_UNUSED(json_en_main);
-
-  parse(parser, hd, &eof_ch, 0, NULL);
-
-  return parser->current_state >= 106;
-}
-
-static void json_parser_reset(upb_json_parser *p) {
-  int cs;
-  int top;
-
-  p->top = p->stack;
-  init_frame(p->top);
-
-  /* Emit Ragel initialization of the parser. */
-  
-#line 3278 "upb/json/parser.c"
-	{
-	cs = json_start;
-	top = 0;
-	}
-
-#line 2847 "upb/json/parser.rl"
-  p->current_state = cs;
-  p->parser_top = top;
-  accumulate_clear(p);
-  p->multipart_state = MULTIPART_INACTIVE;
-  p->capture = NULL;
-  p->accumulated = NULL;
-}
-
-static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
-                                               const upb_msgdef *md) {
-  upb_msg_field_iter i;
-  upb_alloc *alloc = upb_arena_alloc(c->arena);
-
-  upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
-
-  m->cache = c;
-
-  upb_byteshandler_init(&m->input_handler_);
-  upb_byteshandler_setstring(&m->input_handler_, parse, m);
-  upb_byteshandler_setendstr(&m->input_handler_, end, m);
-
-  upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc);
-
-  /* Build name_table */
-
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_value v = upb_value_constptr(f);
-    const char *name;
-
-    /* Add an entry for the JSON name. */
-    name = upb_fielddef_jsonname(f);
-    upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
-
-    if (strcmp(name, upb_fielddef_name(f)) != 0) {
-      /* Since the JSON name is different from the regular field name, add an
-       * entry for the raw name (compliant proto3 JSON parsers must accept
-       * both). */
-      const char *name = upb_fielddef_name(f);
-      upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
-    }
-  }
-
-  return m;
-}
-
-/* Public API *****************************************************************/
-
-upb_json_parser *upb_json_parser_create(upb_arena *arena,
-                                        const upb_json_parsermethod *method,
-                                        const upb_symtab* symtab,
-                                        upb_sink output,
-                                        upb_status *status,
-                                        bool ignore_json_unknown) {
-#ifndef NDEBUG
-  const size_t size_before = upb_arena_bytesallocated(arena);
-#endif
-  upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
-  if (!p) return false;
-
-  p->arena = arena;
-  p->method = method;
-  p->status = status;
-  p->limit = p->stack + UPB_JSON_MAX_DEPTH;
-  p->accumulate_buf = NULL;
-  p->accumulate_buf_size = 0;
-  upb_bytessink_reset(&p->input_, &method->input_handler_, p);
-
-  json_parser_reset(p);
-  p->top->sink = output;
-  p->top->m = upb_handlers_msgdef(output.handlers);
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
-    p->top->is_any = true;
-    p->top->any_frame = json_parser_any_frame_new(p);
-  } else {
-    p->top->is_any = false;
-    p->top->any_frame = NULL;
-  }
-  set_name_table(p, p->top);
-  p->symtab = symtab;
-
-  p->ignore_json_unknown = ignore_json_unknown;
-
-  /* If this fails, uncomment and increase the value in parser.h. */
-  /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
-                      UPB_JSON_PARSER_SIZE);
-  return p;
-}
-
-upb_bytessink upb_json_parser_input(upb_json_parser *p) {
-  return p->input_;
-}
-
-const upb_byteshandler *upb_json_parsermethod_inputhandler(
-    const upb_json_parsermethod *m) {
-  return &m->input_handler_;
-}
-
-upb_json_codecache *upb_json_codecache_new(void) {
-  upb_alloc *alloc;
-  upb_json_codecache *c;
-
-  c = upb_gmalloc(sizeof(*c));
-
-  c->arena = upb_arena_new();
-  alloc = upb_arena_alloc(c->arena);
-
-  upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
-
-  return c;
-}
-
-void upb_json_codecache_free(upb_json_codecache *c) {
-  upb_arena_free(c->arena);
-  upb_gfree(c);
-}
-
-const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
-                                                    const upb_msgdef *md) {
-  upb_json_parsermethod *m;
-  upb_value v;
-  upb_msg_field_iter i;
-  upb_alloc *alloc = upb_arena_alloc(c->arena);
-
-  if (upb_inttable_lookupptr(&c->methods, md, &v)) {
-    return upb_value_getconstptr(v);
-  }
-
-  m = parsermethod_new(c, md);
-  v = upb_value_constptr(m);
-
-  if (!m) return NULL;
-  if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL;
-
-  /* Populate parser methods for all submessages, so the name tables will
-   * be available during parsing. */
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
-      const upb_json_parsermethod *sub_method =
-          upb_json_codecache_get(c, subdef);
-
-      if (!sub_method) return NULL;
-    }
-  }
-
-  return m;
-}
-/*
-** This currently uses snprintf() to format primitives, and could be optimized
-** further.
-*/
-
-
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <string.h>
-#include <time.h>
-
-
-struct upb_json_printer {
-  upb_sink input_;
-  /* BytesSink closure. */
-  void *subc_;
-  upb_bytessink output_;
-
-  /* We track the depth so that we know when to emit startstr/endstr on the
-   * output. */
-  int depth_;
-
-  /* Have we emitted the first element? This state is necessary to emit commas
-   * without leaving a trailing comma in arrays/maps. We keep this state per
-   * frame depth.
-   *
-   * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
-   * We count frames (contexts in which we separate elements by commas) as both
-   * repeated fields and messages (maps), and the worst case is a
-   * message->repeated field->submessage->repeated field->... nesting. */
-  bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
-
-  /* To print timestamp, printer needs to cache its seconds and nanos values
-   * and convert them when ending timestamp message. See comments of
-   * printer_sethandlers_timestamp for more detail. */
-  int64_t seconds;
-  int32_t nanos;
-};
-
-/* StringPiece; a pointer plus a length. */
-typedef struct {
-  char *ptr;
-  size_t len;
-} strpc;
-
-void freestrpc(void *ptr) {
-  strpc *pc = ptr;
-  upb_gfree(pc->ptr);
-  upb_gfree(pc);
-}
-
-typedef struct {
-  bool preserve_fieldnames;
-} upb_json_printercache;
-
-/* Convert fielddef name to JSON name and return as a string piece. */
-strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
-                bool preserve_fieldnames) {
-  /* TODO(haberman): handle malloc failure. */
-  strpc *ret = upb_gmalloc(sizeof(*ret));
-  if (preserve_fieldnames) {
-    ret->ptr = upb_gstrdup(upb_fielddef_name(f));
-    ret->len = strlen(ret->ptr);
-  } else {
-    ret->ptr = upb_gstrdup(upb_fielddef_jsonname(f));
-    ret->len = strlen(ret->ptr);
-  }
-
-  upb_handlers_addcleanup(h, ret, freestrpc);
-  return ret;
-}
-
-/* Convert a null-terminated const char* to a string piece. */
-strpc *newstrpc_str(upb_handlers *h, const char * str) {
-  strpc * ret = upb_gmalloc(sizeof(*ret));
-  ret->ptr = upb_gstrdup(str);
-  ret->len = strlen(str);
-  upb_handlers_addcleanup(h, ret, freestrpc);
-  return ret;
-}
-
-/* ------------ JSON string printing: values, maps, arrays ------------------ */
-
-static void print_data(
-    upb_json_printer *p, const char *buf, size_t len) {
-  /* TODO: Will need to change if we support pushback from the sink. */
-  size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
-  UPB_ASSERT(n == len);
-}
-
-static void print_comma(upb_json_printer *p) {
-  if (!p->first_elem_[p->depth_]) {
-    print_data(p, ",", 1);
-  }
-  p->first_elem_[p->depth_] = false;
-}
-
-/* Helpers that print properly formatted elements to the JSON output stream. */
-
-/* Used for escaping control chars in strings. */
-static const char kControlCharLimit = 0x20;
-
-UPB_INLINE bool is_json_escaped(char c) {
-  /* See RFC 4627. */
-  unsigned char uc = (unsigned char)c;
-  return uc < kControlCharLimit || uc == '"' || uc == '\\';
-}
-
-UPB_INLINE const char* json_nice_escape(char c) {
-  switch (c) {
-    case '"':  return "\\\"";
-    case '\\': return "\\\\";
-    case '\b': return "\\b";
-    case '\f': return "\\f";
-    case '\n': return "\\n";
-    case '\r': return "\\r";
-    case '\t': return "\\t";
-    default:   return NULL;
-  }
-}
-
-/* Write a properly escaped string chunk. The surrounding quotes are *not*
- * printed; this is so that the caller has the option of emitting the string
- * content in chunks. */
-static void putstring(upb_json_printer *p, const char *buf, size_t len) {
-  const char* unescaped_run = NULL;
-  unsigned int i;
-  for (i = 0; i < len; i++) {
-    char c = buf[i];
-    /* Handle escaping. */
-    if (is_json_escaped(c)) {
-      /* Use a "nice" escape, like \n, if one exists for this character. */
-      const char* escape = json_nice_escape(c);
-      /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
-       * escape. */
-      char escape_buf[8];
-      if (!escape) {
-        unsigned char byte = (unsigned char)c;
-        _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
-        escape = escape_buf;
-      }
-
-      /* N.B. that we assume that the input encoding is equal to the output
-       * encoding (both UTF-8 for  now), so for chars >= 0x20 and != \, ", we
-       * can simply pass the bytes through. */
-
-      /* If there's a current run of unescaped chars, print that run first. */
-      if (unescaped_run) {
-        print_data(p, unescaped_run, &buf[i] - unescaped_run);
-        unescaped_run = NULL;
-      }
-      /* Then print the escape code. */
-      print_data(p, escape, strlen(escape));
-    } else {
-      /* Add to the current unescaped run of characters. */
-      if (unescaped_run == NULL) {
-        unescaped_run = &buf[i];
-      }
-    }
-  }
-
-  /* If the string ended in a run of unescaped characters, print that last run. */
-  if (unescaped_run) {
-    print_data(p, unescaped_run, &buf[len] - unescaped_run);
-  }
-}
-
-#define CHKLENGTH(x) if (!(x)) return -1;
-
-/* Helpers that format floating point values according to our custom formats.
- * Right now we use %.8g and %.17g for float/double, respectively, to match
- * proto2::util::JsonFormat's defaults.  May want to change this later. */
-
-const char neginf[] = "\"-Infinity\"";
-const char inf[] = "\"Infinity\"";
-
-static size_t fmt_double(double val, char* buf, size_t length) {
-  if (val == UPB_INFINITY) {
-    CHKLENGTH(length >= strlen(inf));
-    strcpy(buf, inf);
-    return strlen(inf);
-  } else if (val == -UPB_INFINITY) {
-    CHKLENGTH(length >= strlen(neginf));
-    strcpy(buf, neginf);
-    return strlen(neginf);
-  } else {
-    size_t n = _upb_snprintf(buf, length, "%.17g", val);
-    CHKLENGTH(n > 0 && n < length);
-    return n;
-  }
-}
-
-static size_t fmt_float(float val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%.8g", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_bool(bool val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_int64_as_number(int64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%" PRId64, val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_uint64_as_number(uint64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%" PRIu64, val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_int64_as_string(int64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "\"%" PRId64 "\"", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_uint64_as_string(uint64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "\"%" PRIu64 "\"", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-/* Print a map key given a field name. Called by scalar field handlers and by
- * startseq for repeated fields. */
-static bool putkey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  const strpc *key = handler_data;
-  print_comma(p);
-  print_data(p, "\"", 1);
-  putstring(p, key->ptr, key->len);
-  print_data(p, "\":", 2);
-  return true;
-}
-
-#define CHKFMT(val) if ((val) == (size_t)-1) return false;
-#define CHK(val)    if (!(val)) return false;
-
-#define TYPE_HANDLERS(type, fmt_func)                                        \
-  static bool put##type(void *closure, const void *handler_data, type val) { \
-    upb_json_printer *p = closure;                                           \
-    char data[64];                                                           \
-    size_t length = fmt_func(val, data, sizeof(data));                       \
-    UPB_UNUSED(handler_data);                                                \
-    CHKFMT(length);                                                          \
-    print_data(p, data, length);                                             \
-    return true;                                                             \
-  }                                                                          \
-  static bool scalar_##type(void *closure, const void *handler_data,         \
-                            type val) {                                      \
-    CHK(putkey(closure, handler_data));                                      \
-    CHK(put##type(closure, handler_data, val));                              \
-    return true;                                                             \
-  }                                                                          \
-  static bool repeated_##type(void *closure, const void *handler_data,       \
-                              type val) {                                    \
-    upb_json_printer *p = closure;                                           \
-    print_comma(p);                                                          \
-    CHK(put##type(closure, handler_data, val));                              \
-    return true;                                                             \
-  }
-
-#define TYPE_HANDLERS_MAPKEY(type, fmt_func)                                 \
-  static bool putmapkey_##type(void *closure, const void *handler_data,      \
-                            type val) {                                      \
-    upb_json_printer *p = closure;                                           \
-    char data[64];                                                           \
-    size_t length = fmt_func(val, data, sizeof(data));                       \
-    UPB_UNUSED(handler_data);                                                \
-    print_data(p, "\"", 1);                                                  \
-    print_data(p, data, length);                                             \
-    print_data(p, "\":", 2);                                                 \
-    return true;                                                             \
-  }
-
-TYPE_HANDLERS(double,   fmt_double)
-TYPE_HANDLERS(float,    fmt_float)
-TYPE_HANDLERS(bool,     fmt_bool)
-TYPE_HANDLERS(int32_t,  fmt_int64_as_number)
-TYPE_HANDLERS(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS(int64_t,  fmt_int64_as_string)
-TYPE_HANDLERS(uint64_t, fmt_uint64_as_string)
-
-/* double and float are not allowed to be map keys. */
-TYPE_HANDLERS_MAPKEY(bool,     fmt_bool)
-TYPE_HANDLERS_MAPKEY(int32_t,  fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(int64_t,  fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64_as_number)
-
-#undef TYPE_HANDLERS
-#undef TYPE_HANDLERS_MAPKEY
-
-typedef struct {
-  void *keyname;
-  const upb_enumdef *enumdef;
-} EnumHandlerData;
-
-static bool scalar_enum(void *closure, const void *handler_data,
-                        int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-  const char *symbolic_name;
-
-  CHK(putkey(closure, hd->keyname));
-
-  symbolic_name = upb_enumdef_iton(hd->enumdef, val);
-  if (symbolic_name) {
-    print_data(p, "\"", 1);
-    putstring(p, symbolic_name, strlen(symbolic_name));
-    print_data(p, "\"", 1);
-  } else {
-    putint32_t(closure, NULL, val);
-  }
-
-  return true;
-}
-
-static void print_enum_symbolic_name(upb_json_printer *p,
-                                     const upb_enumdef *def,
-                                     int32_t val) {
-  const char *symbolic_name = upb_enumdef_iton(def, val);
-  if (symbolic_name) {
-    print_data(p, "\"", 1);
-    putstring(p, symbolic_name, strlen(symbolic_name));
-    print_data(p, "\"", 1);
-  } else {
-    putint32_t(p, NULL, val);
-  }
-}
-
-static bool repeated_enum(void *closure, const void *handler_data,
-                          int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-  print_comma(p);
-
-  print_enum_symbolic_name(p, hd->enumdef, val);
-
-  return true;
-}
-
-static bool mapvalue_enum(void *closure, const void *handler_data,
-                          int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-
-  print_enum_symbolic_name(p, hd->enumdef, val);
-
-  return true;
-}
-
-static void *scalar_startsubmsg(void *closure, const void *handler_data) {
-  return putkey(closure, handler_data) ? closure : UPB_BREAK;
-}
-
-static void *repeated_startsubmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_comma(p);
-  return closure;
-}
-
-static void start_frame(upb_json_printer *p) {
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-}
-
-static void end_frame(upb_json_printer *p) {
-  print_data(p, "}", 1);
-  p->depth_--;
-}
-
-static bool printer_startmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  start_frame(p);
-  return true;
-}
-
-static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  end_frame(p);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static void *startseq(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  CHK(putkey(closure, handler_data));
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "[", 1);
-  return closure;
-}
-
-static bool endseq(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "]", 1);
-  p->depth_--;
-  return true;
-}
-
-static void *startmap(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  CHK(putkey(closure, handler_data));
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-  return closure;
-}
-
-static bool endmap(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "}", 1);
-  p->depth_--;
-  return true;
-}
-
-static size_t putstr(void *closure, const void *handler_data, const char *str,
-                     size_t len, const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-  putstring(p, str, len);
-  return len;
-}
-
-/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
-static size_t putbytes(void *closure, const void *handler_data, const char *str,
-                       size_t len, const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-
-  /* This is the regular base64, not the "web-safe" version. */
-  static const char base64[] =
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-  /* Base64-encode. */
-  char data[16000];
-  const char *limit = data + sizeof(data);
-  const unsigned char *from = (const unsigned char*)str;
-  char *to = data;
-  size_t remaining = len;
-  size_t bytes;
-
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-
-  print_data(p, "\"", 1);
-
-  while (remaining > 2) {
-    if (limit - to < 4) {
-      bytes = to - data;
-      putstring(p, data, bytes);
-      to = data;
-    }
-
-    to[0] = base64[from[0] >> 2];
-    to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
-    to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
-    to[3] = base64[from[2] & 0x3f];
-
-    remaining -= 3;
-    to += 4;
-    from += 3;
-  }
-
-  switch (remaining) {
-    case 2:
-      to[0] = base64[from[0] >> 2];
-      to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
-      to[2] = base64[(from[1] & 0xf) << 2];
-      to[3] = '=';
-      to += 4;
-      from += 2;
-      break;
-    case 1:
-      to[0] = base64[from[0] >> 2];
-      to[1] = base64[((from[0] & 0x3) << 4)];
-      to[2] = '=';
-      to[3] = '=';
-      to += 4;
-      from += 1;
-      break;
-  }
-
-  bytes = to - data;
-  putstring(p, data, bytes);
-  print_data(p, "\"", 1);
-  return len;
-}
-
-static void *scalar_startstr(void *closure, const void *handler_data,
-                             size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  CHK(putkey(closure, handler_data));
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t scalar_str(void *closure, const void *handler_data,
-                         const char *str, size_t len,
-                         const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool scalar_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static void *repeated_startstr(void *closure, const void *handler_data,
-                               size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_comma(p);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t repeated_str(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool repeated_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static void *mapkeyval_startstr(void *closure, const void *handler_data,
-                                size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t mapkey_str(void *closure, const void *handler_data,
-                         const char *str, size_t len,
-                         const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool mapkey_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\":", 2);
-  return true;
-}
-
-static bool mapvalue_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static size_t scalar_bytes(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  CHK(putkey(closure, handler_data));
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static size_t repeated_bytes(void *closure, const void *handler_data,
-                             const char *str, size_t len,
-                             const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  print_comma(p);
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static size_t mapkey_bytes(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  print_data(p, ":", 1);
-  return len;
-}
-
-static void set_enum_hd(upb_handlers *h,
-                        const upb_fielddef *f,
-                        bool preserve_fieldnames,
-                        upb_handlerattr *attr) {
-  EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
-  hd->enumdef = upb_fielddef_enumsubdef(f);
-  hd->keyname = newstrpc(h, f, preserve_fieldnames);
-  upb_handlers_addcleanup(h, hd, upb_gfree);
-  attr->handler_data = hd;
-}
-
-/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
- * in a map).
- *
- * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
- * key or value cases properly. The right way to do this is to allocate a
- * temporary structure at the start of a mapentry submessage, store key and
- * value data in it as key and value handlers are called, and then print the
- * key/value pair once at the end of the submessage. If we don't do this, we
- * should at least detect the case and throw an error. However, so far all of
- * our sources that emit mapentry messages do so canonically (with one key
- * field, and then one value field), so this is not a pressing concern at the
- * moment. */
-void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
-                                  upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  /* A mapentry message is printed simply as '"key": value'. Rather than
-   * special-case key and value for every type below, we just handle both
-   * fields explicitly here. */
-  const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
-  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  UPB_UNUSED(closure);
-
-  switch (upb_fielddef_type(key_field)) {
-    case UPB_TYPE_INT32:
-      upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
-      break;
-    case UPB_TYPE_INT64:
-      upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT32:
-      upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT64:
-      upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_BOOL:
-      upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
-      break;
-    case UPB_TYPE_STRING:
-      upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
-      upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
-      upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
-      break;
-    case UPB_TYPE_BYTES:
-      upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
-      break;
-    default:
-      UPB_ASSERT(false);
-      break;
-  }
-
-  switch (upb_fielddef_type(value_field)) {
-    case UPB_TYPE_INT32:
-      upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_INT64:
-      upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT32:
-      upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT64:
-      upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_BOOL:
-      upb_handlers_setbool(h, value_field, putbool, &empty_attr);
-      break;
-    case UPB_TYPE_FLOAT:
-      upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
-      break;
-    case UPB_TYPE_DOUBLE:
-      upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
-      break;
-    case UPB_TYPE_STRING:
-      upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
-      upb_handlers_setstring(h, value_field, putstr, &empty_attr);
-      upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
-      break;
-    case UPB_TYPE_BYTES:
-      upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
-      break;
-    case UPB_TYPE_ENUM: {
-      upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
-      set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
-      upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE:
-      /* No handler necessary -- the submsg handlers will print the message
-       * as appropriate. */
-      break;
-  }
-}
-
-static bool putseconds(void *closure, const void *handler_data,
-                       int64_t seconds) {
-  upb_json_printer *p = closure;
-  p->seconds = seconds;
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static bool putnanos(void *closure, const void *handler_data,
-                     int32_t nanos) {
-  upb_json_printer *p = closure;
-  p->nanos = nanos;
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static void *scalar_startstr_nokey(void *closure, const void *handler_data,
-                                   size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t putstr_nokey(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-  print_data(p, "\"", 1);
-  putstring(p, str, len);
-  print_data(p, "\"", 1);
-  return len + 2;
-}
-
-static void *startseq_nokey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "[", 1);
-  return closure;
-}
-
-static void *startseq_fieldmask(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  return closure;
-}
-
-static bool endseq_fieldmask(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_--;
-  return true;
-}
-
-static void *repeated_startstr_fieldmask(
-    void *closure, const void *handler_data,
-    size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_comma(p);
-  return p;
-}
-
-static size_t repeated_str_fieldmask(
-    void *closure, const void *handler_data,
-    const char *str, size_t len,
-    const upb_bufhandle *handle) {
-  const char* limit = str + len;
-  bool upper = false;
-  size_t result_len = 0;
-  for (; str < limit; str++) {
-    if (*str == '_') {
-      upper = true;
-      continue;
-    }
-    if (upper && *str >= 'a' && *str <= 'z') {
-      char upper_char = toupper(*str);
-      CHK(putstr(closure, handler_data, &upper_char, 1, handle));
-    } else {
-      CHK(putstr(closure, handler_data, str, 1, handle));
-    }
-    upper = false;
-    result_len++;
-  }
-  return result_len;
-}
-
-static void *startmap_nokey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-  return closure;
-}
-
-static bool putnull(void *closure, const void *handler_data,
-                    int32_t null) {
-  upb_json_printer *p = closure;
-  print_data(p, "null", 4);
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(null);
-  return true;
-}
-
-static bool printer_startdurationmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-#define UPB_DURATION_MAX_JSON_LEN 23
-#define UPB_DURATION_MAX_NANO_LEN 9
-
-static bool printer_enddurationmsg(void *closure, const void *handler_data,
-                                   upb_status *s) {
-  upb_json_printer *p = closure;
-  char buffer[UPB_DURATION_MAX_JSON_LEN];
-  size_t base_len;
-  size_t curr;
-  size_t i;
-
-  memset(buffer, 0, UPB_DURATION_MAX_JSON_LEN);
-
-  if (p->seconds < -315576000000) {
-    upb_status_seterrf(s, "error parsing duration: "
-                          "minimum acceptable value is "
-                          "-315576000000");
-    return false;
-  }
-
-  if (p->seconds > 315576000000) {
-    upb_status_seterrf(s, "error serializing duration: "
-                          "maximum acceptable value is "
-                          "315576000000");
-    return false;
-  }
-
-  _upb_snprintf(buffer, sizeof(buffer), "%ld", (long)p->seconds);
-  base_len = strlen(buffer);
-
-  if (p->nanos != 0) {
-    char nanos_buffer[UPB_DURATION_MAX_NANO_LEN + 3];
-    _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
-                  p->nanos / 1000000000.0);
-    /* Remove trailing 0. */
-    for (i = UPB_DURATION_MAX_NANO_LEN + 2;
-         nanos_buffer[i] == '0'; i--) {
-      nanos_buffer[i] = 0;
-    }
-    strcpy(buffer + base_len, nanos_buffer + 1);
-  }
-
-  curr = strlen(buffer);
-  strcpy(buffer + curr, "s");
-
-  p->seconds = 0;
-  p->nanos = 0;
-
-  print_data(p, "\"", 1);
-  print_data(p, buffer, strlen(buffer));
-  print_data(p, "\"", 1);
-
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static bool printer_starttimestampmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-#define UPB_TIMESTAMP_MAX_JSON_LEN 31
-#define UPB_TIMESTAMP_BEFORE_NANO_LEN 19
-#define UPB_TIMESTAMP_MAX_NANO_LEN 9
-
-static bool printer_endtimestampmsg(void *closure, const void *handler_data,
-                                    upb_status *s) {
-  upb_json_printer *p = closure;
-  char buffer[UPB_TIMESTAMP_MAX_JSON_LEN];
-  time_t time = p->seconds;
-  size_t curr;
-  size_t i;
-  size_t year_length =
-      strftime(buffer, UPB_TIMESTAMP_MAX_JSON_LEN, "%Y", gmtime(&time));
-
-  if (p->seconds < -62135596800) {
-    upb_status_seterrf(s, "error parsing timestamp: "
-                          "minimum acceptable value is "
-                          "0001-01-01T00:00:00Z");
-    return false;
-  }
-
-  if (p->seconds > 253402300799) {
-    upb_status_seterrf(s, "error parsing timestamp: "
-                          "maximum acceptable value is "
-                          "9999-12-31T23:59:59Z");
-    return false;
-  }
-
-  /* strftime doesn't guarantee 4 digits for year. Prepend 0 by ourselves. */
-  for (i = 0; i < 4 - year_length; i++) {
-    buffer[i] = '0';
-  }
-
-  strftime(buffer + (4 - year_length), UPB_TIMESTAMP_MAX_JSON_LEN,
-           "%Y-%m-%dT%H:%M:%S", gmtime(&time));
-  if (p->nanos != 0) {
-    char nanos_buffer[UPB_TIMESTAMP_MAX_NANO_LEN + 3];
-    _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
-                  p->nanos / 1000000000.0);
-    /* Remove trailing 0. */
-    for (i = UPB_TIMESTAMP_MAX_NANO_LEN + 2;
-         nanos_buffer[i] == '0'; i--) {
-      nanos_buffer[i] = 0;
-    }
-    strcpy(buffer + UPB_TIMESTAMP_BEFORE_NANO_LEN, nanos_buffer + 1);
-  }
-
-  curr = strlen(buffer);
-  strcpy(buffer + curr, "Z");
-
-  p->seconds = 0;
-  p->nanos = 0;
-
-  print_data(p, "\"", 1);
-  print_data(p, buffer, strlen(buffer));
-  print_data(p, "\"", 1);
-
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  return true;
-}
-
-static bool printer_startmsg_noframe(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-static bool printer_endmsg_noframe(
-    void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static bool printer_startmsg_fieldmask(
-    void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static bool printer_endmsg_fieldmask(
-    void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  print_data(p, "\"", 1);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static void *scalar_startstr_onlykey(
-    void *closure, const void *handler_data, size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(size_hint);
-  CHK(putkey(closure, handler_data));
-  return p;
-}
-
-/* Set up handlers for an Any submessage. */
-void printer_sethandlers_any(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* type_field = upb_msgdef_itof(md, UPB_ANY_TYPE);
-  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_ANY_VALUE);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  /* type_url's json name is "@type" */
-  upb_handlerattr type_name_attr = UPB_HANDLERATTR_INIT;
-  upb_handlerattr value_name_attr = UPB_HANDLERATTR_INIT;
-  strpc *type_url_json_name = newstrpc_str(h, "@type");
-  strpc *value_json_name = newstrpc_str(h, "value");
-
-  type_name_attr.handler_data = type_url_json_name;
-  value_name_attr.handler_data = value_json_name;
-
-  /* Set up handlers. */
-  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
-  upb_handlers_setstartstr(h, type_field, scalar_startstr, &type_name_attr);
-  upb_handlers_setstring(h, type_field, scalar_str, &empty_attr);
-  upb_handlers_setendstr(h, type_field, scalar_endstr, &empty_attr);
-
-  /* This is not the full and correct JSON encoding for the Any value field. It
-   * requires further processing by the wrapper code based on the type URL.
-   */
-  upb_handlers_setstartstr(h, value_field, scalar_startstr_onlykey,
-                           &value_name_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a fieldmask submessage. */
-void printer_sethandlers_fieldmask(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startseq_fieldmask, &empty_attr);
-  upb_handlers_setendseq(h, f, endseq_fieldmask, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_fieldmask, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_fieldmask, &empty_attr);
-
-  upb_handlers_setstartstr(h, f, repeated_startstr_fieldmask, &empty_attr);
-  upb_handlers_setstring(h, f, repeated_str_fieldmask, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a duration submessage. */
-void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* seconds_field =
-      upb_msgdef_itof(md, UPB_DURATION_SECONDS);
-  const upb_fielddef* nanos_field =
-      upb_msgdef_itof(md, UPB_DURATION_NANOS);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr);
-  upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
-  upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
-  upb_handlers_setendmsg(h, printer_enddurationmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a timestamp submessage. Instead of printing fields
- * separately, the json representation of timestamp follows RFC 3339 */
-void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* seconds_field =
-      upb_msgdef_itof(md, UPB_TIMESTAMP_SECONDS);
-  const upb_fielddef* nanos_field =
-      upb_msgdef_itof(md, UPB_TIMESTAMP_NANOS);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr);
-  upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
-  upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endtimestampmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_value(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  upb_msg_field_iter i;
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_msg_field_begin(&i, md);
-  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_ENUM:
-        upb_handlers_setint32(h, f, putnull, &empty_attr);
-        break;
-      case UPB_TYPE_DOUBLE:
-        upb_handlers_setdouble(h, f, putdouble, &empty_attr);
-        break;
-      case UPB_TYPE_STRING:
-        upb_handlers_setstartstr(h, f, scalar_startstr_nokey, &empty_attr);
-        upb_handlers_setstring(h, f, scalar_str, &empty_attr);
-        upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
-        break;
-      case UPB_TYPE_BOOL:
-        upb_handlers_setbool(h, f, putbool, &empty_attr);
-        break;
-      case UPB_TYPE_MESSAGE:
-        break;
-      default:
-        UPB_ASSERT(false);
-        break;
-    }
-  }
-
-  UPB_UNUSED(closure);
-}
-
-#define WRAPPER_SETHANDLERS(wrapper, type, putmethod)                      \
-void printer_sethandlers_##wrapper(const void *closure, upb_handlers *h) { \
-  const upb_msgdef *md = upb_handlers_msgdef(h);                           \
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);                          \
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;                \
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);      \
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);          \
-  upb_handlers_set##type(h, f, putmethod, &empty_attr);                    \
-  UPB_UNUSED(closure);                                                     \
-}
-
-WRAPPER_SETHANDLERS(doublevalue, double, putdouble)
-WRAPPER_SETHANDLERS(floatvalue,  float,  putfloat)
-WRAPPER_SETHANDLERS(int64value,  int64,  putint64_t)
-WRAPPER_SETHANDLERS(uint64value, uint64, putuint64_t)
-WRAPPER_SETHANDLERS(int32value,  int32,  putint32_t)
-WRAPPER_SETHANDLERS(uint32value, uint32, putuint32_t)
-WRAPPER_SETHANDLERS(boolvalue,   bool,   putbool)
-WRAPPER_SETHANDLERS(stringvalue, string, putstr_nokey)
-WRAPPER_SETHANDLERS(bytesvalue,  string, putbytes)
-
-#undef WRAPPER_SETHANDLERS
-
-void printer_sethandlers_listvalue(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startseq_nokey, &empty_attr);
-  upb_handlers_setendseq(h, f, endseq, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startmap_nokey, &empty_attr);
-  upb_handlers_setendseq(h, f, endmap, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  bool is_mapentry = upb_msgdef_mapentry(md);
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-  upb_msg_field_iter i;
-  const upb_json_printercache *cache = closure;
-  const bool preserve_fieldnames = cache->preserve_fieldnames;
-
-  if (is_mapentry) {
-    /* mapentry messages are sufficiently different that we handle them
-     * separately. */
-    printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
-    return;
-  }
-
-  switch (upb_msgdef_wellknowntype(md)) {
-    case UPB_WELLKNOWN_UNSPECIFIED:
-      break;
-    case UPB_WELLKNOWN_ANY:
-      printer_sethandlers_any(closure, h);
-      return;
-    case UPB_WELLKNOWN_FIELDMASK:
-      printer_sethandlers_fieldmask(closure, h);
-      return;
-    case UPB_WELLKNOWN_DURATION:
-      printer_sethandlers_duration(closure, h);
-      return;
-    case UPB_WELLKNOWN_TIMESTAMP:
-      printer_sethandlers_timestamp(closure, h);
-      return;
-    case UPB_WELLKNOWN_VALUE:
-      printer_sethandlers_value(closure, h);
-      return;
-    case UPB_WELLKNOWN_LISTVALUE:
-      printer_sethandlers_listvalue(closure, h);
-      return;
-    case UPB_WELLKNOWN_STRUCT:
-      printer_sethandlers_structvalue(closure, h);
-      return;
-#define WRAPPER(wellknowntype, name)        \
-  case wellknowntype:                       \
-    printer_sethandlers_##name(closure, h); \
-    return;                                 \
-
-    WRAPPER(UPB_WELLKNOWN_DOUBLEVALUE, doublevalue);
-    WRAPPER(UPB_WELLKNOWN_FLOATVALUE, floatvalue);
-    WRAPPER(UPB_WELLKNOWN_INT64VALUE, int64value);
-    WRAPPER(UPB_WELLKNOWN_UINT64VALUE, uint64value);
-    WRAPPER(UPB_WELLKNOWN_INT32VALUE, int32value);
-    WRAPPER(UPB_WELLKNOWN_UINT32VALUE, uint32value);
-    WRAPPER(UPB_WELLKNOWN_BOOLVALUE, boolvalue);
-    WRAPPER(UPB_WELLKNOWN_STRINGVALUE, stringvalue);
-    WRAPPER(UPB_WELLKNOWN_BYTESVALUE, bytesvalue);
-
-#undef WRAPPER
-  }
-
-  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
-#define TYPE(type, name, ctype)                                               \
-  case type:                                                                  \
-    if (upb_fielddef_isseq(f)) {                                              \
-      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr);            \
-    } else {                                                                  \
-      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);               \
-    }                                                                         \
-    break;
-
-  upb_msg_field_begin(&i, md);
-  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-
-    upb_handlerattr name_attr = UPB_HANDLERATTR_INIT;
-    name_attr.handler_data = newstrpc(h, f, preserve_fieldnames);
-
-    if (upb_fielddef_ismap(f)) {
-      upb_handlers_setstartseq(h, f, startmap, &name_attr);
-      upb_handlers_setendseq(h, f, endmap, &name_attr);
-    } else if (upb_fielddef_isseq(f)) {
-      upb_handlers_setstartseq(h, f, startseq, &name_attr);
-      upb_handlers_setendseq(h, f, endseq, &empty_attr);
-    }
-
-    switch (upb_fielddef_type(f)) {
-      TYPE(UPB_TYPE_FLOAT,  float,  float);
-      TYPE(UPB_TYPE_DOUBLE, double, double);
-      TYPE(UPB_TYPE_BOOL,   bool,   bool);
-      TYPE(UPB_TYPE_INT32,  int32,  int32_t);
-      TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
-      TYPE(UPB_TYPE_INT64,  int64,  int64_t);
-      TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
-      case UPB_TYPE_ENUM: {
-        /* For now, we always emit symbolic names for enums. We may want an
-         * option later to control this behavior, but we will wait for a real
-         * need first. */
-        upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
-        set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
-
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
-        } else {
-          upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
-        }
-
-        break;
-      }
-      case UPB_TYPE_STRING:
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
-          upb_handlers_setstring(h, f, repeated_str, &empty_attr);
-          upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
-        } else {
-          upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
-          upb_handlers_setstring(h, f, scalar_str, &empty_attr);
-          upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
-        }
-        break;
-      case UPB_TYPE_BYTES:
-        /* XXX: this doesn't support strings that span buffers yet. The base64
-         * encoder will need to be made resumable for this to work properly. */
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
-        } else {
-          upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
-        }
-        break;
-      case UPB_TYPE_MESSAGE:
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
-        } else {
-          upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
-        }
-        break;
-    }
-  }
-
-#undef TYPE
-}
-
-static void json_printer_reset(upb_json_printer *p) {
-  p->depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
-                                          upb_bytessink output) {
-#ifndef NDEBUG
-  size_t size_before = upb_arena_bytesallocated(a);
-#endif
-
-  upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer));
-  if (!p) return NULL;
-
-  p->output_ = output;
-  json_printer_reset(p);
-  upb_sink_reset(&p->input_, h, p);
-  p->seconds = 0;
-  p->nanos = 0;
-
-  /* If this fails, increase the value in printer.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
-                      UPB_JSON_PRINTER_SIZE);
-  return p;
-}
-
-upb_sink upb_json_printer_input(upb_json_printer *p) {
-  return p->input_;
-}
-
-upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) {
-  upb_json_printercache *cache = upb_gmalloc(sizeof(*cache));
-  upb_handlercache *ret = upb_handlercache_new(printer_sethandlers, cache);
-
-  cache->preserve_fieldnames = preserve_proto_fieldnames;
-  upb_handlercache_addcleanup(ret, cache, upb_gfree);
-
-  return ret;
-}
-/* See port_def.inc.  This should #undef all macros #defined there. */
-
-#undef UPB_MAPTYPE_STRING
-#undef UPB_SIZE
-#undef UPB_PTR_AT
-#undef UPB_READ_ONEOF
-#undef UPB_WRITE_ONEOF
-#undef UPB_INLINE
-#undef UPB_FORCEINLINE
-#undef UPB_NOINLINE
-#undef UPB_NORETURN
-#undef UPB_MAX
-#undef UPB_MIN
-#undef UPB_UNUSED
-#undef UPB_ASSUME
-#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
-#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h
deleted file mode 100644
index a346379..0000000
--- a/ruby/ext/google/protobuf_c/upb.h
+++ /dev/null
@@ -1,7474 +0,0 @@
-/* Amalgamated source file */
-#include <stdint.h>/*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-*   #include "upb/foobar.h"
-*   #include "upb/baz.h"
-*
-*   // MUST be last included header.
-*   #include "upb/port_def.inc"
-*
-*   // Code for this file.
-*   // <...>
-*
-*   // Can be omitted for .c files, required for .h.
-*   #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#include <stdint.h>
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-/* If we always read/write as a consistent type to each address, this shouldn't
- * violate aliasing.
- */
-#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
-  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
-      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
-      : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
-  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
-  *UPB_PTR_AT(msg, offset, fieldtype) = value;
-
-#define UPB_MAPTYPE_STRING 0
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else  /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include <stdio.h>
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include <stdarg.h>
-#include <stdio.h>
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
-    (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
-#ifdef NDEBUG
-#ifdef __GNUC__
-#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
-#else
-#define UPB_ASSUME(expr) do {} if (false && (expr))
-#endif
-#else
-#define UPB_ASSUME(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated.  This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode.  This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include <math.h>
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-/*
-** upb_decode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_DECODE_H_
-#define UPB_DECODE_H_
-
-/*
-** Our memory representation for parsing tables and messages themselves.
-** Functions in this file are used by generated code and possibly reflection.
-**
-** The definitions in this file are internal to upb.
-**/
-
-#ifndef UPB_MSG_H_
-#define UPB_MSG_H_
-
-#include <stdint.h>
-#include <string.h>
-
-/*
-** upb_table
-**
-** This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
-** This file defines very fast int->upb_value (inttable) and string->upb_value
-** (strtable) hash tables.
-**
-** The table uses chained scatter with Brent's variation (inspired by the Lua
-** implementation of hash tables).  The hash function for strings is Austin
-** Appleby's "MurmurHash."
-**
-** The inttable uses uintptr_t as its key, which guarantees it can be used to
-** store pointers or integers of at least 32 bits (upb isn't really useful on
-** systems where sizeof(void*) < 4).
-**
-** The table must be homogenous (all values of the same type).  In debug
-** mode, we check this on insert and lookup.
-*/
-
-#ifndef UPB_TABLE_H_
-#define UPB_TABLE_H_
-
-#include <stdint.h>
-#include <string.h>
-/*
-** This file contains shared definitions that are widely used across upb.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_H_
-#define UPB_H_
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#ifdef __cplusplus
-#include <memory>
-namespace upb {
-class Arena;
-class Status;
-template <int N> class InlinedArena;
-}
-#endif
-
-
-/* upb_status *****************************************************************/
-
-/* upb_status represents a success or failure status and error message.
- * It owns no resources and allocates no memory, so it should work
- * even in OOM situations. */
-
-/* The maximum length of an error message before it will get truncated. */
-#define UPB_STATUS_MAX_MESSAGE 127
-
-typedef struct {
-  bool ok;
-  char msg[UPB_STATUS_MAX_MESSAGE];  /* Error message; NULL-terminated. */
-} upb_status;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_status_errmsg(const upb_status *status);
-bool upb_ok(const upb_status *status);
-
-/* Any of the functions that write to a status object allow status to be NULL,
- * to support use cases where the function's caller does not care about the
- * status message. */
-void upb_status_clear(upb_status *status);
-void upb_status_seterrmsg(upb_status *status, const char *msg);
-void upb_status_seterrf(upb_status *status, const char *fmt, ...);
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
-
-UPB_INLINE void upb_status_setoom(upb_status *status) {
-  upb_status_seterrmsg(status, "out of memory");
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::Status {
- public:
-  Status() { upb_status_clear(&status_); }
-
-  upb_status* ptr() { return &status_; }
-
-  /* Returns true if there is no error. */
-  bool ok() const { return upb_ok(&status_); }
-
-  /* Guaranteed to be NULL-terminated. */
-  const char *error_message() const { return upb_status_errmsg(&status_); }
-
-  /* The error message will be truncated if it is longer than
-   * UPB_STATUS_MAX_MESSAGE-4. */
-  void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); }
-  void SetFormattedErrorMessage(const char *fmt, ...) {
-    va_list args;
-    va_start(args, fmt);
-    upb_status_vseterrf(&status_, fmt, args);
-    va_end(args);
-  }
-
-  /* Resets the status to a successful state with no message. */
-  void Clear() { upb_status_clear(&status_); }
-
- private:
-  upb_status status_;
-};
-
-#endif  /* __cplusplus */
-
-/** upb_strview ************************************************************/
-
-typedef struct {
-  const char *data;
-  size_t size;
-} upb_strview;
-
-UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
-  upb_strview ret;
-  ret.data = data;
-  ret.size = size;
-  return ret;
-}
-
-UPB_INLINE upb_strview upb_strview_makez(const char *data) {
-  return upb_strview_make(data, strlen(data));
-}
-
-UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
-  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
-}
-
-#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
-
-#define UPB_STRVIEW_FORMAT "%.*s"
-#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
-
-/** upb_alloc *****************************************************************/
-
-/* A upb_alloc is a possibly-stateful allocator object.
- *
- * It could either be an arena allocator (which doesn't require individual
- * free() calls) or a regular malloc() (which does).  The client must therefore
- * free memory unless it knows that the allocator is an arena allocator. */
-
-struct upb_alloc;
-typedef struct upb_alloc upb_alloc;
-
-/* A malloc()/free() function.
- * If "size" is 0 then the function acts like free(), otherwise it acts like
- * realloc().  Only "oldsize" bytes from a previous allocation are preserved. */
-typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
-                             size_t size);
-
-struct upb_alloc {
-  upb_alloc_func *func;
-};
-
-UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
-  UPB_ASSERT(alloc);
-  return alloc->func(alloc, NULL, 0, size);
-}
-
-UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                             size_t size) {
-  UPB_ASSERT(alloc);
-  return alloc->func(alloc, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
-  assert(alloc);
-  alloc->func(alloc, ptr, 0, 0);
-}
-
-/* The global allocator used by upb.  Uses the standard malloc()/free(). */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern upb_alloc upb_alloc_global;
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-/* Functions that hard-code the global malloc.
- *
- * We still get benefit because we can put custom logic into our global
- * allocator, like injecting out-of-memory faults in debug/testing builds. */
-
-UPB_INLINE void *upb_gmalloc(size_t size) {
-  return upb_malloc(&upb_alloc_global, size);
-}
-
-UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
-  return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_gfree(void *ptr) {
-  upb_free(&upb_alloc_global, ptr);
-}
-
-/* upb_arena ******************************************************************/
-
-/* upb_arena is a specific allocator implementation that uses arena allocation.
- * The user provides an allocator that will be used to allocate the underlying
- * arena blocks.  Arenas by nature do not require the individual allocations
- * to be freed.  However the Arena does allow users to register cleanup
- * functions that will run when the arena is destroyed.
- *
- * A upb_arena is *not* thread-safe.
- *
- * You could write a thread-safe arena allocator that satisfies the
- * upb_alloc interface, but it would not be as efficient for the
- * single-threaded case. */
-
-typedef void upb_cleanup_func(void *ud);
-
-struct upb_arena;
-typedef struct upb_arena upb_arena;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
-  /* We implement the allocator interface.
-   * This must be the first member of upb_arena! */
-  upb_alloc alloc;
-
-  char *ptr, *end;
-} _upb_arena_head;
-
-UPB_INLINE size_t _upb_arena_alignup(size_t size) {
-  const size_t maxalign = 16;
-  return ((size + maxalign - 1) / maxalign) * maxalign;
-}
-
-/* Creates an arena from the given initial block (if any -- n may be 0).
- * Additional blocks will be allocated from |alloc|.  If |alloc| is NULL, this
- * is a fixed-size arena and cannot grow. */
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
-void upb_arena_free(upb_arena *a);
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
-size_t upb_arena_bytesallocated(const upb_arena *a);
-void *_upb_arena_slowmalloc(upb_arena *a, size_t size);
-
-UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
-
-UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
-  _upb_arena_head *h = (_upb_arena_head*)a;
-  size = _upb_arena_alignup(size);
-  if (UPB_LIKELY((size_t)(h->end - h->ptr) >= size)) {
-    void* ret = h->ptr;
-    h->ptr += size;
-    return ret;
-  } else {
-    return _upb_arena_slowmalloc(a, size);
-  }
-}
-
-UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
-                                   size_t size) {
-  if (oldsize == 0) {
-    return upb_arena_malloc(a, size);
-  } else {
-    return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size);
-  }
-}
-
-UPB_INLINE upb_arena *upb_arena_new(void) {
-  return upb_arena_init(NULL, 0, &upb_alloc_global);
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::Arena {
- public:
-  /* A simple arena with no initial memory block and the default allocator. */
-  Arena() : ptr_(upb_arena_new(), upb_arena_free) {}
-
-  upb_arena* ptr() { return ptr_.get(); }
-
-  /* Allows this arena to be used as a generic allocator.
-   *
-   * The arena does not need free() calls so when using Arena as an allocator
-   * it is safe to skip them.  However they are no-ops so there is no harm in
-   * calling free() either. */
-  upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); }
-
-  /* Add a cleanup function to run when the arena is destroyed.
-   * Returns false on out-of-memory. */
-  bool AddCleanup(void *ud, upb_cleanup_func* func) {
-    return upb_arena_addcleanup(ptr_.get(), ud, func);
-  }
-
-  /* Total number of bytes that have been allocated.  It is undefined what
-   * Realloc() does to &arena_ counter. */
-  size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); }
-
- private:
-  std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
-};
-
-#endif
-
-/* upb::InlinedArena **********************************************************/
-
-/* upb::InlinedArena seeds the arenas with a predefined amount of memory.  No
- * heap memory will be allocated until the initial block is exceeded.
- *
- * These types only exist in C++ */
-
-#ifdef __cplusplus
-
-template <int N> class upb::InlinedArena : public upb::Arena {
- public:
-  InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {}
-
-  upb_arena* ptr() { return ptr_.get(); }
-
- private:
-  InlinedArena(const InlinedArena*) = delete;
-  InlinedArena& operator=(const InlinedArena*) = delete;
-
-  std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
-  char initial_block_[N];
-};
-
-#endif  /* __cplusplus */
-
-/* Constants ******************************************************************/
-
-/* Generic function type. */
-typedef void upb_func(void);
-
-/* A list of types as they are encoded on-the-wire. */
-typedef enum {
-  UPB_WIRE_TYPE_VARINT      = 0,
-  UPB_WIRE_TYPE_64BIT       = 1,
-  UPB_WIRE_TYPE_DELIMITED   = 2,
-  UPB_WIRE_TYPE_START_GROUP = 3,
-  UPB_WIRE_TYPE_END_GROUP   = 4,
-  UPB_WIRE_TYPE_32BIT       = 5
-} upb_wiretype_t;
-
-/* The types a field can have.  Note that this list is not identical to the
- * types defined in descriptor.proto, which gives INT32 and SINT32 separate
- * types (we distinguish the two with the "integer encoding" enum below). */
-typedef enum {
-  /* Types stored in 1 byte. */
-  UPB_TYPE_BOOL     = 1,
-  /* Types stored in 4 bytes. */
-  UPB_TYPE_FLOAT    = 2,
-  UPB_TYPE_INT32    = 3,
-  UPB_TYPE_UINT32   = 4,
-  UPB_TYPE_ENUM     = 5,  /* Enum values are int32. */
-  /* Types stored as void* (probably 4 or 8 bytes). */
-  UPB_TYPE_MESSAGE  = 6,
-  /* Types stored as 8 bytes. */
-  UPB_TYPE_DOUBLE   = 7,
-  UPB_TYPE_INT64    = 8,
-  UPB_TYPE_UINT64   = 9,
-  /* Types stored as upb_strview (2 * void*) (probably 8 or 16 bytes). */
-  UPB_TYPE_STRING   = 10,
-  UPB_TYPE_BYTES    = 11
-} upb_fieldtype_t;
-
-/* The repeated-ness of each field; this matches descriptor.proto. */
-typedef enum {
-  UPB_LABEL_OPTIONAL = 1,
-  UPB_LABEL_REQUIRED = 2,
-  UPB_LABEL_REPEATED = 3
-} upb_label_t;
-
-/* Descriptor types, as defined in descriptor.proto. */
-typedef enum {
-  /* Old (long) names.  TODO(haberman): remove */
-  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
-  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
-  UPB_DESCRIPTOR_TYPE_INT64    = 3,
-  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
-  UPB_DESCRIPTOR_TYPE_INT32    = 5,
-  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
-  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
-  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
-  UPB_DESCRIPTOR_TYPE_STRING   = 9,
-  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
-  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
-  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
-  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
-  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
-  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
-  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
-  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
-  UPB_DESCRIPTOR_TYPE_SINT64   = 18,
-
-  UPB_DTYPE_DOUBLE   = 1,
-  UPB_DTYPE_FLOAT    = 2,
-  UPB_DTYPE_INT64    = 3,
-  UPB_DTYPE_UINT64   = 4,
-  UPB_DTYPE_INT32    = 5,
-  UPB_DTYPE_FIXED64  = 6,
-  UPB_DTYPE_FIXED32  = 7,
-  UPB_DTYPE_BOOL     = 8,
-  UPB_DTYPE_STRING   = 9,
-  UPB_DTYPE_GROUP    = 10,
-  UPB_DTYPE_MESSAGE  = 11,
-  UPB_DTYPE_BYTES    = 12,
-  UPB_DTYPE_UINT32   = 13,
-  UPB_DTYPE_ENUM     = 14,
-  UPB_DTYPE_SFIXED32 = 15,
-  UPB_DTYPE_SFIXED64 = 16,
-  UPB_DTYPE_SINT32   = 17,
-  UPB_DTYPE_SINT64   = 18
-} upb_descriptortype_t;
-
-#define UPB_MAP_BEGIN -1
-
-
-#endif  /* UPB_H_ */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* upb_value ******************************************************************/
-
-/* A tagged union (stored untagged inside the table) so that we can check that
- * clients calling table accessors are correctly typed without having to have
- * an explosion of accessors. */
-typedef enum {
-  UPB_CTYPE_INT32    = 1,
-  UPB_CTYPE_INT64    = 2,
-  UPB_CTYPE_UINT32   = 3,
-  UPB_CTYPE_UINT64   = 4,
-  UPB_CTYPE_BOOL     = 5,
-  UPB_CTYPE_CSTR     = 6,
-  UPB_CTYPE_PTR      = 7,
-  UPB_CTYPE_CONSTPTR = 8,
-  UPB_CTYPE_FPTR     = 9,
-  UPB_CTYPE_FLOAT    = 10,
-  UPB_CTYPE_DOUBLE   = 11
-} upb_ctype_t;
-
-typedef struct {
-  uint64_t val;
-} upb_value;
-
-/* Like strdup(), which isn't always available since it's not ANSI C. */
-char *upb_strdup(const char *s, upb_alloc *a);
-/* Variant that works with a length-delimited rather than NULL-delimited string,
- * as supported by strtable. */
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
-
-UPB_INLINE char *upb_gstrdup(const char *s) {
-  return upb_strdup(s, &upb_alloc_global);
-}
-
-UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) {
-  v->val = val;
-}
-
-UPB_INLINE upb_value _upb_value_val(uint64_t val) {
-  upb_value ret;
-  _upb_value_setval(&ret, val);
-  return ret;
-}
-
-/* For each value ctype, define the following set of functions:
- *
- * // Get/set an int32 from a upb_value.
- * int32_t upb_value_getint32(upb_value val);
- * void upb_value_setint32(upb_value *val, int32_t cval);
- *
- * // Construct a new upb_value from an int32.
- * upb_value upb_value_int32(int32_t val); */
-#define FUNCS(name, membername, type_t, converter, proto_type) \
-  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
-    val->val = (converter)cval; \
-  } \
-  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
-    upb_value ret; \
-    upb_value_set ## name(&ret, val); \
-    return ret; \
-  } \
-  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
-    return (type_t)(converter)val.val; \
-  }
-
-FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
-FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
-FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
-FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
-FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
-FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
-FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
-FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
-FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
-
-#undef FUNCS
-
-UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
-  memcpy(&val->val, &cval, sizeof(cval));
-}
-
-UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
-  memcpy(&val->val, &cval, sizeof(cval));
-}
-
-UPB_INLINE upb_value upb_value_float(float cval) {
-  upb_value ret;
-  upb_value_setfloat(&ret, cval);
-  return ret;
-}
-
-UPB_INLINE upb_value upb_value_double(double cval) {
-  upb_value ret;
-  upb_value_setdouble(&ret, cval);
-  return ret;
-}
-
-#undef SET_TYPE
-
-
-/* upb_tabkey *****************************************************************/
-
-/* Either:
- *   1. an actual integer key, or
- *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
- *
- * ...depending on whether this is a string table or an int table.  We would
- * make this a union of those two types, but C89 doesn't support statically
- * initializing a non-first union member. */
-typedef uintptr_t upb_tabkey;
-
-UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
-  char* mem = (char*)key;
-  if (len) memcpy(len, mem, sizeof(*len));
-  return mem + sizeof(*len);
-}
-
-
-/* upb_tabval *****************************************************************/
-
-typedef struct {
-  uint64_t val;
-} upb_tabval;
-
-#define UPB_TABVALUE_EMPTY_INIT  {-1}
-
-/* upb_table ******************************************************************/
-
-typedef struct _upb_tabent {
-  upb_tabkey key;
-  upb_tabval val;
-
-  /* Internal chaining.  This is const so we can create static initializers for
-   * tables.  We cast away const sometimes, but *only* when the containing
-   * upb_table is known to be non-const.  This requires a bit of care, but
-   * the subtlety is confined to table.c. */
-  const struct _upb_tabent *next;
-} upb_tabent;
-
-typedef struct {
-  size_t count;          /* Number of entries in the hash part. */
-  size_t mask;           /* Mask to turn hash value -> bucket. */
-  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
-
-  /* Hash table entries.
-   * Making this const isn't entirely accurate; what we really want is for it to
-   * have the same const-ness as the table it's inside.  But there's no way to
-   * declare that in C.  So we have to make it const so that we can statically
-   * initialize const hash tables.  Then we cast away const when we have to.
-   */
-  const upb_tabent *entries;
-} upb_table;
-
-typedef struct {
-  upb_table t;
-} upb_strtable;
-
-typedef struct {
-  upb_table t;              /* For entries that don't fit in the array part. */
-  const upb_tabval *array;  /* Array part of the table. See const note above. */
-  size_t array_size;        /* Array part size. */
-  size_t array_count;       /* Array part number of elements. */
-} upb_inttable;
-
-#define UPB_ARRAY_EMPTYENT -1
-
-UPB_INLINE size_t upb_table_size(const upb_table *t) {
-  if (t->size_lg2 == 0)
-    return 0;
-  else
-    return 1 << t->size_lg2;
-}
-
-/* Internal-only functions, in .h file only out of necessity. */
-UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
-  return e->key == 0;
-}
-
-/* Used by some of the unit tests for generic hashing functionality. */
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed);
-
-UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
-  return key;
-}
-
-UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
-  return (uint32_t)key;
-}
-
-static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
-  return t->entries + (hash & t->mask);
-}
-
-UPB_INLINE bool upb_arrhas(upb_tabval key) {
-  return key.val != (uint64_t)-1;
-}
-
-/* Initialize and uninitialize a table, respectively.  If memory allocation
- * failed, false is returned that the table is uninitialized. */
-bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
-bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
-void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
-void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
-  return upb_inttable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
-  return upb_strtable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
-  upb_inttable_uninit2(table, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
-  upb_strtable_uninit2(table, &upb_alloc_global);
-}
-
-/* Returns the number of values in the table. */
-size_t upb_inttable_count(const upb_inttable *t);
-UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
-  return t->t.count;
-}
-
-void upb_inttable_packedsize(const upb_inttable *t, size_t *size);
-void upb_strtable_packedsize(const upb_strtable *t, size_t *size);
-upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs,
-                                size_t size);
-upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs,
-                                size_t size);
-void upb_strtable_clear(upb_strtable *t);
-
-/* Inserts the given key into the hashtable with the given value.  The key must
- * not already exist in the hash table.  For string tables, the key must be
- * NULL-terminated, and the table will make an internal copy of the key.
- * Inttables must not insert a value of UINTPTR_MAX.
- *
- * If a table resize was required but memory allocation failed, false is
- * returned and the table is unchanged. */
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
-                          upb_alloc *a);
-bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
-                          upb_value val, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
-                                    upb_value val) {
-  return upb_inttable_insert2(t, key, val, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
-                                     size_t len, upb_value val) {
-  return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
-                                    upb_value val) {
-  return upb_strtable_insert2(t, key, strlen(key), val);
-}
-
-/* Looks up key in this table, returning "true" if the key was found.
- * If v is non-NULL, copies the value for this key into *v. */
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
-                          upb_value *v);
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
-                                    upb_value *v) {
-  return upb_strtable_lookup2(t, key, strlen(key), v);
-}
-
-/* Removes an item from the table.  Returns true if the remove was successful,
- * and stores the removed item in *val if non-NULL. */
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
-                          upb_value *val, upb_alloc *alloc);
-
-UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
-                                     size_t len, upb_value *val) {
-  return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
-                                    upb_value *v) {
-  return upb_strtable_remove2(t, key, strlen(key), v);
-}
-
-/* Updates an existing entry in an inttable.  If the entry does not exist,
- * returns false and does nothing.  Unlike insert/remove, this does not
- * invalidate iterators. */
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
-
-/* Handy routines for treating an inttable like a stack.  May not be mixed with
- * other insert/remove calls. */
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
-upb_value upb_inttable_pop(upb_inttable *t);
-
-UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
-  return upb_inttable_push2(t, val, &upb_alloc_global);
-}
-
-/* Convenience routines for inttables with pointer keys. */
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
-                             upb_alloc *a);
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
-bool upb_inttable_lookupptr(
-    const upb_inttable *t, const void *key, upb_value *val);
-
-UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
-                                       upb_value val) {
-  return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
-}
-
-/* Optimizes the table for the current set of entries, for both memory use and
- * lookup time.  Client should call this after all entries have been inserted;
- * inserting more entries is legal, but will likely require a table resize. */
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
-
-UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
-  upb_inttable_compact2(t, &upb_alloc_global);
-}
-
-/* A special-case inlinable version of the lookup routine for 32-bit
- * integers. */
-UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
-                                      upb_value *v) {
-  *v = upb_value_int32(0);  /* Silence compiler warnings. */
-  if (key < t->array_size) {
-    upb_tabval arrval = t->array[key];
-    if (upb_arrhas(arrval)) {
-      _upb_value_setval(v, arrval.val);
-      return true;
-    } else {
-      return false;
-    }
-  } else {
-    const upb_tabent *e;
-    if (t->t.entries == NULL) return false;
-    for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
-      if ((uint32_t)e->key == key) {
-        _upb_value_setval(v, e->val.val);
-        return true;
-      }
-      if (e->next == NULL) return false;
-    }
-  }
-}
-
-/* Exposed for testing only. */
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
-
-/* Iterators ******************************************************************/
-
-/* Iterators for int and string tables.  We are subject to some kind of unusual
- * design constraints:
- *
- * For high-level languages:
- *  - we must be able to guarantee that we don't crash or corrupt memory even if
- *    the program accesses an invalidated iterator.
- *
- * For C++11 range-based for:
- *  - iterators must be copyable
- *  - iterators must be comparable
- *  - it must be possible to construct an "end" value.
- *
- * Iteration order is undefined.
- *
- * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
- * guaranteed to work even on an invalidated iterator, as long as the table it
- * is iterating over has not been freed.  Calling next() or accessing data from
- * an invalidated iterator yields unspecified elements from the table, but it is
- * guaranteed not to crash and to return real table elements (except when done()
- * is true). */
-
-
-/* upb_strtable_iter **********************************************************/
-
-/*   upb_strtable_iter i;
- *   upb_strtable_begin(&i, t);
- *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- *     const char *key = upb_strtable_iter_key(&i);
- *     const upb_value val = upb_strtable_iter_value(&i);
- *     // ...
- *   }
- */
-
-typedef struct {
-  const upb_strtable *t;
-  size_t index;
-} upb_strtable_iter;
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
-void upb_strtable_next(upb_strtable_iter *i);
-bool upb_strtable_done(const upb_strtable_iter *i);
-upb_strview upb_strtable_iter_key(const upb_strtable_iter *i);
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
-void upb_strtable_iter_setdone(upb_strtable_iter *i);
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
-                               const upb_strtable_iter *i2);
-
-
-/* upb_inttable_iter **********************************************************/
-
-/*   upb_inttable_iter i;
- *   upb_inttable_begin(&i, t);
- *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- *     uintptr_t key = upb_inttable_iter_key(&i);
- *     upb_value val = upb_inttable_iter_value(&i);
- *     // ...
- *   }
- */
-
-typedef struct {
-  const upb_inttable *t;
-  size_t index;
-  bool array_part;
-} upb_inttable_iter;
-
-UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) {
-  return &i->t->t.entries[i->index];
-}
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
-void upb_inttable_next(upb_inttable_iter *i);
-bool upb_inttable_done(const upb_inttable_iter *i);
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
-void upb_inttable_iter_setdone(upb_inttable_iter *i);
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
-                               const upb_inttable_iter *i2);
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* UPB_TABLE_H_ */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)
-
-typedef void upb_msg;
-
-/** upb_msglayout *************************************************************/
-
-/* upb_msglayout represents the memory layout of a given upb_msgdef.  The
- * members are public so generated code can initialize them, but users MUST NOT
- * read or write any of its members. */
-
-/* These aren't real labels according to descriptor.proto, but in the table we
- * use these for map/packed fields instead of UPB_LABEL_REPEATED. */
-enum {
-  _UPB_LABEL_MAP = 4,
-  _UPB_LABEL_PACKED = 7  /* Low 3 bits are common with UPB_LABEL_REPEATED. */
-};
-
-typedef struct {
-  uint32_t number;
-  uint16_t offset;
-  int16_t presence;      /* If >0, hasbit_index.  If <0, -oneof_index. */
-  uint16_t submsg_index;  /* undefined if descriptortype != MESSAGE or GROUP. */
-  uint8_t descriptortype;
-  uint8_t label;
-} upb_msglayout_field;
-
-typedef struct upb_msglayout {
-  const struct upb_msglayout *const* submsgs;
-  const upb_msglayout_field *fields;
-  /* Must be aligned to sizeof(void*).  Doesn't include internal members like
-   * unknown fields, extension dict, pointer to msglayout, etc. */
-  uint16_t size;
-  uint16_t field_count;
-  bool extendable;
-} upb_msglayout;
-
-/** upb_msg *******************************************************************/
-
-/* Internal members of a upb_msg.  We can change this without breaking binary
- * compatibility.  We put these before the user's data.  The user's upb_msg*
- * points after the upb_msg_internal. */
-
-/* Used when a message is not extendable. */
-typedef struct {
-  char *unknown;
-  size_t unknown_len;
-  size_t unknown_size;
-} upb_msg_internal;
-
-/* Used when a message is extendable. */
-typedef struct {
-  upb_inttable *extdict;
-  upb_msg_internal base;
-} upb_msg_internal_withext;
-
-/* Maps upb_fieldtype_t -> memory size. */
-extern char _upb_fieldtype_to_size[12];
-
-/* Creates a new messages with the given layout on the given arena. */
-upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a);
-
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                         upb_arena *arena);
-
-/* Returns a reference to the message's unknown data. */
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-
-UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
-}
-
-UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
-}
-
-UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
-}
-
-UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) {
-  return *PTR_AT(msg, case_ofs, int32_t) == num;
-}
-
-UPB_INLINE bool _upb_has_submsg_nohasbit(const void *msg, size_t ofs) {
-  return *PTR_AT(msg, ofs, const void*) != NULL;
-}
-
-UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) {
-  return (field->label & 3) == UPB_LABEL_REPEATED;
-}
-
-/** upb_array *****************************************************************/
-
-/* Our internal representation for repeated fields.  */
-typedef struct {
-  uintptr_t data;   /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
-  size_t len;   /* Measured in elements. */
-  size_t size;  /* Measured in elements. */
-} upb_array;
-
-UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) {
-  return (void*)(arr->data & ~(uintptr_t)7);
-}
-
-UPB_INLINE void *_upb_array_ptr(upb_array *arr) {
-  return (void*)_upb_array_constptr(arr);
-}
-
-/* Creates a new array on the given arena. */
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type);
-
-/* Resizes the capacity of the array to be at least min_size. */
-bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena);
-
-/* Fallback functions for when the accessors require a resize. */
-void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
-                                 upb_fieldtype_t type, upb_arena *arena);
-bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
-                                upb_fieldtype_t type, upb_arena *arena);
-
-UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
-                                           size_t *size) {
-  const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*);
-  if (arr) {
-    if (size) *size = arr->len;
-    return _upb_array_constptr(arr);
-  } else {
-    if (size) *size = 0;
-    return NULL;
-  }
-}
-
-UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
-                                             size_t *size) {
-  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
-  if (arr) {
-    if (size) *size = arr->len;
-    return _upb_array_ptr(arr);
-  } else {
-    if (size) *size = 0;
-    return NULL;
-  }
-}
-
-UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
-                                            upb_fieldtype_t type,
-                                            upb_arena *arena) {
-  upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
-  upb_array *arr = *arr_ptr;
-  if (!arr || arr->size < size) {
-    return _upb_array_resize_fallback(arr_ptr, size, type, arena);
-  }
-  arr->len = size;
-  return _upb_array_ptr(arr);
-}
-
-
-UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
-                                           size_t elem_size,
-                                           upb_fieldtype_t type,
-                                           const void *value,
-                                           upb_arena *arena) {
-  upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
-  upb_array *arr = *arr_ptr;
-  void* ptr;
-  if (!arr || arr->len == arr->size) {
-    return _upb_array_append_fallback(arr_ptr, value, type, arena);
-  }
-  ptr = _upb_array_ptr(arr);
-  memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size);
-  arr->len++;
-  return true;
-}
-
-/** upb_map *******************************************************************/
-
-/* Right now we use strmaps for everything.  We'll likely want to use
- * integer-specific maps for integer-keyed maps.*/
-typedef struct {
-  /* Size of key and val, based on the map type.  Strings are represented as '0'
-   * because they must be handled specially. */
-  char key_size;
-  char val_size;
-
-  upb_strtable table;
-} upb_map;
-
-/* Map entries aren't actually stored, they are only used during parsing.  For
- * parsing, it helps a lot if all map entry messages have the same layout.
- * The compiler and def.c must ensure that all map entries have this layout. */
-typedef struct {
-  upb_msg_internal internal;
-  union {
-    upb_strview str;  /* For str/bytes. */
-    upb_value val;    /* For all other types. */
-  } k;
-  union {
-    upb_strview str;  /* For str/bytes. */
-    upb_value val;    /* For all other types. */
-  } v;
-} upb_map_entry;
-
-/* Creates a new map on the given arena with this key/value type. */
-upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size);
-
-/* Converting between internal table representation and user values.
- *
- * _upb_map_tokey() and _upb_map_fromkey() are inverses.
- * _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
- *
- * These functions account for the fact that strings are treated differently
- * from other types when stored in a map.
- */
-
-UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) {
-  if (size == UPB_MAPTYPE_STRING) {
-    return *(upb_strview*)key;
-  } else {
-    return upb_strview_make((const char*)key, size);
-  }
-}
-
-UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) {
-  if (size == UPB_MAPTYPE_STRING) {
-    memcpy(out, &key, sizeof(key));
-  } else {
-    memcpy(out, key.data, size);
-  }
-}
-
-UPB_INLINE upb_value _upb_map_tovalue(const void *val, size_t size,
-                                      upb_arena *a) {
-  upb_value ret = {0};
-  if (size == UPB_MAPTYPE_STRING) {
-    upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp));
-    *strp = *(upb_strview*)val;
-    memcpy(&ret, &strp, sizeof(strp));
-  } else {
-    memcpy(&ret, val, size);
-  }
-  return ret;
-}
-
-UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
-  if (size == UPB_MAPTYPE_STRING) {
-    const upb_strview *strp = (const upb_strview*)upb_value_getptr(val);
-    memcpy(out, strp, sizeof(upb_strview));
-  } else {
-    memcpy(out, &val, size);
-  }
-}
-
-/* Map operations, shared by reflection and generated code. */
-
-UPB_INLINE size_t _upb_map_size(const upb_map *map) {
-  return map->table.t.count;
-}
-
-UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key,
-                             size_t key_size, void *val, size_t val_size) {
-  upb_value tabval;
-  upb_strview k = _upb_map_tokey(key, key_size);
-  bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
-  if (ret) {
-    _upb_map_fromvalue(tabval, val, val_size);
-  }
-  return ret;
-}
-
-UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) {
-  upb_strtable_iter it;
-  it.t = &map->table;
-  it.index = *iter;
-  upb_strtable_next(&it);
-  if (upb_strtable_done(&it)) return NULL;
-  *iter = it.index;
-  return (void*)str_tabent(&it);
-}
-
-UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size,
-                             void *val, size_t val_size, upb_arena *arena) {
-  upb_strview strkey = _upb_map_tokey(key, key_size);
-  upb_value tabval = _upb_map_tovalue(val, val_size, arena);
-  upb_alloc *a = upb_arena_alloc(arena);
-
-  /* TODO(haberman): add overwrite operation to minimize number of lookups. */
-  upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a);
-  return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a);
-}
-
-UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) {
-  upb_strview k = _upb_map_tokey(key, key_size);
-  return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL);
-}
-
-UPB_INLINE void _upb_map_clear(upb_map *map) {
-  upb_strtable_clear(&map->table);
-}
-
-/* Message map operations, these get the map from the message first. */
-
-UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  return map ? _upb_map_size(map) : 0;
-}
-
-UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs,
-                                 const void *key, size_t key_size, void *val,
-                                 size_t val_size) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return false;
-  return _upb_map_get(map, key, key_size, val, val_size);
-}
-
-UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs,
-                                   size_t *iter) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return NULL;
-  return _upb_map_next(map, iter);
-}
-
-UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key,
-                                 size_t key_size, void *val, size_t val_size,
-                                 upb_arena *arena) {
-  upb_map **map = PTR_AT(msg, ofs, upb_map *);
-  if (!*map) {
-    *map = _upb_map_new(arena, key_size, val_size);
-  }
-  return _upb_map_set(*map, key, key_size, val, val_size, arena);
-}
-
-UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key,
-                                    size_t key_size) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return false;
-  return _upb_map_delete(map, key, key_size);
-}
-
-UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return;
-  _upb_map_clear(map);
-}
-
-/* Accessing map key/value from a pointer, used by generated code only. */
-
-UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) {
-  const upb_tabent *ent = (const upb_tabent*)msg;
-  uint32_t u32len;
-  upb_strview k;
-  k.data = upb_tabstr(ent->key, &u32len);
-  k.size = u32len;
-  _upb_map_fromkey(k, key, size);
-}
-
-UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) {
-  const upb_tabent *ent = (const upb_tabent*)msg;
-  upb_value v;
-  _upb_value_setval(&v, ent->val.val);
-  _upb_map_fromvalue(v, val, size);
-}
-
-UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) {
-  upb_tabent *ent = (upb_tabent*)msg;
-  /* This is like _upb_map_tovalue() except the entry already exists so we can
-   * reuse the allocated upb_strview for string fields. */
-  if (size == UPB_MAPTYPE_STRING) {
-    upb_strview *strp = (upb_strview*)ent->val.val;
-    memcpy(strp, val, sizeof(*strp));
-  } else {
-    memcpy(&ent->val.val, val, size);
-  }
-}
-
-#undef PTR_AT
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif /* UPB_MSG_H_ */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool upb_decode(const char *buf, size_t size, upb_msg *msg,
-                const upb_msglayout *l, upb_arena *arena);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif  /* UPB_DECODE_H_ */
-/*
-** upb_encode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_ENCODE_H_
-#define UPB_ENCODE_H_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena,
-                 size_t *size);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif  /* UPB_ENCODE_H_ */
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct google_protobuf_FileDescriptorSet;
-struct google_protobuf_FileDescriptorProto;
-struct google_protobuf_DescriptorProto;
-struct google_protobuf_DescriptorProto_ExtensionRange;
-struct google_protobuf_DescriptorProto_ReservedRange;
-struct google_protobuf_ExtensionRangeOptions;
-struct google_protobuf_FieldDescriptorProto;
-struct google_protobuf_OneofDescriptorProto;
-struct google_protobuf_EnumDescriptorProto;
-struct google_protobuf_EnumDescriptorProto_EnumReservedRange;
-struct google_protobuf_EnumValueDescriptorProto;
-struct google_protobuf_ServiceDescriptorProto;
-struct google_protobuf_MethodDescriptorProto;
-struct google_protobuf_FileOptions;
-struct google_protobuf_MessageOptions;
-struct google_protobuf_FieldOptions;
-struct google_protobuf_OneofOptions;
-struct google_protobuf_EnumOptions;
-struct google_protobuf_EnumValueOptions;
-struct google_protobuf_ServiceOptions;
-struct google_protobuf_MethodOptions;
-struct google_protobuf_UninterpretedOption;
-struct google_protobuf_UninterpretedOption_NamePart;
-struct google_protobuf_SourceCodeInfo;
-struct google_protobuf_SourceCodeInfo_Location;
-struct google_protobuf_GeneratedCodeInfo;
-struct google_protobuf_GeneratedCodeInfo_Annotation;
-typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet;
-typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto;
-typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto;
-typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange;
-typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange;
-typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions;
-typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto;
-typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange;
-typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto;
-typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto;
-typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto;
-typedef struct google_protobuf_FileOptions google_protobuf_FileOptions;
-typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions;
-typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions;
-typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions;
-typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions;
-typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions;
-typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions;
-typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions;
-typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption;
-typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart;
-typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo;
-typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location;
-typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo;
-typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation;
-extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
-extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
-extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
-extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_FileOptions_msginit;
-extern const upb_msglayout google_protobuf_MessageOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldOptions_msginit;
-extern const upb_msglayout google_protobuf_OneofOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
-extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
-extern const upb_msglayout google_protobuf_MethodOptions_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
-
-typedef enum {
-  google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
-  google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
-  google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
-} google_protobuf_FieldDescriptorProto_Label;
-
-typedef enum {
-  google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
-  google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
-  google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
-  google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
-  google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
-  google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
-  google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
-  google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
-  google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
-  google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
-  google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
-  google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
-  google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
-  google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
-  google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
-  google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
-  google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
-  google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
-} google_protobuf_FieldDescriptorProto_Type;
-
-typedef enum {
-  google_protobuf_FieldOptions_STRING = 0,
-  google_protobuf_FieldOptions_CORD = 1,
-  google_protobuf_FieldOptions_STRING_PIECE = 2
-} google_protobuf_FieldOptions_CType;
-
-typedef enum {
-  google_protobuf_FieldOptions_JS_NORMAL = 0,
-  google_protobuf_FieldOptions_JS_STRING = 1,
-  google_protobuf_FieldOptions_JS_NUMBER = 2
-} google_protobuf_FieldOptions_JSType;
-
-typedef enum {
-  google_protobuf_FileOptions_SPEED = 1,
-  google_protobuf_FileOptions_CODE_SIZE = 2,
-  google_protobuf_FileOptions_LITE_RUNTIME = 3
-} google_protobuf_FileOptions_OptimizeMode;
-
-typedef enum {
-  google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
-  google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
-  google_protobuf_MethodOptions_IDEMPOTENT = 2
-} google_protobuf_MethodOptions_IdempotencyLevel;
-
-
-/* google.protobuf.FileDescriptorSet */
-
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) {
-  return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) {
-  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) {
-  struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FileDescriptorProto */
-
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); }
-UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
-
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(44, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(48, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(52, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value;
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
-}
-
-/* google.protobuf.DescriptorProto */
-
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); }
-UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); }
-UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
-UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(24, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 56), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(32, 64), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(36, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-
-/* google.protobuf.DescriptorProto.ExtensionRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) {
-  struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.DescriptorProto.ReservedRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-/* google.protobuf.ExtensionRangeOptions */
-
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) {
-  return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FieldDescriptorProto */
-
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 120), const google_protobuf_FieldOptions*); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool); }
-
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 8);
-  *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 9);
-  *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
-  _upb_sethas(msg, 11);
-  *UPB_PTR_AT(msg, UPB_SIZE(76, 120), google_protobuf_FieldOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 10);
-  *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool) = value;
-}
-
-/* google.protobuf.OneofDescriptorProto */
-
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); }
-
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.EnumDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-
-/* google.protobuf.EnumDescriptorProto.EnumReservedRange */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-/* google.protobuf.EnumValueDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); }
-
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.ServiceDescriptorProto */
-
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); }
-
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.MethodDescriptorProto */
-
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-
-/* google.protobuf.FileOptions */
-
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) {
-  return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 12); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 13); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 14); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 15); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 16); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 17); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 18); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 19); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 20); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(108, 192)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(108, 192), len); }
-
-UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 11);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 12);
-  *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 13);
-  *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 8);
-  *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 9);
-  *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 14);
-  *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 15);
-  *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 16);
-  *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 17);
-  *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 18);
-  *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 10);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 19);
-  *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 20);
-  *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 192), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(108, 192), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.MessageOptions */
-
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) {
-  return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); }
-
-UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(8, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FieldOptions */
-
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) {
-  return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 32)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); }
-
-UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.OneofOptions */
-
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) {
-  return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.EnumOptions */
-
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) {
-  return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.EnumValueOptions */
-
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) {
-  return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.ServiceOptions */
-
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) {
-  return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.MethodOptions */
-
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) {
-  return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
-UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 24)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); }
-
-UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.UninterpretedOption */
-
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); }
-UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); }
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(56, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value;
-}
-
-/* google.protobuf.UninterpretedOption.NamePart */
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-
-/* google.protobuf.SourceCodeInfo */
-
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) {
-  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) {
-  struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.SourceCodeInfo.Location */
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-
-/* google.protobuf.GeneratedCodeInfo */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) {
-  struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.GeneratedCodeInfo.Annotation */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len);
-}
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
-/*
-** Defs are upb's internal representation of the constructs that can appear
-** in a .proto file:
-**
-** - upb::MessageDefPtr (upb_msgdef): describes a "message" construct.
-** - upb::FieldDefPtr (upb_fielddef): describes a message field.
-** - upb::FileDefPtr (upb_filedef): describes a .proto file and its defs.
-** - upb::EnumDefPtr (upb_enumdef): describes an enum.
-** - upb::OneofDefPtr (upb_oneofdef): describes a oneof.
-**
-** TODO: definitions of services.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_DEF_H_
-#define UPB_DEF_H_
-
-
-#ifdef __cplusplus
-#include <cstring>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace upb {
-class EnumDefPtr;
-class FieldDefPtr;
-class FileDefPtr;
-class MessageDefPtr;
-class OneofDefPtr;
-class SymbolTable;
-}
-#endif
-
-
-struct upb_enumdef;
-typedef struct upb_enumdef upb_enumdef;
-struct upb_fielddef;
-typedef struct upb_fielddef upb_fielddef;
-struct upb_filedef;
-typedef struct upb_filedef upb_filedef;
-struct upb_msgdef;
-typedef struct upb_msgdef upb_msgdef;
-struct upb_oneofdef;
-typedef struct upb_oneofdef upb_oneofdef;
-struct upb_symtab;
-typedef struct upb_symtab upb_symtab;
-
-typedef enum {
-  UPB_SYNTAX_PROTO2 = 2,
-  UPB_SYNTAX_PROTO3 = 3
-} upb_syntax_t;
-
-/* All the different kind of well known type messages. For simplicity of check,
- * number wrappers and string wrappers are grouped together. Make sure the
- * order and merber of these groups are not changed.
- */
-typedef enum {
-  UPB_WELLKNOWN_UNSPECIFIED,
-  UPB_WELLKNOWN_ANY,
-  UPB_WELLKNOWN_FIELDMASK,
-  UPB_WELLKNOWN_DURATION,
-  UPB_WELLKNOWN_TIMESTAMP,
-  /* number wrappers */
-  UPB_WELLKNOWN_DOUBLEVALUE,
-  UPB_WELLKNOWN_FLOATVALUE,
-  UPB_WELLKNOWN_INT64VALUE,
-  UPB_WELLKNOWN_UINT64VALUE,
-  UPB_WELLKNOWN_INT32VALUE,
-  UPB_WELLKNOWN_UINT32VALUE,
-  /* string wrappers */
-  UPB_WELLKNOWN_STRINGVALUE,
-  UPB_WELLKNOWN_BYTESVALUE,
-  UPB_WELLKNOWN_BOOLVALUE,
-  UPB_WELLKNOWN_VALUE,
-  UPB_WELLKNOWN_LISTVALUE,
-  UPB_WELLKNOWN_STRUCT
-} upb_wellknowntype_t;
-
-/* upb_fielddef ***************************************************************/
-
-/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
- * protobuf wire format. */
-#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_fielddef_fullname(const upb_fielddef *f);
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
-upb_label_t upb_fielddef_label(const upb_fielddef *f);
-uint32_t upb_fielddef_number(const upb_fielddef *f);
-const char *upb_fielddef_name(const upb_fielddef *f);
-const char *upb_fielddef_jsonname(const upb_fielddef *f);
-bool upb_fielddef_isextension(const upb_fielddef *f);
-bool upb_fielddef_lazy(const upb_fielddef *f);
-bool upb_fielddef_packed(const upb_fielddef *f);
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
-uint32_t upb_fielddef_index(const upb_fielddef *f);
-bool upb_fielddef_issubmsg(const upb_fielddef *f);
-bool upb_fielddef_isstring(const upb_fielddef *f);
-bool upb_fielddef_isseq(const upb_fielddef *f);
-bool upb_fielddef_isprimitive(const upb_fielddef *f);
-bool upb_fielddef_ismap(const upb_fielddef *f);
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
-bool upb_fielddef_defaultbool(const upb_fielddef *f);
-float upb_fielddef_defaultfloat(const upb_fielddef *f);
-double upb_fielddef_defaultdouble(const upb_fielddef *f);
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
-bool upb_fielddef_hassubdef(const upb_fielddef *f);
-bool upb_fielddef_haspresence(const upb_fielddef *f);
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
-const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f);
-
-/* Internal only. */
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A upb_fielddef describes a single field in a message.  It is most often
- * found as a part of a upb_msgdef, but can also stand alone to represent
- * an extension. */
-class upb::FieldDefPtr {
- public:
-  FieldDefPtr() : ptr_(nullptr) {}
-  explicit FieldDefPtr(const upb_fielddef *ptr) : ptr_(ptr) {}
-
-  const upb_fielddef* ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  typedef upb_fieldtype_t Type;
-  typedef upb_label_t Label;
-  typedef upb_descriptortype_t DescriptorType;
-
-  const char* full_name() const { return upb_fielddef_fullname(ptr_); }
-
-  Type type() const { return upb_fielddef_type(ptr_); }
-  Label label() const { return upb_fielddef_label(ptr_); }
-  const char* name() const { return upb_fielddef_name(ptr_); }
-  const char* json_name() const { return upb_fielddef_jsonname(ptr_); }
-  uint32_t number() const { return upb_fielddef_number(ptr_); }
-  bool is_extension() const { return upb_fielddef_isextension(ptr_); }
-
-  /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false,
-   * indicates whether this field should have lazy parsing handlers that yield
-   * the unparsed string for the submessage.
-   *
-   * TODO(haberman): I think we want to move this into a FieldOptions container
-   * when we add support for custom options (the FieldOptions struct will
-   * contain both regular FieldOptions like "lazy" *and* custom options). */
-  bool lazy() const { return upb_fielddef_lazy(ptr_); }
-
-  /* For non-string, non-submessage fields, this indicates whether binary
-   * protobufs are encoded in packed or non-packed format.
-   *
-   * TODO(haberman): see note above about putting options like this into a
-   * FieldOptions container. */
-  bool packed() const { return upb_fielddef_packed(ptr_); }
-
-  /* An integer that can be used as an index into an array of fields for
-   * whatever message this field belongs to.  Guaranteed to be less than
-   * f->containing_type()->field_count().  May only be accessed once the def has
-   * been finalized. */
-  uint32_t index() const { return upb_fielddef_index(ptr_); }
-
-  /* The MessageDef to which this field belongs.
-   *
-   * If this field has been added to a MessageDef, that message can be retrieved
-   * directly (this is always the case for frozen FieldDefs).
-   *
-   * If the field has not yet been added to a MessageDef, you can set the name
-   * of the containing type symbolically instead.  This is mostly useful for
-   * extensions, where the extension is declared separately from the message. */
-  MessageDefPtr containing_type() const;
-
-  /* The OneofDef to which this field belongs, or NULL if this field is not part
-   * of a oneof. */
-  OneofDefPtr containing_oneof() const;
-
-  /* The field's type according to the enum in descriptor.proto.  This is not
-   * the same as UPB_TYPE_*, because it distinguishes between (for example)
-   * INT32 and SINT32, whereas our "type" enum does not.  This return of
-   * descriptor_type() is a function of type(), integer_format(), and
-   * is_tag_delimited().  */
-  DescriptorType descriptor_type() const {
-    return upb_fielddef_descriptortype(ptr_);
-  }
-
-  /* Convenient field type tests. */
-  bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); }
-  bool IsString() const { return upb_fielddef_isstring(ptr_); }
-  bool IsSequence() const { return upb_fielddef_isseq(ptr_); }
-  bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); }
-  bool IsMap() const { return upb_fielddef_ismap(ptr_); }
-
-  /* Returns the non-string default value for this fielddef, which may either
-   * be something the client set explicitly or the "default default" (0 for
-   * numbers, empty for strings).  The field's type indicates the type of the
-   * returned value, except for enum fields that are still mutable.
-   *
-   * Requires that the given function matches the field's current type. */
-  int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); }
-  int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); }
-  uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); }
-  uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); }
-  bool default_bool() const { return upb_fielddef_defaultbool(ptr_); }
-  float default_float() const { return upb_fielddef_defaultfloat(ptr_); }
-  double default_double() const { return upb_fielddef_defaultdouble(ptr_); }
-
-  /* The resulting string is always NULL-terminated.  If non-NULL, the length
-   * will be stored in *len. */
-  const char *default_string(size_t * len) const {
-    return upb_fielddef_defaultstr(ptr_, len);
-  }
-
-  /* Returns the enum or submessage def for this field, if any.  The field's
-   * type must match (ie. you may only call enum_subdef() for fields where
-   * type() == UPB_TYPE_ENUM). */
-  EnumDefPtr enum_subdef() const;
-  MessageDefPtr message_subdef() const;
-
- private:
-  const upb_fielddef *ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_oneofdef ***************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef upb_inttable_iter upb_oneof_iter;
-
-const char *upb_oneofdef_name(const upb_oneofdef *o);
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
-int upb_oneofdef_numfields(const upb_oneofdef *o);
-uint32_t upb_oneofdef_index(const upb_oneofdef *o);
-bool upb_oneofdef_synthetic(const upb_oneofdef *o);
-
-/* Oneof lookups:
- * - ntof:  look up a field by name.
- * - ntofz: look up a field by name (as a null-terminated string).
- * - itof:  look up a field by number. */
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
-                                      const char *name, size_t length);
-UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
-                                                  const char *name) {
-  return upb_oneofdef_ntof(o, name, strlen(name));
-}
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
-
-/*  upb_oneof_iter i;
- *  for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) {
- *    // ...
- *  }
- */
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
-void upb_oneof_next(upb_oneof_iter *iter);
-bool upb_oneof_done(upb_oneof_iter *iter);
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
-void upb_oneof_iter_setdone(upb_oneof_iter *iter);
-bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
-                            const upb_oneof_iter *iter2);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Class that represents a oneof. */
-class upb::OneofDefPtr {
- public:
-  OneofDefPtr() : ptr_(nullptr) {}
-  explicit OneofDefPtr(const upb_oneofdef *ptr) : ptr_(ptr) {}
-
-  const upb_oneofdef* ptr() const { return ptr_; }
-  explicit operator bool() { return ptr_ != nullptr; }
-
-  /* Returns the MessageDef that owns this OneofDef. */
-  MessageDefPtr containing_type() const;
-
-  /* Returns the name of this oneof. This is the name used to look up the oneof
-   * by name once added to a message def. */
-  const char* name() const { return upb_oneofdef_name(ptr_); }
-
-  /* Returns the number of fields currently defined in the oneof. */
-  int field_count() const { return upb_oneofdef_numfields(ptr_); }
-
-  /* Looks up by name. */
-  FieldDefPtr FindFieldByName(const char *name, size_t len) const {
-    return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len));
-  }
-  FieldDefPtr FindFieldByName(const char* name) const {
-    return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name));
-  }
-
-  template <class T>
-  FieldDefPtr FindFieldByName(const T& str) const {
-    return FindFieldByName(str.c_str(), str.size());
-  }
-
-  /* Looks up by tag number. */
-  FieldDefPtr FindFieldByNumber(uint32_t num) const {
-    return FieldDefPtr(upb_oneofdef_itof(ptr_, num));
-  }
-
-  class const_iterator
-      : public std::iterator<std::forward_iterator_tag, FieldDefPtr> {
-   public:
-    void operator++() { upb_oneof_next(&iter_); }
-
-    FieldDefPtr operator*() const {
-      return FieldDefPtr(upb_oneof_iter_field(&iter_));
-    }
-
-    bool operator!=(const const_iterator& other) const {
-      return !upb_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-    bool operator==(const const_iterator& other) const {
-      return upb_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-   private:
-    friend class OneofDefPtr;
-
-    const_iterator() {}
-    explicit const_iterator(OneofDefPtr o) {
-      upb_oneof_begin(&iter_, o.ptr());
-    }
-    static const_iterator end() {
-      const_iterator iter;
-      upb_oneof_iter_setdone(&iter.iter_);
-      return iter;
-    }
-
-    upb_oneof_iter iter_;
-  };
-
-  const_iterator begin() const { return const_iterator(*this); }
-  const_iterator end() const { return const_iterator::end(); }
-
- private:
-  const upb_oneofdef *ptr_;
-};
-
-inline upb::OneofDefPtr upb::FieldDefPtr::containing_oneof() const {
-  return OneofDefPtr(upb_fielddef_containingoneof(ptr_));
-}
-
-#endif  /* __cplusplus */
-
-/* upb_msgdef *****************************************************************/
-
-typedef upb_inttable_iter upb_msg_field_iter;
-typedef upb_strtable_iter upb_msg_oneof_iter;
-
-/* Well-known field tag numbers for map-entry messages. */
-#define UPB_MAPENTRY_KEY   1
-#define UPB_MAPENTRY_VALUE 2
-
-/* Well-known field tag numbers for Any messages. */
-#define UPB_ANY_TYPE 1
-#define UPB_ANY_VALUE 2
-
-/* Well-known field tag numbers for timestamp messages. */
-#define UPB_DURATION_SECONDS 1
-#define UPB_DURATION_NANOS 2
-
-/* Well-known field tag numbers for duration messages. */
-#define UPB_TIMESTAMP_SECONDS 1
-#define UPB_TIMESTAMP_NANOS 2
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_msgdef_fullname(const upb_msgdef *m);
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
-const char *upb_msgdef_name(const upb_msgdef *m);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
-bool upb_msgdef_mapentry(const upb_msgdef *m);
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
-bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax);
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
-                                    size_t len);
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
-                                    size_t len);
-int upb_msgdef_numfields(const upb_msgdef *m);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
-const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m);
-const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i);
-
-UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
-                                               const char *name) {
-  return upb_msgdef_ntoo(m, name, strlen(name));
-}
-
-UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
-                                                const char *name) {
-  return upb_msgdef_ntof(m, name, strlen(name));
-}
-
-/* Internal-only. */
-size_t upb_msgdef_selectorcount(const upb_msgdef *m);
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m);
-
-/* Lookup of either field or oneof by name.  Returns whether either was found.
- * If the return is true, then the found def will be set, and the non-found
- * one set to NULL. */
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
-                           const upb_fielddef **f, const upb_oneofdef **o);
-
-UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
-                                       const upb_fielddef **f,
-                                       const upb_oneofdef **o) {
-  return upb_msgdef_lookupname(m, name, strlen(name), f, o);
-}
-
-/* Returns a field by either JSON name or regular proto name. */
-const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
-                                              const char *name, size_t len);
-
-/* Iteration over fields and oneofs.  For example:
- *
- * upb_msg_field_iter i;
- * for(upb_msg_field_begin(&i, m);
- *     !upb_msg_field_done(&i);
- *     upb_msg_field_next(&i)) {
- *   upb_fielddef *f = upb_msg_iter_field(&i);
- *   // ...
- * }
- *
- * For C we don't have separate iterators for const and non-const.
- * It is the caller's responsibility to cast the upb_fielddef* to
- * const if the upb_msgdef* is const. */
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
-void upb_msg_field_next(upb_msg_field_iter *iter);
-bool upb_msg_field_done(const upb_msg_field_iter *iter);
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
-                                const upb_msg_field_iter * iter2);
-
-/* Similar to above, we also support iterating through the oneofs in a
- * msgdef. */
-void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
-void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
-                                const upb_msg_oneof_iter *iter2);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Structure that describes a single .proto message type. */
-class upb::MessageDefPtr {
- public:
-  MessageDefPtr() : ptr_(nullptr) {}
-  explicit MessageDefPtr(const upb_msgdef *ptr) : ptr_(ptr) {}
-
-  const upb_msgdef *ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  const char* full_name() const { return upb_msgdef_fullname(ptr_); }
-  const char* name() const { return upb_msgdef_name(ptr_); }
-
-  /* The number of fields that belong to the MessageDef. */
-  int field_count() const { return upb_msgdef_numfields(ptr_); }
-
-  /* The number of oneofs that belong to the MessageDef. */
-  int oneof_count() const { return upb_msgdef_numoneofs(ptr_); }
-
-  upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); }
-
-  /* These return null pointers if the field is not found. */
-  FieldDefPtr FindFieldByNumber(uint32_t number) const {
-    return FieldDefPtr(upb_msgdef_itof(ptr_, number));
-  }
-  FieldDefPtr FindFieldByName(const char* name, size_t len) const {
-    return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len));
-  }
-  FieldDefPtr FindFieldByName(const char *name) const {
-    return FieldDefPtr(upb_msgdef_ntofz(ptr_, name));
-  }
-
-  template <class T>
-  FieldDefPtr FindFieldByName(const T& str) const {
-    return FindFieldByName(str.c_str(), str.size());
-  }
-
-  OneofDefPtr FindOneofByName(const char* name, size_t len) const {
-    return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len));
-  }
-
-  OneofDefPtr FindOneofByName(const char *name) const {
-    return OneofDefPtr(upb_msgdef_ntooz(ptr_, name));
-  }
-
-  template <class T>
-  OneofDefPtr FindOneofByName(const T &str) const {
-    return FindOneofByName(str.c_str(), str.size());
-  }
-
-  /* Is this message a map entry? */
-  bool mapentry() const { return upb_msgdef_mapentry(ptr_); }
-
-  /* Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for
-   * non-well-known message. */
-  upb_wellknowntype_t wellknowntype() const {
-    return upb_msgdef_wellknowntype(ptr_);
-  }
-
-  /* Whether is a number wrapper. */
-  bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); }
-
-  /* Iteration over fields.  The order is undefined. */
-  class const_field_iterator
-      : public std::iterator<std::forward_iterator_tag, FieldDefPtr> {
-   public:
-    void operator++() { upb_msg_field_next(&iter_); }
-
-    FieldDefPtr operator*() const {
-      return FieldDefPtr(upb_msg_iter_field(&iter_));
-    }
-
-    bool operator!=(const const_field_iterator &other) const {
-      return !upb_msg_field_iter_isequal(&iter_, &other.iter_);
-    }
-
-    bool operator==(const const_field_iterator &other) const {
-      return upb_msg_field_iter_isequal(&iter_, &other.iter_);
-    }
-
-   private:
-    friend class MessageDefPtr;
-
-    explicit const_field_iterator() {}
-
-    explicit const_field_iterator(MessageDefPtr msg) {
-      upb_msg_field_begin(&iter_, msg.ptr());
-    }
-
-    static const_field_iterator end() {
-      const_field_iterator iter;
-      upb_msg_field_iter_setdone(&iter.iter_);
-      return iter;
-    }
-
-    upb_msg_field_iter iter_;
-  };
-
-  /* Iteration over oneofs. The order is undefined. */
-  class const_oneof_iterator
-      : public std::iterator<std::forward_iterator_tag, OneofDefPtr> {
-   public:
-
-    void operator++() { upb_msg_oneof_next(&iter_); }
-
-    OneofDefPtr operator*() const {
-      return OneofDefPtr(upb_msg_iter_oneof(&iter_));
-    }
-
-    bool operator!=(const const_oneof_iterator& other) const {
-      return !upb_msg_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-    bool operator==(const const_oneof_iterator &other) const {
-      return upb_msg_oneof_iter_isequal(&iter_, &other.iter_);
-    }
-
-   private:
-    friend class MessageDefPtr;
-
-    const_oneof_iterator() {}
-
-    explicit const_oneof_iterator(MessageDefPtr msg) {
-      upb_msg_oneof_begin(&iter_, msg.ptr());
-    }
-
-    static const_oneof_iterator end() {
-      const_oneof_iterator iter;
-      upb_msg_oneof_iter_setdone(&iter.iter_);
-      return iter;
-    }
-
-    upb_msg_oneof_iter iter_;
-  };
-
-  class ConstFieldAccessor {
-   public:
-    explicit ConstFieldAccessor(const upb_msgdef* md) : md_(md) {}
-    const_field_iterator begin() { return MessageDefPtr(md_).field_begin(); }
-    const_field_iterator end() { return MessageDefPtr(md_).field_end(); }
-   private:
-    const upb_msgdef* md_;
-  };
-
-  class ConstOneofAccessor {
-   public:
-    explicit ConstOneofAccessor(const upb_msgdef* md) : md_(md) {}
-    const_oneof_iterator begin() { return MessageDefPtr(md_).oneof_begin(); }
-    const_oneof_iterator end() { return MessageDefPtr(md_).oneof_end(); }
-   private:
-    const upb_msgdef* md_;
-  };
-
-  const_field_iterator field_begin() const {
-    return const_field_iterator(*this);
-  }
-
-  const_field_iterator field_end() const { return const_field_iterator::end(); }
-
-  const_oneof_iterator oneof_begin() const {
-    return const_oneof_iterator(*this);
-  }
-
-  const_oneof_iterator oneof_end() const { return const_oneof_iterator::end(); }
-
-  ConstFieldAccessor fields() const { return ConstFieldAccessor(ptr()); }
-  ConstOneofAccessor oneofs() const { return ConstOneofAccessor(ptr()); }
-
- private:
-  const upb_msgdef* ptr_;
-};
-
-inline upb::MessageDefPtr upb::FieldDefPtr::message_subdef() const {
-  return MessageDefPtr(upb_fielddef_msgsubdef(ptr_));
-}
-
-inline upb::MessageDefPtr upb::FieldDefPtr::containing_type() const {
-  return MessageDefPtr(upb_fielddef_containingtype(ptr_));
-}
-
-inline upb::MessageDefPtr upb::OneofDefPtr::containing_type() const {
-  return MessageDefPtr(upb_oneofdef_containingtype(ptr_));
-}
-
-#endif  /* __cplusplus */
-
-/* upb_enumdef ****************************************************************/
-
-typedef upb_strtable_iter upb_enum_iter;
-
-const char *upb_enumdef_fullname(const upb_enumdef *e);
-const char *upb_enumdef_name(const upb_enumdef *e);
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
-int32_t upb_enumdef_default(const upb_enumdef *e);
-int upb_enumdef_numvals(const upb_enumdef *e);
-
-/* Enum lookups:
- * - ntoi:  look up a name with specified length.
- * - ntoiz: look up a name provided as a null-terminated string.
- * - iton:  look up an integer, returning the name as a null-terminated
- *          string. */
-bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
-                      int32_t *num);
-UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
-                                  const char *name, int32_t *num) {
-  return upb_enumdef_ntoi(e, name, strlen(name), num);
-}
-const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
-
-/*  upb_enum_iter i;
- *  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
- *    // ...
- *  }
- */
-void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
-void upb_enum_next(upb_enum_iter *iter);
-bool upb_enum_done(upb_enum_iter *iter);
-const char *upb_enum_iter_name(upb_enum_iter *iter);
-int32_t upb_enum_iter_number(upb_enum_iter *iter);
-
-#ifdef __cplusplus
-
-class upb::EnumDefPtr {
- public:
-  EnumDefPtr() : ptr_(nullptr) {}
-  explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {}
-
-  const upb_enumdef* ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  const char* full_name() const { return upb_enumdef_fullname(ptr_); }
-  const char* name() const { return upb_enumdef_name(ptr_); }
-
-  /* The value that is used as the default when no field default is specified.
-   * If not set explicitly, the first value that was added will be used.
-   * The default value must be a member of the enum.
-   * Requires that value_count() > 0. */
-  int32_t default_value() const { return upb_enumdef_default(ptr_); }
-
-  /* Returns the number of values currently defined in the enum.  Note that
-   * multiple names can refer to the same number, so this may be greater than
-   * the total number of unique numbers. */
-  int value_count() const { return upb_enumdef_numvals(ptr_); }
-
-  /* Lookups from name to integer, returning true if found. */
-  bool FindValueByName(const char *name, int32_t *num) const {
-    return upb_enumdef_ntoiz(ptr_, name, num);
-  }
-
-  /* Finds the name corresponding to the given number, or NULL if none was
-   * found.  If more than one name corresponds to this number, returns the
-   * first one that was added. */
-  const char *FindValueByNumber(int32_t num) const {
-    return upb_enumdef_iton(ptr_, num);
-  }
-
-  /* Iteration over name/value pairs.  The order is undefined.
-   * Adding an enum val invalidates any iterators.
-   *
-   * TODO: make compatible with range-for, with elements as pairs? */
-  class Iterator {
-   public:
-    explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); }
-
-    int32_t number() { return upb_enum_iter_number(&iter_); }
-    const char *name() { return upb_enum_iter_name(&iter_); }
-    bool Done() { return upb_enum_done(&iter_); }
-    void Next() { return upb_enum_next(&iter_); }
-
-   private:
-    upb_enum_iter iter_;
-  };
-
- private:
-  const upb_enumdef *ptr_;
-};
-
-inline upb::EnumDefPtr upb::FieldDefPtr::enum_subdef() const {
-  return EnumDefPtr(upb_fielddef_enumsubdef(ptr_));
-}
-
-#endif  /* __cplusplus */
-
-/* upb_filedef ****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char *upb_filedef_name(const upb_filedef *f);
-const char *upb_filedef_package(const upb_filedef *f);
-const char *upb_filedef_phpprefix(const upb_filedef *f);
-const char *upb_filedef_phpnamespace(const upb_filedef *f);
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
-int upb_filedef_depcount(const upb_filedef *f);
-int upb_filedef_msgcount(const upb_filedef *f);
-int upb_filedef_enumcount(const upb_filedef *f);
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Class that represents a .proto file with some things defined in it.
- *
- * Many users won't care about FileDefs, but they are necessary if you want to
- * read the values of file-level options. */
-class upb::FileDefPtr {
- public:
-  explicit FileDefPtr(const upb_filedef *ptr) : ptr_(ptr) {}
-
-  const upb_filedef* ptr() const { return ptr_; }
-  explicit operator bool() const { return ptr_ != nullptr; }
-
-  /* Get/set name of the file (eg. "foo/bar.proto"). */
-  const char* name() const { return upb_filedef_name(ptr_); }
-
-  /* Package name for definitions inside the file (eg. "foo.bar"). */
-  const char* package() const { return upb_filedef_package(ptr_); }
-
-  /* Sets the php class prefix which is prepended to all php generated classes
-   * from this .proto. Default is empty. */
-  const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); }
-
-  /* Use this option to change the namespace of php generated classes. Default
-   * is empty. When this option is empty, the package name will be used for
-   * determining the namespace. */
-  const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); }
-
-  /* Syntax for the file.  Defaults to proto2. */
-  upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); }
-
-  /* Get the list of dependencies from the file.  These are returned in the
-   * order that they were added to the FileDefPtr. */
-  int dependency_count() const { return upb_filedef_depcount(ptr_); }
-  const FileDefPtr dependency(int index) const {
-    return FileDefPtr(upb_filedef_dep(ptr_, index));
-  }
-
- private:
-  const upb_filedef* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_symtab *****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_symtab *upb_symtab_new(void);
-void upb_symtab_free(upb_symtab* s);
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
-const upb_msgdef *upb_symtab_lookupmsg2(
-    const upb_symtab *s, const char *sym, size_t len);
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
-int upb_symtab_filecount(const upb_symtab *s);
-const upb_filedef *upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
-    upb_status *status);
-
-/* For generated code only: loads a generated descriptor. */
-typedef struct upb_def_init {
-  struct upb_def_init **deps;     /* Dependencies of this file. */
-  const upb_msglayout **layouts;  /* Pre-order layouts of all messages. */
-  const char *filename;
-  upb_strview descriptor;         /* Serialized descriptor. */
-} upb_def_init;
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Non-const methods in upb::SymbolTable are NOT thread-safe. */
-class upb::SymbolTable {
- public:
-  SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {}
-  explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {}
-
-  const upb_symtab* ptr() const { return ptr_.get(); }
-  upb_symtab* ptr() { return ptr_.get(); }
-
-  /* Finds an entry in the symbol table with this exact name.  If not found,
-   * returns NULL. */
-  MessageDefPtr LookupMessage(const char *sym) const {
-    return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym));
-  }
-
-  EnumDefPtr LookupEnum(const char *sym) const {
-    return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym));
-  }
-
-  FileDefPtr LookupFile(const char *name) const {
-    return FileDefPtr(upb_symtab_lookupfile(ptr_.get(), name));
-  }
-
-  /* TODO: iteration? */
-
-  /* Adds the given serialized FileDescriptorProto to the pool. */
-  FileDefPtr AddFile(const google_protobuf_FileDescriptorProto *file_proto,
-                     Status *status) {
-    return FileDefPtr(
-        upb_symtab_addfile(ptr_.get(), file_proto, status->ptr()));
-  }
-
- private:
-  std::unique_ptr<upb_symtab, decltype(&upb_symtab_free)> ptr_;
-};
-
-UPB_INLINE const char* upb_safecstr(const std::string& str) {
-  UPB_ASSERT(str.size() == std::strlen(str.c_str()));
-  return str.c_str();
-}
-
-#endif  /* __cplusplus */
-
-
-#endif /* UPB_DEF_H_ */
-
-#ifndef UPB_REFLECTION_H_
-#define UPB_REFLECTION_H_
-
-
-
-typedef union {
-  bool bool_val;
-  float float_val;
-  double double_val;
-  int32_t int32_val;
-  int64_t int64_val;
-  uint32_t uint32_val;
-  uint64_t uint64_val;
-  const upb_map* map_val;
-  const upb_msg* msg_val;
-  const upb_array* array_val;
-  upb_strview str_val;
-} upb_msgval;
-
-typedef union {
-  upb_map* map;
-  upb_msg* msg;
-  upb_array* array;
-} upb_mutmsgval;
-
-/** upb_msg *******************************************************************/
-
-/* Creates a new message of the given type in the given arena. */
-upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a);
-
-/* Returns the value associated with this field. */
-upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f);
-
-/* Returns a mutable pointer to a map, array, or submessage value.  If the given
- * arena is non-NULL this will construct a new object if it was not previously
- * present.  May not be called for primitive fields. */
-upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a);
-
-/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
-bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f);
-
-/* Returns whether any field is set in the oneof. */
-bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o);
-
-/* Sets the given field to the given value.  For a msg/array/map/string, the
- * value must be in the same arena.  */
-void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
-                 upb_arena *a);
-
-/* Clears any field presence and sets the value back to its default. */
-void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f);
-
-/* Iterate over present fields.
- *
- * size_t iter = UPB_MSG_BEGIN;
- * const upb_fielddef *f;
- * upb_msgval val;
- * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) {
- *   process_field(f, val);
- * }
- *
- * If ext_pool is NULL, no extensions will be returned.  If the given symtab
- * returns extensions that don't match what is in this message, those extensions
- * will be skipped.
- */
-
-#define UPB_MSG_BEGIN -1
-bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
-                  const upb_symtab *ext_pool, const upb_fielddef **f,
-                  upb_msgval *val, size_t *iter);
-
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                        upb_arena *arena);
-
-/* Returns a reference to the message's unknown data. */
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-
-/** upb_array *****************************************************************/
-
-/* Creates a new array on the given arena that holds elements of this type. */
-upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type);
-
-/* Returns the size of the array. */
-size_t upb_array_size(const upb_array *arr);
-
-/* Returns the given element, which must be within the array's current size. */
-upb_msgval upb_array_get(const upb_array *arr, size_t i);
-
-/* Sets the given element, which must be within the array's current size. */
-void upb_array_set(upb_array *arr, size_t i, upb_msgval val);
-
-/* Appends an element to the array.  Returns false on allocation failure. */
-bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena);
-
-/* Changes the size of a vector.  New elements are initialized to empty/0.
- * Returns false on allocation failure. */
-bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena);
-
-/** upb_map *******************************************************************/
-
-/* Creates a new map on the given arena with the given key/value size. */
-upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
-                     upb_fieldtype_t value_type);
-
-/* Returns the number of entries in the map. */
-size_t upb_map_size(const upb_map *map);
-
-/* Stores a value for the given key into |*val| (or the zero value if the key is
- * not present).  Returns whether the key was present.  The |val| pointer may be
- * NULL, in which case the function tests whether the given key is present.  */
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
-
-/* Removes all entries in the map. */
-void upb_map_clear(upb_map *map);
-
-/* Sets the given key to the given value.  Returns true if this was a new key in
- * the map, or false if an existing key was replaced. */
-bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
-                 upb_arena *arena);
-
-/* Deletes this key from the table.  Returns true if the key was present. */
-bool upb_map_delete(upb_map *map, upb_msgval key);
-
-/* Map iteration:
- *
- * size_t iter = UPB_MAP_BEGIN;
- * while (upb_mapiter_next(map, &iter)) {
- *   upb_msgval key = upb_mapiter_key(map, iter);
- *   upb_msgval val = upb_mapiter_value(map, iter);
- *
- *   // If mutating is desired.
- *   upb_mapiter_setvalue(map, iter, value2);
- * }
- */
-
-/* Advances to the next entry.  Returns false if no more entries are present. */
-bool upb_mapiter_next(const upb_map *map, size_t *iter);
-
-/* Returns the key and value for this entry of the map. */
-upb_msgval upb_mapiter_key(const upb_map *map, size_t iter);
-upb_msgval upb_mapiter_value(const upb_map *map, size_t iter);
-
-/* Sets the value for this entry.  The iterator must not be done, and the
- * iterator must not have been initialized const. */
-void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value);
-
-
-#endif /* UPB_REFLECTION_H_ */
-/*
-** upb::Handlers (upb_handlers)
-**
-** A upb_handlers is like a virtual table for a upb_msgdef.  Each field of the
-** message can have associated functions that will be called when we are
-** parsing or visiting a stream of data.  This is similar to how handlers work
-** in SAX (the Simple API for XML).
-**
-** The handlers have no idea where the data is coming from, so a single set of
-** handlers could be used with two completely different data sources (for
-** example, a parser and a visitor over in-memory objects).  This decoupling is
-** the most important feature of upb, because it allows parsers and serializers
-** to be highly reusable.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_HANDLERS_H
-#define UPB_HANDLERS_H
-
-
-
-#ifdef __cplusplus
-namespace upb {
-class HandlersPtr;
-class HandlerCache;
-template <class T> class Handler;
-template <class T> struct CanonicalType;
-}  /* namespace upb */
-#endif
-
-
-/* The maximum depth that the handler graph can have.  This is a resource limit
- * for the C stack since we sometimes need to recursively traverse the graph.
- * Cycles are ok; the traversal will stop when it detects a cycle, but we must
- * hit the cycle before the maximum depth is reached.
- *
- * If having a single static limit is too inflexible, we can add another variant
- * of Handlers::Freeze that allows specifying this as a parameter. */
-#define UPB_MAX_HANDLER_DEPTH 64
-
-/* All the different types of handlers that can be registered.
- * Only needed for the advanced functions in upb::Handlers. */
-typedef enum {
-  UPB_HANDLER_INT32,
-  UPB_HANDLER_INT64,
-  UPB_HANDLER_UINT32,
-  UPB_HANDLER_UINT64,
-  UPB_HANDLER_FLOAT,
-  UPB_HANDLER_DOUBLE,
-  UPB_HANDLER_BOOL,
-  UPB_HANDLER_STARTSTR,
-  UPB_HANDLER_STRING,
-  UPB_HANDLER_ENDSTR,
-  UPB_HANDLER_STARTSUBMSG,
-  UPB_HANDLER_ENDSUBMSG,
-  UPB_HANDLER_STARTSEQ,
-  UPB_HANDLER_ENDSEQ
-} upb_handlertype_t;
-
-#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1)
-
-#define UPB_BREAK NULL
-
-/* A convenient definition for when no closure is needed. */
-extern char _upb_noclosure;
-#define UPB_NO_CLOSURE &_upb_noclosure
-
-/* A selector refers to a specific field handler in the Handlers object
- * (for example: the STARTSUBMSG handler for field "field15"). */
-typedef int32_t upb_selector_t;
-
-/* Static selectors for upb::Handlers. */
-#define UPB_STARTMSG_SELECTOR 0
-#define UPB_ENDMSG_SELECTOR 1
-#define UPB_UNKNOWN_SELECTOR 2
-#define UPB_STATIC_SELECTOR_COUNT 3  /* Warning: also in upb/def.c. */
-
-/* Static selectors for upb::BytesHandler. */
-#define UPB_STARTSTR_SELECTOR 0
-#define UPB_STRING_SELECTOR 1
-#define UPB_ENDSTR_SELECTOR 2
-
-#ifdef __cplusplus
-template<class T> const void *UniquePtrForType() {
-  static const char ch = 0;
-  return &ch;
-}
-#endif
-
-/* upb_handlers ************************************************************/
-
-/* Handler attributes, to be registered with the handler itself. */
-typedef struct {
-  const void *handler_data;
-  const void *closure_type;
-  const void *return_closure_type;
-  bool alwaysok;
-} upb_handlerattr;
-
-#define UPB_HANDLERATTR_INIT {NULL, NULL, NULL, false}
-
-/* Bufhandle, data passed along with a buffer to indicate its provenance. */
-typedef struct {
-  /* The beginning of the buffer.  This may be different than the pointer
-   * passed to a StringBuf handler because the handler may receive data
-   * that is from the middle or end of a larger buffer. */
-  const char *buf;
-
-  /* The offset within the attached object where this buffer begins.  Only
-   * meaningful if there is an attached object. */
-  size_t objofs;
-
-  /* The attached object (if any) and a pointer representing its type. */
-  const void *obj;
-  const void *objtype;
-
-#ifdef __cplusplus
-  template <class T>
-  void SetAttachedObject(const T* _obj) {
-    obj = _obj;
-    objtype = UniquePtrForType<T>();
-  }
-
-  template <class T>
-  const T *GetAttachedObject() const {
-    return objtype == UniquePtrForType<T>() ? static_cast<const T *>(obj)
-                                            : NULL;
-  }
-#endif
-} upb_bufhandle;
-
-#define UPB_BUFHANDLE_INIT {NULL, 0, NULL, NULL}
-
-/* Handler function typedefs. */
-typedef void upb_handlerfree(void *d);
-typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf,
-                                     size_t n);
-typedef bool upb_startmsg_handlerfunc(void *c, const void*);
-typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
-typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
-typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
-typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
-typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
-typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
-typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
-typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
-typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
-                                       size_t size_hint);
-typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
-                                      size_t n, const upb_bufhandle* handle);
-
-struct upb_handlers;
-typedef struct upb_handlers upb_handlers;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Mutating accessors. */
-const upb_status *upb_handlers_status(upb_handlers *h);
-void upb_handlers_clearerr(upb_handlers *h);
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
-                             const upb_handlerattr *attr);
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
-                           upb_int32_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
-                           upb_int64_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
-                            upb_uint32_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
-                            upb_uint64_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
-                           upb_float_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
-                            upb_double_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
-                          upb_bool_handlerfunc *func,
-                          const upb_handlerattr *attr);
-bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
-                              upb_startstr_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
-                            upb_string_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
-                            upb_endfield_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
-                              upb_startfield_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
-                                 upb_startfield_handlerfunc *func,
-                                 const upb_handlerattr *attr);
-bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
-                               upb_endfield_handlerfunc *func,
-                               const upb_handlerattr *attr);
-bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
-                            upb_endfield_handlerfunc *func,
-                            const upb_handlerattr *attr);
-
-/* Read-only accessors. */
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
-                                                const upb_fielddef *f);
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
-                                                    upb_selector_t sel);
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
-                                  const void **handler_data);
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
-                          upb_handlerattr *attr);
-
-/* "Static" methods */
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
-                              upb_selector_t *s);
-UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
-  return start + 1;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-typedef upb_handlers Handlers;
-}
-
-/* Convenience macros for creating a Handler object that is wrapped with a
- * type-safe wrapper function that converts the "void*" parameters/returns
- * of the underlying C API into nice C++ function.
- *
- * Sample usage:
- *   void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
- *     // do stuff ...
- *   }
- *
- *   // Handler that doesn't need any data bound to it.
- *   void OnValue2(MyClosure* c, int32_t val) {
- *     // do stuff ...
- *   }
- *
- *   // Handler that returns bool so it can return failure if necessary.
- *   bool OnValue3(MyClosure* c, int32_t val) {
- *     // do stuff ...
- *     return ok;
- *   }
- *
- *   // Member function handler.
- *   class MyClosure {
- *    public:
- *     void OnValue(int32_t val) {
- *       // do stuff ...
- *     }
- *   };
- *
- *   // Takes ownership of the MyHandlerData.
- *   handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
- *   handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
- *   handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
- *   handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
- */
-
-/* In C++11, the "template" disambiguator can appear even outside templates,
- * so all calls can safely use this pair of macros. */
-
-#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>()
-
-/* We have to be careful to only evaluate "d" once. */
-#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
-
-/* Handler: a struct that contains the (handler, data, deleter) tuple that is
- * used to register all handlers.  Users can Make() these directly but it's
- * more convenient to use the UpbMakeHandler/UpbBind macros above. */
-template <class T> class upb::Handler {
- public:
-  /* The underlying, handler function signature that upb uses internally. */
-  typedef T FuncPtr;
-
-  /* Intentionally implicit. */
-  template <class F> Handler(F func);
-  ~Handler() { UPB_ASSERT(registered_); }
-
-  void AddCleanup(upb_handlers* h) const;
-  FuncPtr handler() const { return handler_; }
-  const upb_handlerattr& attr() const { return attr_; }
-
- private:
-  Handler(const Handler&) = delete;
-  Handler& operator=(const Handler&) = delete;
-
-  FuncPtr handler_;
-  mutable upb_handlerattr attr_;
-  mutable bool registered_;
-  void *cleanup_data_;
-  upb_handlerfree *cleanup_func_;
-};
-
-/* A upb::Handlers object represents the set of handlers associated with a
- * message in the graph of messages.  You can think of it as a big virtual
- * table with functions corresponding to all the events that can fire while
- * parsing or visiting a message of a specific type.
- *
- * Any handlers that are not set behave as if they had successfully consumed
- * the value.  Any unset Start* handlers will propagate their closure to the
- * inner frame.
- *
- * The easiest way to create the *Handler objects needed by the Set* methods is
- * with the UpbBind() and UpbMakeHandler() macros; see below. */
-class upb::HandlersPtr {
- public:
-  HandlersPtr(upb_handlers* ptr) : ptr_(ptr) {}
-
-  upb_handlers* ptr() const { return ptr_; }
-
-  typedef upb_selector_t Selector;
-  typedef upb_handlertype_t Type;
-
-  typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
-  typedef Handler<bool (*)(void *, const void *)> EndFieldHandler;
-  typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
-  typedef Handler<bool (*)(void *, const void *, upb_status *)>
-      EndMessageHandler;
-  typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
-  typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
-                             const upb_bufhandle *)>
-      StringHandler;
-
-  template <class T> struct ValueHandler {
-    typedef Handler<bool(*)(void *, const void *, T)> H;
-  };
-
-  typedef ValueHandler<int32_t>::H     Int32Handler;
-  typedef ValueHandler<int64_t>::H     Int64Handler;
-  typedef ValueHandler<uint32_t>::H    UInt32Handler;
-  typedef ValueHandler<uint64_t>::H    UInt64Handler;
-  typedef ValueHandler<float>::H       FloatHandler;
-  typedef ValueHandler<double>::H      DoubleHandler;
-  typedef ValueHandler<bool>::H        BoolHandler;
-
-  /* Any function pointer can be converted to this and converted back to its
-   * correct type. */
-  typedef void GenericFunction();
-
-  typedef void HandlersCallback(const void *closure, upb_handlers *h);
-
-  /* Returns the msgdef associated with this handlers object. */
-  MessageDefPtr message_def() const {
-    return MessageDefPtr(upb_handlers_msgdef(ptr()));
-  }
-
-  /* Adds the given pointer and function to the list of cleanup functions that
-   * will be run when these handlers are freed.  If this pointer has previously
-   * been registered, the function returns false and does nothing. */
-  bool AddCleanup(void *ptr, upb_handlerfree *cleanup) {
-    return upb_handlers_addcleanup(ptr_, ptr, cleanup);
-  }
-
-  /* Sets the startmsg handler for the message, which is defined as follows:
-   *
-   *   bool startmsg(MyType* closure) {
-   *     // Called when the message begins.  Returns true if processing should
-   *     // continue.
-   *     return true;
-   *   }
-   */
-  bool SetStartMessageHandler(const StartMessageHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartmsg(ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the endmsg handler for the message, which is defined as follows:
-   *
-   *   bool endmsg(MyType* closure, upb_status *status) {
-   *     // Called when processing of this message ends, whether in success or
-   *     // failure.  "status" indicates the final status of processing, and
-   *     // can also be modified in-place to update the final status.
-   *   }
-   */
-  bool SetEndMessageHandler(const EndMessageHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendmsg(ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the value handler for the given field, which is defined as follows
-   * (this is for an int32 field; other field types will pass their native
-   * C/C++ type for "val"):
-   *
-   *   bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
-   *     // Called when the field's value is encountered.  "d" contains
-   *     // whatever data was bound to this field when it was registered.
-   *     // Returns true if processing should continue.
-   *     return true;
-   *   }
-   *
-   *   handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...)));
-   *
-   * The value type must exactly match f->type().
-   * For example, a handler that takes an int32_t parameter may only be used for
-   * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM.
-   *
-   * Returns false if the handler failed to register; in this case the cleanup
-   * handler (if any) will be called immediately.
-   */
-  bool SetInt32Handler(FieldDefPtr f, const Int32Handler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setint32(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetInt64Handler (FieldDefPtr f,  const Int64Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setint64(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetUInt32Handler(FieldDefPtr f, const UInt32Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setuint32(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetUInt64Handler(FieldDefPtr f, const UInt64Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setuint64(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetFloatHandler (FieldDefPtr f,  const FloatHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setfloat(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetDoubleHandler(FieldDefPtr f, const DoubleHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setdouble(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetBoolHandler(FieldDefPtr f, const BoolHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setbool(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Like the previous, but templated on the type on the value (ie. int32).
-   * This is mostly useful to call from other templates.  To call this you must
-   * specify the template parameter explicitly, ie:
-   *   h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); */
-  template <class T>
-  bool SetValueHandler(
-      FieldDefPtr f,
-      const typename ValueHandler<typename CanonicalType<T>::Type>::H &handler);
-
-  /* Sets handlers for a string field, which are defined as follows:
-   *
-   *   MySubClosure* startstr(MyClosure* c, const MyHandlerData* d,
-   *                          size_t size_hint) {
-   *     // Called when a string value begins.  The return value indicates the
-   *     // closure for the string.  "size_hint" indicates the size of the
-   *     // string if it is known, however if the string is length-delimited
-   *     // and the end-of-string is not available size_hint will be zero.
-   *     // This case is indistinguishable from the case where the size is
-   *     // known to be zero.
-   *     //
-   *     // TODO(haberman): is it important to distinguish these cases?
-   *     // If we had ssize_t as a type we could make -1 "unknown", but
-   *     // ssize_t is POSIX (not ANSI) and therefore less portable.
-   *     // In practice I suspect it won't be important to distinguish.
-   *     return closure;
-   *   }
-   *
-   *   size_t str(MyClosure* closure, const MyHandlerData* d,
-   *              const char *str, size_t len) {
-   *     // Called for each buffer of string data; the multiple physical buffers
-   *     // are all part of the same logical string.  The return value indicates
-   *     // how many bytes were consumed.  If this number is less than "len",
-   *     // this will also indicate that processing should be halted for now,
-   *     // like returning false or UPB_BREAK from any other callback.  If
-   *     // number is greater than "len", the excess bytes will be skipped over
-   *     // and not passed to the callback.
-   *     return len;
-   *   }
-   *
-   *   bool endstr(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a string value ends.  Return value indicates whether
-   *     // processing should continue.
-   *     return true;
-   *   }
-   */
-  bool SetStartStringHandler(FieldDefPtr f, const StartStringHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartstr(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetStringHandler(FieldDefPtr f, const StringHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstring(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetEndStringHandler(FieldDefPtr f, const EndFieldHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendstr(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the startseq handler, which is defined as follows:
-   *
-   *   MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a sequence (repeated field) begins.  The returned
-   *     // pointer indicates the closure for the sequence (or UPB_BREAK
-   *     // to interrupt processing).
-   *     return closure;
-   *   }
-   *
-   *   h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...)));
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * repeated field.
-   */
-  bool SetStartSequenceHandler(FieldDefPtr f, const StartFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartseq(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the startsubmsg handler for the given field, which is defined as
-   * follows:
-   *
-   *   MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a submessage begins.  The returned pointer indicates the
-   *     // closure for the sequence (or UPB_BREAK to interrupt processing).
-   *     return closure;
-   *   }
-   *
-   *   h->SetStartSubMessageHandler(f, UpbBind(startsubmsg,
-   *                                           new MyHandlerData(...)));
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * submessage/group field.
-   */
-  bool SetStartSubMessageHandler(FieldDefPtr f, const StartFieldHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the endsubmsg handler for the given field, which is defined as
-   * follows:
-   *
-   *   bool endsubmsg(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a submessage ends.  Returns true to continue processing.
-   *     return true;
-   *   }
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * submessage/group field.
-   */
-  bool SetEndSubMessageHandler(FieldDefPtr f, const EndFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Starts the endsubseq handler for the given field, which is defined as
-   * follows:
-   *
-   *   bool endseq(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a sequence ends.  Returns true continue processing.
-   *     return true;
-   *   }
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * repeated field.
-   */
-  bool SetEndSequenceHandler(FieldDefPtr f, const EndFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendseq(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
- private:
-  upb_handlers* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_handlercache ***********************************************************/
-
-/* A upb_handlercache lazily builds and caches upb_handlers.  You pass it a
- * function (with optional closure) that can build handlers for a given
- * message on-demand, and the cache maintains a map of msgdef->handlers. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct upb_handlercache;
-typedef struct upb_handlercache upb_handlercache;
-
-typedef void upb_handlers_callback(const void *closure, upb_handlers *h);
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
-                                       const void *closure);
-void upb_handlercache_free(upb_handlercache *cache);
-const upb_handlers *upb_handlercache_get(upb_handlercache *cache,
-                                         const upb_msgdef *md);
-bool upb_handlercache_addcleanup(upb_handlercache *h, void *p,
-                                 upb_handlerfree *hfree);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::HandlerCache {
- public:
-  HandlerCache(upb_handlers_callback *callback, const void *closure)
-      : ptr_(upb_handlercache_new(callback, closure), upb_handlercache_free) {}
-  HandlerCache(HandlerCache&&) = default;
-  HandlerCache& operator=(HandlerCache&&) = default;
-  HandlerCache(upb_handlercache* c) : ptr_(c, upb_handlercache_free) {}
-
-  upb_handlercache* ptr() { return ptr_.get(); }
-
-  const upb_handlers *Get(MessageDefPtr md) {
-    return upb_handlercache_get(ptr_.get(), md.ptr());
-  }
-
- private:
-  std::unique_ptr<upb_handlercache, decltype(&upb_handlercache_free)> ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_byteshandler ***********************************************************/
-
-typedef struct {
-  upb_func *func;
-
-  /* It is wasteful to include the entire attributes here:
-   *
-   * * Some of the information is redundant (like storing the closure type
-   *   separately for each handler that must match).
-   * * Some of the info is only needed prior to freeze() (like closure types).
-   * * alignment padding wastes a lot of space for alwaysok_.
-   *
-   * If/when the size and locality of handlers is an issue, we can optimize this
-   * not to store the entire attr like this.  We do not expose the table's
-   * layout to allow this optimization in the future. */
-  upb_handlerattr attr;
-} upb_handlers_tabent;
-
-#define UPB_TABENT_INIT {NULL, UPB_HANDLERATTR_INIT}
-
-typedef struct {
-  upb_handlers_tabent table[3];
-} upb_byteshandler;
-
-#define UPB_BYTESHANDLER_INIT                             \
-  {                                                       \
-    { UPB_TABENT_INIT, UPB_TABENT_INIT, UPB_TABENT_INIT } \
-  }
-
-UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) {
-  upb_byteshandler init = UPB_BYTESHANDLER_INIT;
-  *handler = init;
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Caller must ensure that "d" outlives the handlers. */
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
-                                  upb_startstr_handlerfunc *func, void *d);
-bool upb_byteshandler_setstring(upb_byteshandler *h,
-                                upb_string_handlerfunc *func, void *d);
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
-                                upb_endfield_handlerfunc *func, void *d);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-typedef upb_byteshandler BytesHandler;
-}
-#endif
-
-/** Message handlers ******************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* These are the handlers used internally by upb_msgfactory_getmergehandlers().
- * They write scalar data to a known offset from the message pointer.
- *
- * These would be trivial for anyone to implement themselves, but it's better
- * to use these because some JITs will recognize and specialize these instead
- * of actually calling the function. */
-
-/* Sets a handler for the given primitive field that will write the data at the
- * given offset.  If hasbit > 0, also sets a hasbit at the given bit offset
- * (addressing each byte low to high). */
-bool upb_msg_setscalarhandler(upb_handlers *h,
-                              const upb_fielddef *f,
-                              size_t offset,
-                              int32_t hasbit);
-
-/* If the given handler is a msghandlers_primitive field, returns true and sets
- * *type, *offset and *hasbit.  Otherwise returns false. */
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
-                                  upb_selector_t s,
-                                  upb_fieldtype_t *type,
-                                  size_t *offset,
-                                  int32_t *hasbit);
-
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-/*
-** Inline definitions for handlers.h, which are particularly long and a bit
-** tricky.
-*/
-
-#ifndef UPB_HANDLERS_INL_H_
-#define UPB_HANDLERS_INL_H_
-
-#include <limits.h>
-#include <stddef.h>
-
-
-#ifdef __cplusplus
-
-/* Type detection and typedefs for integer types.
- * For platforms where there are multiple 32-bit or 64-bit types, we need to be
- * able to enumerate them so we can properly create overloads for all variants.
- *
- * If any platform existed where there were three integer types with the same
- * size, this would have to become more complicated.  For example, short, int,
- * and long could all be 32-bits.  Even more diabolically, short, int, long,
- * and long long could all be 64 bits and still be standard-compliant.
- * However, few platforms are this strange, and it's unlikely that upb will be
- * used on the strangest ones. */
-
-/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are
- * only defined when __STDC_LIMIT_MACROS are defined before the *first* include
- * of stdint.h.  We can't guarantee that someone else didn't include these first
- * without defining __STDC_LIMIT_MACROS. */
-#define UPB_INT32_MAX 0x7fffffffLL
-#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
-#define UPB_INT64_MAX 0x7fffffffffffffffLL
-#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
-
-#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
-#define UPB_INT_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
-#define UPB_LONG_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
-#define UPB_LONG_IS_64BITS 1
-#endif
-
-#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
-#define UPB_LLONG_IS_64BITS 1
-#endif
-
-/* We use macros instead of typedefs so we can undefine them later and avoid
- * leaking them outside this header file. */
-#if UPB_INT_IS_32BITS
-#define UPB_INT32_T int
-#define UPB_UINT32_T unsigned int
-
-#if UPB_LONG_IS_32BITS
-#define UPB_TWO_32BIT_TYPES 1
-#define UPB_INT32ALT_T long
-#define UPB_UINT32ALT_T unsigned long
-#endif  /* UPB_LONG_IS_32BITS */
-
-#elif UPB_LONG_IS_32BITS  /* && !UPB_INT_IS_32BITS */
-#define UPB_INT32_T long
-#define UPB_UINT32_T unsigned long
-#endif  /* UPB_INT_IS_32BITS */
-
-
-#if UPB_LONG_IS_64BITS
-#define UPB_INT64_T long
-#define UPB_UINT64_T unsigned long
-
-#if UPB_LLONG_IS_64BITS
-#define UPB_TWO_64BIT_TYPES 1
-#define UPB_INT64ALT_T long long
-#define UPB_UINT64ALT_T unsigned long long
-#endif  /* UPB_LLONG_IS_64BITS */
-
-#elif UPB_LLONG_IS_64BITS  /* && !UPB_LONG_IS_64BITS */
-#define UPB_INT64_T long long
-#define UPB_UINT64_T unsigned long long
-#endif  /* UPB_LONG_IS_64BITS */
-
-#undef UPB_INT32_MAX
-#undef UPB_INT32_MIN
-#undef UPB_INT64_MAX
-#undef UPB_INT64_MIN
-#undef UPB_INT_IS_32BITS
-#undef UPB_LONG_IS_32BITS
-#undef UPB_LONG_IS_64BITS
-#undef UPB_LLONG_IS_64BITS
-
-
-namespace upb {
-
-typedef void CleanupFunc(void *ptr);
-
-/* Template to remove "const" from "const T*" and just return "T*".
- *
- * We define a nonsense default because otherwise it will fail to instantiate as
- * a function parameter type even in cases where we don't expect any caller to
- * actually match the overload. */
-class CouldntRemoveConst {};
-template <class T> struct remove_constptr { typedef CouldntRemoveConst type; };
-template <class T> struct remove_constptr<const T *> { typedef T *type; };
-
-/* Template that we use below to remove a template specialization from
- * consideration if it matches a specific type. */
-template <class T, class U> struct disable_if_same { typedef void Type; };
-template <class T> struct disable_if_same<T, T> {};
-
-template <class T> void DeletePointer(void *p) { delete static_cast<T>(p); }
-
-template <class T1, class T2>
-struct FirstUnlessVoidOrBool {
-  typedef T1 value;
-};
-
-template <class T2>
-struct FirstUnlessVoidOrBool<void, T2> {
-  typedef T2 value;
-};
-
-template <class T2>
-struct FirstUnlessVoidOrBool<bool, T2> {
-  typedef T2 value;
-};
-
-template<class T, class U>
-struct is_same {
-  static bool value;
-};
-
-template<class T>
-struct is_same<T, T> {
-  static bool value;
-};
-
-template<class T, class U>
-bool is_same<T, U>::value = false;
-
-template<class T>
-bool is_same<T, T>::value = true;
-
-/* FuncInfo *******************************************************************/
-
-/* Info about the user's original, pre-wrapped function. */
-template <class C, class R = void>
-struct FuncInfo {
-  /* The type of the closure that the function takes (its first param). */
-  typedef C Closure;
-
-  /* The return type. */
-  typedef R Return;
-};
-
-/* Func ***********************************************************************/
-
-/* Func1, Func2, Func3: Template classes representing a function and its
- * signature.
- *
- * Since the function is a template parameter, calling the function can be
- * inlined at compile-time and does not require a function pointer at runtime.
- * These functions are not bound to a handler data so have no data or cleanup
- * handler. */
-struct UnboundFunc {
-  CleanupFunc *GetCleanup() { return nullptr; }
-  void *GetData() { return nullptr; }
-};
-
-template <class R, class P1, R F(P1), class I>
-struct Func1 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1) { return F(p1); }
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I>
-struct Func2 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2) { return F(p1, p2); }
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
-struct Func3 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I>
-struct Func4 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I>
-struct Func5 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
-    return F(p1, p2, p3, p4, p5);
-  }
-};
-
-/* BoundFunc ******************************************************************/
-
-/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
- * shall be bound to the function's second parameter.
- * 
- * Note that the second parameter is a const pointer, but our stored bound value
- * is non-const so we can free it when the handlers are destroyed. */
-template <class T>
-struct BoundFunc {
-  typedef typename remove_constptr<T>::type MutableP2;
-  explicit BoundFunc(MutableP2 data_) : data(data_) {}
-  CleanupFunc *GetCleanup() { return &DeletePointer<MutableP2>; }
-  MutableP2 GetData() { return data; }
-  MutableP2 data;
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I>
-struct BoundFunc2 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
-struct BoundFunc3 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I>
-struct BoundFunc4 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I>
-struct BoundFunc5 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-/* FuncSig ********************************************************************/
-
-/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
- * *signature*, but without a specific function attached.
- *
- * These classes contain member functions that can be invoked with a
- * specific function to return a Func/BoundFunc class. */
-template <class R, class P1>
-struct FuncSig1 {
-  template <R F(P1)>
-  Func1<R, P1, F, FuncInfo<P1, R> > GetFunc() {
-    return Func1<R, P1, F, FuncInfo<P1, R> >();
-  }
-};
-
-template <class R, class P1, class P2>
-struct FuncSig2 {
-  template <R F(P1, P2)>
-  Func2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc() {
-    return Func2<R, P1, P2, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2)>
-  BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3>
-struct FuncSig3 {
-  template <R F(P1, P2, P3)>
-  Func3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc() {
-    return Func3<R, P1, P2, P3, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3)>
-  BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3, class P4>
-struct FuncSig4 {
-  template <R F(P1, P2, P3, P4)>
-  Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc() {
-    return Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3, P4)>
-  BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-struct FuncSig5 {
-  template <R F(P1, P2, P3, P4, P5)>
-  Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc() {
-    return Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3, P4, P5)>
-  BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-/* Overloaded template function that can construct the appropriate FuncSig*
- * class given a function pointer by deducing the template parameters. */
-template <class R, class P1>
-inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig1<R, P1>();
-}
-
-template <class R, class P1, class P2>
-inline FuncSig2<R, P1, P2> MatchFunc(R (*f)(P1, P2)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig2<R, P1, P2>();
-}
-
-template <class R, class P1, class P2, class P3>
-inline FuncSig3<R, P1, P2, P3> MatchFunc(R (*f)(P1, P2, P3)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig3<R, P1, P2, P3>();
-}
-
-template <class R, class P1, class P2, class P3, class P4>
-inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig4<R, P1, P2, P3, P4>();
-}
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig5<R, P1, P2, P3, P4, P5>();
-}
-
-/* MethodSig ******************************************************************/
-
-/* CallMethod*: a function template that calls a given method. */
-template <class R, class C, R (C::*F)()>
-R CallMethod0(C *obj) {
-  return ((*obj).*F)();
-}
-
-template <class R, class C, class P1, R (C::*F)(P1)>
-R CallMethod1(C *obj, P1 arg1) {
-  return ((*obj).*F)(arg1);
-}
-
-template <class R, class C, class P1, class P2, R (C::*F)(P1, P2)>
-R CallMethod2(C *obj, P1 arg1, P2 arg2) {
-  return ((*obj).*F)(arg1, arg2);
-}
-
-template <class R, class C, class P1, class P2, class P3, R (C::*F)(P1, P2, P3)>
-R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
-  return ((*obj).*F)(arg1, arg2, arg3);
-}
-
-template <class R, class C, class P1, class P2, class P3, class P4,
-          R (C::*F)(P1, P2, P3, P4)>
-R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) {
-  return ((*obj).*F)(arg1, arg2, arg3, arg4);
-}
-
-/* MethodSig: like FuncSig, but for member functions.
- *
- * GetFunc() returns a normal FuncN object, so after calling GetFunc() no
- * more logic is required to special-case methods. */
-template <class R, class C>
-struct MethodSig0 {
-  template <R (C::*F)()>
-  Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> > GetFunc() {
-    return Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> >();
-  }
-};
-
-template <class R, class C, class P1>
-struct MethodSig1 {
-  template <R (C::*F)(P1)>
-  Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc() {
-    return Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1)>
-  BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc(
-      typename remove_constptr<P1>::type param1) {
-    return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >(
-        param1);
-  }
-};
-
-template <class R, class C, class P1, class P2>
-struct MethodSig2 {
-  template <R (C::*F)(P1, P2)>
-  Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
-  GetFunc() {
-    return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2)>
-  BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
-                      FuncInfo<C *, R> >(param1);
-  }
-};
-
-template <class R, class C, class P1, class P2, class P3>
-struct MethodSig3 {
-  template <R (C::*F)(P1, P2, P3)>
-  Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>, FuncInfo<C *, R> >
-  GetFunc() {
-    return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2, P3)>
-  BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-             FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-                      FuncInfo<C *, R> >(param1);
-  }
-};
-
-template <class R, class C, class P1, class P2, class P3, class P4>
-struct MethodSig4 {
-  template <R (C::*F)(P1, P2, P3, P4)>
-  Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-        FuncInfo<C *, R> >
-  GetFunc() {
-    return Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2, P3, P4)>
-  BoundFunc5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-             FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc5<R, C *, P1, P2, P3, P4,
-                      CallMethod4<R, C, P1, P2, P3, P4, F>, FuncInfo<C *, R> >(
-        param1);
-  }
-};
-
-template <class R, class C>
-inline MethodSig0<R, C> MatchFunc(R (C::*f)()) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig0<R, C>();
-}
-
-template <class R, class C, class P1>
-inline MethodSig1<R, C, P1> MatchFunc(R (C::*f)(P1)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig1<R, C, P1>();
-}
-
-template <class R, class C, class P1, class P2>
-inline MethodSig2<R, C, P1, P2> MatchFunc(R (C::*f)(P1, P2)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig2<R, C, P1, P2>();
-}
-
-template <class R, class C, class P1, class P2, class P3>
-inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig3<R, C, P1, P2, P3>();
-}
-
-template <class R, class C, class P1, class P2, class P3, class P4>
-inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig4<R, C, P1, P2, P3, P4>();
-}
-
-/* MaybeWrapReturn ************************************************************/
-
-/* Template class that attempts to wrap the return value of the function so it
- * matches the expected type.  There are two main adjustments it may make:
- *
- *   1. If the function returns void, make it return the expected type and with
- *      a value that always indicates success.
- *   2. If the function returns bool, make it return the expected type with a
- *      value that indicates success or failure.
- *
- * The "expected type" for return is:
- *   1. void* for start handlers.  If the closure parameter has a different type
- *      we will cast it to void* for the return in the success case.
- *   2. size_t for string buffer handlers.
- *   3. bool for everything else. */
-
-/* Template parameters are FuncN type and desired return type. */
-template <class F, class R, class Enable = void>
-struct MaybeWrapReturn;
-
-/* If the return type matches, return the given function unwrapped. */
-template <class F>
-struct MaybeWrapReturn<F, typename F::Return> {
-  typedef F Func;
-};
-
-/* Function wrapper that munges the return value from void to (bool)true. */
-template <class P1, class P2, void F(P1, P2)>
-bool ReturnTrue2(P1 p1, P2 p2) {
-  F(p1, p2);
-  return true;
-}
-
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-bool ReturnTrue3(P1 p1, P2 p2, P3 p3) {
-  F(p1, p2, p3);
-  return true;
-}
-
-/* Function wrapper that munges the return value from void to (void*)arg1  */
-template <class P1, class P2, void F(P1, P2)>
-void *ReturnClosure2(P1 p1, P2 p2) {
-  F(p1, p2);
-  return p1;
-}
-
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-void *ReturnClosure3(P1 p1, P2 p2, P3 p3) {
-  F(p1, p2, p3);
-  return p1;
-}
-
-/* Function wrapper that munges the return value from R to void*. */
-template <class R, class P1, class P2, R F(P1, P2)>
-void *CastReturnToVoidPtr2(P1 p1, P2 p2) {
-  return F(p1, p2);
-}
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) {
-  return F(p1, p2, p3);
-}
-
-/* Function wrapper that munges the return value from bool to void*. */
-template <class P1, class P2, bool F(P1, P2)>
-void *ReturnClosureOrBreak2(P1 p1, P2 p2) {
-  return F(p1, p2) ? p1 : UPB_BREAK;
-}
-
-template <class P1, class P2, class P3, bool F(P1, P2, P3)>
-void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) {
-  return F(p1, p2, p3) ? p1 : UPB_BREAK;
-}
-
-/* For the string callback, which takes five params, returns the size param. */
-template <class P1, class P2,
-          void F(P1, P2, const char *, size_t, const upb_bufhandle *)>
-size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4,
-                       const upb_bufhandle *p5) {
-  F(p1, p2, p3, p4, p5);
-  return p4;
-}
-
-/* For the string callback, which takes five params, returns the size param or
- * zero. */
-template <class P1, class P2,
-          bool F(P1, P2, const char *, size_t, const upb_bufhandle *)>
-size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4,
-                  const upb_bufhandle *p5) {
-  return F(p1, p2, p3, p4, p5) ? p4 : 0;
-}
-
-/* If we have a function returning void but want a function returning bool, wrap
- * it in a function that returns true. */
-template <class P1, class P2, void F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> {
-  typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> {
-  typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func;
-};
-
-/* If our function returns void but we want one returning void*, wrap it in a
- * function that returns the first argument. */
-template <class P1, class P2, void F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> {
-  typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> {
-  typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func;
-};
-
-/* If our function returns R* but we want one returning void*, wrap it in a
- * function that casts to void*. */
-template <class R, class P1, class P2, R *F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *,
-                       typename disable_if_same<R *, void *>::Type> {
-  typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F>, I> Func;
-};
-
-template <class R, class P1, class P2, class P3, R *F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *,
-                       typename disable_if_same<R *, void *>::Type> {
-  typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F>, I>
-      Func;
-};
-
-/* If our function returns bool but we want one returning void*, wrap it in a
- * function that returns either the first param or UPB_BREAK. */
-template <class P1, class P2, bool F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> {
-  typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, bool F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> {
-  typedef Func3<void *, P1, P2, P3, ReturnClosureOrBreak3<P1, P2, P3, F>, I>
-      Func;
-};
-
-/* If our function returns void but we want one returning size_t, wrap it in a
- * function that returns the size argument. */
-template <class P1, class P2,
-          void F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
-struct MaybeWrapReturn<
-    Func5<void, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
-          size_t> {
-  typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
-                ReturnStringLen<P1, P2, F>, I> Func;
-};
-
-/* If our function returns bool but we want one returning size_t, wrap it in a
- * function that returns either 0 or the buf size. */
-template <class P1, class P2,
-          bool F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
-struct MaybeWrapReturn<
-    Func5<bool, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
-    size_t> {
-  typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
-                ReturnNOr0<P1, P2, F>, I> Func;
-};
-
-/* ConvertParams **************************************************************/
-
-/* Template class that converts the function parameters if necessary, and
- * ignores the HandlerData parameter if appropriate.
- *
- * Template parameter is the are FuncN function type. */
-template <class F, class T>
-struct ConvertParams;
-
-/* Function that discards the handler data parameter. */
-template <class R, class P1, R F(P1)>
-R IgnoreHandlerData2(void *p1, const void *hd) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1));
-}
-
-template <class R, class P1, class P2Wrapper, class P2Wrapped,
-          R F(P1, P2Wrapped)>
-R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2);
-}
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2, p3);
-}
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
-R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2, p3, p4);
-}
-
-template <class R, class P1, R F(P1, const char*, size_t)>
-R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2,
-                                size_t p3, const upb_bufhandle *handle) {
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-  return F(static_cast<P1>(p1), p2, p3);
-}
-
-/* Function that casts the handler data parameter. */
-template <class R, class P1, class P2, R F(P1, P2)>
-R CastHandlerData2(void *c, const void *hd) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd));
-}
-
-template <class R, class P1, class P2, class P3Wrapper, class P3Wrapped,
-          R F(P1, P2, P3Wrapped)>
-R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3);
-}
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5)>
-R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4, p5);
-}
-
-template <class R, class P1, class P2, R F(P1, P2, const char *, size_t)>
-R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3,
-                              size_t p4, const upb_bufhandle *handle) {
-  UPB_UNUSED(handle);
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4);
-}
-
-/* For unbound functions, ignore the handler data. */
-template <class R, class P1, R F(P1), class I, class T>
-struct ConvertParams<Func1<R, P1, F, I>, T> {
-  typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func;
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I,
-          class R2, class P1_2, class P2_2, class P3_2>
-struct ConvertParams<Func2<R, P1, P2, F, I>,
-                     R2 (*)(P1_2, P2_2, P3_2)> {
-  typedef Func3<R, void *, const void *, P3_2,
-                IgnoreHandlerData3<R, P1, P3_2, P2, F>, I> Func;
-};
-
-/* For StringBuffer only; this ignores both the handler data and the
- * upb_bufhandle. */
-template <class R, class P1, R F(P1, const char *, size_t), class I, class T>
-struct ConvertParams<Func3<R, P1, const char *, size_t, F, I>, T> {
-  typedef Func5<R, void *, const void *, const char *, size_t,
-                const upb_bufhandle *, IgnoreHandlerDataIgnoreHandle<R, P1, F>,
-                I> Func;
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I, class T>
-struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I>, T> {
-  typedef Func5<R, void *, const void *, P2, P3, P4,
-                IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func;
-};
-
-/* For bound functions, cast the handler data. */
-template <class R, class P1, class P2, R F(P1, P2), class I, class T>
-struct ConvertParams<BoundFunc2<R, P1, P2, F, I>, T> {
-  typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I>
-      Func;
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I,
-          class R2, class P1_2, class P2_2, class P3_2>
-struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I>,
-                     R2 (*)(P1_2, P2_2, P3_2)> {
-  typedef Func3<R, void *, const void *, P3_2,
-                CastHandlerData3<R, P1, P2, P3_2, P3, F>, I> Func;
-};
-
-/* For StringBuffer only; this ignores the upb_bufhandle. */
-template <class R, class P1, class P2, R F(P1, P2, const char *, size_t),
-          class I, class T>
-struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I>, T> {
-  typedef Func5<R, void *, const void *, const char *, size_t,
-                const upb_bufhandle *,
-                CastHandlerDataIgnoreHandle<R, P1, P2, F>, I>
-      Func;
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I, class T>
-struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> {
-  typedef Func5<R, void *, const void *, P3, P4, P5,
-                CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func;
-};
-
-/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
- * variant C type. */
-#define TYPE_METHODS(utype, ltype, ctype, vtype)                      \
-  template <>                                                         \
-  struct CanonicalType<vtype> {                                       \
-    typedef ctype Type;                                               \
-  };                                                                  \
-  template <>                                                         \
-  inline bool HandlersPtr::SetValueHandler<vtype>(                    \
-      FieldDefPtr f, const HandlersPtr::utype##Handler &handler) {    \
-    handler.AddCleanup(ptr());                                        \
-    return upb_handlers_set##ltype(ptr(), f.ptr(), handler.handler(), \
-                                   &handler.attr());                  \
-  }
-
-TYPE_METHODS(Double, double, double,   double)
-TYPE_METHODS(Float,  float,  float,    float)
-TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T)
-TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T)
-TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64_T)
-TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32_T)
-TYPE_METHODS(Bool,   bool,   bool,     bool)
-
-#ifdef UPB_TWO_32BIT_TYPES
-TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32ALT_T)
-TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T)
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64ALT_T)
-TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T)
-#endif
-#undef TYPE_METHODS
-
-template <> struct CanonicalType<Status*> {
-  typedef Status* Type;
-};
-
-template <class F> struct ReturnOf;
-
-template <class R, class P1, class P2>
-struct ReturnOf<R (*)(P1, P2)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3>
-struct ReturnOf<R (*)(P1, P2, P3)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3, class P4>
-struct ReturnOf<R (*)(P1, P2, P3, P4)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-struct ReturnOf<R (*)(P1, P2, P3, P4, P5)> {
-  typedef R Return;
-};
-
-
-template <class T>
-template <class F>
-inline Handler<T>::Handler(F func)
-    : registered_(false),
-      cleanup_data_(func.GetData()),
-      cleanup_func_(func.GetCleanup()) {
-  attr_.handler_data = func.GetData();
-  typedef typename ReturnOf<T>::Return Return;
-  typedef typename ConvertParams<F, T>::Func ConvertedParamsFunc;
-  typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func
-      ReturnWrappedFunc;
-  handler_ = ReturnWrappedFunc().Call;
-
-  /* Set attributes based on what templates can statically tell us about the
-   * user's function. */
-
-  /* If the original function returns void, then we know that we wrapped it to
-   * always return ok. */
-  bool always_ok = is_same<typename F::FuncInfo::Return, void>::value;
-  attr_.alwaysok = always_ok;
-
-  /* Closure parameter and return type. */
-  attr_.closure_type = UniquePtrForType<typename F::FuncInfo::Closure>();
-
-  /* We use the closure type (from the first parameter) if the return type is
-   * void or bool, since these are the two cases we wrap to return the closure's
-   * type anyway.
-   *
-   * This is all nonsense for non START* handlers, but it doesn't matter because
-   * in that case the value will be ignored. */
-  typedef typename FirstUnlessVoidOrBool<typename F::FuncInfo::Return,
-                                         typename F::FuncInfo::Closure>::value
-      EffectiveReturn;
-  attr_.return_closure_type = UniquePtrForType<EffectiveReturn>();
-}
-
-template <class T>
-inline void Handler<T>::AddCleanup(upb_handlers* h) const {
-  UPB_ASSERT(!registered_);
-  registered_ = true;
-  if (cleanup_func_) {
-    bool ok = upb_handlers_addcleanup(h, cleanup_data_, cleanup_func_);
-    UPB_ASSERT(ok);
-  }
-}
-
-}  /* namespace upb */
-
-#endif  /* __cplusplus */
-
-
-#undef UPB_TWO_32BIT_TYPES
-#undef UPB_TWO_64BIT_TYPES
-#undef UPB_INT32_T
-#undef UPB_UINT32_T
-#undef UPB_INT32ALT_T
-#undef UPB_UINT32ALT_T
-#undef UPB_INT64_T
-#undef UPB_UINT64_T
-#undef UPB_INT64ALT_T
-#undef UPB_UINT64ALT_T
-
-
-#endif  /* UPB_HANDLERS_INL_H_ */
-
-#endif  /* UPB_HANDLERS_H */
-/*
-** upb::Sink (upb_sink)
-** upb::BytesSink (upb_bytessink)
-**
-** A upb_sink is an object that binds a upb_handlers object to some runtime
-** state.  It is the object that can actually receive data via the upb_handlers
-** interface.
-**
-** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or
-** thread-safe.  You can create as many of them as you want, but each one may
-** only be used in a single thread at a time.
-**
-** If we compare with class-based OOP, a you can think of a upb_def as an
-** abstract base class, a upb_handlers as a concrete derived class, and a
-** upb_sink as an object (class instance).
-*/
-
-#ifndef UPB_SINK_H
-#define UPB_SINK_H
-
-
-
-#ifdef __cplusplus
-namespace upb {
-class BytesSink;
-class Sink;
-}
-#endif
-
-/* upb_sink *******************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
-  const upb_handlers *handlers;
-  void *closure;
-} upb_sink;
-
-#define PUTVAL(type, ctype)                                           \
-  UPB_INLINE bool upb_sink_put##type(upb_sink s, upb_selector_t sel,  \
-                                     ctype val) {                     \
-    typedef upb_##type##_handlerfunc functype;                        \
-    functype *func;                                                   \
-    const void *hd;                                                   \
-    if (!s.handlers) return true;                                     \
-    func = (functype *)upb_handlers_gethandler(s.handlers, sel, &hd); \
-    if (!func) return true;                                           \
-    return func(s.closure, hd, val);                                  \
-  }
-
-PUTVAL(int32,  int32_t)
-PUTVAL(int64,  int64_t)
-PUTVAL(uint32, uint32_t)
-PUTVAL(uint64, uint64_t)
-PUTVAL(float,  float)
-PUTVAL(double, double)
-PUTVAL(bool,   bool)
-#undef PUTVAL
-
-UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
-  s->handlers = h;
-  s->closure = c;
-}
-
-UPB_INLINE size_t upb_sink_putstring(upb_sink s, upb_selector_t sel,
-                                     const char *buf, size_t n,
-                                     const upb_bufhandle *handle) {
-  typedef upb_string_handlerfunc func;
-  func *handler;
-  const void *hd;
-  if (!s.handlers) return n;
-  handler = (func *)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!handler) return n;
-  return handler(s.closure, hd, buf, n, handle);
-}
-
-UPB_INLINE bool upb_sink_putunknown(upb_sink s, const char *buf, size_t n) {
-  typedef upb_unknown_handlerfunc func;
-  func *handler;
-  const void *hd;
-  if (!s.handlers) return true;
-  handler =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_UNKNOWN_SELECTOR, &hd);
-
-  if (!handler) return n;
-  return handler(s.closure, hd, buf, n);
-}
-
-UPB_INLINE bool upb_sink_startmsg(upb_sink s) {
-  typedef upb_startmsg_handlerfunc func;
-  func *startmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  startmsg =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_STARTMSG_SELECTOR, &hd);
-
-  if (!startmsg) return true;
-  return startmsg(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_endmsg(upb_sink s, upb_status *status) {
-  typedef upb_endmsg_handlerfunc func;
-  func *endmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  endmsg =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_ENDMSG_SELECTOR, &hd);
-
-  if (!endmsg) return true;
-  return endmsg(s.closure, hd, status);
-}
-
-UPB_INLINE bool upb_sink_startseq(upb_sink s, upb_selector_t sel,
-                                  upb_sink *sub) {
-  typedef upb_startfield_handlerfunc func;
-  func *startseq;
-  const void *hd;
-  sub->closure = s.closure;
-  sub->handlers = s.handlers;
-  if (!s.handlers) return true;
-  startseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startseq) return true;
-  sub->closure = startseq(s.closure, hd);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endseq(upb_sink s, upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endseq;
-  const void *hd;
-  if (!s.handlers) return true;
-  endseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endseq) return true;
-  return endseq(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_startstr(upb_sink s, upb_selector_t sel,
-                                  size_t size_hint, upb_sink *sub) {
-  typedef upb_startstr_handlerfunc func;
-  func *startstr;
-  const void *hd;
-  sub->closure = s.closure;
-  sub->handlers = s.handlers;
-  if (!s.handlers) return true;
-  startstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startstr) return true;
-  sub->closure = startstr(s.closure, hd, size_hint);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endstr(upb_sink s, upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endstr;
-  const void *hd;
-  if (!s.handlers) return true;
-  endstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endstr) return true;
-  return endstr(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_startsubmsg(upb_sink s, upb_selector_t sel,
-                                     upb_sink *sub) {
-  typedef upb_startfield_handlerfunc func;
-  func *startsubmsg;
-  const void *hd;
-  sub->closure = s.closure;
-  if (!s.handlers) {
-    sub->handlers = NULL;
-    return true;
-  }
-  sub->handlers = upb_handlers_getsubhandlers_sel(s.handlers, sel);
-  startsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startsubmsg) return true;
-  sub->closure = startsubmsg(s.closure, hd);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_sink sub,
-                                   upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endsubmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  endsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endsubmsg) return true;
-  return endsubmsg(sub.closure, hd);
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A upb::Sink is an object that binds a upb::Handlers object to some runtime
- * state.  It represents an endpoint to which data can be sent.
- *
- * TODO(haberman): right now all of these functions take selectors.  Should they
- * take selectorbase instead?
- *
- * ie. instead of calling:
- *   sink->StartString(FOO_FIELD_START_STRING, ...)
- * a selector base would let you say:
- *   sink->StartString(FOO_FIELD, ...)
- *
- * This would make call sites a little nicer and require emitting fewer selector
- * definitions in .h files.
- *
- * But the current scheme has the benefit that you can retrieve a function
- * pointer for any handler with handlers->GetHandler(selector), without having
- * to have a separate GetHandler() function for each handler type.  The JIT
- * compiler uses this.  To accommodate we'd have to expose a separate
- * GetHandler() for every handler type.
- *
- * Also to ponder: selectors right now are independent of a specific Handlers
- * instance.  In other words, they allocate a number to every possible handler
- * that *could* be registered, without knowing anything about what handlers
- * *are* registered.  That means that using selectors as table offsets prohibits
- * us from compacting the handler table at Freeze() time.  If the table is very
- * sparse, this could be wasteful.
- *
- * Having another selector-like thing that is specific to a Handlers instance
- * would allow this compacting, but then it would be impossible to write code
- * ahead-of-time that can be bound to any Handlers instance at runtime.  For
- * example, a .proto file parser written as straight C will not know what
- * Handlers it will be bound to, so when it calls sink->StartString() what
- * selector will it pass?  It needs a selector like we have today, that is
- * independent of any particular upb::Handlers.
- *
- * Is there a way then to allow Handlers table compaction? */
-class upb::Sink {
- public:
-  /* Constructor with no initialization; must be Reset() before use. */
-  Sink() {}
-
-  Sink(const Sink&) = default;
-  Sink& operator=(const Sink&) = default;
-
-  Sink(const upb_sink& sink) : sink_(sink) {}
-  Sink &operator=(const upb_sink &sink) {
-    sink_ = sink;
-    return *this;
-  }
-
-  upb_sink sink() { return sink_; }
-
-  /* Constructs a new sink for the given frozen handlers and closure.
-   *
-   * TODO: once the Handlers know the expected closure type, verify that T
-   * matches it. */
-  template <class T> Sink(const upb_handlers* handlers, T* closure) {
-    Reset(handlers, closure);
-  }
-
-  upb_sink* ptr() { return &sink_; }
-
-  /* Resets the value of the sink. */
-  template <class T> void Reset(const upb_handlers* handlers, T* closure) {
-    upb_sink_reset(&sink_, handlers, closure);
-  }
-
-  /* Returns the top-level object that is bound to this sink.
-   *
-   * TODO: once the Handlers know the expected closure type, verify that T
-   * matches it. */
-  template <class T> T* GetObject() const {
-    return static_cast<T*>(sink_.closure);
-  }
-
-  /* Functions for pushing data into the sink.
-   *
-   * These return false if processing should stop (either due to error or just
-   * to suspend).
-   *
-   * These may not be called from within one of the same sink's handlers (in
-   * other words, handlers are not re-entrant). */
-
-  /* Should be called at the start and end of every message; both the top-level
-   * message and submessages.  This means that submessages should use the
-   * following sequence:
-   *   sink->StartSubMessage(startsubmsg_selector);
-   *   sink->StartMessage();
-   *   // ...
-   *   sink->EndMessage(&status);
-   *   sink->EndSubMessage(endsubmsg_selector); */
-  bool StartMessage() { return upb_sink_startmsg(sink_); }
-  bool EndMessage(upb_status *status) {
-    return upb_sink_endmsg(sink_, status);
-  }
-
-  /* Putting of individual values.  These work for both repeated and
-   * non-repeated fields, but for repeated fields you must wrap them in
-   * calls to StartSequence()/EndSequence(). */
-  bool PutInt32(HandlersPtr::Selector s, int32_t val) {
-    return upb_sink_putint32(sink_, s, val);
-  }
-
-  bool PutInt64(HandlersPtr::Selector s, int64_t val) {
-    return upb_sink_putint64(sink_, s, val);
-  }
-
-  bool PutUInt32(HandlersPtr::Selector s, uint32_t val) {
-    return upb_sink_putuint32(sink_, s, val);
-  }
-
-  bool PutUInt64(HandlersPtr::Selector s, uint64_t val) {
-    return upb_sink_putuint64(sink_, s, val);
-  }
-
-  bool PutFloat(HandlersPtr::Selector s, float val) {
-    return upb_sink_putfloat(sink_, s, val);
-  }
-
-  bool PutDouble(HandlersPtr::Selector s, double val) {
-    return upb_sink_putdouble(sink_, s, val);
-  }
-
-  bool PutBool(HandlersPtr::Selector s, bool val) {
-    return upb_sink_putbool(sink_, s, val);
-  }
-
-  /* Putting of string/bytes values.  Each string can consist of zero or more
-   * non-contiguous buffers of data.
-   *
-   * For StartString(), the function will write a sink for the string to "sub."
-   * The sub-sink must be used for any/all PutStringBuffer() calls. */
-  bool StartString(HandlersPtr::Selector s, size_t size_hint, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startstr(sink_, s, size_hint, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  size_t PutStringBuffer(HandlersPtr::Selector s, const char *buf, size_t len,
-                         const upb_bufhandle *handle) {
-    return upb_sink_putstring(sink_, s, buf, len, handle);
-  }
-
-  bool EndString(HandlersPtr::Selector s) {
-    return upb_sink_endstr(sink_, s);
-  }
-
-  /* For submessage fields.
-   *
-   * For StartSubMessage(), the function will write a sink for the string to
-   * "sub." The sub-sink must be used for any/all handlers called within the
-   * submessage. */
-  bool StartSubMessage(HandlersPtr::Selector s, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startsubmsg(sink_, s, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  bool EndSubMessage(HandlersPtr::Selector s, Sink sub) {
-    return upb_sink_endsubmsg(sink_, sub.sink_, s);
-  }
-
-  /* For repeated fields of any type, the sequence of values must be wrapped in
-   * these calls.
-   *
-   * For StartSequence(), the function will write a sink for the string to
-   * "sub." The sub-sink must be used for any/all handlers called within the
-   * sequence. */
-  bool StartSequence(HandlersPtr::Selector s, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startseq(sink_, s, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  bool EndSequence(HandlersPtr::Selector s) {
-    return upb_sink_endseq(sink_, s);
-  }
-
-  /* Copy and assign specifically allowed.
-   * We don't even bother making these members private because so many
-   * functions need them and this is mainly just a dumb data container anyway.
-   */
-
- private:
-  upb_sink sink_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_bytessink **************************************************************/
-
-typedef struct {
-  const upb_byteshandler *handler;
-  void *closure;
-} upb_bytessink ;
-
-UPB_INLINE void upb_bytessink_reset(upb_bytessink* s, const upb_byteshandler *h,
-                                    void *closure) {
-  s->handler = h;
-  s->closure = closure;
-}
-
-UPB_INLINE bool upb_bytessink_start(upb_bytessink s, size_t size_hint,
-                                    void **subc) {
-  typedef upb_startstr_handlerfunc func;
-  func *start;
-  *subc = s.closure;
-  if (!s.handler) return true;
-  start = (func *)s.handler->table[UPB_STARTSTR_SELECTOR].func;
-
-  if (!start) return true;
-  *subc = start(s.closure,
-                s.handler->table[UPB_STARTSTR_SELECTOR].attr.handler_data,
-                size_hint);
-  return *subc != NULL;
-}
-
-UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink s, void *subc,
-                                       const char *buf, size_t size,
-                                       const upb_bufhandle* handle) {
-  typedef upb_string_handlerfunc func;
-  func *putbuf;
-  if (!s.handler) return true;
-  putbuf = (func *)s.handler->table[UPB_STRING_SELECTOR].func;
-
-  if (!putbuf) return true;
-  return putbuf(subc, s.handler->table[UPB_STRING_SELECTOR].attr.handler_data,
-                buf, size, handle);
-}
-
-UPB_INLINE bool upb_bytessink_end(upb_bytessink s) {
-  typedef upb_endfield_handlerfunc func;
-  func *end;
-  if (!s.handler) return true;
-  end = (func *)s.handler->table[UPB_ENDSTR_SELECTOR].func;
-
-  if (!end) return true;
-  return end(s.closure,
-             s.handler->table[UPB_ENDSTR_SELECTOR].attr.handler_data);
-}
-
-#ifdef __cplusplus
-
-class upb::BytesSink {
- public:
-  BytesSink() {}
-
-  BytesSink(const BytesSink&) = default;
-  BytesSink& operator=(const BytesSink&) = default;
-
-  BytesSink(const upb_bytessink& sink) : sink_(sink) {}
-  BytesSink &operator=(const upb_bytessink &sink) {
-    sink_ = sink;
-    return *this;
-  }
-
-  upb_bytessink sink() { return sink_; }
-
-  /* Constructs a new sink for the given frozen handlers and closure.
-   *
-   * TODO(haberman): once the Handlers know the expected closure type, verify
-   * that T matches it. */
-  template <class T> BytesSink(const upb_byteshandler* handler, T* closure) {
-    upb_bytessink_reset(sink_, handler, closure);
-  }
-
-  /* Resets the value of the sink. */
-  template <class T> void Reset(const upb_byteshandler* handler, T* closure) {
-    upb_bytessink_reset(&sink_, handler, closure);
-  }
-
-  bool Start(size_t size_hint, void **subc) {
-    return upb_bytessink_start(sink_, size_hint, subc);
-  }
-
-  size_t PutBuffer(void *subc, const char *buf, size_t len,
-                   const upb_bufhandle *handle) {
-    return upb_bytessink_putbuf(sink_, subc, buf, len, handle);
-  }
-
-  bool End() {
-    return upb_bytessink_end(sink_);
-  }
-
- private:
-  upb_bytessink sink_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_bufsrc *****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-template <class T> bool PutBuffer(const T& str, BytesSink sink) {
-  return upb_bufsrc_putbuf(str.data(), str.size(), sink.sink());
-}
-}
-
-#endif  /* __cplusplus */
-
-
-#endif
-/*
-** Internal-only definitions for the decoder.
-*/
-
-#ifndef UPB_DECODER_INT_H_
-#define UPB_DECODER_INT_H_
-
-/*
-** upb::pb::Decoder
-**
-** A high performance, streaming, resumable decoder for the binary protobuf
-** format.
-**
-** This interface works the same regardless of what decoder backend is being
-** used.  A client of this class does not need to know whether decoding is using
-** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder.  By default,
-** it will always use the fastest available decoder.  However, you can call
-** set_allow_jit(false) to disable any JIT decoder that might be available.
-** This is primarily useful for testing purposes.
-*/
-
-#ifndef UPB_DECODER_H_
-#define UPB_DECODER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class CodeCache;
-class DecoderPtr;
-class DecoderMethodPtr;
-class DecoderMethodOptions;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-/* The maximum number of bytes we are required to buffer internally between
- * calls to the decoder.  The value is 14: a 5 byte unknown tag plus ten-byte
- * varint, less one because we are buffering an incomplete value.
- *
- * Should only be used by unit tests. */
-#define UPB_DECODER_MAX_RESIDUAL_BYTES 14
-
-/* upb_pbdecodermethod ********************************************************/
-
-struct upb_pbdecodermethod;
-typedef struct upb_pbdecodermethod upb_pbdecodermethod;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const upb_handlers *upb_pbdecodermethod_desthandlers(
-    const upb_pbdecodermethod *m);
-const upb_byteshandler *upb_pbdecodermethod_inputhandler(
-    const upb_pbdecodermethod *m);
-bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Represents the code to parse a protobuf according to a destination
- * Handlers. */
-class upb::pb::DecoderMethodPtr {
- public:
-  DecoderMethodPtr() : ptr_(nullptr) {}
-  DecoderMethodPtr(const upb_pbdecodermethod* ptr) : ptr_(ptr) {}
-
-  const upb_pbdecodermethod* ptr() { return ptr_; }
-
-  /* The destination handlers that are statically bound to this method.
-   * This method is only capable of outputting to a sink that uses these
-   * handlers. */
-  const Handlers *dest_handlers() const {
-    return upb_pbdecodermethod_desthandlers(ptr_);
-  }
-
-  /* The input handlers for this decoder method. */
-  const BytesHandler* input_handler() const {
-    return upb_pbdecodermethod_inputhandler(ptr_);
-  }
-
-  /* Whether this method is native. */
-  bool is_native() const {
-    return upb_pbdecodermethod_isnative(ptr_);
-  }
-
- private:
-  const upb_pbdecodermethod* ptr_;
-};
-
-#endif
-
-/* upb_pbdecoder **************************************************************/
-
-/* Preallocation hint: decoder won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the decoder library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_PB_DECODER_SIZE 4416
-
-struct upb_pbdecoder;
-typedef struct upb_pbdecoder upb_pbdecoder;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_pbdecoder *upb_pbdecoder_create(upb_arena *arena,
-                                    const upb_pbdecodermethod *method,
-                                    upb_sink output, upb_status *status);
-const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
-upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d);
-uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d);
-size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d);
-bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max);
-void upb_pbdecoder_reset(upb_pbdecoder *d);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A Decoder receives binary protobuf data on its input sink and pushes the
- * decoded data to its output sink. */
-class upb::pb::DecoderPtr {
- public:
-  DecoderPtr() : ptr_(nullptr) {}
-  DecoderPtr(upb_pbdecoder* ptr) : ptr_(ptr) {}
-
-  upb_pbdecoder* ptr() { return ptr_; }
-
-  /* Constructs a decoder instance for the given method, which must outlive this
-   * decoder.  Any errors during parsing will be set on the given status, which
-   * must also outlive this decoder.
-   *
-   * The sink must match the given method. */
-  static DecoderPtr Create(Arena *arena, DecoderMethodPtr method,
-                           upb::Sink output, Status *status) {
-    return DecoderPtr(upb_pbdecoder_create(arena->ptr(), method.ptr(),
-                                           output.sink(), status->ptr()));
-  }
-
-  /* Returns the DecoderMethod this decoder is parsing from. */
-  const DecoderMethodPtr method() const {
-    return DecoderMethodPtr(upb_pbdecoder_method(ptr_));
-  }
-
-  /* The sink on which this decoder receives input. */
-  BytesSink input() { return BytesSink(upb_pbdecoder_input(ptr())); }
-
-  /* Returns number of bytes successfully parsed.
-   *
-   * This can be useful for determining the stream position where an error
-   * occurred.
-   *
-   * This value may not be up-to-date when called from inside a parsing
-   * callback. */
-  uint64_t BytesParsed() { return upb_pbdecoder_bytesparsed(ptr()); }
-
-  /* Gets/sets the parsing nexting limit.  If the total number of nested
-   * submessages and repeated fields hits this limit, parsing will fail.  This
-   * is a resource limit that controls the amount of memory used by the parsing
-   * stack.
-   *
-   * Setting the limit will fail if the parser is currently suspended at a depth
-   * greater than this, or if memory allocation of the stack fails. */
-  size_t max_nesting() { return upb_pbdecoder_maxnesting(ptr()); }
-  bool set_max_nesting(size_t max) { return upb_pbdecoder_maxnesting(ptr()); }
-
-  void Reset() { upb_pbdecoder_reset(ptr()); }
-
-  static const size_t kSize = UPB_PB_DECODER_SIZE;
-
- private:
-  upb_pbdecoder *ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_pbcodecache ************************************************************/
-
-/* Lazily builds and caches decoder methods that will push data to the given
- * handlers.  The destination handlercache must outlive this object. */
-
-struct upb_pbcodecache;
-typedef struct upb_pbcodecache upb_pbcodecache;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest);
-void upb_pbcodecache_free(upb_pbcodecache *c);
-bool upb_pbcodecache_allowjit(const upb_pbcodecache *c);
-void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow);
-void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy);
-const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
-                                               const upb_msgdef *md);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A class for caching protobuf processing code, whether bytecode for the
- * interpreted decoder or machine code for the JIT.
- *
- * This class is not thread-safe. */
-class upb::pb::CodeCache {
- public:
-  CodeCache(upb::HandlerCache *dest)
-      : ptr_(upb_pbcodecache_new(dest->ptr()), upb_pbcodecache_free) {}
-  CodeCache(CodeCache&&) = default;
-  CodeCache& operator=(CodeCache&&) = default;
-
-  upb_pbcodecache* ptr() { return ptr_.get(); }
-  const upb_pbcodecache* ptr() const { return ptr_.get(); }
-
-  /* Whether the cache is allowed to generate machine code.  Defaults to true.
-   * There is no real reason to turn it off except for testing or if you are
-   * having a specific problem with the JIT.
-   *
-   * Note that allow_jit = true does not *guarantee* that the code will be JIT
-   * compiled.  If this platform is not supported or the JIT was not compiled
-   * in, the code may still be interpreted. */
-  bool allow_jit() const { return upb_pbcodecache_allowjit(ptr()); }
-
-  /* This may only be called when the object is first constructed, and prior to
-   * any code generation. */
-  void set_allow_jit(bool allow) { upb_pbcodecache_setallowjit(ptr(), allow); }
-
-  /* Should the decoder push submessages to lazy handlers for fields that have
-   * them?  The caller should set this iff the lazy handlers expect data that is
-   * in protobuf binary format and the caller wishes to lazy parse it. */
-  void set_lazy(bool lazy) { upb_pbcodecache_setlazy(ptr(), lazy); }
-
-  /* Returns a DecoderMethod that can push data to the given handlers.
-   * If a suitable method already exists, it will be returned from the cache. */
-  const DecoderMethodPtr Get(MessageDefPtr md) {
-    return DecoderMethodPtr(upb_pbcodecache_get(ptr(), md.ptr()));
-  }
-
- private:
-  std::unique_ptr<upb_pbcodecache, decltype(&upb_pbcodecache_free)> ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_DECODER_H_ */
-
-
-/* Opcode definitions.  The canonical meaning of each opcode is its
- * implementation in the interpreter (the JIT is written to match this).
- *
- * All instructions have the opcode in the low byte.
- * Instruction format for most instructions is:
- *
- * +-------------------+--------+
- * |     arg (24)      | op (8) |
- * +-------------------+--------+
- *
- * Exceptions are indicated below.  A few opcodes are multi-word. */
-typedef enum {
-  /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types.
-   * Arg for all of these is the upb selector for this field. */
-#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type
-  T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32),
-  T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64),
-#undef T
-  OP_STARTMSG       = 9,   /* No arg. */
-  OP_ENDMSG         = 10,  /* No arg. */
-  OP_STARTSEQ       = 11,
-  OP_ENDSEQ         = 12,
-  OP_STARTSUBMSG    = 14,
-  OP_ENDSUBMSG      = 19,
-  OP_STARTSTR       = 20,
-  OP_STRING         = 21,
-  OP_ENDSTR         = 22,
-
-  OP_PUSHTAGDELIM   = 23,  /* No arg. */
-  OP_PUSHLENDELIM   = 24,  /* No arg. */
-  OP_POP            = 25,  /* No arg. */
-  OP_SETDELIM       = 26,  /* No arg. */
-  OP_SETBIGGROUPNUM = 27,  /* two words:
-                            *   | unused (24)     | opc (8) |
-                            *   |        groupnum (32)      | */
-  OP_CHECKDELIM     = 28,
-  OP_CALL           = 29,
-  OP_RET            = 30,
-  OP_BRANCH         = 31,
-
-  /* Different opcodes depending on how many bytes expected. */
-  OP_TAG1           = 32,  /* | match tag (16) | jump target (8) | opc (8) | */
-  OP_TAG2           = 33,  /* | match tag (16) | jump target (8) | opc (8) | */
-  OP_TAGN           = 34,  /* three words: */
-                           /*   | unused (16) | jump target(8) | opc (8) | */
-                           /*   |           match tag 1 (32)             | */
-                           /*   |           match tag 2 (32)             | */
-
-  OP_SETDISPATCH    = 35,  /* N words: */
-                           /*   | unused (24)         | opc | */
-                           /*   | upb_inttable* (32 or 64)  | */
-
-  OP_DISPATCH       = 36,  /* No arg. */
-
-  OP_HALT           = 37   /* No arg. */
-} opcode;
-
-#define OP_MAX OP_HALT
-
-UPB_INLINE opcode getop(uint32_t instr) { return (opcode)(instr & 0xff); }
-
-struct upb_pbcodecache {
-  upb_arena *arena;
-  upb_handlercache *dest;
-  bool allow_jit;
-  bool lazy;
-
-  /* Map of upb_msgdef -> mgroup. */
-  upb_inttable groups;
-};
-
-/* Method group; represents a set of decoder methods that had their code
- * emitted together.  Immutable once created.  */
-typedef struct {
-  /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod.  Owned by us.
-   *
-   * Ideally this would be on pbcodecache (if we were actually caching code).
-   * Right now we don't actually cache anything, which is wasteful. */
-  upb_inttable methods;
-
-  /* The bytecode for our methods, if any exists.  Owned by us. */
-  uint32_t *bytecode;
-  uint32_t *bytecode_end;
-} mgroup;
-
-/* The maximum that any submessages can be nested.  Matches proto2's limit.
- * This specifies the size of the decoder's statically-sized array and therefore
- * setting it high will cause the upb::pb::Decoder object to be larger.
- *
- * If necessary we can add a runtime-settable property to Decoder that allow
- * this to be larger than the compile-time setting, but this would add
- * complexity, particularly since we would have to decide how/if to give users
- * the ability to set a custom memory allocation function. */
-#define UPB_DECODER_MAX_NESTING 64
-
-/* Internal-only struct used by the decoder. */
-typedef struct {
-  /* Space optimization note: we store two pointers here that the JIT
-   * doesn't need at all; the upb_handlers* inside the sink and
-   * the dispatch table pointer.  We can optimze so that the JIT uses
-   * smaller stack frames than the interpreter.  The only thing we need
-   * to guarantee is that the fallback routines can find end_ofs. */
-  upb_sink sink;
-
-  /* The absolute stream offset of the end-of-frame delimiter.
-   * Non-delimited frames (groups and non-packed repeated fields) reuse the
-   * delimiter of their parent, even though the frame may not end there.
-   *
-   * NOTE: the JIT stores a slightly different value here for non-top frames.
-   * It stores the value relative to the end of the enclosed message.  But the
-   * top frame is still stored the same way, which is important for ensuring
-   * that calls from the JIT into C work correctly. */
-  uint64_t end_ofs;
-  const uint32_t *base;
-
-  /* 0 indicates a length-delimited field.
-   * A positive number indicates a known group.
-   * A negative number indicates an unknown group. */
-  int32_t groupnum;
-  upb_inttable *dispatch;  /* Not used by the JIT. */
-} upb_pbdecoder_frame;
-
-struct upb_pbdecodermethod {
-  /* While compiling, the base is relative in "ofs", after compiling it is
-   * absolute in "ptr". */
-  union {
-    uint32_t ofs;     /* PC offset of method. */
-    void *ptr;        /* Pointer to bytecode or machine code for this method. */
-  } code_base;
-
-  /* The decoder method group to which this method belongs. */
-  const mgroup *group;
-
-  /* Whether this method is native code or bytecode. */
-  bool is_native_;
-
-  /* The handler one calls to invoke this method. */
-  upb_byteshandler input_handler_;
-
-  /* The destination handlers this method is bound to.  We own a ref. */
-  const upb_handlers *dest_handlers_;
-
-  /* Dispatch table -- used by both bytecode decoder and JIT when encountering a
-   * field number that wasn't the one we were expecting to see.  See
-   * decoder.int.h for the layout of this table. */
-  upb_inttable dispatch;
-};
-
-struct upb_pbdecoder {
-  upb_arena *arena;
-
-  /* Our input sink. */
-  upb_bytessink input_;
-
-  /* The decoder method we are parsing with (owned). */
-  const upb_pbdecodermethod *method_;
-
-  size_t call_len;
-  const uint32_t *pc, *last;
-
-  /* Current input buffer and its stream offset. */
-  const char *buf, *ptr, *end, *checkpoint;
-
-  /* End of the delimited region, relative to ptr, NULL if not in this buf. */
-  const char *delim_end;
-
-  /* End of the delimited region, relative to ptr, end if not in this buf. */
-  const char *data_end;
-
-  /* Overall stream offset of "buf." */
-  uint64_t bufstart_ofs;
-
-  /* Buffer for residual bytes not parsed from the previous buffer. */
-  char residual[UPB_DECODER_MAX_RESIDUAL_BYTES];
-  char *residual_end;
-
-  /* Bytes of data that should be discarded from the input beore we start
-   * parsing again.  We set this when we internally determine that we can
-   * safely skip the next N bytes, but this region extends past the current
-   * user buffer. */
-  size_t skip;
-
-  /* Stores the user buffer passed to our decode function. */
-  const char *buf_param;
-  size_t size_param;
-  const upb_bufhandle *handle;
-
-  /* Our internal stack. */
-  upb_pbdecoder_frame *stack, *top, *limit;
-  const uint32_t **callstack;
-  size_t stack_size;
-
-  upb_status *status;
-};
-
-/* Decoder entry points; used as handlers. */
-void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint);
-size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
-                            size_t size, const upb_bufhandle *handle);
-bool upb_pbdecoder_end(void *closure, const void *handler_data);
-
-/* Decoder-internal functions that the JIT calls to handle fallback paths. */
-int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
-                             size_t size, const upb_bufhandle *handle);
-size_t upb_pbdecoder_suspend(upb_pbdecoder *d);
-int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
-                                  uint8_t wire_type);
-int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected);
-int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64);
-int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32);
-int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64);
-void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg);
-
-/* Error messages that are shared between the bytecode and JIT decoders. */
-extern const char *kPbDecoderStackOverflow;
-extern const char *kPbDecoderSubmessageTooLong;
-
-/* Access to decoderplan members needed by the decoder. */
-const char *upb_pbdecoder_getopname(unsigned int op);
-
-/* A special label that means "do field dispatch for this message and branch to
- * wherever that takes you." */
-#define LABEL_DISPATCH 0
-
-/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or
- * RET) for branching to when we find an appropriate ENDGROUP tag. */
-#define DISPATCH_ENDMSG 0
-
-/* It's important to use this invalid wire type instead of 0 (which is a valid
- * wire type). */
-#define NO_WIRE_TYPE 0xff
-
-/* The dispatch table layout is:
- *   [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ]
- *
- * If wt1 matches, jump to the 48-bit offset.  If wt2 matches, lookup
- * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there.
- *
- * We need two wire types because of packed/non-packed compatibility.  A
- * primitive repeated field can use either wire type and be valid.  While we
- * could key the table on fieldnum+wiretype, the table would be 8x sparser.
- *
- * Storing two wire types in the primary value allows us to quickly rule out
- * the second wire type without needing to do a separate lookup (this case is
- * less common than an unknown field). */
-UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1,
-                                               uint8_t wt2) {
-  return (ofs << 16) | (wt2 << 8) | wt1;
-}
-
-UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs,
-                                             uint8_t *wt1, uint8_t *wt2) {
-  *wt1 = (uint8_t)dispatch;
-  *wt2 = (uint8_t)(dispatch >> 8);
-  *ofs = dispatch >> 16;
-}
-
-/* All of the functions in decoder.c that return int32_t return values according
- * to the following scheme:
- *   1. negative values indicate a return code from the following list.
- *   2. positive values indicate that error or end of buffer was hit, and
- *      that the decode function should immediately return the given value
- *      (the decoder state has already been suspended and is ready to be
- *      resumed). */
-#define DECODE_OK -1
-#define DECODE_MISMATCH -2  /* Used only from checktag_slow(). */
-#define DECODE_ENDGROUP -3  /* Used only from checkunknown(). */
-
-#define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; }
-
-
-#endif  /* UPB_DECODER_INT_H_ */
-/*
-** A number of routines for varint manipulation (we keep them all around to
-** have multiple approaches available for benchmarking).
-*/
-
-#ifndef UPB_VARINT_DECODER_H_
-#define UPB_VARINT_DECODER_H_
-
-#include <assert.h>
-#include <stdint.h>
-#include <string.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define UPB_MAX_WIRE_TYPE 5
-
-/* The maximum number of bytes that it takes to encode a 64-bit varint. */
-#define UPB_PB_VARINT_MAX_LEN 10
-
-/* Array of the "native" (ie. non-packed-repeated) wire type for the given a
- * descriptor type (upb_descriptortype_t). */
-extern const uint8_t upb_pb_native_wire_types[];
-
-UPB_INLINE uint64_t byteswap64(uint64_t val) {
-  uint64_t byte = 0xff;
-  return (val & (byte << 56) >> 56)
-    | (val & (byte << 48) >> 40)
-    | (val & (byte << 40) >> 24)
-    | (val & (byte << 32) >> 8)
-    | (val & (byte << 24) << 8)
-    | (val & (byte << 16) << 24)
-    | (val & (byte <<  8) << 40)
-    | (val & (byte <<  0) << 56);
-}
-
-/* Zig-zag encoding/decoding **************************************************/
-
-UPB_INLINE int32_t upb_zzdec_32(uint64_t _n) {
-  uint32_t n = (uint32_t)_n;
-  return (n >> 1) ^ -(int32_t)(n & 1);
-}
-UPB_INLINE int64_t upb_zzdec_64(uint64_t n) {
-  return (n >> 1) ^ -(int64_t)(n & 1);
-}
-UPB_INLINE uint32_t upb_zzenc_32(int32_t n) {
-  return ((uint32_t)n << 1) ^ (n >> 31);
-}
-UPB_INLINE uint64_t upb_zzenc_64(int64_t n) {
-  return ((uint64_t)n << 1) ^ (n >> 63);
-}
-
-/* Decoding *******************************************************************/
-
-/* All decoding functions return this struct by value. */
-typedef struct {
-  const char *p;  /* NULL if the varint was unterminated. */
-  uint64_t val;
-} upb_decoderet;
-
-UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) {
-  upb_decoderet ret;
-  ret.p = p;
-  ret.val = val;
-  return ret;
-}
-
-upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r);
-upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r);
-
-/* Template for a function that checks the first two bytes with branching
- * and dispatches 2-10 bytes with a separate function.  Note that this may read
- * up to 10 bytes, so it must not be used unless there are at least ten bytes
- * left in the buffer! */
-#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function)                  \
-UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) {         \
-  uint8_t *p = (uint8_t*)_p;                                                   \
-  upb_decoderet r;                                                             \
-  if ((*p & 0x80) == 0) {                                                      \
-  /* Common case: one-byte varint. */                                          \
-    return upb_decoderet_make(_p + 1, *p & 0x7fU);                             \
-  }                                                                            \
-  r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7));    \
-  if ((*(p + 1) & 0x80) == 0) {                                                \
-    /* Two-byte varint. */                                                     \
-    return r;                                                                  \
-  }                                                                            \
-  /* Longer varint, fallback to out-of-line function. */                       \
-  return decode_max8_function(r);                                              \
-}
-
-UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32)
-UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64)
-#undef UPB_VARINT_DECODER_CHECK2
-
-/* Our canonical functions for decoding varints, based on the currently
- * favored best-performing implementations. */
-UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) {
-  if (sizeof(long) == 8)
-    return upb_vdecode_check2_branch64(p);
-  else
-    return upb_vdecode_check2_branch32(p);
-}
-
-
-/* Encoding *******************************************************************/
-
-UPB_INLINE int upb_value_size(uint64_t val) {
-#ifdef __GNUC__
-  int high_bit = 63 - __builtin_clzll(val);  /* 0-based, undef if val == 0. */
-#else
-  int high_bit = 0;
-  uint64_t tmp = val;
-  while(tmp >>= 1) high_bit++;
-#endif
-  return val == 0 ? 1 : high_bit / 8 + 1;
-}
-
-/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN
- * bytes long), returning how many bytes were used.
- *
- * TODO: benchmark and optimize if necessary. */
-UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) {
-  size_t i;
-  if (val == 0) { buf[0] = 0; return 1; }
-  i = 0;
-  while (val) {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    buf[i++] = byte;
-  }
-  return i;
-}
-
-UPB_INLINE size_t upb_varint_size(uint64_t val) {
-  char buf[UPB_PB_VARINT_MAX_LEN];
-  return upb_vencode64(val, buf);
-}
-
-/* Encodes a 32-bit varint, *not* sign-extended. */
-UPB_INLINE uint64_t upb_vencode32(uint32_t val) {
-  char buf[UPB_PB_VARINT_MAX_LEN];
-  size_t bytes = upb_vencode64(val, buf);
-  uint64_t ret = 0;
-  UPB_ASSERT(bytes <= 5);
-  memcpy(&ret, buf, bytes);
-#ifdef UPB_BIG_ENDIAN
-  ret = byteswap64(ret);
-#endif
-  UPB_ASSERT(ret <= 0xffffffffffU);
-  return ret;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* UPB_VARINT_DECODER_H_ */
-/*
-** upb::pb::Encoder (upb_pb_encoder)
-**
-** Implements a set of upb_handlers that write protobuf data to the binary wire
-** format.
-**
-** This encoder implementation does not have any access to any out-of-band or
-** precomputed lengths for submessages, so it must buffer submessages internally
-** before it can emit the first byte.
-*/
-
-#ifndef UPB_ENCODER_H_
-#define UPB_ENCODER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class EncoderPtr;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-#define UPB_PBENCODER_MAX_NESTING 100
-
-/* upb_pb_encoder *************************************************************/
-
-/* Preallocation hint: decoder won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the decoder library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_PB_ENCODER_SIZE 784
-
-struct upb_pb_encoder;
-typedef struct upb_pb_encoder upb_pb_encoder;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_sink upb_pb_encoder_input(upb_pb_encoder *p);
-upb_pb_encoder* upb_pb_encoder_create(upb_arena* a, const upb_handlers* h,
-                                      upb_bytessink output);
-
-/* Lazily builds and caches handlers that will push encoded data to a bytessink.
- * Any msgdef objects used with this object must outlive it. */
-upb_handlercache *upb_pb_encoder_newcache(void);
-
-#ifdef __cplusplus
-}  /* extern "C" { */
-
-class upb::pb::EncoderPtr {
- public:
-  EncoderPtr(upb_pb_encoder* ptr) : ptr_(ptr) {}
-
-  upb_pb_encoder* ptr() { return ptr_; }
-
-  /* Creates a new encoder in the given environment.  The Handlers must have
-   * come from NewHandlers() below. */
-  static EncoderPtr Create(Arena* arena, const Handlers* handlers,
-                           BytesSink output) {
-    return EncoderPtr(
-        upb_pb_encoder_create(arena->ptr(), handlers, output.sink()));
-  }
-
-  /* The input to the encoder. */
-  upb::Sink input() { return upb_pb_encoder_input(ptr()); }
-
-  /* Creates a new set of handlers for this MessageDef. */
-  static HandlerCache NewCache() {
-    return HandlerCache(upb_pb_encoder_newcache());
-  }
-
-  static const size_t kSize = UPB_PB_ENCODER_SIZE;
-
- private:
-  upb_pb_encoder* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_ENCODER_H_ */
-/*
-** upb::pb::TextPrinter (upb_textprinter)
-**
-** Handlers for writing to protobuf text format.
-*/
-
-#ifndef UPB_TEXT_H_
-#define UPB_TEXT_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class TextPrinterPtr;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-/* upb_textprinter ************************************************************/
-
-struct upb_textprinter;
-typedef struct upb_textprinter upb_textprinter;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* C API. */
-upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
-                                        upb_bytessink output);
-void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
-upb_sink upb_textprinter_input(upb_textprinter *p);
-upb_handlercache *upb_textprinter_newcache(void);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::pb::TextPrinterPtr {
- public:
-  TextPrinterPtr(upb_textprinter* ptr) : ptr_(ptr) {}
-
-  /* The given handlers must have come from NewHandlers().  It must outlive the
-   * TextPrinter. */
-  static TextPrinterPtr Create(Arena *arena, upb::HandlersPtr *handlers,
-                               BytesSink output) {
-    return TextPrinterPtr(
-        upb_textprinter_create(arena->ptr(), handlers->ptr(), output.sink()));
-  }
-
-  void SetSingleLineMode(bool single_line) {
-    upb_textprinter_setsingleline(ptr_, single_line);
-  }
-
-  Sink input() { return upb_textprinter_input(ptr_); }
-
-  /* If handler caching becomes a requirement we can add a code cache as in
-   * decoder.h */
-  static HandlerCache NewCache() {
-    return HandlerCache(upb_textprinter_newcache());
-  }
-
- private:
-  upb_textprinter* ptr_;
-};
-
-#endif
-
-#endif  /* UPB_TEXT_H_ */
-/*
-** upb::json::Parser (upb_json_parser)
-**
-** Parses JSON according to a specific schema.
-** Support for parsing arbitrary JSON (schema-less) will be added later.
-*/
-
-#ifndef UPB_JSON_PARSER_H_
-#define UPB_JSON_PARSER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace json {
-class CodeCache;
-class ParserPtr;
-class ParserMethodPtr;
-}  /* namespace json */
-}  /* namespace upb */
-#endif
-
-/* upb_json_parsermethod ******************************************************/
-
-struct upb_json_parsermethod;
-typedef struct upb_json_parsermethod upb_json_parsermethod;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const upb_byteshandler* upb_json_parsermethod_inputhandler(
-    const upb_json_parsermethod* m);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::json::ParserMethodPtr {
- public:
-  ParserMethodPtr() : ptr_(nullptr) {}
-  ParserMethodPtr(const upb_json_parsermethod* ptr) : ptr_(ptr) {}
-
-  const upb_json_parsermethod* ptr() const { return ptr_; }
-
-  const BytesHandler* input_handler() const {
-    return upb_json_parsermethod_inputhandler(ptr());
-  }
-
- private:
-  const upb_json_parsermethod* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_json_parser ************************************************************/
-
-/* Preallocation hint: parser won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the parser library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_JSON_PARSER_SIZE 5712
-
-struct upb_json_parser;
-typedef struct upb_json_parser upb_json_parser;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_json_parser* upb_json_parser_create(upb_arena* a,
-                                        const upb_json_parsermethod* m,
-                                        const upb_symtab* symtab,
-                                        upb_sink output,
-                                        upb_status *status,
-                                        bool ignore_json_unknown);
-upb_bytessink upb_json_parser_input(upb_json_parser* p);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Parses an incoming BytesStream, pushing the results to the destination
- * sink. */
-class upb::json::ParserPtr {
- public:
-  ParserPtr(upb_json_parser* ptr) : ptr_(ptr) {}
-
-  static ParserPtr Create(Arena* arena, ParserMethodPtr method,
-                          SymbolTable* symtab, Sink output, Status* status,
-                          bool ignore_json_unknown) {
-    upb_symtab* symtab_ptr = symtab ? symtab->ptr() : nullptr;
-    return ParserPtr(upb_json_parser_create(
-        arena->ptr(), method.ptr(), symtab_ptr, output.sink(), status->ptr(),
-        ignore_json_unknown));
-  }
-
-  BytesSink input() { return upb_json_parser_input(ptr_); }
-
- private:
-  upb_json_parser* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_json_codecache *********************************************************/
-
-/* Lazily builds and caches decoder methods that will push data to the given
- * handlers.  The upb_symtab object(s) must outlive this object. */
-
-struct upb_json_codecache;
-typedef struct upb_json_codecache upb_json_codecache;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_json_codecache *upb_json_codecache_new(void);
-void upb_json_codecache_free(upb_json_codecache *cache);
-const upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache,
-                                                    const upb_msgdef* md);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::json::CodeCache {
- public:
-  CodeCache() : ptr_(upb_json_codecache_new(), upb_json_codecache_free) {}
-
-  /* Returns a DecoderMethod that can push data to the given handlers.
-   * If a suitable method already exists, it will be returned from the cache. */
-  ParserMethodPtr Get(MessageDefPtr md) {
-    return upb_json_codecache_get(ptr_.get(), md.ptr());
-  }
-
- private:
-  std::unique_ptr<upb_json_codecache, decltype(&upb_json_codecache_free)> ptr_;
-};
-
-#endif
-
-#endif  /* UPB_JSON_PARSER_H_ */
-/*
-** upb::json::Printer
-**
-** Handlers that emit JSON according to a specific protobuf schema.
-*/
-
-#ifndef UPB_JSON_TYPED_PRINTER_H_
-#define UPB_JSON_TYPED_PRINTER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace json {
-class PrinterPtr;
-}  /* namespace json */
-}  /* namespace upb */
-#endif
-
-/* upb_json_printer ***********************************************************/
-
-#define UPB_JSON_PRINTER_SIZE 192
-
-struct upb_json_printer;
-typedef struct upb_json_printer upb_json_printer;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Native C API. */
-upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
-                                          upb_bytessink output);
-upb_sink upb_json_printer_input(upb_json_printer *p);
-const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
-                                                 bool preserve_fieldnames,
-                                                 const void *owner);
-
-/* Lazily builds and caches handlers that will push encoded data to a bytessink.
- * Any msgdef objects used with this object must outlive it. */
-upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Prints an incoming stream of data to a BytesSink in JSON format. */
-class upb::json::PrinterPtr {
- public:
-  PrinterPtr(upb_json_printer* ptr) : ptr_(ptr) {}
-
-  static PrinterPtr Create(Arena *arena, const upb::Handlers *handlers,
-                           BytesSink output) {
-    return PrinterPtr(
-        upb_json_printer_create(arena->ptr(), handlers, output.sink()));
-  }
-
-  /* The input to the printer. */
-  Sink input() { return upb_json_printer_input(ptr_); }
-
-  static const size_t kSize = UPB_JSON_PRINTER_SIZE;
-
-  static HandlerCache NewCache(bool preserve_proto_fieldnames) {
-    return upb_json_printer_newcache(preserve_proto_fieldnames);
-  }
-
- private:
-  upb_json_printer* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_JSON_TYPED_PRINTER_H_ */
-/* See port_def.inc.  This should #undef all macros #defined there. */
-
-#undef UPB_MAPTYPE_STRING
-#undef UPB_SIZE
-#undef UPB_PTR_AT
-#undef UPB_READ_ONEOF
-#undef UPB_WRITE_ONEOF
-#undef UPB_INLINE
-#undef UPB_FORCEINLINE
-#undef UPB_NOINLINE
-#undef UPB_NORETURN
-#undef UPB_MAX
-#undef UPB_MIN
-#undef UPB_UNUSED
-#undef UPB_ASSUME
-#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
-#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index cd9af71..36d325e 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -1,6 +1,6 @@
 Gem::Specification.new do |s|
   s.name        = "google-protobuf"
-  s.version     = "3.11.4"
+  s.version     = "3.17.3"
   git_tag       = "v#{s.version.to_s.sub('.rc.', '-rc')}" # Converts X.Y.Z.rc.N to vX.Y.Z-rcN, used for the git tag
   s.licenses    = ["BSD-3-Clause"]
   s.summary     = "Protocol Buffers"
@@ -17,7 +17,7 @@
   else
     s.files     += Dir.glob('ext/**/*')
     s.extensions= ["ext/google/protobuf_c/extconf.rb"]
-    s.add_development_dependency "rake-compiler-dock", ">= 1.0.1", "< 2.0"
+    s.add_development_dependency "rake-compiler-dock", ">= 1.1.0", "< 2.0"
   end
   s.test_files  = ["tests/basic.rb",
                   "tests/stress.rb",
diff --git a/ruby/pom.xml b/ruby/pom.xml
index acd2453..6c96bf4 100644
--- a/ruby/pom.xml
+++ b/ruby/pom.xml
@@ -43,6 +43,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-assembly-plugin</artifactId>
+                <version>3.3.0</version>
                 <configuration>
                     <finalName>${jar.finalName}</finalName>
                     <outputDirectory>${ruby.sources}</outputDirectory>
@@ -64,9 +65,10 @@
             <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
+              <version>3.8.1</version>
               <configuration>
-                <source>1.6</source>
-                <target>1.6</target>
+                <source>1.8</source>
+                <target>1.8</target>
               </configuration>
             </plugin>
         </plugins>
@@ -80,13 +82,13 @@
         <dependency>
             <groupId>org.jruby</groupId>
             <artifactId>jruby-complete</artifactId>
-            <version>1.7.13</version>
+            <version>9.2.11.1</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>com.google.protobuf</groupId>
-            <artifactId>protobuf-java</artifactId>
-            <version>3.0.0</version>
+            <artifactId>protobuf-java-util</artifactId>
+            <version>3.13.0</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java
index 5addae5..b19ea64 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java
@@ -41,8 +41,8 @@
 @JRubyClass(name = "Builder")
 public class RubyBuilder extends RubyObject {
     public static void createRubyBuilder(Ruby runtime) {
-        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
-        RubyClass cBuilder = protobuf.defineClassUnder("Builder", runtime.getObject(), new ObjectAllocator() {
+        RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal");
+        RubyClass cBuilder = internal.defineClassUnder("Builder", runtime.getObject(), new ObjectAllocator() {
             @Override
             public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
                 return new RubyBuilder(runtime, klazz);
@@ -53,10 +53,7 @@
 
     public RubyBuilder(Ruby runtime, RubyClass metaClass) {
         super(runtime, metaClass);
-        this.cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor");
-        this.cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor");
-        this.cMessageBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::MessageBuilderContext");
-        this.cEnumBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumBuilderContext");
+        this.cFileBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::FileBuilderContext");
     }
 
     /*
@@ -68,9 +65,8 @@
      * (co)recursive type references.
      */
     @JRubyMethod
-    public IRubyObject initialize(ThreadContext context) {
-        Ruby runtime = context.runtime;
-        this.pendingList = runtime.newArray();
+    public IRubyObject initialize(ThreadContext context, IRubyObject descriptorPool) {
+        this.descriptorPool = (RubyDescriptorPool) descriptorPool;
         return this;
     }
 
@@ -78,90 +74,74 @@
      * call-seq:
      *     Builder.add_message(name, &block)
      *
-     * Creates a new, empty descriptor with the given name, and invokes the block in
-     * the context of a MessageBuilderContext on that descriptor. The block can then
-     * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
-     * methods to define the message fields.
+     * Old and deprecated way to create a new descriptor.
+     * See FileBuilderContext.add_message for the recommended way.
      *
-     * This is the recommended, idiomatic way to build message definitions.
+     * Exists for backwards compatibility to allow building descriptor pool for
+     * files generated by protoc which don't add messages within "add_file" block.
+     * Descriptors created this way get assigned to a default empty FileDescriptor.
      */
     @JRubyMethod(name = "add_message")
     public IRubyObject addMessage(ThreadContext context, IRubyObject name, Block block) {
-        RubyDescriptor msgdef = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
-        IRubyObject ctx = cMessageBuilderContext.newInstance(context, msgdef, this, Block.NULL_BLOCK);
-        msgdef.setName(context, name);
-        if (block.isGiven()) {
-            if (block.arity() == Arity.ONE_ARGUMENT) {
-                block.yield(context, ctx);
-            } else {
-                Binding binding = block.getBinding();
-                binding.setSelf(ctx);
-                block.yieldSpecific(context);
-            }
-        }
-        this.pendingList.add(msgdef);
-        return context.runtime.getNil();
+        ensureDefaultFileBuilder(context);
+        defaultFileBuilder.addMessage(context, name, block);
+        return context.nil;
     }
 
     /*
      * call-seq:
      *     Builder.add_enum(name, &block)
      *
-     * Creates a new, empty enum descriptor with the given name, and invokes the block in
-     * the context of an EnumBuilderContext on that descriptor. The block can then
-     * call EnumBuilderContext#add_value to define the enum values.
+     * Old and deprecated way to create a new enum descriptor.
+     * See FileBuilderContext.add_enum for the recommended way.
      *
-     * This is the recommended, idiomatic way to build enum definitions.
+     * Exists for backwards compatibility to allow building descriptor pool for
+     * files generated by protoc which don't add enums within "add_file" block.
+     * Enum descriptors created this way get assigned to a default empty
+     * FileDescriptor.
      */
     @JRubyMethod(name = "add_enum")
     public IRubyObject addEnum(ThreadContext context, IRubyObject name, Block block) {
-        RubyEnumDescriptor enumDef = (RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK);
-        IRubyObject ctx = cEnumBuilderContext.newInstance(context, enumDef, Block.NULL_BLOCK);
-        enumDef.setName(context, name);
-
-        if (block.isGiven()) {
-            if (block.arity() == Arity.ONE_ARGUMENT) {
-                block.yield(context, ctx);
-            } else {
-                Binding binding = block.getBinding();
-                binding.setSelf(ctx);
-                block.yieldSpecific(context);
-            }
-        }
-
-        this.pendingList.add(enumDef);
-        return context.runtime.getNil();
+        ensureDefaultFileBuilder(context);
+        defaultFileBuilder.addEnum(context, name, block);
+        return context.nil;
     }
 
     /*
      * call-seq:
-     *     Builder.finalize_to_pool(pool)
+     *     Builder.add_file(name, options = nil, &block)
      *
-     * Adds all accumulated message and enum descriptors created in this builder
-     * context to the given pool. The operation occurs atomically, and all
-     * descriptors can refer to each other (including in cycles). This is the only
-     * way to build (co)recursive message definitions.
+     * Creates a new, file descriptor with the given name and options and invokes
+     * the block in the context of a FileBuilderContext on that descriptor. The
+     * block can then call FileBuilderContext#add_message or
+     * FileBuilderContext#add_enum to define new messages or enums, respectively.
      *
-     * This method is usually called automatically by DescriptorPool#build after it
-     * invokes the given user block in the context of the builder. The user should
-     * not normally need to call this manually because a Builder is not normally
-     * created manually.
+     * This is the recommended, idiomatic way to build file descriptors.
      */
-    @JRubyMethod(name = "finalize_to_pool")
-    public IRubyObject finalizeToPool(ThreadContext context, IRubyObject rbPool) {
-        RubyDescriptorPool pool = (RubyDescriptorPool) rbPool;
-        for (int i = 0; i < this.pendingList.size(); i++) {
-            IRubyObject defRb = this.pendingList.entry(i);
-            if (defRb instanceof RubyDescriptor) {
-                pool.addToSymtab(context, (RubyDescriptor) defRb);
-            } else {
-                pool.addToSymtab(context, (RubyEnumDescriptor) defRb);
-            }
-        }
-        this.pendingList = context.runtime.newArray();
-        return context.runtime.getNil();
+    @JRubyMethod(name = "add_file")
+    public IRubyObject addFile(ThreadContext context, IRubyObject name, IRubyObject options, Block block) {
+        RubyFileBuilderContext ctx = (RubyFileBuilderContext) cFileBuilderContext.newInstance(context, descriptorPool, name, options, Block.NULL_BLOCK);
+        ctx.instance_eval(context, block);
+        ctx.build(context);
+        return context.nil;
     }
 
-    protected RubyArray pendingList;
-    private RubyClass cDescriptor, cEnumDescriptor, cMessageBuilderContext, cEnumBuilderContext;
+    /*
+     * Used to trigger the build when using the deprecated syntax
+     */
+    protected void build(ThreadContext context) {
+        if (defaultFileBuilder != null) {
+            defaultFileBuilder.build(context);
+        }
+    }
+
+    private void ensureDefaultFileBuilder(ThreadContext context) {
+        if (defaultFileBuilder == null) {
+            this.defaultFileBuilder = (RubyFileBuilderContext) cFileBuilderContext.newInstance(context, descriptorPool, context.runtime.newString("ruby_default_file.proto"), Block.NULL_BLOCK);
+        }
+    }
+
+    private RubyClass cFileBuilderContext;
+    private RubyDescriptorPool descriptorPool;
+    private RubyFileBuilderContext defaultFileBuilder;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
index 2f7261a..a59596a 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
@@ -32,12 +32,14 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.DescriptorProtos;
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
 import org.jruby.*;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
 import org.jruby.runtime.Block;
+import org.jruby.runtime.Helpers;
 import org.jruby.runtime.ObjectAllocator;
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
@@ -58,6 +60,8 @@
         });
         cDescriptor.includeModule(runtime.getEnumerable());
         cDescriptor.defineAnnotatedMethods(RubyDescriptor.class);
+        cFieldDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
+        cOneofDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::OneofDescriptor");
     }
 
     public RubyDescriptor(Ruby runtime, RubyClass klazz) {
@@ -66,23 +70,6 @@
 
     /*
      * call-seq:
-     *     Descriptor.new => descriptor
-     *
-     * Creates a new, empty, message type descriptor. At a minimum, its name must be
-     * set before it is added to a pool. It cannot be used to create messages until
-     * it is added to a pool, after which it becomes immutable (as part of a
-     * finalization process).
-     */
-    @JRubyMethod
-    public IRubyObject initialize(ThreadContext context) {
-        this.builder = DescriptorProtos.DescriptorProto.newBuilder();
-        this.fieldDefMap = new HashMap<String, RubyFieldDescriptor>();
-        this.oneofDefs = new HashMap<IRubyObject, RubyOneofDescriptor>();
-        return this;
-    }
-
-    /*
-     * call-seq:
      *     Descriptor.name => name
      *
      * Returns the name of this message type as a fully-qualified string (e.g.,
@@ -90,38 +77,7 @@
      */
     @JRubyMethod(name = "name")
     public IRubyObject getName(ThreadContext context) {
-        return this.name;
-    }
-
-    /*
-     * call-seq:
-     *    Descriptor.name = name
-     *
-     * Assigns a name to this message type. The descriptor must not have been added
-     * to a pool yet.
-     */
-    @JRubyMethod(name = "name=")
-    public IRubyObject setName(ThreadContext context, IRubyObject name) {
-        this.name = name;
-        this.builder.setName(Utils.escapeIdentifier(this.name.asJavaString()));
-        return context.runtime.getNil();
-    }
-
-    /*
-     * call-seq:
-     *     Descriptor.add_field(field) => nil
-     *
-     * Adds the given FieldDescriptor to this message type. The descriptor must not
-     * have been added to a pool yet. Raises an exception if a field with the same
-     * name or number already exists. Sub-type references (e.g. for fields of type
-     * message) are not resolved at this point.
-     */
-    @JRubyMethod(name = "add_field")
-    public IRubyObject addField(ThreadContext context, IRubyObject obj) {
-        RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) obj;
-        this.fieldDefMap.put(fieldDef.getName(context).asJavaString(), fieldDef);
-        this.builder.addField(fieldDef.build());
-        return context.runtime.getNil();
+        return name;
     }
 
     /*
@@ -133,7 +89,7 @@
      */
     @JRubyMethod
     public IRubyObject lookup(ThreadContext context, IRubyObject fieldName) {
-        return this.fieldDefMap.get(fieldName.asJavaString());
+        return Helpers.nullToNil(fieldDescriptors.get(fieldName), context.nil);
     }
 
     /*
@@ -145,10 +101,7 @@
      */
     @JRubyMethod
     public IRubyObject msgclass(ThreadContext context) {
-        if (this.klazz == null) {
-            this.klazz = buildClassFromDescriptor(context);
-        }
-        return this.klazz;
+        return klazz;
     }
 
     /*
@@ -159,33 +112,22 @@
      */
     @JRubyMethod
     public IRubyObject each(ThreadContext context, Block block) {
-        for (Map.Entry<String, RubyFieldDescriptor> entry : fieldDefMap.entrySet()) {
+        for (Map.Entry<IRubyObject, RubyFieldDescriptor> entry : fieldDescriptors.entrySet()) {
             block.yield(context, entry.getValue());
         }
-        return context.runtime.getNil();
+        return context.nil;
     }
 
     /*
      * call-seq:
-     *     Descriptor.add_oneof(oneof) => nil
+     *    Descriptor.file_descriptor
      *
-     * Adds the given OneofDescriptor to this message type. This descriptor must not
-     * have been added to a pool yet. Raises an exception if a oneof with the same
-     * name already exists, or if any of the oneof's fields' names or numbers
-     * conflict with an existing field in this message type. All fields in the oneof
-     * are added to the message descriptor. Sub-type references (e.g. for fields of
-     * type message) are not resolved at this point.
+     * Returns the FileDescriptor object this message belongs to.
      */
-    @JRubyMethod(name = "add_oneof")
-    public IRubyObject addOneof(ThreadContext context, IRubyObject obj) {
-        RubyOneofDescriptor def = (RubyOneofDescriptor) obj;
-        builder.addOneofDecl(def.build(builder.getOneofDeclCount()));
-        for (RubyFieldDescriptor fieldDescriptor : def.getFields()) {
-            addField(context, fieldDescriptor);
-        }
-        oneofDefs.put(def.getName(context), def);
-        return context.runtime.getNil();
-    }
+     @JRubyMethod(name = "file_descriptor")
+     public IRubyObject getFileDescriptor(ThreadContext context) {
+        return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor);
+     }
 
     /*
      * call-seq:
@@ -196,10 +138,10 @@
      */
     @JRubyMethod(name = "each_oneof")
     public IRubyObject eachOneof(ThreadContext context, Block block) {
-        for (RubyOneofDescriptor oneofDescriptor : oneofDefs.values()) {
+        for (RubyOneofDescriptor oneofDescriptor : oneofDescriptors.values()) {
             block.yieldSpecific(context, oneofDescriptor);
         }
-        return context.runtime.getNil();
+        return context.nil;
     }
 
     /*
@@ -211,29 +153,44 @@
      */
     @JRubyMethod(name = "lookup_oneof")
     public IRubyObject lookupOneof(ThreadContext context, IRubyObject name) {
-        if (name instanceof RubySymbol) {
-            name = ((RubySymbol) name).id2name();
-        }
-        return oneofDefs.containsKey(name) ? oneofDefs.get(name) : context.runtime.getNil();
+        return Helpers.nullToNil(oneofDescriptors.get(Utils.symToString(name)), context.nil);
     }
 
-    public void setDescriptor(Descriptors.Descriptor descriptor) {
+    protected FieldDescriptor getField(String name) {
+        return descriptor.findFieldByName(name);
+    }
+
+    protected void setDescriptor(ThreadContext context, Descriptor descriptor, RubyDescriptorPool pool) {
+        Ruby runtime = context.runtime;
+        Map<FieldDescriptor, RubyFieldDescriptor> cache = new HashMap();
         this.descriptor = descriptor;
+
+        // Populate the field caches
+        fieldDescriptors = new HashMap<IRubyObject, RubyFieldDescriptor>();
+        oneofDescriptors = new HashMap<IRubyObject, RubyOneofDescriptor>();
+
+        for (FieldDescriptor fieldDescriptor : descriptor.getFields()) {
+            RubyFieldDescriptor fd = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
+            fd.setDescriptor(context, fieldDescriptor, pool);
+            fieldDescriptors.put(runtime.newString(fieldDescriptor.getName()), fd);
+            cache.put(fieldDescriptor, fd);
+        }
+
+        for (OneofDescriptor oneofDescriptor : descriptor.getRealOneofs()) {
+            RubyOneofDescriptor ood = (RubyOneofDescriptor) cOneofDescriptor.newInstance(context, Block.NULL_BLOCK);
+            ood.setDescriptor(context, oneofDescriptor, cache);
+            oneofDescriptors.put(runtime.newString(oneofDescriptor.getName()), ood);
+        }
+
+        // Make sure our class is built
+        this.klazz = buildClassFromDescriptor(context);
     }
 
-    public Descriptors.Descriptor getDescriptor() {
-        return this.descriptor;
+    protected void setName(IRubyObject name) {
+        this.name = name;
     }
 
-    public DescriptorProtos.DescriptorProto.Builder getBuilder() {
-        return builder;
-    }
-
-    public void setMapEntry(boolean isMapEntry) {
-        this.builder.setOptions(DescriptorProtos.MessageOptions.newBuilder().setMapEntry(isMapEntry));
-    }
-
-    private RubyModule buildClassFromDescriptor(ThreadContext context) {
+    private RubyClass buildClassFromDescriptor(ThreadContext context) {
         Ruby runtime = context.runtime;
 
         ObjectAllocator allocator = new ObjectAllocator() {
@@ -255,15 +212,12 @@
         return klass;
     }
 
-    protected RubyFieldDescriptor lookup(String fieldName) {
-        return fieldDefMap.get(Utils.unescapeIdentifier(fieldName));
-    }
+    private static RubyClass cFieldDescriptor;
+    private static RubyClass cOneofDescriptor;
 
+    private Descriptor descriptor;
     private IRubyObject name;
-    private RubyModule klazz;
-
-    private DescriptorProtos.DescriptorProto.Builder builder;
-    private Descriptors.Descriptor descriptor;
-    private Map<String, RubyFieldDescriptor> fieldDefMap;
-    private Map<IRubyObject, RubyOneofDescriptor> oneofDefs;
+    private Map<IRubyObject, RubyFieldDescriptor> fieldDescriptors;
+    private Map<IRubyObject, RubyOneofDescriptor> oneofDescriptors;
+    private RubyClass klazz;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
index 0345cb9..99a7f02 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
@@ -32,15 +32,20 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.DescriptorProtos;
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
 import org.jruby.*;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
 import org.jruby.runtime.*;
 import org.jruby.runtime.builtin.IRubyObject;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 @JRubyClass(name = "DescriptorPool")
@@ -56,42 +61,38 @@
 
         cDescriptorPool.defineAnnotatedMethods(RubyDescriptorPool.class);
         descriptorPool = (RubyDescriptorPool) cDescriptorPool.newInstance(runtime.getCurrentContext(), Block.NULL_BLOCK);
+        cBuilder = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::Builder");
+        cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor");
+        cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor");
     }
 
-    public RubyDescriptorPool(Ruby ruby, RubyClass klazz) {
-        super(ruby, klazz);
-    }
-
-    @JRubyMethod
-    public IRubyObject initialize(ThreadContext context) {
+    public RubyDescriptorPool(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
+        this.fileDescriptors = new ArrayList<>();
         this.symtab = new HashMap<IRubyObject, IRubyObject>();
-        this.cBuilder = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Builder");
-        this.builder = DescriptorProtos.FileDescriptorProto.newBuilder();
-        return this;
     }
 
     @JRubyMethod
     public IRubyObject build(ThreadContext context, Block block) {
-        RubyBuilder ctx = (RubyBuilder) cBuilder.newInstance(context, Block.NULL_BLOCK);
-        if (block.arity() == Arity.ONE_ARGUMENT) {
-            block.yield(context, ctx);
-        } else {
-            Binding binding = block.getBinding();
-            binding.setSelf(ctx);
-            block.yieldSpecific(context);
-        }
-        ctx.finalizeToPool(context, this);
-        buildFileDescriptor(context);
-        return context.runtime.getNil();
+        RubyBuilder ctx = (RubyBuilder) cBuilder.newInstance(context, this, Block.NULL_BLOCK);
+        ctx.instance_eval(context, block);
+        ctx.build(context); // Needs to be called to support the deprecated syntax
+        return context.nil;
     }
 
+    /*
+     * call-seq:
+     *     DescriptorPool.lookup(name) => descriptor
+     *
+     * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
+     * exists with the given name.
+     *
+     * This currently lazy loads the ruby descriptor objects as they are requested.
+     * This allows us to leave the heavy lifting to the java library
+     */
     @JRubyMethod
     public IRubyObject lookup(ThreadContext context, IRubyObject name) {
-        IRubyObject descriptor = this.symtab.get(name);
-        if (descriptor == null) {
-            return context.runtime.getNil();
-        }
-        return descriptor;
+        return Helpers.nullToNil(symtab.get(name), context.nil);
     }
 
     /*
@@ -108,62 +109,59 @@
         return descriptorPool;
     }
 
-    protected void addToSymtab(ThreadContext context, RubyDescriptor def) {
-        symtab.put(def.getName(context), def);
-        this.builder.addMessageType(def.getBuilder());
-    }
-
-    protected void addToSymtab(ThreadContext context, RubyEnumDescriptor def) {
-        symtab.put(def.getName(context), def);
-        this.builder.addEnumType(def.getBuilder());
-    }
-
-    private void buildFileDescriptor(ThreadContext context) {
-        Ruby runtime = context.runtime;
+    protected void registerFileDescriptor(ThreadContext context, FileDescriptorProto.Builder builder) {
+        final FileDescriptor fd;
         try {
-            this.builder.setSyntax("proto3");
-            final Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(
-                    this.builder.build(), new Descriptors.FileDescriptor[]{});
-
-            for (Descriptors.EnumDescriptor enumDescriptor : fileDescriptor.getEnumTypes()) {
-                String enumName = Utils.unescapeIdentifier(enumDescriptor.getName());
-                if (enumDescriptor.findValueByNumber(0) == null) {
-                    throw runtime.newTypeError("Enum definition " + enumName
-                            + " does not contain a value for '0'");
-                }
-                ((RubyEnumDescriptor) symtab.get(runtime.newString(enumName)))
-                        .setDescriptor(enumDescriptor);
-            }
-            for (Descriptors.Descriptor descriptor : fileDescriptor.getMessageTypes()) {
-                RubyDescriptor rubyDescriptor = ((RubyDescriptor)
-                        symtab.get(runtime.newString(Utils.unescapeIdentifier(descriptor.getName()))));
-                for (Descriptors.FieldDescriptor fieldDescriptor : descriptor.getFields()) {
-                    if (fieldDescriptor.isRequired()) {
-                        throw runtime.newTypeError("Required fields are unsupported in proto3");
-                    }
-                    RubyFieldDescriptor rubyFieldDescriptor = rubyDescriptor.lookup(fieldDescriptor.getName());
-                    rubyFieldDescriptor.setFieldDef(fieldDescriptor);
-                    if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
-                        RubyDescriptor subType = (RubyDescriptor) lookup(context,
-                                runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getMessageType().getName())));
-                        rubyFieldDescriptor.setSubType(subType);
-                    }
-                    if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.ENUM) {
-                        RubyEnumDescriptor subType = (RubyEnumDescriptor) lookup(context,
-                                runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getEnumType().getName())));
-                        rubyFieldDescriptor.setSubType(subType);
-                    }
-                }
-                rubyDescriptor.setDescriptor(descriptor);
-            }
-        } catch (Descriptors.DescriptorValidationException e) {
-            throw runtime.newRuntimeError(e.getMessage());
+            fd = FileDescriptor.buildFrom(builder.build(), existingFileDescriptors());
+        } catch (DescriptorValidationException e) {
+            throw context.runtime.newRuntimeError(e.getMessage());
         }
+
+        String packageName = fd.getPackage();
+        if (!packageName.isEmpty()) {
+            packageName = packageName + ".";
+        }
+
+        // Need to make sure enums are registered first in case anything references them
+        for (EnumDescriptor ed : fd.getEnumTypes()) registerEnumDescriptor(context, ed, packageName);
+        for (Descriptor message : fd.getMessageTypes()) registerDescriptor(context, message, packageName);
+
+        // Mark this as a loaded file
+        fileDescriptors.add(fd);
     }
 
+    private void registerDescriptor(ThreadContext context, Descriptor descriptor, String parentPath) {
+        String fullName = parentPath + descriptor.getName();
+        String fullPath = fullName + ".";
+        RubyString name = context.runtime.newString(fullName);
+
+        RubyDescriptor des = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
+        des.setName(name);
+        des.setDescriptor(context, descriptor, this);
+        symtab.put(name, des);
+
+        // Need to make sure enums are registered first in case anything references them
+        for (EnumDescriptor ed : descriptor.getEnumTypes()) registerEnumDescriptor(context, ed, fullPath);
+        for (Descriptor message : descriptor.getNestedTypes()) registerDescriptor(context, message, fullPath);
+    }
+
+    private void registerEnumDescriptor(ThreadContext context, EnumDescriptor descriptor, String parentPath) {
+        RubyString name = context.runtime.newString(parentPath + descriptor.getName());
+        RubyEnumDescriptor des = (RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK);
+        des.setName(name);
+        des.setDescriptor(context, descriptor);
+        symtab.put(name, des);
+    }
+
+    private FileDescriptor[] existingFileDescriptors() {
+        return fileDescriptors.toArray(new FileDescriptor[fileDescriptors.size()]);
+    }
+
+    private static RubyClass cBuilder;
+    private static RubyClass cDescriptor;
+    private static RubyClass cEnumDescriptor;
     private static RubyDescriptorPool descriptorPool;
 
-    private RubyClass cBuilder;
+    private List<FileDescriptor> fileDescriptors;
     private Map<IRubyObject, IRubyObject> symtab;
-    private DescriptorProtos.FileDescriptorProto.Builder builder;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
index 929d869..17525df 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
@@ -32,9 +32,7 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.Descriptors;
 import org.jruby.RubyModule;
-import org.jruby.RubyNumeric;
 import org.jruby.anno.JRubyMethod;
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
@@ -49,11 +47,8 @@
      */
     @JRubyMethod(meta = true)
     public static IRubyObject lookup(ThreadContext context, IRubyObject recv, IRubyObject number) {
-        RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
-        Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor();
-        Descriptors.EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number));
-        if (value == null) return context.runtime.getNil();
-        return context.runtime.newSymbol(value.getName());
+        RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
+        return rubyEnumDescriptor.numberToName(context, number);
     }
 
     /*
@@ -65,11 +60,8 @@
      */
     @JRubyMethod(meta = true)
     public static IRubyObject resolve(ThreadContext context, IRubyObject recv, IRubyObject name) {
-        RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
-        Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor();
-        Descriptors.EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString());
-        if (value == null) return context.runtime.getNil();
-        return context.runtime.newFixnum(value.getNumber());
+        RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
+        return rubyEnumDescriptor.nameToNumber(context, name);
     }
 
     /*
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java
index e4cac34..38d31ad 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java
@@ -32,9 +32,11 @@
 
 package com.google.protobuf.jruby;
 
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
 import org.jruby.Ruby;
 import org.jruby.RubyClass;
 import org.jruby.RubyModule;
+import org.jruby.RubyNumeric;
 import org.jruby.RubyObject;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
@@ -45,14 +47,14 @@
 @JRubyClass(name = "EnumBuilderContext")
 public class RubyEnumBuilderContext extends RubyObject {
     public static void createRubyEnumBuilderContext(Ruby runtime) {
-        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
-        RubyClass cMessageBuilderContext = protobuf.defineClassUnder("EnumBuilderContext", runtime.getObject(), new ObjectAllocator() {
+        RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal");
+        RubyClass cEnumBuilderContext = internal.defineClassUnder("EnumBuilderContext", runtime.getObject(), new ObjectAllocator() {
             @Override
             public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
                 return new RubyEnumBuilderContext(runtime, klazz);
             }
         });
-        cMessageBuilderContext.defineAnnotatedMethods(RubyEnumBuilderContext.class);
+        cEnumBuilderContext.defineAnnotatedMethods(RubyEnumBuilderContext.class);
     }
 
     public RubyEnumBuilderContext(Ruby ruby, RubyClass klazz) {
@@ -60,8 +62,12 @@
     }
 
     @JRubyMethod
-    public IRubyObject initialize(ThreadContext context, IRubyObject enumDescriptor) {
-        this.enumDescriptor = (RubyEnumDescriptor) enumDescriptor;
+    public IRubyObject initialize(ThreadContext context, IRubyObject fileBuilderContext, IRubyObject name) {
+        this.fileBuilderContext = (RubyFileBuilderContext) fileBuilderContext;
+        this.builder = this.fileBuilderContext.getNewEnumBuilder();
+        this.builder.setName(name.asJavaString());
+        this.builder.getOptionsBuilder().setAllowAlias(true);
+
         return this;
     }
 
@@ -74,9 +80,12 @@
      */
     @JRubyMethod
     public IRubyObject value(ThreadContext context, IRubyObject name, IRubyObject number) {
-        this.enumDescriptor.addValue(context, name, number);
-        return context.runtime.getNil();
+        this.builder.addValueBuilder()
+            .setName(name.asJavaString())
+            .setNumber(RubyNumeric.num2int(number));
+        return context.nil;
     }
 
-    private RubyEnumDescriptor enumDescriptor;
+    private EnumDescriptorProto.Builder builder;
+    private RubyFileBuilderContext fileBuilderContext;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
index 4df832d..e9c1f10 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
@@ -32,8 +32,9 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.DescriptorProtos;
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
 import org.jruby.Ruby;
 import org.jruby.RubyClass;
 import org.jruby.RubyModule;
@@ -66,20 +67,6 @@
 
     /*
      * call-seq:
-     *     EnumDescriptor.new => enum_descriptor
-     *
-     * Creates a new, empty, enum descriptor. Must be added to a pool before the
-     * enum type can be used. The enum type may only be modified prior to adding to
-     * a pool.
-     */
-    @JRubyMethod
-    public IRubyObject initialize(ThreadContext context) {
-        this.builder = DescriptorProtos.EnumDescriptorProto.newBuilder();
-        return this;
-    }
-
-    /*
-     * call-seq:
      *     EnumDescriptor.name => name
      *
      * Returns the name of this enum type.
@@ -91,37 +78,6 @@
 
     /*
      * call-seq:
-     *     EnumDescriptor.name = name
-     *
-     * Sets the name of this enum type. Cannot be called if the enum type has
-     * already been added to a pool.
-     */
-    @JRubyMethod(name = "name=")
-    public IRubyObject setName(ThreadContext context, IRubyObject name) {
-        this.name = name;
-        this.builder.setName(Utils.escapeIdentifier(name.asJavaString()));
-        return context.runtime.getNil();
-    }
-
-    /*
-     * call-seq:
-     *     EnumDescriptor.add_value(key, value)
-     *
-     * Adds a new key => value mapping to this enum type. Key must be given as a
-     * Ruby symbol. Cannot be called if the enum type has already been added to a
-     * pool. Will raise an exception if the key or value is already in use.
-     */
-    @JRubyMethod(name = "add_value")
-    public IRubyObject addValue(ThreadContext context, IRubyObject name, IRubyObject number) {
-        DescriptorProtos.EnumValueDescriptorProto.Builder valueBuilder = DescriptorProtos.EnumValueDescriptorProto.newBuilder();
-        valueBuilder.setName(name.asJavaString());
-        valueBuilder.setNumber(RubyNumeric.num2int(number));
-        this.builder.addValue(valueBuilder);
-        return context.runtime.getNil();
-    }
-
-    /*
-     * call-seq:
      *     EnumDescriptor.each(&block)
      *
      * Iterates over key => value mappings in this enum's definition, yielding to
@@ -130,11 +86,11 @@
     @JRubyMethod
     public IRubyObject each(ThreadContext context, Block block) {
         Ruby runtime = context.runtime;
-        for (Descriptors.EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) {
+        for (EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) {
             block.yield(context, runtime.newArray(runtime.newSymbol(enumValueDescriptor.getName()),
                     runtime.newFixnum(enumValueDescriptor.getNumber())));
         }
-        return runtime.getNil();
+        return context.nil;
     }
 
     /*
@@ -146,31 +102,63 @@
      */
     @JRubyMethod
     public IRubyObject enummodule(ThreadContext context) {
-        if (this.klazz == null) {
-            this.klazz = buildModuleFromDescriptor(context);
+        return module;
+    }
+
+    /*
+     * call-seq:
+     *    EnumDescriptor.file_descriptor
+     *
+     * Returns the FileDescriptor object this enum belongs to.
+     */
+    @JRubyMethod(name = "file_descriptor")
+    public IRubyObject getFileDescriptor(ThreadContext context) {
+       return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor);
+    }
+
+    public boolean isValidValue(ThreadContext context, IRubyObject value) {
+        EnumValueDescriptor enumValue;
+
+        if (Utils.isRubyNum(value)) {
+            enumValue = descriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
+        } else {
+            enumValue = descriptor.findValueByName(value.asJavaString());
         }
-        return this.klazz;
+
+        return enumValue != null;
     }
 
-    public void setDescriptor(Descriptors.EnumDescriptor descriptor) {
+    protected IRubyObject nameToNumber(ThreadContext context, IRubyObject name)  {
+        EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString());
+        return value == null ? context.nil : context.runtime.newFixnum(value.getNumber());
+    }
+
+    protected IRubyObject numberToName(ThreadContext context, IRubyObject number)  {
+        EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number));
+        return value == null ? context.nil : context.runtime.newSymbol(value.getName());
+    }
+
+    protected void setDescriptor(ThreadContext context, EnumDescriptor descriptor) {
         this.descriptor = descriptor;
+        this.module = buildModuleFromDescriptor(context);
     }
 
-    public Descriptors.EnumDescriptor getDescriptor() {
-        return this.descriptor;
-    }
-
-    public DescriptorProtos.EnumDescriptorProto.Builder getBuilder() {
-        return this.builder;
+    protected void setName(IRubyObject name) {
+        this.name = name;
     }
 
     private RubyModule buildModuleFromDescriptor(ThreadContext context) {
         Ruby runtime = context.runtime;
-        Utils.checkNameAvailability(context, name.asJavaString());
 
         RubyModule enumModule = RubyModule.newModule(runtime);
-        for (Descriptors.EnumValueDescriptor value : descriptor.getValues()) {
-            enumModule.defineConstant(value.getName(), runtime.newFixnum(value.getNumber()));
+        for (EnumValueDescriptor value : descriptor.getValues()) {
+            String name = value.getName();
+            // Make sure its a valid constant name before trying to create it
+            if (Character.isUpperCase(name.codePointAt(0))) {
+                enumModule.defineConstant(name, runtime.newFixnum(value.getNumber()));
+            } else {
+                runtime.getWarnings().warn("Enum value " + name + " does not start with an uppercase letter as is required for Ruby constants.");
+            }
         }
 
         enumModule.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
@@ -178,8 +166,8 @@
         return enumModule;
     }
 
+    private EnumDescriptor descriptor;
+    private EnumDescriptorProto.Builder builder;
     private IRubyObject name;
-    private RubyModule klazz;
-    private Descriptors.EnumDescriptor descriptor;
-    private DescriptorProtos.EnumDescriptorProto.Builder builder;
+    private RubyModule module;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
index f3c488b..8ac5e4c 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
@@ -32,8 +32,8 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.DescriptorProtos;
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
 import org.jruby.*;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
@@ -43,7 +43,7 @@
 
 @JRubyClass(name = "FieldDescriptor")
 public class RubyFieldDescriptor extends RubyObject {
-    public static void createRubyFileDescriptor(Ruby runtime) {
+    public static void createRubyFieldDescriptor(Ruby runtime) {
         RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
         RubyClass cFieldDescriptor = mProtobuf.defineClassUnder("FieldDescriptor", runtime.getObject(), new ObjectAllocator() {
             @Override
@@ -60,42 +60,30 @@
 
     /*
      * call-seq:
-     *     FieldDescriptor.new => field
+     *     FieldDescriptor.default => default
      *
-     * Returns a new field descriptor. Its name, type, etc. must be set before it is
-     * added to a message type.
+     * Returns this field's default, as a Ruby object, or nil if not yet set.
      */
-    @JRubyMethod
-    public IRubyObject initialize(ThreadContext context) {
-        builder = DescriptorProtos.FieldDescriptorProto.newBuilder();
-        return this;
-    }
+    // VALUE FieldDescriptor_default(VALUE _self) {
+    //   DEFINE_SELF(FieldDescriptor, self, _self);
+    //   return layout_get_default(self->fielddef);
+    // }
 
     /*
      * call-seq:
-     *     FieldDescriptor.label
+     *     FieldDescriptor.label => label
      *
-     * Return the label of this field.
+     * Returns this field's label (i.e., plurality), as a Ruby symbol.
+     *
+     * Valid field labels are:
+     *     :optional, :repeated
      */
     @JRubyMethod(name = "label")
     public IRubyObject getLabel(ThreadContext context) {
-        return this.label;
-    }
-
-    /*
-     * call-seq:
-     *     FieldDescriptor.label = label
-     *
-     * Sets the label on this field. Cannot be called if field is part of a message
-     * type already in a pool.
-     */
-    @JRubyMethod(name = "label=")
-    public IRubyObject setLabel(ThreadContext context, IRubyObject value) {
-        String labelName = value.asJavaString();
-        this.label = context.runtime.newSymbol(labelName.toLowerCase());
-        this.builder.setLabel(
-                DescriptorProtos.FieldDescriptorProto.Label.valueOf("LABEL_" + labelName.toUpperCase()));
-        return context.runtime.getNil();
+        if (label == null) {
+            calculateLabel(context);
+        }
+        return label;
     }
 
     /*
@@ -111,23 +99,19 @@
 
     /*
      * call-seq:
-     *     FieldDescriptor.name = name
+     *     FieldDescriptor.subtype => message_or_enum_descriptor
      *
-     * Sets the name of this field. Cannot be called once the containing message
-     * type, if any, is added to a pool.
+     * Returns the message or enum descriptor corresponding to this field's type if
+     * it is a message or enum field, respectively, or nil otherwise. Cannot be
+     * called *until* the containing message type is added to a pool (and thus
+     * resolved).
      */
-    @JRubyMethod(name = "name=")
-    public IRubyObject setName(ThreadContext context, IRubyObject value) {
-        String nameStr = value.asJavaString();
-        this.name = context.runtime.newString(nameStr);
-        this.builder.setName(Utils.escapeIdentifier(nameStr));
-        return context.runtime.getNil();
-    }
-
-
     @JRubyMethod(name = "subtype")
-    public IRubyObject getSubType(ThreadContext context) {
-        return subType;
+    public IRubyObject getSubtype(ThreadContext context) {
+        if (subtype == null) {
+            calculateSubtype(context);
+        }
+        return subtype;
     }
 
     /*
@@ -142,48 +126,42 @@
      */
     @JRubyMethod(name = "type")
     public IRubyObject getType(ThreadContext context) {
-        return Utils.fieldTypeToRuby(context, this.builder.getType());
-    }
-
-    /*
-     * call-seq:
-     *     FieldDescriptor.type = type
-     *
-     * Sets this field's type. Cannot be called if field is part of a message type
-     * already in a pool.
-     */
-    @JRubyMethod(name = "type=")
-    public IRubyObject setType(ThreadContext context, IRubyObject value) {
-        this.builder.setType(DescriptorProtos.FieldDescriptorProto.Type.valueOf("TYPE_" + value.asJavaString().toUpperCase()));
-        return context.runtime.getNil();
+        return Utils.fieldTypeToRuby(context, descriptor.getType());
     }
 
     /*
      * call-seq:
      *     FieldDescriptor.number => number
      *
-     * Returns this field's number, as a Ruby Integer, or nil if not yet set.
-     *
+     * Returns the tag number for this field.
      */
     @JRubyMethod(name = "number")
-    public IRubyObject getnumber(ThreadContext context) {
+    public IRubyObject getNumber(ThreadContext context) {
         return this.number;
     }
 
     /*
      * call-seq:
-     *     FieldDescriptor.number = number
+     *     FieldDescriptor.submsg_name => submsg_name
      *
-     * Sets the tag number for this field. Cannot be called if field is part of a
-     * message type already in a pool.
+     * Returns the name of the message or enum type corresponding to this field, if
+     * it is a message or enum field (respectively), or nil otherwise. This type
+     * name will be resolved within the context of the pool to which the containing
+     * message type is added.
      */
-    @JRubyMethod(name = "number=")
-    public IRubyObject setNumber(ThreadContext context, IRubyObject value) {
-        this.number = value;
-        this.builder.setNumber(RubyNumeric.num2int(value));
-        return context.runtime.getNil();
-    }
-
+    // VALUE FieldDescriptor_submsg_name(VALUE _self) {
+    //   DEFINE_SELF(FieldDescriptor, self, _self);
+    //   switch (upb_fielddef_type(self->fielddef)) {
+    //     case UPB_TYPE_ENUM:
+    //       return rb_str_new2(
+    //           upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
+    //     case UPB_TYPE_MESSAGE:
+    //       return rb_str_new2(
+    //           upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
+    //     default:
+    //       return Qnil;
+    //   }
+    // }
     /*
      * call-seq:
      *     FieldDescriptor.submsg_name = submsg_name
@@ -194,10 +172,21 @@
      * Cannot be called on field that are not of message or enum type, or on fields
      * that are part of a message type already added to a pool.
      */
-    @JRubyMethod(name = "submsg_name=")
-    public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) {
-        this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString()));
-        return context.runtime.getNil();
+    // @JRubyMethod(name = "submsg_name=")
+    // public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) {
+    //     this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString()));
+    //     return context.runtime.getNil();
+    // }
+
+    /*
+     * call-seq:
+     *     FieldDescriptor.clear(message)
+     *
+     * Clears the field from the message if it's set.
+     */
+    @JRubyMethod(name = "clear")
+    public IRubyObject clearValue(ThreadContext context, IRubyObject message) {
+        return ((RubyMessage) message).clearField(context, descriptor);
     }
 
     /*
@@ -208,16 +197,24 @@
      * exception if message is of the wrong type.
      */
     @JRubyMethod(name = "get")
-    public IRubyObject getValue(ThreadContext context, IRubyObject msgRb) {
-        RubyMessage message = (RubyMessage) msgRb;
-        if (message.getDescriptor() != fieldDef.getContainingType()) {
-            throw context.runtime.newTypeError("set method called on wrong message type");
-        }
-        return message.getField(context, fieldDef);
+    public IRubyObject getValue(ThreadContext context, IRubyObject message) {
+        return ((RubyMessage) message).getField(context, descriptor);
     }
 
     /*
      * call-seq:
+     *     FieldDescriptor.has?(message) => boolean
+     *
+     * Returns whether the value is set on the given message. Raises an
+     * exception when calling for fields that do not have presence.
+     */
+     @JRubyMethod(name = "has?")
+     public IRubyObject has(ThreadContext context, IRubyObject message) {
+        return ((RubyMessage) message).hasField(context, descriptor);
+     }
+
+    /*
+     * call-seq:
      *     FieldDescriptor.set(message, value)
      *
      * Sets the value corresponding to this field to the given value on the given
@@ -225,53 +222,46 @@
      * ordinary type-checks for field setting.
      */
     @JRubyMethod(name = "set")
-    public IRubyObject setValue(ThreadContext context, IRubyObject msgRb, IRubyObject value) {
-        RubyMessage message = (RubyMessage) msgRb;
-        if (message.getDescriptor() != fieldDef.getContainingType()) {
-            throw context.runtime.newTypeError("set method called on wrong message type");
+    public IRubyObject setValue(ThreadContext context, IRubyObject message, IRubyObject value) {
+        ((RubyMessage) message).setField(context, descriptor, value);
+        return context.nil;
+    }
+
+    protected void setDescriptor(ThreadContext context, FieldDescriptor descriptor, RubyDescriptorPool pool) {
+        this.descriptor = descriptor;
+        this.name = context.runtime.newString(descriptor.getName());
+        this.pool = pool;
+    }
+
+    private void calculateLabel(ThreadContext context) {
+        if (descriptor.isRepeated()) {
+            this.label = context.runtime.newSymbol("repeated");
+        } else if (descriptor.isOptional()) {
+            this.label = context.runtime.newSymbol("optional");
+        } else {
+            this.label = context.nil;
         }
-        message.setField(context, fieldDef, value);
-        return context.runtime.getNil();
     }
 
-    protected void setSubType(IRubyObject rubyDescriptor) {
-        this.subType = rubyDescriptor;
+    private void calculateSubtype(ThreadContext context) {
+        FieldDescriptor.Type fdType = descriptor.getType();
+        if (fdType == FieldDescriptor.Type.MESSAGE) {
+            RubyString messageName = context.runtime.newString(descriptor.getMessageType().getFullName());
+            this.subtype = pool.lookup(context, messageName);
+        } else if (fdType == FieldDescriptor.Type.ENUM) {
+            RubyString enumName = context.runtime.newString(descriptor.getEnumType().getFullName());
+            this.subtype = pool.lookup(context, enumName);
+        } else {
+            this.subtype = context.nil;
+        }
     }
 
-    protected void setFieldDef(Descriptors.FieldDescriptor fieldDescriptor) {
-        this.fieldDef = fieldDescriptor;
-    }
+    private static final String DOT = ".";
 
-    protected void setOneofName(IRubyObject name) {
-        oneofName = name;
-    }
-
-    protected void setOneofIndex(int index) {
-        hasOneofIndex = true;
-        oneofIndex = index;
-    }
-
-    protected IRubyObject getOneofName() {
-        return oneofName;
-    }
-
-    protected Descriptors.FieldDescriptor getFieldDef() {
-        return fieldDef;
-    }
-
-    protected DescriptorProtos.FieldDescriptorProto build() {
-        if (hasOneofIndex)
-            builder.setOneofIndex(oneofIndex);
-        return this.builder.build();
-    }
-
-    private DescriptorProtos.FieldDescriptorProto.Builder builder;
+    private FieldDescriptor descriptor;
     private IRubyObject name;
     private IRubyObject label;
     private IRubyObject number;
-    private IRubyObject subType;
-    private IRubyObject oneofName;
-    private Descriptors.FieldDescriptor fieldDef;
-    private int oneofIndex;
-    private boolean hasOneofIndex = false;
+    private IRubyObject subtype;
+    private RubyDescriptorPool pool;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java
new file mode 100644
index 0000000..00ce3f2
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java
@@ -0,0 +1,348 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc.  All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProtoOrBuilder;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyHash;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.TreeMap;
+
+@JRubyClass(name = "FileBuilderContext")
+public class RubyFileBuilderContext extends RubyObject {
+    public static void createRubyFileBuilderContext(Ruby runtime) {
+        RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal");
+        RubyClass cFileBuilderContext = internal.defineClassUnder("FileBuilderContext", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyFileBuilderContext(runtime, klazz);
+            }
+        });
+        cFileBuilderContext.defineAnnotatedMethods(RubyFileBuilderContext.class);
+
+        cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor");
+        cEnumBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::EnumBuilderContext");
+        cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor");
+        cMessageBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::MessageBuilderContext");
+    }
+
+    public RubyFileBuilderContext(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
+    }
+
+    /*
+     * call-seq:
+     *     FileBuilderContext.new(descriptor_pool, name, options = nil) => context
+     *
+     * Create a new file builder context for the given file descriptor and
+     * builder context. This class is intended to serve as a DSL context to be used
+     * with #instance_eval.
+     */
+    @JRubyMethod(required = 2, optional = 1)
+    public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
+        this.descriptorPool = (RubyDescriptorPool) args[0];
+        this.builder = FileDescriptorProto.newBuilder();
+        this.builder.setName(args[1].asJavaString());
+        this.builder.setSyntax("proto3");
+
+        if (args.length > 2) {
+            RubyHash options = (RubyHash) args[2];
+            IRubyObject syntax = options.fastARef(context.runtime.newSymbol("syntax"));
+
+            if (syntax != null) {
+                String syntaxStr = syntax.asJavaString();
+                this.builder.setSyntax(syntaxStr);
+                this.proto3 = syntaxStr.equals("proto3");
+            }
+        }
+
+        return this;
+    }
+
+    /*
+     * call-seq:
+     *     FileBuilderContext.add_enum(name, &block)
+     *
+     * Creates a new, empty enum descriptor with the given name, and invokes the
+     * block in the context of an EnumBuilderContext on that descriptor. The block
+     * can then call EnumBuilderContext#add_value to define the enum values.
+     *
+     * This is the recommended, idiomatic way to build enum definitions.
+     */
+    @JRubyMethod(name = "add_enum")
+    public IRubyObject addEnum(ThreadContext context, IRubyObject name, Block block) {
+        RubyObject ctx = (RubyObject) cEnumBuilderContext.newInstance(context, this, name, Block.NULL_BLOCK);
+        ctx.instance_eval(context, block);
+
+        return context.nil;
+    }
+
+    /*
+     * call-seq:
+     *     FileBuilderContext.add_message(name, &block)
+     *
+     * Creates a new, empty descriptor with the given name, and invokes the block in
+     * the context of a MessageBuilderContext on that descriptor. The block can then
+     * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
+     * methods to define the message fields.
+     *
+     * This is the recommended, idiomatic way to build message definitions.
+     */
+    @JRubyMethod(name = "add_message")
+    public IRubyObject addMessage(ThreadContext context, IRubyObject name, Block block) {
+        RubyObject ctx = (RubyObject) cMessageBuilderContext.newInstance(context, this, name, Block.NULL_BLOCK);
+        ctx.instance_eval(context, block);
+
+        return context.nil;
+    }
+
+    protected void build(ThreadContext context) {
+        Ruby runtime = context.runtime;
+        List<DescriptorProto.Builder> messageBuilderList = builder.getMessageTypeBuilderList();
+        List<EnumDescriptorProto.Builder> enumBuilderList = builder.getEnumTypeBuilderList();
+
+        // Get the package name from defined names
+        String packageName = getPackageName(messageBuilderList, enumBuilderList);
+
+        if (!packageName.isEmpty()) {
+            builder.setPackage(packageName);
+        }
+
+        // Make an index of the message builders so we can easily nest them
+        TreeMap<String, DescriptorProto.Builder> messageBuilderMap = new TreeMap();
+        for (DescriptorProto.Builder messageBuilder : messageBuilderList) {
+            messageBuilderMap.put(messageBuilder.getName(), messageBuilder);
+        }
+
+        // Make an index of the enum builders so we can easily nest them
+        HashMap<String, EnumDescriptorProto.Builder> enumBuilderMap = new HashMap();
+        for (EnumDescriptorProto.Builder enumBuilder : enumBuilderList) {
+            enumBuilderMap.put("." + enumBuilder.getName(), enumBuilder);
+        }
+
+        // Rename and properly nest messages and create associated ruby objects
+        int packageNameLength = packageName.length();
+        int currentMessageIndex = 0;
+        int currentEnumIndex = 0;
+
+        // Need to get a static list because we are potentially deleting some of them from the collection
+        DescriptorProto.Builder[] messageBuilders = new DescriptorProto.Builder[messageBuilderList.size()];
+        messageBuilderList.toArray(messageBuilders);
+        EnumDescriptorProto.Builder[] enumBuilders = new EnumDescriptorProto.Builder[enumBuilderList.size()];
+        enumBuilderList.toArray(enumBuilders);
+
+        for (EnumDescriptorProto.Builder enumBuilder : enumBuilders) {
+            String name = enumBuilder.getName();
+            int lastDot = name.lastIndexOf('.');
+
+            if (lastDot > packageNameLength) {
+                String parentName = name.substring(0, lastDot);
+                String shortName = name.substring(lastDot + 1);
+
+                enumBuilder.setName(shortName);
+                messageBuilderMap.get(parentName).addEnumType(enumBuilder);
+
+                builder.removeEnumType(currentEnumIndex);
+
+            } else {
+                if (packageNameLength > 0) {
+                    // Remove the package name
+                    String shortName = name.substring(packageNameLength + 1);
+                    enumBuilder.setName(shortName);
+                }
+
+                currentEnumIndex++;
+            }
+
+            // Ensure we have a default value if using proto3 syntax
+            if (proto3) {
+                boolean foundDefault = false;
+                for (EnumValueDescriptorProtoOrBuilder enumValue : enumBuilder.getValueOrBuilderList()) {
+                    if (enumValue.getNumber() == 0) {
+                        foundDefault = true;
+                        break;
+                    }
+                }
+
+                if (!foundDefault) {
+                    throw Utils.createTypeError(context, "Enum definition " + enumBuilder.getName() + " does not contain a value for '0'");
+                }
+            }
+        }
+
+        // Wipe out top level message builders so we can insert only the ones that should be there
+        builder.clearMessageType();
+
+        /*
+         * This block is done in this order because calling
+         * `addNestedType` and `addMessageType` makes a copy of the builder
+         * so the objects that our maps point to are no longer the objects
+         * that are being used to build the descriptions.
+         */
+        for (HashMap.Entry<String, DescriptorProto.Builder> entry : messageBuilderMap.descendingMap().entrySet()) {
+            DescriptorProto.Builder messageBuilder = entry.getValue();
+
+            // Rewrite any enum defaults needed
+            for(FieldDescriptorProto.Builder field : messageBuilder.getFieldBuilderList()) {
+                String typeName = field.getTypeName();
+
+                if (typeName == null || !field.hasDefaultValue()) continue;
+
+                EnumDescriptorProto.Builder enumBuilder = enumBuilderMap.get(typeName);
+
+                if (enumBuilder == null) continue;
+
+                int defaultValue = Integer.parseInt(field.getDefaultValue());
+
+                for (EnumValueDescriptorProtoOrBuilder enumValue : enumBuilder.getValueOrBuilderList()) {
+                    if (enumValue.getNumber() == defaultValue) {
+                        field.setDefaultValue(enumValue.getName());
+                        break;
+                    }
+                }
+            }
+
+            // Turn Foo.Bar.Baz into a correctly nested structure with the correct name
+            String name = messageBuilder.getName();
+            int lastDot = name.lastIndexOf('.');
+
+            if (lastDot > packageNameLength) {
+                String parentName = name.substring(0, lastDot);
+                String shortName = name.substring(lastDot + 1);
+                messageBuilder.setName(shortName);
+                messageBuilderMap.get(parentName).addNestedType(messageBuilder);
+
+            } else {
+                if (packageNameLength > 0) {
+                    // Remove the package name
+                    messageBuilder.setName(name.substring(packageNameLength + 1));
+                }
+
+                // Add back in top level message definitions
+                builder.addMessageType(messageBuilder);
+
+                currentMessageIndex++;
+            }
+        }
+
+        descriptorPool.registerFileDescriptor(context, builder);
+    }
+
+    protected EnumDescriptorProto.Builder getNewEnumBuilder() {
+        return builder.addEnumTypeBuilder();
+    }
+
+    protected DescriptorProto.Builder getNewMessageBuilder() {
+        return builder.addMessageTypeBuilder();
+    }
+
+    protected boolean isProto3() {
+        return proto3;
+    }
+
+    private String getPackageName(List<DescriptorProto.Builder> messages, List<EnumDescriptorProto.Builder> enums) {
+        String shortest = null;
+        String longest = null;
+
+        /*
+         * The >= in the longest string comparisons below makes it so we replace
+         * the name in case all the names are the same length. This makes it so
+         * that the shortest and longest aren't the same name to prevent
+         * finding a "package" that isn't correct
+         */
+
+        for (DescriptorProto.Builder message : messages) {
+            String name = message.getName();
+            int nameLength = name.length();
+            if (shortest == null) {
+                shortest = name;
+                longest = name;
+            } else if (nameLength < shortest.length()) {
+                shortest = name;
+            } else if (nameLength >= longest.length()) {
+                longest = name;
+            }
+        }
+
+        for (EnumDescriptorProto.Builder item : enums) {
+            String name = item.getName();
+            int nameLength = name.length();
+            if (shortest == null) {
+                shortest = name;
+                longest = name;
+            } else if (nameLength < shortest.length()) {
+                shortest = name;
+            } else if (nameLength >= longest.length()) {
+                longest = name;
+            }
+        }
+
+        if (shortest == null) {
+            return "";
+        }
+
+        int lastCommonDot = 0;
+        for (int i = 0; i < shortest.length(); i++) {
+            char nextChar = shortest.charAt(i);
+            if (nextChar != longest.charAt(i)) break;
+            if (nextChar == '.') lastCommonDot = i;
+        }
+
+        return shortest.substring(0, lastCommonDot);
+    }
+
+    private static RubyClass cDescriptor;
+    private static RubyClass cEnumBuilderContext;
+    private static RubyClass cEnumDescriptor;
+    private static RubyClass cMessageBuilderContext;
+
+    private FileDescriptorProto.Builder builder;
+    private RubyDescriptorPool descriptorPool;
+    private boolean proto3 = true;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java
new file mode 100644
index 0000000..b3e1816
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java
@@ -0,0 +1,106 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc.  All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor.Syntax.*;
+import com.google.protobuf.Descriptors.GenericDescriptor;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "FileDescriptor")
+public class RubyFileDescriptor extends RubyObject {
+    public static void createRubyFileDescriptor(Ruby runtime) {
+        RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+        cFileDescriptor = mProtobuf.defineClassUnder("FileDescriptor", runtime.getObject(), new ObjectAllocator() {
+            @Override
+            public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+                return new RubyFileDescriptor(runtime, klazz);
+            }
+        });
+        cFileDescriptor.defineAnnotatedMethods(RubyFileDescriptor.class);
+    }
+
+    public static RubyFileDescriptor getRubyFileDescriptor(ThreadContext context, GenericDescriptor descriptor) {
+        RubyFileDescriptor rfd = (RubyFileDescriptor) cFileDescriptor.newInstance(context, Block.NULL_BLOCK);
+        rfd.fileDescriptor = descriptor.getFile();
+        return rfd;
+    }
+
+    public RubyFileDescriptor(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
+    }
+
+    /*
+     * call-seq:
+     *     FileDescriptor.name => name
+     *
+     * Returns the name of the file.
+     */
+    @JRubyMethod(name = "name")
+    public IRubyObject getName(ThreadContext context) {
+        String name = fileDescriptor.getName();
+        return name == null ? context.nil : context.runtime.newString(name);
+    }
+
+    /*
+     * call-seq:
+     *     FileDescriptor.syntax => syntax
+     *
+     * Returns this file descriptors syntax.
+     *
+     * Valid syntax versions are:
+     *     :proto2 or :proto3.
+     */
+    @JRubyMethod(name = "syntax")
+    public IRubyObject getSyntax(ThreadContext context) {
+        switch (fileDescriptor.getSyntax()) {
+            case PROTO2:
+                return context.runtime.newSymbol("proto2");
+            case PROTO3:
+                return context.runtime.newSymbol("proto3");
+            default:
+                return context.nil;
+        }
+    }
+
+    private static RubyClass cFileDescriptor;
+
+    private FileDescriptor fileDescriptor;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
index 8973862..087f1cb 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
@@ -32,19 +32,19 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.DynamicMessage;
-import com.google.protobuf.MapEntry;
 import org.jruby.*;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
 import org.jruby.internal.runtime.methods.DynamicMethod;
 import org.jruby.runtime.Block;
+import org.jruby.runtime.Helpers;
 import org.jruby.runtime.ObjectAllocator;
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
-import org.jruby.util.ByteList;
 
+import java.nio.ByteBuffer;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -100,7 +100,6 @@
      * references to underlying objects will be shared if the value type is a
      * message type.
      */
-
     @JRubyMethod(required = 2, optional = 2)
     public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
         this.table = new HashMap<IRubyObject, IRubyObject>();
@@ -108,13 +107,15 @@
         this.valueType = Utils.rubyToFieldType(args[1]);
 
         switch(keyType) {
+            case STRING:
+            case BYTES:
+                this.keyTypeIsString = true;
+                break;
             case INT32:
             case INT64:
             case UINT32:
             case UINT64:
             case BOOL:
-            case STRING:
-            case BYTES:
                 // These are OK.
                 break;
             default:
@@ -130,8 +131,6 @@
             this.valueTypeClass = context.runtime.getNilClass();
         }
 
-        // Table value type is always UINT64: this ensures enough space to store the
-        // native_slot value.
         if (args.length > initValueArg) {
             mergeIntoSelf(context, args[initValueArg]);
         }
@@ -148,10 +147,19 @@
      */
     @JRubyMethod(name = "[]=")
     public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) {
-        key = Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass);
-        value = Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass);
+        checkFrozen();
+
+        /*
+         * String types for keys return a different error than
+         * other types for keys, so deal with them specifically first
+         */
+        if (keyTypeIsString && !(key instanceof RubySymbol || key instanceof RubyString)) {
+            throw context.runtime.newTypeError("Expected string for map key");
+        }
+        key = Utils.checkType(context, keyType, "key", key, (RubyModule) valueTypeClass);
+        value = Utils.checkType(context, valueType, "value", value, (RubyModule) valueTypeClass);
         IRubyObject symbol;
-        if (valueType == Descriptors.FieldDescriptor.Type.ENUM &&
+        if (valueType == FieldDescriptor.Type.ENUM &&
                 Utils.isRubyNum(value) &&
                 ! (symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) {
             value = symbol;
@@ -169,9 +177,8 @@
      */
     @JRubyMethod(name = "[]")
     public IRubyObject index(ThreadContext context, IRubyObject key) {
-        if (table.containsKey(key))
-            return this.table.get(key);
-        return context.runtime.getNil();
+        key = Utils.symToString(key);
+        return Helpers.nullToNil(table.get(key), context.nil);
     }
 
     /*
@@ -190,7 +197,7 @@
     @JRubyMethod(name = "==")
     public IRubyObject eq(ThreadContext context, IRubyObject _other) {
         if (_other instanceof RubyHash)
-            return toHash(context).op_equal(context, _other);
+            return singleLevelHash(context).op_equal(context, _other);
         RubyMap other = (RubyMap) _other;
         if (this == other) return context.runtime.getTrue();
         if (!typeCompatible(other) || this.table.size() != other.table.size())
@@ -214,7 +221,7 @@
      */
     @JRubyMethod
     public IRubyObject inspect() {
-        return toHash(getRuntime().getCurrentContext()).inspect();
+        return singleLevelHash(getRuntime().getCurrentContext()).inspect();
     }
 
     /*
@@ -231,7 +238,7 @@
                 digest.update((byte) key.hashCode());
                 digest.update((byte) table.get(key).hashCode());
             }
-            return context.runtime.newString(new ByteList(digest.digest()));
+            return context.runtime.newFixnum(ByteBuffer.wrap(digest.digest()).getLong());
         } catch (NoSuchAlgorithmException ignore) {
             return context.runtime.newFixnum(System.identityHashCode(table));
         }
@@ -267,8 +274,9 @@
      */
     @JRubyMethod
     public IRubyObject clear(ThreadContext context) {
+        checkFrozen();
         table.clear();
-        return context.runtime.getNil();
+        return context.nil;
     }
 
     /*
@@ -284,7 +292,7 @@
         for (IRubyObject key : table.keySet()) {
             block.yieldSpecific(context, key, table.get(key));
         }
-        return context.runtime.getNil();
+        return context.nil;
     }
 
     /*
@@ -296,6 +304,7 @@
      */
     @JRubyMethod
     public IRubyObject delete(ThreadContext context, IRubyObject key) {
+        checkFrozen();
         return table.remove(key);
     }
 
@@ -340,7 +349,20 @@
 
     @JRubyMethod(name = "to_h")
     public RubyHash toHash(ThreadContext context) {
-        return RubyHash.newHash(context.runtime, table, context.runtime.getNil());
+        Map<IRubyObject, IRubyObject> mapForHash = new HashMap();
+
+        table.forEach((key, value) -> {
+            if (!value.isNil()) {
+                if (value.respondsTo("to_h")) {
+                    value = Helpers.invoke(context, value, "to_h");
+                } else if (value.respondsTo("to_a")) {
+                    value = Helpers.invoke(context, value, "to_a");
+                }
+                mapForHash.put(key, value);
+            }
+        });
+
+        return RubyHash.newHash(context.runtime, mapForHash, context.nil);
     }
 
     // Used by Google::Protobuf.deep_copy but not exposed directly.
@@ -361,16 +383,16 @@
         return newMap;
     }
 
-    protected List<DynamicMessage> build(ThreadContext context, RubyDescriptor descriptor) {
+    protected List<DynamicMessage> build(ThreadContext context, RubyDescriptor descriptor, int depth) {
         List<DynamicMessage> list = new ArrayList<DynamicMessage>();
         RubyClass rubyClass = (RubyClass) descriptor.msgclass(context);
-        Descriptors.FieldDescriptor keyField = descriptor.lookup("key").getFieldDef();
-        Descriptors.FieldDescriptor valueField = descriptor.lookup("value").getFieldDef();
+        FieldDescriptor keyField = descriptor.getField("key");
+        FieldDescriptor valueField = descriptor.getField("value");
         for (IRubyObject key : table.keySet()) {
             RubyMessage mapMessage = (RubyMessage) rubyClass.newInstance(context, Block.NULL_BLOCK);
             mapMessage.setField(context, keyField, key);
             mapMessage.setField(context, valueField, table.get(key));
-            list.add(mapMessage.build(context));
+            list.add(mapMessage.build(context, depth + 1));
         }
         return list;
     }
@@ -380,13 +402,16 @@
             ((RubyHash) hashmap).visitAll(new RubyHash.Visitor() {
                 @Override
                 public void visit(IRubyObject key, IRubyObject val) {
+                    if (val instanceof RubyHash && !valueTypeClass.isNil()) {
+                        val = ((RubyClass) valueTypeClass).newInstance(context, val, Block.NULL_BLOCK);
+                    }
                     indexSet(context, key, val);
                 }
             });
         } else if (hashmap instanceof RubyMap) {
             RubyMap other = (RubyMap) hashmap;
             if (!typeCompatible(other)) {
-                throw context.runtime.newTypeError("Attempt to merge Map with mismatching types");
+                throw Utils.createTypeError(context, "Attempt to merge Map with mismatching types");
             }
         } else {
             throw context.runtime.newTypeError("Unknown type merging into Map");
@@ -417,7 +442,15 @@
         return newMap;
     }
 
-    private boolean needTypeclass(Descriptors.FieldDescriptor.Type type) {
+    /*
+     * toHash calls toHash on values, for some camparisons we only need
+     * a hash with the original objects still as values
+     */
+    private RubyHash singleLevelHash(ThreadContext context) {
+        return RubyHash.newHash(context.runtime, table, context.nil);
+    }
+
+    private boolean needTypeclass(FieldDescriptor.Type type) {
         switch(type) {
             case MESSAGE:
             case ENUM:
@@ -427,8 +460,9 @@
         }
     }
 
-    private Descriptors.FieldDescriptor.Type keyType;
-    private Descriptors.FieldDescriptor.Type valueType;
+    private FieldDescriptor.Type keyType;
+    private FieldDescriptor.Type valueType;
     private IRubyObject valueTypeClass;
     private Map<IRubyObject, IRubyObject> table;
+    private boolean keyTypeIsString = false;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
index 774db65..a905c9a 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -32,24 +32,45 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.*;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Message;
+import com.google.protobuf.UnknownFieldSet;
+import com.google.protobuf.util.JsonFormat;
 import org.jruby.*;
 import org.jruby.anno.JRubyMethod;
+import org.jruby.exceptions.RaiseException;
 import org.jruby.runtime.Block;
 import org.jruby.runtime.Helpers;
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
 import org.jruby.util.ByteList;
 
+import java.nio.ByteBuffer;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 public class RubyMessage extends RubyObject {
-    public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descriptor) {
-        super(ruby, klazz);
+    public RubyMessage(Ruby runtime, RubyClass klazz, Descriptor descriptor) {
+        super(runtime, klazz);
+
         this.descriptor = descriptor;
+        this.cRepeatedField = (RubyClass) runtime.getClassFromPath("Google::Protobuf::RepeatedField");
+        this.cMap = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Map");
+        this.builder = DynamicMessage.newBuilder(descriptor);
+        this.fields = new HashMap<FieldDescriptor, IRubyObject>();
+        this.oneofCases = new HashMap<OneofDescriptor, FieldDescriptor>();
+        this.proto3 = descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3;
     }
 
     /*
@@ -67,13 +88,6 @@
     @JRubyMethod(optional = 1)
     public IRubyObject initialize(final ThreadContext context, IRubyObject[] args) {
         final Ruby runtime = context.runtime;
-        this.cRepeatedField = (RubyClass) runtime.getClassFromPath("Google::Protobuf::RepeatedField");
-        this.cMap = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Map");
-        this.builder = DynamicMessage.newBuilder(this.descriptor);
-        this.repeatedFields = new HashMap<Descriptors.FieldDescriptor, RubyRepeatedField>();
-        this.maps = new HashMap<Descriptors.FieldDescriptor, RubyMap>();
-        this.fields = new HashMap<Descriptors.FieldDescriptor, IRubyObject>();
-        this.oneofCases = new HashMap<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor>();
         if (args.length == 1) {
             if (!(args[0] instanceof RubyHash)) {
                 throw runtime.newArgumentError("expected Hash arguments.");
@@ -84,35 +98,36 @@
                 public void visit(IRubyObject key, IRubyObject value) {
                     if (!(key instanceof RubySymbol) && !(key instanceof RubyString))
                         throw runtime.newTypeError("Expected string or symbols as hash keys in initialization map.");
-                    final Descriptors.FieldDescriptor fieldDescriptor = findField(context, key);
+                    final FieldDescriptor fieldDescriptor = findField(context, key, ignoreUnknownFieldsOnInit);
 
-                    if (value.isNil()) return;
+                    if (value == null || value.isNil()) return;
 
                     if (Utils.isMapEntry(fieldDescriptor)) {
                         if (!(value instanceof RubyHash))
-                            throw runtime.newArgumentError("Expected Hash object as initializer value for map field '" +  key.asJavaString() + "'.");
+                            throw runtime.newArgumentError("Expected Hash object as initializer value for map field '" +  key.asJavaString() + "' (given " + value.getMetaClass() + ").");
 
                         final RubyMap map = newMapForField(context, fieldDescriptor);
                         map.mergeIntoSelf(context, value);
-                        maps.put(fieldDescriptor, map);
+                        fields.put(fieldDescriptor, map);
                     } else if (fieldDescriptor.isRepeated()) {
                         if (!(value instanceof RubyArray))
-                            throw runtime.newArgumentError("Expected array as initializer value for repeated field '" +  key.asJavaString() + "'.");
-                        RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, value);
-                        addRepeatedField(fieldDescriptor, repeatedField);
+                            throw runtime.newArgumentError("Expected array as initializer value for repeated field '" +  key.asJavaString() + "' (given " + value.getMetaClass() + ").");
+                        fields.put(fieldDescriptor, rubyToRepeatedField(context, fieldDescriptor, value));
                     } else {
-                        Descriptors.OneofDescriptor oneof = fieldDescriptor.getContainingOneof();
+                        OneofDescriptor oneof = fieldDescriptor.getContainingOneof();
                         if (oneof != null) {
                             oneofCases.put(oneof, fieldDescriptor);
                         }
 
-                        if (value instanceof RubyHash && fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
+                        if (value instanceof RubyHash && fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE) {
                             RubyDescriptor descriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
                             RubyClass typeClass = (RubyClass) descriptor.msgclass(context);
                             value = (IRubyObject) typeClass.newInstance(context, value, Block.NULL_BLOCK);
+                            fields.put(fieldDescriptor, value);
+                        } else {
+                            indexSet(context, key, value);
                         }
 
-                        fields.put(fieldDescriptor, value);
                     }
                 }
             });
@@ -129,8 +144,8 @@
      */
     @JRubyMethod(name = "[]=")
     public IRubyObject indexSet(ThreadContext context, IRubyObject fieldName, IRubyObject value) {
-        Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName);
-        return setField(context, fieldDescriptor, value);
+        FieldDescriptor fieldDescriptor = findField(context, fieldName);
+        return setFieldInternal(context, fieldDescriptor, value);
     }
 
     /*
@@ -142,8 +157,8 @@
      */
     @JRubyMethod(name = "[]")
     public IRubyObject index(ThreadContext context, IRubyObject fieldName) {
-        Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName);
-        return getField(context, fieldDescriptor);
+        FieldDescriptor fieldDescriptor = findField(context, fieldName);
+        return getFieldInternal(context, fieldDescriptor);
     }
 
     /*
@@ -154,16 +169,37 @@
      * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
      * field's value is represented according to its own #inspect method.
      */
-    @JRubyMethod
+    @JRubyMethod(name = {"inspect", "to_s"})
     public IRubyObject inspect() {
+        ThreadContext context = getRuntime().getCurrentContext();
         String cname = metaClass.getName();
+        String colon = ": ";
+        String comma = ", ";
         StringBuilder sb = new StringBuilder("<");
-        sb.append(cname);
-        sb.append(": ");
-        sb.append(this.layoutInspect());
+        boolean addComma = false;
+
+        sb.append(cname).append(colon);
+
+        for (FieldDescriptor fd : descriptor.getFields()) {
+            if (addComma) {
+                sb.append(comma);
+            } else {
+                addComma = true;
+            }
+
+            sb.append(fd.getName()).append(colon);
+
+            IRubyObject value = getFieldInternal(context, fd);
+            if (value instanceof RubyBoolean) {
+                // Booleans don't implement internal "inspect" methods so have to call handle them manually
+                sb.append(value.isTrue() ? "true" : "false");
+            } else {
+                sb.append(value.inspect());
+            }
+        }
         sb.append(">");
 
-        return getRuntime().newString(sb.toString());
+        return context.runtime.newString(sb.toString());
     }
 
     /*
@@ -176,16 +212,10 @@
     public IRubyObject hash(ThreadContext context) {
         try {
             MessageDigest digest = MessageDigest.getInstance("SHA-256");
-            for (RubyMap map : maps.values()) {
-                digest.update((byte) map.hashCode());
+            for (FieldDescriptor fd : descriptor.getFields()) {
+                digest.update((byte) getFieldInternal(context, fd).hashCode());
             }
-            for (RubyRepeatedField repeatedField : repeatedFields.values()) {
-                digest.update((byte) repeatedFields.hashCode());
-            }
-            for (IRubyObject field : fields.values()) {
-                digest.update((byte) field.hashCode());
-            }
-            return context.runtime.newString(new ByteList(digest.digest()));
+            return context.runtime.newFixnum(ByteBuffer.wrap(digest.digest()).getLong());
         } catch (NoSuchAlgorithmException ignore) {
             return context.runtime.newFixnum(System.identityHashCode(this));
         }
@@ -200,7 +230,7 @@
      * method's semantics (a more efficient comparison may actually be done if the
      * field is of a primitive type).
      */
-    @JRubyMethod(name = "==")
+    @JRubyMethod(name = {"==", "eql?"})
     public IRubyObject eq(ThreadContext context, IRubyObject other) {
         Ruby runtime = context.runtime;
         if (!(other instanceof RubyMessage))
@@ -210,9 +240,9 @@
             return runtime.getFalse();
         }
 
-        for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) {
-            IRubyObject thisVal = getField(context, fdef);
-            IRubyObject thatVal = message.getField(context, fdef);
+        for (FieldDescriptor fdef : descriptor.getFields()) {
+            IRubyObject thisVal = getFieldInternal(context, fdef);
+            IRubyObject thatVal = message.getFieldInternal(context, fdef);
             IRubyObject ret = thisVal.callMethod(context, "==", thatVal);
             if (!ret.isTrue()) {
                 return runtime.getFalse();
@@ -225,46 +255,169 @@
      * call-seq:
      *     Message.method_missing(*args)
      *
-     * Provides accessors and setters for message fields according to their field
-     * names. For any field whose name does not conflict with a built-in method, an
+     * Provides accessors and setters and methods to clear and check for presence of
+     * message fields according to their field names.
+     *
+     * For any field whose name does not conflict with a built-in method, an
      * accessor is provided with the same name as the field, and a setter is
      * provided with the name of the field plus the '=' suffix. Thus, given a
      * message instance 'msg' with field 'foo', the following code is valid:
      *
      *     msg.foo = 42
      *     puts msg.foo
+     *
+     * This method also provides read-only accessors for oneofs. If a oneof exists
+     * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
+     * the name of the field in that oneof that is currently set, or nil if none.
+     *
+     * It also provides methods of the form 'clear_fieldname' to clear the value
+     * of the field 'fieldname'. For basic data types, this will set the default
+     * value of the field.
+     *
+     * Additionally, it provides methods of the form 'has_fieldname?', which returns
+     * true if the field 'fieldname' is set in the message object, else false. For
+     * 'proto3' syntax, calling this for a basic type field will result in an error.
      */
     @JRubyMethod(name = "method_missing", rest = true)
     public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) {
+        Ruby runtime = context.runtime;
+        String methodName = args[0].asJavaString();
+
         if (args.length == 1) {
             RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
+
+            // If we find a Oneof return it's name (use lookupOneof because it has an index)
             IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, args[0]);
-            if (oneofDescriptor.isNil()) {
-                if (!hasField(args[0])) {
-                    return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK);
+
+            if (!oneofDescriptor.isNil()) {
+                RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor;
+                OneofDescriptor ood = rubyOneofDescriptor.getDescriptor();
+
+                // Check to see if we set this through ruby
+                FieldDescriptor fieldDescriptor = oneofCases.get(ood);
+
+                if (fieldDescriptor == null) {
+                    // See if we set this from decoding a message
+                    fieldDescriptor = builder.getOneofFieldDescriptor(ood);
+
+                    if (fieldDescriptor == null) {
+                        return context.nil;
+                    } else {
+                        // Cache it so we don't need to do multiple checks next time
+                        oneofCases.put(ood, fieldDescriptor);
+                        return runtime.newSymbol(fieldDescriptor.getName());
+                    }
+                } else {
+                    return runtime.newSymbol(fieldDescriptor.getName());
                 }
-                return index(context, args[0]);
-            }
-            RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor;
-            Descriptors.FieldDescriptor fieldDescriptor =
-                    oneofCases.get(rubyOneofDescriptor.getOneofDescriptor());
-            if (fieldDescriptor == null)
-                return context.runtime.getNil();
-
-            return context.runtime.newSymbol(fieldDescriptor.getName());
-        } else {
-            // fieldName is RubySymbol
-            RubyString field = args[0].asString();
-            RubyString equalSign = context.runtime.newString(Utils.EQUAL_SIGN);
-            if (field.end_with_p(context, equalSign).isTrue()) {
-                field.chomp_bang(context, equalSign);
             }
 
-            if (!hasField(field)) {
-                return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK);
+            // If we find a field return its value
+            FieldDescriptor fieldDescriptor = descriptor.findFieldByName(methodName);
+
+            if (fieldDescriptor != null) {
+                return getFieldInternal(context, fieldDescriptor);
             }
-            return indexSet(context, field, args[1]);
+
+            if (methodName.startsWith(CLEAR_PREFIX)) {
+                methodName = methodName.substring(6);
+                oneofDescriptor = rubyDescriptor.lookupOneof(context, runtime.newSymbol(methodName));
+
+                if (!oneofDescriptor.isNil()) {
+                    fieldDescriptor = oneofCases.get(((RubyOneofDescriptor) oneofDescriptor).getDescriptor());
+                }
+
+                if (fieldDescriptor == null) {
+                    fieldDescriptor = descriptor.findFieldByName(methodName);
+                }
+
+                if (fieldDescriptor != null) {
+                    return clearFieldInternal(context, fieldDescriptor);
+                }
+
+            } else if (methodName.startsWith(HAS_PREFIX) && methodName.endsWith(QUESTION_MARK)) {
+                methodName = methodName.substring(4, methodName.length() - 1); // Trim "has_" and "?" off the field name
+                oneofDescriptor = rubyDescriptor.lookupOneof(context, runtime.newSymbol(methodName));
+                if (!oneofDescriptor.isNil()) {
+                    RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor;
+                    return oneofCases.containsKey(rubyOneofDescriptor.getDescriptor()) ? runtime.getTrue() : runtime.getFalse();
+                }
+
+                fieldDescriptor = descriptor.findFieldByName(methodName);
+
+                if (fieldDescriptor != null &&
+                        (!proto3 || fieldDescriptor.getContainingOneof() == null) && // This seems like a bug but its needed to pass the tests...
+                        fieldHasPresence(fieldDescriptor)) {
+                    return fields.containsKey(fieldDescriptor) ? runtime.getTrue() : runtime.getFalse();
+                }
+
+            } else if (methodName.endsWith(AS_VALUE_SUFFIX)) {
+                methodName = methodName.substring(0, methodName.length() - 9);
+                fieldDescriptor = descriptor.findFieldByName(methodName);
+
+                if (fieldDescriptor != null && isWrappable(fieldDescriptor)) {
+                    IRubyObject value = getFieldInternal(context, fieldDescriptor);
+
+                    if (!value.isNil() && value instanceof RubyMessage) {
+                        return ((RubyMessage) value).index(context, runtime.newString("value"));
+                    }
+
+                    return value;
+                }
+
+            } else if (methodName.endsWith(CONST_SUFFIX)) {
+                methodName = methodName.substring(0, methodName.length() - 6);
+                fieldDescriptor = descriptor.findFieldByName(methodName);
+
+                if (fieldDescriptor.getType() == FieldDescriptor.Type.ENUM) {
+                    IRubyObject enumValue = getFieldInternal(context, fieldDescriptor);
+
+                    if (!enumValue.isNil()) {
+                        EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
+                        if (enumValue instanceof RubyRepeatedField) {
+                            RubyArray values = (RubyArray) ((RubyRepeatedField) enumValue).toArray(context);
+                            RubyArray retValues = runtime.newArray(values.getLength());
+                            for (int i = 0; i < values.getLength(); i++) {
+                                String val = values.eltInternal(i).toString();
+                                retValues.store((long) i, runtime.newFixnum(enumDescriptor.findValueByName(val).getNumber()));
+                            }
+                            return retValues;
+                        }
+
+                        return runtime.newFixnum(enumDescriptor.findValueByName(enumValue.asJavaString()).getNumber());
+                    }
+                }
+            }
+
+        } else if (args.length == 2 && methodName.endsWith(Utils.EQUAL_SIGN)) {
+
+            methodName = methodName.substring(0, methodName.length() - 1); // Trim equals sign
+            FieldDescriptor fieldDescriptor = descriptor.findFieldByName(methodName);
+
+            if (fieldDescriptor != null) {
+                return setFieldInternal(context, fieldDescriptor, args[1]);
+            }
+
+            if (methodName.endsWith(AS_VALUE_SUFFIX)) {
+                methodName = methodName.substring(0, methodName.length() - 9);
+
+                fieldDescriptor = descriptor.findFieldByName(methodName);
+
+                if (fieldDescriptor != null) {
+                    if (args[1].isNil()) {
+                        return setFieldInternal(context, fieldDescriptor, args[1]);
+                    }
+
+                    RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+                    RubyMessage msg = (RubyMessage) typeClass.newInstance(context, Block.NULL_BLOCK);
+                    msg.indexSet(context, runtime.newString("value"), args[1]);
+                    return setFieldInternal(context, fieldDescriptor, msg);
+                }
+            }
+
         }
+
+        return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK);
     }
 
     /**
@@ -276,18 +429,15 @@
     public IRubyObject dup(ThreadContext context) {
         RubyMessage dup = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK);
         IRubyObject value;
-        for (Descriptors.FieldDescriptor fieldDescriptor : this.descriptor.getFields()) {
+        for (FieldDescriptor fieldDescriptor : this.descriptor.getFields()) {
             if (fieldDescriptor.isRepeated()) {
-                dup.addRepeatedField(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor));
+                dup.fields.put(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor));
             } else if (fields.containsKey(fieldDescriptor)) {
                 dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor));
             } else if (this.builder.hasField(fieldDescriptor)) {
                 dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor)));
             }
         }
-        for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) {
-            dup.maps.put(fieldDescriptor, maps.get(fieldDescriptor));
-        }
         return dup;
     }
 
@@ -312,6 +462,9 @@
      */
     @JRubyMethod(meta = true)
     public static IRubyObject encode(ThreadContext context, IRubyObject recv, IRubyObject value) {
+        if (recv != value.getMetaClass()) {
+            throw context.runtime.newArgumentError("Tried to encode a " + value.getMetaClass() + " message with " + recv);
+        }
         RubyMessage message = (RubyMessage) value;
         return context.runtime.newString(new ByteList(message.build(context).toByteArray()));
     }
@@ -331,40 +484,110 @@
         try {
             ret.builder.mergeFrom(bin);
         } catch (InvalidProtocolBufferException e) {
-            throw context.runtime.newRuntimeError(e.getMessage());
+            throw RaiseException.from(context.runtime, (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::ParseError"), e.getMessage());
         }
+
+        if (!ret.proto3) {
+            // Need to reset unknown values in repeated enum fields
+            ret.builder.getUnknownFields().asMap().forEach((i, values) -> {
+                FieldDescriptor fd = ret.builder.getDescriptorForType().findFieldByNumber(i);
+                if (fd != null && fd.isRepeated() && fd.getType() == FieldDescriptor.Type.ENUM) {
+                    EnumDescriptor ed = fd.getEnumType();
+                    values.getVarintList().forEach(value -> {
+                        ret.builder.addRepeatedField(fd, ed.findValueByNumberCreatingIfUnknown(value.intValue()));
+                    });
+                }
+            });
+        }
+
         return ret;
     }
 
     /*
      * call-seq:
-     *     MessageClass.encode_json(msg) => json_string
+     *     MessageClass.encode_json(msg, options = {}) => json_string
      *
      * Encodes the given message object into its serialized JSON representation.
+     * @param options [Hash] options for the decoder
+     *  preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
+     *  emit_defaults: set true to emit 0/false values (default is to omit them)
      */
-    @JRubyMethod(name = "encode_json", meta = true)
-    public static IRubyObject encodeJson(ThreadContext context, IRubyObject recv, IRubyObject msgRb) {
-        RubyMessage message = (RubyMessage) msgRb;
-        return Helpers.invoke(context, message.toHash(context), "to_json");
+    @JRubyMethod(name = "encode_json", required = 1, optional = 1, meta = true)
+    public static IRubyObject encodeJson(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
+        Ruby runtime = context.runtime;
+        RubyMessage message = (RubyMessage) args[0];
+        JsonFormat.Printer printer = JsonFormat.printer().omittingInsignificantWhitespace();
+        String result;
+
+        if (args.length > 1) {
+            RubyHash options = (RubyHash) args[1];
+            IRubyObject emitDefaults = options.fastARef(runtime.newSymbol("emit_defaults"));
+            IRubyObject preserveNames = options.fastARef(runtime.newSymbol("preserve_proto_fieldnames"));
+
+            if (emitDefaults != null && emitDefaults.isTrue()) {
+                printer = printer.includingDefaultValueFields();
+            }
+
+            if (preserveNames != null && preserveNames.isTrue()) {
+                printer = printer.preservingProtoFieldNames();
+            }
+        }
+
+        try {
+            result = printer.print(message.build(context));
+        } catch(InvalidProtocolBufferException e) {
+            throw runtime.newRuntimeError(e.getMessage());
+        }
+
+        return runtime.newString(result);
     }
 
     /*
      * call-seq:
-     *     MessageClass.decode_json(data) => message
+     *     MessageClass.decode_json(data, options = {}) => message
      *
      * Decodes the given data (as a string containing bytes in protocol buffers wire
      * format) under the interpretration given by this message class's definition
      * and returns a message object with the corresponding field values.
+     *
+     *  @param options [Hash] options for the decoder
+     *   ignore_unknown_fields: set true to ignore unknown fields (default is to
+     *   raise an error)
      */
-    @JRubyMethod(name = "decode_json", meta = true)
-    public static IRubyObject decodeJson(ThreadContext context, IRubyObject recv, IRubyObject json) {
+    @JRubyMethod(name = "decode_json", required = 1, optional = 1, meta = true)
+    public static IRubyObject decodeJson(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
         Ruby runtime = context.runtime;
+        boolean ignoreUnknownFields = false;
+        IRubyObject data = args[0];
+        JsonFormat.Parser parser = JsonFormat.parser();
+
+        if (args.length == 2) {
+            if (!(args[1] instanceof RubyHash)) {
+                throw runtime.newArgumentError("Expected hash arguments.");
+            }
+
+            IRubyObject ignoreSetting = ((RubyHash) args[1]).fastARef(runtime.newSymbol("ignore_unknown_fields"));
+            if (ignoreSetting != null && ignoreSetting.isTrue()) {
+                parser = parser.ignoringUnknownFields();
+            }
+        }
+
+        if (!(data instanceof RubyString)) {
+            throw runtime.newArgumentError("Expected string for JSON data.");
+        }
+
         RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK);
-        RubyModule jsonModule = runtime.getClassFromPath("JSON");
-        RubyHash opts = RubyHash.newHash(runtime);
-        opts.fastASet(runtime.newSymbol("symbolize_names"), runtime.getTrue());
-        IRubyObject[] args = new IRubyObject[] { Helpers.invoke(context, jsonModule, "parse", json, opts) };
-        ret.initialize(context, args);
+
+        try {
+            parser.merge(data.asJavaString(), ret.builder);
+        } catch(InvalidProtocolBufferException e) {
+            throw createParseError(context, e.getMessage().replace("Cannot find", "No such"));
+        }
+
+        if (isWrapper(ret.descriptor)) {
+            throw runtime.newRuntimeError("Parsing a wrapper type from JSON at the top level does not work.");
+        }
+
         return ret;
     }
 
@@ -372,11 +595,13 @@
     public IRubyObject toHash(ThreadContext context) {
         Ruby runtime = context.runtime;
         RubyHash ret = RubyHash.newHash(runtime);
-        for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
-            IRubyObject value = getField(context, fdef);
+        for (FieldDescriptor fdef : this.descriptor.getFields()) {
+            IRubyObject value = getFieldInternal(context, fdef, proto3);
+
             if (!value.isNil()) {
                 if (fdef.isRepeated() && !fdef.isMapField()) {
-                    if (fdef.getType() != Descriptors.FieldDescriptor.Type.MESSAGE) {
+                    if (!proto3 && ((RubyRepeatedField) value).size() == 0) continue; // Don't output empty repeated fields for proto2
+                    if (fdef.getType() != FieldDescriptor.Type.MESSAGE) {
                         value = Helpers.invoke(context, value, "to_a");
                     } else {
                         RubyArray ary = value.convertToArray();
@@ -393,7 +618,9 @@
                     value = Helpers.invoke(context, value, "to_a");
                 }
             }
-            ret.fastASet(runtime.newSymbol(fdef.getName()), value);
+            if (proto3 || !value.isNil()) {
+                ret.fastASet(runtime.newSymbol(fdef.getName()), value);
+            }
         }
         return ret;
     }
@@ -406,176 +633,197 @@
         if (depth > SINK_MAXIMUM_NESTING) {
             throw context.runtime.newRuntimeError("Maximum recursion depth exceeded during encoding.");
         }
-        for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) {
-            this.builder.clearField(fieldDescriptor);
-            RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
-            for (DynamicMessage kv : maps.get(fieldDescriptor).build(context, mapDescriptor)) {
-                this.builder.addRepeatedField(fieldDescriptor, kv);
-            }
-        }
-        for (Descriptors.FieldDescriptor fieldDescriptor : repeatedFields.keySet()) {
-            RubyRepeatedField repeatedField = repeatedFields.get(fieldDescriptor);
-            this.builder.clearField(fieldDescriptor);
-            for (int i = 0; i < repeatedField.size(); i++) {
-                Object item = convert(context, fieldDescriptor, repeatedField.get(i), depth);
-                this.builder.addRepeatedField(fieldDescriptor, item);
-            }
-        }
-        for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) {
+        for (FieldDescriptor fieldDescriptor : fields.keySet()) {
             IRubyObject value = fields.get(fieldDescriptor);
-            this.builder.setField(fieldDescriptor, convert(context, fieldDescriptor, value, depth));
-        }
-        return this.builder.build();
-    }
 
-    protected Descriptors.Descriptor getDescriptor() {
-        return this.descriptor;
+            if (value instanceof RubyMap) {
+                builder.clearField(fieldDescriptor);
+                RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
+                for (DynamicMessage kv : ((RubyMap) value).build(context, mapDescriptor, depth)) {
+                    builder.addRepeatedField(fieldDescriptor, kv);
+                }
+
+            } else if (value instanceof RubyRepeatedField) {
+                RubyRepeatedField repeatedField = (RubyRepeatedField) value;
+
+                builder.clearField(fieldDescriptor);
+                for (int i = 0; i < repeatedField.size(); i++) {
+                    Object item = convert(context, fieldDescriptor, repeatedField.get(i), depth);
+                    builder.addRepeatedField(fieldDescriptor, item);
+                }
+
+            } else {
+                builder.setField(fieldDescriptor, convert(context, fieldDescriptor, value, depth));
+            }
+        }
+
+        return builder.build();
     }
 
     // Internal use only, called by Google::Protobuf.deep_copy
     protected IRubyObject deepCopy(ThreadContext context) {
         RubyMessage copy = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK);
-        for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
+        for (FieldDescriptor fdef : descriptor.getFields()) {
             if (fdef.isRepeated()) {
-                copy.addRepeatedField(fdef, this.getRepeatedField(context, fdef).deepCopy(context));
+                copy.fields.put(fdef, this.getRepeatedField(context, fdef).deepCopy(context));
             } else if (fields.containsKey(fdef)) {
                 copy.fields.put(fdef, fields.get(fdef));
-            } else if (this.builder.hasField(fdef)) {
-                copy.fields.put(fdef, wrapField(context, fdef, this.builder.getField(fdef)));
+            } else if (builder.hasField(fdef)) {
+                copy.fields.put(fdef, wrapField(context, fdef, builder.getField(fdef)));
             }
         }
         return copy;
     }
 
-    private RubyRepeatedField getRepeatedField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
-        if (this.repeatedFields.containsKey(fieldDescriptor)) {
-            return this.repeatedFields.get(fieldDescriptor);
+    protected IRubyObject clearField(ThreadContext context, FieldDescriptor fieldDescriptor) {
+        validateMessageType(context, fieldDescriptor, "clear");
+        return clearFieldInternal(context, fieldDescriptor);
+    }
+
+    protected void discardUnknownFields(ThreadContext context) {
+        discardUnknownFields(context, builder);
+    }
+
+    protected IRubyObject getField(ThreadContext context, FieldDescriptor fieldDescriptor) {
+        validateMessageType(context, fieldDescriptor, "get");
+        return getFieldInternal(context, fieldDescriptor);
+    }
+
+    protected IRubyObject hasField(ThreadContext context, FieldDescriptor fieldDescriptor) {
+        validateMessageType(context, fieldDescriptor, "has?");
+        if (!fieldHasPresence(fieldDescriptor)) throw context.runtime.newArgumentError("does not track presence");
+        return fields.containsKey(fieldDescriptor) ? context.runtime.getTrue() : context.runtime.getFalse();
+    }
+
+    protected IRubyObject setField(ThreadContext context, FieldDescriptor fieldDescriptor, IRubyObject value) {
+        validateMessageType(context, fieldDescriptor, "set");
+        return setFieldInternal(context, fieldDescriptor, value);
+    }
+
+    private RubyRepeatedField getRepeatedField(ThreadContext context, FieldDescriptor fieldDescriptor) {
+        if (fields.containsKey(fieldDescriptor)) {
+            return (RubyRepeatedField) fields.get(fieldDescriptor);
         }
         int count = this.builder.getRepeatedFieldCount(fieldDescriptor);
         RubyRepeatedField ret = repeatedFieldForFieldDescriptor(context, fieldDescriptor);
         for (int i = 0; i < count; i++) {
-            ret.push(context, wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i)));
+            ret.push(context, new IRubyObject[] {wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i))});
         }
-        addRepeatedField(fieldDescriptor, ret);
+        fields.put(fieldDescriptor, ret);
         return ret;
     }
 
-    private void addRepeatedField(Descriptors.FieldDescriptor fieldDescriptor, RubyRepeatedField repeatedField) {
-        this.repeatedFields.put(fieldDescriptor, repeatedField);
-    }
-
     private IRubyObject buildFrom(ThreadContext context, DynamicMessage dynamicMessage) {
         this.builder.mergeFrom(dynamicMessage);
         return this;
     }
 
-    private Descriptors.FieldDescriptor findField(ThreadContext context, IRubyObject fieldName) {
+    private IRubyObject clearFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor) {
+        OneofDescriptor ood = fieldDescriptor.getContainingOneof();
+        if (ood != null) oneofCases.remove(ood);
+        fields.remove(fieldDescriptor);
+        builder.clearField(fieldDescriptor);
+        return context.nil;
+    }
+
+    private void discardUnknownFields(ThreadContext context, Message.Builder messageBuilder) {
+        messageBuilder.setUnknownFields(UnknownFieldSet.getDefaultInstance());
+        messageBuilder.getAllFields().forEach((fd, value) -> {
+            if (fd.getType() == FieldDescriptor.Type.MESSAGE) {
+                if (fd.isRepeated()) {
+                    messageBuilder.clearField(fd);
+                    ((List) value).forEach((val) -> {
+                        Message.Builder submessageBuilder = ((DynamicMessage) val).toBuilder();
+                        discardUnknownFields(context, submessageBuilder);
+                        messageBuilder.addRepeatedField(fd, submessageBuilder.build());
+                    });
+                } else {
+                    Message.Builder submessageBuilder = ((DynamicMessage) value).toBuilder();
+                    discardUnknownFields(context, submessageBuilder);
+                    messageBuilder.setField(fd, submessageBuilder.build());
+                }
+            }
+        });
+    }
+
+    private FieldDescriptor findField(ThreadContext context, IRubyObject fieldName) {
+        return findField(context, fieldName, false);
+    }
+
+    private FieldDescriptor findField(ThreadContext context, IRubyObject fieldName, boolean ignoreUnknownField) {
         String nameStr = fieldName.asJavaString();
-        Descriptors.FieldDescriptor ret = this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr));
-        if (ret == null)
+        FieldDescriptor ret = this.descriptor.findFieldByName(nameStr);
+        if (ret == null && !ignoreUnknownField) {
             throw context.runtime.newArgumentError("field " + fieldName.asJavaString() + " is not found");
+        }
         return ret;
     }
 
-    private boolean hasField(IRubyObject fieldName) {
-        String nameStr = fieldName.asJavaString();
-        return this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr)) != null;
-    }
-
-    private void checkRepeatedFieldType(ThreadContext context, IRubyObject value,
-                                        Descriptors.FieldDescriptor fieldDescriptor) {
-        Ruby runtime = context.runtime;
-        if (!(value instanceof RubyRepeatedField)) {
-            throw runtime.newTypeError("Expected repeated field array");
-        }
-    }
-
-    // convert a ruby object to protobuf type, with type check
+    // convert a ruby object to protobuf type, skip type check since it is checked on the way in
     private Object convert(ThreadContext context,
-                           Descriptors.FieldDescriptor fieldDescriptor,
+                           FieldDescriptor fieldDescriptor,
                            IRubyObject value, int depth) {
         Ruby runtime = context.runtime;
         Object val = null;
         switch (fieldDescriptor.getType()) {
             case INT32:
+                val = RubyNumeric.num2int(value);
+                break;
             case INT64:
+                val = RubyNumeric.num2long(value);
+                break;
             case UINT32:
+                val = Utils.num2uint(value);
+                break;
             case UINT64:
-                if (!Utils.isRubyNum(value)) {
-                    throw runtime.newTypeError("Expected number type for integral field.");
-                }
-                Utils.checkIntTypePrecision(context, fieldDescriptor.getType(), value);
-                switch (fieldDescriptor.getType()) {
-                    case INT32:
-                        val = RubyNumeric.num2int(value);
-                        break;
-                    case INT64:
-                        val = RubyNumeric.num2long(value);
-                        break;
-                    case UINT32:
-                        val = Utils.num2uint(value);
-                        break;
-                    case UINT64:
-                        val = Utils.num2ulong(context.runtime, value);
-                        break;
-                    default:
-                        break;
-                }
+                val = Utils.num2ulong(context.runtime, value);
                 break;
             case FLOAT:
-                if (!Utils.isRubyNum(value))
-                    throw runtime.newTypeError("Expected number type for float field.");
                 val = (float) RubyNumeric.num2dbl(value);
                 break;
             case DOUBLE:
-                if (!Utils.isRubyNum(value))
-                    throw runtime.newTypeError("Expected number type for double field.");
-                val = RubyNumeric.num2dbl(value);
+                val = (double) RubyNumeric.num2dbl(value);
                 break;
             case BOOL:
-                if (!(value instanceof RubyBoolean))
-                    throw runtime.newTypeError("Invalid argument for boolean field.");
                 val = value.isTrue();
                 break;
             case BYTES:
-                Utils.validateStringEncoding(context, fieldDescriptor.getType(), value);
                 val = ByteString.copyFrom(((RubyString) value).getBytes());
                 break;
             case STRING:
-                Utils.validateStringEncoding(context, fieldDescriptor.getType(), value);
                 val = ((RubyString) value).asJavaString();
                 break;
             case MESSAGE:
-                RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
-                if (!value.getMetaClass().equals(typeClass))
-                    throw runtime.newTypeError(value, "Invalid type to assign to submessage field.");
                 val = ((RubyMessage) value).build(context, depth + 1);
                 break;
             case ENUM:
-                Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
-
+                EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
                 if (Utils.isRubyNum(value)) {
                     val = enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
-                } else if (value instanceof RubySymbol || value instanceof RubyString) {
-                    val = enumDescriptor.findValueByName(value.asJavaString());
                 } else {
-                    throw runtime.newTypeError("Expected number or symbol type for enum field.");
-                }
-                if (val == null) {
-                    throw runtime.newRangeError("Enum value " + value + " is not found.");
+                    val = enumDescriptor.findValueByName(value.asJavaString());
                 }
                 break;
             default:
                 break;
         }
+
         return val;
     }
 
-    private IRubyObject wrapField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, Object value) {
+    private static RaiseException createParseError(ThreadContext context, String message) {
+        if (parseErrorClass == null) {
+            parseErrorClass = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::ParseError");
+        }
+        return RaiseException.from(context.runtime, parseErrorClass, message);
+    }
+
+    private IRubyObject wrapField(ThreadContext context, FieldDescriptor fieldDescriptor, Object value) {
         if (value == null) {
             return context.runtime.getNil();
         }
         Ruby runtime = context.runtime;
+
         switch (fieldDescriptor.getType()) {
             case INT32:
             case INT64:
@@ -592,7 +840,7 @@
                 RubyMessage msg = (RubyMessage) typeClass.newInstance(context, Block.NULL_BLOCK);
                 return msg.buildFrom(context, (DynamicMessage) value);
             case ENUM:
-                Descriptors.EnumValueDescriptor enumValueDescriptor = (Descriptors.EnumValueDescriptor) value;
+                EnumValueDescriptor enumValueDescriptor = (EnumValueDescriptor) value;
                 if (enumValueDescriptor.getIndex() == -1) { // UNKNOWN ENUM VALUE
                     return runtime.newFixnum(enumValueDescriptor.getNumber());
                 }
@@ -602,48 +850,59 @@
         }
     }
 
-    private RubyRepeatedField repeatedFieldForFieldDescriptor(ThreadContext context,
-                                                              Descriptors.FieldDescriptor fieldDescriptor) {
+    private RubyRepeatedField repeatedFieldForFieldDescriptor(ThreadContext context, FieldDescriptor fieldDescriptor) {
         IRubyObject typeClass = context.runtime.getNilClass();
-
         IRubyObject descriptor = getDescriptorForField(context, fieldDescriptor);
-        Descriptors.FieldDescriptor.Type type = fieldDescriptor.getType();
-        if (type == Descriptors.FieldDescriptor.Type.MESSAGE) {
+        FieldDescriptor.Type type = fieldDescriptor.getType();
+
+        if (type == FieldDescriptor.Type.MESSAGE) {
             typeClass = ((RubyDescriptor) descriptor).msgclass(context);
 
-        } else if (type == Descriptors.FieldDescriptor.Type.ENUM) {
+        } else if (type == FieldDescriptor.Type.ENUM) {
             typeClass = ((RubyEnumDescriptor) descriptor).enummodule(context);
         }
-        return new RubyRepeatedField(context.runtime, cRepeatedField, type, typeClass);
+
+        RubyRepeatedField field = new RubyRepeatedField(context.runtime, cRepeatedField, type, typeClass);
+        field.setName(fieldDescriptor.getName());
+
+        return field;
     }
 
-    protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
-        Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+    private IRubyObject getFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor) {
+        return getFieldInternal(context, fieldDescriptor, true);
+    }
+
+    private IRubyObject getFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor, boolean returnDefaults) {
+        OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
         if (oneofDescriptor != null) {
             if (oneofCases.get(oneofDescriptor) == fieldDescriptor) {
                 return fields.get(fieldDescriptor);
             } else {
-                Descriptors.FieldDescriptor oneofCase = builder.getOneofFieldDescriptor(oneofDescriptor);
+                FieldDescriptor oneofCase = builder.getOneofFieldDescriptor(oneofDescriptor);
                 if (oneofCase != fieldDescriptor) {
-                  if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
-                    return context.runtime.getNil();
+                  if (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE || !returnDefaults) {
+                    return context.nil;
                   } else {
                     return wrapField(context, fieldDescriptor, fieldDescriptor.getDefaultValue());
                   }
                 }
-                IRubyObject value = wrapField(context, oneofCase, builder.getField(oneofCase));
-                fields.put(fieldDescriptor, value);
-                return value;
+                if (returnDefaults || builder.hasField(fieldDescriptor)) {
+                    IRubyObject value = wrapField(context, oneofCase, builder.getField(oneofCase));
+                    fields.put(fieldDescriptor, value);
+                    return value;
+                } else {
+                    return context.nil;
+                }
             }
         }
 
         if (Utils.isMapEntry(fieldDescriptor)) {
-            RubyMap map = maps.get(fieldDescriptor);
+            RubyMap map = (RubyMap) fields.get(fieldDescriptor);
             if (map == null) {
                 map = newMapForField(context, fieldDescriptor);
                 int mapSize = this.builder.getRepeatedFieldCount(fieldDescriptor);
-                Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
-                Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
+                FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
+                FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
                 RubyDescriptor kvDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
                 RubyClass kvClass = (RubyClass) kvDescriptor.msgclass(context);
                 for (int i = 0; i < mapSize; i++) {
@@ -652,158 +911,234 @@
                     kvMessage.buildFrom(context, message);
                     map.indexSet(context, kvMessage.getField(context, keyField), kvMessage.getField(context, valueField));
                 }
-                maps.put(fieldDescriptor, map);
+                fields.put(fieldDescriptor, map);
             }
             return map;
         }
+
         if (fieldDescriptor.isRepeated()) {
             return getRepeatedField(context, fieldDescriptor);
         }
-        if (fieldDescriptor.getType() != Descriptors.FieldDescriptor.Type.MESSAGE ||
-                this.builder.hasField(fieldDescriptor) || fields.containsKey(fieldDescriptor)) {
+
+        if (fieldDescriptor.getType() != FieldDescriptor.Type.MESSAGE ||
+                builder.hasField(fieldDescriptor) || fields.containsKey(fieldDescriptor)) {
             if (fields.containsKey(fieldDescriptor)) {
                 return fields.get(fieldDescriptor);
-            } else {
-                IRubyObject value = wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor));
-                if (this.builder.hasField(fieldDescriptor)) {
+            } else if (returnDefaults || builder.hasField(fieldDescriptor)) {
+                IRubyObject value = wrapField(context, fieldDescriptor, builder.getField(fieldDescriptor));
+                if (builder.hasField(fieldDescriptor)) {
                     fields.put(fieldDescriptor, value);
                 }
                 return value;
             }
         }
-        return context.runtime.getNil();
+        return context.nil;
     }
 
-    protected IRubyObject setField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) {
+    private IRubyObject setFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor, IRubyObject value) {
+        testFrozen("can't modify frozen " + getMetaClass());
+
         if (Utils.isMapEntry(fieldDescriptor)) {
             if (!(value instanceof RubyMap)) {
-                throw context.runtime.newTypeError("Expected Map instance");
+                throw Utils.createTypeError(context, "Expected Map instance");
             }
-            RubyMap thisMap = (RubyMap) getField(context, fieldDescriptor);
+            RubyMap thisMap = (RubyMap) getFieldInternal(context, fieldDescriptor);
             thisMap.mergeIntoSelf(context, value);
+
         } else if (fieldDescriptor.isRepeated()) {
-            checkRepeatedFieldType(context, value, fieldDescriptor);
             if (value instanceof RubyRepeatedField) {
-                addRepeatedField(fieldDescriptor, (RubyRepeatedField) value);
+                fields.put(fieldDescriptor, value);
             } else {
-                RubyArray ary = value.convertToArray();
-                RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, ary);
-                addRepeatedField(fieldDescriptor, repeatedField);
+                throw Utils.createTypeError(context, "Expected repeated field array");
             }
+
         } else {
-            Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+            boolean addValue = true;
+            FieldDescriptor.Type fieldType = fieldDescriptor.getType();
+            OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+
+            // Determine the typeclass, if any
+            IRubyObject typeClass = context.runtime.getObject();
+            if (fieldType == FieldDescriptor.Type.MESSAGE) {
+                typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+                if (value.isNil()){
+                    addValue = false;
+                }
+            } else if (fieldType == FieldDescriptor.Type.ENUM) {
+                typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context);
+                value = enumToSymbol(context, fieldDescriptor.getEnumType(), value);
+            }
+
             if (oneofDescriptor != null) {
-                Descriptors.FieldDescriptor oneofCase = oneofCases.get(oneofDescriptor);
+                FieldDescriptor oneofCase = oneofCases.get(oneofDescriptor);
+
+                // Remove the existing field if we are setting a different field in the Oneof
                 if (oneofCase != null && oneofCase != fieldDescriptor) {
                     fields.remove(oneofCase);
                 }
+
+                // Keep track of what Oneofs are set
                 if (value.isNil()) {
                     oneofCases.remove(oneofDescriptor);
-                    fields.remove(fieldDescriptor);
+                    addValue = false;
                 } else {
                     oneofCases.put(oneofDescriptor, fieldDescriptor);
-                    fields.put(fieldDescriptor, value);
-                }
-            } else {
-                Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
-                IRubyObject typeClass = context.runtime.getObject();
-                boolean addValue = true;
-                if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
-                    typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
-                    if (value.isNil()){
-                        addValue = false;
-                    }
-                } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
-                    typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context);
-                    Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
-                    if (Utils.isRubyNum(value)) {
-                        Descriptors.EnumValueDescriptor val =
-                                enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
-                        if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName());
-                    }
-                }
-                if (addValue) {
-                    value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
-                    this.fields.put(fieldDescriptor, value);
-                } else {
-                    this.fields.remove(fieldDescriptor);
                 }
             }
+
+            if (addValue) {
+                value = Utils.checkType(context, fieldType, fieldDescriptor.getName(), value, (RubyModule) typeClass);
+                fields.put(fieldDescriptor, value);
+            } else {
+                fields.remove(fieldDescriptor);
+            }
         }
-        return context.runtime.getNil();
+        return context.nil;
     }
 
-    private String layoutInspect() {
-        ThreadContext context = getRuntime().getCurrentContext();
-        StringBuilder sb = new StringBuilder();
-        for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) {
-            sb.append(Utils.unescapeIdentifier(fdef.getName()));
-            sb.append(": ");
-            sb.append(getField(context, fdef).inspect());
-            sb.append(", ");
-        }
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    private IRubyObject getDescriptorForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+    private IRubyObject getDescriptorForField(ThreadContext context, FieldDescriptor fieldDescriptor) {
         RubyDescriptor thisRbDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
-        return thisRbDescriptor.lookup(fieldDescriptor.getName()).getSubType(context);
+        RubyFieldDescriptor fd = (RubyFieldDescriptor) thisRbDescriptor.lookup(context, context.runtime.newString(fieldDescriptor.getName()));
+        return fd.getSubtype(context);
+    }
+
+    private IRubyObject enumToSymbol(ThreadContext context, EnumDescriptor enumDescriptor, IRubyObject value) {
+        if (value instanceof RubySymbol) {
+            return (RubySymbol) value;
+        } else if (Utils.isRubyNum(value)) {
+            EnumValueDescriptor enumValue = enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
+            if (enumValue.getIndex() != -1) {
+                return context.runtime.newSymbol(enumValue.getName());
+            } else {
+                return value;
+            }
+        } else if (value instanceof RubyString) {
+            return ((RubyString) value).intern();
+        }
+
+        return context.runtime.newSymbol("UNKNOWN");
+    }
+
+    private boolean fieldHasPresence(FieldDescriptor fieldDescriptor) {
+      return !fieldDescriptor.isRepeated() &&
+              (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE ||
+                fieldDescriptor.getContainingOneof() != null ||
+                !proto3);
     }
 
     private RubyRepeatedField rubyToRepeatedField(ThreadContext context,
-                                                  Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) {
+                                                  FieldDescriptor fieldDescriptor, IRubyObject value) {
         RubyArray arr = value.convertToArray();
         RubyRepeatedField repeatedField = repeatedFieldForFieldDescriptor(context, fieldDescriptor);
+        IRubyObject[] values = new IRubyObject[arr.size()];
+        FieldDescriptor.Type fieldType = fieldDescriptor.getType();
+        String fieldName = fieldDescriptor.getName();
 
-        RubyClass typeClass = null;
-        if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
+        RubyModule typeClass = null;
+        if (fieldType == FieldDescriptor.Type.MESSAGE) {
             RubyDescriptor descriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
-            typeClass = (RubyClass) descriptor.msgclass(context);
+            typeClass = (RubyModule) descriptor.msgclass(context);
+        } else if (fieldType == FieldDescriptor.Type.ENUM) {
+            RubyEnumDescriptor enumDescriptor = (RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor);
+            typeClass = (RubyModule) enumDescriptor.enummodule(context);
         }
 
         for (int i = 0; i < arr.size(); i++) {
-            IRubyObject row = arr.eltInternal(i);
-            if (row instanceof RubyHash && typeClass != null) {
-                row = (IRubyObject) typeClass.newInstance(context, row, Block.NULL_BLOCK);
-            }
+            IRubyObject item = arr.eltInternal(i);
+            if (item instanceof RubyHash && typeClass != null) {
+                values[i] = (IRubyObject) ((RubyClass) typeClass).newInstance(context, item, Block.NULL_BLOCK);
+            } else {
+                if (fieldType == FieldDescriptor.Type.ENUM) {
+                    item = enumToSymbol(context, fieldDescriptor.getEnumType(), item);
+                }
 
-            repeatedField.push(context, row);
+                values[i] = item;
+            }
         }
+        repeatedField.push(context, values);
+
         return repeatedField;
     }
 
-    private RubyMap newMapForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+    private RubyMap newMapForField(ThreadContext context, FieldDescriptor fieldDescriptor) {
         RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
-        Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
-        Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
+        FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
+        FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
         IRubyObject keyType = RubySymbol.newSymbol(context.runtime, keyField.getType().name());
         IRubyObject valueType = RubySymbol.newSymbol(context.runtime, valueField.getType().name());
-        if (valueField.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
+
+        if (valueField.getType() == FieldDescriptor.Type.MESSAGE) {
             RubyFieldDescriptor rubyFieldDescriptor = (RubyFieldDescriptor) mapDescriptor.lookup(context,
                     context.runtime.newString("value"));
-            RubyDescriptor rubyDescriptor = (RubyDescriptor) rubyFieldDescriptor.getSubType(context);
+            RubyDescriptor rubyDescriptor = (RubyDescriptor) rubyFieldDescriptor.getSubtype(context);
             return (RubyMap) cMap.newInstance(context, keyType, valueType,
                     rubyDescriptor.msgclass(context), Block.NULL_BLOCK);
+
+        } else if (valueField.getType() == FieldDescriptor.Type.ENUM) {
+            RubyFieldDescriptor rubyFieldDescriptor = (RubyFieldDescriptor) mapDescriptor.lookup(context,
+                    context.runtime.newString("value"));
+            RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) rubyFieldDescriptor.getSubtype(context);
+            return (RubyMap) cMap.newInstance(context, keyType, valueType,
+                    rubyEnumDescriptor.enummodule(context), Block.NULL_BLOCK);
+
         } else {
             return (RubyMap) cMap.newInstance(context, keyType, valueType, Block.NULL_BLOCK);
         }
     }
 
-    private Descriptors.FieldDescriptor getOneofCase(Descriptors.OneofDescriptor oneof) {
+    private FieldDescriptor getOneofCase(OneofDescriptor oneof) {
         if (oneofCases.containsKey(oneof)) {
             return oneofCases.get(oneof);
         }
         return builder.getOneofFieldDescriptor(oneof);
     }
 
-    private Descriptors.Descriptor descriptor;
+    private boolean isWrappable(FieldDescriptor fieldDescriptor) {
+      if (fieldDescriptor.getType() != FieldDescriptor.Type.MESSAGE) return false;
+
+      return isWrapper(fieldDescriptor.getMessageType());
+    }
+
+    private static boolean isWrapper(Descriptor messageDescriptor) {
+      switch(messageDescriptor.getFullName()) {
+          case "google.protobuf.DoubleValue":
+          case "google.protobuf.FloatValue":
+          case "google.protobuf.Int64Value":
+          case "google.protobuf.UInt64Value":
+          case "google.protobuf.Int32Value":
+          case "google.protobuf.UInt32Value":
+          case "google.protobuf.BoolValue":
+          case "google.protobuf.StringValue":
+          case "google.protobuf.BytesValue":
+              return true;
+          default:
+              return false;
+      }
+    }
+
+    private void validateMessageType(ThreadContext context, FieldDescriptor fieldDescriptor, String methodName) {
+        if (descriptor != fieldDescriptor.getContainingType()) {
+            throw context.runtime.newTypeError(methodName + " method called on wrong message type");
+        }
+    }
+
+    private static RubyClass parseErrorClass;
+
+    private static final String AS_VALUE_SUFFIX = "_as_value";
+    private static final String CLEAR_PREFIX = "clear_";
+    private static final String CONST_SUFFIX = "_const";
+    private static final String HAS_PREFIX = "has_";
+    private static final String QUESTION_MARK = "?";
+    private static final int SINK_MAXIMUM_NESTING = 63;
+
+    private Descriptor descriptor;
     private DynamicMessage.Builder builder;
+    private Map<FieldDescriptor, IRubyObject> fields;
+    private Map<OneofDescriptor, FieldDescriptor> oneofCases;
     private RubyClass cRepeatedField;
     private RubyClass cMap;
-    private Map<Descriptors.FieldDescriptor, RubyRepeatedField> repeatedFields;
-    private Map<Descriptors.FieldDescriptor, RubyMap> maps;
-    private Map<Descriptors.FieldDescriptor, IRubyObject> fields;
-    private Map<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor> oneofCases;
+    private boolean ignoreUnknownFieldsOnInit = false;
+    private boolean proto3;
 
-    private static final int SINK_MAXIMUM_NESTING = 64;
+
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java
index a619b80..211236c 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java
@@ -32,7 +32,9 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.OneofDescriptorProto;
 import org.jruby.*;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
@@ -45,52 +47,58 @@
 @JRubyClass(name = "MessageBuilderContext")
 public class RubyMessageBuilderContext extends RubyObject {
     public static void createRubyMessageBuilderContext(Ruby runtime) {
-        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
-        RubyClass cMessageBuilderContext = protobuf.defineClassUnder("MessageBuilderContext", runtime.getObject(), new ObjectAllocator() {
+        RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal");
+        RubyClass cMessageBuilderContext = internal.defineClassUnder("MessageBuilderContext", runtime.getObject(), new ObjectAllocator() {
             @Override
             public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
                 return new RubyMessageBuilderContext(runtime, klazz);
             }
         });
         cMessageBuilderContext.defineAnnotatedMethods(RubyMessageBuilderContext.class);
+
+        cFieldDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
+        cOneofBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::OneofBuilderContext");
     }
 
-    public RubyMessageBuilderContext(Ruby ruby, RubyClass klazz) {
-        super(ruby, klazz);
+    public RubyMessageBuilderContext(Ruby runtime, RubyClass klazz) {
+        super(runtime, klazz);
     }
 
     @JRubyMethod
-    public IRubyObject initialize(ThreadContext context, IRubyObject descriptor, IRubyObject rubyBuilder) {
-        this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
-        this.cDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Descriptor");
-        this.cOneofDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::OneofDescriptor");
-        this.cOneofBuilderContext = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Internal::OneofBuilderContext");
-        this.descriptor = (RubyDescriptor) descriptor;
-        this.builder = (RubyBuilder) rubyBuilder;
+    public IRubyObject initialize(ThreadContext context, IRubyObject fileBuilderContext, IRubyObject name) {
+        this.fileBuilderContext = (RubyFileBuilderContext) fileBuilderContext;
+        this.builder = this.fileBuilderContext.getNewMessageBuilder();
+        this.builder.setName(name.asJavaString());
+
         return this;
     }
 
     /*
      * call-seq:
-     *     MessageBuilderContext.optional(name, type, number, type_class = nil)
+     *     MessageBuilderContext.optional(name, type, number, type_class = nil,
+     *                                    options = nil)
      *
      * Defines a new optional field on this message type with the given type, tag
      * number, and type class (for message and enum fields). The type must be a Ruby
      * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
      * string, if present (as accepted by FieldDescriptor#submsg_name=).
      */
-    @JRubyMethod(required = 3, optional = 1)
+    @JRubyMethod(required = 3, optional = 2)
     public IRubyObject optional(ThreadContext context, IRubyObject[] args) {
-        Ruby runtime = context.runtime;
-        IRubyObject typeClass = runtime.getNil();
-        if (args.length > 3) typeClass = args[3];
-        msgdefAddField(context, "optional", args[0], args[1], args[2], typeClass);
-        return context.runtime.getNil();
+        addField(context, OPTIONAL, args, false);
+        return context.nil;
+    }
+
+    @JRubyMethod(required = 3, optional = 2)
+    public IRubyObject proto3_optional(ThreadContext context, IRubyObject[] args) {
+      addField(context, OPTIONAL, args, true);
+      return context.nil;
     }
 
     /*
      * call-seq:
-     *     MessageBuilderContext.required(name, type, number, type_class = nil)
+     *     MessageBuilderContext.required(name, type, number, type_class = nil,
+     *                                    options = nil)
      *
      * Defines a new required field on this message type with the given type, tag
      * number, and type class (for message and enum fields). The type must be a Ruby
@@ -101,12 +109,11 @@
      * completeness. Any attempt to add a message type with required fields to a
      * pool will currently result in an error.
      */
-    @JRubyMethod(required = 3, optional = 1)
+    @JRubyMethod(required = 3, optional = 2)
     public IRubyObject required(ThreadContext context, IRubyObject[] args) {
-        IRubyObject typeClass = context.runtime.getNil();
-        if (args.length > 3) typeClass = args[3];
-        msgdefAddField(context, "required", args[0], args[1], args[2], typeClass);
-        return context.runtime.getNil();
+        if (fileBuilderContext.isProto3()) throw Utils.createTypeError(context, "Required fields are unsupported in proto3");
+        addField(context, "required", args, false);
+        return context.nil;
     }
 
     /*
@@ -120,10 +127,8 @@
      */
     @JRubyMethod(required = 3, optional = 1)
     public IRubyObject repeated(ThreadContext context, IRubyObject[] args) {
-        IRubyObject typeClass = context.runtime.getNil();
-        if (args.length > 3) typeClass = args[3];
-        msgdefAddField(context, "repeated", args[0], args[1], args[2], typeClass);
-        return context.runtime.getNil();
+        addField(context, "repeated", args, false);
+        return context.nil;
     }
 
     /*
@@ -141,77 +146,110 @@
     @JRubyMethod(required = 4, optional = 1)
     public IRubyObject map(ThreadContext context, IRubyObject[] args) {
         Ruby runtime = context.runtime;
+        if (!fileBuilderContext.isProto3()) throw runtime.newArgumentError("Cannot add a native map field using proto2 syntax.");
+
+        RubySymbol messageSym = runtime.newSymbol("message");
+
         IRubyObject name = args[0];
         IRubyObject keyType = args[1];
         IRubyObject valueType = args[2];
         IRubyObject number = args[3];
-        IRubyObject typeClass = args.length > 4 ? args[4] : context.runtime.getNil();
+        IRubyObject typeClass = args.length > 4 ? args[4] : context.nil;
 
         // Validate the key type. We can't accept enums, messages, or floats/doubles
         // as map keys. (We exclude these explicitly, and the field-descriptor setter
         // below then ensures that the type is one of the remaining valid options.)
-        if (keyType.equals(RubySymbol.newSymbol(runtime, "float")) ||
-                keyType.equals(RubySymbol.newSymbol(runtime, "double")) ||
-                keyType.equals(RubySymbol.newSymbol(runtime, "enum")) ||
-                keyType.equals(RubySymbol.newSymbol(runtime, "message")))
+        if (keyType.equals(runtime.newSymbol("float")) ||
+                keyType.equals(runtime.newSymbol("double")) ||
+                keyType.equals(runtime.newSymbol("enum")) ||
+                keyType.equals(messageSym))
             throw runtime.newArgumentError("Cannot add a map field with a float, double, enum, or message type.");
 
-        // Create a new message descriptor for the map entry message, and create a
-        // repeated submessage field here with that type.
-        RubyDescriptor mapentryDesc = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
-        IRubyObject mapentryDescName = RubySymbol.newSymbol(runtime, name).id2name(context);
-        mapentryDesc.setName(context, mapentryDescName);
-        mapentryDesc.setMapEntry(true);
+        DescriptorProto.Builder mapEntryBuilder = fileBuilderContext.getNewMessageBuilder();
+        mapEntryBuilder.setName(builder.getName() + "_MapEntry_" + name.asJavaString());
+        mapEntryBuilder.getOptionsBuilder().setMapEntry(true);
 
-        //optional <type> key = 1;
-        RubyFieldDescriptor keyField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
-        keyField.setName(context, runtime.newString("key"));
-        keyField.setLabel(context, RubySymbol.newSymbol(runtime, "optional"));
-        keyField.setNumber(context, runtime.newFixnum(1));
-        keyField.setType(context, keyType);
-        mapentryDesc.addField(context, keyField);
+        mapEntryBuilder.addField(
+            Utils.createFieldBuilder(
+                context,
+                OPTIONAL,
+                new IRubyObject[] {
+                    runtime.newString("key"),
+                    keyType,
+                    runtime.newFixnum(1)
+                }
+            )
+        );
 
-        //optional <type> value = 2;
-        RubyFieldDescriptor valueField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
-        valueField.setName(context, runtime.newString("value"));
-        valueField.setLabel(context, RubySymbol.newSymbol(runtime, "optional"));
-        valueField.setNumber(context, runtime.newFixnum(2));
-        valueField.setType(context, valueType);
-        if (! typeClass.isNil()) valueField.setSubmsgName(context, typeClass);
-        mapentryDesc.addField(context, valueField);
+        mapEntryBuilder.addField(
+            Utils.createFieldBuilder(
+                context,
+                OPTIONAL,
+                new IRubyObject[] {
+                    runtime.newString("value"),
+                    valueType,
+                    runtime.newFixnum(2),
+                    typeClass
+                }
+            )
+        );
 
-        // Add the map-entry message type to the current builder, and use the type to
-        // create the map field itself.
-        this.builder.pendingList.add(mapentryDesc);
+        IRubyObject[] addFieldArgs = {
+            name, messageSym, number, runtime.newString(mapEntryBuilder.getName())
+        };
 
-        msgdefAddField(context, "repeated", name, runtime.newSymbol("message"), number, mapentryDescName);
-        return runtime.getNil();
+        repeated(context, addFieldArgs);
+
+        return context.nil;
     }
 
+    /*
+     * call-seq:
+     *     MessageBuilderContext.oneof(name, &block) => nil
+     *
+     * Creates a new OneofDescriptor with the given name, creates a
+     * OneofBuilderContext attached to that OneofDescriptor, evaluates the given
+     * block in the context of that OneofBuilderContext with #instance_eval, and
+     * then adds the oneof to the message.
+     *
+     * This is the recommended, idiomatic way to build oneof definitions.
+     */
     @JRubyMethod
     public IRubyObject oneof(ThreadContext context, IRubyObject name, Block block) {
-        RubyOneofDescriptor oneofdef = (RubyOneofDescriptor)
-                cOneofDescriptor.newInstance(context, Block.NULL_BLOCK);
         RubyOneofBuilderContext ctx = (RubyOneofBuilderContext)
-                cOneofBuilderContext.newInstance(context, oneofdef, Block.NULL_BLOCK);
-        oneofdef.setName(context, name);
-        Binding binding = block.getBinding();
-        binding.setSelf(ctx);
-        block.yieldSpecific(context);
-        descriptor.addOneof(context, oneofdef);
-        return context.runtime.getNil();
+                cOneofBuilderContext.newInstance(
+                        context,
+                        context.runtime.newFixnum(builder.getOneofDeclCount()),
+                        this,
+                        Block.NULL_BLOCK
+                );
+
+        builder.addOneofDeclBuilder().setName(name.asJavaString());
+        ctx.instance_eval(context, block);
+
+        return context.nil;
     }
 
-    private void msgdefAddField(ThreadContext context, String label, IRubyObject name,
-                                IRubyObject type, IRubyObject number, IRubyObject typeClass) {
-        descriptor.addField(context,
-                Utils.msgdefCreateField(context, label, name, type, number, typeClass, cFieldDescriptor));
+    protected void addFieldBuilder(FieldDescriptorProto.Builder fieldBuilder) {
+        builder.addField(fieldBuilder);
     }
 
-    private RubyDescriptor descriptor;
-    private RubyBuilder builder;
-    private RubyClass cFieldDescriptor;
-    private RubyClass cOneofDescriptor;
-    private RubyClass cOneofBuilderContext;
+    private FieldDescriptorProto.Builder addField(ThreadContext context, String label, IRubyObject[] args, boolean proto3Optional) {
+        FieldDescriptorProto.Builder fieldBuilder =
+                Utils.createFieldBuilder(context, label, args);
+
+        fieldBuilder.setProto3Optional(proto3Optional);
+        builder.addField(fieldBuilder);
+
+        return fieldBuilder;
+    }
+
+    private static RubyClass cFieldDescriptor;
+    private static RubyClass cOneofBuilderContext;
+
+    private static final String OPTIONAL = "optional";
+
+    private DescriptorProto.Builder builder;
     private RubyClass cDescriptor;
+    private RubyFileBuilderContext fileBuilderContext;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java
index c9b99e0..1ce500e 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java
@@ -32,9 +32,12 @@
 
 package com.google.protobuf.jruby;
 
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
 import org.jruby.Ruby;
 import org.jruby.RubyClass;
+import org.jruby.RubyHash;
 import org.jruby.RubyModule;
+import org.jruby.RubyNumeric;
 import org.jruby.RubyObject;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
@@ -45,8 +48,7 @@
 @JRubyClass(name = "OneofBuilderContext")
 public class RubyOneofBuilderContext extends RubyObject {
     public static void createRubyOneofBuilderContext(Ruby runtime) {
-        RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
-        RubyModule internal = protobuf.defineModuleUnder("Internal");
+        RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal");
         RubyClass cRubyOneofBuidlerContext = internal.defineClassUnder("OneofBuilderContext", runtime.getObject(), new ObjectAllocator() {
             @Override
             public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
@@ -60,25 +62,42 @@
         super(ruby, rubyClass);
     }
 
+    /*
+     * call-seq:
+     *     OneofBuilderContext.new(oneof_index, message_builder) => context
+     *
+     * Create a new oneof builder context around the given oneof descriptor and
+     * builder context. This class is intended to serve as a DSL context to be used
+     * with #instance_eval.
+     */
     @JRubyMethod
-    public IRubyObject initialize(ThreadContext context, IRubyObject oneofdef) {
-        this.descriptor = (RubyOneofDescriptor) oneofdef;
-        this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
+    public IRubyObject initialize(ThreadContext context, IRubyObject index, IRubyObject messageBuilder) {
+        this.builder = (RubyMessageBuilderContext) messageBuilder;
+        this.index = RubyNumeric.num2int(index);
+
         return this;
     }
 
-    @JRubyMethod(required = 3, optional = 1)
+    /*
+     * call-seq:
+     *     OneofBuilderContext.optional(name, type, number, type_class = nil,
+     *                                  options = nil)
+     *
+     * Defines a new optional field in this oneof with the given type, tag number,
+     * and type class (for message and enum fields). The type must be a Ruby symbol
+     * (as accepted by FieldDescriptor#type=) and the type_class must be a string,
+     * if present (as accepted by FieldDescriptor#submsg_name=).
+     */
+    @JRubyMethod(required = 3, optional = 2)
     public IRubyObject optional(ThreadContext context, IRubyObject[] args) {
-        IRubyObject name = args[0];
-        IRubyObject type = args[1];
-        IRubyObject number = args[2];
-        IRubyObject typeClass = args.length > 3 ? args[3] : context.runtime.getNil();
-        RubyFieldDescriptor fieldDescriptor = Utils.msgdefCreateField(context, "optional",
-                name, type, number, typeClass, cFieldDescriptor);
-        descriptor.addField(context, fieldDescriptor);
-        return this;
+        FieldDescriptorProto.Builder fieldBuilder =
+                Utils.createFieldBuilder(context, "optional", args);
+        fieldBuilder.setOneofIndex(index);
+        builder.addFieldBuilder(fieldBuilder);
+
+        return context.nil;
     }
 
-    private RubyOneofDescriptor descriptor;
-    private RubyClass cFieldDescriptor;
+    private RubyMessageBuilderContext builder;
+    private int index;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
index cc4ab66..6f2ebdb 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
@@ -1,7 +1,7 @@
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.DescriptorProtos;
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
 import org.jruby.Ruby;
 import org.jruby.RubyClass;
 import org.jruby.RubyModule;
@@ -13,7 +13,10 @@
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 @JRubyClass(name = "OneofDescriptor", include = "Enumerable")
 public class RubyOneofDescriptor extends RubyObject {
@@ -32,13 +35,7 @@
 
     public RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass) {
         super(ruby, rubyClass);
-    }
-
-    @JRubyMethod
-    public IRubyObject initialize(ThreadContext context) {
-        builder = DescriptorProtos.OneofDescriptorProto.newBuilder();
         fields = new ArrayList<RubyFieldDescriptor>();
-        return this;
     }
 
     /*
@@ -54,42 +51,6 @@
 
     /*
      * call-seq:
-     *     OneofDescriptor.name = name
-     *
-     * Sets a new name for this oneof. The oneof must not have been added to a
-     * message descriptor yet.
-     */
-    @JRubyMethod(name = "name=")
-    public IRubyObject setName(ThreadContext context, IRubyObject name) {
-        this.name = context.runtime.newString(name.asJavaString());
-        this.builder.setName(name.asJavaString());
-        return context.runtime.getNil();
-    }
-
-    /*
-     * call-seq:
-     *     OneofDescriptor.add_field(field) => nil
-     *
-     * Adds a field to this oneof. The field may have been added to this oneof in
-     * the past, or the message to which this oneof belongs (if any), but may not
-     * have already been added to any other oneof or message. Otherwise, an
-     * exception is raised.
-     *
-     * All fields added to the oneof via this method will be automatically added to
-     * the message to which this oneof belongs, if it belongs to one currently, or
-     * else will be added to any message to which the oneof is later added at the
-     * time that it is added.
-     */
-    @JRubyMethod(name = "add_field")
-    public IRubyObject addField(ThreadContext context, IRubyObject obj) {
-        RubyFieldDescriptor fieldDescriptor = (RubyFieldDescriptor) obj;
-        fieldDescriptor.setOneofName(this.name);
-        fields.add(fieldDescriptor);
-        return context.runtime.getNil();
-    }
-
-    /*
-     * call-seq:
      *     OneofDescriptor.each(&block) => nil
      *
      * Iterates through fields in this oneof, yielding to the block on each one.
@@ -99,26 +60,27 @@
         for (RubyFieldDescriptor field : fields) {
             block.yieldSpecific(context, field);
         }
-        return context.runtime.getNil();
-    }
-
-    public DescriptorProtos.OneofDescriptorProto build(int index) {
-        for (RubyFieldDescriptor field: fields) {
-            field.setOneofIndex(index);
-        }
-        return this.builder.build();
+        return context.nil;
     }
 
     protected Collection<RubyFieldDescriptor> getFields() {
         return fields;
     }
 
-    protected Descriptors.OneofDescriptor getOneofDescriptor() {
-        RubyFieldDescriptor fieldDescriptor = fields.get(0);
-        return fieldDescriptor.getFieldDef().getContainingOneof();
+    protected OneofDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    protected void setDescriptor(ThreadContext context, OneofDescriptor descriptor, Map<FieldDescriptor, RubyFieldDescriptor> fieldCache) {
+        this.descriptor = descriptor;
+        this.name = context.runtime.newString(descriptor.getName());
+
+        for (FieldDescriptor fd : descriptor.getFields()) {
+            fields.add(fieldCache.get(fd));
+        }
     }
 
     private IRubyObject name;
-    private DescriptorProtos.OneofDescriptorProto.Builder builder;
     private List<RubyFieldDescriptor> fields;
+    private OneofDescriptor descriptor;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
index 2cf210d..582c675 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
@@ -46,6 +46,7 @@
         RubyModule mGoogle = runtime.getModule("Google");
         RubyModule mProtobuf = mGoogle.defineModuleUnder("Protobuf");
         mProtobuf.defineAnnotatedMethods(RubyProtobuf.class);
+        RubyModule mInternal = mProtobuf.defineModuleUnder("Internal");
     }
 
     /*
@@ -65,4 +66,17 @@
             return ((RubyMap) message).deepCopy(context);
         }
     }
+
+    /*
+     * call-seq:
+     *     Google::Protobuf.discard_unknown(msg)
+     *
+     * Discard unknown fields in the given message object and recursively discard
+     * unknown fields in submessages.
+     */
+    @JRubyMethod(name = "discard_unknown", meta = true)
+    public static IRubyObject discardUnknown(ThreadContext context, IRubyObject self, IRubyObject message) {
+        ((RubyMessage) message).discardUnknownFields(context);
+        return context.nil;
+    }
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
index ae2907a..995171f 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
@@ -32,7 +32,7 @@
 
 package com.google.protobuf.jruby;
 
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.Descriptors.FieldDescriptor;
 import org.jruby.*;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
@@ -61,7 +61,7 @@
         super(runtime, klazz);
     }
 
-    public RubyRepeatedField(Ruby runtime, RubyClass klazz, Descriptors.FieldDescriptor.Type fieldType, IRubyObject typeClass) {
+    public RubyRepeatedField(Ruby runtime, RubyClass klazz, FieldDescriptor.Type fieldType, IRubyObject typeClass) {
         this(runtime, klazz);
         this.fieldType = fieldType;
         this.storage = runtime.newArray();
@@ -77,8 +77,8 @@
             throw runtime.newArgumentError("Expected Symbol for type name");
         }
         this.fieldType = Utils.rubyToFieldType(args[0]);
-        if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE
-                || fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
+        if (fieldType == FieldDescriptor.Type.MESSAGE
+                || fieldType == FieldDescriptor.Type.ENUM) {
             if (args.length < 2)
                 throw runtime.newArgumentError("Expected at least 2 arguments for message/enum");
             typeClass = args[1];
@@ -110,7 +110,7 @@
     @JRubyMethod(name = "[]=")
     public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
         int arrIndex = normalizeArrayIndex(index);
-        value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+        value = Utils.checkType(context, fieldType, name, value, (RubyModule) typeClass);
         IRubyObject defaultValue = defaultValue(context);
         for (int i = this.storage.size(); i < arrIndex; i++) {
             this.storage.set(i, defaultValue);
@@ -138,9 +138,12 @@
                 return this.storage.eltInternal(arrIndex);
             } else if (arg instanceof RubyRange) {
                 RubyRange range = ((RubyRange) arg);
+
                 int beg = RubyNumeric.num2int(range.first(context));
-                int to = RubyNumeric.num2int(range.last(context));
-                int len = to - beg + 1;
+                int len = RubyNumeric.num2int(range.size(context));
+
+                if (len == 0) return context.runtime.newEmptyArray();
+
                 return this.storage.subseq(beg, len);
             }
         }
@@ -162,14 +165,17 @@
      *
      * Adds a new element to the repeated field.
      */
-    @JRubyMethod(name = {"push", "<<"})
-    public IRubyObject push(ThreadContext context, IRubyObject value) {
-        if (!(fieldType == Descriptors.FieldDescriptor.Type.MESSAGE &&
-            value == context.runtime.getNil())) {
-            value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+    @JRubyMethod(name = {"push", "<<"}, required = 1, rest = true)
+    public IRubyObject push(ThreadContext context, IRubyObject[] args) {
+        for (int i = 0; i < args.length; i++) {
+            IRubyObject val = args[i];
+            if (fieldType != FieldDescriptor.Type.MESSAGE || !val.isNil()) {
+                val = Utils.checkType(context, fieldType, name, val, (RubyModule) typeClass);
+            }
+            storage.add(val);
         }
-        this.storage.add(value);
-        return this.storage;
+
+        return this;
     }
 
     /*
@@ -193,7 +199,7 @@
         RubyArray arr = (RubyArray) list;
         checkArrayElementType(context, arr);
         this.storage = arr;
-        return this.storage;
+        return this;
     }
 
     /*
@@ -205,7 +211,7 @@
     @JRubyMethod
     public IRubyObject clear(ThreadContext context) {
         this.storage.clear();
-        return this.storage;
+        return this;
     }
 
     /*
@@ -261,7 +267,7 @@
                 throw context.runtime.newArgumentError("Attempt to append RepeatedField with different element type.");
             this.storage.addAll((RubyArray) repeatedField.toArray(context));
         }
-        return this.storage;
+        return this;
     }
 
     /*
@@ -301,7 +307,7 @@
     @JRubyMethod
     public IRubyObject each(ThreadContext context, Block block) {
         this.storage.each(context, block);
-        return this.storage;
+        return this;
     }
 
 
@@ -320,12 +326,15 @@
     @JRubyMethod
     public IRubyObject dup(ThreadContext context) {
         RubyRepeatedField dup = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
-        for (int i = 0; i < this.storage.size(); i++) {
-            dup.push(context, this.storage.eltInternal(i));
-        }
+        dup.push(context, storage.toJavaArray());
         return dup;
     }
 
+    @JRubyMethod
+    public IRubyObject inspect() {
+        return storage.inspect();
+    }
+
     // Java API
     protected IRubyObject get(int index) {
         return this.storage.eltInternal(index);
@@ -335,7 +344,7 @@
         RubyRepeatedField copy = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
         for (int i = 0; i < size(); i++) {
             IRubyObject value = storage.eltInternal(i);
-            if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
+            if (fieldType == FieldDescriptor.Type.MESSAGE) {
                 copy.storage.add(((RubyMessage) value).deepCopy(context));
             } else {
                 copy.storage.add(value);
@@ -344,6 +353,10 @@
         return copy;
     }
 
+    protected void setName(String name) {
+        this.name = name;
+    }
+
     protected int size() {
         return this.storage.size();
     }
@@ -390,7 +403,7 @@
 
     private void checkArrayElementType(ThreadContext context, RubyArray arr) {
         for (int i = 0; i < arr.getLength(); i++) {
-            Utils.checkType(context, fieldType, arr.eltInternal(i), (RubyModule) typeClass);
+            Utils.checkType(context, fieldType, name, arr.eltInternal(i), (RubyModule) typeClass);
         }
     }
 
@@ -403,7 +416,8 @@
         return arrIndex;
     }
 
-    private RubyArray storage;
-    private Descriptors.FieldDescriptor.Type fieldType;
+    private FieldDescriptor.Type fieldType;
     private IRubyObject typeClass;
+    private RubyArray storage;
+    private String name;
 }
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
index f199feb..17c1c8d 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
@@ -33,29 +33,30 @@
 package com.google.protobuf.jruby;
 
 import com.google.protobuf.ByteString;
-import com.google.protobuf.DescriptorProtos;
-import com.google.protobuf.Descriptors;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.Descriptors.FieldDescriptor;
 import org.jcodings.Encoding;
 import org.jcodings.specific.ASCIIEncoding;
-import org.jcodings.specific.USASCIIEncoding;
-import org.jcodings.specific.UTF8Encoding;
 import org.jruby.*;
+import org.jruby.exceptions.RaiseException;
+import org.jruby.ext.bigdecimal.RubyBigDecimal;
 import org.jruby.runtime.Block;
+import org.jruby.runtime.Helpers;
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
 
 import java.math.BigInteger;
 
 public class Utils {
-    public static Descriptors.FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) {
-        return Descriptors.FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase());
+    public static FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) {
+        return FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase());
     }
 
-    public static IRubyObject fieldTypeToRuby(ThreadContext context, Descriptors.FieldDescriptor.Type type) {
+    public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptor.Type type) {
         return fieldTypeToRuby(context, type.name());
     }
 
-    public static IRubyObject fieldTypeToRuby(ThreadContext context, DescriptorProtos.FieldDescriptorProto.Type type) {
+    public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptorProto.Type type) {
         return fieldTypeToRuby(context, type.name());
     }
 
@@ -64,64 +65,115 @@
         return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase());
     }
 
-    public static IRubyObject checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType,
-                                        IRubyObject value, RubyModule typeClass) {
+    public static IRubyObject checkType(ThreadContext context, FieldDescriptor.Type fieldType,
+                                        String fieldName, IRubyObject value, RubyModule typeClass) {
         Ruby runtime = context.runtime;
-        Object val;
+
         switch(fieldType) {
             case INT32:
             case INT64:
             case UINT32:
             case UINT64:
-                if (!isRubyNum(value)) {
-                    throw runtime.newTypeError("Expected number type for integral field.");
+                if (!isRubyNum(value))
+                    throw createExpectedTypeError(context, "number", "integral", fieldName, value);
+
+                if (value instanceof RubyFloat) {
+                    double doubleVal = RubyNumeric.num2dbl(value);
+                    if (Math.floor(doubleVal) != doubleVal) {
+                        throw runtime.newRangeError("Non-integral floating point value assigned to integer field '" + fieldName + "' (given " + value.getMetaClass() + ").");
+                    }
                 }
+                if (fieldType == FieldDescriptor.Type.UINT32 || fieldType == FieldDescriptor.Type.UINT64) {
+                    if (((RubyNumeric) value).isNegative()) {
+                        throw runtime.newRangeError("Assigning negative value to unsigned integer field '" + fieldName + "' (given " + value.getMetaClass() + ").");
+                    }
+                }
+
                 switch(fieldType) {
                     case INT32:
                         RubyNumeric.num2int(value);
                         break;
-                    case INT64:
-                        RubyNumeric.num2long(value);
-                        break;
                     case UINT32:
                         num2uint(value);
                         break;
-                    default:
+                    case UINT64:
                         num2ulong(context.runtime, value);
                         break;
+                    default:
+                        RubyNumeric.num2long(value);
+                        break;
                 }
-                checkIntTypePrecision(context, fieldType, value);
                 break;
             case FLOAT:
                 if (!isRubyNum(value))
-                    throw runtime.newTypeError("Expected number type for float field.");
+                    throw createExpectedTypeError(context, "number", "float", fieldName, value);
                 break;
             case DOUBLE:
                 if (!isRubyNum(value))
-                    throw runtime.newTypeError("Expected number type for double field.");
+                    throw createExpectedTypeError(context, "number", "double", fieldName, value);
                 break;
             case BOOL:
                 if (!(value instanceof RubyBoolean))
-                    throw runtime.newTypeError("Invalid argument for boolean field.");
+                    throw createInvalidTypeError(context, "boolean", fieldName, value);
                 break;
             case BYTES:
+                value = validateAndEncodeString(context, "bytes", fieldName, value, "Encoding::ASCII_8BIT");
+                break;
             case STRING:
-                value = validateStringEncoding(context, fieldType, value);
+                value = validateAndEncodeString(context, "string", fieldName, symToString(value), "Encoding::UTF_8");
                 break;
             case MESSAGE:
                 if (value.getMetaClass() != typeClass) {
-                    throw runtime.newTypeError(value, typeClass);
+                    // See if we can convert the value before flagging it as invalid
+                    String className = typeClass.getName();
+
+                    if (className.equals("Google::Protobuf::Timestamp") && value instanceof RubyTime) {
+                        RubyTime rt = (RubyTime) value;
+                        RubyHash timestampArgs =
+                            Helpers.constructHash(runtime,
+                                runtime.newString("nanos"), rt.nsec(), false,
+                                runtime.newString("seconds"), rt.to_i(), false);
+                        return ((RubyClass) typeClass).newInstance(context, timestampArgs, Block.NULL_BLOCK);
+
+                    } else if (className.equals("Google::Protobuf::Duration") && value instanceof RubyNumeric) {
+                        IRubyObject seconds;
+                        if (value instanceof RubyFloat) {
+                            seconds = ((RubyFloat) value).truncate(context);
+                        } else if (value instanceof RubyRational) {
+                            seconds = ((RubyRational) value).to_i(context);
+                        } else if (value instanceof RubyBigDecimal) {
+                            seconds = ((RubyBigDecimal) value).to_int(context);
+                        } else {
+                            seconds = ((RubyInteger) value).to_i();
+                        }
+
+                        IRubyObject nanos = ((RubyNumeric) value).remainder(context, RubyFixnum.one(runtime));
+                        if (nanos instanceof RubyFloat) {
+                            nanos = ((RubyFloat) nanos).op_mul(context, 1000000000);
+                        } else if (nanos instanceof RubyRational) {
+                            nanos = ((RubyRational) nanos).op_mul(context, runtime.newFixnum(1000000000));
+                        } else if (nanos instanceof RubyBigDecimal) {
+                            nanos = ((RubyBigDecimal) nanos).op_mul(context, runtime.newFixnum(1000000000));
+                        } else {
+                            nanos = ((RubyInteger) nanos).op_mul(context, 1000000000);
+                        }
+
+                        RubyHash durationArgs =
+                            Helpers.constructHash(runtime,
+                                runtime.newString("nanos"), ((RubyNumeric) nanos).round(context), false,
+                                runtime.newString("seconds"), seconds, false);
+                        return ((RubyClass) typeClass).newInstance(context, durationArgs, Block.NULL_BLOCK);
+                    }
+
+                    // Not able to convert so flag as invalid
+                    throw createTypeError(context, "Invalid type " + value.getMetaClass() + " to assign to submessage field '" + fieldName + "'.");
                 }
+
                 break;
             case ENUM:
-                if (value instanceof RubySymbol) {
-                    Descriptors.EnumDescriptor enumDescriptor =
-                            ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).getDescriptor();
-                    val = enumDescriptor.findValueByName(value.asJavaString());
-                    if (val == null)
-                        throw runtime.newRangeError("Enum value " + value + " is not found.");
-                } else if(!isRubyNum(value)) {
-                    throw runtime.newTypeError("Expected number or symbol type for enum field.");
+                boolean isValid = ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).isValidValue(context, value);
+                if (!isValid) {
+                    throw runtime.newRangeError("Unknown symbol value for enum field '" + fieldName + "'.");
                 }
                 break;
             default:
@@ -130,7 +182,7 @@
         return value;
     }
 
-    public static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, Object value) {
+    public static IRubyObject wrapPrimaryValue(ThreadContext context, FieldDescriptor.Type fieldType, Object value) {
         Ruby runtime = context.runtime;
         switch (fieldType) {
             case INT32:
@@ -150,7 +202,7 @@
             case BOOL:
                 return (Boolean) value ? runtime.getTrue() : runtime.getFalse();
             case BYTES: {
-                IRubyObject wrapped = runtime.newString(((ByteString) value).toStringUtf8());
+                IRubyObject wrapped = RubyString.newString(runtime, ((ByteString) value).toStringUtf8(), ASCIIEncoding.INSTANCE);
                 wrapped.setFrozen(true);
                 return wrapped;
             }
@@ -187,21 +239,14 @@
         }
     }
 
-    public static IRubyObject validateStringEncoding(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
-        if (!(value instanceof RubyString))
-            throw context.runtime.newTypeError("Invalid argument for string field.");
-        switch(type) {
-            case BYTES:
-                value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::ASCII_8BIT"));
-                break;
-            case STRING:
-                value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::UTF_8"));
-                break;
-            default:
-                break;
+    /*
+     * Helper to make it easier to support symbols being passed instead of strings
+     */
+    public static IRubyObject symToString(IRubyObject sym) {
+        if (sym instanceof RubySymbol) {
+            return ((RubySymbol) sym).id2name();
         }
-        value.setFrozen(true);
-        return value;
+        return sym;
     }
 
     public static void checkNameAvailability(ThreadContext context, String name) {
@@ -209,67 +254,84 @@
             throw context.runtime.newNameError(name + " is already defined", name);
     }
 
-    /**
-     * Replace invalid "." in descriptor with __DOT__
-     * @param name
-     * @return
-     */
-    public static String escapeIdentifier(String name) {
-        return name.replace(".", BADNAME_REPLACEMENT);
-    }
-
-    /**
-     * Replace __DOT__ in descriptor name with "."
-     * @param name
-     * @return
-     */
-    public static String unescapeIdentifier(String name) {
-        return name.replace(BADNAME_REPLACEMENT, ".");
-    }
-
-    public static boolean isMapEntry(Descriptors.FieldDescriptor fieldDescriptor) {
-        return fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
+    public static boolean isMapEntry(FieldDescriptor fieldDescriptor) {
+        return fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE &&
                 fieldDescriptor.isRepeated() &&
                 fieldDescriptor.getMessageType().getOptions().getMapEntry();
     }
 
-    public static RubyFieldDescriptor msgdefCreateField(ThreadContext context, String label, IRubyObject name,
-                                      IRubyObject type, IRubyObject number, IRubyObject typeClass, RubyClass cFieldDescriptor) {
+    /*
+     * call-seq:
+     *     Utils.createFieldBuilder(context, label, name, type, number, typeClass = nil, options = nil)
+     *
+     * Most places calling this are already dealing with an optional number of
+     * arguments so dealing with them here. This helper is a standard way to
+     * create a FieldDescriptor builder that handles some of the options that
+     * are used in different places.
+     */
+    public static FieldDescriptorProto.Builder createFieldBuilder(ThreadContext context,
+            String label, IRubyObject[] args) {
+
         Ruby runtime = context.runtime;
-        RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
-        fieldDef.setLabel(context, runtime.newString(label));
-        fieldDef.setName(context, name);
-        fieldDef.setType(context, type);
-        fieldDef.setNumber(context, number);
+        IRubyObject options = context.nil;
+        IRubyObject typeClass = context.nil;
+
+        if (args.length > 4) {
+            options = args[4];
+            typeClass = args[3];
+        } else if (args.length > 3) {
+            if (args[3] instanceof RubyHash) {
+                options = args[3];
+            } else {
+                typeClass = args[3];
+            }
+        }
+
+        FieldDescriptorProto.Builder builder = FieldDescriptorProto.newBuilder();
+
+        builder.setLabel(FieldDescriptorProto.Label.valueOf("LABEL_" + label.toUpperCase()))
+            .setName(args[0].asJavaString())
+            .setNumber(RubyNumeric.num2int(args[2]))
+            .setType(FieldDescriptorProto.Type.valueOf("TYPE_" + args[1].asJavaString().toUpperCase()));
 
         if (!typeClass.isNil()) {
             if (!(typeClass instanceof RubyString)) {
                 throw runtime.newArgumentError("expected string for type class");
             }
-            fieldDef.setSubmsgName(context, typeClass);
+            builder.setTypeName("." + typeClass.asJavaString());
         }
-        return fieldDef;
+
+        if (options instanceof RubyHash) {
+            IRubyObject defaultValue = ((RubyHash) options).fastARef(runtime.newSymbol("default"));
+            if (defaultValue != null) {
+                builder.setDefaultValue(defaultValue.toString());
+            }
+        }
+
+        return builder;
     }
 
-    protected static void checkIntTypePrecision(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
-        if (value instanceof RubyFloat) {
-            double doubleVal = RubyNumeric.num2dbl(value);
-            if (Math.floor(doubleVal) != doubleVal) {
-                throw context.runtime.newRangeError("Non-integral floating point value assigned to integer field.");
-            }
+
+    public static RaiseException createTypeError(ThreadContext context, String message) {
+        if (cTypeError == null) {
+            cTypeError = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::TypeError");
         }
-        if (type == Descriptors.FieldDescriptor.Type.UINT32 || type == Descriptors.FieldDescriptor.Type.UINT64) {
-            if (RubyNumeric.num2dbl(value) < 0) {
-                throw context.runtime.newRangeError("Assigning negative value to unsigned integer field.");
-            }
-        }
+        return RaiseException.from(context.runtime, cTypeError, message);
+    }
+
+    public static RaiseException createExpectedTypeError(ThreadContext context, String type, String fieldType, String fieldName, IRubyObject value) {
+        return createTypeError(context, String.format(EXPECTED_TYPE_ERROR_FORMAT, type, fieldType, fieldName, value.getMetaClass()));
+    }
+
+    public static RaiseException createInvalidTypeError(ThreadContext context, String fieldType, String fieldName, IRubyObject value) {
+        return createTypeError(context, String.format(INVALID_TYPE_ERROR_FORMAT, fieldType, fieldName, value.getMetaClass()));
     }
 
     protected static boolean isRubyNum(Object value) {
         return value instanceof RubyFixnum || value instanceof RubyFloat || value instanceof RubyBignum;
     }
 
-    protected static void validateTypeClass(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+    protected static void validateTypeClass(ThreadContext context, FieldDescriptor.Type type, IRubyObject value) {
         Ruby runtime = context.runtime;
         if (!(value instanceof RubyModule)) {
             throw runtime.newArgumentError("TypeClass has incorrect type");
@@ -280,24 +342,36 @@
             throw runtime.newArgumentError("Type class has no descriptor. Please pass a " +
                     "class or enum as returned by the DescriptorPool.");
         }
-        if (type == Descriptors.FieldDescriptor.Type.MESSAGE) {
+        if (type == FieldDescriptor.Type.MESSAGE) {
             if (! (descriptor instanceof RubyDescriptor)) {
                 throw runtime.newArgumentError("Descriptor has an incorrect type");
             }
-        } else if (type == Descriptors.FieldDescriptor.Type.ENUM) {
+        } else if (type == FieldDescriptor.Type.ENUM) {
             if (! (descriptor instanceof RubyEnumDescriptor)) {
                 throw runtime.newArgumentError("Descriptor has an incorrect type");
             }
         }
     }
 
-    public static String BADNAME_REPLACEMENT = "__DOT__";
+    private static IRubyObject validateAndEncodeString(ThreadContext context, String fieldType, String fieldName, IRubyObject value, String encoding) {
+        if (!(value instanceof RubyString))
+            throw createInvalidTypeError(context, fieldType, fieldName, value);
 
-    public static String DESCRIPTOR_INSTANCE_VAR = "@descriptor";
+        value = ((RubyString) value).encode(context, context.runtime.evalScriptlet(encoding));
+        value.setFrozen(true);
+        return value;
+    }
 
-    public static String EQUAL_SIGN = "=";
+    public static final String DESCRIPTOR_INSTANCE_VAR = "@descriptor";
 
-    private static BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64)
+    public static final String EQUAL_SIGN = "=";
 
-    private static long UINT_MAX = 0xffffffffl;
+    private static final BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64)
+
+    private static final String EXPECTED_TYPE_ERROR_FORMAT = "Expected %s type for %s field '%s' (given %s).";
+    private static final String INVALID_TYPE_ERROR_FORMAT = "Invalid argument for %s field '%s' (given %s).";
+
+    private static final long UINT_MAX = 0xffffffffl;
+
+    private static RubyClass cTypeError;
 }
diff --git a/ruby/src/main/java/google/ProtobufJavaService.java b/ruby/src/main/java/google/ProtobufJavaService.java
index bffb492..a364719 100644
--- a/ruby/src/main/java/google/ProtobufJavaService.java
+++ b/ruby/src/main/java/google/ProtobufJavaService.java
@@ -42,19 +42,26 @@
     @Override
     public boolean basicLoad(Ruby ruby) throws IOException {
         ruby.defineModule("Google");
+
+        /*
+         * The order these happen in is important because we
+         * save a static reference to some classes and they
+         * need to exist before we try to save a reference to them
+         */
         RubyProtobuf.createProtobuf(ruby);
-        RubyDescriptor.createRubyDescriptor(ruby);
         RubyBuilder.createRubyBuilder(ruby);
-        RubyFieldDescriptor.createRubyFileDescriptor(ruby);
-        RubyMessageBuilderContext.createRubyMessageBuilderContext(ruby);
+        RubyFileDescriptor.createRubyFileDescriptor(ruby);
         RubyEnumDescriptor.createRubyEnumDescriptor(ruby);
         RubyEnumBuilderContext.createRubyEnumBuilderContext(ruby);
-        RubyDescriptorPool.createRubyDescriptorPool(ruby);
         RubyRepeatedField.createRubyRepeatedField(ruby);
-        RubyFieldDescriptor.createRubyFileDescriptor(ruby);
+        RubyFieldDescriptor.createRubyFieldDescriptor(ruby);
         RubyMap.createRubyMap(ruby);
         RubyOneofDescriptor.createRubyOneofDescriptor(ruby);
         RubyOneofBuilderContext.createRubyOneofBuilderContext(ruby);
+        RubyMessageBuilderContext.createRubyMessageBuilderContext(ruby);
+        RubyDescriptor.createRubyDescriptor(ruby);
+        RubyFileBuilderContext.createRubyFileBuilderContext(ruby);
+        RubyDescriptorPool.createRubyDescriptorPool(ruby);
         return true;
     }
 }
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index d1a66a6..6beb4b7 100755
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -31,12 +31,51 @@
     end
     include CommonTests
 
+    def test_issue_8311_crash
+      Google::Protobuf::DescriptorPool.generated_pool.build do
+        add_file("inner.proto", :syntax => :proto3) do
+          add_message "Inner" do
+            # Removing either of these fixes the segfault.
+            optional :foo, :string, 1
+            optional :bar, :string, 2
+          end
+        end
+      end
+
+      Google::Protobuf::DescriptorPool.generated_pool.build do
+        add_file("outer.proto", :syntax => :proto3) do
+          add_message "Outer" do
+            repeated :inners, :message, 1, "Inner"
+          end
+        end
+      end
+
+      outer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Outer").msgclass
+
+      outer.new(
+          inners: []
+      )['inners'].to_s
+
+      assert_raise Google::Protobuf::TypeError do
+        outer.new(
+            inners: [nil]
+        ).to_s
+      end
+    end
+
+    def test_issue_8559_crash
+      msg = TestMessage.new
+      msg.repeated_int32 = ::Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
+      GC.start(full_mark: true, immediate_sweep: true)
+      TestMessage.encode(msg)
+    end
+
     def test_has_field
-      m = TestMessage.new
-      assert !m.has_optional_msg?
-      m.optional_msg = TestMessage2.new
-      assert m.has_optional_msg?
-      assert TestMessage.descriptor.lookup('optional_msg').has?(m)
+      m = TestSingularFields.new
+      assert !m.has_singular_msg?
+      m.singular_msg = TestMessage2.new
+      assert m.has_singular_msg?
+      assert TestSingularFields.descriptor.lookup('singular_msg').has?(m)
 
       m = OneofMessage.new
       assert !m.has_my_oneof?
@@ -45,33 +84,32 @@
       assert_raise NoMethodError do
         m.has_a?
       end
+      assert_true OneofMessage.descriptor.lookup('a').has?(m)
+
+      m = TestSingularFields.new
+      assert_raise NoMethodError do
+        m.has_singular_int32?
+      end
       assert_raise ArgumentError do
-        OneofMessage.descriptor.lookup('a').has?(m)
+        TestSingularFields.descriptor.lookup('singular_int32').has?(m)
+      end
+
+      assert_raise NoMethodError do
+        m.has_singular_string?
+      end
+      assert_raise ArgumentError do
+        TestSingularFields.descriptor.lookup('singular_string').has?(m)
+      end
+
+      assert_raise NoMethodError do
+        m.has_singular_bool?
+      end
+      assert_raise ArgumentError do
+        TestSingularFields.descriptor.lookup('singular_bool').has?(m)
       end
 
       m = TestMessage.new
       assert_raise NoMethodError do
-        m.has_optional_int32?
-      end
-      assert_raise ArgumentError do
-        TestMessage.descriptor.lookup('optional_int32').has?(m)
-      end
-
-      assert_raise NoMethodError do
-        m.has_optional_string?
-      end
-      assert_raise ArgumentError do
-        TestMessage.descriptor.lookup('optional_string').has?(m)
-      end
-
-      assert_raise NoMethodError do
-        m.has_optional_bool?
-      end
-      assert_raise ArgumentError do
-        TestMessage.descriptor.lookup('optional_bool').has?(m)
-      end
-
-      assert_raise NoMethodError do
         m.has_repeated_msg?
       end
       assert_raise ArgumentError do
@@ -79,41 +117,60 @@
       end
     end
 
+    def test_no_presence
+      m = TestSingularFields.new
+
+      # Explicitly setting to zero does not cause anything to be serialized.
+      m.singular_int32 = 0
+      assert_equal "", TestSingularFields.encode(m)
+
+      # Explicitly setting to a non-zero value *does* cause serialization.
+      m.singular_int32 = 1
+      assert_not_equal "", TestSingularFields.encode(m)
+
+      m.singular_int32 = 0
+      assert_equal "", TestSingularFields.encode(m)
+    end
+
     def test_set_clear_defaults
+      m = TestSingularFields.new
+
+      m.singular_int32 = -42
+      assert_equal -42, m.singular_int32
+      m.clear_singular_int32
+      assert_equal 0, m.singular_int32
+
+      m.singular_int32 = 50
+      assert_equal 50, m.singular_int32
+      TestSingularFields.descriptor.lookup('singular_int32').clear(m)
+      assert_equal 0, m.singular_int32
+
+      m.singular_string = "foo bar"
+      assert_equal "foo bar", m.singular_string
+      m.clear_singular_string
+      assert_equal "", m.singular_string
+
+      m.singular_string = "foo"
+      assert_equal "foo", m.singular_string
+      TestSingularFields.descriptor.lookup('singular_string').clear(m)
+      assert_equal "", m.singular_string
+
+      m.singular_msg = TestMessage2.new(:foo => 42)
+      assert_equal TestMessage2.new(:foo => 42), m.singular_msg
+      assert m.has_singular_msg?
+      m.clear_singular_msg
+      assert_equal nil, m.singular_msg
+      assert !m.has_singular_msg?
+
+      m.singular_msg = TestMessage2.new(:foo => 42)
+      assert_equal TestMessage2.new(:foo => 42), m.singular_msg
+      TestSingularFields.descriptor.lookup('singular_msg').clear(m)
+      assert_equal nil, m.singular_msg
+    end
+
+    def test_clear_repeated_fields
       m = TestMessage.new
 
-      m.optional_int32 = -42
-      assert_equal -42, m.optional_int32
-      m.clear_optional_int32
-      assert_equal 0, m.optional_int32
-
-      m.optional_int32 = 50
-      assert_equal 50, m.optional_int32
-      TestMessage.descriptor.lookup('optional_int32').clear(m)
-      assert_equal 0, m.optional_int32
-
-      m.optional_string = "foo bar"
-      assert_equal "foo bar", m.optional_string
-      m.clear_optional_string
-      assert_equal "", m.optional_string
-
-      m.optional_string = "foo"
-      assert_equal "foo", m.optional_string
-      TestMessage.descriptor.lookup('optional_string').clear(m)
-      assert_equal "", m.optional_string
-
-      m.optional_msg = TestMessage2.new(:foo => 42)
-      assert_equal TestMessage2.new(:foo => 42), m.optional_msg
-      assert m.has_optional_msg?
-      m.clear_optional_msg
-      assert_equal nil, m.optional_msg
-      assert !m.has_optional_msg?
-
-      m.optional_msg = TestMessage2.new(:foo => 42)
-      assert_equal TestMessage2.new(:foo => 42), m.optional_msg
-      TestMessage.descriptor.lookup('optional_msg').clear(m)
-      assert_equal nil, m.optional_msg
-
       m.repeated_int32.push(1)
       assert_equal [1], m.repeated_int32
       m.clear_repeated_int32
@@ -128,6 +185,7 @@
       m.a = "foo"
       assert_equal "foo", m.a
       assert m.has_my_oneof?
+      assert_equal :a, m.my_oneof
       m.clear_a
       assert !m.has_my_oneof?
 
@@ -143,7 +201,6 @@
       assert !m.has_my_oneof?
     end
 
-
     def test_initialization_map_errors
       e = assert_raise ArgumentError do
         TestMessage.new(:hello => "world")
@@ -198,7 +255,7 @@
         m.map_string_int32 = {}
       end
 
-      assert_raise TypeError do
+      assert_raise Google::Protobuf::TypeError do
         m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
       end
     end
@@ -223,8 +280,12 @@
         :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
                             "b" => TestMessage2.new(:foo => 2)},
         :map_string_enum => {"a" => :A, "b" => :B})
-      expected = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
-      assert_equal expected, m.inspect
+
+      # JRuby doesn't keep consistent ordering so check for either version
+      expected_a = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
+      expected_b = "<BasicTest::MapMessage: map_string_int32: {\"a\"=>1, \"b\"=>2}, map_string_msg: {\"a\"=><BasicTest::TestMessage2: foo: 1>, \"b\"=><BasicTest::TestMessage2: foo: 2>}, map_string_enum: {\"a\"=>:A, \"b\"=>:B}>"
+      inspect_result = m.inspect
+      assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}"
     end
 
     def test_map_corruption
@@ -425,6 +486,7 @@
         :optional_int32=>0,
         :optional_int64=>0,
         :optional_msg=>nil,
+        :optional_msg2=>nil,
         :optional_string=>"foo",
         :optional_uint32=>0,
         :optional_uint64=>0,
@@ -462,9 +524,9 @@
       m = MapMessage.new(:map_string_int32 => {"a" => 1})
       expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
       expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
-      assert_equal JSON.parse(MapMessage.encode_json(m), :symbolize_names => true), expected
+      assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
 
-      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
+      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
       assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
 
       m2 = MapMessage.decode_json(MapMessage.encode_json(m))
@@ -474,7 +536,7 @@
     def test_json_maps_emit_defaults_submsg
       # TODO: Fix JSON in JRuby version.
       return if RUBY_PLATFORM == "java"
-      m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
+      m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
       expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
 
       actual = MapMessage.encode_json(m, :emit_defaults => true)
@@ -482,6 +544,30 @@
       assert_equal JSON.parse(actual, :symbolize_names => true), expected
     end
 
+    def test_json_emit_defaults_submsg
+      # TODO: Fix JSON in JRuby version.
+      return if RUBY_PLATFORM == "java"
+      m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
+
+      expected = {
+        singularInt32: 0,
+        singularInt64: "0",
+        singularUint32: 0,
+        singularUint64: "0",
+        singularBool: false,
+        singularFloat: 0,
+        singularDouble: 0,
+        singularString: "",
+        singularBytes: "",
+        singularMsg: {},
+        singularEnum: "Default",
+      }
+
+      actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
+
+      assert_equal expected, JSON.parse(actual, :symbolize_names => true)
+    end
+
     def test_respond_to
       # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
       return if RUBY_PLATFORM == "java"
diff --git a/ruby/tests/basic_proto2.rb b/ruby/tests/basic_proto2.rb
index 4c7ddd5..a7114ea 100755
--- a/ruby/tests/basic_proto2.rb
+++ b/ruby/tests/basic_proto2.rb
@@ -73,10 +73,11 @@
       m = OneofMessage.new
       assert !m.has_my_oneof?
       m.a = "foo"
+      assert m.has_my_oneof?
+      assert_equal :a, m.my_oneof
       assert m.has_a?
       assert OneofMessage.descriptor.lookup('a').has?(m)
       assert_equal "foo", m.a
-      assert m.has_my_oneof?
       assert !m.has_b?
       assert !OneofMessage.descriptor.lookup('b').has?(m)
       assert !m.has_c?
@@ -197,6 +198,17 @@
       assert !m.has_my_oneof?
     end
 
+    def test_assign_nil
+      m = TestMessageDefaults.new
+      m.optional_msg = TestMessage2.new(:foo => 42)
+
+      assert_equal TestMessage2.new(:foo => 42), m.optional_msg
+      assert m.has_optional_msg?
+      m.optional_msg = nil
+      assert_equal nil, m.optional_msg
+      assert !m.has_optional_msg?
+    end
+
     def test_initialization_map_errors
       e = assert_raise ArgumentError do
         TestMessage.new(:hello => "world")
@@ -225,23 +237,6 @@
       assert_equal expected_result, m.to_h
     end
 
-    def test_map_keyword_disabled
-      pool = Google::Protobuf::DescriptorPool.new
-
-      e = assert_raise ArgumentError do
-        pool.build do
-          add_file 'test_file.proto', syntax: :proto2 do
-            add_message "MapMessage" do
-              map :map_string_int32, :string, :int32, 1
-              map :map_string_msg, :string, :message, 2, "TestMessage2"
-            end
-          end
-        end
-      end
-
-      assert_match(/Cannot add a native map/, e.message)
-    end
-
     def test_respond_to
       # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
       return if RUBY_PLATFORM == "java"
diff --git a/ruby/tests/basic_test.proto b/ruby/tests/basic_test.proto
index a918540..5b4ed63 100644
--- a/ruby/tests/basic_test.proto
+++ b/ruby/tests/basic_test.proto
@@ -21,17 +21,17 @@
 }
 
 message TestMessage {
-  int32 optional_int32 = 1;
-  int64 optional_int64 = 2;
-  uint32 optional_uint32 = 3;
-  uint64 optional_uint64 = 4;
-  bool optional_bool = 5;
-  float optional_float = 6;
-  double optional_double = 7;
-  string optional_string = 8;
-  bytes optional_bytes = 9;
-  TestMessage2 optional_msg = 10;
-  TestEnum optional_enum = 11;
+  optional int32 optional_int32 = 1;
+  optional int64 optional_int64 = 2;
+  optional uint32 optional_uint32 = 3;
+  optional uint64 optional_uint64 = 4;
+  optional bool optional_bool = 5;
+  optional float optional_float = 6;
+  optional double optional_double = 7;
+  optional string optional_string = 8;
+  optional bytes optional_bytes = 9;
+  optional TestMessage2 optional_msg = 10;
+  optional TestEnum optional_enum = 11;
 
   repeated int32 repeated_int32 = 12;
   repeated int64 repeated_int64 = 13;
@@ -44,10 +44,26 @@
   repeated bytes repeated_bytes = 20;
   repeated TestMessage2 repeated_msg = 21;
   repeated TestEnum repeated_enum = 22;
+
+  optional TestSingularFields optional_msg2 = 23;
+}
+
+message TestSingularFields {
+  int32 singular_int32 = 1;
+  int64 singular_int64 = 2;
+  uint32 singular_uint32 = 3;
+  uint64 singular_uint64 = 4;
+  bool singular_bool = 5;
+  float singular_float = 6;
+  double singular_double = 7;
+  string singular_string = 8;
+  bytes singular_bytes = 9;
+  TestMessage2 singular_msg = 10;
+  TestEnum singular_enum = 11;
 }
 
 message TestMessage2 {
-  int32 foo = 1;
+  optional int32 foo = 1;
 }
 
 enum TestEnum {
diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb
index 1f5013a..7021d60 100644
--- a/ruby/tests/common_tests.rb
+++ b/ruby/tests/common_tests.rb
@@ -115,14 +115,14 @@
     m = proto_module::TestMessage.new(
       :optional_int32 => -42,
       :optional_enum => :A,
-      :optional_msg => proto_module::TestMessage2.new,
+      :optional_msg => proto_module::TestMessage2.new(foo: 0),
       :repeated_string => ["hello", "there", "world"])
-    expected = "<#{proto_module}::TestMessage: optional_int32: -42, optional_int64: 0, optional_uint32: 0, optional_uint64: 0, optional_bool: false, optional_float: 0.0, optional_double: 0.0, optional_string: \"\", optional_bytes: \"\", optional_msg: <#{proto_module}::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: [\"hello\", \"there\", \"world\"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>"
+    expected = "<#{proto_module}::TestMessage: optional_int32: -42, optional_msg: <#{proto_module}::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: [\"hello\", \"there\", \"world\"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>"
     assert_equal expected, m.inspect
     assert_equal expected, m.to_s
 
     m = proto_module::OneofMessage.new(:b => -42)
-    expected = "<#{proto_module}::OneofMessage: a: \"\", b: -42, c: nil, d: :Default>"
+    expected = "<#{proto_module}::OneofMessage: b: -42>"
     assert_equal expected, m.inspect
     assert_equal expected, m.to_s
   end
@@ -428,7 +428,7 @@
     assert m.length == 0
     assert m == {}
 
-    assert_raise TypeError do
+    assert_raise Google::Protobuf::TypeError do
       m[1] = 1
     end
     assert_raise RangeError do
@@ -436,6 +436,18 @@
     end
   end
 
+  def test_b_8385
+    m1 = Google::Protobuf::Map.new(:string, :string)
+    m2 = Google::Protobuf::Map.new(:string, :string)
+
+    assert_equal m1, m2
+
+    m1["counter"] = "a"
+    m2["counter"] = "aa"
+
+    assert_not_equal m1, m2
+  end
+
   def test_map_ctor
     m = Google::Protobuf::Map.new(:string, :int32,
                                   {"a" => 1, "b" => 2, "c" => 3})
@@ -492,7 +504,7 @@
 
     m = Google::Protobuf::Map.new(:string, :int32)
     m["asdf"] = 1
-    assert_raise TypeError do
+    assert_raise Google::Protobuf::TypeError do
       m[1] = 1
     end
     assert_raise Encoding::UndefinedConversionError do
@@ -505,7 +517,7 @@
     m[bytestring] = 1
     # Allowed -- we will automatically convert to ASCII-8BIT.
     m["asdf"] = 1
-    assert_raise TypeError do
+    assert_raise Google::Protobuf::TypeError do
       m[1] = 1
     end
   end
@@ -547,6 +559,7 @@
         "b" => proto_module::TestMessage.new(:optional_int32 => 84) })
 
     m2 = m.dup
+    assert m.to_h == m2.to_h
     assert m == m2
     assert m.object_id != m2.object_id
     assert m["a"].object_id == m2["a"].object_id
@@ -686,12 +699,13 @@
     assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
   end
 
-  def test_eq
+  def test_message_eq
     m = proto_module::TestMessage.new(:optional_int32 => 42,
                                       :repeated_int32 => [1, 2, 3])
     m2 = proto_module::TestMessage.new(:optional_int32 => 43,
                                        :repeated_int32 => [1, 2, 3])
     assert m != m2
+    assert_not_equal proto_module::TestMessage.new, proto_module::TestMessage2.new
   end
 
   def test_enum_lookup
@@ -1103,16 +1117,6 @@
     m = proto_module::TestMessage.new
 
     expected = {
-      optionalInt32: 0,
-      optionalInt64: "0",
-      optionalUint32: 0,
-      optionalUint64: "0",
-      optionalBool: false,
-      optionalFloat: 0,
-      optionalDouble: 0,
-      optionalString: "",
-      optionalBytes: "",
-      optionalEnum: "Default",
       repeatedInt32: [],
       repeatedInt64: [],
       repeatedUint32: [],
@@ -1137,17 +1141,7 @@
     m = proto_module::TestMessage.new(optional_msg: proto_module::TestMessage2.new)
 
     expected = {
-      optionalInt32: 0,
-      optionalInt64: "0",
-      optionalUint32: 0,
-      optionalUint64: "0",
-      optionalBool: false,
-      optionalFloat: 0,
-      optionalDouble: 0,
-      optionalString: "",
-      optionalBytes: "",
-      optionalMsg: {foo: 0},
-      optionalEnum: "Default",
+      optionalMsg: {},
       repeatedInt32: [],
       repeatedInt64: [],
       repeatedUint32: [],
@@ -1172,16 +1166,6 @@
     m = proto_module::TestMessage.new(repeated_msg: [proto_module::TestMessage2.new])
 
     expected = {
-      optionalInt32: 0,
-      optionalInt64: "0",
-      optionalUint32: 0,
-      optionalUint64: "0",
-      optionalBool: false,
-      optionalFloat: 0,
-      optionalDouble: 0,
-      optionalString: "",
-      optionalBytes: "",
-      optionalEnum: "Default",
       repeatedInt32: [],
       repeatedInt64: [],
       repeatedUint32: [],
@@ -1191,7 +1175,7 @@
       repeatedDouble: [],
       repeatedString: [],
       repeatedBytes: [],
-      repeatedMsg: [{foo: 0}],
+      repeatedMsg: [{}],
       repeatedEnum: []
     }
 
@@ -1256,8 +1240,9 @@
     assert_equal json, struct.to_json
 
     assert_raise(RuntimeError, "Maximum recursion depth exceeded during encoding") do
-      proto_module::MyRepeatedStruct.encode(
-        proto_module::MyRepeatedStruct.new(structs: [proto_module::MyStruct.new(struct: struct)]))
+      struct = Google::Protobuf::Struct.new
+      struct.fields["foobar"] = Google::Protobuf::Value.new(struct_value: struct)
+      Google::Protobuf::Struct.encode(struct)
     end
   end
 
@@ -1729,6 +1714,12 @@
     m = proto_module::TimeMessage.new(duration: 1.1)
     assert_equal Google::Protobuf::Duration.new(seconds: 1, nanos: 100_000_000), m.duration
 
+    m = proto_module::TimeMessage.new(duration: 123.321)
+    assert_equal Google::Protobuf::Duration.new(seconds: 123, nanos: 321_000_000), m.duration
+
+    m = proto_module::TimeMessage.new(duration: -123.321)
+    assert_equal Google::Protobuf::Duration.new(seconds: -123, nanos: -321_000_000), m.duration
+
     assert_raise(Google::Protobuf::TypeError) { m.duration = '2' }
     assert_raise(Google::Protobuf::TypeError) { m.duration = proto_module::TimeMessage.new }
   end
@@ -1786,4 +1777,25 @@
     assert m1.hash != m2.hash
     assert_nil h[m2]
   end
+
+  def test_object_gc
+    m = proto_module::TestMessage.new(optional_msg: proto_module::TestMessage2.new)
+    m.optional_msg
+    GC.start(full_mark: true, immediate_sweep: true)
+    m.optional_msg.inspect
+  end
+
+  def test_object_gc_freeze
+    m = proto_module::TestMessage.new
+    m.repeated_float.freeze
+    GC.start(full_mark: true)
+
+    # Make sure we remember that the object is frozen.
+    # The wrapper object contains this information, so we need to ensure that
+    # the previous GC did not collect it.
+    assert m.repeated_float.frozen?
+
+    GC.start(full_mark: true, immediate_sweep: true)
+    assert m.repeated_float.frozen?
+  end
 end
diff --git a/ruby/tests/encode_decode_test.rb b/ruby/tests/encode_decode_test.rb
index d3cebab..429ac43 100755
--- a/ruby/tests/encode_decode_test.rb
+++ b/ruby/tests/encode_decode_test.rb
@@ -4,6 +4,7 @@
 $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
 
 require 'generated_code_pb'
+require 'google/protobuf/well_known_types'
 require 'test/unit'
 
 def hex2bin(s)
@@ -94,4 +95,10 @@
     end
   end
 
+  def test_json_name
+    msg = A::B::C::TestJsonName.new(:value => 42)
+    json = msg.to_json
+    assert_match json, "{\"CustomJsonName\":42}"
+  end
+
 end
diff --git a/ruby/tests/gc_test.rb b/ruby/tests/gc_test.rb
index 55b9628..d7fecae 100755
--- a/ruby/tests/gc_test.rb
+++ b/ruby/tests/gc_test.rb
@@ -4,7 +4,9 @@
 $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
 
 old_gc = GC.stress
-GC.stress = 0x01 | 0x04
+# Ruby 2.7.0 - 2.7.1 has a GC bug in its parser, so turn off stress for now
+# See https://bugs.ruby-lang.org/issues/16807
+GC.stress = 0x01 | 0x04 unless RUBY_VERSION.match?(/^2\.7\./)
 require 'generated_code_pb'
 require 'generated_code_proto2_pb'
 GC.stress = old_gc
@@ -93,9 +95,15 @@
     data = A::B::C::TestMessage.encode(from)
     to = A::B::C::TestMessage.decode(data)
 
-    from = get_msg_proto2
-    data = A::B::Proto2::TestMessage.encode(from)
-    to = A::B::Proto2::TestMessage.decode(data)
+    # This doesn't work for proto2 on JRuby because there is a nested required message.
+    # A::B::Proto2::TestMessage has :required_msg which is of type:
+    # A::B::Proto2::TestMessage so there is no way to generate a valid
+    # message that doesn't exceed the depth limit
+    if !defined? JRUBY_VERSION
+        from = get_msg_proto2
+        data = A::B::Proto2::TestMessage.encode(from)
+        to = A::B::Proto2::TestMessage.decode(data)
+    end
     GC.stress = old_gc
     puts "passed"
   end
diff --git a/ruby/tests/generated_code.proto b/ruby/tests/generated_code.proto
index e811669..bfdfa5a 100644
--- a/ruby/tests/generated_code.proto
+++ b/ruby/tests/generated_code.proto
@@ -83,3 +83,7 @@
   map<string, TestUnknown> map_unknown = 67;
   int32 unknown_field = 89;
 }
+
+message TestJsonName {
+  int32 value = 1 [json_name = "CustomJsonName"];
+}
diff --git a/ruby/tests/multi_level_nesting_test.proto b/ruby/tests/multi_level_nesting_test.proto
new file mode 100644
index 0000000..84c3fa4
--- /dev/null
+++ b/ruby/tests/multi_level_nesting_test.proto
@@ -0,0 +1,19 @@
+syntax = "proto3";
+
+message Function {
+  string name = 1;
+  repeated Function.Parameter parameters = 2;
+  string return_type = 3;
+
+  message Parameter {
+    string name = 1;
+    Function.Parameter.Value value = 2;
+
+    message Value {
+      oneof type {
+        string string = 1;
+        int64 integer = 2;
+      }
+    }
+  }
+}
diff --git a/ruby/tests/multi_level_nesting_test.rb b/ruby/tests/multi_level_nesting_test.rb
new file mode 100644
index 0000000..7e5d0ec
--- /dev/null
+++ b/ruby/tests/multi_level_nesting_test.rb
@@ -0,0 +1,20 @@
+#!/usr/bin/ruby
+
+# multi_level_nesting_test_pb.rb is in the same directory as this test.
+$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
+
+require 'test/unit'
+require 'multi_level_nesting_test_pb'
+
+#
+# Provide tests for having messages nested 3 levels deep
+#
+class MultiLevelNestingTest < Test::Unit::TestCase
+
+  def test_levels_exist
+    assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function").msgclass
+    assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function.Parameter").msgclass
+    assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function.Parameter.Value").msgclass
+  end
+
+end
diff --git a/ruby/tests/repeated_field_test.rb b/ruby/tests/repeated_field_test.rb
index 6307447..1df6e1d 100755
--- a/ruby/tests/repeated_field_test.rb
+++ b/ruby/tests/repeated_field_test.rb
@@ -339,18 +339,6 @@
     end
   end
 
-  def test_compact!
-    m = TestMessage.new
-    m.repeated_msg << TestMessage2.new(:foo => 1)
-    m.repeated_msg << nil
-    m.repeated_msg << TestMessage2.new(:foo => 2)
-    reference_arr = m.repeated_string.to_a
-
-    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
-      arr.compact!
-    end
-  end
-
   def test_delete
     m = TestMessage.new
     reference_arr = %w(foo bar baz)
diff --git a/ruby/tests/well_known_types_test.rb b/ruby/tests/well_known_types_test.rb
index 3eafe09..ea042eb 100755
--- a/ruby/tests/well_known_types_test.rb
+++ b/ruby/tests/well_known_types_test.rb
@@ -193,4 +193,12 @@
     assert_equal false, s['b'][:y]
     assert_equal false, s[:b]['y']
   end
+
+  def test_b8325
+    value_field = Google::Protobuf::ListValue.descriptor.lookup("values")
+    proto = Google::Protobuf::ListValue.new(
+        values: [Google::Protobuf::Value.new(string_value: "Hello")]
+    )
+    assert_equal '[<Google::Protobuf::Value: string_value: "Hello">]', value_field.get(proto).inspect
+  end
 end
diff --git a/ruby/travis-test.sh b/ruby/travis-test.sh
index 6dec0c9..faf0f9d 100755
--- a/ruby/travis-test.sh
+++ b/ruby/travis-test.sh
@@ -8,15 +8,17 @@
 
   RUBY_CONFORMANCE=test_ruby
 
-  if [ "$version" == "jruby-1.7" ] ; then
-    # No conformance tests yet -- JRuby is too broken to run them.
+  if [ "$version" == "jruby-9.2.11.1" ] ; then
     bash --login -c \
       "rvm install $version && rvm use $version && rvm get head && \
        which ruby && \
        git clean -f && \
        gem install bundler && bundle && \
-       rake test"
-  elif [ "$version" == "ruby-2.6.0" ] ; then
+       rake test &&
+       rake gc_test &&
+       cd ../conformance && make test_jruby &&
+       cd ../ruby/compatibility_tests/v3.0.0 && ./test.sh"
+  elif [ "$version" == "ruby-2.6.0" -o "$version" == "ruby-2.7.0" -o "$version" == "ruby-3.0.0" ] ; then
     bash --login -c \
       "rvm install $version && rvm use $version && \
        which ruby && \
diff --git a/src/Makefile.am b/src/Makefile.am
index 3212a50..edd3660 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@
 PTHREAD_DEF =
 endif
 
-PROTOBUF_VERSION = 22:4:0
+PROTOBUF_VERSION = 28:3:0
 
 if GCC
 # Turn on all warnings except for sign comparison (we ignore sign comparison
@@ -30,7 +30,7 @@
 
 AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG)
 
-AM_LDFLAGS = $(PTHREAD_CFLAGS)
+AM_LDFLAGS = $(PTHREAD_CFLAGS) ${LIBLOG_LIBS}
 
 # If I say "dist_include_DATA", automake complains that $(includedir) is not
 # a "legitimate" directory for DATA.  Screw you, automake.
@@ -68,7 +68,6 @@
   google/protobuf/stubs/bytestream.h                             \
   google/protobuf/stubs/casts.h                                  \
   google/protobuf/stubs/common.h                                 \
-  google/protobuf/stubs/fastmem.h                                \
   google/protobuf/stubs/hash.h                                   \
   google/protobuf/stubs/logging.h                                \
   google/protobuf/stubs/macros.h                                 \
@@ -96,15 +95,18 @@
   google/protobuf/empty.pb.h                                     \
   google/protobuf/extension_set.h                                \
   google/protobuf/extension_set_inl.h                            \
+  google/protobuf/field_access_listener.h                        \
   google/protobuf/field_mask.pb.h                                \
   google/protobuf/generated_enum_reflection.h                    \
   google/protobuf/generated_enum_util.h                          \
   google/protobuf/generated_message_reflection.h                 \
   google/protobuf/generated_message_table_driven.h               \
+  google/protobuf/generated_message_tctable_decl.h               \
+  google/protobuf/generated_message_tctable_impl.h               \
+  google/protobuf/generated_message_tctable_impl.inc             \
   google/protobuf/generated_message_util.h                       \
   google/protobuf/has_bits.h                                     \
   google/protobuf/implicit_weak_message.h                        \
-  google/protobuf/inlined_string_field.h                         \
   google/protobuf/io/io_win32.h                                \
   google/protobuf/map_entry.h                                    \
   google/protobuf/map_entry_lite.h                               \
@@ -152,6 +154,7 @@
   google/protobuf/compiler/csharp/csharp_generator.h             \
   google/protobuf/compiler/csharp/csharp_names.h                 \
   google/protobuf/compiler/java/java_generator.h                 \
+  google/protobuf/compiler/java/java_kotlin_generator.h          \
   google/protobuf/compiler/java/java_names.h                     \
   google/protobuf/compiler/js/js_generator.h                     \
   google/protobuf/compiler/js/well_known_types_embed.h           \
@@ -202,12 +205,14 @@
   google/protobuf/stubs/time.h                                 \
   google/protobuf/any_lite.cc                                  \
   google/protobuf/arena.cc                                     \
+  google/protobuf/arenastring.cc                               \
   google/protobuf/extension_set.cc                             \
   google/protobuf/generated_enum_util.cc                       \
   google/protobuf/generated_message_util.cc                    \
   google/protobuf/generated_message_table_driven_lite.h        \
   google/protobuf/generated_message_table_driven_lite.cc       \
   google/protobuf/implicit_weak_message.cc                     \
+  google/protobuf/map.cc                                       \
   google/protobuf/message_lite.cc                              \
   google/protobuf/parse_context.cc                             \
   google/protobuf/repeated_field.cc                            \
@@ -236,6 +241,7 @@
   google/protobuf/dynamic_message.cc                           \
   google/protobuf/empty.pb.cc                                  \
   google/protobuf/extension_set_heavy.cc                       \
+  google/protobuf/field_access_listener.cc                     \
   google/protobuf/field_mask.pb.cc                             \
   google/protobuf/generated_message_reflection.cc              \
   google/protobuf/generated_message_table_driven_lite.h        \
@@ -341,9 +347,12 @@
   google/protobuf/compiler/cpp/cpp_message_field.cc            \
   google/protobuf/compiler/cpp/cpp_message_field.h             \
   google/protobuf/compiler/cpp/cpp_message_layout_helper.h     \
+  google/protobuf/compiler/cpp/cpp_names.h                     \
   google/protobuf/compiler/cpp/cpp_options.h                   \
   google/protobuf/compiler/cpp/cpp_padding_optimizer.cc        \
   google/protobuf/compiler/cpp/cpp_padding_optimizer.h         \
+  google/protobuf/compiler/cpp/cpp_parse_function_generator.cc \
+  google/protobuf/compiler/cpp/cpp_parse_function_generator.h  \
   google/protobuf/compiler/cpp/cpp_primitive_field.cc          \
   google/protobuf/compiler/cpp/cpp_primitive_field.h           \
   google/protobuf/compiler/cpp/cpp_service.cc                  \
@@ -373,6 +382,7 @@
   google/protobuf/compiler/java/java_generator_factory.h       \
   google/protobuf/compiler/java/java_helpers.cc                \
   google/protobuf/compiler/java/java_helpers.h                 \
+  google/protobuf/compiler/java/java_kotlin_generator.cc       \
   google/protobuf/compiler/java/java_map_field.cc              \
   google/protobuf/compiler/java/java_map_field.h               \
   google/protobuf/compiler/java/java_map_field_lite.cc         \
@@ -497,9 +507,6 @@
   google/protobuf/unittest_lite.proto                             \
   google/protobuf/unittest_mset.proto                             \
   google/protobuf/unittest_mset_wire_format.proto                 \
-  google/protobuf/unittest_no_arena_lite.proto                    \
-  google/protobuf/unittest_no_arena_import.proto                  \
-  google/protobuf/unittest_no_arena.proto                         \
   google/protobuf/unittest_no_field_presence.proto                \
   google/protobuf/unittest_no_generic_services.proto              \
   google/protobuf/unittest_optimize_for.proto                     \
@@ -573,8 +580,6 @@
   google/protobuf/map_lite_unittest.pb.h                       \
   google/protobuf/unittest_lite.pb.cc                          \
   google/protobuf/unittest_lite.pb.h                           \
-  google/protobuf/unittest_no_arena_lite.pb.cc                 \
-  google/protobuf/unittest_no_arena_lite.pb.h                  \
   google/protobuf/unittest_import_lite.pb.cc                   \
   google/protobuf/unittest_import_lite.pb.h                    \
   google/protobuf/unittest_import_public_lite.pb.cc            \
@@ -620,10 +625,6 @@
   google/protobuf/unittest_mset.pb.h                              \
   google/protobuf/unittest_mset_wire_format.pb.cc                 \
   google/protobuf/unittest_mset_wire_format.pb.h                  \
-  google/protobuf/unittest_no_arena_import.pb.cc                  \
-  google/protobuf/unittest_no_arena_import.pb.h                   \
-  google/protobuf/unittest_no_arena.pb.cc                         \
-  google/protobuf/unittest_no_arena.pb.h                          \
   google/protobuf/unittest_no_field_presence.pb.cc                \
   google/protobuf/unittest_no_field_presence.pb.h                 \
   google/protobuf/unittest_no_generic_services.pb.cc              \
@@ -893,7 +894,9 @@
 no_warning_test.cc:
 	echo "// Generated from Makefile.am" > no_warning_test.cc
 	for FILE in $(nobase_include_HEADERS); do \
-    echo "#include <$${FILE}>" >> no_warning_test.cc; \
+          if [[ $$FILE != *.inc ]]; then \
+	    echo "#include <$${FILE}>" >> no_warning_test.cc; \
+	  fi \
 	done
 	echo "int main(int, char**) { return 0; }" >> no_warning_test.cc
 
diff --git a/src/README.md b/src/README.md
index 007deb3..ec4901d 100644
--- a/src/README.md
+++ b/src/README.md
@@ -40,22 +40,21 @@
 have also cloned the submodules and generated the configure script (skip this
 if you are using a release .tar.gz or .zip package):
 
-```shell
     git clone https://github.com/protocolbuffers/protobuf.git
     cd protobuf
     git submodule update --init --recursive
     ./autogen.sh
-```
+
 To build and install the C++ Protocol Buffer runtime and the Protocol
 Buffer compiler (protoc) execute the following:
 
-```shell
+
      ./configure
      make
      make check
      sudo make install
      sudo ldconfig # refresh shared library cache.
-```
+
 If "make check" fails, you can still install, but it is likely that
 some features of this library will not work correctly on your system.
 Proceed at your own risk.
@@ -123,15 +122,15 @@
 For a Mac system, Unix tools are not available by default. You will first need
 to install Xcode from the Mac AppStore and then run the following command from
 a terminal:
-```shell
+
     sudo xcode-select --install
-```shell
+
 To install Unix tools, you can install "port" following the instructions at
 https://www.macports.org . This will reside in /opt/local/bin/port for most
 Mac installations.
-```shell
+
     sudo /opt/local/bin/port install autoconf automake libtool
-```
+
 Then follow the Unix instructions above.
 
 **Note for cross-compiling**
@@ -230,4 +229,4 @@
 The complete documentation for Protocol Buffers is available via the
 web at:
 
-    https://developers.google.com/protocol-buffers/
+https://developers.google.com/protocol-buffers/
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
index a79214b..955dd80 100644
--- a/src/google/protobuf/any.cc
+++ b/src/google/protobuf/any.cc
@@ -41,24 +41,26 @@
 namespace protobuf {
 namespace internal {
 
-void AnyMetadata::PackFrom(const Message& message) {
-  PackFrom(message, kTypeGoogleApisComPrefix);
+bool AnyMetadata::PackFrom(Arena* arena, const Message& message) {
+  return PackFrom(arena, message, kTypeGoogleApisComPrefix);
 }
 
-void AnyMetadata::PackFrom(const Message& message,
-                           const std::string& type_url_prefix) {
-  type_url_->SetNoArena(
+bool AnyMetadata::PackFrom(Arena* arena,
+                           const Message& message,
+                           StringPiece type_url_prefix) {
+  type_url_->Set(
       &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(),
-      GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix));
-  message.SerializeToString(value_->MutableNoArena(
-      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()));
+      GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix),
+      arena);
+  return message.SerializeToString(
+      value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
 }
 
 bool AnyMetadata::UnpackTo(Message* message) const {
   if (!InternalIs(message->GetDescriptor()->full_name())) {
     return false;
   }
-  return message->ParseFromString(value_->GetNoArena());
+  return message->ParseFromString(value_->Get());
 }
 
 bool GetAnyFieldDescriptors(const Message& message,
@@ -79,3 +81,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
index 59dd50c..3ec8294 100644
--- a/src/google/protobuf/any.h
+++ b/src/google/protobuf/any.h
@@ -60,16 +60,19 @@
   typedef ArenaStringPtr ValueType;
  public:
   // AnyMetadata does not take ownership of "type_url" and "value".
-  AnyMetadata(UrlType* type_url, ValueType* value);
+  constexpr AnyMetadata(UrlType* type_url, ValueType* value)
+      : type_url_(type_url), value_(value) {}
 
   // Packs a message using the default type URL prefix: "type.googleapis.com".
   // The resulted type URL will be "type.googleapis.com/<message_full_name>".
+  // Returns false if serializing the message failed.
   template <typename T>
-  void PackFrom(const T& message) {
-    InternalPackFrom(message, kTypeGoogleApisComPrefix, T::FullMessageName());
+  bool PackFrom(Arena* arena, const T& message) {
+    return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix,
+                            T::FullMessageName());
   }
 
-  void PackFrom(const Message& message);
+  bool PackFrom(Arena* arena, const Message& message);
 
   // Packs a message using the given type URL prefix. The type URL will be
   // constructed by concatenating the message type's full name to the prefix
@@ -77,12 +80,13 @@
   // For example, both PackFrom(message, "type.googleapis.com") and
   // PackFrom(message, "type.googleapis.com/") yield the same result type
   // URL: "type.googleapis.com/<message_full_name>".
+  // Returns false if serializing the message failed.
   template <typename T>
-  void PackFrom(const T& message, StringPiece type_url_prefix) {
-    InternalPackFrom(message, type_url_prefix, T::FullMessageName());
+  bool PackFrom(Arena* arena, const T& message, StringPiece type_url_prefix) {
+    return InternalPackFrom(arena, message, type_url_prefix, T::FullMessageName());
   }
 
-  void PackFrom(const Message& message, const std::string& type_url_prefix);
+  bool PackFrom(Arena* arena, const Message& message, StringPiece type_url_prefix);
 
   // Unpacks the payload into the given message. Returns false if the message's
   // type doesn't match the type specified in the type URL (i.e., the full
@@ -104,7 +108,8 @@
   }
 
  private:
-  void InternalPackFrom(const MessageLite& message,
+  bool InternalPackFrom(Arena* arena,
+                        const MessageLite& message,
                         StringPiece type_url_prefix,
                         StringPiece type_name);
   bool InternalUnpackTo(StringPiece type_name,
@@ -124,14 +129,14 @@
 //
 // NOTE: this function is available publicly as:
 //   google::protobuf::Any()  // static method on the generated message type.
-bool ParseAnyTypeUrl(const std::string& type_url, std::string* full_type_name);
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
 
 // Get the proto type name and prefix from Any::type_url value. For example,
 // passing "type.googleapis.com/rpc.QueryOrigin" will return
 // "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
 // *full_type_name. Returns false if the type_url does not have a "/" in the
 // type url separating the full type name.
-bool ParseAnyTypeUrl(const std::string& type_url, std::string* url_prefix,
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
                      std::string* full_type_name);
 
 // See if message is of type google.protobuf.Any, if so, return the descriptors
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index 1eba999..c6dff7b 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -14,26 +14,24 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class AnyDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Any> _instance;
-} _Any_default_instance_;
+constexpr Any::Any(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , _any_metadata_(&type_url_, &value_){}
+struct AnyDefaultTypeInternal {
+  constexpr AnyDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~AnyDefaultTypeInternal() {}
+  union {
+    Any _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT AnyDefaultTypeInternal _Any_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Any_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Any();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Any::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
@@ -58,32 +56,28 @@
 const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
   "\n\031google/protobuf/any.proto\022\017google.prot"
   "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
-  " \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
-  "%github.com/golang/protobuf/ptypes/any\242\002"
-  "\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p"
-  "roto3"
+  " \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z"
+  ",google.golang.org/protobuf/types/known/"
+  "anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT"
+  "ypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fany_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fany_2eproto_sccs[1] = {
-  &scc_info_Any_google_2fprotobuf_2fany_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", 205,
-  &descriptor_table_google_2fprotobuf_2fany_2eproto_once, descriptor_table_google_2fprotobuf_2fany_2eproto_sccs, descriptor_table_google_2fprotobuf_2fany_2eproto_deps, 1, 0,
+  false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", 
+  &descriptor_table_google_2fprotobuf_2fany_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fany_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
+  file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fany_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fany_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fany_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void Any::InitAsDefaultInstance() {
-}
 bool Any::GetAnyFieldDescriptors(
     const ::PROTOBUF_NAMESPACE_ID::Message& message,
     const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
@@ -91,8 +85,9 @@
   return ::PROTOBUF_NAMESPACE_ID::internal::GetAnyFieldDescriptors(
       message, type_url_field, value_field);
 }
-bool Any::ParseAnyTypeUrl(const string& type_url,
-                                  std::string* full_type_name) {
+bool Any::ParseAnyTypeUrl(
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
+    std::string* full_type_name) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseAnyTypeUrl(type_url,
                                              full_type_name);
 }
@@ -101,11 +96,14 @@
  public:
 };
 
-Any::Any(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+Any::Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _any_metadata_(&type_url_, &value_) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Any)
 }
 Any::Any(const Any& from)
@@ -114,31 +112,31 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_type_url().empty()) {
-    type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_type_url(),
-      GetArena());
+    type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(), 
+      GetArenaForAllocation());
   }
   value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_value().empty()) {
-    value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_value(),
-      GetArena());
+    value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(), 
+      GetArenaForAllocation());
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
 }
 
-void Any::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
-  type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+inline void Any::SharedCtor() {
+type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 Any::~Any() {
   // @@protoc_insertion_point(destructor:google.protobuf.Any)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Any::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Any::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
@@ -152,11 +150,6 @@
 void Any::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Any& Any::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Any::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
@@ -164,18 +157,16 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  type_url_.ClearToEmpty();
+  value_.ClearToEmpty();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Any::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string type_url = 1;
       case 1:
@@ -196,7 +187,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -223,7 +215,7 @@
   (void) cached_has_bits;
 
   // string type_url = 1;
-  if (this->type_url().size() > 0) {
+  if (!this->_internal_type_url().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -233,7 +225,7 @@
   }
 
   // bytes value = 2;
-  if (this->value().size() > 0) {
+  if (!this->_internal_value().empty()) {
     target = stream->WriteBytesMaybeAliased(
         2, this->_internal_value(), target);
   }
@@ -255,14 +247,14 @@
   (void) cached_has_bits;
 
   // string type_url = 1;
-  if (this->type_url().size() > 0) {
+  if (!this->_internal_type_url().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_type_url());
   }
 
   // bytes value = 2;
-  if (this->value().size() > 0) {
+  if (!this->_internal_value().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
         this->_internal_value());
@@ -277,41 +269,32 @@
   return total_size;
 }
 
-void Any::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Any* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Any>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Any::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Any::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Any::GetClassData() const { return &_class_data_; }
+
+void Any::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Any *>(to)->MergeFrom(
+      static_cast<const Any &>(from));
 }
 
+
 void Any::MergeFrom(const Any& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.type_url().size() > 0) {
+  if (!from._internal_type_url().empty()) {
     _internal_set_type_url(from._internal_type_url());
   }
-  if (from.value().size() > 0) {
+  if (!from._internal_value().empty()) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void Any::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Any::CopyFrom(const Any& from) {
@@ -327,16 +310,25 @@
 
 void Any::InternalSwap(Any* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  type_url_.Swap(&other->type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &type_url_, GetArenaForAllocation(),
+      &other->type_url_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &value_, GetArenaForAllocation(),
+      &other->value_, other->GetArenaForAllocation()
+  );
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fany_2eproto_getter, &descriptor_table_google_2fprotobuf_2fany_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fany_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index 187f7d8..b4ab93c 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -45,7 +44,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -53,10 +52,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class Any;
-class AnyDefaultTypeInternal;
+struct AnyDefaultTypeInternal;
 PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -66,11 +65,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT Any PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Any final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
  public:
-  inline Any() : Any(nullptr) {};
-  virtual ~Any();
+  inline Any() : Any(nullptr) {}
+  ~Any() override;
+  explicit constexpr Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Any(const Any& from);
   Any(Any&& from) noexcept
@@ -83,8 +83,9 @@
     return *this;
   }
   inline Any& operator=(Any&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -95,14 +96,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Any& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Any& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Any* internal_default_instance() {
     return reinterpret_cast<const Any*>(
                &_Any_default_instance_);
@@ -112,12 +113,12 @@
 
   // implements Any -----------------------------------------------
 
-  void PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {
-    _any_metadata_.PackFrom(message);
+  bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {
+    return _any_metadata_.PackFrom(GetArena(), message);
   }
-  void PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
-                const std::string& type_url_prefix) {
-    _any_metadata_.PackFrom(message, type_url_prefix);
+  bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
+                ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
+    return _any_metadata_.PackFrom(GetArena(), message, type_url_prefix);
   }
   bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const {
     return _any_metadata_.UnpackTo(message);
@@ -127,13 +128,13 @@
       const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
       const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field);
   template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
-  void PackFrom(const T& message) {
-    _any_metadata_.PackFrom<T>(message);
+  bool PackFrom(const T& message) {
+    return _any_metadata_.PackFrom<T>(message);
   }
   template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
-  void PackFrom(const T& message,
-                const std::string& type_url_prefix) {
-    _any_metadata_.PackFrom<T>(message, type_url_prefix);}
+  bool PackFrom(const T& message,
+                ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
+    return _any_metadata_.PackFrom<T>(message, type_url_prefix);}
   template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
   bool UnpackTo(T* message) const {
     return _any_metadata_.UnpackTo<T>(message);
@@ -141,14 +142,14 @@
   template<typename T> bool Is() const {
     return _any_metadata_.Is<T>();
   }
-  static bool ParseAnyTypeUrl(const string& type_url,
+  static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
                               std::string* full_type_name);
   friend void swap(Any& a, Any& b) {
     a.Swap(&b);
   }
   inline void Swap(Any* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -156,23 +157,26 @@
   }
   void UnsafeArenaSwap(Any* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Any* New() const final {
-    return CreateMaybeMessage<Any>(nullptr);
+    return new Any();
   }
 
   Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Any>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Any& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Any& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -183,8 +187,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Any* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -192,20 +196,17 @@
     return "google.protobuf.Any";
   }
   protected:
-  explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fany_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -218,50 +219,28 @@
   // string type_url = 1;
   void clear_type_url();
   const std::string& type_url() const;
-  void set_type_url(const std::string& value);
-  void set_type_url(std::string&& value);
-  void set_type_url(const char* value);
-  void set_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_type_url();
-  std::string* release_type_url();
+  PROTOBUF_MUST_USE_RESULT std::string* release_type_url();
   void set_allocated_type_url(std::string* type_url);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_type_url();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_type_url(
-      std::string* type_url);
   private:
   const std::string& _internal_type_url() const;
-  void _internal_set_type_url(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value);
   std::string* _internal_mutable_type_url();
   public:
 
   // bytes value = 2;
   void clear_value();
   const std::string& value() const;
-  void set_value(const std::string& value);
-  void set_value(std::string&& value);
-  void set_value(const char* value);
-  void set_value(const void* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_value();
-  std::string* release_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_value();
   void set_allocated_value(std::string* value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_value(
-      std::string* value);
   private:
   const std::string& _internal_value() const;
-  void _internal_set_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value);
   std::string* _internal_mutable_value();
   public:
 
@@ -291,54 +270,38 @@
 
 // string type_url = 1;
 inline void Any::clear_type_url() {
-  type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  type_url_.ClearToEmpty();
 }
 inline const std::string& Any::type_url() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
   return _internal_type_url();
 }
-inline void Any::set_type_url(const std::string& value) {
-  _internal_set_type_url(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Any::set_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
 }
 inline std::string* Any::mutable_type_url() {
+  std::string* _s = _internal_mutable_type_url();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
-  return _internal_mutable_type_url();
+  return _s;
 }
 inline const std::string& Any::_internal_type_url() const {
   return type_url_.Get();
 }
 inline void Any::_internal_set_type_url(const std::string& value) {
   
-  type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Any::set_type_url(std::string&& value) {
-  
-  type_url_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url)
-}
-inline void Any::set_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
-}
-inline void Any::set_type_url(const char* value,
-    size_t size) {
-  
-  type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
+  type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Any::_internal_mutable_type_url() {
   
-  return type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Any::release_type_url() {
   // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
-  return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Any::set_allocated_type_url(std::string* type_url) {
   if (type_url != nullptr) {
@@ -347,79 +310,44 @@
     
   }
   type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_url,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
 }
-inline std::string* Any::unsafe_arena_release_type_url() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Any.type_url)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return type_url_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Any::unsafe_arena_set_allocated_type_url(
-    std::string* type_url) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (type_url != nullptr) {
-    
-  } else {
-    
-  }
-  type_url_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      type_url, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Any.type_url)
-}
 
 // bytes value = 2;
 inline void Any::clear_value() {
-  value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  value_.ClearToEmpty();
 }
 inline const std::string& Any::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Any.value)
   return _internal_value();
 }
-inline void Any::set_value(const std::string& value) {
-  _internal_set_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Any::set_value(ArgT0&& arg0, ArgT... args) {
+ 
+ value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Any.value)
 }
 inline std::string* Any::mutable_value() {
+  std::string* _s = _internal_mutable_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
-  return _internal_mutable_value();
+  return _s;
 }
 inline const std::string& Any::_internal_value() const {
   return value_.Get();
 }
 inline void Any::_internal_set_value(const std::string& value) {
   
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Any::set_value(std::string&& value) {
-  
-  value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value)
-}
-inline void Any::set_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
-}
-inline void Any::set_value(const void* value,
-    size_t size) {
-  
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
+  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Any::_internal_mutable_value() {
   
-  return value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Any::release_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.Any.value)
-  return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Any::set_allocated_value(std::string* value) {
   if (value != nullptr) {
@@ -428,28 +356,9 @@
     
   }
   value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
 }
-inline std::string* Any::unsafe_arena_release_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Any.value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Any::unsafe_arena_set_allocated_value(
-    std::string* value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (value != nullptr) {
-    
-  } else {
-    
-  }
-  value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Any.value)
-}
 
 #ifdef __GNUC__
   #pragma GCC diagnostic pop
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
index c9be854..6ed8a23 100644
--- a/src/google/protobuf/any.proto
+++ b/src/google/protobuf/any.proto
@@ -33,7 +33,7 @@
 package google.protobuf;
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-option go_package = "github.com/golang/protobuf/ptypes/any";
+option go_package = "google.golang.org/protobuf/types/known/anypb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "AnyProto";
 option java_multiple_files = true;
@@ -77,10 +77,13 @@
 //  Example 4: Pack and unpack a message in Go
 //
 //      foo := &pb.Foo{...}
-//      any, err := ptypes.MarshalAny(foo)
+//      any, err := anypb.New(foo)
+//      if err != nil {
+//        ...
+//      }
 //      ...
 //      foo := &pb.Foo{}
-//      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+//      if err := any.UnmarshalTo(foo); err != nil {
 //        ...
 //      }
 //
diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc
index 7839381..1fa06c7 100644
--- a/src/google/protobuf/any_lite.cc
+++ b/src/google/protobuf/any_lite.cc
@@ -53,16 +53,14 @@
 const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
 const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
 
-AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
-    : type_url_(type_url), value_(value) {}
-
-void AnyMetadata::InternalPackFrom(const MessageLite& message,
+bool AnyMetadata::InternalPackFrom(Arena* arena,
+                                   const MessageLite& message,
                                    StringPiece type_url_prefix,
                                    StringPiece type_name) {
-  type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
-                        GetTypeUrl(type_name, type_url_prefix));
-  message.SerializeToString(value_->MutableNoArena(
-      &::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+  type_url_->Set(&::google::protobuf::internal::GetEmptyString(),
+                 GetTypeUrl(type_name, type_url_prefix), arena);
+  return message.SerializeToString(
+      value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
 }
 
 bool AnyMetadata::InternalUnpackTo(StringPiece type_name,
@@ -70,50 +68,30 @@
   if (!InternalIs(type_name)) {
     return false;
   }
-  return message->ParseFromString(value_->GetNoArena());
+  return message->ParseFromString(value_->Get());
 }
 
-namespace {
-
-// The type URL could be stored in either an ArenaStringPtr or a
-// StringPieceField, so we provide these helpers to get a string_view from
-// either type. We use a template function as a way to avoid depending on
-// StringPieceField.
-
-template <typename T>
-StringPiece Get(const T* ptr) {
-  return ptr->Get();
-}
-
-template <>
-// NOLINTNEXTLINE: clang-diagnostic-unused-function
-StringPiece Get(const ArenaStringPtr* ptr) {
-  return ptr->GetNoArena();
-}
-
-}  // namespace
-
 bool AnyMetadata::InternalIs(StringPiece type_name) const {
-  StringPiece type_url = Get(type_url_);
+  StringPiece type_url = type_url_->Get();
   return type_url.size() >= type_name.size() + 1 &&
          type_url[type_url.size() - type_name.size() - 1] == '/' &&
          HasSuffixString(type_url, type_name);
 }
 
-bool ParseAnyTypeUrl(const std::string& type_url, std::string* url_prefix,
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
                      std::string* full_type_name) {
-  size_t pos = type_url.find_last_of("/");
+  size_t pos = type_url.find_last_of('/');
   if (pos == std::string::npos || pos + 1 == type_url.size()) {
     return false;
   }
   if (url_prefix) {
-    *url_prefix = type_url.substr(0, pos + 1);
+    *url_prefix = std::string(type_url.substr(0, pos + 1));
   }
-  *full_type_name = type_url.substr(pos + 1);
+  *full_type_name = std::string(type_url.substr(pos + 1));
   return true;
 }
 
-bool ParseAnyTypeUrl(const std::string& type_url, std::string* full_type_name) {
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) {
   return ParseAnyTypeUrl(type_url, nullptr, full_type_name);
 }
 
diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc
index 0d8893f..1d136aa 100644
--- a/src/google/protobuf/any_test.cc
+++ b/src/google/protobuf/any_test.cc
@@ -33,15 +33,23 @@
 #include <gtest/gtest.h>
 
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 namespace {
 
+TEST(AnyMetadataTest, ConstInit) {
+  PROTOBUF_CONSTINIT static internal::AnyMetadata metadata(nullptr, nullptr);
+  (void)metadata;
+}
+
 TEST(AnyTest, TestPackAndUnpack) {
   protobuf_unittest::TestAny submessage;
   submessage.set_int32_value(12345);
   protobuf_unittest::TestAny message;
-  message.mutable_any_value()->PackFrom(submessage);
+  ASSERT_TRUE(message.mutable_any_value()->PackFrom(submessage));
 
   std::string data = message.SerializeAsString();
 
@@ -52,6 +60,13 @@
   EXPECT_EQ(12345, submessage.int32_value());
 }
 
+TEST(AnyTest, TestPackFromSerializationExceedsSizeLimit) {
+  protobuf_unittest::TestAny submessage;
+  submessage.mutable_text()->resize(INT_MAX, 'a');
+  protobuf_unittest::TestAny message;
+  EXPECT_FALSE(message.mutable_any_value()->PackFrom(submessage));
+}
+
 TEST(AnyTest, TestUnpackWithTypeMismatch) {
   protobuf_unittest::TestAny payload;
   payload.set_int32_value(13);
@@ -165,3 +180,5 @@
 }  // namespace
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/any_test.proto b/src/google/protobuf/any_test.proto
index 0c5b30b..256035b 100644
--- a/src/google/protobuf/any_test.proto
+++ b/src/google/protobuf/any_test.proto
@@ -34,8 +34,11 @@
 
 import "google/protobuf/any.proto";
 
+option java_outer_classname = "TestAnyProto";
+
 message TestAny {
   int32 int32_value = 1;
   google.protobuf.Any any_value = 2;
   repeated google.protobuf.Any repeated_any_value = 3;
+  string text = 4;
 }
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index 816df12..310ea2b 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -14,71 +14,61 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto;
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class ApiDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Api> _instance;
-} _Api_default_instance_;
-class MethodDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Method> _instance;
-} _Method_default_instance_;
-class MixinDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Mixin> _instance;
-} _Mixin_default_instance_;
+constexpr Api::Api(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : methods_()
+  , options_()
+  , mixins_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , version_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , source_context_(nullptr)
+  , syntax_(0)
+{}
+struct ApiDefaultTypeInternal {
+  constexpr ApiDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ApiDefaultTypeInternal() {}
+  union {
+    Api _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ApiDefaultTypeInternal _Api_default_instance_;
+constexpr Method::Method(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , request_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , response_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , request_streaming_(false)
+  , response_streaming_(false)
+  , syntax_(0)
+{}
+struct MethodDefaultTypeInternal {
+  constexpr MethodDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MethodDefaultTypeInternal() {}
+  union {
+    Method _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MethodDefaultTypeInternal _Method_default_instance_;
+constexpr Mixin::Mixin(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , root_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct MixinDefaultTypeInternal {
+  constexpr MixinDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MixinDefaultTypeInternal() {}
+  union {
+    Mixin _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MixinDefaultTypeInternal _Mixin_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Api_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Api();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Api::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<4> scc_info_Api_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 4, 0, InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto}, {
-      &scc_info_Method_google_2fprotobuf_2fapi_2eproto.base,
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,
-      &scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base,}};
-
-static void InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Method_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Method();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Method::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto}, {
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
-
-static void InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Mixin();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Mixin::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fapi_2eproto[3];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
@@ -144,38 +134,32 @@
   "esponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\013"
   "2\027.google.protobuf.Option\022\'\n\006syntax\030\007 \001("
   "\0162\027.google.protobuf.Syntax\"#\n\005Mixin\022\014\n\004n"
-  "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBu\n\023com.google.pr"
-  "otobufB\010ApiProtoP\001Z+google.golang.org/ge"
-  "nproto/protobuf/api;api\242\002\003GPB\252\002\036Google.P"
-  "rotobuf.WellKnownTypesb\006proto3"
+  "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBv\n\023com.google.pr"
+  "otobufB\010ApiProtoP\001Z,google.golang.org/pr"
+  "otobuf/types/known/apipb\242\002\003GPB\252\002\036Google."
+  "Protobuf.WellKnownTypesb\006proto3"
   ;
 static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fapi_2eproto_deps[2] = {
   &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
   &::descriptor_table_google_2fprotobuf_2ftype_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fapi_2eproto_sccs[3] = {
-  &scc_info_Api_google_2fprotobuf_2fapi_2eproto.base,
-  &scc_info_Method_google_2fprotobuf_2fapi_2eproto.base,
-  &scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, "google/protobuf/api.proto", 750,
-  &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_sccs, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 3, 2,
+  false, false, 751, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, "google/protobuf/api.proto", 
+  &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 2, 3,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fapi_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fapi_2eproto, 3, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
+  file_level_metadata_google_2fprotobuf_2fapi_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fapi_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fapi_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void Api::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_Api_default_instance_._instance.get_mutable()->source_context_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceContext*>(
-      PROTOBUF_NAMESPACE_ID::SourceContext::internal_default_instance());
-}
 class Api::_Internal {
  public:
   static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Api* msg);
@@ -189,18 +173,21 @@
   options_.Clear();
 }
 void Api::clear_source_context() {
-  if (GetArena() == nullptr && source_context_ != nullptr) {
+  if (GetArenaForAllocation() == nullptr && source_context_ != nullptr) {
     delete source_context_;
   }
   source_context_ = nullptr;
 }
-Api::Api(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+Api::Api(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   methods_(arena),
   options_(arena),
   mixins_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Api)
 }
 Api::Api(const Api& from)
@@ -211,13 +198,13 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_version().empty()) {
-    version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_version(),
-      GetArena());
+    version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_version(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_source_context()) {
     source_context_ = new PROTOBUF_NAMESPACE_ID::SourceContext(*from.source_context_);
@@ -228,23 +215,24 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Api)
 }
 
-void Api::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Api_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&source_context_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
+inline void Api::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
 }
 
 Api::~Api() {
   // @@protoc_insertion_point(destructor:google.protobuf.Api)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Api::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Api::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   version_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete source_context_;
@@ -259,11 +247,6 @@
 void Api::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Api& Api::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Api_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Api::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
@@ -274,9 +257,9 @@
   methods_.Clear();
   options_.Clear();
   mixins_.Clear();
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  version_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  if (GetArena() == nullptr && source_context_ != nullptr) {
+  name_.ClearToEmpty();
+  version_.ClearToEmpty();
+  if (GetArenaForAllocation() == nullptr && source_context_ != nullptr) {
     delete source_context_;
   }
   source_context_ = nullptr;
@@ -286,11 +269,9 @@
 
 const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -363,7 +344,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -390,7 +372,7 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -416,7 +398,7 @@
   }
 
   // string version = 4;
-  if (this->version().size() > 0) {
+  if (!this->_internal_version().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_version().data(), static_cast<int>(this->_internal_version().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -426,7 +408,7 @@
   }
 
   // .google.protobuf.SourceContext source_context = 5;
-  if (this->has_source_context()) {
+  if (this->_internal_has_source_context()) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(
@@ -442,7 +424,7 @@
   }
 
   // .google.protobuf.Syntax syntax = 7;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
       7, this->_internal_syntax(), target);
@@ -486,28 +468,28 @@
   }
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // string version = 4;
-  if (this->version().size() > 0) {
+  if (!this->_internal_version().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_version());
   }
 
   // .google.protobuf.SourceContext source_context = 5;
-  if (this->has_source_context()) {
+  if (this->_internal_has_source_context()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
         *source_context_);
   }
 
   // .google.protobuf.Syntax syntax = 7;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax());
   }
@@ -521,50 +503,41 @@
   return total_size;
 }
 
-void Api::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Api)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Api* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Api>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Api)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Api)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Api::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Api::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Api::GetClassData() const { return &_class_data_; }
+
+void Api::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Api *>(to)->MergeFrom(
+      static_cast<const Api &>(from));
 }
 
+
 void Api::MergeFrom(const Api& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   methods_.MergeFrom(from.methods_);
   options_.MergeFrom(from.options_);
   mixins_.MergeFrom(from.mixins_);
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.version().size() > 0) {
+  if (!from._internal_version().empty()) {
     _internal_set_version(from._internal_version());
   }
-  if (from.has_source_context()) {
+  if (from._internal_has_source_context()) {
     _internal_mutable_source_context()->PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom(from._internal_source_context());
   }
-  if (from.syntax() != 0) {
+  if (from._internal_syntax() != 0) {
     _internal_set_syntax(from._internal_syntax());
   }
-}
-
-void Api::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Api)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Api::CopyFrom(const Api& from) {
@@ -580,12 +553,20 @@
 
 void Api::InternalSwap(Api* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   methods_.InternalSwap(&other->methods_);
   options_.InternalSwap(&other->options_);
   mixins_.InternalSwap(&other->mixins_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  version_.Swap(&other->version_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &version_, GetArenaForAllocation(),
+      &other->version_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Api, syntax_)
       + sizeof(Api::syntax_)
@@ -595,14 +576,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Api::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fapi_2eproto[0]);
 }
 
-
 // ===================================================================
 
-void Method::InitAsDefaultInstance() {
-}
 class Method::_Internal {
  public:
 };
@@ -610,11 +590,14 @@
 void Method::clear_options() {
   options_.Clear();
 }
-Method::Method(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+Method::Method(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   options_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Method)
 }
 Method::Method(const Method& from)
@@ -623,18 +606,18 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_request_type_url().empty()) {
-    request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_request_type_url(),
-      GetArena());
+    request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_request_type_url(), 
+      GetArenaForAllocation());
   }
   response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_response_type_url().empty()) {
-    response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_response_type_url(),
-      GetArena());
+    response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_response_type_url(), 
+      GetArenaForAllocation());
   }
   ::memcpy(&request_streaming_, &from.request_streaming_,
     static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
@@ -642,24 +625,25 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Method)
 }
 
-void Method::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Method_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&request_streaming_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
+inline void Method::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&request_streaming_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
 }
 
 Method::~Method() {
   // @@protoc_insertion_point(destructor:google.protobuf.Method)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Method::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Method::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   request_type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   response_type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
@@ -674,11 +658,6 @@
 void Method::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Method& Method::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Method_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Method::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
@@ -687,9 +666,9 @@
   (void) cached_has_bits;
 
   options_.Clear();
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  request_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  response_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
+  request_type_url_.ClearToEmpty();
+  response_type_url_.ClearToEmpty();
   ::memset(&request_streaming_, 0, static_cast<size_t>(
       reinterpret_cast<char*>(&syntax_) -
       reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
@@ -698,11 +677,9 @@
 
 const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -767,7 +744,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -794,7 +772,7 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -804,7 +782,7 @@
   }
 
   // string request_type_url = 2;
-  if (this->request_type_url().size() > 0) {
+  if (!this->_internal_request_type_url().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_request_type_url().data(), static_cast<int>(this->_internal_request_type_url().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -814,13 +792,13 @@
   }
 
   // bool request_streaming = 3;
-  if (this->request_streaming() != 0) {
+  if (this->_internal_request_streaming() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->_internal_request_streaming(), target);
   }
 
   // string response_type_url = 4;
-  if (this->response_type_url().size() > 0) {
+  if (!this->_internal_response_type_url().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_response_type_url().data(), static_cast<int>(this->_internal_response_type_url().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -830,7 +808,7 @@
   }
 
   // bool response_streaming = 5;
-  if (this->response_streaming() != 0) {
+  if (this->_internal_response_streaming() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(5, this->_internal_response_streaming(), target);
   }
@@ -844,7 +822,7 @@
   }
 
   // .google.protobuf.Syntax syntax = 7;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
       7, this->_internal_syntax(), target);
@@ -874,38 +852,38 @@
   }
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // string request_type_url = 2;
-  if (this->request_type_url().size() > 0) {
+  if (!this->_internal_request_type_url().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_request_type_url());
   }
 
   // string response_type_url = 4;
-  if (this->response_type_url().size() > 0) {
+  if (!this->_internal_response_type_url().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_response_type_url());
   }
 
   // bool request_streaming = 3;
-  if (this->request_streaming() != 0) {
+  if (this->_internal_request_streaming() != 0) {
     total_size += 1 + 1;
   }
 
   // bool response_streaming = 5;
-  if (this->response_streaming() != 0) {
+  if (this->_internal_response_streaming() != 0) {
     total_size += 1 + 1;
   }
 
   // .google.protobuf.Syntax syntax = 7;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax());
   }
@@ -919,54 +897,45 @@
   return total_size;
 }
 
-void Method::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Method)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Method* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Method>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Method)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Method)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Method::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Method::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Method::GetClassData() const { return &_class_data_; }
+
+void Method::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Method *>(to)->MergeFrom(
+      static_cast<const Method &>(from));
 }
 
+
 void Method::MergeFrom(const Method& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   options_.MergeFrom(from.options_);
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.request_type_url().size() > 0) {
+  if (!from._internal_request_type_url().empty()) {
     _internal_set_request_type_url(from._internal_request_type_url());
   }
-  if (from.response_type_url().size() > 0) {
+  if (!from._internal_response_type_url().empty()) {
     _internal_set_response_type_url(from._internal_response_type_url());
   }
-  if (from.request_streaming() != 0) {
+  if (from._internal_request_streaming() != 0) {
     _internal_set_request_streaming(from._internal_request_streaming());
   }
-  if (from.response_streaming() != 0) {
+  if (from._internal_response_streaming() != 0) {
     _internal_set_response_streaming(from._internal_response_streaming());
   }
-  if (from.syntax() != 0) {
+  if (from._internal_syntax() != 0) {
     _internal_set_syntax(from._internal_syntax());
   }
-}
-
-void Method::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Method)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Method::CopyFrom(const Method& from) {
@@ -982,11 +951,23 @@
 
 void Method::InternalSwap(Method* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   options_.InternalSwap(&other->options_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  request_type_url_.Swap(&other->request_type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  response_type_url_.Swap(&other->response_type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &request_type_url_, GetArenaForAllocation(),
+      &other->request_type_url_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &response_type_url_, GetArenaForAllocation(),
+      &other->response_type_url_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Method, syntax_)
       + sizeof(Method::syntax_)
@@ -996,22 +977,24 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Method::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fapi_2eproto[1]);
 }
 
-
 // ===================================================================
 
-void Mixin::InitAsDefaultInstance() {
-}
 class Mixin::_Internal {
  public:
 };
 
-Mixin::Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Mixin::Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Mixin)
 }
 Mixin::Mixin(const Mixin& from)
@@ -1019,31 +1002,31 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_root().empty()) {
-    root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_root(),
-      GetArena());
+    root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_root(), 
+      GetArenaForAllocation());
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin)
 }
 
-void Mixin::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+inline void Mixin::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 Mixin::~Mixin() {
   // @@protoc_insertion_point(destructor:google.protobuf.Mixin)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Mixin::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Mixin::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   root_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
@@ -1057,11 +1040,6 @@
 void Mixin::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Mixin& Mixin::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Mixin::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)
@@ -1069,18 +1047,16 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  root_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
+  root_.ClearToEmpty();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Mixin::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1102,7 +1078,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1129,7 +1106,7 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1139,7 +1116,7 @@
   }
 
   // string root = 2;
-  if (this->root().size() > 0) {
+  if (!this->_internal_root().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_root().data(), static_cast<int>(this->_internal_root().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1165,14 +1142,14 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // string root = 2;
-  if (this->root().size() > 0) {
+  if (!this->_internal_root().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_root());
@@ -1187,41 +1164,32 @@
   return total_size;
 }
 
-void Mixin::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Mixin)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Mixin* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Mixin>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Mixin)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Mixin)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Mixin::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Mixin::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Mixin::GetClassData() const { return &_class_data_; }
+
+void Mixin::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Mixin *>(to)->MergeFrom(
+      static_cast<const Mixin &>(from));
 }
 
+
 void Mixin::MergeFrom(const Mixin& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.root().size() > 0) {
+  if (!from._internal_root().empty()) {
     _internal_set_root(from._internal_root());
   }
-}
-
-void Mixin::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Mixin)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Mixin::CopyFrom(const Mixin& from) {
@@ -1237,16 +1205,25 @@
 
 void Mixin::InternalSwap(Mixin* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  root_.Swap(&other->root_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &root_, GetArenaForAllocation(),
+      &other->root_, other->GetArenaForAllocation()
+  );
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Mixin::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fapi_2eproto[2]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index 66ac61a..67e9d84 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -47,7 +46,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fapi_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[3]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -55,16 +54,16 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class Api;
-class ApiDefaultTypeInternal;
+struct ApiDefaultTypeInternal;
 PROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_;
 class Method;
-class MethodDefaultTypeInternal;
+struct MethodDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_;
 class Mixin;
-class MixinDefaultTypeInternal;
+struct MixinDefaultTypeInternal;
 PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -76,11 +75,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT Api PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Api final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ {
  public:
-  inline Api() : Api(nullptr) {};
-  virtual ~Api();
+  inline Api() : Api(nullptr) {}
+  ~Api() override;
+  explicit constexpr Api(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Api(const Api& from);
   Api(Api&& from) noexcept
@@ -93,8 +93,9 @@
     return *this;
   }
   inline Api& operator=(Api&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -105,14 +106,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Api& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Api& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Api* internal_default_instance() {
     return reinterpret_cast<const Api*>(
                &_Api_default_instance_);
@@ -125,7 +126,7 @@
   }
   inline void Swap(Api* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -133,23 +134,26 @@
   }
   void UnsafeArenaSwap(Api* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Api* New() const final {
-    return CreateMaybeMessage<Api>(nullptr);
+    return new Api();
   }
 
   Api* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Api>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Api& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Api& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -160,8 +164,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Api* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -169,20 +173,17 @@
     return "google.protobuf.Api";
   }
   protected:
-  explicit Api(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Api(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -254,50 +255,28 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
   // string version = 4;
   void clear_version();
   const std::string& version() const;
-  void set_version(const std::string& value);
-  void set_version(std::string&& value);
-  void set_version(const char* value);
-  void set_version(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_version(ArgT0&& arg0, ArgT... args);
   std::string* mutable_version();
-  std::string* release_version();
+  PROTOBUF_MUST_USE_RESULT std::string* release_version();
   void set_allocated_version(std::string* version);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_version();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_version(
-      std::string* version);
   private:
   const std::string& _internal_version() const;
-  void _internal_set_version(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_version(const std::string& value);
   std::string* _internal_mutable_version();
   public:
 
@@ -308,7 +287,7 @@
   public:
   void clear_source_context();
   const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
-  PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
   PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
   void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
   private:
@@ -347,11 +326,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Method PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Method final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ {
  public:
-  inline Method() : Method(nullptr) {};
-  virtual ~Method();
+  inline Method() : Method(nullptr) {}
+  ~Method() override;
+  explicit constexpr Method(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Method(const Method& from);
   Method(Method&& from) noexcept
@@ -364,8 +344,9 @@
     return *this;
   }
   inline Method& operator=(Method&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -376,14 +357,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Method& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Method& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Method* internal_default_instance() {
     return reinterpret_cast<const Method*>(
                &_Method_default_instance_);
@@ -396,7 +377,7 @@
   }
   inline void Swap(Method* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -404,23 +385,26 @@
   }
   void UnsafeArenaSwap(Method* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Method* New() const final {
-    return CreateMaybeMessage<Method>(nullptr);
+    return new Method();
   }
 
   Method* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Method>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Method& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Method& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -431,8 +415,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Method* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -440,20 +424,17 @@
     return "google.protobuf.Method";
   }
   protected:
-  explicit Method(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Method(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -489,75 +470,42 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
   // string request_type_url = 2;
   void clear_request_type_url();
   const std::string& request_type_url() const;
-  void set_request_type_url(const std::string& value);
-  void set_request_type_url(std::string&& value);
-  void set_request_type_url(const char* value);
-  void set_request_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_request_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_request_type_url();
-  std::string* release_request_type_url();
+  PROTOBUF_MUST_USE_RESULT std::string* release_request_type_url();
   void set_allocated_request_type_url(std::string* request_type_url);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_request_type_url();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_request_type_url(
-      std::string* request_type_url);
   private:
   const std::string& _internal_request_type_url() const;
-  void _internal_set_request_type_url(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_request_type_url(const std::string& value);
   std::string* _internal_mutable_request_type_url();
   public:
 
   // string response_type_url = 4;
   void clear_response_type_url();
   const std::string& response_type_url() const;
-  void set_response_type_url(const std::string& value);
-  void set_response_type_url(std::string&& value);
-  void set_response_type_url(const char* value);
-  void set_response_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_response_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_response_type_url();
-  std::string* release_response_type_url();
+  PROTOBUF_MUST_USE_RESULT std::string* release_response_type_url();
   void set_allocated_response_type_url(std::string* response_type_url);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_response_type_url();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_response_type_url(
-      std::string* response_type_url);
   private:
   const std::string& _internal_response_type_url() const;
-  void _internal_set_response_type_url(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_response_type_url(const std::string& value);
   std::string* _internal_mutable_response_type_url();
   public:
 
@@ -607,11 +555,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Mixin PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Mixin final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ {
  public:
-  inline Mixin() : Mixin(nullptr) {};
-  virtual ~Mixin();
+  inline Mixin() : Mixin(nullptr) {}
+  ~Mixin() override;
+  explicit constexpr Mixin(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Mixin(const Mixin& from);
   Mixin(Mixin&& from) noexcept
@@ -624,8 +573,9 @@
     return *this;
   }
   inline Mixin& operator=(Mixin&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -636,14 +586,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Mixin& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Mixin& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Mixin* internal_default_instance() {
     return reinterpret_cast<const Mixin*>(
                &_Mixin_default_instance_);
@@ -656,7 +606,7 @@
   }
   inline void Swap(Mixin* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -664,23 +614,26 @@
   }
   void UnsafeArenaSwap(Mixin* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Mixin* New() const final {
-    return CreateMaybeMessage<Mixin>(nullptr);
+    return new Mixin();
   }
 
   Mixin* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Mixin>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Mixin& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Mixin& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -691,8 +644,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Mixin* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -700,20 +653,17 @@
     return "google.protobuf.Mixin";
   }
   protected:
-  explicit Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -726,50 +676,28 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
   // string root = 2;
   void clear_root();
   const std::string& root() const;
-  void set_root(const std::string& value);
-  void set_root(std::string&& value);
-  void set_root(const char* value);
-  void set_root(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_root(ArgT0&& arg0, ArgT... args);
   std::string* mutable_root();
-  std::string* release_root();
+  PROTOBUF_MUST_USE_RESULT std::string* release_root();
   void set_allocated_root(std::string* root);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_root();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_root(
-      std::string* root);
   private:
   const std::string& _internal_root() const;
-  void _internal_set_root(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_root(const std::string& value);
   std::string* _internal_mutable_root();
   public:
 
@@ -798,54 +726,38 @@
 
 // string name = 1;
 inline void Api::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& Api::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Api.name)
   return _internal_name();
 }
-inline void Api::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Api::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Api.name)
 }
 inline std::string* Api::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& Api::_internal_name() const {
   return name_.Get();
 }
 inline void Api::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Api::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.name)
-}
-inline void Api::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name)
-}
-inline void Api::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Api::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Api::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Api.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Api::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -854,28 +766,9 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name)
 }
-inline std::string* Api::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Api.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Api::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.name)
-}
 
 // repeated .google.protobuf.Method methods = 2;
 inline int Api::_internal_methods_size() const {
@@ -907,8 +800,9 @@
   return methods_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Method* Api::add_methods() {
+  PROTOBUF_NAMESPACE_ID::Method* _add = _internal_add_methods();
   // @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
-  return _internal_add_methods();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >&
 Api::methods() const {
@@ -943,8 +837,9 @@
   return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* Api::add_options() {
+  PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
   // @@protoc_insertion_point(field_add:google.protobuf.Api.options)
-  return _internal_add_options();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 Api::options() const {
@@ -954,54 +849,38 @@
 
 // string version = 4;
 inline void Api::clear_version() {
-  version_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  version_.ClearToEmpty();
 }
 inline const std::string& Api::version() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Api.version)
   return _internal_version();
 }
-inline void Api::set_version(const std::string& value) {
-  _internal_set_version(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Api::set_version(ArgT0&& arg0, ArgT... args) {
+ 
+ version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Api.version)
 }
 inline std::string* Api::mutable_version() {
+  std::string* _s = _internal_mutable_version();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
-  return _internal_mutable_version();
+  return _s;
 }
 inline const std::string& Api::_internal_version() const {
   return version_.Get();
 }
 inline void Api::_internal_set_version(const std::string& value) {
   
-  version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Api::set_version(std::string&& value) {
-  
-  version_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.version)
-}
-inline void Api::set_version(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version)
-}
-inline void Api::set_version(const char* value,
-    size_t size) {
-  
-  version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version)
+  version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Api::_internal_mutable_version() {
   
-  return version_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return version_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Api::release_version() {
   // @@protoc_insertion_point(field_release:google.protobuf.Api.version)
-  return version_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return version_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Api::set_allocated_version(std::string* version) {
   if (version != nullptr) {
@@ -1010,28 +889,9 @@
     
   }
   version_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), version,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version)
 }
-inline std::string* Api::unsafe_arena_release_version() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Api.version)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return version_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Api::unsafe_arena_set_allocated_version(
-    std::string* version) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (version != nullptr) {
-    
-  } else {
-    
-  }
-  version_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      version, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.version)
-}
 
 // .google.protobuf.SourceContext source_context = 5;
 inline bool Api::_internal_has_source_context() const {
@@ -1042,8 +902,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::_internal_source_context() const {
   const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceContext*>(
-      &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceContext&>(
+      PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::source_context() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
@@ -1051,7 +911,7 @@
 }
 inline void Api::unsafe_arena_set_allocated_source_context(
     PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_);
   }
   source_context_ = source_context;
@@ -1063,10 +923,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.source_context)
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::release_source_context() {
-  auto temp = unsafe_arena_release_source_context();
-  if (GetArena() != nullptr) {
+  
+  PROTOBUF_NAMESPACE_ID::SourceContext* temp = source_context_;
+  source_context_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::unsafe_arena_release_source_context() {
@@ -1079,23 +947,26 @@
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::_internal_mutable_source_context() {
   
   if (source_context_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceContext>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaForAllocation());
     source_context_ = p;
   }
   return source_context_;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::mutable_source_context() {
+  PROTOBUF_NAMESPACE_ID::SourceContext* _msg = _internal_mutable_source_context();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
-  return _internal_mutable_source_context();
+  return _msg;
 }
 inline void Api::set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_);
   }
   if (source_context) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context)->GetArena();
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<
+            ::PROTOBUF_NAMESPACE_ID::MessageLite>::GetOwningArena(
+                reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context));
     if (message_arena != submessage_arena) {
       source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_context, submessage_arena);
@@ -1138,8 +1009,9 @@
   return mixins_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Mixin* Api::add_mixins() {
+  PROTOBUF_NAMESPACE_ID::Mixin* _add = _internal_add_mixins();
   // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
-  return _internal_add_mixins();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >&
 Api::mixins() const {
@@ -1173,54 +1045,38 @@
 
 // string name = 1;
 inline void Method::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& Method::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Method.name)
   return _internal_name();
 }
-inline void Method::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Method::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Method.name)
 }
 inline std::string* Method::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& Method::_internal_name() const {
   return name_.Get();
 }
 inline void Method::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Method::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.name)
-}
-inline void Method::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name)
-}
-inline void Method::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Method::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Method::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Method.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Method::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -1229,79 +1085,44 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name)
 }
-inline std::string* Method::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Method.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Method::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Method.name)
-}
 
 // string request_type_url = 2;
 inline void Method::clear_request_type_url() {
-  request_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  request_type_url_.ClearToEmpty();
 }
 inline const std::string& Method::request_type_url() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
   return _internal_request_type_url();
 }
-inline void Method::set_request_type_url(const std::string& value) {
-  _internal_set_request_type_url(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Method::set_request_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
 }
 inline std::string* Method::mutable_request_type_url() {
+  std::string* _s = _internal_mutable_request_type_url();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
-  return _internal_mutable_request_type_url();
+  return _s;
 }
 inline const std::string& Method::_internal_request_type_url() const {
   return request_type_url_.Get();
 }
 inline void Method::_internal_set_request_type_url(const std::string& value) {
   
-  request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Method::set_request_type_url(std::string&& value) {
-  
-  request_type_url_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.request_type_url)
-}
-inline void Method::set_request_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url)
-}
-inline void Method::set_request_type_url(const char* value,
-    size_t size) {
-  
-  request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url)
+  request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Method::_internal_mutable_request_type_url() {
   
-  return request_type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return request_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Method::release_request_type_url() {
   // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url)
-  return request_type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return request_type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Method::set_allocated_request_type_url(std::string* request_type_url) {
   if (request_type_url != nullptr) {
@@ -1310,28 +1131,9 @@
     
   }
   request_type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), request_type_url,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url)
 }
-inline std::string* Method::unsafe_arena_release_request_type_url() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Method.request_type_url)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return request_type_url_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Method::unsafe_arena_set_allocated_request_type_url(
-    std::string* request_type_url) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (request_type_url != nullptr) {
-    
-  } else {
-    
-  }
-  request_type_url_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      request_type_url, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Method.request_type_url)
-}
 
 // bool request_streaming = 3;
 inline void Method::clear_request_streaming() {
@@ -1355,54 +1157,38 @@
 
 // string response_type_url = 4;
 inline void Method::clear_response_type_url() {
-  response_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  response_type_url_.ClearToEmpty();
 }
 inline const std::string& Method::response_type_url() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
   return _internal_response_type_url();
 }
-inline void Method::set_response_type_url(const std::string& value) {
-  _internal_set_response_type_url(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Method::set_response_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
 }
 inline std::string* Method::mutable_response_type_url() {
+  std::string* _s = _internal_mutable_response_type_url();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
-  return _internal_mutable_response_type_url();
+  return _s;
 }
 inline const std::string& Method::_internal_response_type_url() const {
   return response_type_url_.Get();
 }
 inline void Method::_internal_set_response_type_url(const std::string& value) {
   
-  response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Method::set_response_type_url(std::string&& value) {
-  
-  response_type_url_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.response_type_url)
-}
-inline void Method::set_response_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url)
-}
-inline void Method::set_response_type_url(const char* value,
-    size_t size) {
-  
-  response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url)
+  response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Method::_internal_mutable_response_type_url() {
   
-  return response_type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return response_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Method::release_response_type_url() {
   // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url)
-  return response_type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return response_type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Method::set_allocated_response_type_url(std::string* response_type_url) {
   if (response_type_url != nullptr) {
@@ -1411,28 +1197,9 @@
     
   }
   response_type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), response_type_url,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url)
 }
-inline std::string* Method::unsafe_arena_release_response_type_url() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Method.response_type_url)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return response_type_url_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Method::unsafe_arena_set_allocated_response_type_url(
-    std::string* response_type_url) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (response_type_url != nullptr) {
-    
-  } else {
-    
-  }
-  response_type_url_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      response_type_url, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Method.response_type_url)
-}
 
 // bool response_streaming = 5;
 inline void Method::clear_response_streaming() {
@@ -1481,8 +1248,9 @@
   return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* Method::add_options() {
+  PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
   // @@protoc_insertion_point(field_add:google.protobuf.Method.options)
-  return _internal_add_options();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 Method::options() const {
@@ -1516,54 +1284,38 @@
 
 // string name = 1;
 inline void Mixin::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& Mixin::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
   return _internal_name();
 }
-inline void Mixin::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Mixin::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
 }
 inline std::string* Mixin::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& Mixin::_internal_name() const {
   return name_.Get();
 }
 inline void Mixin::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Mixin::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.name)
-}
-inline void Mixin::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name)
-}
-inline void Mixin::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Mixin::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Mixin::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Mixin::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -1572,79 +1324,44 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name)
 }
-inline std::string* Mixin::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Mixin.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Mixin::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Mixin.name)
-}
 
 // string root = 2;
 inline void Mixin::clear_root() {
-  root_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  root_.ClearToEmpty();
 }
 inline const std::string& Mixin::root() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
   return _internal_root();
 }
-inline void Mixin::set_root(const std::string& value) {
-  _internal_set_root(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Mixin::set_root(ArgT0&& arg0, ArgT... args) {
+ 
+ root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
 }
 inline std::string* Mixin::mutable_root() {
+  std::string* _s = _internal_mutable_root();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
-  return _internal_mutable_root();
+  return _s;
 }
 inline const std::string& Mixin::_internal_root() const {
   return root_.Get();
 }
 inline void Mixin::_internal_set_root(const std::string& value) {
   
-  root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Mixin::set_root(std::string&& value) {
-  
-  root_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.root)
-}
-inline void Mixin::set_root(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root)
-}
-inline void Mixin::set_root(const char* value,
-    size_t size) {
-  
-  root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root)
+  root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Mixin::_internal_mutable_root() {
   
-  return root_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return root_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Mixin::release_root() {
   // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root)
-  return root_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return root_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Mixin::set_allocated_root(std::string* root) {
   if (root != nullptr) {
@@ -1653,28 +1370,9 @@
     
   }
   root_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), root,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
 }
-inline std::string* Mixin::unsafe_arena_release_root() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Mixin.root)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return root_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Mixin::unsafe_arena_set_allocated_root(
-    std::string* root) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (root != nullptr) {
-    
-  } else {
-    
-  }
-  root_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      root, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Mixin.root)
-}
 
 #ifdef __GNUC__
   #pragma GCC diagnostic pop
diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto
index f37ee2f..3d598fc 100644
--- a/src/google/protobuf/api.proto
+++ b/src/google/protobuf/api.proto
@@ -40,7 +40,7 @@
 option java_outer_classname = "ApiProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
-option go_package = "google.golang.org/genproto/protobuf/api;api";
+option go_package = "google.golang.org/protobuf/types/known/apipb";
 
 // Api is a light-weight descriptor for an API Interface.
 //
@@ -52,7 +52,6 @@
 // this message itself. See https://cloud.google.com/apis/design/glossary for
 // detailed terminology.
 message Api {
-
   // The fully qualified name of this interface, including package name
   // followed by the interface's simple name.
   string name = 1;
@@ -99,7 +98,6 @@
 
 // Method represents a method of an API interface.
 message Method {
-
   // The simple name of this method.
   string name = 1;
 
@@ -169,7 +167,7 @@
 // The mixin construct implies that all methods in `AccessControl` are
 // also declared with same name and request/response types in
 // `Storage`. A documentation generator or annotation processor will
-// see the effective `Storage.GetAcl` method after inherting
+// see the effective `Storage.GetAcl` method after inheriting
 // documentation and annotations as follows:
 //
 //     service Storage {
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 069dcdf..bd9516b 100644
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -32,306 +32,404 @@
 
 #include <algorithm>
 #include <atomic>
+#include <cstddef>
+#include <cstdint>
 #include <limits>
+#include <typeinfo>
+
+#include <google/protobuf/arena_impl.h>
 
 #include <google/protobuf/stubs/mutex.h>
-
 #ifdef ADDRESS_SANITIZER
 #include <sanitizer/asan_interface.h>
 #endif  // ADDRESS_SANITIZER
 
 #include <google/protobuf/port_def.inc>
 
-static const size_t kMinCleanupListElements = 8;
-static const size_t kMaxCleanupListElements = 64;  // 1kB on 64-bit.
-
 namespace google {
 namespace protobuf {
 namespace internal {
 
+static SerialArena::Memory AllocateMemory(const AllocationPolicy* policy_ptr,
+                                          size_t last_size, size_t min_bytes) {
+  AllocationPolicy policy;  // default policy
+  if (policy_ptr) policy = *policy_ptr;
+  size_t size;
+  if (last_size != 0) {
+    // Double the current block size, up to a limit.
+    auto max_size = policy.max_block_size;
+    size = std::min(2 * last_size, max_size);
+  } else {
+    size = policy.start_block_size;
+  }
+  // Verify that min_bytes + kBlockHeaderSize won't overflow.
+  GOOGLE_CHECK_LE(min_bytes,
+           std::numeric_limits<size_t>::max() - SerialArena::kBlockHeaderSize);
+  size = std::max(size, SerialArena::kBlockHeaderSize + min_bytes);
 
-std::atomic<LifecycleId> ArenaImpl::lifecycle_id_generator_;
+  void* mem;
+  if (policy.block_alloc == nullptr) {
+    mem = ::operator new(size);
+  } else {
+    mem = policy.block_alloc(size);
+  }
+  return {mem, size};
+}
+
+class GetDeallocator {
+ public:
+  GetDeallocator(const AllocationPolicy* policy, size_t* space_allocated)
+      : dealloc_(policy ? policy->block_dealloc : nullptr),
+        space_allocated_(space_allocated) {}
+
+  void operator()(SerialArena::Memory mem) const {
+#ifdef ADDRESS_SANITIZER
+    // This memory was provided by the underlying allocator as unpoisoned,
+    // so return it in an unpoisoned state.
+    ASAN_UNPOISON_MEMORY_REGION(mem.ptr, mem.size);
+#endif  // ADDRESS_SANITIZER
+    if (dealloc_) {
+      dealloc_(mem.ptr, mem.size);
+    } else {
+#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
+      ::operator delete(mem.ptr, mem.size);
+#else
+      ::operator delete(mem.ptr);
+#endif
+    }
+    *space_allocated_ += mem.size;
+  }
+
+ private:
+  void (*dealloc_)(void*, size_t);
+  size_t* space_allocated_;
+};
+
+SerialArena::SerialArena(Block* b, void* owner) : space_allocated_(b->size) {
+  owner_ = owner;
+  head_ = b;
+  ptr_ = b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize);
+  limit_ = b->Pointer(b->size & static_cast<size_t>(-8));
+}
+
+SerialArena* SerialArena::New(Memory mem, void* owner) {
+  GOOGLE_DCHECK_LE(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize, mem.size);
+
+  auto b = new (mem.ptr) Block{nullptr, mem.size};
+  return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, owner);
+}
+
+template <typename Deallocator>
+SerialArena::Memory SerialArena::Free(Deallocator deallocator) {
+  Block* b = head_;
+  Memory mem = {b, b->size};
+  while (b->next) {
+    b = b->next;  // We must first advance before deleting this block
+    deallocator(mem);
+    mem = {b, b->size};
+  }
+  return mem;
+}
+
+PROTOBUF_NOINLINE
+std::pair<void*, SerialArena::CleanupNode*>
+SerialArena::AllocateAlignedWithCleanupFallback(
+    size_t n, const AllocationPolicy* policy) {
+  AllocateNewBlock(n + kCleanupSize, policy);
+  return AllocateAlignedWithCleanup(n, policy);
+}
+
+PROTOBUF_NOINLINE
+void* SerialArena::AllocateAlignedFallback(size_t n,
+                                           const AllocationPolicy* policy) {
+  AllocateNewBlock(n, policy);
+  return AllocateAligned(n, policy);
+}
+
+void SerialArena::AllocateNewBlock(size_t n, const AllocationPolicy* policy) {
+  // Sync limit to block
+  head_->start = reinterpret_cast<CleanupNode*>(limit_);
+
+  // Record how much used in this block.
+  space_used_ += ptr_ - head_->Pointer(kBlockHeaderSize);
+
+  auto mem = AllocateMemory(policy, head_->size, n);
+  // We don't want to emit an expensive RMW instruction that requires
+  // exclusive access to a cacheline. Hence we write it in terms of a
+  // regular add.
+  auto relaxed = std::memory_order_relaxed;
+  space_allocated_.store(space_allocated_.load(relaxed) + mem.size, relaxed);
+  head_ = new (mem.ptr) Block{head_, mem.size};
+  ptr_ = head_->Pointer(kBlockHeaderSize);
+  limit_ = head_->Pointer(head_->size);
+
+#ifdef ADDRESS_SANITIZER
+  ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
+#endif  // ADDRESS_SANITIZER
+}
+
+uint64 SerialArena::SpaceUsed() const {
+  uint64 space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
+  space_used += space_used_;
+  // Remove the overhead of the SerialArena itself.
+  space_used -= ThreadSafeArena::kSerialArenaSize;
+  return space_used;
+}
+
+void SerialArena::CleanupList() {
+  Block* b = head_;
+  b->start = reinterpret_cast<CleanupNode*>(limit_);
+  do {
+    auto* limit = reinterpret_cast<CleanupNode*>(
+        b->Pointer(b->size & static_cast<size_t>(-8)));
+    auto it = b->start;
+    auto num = limit - it;
+    if (num > 0) {
+      for (; it < limit; it++) {
+        it->cleanup(it->elem);
+      }
+    }
+    b = b->next;
+  } while (b);
+}
+
+
+ThreadSafeArena::CacheAlignedLifecycleIdGenerator
+    ThreadSafeArena::lifecycle_id_generator_;
 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
-ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
+ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
   static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
       new internal::ThreadLocalStorage<ThreadCache>();
   return *thread_cache_->Get();
 }
 #elif defined(PROTOBUF_USE_DLLS)
-ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
-  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = {-1, NULL};
+ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
+  static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {
+      0, static_cast<LifecycleIdAtomic>(-1), nullptr};
   return thread_cache_;
 }
 #else
-GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL};
+PROTOBUF_THREAD_LOCAL ThreadSafeArena::ThreadCache
+    ThreadSafeArena::thread_cache_ = {0, static_cast<LifecycleIdAtomic>(-1),
+                                      nullptr};
 #endif
 
-void ArenaImpl::Init() {
-  lifecycle_id_ =
-      lifecycle_id_generator_.fetch_add(1, std::memory_order_relaxed);
-  hint_.store(nullptr, std::memory_order_relaxed);
-  threads_.store(nullptr, std::memory_order_relaxed);
+void ThreadSafeArena::InitializeFrom(void* mem, size_t size) {
+  GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
+  Init(false);
 
-  if (initial_block_) {
-    // Thread which calls Init() owns the first block. This allows the
-    // single-threaded case to allocate on the first block without having to
-    // perform atomic operations.
-    new (initial_block_) Block(options_.initial_block_size, NULL);
-    SerialArena* serial =
-        SerialArena::New(initial_block_, &thread_cache(), this);
-    serial->set_next(NULL);
-    threads_.store(serial, std::memory_order_relaxed);
-    space_allocated_.store(options_.initial_block_size,
-                           std::memory_order_relaxed);
-    CacheSerialArena(serial);
-  } else {
-    space_allocated_.store(0, std::memory_order_relaxed);
+  // Ignore initial block if it is too small.
+  if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) {
+    alloc_policy_ |= kUserOwnedInitialBlock;
+    SetInitialBlock(mem, size);
   }
 }
 
-ArenaImpl::~ArenaImpl() {
-  // Have to do this in a first pass, because some of the destructors might
-  // refer to memory in other blocks.
-  CleanupList();
-  FreeBlocks();
+void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size,
+                                           bool record_allocs,
+                                           AllocationPolicy policy) {
+  GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
+
+  Init(record_allocs);
+
+  // Ignore initial block if it is too small. We include an optional
+  // AllocationPolicy in this check, so that this can be allocated on the
+  // first block.
+  constexpr size_t kAPSize = internal::AlignUpTo8(sizeof(AllocationPolicy));
+  constexpr size_t kMinimumSize = kBlockHeaderSize + kSerialArenaSize + kAPSize;
+  if (mem != nullptr && size >= kMinimumSize) {
+    alloc_policy_ = kUserOwnedInitialBlock;
+  } else {
+    alloc_policy_ = 0;
+    auto tmp = AllocateMemory(&policy, 0, kMinimumSize);
+    mem = tmp.ptr;
+    size = tmp.size;
+  }
+  SetInitialBlock(mem, size);
+
+  auto sa = threads_.load(std::memory_order_relaxed);
+  // We ensured enough space so this cannot fail.
+  void* p;
+  if (!sa || !sa->MaybeAllocateAligned(kAPSize, &p)) {
+    GOOGLE_LOG(FATAL) << "MaybeAllocateAligned cannot fail here.";
+    return;
+  }
+  new (p) AllocationPolicy{policy};
+  alloc_policy_ |= reinterpret_cast<intptr_t>(p);
 }
 
-uint64 ArenaImpl::Reset() {
+void ThreadSafeArena::Init(bool record_allocs) {
+  ThreadCache& tc = thread_cache();
+  auto id = tc.next_lifecycle_id;
+  // We increment lifecycle_id's by multiples of two so we can use bit 0 as
+  // a tag.
+  constexpr uint64 kDelta = 2;
+  constexpr uint64 kInc = ThreadCache::kPerThreadIds * kDelta;
+  if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) {
+    constexpr auto relaxed = std::memory_order_relaxed;
+    // On platforms that don't support uint64 atomics we can certainly not
+    // afford to increment by large intervals and expect uniqueness due to
+    // wrapping, hence we only add by 1.
+    id = lifecycle_id_generator_.id.fetch_add(1, relaxed) * kInc;
+  }
+  tc.next_lifecycle_id = id + kDelta;
+  tag_and_id_ = id | (record_allocs ? kRecordAllocs : 0);
+  hint_.store(nullptr, std::memory_order_relaxed);
+  threads_.store(nullptr, std::memory_order_relaxed);
+}
+
+void ThreadSafeArena::SetInitialBlock(void* mem, size_t size) {
+  SerialArena* serial = SerialArena::New({mem, size}, &thread_cache());
+  serial->set_next(NULL);
+  threads_.store(serial, std::memory_order_relaxed);
+  CacheSerialArena(serial);
+}
+
+ThreadSafeArena::~ThreadSafeArena() {
   // Have to do this in a first pass, because some of the destructors might
   // refer to memory in other blocks.
   CleanupList();
-  uint64 space_allocated = FreeBlocks();
-  Init();
+
+  size_t space_allocated = 0;
+  auto mem = Free(&space_allocated);
+
+  // Policy is about to get deleted.
+  auto p = AllocPolicy();
+  ArenaMetricsCollector* collector = p ? p->metrics_collector : nullptr;
+
+  if (alloc_policy_ & kUserOwnedInitialBlock) {
+    space_allocated += mem.size;
+  } else {
+    GetDeallocator(AllocPolicy(), &space_allocated)(mem);
+  }
+
+  if (collector) collector->OnDestroy(space_allocated);
+}
+
+SerialArena::Memory ThreadSafeArena::Free(size_t* space_allocated) {
+  SerialArena::Memory mem = {nullptr, 0};
+  auto deallocator = GetDeallocator(AllocPolicy(), space_allocated);
+  PerSerialArena([deallocator, &mem](SerialArena* a) {
+    if (mem.ptr) deallocator(mem);
+    mem = a->Free(deallocator);
+  });
+  return mem;
+}
+
+uint64 ThreadSafeArena::Reset() {
+  // Have to do this in a first pass, because some of the destructors might
+  // refer to memory in other blocks.
+  CleanupList();
+
+  // Discard all blocks except the special block (if present).
+  size_t space_allocated = 0;
+  auto mem = Free(&space_allocated);
+
+  if (AllocPolicy()) {
+    auto saved_policy = *AllocPolicy();
+    if (alloc_policy_ & kUserOwnedInitialBlock) {
+      space_allocated += mem.size;
+    } else {
+      GetDeallocator(AllocPolicy(), &space_allocated)(mem);
+      mem.ptr = nullptr;
+      mem.size = 0;
+    }
+    ArenaMetricsCollector* collector = saved_policy.metrics_collector;
+    if (collector) collector->OnReset(space_allocated);
+    InitializeWithPolicy(mem.ptr, mem.size, ShouldRecordAlloc(), saved_policy);
+  } else {
+    // Nullptr policy
+    if (alloc_policy_ & kUserOwnedInitialBlock) {
+      space_allocated += mem.size;
+      InitializeFrom(mem.ptr, mem.size);
+    } else {
+      GetDeallocator(AllocPolicy(), &space_allocated)(mem);
+      Init(false);
+    }
+  }
 
   return space_allocated;
 }
 
-ArenaImpl::Block* ArenaImpl::NewBlock(Block* last_block, size_t min_bytes) {
-  size_t size;
-  if (last_block) {
-    // Double the current block size, up to a limit.
-    size = std::min(2 * last_block->size(), options_.max_block_size);
-  } else {
-    size = options_.start_block_size;
-  }
-  // Verify that min_bytes + kBlockHeaderSize won't overflow.
-  GOOGLE_CHECK_LE(min_bytes, std::numeric_limits<size_t>::max() - kBlockHeaderSize);
-  size = std::max(size, kBlockHeaderSize + min_bytes);
-
-  void* mem = options_.block_alloc(size);
-  Block* b = new (mem) Block(size, last_block);
-  space_allocated_.fetch_add(size, std::memory_order_relaxed);
-  return b;
-}
-
-ArenaImpl::Block::Block(size_t size, Block* next)
-    : next_(next), pos_(kBlockHeaderSize), size_(size) {}
-
-PROTOBUF_NOINLINE
-void ArenaImpl::SerialArena::AddCleanupFallback(void* elem,
-                                                void (*cleanup)(void*)) {
-  size_t size = cleanup_ ? cleanup_->size * 2 : kMinCleanupListElements;
-  size = std::min(size, kMaxCleanupListElements);
-  size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size));
-  CleanupChunk* list = reinterpret_cast<CleanupChunk*>(AllocateAligned(bytes));
-  list->next = cleanup_;
-  list->size = size;
-
-  cleanup_ = list;
-  cleanup_ptr_ = &list->nodes[0];
-  cleanup_limit_ = &list->nodes[size];
-
-  AddCleanup(elem, cleanup);
-}
-
-void* ArenaImpl::AllocateAlignedAndAddCleanup(size_t n,
-                                              void (*cleanup)(void*)) {
+std::pair<void*, SerialArena::CleanupNode*>
+ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
+                                            const std::type_info* type) {
   SerialArena* arena;
-  if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
-    return arena->AllocateAlignedAndAddCleanup(n, cleanup);
+  if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(tag_and_id_, &arena))) {
+    return arena->AllocateAlignedWithCleanup(n, AllocPolicy());
   } else {
-    return AllocateAlignedAndAddCleanupFallback(n, cleanup);
+    return AllocateAlignedWithCleanupFallback(n, type);
   }
 }
 
-void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) {
+void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) {
   SerialArena* arena;
-  if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
-    arena->AddCleanup(elem, cleanup);
+  if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(LifeCycleId(), &arena))) {
+    arena->AddCleanup(elem, cleanup, AllocPolicy());
   } else {
     return AddCleanupFallback(elem, cleanup);
   }
 }
 
 PROTOBUF_NOINLINE
-void* ArenaImpl::AllocateAlignedFallback(size_t n) {
-  return GetSerialArena()->AllocateAligned(n);
-}
-
-PROTOBUF_NOINLINE
-void* ArenaImpl::AllocateAlignedAndAddCleanupFallback(size_t n,
-                                                      void (*cleanup)(void*)) {
-  return GetSerialArena()->AllocateAlignedAndAddCleanup(n, cleanup);
-}
-
-PROTOBUF_NOINLINE
-void ArenaImpl::AddCleanupFallback(void* elem, void (*cleanup)(void*)) {
-  GetSerialArena()->AddCleanup(elem, cleanup);
-}
-
-ArenaImpl::SerialArena* ArenaImpl::GetSerialArena() {
-  SerialArena* arena;
-  if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
-    return arena;
-  } else {
-    return GetSerialArenaFallback(&thread_cache());
+void* ThreadSafeArena::AllocateAlignedFallback(size_t n,
+                                               const std::type_info* type) {
+  if (ShouldRecordAlloc()) {
+    RecordAlloc(type, n);
+    SerialArena* arena;
+    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(LifeCycleId(), &arena))) {
+      return arena->AllocateAligned(n, AllocPolicy());
+    }
   }
+  return GetSerialArenaFallback(&thread_cache())
+      ->AllocateAligned(n, AllocPolicy());
 }
 
 PROTOBUF_NOINLINE
-void* ArenaImpl::SerialArena::AllocateAlignedFallback(size_t n) {
-  // Sync back to current's pos.
-  head_->set_pos(head_->size() - (limit_ - ptr_));
-
-  head_ = arena_->NewBlock(head_, n);
-  ptr_ = head_->Pointer(head_->pos());
-  limit_ = head_->Pointer(head_->size());
-
-#ifdef ADDRESS_SANITIZER
-  ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
-#endif  // ADDRESS_SANITIZER
-
-  return AllocateAligned(n);
+std::pair<void*, SerialArena::CleanupNode*>
+ThreadSafeArena::AllocateAlignedWithCleanupFallback(
+    size_t n, const std::type_info* type) {
+  if (ShouldRecordAlloc()) {
+    RecordAlloc(type, n);
+    SerialArena* arena;
+    if (GetSerialArenaFast(LifeCycleId(), &arena)) {
+      return arena->AllocateAlignedWithCleanup(n, AllocPolicy());
+    }
+  }
+  return GetSerialArenaFallback(&thread_cache())
+      ->AllocateAlignedWithCleanup(n, AllocPolicy());
 }
 
-uint64 ArenaImpl::SpaceAllocated() const {
-  return space_allocated_.load(std::memory_order_relaxed);
+PROTOBUF_NOINLINE
+void ThreadSafeArena::AddCleanupFallback(void* elem, void (*cleanup)(void*)) {
+  GetSerialArenaFallback(&thread_cache())
+      ->AddCleanup(elem, cleanup, AllocPolicy());
 }
 
-uint64 ArenaImpl::SpaceUsed() const {
+uint64 ThreadSafeArena::SpaceAllocated() const {
+  SerialArena* serial = threads_.load(std::memory_order_acquire);
+  uint64 res = 0;
+  for (; serial; serial = serial->next()) {
+    res += serial->SpaceAllocated();
+  }
+  return res;
+}
+
+uint64 ThreadSafeArena::SpaceUsed() const {
   SerialArena* serial = threads_.load(std::memory_order_acquire);
   uint64 space_used = 0;
   for (; serial; serial = serial->next()) {
     space_used += serial->SpaceUsed();
   }
-  return space_used;
+  return space_used - (AllocPolicy() ? sizeof(AllocationPolicy) : 0);
 }
 
-uint64 ArenaImpl::SerialArena::SpaceUsed() const {
-  // Get current block's size from ptr_ (since we can't trust head_->pos().
-  uint64 space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
-  // Get subsequent block size from b->pos().
-  for (Block* b = head_->next(); b; b = b->next()) {
-    space_used += (b->pos() - kBlockHeaderSize);
-  }
-  // Remove the overhead of the SerialArena itself.
-  space_used -= kSerialArenaSize;
-  return space_used;
-}
-
-uint64 ArenaImpl::FreeBlocks() {
-  uint64 space_allocated = 0;
-  // By omitting an Acquire barrier we ensure that any user code that doesn't
-  // properly synchronize Reset() or the destructor will throw a TSAN warning.
-  SerialArena* serial = threads_.load(std::memory_order_relaxed);
-
-  while (serial) {
-    // This is inside a block we are freeing, so we need to read it now.
-    SerialArena* next = serial->next();
-    space_allocated += ArenaImpl::SerialArena::Free(serial, initial_block_,
-                                                    options_.block_dealloc);
-    // serial is dead now.
-    serial = next;
-  }
-
-  return space_allocated;
-}
-
-uint64 ArenaImpl::SerialArena::Free(ArenaImpl::SerialArena* serial,
-                                    Block* initial_block,
-                                    void (*block_dealloc)(void*, size_t)) {
-  uint64 space_allocated = 0;
-
-  // We have to be careful in this function, since we will be freeing the Block
-  // that contains this SerialArena.  Be careful about accessing |serial|.
-
-  for (Block* b = serial->head_; b;) {
-    // This is inside the block we are freeing, so we need to read it now.
-    Block* next_block = b->next();
-    space_allocated += (b->size());
-
-#ifdef ADDRESS_SANITIZER
-    // This memory was provided by the underlying allocator as unpoisoned, so
-    // return it in an unpoisoned state.
-    ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size());
-#endif  // ADDRESS_SANITIZER
-
-    if (b != initial_block) {
-      block_dealloc(b, b->size());
-    }
-
-    b = next_block;
-  }
-
-  return space_allocated;
-}
-
-void ArenaImpl::CleanupList() {
-  // By omitting an Acquire barrier we ensure that any user code that doesn't
-  // properly synchronize Reset() or the destructor will throw a TSAN warning.
-  SerialArena* serial = threads_.load(std::memory_order_relaxed);
-
-  for (; serial; serial = serial->next()) {
-    serial->CleanupList();
-  }
-}
-
-void ArenaImpl::SerialArena::CleanupList() {
-  if (cleanup_ != NULL) {
-    CleanupListFallback();
-  }
-}
-
-void ArenaImpl::SerialArena::CleanupListFallback() {
-  // The first chunk might be only partially full, so calculate its size
-  // from cleanup_ptr_. Subsequent chunks are always full, so use list->size.
-  size_t n = cleanup_ptr_ - &cleanup_->nodes[0];
-  CleanupChunk* list = cleanup_;
-  while (true) {
-    CleanupNode* node = &list->nodes[0];
-    // Cleanup newest elements first (allocated last).
-    for (size_t i = n; i > 0; i--) {
-      node[i - 1].cleanup(node[i - 1].elem);
-    }
-    list = list->next;
-    if (list == nullptr) {
-      break;
-    }
-    // All but the first chunk are always full.
-    n = list->size;
-  }
-}
-
-ArenaImpl::SerialArena* ArenaImpl::SerialArena::New(Block* b, void* owner,
-                                                    ArenaImpl* arena) {
-  GOOGLE_DCHECK_EQ(b->pos(), kBlockHeaderSize);  // Should be a fresh block
-  GOOGLE_DCHECK_LE(kBlockHeaderSize + kSerialArenaSize, b->size());
-  SerialArena* serial =
-      reinterpret_cast<SerialArena*>(b->Pointer(kBlockHeaderSize));
-  b->set_pos(kBlockHeaderSize + kSerialArenaSize);
-  serial->arena_ = arena;
-  serial->owner_ = owner;
-  serial->head_ = b;
-  serial->ptr_ = b->Pointer(b->pos());
-  serial->limit_ = b->Pointer(b->size());
-  serial->cleanup_ = NULL;
-  serial->cleanup_ptr_ = NULL;
-  serial->cleanup_limit_ = NULL;
-  return serial;
+void ThreadSafeArena::CleanupList() {
+  PerSerialArena([](SerialArena* a) { a->CleanupList(); });
 }
 
 PROTOBUF_NOINLINE
-ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) {
+SerialArena* ThreadSafeArena::GetSerialArenaFallback(void* me) {
   // Look for this SerialArena in our linked list.
   SerialArena* serial = threads_.load(std::memory_order_acquire);
   for (; serial; serial = serial->next()) {
@@ -343,8 +441,8 @@
   if (!serial) {
     // This thread doesn't have any SerialArena, which also means it doesn't
     // have any blocks yet.  So we'll allocate its first block now.
-    Block* b = NewBlock(NULL, kSerialArenaSize);
-    serial = SerialArena::New(b, me, this);
+    serial = SerialArena::New(
+        AllocateMemory(AllocPolicy(), 0, kSerialArenaSize), me);
 
     SerialArena* head = threads_.load(std::memory_order_relaxed);
     do {
@@ -361,28 +459,21 @@
 
 PROTOBUF_FUNC_ALIGN(32)
 void* Arena::AllocateAlignedNoHook(size_t n) {
-  return impl_.AllocateAligned(n);
+  return impl_.AllocateAligned(n, nullptr);
 }
 
-void Arena::CallDestructorHooks() {
-  uint64 space_allocated = impl_.SpaceAllocated();
-  // Call the reset hook
-  if (on_arena_reset_ != NULL) {
-    on_arena_reset_(this, hooks_cookie_, space_allocated);
-  }
-
-  // Call the destruction hook
-  if (on_arena_destruction_ != NULL) {
-    on_arena_destruction_(this, hooks_cookie_, space_allocated);
-  }
+PROTOBUF_FUNC_ALIGN(32)
+void* Arena::AllocateAlignedWithHook(size_t n, const std::type_info* type) {
+  return impl_.AllocateAligned(n, type);
 }
 
-void Arena::OnArenaAllocation(const std::type_info* allocated_type,
-                              size_t n) const {
-  if (on_arena_allocation_ != NULL) {
-    on_arena_allocation_(allocated_type, n, hooks_cookie_);
-  }
+PROTOBUF_FUNC_ALIGN(32)
+std::pair<void*, internal::SerialArena::CleanupNode*>
+Arena::AllocateAlignedWithCleanup(size_t n, const std::type_info* type) {
+  return impl_.AllocateAlignedWithCleanup(n, type);
 }
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 038553c..897a70f 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -84,6 +84,10 @@
 
 }  // namespace arena_metrics
 
+namespace TestUtil {
+class ReflectionTester;  // defined in test_util.h
+}  // namespace TestUtil
+
 namespace internal {
 
 struct ArenaStringPtr;  // defined in arenastring.h
@@ -93,24 +97,32 @@
 template <typename Type>
 class GenericTypeHandler;  // defined in repeated_field.h
 
+inline PROTOBUF_ALWAYS_INLINE
+void* AlignTo(void* ptr, size_t align) {
+  return reinterpret_cast<void*>(
+      (reinterpret_cast<uintptr_t>(ptr) + align - 1) & (~align + 1));
+}
+
 // Templated cleanup methods.
 template <typename T>
 void arena_destruct_object(void* object) {
   reinterpret_cast<T*>(object)->~T();
 }
+
+template <bool destructor_skippable, typename T>
+struct ObjectDestructor {
+  constexpr static void (*destructor)(void*) = &arena_destruct_object<T>;
+};
+
+template <typename T>
+struct ObjectDestructor<true, T> {
+  constexpr static void (*destructor)(void*) = nullptr;
+};
+
 template <typename T>
 void arena_delete_object(void* object) {
   delete reinterpret_cast<T*>(object);
 }
-inline void arena_free(void* object, size_t size) {
-#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
-  ::operator delete(object, size);
-#else
-  (void)size;
-  ::operator delete(object);
-#endif
-}
-
 }  // namespace internal
 
 // ArenaOptions provides optional additional parameters to arena construction
@@ -147,46 +159,36 @@
   void (*block_dealloc)(void*, size_t);
 
   ArenaOptions()
-      : start_block_size(kDefaultStartBlockSize),
-        max_block_size(kDefaultMaxBlockSize),
+      : start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize),
+        max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize),
         initial_block(NULL),
         initial_block_size(0),
-        block_alloc(&::operator new),
-        block_dealloc(&internal::arena_free),
-        on_arena_init(NULL),
-        on_arena_reset(NULL),
-        on_arena_destruction(NULL),
-        on_arena_allocation(NULL) {}
+        block_alloc(nullptr),
+        block_dealloc(nullptr),
+        make_metrics_collector(nullptr) {}
 
  private:
-  // Hooks for adding external functionality such as user-specific metrics
-  // collection, specific debugging abilities, etc.
-  // Init hook (if set) will always be called at Arena init time. Init hook may
-  // return a pointer to a cookie to be stored in the arena. Reset and
-  // destruction hooks will then be called with the same cookie pointer. This
-  // allows us to save an external object per arena instance and use it on the
-  // other hooks (Note: If init hook returns NULL, the other hooks will NOT be
-  // called on this arena instance).
-  // on_arena_reset and on_arena_destruction also receive the space used in the
-  // arena just before the reset.
-  void* (*on_arena_init)(Arena* arena);
-  void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
-  void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
+  // If make_metrics_collector is not nullptr, it will be called at Arena init
+  // time. It may return a pointer to a collector instance that will be notified
+  // of interesting events related to the arena.
+  internal::ArenaMetricsCollector* (*make_metrics_collector)();
 
-  // type_info is promised to be static - its lifetime extends to
-  // match program's lifetime (It is given by typeid operator).
-  // Note: typeid(void) will be passed as allocated_type every time we
-  // intentionally want to avoid monitoring an allocation. (i.e. internal
-  // allocations for managing the arena)
-  void (*on_arena_allocation)(const std::type_info* allocated_type,
-                              uint64 alloc_size, void* cookie);
+  internal::ArenaMetricsCollector* MetricsCollector() const {
+    return make_metrics_collector ? (*make_metrics_collector)() : nullptr;
+  }
 
-  // Constants define default starting block size and max block size for
-  // arena allocator behavior -- see descriptions above.
-  static const size_t kDefaultStartBlockSize = 256;
-  static const size_t kDefaultMaxBlockSize = 8192;
+  internal::AllocationPolicy AllocationPolicy() const {
+    internal::AllocationPolicy res;
+    res.start_block_size = start_block_size;
+    res.max_block_size = max_block_size;
+    res.block_alloc = block_alloc;
+    res.block_dealloc = block_dealloc;
+    res.metrics_collector = MetricsCollector();
+    return res;
+  }
 
   friend void arena_metrics::EnableArenaMetrics(ArenaOptions*);
+
   friend class Arena;
   friend class ArenaOptionsTestFriend;
 };
@@ -246,11 +248,22 @@
 // should not rely on this protocol.
 class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
  public:
-  // Arena constructor taking custom options. See ArenaOptions below for
+  // Default constructor with sensible default options, tuned for average
+  // use-cases.
+  inline Arena() : impl_() {}
+
+  // Construct an arena with default options, except for the supplied
+  // initial block. It is more efficient to use this constructor
+  // instead of passing ArenaOptions if the only configuration needed
+  // by the caller is supplying an initial block.
+  inline Arena(char* initial_block, size_t initial_block_size)
+      : impl_(initial_block, initial_block_size) {}
+
+  // Arena constructor taking custom options. See ArenaOptions above for
   // descriptions of the options available.
-  explicit Arena(const ArenaOptions& options) : impl_(options) {
-    Init(options);
-  }
+  explicit Arena(const ArenaOptions& options)
+      : impl_(options.initial_block, options.initial_block_size,
+              options.AllocationPolicy()) {}
 
   // Block overhead.  Use this as a guide for how much to over-allocate the
   // initial block if you want an allocation of size N to fit inside it.
@@ -258,30 +271,14 @@
   // WARNING: if you allocate multiple objects, it is difficult to guarantee
   // that a series of allocations will fit in the initial block, especially if
   // Arena changes its alignment guarantees in the future!
-  static const size_t kBlockOverhead = internal::ArenaImpl::kBlockHeaderSize +
-                                       internal::ArenaImpl::kSerialArenaSize;
+  static const size_t kBlockOverhead =
+      internal::ThreadSafeArena::kBlockHeaderSize +
+      internal::ThreadSafeArena::kSerialArenaSize;
 
-  // Default constructor with sensible default options, tuned for average
-  // use-cases.
-  Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); }
+  inline ~Arena() {}
 
-  ~Arena() {
-    if (hooks_cookie_) {
-      CallDestructorHooks();
-    }
-  }
-
-  void Init(const ArenaOptions& options) {
-    on_arena_allocation_ = options.on_arena_allocation;
-    on_arena_reset_ = options.on_arena_reset;
-    on_arena_destruction_ = options.on_arena_destruction;
-    // Call the initialization hook
-    if (options.on_arena_init != NULL) {
-      hooks_cookie_ = options.on_arena_init(this);
-    } else {
-      hooks_cookie_ = NULL;
-    }
-  }
+  // TODO(protobuf-team): Fix callers to use constructor and delete this method.
+  void Init(const ArenaOptions&) {}
 
   // API to create proto2 message objects on the arena. If the arena passed in
   // is NULL, then a heap allocated object is returned. Type T must be a message
@@ -320,9 +317,9 @@
   // if the object were allocated on the heap (except that the underlying memory
   // is obtained from the arena).
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* Create(Arena* arena, Args&&... args) {
-    return CreateNoMessage<T>(arena, is_arena_constructable<T>(),
-                              std::forward<Args>(args)...);
+  PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
+    return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
+                             std::forward<Args>(args)...);
   }
 
   // Create an array of object type T on the arena *without* invoking the
@@ -332,9 +329,9 @@
   // (when compiled as C++11) that T is trivially default-constructible and
   // trivially destructible.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static T* CreateArray(Arena* arena,
+  PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
                                                size_t num_elements) {
-    static_assert(std::is_pod<T>::value,
+    static_assert(std::is_trivial<T>::value,
                   "CreateArray requires a trivially constructible type");
     static_assert(std::is_trivially_destructible<T>::value,
                   "CreateArray requires a trivially destructible type");
@@ -347,9 +344,12 @@
     }
   }
 
+  // The following are routines are for monitoring. They will approximate the
+  // total sum allocated and used memory, but the exact value is an
+  // implementation deal. For instance allocated space depends on growth
+  // policies. Do not use these in unit tests.
   // Returns the total space allocated by the arena, which is the sum of the
-  // sizes of the underlying blocks. This method is relatively fast; a counter
-  // is kept as blocks are allocated.
+  // sizes of the underlying blocks.
   uint64 SpaceAllocated() const { return impl_.SpaceAllocated(); }
   // Returns the total space used by the arena. Similar to SpaceAllocated but
   // does not include free space and block overhead. The total space returned
@@ -362,19 +362,13 @@
   // Any objects allocated on this arena are unusable after this call. It also
   // returns the total space used by the arena which is the sums of the sizes
   // of the allocated blocks. This method is not thread-safe.
-  PROTOBUF_NOINLINE uint64 Reset() {
-    // Call the reset hook
-    if (on_arena_reset_ != NULL) {
-      on_arena_reset_(this, hooks_cookie_, impl_.SpaceAllocated());
-    }
-    return impl_.Reset();
-  }
+  uint64 Reset() { return impl_.Reset(); }
 
   // Adds |object| to a list of heap-allocated objects to be freed with |delete|
   // when the arena is destroyed or reset.
   template <typename T>
-  PROTOBUF_NOINLINE void Own(T* object) {
-    OwnInternal(object, std::is_convertible<T*, Message*>());
+  PROTOBUF_ALWAYS_INLINE void Own(T* object) {
+    OwnInternal(object, std::is_convertible<T*, MessageLite*>());
   }
 
   // Adds |object| to a list of objects whose destructors will be manually
@@ -383,7 +377,7 @@
   // normally only used for objects that are placement-newed into
   // arena-allocated memory.
   template <typename T>
-  PROTOBUF_NOINLINE void OwnDestructor(T* object) {
+  PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) {
     if (object != NULL) {
       impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
     }
@@ -393,8 +387,8 @@
   // will be manually called when the arena is destroyed or reset. This differs
   // from OwnDestructor() in that any member function may be specified, not only
   // the class destructor.
-  PROTOBUF_NOINLINE void OwnCustomDestructor(void* object,
-                                             void (*destruct)(void*)) {
+  PROTOBUF_ALWAYS_INLINE void OwnCustomDestructor(void* object,
+                                                  void (*destruct)(void*)) {
     impl_.AddCleanup(object, destruct);
   }
 
@@ -409,6 +403,49 @@
 
   template <typename T>
   class InternalHelper {
+   public:
+    // Provides access to protected GetOwningArena to generated messages.
+    static Arena* GetOwningArena(const T* p) { return p->GetOwningArena(); }
+
+    // Provides access to protected GetArenaForAllocation to generated messages.
+    static Arena* GetArenaForAllocation(const T* p) {
+      return GetArenaForAllocationInternal(
+          p, std::is_convertible<T*, MessageLite*>());
+    }
+
+   private:
+    static Arena* GetArenaForAllocationInternal(
+        const T* p, std::true_type /*is_derived_from<MessageLite>*/) {
+      return p->GetArenaForAllocation();
+    }
+
+    static Arena* GetArenaForAllocationInternal(
+        const T* p, std::false_type /*is_derived_from<MessageLite>*/) {
+      return GetArenaForAllocationForNonMessage(
+          p, typename is_arena_constructable::type());
+    }
+
+    static Arena* GetArenaForAllocationForNonMessage(
+        const T* p, std::true_type /*is_arena_constructible*/) {
+      return p->GetArena();
+    }
+
+    static Arena* GetArenaForAllocationForNonMessage(
+        const T* p, std::false_type /*is_arena_constructible*/) {
+      return GetArenaForAllocationForNonMessageNonArenaConstructible(
+          p, typename has_get_arena::type());
+    }
+
+    static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
+        const T* p, std::true_type /*has_get_arena*/) {
+      return p->GetArena();
+    }
+
+    static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
+        const T* /* p */, std::false_type /*has_get_arena*/) {
+      return nullptr;
+    }
+
     template <typename U>
     static char DestructorSkippable(const typename U::DestructorSkippable_*);
     template <typename U>
@@ -449,9 +486,14 @@
       return new (ptr) T(std::forward<Args>(args)...);
     }
 
+    static T* New() {
+      return new T(nullptr);
+    }
+
     static Arena* GetArena(const T* p) { return p->GetArena(); }
 
     friend class Arena;
+    friend class TestUtil::ReflectionTester;
   };
 
   // Helper typetraits that indicates support for arenas in a type T at compile
@@ -473,11 +515,13 @@
   };
 
  private:
+  internal::ThreadSafeArena impl_;
+
   template <typename T>
   struct has_get_arena : InternalHelper<T>::has_get_arena {};
 
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena,
+  PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena,
                                                          Args&&... args) {
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
@@ -493,50 +537,40 @@
   // slightly different.  When the arena pointer is nullptr, it calls T()
   // instead of T(nullptr).
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena) {
+  PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) {
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
         "CreateMessage can only construct types that are ArenaConstructable");
     if (arena == NULL) {
-      return new T();
+      // Generated arena constructor T(Arena*) is protected. Call via
+      // InternalHelper.
+      return InternalHelper<T>::New();
     } else {
       return arena->DoCreateMessage<T>();
     }
   }
 
-  template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena,
-                                                  Args&&... args) {
-    if (arena == NULL) {
-      return new T(std::forward<Args>(args)...);
-    } else {
-      return arena->DoCreate<T>(std::is_trivially_destructible<T>::value,
-                                std::forward<Args>(args)...);
-    }
-  }
-
-  void CallDestructorHooks();
-  void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const;
-  inline void AllocHook(const std::type_info* allocated_type, size_t n) const {
-    if (PROTOBUF_PREDICT_FALSE(hooks_cookie_ != NULL)) {
-      OnArenaAllocation(allocated_type, n);
-    }
-  }
-
-  // Allocate and also optionally call on_arena_allocation callback with the
-  // allocated type info when the hooks are in place in ArenaOptions and
-  // the cookie is not null.
-  template <typename T>
-  PROTOBUF_ALWAYS_INLINE void* AllocateInternal(bool skip_explicit_ownership) {
-    static_assert(alignof(T) <= 8, "T is overaligned, see b/151247138");
-    const size_t n = internal::AlignUpTo8(sizeof(T));
-    AllocHook(RTTI_TYPE_ID(T), n);
+  // Allocate and also optionally call collector with the allocated type info
+  // when allocation recording is enabled.
+  PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align,
+                                                void (*destructor)(void*),
+                                                const std::type_info* type) {
     // Monitor allocation if needed.
-    if (skip_explicit_ownership) {
-      return AllocateAlignedNoHook(n);
+    if (destructor == nullptr) {
+      return AllocateAlignedWithHook(size, align, type);
     } else {
-      return impl_.AllocateAlignedAndAddCleanup(
-          n, &internal::arena_destruct_object<T>);
+      if (align <= 8) {
+        auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type);
+        res.second->elem = res.first;
+        res.second->cleanup = destructor;
+        return res.first;
+      } else {
+        auto res = AllocateAlignedWithCleanup(size + align - 8, type);
+        auto ptr = internal::AlignTo(res.first, align);
+        res.second->elem = ptr;
+        res.second->cleanup = destructor;
+        return ptr;
+      }
     }
   }
 
@@ -556,7 +590,7 @@
   PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
                                                         std::false_type,
                                                         Args&&... args) {
-    return CreateInternal<T>(arena, std::forward<Args>(args)...);
+    return Create<T>(arena, std::forward<Args>(args)...);
   }
 
   template <typename T, typename... Args>
@@ -566,47 +600,27 @@
                                    std::forward<Args>(args)...);
   }
 
-  template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* CreateNoMessage(Arena* arena, std::true_type,
-                                                   Args&&... args) {
-    // User is constructing with Create() despite the fact that T supports arena
-    // construction.  In this case we have to delegate to CreateInternal(), and
-    // we can't use any CreateMaybeMessage() specialization that may be defined.
-    return CreateInternal<T>(arena, std::forward<Args>(args)...);
-  }
-
-  template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* CreateNoMessage(Arena* arena,
-                                                   std::false_type,
-                                                   Args&&... args) {
-    // User is constructing with Create() and the type does not support arena
-    // construction.  In this case we can delegate to CreateMaybeMessage() and
-    // use any specialization that may be available for that.
-    return CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
-  }
-
   // Just allocate the required size for the given type assuming the
   // type has a trivial constructor.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE T* CreateInternalRawArray(size_t num_elements) {
+  PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) {
     GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
         << "Requested size is too large to fit into size_t.";
-    const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements);
-    // Monitor allocation if needed.
-    AllocHook(RTTI_TYPE_ID(T), n);
-    return static_cast<T*>(AllocateAlignedNoHook(n));
+    // We count on compiler to realize that if sizeof(T) is a multiple of
+    // 8 AlignUpTo can be elided.
+    const size_t n = sizeof(T) * num_elements;
+    return static_cast<T*>(
+        AllocateAlignedWithHook(n, alignof(T), RTTI_TYPE_ID(T)));
   }
 
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE T* DoCreate(bool skip_explicit_ownership,
-                                     Args&&... args) {
-    return new (AllocateInternal<T>(skip_explicit_ownership))
-        T(std::forward<Args>(args)...);
-  }
-  template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
+  PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
     return InternalHelper<T>::Construct(
-        AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
+        AllocateInternal(sizeof(T), alignof(T),
+                         internal::ObjectDestructor<
+                             InternalHelper<T>::is_destructor_skippable::value,
+                             T>::destructor,
+                         RTTI_TYPE_ID(T)),
         this, std::forward<Args>(args)...);
   }
 
@@ -643,6 +657,39 @@
     arena->OwnDestructor(ptr);
   }
 
+  // These implement Create(). The second parameter has type 'true_type' if T is
+  // a subtype of Message and 'false_type' otherwise.
+  template <typename T, typename... Args>
+  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type,
+                                                  Args&&... args) {
+    if (arena == nullptr) {
+      return new T(std::forward<Args>(args)...);
+    } else {
+      auto destructor =
+          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
+                                     T>::destructor;
+      T* result =
+          new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
+                                       RTTI_TYPE_ID(T)))
+          T(std::forward<Args>(args)...);
+      return result;
+    }
+  }
+  template <typename T, typename... Args>
+  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type,
+                                                  Args&&... args) {
+    if (arena == nullptr) {
+      return new T(std::forward<Args>(args)...);
+    } else {
+      auto destructor =
+          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
+                                     T>::destructor;
+      return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
+                                          RTTI_TYPE_ID(T)))
+          T(std::forward<Args>(args)...);
+    }
+  }
+
   // These implement Own(), which registers an object for deletion (destructor
   // call and operator delete()). The second parameter has type 'true_type' if T
   // is a subtype of Message and 'false_type' otherwise. Collapsing
@@ -651,7 +698,7 @@
   template <typename T>
   PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
     if (object != NULL) {
-      impl_.AddCleanup(object, &internal::arena_delete_object<Message>);
+      impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
     }
   }
   template <typename T>
@@ -685,35 +732,58 @@
     return nullptr;
   }
 
-  // For friends of arena.
-  void* AllocateAligned(size_t n) {
-    AllocHook(NULL, n);
-    return AllocateAlignedNoHook(internal::AlignUpTo8(n));
+  template <typename T>
+  PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArena(const T* value) {
+    return GetOwningArenaInternal(
+        value, std::is_convertible<T*, MessageLite*>());
   }
-  template<size_t Align>
-  void* AllocateAlignedTo(size_t n) {
-    static_assert(Align > 0, "Alignment must be greater than 0");
-    static_assert((Align & (Align - 1)) == 0, "Alignment must be power of two");
-    if (Align <= 8) return AllocateAligned(n);
-    // TODO(b/151247138): if the pointer would have been aligned already,
-    // this is wasting space. We should pass the alignment down.
-    uintptr_t ptr = reinterpret_cast<uintptr_t>(AllocateAligned(n + Align - 8));
-    ptr = (ptr + Align - 1) & -Align;
-    return reinterpret_cast<void*>(ptr);
+
+  // Implementation for GetOwningArena(). All and only message objects have
+  // GetOwningArena() method.
+  template <typename T>
+  PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
+      const T* value, std::true_type) {
+    return InternalHelper<T>::GetOwningArena(value);
+  }
+  template <typename T>
+  PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
+      const T* /* value */, std::false_type) {
+    return nullptr;
+  }
+
+  // For friends of arena.
+  void* AllocateAligned(size_t n, size_t align = 8) {
+    if (align <= 8) {
+      return AllocateAlignedNoHook(internal::AlignUpTo8(n));
+    } else {
+      // We are wasting space by over allocating align - 8 bytes. Compared
+      // to a dedicated function that takes current alignment in consideration.
+      // Such a scheme would only waste (align - 8)/2 bytes on average, but
+      // requires a dedicated function in the outline arena allocation
+      // functions. Possibly re-evaluate tradeoffs later.
+      return internal::AlignTo(AllocateAlignedNoHook(n + align - 8), align);
+    }
+  }
+
+  void* AllocateAlignedWithHook(size_t n, size_t align,
+                                const std::type_info* type) {
+    if (align <= 8) {
+      return AllocateAlignedWithHook(internal::AlignUpTo8(n), type);
+    } else {
+      // We are wasting space by over allocating align - 8 bytes. Compared
+      // to a dedicated function that takes current alignment in consideration.
+      // Such a schemee would only waste (align - 8)/2 bytes on average, but
+      // requires a dedicated function in the outline arena allocation
+      // functions. Possibly re-evaluate tradeoffs later.
+      return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type),
+                               align);
+    }
   }
 
   void* AllocateAlignedNoHook(size_t n);
-
-  internal::ArenaImpl impl_;
-
-  void (*on_arena_allocation_)(const std::type_info* allocated_type,
-                               uint64 alloc_size, void* cookie);
-  void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used);
-  void (*on_arena_destruction_)(Arena* arena, void* cookie, uint64 space_used);
-
-  // The arena may save a cookie it receives from the external on_init hook
-  // and then use it when calling the on_reset and on_destruction hooks.
-  void* hooks_cookie_;
+  void* AllocateAlignedWithHook(size_t n, const std::type_info* type);
+  std::pair<void*, internal::SerialArena::CleanupNode*>
+  AllocateAlignedWithCleanup(size_t n, const std::type_info* type);
 
   template <typename Type>
   friend class internal::GenericTypeHandler;
diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h
index d7b7ed7..40608df 100644
--- a/src/google/protobuf/arena_impl.h
+++ b/src/google/protobuf/arena_impl.h
@@ -35,6 +35,7 @@
 
 #include <atomic>
 #include <limits>
+#include <typeinfo>
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
@@ -50,95 +51,81 @@
 namespace protobuf {
 namespace internal {
 
-inline size_t AlignUpTo8(size_t n) {
+inline constexpr size_t AlignUpTo8(size_t n) {
   // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
   return (n + 7) & static_cast<size_t>(-8);
 }
 
-using LifecycleId = int64_t;
+using LifecycleIdAtomic = uint64_t;
 
-// This class provides the core Arena memory allocation library. Different
-// implementations only need to implement the public interface below.
-// Arena is not a template type as that would only be useful if all protos
-// in turn would be templates, which will/cannot happen. However separating
-// the memory allocation part from the cruft of the API users expect we can
-// use #ifdef the select the best implementation based on hardware / OS.
-class PROTOBUF_EXPORT ArenaImpl {
+// MetricsCollector collects stats for a particular arena.
+class PROTOBUF_EXPORT ArenaMetricsCollector {
  public:
-  struct Options {
-    size_t start_block_size;
-    size_t max_block_size;
-    char* initial_block;
-    size_t initial_block_size;
-    void* (*block_alloc)(size_t);
-    void (*block_dealloc)(void*, size_t);
+  ArenaMetricsCollector(bool record_allocs) : record_allocs_(record_allocs) {}
 
-    template <typename O>
-    explicit Options(const O& options)
-        : start_block_size(options.start_block_size),
-          max_block_size(options.max_block_size),
-          initial_block(options.initial_block),
-          initial_block_size(options.initial_block_size),
-          block_alloc(options.block_alloc),
-          block_dealloc(options.block_dealloc) {}
+  // Invoked when the arena is about to be destroyed. This method will
+  // typically finalize any metric collection and delete the collector.
+  // space_allocated is the space used by the arena.
+  virtual void OnDestroy(uint64 space_allocated) = 0;
+
+  // OnReset() is called when the associated arena is reset.
+  // space_allocated is the space used by the arena just before the reset.
+  virtual void OnReset(uint64 space_allocated) = 0;
+
+  // OnAlloc is called when an allocation happens.
+  // type_info is promised to be static - its lifetime extends to
+  // match program's lifetime (It is given by typeid operator).
+  // Note: typeid(void) will be passed as allocated_type every time we
+  // intentionally want to avoid monitoring an allocation. (i.e. internal
+  // allocations for managing the arena)
+  virtual void OnAlloc(const std::type_info* allocated_type,
+                       uint64 alloc_size) = 0;
+
+  // Does OnAlloc() need to be called?  If false, metric collection overhead
+  // will be reduced since we will not do extra work per allocation.
+  bool RecordAllocs() { return record_allocs_; }
+
+ protected:
+  // This class is destructed by the call to OnDestroy().
+  ~ArenaMetricsCollector() = default;
+  const bool record_allocs_;
+};
+
+struct AllocationPolicy {
+  static constexpr size_t kDefaultStartBlockSize = 256;
+  static constexpr size_t kDefaultMaxBlockSize = 8192;
+
+  size_t start_block_size = kDefaultStartBlockSize;
+  size_t max_block_size = kDefaultMaxBlockSize;
+  void* (*block_alloc)(size_t) = nullptr;
+  void (*block_dealloc)(void*, size_t) = nullptr;
+  ArenaMetricsCollector* metrics_collector = nullptr;
+
+  bool IsDefault() const {
+    return start_block_size == kDefaultMaxBlockSize &&
+           max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr &&
+           block_dealloc == nullptr && metrics_collector == nullptr;
+  }
+};
+
+// A simple arena allocator. Calls to allocate functions must be properly
+// serialized by the caller, hence this class cannot be used as a general
+// purpose allocator in a multi-threaded program. It serves as a building block
+// for ThreadSafeArena, which provides a thread-safe arena allocator.
+//
+// This class manages
+// 1) Arena bump allocation + owning memory blocks.
+// 2) Maintaining a cleanup list.
+// It delagetes the actual memory allocation back to ThreadSafeArena, which
+// contains the information on block growth policy and backing memory allocation
+// used.
+class PROTOBUF_EXPORT SerialArena {
+ public:
+  struct Memory {
+    void* ptr;
+    size_t size;
   };
 
-  template <typename O>
-  explicit ArenaImpl(const O& options) : options_(options) {
-    if (options_.initial_block != NULL && options_.initial_block_size > 0) {
-      GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block))
-          << ": Initial block size too small for header.";
-      initial_block_ = reinterpret_cast<Block*>(options_.initial_block);
-    } else {
-      initial_block_ = NULL;
-    }
-
-    Init();
-  }
-
-  // Destructor deletes all owned heap allocated objects, and destructs objects
-  // that have non-trivial destructors, except for proto2 message objects whose
-  // destructors can be skipped. Also, frees all blocks except the initial block
-  // if it was passed in.
-  ~ArenaImpl();
-
-  uint64 Reset();
-
-  uint64 SpaceAllocated() const;
-  uint64 SpaceUsed() const;
-
-  void* AllocateAligned(size_t n) {
-    SerialArena* arena;
-    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
-      return arena->AllocateAligned(n);
-    } else {
-      return AllocateAlignedFallback(n);
-    }
-  }
-
-  // This function allocates n bytes if the common happy case is true and
-  // returns true. Otherwise does nothing and returns false. This strange
-  // semantics is necessary to allow callers to program functions that only
-  // have fallback function calls in tail position. This substantially improves
-  // code for the happy path.
-  PROTOBUF_ALWAYS_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
-    SerialArena* a;
-    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFromThreadCache(&a))) {
-      return a->MaybeAllocateAligned(n, out);
-    }
-    return false;
-  }
-
-  void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*));
-
-  // Add object pointer and cleanup function pointer to the list.
-  void AddCleanup(void* elem, void (*cleanup)(void*));
-
- private:
-  void* AllocateAlignedFallback(size_t n);
-  void* AllocateAlignedAndAddCleanupFallback(size_t n, void (*cleanup)(void*));
-  void AddCleanupFallback(void* elem, void (*cleanup)(void*));
-
   // Node contains the ptr of the object to be cleaned up and the associated
   // cleanup function ptr.
   struct CleanupNode {
@@ -146,190 +133,239 @@
     void (*cleanup)(void*);  // Function pointer to the destructor or deleter.
   };
 
-  // Cleanup uses a chunked linked list, to reduce pointer chasing.
-  struct CleanupChunk {
-    static size_t SizeOf(size_t i) {
-      return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1));
+  // Creates a new SerialArena inside mem using the remaining memory as for
+  // future allocations.
+  static SerialArena* New(SerialArena::Memory mem, void* owner);
+  // Free SerialArena returning the memory passed in to New
+  template <typename Deallocator>
+  Memory Free(Deallocator deallocator);
+
+  void CleanupList();
+  uint64 SpaceAllocated() const {
+    return space_allocated_.load(std::memory_order_relaxed);
+  }
+  uint64 SpaceUsed() const;
+
+  bool HasSpace(size_t n) { return n <= static_cast<size_t>(limit_ - ptr_); }
+
+  void* AllocateAligned(size_t n, const AllocationPolicy* policy) {
+    GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
+    GOOGLE_DCHECK_GE(limit_, ptr_);
+    if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
+      return AllocateAlignedFallback(n, policy);
     }
-    size_t size;           // Total elements in the list.
-    CleanupChunk* next;    // Next node in the list.
-    CleanupNode nodes[1];  // True length is |size|.
-  };
-
-  class Block;
-
-  // A thread-unsafe Arena that can only be used within its owning thread.
-  class PROTOBUF_EXPORT SerialArena {
-   public:
-    // The allocate/free methods here are a little strange, since SerialArena is
-    // allocated inside a Block which it also manages.  This is to avoid doing
-    // an extra allocation for the SerialArena itself.
-
-    // Creates a new SerialArena inside Block* and returns it.
-    static SerialArena* New(Block* b, void* owner, ArenaImpl* arena);
-
-    // Destroys this SerialArena, freeing all blocks with the given dealloc
-    // function, except any block equal to |initial_block|.
-    static uint64 Free(SerialArena* serial, Block* initial_block,
-                       void (*block_dealloc)(void*, size_t));
-
-    void CleanupList();
-    uint64 SpaceUsed() const;
-
-    bool HasSpace(size_t n) { return n <= static_cast<size_t>(limit_ - ptr_); }
-
-    void* AllocateAligned(size_t n) {
-      GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
-      GOOGLE_DCHECK_GE(limit_, ptr_);
-      if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
-        return AllocateAlignedFallback(n);
-      }
-      void* ret = ptr_;
-      ptr_ += n;
+    void* ret = ptr_;
+    ptr_ += n;
 #ifdef ADDRESS_SANITIZER
-      ASAN_UNPOISON_MEMORY_REGION(ret, n);
+    ASAN_UNPOISON_MEMORY_REGION(ret, n);
 #endif  // ADDRESS_SANITIZER
-      return ret;
-    }
+    return ret;
+  }
 
-    // Allocate space if the current region provides enough space.
-    bool MaybeAllocateAligned(size_t n, void** out) {
-      GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
-      GOOGLE_DCHECK_GE(limit_, ptr_);
-      if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
-      void* ret = ptr_;
-      ptr_ += n;
+  // Allocate space if the current region provides enough space.
+  bool MaybeAllocateAligned(size_t n, void** out) {
+    GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
+    GOOGLE_DCHECK_GE(limit_, ptr_);
+    if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
+    void* ret = ptr_;
+    ptr_ += n;
 #ifdef ADDRESS_SANITIZER
-      ASAN_UNPOISON_MEMORY_REGION(ret, n);
+    ASAN_UNPOISON_MEMORY_REGION(ret, n);
 #endif  // ADDRESS_SANITIZER
-      *out = ret;
-      return true;
+    *out = ret;
+    return true;
+  }
+
+  std::pair<void*, CleanupNode*> AllocateAlignedWithCleanup(
+      size_t n, const AllocationPolicy* policy) {
+    if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) {
+      return AllocateAlignedWithCleanupFallback(n, policy);
     }
+    void* ret = ptr_;
+    ptr_ += n;
+    limit_ -= kCleanupSize;
+#ifdef ADDRESS_SANITIZER
+    ASAN_UNPOISON_MEMORY_REGION(ret, n);
+    ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize);
+#endif  // ADDRESS_SANITIZER
+    return CreatePair(ret, reinterpret_cast<CleanupNode*>(limit_));
+  }
 
-    void AddCleanup(void* elem, void (*cleanup)(void*)) {
-      if (PROTOBUF_PREDICT_FALSE(cleanup_ptr_ == cleanup_limit_)) {
-        AddCleanupFallback(elem, cleanup);
-        return;
-      }
-      cleanup_ptr_->elem = elem;
-      cleanup_ptr_->cleanup = cleanup;
-      cleanup_ptr_++;
-    }
+  void AddCleanup(void* elem, void (*cleanup)(void*),
+                  const AllocationPolicy* policy) {
+    auto res = AllocateAlignedWithCleanup(0, policy);
+    res.second->elem = elem;
+    res.second->cleanup = cleanup;
+  }
 
-    void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*)) {
-      void* ret = AllocateAligned(n);
-      AddCleanup(ret, cleanup);
-      return ret;
-    }
+  void* owner() const { return owner_; }
+  SerialArena* next() const { return next_; }
+  void set_next(SerialArena* next) { next_ = next; }
 
-    void* owner() const { return owner_; }
-    SerialArena* next() const { return next_; }
-    void set_next(SerialArena* next) { next_ = next; }
-
-   private:
-    void* AllocateAlignedFallback(size_t n);
-    void AddCleanupFallback(void* elem, void (*cleanup)(void*));
-    void CleanupListFallback();
-
-    ArenaImpl* arena_;       // Containing arena.
-    void* owner_;            // &ThreadCache of this thread;
-    Block* head_;            // Head of linked list of blocks.
-    CleanupChunk* cleanup_;  // Head of cleanup list.
-    SerialArena* next_;      // Next SerialArena in this linked list.
-
-    // Next pointer to allocate from.  Always 8-byte aligned.  Points inside
-    // head_ (and head_->pos will always be non-canonical).  We keep these
-    // here to reduce indirection.
-    char* ptr_;
-    char* limit_;
-
-    // Next CleanupList members to append to.  These point inside cleanup_.
-    CleanupNode* cleanup_ptr_;
-    CleanupNode* cleanup_limit_;
-  };
-
+ private:
   // Blocks are variable length malloc-ed objects.  The following structure
   // describes the common header for all blocks.
-  class PROTOBUF_EXPORT Block {
-   public:
-    Block(size_t size, Block* next);
-
+  struct Block {
     char* Pointer(size_t n) {
-      GOOGLE_DCHECK(n <= size_);
+      GOOGLE_DCHECK(n <= size);
       return reinterpret_cast<char*>(this) + n;
     }
 
-    Block* next() const { return next_; }
-    size_t pos() const { return pos_; }
-    size_t size() const { return size_; }
-    void set_pos(size_t pos) { pos_ = pos; }
-
-   private:
-    Block* next_;  // Next block for this thread.
-    size_t pos_;
-    size_t size_;
+    Block* next;
+    size_t size;
+    CleanupNode* start;
     // data follows
   };
 
-  struct ThreadCache {
-#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
-    // If we are using the ThreadLocalStorage class to store the ThreadCache,
-    // then the ThreadCache's default constructor has to be responsible for
-    // initializing it.
-    ThreadCache() : last_lifecycle_id_seen(-1), last_serial_arena(NULL) {}
-#endif
+  void* owner_;            // &ThreadCache of this thread;
+  Block* head_;            // Head of linked list of blocks.
+  SerialArena* next_;      // Next SerialArena in this linked list.
+  size_t space_used_ = 0;  // Necessary for metrics.
+  std::atomic<size_t> space_allocated_;
 
-    // The ThreadCache is considered valid as long as this matches the
-    // lifecycle_id of the arena being used.
-    LifecycleId last_lifecycle_id_seen;
-    SerialArena* last_serial_arena;
-  };
-  static std::atomic<LifecycleId> lifecycle_id_generator_;
-#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
-  // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
-  // local storage class we implemented.
-  // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
-  static ThreadCache& thread_cache();
-#elif defined(PROTOBUF_USE_DLLS)
-  // Thread local variables cannot be exposed through DLL interface but we can
-  // wrap them in static functions.
-  static ThreadCache& thread_cache();
-#else
-  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
-  static ThreadCache& thread_cache() { return thread_cache_; }
-#endif
+  // Next pointer to allocate from.  Always 8-byte aligned.  Points inside
+  // head_ (and head_->pos will always be non-canonical).  We keep these
+  // here to reduce indirection.
+  char* ptr_;
+  char* limit_;
 
-  void Init();
+  // Constructor is private as only New() should be used.
+  inline SerialArena(Block* b, void* owner);
+  void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy);
+  std::pair<void*, CleanupNode*> AllocateAlignedWithCleanupFallback(
+      size_t n, const AllocationPolicy* policy);
+  void AllocateNewBlock(size_t n, const AllocationPolicy* policy);
 
-  // Free all blocks and return the total space used which is the sums of sizes
-  // of the all the allocated blocks.
-  uint64 FreeBlocks();
+  std::pair<void*, CleanupNode*> CreatePair(void* ptr, CleanupNode* node) {
+    return {ptr, node};
+  }
+
+ public:
+  static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block));
+  static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode));
+};
+
+// This class provides the core Arena memory allocation library. Different
+// implementations only need to implement the public interface below.
+// Arena is not a template type as that would only be useful if all protos
+// in turn would be templates, which will/cannot happen. However separating
+// the memory allocation part from the cruft of the API users expect we can
+// use #ifdef the select the best implementation based on hardware / OS.
+class PROTOBUF_EXPORT ThreadSafeArena {
+ public:
+  ThreadSafeArena() { Init(false); }
+
+  ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); }
+
+  explicit ThreadSafeArena(void* mem, size_t size,
+                           const AllocationPolicy& policy) {
+    if (policy.IsDefault()) {
+      // Legacy code doesn't use the API above, but provides the initial block
+      // through ArenaOptions. I suspect most do not touch the allocation
+      // policy parameters.
+      InitializeFrom(mem, size);
+    } else {
+      auto collector = policy.metrics_collector;
+      bool record_allocs = collector && collector->RecordAllocs();
+      InitializeWithPolicy(mem, size, record_allocs, policy);
+    }
+  }
+
+  // Destructor deletes all owned heap allocated objects, and destructs objects
+  // that have non-trivial destructors, except for proto2 message objects whose
+  // destructors can be skipped. Also, frees all blocks except the initial block
+  // if it was passed in.
+  ~ThreadSafeArena();
+
+  uint64 Reset();
+
+  uint64 SpaceAllocated() const;
+  uint64 SpaceUsed() const;
+
+  void* AllocateAligned(size_t n, const std::type_info* type) {
+    SerialArena* arena;
+    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(tag_and_id_, &arena))) {
+      return arena->AllocateAligned(n, AllocPolicy());
+    } else {
+      return AllocateAlignedFallback(n, type);
+    }
+  }
+
+  // This function allocates n bytes if the common happy case is true and
+  // returns true. Otherwise does nothing and returns false. This strange
+  // semantics is necessary to allow callers to program functions that only
+  // have fallback function calls in tail position. This substantially improves
+  // code for the happy path.
+  PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
+    SerialArena* a;
+    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFromThreadCache(tag_and_id_, &a))) {
+      return a->MaybeAllocateAligned(n, out);
+    }
+    return false;
+  }
+
+  std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup(
+      size_t n, const std::type_info* type);
+
+  // Add object pointer and cleanup function pointer to the list.
+  void AddCleanup(void* elem, void (*cleanup)(void*));
+
+ private:
+  // Unique for each arena. Changes on Reset().
+  uint64 tag_and_id_;
+  // The LSB of tag_and_id_ indicates if allocs in this arena are recorded.
+  enum { kRecordAllocs = 1 };
+
+  intptr_t alloc_policy_ = 0;  // Tagged pointer to AllocPolicy.
+  // The LSB of alloc_policy_ indicates if the user owns the initial block.
+  enum { kUserOwnedInitialBlock = 1 };
+
+  // Pointer to a linked list of SerialArena.
+  std::atomic<SerialArena*> threads_;
+  std::atomic<SerialArena*> hint_;  // Fast thread-local block access
+
+  const AllocationPolicy* AllocPolicy() const {
+    return reinterpret_cast<const AllocationPolicy*>(alloc_policy_ & -8);
+  }
+  void InitializeFrom(void* mem, size_t size);
+  void InitializeWithPolicy(void* mem, size_t size, bool record_allocs,
+                            AllocationPolicy policy);
+  void* AllocateAlignedFallback(size_t n, const std::type_info* type);
+  std::pair<void*, SerialArena::CleanupNode*>
+  AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type);
+  void AddCleanupFallback(void* elem, void (*cleanup)(void*));
+
+  void Init(bool record_allocs);
+  void SetInitialBlock(void* mem, size_t size);
+
   // Delete or Destruct all objects owned by the arena.
   void CleanupList();
 
+  inline bool ShouldRecordAlloc() const { return tag_and_id_ & kRecordAllocs; }
+
+  inline uint64 LifeCycleId() const {
+    return tag_and_id_ & (-kRecordAllocs - 1);
+  }
+
+  inline void RecordAlloc(const std::type_info* allocated_type,
+                          size_t n) const {
+    AllocPolicy()->metrics_collector->OnAlloc(allocated_type, n);
+  }
+
   inline void CacheSerialArena(SerialArena* serial) {
     thread_cache().last_serial_arena = serial;
-    thread_cache().last_lifecycle_id_seen = lifecycle_id_;
+    thread_cache().last_lifecycle_id_seen = LifeCycleId();
     // TODO(haberman): evaluate whether we would gain efficiency by getting rid
-    // of hint_.  It's the only write we do to ArenaImpl in the allocation path,
-    // which will dirty the cache line.
+    // of hint_.  It's the only write we do to ThreadSafeArena in the allocation
+    // path, which will dirty the cache line.
 
     hint_.store(serial, std::memory_order_release);
   }
 
-  std::atomic<SerialArena*>
-      threads_;                     // Pointer to a linked list of SerialArena.
-  std::atomic<SerialArena*> hint_;  // Fast thread-local block access
-  std::atomic<size_t> space_allocated_;  // Total size of all allocated blocks.
-
-  Block* initial_block_;  // If non-NULL, points to the block that came from
-                          // user data.
-
-  Block* NewBlock(Block* last_block, size_t min_bytes);
-
-  SerialArena* GetSerialArena();
-  PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFast(SerialArena** arena) {
-    if (GetSerialArenaFromThreadCache(arena)) return true;
+  PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(uint64 lifecycle_id,
+                                                 SerialArena** arena) {
+    if (GetSerialArenaFromThreadCache(lifecycle_id, arena)) return true;
+    if (lifecycle_id & kRecordAllocs) return false;
 
     // Check whether we own the last accessed SerialArena on this arena.  This
     // fast path optimizes the case where a single thread uses multiple arenas.
@@ -342,35 +378,97 @@
     return false;
   }
 
-  PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFromThreadCache(
-      SerialArena** arena) {
+  PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
+      uint64 lifecycle_id, SerialArena** arena) {
     // If this thread already owns a block in this arena then try to use that.
     // This fast path optimizes the case where multiple threads allocate from
     // the same arena.
     ThreadCache* tc = &thread_cache();
-    if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == lifecycle_id_)) {
+    if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == lifecycle_id)) {
       *arena = tc->last_serial_arena;
       return true;
     }
     return false;
   }
   SerialArena* GetSerialArenaFallback(void* me);
-  LifecycleId lifecycle_id_;  // Unique for each arena. Changes on Reset().
 
-  Options options_;
+  template <typename Functor>
+  void PerSerialArena(Functor fn) {
+    // By omitting an Acquire barrier we ensure that any user code that doesn't
+    // properly synchronize Reset() or the destructor will throw a TSAN warning.
+    SerialArena* serial = threads_.load(std::memory_order_relaxed);
 
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl);
+    for (; serial; serial = serial->next()) fn(serial);
+  }
+
+  // Releases all memory except the first block which it returns. The first
+  // block might be owned by the user and thus need some extra checks before
+  // deleting.
+  SerialArena::Memory Free(size_t* space_allocated);
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4324)
+#endif
+  struct alignas(64) ThreadCache {
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+    // If we are using the ThreadLocalStorage class to store the ThreadCache,
+    // then the ThreadCache's default constructor has to be responsible for
+    // initializing it.
+    ThreadCache()
+        : next_lifecycle_id(0),
+          last_lifecycle_id_seen(-1),
+          last_serial_arena(NULL) {}
+#endif
+
+    // Number of per-thread lifecycle IDs to reserve. Must be power of two.
+    // To reduce contention on a global atomic, each thread reserves a batch of
+    // IDs.  The following number is calculated based on a stress test with
+    // ~6500 threads all frequently allocating a new arena.
+    static constexpr size_t kPerThreadIds = 256;
+    // Next lifecycle ID available to this thread. We need to reserve a new
+    // batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`.
+    uint64 next_lifecycle_id;
+    // The ThreadCache is considered valid as long as this matches the
+    // lifecycle_id of the arena being used.
+    uint64 last_lifecycle_id_seen;
+    SerialArena* last_serial_arena;
+  };
+
+  // Lifecycle_id can be highly contended variable in a situation of lots of
+  // arena creation. Make sure that other global variables are not sharing the
+  // cacheline.
+#ifdef _MSC_VER
+#pragma warning(disable : 4324)
+#endif
+  struct alignas(64) CacheAlignedLifecycleIdGenerator {
+    std::atomic<LifecycleIdAtomic> id;
+  };
+  static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+  // Android ndk does not support __thread keyword so we use a custom thread
+  // local storage class we implemented.
+  // iOS also does not support the __thread keyword.
+  static ThreadCache& thread_cache();
+#elif defined(PROTOBUF_USE_DLLS)
+  // Thread local variables cannot be exposed through DLL interface but we can
+  // wrap them in static functions.
+  static ThreadCache& thread_cache();
+#else
+  static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
+  static ThreadCache& thread_cache() { return thread_cache_; }
+#endif
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena);
   // All protos have pointers back to the arena hence Arena must have
   // pointer stability.
-  ArenaImpl(ArenaImpl&&) = delete;
-  ArenaImpl& operator=(ArenaImpl&&) = delete;
+  ThreadSafeArena(ThreadSafeArena&&) = delete;
+  ThreadSafeArena& operator=(ThreadSafeArena&&) = delete;
 
  public:
   // kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
   // to protect the invariant that pos is always at a multiple of 8.
-  static const size_t kBlockHeaderSize =
-      (sizeof(Block) + 7) & static_cast<size_t>(-8);
-  static const size_t kSerialArenaSize =
+  static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize;
+  static constexpr size_t kSerialArenaSize =
       (sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
   static_assert(kBlockHeaderSize % 8 == 0,
                 "kBlockHeaderSize must be a multiple of 8.");
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
index 84df349..33f5cf4 100644
--- a/src/google/protobuf/arena_test_util.h
+++ b/src/google/protobuf/arena_test_util.h
@@ -84,7 +84,7 @@
  private:
   class NewDeleteCapture {
    public:
-    // TOOD(xiaofeng): Implement this for opensource protobuf.
+    // TODO(xiaofeng): Implement this for opensource protobuf.
     void Hook() {}
     void Unhook() {}
     int alloc_count() { return 0; }
@@ -92,6 +92,33 @@
   } capture_alloc;
 };
 
+// Owns the internal T only if it's not owned by an arena.
+// T needs to be arena constructible and destructor skippable.
+template <typename T>
+class ArenaHolder {
+ public:
+  explicit ArenaHolder(Arena* arena)
+      : field_(Arena::CreateMessage<T>(arena)),
+        owned_by_arena_(arena != nullptr) {
+    GOOGLE_DCHECK(google::protobuf::Arena::is_arena_constructable<T>::value);
+    GOOGLE_DCHECK(google::protobuf::Arena::is_destructor_skippable<T>::value);
+  }
+
+  ~ArenaHolder() {
+    if (!owned_by_arena_) {
+      delete field_;
+    }
+  }
+
+  T* get() { return field_; }
+  T* operator->() { return field_; }
+  T& operator*() { return *field_; }
+
+ private:
+  T* field_;
+  bool owned_by_arena_;
+};
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 7e5b115..03c3d8d 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -31,6 +31,7 @@
 #include <google/protobuf/arena.h>
 
 #include <algorithm>
+#include <cstddef>
 #include <cstring>
 #include <memory>
 #include <string>
@@ -44,7 +45,6 @@
 #include <google/protobuf/test_util.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_arena.pb.h>
-#include <google/protobuf/unittest_no_arena.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/descriptor.h>
@@ -58,12 +58,14 @@
 #include <google/protobuf/stubs/strutil.h>
 
 
+// Must be included last
+#include <google/protobuf/port_def.inc>
+
 using proto2_arena_unittest::ArenaMessage;
 using protobuf_unittest::TestAllExtensions;
 using protobuf_unittest::TestAllTypes;
 using protobuf_unittest::TestEmptyMessage;
 using protobuf_unittest::TestOneof2;
-using protobuf_unittest_no_arena::TestNoArenaMessage;
 
 namespace google {
 namespace protobuf {
@@ -156,14 +158,12 @@
 TEST(ArenaTest, ArenaConstructable) {
   EXPECT_TRUE(Arena::is_arena_constructable<TestAllTypes>::type::value);
   EXPECT_TRUE(Arena::is_arena_constructable<const TestAllTypes>::type::value);
-  EXPECT_FALSE(Arena::is_arena_constructable<TestNoArenaMessage>::type::value);
   EXPECT_FALSE(Arena::is_arena_constructable<Arena>::type::value);
 }
 
 TEST(ArenaTest, DestructorSkippable) {
   EXPECT_TRUE(Arena::is_destructor_skippable<TestAllTypes>::type::value);
   EXPECT_TRUE(Arena::is_destructor_skippable<const TestAllTypes>::type::value);
-  EXPECT_FALSE(Arena::is_destructor_skippable<TestNoArenaMessage>::type::value);
   EXPECT_FALSE(Arena::is_destructor_skippable<Arena>::type::value);
 }
 
@@ -273,28 +273,36 @@
 }
 
 TEST(ArenaTest, InitialBlockTooSmall) {
-  // Construct a small (64 byte) initial block of memory to be used by the
-  // arena allocator; then, allocate an object which will not fit in the
-  // initial block.
-  std::vector<char> arena_block(96);
-  ArenaOptions options;
-  options.initial_block = &arena_block[0];
-  options.initial_block_size = arena_block.size();
-  Arena arena(options);
+  // Construct a small blocks of memory to be used by the arena allocator; then,
+  // allocate an object which will not fit in the initial block.
+  for (int size = 0; size <= Arena::kBlockOverhead + 32; size++) {
+    std::vector<char> arena_block(size);
+    ArenaOptions options;
+    options.initial_block = arena_block.data();
+    options.initial_block_size = arena_block.size();
 
-  char* p = Arena::CreateArray<char>(&arena, 96);
-  uintptr_t allocation = reinterpret_cast<uintptr_t>(p);
+    // Try sometimes with non-default block sizes so that we exercise paths
+    // with and without ArenaImpl::Options.
+    if ((size % 2) != 0) {
+      options.start_block_size += 8;
+    }
 
-  // Ensure that the arena allocator did not return memory pointing into the
-  // initial block of memory.
-  uintptr_t arena_start = reinterpret_cast<uintptr_t>(&arena_block[0]);
-  uintptr_t arena_end = arena_start + arena_block.size();
-  EXPECT_FALSE(allocation >= arena_start && allocation < arena_end);
+    Arena arena(options);
 
-  // Write to the memory we allocated; this should (but is not guaranteed to)
-  // trigger a check for heap corruption if the object was allocated from the
-  // initially-provided block.
-  memset(p, '\0', 96);
+    char* p = Arena::CreateArray<char>(&arena, 96);
+    uintptr_t allocation = reinterpret_cast<uintptr_t>(p);
+
+    // Ensure that the arena allocator did not return memory pointing into the
+    // initial block of memory.
+    uintptr_t arena_start = reinterpret_cast<uintptr_t>(arena_block.data());
+    uintptr_t arena_end = arena_start + arena_block.size();
+    EXPECT_FALSE(allocation >= arena_start && allocation < arena_end);
+
+    // Write to the memory we allocated; this should (but is not guaranteed to)
+    // trigger a check for heap corruption if the object was allocated from the
+    // initially-provided block.
+    memset(p, '\0', 96);
+  }
 }
 
 TEST(ArenaTest, Parsing) {
@@ -462,13 +470,6 @@
   nested->set_bb(118);
   arena_message->set_allocated_optional_nested_message(nested);
   EXPECT_EQ(118, arena_message->optional_nested_message().bb());
-
-  TestNoArenaMessage no_arena_message;
-  EXPECT_FALSE(no_arena_message.has_arena_message());
-  no_arena_message.set_allocated_arena_message(NULL);
-  EXPECT_FALSE(no_arena_message.has_arena_message());
-  no_arena_message.set_allocated_arena_message(new ArenaMessage);
-  EXPECT_TRUE(no_arena_message.has_arena_message());
 }
 
 TEST(ArenaTest, ReleaseMessage) {
@@ -621,7 +622,11 @@
     TestAllTypes::NestedMessage* arena2_submessage =
         Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
     arena2_submessage->set_bb(42);
-    arena1_message->set_allocated_optional_nested_message(arena2_submessage);
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+    EXPECT_DEBUG_DEATH(arena1_message->set_allocated_optional_nested_message(
+                           arena2_submessage),
+                       "submessage_arena");
+#endif
     EXPECT_NE(arena2_submessage,
               arena1_message->mutable_optional_nested_message());
   }
@@ -630,11 +635,43 @@
       Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
   arena1_submessage->set_bb(42);
   TestAllTypes* heap_message = new TestAllTypes;
-  heap_message->set_allocated_optional_nested_message(arena1_submessage);
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  EXPECT_DEBUG_DEATH(
+      heap_message->set_allocated_optional_nested_message(arena1_submessage),
+      "submessage_arena");
+#endif
   EXPECT_NE(arena1_submessage, heap_message->mutable_optional_nested_message());
   delete heap_message;
 }
 
+TEST(ArenaTest, UnsafeArenaSetAllocatedAcrossArenas) {
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    arena1_message->unsafe_arena_set_allocated_optional_nested_message(
+        arena2_submessage);
+    EXPECT_EQ(arena2_submessage,
+              arena1_message->mutable_optional_nested_message());
+    EXPECT_EQ(arena2_submessage,
+              arena1_message->unsafe_arena_release_optional_nested_message());
+  }
+
+  TestAllTypes::NestedMessage* arena1_submessage =
+      Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
+  arena1_submessage->set_bb(42);
+  TestAllTypes* heap_message = new TestAllTypes;
+  heap_message->unsafe_arena_set_allocated_optional_nested_message(
+      arena1_submessage);
+  EXPECT_EQ(arena1_submessage, heap_message->mutable_optional_nested_message());
+  EXPECT_EQ(arena1_submessage,
+            heap_message->unsafe_arena_release_optional_nested_message());
+  delete heap_message;
+}
+
 TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) {
   // Same as above, with reflection.
   Arena arena1;
@@ -654,7 +691,11 @@
     TestAllTypes::NestedMessage* arena2_submessage =
         Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
     arena2_submessage->set_bb(42);
-    r->SetAllocatedMessage(arena1_message, arena2_submessage, msg_field);
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+    EXPECT_DEBUG_DEATH(
+        r->SetAllocatedMessage(arena1_message, arena2_submessage, msg_field),
+        "GetOwningArena");
+#endif
     EXPECT_NE(arena2_submessage,
               arena1_message->mutable_optional_nested_message());
   }
@@ -663,25 +704,54 @@
       Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
   arena1_submessage->set_bb(42);
   TestAllTypes* heap_message = new TestAllTypes;
-  r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field);
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  EXPECT_DEBUG_DEATH(
+      r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field),
+      "GetOwningArena");
+#endif
   EXPECT_NE(arena1_submessage, heap_message->mutable_optional_nested_message());
   delete heap_message;
 }
 
+TEST(ArenaTest, UnsafeArenaSetAllocatedAcrossArenasWithReflection) {
+  // Same as above, with reflection.
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  const Reflection* r = arena1_message->GetReflection();
+  const Descriptor* d = arena1_message->GetDescriptor();
+  const FieldDescriptor* msg_field =
+      d->FindFieldByName("optional_nested_message");
+  {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    r->UnsafeArenaSetAllocatedMessage(arena1_message, arena2_submessage,
+                                      msg_field);
+    EXPECT_EQ(arena2_submessage,
+              arena1_message->mutable_optional_nested_message());
+    EXPECT_EQ(arena2_submessage,
+              arena1_message->unsafe_arena_release_optional_nested_message());
+  }
+
+  TestAllTypes::NestedMessage* arena1_submessage =
+      Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
+  arena1_submessage->set_bb(42);
+  TestAllTypes* heap_message = new TestAllTypes;
+  r->UnsafeArenaSetAllocatedMessage(heap_message, arena1_submessage, msg_field);
+  EXPECT_EQ(arena1_submessage, heap_message->mutable_optional_nested_message());
+  EXPECT_EQ(arena1_submessage,
+            heap_message->unsafe_arena_release_optional_nested_message());
+  delete heap_message;
+}
+
 TEST(ArenaTest, AddAllocatedWithReflection) {
   Arena arena1;
   ArenaMessage* arena1_message = Arena::CreateMessage<ArenaMessage>(&arena1);
   const Reflection* r = arena1_message->GetReflection();
   const Descriptor* d = arena1_message->GetDescriptor();
-  const FieldDescriptor* fd =
-      d->FindFieldByName("repeated_import_no_arena_message");
-  // Message with cc_enable_arenas = false;
-  r->AddMessage(arena1_message, fd);
-  r->AddMessage(arena1_message, fd);
-  r->AddMessage(arena1_message, fd);
-  EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
   // Message with cc_enable_arenas = true;
-  fd = d->FindFieldByName("repeated_nested_message");
+  const FieldDescriptor* fd = d->FindFieldByName("repeated_nested_message");
   r->AddMessage(arena1_message, fd);
   r->AddMessage(arena1_message, fd);
   r->AddMessage(arena1_message, fd);
@@ -733,29 +803,35 @@
     TestAllTypes::NestedMessage* arena2_submessage =
         Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
     arena2_submessage->set_bb(42);
-    arena1_message->mutable_repeated_nested_message()->AddAllocated(
-        arena2_submessage);
-    // Should copy object.
-    EXPECT_NE(arena2_submessage, &arena1_message->repeated_nested_message(i));
-    EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+    EXPECT_DEBUG_DEATH(
+        arena1_message->mutable_repeated_nested_message()->AddAllocated(
+            arena2_submessage),
+        "value_arena");
+#endif
+    // Should not receive object.
+    EXPECT_TRUE(arena1_message->repeated_nested_message().empty());
   }
 
   // Arena->heap case.
-  TestAllTypes* heap_message = new TestAllTypes();
+  TestAllTypes* heap_message = new TestAllTypes;
   for (int i = 0; i < 10; i++) {
     Arena arena2;
     TestAllTypes::NestedMessage* arena2_submessage =
         Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
     arena2_submessage->set_bb(42);
-    heap_message->mutable_repeated_nested_message()->AddAllocated(
-        arena2_submessage);
-    // Should copy object.
-    EXPECT_NE(arena2_submessage, &heap_message->repeated_nested_message(i));
-    EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+    EXPECT_DEBUG_DEATH(
+        heap_message->mutable_repeated_nested_message()->AddAllocated(
+            arena2_submessage),
+        "value_arena");
+#endif
+    // Should not receive object.
+    EXPECT_TRUE(heap_message->repeated_nested_message().empty());
   }
   delete heap_message;
 
-  // Heap-arena case for strings (which are not arena-allocated).
+  // Heap->arena case for strings (which are not arena-allocated).
   arena1_message->Clear();
   for (int i = 0; i < 10; i++) {
     std::string* s = new std::string("Test");
@@ -766,6 +842,65 @@
   }
 }
 
+TEST(ArenaTest, UnsafeArenaAddAllocatedToRepeatedField) {
+  // Heap->arena case.
+  Arena arena1;
+  TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+  {
+    auto* heap_submessage = new TestAllTypes::NestedMessage;
+    arena1_message->mutable_repeated_nested_message()->UnsafeArenaAddAllocated(
+        heap_submessage);
+    // Should not copy object.
+    EXPECT_EQ(heap_submessage, &arena1_message->repeated_nested_message(0));
+    EXPECT_EQ(heap_submessage, arena1_message->mutable_repeated_nested_message()
+                                   ->UnsafeArenaReleaseLast());
+    delete heap_submessage;
+  }
+
+  // Arena1->Arena2 case.
+  arena1_message->Clear();
+  {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    arena1_message->mutable_repeated_nested_message()->UnsafeArenaAddAllocated(
+        arena2_submessage);
+    // Should own object.
+    EXPECT_EQ(arena2_submessage, &arena1_message->repeated_nested_message(0));
+    EXPECT_EQ(arena2_submessage,
+              arena1_message->mutable_repeated_nested_message()
+                  ->UnsafeArenaReleaseLast());
+  }
+
+  // Arena->heap case.
+  TestAllTypes* heap_message = new TestAllTypes;
+  {
+    Arena arena2;
+    TestAllTypes::NestedMessage* arena2_submessage =
+        Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+    arena2_submessage->set_bb(42);
+    heap_message->mutable_repeated_nested_message()->UnsafeArenaAddAllocated(
+        arena2_submessage);
+    // Should own object.
+    EXPECT_EQ(arena2_submessage, &heap_message->repeated_nested_message(0));
+    EXPECT_EQ(arena2_submessage, heap_message->mutable_repeated_nested_message()
+                                     ->UnsafeArenaReleaseLast());
+  }
+  delete heap_message;
+
+  // Heap->arena case for strings (which are not arena-allocated).
+  arena1_message->Clear();
+  {
+    std::string* s = new std::string("Test");
+    arena1_message->mutable_repeated_string()->UnsafeArenaAddAllocated(s);
+    // Should not copy.
+    EXPECT_EQ(s, &arena1_message->repeated_string(0));
+    EXPECT_EQ("Test", arena1_message->repeated_string(0));
+    delete arena1_message->mutable_repeated_string()->UnsafeArenaReleaseLast();
+  }
+}
+
 TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) {
   // Heap->arena case.
   Arena arena1;
@@ -790,10 +925,13 @@
     TestAllTypes::NestedMessage* arena2_submessage =
         Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
     arena2_submessage->set_bb(42);
-    r->AddAllocatedMessage(arena1_message, fd, arena2_submessage);
-    // Should copy object.
-    EXPECT_NE(arena2_submessage, &arena1_message->repeated_nested_message(i));
-    EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+    EXPECT_DEBUG_DEATH(
+        r->AddAllocatedMessage(arena1_message, fd, arena2_submessage),
+        "value_arena");
+#endif
+    // Should not receive object.
+    EXPECT_TRUE(arena1_message->repeated_nested_message().empty());
   }
 
   // Arena->heap case.
@@ -803,10 +941,13 @@
     TestAllTypes::NestedMessage* arena2_submessage =
         Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
     arena2_submessage->set_bb(42);
-    r->AddAllocatedMessage(heap_message, fd, arena2_submessage);
-    // Should copy object.
-    EXPECT_NE(arena2_submessage, &heap_message->repeated_nested_message(i));
-    EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+    EXPECT_DEBUG_DEATH(
+        r->AddAllocatedMessage(heap_message, fd, arena2_submessage),
+        "value_arena");
+#endif
+    // Should not receive object.
+    EXPECT_TRUE(heap_message->repeated_nested_message().empty());
   }
   delete heap_message;
 }
@@ -873,23 +1014,6 @@
   }
 }
 
-TEST(ArenaTest, UnsafeArenaReleaseAdd) {
-  // Use unsafe_arena_release() and unsafe_arena_set_allocated() to transfer an
-  // arena-allocated string from one message to another.
-  const char kContent[] = "Test content";
-
-  Arena arena;
-  TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&arena);
-  TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&arena);
-  std::string* arena_string = Arena::Create<std::string>(&arena);
-  *arena_string = kContent;
-
-  message1->unsafe_arena_set_allocated_optional_string(arena_string);
-  message2->unsafe_arena_set_allocated_optional_string(
-      message1->unsafe_arena_release_optional_string());
-  EXPECT_EQ(kContent, message2->optional_string());
-}
-
 TEST(ArenaTest, UnsafeArenaAddAllocated) {
   Arena arena;
   TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -900,43 +1024,20 @@
   }
 }
 
-TEST(ArenaTest, UnsafeArenaRelease) {
-  Arena arena;
-  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
-
-  std::string* s = new std::string("test string");
-  message->unsafe_arena_set_allocated_optional_string(s);
-  EXPECT_TRUE(message->has_optional_string());
-  EXPECT_EQ("test string", message->optional_string());
-  s = message->unsafe_arena_release_optional_string();
-  EXPECT_FALSE(message->has_optional_string());
-  delete s;
-
-  s = new std::string("test string");
-  message->unsafe_arena_set_allocated_oneof_string(s);
-  EXPECT_TRUE(message->has_oneof_string());
-  EXPECT_EQ("test string", message->oneof_string());
-  s = message->unsafe_arena_release_oneof_string();
-  EXPECT_FALSE(message->has_oneof_string());
-  delete s;
-}
-
 TEST(ArenaTest, OneofMerge) {
   Arena arena;
   TestAllTypes* message0 = Arena::CreateMessage<TestAllTypes>(&arena);
   TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&arena);
 
-  message0->unsafe_arena_set_allocated_oneof_string(new std::string("x"));
+  message0->set_oneof_string("x");
   ASSERT_TRUE(message0->has_oneof_string());
-  message1->unsafe_arena_set_allocated_oneof_string(new std::string("y"));
+  message1->set_oneof_string("y");
   ASSERT_TRUE(message1->has_oneof_string());
   EXPECT_EQ("x", message0->oneof_string());
   EXPECT_EQ("y", message1->oneof_string());
   message0->MergeFrom(*message1);
   EXPECT_EQ("y", message0->oneof_string());
   EXPECT_EQ("y", message1->oneof_string());
-  delete message0->unsafe_arena_release_oneof_string();
-  delete message1->unsafe_arena_release_oneof_string();
 }
 
 TEST(ArenaTest, ArenaOneofReflection) {
@@ -1043,10 +1144,7 @@
 TEST(ArenaTest, RepeatedFieldOnArena) {
   // Preallocate an initial arena block to avoid mallocs during hooked region.
   std::vector<char> arena_block(1024 * 1024);
-  ArenaOptions options;
-  options.initial_block = &arena_block[0];
-  options.initial_block_size = arena_block.size();
-  Arena arena(options);
+  Arena arena(arena_block.data(), arena_block.size());
 
   {
     internal::NoHeapChecker no_heap;
@@ -1221,7 +1319,6 @@
 }
 #endif  // PROTOBUF_RTTI
 
-
 // RepeatedField should support non-POD types, and invoke constructors and
 // destructors appropriately, because it's used this way by lots of other code
 // (even if this was not its original intent).
@@ -1245,10 +1342,7 @@
 uint64 Align8(uint64 n) { return (n + 7) & -8; }
 
 TEST(ArenaTest, SpaceAllocated_and_Used) {
-  ArenaOptions options;
-  options.start_block_size = 256;
-  options.max_block_size = 8192;
-  Arena arena_1(options);
+  Arena arena_1;
   EXPECT_EQ(0, arena_1.SpaceAllocated());
   EXPECT_EQ(0, arena_1.SpaceUsed());
   EXPECT_EQ(0, arena_1.Reset());
@@ -1260,6 +1354,9 @@
 
   // Test with initial block.
   std::vector<char> arena_block(1024);
+  ArenaOptions options;
+  options.start_block_size = 256;
+  options.max_block_size = 8192;
   options.initial_block = &arena_block[0];
   options.initial_block_size = arena_block.size();
   Arena arena_2(options);
@@ -1270,19 +1367,25 @@
   EXPECT_EQ(1024, arena_2.SpaceAllocated());
   EXPECT_EQ(Align8(55), arena_2.SpaceUsed());
   EXPECT_EQ(1024, arena_2.Reset());
+}
 
-  // Reset options to test doubling policy explicitly.
-  options.initial_block = NULL;
-  options.initial_block_size = 0;
-  Arena arena_3(options);
-  EXPECT_EQ(0, arena_3.SpaceUsed());
-  Arena::CreateArray<char>(&arena_3, 160);
-  EXPECT_EQ(256, arena_3.SpaceAllocated());
-  EXPECT_EQ(Align8(160), arena_3.SpaceUsed());
-  Arena::CreateArray<char>(&arena_3, 70);
-  EXPECT_EQ(256 + 512, arena_3.SpaceAllocated());
-  EXPECT_EQ(Align8(160) + Align8(70), arena_3.SpaceUsed());
-  EXPECT_EQ(256 + 512, arena_3.Reset());
+TEST(ArenaTest, BlockSizeDoubling) {
+  Arena arena;
+  EXPECT_EQ(0, arena.SpaceUsed());
+  EXPECT_EQ(0, arena.SpaceAllocated());
+
+  // Allocate something to get initial block size.
+  Arena::CreateArray<char>(&arena, 1);
+  auto first_block_size = arena.SpaceAllocated();
+
+  // Keep allocating until space used increases.
+  while (arena.SpaceAllocated() == first_block_size) {
+    Arena::CreateArray<char>(&arena, 1);
+  }
+  ASSERT_GT(arena.SpaceAllocated(), first_block_size);
+  auto second_block_size = (arena.SpaceAllocated() - first_block_size);
+
+  EXPECT_EQ(second_block_size, 2*first_block_size);
 }
 
 TEST(ArenaTest, Alignment) {
@@ -1331,11 +1434,6 @@
 }
 
 TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaCompatibleTypes) {
-  TestNoArenaMessage message;
-  const TestNoArenaMessage* const_pointer_to_message = &message;
-  EXPECT_EQ(nullptr, Arena::GetArena(&message));
-  EXPECT_EQ(nullptr, Arena::GetArena(const_pointer_to_message));
-
   // Test that GetArena returns nullptr for types that have a GetArena method
   // that doesn't return Arena*.
   struct {
@@ -1365,96 +1463,93 @@
   }
 }
 
-TEST(ArenaTest, UnsafeSetAllocatedOnArena) {
-  Arena arena;
-  TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
-  EXPECT_FALSE(message->has_optional_string());
+namespace {
+uint32 hooks_num_init = 0;
+uint32 hooks_num_allocations = 0;
+uint32 hooks_num_reset = 0;
+uint32 hooks_num_destruct = 0;
 
-  std::string owned_string = "test with long enough content to heap-allocate";
-  message->unsafe_arena_set_allocated_optional_string(&owned_string);
-  EXPECT_TRUE(message->has_optional_string());
-
-  message->unsafe_arena_set_allocated_optional_string(NULL);
-  EXPECT_FALSE(message->has_optional_string());
+void ClearHookCounts() {
+  hooks_num_init = 0;
+  hooks_num_allocations = 0;
+  hooks_num_reset = 0;
+  hooks_num_destruct = 0;
 }
+}  // namespace
 
-// A helper utility class to only contain static hook functions, some
-// counters to be used to verify the counters have been called and a cookie
-// value to be verified.
-class ArenaHooksTestUtil {
+// A helper utility class that handles arena callbacks.
+class ArenaOptionsTestFriend final : public internal::ArenaMetricsCollector {
  public:
-  static void* on_init(Arena* arena) {
-    ++num_init;
-    int* cookie = new int(kCookieValue);
-    return static_cast<void*>(cookie);
+  static internal::ArenaMetricsCollector* NewWithAllocs() {
+    return new ArenaOptionsTestFriend(true);
   }
 
-  static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size,
-                            void* cookie) {
-    ++num_allocations;
-    int cookie_value = *static_cast<int*>(cookie);
-    EXPECT_EQ(kCookieValue, cookie_value);
+  static internal::ArenaMetricsCollector* NewWithoutAllocs() {
+    return new ArenaOptionsTestFriend(false);
   }
 
-  static void on_reset(Arena* arena, void* cookie, uint64 space_used) {
-    ++num_reset;
-    int cookie_value = *static_cast<int*>(cookie);
-    EXPECT_EQ(kCookieValue, cookie_value);
+  static void Enable(ArenaOptions* options) {
+    ClearHookCounts();
+    options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithAllocs;
   }
 
-  static void on_destruction(Arena* arena, void* cookie, uint64 space_used) {
-    ++num_destruct;
-    int cookie_value = *static_cast<int*>(cookie);
-    EXPECT_EQ(kCookieValue, cookie_value);
-    delete static_cast<int*>(cookie);
+  static void EnableWithoutAllocs(ArenaOptions* options) {
+    ClearHookCounts();
+    options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithoutAllocs;
   }
 
-  static const int kCookieValue = 999;
-  static uint32 num_init;
-  static uint32 num_allocations;
-  static uint32 num_reset;
-  static uint32 num_destruct;
-};
-uint32 ArenaHooksTestUtil::num_init = 0;
-uint32 ArenaHooksTestUtil::num_allocations = 0;
-uint32 ArenaHooksTestUtil::num_reset = 0;
-uint32 ArenaHooksTestUtil::num_destruct = 0;
-const int ArenaHooksTestUtil::kCookieValue;
-
-class ArenaOptionsTestFriend {
- public:
-  static void Set(ArenaOptions* options) {
-    options->on_arena_init = ArenaHooksTestUtil::on_init;
-    options->on_arena_allocation = ArenaHooksTestUtil::on_allocation;
-    options->on_arena_reset = ArenaHooksTestUtil::on_reset;
-    options->on_arena_destruction = ArenaHooksTestUtil::on_destruction;
+  explicit ArenaOptionsTestFriend(bool record_allocs)
+      : ArenaMetricsCollector(record_allocs) {
+    ++hooks_num_init;
+  }
+  void OnDestroy(uint64 space_allocated) override {
+    ++hooks_num_destruct;
+    delete this;
+  }
+  void OnReset(uint64 space_allocated) override { ++hooks_num_reset; }
+  void OnAlloc(const std::type_info* allocated_type,
+               uint64 alloc_size) override {
+    ++hooks_num_allocations;
   }
 };
 
-// Test the hooks are correctly called and that the cookie is passed.
+// Test the hooks are correctly called.
 TEST(ArenaTest, ArenaHooksSanity) {
   ArenaOptions options;
-  ArenaOptionsTestFriend::Set(&options);
+  ArenaOptionsTestFriend::Enable(&options);
 
   // Scope for defining the arena
   {
     Arena arena(options);
-    EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
-    EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
+    EXPECT_EQ(1, hooks_num_init);
+    EXPECT_EQ(0, hooks_num_allocations);
     Arena::Create<uint64>(&arena);
     if (std::is_trivially_destructible<uint64>::value) {
-      EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
+      EXPECT_EQ(1, hooks_num_allocations);
     } else {
-      EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations);
+      EXPECT_EQ(2, hooks_num_allocations);
     }
     arena.Reset();
     arena.Reset();
-    EXPECT_EQ(2, ArenaHooksTestUtil::num_reset);
+    EXPECT_EQ(2, hooks_num_reset);
   }
-  EXPECT_EQ(3, ArenaHooksTestUtil::num_reset);
-  EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct);
+  EXPECT_EQ(2, hooks_num_reset);
+  EXPECT_EQ(1, hooks_num_destruct);
+}
+
+// Test that allocation hooks are not called when we don't need them.
+TEST(ArenaTest, ArenaHooksWhenAllocationsNotNeeded) {
+  ArenaOptions options;
+  ArenaOptionsTestFriend::EnableWithoutAllocs(&options);
+
+  Arena arena(options);
+  EXPECT_EQ(0, hooks_num_allocations);
+  Arena::Create<uint64>(&arena);
+  EXPECT_EQ(0, hooks_num_allocations);
 }
 
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc
new file mode 100644
index 0000000..7608b13
--- /dev/null
+++ b/src/google/protobuf/arenastring.cc
@@ -0,0 +1,282 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/arenastring.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/parse_context.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+// clang-format off
+#include <google/protobuf/port_def.inc>
+// clang-format on
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+const std::string& LazyString::Init() const {
+  static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
+  mu.Lock();
+  const std::string* res = inited_.load(std::memory_order_acquire);
+  if (res == nullptr) {
+    auto init_value = init_value_;
+    res = ::new (static_cast<void*>(string_buf_))
+        std::string(init_value.ptr, init_value.size);
+    inited_.store(res, std::memory_order_release);
+  }
+  mu.Unlock();
+  return *res;
+}
+
+
+std::string* ArenaStringPtr::SetAndReturnNewString() {
+  std::string* new_string = new std::string();
+  tagged_ptr_.Set(new_string);
+  return new_string;
+}
+
+void ArenaStringPtr::DestroyNoArenaSlowPath() { delete UnsafeMutablePointer(); }
+
+void ArenaStringPtr::Set(const std::string* default_value,
+                         ConstStringParam value, ::google::protobuf::Arena* arena) {
+  if (IsDefault(default_value)) {
+    tagged_ptr_.Set(Arena::Create<std::string>(arena, value));
+  } else {
+    UnsafeMutablePointer()->assign(value.data(), value.length());
+  }
+}
+
+void ArenaStringPtr::Set(const std::string* default_value, std::string&& value,
+                         ::google::protobuf::Arena* arena) {
+  if (IsDefault(default_value)) {
+    if (arena == nullptr) {
+      tagged_ptr_.Set(new std::string(std::move(value)));
+    } else {
+      tagged_ptr_.Set(Arena::Create<std::string>(arena, std::move(value)));
+    }
+  } else if (IsDonatedString()) {
+    std::string* current = tagged_ptr_.Get();
+    auto* s = new (current) std::string(std::move(value));
+    arena->OwnDestructor(s);
+    tagged_ptr_.Set(s);
+  } else /* !IsDonatedString() */ {
+    *UnsafeMutablePointer() = std::move(value);
+  }
+}
+
+void ArenaStringPtr::Set(EmptyDefault, ConstStringParam value,
+                         ::google::protobuf::Arena* arena) {
+  Set(&GetEmptyStringAlreadyInited(), value, arena);
+}
+
+void ArenaStringPtr::Set(EmptyDefault, std::string&& value,
+                         ::google::protobuf::Arena* arena) {
+  Set(&GetEmptyStringAlreadyInited(), std::move(value), arena);
+}
+
+void ArenaStringPtr::Set(NonEmptyDefault, ConstStringParam value,
+                         ::google::protobuf::Arena* arena) {
+  Set(nullptr, value, arena);
+}
+
+void ArenaStringPtr::Set(NonEmptyDefault, std::string&& value,
+                         ::google::protobuf::Arena* arena) {
+  Set(nullptr, std::move(value), arena);
+}
+
+std::string* ArenaStringPtr::Mutable(EmptyDefault, ::google::protobuf::Arena* arena) {
+  if (!IsDonatedString() && !IsDefault(&GetEmptyStringAlreadyInited())) {
+    return UnsafeMutablePointer();
+  } else {
+    return MutableSlow(arena);
+  }
+}
+
+std::string* ArenaStringPtr::Mutable(const LazyString& default_value,
+                                     ::google::protobuf::Arena* arena) {
+  if (!IsDonatedString() && !IsDefault(nullptr)) {
+    return UnsafeMutablePointer();
+  } else {
+    return MutableSlow(arena, default_value);
+  }
+}
+
+std::string* ArenaStringPtr::MutableNoCopy(const std::string* default_value,
+                                           ::google::protobuf::Arena* arena) {
+  if (!IsDonatedString() && !IsDefault(default_value)) {
+    return UnsafeMutablePointer();
+  } else {
+    GOOGLE_DCHECK(IsDefault(default_value));
+    // Allocate empty. The contents are not relevant.
+    std::string* new_string = Arena::Create<std::string>(arena);
+    tagged_ptr_.Set(new_string);
+    return new_string;
+  }
+}
+
+template <typename... Lazy>
+std::string* ArenaStringPtr::MutableSlow(::google::protobuf::Arena* arena,
+                                         const Lazy&... lazy_default) {
+  const std::string* const default_value =
+      sizeof...(Lazy) == 0 ? &GetEmptyStringAlreadyInited() : nullptr;
+  GOOGLE_DCHECK(IsDefault(default_value));
+  std::string* new_string =
+      Arena::Create<std::string>(arena, lazy_default.get()...);
+  tagged_ptr_.Set(new_string);
+  return new_string;
+}
+
+std::string* ArenaStringPtr::Release(const std::string* default_value,
+                                     ::google::protobuf::Arena* arena) {
+  if (IsDefault(default_value)) {
+    return nullptr;
+  } else {
+    return ReleaseNonDefault(default_value, arena);
+  }
+}
+
+std::string* ArenaStringPtr::ReleaseNonDefault(const std::string* default_value,
+                                               ::google::protobuf::Arena* arena) {
+  GOOGLE_DCHECK(!IsDefault(default_value));
+
+  if (!IsDonatedString()) {
+    std::string* released;
+    if (arena != nullptr) {
+      released = new std::string;
+      released->swap(*UnsafeMutablePointer());
+    } else {
+      released = UnsafeMutablePointer();
+    }
+    tagged_ptr_.Set(const_cast<std::string*>(default_value));
+    return released;
+  } else /* IsDonatedString() */ {
+    GOOGLE_DCHECK(arena != nullptr);
+    std::string* released = new std::string(Get());
+    tagged_ptr_.Set(const_cast<std::string*>(default_value));
+    return released;
+  }
+}
+
+void ArenaStringPtr::SetAllocated(const std::string* default_value,
+                                  std::string* value, ::google::protobuf::Arena* arena) {
+  // Release what we have first.
+  if (arena == nullptr && !IsDefault(default_value)) {
+    delete UnsafeMutablePointer();
+  }
+  if (value == nullptr) {
+    tagged_ptr_.Set(const_cast<std::string*>(default_value));
+  } else {
+#ifdef NDEBUG
+    tagged_ptr_.Set(value);
+    if (arena != nullptr) {
+      arena->Own(value);
+    }
+#else
+    // On debug builds, copy the string so the address differs.  delete will
+    // fail if value was a stack-allocated temporary/etc., which would have
+    // failed when arena ran its cleanup list.
+    std::string* new_value = Arena::Create<std::string>(arena, *value);
+    delete value;
+    tagged_ptr_.Set(new_value);
+#endif
+  }
+}
+
+void ArenaStringPtr::Destroy(const std::string* default_value,
+                             ::google::protobuf::Arena* arena) {
+  if (arena == nullptr) {
+    GOOGLE_DCHECK(!IsDonatedString());
+    if (!IsDefault(default_value)) {
+      delete UnsafeMutablePointer();
+    }
+  }
+}
+
+void ArenaStringPtr::Destroy(EmptyDefault, ::google::protobuf::Arena* arena) {
+  Destroy(&GetEmptyStringAlreadyInited(), arena);
+}
+
+void ArenaStringPtr::Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena) {
+  Destroy(nullptr, arena);
+}
+
+void ArenaStringPtr::ClearToEmpty() {
+  if (IsDefault(&GetEmptyStringAlreadyInited())) {
+    // Already set to default -- do nothing.
+  } else {
+    // Unconditionally mask away the tag.
+    //
+    // UpdateDonatedString uses assign when capacity is larger than the new
+    // value, which is trivially true in the donated string case.
+    // const_cast<std::string*>(PtrValue<std::string>())->clear();
+    tagged_ptr_.Get()->clear();
+  }
+}
+
+void ArenaStringPtr::ClearToDefault(const LazyString& default_value,
+                                    ::google::protobuf::Arena* arena) {
+  (void)arena;
+  if (IsDefault(nullptr)) {
+    // Already set to default -- do nothing.
+  } else if (!IsDonatedString()) {
+    UnsafeMutablePointer()->assign(default_value.get());
+  }
+}
+
+const char* EpsCopyInputStream::ReadArenaString(const char* ptr,
+                                                ArenaStringPtr* s,
+                                                Arena* arena) {
+  GOOGLE_DCHECK(arena != nullptr);
+
+  int size = ReadSize(&ptr);
+  if (!ptr) return nullptr;
+
+  auto str = Arena::Create<std::string>(arena);
+  ptr = ReadString(ptr, size, str);
+  GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+
+  TaggedPtr<std::string> res;
+  res.Set(str);
+  s->UnsafeSetTaggedPointer(res);
+
+  return ptr;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index 122f391..1fafa69 100644
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -37,7 +37,6 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/fastmem.h>
 #include <google/protobuf/arena.h>
 #include <google/protobuf/port.h>
 
@@ -48,358 +47,369 @@
 #endif
 
 
-// This is the implementation of arena string fields written for the open-source
-// release. The ArenaStringPtr struct below is an internal implementation class
-// and *should not be used* by user code. It is used to collect string
-// operations together into one place and abstract away the underlying
-// string-field pointer representation, so that (for example) an alternate
-// implementation that knew more about ::std::string's internals could integrate
-// more closely with the arena allocator.
-
 namespace google {
 namespace protobuf {
 namespace internal {
 
 template <typename T>
-class TaggedPtr {
+class ExplicitlyConstructed;
+
+class SwapFieldHelper;
+
+// Lazy string instance to support string fields with non-empty default.
+// These are initialized on the first call to .get().
+class PROTOBUF_EXPORT LazyString {
  public:
-  void Set(T* p) { ptr_ = reinterpret_cast<uintptr_t>(p); }
-  T* Get() const { return reinterpret_cast<T*>(ptr_); }
+  // We explicitly make LazyString an aggregate so that MSVC can do constant
+  // initialization on it without marking it `constexpr`.
+  // We do not want to use `constexpr` because it makes it harder to have extern
+  // storage for it and causes library bloat.
+  struct InitValue {
+    const char* ptr;
+    size_t size;
+  };
+  // We keep a union of the initialization value and the std::string to save on
+  // space. We don't need the string array after Init() is done.
+  union {
+    mutable InitValue init_value_;
+    alignas(std::string) mutable char string_buf_[sizeof(std::string)];
+  };
+  mutable std::atomic<const std::string*> inited_;
 
-  bool IsNull() { return ptr_ == 0; }
-
- private:
-  uintptr_t ptr_;
-};
-
-struct PROTOBUF_EXPORT ArenaStringPtr {
-  inline void Set(const ::std::string* default_value,
-                  const ::std::string& value, Arena* arena) {
-    if (ptr_ == default_value) {
-      CreateInstance(arena, &value);
-    } else {
-      *ptr_ = value;
-    }
+  const std::string& get() const {
+    // This check generates less code than a call-once invocation.
+    auto* res = inited_.load(std::memory_order_acquire);
+    if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
+    return *res;
   }
 
-  inline void SetLite(const ::std::string* default_value,
-                      const ::std::string& value, Arena* arena) {
-    Set(default_value, value, arena);
+ private:
+  // Initialize the string in `string_buf_`, update `inited_` and return it.
+  // We return it here to avoid having to read it again in the inlined code.
+  const std::string& Init() const;
+};
+
+template <typename T>
+class TaggedPtr {
+ public:
+  TaggedPtr() = default;
+  explicit constexpr TaggedPtr(const ExplicitlyConstructed<std::string>* ptr)
+      : ptr_(const_cast<ExplicitlyConstructed<std::string>*>(ptr)) {}
+
+  void SetTagged(T* p) {
+    Set(p);
+    ptr_ = reinterpret_cast<void*>(as_int() | 1);
+  }
+  void Set(T* p) { ptr_ = p; }
+  T* Get() const { return reinterpret_cast<T*>(as_int() & -2); }
+  bool IsTagged() const { return as_int() & 1; }
+
+  // Returned value is only safe to dereference if IsTagged() == false.
+  // It is safe to compare.
+  T* UnsafeGet() const { return static_cast<T*>(ptr_); }
+
+  bool IsNull() { return ptr_ == nullptr; }
+
+ private:
+  uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); }
+  void* ptr_;
+};
+
+static_assert(std::is_trivial<TaggedPtr<std::string>>::value,
+              "TaggedPtr must be trivial");
+
+// This class encapsulates a pointer to a std::string with or without a donated
+// buffer, tagged by bottom bit. It is a high-level wrapper that almost directly
+// corresponds to the interface required by string fields in generated
+// code. It replaces the old std::string* pointer in such cases.
+//
+// The object has different but similar code paths for when the default value is
+// the empty string and when it is a non-empty string.
+// The empty string is handled different throughout the library and there is a
+// single global instance of it we can share.
+//
+// For fields with an empty string default value, there are three distinct
+// states:
+//
+// - Pointer set to 'String' tag (LSB is 0), equal to
+//   &GetEmptyStringAlreadyInited(): field is set to its default value. Points
+//   to a true std::string*, but we do not own that std::string* (it's a
+//   globally shared instance).
+//
+// - Pointer set to 'String' tag (LSB is 0), but not equal to the global empty
+//   string: field points to a true std::string* instance that we own. This
+//   instance is either on the heap or on the arena (i.e. registered on
+//   free()/destructor-call list) as appropriate.
+//
+// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
+//   instance with a buffer on the arena (arena != NULL, always, in this case).
+//
+// For fields with a non-empty string default value, there are three distinct
+// states:
+//
+// - Pointer set to 'String' tag (LSB is 0), equal to `nullptr`:
+//   Field is in "default" mode and does not point to any actual instance.
+//   Methods that might need to create an instance of the object will pass a
+//   `const LazyString&` for it.
+//
+// - Pointer set to 'String' tag (LSB is 0), but not equal to `nullptr`:
+//   field points to a true std::string* instance that we own. This instance is
+//   either on the heap or on the arena (i.e. registered on
+//   free()/destructor-call list) as appropriate.
+//
+// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
+//   instance with a buffer on the arena (arena != NULL, always, in this case).
+//
+// Generated code and reflection code both ensure that ptr_ is never null for
+// fields with an empty default.
+// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
+// so the field is always manually initialized via method calls.
+//
+// Side-note: why pass information about the default on every API call? Because
+// we don't want to hold it in a member variable, or else this would go into
+// every proto message instance. This would be a huge waste of space, since the
+// default instance pointer is typically a global (static class field). We want
+// the generated code to be as efficient as possible, and if we take
+// the default value information as a parameter that's in practice taken from a
+// static class field, and compare ptr_ to the default value, we end up with a
+// single "cmp %reg, GLOBAL" in the resulting machine code. (Note that this also
+// requires the String tag to be 0 so we can avoid the mask before comparing.)
+struct PROTOBUF_EXPORT ArenaStringPtr {
+  ArenaStringPtr() = default;
+  explicit constexpr ArenaStringPtr(
+      const ExplicitlyConstructed<std::string>* default_value)
+      : tagged_ptr_(default_value) {}
+
+  // Some methods below are overloaded on a `default_value` and on tags.
+  // The tagged overloads help reduce code size in the callers in generated
+  // code, while the `default_value` overloads are useful from reflection.
+  // By-value empty struct arguments are elided in the ABI.
+  struct EmptyDefault {};
+  struct NonEmptyDefault {};
+
+  void Set(const std::string* default_value, ConstStringParam value,
+           ::google::protobuf::Arena* arena);
+  void Set(const std::string* default_value, std::string&& value,
+           ::google::protobuf::Arena* arena);
+  void Set(EmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
+  void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
+  void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
+  void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
+  template <typename FirstParam>
+  void Set(FirstParam p1, const char* str, ::google::protobuf::Arena* arena) {
+    Set(p1, ConstStringParam(str), arena);
+  }
+  template <typename FirstParam>
+  void Set(FirstParam p1, const char* str, size_t size,
+           ::google::protobuf::Arena* arena) {
+    ConstStringParam sp{str, size};  // for string_view and `const string &`
+    Set(p1, sp, arena);
+  }
+  template <typename FirstParam, typename RefWrappedType>
+  void Set(FirstParam p1,
+           std::reference_wrapper<RefWrappedType> const_string_ref,
+           ::google::protobuf::Arena* arena) {
+    Set(p1, const_string_ref.get(), arena);
+  }
+
+  template <typename FirstParam, typename SecondParam>
+  void SetBytes(FirstParam p1, SecondParam&& p2, ::google::protobuf::Arena* arena) {
+    Set(p1, static_cast<SecondParam&&>(p2), arena);
+  }
+  template <typename FirstParam>
+  void SetBytes(FirstParam p1, const void* str, size_t size,
+                ::google::protobuf::Arena* arena) {
+    // must work whether ConstStringParam is string_view or `const string &`
+    ConstStringParam sp{static_cast<const char*>(str), size};
+    Set(p1, sp, arena);
   }
 
   // Basic accessors.
-  inline const ::std::string& Get() const { return *ptr_; }
-
-  inline ::std::string* Mutable(const ::std::string* default_value,
-                                Arena* arena) {
-    if (ptr_ == default_value) {
-      CreateInstance(arena, default_value);
-    }
-    return ptr_;
+  PROTOBUF_NDEBUG_INLINE const std::string& Get() const {
+    // Unconditionally mask away the tag.
+    return *tagged_ptr_.Get();
+  }
+  PROTOBUF_NDEBUG_INLINE const std::string* GetPointer() const {
+    // Unconditionally mask away the tag.
+    return tagged_ptr_.Get();
   }
 
-  // Release returns a ::std::string* instance that is heap-allocated and is not
-  // Own()'d by any arena. If the field was not set, it returns NULL. The caller
-  // retains ownership. Clears this field back to NULL state. Used to implement
-  // release_<field>() methods on generated classes.
-  inline ::std::string* Release(const ::std::string* default_value,
-                                Arena* arena) {
-    if (ptr_ == default_value) {
-      return NULL;
-    }
-    return ReleaseNonDefault(default_value, arena);
-  }
+  // For fields with an empty default value.
+  std::string* Mutable(EmptyDefault, ::google::protobuf::Arena* arena);
+  // For fields with a non-empty default value.
+  std::string* Mutable(const LazyString& default_value, ::google::protobuf::Arena* arena);
 
-  // Similar to Release, but ptr_ cannot be the default_value.
-  inline ::std::string* ReleaseNonDefault(const ::std::string* default_value,
-                                          Arena* arena) {
-    GOOGLE_DCHECK(!IsDefault(default_value));
-    ::std::string* released = NULL;
-    if (arena != NULL) {
-      // ptr_ is owned by the arena.
-      released = new ::std::string;
-      released->swap(*ptr_);
-    } else {
-      released = ptr_;
-    }
-    ptr_ = const_cast< ::std::string*>(default_value);
-    return released;
-  }
+  // Release returns a std::string* instance that is heap-allocated and is not
+  // Own()'d by any arena. If the field is not set, this returns NULL. The
+  // caller retains ownership. Clears this field back to NULL state. Used to
+  // implement release_<field>() methods on generated classes.
+  PROTOBUF_MUST_USE_RESULT std::string* Release(
+      const std::string* default_value, ::google::protobuf::Arena* arena);
+  PROTOBUF_MUST_USE_RESULT std::string* ReleaseNonDefault(
+      const std::string* default_value, ::google::protobuf::Arena* arena);
 
-  // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned
-  // (i.e.  have its destructor already registered) if arena != NULL. If the
-  // field was not set, this returns NULL. This method clears this field back to
-  // NULL state. Used to implement unsafe_arena_release_<field>() methods on
-  // generated classes.
-  inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
-                                           Arena* /* arena */) {
-    if (ptr_ == default_value) {
-      return NULL;
-    }
-    ::std::string* released = ptr_;
-    ptr_ = const_cast< ::std::string*>(default_value);
-    return released;
-  }
-
-  // Takes a string that is heap-allocated, and takes ownership. The string's
-  // destructor is registered with the arena. Used to implement
+  // Takes a std::string that is heap-allocated, and takes ownership. The
+  // std::string's destructor is registered with the arena. Used to implement
   // set_allocated_<field> in generated classes.
-  inline void SetAllocated(const ::std::string* default_value,
-                           ::std::string* value, Arena* arena) {
-    if (arena == NULL && ptr_ != default_value) {
-      Destroy(default_value, arena);
-    }
-    if (value != NULL) {
-      ptr_ = value;
-      if (arena != NULL) {
-        arena->Own(value);
-      }
-    } else {
-      ptr_ = const_cast< ::std::string*>(default_value);
-    }
-  }
-
-  // Takes a string that has lifetime equal to the arena's lifetime. The arena
-  // must be non-null. It is safe only to pass this method a value returned by
-  // UnsafeArenaRelease() on another field of a message in the same arena. Used
-  // to implement unsafe_arena_set_allocated_<field> in generated classes.
-  inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
-                                      ::std::string* value,
-                                      Arena* /* arena */) {
-    if (value != NULL) {
-      ptr_ = value;
-    } else {
-      ptr_ = const_cast< ::std::string*>(default_value);
-    }
-  }
+  void SetAllocated(const std::string* default_value, std::string* value,
+                    ::google::protobuf::Arena* arena);
 
   // Swaps internal pointers. Arena-safety semantics: this is guarded by the
   // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
   // 'unsafe' if called directly.
-  PROTOBUF_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
-    std::swap(ptr_, other->ptr_);
-  }
-  PROTOBUF_ALWAYS_INLINE void Swap(ArenaStringPtr* other,
-                                   const ::std::string* default_value,
-                                   Arena* arena) {
-#ifndef NDEBUG
-    // For debug builds, we swap the contents of the string, rather than the
-    // string instances themselves.  This invalidates previously taken const
-    // references that are (per our documentation) invalidated by calling Swap()
-    // on the message.
-    //
-    // If both strings are the default_value, swapping is uninteresting.
-    // Otherwise, we use ArenaStringPtr::Mutable() to access the string, to
-    // ensure that we do not try to mutate default_value itself.
-    if (IsDefault(default_value) && other->IsDefault(default_value)) {
-      return;
-    }
-
-    ::std::string* this_ptr = Mutable(default_value, arena);
-    ::std::string* other_ptr = other->Mutable(default_value, arena);
-
-    this_ptr->swap(*other_ptr);
-#else
-    std::swap(ptr_, other->ptr_);
-    (void)default_value;
-    (void)arena;
-#endif
-  }
+  inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(
+      const std::string* default_value, ArenaStringPtr* rhs, Arena* rhs_arena,
+      ArenaStringPtr* lhs, Arena* lhs_arena);
 
   // Frees storage (if not on an arena).
-  inline void Destroy(const ::std::string* default_value, Arena* arena) {
-    if (arena == NULL && ptr_ != default_value) {
-      delete ptr_;
-    }
-  }
+  void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena);
+  void Destroy(EmptyDefault, ::google::protobuf::Arena* arena);
+  void Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena);
 
-  // Clears content, but keeps allocated string if arena != NULL, to avoid the
-  // overhead of heap operations. After this returns, the content (as seen by
-  // the user) will always be the empty string. Assumes that |default_value|
-  // is an empty string.
-  inline void ClearToEmpty(const ::std::string* default_value,
-                           Arena* /* arena */) {
-    if (ptr_ == default_value) {
-      // Already set to default (which is empty) -- do nothing.
-    } else {
-      ptr_->clear();
-    }
-  }
+  // Clears content, but keeps allocated std::string, to avoid the overhead of
+  // heap operations. After this returns, the content (as seen by the user) will
+  // always be the empty std::string. Assumes that |default_value| is an empty
+  // std::string.
+  void ClearToEmpty();
 
-  // Clears content, assuming that the current value is not the empty string
-  // default.
-  inline void ClearNonDefaultToEmpty() { ptr_->clear(); }
-  inline void ClearNonDefaultToEmptyNoArena() { ptr_->clear(); }
+  // Clears content, assuming that the current value is not the empty
+  // string default.
+  void ClearNonDefaultToEmpty();
 
-  // Clears content, but keeps allocated string if arena != NULL, to avoid the
-  // overhead of heap operations. After this returns, the content (as seen by
-  // the user) will always be equal to |default_value|.
-  inline void ClearToDefault(const ::std::string* default_value,
-                             Arena* /* arena */) {
-    if (ptr_ == default_value) {
-      // Already set to default -- do nothing.
-    } else {
-      // Have another allocated string -- rather than throwing this away and
-      // resetting ptr_ to the canonical default string instance, we just reuse
-      // this instance.
-      *ptr_ = *default_value;
-    }
-  }
+  // Clears content, but keeps allocated std::string if arena != NULL, to avoid
+  // the overhead of heap operations. After this returns, the content (as seen
+  // by the user) will always be equal to |default_value|.
+  void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
 
   // Called from generated code / reflection runtime only. Resets value to point
-  // to a default string pointer, with the semantics that this ArenaStringPtr
-  // does not own the pointed-to memory. Disregards initial value of ptr_ (so
-  // this is the *ONLY* safe method to call after construction or when
-  // reinitializing after becoming the active field in a oneof union).
-  inline void UnsafeSetDefault(const ::std::string* default_value) {
-    // Casting away 'const' is safe here: accessors ensure that ptr_ is only
-    // returned as a const if it is equal to default_value.
-    ptr_ = const_cast< ::std::string*>(default_value);
-  }
+  // to a default string pointer, with the semantics that this
+  // ArenaStringPtr does not own the pointed-to memory. Disregards initial value
+  // of ptr_ (so this is the *ONLY* safe method to call after construction or
+  // when reinitializing after becoming the active field in a oneof union).
+  inline void UnsafeSetDefault(const std::string* default_value);
 
-  // The 'NoArena' variants of methods below assume arena == NULL and are
-  // optimized to provide very little overhead relative to a raw string pointer
-  // (while still being in-memory compatible with other code that assumes
-  // ArenaStringPtr). Note the invariant that a class instance that has only
-  // ever been mutated by NoArena methods must *only* be in the String state
-  // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
-  // tagged-pointer manipulations to be avoided.
-  inline void SetNoArena(const ::std::string* default_value,
-                         const ::std::string& value) {
-    if (ptr_ == default_value) {
-      CreateInstanceNoArena(&value);
-    } else {
-      *ptr_ = value;
-    }
-  }
+  // Returns a mutable pointer, but doesn't initialize the string to the
+  // default value.
+  std::string* MutableNoArenaNoDefault(const std::string* default_value);
 
-  void SetNoArena(const ::std::string* default_value, ::std::string&& value) {
-    if (IsDefault(default_value)) {
-      ptr_ = new ::std::string(std::move(value));
-    } else {
-      *ptr_ = std::move(value);
-    }
-  }
+  // Get a mutable pointer with unspecified contents.
+  // Similar to `MutableNoArenaNoDefault`, but also handles the arena case.
+  // If the value was donated, the contents are discarded.
+  std::string* MutableNoCopy(const std::string* default_value,
+                             ::google::protobuf::Arena* arena);
 
-  void AssignWithDefault(const ::std::string* default_value,
-                         ArenaStringPtr value);
+  // Destroy the string. Assumes `arena == nullptr`.
+  void DestroyNoArena(const std::string* default_value);
 
-  inline const ::std::string& GetNoArena() const { return *ptr_; }
-
-  inline ::std::string* MutableNoArena(const ::std::string* default_value) {
-    if (ptr_ == default_value) {
-      CreateInstanceNoArena(default_value);
-    }
-    return ptr_;
-  }
-
-  inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
-    if (ptr_ == default_value) {
-      return NULL;
-    } else {
-      return ReleaseNonDefaultNoArena(default_value);
-    }
-  }
-
-  inline ::std::string* ReleaseNonDefaultNoArena(
-      const ::std::string* default_value) {
-    GOOGLE_DCHECK(!IsDefault(default_value));
-    ::std::string* released = ptr_;
-    ptr_ = const_cast< ::std::string*>(default_value);
-    return released;
-  }
-
-  inline void SetAllocatedNoArena(const ::std::string* default_value,
-                                  ::std::string* value) {
-    if (ptr_ != default_value) {
-      delete ptr_;
-    }
-    if (value != NULL) {
-      ptr_ = value;
-    } else {
-      ptr_ = const_cast< ::std::string*>(default_value);
-    }
-  }
-
-  inline void DestroyNoArena(const ::std::string* default_value) {
-    if (ptr_ != default_value) {
-      delete ptr_;
-    }
-  }
-
-  inline void ClearToEmptyNoArena(const ::std::string* default_value) {
-    if (ptr_ == default_value) {
-      // Nothing: already equal to default (which is the empty string).
-    } else {
-      ptr_->clear();
-    }
-  }
-
-  inline void ClearToDefaultNoArena(const ::std::string* default_value) {
-    if (ptr_ == default_value) {
-      // Nothing: already set to default.
-    } else {
-      // Reuse existing allocated instance.
-      *ptr_ = *default_value;
-    }
-  }
-
-  // Internal accessor used only at parse time to provide direct access to the
-  // raw pointer from the shared parse routine (in the non-arenas case). The
-  // parse routine does the string allocation in order to save code size in the
-  // generated parsing code.
-  inline ::std::string** UnsafeRawStringPointer() { return &ptr_; }
-
-  inline bool IsDefault(const ::std::string* default_value) const {
-    return ptr_ == default_value;
-  }
-
-  // Internal accessors!!!!
-  void UnsafeSetTaggedPointer(TaggedPtr< ::std::string> value) {
-    ptr_ = value.Get();
+  // Internal setter used only at parse time to directly set a donated string
+  // value.
+  void UnsafeSetTaggedPointer(TaggedPtr<std::string> value) {
+    tagged_ptr_ = value;
   }
   // Generated code only! An optimization, in certain cases the generated
-  // code is certain we can obtain a string with no default checks and
+  // code is certain we can obtain a std::string with no default checks and
   // tag tests.
-  ::std::string* UnsafeMutablePointer() { return ptr_; }
+  std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL;
+
+  inline bool IsDefault(const std::string* default_value) const {
+    // Relies on the fact that kPtrTagString == 0, so if IsString(), ptr_ is the
+    // actual std::string pointer (and if !IsString(), ptr_ will never be equal
+    // to any aligned |default_value| pointer). The key is that we want to avoid
+    // masking in the fastpath const-pointer Get() case for non-arena code.
+    return tagged_ptr_.UnsafeGet() == default_value;
+  }
 
  private:
-  ::std::string* ptr_;
+  TaggedPtr<std::string> tagged_ptr_;
 
-  PROTOBUF_NOINLINE
-  void CreateInstance(Arena* arena, const ::std::string* initial_value) {
-    GOOGLE_DCHECK(initial_value != NULL);
-    // uses "new ::std::string" when arena is nullptr
-    ptr_ = Arena::Create< ::std::string>(arena, *initial_value);
+  bool IsDonatedString() const { return false; }
+
+  // Swaps tagged pointer without debug hardening. This is to allow python
+  // protobuf to maintain pointer stability even in DEBUG builds.
+  inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap(
+      ArenaStringPtr* rhs, ArenaStringPtr* lhs) {
+    std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
   }
-  PROTOBUF_NOINLINE
-  void CreateInstanceNoArena(const ::std::string* initial_value) {
-    GOOGLE_DCHECK(initial_value != NULL);
-    ptr_ = new ::std::string(*initial_value);
-  }
+
+  friend class ::google::protobuf::internal::SwapFieldHelper;
+
+  // Slow paths.
+
+  // MutableSlow requires that !IsString() || IsDefault
+  // Variadic to support 0 args for EmptyDefault and 1 arg for LazyString.
+  template <typename... Lazy>
+  std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
+
+  // Sets value to a newly allocated string and returns it
+  std::string* SetAndReturnNewString();
+
+  // Destroys the non-default string value out-of-line
+  void DestroyNoArenaSlowPath();
+
 };
 
-}  // namespace internal
-}  // namespace protobuf
+inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) {
+  tagged_ptr_.Set(const_cast<std::string*>(value));
+}
 
-namespace protobuf {
-namespace internal {
+inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap(  //
+    const std::string* default_value,                             //
+    ArenaStringPtr* rhs, Arena* rhs_arena,                        //
+    ArenaStringPtr* lhs, Arena* lhs_arena) {
+  (void)default_value;
+  std::swap(lhs_arena, rhs_arena);
+  std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  auto force_realloc = [default_value](ArenaStringPtr* p, Arena* arena) {
+    if (p->IsDefault(default_value)) return;
+    std::string* old_value = p->tagged_ptr_.Get();
+    std::string* new_value =
+        p->IsDonatedString()
+            ? Arena::Create<std::string>(arena, *old_value)
+            : Arena::Create<std::string>(arena, std::move(*old_value));
+    if (arena == nullptr) delete old_value;
+    p->tagged_ptr_.Set(new_value);
+  };
+  force_realloc(lhs, lhs_arena);
+  force_realloc(rhs, rhs_arena);
+#endif  // PROTOBUF_FORCE_COPY_IN_SWAP
+}
 
-inline void ArenaStringPtr::AssignWithDefault(
-    const ::std::string* default_value, ArenaStringPtr value) {
-  const ::std::string* me = *UnsafeRawStringPointer();
-  const ::std::string* other = *value.UnsafeRawStringPointer();
-  // If the pointers are the same then do nothing.
-  if (me != other) {
-    SetNoArena(default_value, value.GetNoArena());
+inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
+  // Unconditionally mask away the tag.
+  tagged_ptr_.Get()->clear();
+}
+
+inline std::string* ArenaStringPtr::MutableNoArenaNoDefault(
+    const std::string* default_value) {
+  // VERY IMPORTANT for performance and code size: this will reduce to a member
+  // variable load, a pointer check (against |default_value|, in practice a
+  // static global) and a branch to the slowpath (which calls operator new and
+  // the ctor). DO NOT add any tagged-pointer operations here.
+  if (IsDefault(default_value)) {
+    return SetAndReturnNewString();
+  } else {
+    return UnsafeMutablePointer();
   }
 }
 
+inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) {
+  if (!IsDefault(default_value)) {
+    DestroyNoArenaSlowPath();
+  }
+}
+
+inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
+  GOOGLE_DCHECK(!tagged_ptr_.IsTagged());
+  GOOGLE_DCHECK(tagged_ptr_.UnsafeGet() != nullptr);
+  return tagged_ptr_.UnsafeGet();
+}
+
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
-
 #include <google/protobuf/port_undef.inc>
 
 #endif  // GOOGLE_PROTOBUF_ARENASTRING_H__
diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
index c5da447..db988af 100644
--- a/src/google/protobuf/arenastring_unittest.cc
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -28,8 +28,6 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Based on mvels@'s frankenstring.
-
 #include <google/protobuf/arenastring.h>
 
 #include <algorithm>
@@ -42,95 +40,118 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message_lite.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/strutil.h>
 
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 
 using internal::ArenaStringPtr;
 
-static std::string WrapString(const char* value) { return value; }
+using EmptyDefault = ArenaStringPtr::EmptyDefault;
 
-// Test ArenaStringPtr with arena == NULL.
-TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
+const internal::LazyString nonempty_default{{{"default", 7}}, {nullptr}};
+const std::string* empty_default = &internal::GetEmptyString();
+
+class SingleArena : public testing::TestWithParam<bool> {
+ public:
+  std::unique_ptr<Arena> GetArena() {
+    if (this->GetParam()) return nullptr;
+    return std::unique_ptr<Arena>(new Arena());
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(ArenaString, SingleArena, testing::Bool());
+
+TEST_P(SingleArena, GetSet) {
+  auto arena = GetArena();
   ArenaStringPtr field;
-  std::string default_value = "default";
-  field.UnsafeSetDefault(&default_value);
-  EXPECT_EQ(std::string("default"), field.Get());
-  field.Set(&default_value, WrapString("Test short"), NULL);
-  EXPECT_EQ(std::string("Test short"), field.Get());
-  field.Set(&default_value, WrapString("Test long long long long value"), NULL);
-  EXPECT_EQ(std::string("Test long long long long value"), field.Get());
-  field.Set(&default_value, std::string(""), NULL);
-  field.Destroy(&default_value, NULL);
-
-  ArenaStringPtr field2;
-  field2.UnsafeSetDefault(&default_value);
-  std::string* mut = field2.Mutable(&default_value, NULL);
-  EXPECT_EQ(mut, field2.Mutable(&default_value, NULL));
-  EXPECT_EQ(mut, &field2.Get());
-  EXPECT_NE(&default_value, mut);
-  EXPECT_EQ(std::string("default"), *mut);
-  *mut = "Test long long long long value";  // ensure string allocates storage
-  EXPECT_EQ(std::string("Test long long long long value"), field2.Get());
-  field2.Destroy(&default_value, NULL);
+  field.UnsafeSetDefault(empty_default);
+  EXPECT_EQ("", field.Get());
+  field.Set(empty_default, "Test short", arena.get());
+  EXPECT_EQ("Test short", field.Get());
+  field.Set(empty_default, "Test long long long long value", arena.get());
+  EXPECT_EQ("Test long long long long value", field.Get());
+  field.Set(empty_default, "", arena.get());
+  field.Destroy(empty_default, arena.get());
 }
 
-TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
-  Arena arena;
+TEST_P(SingleArena, MutableAccessor) {
+  auto arena = GetArena();
   ArenaStringPtr field;
-  std::string default_value = "default";
-  field.UnsafeSetDefault(&default_value);
-  EXPECT_EQ(std::string("default"), field.Get());
-  field.Set(&default_value, WrapString("Test short"), &arena);
-  EXPECT_EQ(std::string("Test short"), field.Get());
-  field.Set(&default_value, WrapString("Test long long long long value"),
-            &arena);
-  EXPECT_EQ(std::string("Test long long long long value"), field.Get());
-  field.Set(&default_value, std::string(""), &arena);
-  field.Destroy(&default_value, &arena);
+  const std::string* empty_default = &internal::GetEmptyString();
+  field.UnsafeSetDefault(empty_default);
 
-  ArenaStringPtr field2;
-  field2.UnsafeSetDefault(&default_value);
-  std::string* mut = field2.Mutable(&default_value, &arena);
-  EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
-  EXPECT_EQ(mut, &field2.Get());
-  EXPECT_NE(&default_value, mut);
-  EXPECT_EQ(std::string("default"), *mut);
+  std::string* mut = field.Mutable(EmptyDefault{}, arena.get());
+  EXPECT_EQ(mut, field.Mutable(EmptyDefault{}, arena.get()));
+  EXPECT_EQ(mut, &field.Get());
+  EXPECT_NE(empty_default, mut);
+  EXPECT_EQ("", *mut);
   *mut = "Test long long long long value";  // ensure string allocates storage
-  EXPECT_EQ(std::string("Test long long long long value"), field2.Get());
-  field2.Destroy(&default_value, &arena);
+  EXPECT_EQ("Test long long long long value", field.Get());
+  field.Destroy(empty_default, arena.get());
 }
 
-TEST(ArenaStringPtrTest, ArenaStringPtrOnArenaNoSSO) {
-  Arena arena;
+TEST_P(SingleArena, NullDefault) {
+  auto arena = GetArena();
+
   ArenaStringPtr field;
-  std::string default_value = "default";
-  field.UnsafeSetDefault(&default_value);
-  EXPECT_EQ(std::string("default"), field.Get());
-
-  // Avoid triggering the SSO optimization by setting the string to something
-  // larger than the internal buffer.
-  field.Set(&default_value, WrapString("Test long long long long value"),
-            &arena);
-  EXPECT_EQ(std::string("Test long long long long value"), field.Get());
-  field.Set(&default_value, std::string(""), &arena);
-  field.Destroy(&default_value, &arena);
-
-  ArenaStringPtr field2;
-  field2.UnsafeSetDefault(&default_value);
-  std::string* mut = field2.Mutable(&default_value, &arena);
-  EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
-  EXPECT_EQ(mut, &field2.Get());
-  EXPECT_NE(&default_value, mut);
-  EXPECT_EQ(std::string("default"), *mut);
+  field.UnsafeSetDefault(nullptr);
+  std::string* mut = field.Mutable(nonempty_default, arena.get());
+  EXPECT_EQ(mut, field.Mutable(nonempty_default, arena.get()));
+  EXPECT_EQ(mut, &field.Get());
+  EXPECT_NE(nullptr, mut);
+  EXPECT_EQ("default", *mut);
   *mut = "Test long long long long value";  // ensure string allocates storage
-  EXPECT_EQ(std::string("Test long long long long value"), field2.Get());
-  field2.Destroy(&default_value, &arena);
+  EXPECT_EQ("Test long long long long value", field.Get());
+  field.Destroy(nullptr, arena.get());
+}
+
+class DualArena : public testing::TestWithParam<std::tuple<bool, bool>> {
+ public:
+  std::unique_ptr<Arena> GetLhsArena() {
+    if (std::get<0>(this->GetParam())) return nullptr;
+    return std::unique_ptr<Arena>(new Arena());
+  }
+  std::unique_ptr<Arena> GetRhsArena() {
+    if (std::get<1>(this->GetParam())) return nullptr;
+    return std::unique_ptr<Arena>(new Arena());
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(ArenaString, DualArena,
+                         testing::Combine(testing::Bool(), testing::Bool()));
+
+TEST_P(DualArena, Swap) {
+  auto lhs_arena = GetLhsArena();
+  ArenaStringPtr lhs;
+  lhs.UnsafeSetDefault(empty_default);
+  ArenaStringPtr rhs;
+  rhs.UnsafeSetDefault(empty_default);
+
+  {
+    auto rhs_arena = GetRhsArena();
+    lhs.Set(empty_default, "lhs value that has some heft", lhs_arena.get());
+    rhs.Set(empty_default, "rhs value that has some heft", rhs_arena.get());
+    ArenaStringPtr::InternalSwap(empty_default,          //
+                                 &lhs, lhs_arena.get(),  //
+                                 &rhs, rhs_arena.get());
+    EXPECT_EQ("rhs value that has some heft", lhs.Get());
+    EXPECT_EQ("lhs value that has some heft", rhs.Get());
+    lhs.Destroy(empty_default, rhs_arena.get());
+  }
+  EXPECT_EQ("lhs value that has some heft", rhs.Get());
+  rhs.Destroy(empty_default, lhs_arena.get());
 }
 
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/compiler/annotation_test_util.cc b/src/google/protobuf/compiler/annotation_test_util.cc
index d33f29f..3c47aa4 100644
--- a/src/google/protobuf/compiler/annotation_test_util.cc
+++ b/src/google/protobuf/compiler/annotation_test_util.cc
@@ -30,16 +30,17 @@
 
 #include <google/protobuf/compiler/annotation_test_util.h>
 
+#include <cstdint>
 #include <memory>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/descriptor.pb.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
@@ -141,8 +142,8 @@
            e = annotations.end();
        i != e; ++i) {
     const GeneratedCodeInfo::Annotation* annotation = *i;
-    uint32 begin = annotation->begin();
-    uint32 end = annotation->end();
+    uint32_t begin = annotation->begin();
+    uint32_t end = annotation->end();
     if (end < begin || end > file_content.size()) {
       return false;
     }
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 693300d..4544f3e 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -85,6 +85,12 @@
   return NULL;  // make compiler happy
 }
 
+io::ZeroCopyOutputStream* GeneratorContext::OpenForInsertWithGeneratedCodeInfo(
+    const std::string& filename, const std::string& insertion_point,
+    const google::protobuf::GeneratedCodeInfo& /*info*/) {
+  return OpenForInsert(filename, insertion_point);
+}
+
 void GeneratorContext::ListParsedFiles(
     std::vector<const FileDescriptor*>* output) {
   GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
@@ -117,6 +123,15 @@
   }
 }
 
+// Strips ".proto" or ".protodevel" from the end of a filename.
+std::string StripProto(const std::string& filename) {
+  if (HasSuffixString(filename, ".protodevel")) {
+    return StripSuffixString(filename, ".protodevel");
+  } else {
+    return StripSuffixString(filename, ".proto");
+  }
+}
+
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index 1bc8dfc..c8d9e49 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -52,6 +52,7 @@
 class ZeroCopyOutputStream;
 }
 class FileDescriptor;
+class GeneratedCodeInfo;
 
 namespace compiler {
 class AccessInfoMap;
@@ -110,7 +111,7 @@
   // Implement this to indicate what features this code generator supports.
   // This should be a bitwise OR of features from the Features enum in
   // plugin.proto.
-  virtual uint64 GetSupportedFeatures() const { return 0; }
+  virtual uint64_t GetSupportedFeatures() const { return 0; }
 
   // This is no longer used, but this class is part of the opensource protobuf
   // library, so it has to remain to keep vtables the same for the current
@@ -156,6 +157,15 @@
   virtual io::ZeroCopyOutputStream* OpenForInsert(
       const std::string& filename, const std::string& insertion_point);
 
+  // Similar to OpenForInsert, but if `info` is non-empty, will open (or create)
+  // filename.pb.meta and insert info at the appropriate place with the
+  // necessary shifts. The default implementation ignores `info`.
+  //
+  // WARNING:  This feature will be REMOVED in the near future.
+  virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
+      const std::string& filename, const std::string& insertion_point,
+      const google::protobuf::GeneratedCodeInfo& info);
+
   // Returns a vector of FileDescriptors for all the files being compiled
   // in this run.  Useful for languages, such as Go, that treat files
   // differently when compiled as a set rather than individually.
@@ -183,6 +193,9 @@
 PROTOC_EXPORT void ParseGeneratorParameter(
     const std::string&, std::vector<std::pair<std::string, std::string> >*);
 
+// Strips ".proto" or ".protodevel" from the end of a filename.
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index ed64289..a68a604 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -34,6 +34,8 @@
 
 #include <google/protobuf/compiler/command_line_interface.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/platform_macros.h>
 
 #include <stdio.h>
@@ -58,8 +60,10 @@
 
 #include <memory>
 
-#ifdef __APPLE__
+#if defined(__APPLE__)
 #include <mach-o/dyld.h>
+#elif defined(__FreeBSD__)
+#include <sys/sysctl.h>
 #endif
 
 #include <google/protobuf/stubs/common.h>
@@ -202,6 +206,13 @@
     realpath(dirtybuffer, buffer);
     len = strlen(buffer);
   }
+#elif defined(__FreeBSD__)
+  char buffer[PATH_MAX];
+  size_t len = PATH_MAX;
+  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+  if (sysctl(mib, 4, &buffer, &len, NULL, 0) != 0) {
+    len = 0;
+  }
 #else
   char buffer[PATH_MAX];
   int len = readlink("/proc/self/exe", buffer, PATH_MAX);
@@ -225,7 +236,7 @@
 // Add the paths where google/protobuf/descriptor.proto and other well-known
 // type protos are installed.
 void AddDefaultProtoPaths(
-    std::vector<std::pair<std::string, std::string> >* paths) {
+    std::vector<std::pair<std::string, std::string>>* paths) {
   // TODO(xiaofeng): The code currently only checks relative paths of where
   // the protoc binary is installed. We probably should make it handle more
   // cases than that.
@@ -279,45 +290,51 @@
       public DescriptorPool::ErrorCollector {
  public:
   ErrorPrinter(ErrorFormat format, DiskSourceTree* tree = NULL)
-      : format_(format), tree_(tree), found_errors_(false) {}
+      : format_(format),
+        tree_(tree),
+        found_errors_(false),
+        found_warnings_(false) {}
   ~ErrorPrinter() {}
 
   // implements MultiFileErrorCollector ------------------------------
   void AddError(const std::string& filename, int line, int column,
-                const std::string& message) {
+                const std::string& message) override {
     found_errors_ = true;
     AddErrorOrWarning(filename, line, column, message, "error", std::cerr);
   }
 
   void AddWarning(const std::string& filename, int line, int column,
-                  const std::string& message) {
+                  const std::string& message) override {
+    found_warnings_ = true;
     AddErrorOrWarning(filename, line, column, message, "warning", std::clog);
   }
 
   // implements io::ErrorCollector -----------------------------------
-  void AddError(int line, int column, const std::string& message) {
+  void AddError(int line, int column, const std::string& message) override {
     AddError("input", line, column, message);
   }
 
-  void AddWarning(int line, int column, const std::string& message) {
+  void AddWarning(int line, int column, const std::string& message) override {
     AddErrorOrWarning("input", line, column, message, "warning", std::clog);
   }
 
   // implements DescriptorPool::ErrorCollector-------------------------
   void AddError(const std::string& filename, const std::string& element_name,
                 const Message* descriptor, ErrorLocation location,
-                const std::string& message) {
+                const std::string& message) override {
     AddErrorOrWarning(filename, -1, -1, message, "error", std::cerr);
   }
 
   void AddWarning(const std::string& filename, const std::string& element_name,
                   const Message* descriptor, ErrorLocation location,
-                  const std::string& message) {
+                  const std::string& message) override {
     AddErrorOrWarning(filename, -1, -1, message, "warning", std::clog);
   }
 
   bool FoundErrors() const { return found_errors_; }
 
+  bool FoundWarnings() const { return found_warnings_; }
+
  private:
   void AddErrorOrWarning(const std::string& filename, int line, int column,
                          const std::string& message, const std::string& type,
@@ -356,6 +373,7 @@
   const ErrorFormat format_;
   DiskSourceTree* tree_;
   bool found_errors_;
+  bool found_warnings_;
 };
 
 // -------------------------------------------------------------------
@@ -382,18 +400,22 @@
   void GetOutputFilenames(std::vector<std::string>* output_filenames);
 
   // implements GeneratorContext --------------------------------------
-  io::ZeroCopyOutputStream* Open(const std::string& filename);
-  io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename);
+  io::ZeroCopyOutputStream* Open(const std::string& filename) override;
+  io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename) override;
   io::ZeroCopyOutputStream* OpenForInsert(const std::string& filename,
-                                          const std::string& insertion_point);
-  void ListParsedFiles(std::vector<const FileDescriptor*>* output) {
+                                          const std::string& insertion_point) override;
+  io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
+      const std::string& filename, const std::string& insertion_point,
+      const google::protobuf::GeneratedCodeInfo& info) override;
+  void ListParsedFiles(std::vector<const FileDescriptor*>* output) override {
     *output = parsed_files_;
   }
 
  private:
   friend class MemoryOutputStream;
 
-  // map instead of unordered_map so that files are written in order (good when
+  // The files_ field maps from path keys to file content values. It's a map
+  // instead of an unordered_map so that files are written in order (good when
   // writing zips).
   std::map<std::string, std::string> files_;
   const std::vector<const FileDescriptor*>& parsed_files_;
@@ -408,6 +430,10 @@
   MemoryOutputStream(GeneratorContextImpl* directory,
                      const std::string& filename,
                      const std::string& insertion_point);
+  MemoryOutputStream(GeneratorContextImpl* directory,
+                     const std::string& filename,
+                     const std::string& insertion_point,
+                     const google::protobuf::GeneratedCodeInfo& info);
   virtual ~MemoryOutputStream();
 
   // implements ZeroCopyOutputStream ---------------------------------
@@ -418,12 +444,23 @@
   int64_t ByteCount() const override { return inner_->ByteCount(); }
 
  private:
-  // Checks to see if "filename_.meta" exists in directory_; if so, fixes the
+  // Checks to see if "filename_.pb.meta" exists in directory_; if so, fixes the
   // offsets in that GeneratedCodeInfo record to reflect bytes inserted in
   // filename_ at original offset insertion_offset with length insertion_length.
-  // We assume that insertions will not occur within any given annotated span
-  // of text.
-  void UpdateMetadata(size_t insertion_offset, size_t insertion_length);
+  // Also adds in the data from info_to_insert_ with updated offsets governed by
+  // insertion_offset and indent_length. We assume that insertions will not
+  // occur within any given annotated span of text. insertion_content must end
+  // with an endline.
+  void UpdateMetadata(const std::string& insertion_content,
+                      size_t insertion_offset, size_t insertion_length,
+                      size_t indent_length);
+
+  // Inserts info_to_insert_ into target_info, assuming that the relevant
+  // insertion was made at insertion_offset in file_content with the given
+  // indent_length. insertion_content must end with an endline.
+  void InsertShiftedInfo(const std::string& insertion_content,
+                         size_t insertion_offset, size_t indent_length,
+                         google::protobuf::GeneratedCodeInfo& target_info);
 
   // Where to insert the string when it's done.
   GeneratorContextImpl* directory_;
@@ -438,6 +475,9 @@
 
   // StringOutputStream writing to data_.
   std::unique_ptr<io::StringOutputStream> inner_;
+
+  // The GeneratedCodeInfo to insert at the insertion point.
+  google::protobuf::GeneratedCodeInfo info_to_insert_;
 };
 
 // -------------------------------------------------------------------
@@ -551,10 +591,12 @@
 
   if (stream.GetErrno() != 0) {
     std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+    return false;
   }
 
   if (!stream.Close()) {
     std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+    return false;
   }
 
   return true;
@@ -594,6 +636,13 @@
   return new MemoryOutputStream(this, filename, insertion_point);
 }
 
+io::ZeroCopyOutputStream*
+CommandLineInterface::GeneratorContextImpl::OpenForInsertWithGeneratedCodeInfo(
+    const std::string& filename, const std::string& insertion_point,
+    const google::protobuf::GeneratedCodeInfo& info) {
+  return new MemoryOutputStream(this, filename, insertion_point, info);
+}
+
 // -------------------------------------------------------------------
 
 CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
@@ -612,40 +661,114 @@
       insertion_point_(insertion_point),
       inner_(new io::StringOutputStream(&data_)) {}
 
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+    GeneratorContextImpl* directory, const std::string& filename,
+    const std::string& insertion_point, const google::protobuf::GeneratedCodeInfo& info)
+    : directory_(directory),
+      filename_(filename),
+      insertion_point_(insertion_point),
+      inner_(new io::StringOutputStream(&data_)),
+      info_to_insert_(info) {}
+
+void CommandLineInterface::MemoryOutputStream::InsertShiftedInfo(
+    const std::string& insertion_content, size_t insertion_offset,
+    size_t indent_length, google::protobuf::GeneratedCodeInfo& target_info) {
+  // Keep track of how much extra data was added for indents before the
+  // current annotation being inserted. `pos` and `source_annotation.begin()`
+  // are offsets in `insertion_content`. `insertion_offset` is updated so that
+  // it can be added to an annotation's `begin` field to reflect that
+  // annotation's updated location after `insertion_content` was inserted into
+  // the target file.
+  size_t pos = 0;
+  insertion_offset += indent_length;
+  for (const auto& source_annotation : info_to_insert_.annotation()) {
+    GeneratedCodeInfo::Annotation* annotation = target_info.add_annotation();
+    int inner_indent = 0;
+    // insertion_content is guaranteed to end in an endline. This last endline
+    // has no effect on indentation.
+    for (; pos < source_annotation.end() && pos < insertion_content.size() - 1;
+         ++pos) {
+      if (insertion_content[pos] == '\n') {
+        if (pos >= source_annotation.begin()) {
+          // The beginning of the annotation is at insertion_offset, but the end
+          // can still move further in the target file.
+          inner_indent += indent_length;
+        } else {
+          insertion_offset += indent_length;
+        }
+      }
+    }
+    *annotation = source_annotation;
+    annotation->set_begin(annotation->begin() + insertion_offset);
+    insertion_offset += inner_indent;
+    annotation->set_end(annotation->end() + insertion_offset);
+  }
+}
+
 void CommandLineInterface::MemoryOutputStream::UpdateMetadata(
-    size_t insertion_offset, size_t insertion_length) {
-  auto it = directory_->files_.find(filename_ + ".meta");
-  if (it == directory_->files_.end()) {
+    const std::string& insertion_content, size_t insertion_offset,
+    size_t insertion_length, size_t indent_length) {
+  auto it = directory_->files_.find(filename_ + ".pb.meta");
+  if (it == directory_->files_.end() && info_to_insert_.annotation().empty()) {
     // No metadata was recorded for this file.
     return;
   }
-  std::string& encoded_data = it->second;
   GeneratedCodeInfo metadata;
   bool is_text_format = false;
-  if (!metadata.ParseFromString(encoded_data)) {
-    if (!TextFormat::ParseFromString(encoded_data, &metadata)) {
-      // The metadata is invalid.
-      std::cerr << filename_
-                << ".meta: Could not parse metadata as wire or text format."
-                << std::endl;
-      return;
+  std::string* encoded_data = nullptr;
+  if (it != directory_->files_.end()) {
+    encoded_data = &it->second;
+    // Try to decode a GeneratedCodeInfo proto from the .pb.meta file. It may be
+    // in wire or text format. Keep the same format when the data is written out
+    // later.
+    if (!metadata.ParseFromString(*encoded_data)) {
+      if (!TextFormat::ParseFromString(*encoded_data, &metadata)) {
+        // The metadata is invalid.
+        std::cerr
+            << filename_
+            << ".pb.meta: Could not parse metadata as wire or text format."
+            << std::endl;
+        return;
+      }
+      // Generators that use the public plugin interface emit text-format
+      // metadata (because in the public plugin protocol, file content must be
+      // UTF8-encoded strings).
+      is_text_format = true;
     }
-    // Generators that use the public plugin interface emit text-format
-    // metadata (because in the public plugin protocol, file content must be
-    // UTF8-encoded strings).
-    is_text_format = true;
+  } else {
+    // Create a new file to store the new metadata in info_to_insert_.
+    encoded_data =
+        &directory_->files_.insert({filename_ + ".pb.meta", ""}).first->second;
   }
-  for (int i = 0; i < metadata.annotation_size(); ++i) {
-    GeneratedCodeInfo::Annotation* annotation = metadata.mutable_annotation(i);
-    if (annotation->begin() >= insertion_offset) {
-      annotation->set_begin(annotation->begin() + insertion_length);
-      annotation->set_end(annotation->end() + insertion_length);
+  GeneratedCodeInfo new_metadata;
+  bool crossed_offset = false;
+  size_t to_add = 0;
+  for (const auto& source_annotation : metadata.annotation()) {
+    // The first time an annotation at or after the insertion point is found,
+    // insert the new metadata from info_to_insert_. Shift all annotations
+    // after the new metadata by the length of the text that was inserted
+    // (including any additional indent length).
+    if (source_annotation.begin() >= insertion_offset && !crossed_offset) {
+      crossed_offset = true;
+      InsertShiftedInfo(insertion_content, insertion_offset, indent_length,
+                        new_metadata);
+      to_add += insertion_length;
     }
+    GeneratedCodeInfo::Annotation* annotation = new_metadata.add_annotation();
+    *annotation = source_annotation;
+    annotation->set_begin(annotation->begin() + to_add);
+    annotation->set_end(annotation->end() + to_add);
+  }
+  // If there were never any annotations at or after the insertion point,
+  // make sure to still insert the new metadata from info_to_insert_.
+  if (!crossed_offset) {
+    InsertShiftedInfo(insertion_content, insertion_offset, indent_length,
+                      new_metadata);
   }
   if (is_text_format) {
-    TextFormat::PrintToString(metadata, &encoded_data);
+    TextFormat::PrintToString(new_metadata, encoded_data);
   } else {
-    metadata.SerializeToString(&encoded_data);
+    new_metadata.SerializeToString(encoded_data);
   }
 }
 
@@ -728,7 +851,7 @@
     if (indent_.empty()) {
       // No indent.  This makes things easier.
       target->insert(pos, data_);
-      UpdateMetadata(pos, data_.size());
+      UpdateMetadata(data_, pos, data_.size(), 0);
     } else {
       // Calculate how much space we need.
       int indent_size = 0;
@@ -738,7 +861,6 @@
 
       // Make a hole for it.
       target->insert(pos, data_.size() + indent_size, '\0');
-      UpdateMetadata(pos, data_.size() + indent_size);
 
       // Now copy in the data.
       std::string::size_type data_pos = 0;
@@ -757,6 +879,7 @@
         target_ptr += line_length;
         data_pos += line_length;
       }
+      UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size());
 
       GOOGLE_CHECK_EQ(target_ptr,
                ::google::protobuf::string_as_array(target) + pos + data_.size() + indent_size);
@@ -924,16 +1047,6 @@
   }
 
 
-  for (auto fd : parsed_files) {
-    if (!AllowProto3Optional(*fd) && ContainsProto3Optional(fd)) {
-      std::cerr << fd->name()
-                << ": This file contains proto3 optional fields, but "
-                   "--experimental_allow_proto3_optional was not set."
-                << std::endl;
-      return 1;
-    }
-  }
-
   // We construct a separate GeneratorContext for each output location.  Note
   // that two code generators may output to the same location, in which case
   // they should share a single GeneratorContext so that OpenForInsert() works.
@@ -1015,7 +1128,8 @@
     }
   }
 
-  if (error_collector->FoundErrors()) {
+  if (error_collector->FoundErrors() ||
+      (fatal_warnings_ && error_collector->FoundWarnings())) {
     return 1;
   }
 
@@ -1102,19 +1216,6 @@
 
 }  // namespace
 
-bool CommandLineInterface::AllowProto3Optional(
-    const FileDescriptor& file) const {
-  if (allow_proto3_optional_) return true;
-  // Whitelist all ads protos. Ads is an early adopter of this feature.
-  if (file.name().find("google/ads/googleads") != std::string::npos) {
-    return true;
-  }
-  if (file.name() == "google/protobuf/unittest_proto3_optional.proto" ||
-      file.name() == "google/protobuf/internal/test_proto3_optional.proto") {
-    return true;
-  }
-  return false;
-}
 
 bool CommandLineInterface::VerifyInputFilesInDescriptors(
     DescriptorDatabase* database) {
@@ -1134,6 +1235,7 @@
                 << std::endl;
       return false;
     }
+
   }
   return true;
 }
@@ -1184,6 +1286,7 @@
       break;
     }
 
+
     // Enforce --direct_dependencies
     if (direct_dependencies_explicitly_set_) {
       bool indirect_imports = false;
@@ -1229,7 +1332,7 @@
   source_info_in_descriptor_set_ = false;
   disallow_services_ = false;
   direct_dependencies_explicitly_set_ = false;
-  allow_proto3_optional_ = false;
+  deterministic_output_ = false;
 }
 
 bool CommandLineInterface::MakeProtoProtoPathRelative(
@@ -1269,13 +1372,17 @@
                    "comes first."
                 << std::endl;
       return false;
-    case DiskSourceTree::CANNOT_OPEN:
+    case DiskSourceTree::CANNOT_OPEN: {
       if (in_fallback_database) {
         return true;
       }
+      std::string error_str = source_tree->GetLastErrorMessage().empty()
+                                  ? strerror(errno)
+                                  : source_tree->GetLastErrorMessage();
       std::cerr << "Could not map to virtual file: " << *proto << ": "
-                << strerror(errno) << std::endl;
+                << error_str << std::endl;
       return false;
+    }
     case DiskSourceTree::NO_MAPPING: {
       // Try to interpret the path as a virtual path.
       std::string disk_file;
@@ -1418,13 +1525,36 @@
     proto_path_.push_back(std::pair<std::string, std::string>("", "."));
   }
 
-  // Check some error cases.
-  bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
-  if (decoding_raw && !input_files_.empty()) {
-    std::cerr << "When using --decode_raw, no input files should be given."
+  // Check error cases that span multiple flag values.
+  bool missing_proto_definitions = false;
+  switch (mode_) {
+    case MODE_COMPILE:
+      missing_proto_definitions = input_files_.empty();
+      break;
+    case MODE_DECODE:
+      // Handle --decode_raw separately, since it requires that no proto
+      // definitions are specified.
+      if (codec_type_.empty()) {
+        if (!input_files_.empty() || !descriptor_set_in_names_.empty()) {
+          std::cerr
+              << "When using --decode_raw, no input files should be given."
               << std::endl;
-    return PARSE_ARGUMENT_FAIL;
-  } else if (!decoding_raw && input_files_.empty()) {
+          return PARSE_ARGUMENT_FAIL;
+        }
+        missing_proto_definitions = false;
+        break;  // only for --decode_raw
+      }
+      // --decode (not raw) is handled the same way as the rest of the modes.
+      PROTOBUF_FALLTHROUGH_INTENDED;
+    case MODE_ENCODE:
+    case MODE_PRINT:
+      missing_proto_definitions =
+          input_files_.empty() && descriptor_set_in_names_.empty();
+      break;
+    default:
+      GOOGLE_LOG(FATAL) << "Unexpected mode: " << mode_;
+  }
+  if (missing_proto_definitions) {
     std::cerr << "Missing input file." << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
@@ -1438,6 +1568,11 @@
               << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
+  if (mode_ != MODE_ENCODE && deterministic_output_) {
+    std::cerr << "Can only use --deterministic_output with --encode."
+              << std::endl;
+    return PARSE_ARGUMENT_FAIL;
+  }
   if (!dependency_out_name_.empty() && input_files_.size() > 1) {
     std::cerr
         << "Can only process one input file when using --dependency_out=FILE."
@@ -1506,7 +1641,8 @@
       *name == "--include_imports" || *name == "--include_source_info" ||
       *name == "--version" || *name == "--decode_raw" ||
       *name == "--print_free_field_numbers" ||
-      *name == "--experimental_allow_proto3_optional") {
+      *name == "--experimental_allow_proto3_optional" ||
+      *name == "--deterministic_output" || *name == "--fatal_warnings") {
     // HACK:  These are the only flags that don't take a value.
     //   They probably should not be hard-coded like this but for now it's
     //   not worth doing better.
@@ -1707,15 +1843,15 @@
       std::cout << version_info_ << std::endl;
     }
     std::cout << "libprotoc " << internal::VersionString(PROTOBUF_VERSION)
-              << std::endl;
+              << PROTOBUF_VERSION_SUFFIX << std::endl;
     return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
 
   } else if (name == "--disallow_services") {
     disallow_services_ = true;
 
-  } else if (name == "--experimental_allow_proto3_optional") {
-    allow_proto3_optional_ = true;
 
+  } else if (name == "--experimental_allow_proto3_optional") {
+    // Flag is no longer observed, but we allow it for backward compat.
   } else if (name == "--encode" || name == "--decode" ||
              name == "--decode_raw") {
     if (mode_ != MODE_COMPILE) {
@@ -1746,6 +1882,9 @@
 
     codec_type_ = value;
 
+  } else if (name == "--deterministic_output") {
+    deterministic_output_ = true;
+
   } else if (name == "--error_format") {
     if (value == "gcc") {
       error_format_ = ERROR_FORMAT_GCC;
@@ -1756,6 +1895,12 @@
       return PARSE_ARGUMENT_FAIL;
     }
 
+  } else if (name == "--fatal_warnings") {
+    if (fatal_warnings_) {
+      std::cerr << name << " may only be passed once." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    fatal_warnings_ = true;
   } else if (name == "--plugin") {
     if (plugin_prefix_.empty()) {
       std::cerr << "This compiler does not support plugins." << std::endl;
@@ -1860,124 +2005,80 @@
 
 void CommandLineInterface::PrintHelpText() {
   // Sorry for indentation here; line wrapping would be uglier.
-  std::cout
-      <<
-      "Usage: " << executable_name_
-      << " [OPTION] PROTO_FILES\n"
-         "Parse PROTO_FILES and generate output based on the options given:\n"
-         "  -IPATH, --proto_path=PATH   Specify the directory in which to "
-         "search for\n"
-         "                              imports.  May be specified multiple "
-         "times;\n"
-         "                              directories will be searched in order. "
-         " If not\n"
-         "                              given, the current working directory "
-         "is used.\n"
-         "                              If not found in any of the these "
-         "directories,\n"
-         "                              the --descriptor_set_in descriptors "
-         "will be\n"
-         "                              checked for required proto file.\n"
-         "  --version                   Show version info and exit.\n"
-         "  -h, --help                  Show this text and exit.\n"
-         "  --encode=MESSAGE_TYPE       Read a text-format message of the "
-         "given type\n"
-         "                              from standard input and write it in "
-         "binary\n"
-         "                              to standard output.  The message type "
-         "must\n"
-         "                              be defined in PROTO_FILES or their "
-         "imports.\n"
-         "  --decode=MESSAGE_TYPE       Read a binary message of the given "
-         "type from\n"
-         "                              standard input and write it in text "
-         "format\n"
-         "                              to standard output.  The message type "
-         "must\n"
-         "                              be defined in PROTO_FILES or their "
-         "imports.\n"
-         "  --decode_raw                Read an arbitrary protocol message "
-         "from\n"
-         "                              standard input and write the raw "
-         "tag/value\n"
-         "                              pairs in text format to standard "
-         "output.  No\n"
-         "                              PROTO_FILES should be given when using "
-         "this\n"
-         "                              flag.\n"
-         "  --descriptor_set_in=FILES   Specifies a delimited list of FILES\n"
-         "                              each containing a FileDescriptorSet "
-         "(a\n"
-         "                              protocol buffer defined in "
-         "descriptor.proto).\n"
-         "                              The FileDescriptor for each of the "
-         "PROTO_FILES\n"
-         "                              provided will be loaded from these\n"
-         "                              FileDescriptorSets. If a "
-         "FileDescriptor\n"
-         "                              appears multiple times, the first "
-         "occurrence\n"
-         "                              will be used.\n"
-         "  -oFILE,                     Writes a FileDescriptorSet (a protocol "
-         "buffer,\n"
-         "    --descriptor_set_out=FILE defined in descriptor.proto) "
-         "containing all of\n"
-         "                              the input files to FILE.\n"
-         "  --include_imports           When using --descriptor_set_out, also "
-         "include\n"
-         "                              all dependencies of the input files in "
-         "the\n"
-         "                              set, so that the set is "
-         "self-contained.\n"
-         "  --include_source_info       When using --descriptor_set_out, do "
-         "not strip\n"
-         "                              SourceCodeInfo from the "
-         "FileDescriptorProto.\n"
-         "                              This results in vastly larger "
-         "descriptors that\n"
-         "                              include information about the "
-         "original\n"
-         "                              location of each decl in the source "
-         "file as\n"
-         "                              well as surrounding comments.\n"
-         "  --dependency_out=FILE       Write a dependency output file in the "
-         "format\n"
-         "                              expected by make. This writes the "
-         "transitive\n"
-         "                              set of input file paths to FILE\n"
-         "  --error_format=FORMAT       Set the format in which to print "
-         "errors.\n"
-         "                              FORMAT may be 'gcc' (the default) or "
-         "'msvs'\n"
-         "                              (Microsoft Visual Studio format).\n"
-         "  --print_free_field_numbers  Print the free field numbers of the "
-         "messages\n"
-         "                              defined in the given proto files. "
-         "Groups share\n"
-         "                              the same field number space with the "
-         "parent \n"
-         "                              message. Extension ranges are counted "
-         "as \n"
-         "                              occupied fields numbers.\n"
-      << std::endl;
+  std::cout << "Usage: " << executable_name_ << " [OPTION] PROTO_FILES";
+  std::cout << R"(
+Parse PROTO_FILES and generate output based on the options given:
+  -IPATH, --proto_path=PATH   Specify the directory in which to search for
+                              imports.  May be specified multiple times;
+                              directories will be searched in order.  If not
+                              given, the current working directory is used.
+                              If not found in any of the these directories,
+                              the --descriptor_set_in descriptors will be
+                              checked for required proto file.
+  --version                   Show version info and exit.
+  -h, --help                  Show this text and exit.
+  --encode=MESSAGE_TYPE       Read a text-format message of the given type
+                              from standard input and write it in binary
+                              to standard output.  The message type must
+                              be defined in PROTO_FILES or their imports.
+  --deterministic_output      When using --encode, ensure map fields are
+                              deterministically ordered. Note that this order
+                              is not canonical, and changes across builds or
+                              releases of protoc.
+  --decode=MESSAGE_TYPE       Read a binary message of the given type from
+                              standard input and write it in text format
+                              to standard output.  The message type must
+                              be defined in PROTO_FILES or their imports.
+  --decode_raw                Read an arbitrary protocol message from
+                              standard input and write the raw tag/value
+                              pairs in text format to standard output.  No
+                              PROTO_FILES should be given when using this
+                              flag.
+  --descriptor_set_in=FILES   Specifies a delimited list of FILES
+                              each containing a FileDescriptorSet (a
+                              protocol buffer defined in descriptor.proto).
+                              The FileDescriptor for each of the PROTO_FILES
+                              provided will be loaded from these
+                              FileDescriptorSets. If a FileDescriptor
+                              appears multiple times, the first occurrence
+                              will be used.
+  -oFILE,                     Writes a FileDescriptorSet (a protocol buffer,
+    --descriptor_set_out=FILE defined in descriptor.proto) containing all of
+                              the input files to FILE.
+  --include_imports           When using --descriptor_set_out, also include
+                              all dependencies of the input files in the
+                              set, so that the set is self-contained.
+  --include_source_info       When using --descriptor_set_out, do not strip
+                              SourceCodeInfo from the FileDescriptorProto.
+                              This results in vastly larger descriptors that
+                              include information about the original
+                              location of each decl in the source file as
+                              well as surrounding comments.
+  --dependency_out=FILE       Write a dependency output file in the format
+                              expected by make. This writes the transitive
+                              set of input file paths to FILE
+  --error_format=FORMAT       Set the format in which to print errors.
+                              FORMAT may be 'gcc' (the default) or 'msvs'
+                              (Microsoft Visual Studio format).
+  --fatal_warnings            Make warnings be fatal (similar to -Werr in
+                              gcc). This flag will make protoc return
+                              with a non-zero exit code if any warnings
+                              are generated.
+  --print_free_field_numbers  Print the free field numbers of the messages
+                              defined in the given proto files. Groups share
+                              the same field number space with the parent
+                              message. Extension ranges are counted as
+                              occupied fields numbers.)";
   if (!plugin_prefix_.empty()) {
-    std::cout
-        << "  --plugin=EXECUTABLE         Specifies a plugin executable to "
-           "use.\n"
-           "                              Normally, protoc searches the PATH "
-           "for\n"
-           "                              plugins, but you may specify "
-           "additional\n"
-           "                              executables not in the path using "
-           "this flag.\n"
-           "                              Additionally, EXECUTABLE may be of "
-           "the form\n"
-           "                              NAME=PATH, in which case the given "
-           "plugin name\n"
-           "                              is mapped to the given executable "
-           "even if\n"
-           "                              the executable's own name differs."
-        << std::endl;
+    std::cout << R"(
+  --plugin=EXECUTABLE         Specifies a plugin executable to use.
+                              Normally, protoc searches the PATH for
+                              plugins, but you may specify additional
+                              executables not in the path using this flag.
+                              Additionally, EXECUTABLE may be of the form
+                              NAME=PATH, in which case the given plugin name
+                              is mapped to the given executable even if
+                              the executable's own name differs.)";
   }
 
   for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
@@ -1985,39 +2086,30 @@
     // FIXME(kenton):  If the text is long enough it will wrap, which is ugly,
     //   but fixing this nicely (e.g. splitting on spaces) is probably more
     //   trouble than it's worth.
-    std::cout << "  " << iter->first << "=OUT_DIR "
+    std::cout << std::endl
+              << "  " << iter->first << "=OUT_DIR "
               << std::string(19 - iter->first.size(),
                              ' ')  // Spaces for alignment.
-              << iter->second.help_text << std::endl;
+              << iter->second.help_text;
   }
-  std::cout << "  @<filename>                 Read options and filenames from "
-               "file. If a\n"
-               "                              relative file path is specified, "
-               "the file\n"
-               "                              will be searched in the working "
-               "directory.\n"
-               "                              The --proto_path option will not "
-               "affect how\n"
-               "                              this argument file is searched. "
-               "Content of\n"
-               "                              the file will be expanded in the "
-               "position of\n"
-               "                              @<filename> as in the argument "
-               "list. Note\n"
-               "                              that shell expansion is not "
-               "applied to the\n"
-               "                              content of the file (i.e., you "
-               "cannot use\n"
-               "                              quotes, wildcards, escapes, "
-               "commands, etc.).\n"
-               "                              Each line corresponds to a "
-               "single argument,\n"
-               "                              even if it contains spaces."
-            << std::endl;
+  std::cout << R"(
+  @<filename>                 Read options and filenames from file. If a
+                              relative file path is specified, the file
+                              will be searched in the working directory.
+                              The --proto_path option will not affect how
+                              this argument file is searched. Content of
+                              the file will be expanded in the position of
+                              @<filename> as in the argument list. Note
+                              that shell expansion is not applied to the
+                              content of the file (i.e., you cannot use
+                              quotes, wildcards, escapes, commands, etc.).
+                              Each line corresponds to a single argument,
+                              even if it contains spaces.)";
+  std::cout << std::endl;
 }
 
 bool CommandLineInterface::EnforceProto3OptionalSupport(
-    const std::string& codegen_name, uint64 supported_features,
+    const std::string& codegen_name, uint64_t supported_features,
     const std::vector<const FileDescriptor*>& parsed_files) const {
   bool supports_proto3_optional =
       supported_features & CodeGenerator::FEATURE_PROTO3_OPTIONAL;
@@ -2215,8 +2307,10 @@
       // We reset current_output to NULL first so that the old file is closed
       // before the new one is opened.
       current_output.reset();
-      current_output.reset(generator_context->OpenForInsert(
-          filename, output_file.insertion_point()));
+      current_output.reset(
+          generator_context->OpenForInsertWithGeneratedCodeInfo(
+              filename, output_file.insertion_point(),
+              output_file.generated_code_info()));
     } else if (!output_file.name().empty()) {
       // Starting a new file.  Open it.
       // We reset current_output to NULL first so that the old file is closed
@@ -2298,7 +2392,9 @@
 
   if (mode_ == MODE_ENCODE) {
     // Output is binary.
-    if (!message->SerializePartialToZeroCopyStream(&out)) {
+    io::CodedOutputStream coded_out(&out);
+    coded_out.SetSerializationDeterministic(deterministic_output_);
+    if (!message->SerializePartialToCodedStream(&coded_out)) {
       std::cerr << "output: I/O error." << std::endl;
       return false;
     }
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 3c95cd6..27178b1 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -38,6 +38,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
 #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <set>
@@ -104,7 +105,7 @@
 //   2. protoc --proto_path=src foo.proto (virtual path relative to src)
 //
 // If a file path can be interpreted both as a physical file path and as a
-// relative virtual path, the physical file path takes precendence.
+// relative virtual path, the physical file path takes precedence.
 //
 // For a full description of the command-line syntax, invoke it with --help.
 class PROTOC_EXPORT CommandLineInterface {
@@ -226,15 +227,10 @@
   bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree,
                                      DescriptorDatabase* fallback_database);
 
-  // Is this .proto file whitelisted, or do we have a command-line flag allowing
-  // us to use proto3 optional? This is a temporary control to avoid people from
-  // using proto3 optional until code generators have implemented it.
-  bool AllowProto3Optional(const FileDescriptor& file) const;
-
   // Fails if these files use proto3 optional and the code generator doesn't
   // support it. This is a permanent check.
   bool EnforceProto3OptionalSupport(
-      const std::string& codegen_name, uint64 supported_features,
+      const std::string& codegen_name, uint64_t supported_features,
       const std::vector<const FileDescriptor*>& parsed_files) const;
 
 
@@ -397,6 +393,9 @@
 
   ErrorFormat error_format_ = ERROR_FORMAT_GCC;
 
+  // True if we should treat warnings as errors that fail the compilation.
+  bool fatal_warnings_ = false;
+
   std::vector<std::pair<std::string, std::string> >
       proto_path_;                        // Search path for proto files.
   std::vector<std::string> input_files_;  // Names of the input proto files.
@@ -448,8 +447,8 @@
   // Was the --disallow_services flag used?
   bool disallow_services_ = false;
 
-  // Was the --experimental_allow_proto3_optional flag used?
-  bool allow_proto3_optional_ = false;
+  // When using --encode, this will be passed to SetSerializationDeterministic.
+  bool deterministic_output_ = false;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
 };
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index a51ad92..9cc8cf9 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -36,16 +36,20 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <cstdint>
+
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <memory>
+#include <string>
 #include <vector>
 
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/file.h>
+#include <google/protobuf/any.pb.h>
 #include <google/protobuf/compiler/mock_code_generator.h>
 #include <google/protobuf/compiler/subprocess.h>
 #include <google/protobuf/compiler/code_generator.h>
@@ -59,10 +63,10 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/io/io_win32.h>
 
-#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -122,7 +126,7 @@
   void SwitchToTempDirectory() {
     File::ChangeWorkingDirectory(temp_directory_);
   }
-#else   // !PROTOBUF_OPENSOURCE
+#else  // !PROTOBUF_OPENSOURCE
   // TODO(teboring): Figure out how to change and get working directory in
   // google3.
 #endif  // !PROTOBUF_OPENSOURCE
@@ -155,6 +159,11 @@
   void ExpectCapturedStdoutSubstringWithZeroReturnCode(
       const std::string& expected_substring);
 
+  // Checks that Run() returned zero and the stderr contains the given
+  // substring.
+  void ExpectCapturedStderrSubstringWithZeroReturnCode(
+      const std::string& expected_substring);
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
   // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
   // does not fail otherwise.
@@ -209,7 +218,7 @@
   // code generator that omits the given feature(s).
   void CreateGeneratorWithMissingFeatures(const std::string& name,
                                           const std::string& description,
-                                          uint64 features) {
+                                          uint64_t features) {
     MockCodeGenerator* generator = new MockCodeGenerator(name);
     generator->SuppressFeatures(features);
     mock_generators_to_delete_.push_back(generator);
@@ -424,8 +433,8 @@
 
 void CommandLineInterfaceTest::ExpectWarningSubstring(
     const std::string& expected_substring) {
-  EXPECT_EQ(0, return_code_);
   EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+  EXPECT_EQ(0, return_code_);
 }
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -513,6 +522,12 @@
                       captured_stdout_);
 }
 
+void CommandLineInterfaceTest::ExpectCapturedStderrSubstringWithZeroReturnCode(
+    const std::string& expected_substring) {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
 void CommandLineInterfaceTest::ExpectFileContent(const std::string& filename,
                                                  const std::string& content) {
   std::string path = temp_directory_ + "/" + filename;
@@ -680,6 +695,9 @@
       FileDescriptorProto::descriptor()->file();
   descriptor_file->CopyTo(file_descriptor_set.add_file());
 
+  FileDescriptorProto& any_proto = *file_descriptor_set.add_file();
+  google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
+
   const FileDescriptor* custom_file =
       protobuf_unittest::AggregateMessage::descriptor()->file();
   FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
@@ -1192,8 +1210,8 @@
   Run("protocol_compiler "
       "--test_out=TestParameter:$tmpdir "
       "--plug_out=TestPluginParameter:$tmpdir "
-      "--test_out=insert=test_generator,test_plugin:$tmpdir "
-      "--plug_out=insert=test_generator,test_plugin:$tmpdir "
+      "--test_out=insert_endlines=test_generator,test_plugin:$tmpdir "
+      "--plug_out=insert_endlines=test_generator,test_plugin:$tmpdir "
       "--proto_path=$tmpdir foo.proto");
 
   ExpectNoErrors();
@@ -1387,6 +1405,7 @@
   ExpectGenerated("test_generator", "", "foo.proto", "Foo");
 }
 
+
 TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) {
   CreateTempFile("foo.proto",
                  "syntax = \"proto2\";\n"
@@ -2297,7 +2316,7 @@
 }
 
 TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
-  // Test --error_format=msvs
+  // Test invalid --error_format
 
   CreateTempFile("foo.proto",
                  "syntax = \"proto2\";\n"
@@ -2309,6 +2328,24 @@
   ExpectErrorText("Unknown error format: invalid\n");
 }
 
+TEST_F(CommandLineInterfaceTest, Warnings) {
+  // Test --fatal_warnings.
+
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n");
+  CreateTempFile("bar.proto", "syntax = \"proto2\";\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+  ExpectCapturedStderrSubstringWithZeroReturnCode(
+      "foo.proto:2:1: warning: Import bar.proto is unused.");
+
+  Run("protocol_compiler --test_out=$tmpdir --fatal_warnings "
+      "--proto_path=$tmpdir foo.proto");
+  ExpectErrorSubstring("foo.proto:2:1: warning: Import bar.proto is unused.");
+}
+
 // -------------------------------------------------------------------
 // Flag parsing tests
 
@@ -2372,49 +2409,8 @@
   ExpectErrorText("Missing value for flag: --test_out\n");
 }
 
-TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowed) {
-  CreateTempFile("foo.proto",
-                 "syntax = \"proto3\";\n"
-                 "message Foo {\n"
-                 "  optional int32 i = 1;\n"
-                 "}\n");
-
-  Run("protocol_compiler --proto_path=$tmpdir foo.proto -odescriptor.pb");
-
-  ExpectErrorSubstring("--experimental_allow_proto3_optional was not set");
-}
-
-TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedDescriptor) {
-  CreateTempFile("foo.proto",
-                 "syntax = \"proto3\";\n"
-                 "message Foo {\n"
-                 "  optional int32 i = 1;\n"
-                 "}\n");
-
-  Run("protocol_compiler --experimental_allow_proto3_optional "
-      "--proto_path=$tmpdir foo.proto "
-      " -o$tmpdir/descriptor.pb");
-  ExpectNoErrors();
-
-  Run("protocol_compiler --descriptor_set_in=$tmpdir/descriptor.pb foo.proto "
-      "--test_out=$tmpdir");
-  ExpectErrorSubstring("--experimental_allow_proto3_optional was not set");
-}
-
-TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedGenCode) {
-  CreateTempFile("foo.proto",
-                 "syntax = \"proto3\";\n"
-                 "message Foo {\n"
-                 "  optional int32 i = 1;\n"
-                 "}\n");
-
-  Run("protocol_compiler --proto_path=$tmpdir foo.proto --test_out=$tmpdir");
-
-  ExpectErrorSubstring("--experimental_allow_proto3_optional was not set");
-}
-
 TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedNoCodegenSupport) {
-  CreateTempFile("foo.proto",
+  CreateTempFile("google/foo.proto",
                  "syntax = \"proto3\";\n"
                  "message Foo {\n"
                  "  optional int32 i = 1;\n"
@@ -2425,7 +2421,7 @@
                                      CodeGenerator::FEATURE_PROTO3_OPTIONAL);
 
   Run("protocol_compiler --experimental_allow_proto3_optional "
-      "--proto_path=$tmpdir foo.proto --no_proto3_optional_out=$tmpdir");
+      "--proto_path=$tmpdir google/foo.proto --no_proto3_optional_out=$tmpdir");
 
   ExpectErrorSubstring(
       "code generator --no_proto3_optional_out hasn't been updated to support "
@@ -2433,14 +2429,14 @@
 }
 
 TEST_F(CommandLineInterfaceTest, Proto3OptionalAllowWithFlag) {
-  CreateTempFile("foo.proto",
+  CreateTempFile("google/foo.proto",
                  "syntax = \"proto3\";\n"
                  "message Foo {\n"
                  "  optional int32 i = 1;\n"
                  "}\n");
 
   Run("protocol_compiler --experimental_allow_proto3_optional "
-      "--proto_path=$tmpdir foo.proto --test_out=$tmpdir");
+      "--proto_path=$tmpdir google/foo.proto --test_out=$tmpdir");
   ExpectNoErrors();
 }
 
@@ -2562,20 +2558,25 @@
   enum Type { TEXT, BINARY };
   enum ReturnCode { SUCCESS, ERROR };
 
-  bool Run(const std::string& command) {
+  bool Run(const std::string& command, bool specify_proto_files = true) {
     std::vector<std::string> args;
     args.push_back("protoc");
-    SplitStringUsing(command, " ", &args);
-    switch (GetParam()) {
-      case PROTO_PATH:
-        args.push_back("--proto_path=" + TestUtil::TestSourceDir());
-        break;
-      case DESCRIPTOR_SET_IN:
-        args.push_back(StrCat("--descriptor_set_in=",
-                                    unittest_proto_descriptor_set_filename_));
-        break;
-      default:
-        ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam();
+    for (StringPiece split_piece :
+         Split(command, " ", true)) {
+      args.push_back(std::string(split_piece));
+    }
+    if (specify_proto_files) {
+      switch (GetParam()) {
+        case PROTO_PATH:
+          args.push_back("--proto_path=" + TestUtil::TestSourceDir());
+          break;
+        case DESCRIPTOR_SET_IN:
+          args.push_back(StrCat("--descriptor_set_in=",
+                                      unittest_proto_descriptor_set_filename_));
+          break;
+        default:
+          ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam();
+      }
     }
 
     std::unique_ptr<const char*[]> argv(new const char*[args.size()]);
@@ -2657,9 +2658,12 @@
   RedirectStdinFromFile(TestUtil::GetTestDataPath(
       "net/proto2/internal/"
       "testdata/text_format_unittest_data_oneof_implemented.txt"));
-  EXPECT_TRUE(
-      Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
-          " --encode=protobuf_unittest.TestAllTypes"));
+  std::string args;
+  if (GetParam() != DESCRIPTOR_SET_IN) {
+    args.append(
+        TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto"));
+  }
+  EXPECT_TRUE(Run(args + " --encode=protobuf_unittest.TestAllTypes"));
   ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath(
       "net/proto2/internal/testdata/golden_message_oneof_implemented"));
   ExpectStderrMatchesText("");
@@ -2695,7 +2699,7 @@
   message.SerializeToString(&data);
 
   RedirectStdinFromText(data);
-  EXPECT_TRUE(Run("--decode_raw"));
+  EXPECT_TRUE(Run("--decode_raw", /*specify_proto_files=*/false));
   ExpectStdoutMatchesText(
       "1: 123\n"
       "14: \"foo\"\n");
@@ -2719,6 +2723,32 @@
       "net/proto2/internal/no_such_file.proto: No such file or directory\n");
 }
 
+TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) {
+  RedirectStdinFromFile(TestUtil::GetTestDataPath(
+      "net/proto2/internal/"
+      "testdata/text_format_unittest_data_oneof_implemented.txt"));
+  std::string args;
+  if (GetParam() != DESCRIPTOR_SET_IN) {
+    args.append(
+        TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto"));
+  }
+  EXPECT_TRUE(Run(
+      args + " --encode=protobuf_unittest.TestAllTypes --deterministic_output"));
+  ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath(
+      "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+  ExpectStderrMatchesText("");
+}
+
+TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) {
+  RedirectStdinFromFile(TestUtil::GetTestDataPath(
+      "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+  EXPECT_FALSE(
+      Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+          " --decode=protobuf_unittest.TestAllTypes --deterministic_output"));
+  ExpectStderrMatchesText(
+      "Can only use --deterministic_output with --encode.\n");
+}
+
 INSTANTIATE_TEST_SUITE_P(FileDescriptorSetSource, EncodeDecodeTest,
                          testing::Values(PROTO_PATH, DESCRIPTOR_SET_IN));
 }  // anonymous namespace
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 31fe5a6..60619f1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -137,14 +137,10 @@
   // of the data to compare to.
   std::map<std::string, std::string> vpath_map;
   std::map<std::string, std::string> rpath_map;
-  rpath_map
-      ["third_party/protobuf_legacy_opensource/src/google/protobuf/"
-       "test_messages_proto2"] =
-          "net/proto2/z_generated_example/test_messages_proto2";
-  rpath_map
-      ["third_party/protobuf_legacy_opensource/src/google/protobuf/"
-       "test_messages_proto3"] =
-          "net/proto2/z_generated_example/test_messages_proto3";
+  rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto2"] =
+      "net/proto2/z_generated_example/test_messages_proto2";
+  rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto3"] =
+      "net/proto2/z_generated_example/test_messages_proto3";
   rpath_map["net/proto2/internal/proto2_weak"] =
       "net/proto2/z_generated_example/proto2_weak";
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index c0a03ad..c9b9c20 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -32,10 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/cpp/cpp_enum.h>
+
+#include <cstdint>
+#include <limits>
 #include <map>
 
-#include <google/protobuf/compiler/cpp/cpp_enum.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_names.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -49,13 +53,13 @@
 // is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
 // generation of the GOOGLE_ARRAYSIZE constant.
 bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
-  int32 max_value = descriptor->value(0)->number();
+  int32_t max_value = descriptor->value(0)->number();
   for (int i = 0; i < descriptor->value_count(); i++) {
     if (descriptor->value(i)->number() > max_value) {
       max_value = descriptor->value(i)->number();
     }
   }
-  return max_value != kint32max;
+  return max_value != std::numeric_limits<int32_t>::max();
 }
 
 // Returns the number of unique numeric enum values. This is less than
@@ -180,14 +184,17 @@
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
     format(
         "inline bool $classname$_Parse(\n"
-        "    const std::string& name, $classname$* value) {\n"
+        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+        "value) "
+        "{\n"
         "  return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
         "    $classname$_descriptor(), name, value);\n"
         "}\n");
   } else {
     format(
         "bool $classname$_Parse(\n"
-        "    const std::string& name, $classname$* value);\n");
+        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+        "value);\n");
   }
 }
 
@@ -253,7 +260,8 @@
       "  return $classname$_Name(enum_t_value);\n"
       "}\n");
   format(
-      "static inline bool $nested_name$_Parse(const std::string& name,\n"
+      "static inline bool "
+      "$nested_name$_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n"
       "    $resolved_name$* value) {\n"
       "  return $classname$_Parse(name, value);\n"
       "}\n");
@@ -383,7 +391,9 @@
         CountUniqueValues(descriptor_));
     format(
         "bool $classname$_Parse(\n"
-        "    const std::string& name, $classname$* value) {\n"
+        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+        "value) "
+        "{\n"
         "  int int_value;\n"
         "  bool success = ::$proto_ns$::internal::LookUpEnumValue(\n"
         "      $classname$_entries, $1$, name, &int_value);\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 7602e9f..cdcd9a6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -93,7 +93,7 @@
       "  return static_cast< $type$ >($name$_);\n"
       "}\n"
       "inline $type$ $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
@@ -106,8 +106,8 @@
       "  $name$_ = value;\n"
       "}\n"
       "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$"
       "  _internal_set_$name$(value);\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n");
 }
@@ -156,6 +156,12 @@
       "));\n");
 }
 
+void EnumFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_($default$)\n");
+}
+
 // ===================================================================
 
 EnumOneofFieldGenerator::EnumOneofFieldGenerator(
@@ -177,7 +183,7 @@
       "  return static_cast< $type$ >($default$);\n"
       "}\n"
       "inline $type$ $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
@@ -193,9 +199,9 @@
       "  $field_member$ = value;\n"
       "}\n"
       "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "  _internal_set_$name$(value);\n"
+      "$annotate_set$"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n");
 }
 
@@ -262,17 +268,17 @@
       "  return static_cast< $type$ >($name$_.Get(index));\n"
       "}\n"
       "inline $type$ $classname$::$name$(int index) const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$(index);\n"
       "}\n"
-      "inline void $classname$::set_$name$(int index, $type$ value) {\n"
-      "$annotate_accessor$");
+      "inline void $classname$::set_$name$(int index, $type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
       "  $name$_.Set(index, value);\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline void $classname$::_internal_add_$name$($type$ value) {\n");
@@ -283,13 +289,13 @@
       "  $name$_.Add(value);\n"
       "}\n"
       "inline void $classname$::add_$name$($type$ value) {\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_add:$full_name$)\n"
       "  _internal_add_$name$(value);\n"
+      "$annotate_add$"
+      "  // @@protoc_insertion_point(field_add:$full_name$)\n"
       "}\n"
       "inline const ::$proto_ns$::RepeatedField<int>&\n"
       "$classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_list$"
       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
       "  return $name$_;\n"
       "}\n"
@@ -299,7 +305,7 @@
       "}\n"
       "inline ::$proto_ns$::RepeatedField<int>*\n"
       "$classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "$annotate_mutable_list$"
       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
       "  return _internal_mutable_$name$();\n"
       "}\n");
@@ -484,6 +490,16 @@
   format("}\n");
 }
 
+void RepeatedEnumFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    format("\n, _$name$_cached_byte_size_(0)");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 3b97608..793ab2d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -50,16 +50,18 @@
   ~EnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override;
+  void GenerateSerializeWithCachedSizesToArray(
+      io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
@@ -72,10 +74,10 @@
   ~EnumOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
@@ -88,18 +90,20 @@
   ~RepeatedEnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const {}
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override {}
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GenerateSerializeWithCachedSizesToArray(
+      io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 06da3f3..3792db8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -99,8 +99,7 @@
   std::string scope =
       IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : "";
   variables_["scope"] = scope;
-  std::string scoped_name = scope + ResolveKeyword(name);
-  variables_["scoped_name"] = scoped_name;
+  variables_["scoped_name"] = ExtensionName(descriptor_);
   variables_["number"] = StrCat(descriptor_->number());
 }
 
@@ -175,6 +174,7 @@
   }
 
   format(
+      "PROTOBUF_ATTRIBUTE_INIT_PRIORITY "
       "::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n"
       "    ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n"
       "  $scoped_name$($constant_name$, $1$);\n",
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index f95e14e..82247ff 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -33,11 +33,16 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+
+#include <cstdint>
 #include <memory>
+#include <string>
 
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
@@ -46,7 +51,6 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -55,6 +59,209 @@
 
 using internal::WireFormat;
 
+namespace {
+
+std::string GenerateAnnotation(StringPiece substitute_template_prefix,
+                               StringPiece prepared_template,
+                               StringPiece substitute_template_suffix,
+                               int field_index, StringPiece lambda_args,
+                               StringPiece access_type) {
+  return strings::Substitute(
+      StrCat(substitute_template_prefix, prepared_template,
+                   substitute_template_suffix),
+      field_index, access_type, lambda_args);
+}
+
+std::string GenerateTemplateForOneofString(const FieldDescriptor* descriptor,
+                                           StringPiece proto_ns,
+                                           StringPiece field_member) {
+  std::string field_pointer =
+      descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
+          ? "$0.GetPointer()"
+          : "$0";
+
+  if (descriptor->default_value_string().empty()) {
+    return strings::Substitute(
+        StrCat("_internal_has_",
+                     google::protobuf::compiler::cpp::FieldName(descriptor),
+                     "()? _listener_->ExtractFieldInfo(", field_pointer,
+                     "): ::", proto_ns, "::FieldAccessListener::AddressInfo()"),
+        field_member);
+  }
+
+  if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING_PIECE) {
+    return StrCat("_listener_->ExtractFieldInfo(_internal_",
+                        google::protobuf::compiler::cpp::FieldName(descriptor), "())");
+  }
+
+  std::string default_value_pointer =
+      descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
+          ? "&$1.get()"
+          : "&$1";
+  return strings::Substitute(
+      StrCat("_listener_->ExtractFieldInfo(_internal_has_",
+                   google::protobuf::compiler::cpp::FieldName(descriptor), "()? ",
+                   field_pointer, " : ", default_value_pointer, ")"),
+      field_member, MakeDefaultName(descriptor));
+}
+
+std::string GenerateTemplateForSingleString(const FieldDescriptor* descriptor,
+                                            StringPiece field_member) {
+  if (descriptor->default_value_string().empty()) {
+    return strings::Substitute("_listener_->ExtractFieldInfo(&$0)", field_member);
+  }
+
+  if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING) {
+    return strings::Substitute(
+        "_listener_->ExtractFieldInfo($0.IsDefault("
+        "nullptr) ? &$1.get() : $0.GetPointer())",
+        field_member, MakeDefaultName(descriptor));
+  }
+
+  return strings::Substitute("_listener_->ExtractFieldInfo(&$0)", field_member);
+}
+
+}  // namespace
+
+void AddAccessorAnnotations(const FieldDescriptor* descriptor,
+                            const Options& options,
+                            std::map<std::string, std::string>* variables) {
+  // Can be expanded to include more specific calls, for example, for arena or
+  // clear calls.
+  static constexpr const char* kAccessorsAnnotations[] = {
+      "annotate_add",     "annotate_get",         "annotate_has",
+      "annotate_list",    "annotate_mutable",     "annotate_mutable_list",
+      "annotate_release", "annotate_set",         "annotate_size",
+      "annotate_clear",   "annotate_add_mutable",
+  };
+  for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
+    (*variables)[kAccessorsAnnotations[i]] = "";
+  }
+  if (options.annotate_accessor) {
+    for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
+      (*variables)[kAccessorsAnnotations[i]] = StrCat(
+          "  ", FieldName(descriptor), "_AccessedNoStrip = true;\n");
+    }
+  }
+  if (!options.inject_field_listener_events) {
+    return;
+  }
+  if (descriptor->file()->options().optimize_for() ==
+      google::protobuf::FileOptions::LITE_RUNTIME) {
+    return;
+  }
+  std::string field_member = (*variables)["field_member"];
+  const google::protobuf::OneofDescriptor* oneof_member =
+      descriptor->real_containing_oneof();
+  if (oneof_member) {
+    field_member = StrCat(oneof_member->name(), "_.", field_member);
+  }
+  const std::string proto_ns = (*variables)["proto_ns"];
+  std::string lambda_args = "_listener_, this";
+  std::string lambda_flat_args = "_listener_, this";
+  const std::string substitute_template_prefix = StrCat(
+      "  {\n"
+      "    auto _listener_ = ::",
+      proto_ns,
+      "::FieldAccessListener::GetListener();\n"
+      "    if (_listener_) _listener_->OnFieldAccess([$2] { return ");
+  const std::string substitute_template_suffix = StrCat(
+      "; }, "
+      "GetDescriptor()->field($0), "
+      "::",
+      proto_ns,
+      "::FieldAccessListener::FieldAccessType::$1);\n"
+      "  }\n");
+  std::string prepared_template;
+
+  // Flat template is needed if the prepared one is introspecting the values
+  // inside the returned values, for example, for repeated fields and maps.
+  std::string prepared_flat_template;
+  std::string prepared_add_template;
+  // TODO(jianzhouzh): Fix all forward declared messages and deal with the
+  // weak fields.
+  if (descriptor->is_repeated() && !descriptor->is_map()) {
+    if (descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
+        descriptor->type() != FieldDescriptor::TYPE_GROUP) {
+      lambda_args = "_listener_, this, index";
+      prepared_template = strings::Substitute(
+          "_listener_->ExtractFieldInfo(&$0.Get(index))", field_member);
+      prepared_add_template = strings::Substitute(
+          "_listener_->ExtractFieldInfo(&$0.Get($0.size() - 1))", field_member);
+    } else {
+      prepared_template =
+          StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+      prepared_add_template =
+          StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+    }
+  } else if (descriptor->is_map()) {
+    prepared_template =
+        StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+  } else if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
+             !descriptor->options().lazy()) {
+    prepared_template =
+        StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+  } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+    if (oneof_member) {
+      prepared_template = GenerateTemplateForOneofString(
+          descriptor, (*variables)["proto_ns"], field_member);
+    } else {
+      prepared_template =
+          GenerateTemplateForSingleString(descriptor, field_member);
+    }
+  } else {
+    prepared_template =
+        strings::Substitute("_listener_->ExtractFieldInfo(&$0)", field_member);
+  }
+  if (descriptor->is_repeated() && !descriptor->is_map() &&
+      descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
+      descriptor->type() != FieldDescriptor::TYPE_GROUP) {
+    prepared_flat_template =
+        strings::Substitute("_listener_->ExtractFieldInfo(&$0)", field_member);
+  } else {
+    prepared_flat_template = prepared_template;
+  }
+  (*variables)["annotate_get"] = GenerateAnnotation(
+      substitute_template_prefix, prepared_template, substitute_template_suffix,
+      descriptor->index(), lambda_args, "kGet");
+  (*variables)["annotate_set"] = GenerateAnnotation(
+      substitute_template_prefix, prepared_template, substitute_template_suffix,
+      descriptor->index(), lambda_args, "kSet");
+  (*variables)["annotate_has"] = GenerateAnnotation(
+      substitute_template_prefix, prepared_template, substitute_template_suffix,
+      descriptor->index(), lambda_args, "kHas");
+  (*variables)["annotate_mutable"] = GenerateAnnotation(
+      substitute_template_prefix, prepared_template, substitute_template_suffix,
+      descriptor->index(), lambda_args, "kMutable");
+  (*variables)["annotate_release"] = GenerateAnnotation(
+      substitute_template_prefix, prepared_template, substitute_template_suffix,
+      descriptor->index(), lambda_args, "kRelease");
+  (*variables)["annotate_clear"] =
+      GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+                         substitute_template_suffix, descriptor->index(),
+                         lambda_flat_args, "kClear");
+  (*variables)["annotate_size"] =
+      GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+                         substitute_template_suffix, descriptor->index(),
+                         lambda_flat_args, "kSize");
+  (*variables)["annotate_list"] =
+      GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+                         substitute_template_suffix, descriptor->index(),
+                         lambda_flat_args, "kList");
+  (*variables)["annotate_mutable_list"] =
+      GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+                         substitute_template_suffix, descriptor->index(),
+                         lambda_flat_args, "kMutableList");
+  (*variables)["annotate_add"] =
+      GenerateAnnotation(substitute_template_prefix, prepared_add_template,
+                         substitute_template_suffix, descriptor->index(),
+                         lambda_flat_args, "kAdd");
+  (*variables)["annotate_add_mutable"] =
+      GenerateAnnotation(substitute_template_prefix, prepared_add_template,
+                         substitute_template_suffix, descriptor->index(),
+                         lambda_flat_args, "kAddMutable");
+}
+
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
                              std::map<std::string, std::string>* variables,
                              const Options& options) {
@@ -79,7 +286,8 @@
   } else {
     (*variables)["set_hasbit_io"] = "";
   }
-  (*variables)["annotate_accessor"] = "";
+
+  AddAccessorAnnotations(descriptor, options, variables);
 
   // These variables are placeholders to pick out the beginning and ends of
   // identifiers for annotations (when doing so with existing variables would
@@ -89,7 +297,7 @@
   (*variables)["}"] = "";
 }
 
-void FieldGenerator::SetHasBitIndex(int32 has_bit_index) {
+void FieldGenerator::SetHasBitIndex(int32_t has_bit_index) {
   if (!HasHasbit(descriptor_)) {
     GOOGLE_CHECK_EQ(has_bit_index, -1);
     return;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index aef9aaf..b210ef9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -35,6 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <string>
@@ -164,9 +165,11 @@
     return false;
   }
 
-  // Generate code that allocates the fields's default instance.
-  virtual void GenerateDefaultInstanceAllocator(
-      io::Printer* /*printer*/) const {}
+  // Generate initialization code for private members declared by
+  // GeneratePrivateMembers(), specifically for the constexpr constructor.
+  // These go into the constructor's initializer list and must follow that
+  // syntax (eg `field_(args)`). Does not include `:` or `,` separators.
+  virtual void GenerateConstinitInitializer(io::Printer* printer) const {}
 
   // Generate lines to serialize this field directly to the array "target",
   // which are placed within the message's SerializeWithCachedSizesToArray()
@@ -178,12 +181,7 @@
   // are placed in the message's ByteSize() method.
   virtual void GenerateByteSize(io::Printer* printer) const = 0;
 
-  // Any tags about field layout decisions (such as inlining) to embed in the
-  // offset.
-  virtual uint32 CalculateFieldTag() const { return 0; }
-  virtual bool IsInlined() const { return false; }
-
-  void SetHasBitIndex(int32 has_bit_index);
+  void SetHasBitIndex(int32_t has_bit_index);
 
  protected:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index e2961e5..0c23947 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -38,6 +38,7 @@
 #include <map>
 #include <memory>
 #include <set>
+#include <unordered_map>
 #include <unordered_set>
 #include <vector>
 
@@ -52,6 +53,7 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
+// Must be last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -73,11 +75,6 @@
   return val.name();
 }
 
-template <>
-std::string GetSortKey<SCC>(const SCC& val) {
-  return val.GetRepresentative()->full_name();
-}
-
 template <class T>
 bool CompareSortKeys(const T* a, const T* b) {
   return GetSortKey(*a) < GetSortKey(*b);
@@ -138,13 +135,6 @@
   for (int i = 0; i < file->weak_dependency_count(); ++i) {
     weak_deps_.insert(file->weak_dependency(i));
   }
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
-      sccs_.push_back(GetSCC(message_generators_[i]->descriptor_));
-    }
-  }
-
-  std::sort(sccs_.begin(), sccs_.end(), CompareSortKeys<SCC>);
 }
 
 FileGenerator::~FileGenerator() = default;
@@ -413,6 +403,11 @@
     IncludeFile("net/proto2/public/wire_format.h", printer);
   }
 
+  if (HasGeneratedMethods(file_, options_) &&
+      options_.tctable_mode != Options::kTCTableNever) {
+    IncludeFile("net/proto2/public/generated_message_tctable_impl.h", printer);
+  }
+
   if (options_.proto_h) {
     // Use the smaller .proto.h files.
     for (int i = 0; i < file_->dependency_count(); i++) {
@@ -426,27 +421,51 @@
       format("#include \"$1$.proto.h\"\n", basename);
     }
   }
+  if (HasCordFields(file_, options_)) {
+    format(
+        "#include \"third_party/absl/strings/internal/string_constant.h\"\n");
+  }
 
   format("// @@protoc_insertion_point(includes)\n");
   IncludeFile("net/proto2/public/port_def.inc", printer);
+
+  // For MSVC builds, we use #pragma init_seg to move the initialization of our
+  // libraries to happen before the user code.
+  // This worksaround the fact that MSVC does not do constant initializers when
+  // required by the standard.
+  format("\nPROTOBUF_PRAGMA_INIT_SEG\n");
 }
 
 void FileGenerator::GenerateSourceDefaultInstance(int idx,
                                                   io::Printer* printer) {
   Formatter format(printer, variables_);
   MessageGenerator* generator = message_generators_[idx].get();
+  generator->GenerateConstexprConstructor(printer);
+  // Use a union to disable the destructor of the _instance member.
+  // We can constant initialize, but the object will still have a non-trivial
+  // destructor that we need to elide.
   format(
-      "class $1$ {\n"
-      " public:\n"
-      "  ::$proto_ns$::internal::ExplicitlyConstructed<$2$> _instance;\n",
+      "struct $1$ {\n"
+      "  constexpr $1$()\n"
+      "    : _instance(::$proto_ns$::internal::ConstantInitialized{}) {}\n"
+      "  ~$1$() {}\n"
+      "  union {\n"
+      "    $2$ _instance;\n"
+      "  };\n"
+      "};\n",
       DefaultInstanceType(generator->descriptor_, options_),
       generator->classname_);
-  format.Indent();
-  generator->GenerateExtraDefaultFields(printer);
-  format.Outdent();
-  format("} $1$;\n", DefaultInstanceName(generator->descriptor_, options_));
+  // NO_DESTROY is not necessary for correctness. The empty destructor is
+  // enough. However, the empty destructor fails to be elided in some
+  // configurations (like non-opt or with certain sanitizers). NO_DESTROY is
+  // there just to improve performance and binary size in these builds.
+  format("PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT $1$ $2$;\n",
+         DefaultInstanceType(generator->descriptor_, options_),
+         DefaultInstanceName(generator->descriptor_, options_));
+
   if (options_.lite_implicit_weak_fields) {
-    format("$1$DefaultTypeInternal* $2$ = &$3$;\n", generator->classname_,
+    format("$1$* $2$ = &$3$;\n",
+           DefaultInstanceType(generator->descriptor_, options_),
            DefaultInstancePtr(generator->descriptor_, options_),
            DefaultInstanceName(generator->descriptor_, options_));
   }
@@ -456,8 +475,6 @@
 // another .pb.cc file.
 struct FileGenerator::CrossFileReferences {
   // Populated if we are referencing from messages or files.
-  std::unordered_set<const SCC*> strong_sccs;
-  std::unordered_set<const SCC*> weak_sccs;
   std::unordered_set<const Descriptor*> weak_default_instances;
 
   // Only if we are referencing from files.
@@ -469,16 +486,10 @@
                                                    CrossFileReferences* refs) {
   const Descriptor* msg = field->message_type();
   if (msg == nullptr) return;
-  const SCC* scc = GetSCC(msg);
 
   if (IsImplicitWeakField(field, options_, &scc_analyzer_) ||
       IsWeak(field, options_)) {
-    refs->weak_sccs.insert(scc);
     refs->weak_default_instances.insert(msg);
-  } else {
-    refs->strong_sccs.insert(scc);
-    // We don't need to declare default instances, because it is declared in the
-    // .proto.h file we imported.
   }
 }
 
@@ -505,35 +516,6 @@
     const CrossFileReferences& refs, io::Printer* printer) {
   Formatter format(printer, variables_);
 
-  for (auto scc : Sorted(refs.strong_sccs)) {
-    format("extern $1$ ::$proto_ns$::internal::SCCInfo<$2$> $3$;\n",
-           FileDllExport(scc->GetFile(), options_), scc->children.size(),
-           SccInfoSymbol(scc, options_));
-  }
-
-  for (auto scc : Sorted(refs.weak_sccs)) {
-    // We do things a little bit differently for proto1-style weak fields versus
-    // lite implicit weak fields, even though they are trying to accomplish
-    // similar things. We need to support implicit weak fields on iOS, and the
-    // Apple linker only supports weak definitions, not weak declarations. For
-    // that reason we need a pointer type which we can weakly define to be null.
-    // However, code size considerations prevent us from using the same approach
-    // for proto1-style weak fields.
-    if (options_.lite_implicit_weak_fields) {
-      format("extern ::$proto_ns$::internal::SCCInfo<$1$> $2$;\n",
-             scc->children.size(), SccInfoSymbol(scc, options_));
-      format(
-          "__attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$>*\n"
-          "    $2$ = nullptr;\n",
-          scc->children.size(), SccInfoPtrSymbol(scc, options_));
-    } else {
-      format(
-          "extern __attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$> "
-          "$2$;\n",
-          scc->children.size(), SccInfoSymbol(scc, options_));
-    }
-  }
-
   {
     NamespaceOpener ns(format);
     for (auto instance : Sorted(refs.weak_default_instances)) {
@@ -564,24 +546,13 @@
   Formatter format(printer, variables_);
   GenerateSourceIncludes(printer);
 
-  // Generate weak declarations. We do this for the whole strongly-connected
-  // component (SCC), because we have a single InitDefaults* function for the
-  // SCC.
   CrossFileReferences refs;
-  for (const Descriptor* message :
-       scc_analyzer_.GetSCC(message_generators_[idx]->descriptor_)
-           ->descriptors) {
-    ForEachField(message, [this, &refs](const FieldDescriptor* field) {
-      GetCrossFileReferencesForField(field, &refs);
-    });
-  }
+  ForEachField(message_generators_[idx]->descriptor_,
+               [this, &refs](const FieldDescriptor* field) {
+                 GetCrossFileReferencesForField(field, &refs);
+               });
   GenerateInternalForwardDeclarations(refs, printer);
 
-  if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
-    GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), refs,
-                       printer);
-  }
-
   {  // package namespace
     NamespaceOpener ns(Namespace(file_, options_), format);
 
@@ -663,11 +634,6 @@
   {
     GenerateTables(printer);
 
-    // Now generate the InitDefaults for each SCC.
-    for (auto scc : sccs_) {
-      GenerateInitForSCC(scc, refs, printer);
-    }
-
     if (HasDescriptorMethods(file_, options_)) {
       // Define the code to initialize reflection. This code uses a global
       // constructor to register reflection data with the runtime pre-main.
@@ -733,10 +699,6 @@
   if (!message_generators_.empty()) {
     format("static ::$proto_ns$::Metadata $file_level_metadata$[$1$];\n",
            message_generators_.size());
-  } else {
-    format(
-        "static "
-        "constexpr ::$proto_ns$::Metadata* $file_level_metadata$ = nullptr;\n");
   }
   if (!enum_generators_.empty()) {
     format(
@@ -867,31 +829,21 @@
       refs.strong_reflection_files.size() + refs.weak_reflection_files.size();
 
   // Build array of DescriptorTable deps.
-  format(
-      "static const ::$proto_ns$::internal::DescriptorTable*const "
-      "$desc_table$_deps[$1$] = {\n",
-      std::max(num_deps, 1));
+  if (num_deps > 0) {
+    format(
+        "static const ::$proto_ns$::internal::DescriptorTable*const "
+        "$desc_table$_deps[$1$] = {\n",
+        num_deps);
 
-  for (auto dep : Sorted(refs.strong_reflection_files)) {
-    format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    for (auto dep : Sorted(refs.strong_reflection_files)) {
+      format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    }
+    for (auto dep : Sorted(refs.weak_reflection_files)) {
+      format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    }
+
+    format("};\n");
   }
-  for (auto dep : Sorted(refs.weak_reflection_files)) {
-    format("  &::$1$,\n", DescriptorTableName(dep, options_));
-  }
-
-  format("};\n");
-
-  // Build array of SCCs from this file.
-  format(
-      "static ::$proto_ns$::internal::SCCInfoBase*const "
-      "$desc_table$_sccs[$1$] = {\n",
-      std::max<int>(sccs_.size(), 1));
-
-  for (auto scc : sccs_) {
-    format("  &$1$.base,\n", SccInfoSymbol(scc, options_));
-  }
-
-  format("};\n");
 
   // The DescriptorTable itself.
   // Should be "bool eager = NeedsEagerDescriptorAssignment(file_, options_);"
@@ -901,14 +853,33 @@
   format(
       "static ::$proto_ns$::internal::once_flag $desc_table$_once;\n"
       "const ::$proto_ns$::internal::DescriptorTable $desc_table$ = {\n"
-      "  false, $1$, $2$, \"$filename$\", $3$,\n"
-      "  &$desc_table$_once, $desc_table$_sccs, $desc_table$_deps, $4$, $5$,\n"
+      "  false, $1$, $2$, $3$, \"$filename$\", \n"
+      "  &$desc_table$_once, $4$, $5$, $6$,\n"
       "  schemas, file_default_instances, $tablename$::offsets,\n"
-      "  $file_level_metadata$, $6$, $file_level_enum_descriptors$, "
+      "  $7$, $file_level_enum_descriptors$, "
       "$file_level_service_descriptors$,\n"
-      "};\n\n",
-      eager ? "true" : "false", protodef_name, file_data.size(), sccs_.size(),
-      num_deps, message_generators_.size());
+      "};\n"
+      // This function exists to be marked as weak.
+      // It can significantly speed up compilation by breaking up LLVM's SCC in
+      // the .pb.cc translation units. Large translation units see a reduction
+      // of more than 35% of walltime for optimized builds.
+      // Without the weak attribute all the messages in the file, including all
+      // the vtables and everything they use become part of the same SCC through
+      // a cycle like:
+      // GetMetadata -> descriptor table -> default instances ->
+      //   vtables -> GetMetadata
+      // By adding a weak function here we break the connection from the
+      // individual vtables back into the descriptor table.
+      "PROTOBUF_ATTRIBUTE_WEAK const ::$proto_ns$::internal::DescriptorTable* "
+      "$desc_table$_getter() {\n"
+      "  return &$desc_table$;\n"
+      "}\n"
+      "\n",
+      eager ? "true" : "false", file_data.size(), protodef_name,
+      num_deps == 0 ? "nullptr" : variables_["desc_table"] + "_deps", num_deps,
+      message_generators_.size(),
+      message_generators_.empty() ? "nullptr"
+                                  : variables_["file_level_metadata"]);
 
   // For descriptor.proto we want to avoid doing any dynamic initialization,
   // because in some situations that would otherwise pull in a lot of
@@ -917,106 +888,13 @@
   if (file_->name() != "net/proto2/proto/descriptor.proto") {
     format(
         "// Force running AddDescriptors() at dynamic initialization time.\n"
-        "static bool $1$ = (static_cast<void>("
-        "::$proto_ns$::internal::AddDescriptors(&$desc_table$)), true);\n",
+        "PROTOBUF_ATTRIBUTE_INIT_PRIORITY "
+        "static ::$proto_ns$::internal::AddDescriptorsRunner "
+        "$1$(&$desc_table$);\n",
         UniqueName("dynamic_init_dummy", file_, options_));
   }
 }
 
-void FileGenerator::GenerateInitForSCC(const SCC* scc,
-                                       const CrossFileReferences& refs,
-                                       io::Printer* printer) {
-  Formatter format(printer, variables_);
-  // We use static and not anonymous namespace because symbol names are
-  // substantially shorter.
-  format("static void InitDefaults$1$() {\n", SccInfoSymbol(scc, options_));
-
-  if (options_.opensource_runtime) {
-    format("  GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n");
-  }
-
-  format.Indent();
-
-  // First construct all the necessary default instances.
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
-      continue;
-    }
-    // TODO(gerbens) This requires this function to be friend. Remove
-    // the need for this.
-    message_generators_[i]->GenerateFieldDefaultInstances(printer);
-    format(
-        "{\n"
-        "  void* ptr = &$1$;\n"
-        "  new (ptr) $2$();\n",
-        QualifiedDefaultInstanceName(message_generators_[i]->descriptor_,
-                                     options_),
-        QualifiedClassName(message_generators_[i]->descriptor_, options_));
-    if (options_.opensource_runtime &&
-        !IsMapEntryMessage(message_generators_[i]->descriptor_)) {
-      format(
-          "  "
-          "::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);"
-          "\n");
-    }
-    format("}\n");
-  }
-
-  // TODO(gerbens) make default instances be the same as normal instances.
-  // Default instances differ from normal instances because they have cross
-  // linked message fields.
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
-      continue;
-    }
-    format("$1$::InitAsDefaultInstance();\n",
-           QualifiedClassName(message_generators_[i]->descriptor_, options_));
-  }
-  format.Outdent();
-  format("}\n\n");
-
-  // If we are using lite implicit weak fields then we need to distinguish
-  // between regular SCC dependencies and ones that we need to reference weakly
-  // through an extra pointer indirection.
-  std::vector<const SCC*> regular_sccs;
-  std::vector<const SCC*> implicit_weak_sccs;
-  for (const SCC* child : scc->children) {
-    if (options_.lite_implicit_weak_fields &&
-        refs.weak_sccs.find(child) != refs.weak_sccs.end()) {
-      implicit_weak_sccs.push_back(child);
-    } else {
-      regular_sccs.push_back(child);
-    }
-  }
-
-  format(
-      "$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$> $2$ =\n"
-      "    "
-      "{{ATOMIC_VAR_INIT(::$proto_ns$::internal::SCCInfoBase::kUninitialized), "
-      "$3$, $4$, InitDefaults$2$}, {",
-      scc->children.size(),  // 1
-      SccInfoSymbol(scc, options_), regular_sccs.size(),
-      implicit_weak_sccs.size());
-  for (const SCC* child : regular_sccs) {
-    format("\n      &$1$.base,", SccInfoSymbol(child, options_));
-  }
-  for (const SCC* child : implicit_weak_sccs) {
-    format(
-        "\n      reinterpret_cast<::$proto_ns$::internal::SCCInfoBase**>("
-        "\n          &$1$),",
-        SccInfoPtrSymbol(child, options_));
-  }
-  format("}};\n\n");
-
-  if (options_.lite_implicit_weak_fields) {
-    format(
-        "$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$>*\n"
-        "    $2$ = &$3$;\n\n",
-        scc->children.size(), SccInfoPtrSymbol(scc, options_),
-        SccInfoSymbol(scc, options_));
-  }
-}
-
 void FileGenerator::GenerateTables(io::Printer* printer) {
   Formatter format(printer, variables_);
   if (options_.table_driven_parsing) {
@@ -1046,7 +924,7 @@
         "};\n"
         "\n"
         "PROTOBUF_CONSTEXPR_VAR "
-        "::$proto_ns$::internal::AuxillaryParseTableField\n"
+        "::$proto_ns$::internal::AuxiliaryParseTableField\n"
         "    const $tablename$::aux[] "
         "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
     format.Indent();
@@ -1060,7 +938,7 @@
     }
 
     if (count == 0) {
-      format("::$proto_ns$::internal::AuxillaryParseTableField(),\n");
+      format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
     }
 
     format.Outdent();
@@ -1146,7 +1024,7 @@
       const Descriptor* class_desc = p.second;
       format(
           "class ${1$$2$$}$;\n"
-          "class $3$;\n"
+          "struct $3$;\n"
           "$dllexport_decl $extern $3$ $4$;\n",
           class_desc, classname, DefaultInstanceType(class_desc, options),
           DefaultInstanceName(class_desc, options));
@@ -1212,7 +1090,6 @@
       decls[Namespace(d, options_)].AddEnum(d);
   }
 
-
   {
     NamespaceOpener ns(format);
     for (const auto& pair : decls) {
@@ -1262,7 +1139,7 @@
     GOOGLE_CHECK(!options_.opensource_runtime);
     IncludeFile("net/proto2/public/weak_field_map.h", printer);
   }
-  if (HasLazyFields(file_, options_)) {
+  if (HasLazyFields(file_, options_, &scc_analyzer_)) {
     GOOGLE_CHECK(!options_.opensource_runtime);
     IncludeFile("net/proto2/public/lazy_field.h", printer);
   }
@@ -1294,8 +1171,11 @@
   IncludeFile("net/proto2/public/arena.h", printer);
   IncludeFile("net/proto2/public/arenastring.h", printer);
   IncludeFile("net/proto2/public/generated_message_table_driven.h", printer);
+  if (HasGeneratedMethods(file_, options_) &&
+      options_.tctable_mode != Options::kTCTableNever) {
+    IncludeFile("net/proto2/public/generated_message_tctable_decl.h", printer);
+  }
   IncludeFile("net/proto2/public/generated_message_util.h", printer);
-  IncludeFile("net/proto2/public/inlined_string_field.h", printer);
   IncludeFile("net/proto2/public/metadata_lite.h", printer);
 
   if (HasDescriptorMethods(file_, options_)) {
@@ -1406,7 +1286,7 @@
       // for table driven code.
       "  static const ::$proto_ns$::internal::ParseTableField entries[]\n"
       "    PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n"
-      "  static const ::$proto_ns$::internal::AuxillaryParseTableField aux[]\n"
+      "  static const ::$proto_ns$::internal::AuxiliaryParseTableField aux[]\n"
       "    PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n"
       "  static const ::$proto_ns$::internal::ParseTable schema[$1$]\n"
       "    PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n"
@@ -1418,7 +1298,7 @@
       std::max(size_t(1), message_generators_.size()));
   if (HasDescriptorMethods(file_, options_)) {
     format(
-        "extern $dllexport_decl $const ::$proto_ns$::internal::DescriptorTable "
+        "$dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable "
         "$desc_table$;\n");
   }
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index da5e1de..35a9085 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -162,14 +162,6 @@
   // generally a breaking change so we prefer the #undef approach.
   void GenerateMacroUndefs(io::Printer* printer);
 
-  bool IsSCCRepresentative(const Descriptor* d) {
-    return GetSCCRepresentative(d) == d;
-  }
-  const Descriptor* GetSCCRepresentative(const Descriptor* d) {
-    return GetSCC(d)->GetRepresentative();
-  }
-  const SCC* GetSCC(const Descriptor* d) { return scc_analyzer_.GetSCC(d); }
-
   bool IsDepWeak(const FileDescriptor* dep) const {
     if (weak_deps_.count(dep) != 0) {
       GOOGLE_CHECK(!options_.opensource_runtime);
@@ -179,7 +171,6 @@
   }
 
   std::set<const FileDescriptor*> weak_deps_;
-  std::vector<const SCC*> sccs_;
 
   const FileDescriptor* file_;
   const Options options_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 2c45ca8..2a6087e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -104,10 +104,30 @@
         file_options.num_cc_files =
             strto32(options[i].second.c_str(), NULL, 10);
       }
+    } else if (options[i].first == "annotate_accessor") {
+      file_options.annotate_accessor = true;
+    } else if (options[i].first == "inject_field_listener_events") {
+      file_options.inject_field_listener_events = true;
+    } else if (options[i].first == "eagerly_verified_lazy") {
+      file_options.eagerly_verified_lazy = true;
+    } else if (options[i].first == "force_eagerly_verified_lazy") {
+      file_options.force_eagerly_verified_lazy = true;
     } else if (options[i].first == "table_driven_parsing") {
       file_options.table_driven_parsing = true;
     } else if (options[i].first == "table_driven_serialization") {
       file_options.table_driven_serialization = true;
+    } else if (options[i].first == "experimental_tail_call_table_mode") {
+      if (options[i].second == "never") {
+        file_options.tctable_mode = Options::kTCTableNever;
+      } else if (options[i].second == "guarded") {
+        file_options.tctable_mode = Options::kTCTableGuarded;
+      } else if (options[i].second == "always") {
+        file_options.tctable_mode = Options::kTCTableAlways;
+      } else {
+        *error = "Unknown value for experimental_tail_call_table_mode: " +
+                 options[i].second;
+        return false;
+      }
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h
index 85a5aab..97e848d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.h
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.h
@@ -84,7 +84,7 @@
                 GeneratorContext* generator_context,
                 std::string* error) const override;
 
-  uint64 GetSupportedFeatures() const override {
+  uint64_t GetSupportedFeatures() const override {
     // We don't fully support this yet, but this is needed to unblock the tests,
     // and we will have full support before the experimental flag is removed.
     return FEATURE_PROTO3_OPTIONAL;
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 976823a..c25de21 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -34,6 +34,7 @@
 
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 
+#include <cstdint>
 #include <functional>
 #include <limits>
 #include <map>
@@ -44,6 +45,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/cpp_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/compiler/scc.h>
@@ -167,30 +169,6 @@
 
 static std::unordered_set<std::string>& kKeywords = *MakeKeywordsMap();
 
-// Encode [0..63] as 'A'-'Z', 'a'-'z', '0'-'9', '_'
-char Base63Char(int value) {
-  GOOGLE_CHECK_GE(value, 0);
-  if (value < 26) return 'A' + value;
-  value -= 26;
-  if (value < 26) return 'a' + value;
-  value -= 26;
-  if (value < 10) return '0' + value;
-  GOOGLE_CHECK_EQ(value, 10);
-  return '_';
-}
-
-// Given a c identifier has 63 legal characters we can't implement base64
-// encoding. So we return the k least significant "digits" in base 63.
-template <typename I>
-std::string Base63(I n, int k) {
-  std::string res;
-  while (k-- > 0) {
-    res += Base63Char(static_cast<int>(n % 63));
-    n /= 63;
-  }
-  return res;
-}
-
 std::string IntTypeName(const Options& options, const std::string& type) {
   if (options.opensource_runtime) {
     return "::PROTOBUF_NAMESPACE_ID::" + type;
@@ -203,13 +181,20 @@
                std::map<std::string, std::string>* variables) {
   (*variables)[type] = IntTypeName(options, type);
 }
-
-bool HasInternalAccessors(const FieldOptions::CType ctype) {
-  return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
+bool IsEagerlyVerifiedLazyImpl(const FieldDescriptor* field,
+                               const Options& options,
+                               MessageSCCAnalyzer* scc_analyzer) {
+  return false;
 }
 
 }  // namespace
 
+bool IsLazy(const FieldDescriptor* field, const Options& options,
+            MessageSCCAnalyzer* scc_analyzer) {
+  return IsLazilyVerifiedLazy(field, options) ||
+         IsEagerlyVerifiedLazyImpl(field, options, scc_analyzer);
+}
+
 void SetCommonVars(const Options& options,
                    std::map<std::string, std::string>* variables) {
   (*variables)["proto_ns"] = ProtobufNamespace(options);
@@ -247,9 +232,9 @@
   (*variables)["string"] = "std::string";
 }
 
-void SetUnknkownFieldsVariable(const Descriptor* descriptor,
-                               const Options& options,
-                               std::map<std::string, std::string>* variables) {
+void SetUnknownFieldsVariable(const Descriptor* descriptor,
+                              const Options& options,
+                              std::map<std::string, std::string>* variables) {
   std::string proto_ns = ProtobufNamespace(options);
   std::string unknown_fields_type;
   if (UseUnknownFieldSet(descriptor->file(), options)) {
@@ -362,10 +347,16 @@
   return QualifiedClassName(d, Options());
 }
 
+std::string ExtensionName(const FieldDescriptor* d) {
+  if (const Descriptor* scope = d->extension_scope())
+    return StrCat(ClassName(scope), "::", ResolveKeyword(d->name()));
+  return ResolveKeyword(d->name());
+}
+
 std::string QualifiedExtensionName(const FieldDescriptor* d,
                                    const Options& options) {
   GOOGLE_DCHECK(d->is_extension());
-  return QualifiedFileLevelSymbol(d->file(), FieldName(d), options);
+  return QualifiedFileLevelSymbol(d->file(), ExtensionName(d), options);
 }
 
 std::string QualifiedExtensionName(const FieldDescriptor* d) {
@@ -516,11 +507,11 @@
 }
 
 std::string StripProto(const std::string& filename) {
-  if (HasSuffixString(filename, ".protodevel")) {
-    return StripSuffixString(filename, ".protodevel");
-  } else {
-    return StripSuffixString(filename, ".proto");
-  }
+  /*
+   * TODO(github/georgthegreat) remove this proxy method
+   * once Google's internal codebase will become ready
+   */
+  return compiler::StripProto(filename);
 }
 
 const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
@@ -635,7 +626,7 @@
 }
 
 std::string Int32ToString(int number) {
-  if (number == kint32min) {
+  if (number == std::numeric_limits<int32_t>::min()) {
     // This needs to be special-cased, see explanation here:
     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
     return StrCat(number + 1, " - 1");
@@ -644,28 +635,21 @@
   }
 }
 
-std::string Int64ToString(const std::string& macro_prefix, int64 number) {
-  if (number == kint64min) {
+static std::string Int64ToString(int64_t number) {
+  if (number == std::numeric_limits<int64_t>::min()) {
     // This needs to be special-cased, see explanation here:
     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
-    return StrCat(macro_prefix, "_LONGLONG(", number + 1, ") - 1");
+    return StrCat("int64_t{", number + 1, "} - 1");
   }
-  return StrCat(macro_prefix, "_LONGLONG(", number, ")");
+  return StrCat("int64_t{", number, "}");
 }
 
-std::string UInt64ToString(const std::string& macro_prefix, uint64 number) {
-  return StrCat(macro_prefix, "_ULONGLONG(", number, ")");
+static std::string UInt64ToString(uint64_t number) {
+  return StrCat("uint64_t{", number, "u}");
 }
 
 std::string DefaultValue(const FieldDescriptor* field) {
-  switch (field->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_INT64:
-      return Int64ToString("GG", field->default_value_int64());
-    case FieldDescriptor::CPPTYPE_UINT64:
-      return UInt64ToString("GG", field->default_value_uint64());
-    default:
-      return DefaultValue(Options(), field);
-  }
+  return DefaultValue(Options(), field);
 }
 
 std::string DefaultValue(const Options& options, const FieldDescriptor* field) {
@@ -675,9 +659,9 @@
     case FieldDescriptor::CPPTYPE_UINT32:
       return StrCat(field->default_value_uint32()) + "u";
     case FieldDescriptor::CPPTYPE_INT64:
-      return Int64ToString("PROTOBUF", field->default_value_int64());
+      return Int64ToString(field->default_value_int64());
     case FieldDescriptor::CPPTYPE_UINT64:
-      return UInt64ToString("PROTOBUF", field->default_value_uint64());
+      return UInt64ToString(field->default_value_uint64());
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field->default_value_double();
       if (value == std::numeric_limits<double>::infinity()) {
@@ -741,7 +725,8 @@
     } else {
       // Not alphanumeric.  To avoid any possibility of name conflicts we
       // use the hex code for the character.
-      StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
+      StrAppend(&result, "_",
+                      strings::Hex(static_cast<uint8_t>(filename[i])));
     }
   }
   return result;
@@ -787,39 +772,20 @@
   return function_name;
 }
 
-bool IsStringInlined(const FieldDescriptor* descriptor,
-                     const Options& options) {
-  if (options.opensource_runtime) return false;
-
-  // TODO(ckennelly): Handle inlining for any.proto.
-  if (IsAnyMessage(descriptor->containing_type(), options)) return false;
-  if (descriptor->containing_type()->options().map_entry()) return false;
-
-  // We rely on has bits to distinguish field presence for release_$name$.  When
-  // there is no hasbit, we cannot use the address of the string instance when
-  // the field has been inlined.
-  if (!HasHasbit(descriptor)) return false;
-
-  if (options.access_info_map) {
-    if (descriptor->is_required()) return true;
-  }
-  return false;
-}
-
-static bool HasLazyFields(const Descriptor* descriptor,
-                          const Options& options) {
+static bool HasLazyFields(const Descriptor* descriptor, const Options& options,
+                          MessageSCCAnalyzer* scc_analyzer) {
   for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) {
-    if (IsLazy(descriptor->field(field_idx), options)) {
+    if (IsLazy(descriptor->field(field_idx), options, scc_analyzer)) {
       return true;
     }
   }
   for (int idx = 0; idx < descriptor->extension_count(); idx++) {
-    if (IsLazy(descriptor->extension(idx), options)) {
+    if (IsLazy(descriptor->extension(idx), options, scc_analyzer)) {
       return true;
     }
   }
   for (int idx = 0; idx < descriptor->nested_type_count(); idx++) {
-    if (HasLazyFields(descriptor->nested_type(idx), options)) {
+    if (HasLazyFields(descriptor->nested_type(idx), options, scc_analyzer)) {
       return true;
     }
   }
@@ -827,15 +793,16 @@
 }
 
 // Does the given FileDescriptor use lazy fields?
-bool HasLazyFields(const FileDescriptor* file, const Options& options) {
+bool HasLazyFields(const FileDescriptor* file, const Options& options,
+                   MessageSCCAnalyzer* scc_analyzer) {
   for (int i = 0; i < file->message_type_count(); i++) {
     const Descriptor* descriptor(file->message_type(i));
-    if (HasLazyFields(descriptor, options)) {
+    if (HasLazyFields(descriptor, options, scc_analyzer)) {
       return true;
     }
   }
   for (int field_idx = 0; field_idx < file->extension_count(); field_idx++) {
-    if (IsLazy(file->extension(field_idx), options)) {
+    if (IsLazy(file->extension(field_idx), options, scc_analyzer)) {
       return true;
     }
   }
@@ -1036,13 +1003,13 @@
                                const Options& options) {
   if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
       FieldEnforceUtf8(field, options)) {
-    return STRICT;
+    return Utf8CheckMode::kStrict;
   } else if (GetOptimizeFor(field->file(), options) !=
                  FileOptions::LITE_RUNTIME &&
              FileUtf8Verification(field->file(), options)) {
-    return VERIFY;
+    return Utf8CheckMode::kVerify;
   } else {
-    return NONE;
+    return Utf8CheckMode::kNone;
   }
 }
 
@@ -1053,7 +1020,7 @@
                                   const char* verify_function,
                                   const Formatter& format) {
   switch (GetUtf8CheckMode(field, options)) {
-    case STRICT: {
+    case Utf8CheckMode::kStrict: {
       if (for_parse) {
         format("DO_(");
       }
@@ -1073,7 +1040,7 @@
       format.Outdent();
       break;
     }
-    case VERIFY: {
+    case Utf8CheckMode::kVerify: {
       format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function);
       format.Indent();
       format(parameters);
@@ -1086,7 +1053,7 @@
       format.Outdent();
       break;
     }
-    case NONE:
+    case Utf8CheckMode::kNone:
       break;
   }
 }
@@ -1164,25 +1131,25 @@
 MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
   if (analysis_cache_.count(scc)) return analysis_cache_[scc];
   MessageAnalysis result{};
+  if (UsingImplicitWeakFields(scc->GetFile(), options_)) {
+    result.contains_weak = true;
+  }
   for (int i = 0; i < scc->descriptors.size(); i++) {
     const Descriptor* descriptor = scc->descriptors[i];
     if (descriptor->extension_range_count() > 0) {
       result.contains_extension = true;
-      // Extensions are found by looking up default_instance and extension
-      // number in a map. So you'd maybe expect here
-      // result.constructor_requires_initialization = true;
-      // However the extension registration mechanism already makes sure
-      // the default will be initialized.
     }
     for (int i = 0; i < descriptor->field_count(); i++) {
       const FieldDescriptor* field = descriptor->field(i);
       if (field->is_required()) {
         result.contains_required = true;
       }
+      if (field->options().weak()) {
+        result.contains_weak = true;
+      }
       switch (field->type()) {
         case FieldDescriptor::TYPE_STRING:
         case FieldDescriptor::TYPE_BYTES: {
-          result.constructor_requires_initialization = true;
           if (field->options().ctype() == FieldOptions::CORD) {
             result.contains_cord = true;
           }
@@ -1190,7 +1157,6 @@
         }
         case FieldDescriptor::TYPE_GROUP:
         case FieldDescriptor::TYPE_MESSAGE: {
-          result.constructor_requires_initialization = true;
           const SCC* child = analyzer_.GetSCC(field->message_type());
           if (child != scc) {
             MessageAnalysis analysis = GetSCCAnalysis(child);
@@ -1199,6 +1165,7 @@
             if (!ShouldIgnoreRequiredFieldCheck(field, options_)) {
               result.contains_required |= analysis.contains_required;
             }
+            result.contains_weak |= analysis.contains_weak;
           } else {
             // This field points back into the same SCC hence the messages
             // in the SCC are recursive. Note if SCC contains more than two
@@ -1366,524 +1333,6 @@
   }
 }
 
-class ParseLoopGenerator {
- public:
-  ParseLoopGenerator(int num_hasbits, const Options& options,
-                     MessageSCCAnalyzer* scc_analyzer, io::Printer* printer)
-      : scc_analyzer_(scc_analyzer),
-        options_(options),
-        format_(printer),
-        num_hasbits_(num_hasbits) {}
-
-  void GenerateParserLoop(const Descriptor* descriptor) {
-    format_.Set("classname", ClassName(descriptor));
-    format_.Set("p_ns", "::" + ProtobufNamespace(options_));
-    format_.Set("pi_ns",
-                StrCat("::", ProtobufNamespace(options_), "::internal"));
-    format_.Set("GOOGLE_PROTOBUF", MacroPrefix(options_));
-    std::map<std::string, std::string> vars;
-    SetCommonVars(options_, &vars);
-    SetUnknkownFieldsVariable(descriptor, options_, &vars);
-    format_.AddMap(vars);
-
-    std::vector<const FieldDescriptor*> ordered_fields;
-    for (auto field : FieldRange(descriptor)) {
-      if (IsFieldUsed(field, options_)) {
-        ordered_fields.push_back(field);
-      }
-    }
-    std::sort(ordered_fields.begin(), ordered_fields.end(),
-              [](const FieldDescriptor* a, const FieldDescriptor* b) {
-                return a->number() < b->number();
-              });
-
-    format_(
-        "const char* $classname$::_InternalParse(const char* ptr, "
-        "$pi_ns$::ParseContext* ctx) {\n"
-        "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure\n");
-    format_.Indent();
-    int hasbits_size = 0;
-    if (num_hasbits_ > 0) {
-      hasbits_size = (num_hasbits_ + 31) / 32;
-    }
-    // For now only optimize small hasbits.
-    if (hasbits_size != 1) hasbits_size = 0;
-    if (hasbits_size) {
-      format_("_Internal::HasBits has_bits{};\n");
-      format_.Set("has_bits", "has_bits");
-    } else {
-      format_.Set("has_bits", "_has_bits_");
-    }
-
-    if (descriptor->file()->options().cc_enable_arenas()) {
-      format_("$p_ns$::Arena* arena = GetArena(); (void)arena;\n");
-    }
-    GenerateParseLoop(descriptor, ordered_fields);
-    format_.Outdent();
-    format_("success:\n");
-    if (hasbits_size) format_("  _has_bits_.Or(has_bits);\n");
-
-    format_(
-        "  return ptr;\n"
-        "failure:\n"
-        "  ptr = nullptr;\n"
-        "  goto success;\n"
-        "#undef CHK_\n"
-        "}\n");
-  }
-
- private:
-  MessageSCCAnalyzer* scc_analyzer_;
-  const Options& options_;
-  Formatter format_;
-  int num_hasbits_;
-
-  using WireFormat = internal::WireFormat;
-  using WireFormatLite = internal::WireFormatLite;
-
-  void GenerateArenaString(const FieldDescriptor* field) {
-    if (HasHasbit(field)) {
-      format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
-    }
-    std::string default_string =
-        field->default_value_string().empty()
-            ? "::" + ProtobufNamespace(options_) +
-                  "::internal::GetEmptyStringAlreadyInited()"
-            : QualifiedClassName(field->containing_type(), options_) +
-                  "::" + MakeDefaultName(field) + ".get()";
-    format_(
-        "if (arena != nullptr) {\n"
-        "  ptr = ctx->ReadArenaString(ptr, &$1$_, arena);\n"
-        "} else {\n"
-        "  ptr = "
-        "$pi_ns$::InlineGreedyStringParser($1$_.MutableNoArenaNoDefault(&$2$"
-        "), ptr, ctx);"
-        "\n}\n"
-        "const std::string* str = &$1$_.Get(); (void)str;\n",
-        FieldName(field), default_string);
-  }
-
-  void GenerateStrings(const FieldDescriptor* field, bool check_utf8) {
-    FieldOptions::CType ctype = FieldOptions::STRING;
-    if (!options_.opensource_runtime) {
-      // Open source doesn't support other ctypes;
-      ctype = field->options().ctype();
-    }
-    if (field->file()->options().cc_enable_arenas() && !field->is_repeated() &&
-        !options_.opensource_runtime &&
-        GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
-        // For now only use arena string for strings with empty defaults.
-        field->default_value_string().empty() &&
-        !IsStringInlined(field, options_) && !field->real_containing_oneof() &&
-        ctype == FieldOptions::STRING) {
-      GenerateArenaString(field);
-    } else {
-      std::string name;
-      switch (ctype) {
-        case FieldOptions::STRING:
-          name = "GreedyStringParser";
-          break;
-        case FieldOptions::CORD:
-          name = "CordParser";
-          break;
-        case FieldOptions::STRING_PIECE:
-          name = "StringPieceParser";
-          break;
-      }
-      format_(
-          "auto str = $1$$2$_$3$();\n"
-          "ptr = $pi_ns$::Inline$4$(str, ptr, ctx);\n",
-          HasInternalAccessors(ctype) ? "_internal_" : "",
-          field->is_repeated() && !field->is_packable() ? "add" : "mutable",
-          FieldName(field), name);
-    }
-    if (!check_utf8) return;  // return if this is a bytes field
-    auto level = GetUtf8CheckMode(field, options_);
-    switch (level) {
-      case NONE:
-        return;
-      case VERIFY:
-        format_("#ifndef NDEBUG\n");
-        break;
-      case STRICT:
-        format_("CHK_(");
-        break;
-    }
-    std::string field_name;
-    field_name = "nullptr";
-    if (HasDescriptorMethods(field->file(), options_)) {
-      field_name = StrCat("\"", field->full_name(), "\"");
-    }
-    format_("$pi_ns$::VerifyUTF8(str, $1$)", field_name);
-    switch (level) {
-      case NONE:
-        return;
-      case VERIFY:
-        format_(
-            ";\n"
-            "#endif  // !NDEBUG\n");
-        break;
-      case STRICT:
-        format_(");\n");
-        break;
-    }
-  }
-
-  void GenerateLengthDelim(const FieldDescriptor* field) {
-    if (field->is_packable()) {
-      std::string enum_validator;
-      if (field->type() == FieldDescriptor::TYPE_ENUM &&
-          !HasPreservingUnknownEnumSemantics(field)) {
-        enum_validator =
-            StrCat(", ", QualifiedClassName(field->enum_type(), options_),
-                         "_IsValid, &_internal_metadata_, ", field->number());
-        format_(
-            "ptr = "
-            "$pi_ns$::Packed$1$Parser<$unknown_fields_type$>(_internal_mutable_"
-            "$2$(), ptr, "
-            "ctx$3$);\n",
-            DeclaredTypeMethodName(field->type()), FieldName(field),
-            enum_validator);
-      } else {
-        format_(
-            "ptr = $pi_ns$::Packed$1$Parser(_internal_mutable_$2$(), ptr, "
-            "ctx$3$);\n",
-            DeclaredTypeMethodName(field->type()), FieldName(field),
-            enum_validator);
-      }
-    } else {
-      auto field_type = field->type();
-      switch (field_type) {
-        case FieldDescriptor::TYPE_STRING:
-          GenerateStrings(field, true /* utf8 */);
-          break;
-        case FieldDescriptor::TYPE_BYTES:
-          GenerateStrings(field, false /* utf8 */);
-          break;
-        case FieldDescriptor::TYPE_MESSAGE: {
-          if (field->is_map()) {
-            const FieldDescriptor* val =
-                field->message_type()->FindFieldByName("value");
-            GOOGLE_CHECK(val);
-            if (val->type() == FieldDescriptor::TYPE_ENUM &&
-                !HasPreservingUnknownEnumSemantics(field)) {
-              format_(
-                  "auto object = "
-                  "::$proto_ns$::internal::InitEnumParseWrapper<$unknown_"
-                  "fields_type$>("
-                  "&$1$_, $2$_IsValid, $3$, &_internal_metadata_);\n"
-                  "ptr = ctx->ParseMessage(&object, ptr);\n",
-                  FieldName(field), QualifiedClassName(val->enum_type()),
-                  field->number());
-            } else {
-              format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
-                      FieldName(field));
-            }
-          } else if (IsLazy(field, options_)) {
-            if (field->real_containing_oneof()) {
-              format_(
-                  "if (!_internal_has_$1$()) {\n"
-                  "  clear_$2$();\n"
-                  "  $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n"
-                  "      $pi_ns$::LazyField>(GetArena());\n"
-                  "  set_has_$1$();\n"
-                  "}\n"
-                  "ptr = ctx->ParseMessage($2$_.$1$_, ptr);\n",
-                  FieldName(field), field->containing_oneof()->name());
-            } else if (HasHasbit(field)) {
-              format_(
-                  "_Internal::set_has_$1$(&$has_bits$);\n"
-                  "ptr = ctx->ParseMessage(&$1$_, ptr);\n",
-                  FieldName(field));
-            } else {
-              format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n",
-                      FieldName(field));
-            }
-          } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
-            if (!field->is_repeated()) {
-              format_(
-                  "ptr = ctx->ParseMessage(_Internal::mutable_$1$(this), "
-                  "ptr);\n",
-                  FieldName(field));
-            } else {
-              format_(
-                  "ptr = ctx->ParseMessage($1$_.AddWeak(reinterpret_cast<const "
-                  "::$proto_ns$::MessageLite*>($2$::_$3$_default_instance_ptr_)"
-                  "), ptr);\n",
-                  FieldName(field), Namespace(field->message_type(), options_),
-                  ClassName(field->message_type()));
-            }
-          } else if (IsWeak(field, options_)) {
-            format_(
-                "ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($1$,"
-                " _$classname$_default_instance_.$2$_), ptr);\n",
-                field->number(), FieldName(field));
-          } else {
-            format_("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n",
-                    field->is_repeated() ? "add" : "mutable", FieldName(field));
-          }
-          break;
-        }
-        default:
-          GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
-                     << " filed type is " << field->type();
-      }
-    }
-  }
-
-  // Convert a 1 or 2 byte varint into the equivalent value upon a direct load.
-  static uint32 SmallVarintValue(uint32 x) {
-    GOOGLE_DCHECK(x < 128 * 128);
-    if (x >= 128) x += (x & 0xFF80) + 128;
-    return x;
-  }
-
-  static bool ShouldRepeat(const FieldDescriptor* descriptor,
-                           internal::WireFormatLite::WireType wiretype) {
-    constexpr int kMaxTwoByteFieldNumber = 16 * 128;
-    return descriptor->number() < kMaxTwoByteFieldNumber &&
-           descriptor->is_repeated() &&
-           (!descriptor->is_packable() ||
-            wiretype != internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-  }
-
-  void GenerateFieldBody(internal::WireFormatLite::WireType wiretype,
-                         const FieldDescriptor* field) {
-    uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype);
-    switch (wiretype) {
-      case WireFormatLite::WIRETYPE_VARINT: {
-        std::string type = PrimitiveTypeName(options_, field->cpp_type());
-        std::string prefix = field->is_repeated() ? "add" : "set";
-        if (field->type() == FieldDescriptor::TYPE_ENUM) {
-          format_(
-              "$uint64$ val = $pi_ns$::ReadVarint64(&ptr);\n"
-              "CHK_(ptr);\n");
-          if (!HasPreservingUnknownEnumSemantics(field)) {
-            format_("if (PROTOBUF_PREDICT_TRUE($1$_IsValid(val))) {\n",
-                    QualifiedClassName(field->enum_type(), options_));
-            format_.Indent();
-          }
-          format_("_internal_$1$_$2$(static_cast<$3$>(val));\n", prefix,
-                  FieldName(field),
-                  QualifiedClassName(field->enum_type(), options_));
-          if (!HasPreservingUnknownEnumSemantics(field)) {
-            format_.Outdent();
-            format_(
-                "} else {\n"
-                "  $pi_ns$::WriteVarint($1$, val, mutable_unknown_fields());\n"
-                "}\n",
-                field->number());
-          }
-        } else {
-          std::string size = (field->type() == FieldDescriptor::TYPE_SINT32 ||
-                              field->type() == FieldDescriptor::TYPE_UINT32)
-                                 ? "32"
-                                 : "64";
-          std::string zigzag;
-          if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
-               field->type() == FieldDescriptor::TYPE_SINT64)) {
-            zigzag = "ZigZag";
-          }
-          if (field->is_repeated() || field->real_containing_oneof()) {
-            std::string prefix = field->is_repeated() ? "add" : "set";
-            format_(
-                "_internal_$1$_$2$($pi_ns$::ReadVarint$3$$4$(&ptr));\n"
-                "CHK_(ptr);\n",
-                prefix, FieldName(field), zigzag, size);
-          } else {
-            if (HasHasbit(field)) {
-              format_("_Internal::set_has_$1$(&$has_bits$);\n",
-                      FieldName(field));
-            }
-            format_(
-                "$1$_ = $pi_ns$::ReadVarint$2$$3$(&ptr);\n"
-                "CHK_(ptr);\n",
-                FieldName(field), zigzag, size);
-          }
-        }
-        break;
-      }
-      case WireFormatLite::WIRETYPE_FIXED32:
-      case WireFormatLite::WIRETYPE_FIXED64: {
-        std::string type = PrimitiveTypeName(options_, field->cpp_type());
-        if (field->is_repeated() || field->real_containing_oneof()) {
-          std::string prefix = field->is_repeated() ? "add" : "set";
-          format_(
-              "_internal_$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n"
-              "ptr += sizeof($3$);\n",
-              prefix, FieldName(field), type);
-        } else {
-          if (HasHasbit(field)) {
-            format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
-          }
-          format_(
-              "$1$_ = $pi_ns$::UnalignedLoad<$2$>(ptr);\n"
-              "ptr += sizeof($2$);\n",
-              FieldName(field), type);
-        }
-        break;
-      }
-      case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
-        GenerateLengthDelim(field);
-        format_("CHK_(ptr);\n");
-        break;
-      }
-      case WireFormatLite::WIRETYPE_START_GROUP: {
-        format_(
-            "ptr = ctx->ParseGroup(_internal_$1$_$2$(), ptr, $3$);\n"
-            "CHK_(ptr);\n",
-            field->is_repeated() ? "add" : "mutable", FieldName(field), tag);
-        break;
-      }
-      case WireFormatLite::WIRETYPE_END_GROUP: {
-        GOOGLE_LOG(FATAL) << "Can't have end group field\n";
-        break;
-      }
-    }  // switch (wire_type)
-  }
-
-  // Returns the tag for this field and in case of repeated packable fields,
-  // sets a fallback tag in fallback_tag_ptr.
-  static uint32 ExpectedTag(const FieldDescriptor* field,
-                            uint32* fallback_tag_ptr) {
-    uint32 expected_tag;
-    if (field->is_packable()) {
-      auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
-      expected_tag =
-          WireFormatLite::MakeTag(field->number(), expected_wiretype);
-      GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-      auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
-      uint32 fallback_tag =
-          WireFormatLite::MakeTag(field->number(), fallback_wiretype);
-
-      if (field->is_packed()) std::swap(expected_tag, fallback_tag);
-      *fallback_tag_ptr = fallback_tag;
-    } else {
-      auto expected_wiretype = WireFormat::WireTypeForField(field);
-      expected_tag =
-          WireFormatLite::MakeTag(field->number(), expected_wiretype);
-    }
-    return expected_tag;
-  }
-
-  void GenerateParseLoop(
-      const Descriptor* descriptor,
-      const std::vector<const FieldDescriptor*>& ordered_fields) {
-    format_(
-        "while (!ctx->Done(&ptr)) {\n"
-        "  $uint32$ tag;\n"
-        "  ptr = $pi_ns$::ReadTag(ptr, &tag);\n"
-        "  CHK_(ptr);\n");
-    if (!ordered_fields.empty()) format_("  switch (tag >> 3) {\n");
-
-    format_.Indent();
-    format_.Indent();
-
-    for (const auto* field : ordered_fields) {
-      PrintFieldComment(format_, field);
-      format_("case $1$:\n", field->number());
-      format_.Indent();
-      uint32 fallback_tag = 0;
-      uint32 expected_tag = ExpectedTag(field, &fallback_tag);
-      format_(
-          "if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
-          expected_tag & 0xFF);
-      format_.Indent();
-      auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
-      uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype);
-      int tag_size = io::CodedOutputStream::VarintSize32(tag);
-      bool is_repeat = ShouldRepeat(field, wiretype);
-      if (is_repeat) {
-        format_(
-            "ptr -= $1$;\n"
-            "do {\n"
-            "  ptr += $1$;\n",
-            tag_size);
-        format_.Indent();
-      }
-      GenerateFieldBody(wiretype, field);
-      if (is_repeat) {
-        format_.Outdent();
-        format_(
-            "  if (!ctx->DataAvailable(ptr)) break;\n"
-            "} while ($pi_ns$::ExpectTag<$1$>(ptr));\n",
-            tag);
-      }
-      format_.Outdent();
-      if (fallback_tag) {
-        format_("} else if (static_cast<$uint8$>(tag) == $1$) {\n",
-                fallback_tag & 0xFF);
-        format_.Indent();
-        GenerateFieldBody(WireFormatLite::GetTagWireType(fallback_tag), field);
-        format_.Outdent();
-      }
-      format_.Outdent();
-      format_(
-          "  } else goto handle_unusual;\n"
-          "  continue;\n");
-    }  // for loop over ordered fields
-
-    // Default case
-    if (!ordered_fields.empty()) format_("default: {\n");
-    if (!ordered_fields.empty()) format_("handle_unusual:\n");
-    format_(
-        "  if ((tag & 7) == 4 || tag == 0) {\n"
-        "    ctx->SetLastTag(tag);\n"
-        "    goto success;\n"
-        "  }\n");
-    if (IsMapEntryMessage(descriptor)) {
-      format_("  continue;\n");
-    } else {
-      if (descriptor->extension_range_count() > 0) {
-        format_("if (");
-        for (int i = 0; i < descriptor->extension_range_count(); i++) {
-          const Descriptor::ExtensionRange* range =
-              descriptor->extension_range(i);
-          if (i > 0) format_(" ||\n    ");
-
-          uint32 start_tag = WireFormatLite::MakeTag(
-              range->start, static_cast<WireFormatLite::WireType>(0));
-          uint32 end_tag = WireFormatLite::MakeTag(
-              range->end, static_cast<WireFormatLite::WireType>(0));
-
-          if (range->end > FieldDescriptor::kMaxNumber) {
-            format_("($1$u <= tag)", start_tag);
-          } else {
-            format_("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
-          }
-        }
-        format_(") {\n");
-        format_(
-            "  ptr = _extensions_.ParseField(tag, ptr,\n"
-            "      internal_default_instance(), &_internal_metadata_, ctx);\n"
-            "  CHK_(ptr != nullptr);\n"
-            "  continue;\n"
-            "}\n");
-      }
-      format_(
-          "  ptr = UnknownFieldParse(tag,\n"
-          "      _internal_metadata_.mutable_unknown_fields<$unknown_"
-          "fields_type$>(),\n"
-          "      ptr, ctx);\n"
-          "  CHK_(ptr != nullptr);\n"
-          "  continue;\n");
-    }
-    if (!ordered_fields.empty()) format_("}\n");  // default case
-    format_.Outdent();
-    format_.Outdent();
-    if (!ordered_fields.empty()) format_("  }  // switch\n");
-    format_("}  // while\n");
-  }
-};
-
-void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits,
-                        const Options& options,
-                        MessageSCCAnalyzer* scc_analyzer,
-                        io::Printer* printer) {
-  ParseLoopGenerator generator(num_hasbits, options, scc_analyzer, printer);
-  generator.GenerateParserLoop(descriptor);
-}
-
 static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file,
                                  const Options& options,
                                  bool* has_opt_codesize_extension) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 988e609..247c161 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -36,11 +36,13 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
 
 #include <algorithm>
+#include <cstdint>
 #include <iterator>
 #include <map>
 #include <string>
 
 #include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/cpp_names.h>
 #include <google/protobuf/compiler/scc.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -57,7 +59,7 @@
 namespace compiler {
 namespace cpp {
 
-inline std::string ProtobufNamespace(const Options& options) {
+inline std::string ProtobufNamespace(const Options& /* options */) {
   return "PROTOBUF_NAMESPACE_ID";
 }
 
@@ -65,12 +67,12 @@
   return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF";
 }
 
-inline std::string DeprecatedAttribute(const Options& options,
+inline std::string DeprecatedAttribute(const Options& /* options */,
                                        const FieldDescriptor* d) {
   return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : "";
 }
 
-inline std::string DeprecatedAttribute(const Options& options,
+inline std::string DeprecatedAttribute(const Options& /* options */,
                                        const EnumValueDescriptor* d) {
   return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : "";
 }
@@ -83,9 +85,9 @@
 void SetCommonVars(const Options& options,
                    std::map<std::string, std::string>* variables);
 
-void SetUnknkownFieldsVariable(const Descriptor* descriptor,
-                               const Options& options,
-                               std::map<std::string, std::string>* variables);
+void SetUnknownFieldsVariable(const Descriptor* descriptor,
+                              const Options& options,
+                              std::map<std::string, std::string>* variables);
 
 bool GetBootstrapBasename(const Options& options, const std::string& basename,
                           std::string* bootstrap_basename);
@@ -134,6 +136,10 @@
                    : ClassName(descriptor);
 }
 
+// Returns the extension name prefixed with the class name if nested but without
+// the package name.
+std::string ExtensionName(const FieldDescriptor* d);
+
 std::string QualifiedExtensionName(const FieldDescriptor* d,
                                    const Options& options);
 std::string QualifiedExtensionName(const FieldDescriptor* d);
@@ -180,9 +186,6 @@
 // anyway, so normally this just returns field->name().
 std::string FieldName(const FieldDescriptor* field);
 
-// Get the sanitized name that should be used for the given enum in C++ code.
-std::string EnumValueName(const EnumValueDescriptor* enum_value);
-
 // Returns an estimate of the compiler's alignment for 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
@@ -205,9 +208,6 @@
 std::string FieldMessageTypeName(const FieldDescriptor* field,
                                  const Options& options);
 
-// Strips ".proto" or ".protodevel" from the end of a filename.
-PROTOC_EXPORT std::string StripProto(const std::string& filename);
-
 // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
 const char* PrimitiveTypeName(FieldDescriptor::CppType type);
 std::string PrimitiveTypeName(const Options& options,
@@ -220,9 +220,6 @@
 // Return the code that evaluates to the number when compiled.
 std::string Int32ToString(int number);
 
-// Return the code that evaluates to the number when compiled.
-std::string Int64ToString(const Options& options, int64 number);
-
 // Get code that evaluates to the field's default value.
 std::string DefaultValue(const Options& options, const FieldDescriptor* field);
 
@@ -318,8 +315,6 @@
   return false;
 }
 
-bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
-
 // For a string field, returns the effective ctype.  If the actual ctype is
 // not supported, returns the default of STRING.
 FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field,
@@ -336,23 +331,41 @@
          EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
 }
 
+class MessageSCCAnalyzer;
+
 // Does the given FileDescriptor use lazy fields?
-bool HasLazyFields(const FileDescriptor* file, const Options& options);
+bool HasLazyFields(const FileDescriptor* file, const Options& options,
+                   MessageSCCAnalyzer* scc_analyzer);
 
 // Is the given field a supported lazy field?
-inline bool IsLazy(const FieldDescriptor* field, const Options& options) {
+bool IsLazy(const FieldDescriptor* field, const Options& options,
+            MessageSCCAnalyzer* scc_analyzer);
+
+inline bool IsLazilyVerifiedLazy(const FieldDescriptor* field,
+                                 const Options& options) {
   return field->options().lazy() && !field->is_repeated() &&
          field->type() == FieldDescriptor::TYPE_MESSAGE &&
          GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME &&
          !options.opensource_runtime;
 }
 
-// Returns true if "field" is used.
-inline bool IsFieldUsed(const FieldDescriptor* /*field*/,
-                        const Options& /*options*/) {
+inline bool IsEagerlyVerifiedLazy(const FieldDescriptor* field,
+                                  const Options& options,
+                                  MessageSCCAnalyzer* scc_analyzer) {
+  return IsLazy(field, options, scc_analyzer) && !field->options().lazy();
+}
+
+inline bool IsFieldUsed(const FieldDescriptor* /* field */,
+                        const Options& options) {
   return true;
 }
 
+// Returns true if "field" is stripped.
+inline bool IsFieldStripped(const FieldDescriptor* /*field*/,
+                            const Options& /*options*/) {
+  return false;
+}
+
 // Does the file contain any definitions that need extension_set.h?
 bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
 
@@ -406,14 +419,6 @@
          descriptor->full_name() == "google.protobuf.bridge.MessageSet";
 }
 
-inline bool IsProto2MessageSetFile(const FileDescriptor* file,
-                                   const Options& options) {
-  return !options.opensource_runtime &&
-         options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
-         !options.lite_implicit_weak_fields &&
-         file->name() == "net/proto2/bridge/proto/message_set.proto";
-}
-
 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
   return descriptor->options().map_entry();
 }
@@ -424,8 +429,8 @@
 std::string UnderscoresToCamelCase(const std::string& input,
                                    bool cap_next_letter);
 
-inline bool HasFieldPresence(const FileDescriptor* file) {
-  return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+inline bool IsProto3(const FileDescriptor* file) {
+  return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
 }
 
 inline bool HasHasbit(const FieldDescriptor* field) {
@@ -450,27 +455,11 @@
   return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
 }
 
-inline bool SupportsArenas(const FileDescriptor* file) {
-  return file->options().cc_enable_arenas();
-}
-
-inline bool SupportsArenas(const Descriptor* desc) {
-  return SupportsArenas(desc->file());
-}
-
-inline bool SupportsArenas(const FieldDescriptor* field) {
-  return SupportsArenas(field->file());
-}
-
 inline bool IsCrossFileMessage(const FieldDescriptor* field) {
   return field->type() == FieldDescriptor::TYPE_MESSAGE &&
          field->message_type()->file() != field->file();
 }
 
-inline std::string MessageCreateFunction(const Descriptor* d) {
-  return SupportsArenas(d) ? "CreateMessage" : "Create";
-}
-
 inline std::string MakeDefaultName(const FieldDescriptor* field) {
   return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
          "_";
@@ -551,8 +540,8 @@
 // given field.
 inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
                                                   const Options& options) {
-  // Do not check "required" for lazy fields.
-  return IsLazy(field, options);
+  // Do not check "required" for lazily verified lazy fields.
+  return IsLazilyVerifiedLazy(field, options);
 }
 
 struct MessageAnalysis {
@@ -560,7 +549,7 @@
   bool contains_cord;
   bool contains_extension;
   bool contains_required;
-  bool constructor_requires_initialization;
+  bool contains_weak;  // Implicit weak as well.
 };
 
 // This class is used in FileGenerator, to ensure linear instead of
@@ -577,6 +566,10 @@
     MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
     return result.contains_required || result.contains_extension;
   }
+  bool HasWeakField(const Descriptor* descriptor) {
+    MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
+    return result.contains_weak;
+  }
   const SCC* GetSCC(const Descriptor* descriptor) {
     return analyzer_.GetSCC(descriptor);
   }
@@ -598,16 +591,6 @@
   std::map<const SCC*, MessageAnalysis> analysis_cache_;
 };
 
-inline std::string SccInfoSymbol(const SCC* scc, const Options& options) {
-  return UniqueName("scc_info_" + ClassName(scc->GetRepresentative()),
-                    scc->GetRepresentative(), options);
-}
-
-inline std::string SccInfoPtrSymbol(const SCC* scc, const Options& options) {
-  return UniqueName("scc_info_ptr_" + ClassName(scc->GetRepresentative()),
-                    scc->GetRepresentative(), options);
-}
-
 void ListAllFields(const Descriptor* d,
                    std::vector<const FieldDescriptor*>* fields);
 void ListAllFields(const FileDescriptor* d,
@@ -746,8 +729,8 @@
     std::vector<int> path;
     descriptor->GetLocationPath(&path);
     GeneratedCodeInfo::Annotation annotation;
-    for (int i = 0; i < path.size(); ++i) {
-      annotation.add_path(path[i]);
+    for (int index : path) {
+      annotation.add_path(index);
     }
     annotation.set_source_file(descriptor->file()->name());
     return annotation.SerializeAsString();
@@ -779,21 +762,22 @@
   void ChangeTo(const std::string& name) {
     std::vector<std::string> new_stack_ =
         Split(name, "::", true);
-    int len = std::min(name_stack_.size(), new_stack_.size());
-    int common_idx = 0;
+    size_t len = std::min(name_stack_.size(), new_stack_.size());
+    size_t common_idx = 0;
     while (common_idx < len) {
       if (name_stack_[common_idx] != new_stack_[common_idx]) break;
       common_idx++;
     }
-    for (int i = name_stack_.size() - 1; i >= common_idx; i--) {
-      if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
+    for (auto it = name_stack_.crbegin();
+         it != name_stack_.crend() - common_idx; ++it) {
+      if (*it == "PROTOBUF_NAMESPACE_ID") {
         printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n");
       } else {
-        printer_->Print("}  // namespace $ns$\n", "ns", name_stack_[i]);
+        printer_->Print("}  // namespace $ns$\n", "ns", *it);
       }
     }
     name_stack_.swap(new_stack_);
-    for (int i = common_idx; i < name_stack_.size(); i++) {
+    for (size_t i = common_idx; i < name_stack_.size(); ++i) {
       if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
         printer_->Print("PROTOBUF_NAMESPACE_OPEN\n");
       } else {
@@ -807,10 +791,10 @@
   std::vector<std::string> name_stack_;
 };
 
-enum Utf8CheckMode {
-  STRICT = 0,  // Parsing will fail if non UTF-8 data is in string fields.
-  VERIFY = 1,  // Only log an error but parsing will succeed.
-  NONE = 2,    // No UTF-8 check.
+enum class Utf8CheckMode {
+  kStrict = 0,  // Parsing will fail if non UTF-8 data is in string fields.
+  kVerify = 1,  // Only log an error but parsing will succeed.
+  kNone = 2,    // No UTF-8 check.
 };
 
 Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
@@ -898,9 +882,9 @@
 
 inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
 
-void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits,
-                        const Options& options,
-                        MessageSCCAnalyzer* scc_analyzer, io::Printer* printer);
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
+inline bool EnableMessageOwnedArena(const Descriptor* desc) { return false; }
 
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index bea315e..49f65f3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -29,6 +29,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <google/protobuf/compiler/cpp/cpp_map_field.h>
+
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
@@ -80,13 +81,6 @@
   } else {
     (*variables)["lite"] = "Lite";
   }
-
-  if (!IsProto3Field(descriptor) && val->type() == FieldDescriptor::TYPE_ENUM) {
-    const EnumValueDescriptor* default_value = val->default_value_enum();
-    (*variables)["default_enum_value"] = Int32ToString(default_value->number());
-  } else {
-    (*variables)["default_enum_value"] = "0";
-  }
 }
 
 MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
@@ -104,8 +98,8 @@
       "    $map_classname$,\n"
       "    $key_cpp$, $val_cpp$,\n"
       "    ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
-      "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n"
-      "    $default_enum_value$ > $name$_;\n");
+      "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
+      "$name$_;\n");
 }
 
 void MapFieldGenerator::GenerateAccessorDeclarations(
@@ -135,7 +129,7 @@
       "}\n"
       "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
       "$classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_map:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
@@ -145,7 +139,7 @@
       "}\n"
       "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
       "$classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "$annotate_mutable$"
       "  // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
       "  return _internal_mutable_$name$();\n"
       "}\n");
@@ -163,7 +157,7 @@
 
 void MapFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  format("$name$_.Swap(&other->$name$_);\n");
+  format("$name$_.InternalSwap(&other->$name$_);\n");
 }
 
 void MapFieldGenerator::GenerateCopyConstructorCode(
@@ -235,7 +229,10 @@
   if (utf8_check) {
     format(
         "struct Utf8Check {\n"
-        "  static void Check(ConstPtr p) {\n");
+        "  static void Check(ConstPtr p) {\n"
+        // p may be unused when GetUtf8CheckMode evaluates to kNone,
+        // thus disabling the validation.
+        "    (void)p;\n");
     format.Indent();
     format.Indent();
     if (string_key) {
@@ -296,6 +293,29 @@
       "}\n");
 }
 
+void MapFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    format("$name$_(::$proto_ns$::internal::ConstantInitialized{})");
+  } else {
+    format("$name$_()");
+  }
+}
+
+bool MapFieldGenerator::GenerateArenaDestructorCode(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    // _this is the object being destructed (we are inside a static method
+    // here).
+    format("_this->$name$_. ~MapField();\n");
+    return true;
+  } else {
+    return false;
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index e0c14f3..5ea0429 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -47,16 +47,19 @@
   ~MapFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const {}
-  void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override {}
+  void GenerateCopyConstructorCode(io::Printer* printer) const override;
+  void GenerateSerializeWithCachedSizesToArray(
+      io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
+  bool GenerateArenaDestructorCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 1cc0891..79ed8aa 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/cpp/cpp_message.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <functional>
 #include <map>
 #include <memory>
@@ -47,6 +48,7 @@
 #include <google/protobuf/compiler/cpp/cpp_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
+#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/printer.h>
@@ -59,6 +61,9 @@
 #include <google/protobuf/stubs/hash.h>
 
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -76,7 +81,7 @@
 // masks is allowed to be shorter than _has_bits_, but at least one element of
 // masks must be non-zero.
 std::string ConditionalToCheckBitmasks(
-    const std::vector<uint32>& masks, bool return_success = true,
+    const std::vector<uint32_t>& masks, bool return_success = true,
     StringPiece has_bits_var = "_has_bits_") {
   std::vector<std::string> parts;
   for (int i = 0; i < masks.size(); i++) {
@@ -163,14 +168,16 @@
 // Anything that is a POD or a "normal" message (represented by a pointer) can
 // be manipulated as raw bytes.
 bool CanBeManipulatedAsRawBytes(const FieldDescriptor* field,
-                                const Options& options) {
+                                const Options& options,
+                                MessageSCCAnalyzer* scc_analyzer) {
   bool ret = CanInitializeByZeroing(field);
 
   // Non-repeated, non-lazy message fields are simply raw pointers, so we can
   // swap them or use memset to initialize these in SharedCtor. We cannot use
   // this in Clear, as we need to potentially delete the existing value.
-  ret = ret || (!field->is_repeated() && !IsLazy(field, options) &&
-                field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+  ret =
+      ret || (!field->is_repeated() && !IsLazy(field, options, scc_analyzer) &&
+              field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
   return ret;
 }
 
@@ -213,16 +220,18 @@
   // if non-zero (numeric) or non-empty (string).
   if (!field->is_repeated() && !field->containing_oneof()) {
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
-      format("if ($prefix$$name$().size() > 0) {\n");
+      format("if (!$prefix$_internal_$name$().empty()) {\n");
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       // Message fields still have has_$name$() methods.
-      format("if ($prefix$has_$name$()) {\n");
+      format("if ($prefix$_internal_has_$name$()) {\n");
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE ||
                field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT) {
       // Handle float comparison to prevent -Wfloat-equal warnings
-      format("if (!($prefix$$name$() <= 0 && $prefix$$name$() >= 0)) {\n");
+      format(
+          "if (!($prefix$_internal_$name$() <= 0 && $prefix$_internal_$name$() "
+          ">= 0)) {\n");
     } else {
-      format("if ($prefix$$name$() != 0) {\n");
+      format("if ($prefix$_internal_$name$() != 0) {\n");
     }
     format.Indent();
     return true;
@@ -236,14 +245,14 @@
 
 // Does the given field have a has_$name$() method?
 bool HasHasMethod(const FieldDescriptor* field) {
-  if (HasFieldPresence(field->file())) {
+  if (!IsProto3(field->file())) {
     // In proto1/proto2, every field has a has_$name$() method.
     return true;
   }
   // For message types without true field presence, only fields with a message
-  // type have a has_$name$() method.
+  // type or inside an one-of have a has_$name$() method.
   return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
-         field->has_optional_keyword();
+         field->has_optional_keyword() || field->real_containing_oneof();
 }
 
 // Collects map entry message type information.
@@ -268,13 +277,6 @@
       "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
   vars["val_wire_type"] =
       "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type()));
-  if (descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
-      val->type() == FieldDescriptor::TYPE_ENUM) {
-    const EnumValueDescriptor* default_value = val->default_value_enum();
-    vars["default_enum_value"] = Int32ToString(default_value->number());
-  } else {
-    vars["default_enum_value"] = "0";
-  }
 }
 
 // Does the given field have a private (internal helper only) has_$name$()
@@ -282,7 +284,7 @@
 bool HasPrivateHasMethod(const FieldDescriptor* field) {
   // Only for oneofs in message types with no field presence. has_$name$(),
   // based on the oneof case, is still useful internally for generated code.
-  return (!HasFieldPresence(field->file()) && field->real_containing_oneof());
+  return IsProto3(field->file()) && field->real_containing_oneof();
 }
 
 // TODO(ckennelly):  Cull these exclusions if/when these protos do not have
@@ -303,28 +305,20 @@
          options.opensource_runtime;
 }
 
-bool ShouldMarkIsInitializedAsFinal(const Descriptor* descriptor,
-                                    const Options& options) {
-  static std::set<std::string> exclusions{
-  };
-
-  const std::string name = ClassName(descriptor, true);
-  return exclusions.find(name) == exclusions.end() ||
-         options.opensource_runtime;
-}
-
-bool ShouldMarkNewAsFinal(const Descriptor* descriptor,
-                          const Options& options) {
-  static std::set<std::string> exclusions{
-  };
-
-  const std::string name = ClassName(descriptor, true);
-  return exclusions.find(name) == exclusions.end() ||
-         options.opensource_runtime;
+// Returns true to make the message serialize in order, decided by the following
+// factors in the order of precedence.
+// --options().message_set_wire_format() == true
+// --the message is in the allowlist (true)
+// --GOOGLE_PROTOBUF_SHUFFLE_SERIALIZE is defined (false)
+// --a ranage of message names that are allowed to stay in order (true)
+bool ShouldSerializeInOrder(const Descriptor* descriptor,
+                            const Options& options) {
+  return true;
 }
 
 bool TableDrivenParsingEnabled(const Descriptor* descriptor,
-                               const Options& options) {
+                               const Options& options,
+                               MessageSCCAnalyzer* scc_analyzer) {
   if (!options.table_driven_parsing) {
     return false;
   }
@@ -355,7 +349,7 @@
     }
 
     // - There are no lazy fields (they require the non-lite library).
-    if (IsLazy(field, options)) {
+    if (IsLazy(field, options, scc_analyzer)) {
       return false;
     }
   }
@@ -421,23 +415,23 @@
 // Returns a bit mask based on has_bit index of "fields" that are typically on
 // the same chunk. It is used in a group presence check where _has_bits_ is
 // masked to tell if any thing in "fields" is present.
-uint32 GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
-                    const std::vector<int>& has_bit_indices) {
+uint32_t GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
+                      const std::vector<int>& has_bit_indices) {
   GOOGLE_CHECK(!fields.empty());
   int first_index_offset = has_bit_indices[fields.front()->index()] / 32;
-  uint32 chunk_mask = 0;
+  uint32_t chunk_mask = 0;
   for (auto field : fields) {
     // "index" defines where in the _has_bits_ the field appears.
     int index = has_bit_indices[field->index()];
     GOOGLE_CHECK_EQ(first_index_offset, index / 32);
-    chunk_mask |= static_cast<uint32>(1) << (index % 32);
+    chunk_mask |= static_cast<uint32_t>(1) << (index % 32);
   }
   GOOGLE_CHECK_NE(0, chunk_mask);
   return chunk_mask;
 }
 
 // Return the number of bits set in n, a non-negative integer.
-static int popcnt(uint32 n) {
+static int popcnt(uint32_t n) {
   int result = 0;
   while (n != 0) {
     result += (n & 1);
@@ -523,7 +517,7 @@
   format("if (PROTOBUF_PREDICT_FALSE(");
   int first_word = HasbitWord(chunk, 0);
   while (chunk < limit_chunk_) {
-    uint32 mask = 0;
+    uint32_t mask = 0;
     int this_word = HasbitWord(chunk, 0);
     // Generate mask for chunks on the same word.
     for (; chunk < limit_chunk_ && HasbitWord(chunk, 0) == this_word; chunk++) {
@@ -583,15 +577,48 @@
   // Variables that apply to this class
   variables_["classname"] = classname_;
   variables_["classtype"] = QualifiedClassName(descriptor_, options);
-  variables_["scc_info"] =
-      SccInfoSymbol(scc_analyzer_->GetSCC(descriptor_), options_);
   variables_["full_name"] = descriptor_->full_name();
   variables_["superclass"] = SuperClassName(descriptor_, options_);
+  variables_["annotate_serialize"] = "";
+  variables_["annotate_deserialize"] = "";
+  variables_["annotate_reflection"] = "";
+  variables_["annotate_bytesize"] = "";
+
+  if (options.inject_field_listener_events &&
+      descriptor->file()->options().optimize_for() !=
+          google::protobuf::FileOptions::LITE_RUNTIME) {
+    const std::string injector_template = StrCat(
+        "  {\n"
+        "    auto _listener_ = ::",
+        variables_["proto_ns"],
+        "::FieldAccessListener::GetListener();\n"
+        "    if (_listener_) ");
+
+    StrAppend(&variables_["annotate_serialize"], injector_template,
+                    "_listener_->OnSerializationAccess(this);\n"
+                    "  }\n");
+    StrAppend(&variables_["annotate_deserialize"], injector_template,
+                    " _listener_->OnDeserializationAccess(this);\n"
+                    "  }\n");
+    // TODO(danilak): Ideally annotate_reflection should not exist and we need
+    // to annotate all reflective calls on our own, however, as this is a cause
+    // for side effects, i.e. reading values dynamically, we want the users know
+    // that dynamic access can happen.
+    StrAppend(&variables_["annotate_reflection"], injector_template,
+                    "_listener_->OnReflectionAccess(default_instance()"
+                    ".GetMetadata().descriptor);\n"
+                    "  }\n");
+    StrAppend(&variables_["annotate_bytesize"], injector_template,
+                    "_listener_->OnByteSizeAccess(this);\n"
+                    "  }\n");
+  }
+
+  SetUnknownFieldsVariable(descriptor_, options_, &variables_);
 
   // Compute optimized field order to be used for layout and initialization
   // purposes.
   for (auto field : FieldRange(descriptor_)) {
-    if (!IsFieldUsed(field, options_)) {
+    if (IsFieldStripped(field, options_)) {
       continue;
     }
 
@@ -602,7 +629,8 @@
     }
   }
 
-  message_layout_helper_->OptimizeLayout(&optimized_order_, options_);
+  message_layout_helper_->OptimizeLayout(&optimized_order_, options_,
+                                         scc_analyzer_);
 
   // This message has hasbits iff one or more fields need one.
   for (auto field : optimized_order_) {
@@ -614,7 +642,6 @@
     }
   }
 
-
   if (!has_bit_indices_.empty()) {
     field_generators_.SetHasBitIndices(has_bit_indices_);
   }
@@ -626,22 +653,17 @@
     }
   }
 
-  table_driven_ = TableDrivenParsingEnabled(descriptor_, options_);
+  table_driven_ =
+      TableDrivenParsingEnabled(descriptor_, options_, scc_analyzer_);
+  parse_function_generator_.reset(new ParseFunctionGenerator(
+      descriptor_, max_has_bit_index_, has_bit_indices_, options_,
+      scc_analyzer_, variables_));
 }
 
 MessageGenerator::~MessageGenerator() = default;
 
 size_t MessageGenerator::HasBitsSize() const {
-  size_t sizeof_has_bits = (max_has_bit_index_ + 31) / 32 * 4;
-  if (sizeof_has_bits == 0) {
-    // Zero-size arrays aren't technically allowed, and MSVC in particular
-    // doesn't like them.  We still need to declare these arrays to make
-    // other code compile.  Since this is an uncommon case, we'll just declare
-    // them with size 1 and waste some space.  Oh well.
-    sizeof_has_bits = 4;
-  }
-
-  return sizeof_has_bits;
+  return (max_has_bit_index_ + 31) / 32;
 }
 
 int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const {
@@ -690,7 +712,7 @@
                         optimized_order_.end());
   for (auto field : FieldRange(descriptor_)) {
     if (!field->real_containing_oneof() && !field->options().weak() &&
-        IsFieldUsed(field, options_)) {
+        !IsFieldStripped(field, options_)) {
       continue;
     }
     ordered_fields.push_back(field);
@@ -719,8 +741,8 @@
 
     if (field->is_repeated()) {
       format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field,
-             IsFieldUsed(field, options_) ? ";" : " {__builtin_trap();}");
-      if (IsFieldUsed(field, options_)) {
+             !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
+      if (!IsFieldStripped(field, options_)) {
         format(
             "private:\n"
             "int ${1$_internal_$name$_size$}$() const;\n"
@@ -729,15 +751,15 @@
       }
     } else if (HasHasMethod(field)) {
       format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field,
-             IsFieldUsed(field, options_) ? ";" : " {__builtin_trap();}");
-      if (IsFieldUsed(field, options_)) {
+             !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
+      if (!IsFieldStripped(field, options_)) {
         format(
             "private:\n"
             "bool _internal_has_$name$() const;\n"
             "public:\n");
       }
     } else if (HasPrivateHasMethod(field)) {
-      if (IsFieldUsed(field, options_)) {
+      if (!IsFieldStripped(field, options_)) {
         format(
             "private:\n"
             "bool ${1$_internal_has_$name$$}$() const;\n"
@@ -746,7 +768,7 @@
       }
     }
     format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field,
-           IsFieldUsed(field, options_) ? ";" : "{__builtin_trap();}");
+           !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}");
 
     // Generate type-specific accessor declarations.
     field_generators_.get(field).GenerateAccessorDeclarations(printer);
@@ -781,7 +803,7 @@
 
 void MessageGenerator::GenerateSingularFieldHasBits(
     const FieldDescriptor* field, Formatter format) {
-  if (!IsFieldUsed(field, options_)) {
+  if (IsFieldStripped(field, options_)) {
     format(
         "inline bool $classname$::has_$name$() const { "
         "__builtin_trap(); }\n");
@@ -790,7 +812,7 @@
   if (field->options().weak()) {
     format(
         "inline bool $classname$::has_$name$() const {\n"
-        "$annotate_accessor$"
+        "$annotate_has$"
         "  return _weak_field_map_.Has($number$);\n"
         "}\n");
     return;
@@ -808,7 +830,7 @@
         "(_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n");
 
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
-        !IsLazy(field, options_)) {
+        !IsLazy(field, options_, scc_analyzer_)) {
       // We maintain the invariant that for a submessage x, has_x() returning
       // true implies that x_ is not null. By giving this information to the
       // compiler, we allow it to eliminate unnecessary null checks later on.
@@ -819,12 +841,12 @@
         "  return value;\n"
         "}\n"
         "inline bool $classname$::has_$name$() const {\n"
-        "$annotate_accessor$"
+        "$annotate_has$"
         "  return _internal_has_$name$();\n"
         "}\n");
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     // Message fields have a has_$name$() method.
-    if (IsLazy(field, options_)) {
+    if (IsLazy(field, options_, scc_analyzer_)) {
       format(
           "inline bool $classname$::_internal_has_$name$() const {\n"
           "  return !$name$_.IsCleared();\n"
@@ -838,7 +860,7 @@
     }
     format(
         "inline bool $classname$::has_$name$() const {\n"
-        "$annotate_accessor$"
+        "$annotate_has$"
         "  return _internal_has_$name$();\n"
         "}\n");
   }
@@ -862,7 +884,7 @@
 
 void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
                                                   const Formatter& format) {
-  if (!IsFieldUsed(field, options_)) {
+  if (IsFieldStripped(field, options_)) {
     if (HasHasMethod(field)) {
       format(
           "inline bool $classname$::has_$name$() const { "
@@ -888,7 +910,7 @@
         "  return $oneof_name$_case() == k$field_name$;\n"
         "}\n"
         "inline bool $classname$::has_$name$() const {\n"
-        "$annotate_accessor$"
+        "$annotate_has$"
         "  return _internal_has_$name$();\n"
         "}\n");
   } else if (HasPrivateHasMethod(field)) {
@@ -907,7 +929,7 @@
 
 void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
                                           bool is_inline, Formatter format) {
-  if (!IsFieldUsed(field, options_)) {
+  if (IsFieldStripped(field, options_)) {
     format("void $classname$::clear_$name$() { __builtin_trap(); }\n");
     return;
   }
@@ -916,9 +938,7 @@
   if (is_inline) {
     format("inline ");
   }
-  format(
-      "void $classname$::clear_$name$() {\n"
-      "$annotate_accessor$");
+  format("void $classname$::clear_$name$() {\n");
 
   format.Indent();
 
@@ -941,7 +961,7 @@
       format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n");
     }
   }
-
+  format("$annotate_clear$");
   format.Outdent();
   format("}\n");
 }
@@ -953,7 +973,7 @@
   for (auto field : FieldRange(descriptor_)) {
     PrintFieldComment(format, field);
 
-    if (!IsFieldUsed(field, options_)) {
+    if (IsFieldStripped(field, options_)) {
       continue;
     }
 
@@ -965,7 +985,7 @@
 
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
-      if (!IsFieldUsed(field, options_)) {
+      if (IsFieldStripped(field, options_)) {
         format(
             "inline int $classname$::$name$_size() const { "
             "__builtin_trap(); }\n");
@@ -975,7 +995,7 @@
             "  return $name$_$1$.size();\n"
             "}\n"
             "inline int $classname$::$name$_size() const {\n"
-            "$annotate_accessor$"
+            "$annotate_size$"
             "  return _internal_$name$_size();\n"
             "}\n",
             IsImplicitWeakField(field, options_, scc_analyzer_) &&
@@ -999,7 +1019,7 @@
     }
 
     // Generate type-specific accessors.
-    if (IsFieldUsed(field, options_)) {
+    if (!IsFieldStripped(field, options_)) {
       field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
     }
 
@@ -1012,9 +1032,8 @@
 
 void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
   Formatter format(printer, variables_);
-  format.Set("class_final", ShouldMarkClassAsFinal(descriptor_, options_)
-                                ? "PROTOBUF_FINAL"
-                                : "");
+  format.Set("class_final",
+             ShouldMarkClassAsFinal(descriptor_, options_) ? "final" : "");
 
   if (IsMapEntryMessage(descriptor_)) {
     std::map<std::string, std::string> vars;
@@ -1027,24 +1046,25 @@
         "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
         "    $key_cpp$, $val_cpp$,\n"
         "    ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
-        "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n"
-        "    $default_enum_value$ > {\n"
+        "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n"
         "public:\n"
         "  typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
         "    $key_cpp$, $val_cpp$,\n"
         "    ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
-        "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n"
-        "    $default_enum_value$ > SuperType;\n"
+        "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
+        "SuperType;\n"
         "  $classname$();\n"
-        "  $classname$(::$proto_ns$::Arena* arena);\n"
+        "  explicit constexpr $classname$(\n"
+        "      ::$proto_ns$::internal::ConstantInitialized);\n"
+        "  explicit $classname$(::$proto_ns$::Arena* arena);\n"
         "  void MergeFrom(const $classname$& other);\n"
         "  static const $classname$* internal_default_instance() { return "
         "reinterpret_cast<const "
         "$classname$*>(&_$classname$_default_instance_); }\n");
     auto utf8_check = GetUtf8CheckMode(descriptor_->field(0), options_);
     if (descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING &&
-        utf8_check != NONE) {
-      if (utf8_check == STRICT) {
+        utf8_check != Utf8CheckMode::kNone) {
+      if (utf8_check == Utf8CheckMode::kStrict) {
         format(
             "  static bool ValidateKey(std::string* s) {\n"
             "    return ::$proto_ns$::internal::WireFormatLite::"
@@ -1053,7 +1073,7 @@
             " }\n",
             descriptor_->field(0)->full_name());
       } else {
-        GOOGLE_CHECK(utf8_check == VERIFY);
+        GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
         format(
             "  static bool ValidateKey(std::string* s) {\n"
             "#ifndef NDEBUG\n"
@@ -1061,6 +1081,8 @@
             "       s->data(), static_cast<int>(s->size()), "
             "::$proto_ns$::internal::"
             "WireFormatLite::PARSE, \"$1$\");\n"
+            "#else\n"
+            "    (void) s;\n"
             "#endif\n"
             "    return true;\n"
             " }\n",
@@ -1070,8 +1092,8 @@
       format("  static bool ValidateKey(void*) { return true; }\n");
     }
     if (descriptor_->field(1)->type() == FieldDescriptor::TYPE_STRING &&
-        utf8_check != NONE) {
-      if (utf8_check == STRICT) {
+        utf8_check != Utf8CheckMode::kNone) {
+      if (utf8_check == Utf8CheckMode::kStrict) {
         format(
             "  static bool ValidateValue(std::string* s) {\n"
             "    return ::$proto_ns$::internal::WireFormatLite::"
@@ -1080,7 +1102,7 @@
             " }\n",
             descriptor_->field(1)->full_name());
       } else {
-        GOOGLE_CHECK(utf8_check = VERIFY);
+        GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
         format(
             "  static bool ValidateValue(std::string* s) {\n"
             "#ifndef NDEBUG\n"
@@ -1088,6 +1110,8 @@
             "       s->data(), static_cast<int>(s->size()), "
             "::$proto_ns$::internal::"
             "WireFormatLite::PARSE, \"$1$\");\n"
+            "#else\n"
+            "    (void) s;\n"
             "#endif\n"
             "    return true;\n"
             " }\n",
@@ -1098,20 +1122,11 @@
     }
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format(
-          "  void MergeFrom(const ::$proto_ns$::Message& other) final;\n"
-          "  ::$proto_ns$::Metadata GetMetadata() const final;\n"
-          "  private:\n"
-          "  static ::$proto_ns$::Metadata GetMetadataStatic() {\n"
-          "    ::$proto_ns$::internal::AssignDescriptors(&::$desc_table$);\n"
-          "    return ::$desc_table$.file_level_metadata[$1$];\n"
-          "  }\n"
-          "\n"
-          "  public:\n"
-          "};\n",
-          index_in_file_messages_);
-    } else {
-      format("};\n");
+          "  using ::$proto_ns$::Message::MergeFrom;\n"
+          ""
+          "  ::$proto_ns$::Metadata GetMetadata() const final;\n");
     }
+    format("};\n");
     return;
   }
 
@@ -1123,14 +1138,17 @@
   format(" public:\n");
   format.Indent();
 
-  if (SupportsArenas(descriptor_)) {
-    format("inline $classname$() : $classname$(nullptr) {};\n");
+  if (EnableMessageOwnedArena(descriptor_)) {
+    format(
+        "inline $classname$() : $classname$("
+        "new ::$proto_ns$::Arena(), true) {}\n");
   } else {
-    format("$classname$();\n");
+    format("inline $classname$() : $classname$(nullptr) {}\n");
   }
-
   format(
-      "virtual ~$classname$();\n"
+      "~$classname$() override;\n"
+      "explicit constexpr "
+      "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
       "\n"
       "$classname$(const $classname$& from);\n"
       "$classname$($classname$&& from) noexcept\n"
@@ -1143,8 +1161,9 @@
       "  return *this;\n"
       "}\n"
       "inline $classname$& operator=($classname$&& from) noexcept {\n"
-      "  if (GetArena() == from.GetArena()) {\n"
-      "    if (this != &from) InternalSwap(&from);\n"
+      "  if (this == &from) return *this;\n"
+      "  if (GetOwningArena() == from.GetOwningArena()) {\n"
+      "    InternalSwap(&from);\n"
       "  } else {\n"
       "    CopyFrom(from);\n"
       "  }\n"
@@ -1155,14 +1174,11 @@
   if (options_.table_driven_serialization) {
     format(
         "private:\n"
-        "const void* InternalGetTable() const;\n"
+        "const void* InternalGetTable() const override;\n"
         "public:\n"
         "\n");
   }
 
-  std::map<std::string, std::string> vars;
-  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
-  format.AddMap(vars);
   if (PublicUnknownFieldsAccessors(descriptor_)) {
     format(
         "inline const $unknown_fields_type$& unknown_fields() const {\n"
@@ -1194,16 +1210,18 @@
     // separately.
     format(
         "static const ::$proto_ns$::Descriptor* GetDescriptor() {\n"
-        "  return GetMetadataStatic().descriptor;\n"
+        "  return default_instance().GetMetadata().descriptor;\n"
         "}\n"
         "static const ::$proto_ns$::Reflection* GetReflection() {\n"
-        "  return GetMetadataStatic().reflection;\n"
+        "$annotate_reflection$"
+        "  return default_instance().GetMetadata().reflection;\n"
         "}\n");
   }
 
   format(
-      "static const $classname$& default_instance();\n"
-      "\n");
+      "static const $classname$& default_instance() {\n"
+      "  return *internal_default_instance();\n"
+      "}\n");
 
   // Generate enum values for every field in oneofs. One list is generated for
   // each oneof with an additional *_NOT_SET value.
@@ -1225,7 +1243,6 @@
 
   // TODO(gerbens) make this private, while still granting other protos access.
   format(
-      "static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY\n"
       "static inline const $classname$* internal_default_instance() {\n"
       "  return reinterpret_cast<const $classname$*>(\n"
       "             &_$classname$_default_instance_);\n"
@@ -1241,12 +1258,13 @@
         "\n");
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format(
-          "void PackFrom(const ::$proto_ns$::Message& message) {\n"
-          "  _any_metadata_.PackFrom(message);\n"
+          "bool PackFrom(const ::$proto_ns$::Message& message) {\n"
+          "  return _any_metadata_.PackFrom(GetArena(), message);\n"
           "}\n"
-          "void PackFrom(const ::$proto_ns$::Message& message,\n"
-          "              const std::string& type_url_prefix) {\n"
-          "  _any_metadata_.PackFrom(message, type_url_prefix);\n"
+          "bool PackFrom(const ::$proto_ns$::Message& message,\n"
+          "              ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+          "type_url_prefix) {\n"
+          "  return _any_metadata_.PackFrom(GetArena(), message, type_url_prefix);\n"
           "}\n"
           "bool UnpackTo(::$proto_ns$::Message* message) const {\n"
           "  return _any_metadata_.UnpackTo(message);\n"
@@ -1258,15 +1276,16 @@
           "template <typename T, class = typename std::enable_if<"
           "!std::is_convertible<T, const ::$proto_ns$::Message&>"
           "::value>::type>\n"
-          "void PackFrom(const T& message) {\n"
-          "  _any_metadata_.PackFrom<T>(message);\n"
+          "bool PackFrom(const T& message) {\n"
+          "  return _any_metadata_.PackFrom<T>(GetArena(), message);\n"
           "}\n"
           "template <typename T, class = typename std::enable_if<"
           "!std::is_convertible<T, const ::$proto_ns$::Message&>"
           "::value>::type>\n"
-          "void PackFrom(const T& message,\n"
-          "              const std::string& type_url_prefix) {\n"
-          "  _any_metadata_.PackFrom<T>(message, type_url_prefix);"
+          "bool PackFrom(const T& message,\n"
+          "              ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+          "type_url_prefix) {\n"
+          "  return _any_metadata_.PackFrom<T>(GetArena(), message, type_url_prefix);"
           "}\n"
           "template <typename T, class = typename std::enable_if<"
           "!std::is_convertible<T, const ::$proto_ns$::Message&>"
@@ -1277,13 +1296,14 @@
     } else {
       format(
           "template <typename T>\n"
-          "void PackFrom(const T& message) {\n"
-          "  _any_metadata_.PackFrom(message);\n"
+          "bool PackFrom(const T& message) {\n"
+          "  return _any_metadata_.PackFrom(message);\n"
           "}\n"
           "template <typename T>\n"
-          "void PackFrom(const T& message,\n"
-          "              const std::string& type_url_prefix) {\n"
-          "  _any_metadata_.PackFrom(message, type_url_prefix);\n"
+          "bool PackFrom(const T& message,\n"
+          "              ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+          "type_url_prefix) {\n"
+          "  return _any_metadata_.PackFrom(message, type_url_prefix);\n"
           "}\n"
           "template <typename T>\n"
           "bool UnpackTo(T* message) const {\n"
@@ -1294,50 +1314,43 @@
         "template<typename T> bool Is() const {\n"
         "  return _any_metadata_.Is<T>();\n"
         "}\n"
-        "static bool ParseAnyTypeUrl(const string& type_url,\n"
+        "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+        "type_url,\n"
         "                            std::string* full_type_name);\n");
   }
 
-  format.Set("new_final",
-             ShouldMarkNewAsFinal(descriptor_, options_) ? "final" : "");
-
   format(
       "friend void swap($classname$& a, $classname$& b) {\n"
       "  a.Swap(&b);\n"
+      "}\n"
+      "inline void Swap($classname$* other) {\n"
+      "  if (other == this) return;\n"
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+      "  if (GetOwningArena() != nullptr &&\n"
+      "      GetOwningArena() == other->GetOwningArena()) {\n"
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
+      "  if (GetOwningArena() == other->GetOwningArena()) {\n"
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+      "    InternalSwap(other);\n"
+      "  } else {\n"
+      "    ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
+      "  }\n"
+      "}\n"
+      "void UnsafeArenaSwap($classname$* other) {\n"
+      "  if (other == this) return;\n"
+      "  $DCHK$(GetOwningArena() == other->GetOwningArena());\n"
+      "  InternalSwap(other);\n"
       "}\n");
 
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "inline void Swap($classname$* other) {\n"
-        "  if (other == this) return;\n"
-        "  if (GetArena() == other->GetArena()) {\n"
-        "    InternalSwap(other);\n"
-        "  } else {\n"
-        "    ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
-        "  }\n"
-        "}\n"
-        "void UnsafeArenaSwap($classname$* other) {\n"
-        "  if (other == this) return;\n"
-        "  $DCHK$(GetArena() == other->GetArena());\n"
-        "  InternalSwap(other);\n"
-        "}\n");
-  } else {
-    format(
-        "inline void Swap($classname$* other) {\n"
-        "  if (other == this) return;\n"
-        "  InternalSwap(other);\n"
-        "}\n");
-  }
-
   format(
       "\n"
       "// implements Message ----------------------------------------------\n"
       "\n"
-      "inline $classname$* New() const$ new_final$ {\n"
-      "  return CreateMaybeMessage<$classname$>(nullptr);\n"
+      "inline $classname$* New() const final {\n"
+      "  return new $classname$();\n"
       "}\n"
       "\n"
-      "$classname$* New(::$proto_ns$::Arena* arena) const$ new_final$ {\n"
+      "$classname$* New(::$proto_ns$::Arena* arena) const final {\n"
       "  return CreateMaybeMessage<$classname$>(arena);\n"
       "}\n");
 
@@ -1350,29 +1363,41 @@
   if (HasGeneratedMethods(descriptor_->file(), options_)) {
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format(
-          "void CopyFrom(const ::$proto_ns$::Message& from) final;\n"
-          "void MergeFrom(const ::$proto_ns$::Message& from) final;\n");
+          // Use Message's built-in MergeFrom and CopyFrom when the passed-in
+          // argument is a generic Message instance, and only define the custom
+          // MergeFrom and CopyFrom instances when the source of the merge/copy
+          // is known to be the same class as the destination.
+          // TODO(jorg): Define MergeFrom in terms of MergeImpl, rather than the
+          // other way around, to save even more code size.
+          "using $superclass$::CopyFrom;\n"
+          "void CopyFrom(const $classname$& from);\n"
+          ""
+          "using $superclass$::MergeFrom;\n"
+          "void MergeFrom(const $classname$& from);\n"
+          "private:\n"
+          "static void MergeImpl(::$proto_ns$::Message*to, const "
+          "::$proto_ns$::Message&from);\n"
+          "public:\n");
     } else {
       format(
-          "void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)\n"
-          "  final;\n");
+          "void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)"
+          "  final;\n"
+          "void CopyFrom(const $classname$& from);\n"
+          "void MergeFrom(const $classname$& from);\n");
     }
 
     format.Set("clear_final",
                ShouldMarkClearAsFinal(descriptor_, options_) ? "final" : "");
-    format.Set(
-        "is_initialized_final",
-        ShouldMarkIsInitializedAsFinal(descriptor_, options_) ? "final" : "");
 
     format(
-        "void CopyFrom(const $classname$& from);\n"
-        "void MergeFrom(const $classname$& from);\n"
         "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear()$ clear_final$;\n"
-        "bool IsInitialized() const$ is_initialized_final$;\n"
+        "bool IsInitialized() const final;\n"
         "\n"
-        "size_t ByteSizeLong() const final;\n"
-        "const char* _InternalParse(const char* ptr, "
-        "::$proto_ns$::internal::ParseContext* ctx) final;\n"
+        "size_t ByteSizeLong() const final;\n");
+
+    parse_function_generator_->GenerateMethodDecls(printer);
+
+    format(
         "$uint8$* _InternalSerialize(\n"
         "    $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
         "const final;\n");
@@ -1387,8 +1412,8 @@
   format(
       "int GetCachedSize() const final { return _cached_size_.Get(); }"
       "\n\nprivate:\n"
-      "inline void SharedCtor();\n"
-      "inline void SharedDtor();\n"
+      "void SharedCtor();\n"
+      "void SharedDtor();\n"
       "void SetCachedSize(int size) const$ full_final$;\n"
       "void InternalSwap($classname$* other);\n");
 
@@ -1401,32 +1426,31 @@
       options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece"
                                   : "::StringPiece");
 
-  if (SupportsArenas(descriptor_)) {
-    format(
-        // TODO(gerbens) Make this private! Currently people are deriving from
-        // protos to give access to this constructor, breaking the invariants
-        // we rely on.
-        "protected:\n"
-        "explicit $classname$(::$proto_ns$::Arena* arena);\n"
-        "private:\n"
-        "static void ArenaDtor(void* object);\n"
-        "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n");
-  }
+  format(
+      // TODO(gerbens) Make this private! Currently people are deriving from
+      // protos to give access to this constructor, breaking the invariants
+      // we rely on.
+      "protected:\n"
+      "explicit $classname$(::$proto_ns$::Arena* arena,\n"
+      "                     bool is_message_owned = false);\n"
+      "private:\n"
+      "static void ArenaDtor(void* object);\n"
+      "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n");
 
   format(
       "public:\n"
       "\n");
 
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    if (HasGeneratedMethods(descriptor_->file(), options_)) {
+      format(
+          "static const ClassData _class_data_;\n"
+          "const ::$proto_ns$::Message::ClassData*"
+          "GetClassData() const final;\n"
+          "\n");
+    }
     format(
         "::$proto_ns$::Metadata GetMetadata() const final;\n"
-        "private:\n"
-        "static ::$proto_ns$::Metadata GetMetadataStatic() {\n"
-        "  ::$proto_ns$::internal::AssignDescriptors(&::$desc_table$);\n"
-        "  return ::$desc_table$.file_level_metadata[kIndexInFileMessages];\n"
-        "}\n"
-        "\n"
-        "public:\n"
         "\n");
   } else {
     format(
@@ -1507,6 +1531,10 @@
         "size_t RequiredFieldsByteSizeFallback() const;\n\n");
   }
 
+  if (HasGeneratedMethods(descriptor_->file(), options_)) {
+    parse_function_generator_->GenerateDataDecls(printer);
+  }
+
   // Prepare decls for _cached_size_ and _has_bits_.  Their position in the
   // output will be determined later.
 
@@ -1516,10 +1544,9 @@
 
   const size_t sizeof_has_bits = HasBitsSize();
   const std::string has_bits_decl =
-      sizeof_has_bits == 0
-          ? ""
-          : StrCat("::$proto_ns$::internal::HasBits<",
-                         sizeof_has_bits / 4, "> _has_bits_;\n");
+      sizeof_has_bits == 0 ? ""
+                           : StrCat("::$proto_ns$::internal::HasBits<",
+                                          sizeof_has_bits, "> _has_bits_;\n");
 
   // To minimize padding, data members are divided into three sections:
   // (1) members assumed to align to 8 bytes
@@ -1535,13 +1562,11 @@
         "\n");
   }
 
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "template <typename T> friend class "
-        "::$proto_ns$::Arena::InternalHelper;\n"
-        "typedef void InternalArenaConstructable_;\n"
-        "typedef void DestructorSkippable_;\n");
-  }
+  format(
+      "template <typename T> friend class "
+      "::$proto_ns$::Arena::InternalHelper;\n"
+      "typedef void InternalArenaConstructable_;\n"
+      "typedef void DestructorSkippable_;\n");
 
   if (!has_bit_indices_.empty()) {
     // _has_bits_ is frequently accessed, so to reduce code size and improve
@@ -1565,22 +1590,23 @@
   // For each oneof generate a union
   for (auto oneof : OneOfRange(descriptor_)) {
     std::string camel_oneof_name = UnderscoresToCamelCase(oneof->name(), true);
+    format("union $1$Union {\n", camel_oneof_name);
+    format.Indent();
     format(
-        "union $1$Union {\n"
         // explicit empty constructor is needed when union contains
         // ArenaStringPtr members for string fields.
-        "  $1$Union() {}\n",
+        "constexpr $1$Union() : _constinit_{} {}\n"
+        "  ::$proto_ns$::internal::ConstantInitialized _constinit_;\n",
         camel_oneof_name);
-    format.Indent();
     for (auto field : FieldRange(oneof)) {
-      if (IsFieldUsed(field, options_)) {
+      if (!IsFieldStripped(field, options_)) {
         field_generators_.get(field).GeneratePrivateMembers(printer);
       }
     }
     format.Outdent();
     format("} $1$_;\n", oneof->name());
     for (auto field : FieldRange(oneof)) {
-      if (IsFieldUsed(field, options_)) {
+      if (!IsFieldStripped(field, options_)) {
         field_generators_.get(field).GenerateStaticMembers(printer);
       }
     }
@@ -1638,30 +1664,6 @@
   }
 }
 
-void MessageGenerator::GenerateExtraDefaultFields(io::Printer* printer) {
-  // Generate oneof default instance and weak field instances for reflection
-  // usage.
-  Formatter format(printer, variables_);
-  for (auto oneof : OneOfRange(descriptor_)) {
-    for (auto field : FieldRange(oneof)) {
-      if (!IsFieldUsed(field, options_)) {
-        continue;
-      }
-      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
-          (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
-           EffectiveStringCType(field, options_) != FieldOptions::STRING)) {
-        format("const ");
-      }
-      field_generators_.get(field).GeneratePrivateMembers(printer);
-    }
-  }
-  for (auto field : FieldRange(descriptor_)) {
-    if (field->options().weak() && IsFieldUsed(field, options_)) {
-      format("  const ::$proto_ns$::Message* $1$_;\n", FieldName(field));
-    }
-  }
-}
-
 bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
                                           size_t aux_offset) {
   Formatter format(printer, variables_);
@@ -1707,7 +1709,7 @@
   }
 
   // TODO(ckennelly): Consolidate this with the calculation for
-  // AuxillaryParseTableField.
+  // AuxiliaryParseTableField.
   format(
       "PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n"
       "&$package_ns$::_$classname$_default_instance_,\n");
@@ -1737,15 +1739,12 @@
 
 // We need to calculate for each field what function the table driven code
 // should use to serialize it. This returns the index in a lookup table.
-uint32 CalcFieldNum(const FieldGenerator& generator,
-                    const FieldDescriptor* field, const Options& options) {
+uint32_t CalcFieldNum(const FieldGenerator& generator,
+                      const FieldDescriptor* field, const Options& options) {
   bool is_a_map = IsMapEntryMessage(field->containing_type());
   int type = field->type();
   if (type == FieldDescriptor::TYPE_STRING ||
       type == FieldDescriptor::TYPE_BYTES) {
-    if (generator.IsInlined()) {
-      type = internal::FieldMetadata::kInlinedType;
-    }
     // string field
     if (IsCord(field, options)) {
       type = internal::FieldMetadata::kCordType;
@@ -1793,7 +1792,7 @@
       const FieldDescriptor* field = sorted[i];
       const FieldGenerator& generator = field_generators_.get(field);
 
-      uint32 tag = internal::WireFormatLite::MakeTag(
+      uint32_t tag = internal::WireFormatLite::MakeTag(
           field->number(), WireFormat::WireTypeForFieldType(field->type()));
 
       std::map<std::string, std::string> vars;
@@ -1850,7 +1849,7 @@
     if (i == sorted.size()) break;
     const FieldDescriptor* field = sorted[i];
 
-    uint32 tag = internal::WireFormatLite::MakeTag(
+    uint32_t tag = internal::WireFormatLite::MakeTag(
         field->number(), WireFormat::WireTypeForFieldType(field->type()));
     if (field->is_packed()) {
       tag = internal::WireFormatLite::MakeTag(
@@ -1890,7 +1889,7 @@
     const FieldGenerator& generator = field_generators_.get(field);
     int type = CalcFieldNum(generator, field, options_);
 
-    if (IsLazy(field, options_)) {
+    if (IsLazy(field, options_, scc_analyzer_)) {
       type = internal::FieldMetadata::kSpecial;
       ptr = "reinterpret_cast<const void*>(::" + variables_["proto_ns"] +
             "::internal::LazyFieldSerializer";
@@ -1913,7 +1912,7 @@
           tag);
     } else if (field->real_containing_oneof()) {
       format.Set("oneofoffset",
-                 sizeof(uint32) * field->containing_oneof()->index());
+                 sizeof(uint32_t) * field->containing_oneof()->index());
       format(
           "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$,"
           " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + "
@@ -1946,73 +1945,6 @@
   return num_field_metadata;
 }
 
-void MessageGenerator::GenerateFieldDefaultInstances(io::Printer* printer) {
-  // Construct the default instances for all fields that need one.
-  for (auto field : FieldRange(descriptor_)) {
-    field_generators_.get(field).GenerateDefaultInstanceAllocator(printer);
-  }
-}
-
-void MessageGenerator::GenerateDefaultInstanceInitializer(
-    io::Printer* printer) {
-  Formatter format(printer, variables_);
-
-  // The default instance needs all of its embedded message pointers
-  // cross-linked to other default instances.  We can't do this initialization
-  // in the constructor because some other default instances may not have been
-  // constructed yet at that time.
-  // TODO(kenton):  Maybe all message fields (even for non-default messages)
-  //   should be initialized to point at default instances rather than NULL?
-  for (auto field : FieldRange(descriptor_)) {
-    if (!IsFieldUsed(field, options_)) {
-      continue;
-    }
-    Formatter::SaveState saver(&format);
-
-    if (!field->is_repeated() && !IsLazy(field, options_) &&
-        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
-        (!field->real_containing_oneof() ||
-         HasDescriptorMethods(descriptor_->file(), options_))) {
-      std::string name;
-      if (field->real_containing_oneof() || field->options().weak()) {
-        name = "_" + classname_ + "_default_instance_.";
-      } else {
-        name =
-            "_" + classname_ + "_default_instance_._instance.get_mutable()->";
-      }
-      name += FieldName(field);
-      format.Set("name", name);
-      if (IsWeak(field, options_)) {
-        format(
-            "$package_ns$::$name$_ = reinterpret_cast<const "
-            "::$proto_ns$::Message*>(&$1$);\n"
-            "if ($package_ns$::$name$_ == nullptr) {\n"
-            "  $package_ns$::$name$_ = "
-            "::$proto_ns$::Empty::internal_default_instance();\n"
-            "}\n",
-            QualifiedDefaultInstanceName(field->message_type(),
-                                         options_));  // 1
-        continue;
-      }
-      if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
-        format(
-            "$package_ns$::$name$_ = reinterpret_cast<$1$*>(\n"
-            "    $2$);\n",
-            FieldMessageTypeName(field, options_),
-            QualifiedDefaultInstancePtr(field->message_type(), options_));
-      } else {
-        format(
-            "$package_ns$::$name$_ = const_cast< $1$*>(\n"
-            "    $1$::internal_default_instance());\n",
-            FieldMessageTypeName(field, options_));
-      }
-    } else if (field->real_containing_oneof() &&
-               HasDescriptorMethods(descriptor_->file(), options_)) {
-      field_generators_.get(field).GenerateConstructorCode(printer);
-    }
-  }
-}
-
 void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
   Formatter format(printer, variables_);
   if (IsMapEntryMessage(descriptor_)) {
@@ -2026,26 +1958,15 @@
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format(
           "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
-          "  return GetMetadataStatic();\n"
-          "}\n");
-      format(
-          "void $classname$::MergeFrom(\n"
-          "    const ::$proto_ns$::Message& other) {\n"
-          "  ::$proto_ns$::Message::MergeFrom(other);\n"
-          "}\n"
-          "\n");
+          "  return ::$proto_ns$::internal::AssignDescriptors(\n"
+          "      &$desc_table$_getter, &$desc_table$_once,\n"
+          "      $file_level_metadata$[$1$]);\n"
+          "}\n",
+          index_in_file_messages_);
     }
     return;
   }
 
-  // TODO(gerbens) Remove this function. With a little bit of cleanup and
-  // refactoring this is superfluous.
-  format("void $classname$::InitAsDefaultInstance() {\n");
-  format.Indent();
-  GenerateDefaultInstanceInitializer(printer);
-  format.Outdent();
-  format("}\n");
-
   if (IsAnyMessage(descriptor_, options_)) {
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format(
@@ -2058,8 +1979,9 @@
           "}\n");
     }
     format(
-        "bool $classname$::ParseAnyTypeUrl(const string& type_url,\n"
-        "                                  std::string* full_type_name) {\n"
+        "bool $classname$::ParseAnyTypeUrl(\n"
+        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n"
+        "    std::string* full_type_name) {\n"
         "  return ::$proto_ns$::internal::ParseAnyTypeUrl(type_url,\n"
         "                                             full_type_name);\n"
         "}\n"
@@ -2076,7 +1998,7 @@
   }
   for (auto field : FieldRange(descriptor_)) {
     field_generators_.get(field).GenerateInternalAccessorDeclarations(printer);
-    if (!IsFieldUsed(field, options_)) {
+    if (IsFieldStripped(field, options_)) {
       continue;
     }
     if (HasHasbit(field)) {
@@ -2090,7 +2012,7 @@
     }
   }
   if (num_required_fields_ > 0) {
-    const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
+    const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
     format(
         "static bool MissingRequiredFields(const HasBits& has_bits) "
         "{\n"
@@ -2102,14 +2024,14 @@
   format.Outdent();
   format("};\n\n");
   for (auto field : FieldRange(descriptor_)) {
-    if (IsFieldUsed(field, options_)) {
+    if (!IsFieldStripped(field, options_)) {
       field_generators_.get(field).GenerateInternalAccessorDefinitions(printer);
     }
   }
 
   // Generate non-inline field definitions.
   for (auto field : FieldRange(descriptor_)) {
-    if (!IsFieldUsed(field, options_)) {
+    if (IsFieldStripped(field, options_)) {
       continue;
     }
     field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer);
@@ -2137,9 +2059,11 @@
     GenerateClear(printer);
     format("\n");
 
-    GenerateMergeFromCodedStream(printer);
+    parse_function_generator_->GenerateMethodImpls(printer);
     format("\n");
 
+    parse_function_generator_->GenerateDataDefinitions(printer);
+
     GenerateSerializeWithCachedSizesToArray(printer);
     format("\n");
 
@@ -2173,9 +2097,11 @@
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
     format(
         "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
-        "  return GetMetadataStatic();\n"
-        "}\n"
-        "\n");
+        "  return ::$proto_ns$::internal::AssignDescriptors(\n"
+        "      &$desc_table$_getter, &$desc_table$_once,\n"
+        "      $file_level_metadata$[$1$]);\n"
+        "}\n",
+        index_in_file_messages_);
   } else {
     format(
         "std::string $classname$::GetTypeName() const {\n"
@@ -2222,14 +2148,9 @@
     }
 
     processing_type = static_cast<unsigned>(field->type());
-    const FieldGenerator& generator = field_generators_.get(field);
     if (field->type() == FieldDescriptor::TYPE_STRING) {
       switch (EffectiveStringCType(field, options_)) {
         case FieldOptions::STRING:
-          if (generator.IsInlined()) {
-            processing_type = internal::TYPE_STRING_INLINED;
-            break;
-          }
           break;
         case FieldOptions::CORD:
           processing_type = internal::TYPE_STRING_CORD;
@@ -2241,10 +2162,6 @@
     } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
       switch (EffectiveStringCType(field, options_)) {
         case FieldOptions::STRING:
-          if (generator.IsInlined()) {
-            processing_type = internal::TYPE_BYTES_INLINED;
-            break;
-          }
           break;
         case FieldOptions::CORD:
           processing_type = internal::TYPE_BYTES_CORD;
@@ -2303,14 +2220,14 @@
   std::vector<const FieldDescriptor*> ordered_fields =
       SortFieldsByNumber(descriptor_);
 
-  format("::$proto_ns$::internal::AuxillaryParseTableField(),\n");
+  format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
   int last_field_number = 1;
   for (auto field : ordered_fields) {
     Formatter::SaveState saver(&format);
 
     GOOGLE_CHECK_GE(field->number(), last_field_number);
     for (; last_field_number < field->number(); last_field_number++) {
-      format("::$proto_ns$::internal::AuxillaryParseTableField(),\n");
+      format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
     }
 
     std::map<std::string, std::string> vars;
@@ -2321,11 +2238,11 @@
       case FieldDescriptor::CPPTYPE_ENUM:
         if (HasPreservingUnknownEnumSemantics(field)) {
           format(
-              "{::$proto_ns$::internal::AuxillaryParseTableField::enum_aux{"
+              "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{"
               "nullptr}},\n");
         } else {
           format(
-              "{::$proto_ns$::internal::AuxillaryParseTableField::enum_aux{"
+              "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{"
               "$1$_IsValid}},\n",
               ClassName(field->enum_type(), true));
         }
@@ -2334,7 +2251,7 @@
       case FieldDescriptor::CPPTYPE_MESSAGE: {
         if (field->is_map()) {
           format(
-              "{::$proto_ns$::internal::AuxillaryParseTableField::map_"
+              "{::$proto_ns$::internal::AuxiliaryParseTableField::map_"
               "aux{&::$proto_ns$::internal::ParseMap<$1$>}},\n",
               QualifiedClassName(field->message_type(), options_));
           last_field_number++;
@@ -2345,7 +2262,7 @@
                                            field->message_type(), options_));
 
         format(
-            "{::$proto_ns$::internal::AuxillaryParseTableField::message_aux{\n"
+            "{::$proto_ns$::internal::AuxiliaryParseTableField::message_aux{\n"
             "  &$default_instance$}},\n");
         last_field_number++;
         break;
@@ -2368,7 +2285,7 @@
             break;
         }
         format(
-            "{::$proto_ns$::internal::AuxillaryParseTableField::string_aux{\n"
+            "{::$proto_ns$::internal::AuxiliaryParseTableField::string_aux{\n"
             "  $1$,\n"
             "  \"$2$\"\n"
             "}},\n",
@@ -2409,33 +2326,32 @@
   } else {
     format("~0u,  // no _weak_field_map_\n");
   }
-  int num_stripped = 0;
-  for (auto field : FieldRange(descriptor_)) {
-    if (!IsFieldUsed(field, options_)) {
-      num_stripped++;
-    }
-  }
   const int kNumGenericOffsets = 5;  // the number of fixed offsets above
   const size_t offsets = kNumGenericOffsets + descriptor_->field_count() +
-                         descriptor_->real_oneof_decl_count() - num_stripped;
+                         descriptor_->real_oneof_decl_count();
   size_t entries = offsets;
   for (auto field : FieldRange(descriptor_)) {
-    if (!IsFieldUsed(field, options_)) {
+    if (IsFieldStripped(field, options_)) {
+      format("~0u,  // stripped\n");
       continue;
     }
-    if (field->real_containing_oneof() || field->options().weak()) {
-      format("offsetof($classtype$DefaultTypeInternal, $1$_)",
-             FieldName(field));
+    // TODO(sbenza): We should not have an entry in the offset table for fields
+    // that do not use them.
+    if (field->options().weak() || field->real_containing_oneof()) {
+      // Mark the field to prevent unintentional access through reflection.
+      // Don't use the top bit because that is for unused fields.
+      format("::$proto_ns$::internal::kInvalidFieldOffsetTag");
     } else {
       format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_)", FieldName(field));
     }
 
-    uint32 tag = field_generators_.get(field).CalculateFieldTag();
-    if (tag != 0) {
-      format(" | $1$", tag);
+    if (!IsFieldUsed(field, options_)) {
+      format(" | 0x80000000u, // unused\n");
+    } else if (IsEagerlyVerifiedLazy(field, options_, scc_analyzer_)) {
+      format(" | 0x1u, // eagerly verified lazy\n");
+    } else {
+      format(",\n");
     }
-
-    format(",\n");
   }
 
   int count = 0;
@@ -2451,11 +2367,8 @@
         "0,\n"
         "1,\n");
   } else if (!has_bit_indices_.empty()) {
-    entries += has_bit_indices_.size() - num_stripped;
+    entries += has_bit_indices_.size();
     for (int i = 0; i < has_bit_indices_.size(); i++) {
-      if (!IsFieldUsed(descriptor_->field(i), options_)) {
-        continue;
-      }
       const std::string index =
           has_bit_indices_[i] >= 0 ? StrCat(has_bit_indices_[i]) : "~0u";
       format("$1$,\n", index);
@@ -2468,13 +2381,7 @@
 void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) {
   Formatter format(printer, variables_);
 
-  format("void $classname$::SharedCtor() {\n");
-  if (scc_analyzer_->GetSCCAnalysis(scc_analyzer_->GetSCC(descriptor_))
-          .constructor_requires_initialization) {
-    format("  ::$proto_ns$::internal::InitSCC(&$scc_info$.base);\n");
-  }
-
-  format.Indent();
+  format("inline void $classname$::SharedCtor() {\n");
 
   std::vector<bool> processed(optimized_order_.size(), false);
   GenerateConstructorBody(printer, processed, false);
@@ -2483,18 +2390,15 @@
     format("clear_has_$1$();\n", oneof->name());
   }
 
-  format.Outdent();
   format("}\n\n");
 }
 
 void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
   Formatter format(printer, variables_);
 
-  format("void $classname$::SharedDtor() {\n");
+  format("inline void $classname$::SharedDtor() {\n");
   format.Indent();
-  if (SupportsArenas(descriptor_)) {
-    format("$DCHK$(GetArena() == nullptr);\n");
-  }
+  format("$DCHK$(GetArenaForAllocation() == nullptr);\n");
   // Write the destructors for each field except oneof members.
   // optimized_order_ does not contain oneof fields.
   for (auto field : optimized_order_) {
@@ -2550,18 +2454,12 @@
   // and returns false for oneof fields.
   for (auto oneof : OneOfRange(descriptor_)) {
     for (auto field : FieldRange(oneof)) {
-      if (IsFieldUsed(field, options_) &&
+      if (!IsFieldStripped(field, options_) &&
           field_generators_.get(field).GenerateArenaDestructorCode(printer)) {
         need_registration = true;
       }
     }
   }
-  if (num_weak_fields_) {
-    // _this is the object being destructed (we are inside a static method
-    // here).
-    format("_this->_weak_field_map_.ClearAll();\n");
-    need_registration = true;
-  }
 
   format.Outdent();
   format("}\n");
@@ -2581,6 +2479,42 @@
   }
 }
 
+void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) {
+  Formatter format(printer, variables_);
+
+  format(
+      "constexpr $classname$::$classname$(\n"
+      "  ::$proto_ns$::internal::ConstantInitialized)");
+  format.Indent();
+  const char* field_sep = ":";
+  const auto put_sep = [&] {
+    format("\n$1$ ", field_sep);
+    field_sep = ",";
+  };
+
+  if (!IsMapEntryMessage(descriptor_)) {
+    // Process non-oneof fields first.
+    for (auto field : optimized_order_) {
+      auto& gen = field_generators_.get(field);
+      put_sep();
+      gen.GenerateConstinitInitializer(printer);
+    }
+
+    if (IsAnyMessage(descriptor_, options_)) {
+      put_sep();
+      format("_any_metadata_(&type_url_, &value_)");
+    }
+
+    if (descriptor_->real_oneof_decl_count() != 0) {
+      put_sep();
+      format("_oneof_case_{}");
+    }
+  }
+
+  format.Outdent();
+  format("{}\n");
+}
+
 void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
                                                std::vector<bool> processed,
                                                bool copy_constructor) const {
@@ -2590,7 +2524,7 @@
       optimized_order_, [copy_constructor, this](const FieldDescriptor* field) {
         return (copy_constructor && IsPOD(field)) ||
                (!copy_constructor &&
-                CanBeManipulatedAsRawBytes(field, options_));
+                CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_));
       });
 
   std::string pod_template;
@@ -2601,8 +2535,10 @@
         "  reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
   } else {
     pod_template =
-        "::memset(&$first$_, 0, static_cast<size_t>(\n"
-        "    reinterpret_cast<char*>(&$last$_) -\n"
+        "::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(\n"
+        "    reinterpret_cast<char*>(&$first$_) - "
+        "reinterpret_cast<char*>(this)),\n"
+        "    0, static_cast<size_t>(reinterpret_cast<char*>(&$last$_) -\n"
         "    reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
   }
 
@@ -2645,7 +2581,7 @@
 
   std::string superclass;
   superclass = SuperClassName(descriptor_, options_);
-  std::string initializer_with_arena = superclass + "(arena)";
+  std::string initializer_with_arena = superclass + "(arena, is_message_owned)";
 
   if (descriptor_->extension_range_count() > 0) {
     initializer_with_arena += ",\n  _extensions_(arena)";
@@ -2653,10 +2589,11 @@
 
   // Initialize member variables with arena constructor.
   for (auto field : optimized_order_) {
-    GOOGLE_DCHECK(IsFieldUsed(field, options_));
+    GOOGLE_DCHECK(!IsFieldStripped(field, options_));
     bool has_arena_constructor = field->is_repeated();
     if (!field->real_containing_oneof() &&
-        (IsLazy(field, options_) || IsStringPiece(field, options_))) {
+        (IsLazy(field, options_, scc_analyzer_) ||
+         IsStringPiece(field, options_))) {
       has_arena_constructor = true;
     }
     if (has_arena_constructor) {
@@ -2680,27 +2617,20 @@
     initializer_null += ", _weak_field_map_(nullptr)";
   }
 
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "$classname$::$classname$(::$proto_ns$::Arena* arena)\n"
-        "  : $1$ {\n"
-        "  SharedCtor();\n"
-        "  RegisterArenaDtor(arena);\n"
-        "  // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
-        "}\n",
-        initializer_with_arena);
-  } else {
-    format(
-        "$classname$::$classname$()\n"
-        "  : $1$ {\n"
-        "  SharedCtor();\n"
-        "  // @@protoc_insertion_point(constructor:$full_name$)\n"
-        "}\n",
-        initializer_null);
-  }
+  format(
+      "$classname$::$classname$(::$proto_ns$::Arena* arena,\n"
+      "                         bool is_message_owned)\n"
+      "  : $1$ {\n"
+      "  SharedCtor();\n"
+      "  if (!is_message_owned) {\n"
+      "    RegisterArenaDtor(arena);\n"
+      "  }\n"
+      "  // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
+      "}\n",
+      initializer_with_arena);
 
   std::map<std::string, std::string> vars;
-  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  SetUnknownFieldsVariable(descriptor_, options_, &vars);
   format.AddMap(vars);
 
   // Generate the copy constructor.
@@ -2769,7 +2699,7 @@
       for (auto field : FieldRange(oneof)) {
         format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
         format.Indent();
-        if (IsFieldUsed(field, options_)) {
+        if (!IsFieldStripped(field, options_)) {
           field_generators_.get(field).GenerateMergingCode(printer);
         }
         format("break;\n");
@@ -2799,6 +2729,7 @@
   format(
       "$classname$::~$classname$() {\n"
       "  // @@protoc_insertion_point(destructor:$full_name$)\n"
+      "  if (GetArenaForAllocation() != nullptr) return;\n"
       "  SharedDtor();\n"
       "  _internal_metadata_.Delete<$unknown_fields_type$>();\n"
       "}\n"
@@ -2808,23 +2739,13 @@
   GenerateSharedDestructorCode(printer);
 
   // Generate the arena-specific destructor code.
-  if (SupportsArenas(descriptor_)) {
-    GenerateArenaDestructorCode(printer);
-  }
+  GenerateArenaDestructorCode(printer);
 
   // Generate SetCachedSize.
   format(
       "void $classname$::SetCachedSize(int size) const {\n"
       "  _cached_size_.Set(size);\n"
       "}\n");
-
-  format(
-      "const $classname$& $classname$::default_instance() {\n"
-      "  "
-      "::$proto_ns$::internal::InitSCC(&::$scc_info$.base)"
-      ";\n"
-      "  return *internal_default_instance();\n"
-      "}\n\n");
 }
 
 void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
@@ -2833,9 +2754,8 @@
       "template<> "
       "PROTOBUF_NOINLINE "
       "$classtype$* Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n"
-      "  return Arena::$1$Internal< $classtype$ >(arena);\n"
-      "}\n",
-      MessageCreateFunction(descriptor_));
+      "  return Arena::CreateMessageInternal< $classtype$ >(arena);\n"
+      "}\n");
 }
 
 void MessageGenerator::GenerateClear(io::Printer* printer) {
@@ -2919,7 +2839,7 @@
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
-      uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
           StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
 
@@ -3002,7 +2922,7 @@
   }
 
   std::map<std::string, std::string> vars;
-  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  SetUnknownFieldsVariable(descriptor_, options_, &vars);
   format.AddMap(vars);
   format("_internal_metadata_.Clear<$unknown_fields_type$>();\n");
 
@@ -3027,7 +2947,7 @@
       format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
       format.Indent();
       // We clear only allocated objects in oneofs
-      if (!IsStringOrMessage(field) || !IsFieldUsed(field, options_)) {
+      if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) {
         format("// No need to clear\n");
       } else {
         field_generators_.get(field).GenerateClearingCode(printer);
@@ -3063,18 +2983,16 @@
 
   if (HasGeneratedMethods(descriptor_->file(), options_)) {
     if (descriptor_->extension_range_count() > 0) {
-      format("_extensions_.Swap(&other->_extensions_);\n");
+      format("_extensions_.InternalSwap(&other->_extensions_);\n");
     }
 
     std::map<std::string, std::string> vars;
-    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    SetUnknownFieldsVariable(descriptor_, options_, &vars);
     format.AddMap(vars);
-    format(
-        "_internal_metadata_.Swap<$unknown_fields_type$>(&other->_internal_"
-        "metadata_);\n");
+    format("_internal_metadata_.InternalSwap(&other->_internal_metadata_);\n");
 
     if (!has_bit_indices_.empty()) {
-      for (int i = 0; i < HasBitsSize() / 4; ++i) {
+      for (int i = 0; i < HasBitsSize(); ++i) {
         format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i);
       }
     }
@@ -3082,7 +3000,7 @@
     // If possible, we swap several fields at once, including padding.
     const RunMap runs =
         FindRuns(optimized_order_, [this](const FieldDescriptor* field) {
-          return CanBeManipulatedAsRawBytes(field, options_);
+          return CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_);
         });
 
     for (int i = 0; i < optimized_order_.size(); ++i) {
@@ -3139,35 +3057,30 @@
 void MessageGenerator::GenerateMergeFrom(io::Printer* printer) {
   Formatter format(printer, variables_);
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    // Generate the generalized MergeFrom (aka that which takes in the Message
-    // base class as a parameter).
-    format(
-        "void $classname$::MergeFrom(const ::$proto_ns$::Message& from) {\n"
-        "// @@protoc_insertion_point(generalized_merge_from_start:"
-        "$full_name$)\n"
-        "  $DCHK$_NE(&from, this);\n");
-    format.Indent();
+    // We don't override the generalized MergeFrom (aka that which
+    // takes in the Message base class as a parameter); instead we just
+    // let the base Message::MergeFrom take care of it.  The base MergeFrom
+    // knows how to quickly confirm the types exactly match, and if so, will
+    // use GetClassData() to retrieve the address of MergeImpl, which calls
+    // the fast MergeFrom overload.  Most callers avoid all this by passing
+    // a "from" message that is the same type as the message being merged
+    // into, rather than a generic Message.
 
-    // Cast the message to the proper type. If we find that the message is
-    // *not* of the proper type, we can still call Merge via the reflection
-    // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
-    // for each message.
     format(
-        "const $classname$* source =\n"
-        "    ::$proto_ns$::DynamicCastToGenerated<$classname$>(\n"
-        "        &from);\n"
-        "if (source == nullptr) {\n"
-        "// @@protoc_insertion_point(generalized_merge_from_cast_fail:"
-        "$full_name$)\n"
-        "  ::$proto_ns$::internal::ReflectionOps::Merge(from, this);\n"
-        "} else {\n"
-        "// @@protoc_insertion_point(generalized_merge_from_cast_success:"
-        "$full_name$)\n"
-        "  MergeFrom(*source);\n"
-        "}\n");
-
-    format.Outdent();
-    format("}\n");
+        "const ::$proto_ns$::Message::ClassData "
+        "$classname$::_class_data_ = {\n"
+        "    ::$proto_ns$::Message::CopyWithSizeCheck,\n"
+        "    $classname$::MergeImpl\n"
+        "};\n"
+        "const ::$proto_ns$::Message::ClassData*"
+        "$classname$::GetClassData() const { return &_class_data_; }\n"
+        "\n"
+        "void $classname$::MergeImpl(::$proto_ns$::Message*to,\n"
+        "                      const ::$proto_ns$::Message&from) {\n"
+        "  static_cast<$classname$ *>(to)->MergeFrom(\n"
+        "      static_cast<const $classname$ &>(from));\n"
+        "}\n"
+        "\n");
   } else {
     // Generate CheckTypeAndMergeFrom().
     format(
@@ -3189,15 +3102,7 @@
       "  $DCHK$_NE(&from, this);\n");
   format.Indent();
 
-  if (descriptor_->extension_range_count() > 0) {
-    format("_extensions_.MergeFrom(from._extensions_);\n");
-  }
-  std::map<std::string, std::string> vars;
-  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
-  format.AddMap(vars);
   format(
-      "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
-      "metadata_);\n"
       "$uint32$ cached_has_bits = 0;\n"
       "(void) cached_has_bits;\n\n");
 
@@ -3223,7 +3128,7 @@
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
-      uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
           StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
 
@@ -3316,7 +3221,7 @@
     for (auto field : FieldRange(oneof)) {
       format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
       format.Indent();
-      if (IsFieldUsed(field, options_)) {
+      if (!IsFieldStripped(field, options_)) {
         field_generators_.get(field).GenerateMergingCode(printer);
       }
       format("break;\n");
@@ -3335,6 +3240,16 @@
     format("_weak_field_map_.MergeFrom(from._weak_field_map_);\n");
   }
 
+  // Merging of extensions and unknown fields is done last, to maximize
+  // the opportunity for tail calls.
+  if (descriptor_->extension_range_count() > 0) {
+    format("_extensions_.MergeFrom(from._extensions_);\n");
+  }
+
+  format(
+      "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
+      "metadata_);\n");
+
   format.Outdent();
   format("}\n");
 }
@@ -3342,38 +3257,16 @@
 void MessageGenerator::GenerateCopyFrom(io::Printer* printer) {
   Formatter format(printer, variables_);
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    // Generate the generalized CopyFrom (aka that which takes in the Message
-    // base class as a parameter).
-    format(
-        "void $classname$::CopyFrom(const ::$proto_ns$::Message& from) {\n"
-        "// @@protoc_insertion_point(generalized_copy_from_start:"
-        "$full_name$)\n");
-    format.Indent();
-
-    format("if (&from == this) return;\n");
-
-    if (!options_.opensource_runtime) {
-      // This check is disabled in the opensource release because we're
-      // concerned that many users do not define NDEBUG in their release
-      // builds.
-      format(
-          "#ifndef NDEBUG\n"
-          "size_t from_size = from.ByteSizeLong();\n"
-          "#endif\n"
-          "Clear();\n"
-          "#ifndef NDEBUG\n"
-          "$CHK$_EQ(from_size, from.ByteSizeLong())\n"
-          "  << \"Source of CopyFrom changed when clearing target.  Either \"\n"
-          "  << \"source is a nested message in target (not allowed), or \"\n"
-          "  << \"another thread is modifying the source.\";\n"
-          "#endif\n");
-    } else {
-      format("Clear();\n");
-    }
-    format("MergeFrom(from);\n");
-
-    format.Outdent();
-    format("}\n\n");
+    // We don't override the generalized CopyFrom (aka that which
+    // takes in the Message base class as a parameter); instead we just
+    // let the base Message::CopyFrom take care of it.  The base MergeFrom
+    // knows how to quickly confirm the types exactly match, and if so, will
+    // use GetClassData() to get the address of Message::CopyWithSizeCheck,
+    // which calls Clear() and then MergeFrom(), as well as making sure that
+    // clearing the destination message doesn't alter the size of the source,
+    // when in debug builds.
+    // Most callers avoid this by passing a "from" message that is the same
+    // type as the message being merged into, rather than a generic Message.
   }
 
   // Generate the class-specific CopyFrom.
@@ -3396,8 +3289,8 @@
         "#ifndef NDEBUG\n"
         "$CHK$_EQ(from_size, from.ByteSizeLong())\n"
         "  << \"Source of CopyFrom changed when clearing target.  Either \"\n"
-        "  << \"source is a nested message in target (not allowed), or \"\n"
-        "  << \"another thread is modifying the source.\";\n"
+        "     \"source is a nested message in target (not allowed), or \"\n"
+        "     \"another thread is modifying the source.\";\n"
         "#endif\n");
   } else {
     format("Clear();\n");
@@ -3408,24 +3301,6 @@
   format("}\n");
 }
 
-void MessageGenerator::GenerateMergeFromCodedStream(io::Printer* printer) {
-  std::map<std::string, std::string> vars = variables_;
-  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
-  Formatter format(printer, vars);
-  if (descriptor_->options().message_set_wire_format()) {
-    // Special-case MessageSet.
-    format(
-        "const char* $classname$::_InternalParse(const char* ptr,\n"
-        "                  ::$proto_ns$::internal::ParseContext* ctx) {\n"
-        "  return _extensions_.ParseMessageSet(ptr, \n"
-        "      internal_default_instance(), &_internal_metadata_, ctx);\n"
-        "}\n");
-    return;
-  }
-  GenerateParserLoop(descriptor_, max_has_bit_index_, options_, scc_analyzer_,
-                     printer);
-}
-
 void MessageGenerator::GenerateSerializeOneofFields(
     io::Printer* printer, const std::vector<const FieldDescriptor*>& fields) {
   Formatter format(printer, variables_);
@@ -3513,10 +3388,11 @@
         "$uint8$* $classname$::_InternalSerialize(\n"
         "    $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
         "const {\n"
+        "$annotate_serialize$"
         "  target = _extensions_."
         "InternalSerializeMessageSetWithCachedSizesToArray(target, stream);\n");
     std::map<std::string, std::string> vars;
-    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    SetUnknownFieldsVariable(descriptor_, options_, &vars);
     format.AddMap(vars);
     format(
         "  target = ::$proto_ns$::internal::"
@@ -3531,13 +3407,32 @@
   format(
       "$uint8$* $classname$::_InternalSerialize(\n"
       "    $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
-      "const {\n");
+      "const {\n"
+      "$annotate_serialize$");
   format.Indent();
 
   format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n");
 
+  if (!ShouldSerializeInOrder(descriptor_, options_)) {
+    format.Outdent();
+    format("#ifdef NDEBUG\n");
+    format.Indent();
+  }
+
   GenerateSerializeWithCachedSizesBody(printer);
 
+  if (!ShouldSerializeInOrder(descriptor_, options_)) {
+    format.Outdent();
+    format("#else  // NDEBUG\n");
+    format.Indent();
+
+    GenerateSerializeWithCachedSizesBodyShuffled(printer);
+
+    format.Outdent();
+    format("#endif  // !NDEBUG\n");
+    format.Indent();
+  }
+
   format("// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n");
 
   format.Outdent();
@@ -3559,7 +3454,7 @@
     LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer)
         : mg_(mg),
           format_(printer),
-          eager_(!HasFieldPresence(mg->descriptor_->file())),
+          eager_(IsProto3(mg->descriptor_->file())),
           cached_has_bit_index_(kNoHasbit) {}
 
     ~LazySerializerEmitter() { Flush(); }
@@ -3595,6 +3490,12 @@
       }
     }
 
+    void EmitIfNotNull(const FieldDescriptor* field) {
+      if (field != nullptr) {
+        Emit(field);
+      }
+    }
+
     void Flush() {
       if (!v_.empty()) {
         mg_->GenerateSerializeOneofFields(format_.printer(), v_);
@@ -3621,6 +3522,61 @@
     int cached_has_bit_index_;
   };
 
+  class LazyExtensionRangeEmitter {
+   public:
+    LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* printer)
+        : mg_(mg), format_(printer) {}
+
+    void AddToRange(const Descriptor::ExtensionRange* range) {
+      if (!has_current_range_) {
+        current_combined_range_ = *range;
+        has_current_range_ = true;
+      } else {
+        current_combined_range_.start =
+            std::min(current_combined_range_.start, range->start);
+        current_combined_range_.end =
+            std::max(current_combined_range_.end, range->end);
+      }
+    }
+
+    void Flush() {
+      if (has_current_range_) {
+        mg_->GenerateSerializeOneExtensionRange(format_.printer(),
+                                                &current_combined_range_);
+      }
+      has_current_range_ = false;
+    }
+
+   private:
+    MessageGenerator* mg_;
+    Formatter format_;
+    bool has_current_range_ = false;
+    Descriptor::ExtensionRange current_combined_range_;
+  };
+
+  // We need to track the largest weak field, because weak fields are serialized
+  // differently than normal fields.  The WeakFieldMap::FieldWriter will
+  // serialize all weak fields that are ordinally between the last serialized
+  // weak field and the current field.  In order to guarantee that all weak
+  // fields are serialized, we need to make sure to emit the code to serialize
+  // the largest weak field present at some point.
+  class LargestWeakFieldHolder {
+   public:
+    const FieldDescriptor* Release() {
+      const FieldDescriptor* result = field_;
+      field_ = nullptr;
+      return result;
+    }
+    void ReplaceIfLarger(const FieldDescriptor* field) {
+      if (field_ == nullptr || field_->number() < field->number()) {
+        field_ = field;
+      }
+    }
+
+   private:
+    const FieldDescriptor* field_ = nullptr;
+  };
+
   std::vector<const FieldDescriptor*> ordered_fields =
       SortFieldsByNumber(descriptor_);
 
@@ -3644,7 +3600,8 @@
   // Merge the fields and the extension ranges, both sorted by field number.
   {
     LazySerializerEmitter e(this, printer);
-    const FieldDescriptor* last_weak_field = nullptr;
+    LazyExtensionRangeEmitter re(this, printer);
+    LargestWeakFieldHolder largest_weak_field;
     int i, j;
     for (i = 0, j = 0;
          i < ordered_fields.size() || j < sorted_extensions.size();) {
@@ -3652,35 +3609,29 @@
           (i < descriptor_->field_count() &&
            ordered_fields[i]->number() < sorted_extensions[j]->start)) {
         const FieldDescriptor* field = ordered_fields[i++];
-        if (!IsFieldUsed(field, options_)) {
+        if (IsFieldStripped(field, options_)) {
           continue;
         }
+        re.Flush();
         if (field->options().weak()) {
-          last_weak_field = field;
+          largest_weak_field.ReplaceIfLarger(field);
           PrintFieldComment(format, field);
         } else {
-          if (last_weak_field != nullptr) {
-            e.Emit(last_weak_field);
-            last_weak_field = nullptr;
-          }
+          e.EmitIfNotNull(largest_weak_field.Release());
           e.Emit(field);
         }
       } else {
-        if (last_weak_field != nullptr) {
-          e.Emit(last_weak_field);
-          last_weak_field = nullptr;
-        }
+        e.EmitIfNotNull(largest_weak_field.Release());
         e.Flush();
-        GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+        re.AddToRange(sorted_extensions[j++]);
       }
     }
-    if (last_weak_field != nullptr) {
-      e.Emit(last_weak_field);
-    }
+    re.Flush();
+    e.EmitIfNotNull(largest_weak_field.Release());
   }
 
   std::map<std::string, std::string> vars;
-  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  SetUnknownFieldsVariable(descriptor_, options_, &vars);
   format.AddMap(vars);
   format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
   format.Indent();
@@ -3699,9 +3650,101 @@
   format("}\n");
 }
 
-std::vector<uint32> MessageGenerator::RequiredFieldsBitMask() const {
+void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled(
+    io::Printer* printer) {
+  Formatter format(printer, variables_);
+
+  std::vector<const FieldDescriptor*> ordered_fields =
+      SortFieldsByNumber(descriptor_);
+  ordered_fields.erase(
+      std::remove_if(ordered_fields.begin(), ordered_fields.end(),
+                     [this](const FieldDescriptor* f) {
+                       return !IsFieldUsed(f, options_);
+                     }),
+      ordered_fields.end());
+
+  std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  sorted_extensions.reserve(descriptor_->extension_range_count());
+  for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+    sorted_extensions.push_back(descriptor_->extension_range(i));
+  }
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeSorter());
+
+  int num_fields = ordered_fields.size() + sorted_extensions.size();
+  constexpr int kLargePrime = 1000003;
+  GOOGLE_CHECK_LT(num_fields, kLargePrime)
+      << "Prime offset must be greater than the number of fields to ensure "
+         "those are coprime.";
+
+  if (num_weak_fields_) {
+    format(
+        "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer("
+        "_weak_field_map_);\n");
+  }
+
+  format("for (int i = $1$; i >= 0; i-- ) {\n", num_fields - 1);
+
+  format.Indent();
+  format("switch(i) {\n");
+  format.Indent();
+
+  int index = 0;
+  for (const auto* f : ordered_fields) {
+    format("case $1$: {\n", index++);
+    format.Indent();
+
+    GenerateSerializeOneField(printer, f, -1);
+
+    format("break;\n");
+    format.Outdent();
+    format("}\n");
+  }
+
+  for (const auto* r : sorted_extensions) {
+    format("case $1$: {\n", index++);
+    format.Indent();
+
+    GenerateSerializeOneExtensionRange(printer, r);
+
+    format("break;\n");
+    format.Outdent();
+    format("}\n");
+  }
+
+  format(
+      "default: {\n"
+      "  $DCHK$(false) << \"Unexpected index: \" << i;\n"
+      "}\n");
+  format.Outdent();
+  format("}\n");
+
+  format.Outdent();
+  format("}\n");
+
+  std::map<std::string, std::string> vars;
+  SetUnknownFieldsVariable(descriptor_, options_, &vars);
+  format.AddMap(vars);
+  format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
+  format.Indent();
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    format(
+        "target = "
+        "::$proto_ns$::internal::WireFormat::"
+        "InternalSerializeUnknownFieldsToArray(\n"
+        "    $unknown_fields$, target, stream);\n");
+  } else {
+    format(
+        "target = stream->WriteRaw($unknown_fields$.data(),\n"
+        "    static_cast<int>($unknown_fields$.size()), target);\n");
+  }
+  format.Outdent();
+  format("}\n");
+}
+
+std::vector<uint32_t> MessageGenerator::RequiredFieldsBitMask() const {
   const int array_size = HasBitsSize();
-  std::vector<uint32> masks(array_size, 0);
+  std::vector<uint32_t> masks(array_size, 0);
 
   for (auto field : FieldRange(descriptor_)) {
     if (!field->is_required()) {
@@ -3709,7 +3752,8 @@
     }
 
     const int has_bit_index = has_bit_indices_[field->index()];
-    masks[has_bit_index / 32] |= static_cast<uint32>(1) << (has_bit_index % 32);
+    masks[has_bit_index / 32] |= static_cast<uint32_t>(1)
+                                 << (has_bit_index % 32);
   }
   return masks;
 }
@@ -3720,10 +3764,11 @@
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
     std::map<std::string, std::string> vars;
-    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    SetUnknownFieldsVariable(descriptor_, options_, &vars);
     format.AddMap(vars);
     format(
         "size_t $classname$::ByteSizeLong() const {\n"
+        "$annotate_bytesize$"
         "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
         "  size_t total_size = _extensions_.MessageSetByteSize();\n"
         "  if ($have_unknown_fields$) {\n"
@@ -3769,6 +3814,7 @@
 
   format(
       "size_t $classname$::ByteSizeLong() const {\n"
+      "$annotate_bytesize$"
       "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n");
   format.Indent();
   format(
@@ -3782,7 +3828,7 @@
   }
 
   std::map<std::string, std::string> vars;
-  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  SetUnknownFieldsVariable(descriptor_, options_, &vars);
   format.AddMap(vars);
 
   // Handle required fields (if any).  We expect all of them to be
@@ -3790,7 +3836,7 @@
   // present then the fast path executes; otherwise the slow path executes.
   if (num_required_fields_ > 1) {
     // The fast path works if all required fields are present.
-    const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
+    const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
     format("if ($1$) {  // All required fields are present.\n",
            ConditionalToCheckBitmasks(masks_for_has_bits));
     format.Indent();
@@ -3846,7 +3892,7 @@
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
-      uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
           StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
 
@@ -3920,7 +3966,7 @@
       PrintFieldComment(format, field);
       format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
       format.Indent();
-      if (IsFieldUsed(field, options_)) {
+      if (!IsFieldStripped(field, options_)) {
         field_generators_.get(field).GenerateByteSize(printer);
       }
       format("break;\n");
@@ -4011,6 +4057,13 @@
         }
       } else if (field->options().weak()) {
         continue;
+      } else if (IsEagerlyVerifiedLazy(field, options_, scc_analyzer_)) {
+        GOOGLE_CHECK(!field->real_containing_oneof());
+        format(
+            "if (_internal_has_$1$()) {\n"
+            "  if (!$1$().IsInitialized()) return false;\n"
+            "}\n",
+            FieldName(field));
       } else {
         GOOGLE_CHECK(!field->real_containing_oneof());
         format(
@@ -4048,7 +4101,7 @@
       format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
       format.Indent();
 
-      if (IsFieldUsed(field, options_) &&
+      if (!IsFieldStripped(field, options_) &&
           field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
           !ShouldIgnoreRequiredFieldCheck(field, options_) &&
           scc_analyzer_->HasRequiredFields(field->message_type())) {
@@ -4087,3 +4140,5 @@
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index a212ff4..339d6e7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -35,13 +35,16 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
 
+#include <cstdint>
 #include <memory>
 #include <set>
 #include <string>
+
 #include <google/protobuf/compiler/cpp/cpp_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
 
 namespace google {
 namespace protobuf {
@@ -82,17 +85,6 @@
 
   // Source file stuff.
 
-  // Generate extra fields
-  void GenerateExtraDefaultFields(io::Printer* printer);
-
-  // Generates code that creates default instances for fields.
-  void GenerateFieldDefaultInstances(io::Printer* printer);
-
-  // Generates code that initializes the message's default instance.  This
-  // is separate from allocating because all default instances must be
-  // allocated before any can be initialized.
-  void GenerateDefaultInstanceInitializer(io::Printer* printer);
-
   // Generate all non-inline methods for this class.
   void GenerateClassMethods(io::Printer* printer);
 
@@ -113,7 +105,7 @@
   bool GenerateParseTable(io::Printer* printer, size_t offset,
                           size_t aux_offset);
 
-  // Generate the field offsets array.  Returns the a pair of the total numer
+  // Generate the field offsets array.  Returns the a pair of the total number
   // of entries generated and the index of the first has_bit entry.
   std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
   void GenerateSchema(io::Printer* printer, int offset, int has_offset);
@@ -135,13 +127,17 @@
   // Generate the arena-specific destructor code.
   void GenerateArenaDestructorCode(io::Printer* printer);
 
+  // Generate the constexpr constructor for constant initialization of the
+  // default instance.
+  void GenerateConstexprConstructor(io::Printer* printer);
+
   // Generate standard Message methods.
   void GenerateClear(io::Printer* printer);
   void GenerateOneofClear(io::Printer* printer);
-  void GenerateMergeFromCodedStream(io::Printer* printer);
   void GenerateSerializeWithCachedSizes(io::Printer* printer);
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
   void GenerateSerializeWithCachedSizesBody(io::Printer* printer);
+  void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer);
   void GenerateByteSize(io::Printer* printer);
   void GenerateMergeFrom(io::Printer* printer);
   void GenerateClassSpecificMergeFrom(io::Printer* printer);
@@ -185,7 +181,7 @@
   int HasByteIndex(const FieldDescriptor* a) const;
   int HasWordIndex(const FieldDescriptor* a) const;
   bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const;
-  std::vector<uint32> RequiredFieldsBitMask() const;
+  std::vector<uint32_t> RequiredFieldsBitMask() const;
 
   const Descriptor* descriptor_;
   int index_in_file_messages_;
@@ -208,6 +204,7 @@
   bool table_driven_;
 
   std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
+  std::unique_ptr<ParseFunctionGenerator> parse_function_generator_;
 
   MessageSCCAnalyzer* scc_analyzer_;
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index b6b8f24..ee677ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -67,8 +67,9 @@
       QualifiedDefaultInstancePtr(descriptor->message_type(), options);
   (*variables)["type_reference_function"] =
       implicit_weak ? ("  ::" + (*variables)["proto_ns"] +
-                       "::internal::StrongReference(" +
-                       (*variables)["type_default_instance"] + ");\n")
+                       "::internal::StrongReference(reinterpret_cast<const " +
+                       (*variables)["type"] + "&>(\n" +
+                       (*variables)["type_default_instance"] + "));\n")
                     : "";
   // NOTE: Escaped here to unblock proto1->proto2 migration.
   // TODO(liujisi): Extend this to apply for other conflicting methods.
@@ -104,36 +105,34 @@
 void MessageFieldGenerator::GenerateAccessorDeclarations(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (!IsFieldUsed(descriptor_, options_)) {
+  if (IsFieldStripped(descriptor_, options_)) {
     format(
         "$deprecated_attr$const $type$& ${1$$name$$}$() const { "
         "__builtin_trap(); }\n"
-        "$deprecated_attr$$type$* ${1$$release_name$$}$() { "
+        "PROTOBUF_MUST_USE_RESULT $deprecated_attr$$type$* "
+        "${1$$release_name$$}$() { "
         "__builtin_trap(); }\n"
         "$deprecated_attr$$type$* ${1$mutable_$name$$}$() { "
         "__builtin_trap(); }\n"
         "$deprecated_attr$void ${1$set_allocated_$name$$}$"
-        "($type$* $name$) { __builtin_trap(); }\n",
+        "($type$* $name$) { __builtin_trap(); }\n"
+        "$deprecated_attr$void "
+        "${1$unsafe_arena_set_allocated_$name$$}$(\n"
+        "    $type$* $name$) { __builtin_trap(); }\n"
+        "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { "
+        "__builtin_trap(); }\n",
         descriptor_);
-    if (SupportsArenas(descriptor_)) {
-      format(
-          "$deprecated_attr$void "
-          "${1$unsafe_arena_set_allocated_$name$$}$(\n"
-          "    $type$* $name$) { __builtin_trap(); }\n"
-          "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { "
-          "__builtin_trap(); }\n",
-          descriptor_);
-    }
     return;
   }
   format(
       "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
-      "$deprecated_attr$$type$* ${1$$release_name$$}$();\n"
+      "PROTOBUF_MUST_USE_RESULT $deprecated_attr$$type$* "
+      "${1$$release_name$$}$();\n"
       "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
       "$deprecated_attr$void ${1$set_allocated_$name$$}$"
       "($type$* $name$);\n",
       descriptor_);
-  if (IsFieldUsed(descriptor_, options_)) {
+  if (!IsFieldStripped(descriptor_, options_)) {
     format(
         "private:\n"
         "const $type$& ${1$_internal_$name$$}$() const;\n"
@@ -141,14 +140,12 @@
         "public:\n",
         descriptor_);
   }
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "$deprecated_attr$void "
-        "${1$unsafe_arena_set_allocated_$name$$}$(\n"
-        "    $type$* $name$);\n"
-        "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n",
-        descriptor_);
-  }
+  format(
+      "$deprecated_attr$void "
+      "${1$unsafe_arena_set_allocated_$name$$}$(\n"
+      "    $type$* $name$);\n"
+      "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n",
+      descriptor_);
 }
 
 void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
@@ -162,55 +159,60 @@
       "inline const $type$& $classname$::_internal_$name$() const {\n"
       "$type_reference_function$"
       "  const $type$* p = $casted_member$;\n"
-      "  return p != nullptr ? *p : *reinterpret_cast<const $type$*>(\n"
-      "      &$type_default_instance$);\n"
+      "  return p != nullptr ? *p : reinterpret_cast<const $type$&>(\n"
+      "      $type_default_instance$);\n"
       "}\n"
       "inline const $type$& $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n");
 
-  if (SupportsArenas(descriptor_)) {
+  format(
+      "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+      "    $type$* $name$) {\n"
+      // If we're not on an arena, free whatever we were holding before.
+      // (If we are on arena, we can just forget the earlier pointer.)
+      "  if (GetArenaForAllocation() == nullptr) {\n"
+      "    delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n"
+      "  }\n");
+  if (implicit_weak_field_) {
     format(
-        "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
-        "    $type$* $name$) {\n"
-        "$annotate_accessor$"
-        // If we're not on an arena, free whatever we were holding before.
-        // (If we are on arena, we can just forget the earlier pointer.)
-        "  if (GetArena() == nullptr) {\n"
-        "    delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n"
-        "  }\n");
-    if (implicit_weak_field_) {
-      format(
-          "  $name$_ = "
-          "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n");
-    } else {
-      format("  $name$_ = $name$;\n");
-    }
-    format(
-        "  if ($name$) {\n"
-        "    $set_hasbit$\n"
-        "  } else {\n"
-        "    $clear_hasbit$\n"
-        "  }\n"
-        "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
-        ":$full_name$)\n"
-        "}\n");
-    format(
-        "inline $type$* $classname$::$release_name$() {\n"
-        "  auto temp = unsafe_arena_release_$name$();\n"
-        "  if (GetArena() != nullptr) {\n"
-        "    temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
-        "  }\n"
-        "  return temp;\n"
-        "}\n"
-        "inline $type$* $classname$::unsafe_arena_release_$name$() {\n");
+        "  $name$_ = "
+        "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n");
   } else {
-    format("inline $type$* $classname$::$release_name$() {\n");
+    format("  $name$_ = $name$;\n");
   }
   format(
-      "$annotate_accessor$"
+      "  if ($name$) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "$annotate_set$"
+      "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
+      ":$full_name$)\n"
+      "}\n");
+  format(
+      "inline $type$* $classname$::$release_name$() {\n"
+      "$type_reference_function$"
+      "$annotate_release$"
+      "  $clear_hasbit$\n"
+      "  $type$* temp = $casted_member$;\n"
+      "  $name$_ = nullptr;\n"
+      "#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE\n"
+      "  auto* old =  reinterpret_cast<::$proto_ns$::MessageLite*>(temp);\n"
+      "  temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
+      "  if (GetArenaForAllocation() == nullptr) { delete old; }\n"
+      "#else  // PROTOBUF_FORCE_COPY_IN_RELEASE\n"
+      "  if (GetArenaForAllocation() != nullptr) {\n"
+      "    temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
+      "  }\n"
+      "#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE\n"
+      "  return temp;\n"
+      "}\n"
+      "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "$annotate_release$"
       "  // @@protoc_insertion_point(field_release:$full_name$)\n"
       "$type_reference_function$"
       "  $clear_hasbit$\n"
@@ -224,7 +226,7 @@
       "$type_reference_function$"
       "  $set_hasbit$\n"
       "  if ($name$_ == nullptr) {\n"
-      "    auto* p = CreateMaybeMessage<$type$>(GetArena());\n");
+      "    auto* p = CreateMaybeMessage<$type$>(GetArenaForAllocation());\n");
   if (implicit_weak_field_) {
     format("    $name$_ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n");
   } else {
@@ -235,17 +237,17 @@
       "  return $casted_member$;\n"
       "}\n"
       "inline $type$* $classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "  $type$* _msg = _internal_mutable_$name$();\n"
+      "$annotate_mutable$"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return _internal_mutable_$name$();\n"
+      "  return _msg;\n"
       "}\n");
 
   // We handle the most common case inline, and delegate less common cases to
   // the slow fallback function.
   format(
       "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
-      "$annotate_accessor$"
-      "  ::$proto_ns$::Arena* message_arena = GetArena();\n");
+      "  ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n");
   format("  if (message_arena == nullptr) {\n");
   if (IsCrossFileMessage(descriptor_)) {
     format(
@@ -256,20 +258,20 @@
   format(
       "  }\n"
       "  if ($name$) {\n");
-  if (SupportsArenas(descriptor_->message_type()) &&
-      IsCrossFileMessage(descriptor_)) {
+  if (IsCrossFileMessage(descriptor_)) {
     // We have to read the arena through the virtual method, because the type
     // isn't defined in this file.
     format(
         "    ::$proto_ns$::Arena* submessage_arena =\n"
-        "      "
-        "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n");
-  } else if (!SupportsArenas(descriptor_->message_type())) {
-    format("    ::$proto_ns$::Arena* submessage_arena = nullptr;\n");
+        "        ::$proto_ns$::Arena::InternalHelper<\n"
+        "            ::$proto_ns$::MessageLite>::GetOwningArena(\n"
+        "                reinterpret_cast<::$proto_ns$::MessageLite*>("
+        "$name$));\n");
   } else {
     format(
         "    ::$proto_ns$::Arena* submessage_arena =\n"
-        "      ::$proto_ns$::Arena::GetArena($name$);\n");
+        "        ::$proto_ns$::Arena::InternalHelper<$type$>::GetOwningArena("
+        "$name$);\n");
   }
   format(
       "    if (message_arena != submessage_arena) {\n"
@@ -286,6 +288,7 @@
     format("  $name$_ = $name$;\n");
   }
   format(
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
       "}\n");
 }
@@ -327,48 +330,27 @@
         "*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n"
         "  }\n"
         "}\n");
-    if (SupportsArenas(descriptor_)) {
-      format(
-          "::$proto_ns$::MessageLite*\n"
-          "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
-      if (HasFieldPresence(descriptor_->file())) {
-        format("  msg->$set_hasbit$\n");
-      }
-      format(
-          "  if (msg->$name$_ == nullptr) {\n"
-          "    if ($type_default_instance_ptr$ == nullptr) {\n"
-          "      msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
-          "          ::$proto_ns$::internal::ImplicitWeakMessage>(\n"
-          "              msg->GetArena());\n"
-          "    } else {\n"
-          "      msg->$name$_ = reinterpret_cast<const "
-          "::$proto_ns$::MessageLite*>(\n"
-          "          $type_default_instance_ptr$)->New(msg->GetArena());\n"
-          "    }\n"
-          "  }\n"
-          "  return msg->$name$_;\n"
-          "}\n");
-    } else {
-      format(
-          "::$proto_ns$::MessageLite*\n"
-          "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
-      if (HasFieldPresence(descriptor_->file())) {
-        format("  msg->$set_hasbit$\n");
-      }
-      format(
-          "  if (msg->$name$_ == nullptr) {\n"
-          "    if ($type_default_instance_ptr$ == nullptr) {\n"
-          "      msg->$name$_ = "
-          "new ::$proto_ns$::internal::ImplicitWeakMessage;\n"
-          "    } else {\n"
-          "      msg->$name$_ = "
-          "reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
-          "          $type_default_instance_ptr$)->New();\n"
-          "    }\n"
-          "  }\n"
-          "  return msg->$name$_;\n"
-          "}\n");
+    format(
+        "::$proto_ns$::MessageLite*\n"
+        "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
+    if (HasHasbit(descriptor_)) {
+      format("  msg->$set_hasbit$\n");
     }
+    format(
+        "  if (msg->$name$_ == nullptr) {\n"
+        "    if ($type_default_instance_ptr$ == nullptr) {\n"
+        "      msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
+        "          ::$proto_ns$::internal::ImplicitWeakMessage>(\n"
+        "              msg->GetArenaForAllocation());\n"
+        "    } else {\n"
+        "      msg->$name$_ = \n"
+        "          reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
+        "              $type_default_instance_ptr$)->New(\n"
+        "                  msg->GetArenaForAllocation());\n"
+        "    }\n"
+        "  }\n"
+        "  return msg->$name$_;\n"
+        "}\n");
   } else {
     // This inline accessor directly returns member field and is used in
     // Serialize such that AFDO profile correctly captures access information to
@@ -382,14 +364,14 @@
 }
 
 void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
-  if (!HasFieldPresence(descriptor_->file())) {
+  if (!HasHasbit(descriptor_)) {
     // If we don't have has-bits, message presence is indicated only by ptr !=
     // NULL. Thus on clear, we need to delete the object.
     format(
-        "if (GetArena() == nullptr && $name$_ != nullptr) {\n"
+        "if (GetArenaForAllocation() == nullptr && $name$_ != nullptr) {\n"
         "  delete $name$_;\n"
         "}\n"
         "$name$_ = nullptr;\n");
@@ -400,14 +382,14 @@
 
 void MessageFieldGenerator::GenerateMessageClearingCode(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
-  if (!HasFieldPresence(descriptor_->file())) {
+  if (!HasHasbit(descriptor_)) {
     // If we don't have has-bits, message presence is indicated only by ptr !=
     // NULL. Thus on clear, we need to delete the object.
     format(
-        "if (GetArena() == nullptr && $name$_ != nullptr) {\n"
+        "if (GetArenaForAllocation() == nullptr && $name$_ != nullptr) {\n"
         "  delete $name$_;\n"
         "}\n"
         "$name$_ = nullptr;\n");
@@ -419,7 +401,7 @@
 }
 
 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   if (implicit_weak_field_) {
@@ -434,14 +416,14 @@
 }
 
 void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format("swap($name$_, other->$name$_);\n");
 }
 
 void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   if (options_.opensource_runtime) {
@@ -457,7 +439,7 @@
 
 void MessageFieldGenerator::GenerateConstructorCode(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format("$name$_ = nullptr;\n");
@@ -465,7 +447,7 @@
 
 void MessageFieldGenerator::GenerateCopyConstructorCode(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format(
@@ -478,7 +460,7 @@
 
 void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format(
@@ -489,7 +471,7 @@
 }
 
 void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format(
@@ -498,6 +480,12 @@
       "    *$field_member$);\n");
 }
 
+void MessageFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_(nullptr)");
+}
+
 // ===================================================================
 
 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
@@ -514,24 +502,23 @@
   Formatter format(printer, variables_);
   format(
       "void $classname$::set_allocated_$name$($type$* $name$) {\n"
-      "$annotate_accessor$"
-      "  ::$proto_ns$::Arena* message_arena = GetArena();\n"
+      "  ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n"
       "  clear_$oneof_name$();\n"
       "  if ($name$) {\n");
-  if (SupportsArenas(descriptor_->message_type()) &&
-      descriptor_->file() != descriptor_->message_type()->file()) {
+  if (descriptor_->file() != descriptor_->message_type()->file()) {
     // We have to read the arena through the virtual method, because the type
     // isn't defined in this file.
     format(
         "    ::$proto_ns$::Arena* submessage_arena =\n"
-        "      "
-        "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n");
-  } else if (!SupportsArenas(descriptor_->message_type())) {
-    format("    ::$proto_ns$::Arena* submessage_arena = nullptr;\n");
+        "        ::$proto_ns$::Arena::InternalHelper<\n"
+        "            ::$proto_ns$::MessageLite>::GetOwningArena(\n"
+        "                reinterpret_cast<::$proto_ns$::MessageLite*>("
+        "$name$));\n");
   } else {
     format(
         "    ::$proto_ns$::Arena* submessage_arena =\n"
-        "      ::$proto_ns$::Arena::GetArena($name$);\n");
+        "      ::$proto_ns$::Arena::InternalHelper<"
+        "$type$>::GetOwningArena($name$);\n");
   }
   format(
       "    if (message_arena != submessage_arena) {\n"
@@ -541,6 +528,7 @@
       "    set_has_$name$();\n"
       "    $field_member$ = $name$;\n"
       "  }\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
       "}\n");
 }
@@ -550,18 +538,14 @@
   Formatter format(printer, variables_);
   format(
       "inline $type$* $classname$::$release_name$() {\n"
-      "$annotate_accessor$"
+      "$annotate_release$"
       "  // @@protoc_insertion_point(field_release:$full_name$)\n"
       "  if (_internal_has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
-      "      $type$* temp = $field_member$;\n");
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "    if (GetArena() != nullptr) {\n"
-        "      temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
-        "    }\n");
-  }
-  format(
+      "      $type$* temp = $field_member$;\n"
+      "    if (GetArenaForAllocation() != nullptr) {\n"
+      "      temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
+      "    }\n"
       "    $field_member$ = nullptr;\n"
       "    return temp;\n"
       "  } else {\n"
@@ -573,74 +557,66 @@
       "inline const $type$& $classname$::_internal_$name$() const {\n"
       "  return _internal_has_$name$()\n"
       "      ? *$field_member$\n"
-      "      : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
+      "      : reinterpret_cast< $type$&>($type_default_instance$);\n"
       "}\n"
       "inline const $type$& $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
-      "}\n");
-
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_unsafe_arena_release"
-        ":$full_name$)\n"
-        "  if (_internal_has_$name$()) {\n"
-        "    clear_has_$oneof_name$();\n"
-        "    $type$* temp = $field_member$;\n"
-        "    $field_member$ = nullptr;\n"
-        "    return temp;\n"
-        "  } else {\n"
-        "    return nullptr;\n"
-        "  }\n"
-        "}\n"
-        "inline void $classname$::unsafe_arena_set_allocated_$name$"
-        "($type$* $name$) {\n"
-        "$annotate_accessor$"
-        // We rely on the oneof clear method to free the earlier contents of
-        // this oneof. We can directly use the pointer we're given to set the
-        // new value.
-        "  clear_$oneof_name$();\n"
-        "  if ($name$) {\n"
-        "    set_has_$name$();\n"
-        "    $field_member$ = $name$;\n"
-        "  }\n"
-        "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
-        "$full_name$)\n"
-        "}\n");
-  }
-
-  format(
+      "}\n"
+      "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "$annotate_release$"
+      "  // @@protoc_insertion_point(field_unsafe_arena_release"
+      ":$full_name$)\n"
+      "  if (_internal_has_$name$()) {\n"
+      "    clear_has_$oneof_name$();\n"
+      "    $type$* temp = $field_member$;\n"
+      "    $field_member$ = nullptr;\n"
+      "    return temp;\n"
+      "  } else {\n"
+      "    return nullptr;\n"
+      "  }\n"
+      "}\n"
+      "inline void $classname$::unsafe_arena_set_allocated_$name$"
+      "($type$* $name$) {\n"
+      // We rely on the oneof clear method to free the earlier contents of
+      // this oneof. We can directly use the pointer we're given to set the
+      // new value.
+      "  clear_$oneof_name$();\n"
+      "  if ($name$) {\n"
+      "    set_has_$name$();\n"
+      "    $field_member$ = $name$;\n"
+      "  }\n"
+      "$annotate_set$"
+      "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+      "$full_name$)\n"
+      "}\n"
       "inline $type$* $classname$::_internal_mutable_$name$() {\n"
       "  if (!_internal_has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
-      "    $field_member$ = CreateMaybeMessage< $type$ >(GetArena());\n"
+      "    $field_member$ = CreateMaybeMessage< $type$ "
+      ">(GetArenaForAllocation());\n"
       "  }\n"
       "  return $field_member$;\n"
       "}\n"
       "inline $type$* $classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "  $type$* _msg = _internal_mutable_$name$();\n"
+      "$annotate_mutable$"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return _internal_mutable_$name$();\n"
+      "  return _msg;\n"
       "}\n");
 }
 
 void MessageOneofFieldGenerator::GenerateClearingCode(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "if (GetArena() == nullptr) {\n"
-        "  delete $field_member$;\n"
-        "}\n");
-  } else {
-    format("delete $field_member$;\n");
-  }
+  format(
+      "if (GetArenaForAllocation() == nullptr) {\n"
+      "  delete $field_member$;\n"
+      "}\n");
 }
 
 void MessageOneofFieldGenerator::GenerateMessageClearingCode(
@@ -691,7 +667,7 @@
 void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (!IsFieldUsed(descriptor_, options_)) {
+  if (IsFieldStripped(descriptor_, options_)) {
     format(
         "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { "
         "__builtin_trap(); }\n"
@@ -711,7 +687,7 @@
       "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
       "    ${1$mutable_$name$$}$();\n",
       descriptor_);
-  if (IsFieldUsed(descriptor_, options_)) {
+  if (!IsFieldStripped(descriptor_, options_)) {
     format(
         "private:\n"
         "const $type$& ${1$_internal_$name$$}$(int index) const;\n"
@@ -734,7 +710,7 @@
 
   format(
       "inline $type$* $classname$::mutable_$name$(int index) {\n"
-      "$annotate_accessor$"
+      "$annotate_mutable$"
       // TODO(dlj): move insertion points
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "$type_reference_function$"
@@ -742,7 +718,7 @@
       "}\n"
       "inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n"
       "$classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "$annotate_mutable_list$"
       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
       "$type_reference_function$"
       "  return &$name$_$weak$;\n"
@@ -753,7 +729,7 @@
         "inline const $type$& $classname$::_internal_$name$(int index) const "
         "{\n"
         "  return $name$_$weak$.InternalCheckedGet(index,\n"
-        "      *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
+        "      reinterpret_cast<const $type$&>($type_default_instance$));\n"
         "}\n");
   } else {
     format(
@@ -766,7 +742,7 @@
 
   format(
       "inline const $type$& $classname$::$name$(int index) const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$(index);\n"
       "}\n"
@@ -774,15 +750,16 @@
       "  return $name$_$weak$.Add();\n"
       "}\n"
       "inline $type$* $classname$::add_$name$() {\n"
-      "$annotate_accessor$"
+      "  $type$* _add = _internal_add_$name$();\n"
+      "$annotate_add_mutable$"
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-      "  return _internal_add_$name$();\n"
+      "  return _add;\n"
       "}\n");
 
   format(
       "inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
       "$classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_list$"
       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
       "$type_reference_function$"
       "  return $name$_$weak$;\n"
@@ -791,7 +768,7 @@
 
 void RepeatedMessageFieldGenerator::GenerateClearingCode(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format("$name$_.Clear();\n");
@@ -799,7 +776,7 @@
 
 void RepeatedMessageFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format("$name$_.MergeFrom(from.$name$_);\n");
@@ -807,7 +784,7 @@
 
 void RepeatedMessageFieldGenerator::GenerateSwappingCode(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format("$name$_.InternalSwap(&other->$name$_);\n");
@@ -820,7 +797,7 @@
 
 void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   if (implicit_weak_field_) {
@@ -847,7 +824,7 @@
 
 void RepeatedMessageFieldGenerator::GenerateByteSize(
     io::Printer* printer) const {
-  GOOGLE_CHECK(IsFieldUsed(descriptor_, options_));
+  GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
   format(
@@ -858,6 +835,12 @@
       "}\n");
 }
 
+void RepeatedMessageFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index fe5cf13..712ddbf 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -53,21 +53,25 @@
   ~MessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateInternalAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInternalAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMessageClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateDestructorCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateNonInlineAccessorDefinitions(
+      io::Printer* printer) const override;
+  void GenerateInternalAccessorDeclarations(
+      io::Printer* printer) const override;
+  void GenerateInternalAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMessageClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateDestructorCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override;
+  void GenerateSerializeWithCachedSizesToArray(
+      io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  protected:
   const bool implicit_weak_field_;
@@ -84,16 +88,17 @@
   ~MessageOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateNonInlineAccessorDefinitions(
+      io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
 
   // MessageFieldGenerator, from which we inherit, overrides this so we need to
   // override it as well.
-  void GenerateMessageClearingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateDestructorCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateMessageClearingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateDestructorCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
@@ -107,16 +112,18 @@
   ~RepeatedMessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const {}
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override {}
+  void GenerateSerializeWithCachedSizesToArray(
+      io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  private:
   const bool implicit_weak_field_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
index 67eeff0..9d8063d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
@@ -43,6 +43,8 @@
 namespace compiler {
 namespace cpp {
 
+class MessageSCCAnalyzer;
+
 // Provides an abstract interface to optimize message layout
 // by rearranging the fields of a message.
 class MessageLayoutHelper {
@@ -50,7 +52,8 @@
   virtual ~MessageLayoutHelper() {}
 
   virtual void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
-                              const Options& options) = 0;
+                              const Options& options,
+                              MessageSCCAnalyzer* scc_analyzer) = 0;
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_names.h b/src/google/protobuf/compiler/cpp/cpp_names.h
new file mode 100644
index 0000000..cbc69a7
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_names.h
@@ -0,0 +1,90 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
+
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class EnumValueDescriptor;
+class FieldDescriptor;
+
+namespace compiler {
+namespace cpp {
+
+// Returns the unqualified C++ name.
+//
+// For example, if you had:
+//   package foo.bar;
+//   message Baz { message Qux {} }
+// Then the non-qualified version would be:
+//   Baz_Qux
+std::string ClassName(const Descriptor* descriptor);
+std::string ClassName(const EnumDescriptor* enum_descriptor);
+
+// Returns the fully qualified C++ name.
+//
+// For example, if you had:
+//   package foo.bar;
+//   message Baz { message Qux {} }
+// Then the qualified ClassName for Qux would be:
+//   ::foo::bar::Baz_Qux
+std::string QualifiedClassName(const Descriptor* d);
+std::string QualifiedClassName(const EnumDescriptor* d);
+std::string QualifiedExtensionName(const FieldDescriptor* d);
+
+// Get the (unqualified) name that should be used for this field in C++ code.
+// The name is coerced to lower-case to emulate proto1 behavior.  People
+// should be using lowercase-with-underscores style for proto field names
+// anyway, so normally this just returns field->name().
+std::string FieldName(const FieldDescriptor* field);
+
+// Get the (unqualified) name that should be used for this enum value in C++
+// code.
+std::string EnumValueName(const EnumValueDescriptor* enum_value);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 92b5548..2e97c3d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -69,6 +69,14 @@
   std::string annotation_pragma_name;
   std::string annotation_guard_name;
   const AccessInfoMap* access_info_map = nullptr;
+  enum {
+    kTCTableNever,
+    kTCTableGuarded,
+    kTCTableAlways
+  } tctable_mode = kTCTableNever;
+  bool inject_field_listener_events = false;
+  bool eagerly_verified_lazy = false;
+  bool force_eagerly_verified_lazy = false;
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
index 2f78bda..0b660c7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
@@ -118,7 +118,8 @@
 //
 // OTHER these fields are initialized one-by-one.
 void PaddingOptimizer::OptimizeLayout(
-    std::vector<const FieldDescriptor*>* fields, const Options& options) {
+    std::vector<const FieldDescriptor*>* fields, const Options& options,
+    MessageSCCAnalyzer* scc_analyzer) {
   // The sorted numeric order of Family determines the declaration order in the
   // memory layout.
   enum Family {
@@ -147,7 +148,7 @@
       f = STRING;
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       f = MESSAGE;
-      if (IsLazy(field, options)) {
+      if (IsLazy(field, options, scc_analyzer)) {
         f = LAZY_MESSAGE;
       }
     } else if (CanInitializeByZeroing(field)) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
index 2382081..ebdb17d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
+++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
@@ -53,7 +53,8 @@
   ~PaddingOptimizer() override {}
 
   void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
-                      const Options& options) override;
+                      const Options& options,
+                      MessageSCCAnalyzer* scc_analyzer) override;
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
new file mode 100644
index 0000000..6886b4f
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
@@ -0,0 +1,1178 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
+
+#include <limits>
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+using google::protobuf::internal::TcFieldData;
+using google::protobuf::internal::WireFormat;
+using google::protobuf::internal::WireFormatLite;
+
+std::vector<const FieldDescriptor*> GetOrderedFields(
+    const Descriptor* descriptor, const Options& options) {
+  std::vector<const FieldDescriptor*> ordered_fields;
+  for (auto field : FieldRange(descriptor)) {
+    if (!IsFieldStripped(field, options)) {
+      ordered_fields.push_back(field);
+    }
+  }
+  std::sort(ordered_fields.begin(), ordered_fields.end(),
+            [](const FieldDescriptor* a, const FieldDescriptor* b) {
+              return a->number() < b->number();
+            });
+  return ordered_fields;
+}
+
+bool HasInternalAccessors(const FieldOptions::CType ctype) {
+  return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
+}
+
+bool IsTcTableEnabled(const Options& options) {
+  return options.tctable_mode == Options::kTCTableAlways;
+}
+bool IsTcTableGuarded(const Options& options) {
+  return options.tctable_mode == Options::kTCTableGuarded;
+}
+bool IsTcTableDisabled(const Options& options) {
+  return options.tctable_mode == Options::kTCTableNever;
+}
+
+int TagSize(uint32_t field_number) {
+  if (field_number < 16) return 1;
+  GOOGLE_CHECK_LT(field_number, (1 << 14))
+      << "coded tag for " << field_number << " too big for uint16_t";
+  return 2;
+}
+
+const char* TagType(const FieldDescriptor* field) {
+  return CodedTagType(TagSize(field->number()));
+}
+
+std::string MessageParseFunctionName(const FieldDescriptor* field,
+                                     const Options& options) {
+  std::string name =
+      "::" + ProtobufNamespace(options) + "::internal::TcParserBase::";
+  if (field->is_repeated()) {
+    name.append("Repeated");
+  } else {
+    name.append("Singular");
+  }
+  name.append("ParseMessage<" + QualifiedClassName(field->message_type()) +
+              ", " + TagType(field) + ">");
+  return name;
+}
+
+std::string FieldParseFunctionName(const FieldDescriptor* field,
+                                   const Options& options,
+                                   uint32_t table_size_log2);
+
+}  // namespace
+
+const char* CodedTagType(int tag_size) {
+  return tag_size == 1 ? "uint8_t" : "uint16_t";
+}
+
+TailCallTableInfo::TailCallTableInfo(const Descriptor* descriptor,
+                                     const Options& options,
+                                     const std::vector<int>& has_bit_indices,
+                                     MessageSCCAnalyzer* scc_analyzer) {
+  std::vector<const FieldDescriptor*> ordered_fields =
+      GetOrderedFields(descriptor, options);
+
+  // The table size is rounded up to the nearest power of 2, clamping at 2^5.
+  // Note that this is a naive approach: a better approach should only consider
+  // table-eligible fields. We may also want to push rarely-encountered fields
+  // into the fallback, to make the table smaller.
+  table_size_log2 = ordered_fields.size() >= 16  ? 5
+                    : ordered_fields.size() >= 8 ? 4
+                    : ordered_fields.size() >= 4 ? 3
+                    : ordered_fields.size() >= 2 ? 2
+                                                 : 1;
+  const unsigned table_size = 1 << table_size_log2;
+
+  // Construct info for each possible entry. Fields that do not use table-driven
+  // parsing will still have an entry that nominates the fallback function.
+  fast_path_fields.resize(table_size);
+
+  for (const auto* field : ordered_fields) {
+    // Eagerly assume slow path. If we can handle this field on the fast path,
+    // we will pop its entry from `fallback_fields`.
+    fallback_fields.push_back(field);
+
+    // Anything difficult slow path:
+    if (field->is_map()) continue;
+    if (field->real_containing_oneof()) continue;
+    if (field->options().lazy()) continue;
+    if (field->options().weak()) continue;
+    if (IsImplicitWeakField(field, options, scc_analyzer)) continue;
+
+    // The largest tag that can be read by the tailcall parser is two bytes
+    // when varint-coded. This allows 14 bits for the numeric tag value:
+    //   byte 0   byte 1
+    //   1nnnnttt 0nnnnnnn
+    //    ^^^^^^^  ^^^^^^^
+    uint32_t tag = WireFormat::MakeTag(field);
+    if (tag >= 1 << 14) {
+      continue;
+    } else if (tag >= 1 << 7) {
+      tag = ((tag << 1) & 0x7F00) | 0x80 | (tag & 0x7F);
+    }
+    // The field index is determined by the low bits of the field number, where
+    // the table size determines the width of the mask. The largest table
+    // supported is 32 entries. The parse loop uses these bits directly, so that
+    // the dispatch does not require arithmetic:
+    //   byte 0   byte 1
+    //   1nnnnttt 0nnnnnnn
+    //   ^^^^^
+    // This means that any field number that does not fit in the lower 4 bits
+    // will always have the top bit of its table index asserted:
+    uint32_t idx = (tag >> 3) & (table_size - 1);
+    // If this entry in the table is already used, then this field will be
+    // handled by the generated fallback function.
+    if (!fast_path_fields[idx].func_name.empty()) continue;
+
+    // Determine the hasbit mask for this field, if needed. (Note that fields
+    // without hasbits use different parse functions.)
+    int hasbit_idx;
+    if (HasHasbit(field)) {
+      hasbit_idx = has_bit_indices[field->index()];
+      GOOGLE_CHECK_NE(-1, hasbit_idx) << field->DebugString();
+      // The tailcall parser can only update the first 32 hasbits. If this
+      // field's has-bit is beyond that, then it will need to be handled by the
+      // fallback parse function.
+      if (hasbit_idx >= 32) continue;
+    } else {
+      // The tailcall parser only ever syncs 32 has-bits, so if there is no
+      // presence, set a bit that will not be used.
+      hasbit_idx = 63;
+    }
+
+    // Determine the name of the fastpath parse function to use for this field.
+    std::string name;
+
+    switch (field->type()) {
+      case FieldDescriptor::TYPE_MESSAGE:
+        name = MessageParseFunctionName(field, options);
+        break;
+
+      case FieldDescriptor::TYPE_FIXED64:
+      case FieldDescriptor::TYPE_FIXED32:
+      case FieldDescriptor::TYPE_SFIXED64:
+      case FieldDescriptor::TYPE_SFIXED32:
+      case FieldDescriptor::TYPE_DOUBLE:
+      case FieldDescriptor::TYPE_FLOAT:
+      case FieldDescriptor::TYPE_INT64:
+      case FieldDescriptor::TYPE_INT32:
+      case FieldDescriptor::TYPE_UINT64:
+      case FieldDescriptor::TYPE_UINT32:
+      case FieldDescriptor::TYPE_SINT64:
+      case FieldDescriptor::TYPE_SINT32:
+      case FieldDescriptor::TYPE_BOOL:
+        name = FieldParseFunctionName(field, options, table_size_log2);
+        break;
+
+      case FieldDescriptor::TYPE_BYTES:
+        if (field->options().ctype() == FieldOptions::STRING &&
+            field->default_value_string().empty()) {
+          name = FieldParseFunctionName(field, options, table_size_log2);
+        }
+        break;
+
+      default:
+        break;
+    }
+
+    if (name.empty()) {
+      continue;
+    }
+    // This field made it into the fast path, so remove it from the fallback
+    // fields and fill in the table entry.
+    fallback_fields.pop_back();
+    fast_path_fields[idx].func_name = name;
+    fast_path_fields[idx].bits = TcFieldData(tag, hasbit_idx, 0);
+    fast_path_fields[idx].field = field;
+  }
+
+  // Construct a mask of has-bits for required fields numbered <= 32.
+  has_hasbits_required_mask = 0;
+  for (auto field : FieldRange(descriptor)) {
+    if (field->is_required()) {
+      int idx = has_bit_indices[field->index()];
+      if (idx >= 32) continue;
+      has_hasbits_required_mask |= 1u << idx;
+    }
+  }
+
+  // If there are no fallback fields, and at most one extension range, the
+  // parser can use a generic fallback function. Otherwise, a message-specific
+  // fallback routine is needed.
+  use_generated_fallback =
+      !fallback_fields.empty() || descriptor->extension_range_count() > 1;
+}
+
+ParseFunctionGenerator::ParseFunctionGenerator(
+    const Descriptor* descriptor, int max_has_bit_index,
+    const std::vector<int>& has_bit_indices, const Options& options,
+    MessageSCCAnalyzer* scc_analyzer,
+    const std::map<std::string, std::string>& vars)
+    : descriptor_(descriptor),
+      scc_analyzer_(scc_analyzer),
+      options_(options),
+      variables_(vars),
+      num_hasbits_(max_has_bit_index) {
+  if (IsTcTableGuarded(options_) || IsTcTableEnabled(options_)) {
+    tc_table_info_.reset(new TailCallTableInfo(descriptor_, options_,
+                                               has_bit_indices, scc_analyzer));
+  }
+  SetCommonVars(options_, &variables_);
+  SetUnknownFieldsVariable(descriptor_, options_, &variables_);
+  variables_["classname"] = ClassName(descriptor, false);
+}
+
+void ParseFunctionGenerator::GenerateMethodDecls(io::Printer* printer) {
+  Formatter format(printer, variables_);
+  if (IsTcTableGuarded(options_)) {
+    format.Outdent();
+    format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+    format.Indent();
+  }
+  if (IsTcTableGuarded(options_) || IsTcTableEnabled(options_)) {
+    if (tc_table_info_->use_generated_fallback) {
+      format(
+          "static const char* Tct_ParseFallback(\n"
+          "    ::$proto_ns$::MessageLite *msg, const char *ptr,\n"
+          "    ::$proto_ns$::internal::ParseContext *ctx,\n"
+          "    const ::$proto_ns$::internal::TailCallParseTableBase *table,\n"
+          "    uint64_t hasbits, ::$proto_ns$::internal::TcFieldData data);\n"
+          "inline const char* Tct_FallbackImpl(\n"
+          "    const char* ptr, ::$proto_ns$::internal::ParseContext* ctx,\n"
+          "    const void*, $uint64$ hasbits);\n");
+    }
+  }
+  if (IsTcTableGuarded(options_)) {
+    format.Outdent();
+    format("#endif\n");
+    format.Indent();
+  }
+  format(
+      "const char* _InternalParse(const char* ptr, "
+      "::$proto_ns$::internal::ParseContext* ctx) final;\n");
+}
+
+void ParseFunctionGenerator::GenerateMethodImpls(io::Printer* printer) {
+  Formatter format(printer, variables_);
+  if (descriptor_->options().message_set_wire_format()) {
+    // Special-case MessageSet.
+    format(
+        "const char* $classname$::_InternalParse(const char* ptr,\n"
+        "                  ::$proto_ns$::internal::ParseContext* ctx) {\n"
+        "$annotate_deserialize$"
+        "  return _extensions_.ParseMessageSet(ptr, \n"
+        "      internal_default_instance(), &_internal_metadata_, ctx);\n"
+        "}\n");
+    return;
+  }
+  if (IsTcTableGuarded(options_)) {
+    format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n\n");
+  }
+  if (IsTcTableGuarded(options_) || IsTcTableEnabled(options_)) {
+    format(
+        "const char* $classname$::_InternalParse(\n"
+        "    const char* ptr, ::$proto_ns$::internal::ParseContext* ctx) {\n"
+        "  return ::$proto_ns$::internal::TcParser<$1$>::ParseLoop(\n"
+        "      this, ptr, ctx, &_table_.header);\n"
+        "}\n"
+        "\n",
+        tc_table_info_->table_size_log2);
+    if (tc_table_info_->use_generated_fallback) {
+      GenerateTailcallFallbackFunction(format);
+    }
+  }
+  if (IsTcTableGuarded(options_)) {
+    format("\n#else  // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n\n");
+  }
+  if (IsTcTableGuarded(options_) || IsTcTableDisabled(options_)) {
+    GenerateLoopingParseFunction(format);
+  }
+  if (IsTcTableGuarded(options_)) {
+    format("\n#endif  // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+  }
+}
+
+void ParseFunctionGenerator::GenerateTailcallFallbackFunction(
+    Formatter& format) {
+  format(
+      "const char* $classname$::Tct_ParseFallback(PROTOBUF_TC_PARAM_DECL) {\n"
+      "  return static_cast<$classname$*>(msg)->Tct_FallbackImpl(ptr, ctx, "
+      "table, hasbits);\n"
+      "}\n\n");
+
+  format(
+      "const char* $classname$::Tct_FallbackImpl(const char* ptr, "
+      "::$proto_ns$::internal::ParseContext* ctx, const void*, "
+      "$uint64$ hasbits) {\n"
+      "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr\n");
+  format.Indent();
+
+  if (num_hasbits_ > 0) {
+    // Sync hasbits
+    format("_has_bits_[0] = hasbits;\n");
+  }
+
+  format.Set("has_bits", "_has_bits_");
+  format.Set("continue", "goto success");
+  GenerateParseIterationBody(format, descriptor_,
+                             tc_table_info_->fallback_fields);
+
+  format.Outdent();
+  format("success:\n");
+  format("  return ptr;\n");
+  format(
+      "#undef CHK_\n"
+      "}\n");
+}
+
+void ParseFunctionGenerator::GenerateDataDecls(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    return;
+  }
+  Formatter format(printer, variables_);
+  if (IsTcTableGuarded(options_)) {
+    format.Outdent();
+    format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+    format.Indent();
+  }
+  if (IsTcTableGuarded(options_) || IsTcTableEnabled(options_)) {
+    format(
+        "static const ::$proto_ns$::internal::TailCallParseTable<$1$>\n"
+        "    _table_;\n",
+        tc_table_info_->table_size_log2);
+  }
+  if (IsTcTableGuarded(options_)) {
+    format.Outdent();
+    format("#endif  // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+    format.Indent();
+  }
+}
+
+void ParseFunctionGenerator::GenerateDataDefinitions(io::Printer* printer) {
+  if (descriptor_->options().message_set_wire_format()) {
+    return;
+  }
+  Formatter format(printer, variables_);
+  if (IsTcTableGuarded(options_)) {
+    format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+  }
+  if (IsTcTableGuarded(options_) || IsTcTableEnabled(options_)) {
+    GenerateTailCallTable(format);
+  }
+  if (IsTcTableGuarded(options_)) {
+    format("#endif  // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+  }
+}
+
+void ParseFunctionGenerator::GenerateLoopingParseFunction(Formatter& format) {
+  format(
+      "const char* $classname$::_InternalParse(const char* ptr, "
+      "::$proto_ns$::internal::ParseContext* ctx) {\n"
+      "$annotate_deserialize$"
+      "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure\n");
+  format.Indent();
+  int hasbits_size = 0;
+  if (num_hasbits_ > 0) {
+    hasbits_size = (num_hasbits_ + 31) / 32;
+  }
+  // For now only optimize small hasbits.
+  if (hasbits_size != 1) hasbits_size = 0;
+  if (hasbits_size) {
+    format("_Internal::HasBits has_bits{};\n");
+    format.Set("has_bits", "has_bits");
+  } else {
+    format.Set("has_bits", "_has_bits_");
+  }
+  format.Set("continue", "continue");
+  format("while (!ctx->Done(&ptr)) {\n");
+  format.Indent();
+
+  GenerateParseIterationBody(format, descriptor_,
+                             GetOrderedFields(descriptor_, options_));
+
+  format.Outdent();
+  format("}  // while\n");
+
+  format.Outdent();
+  format("success:\n");
+  if (hasbits_size) format("  _has_bits_.Or(has_bits);\n");
+
+  format(
+      "  return ptr;\n"
+      "failure:\n"
+      "  ptr = nullptr;\n"
+      "  goto success;\n"
+      "#undef CHK_\n"
+      "}\n");
+}
+
+void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) {
+  // All entries without a fast-path parsing function need a fallback.
+  std::string fallback;
+  if (tc_table_info_->use_generated_fallback) {
+    fallback = ClassName(descriptor_) + "::Tct_ParseFallback";
+  } else {
+    fallback = "::" + ProtobufNamespace(options_) +
+               "::internal::TcParserBase::GenericFallback";
+    if (GetOptimizeFor(descriptor_->file(), options_) ==
+        FileOptions::LITE_RUNTIME) {
+      fallback += "Lite";
+    }
+  }
+
+  // For simplicity and speed, the table is not covering all proto
+  // configurations. This model uses a fallback to cover all situations that
+  // the table can't accommodate, together with unknown fields or extensions.
+  // These are number of fields over 32, fields with 3 or more tag bytes,
+  // maps, weak fields, lazy, more than 1 extension range. In the cases
+  // the table is sufficient we can use a generic routine, that just handles
+  // unknown fields and potentially an extension range.
+  format(
+      "const ::$proto_ns$::internal::TailCallParseTable<$1$>\n"
+      "    $classname$::_table_ = {\n",
+      tc_table_info_->table_size_log2);
+  format.Indent();
+  format("{\n");
+  format.Indent();
+  if (num_hasbits_ > 0 || IsMapEntryMessage(descriptor_)) {
+    format("PROTOBUF_FIELD_OFFSET($classname$, _has_bits_),\n");
+  } else {
+    format("0,  // no _has_bits_\n");
+  }
+  if (descriptor_->extension_range_count() == 1) {
+    format(
+        "PROTOBUF_FIELD_OFFSET($classname$, _extensions_),\n"
+        "$1$, $2$,  // extension_range_{low,high}\n",
+        descriptor_->extension_range(0)->start,
+        descriptor_->extension_range(0)->end);
+  } else {
+    format("0, 0, 0,  // no _extensions_\n");
+  }
+  format(
+      "$1$,  // has_bits_required_mask\n"
+      "&$2$._instance,\n"
+      "$3$  // fallback\n",
+      tc_table_info_->has_hasbits_required_mask,
+      DefaultInstanceName(descriptor_, options_), fallback);
+  format.Outdent();
+  format("}, {\n");
+  format.Indent();
+  for (const auto& info : tc_table_info_->fast_path_fields) {
+    if (info.field != nullptr) {
+      PrintFieldComment(format, info.field);
+    }
+    format("{$1$, ", info.func_name.empty() ? fallback : info.func_name);
+    if (info.bits.data) {
+      GOOGLE_DCHECK_NE(nullptr, info.field);
+      format(
+          "{$1$, $2$, "
+          "static_cast<uint16_t>(PROTOBUF_FIELD_OFFSET($classname$, $3$_))}",
+          info.bits.coded_tag(), info.bits.hasbit_idx(), FieldName(info.field));
+    } else {
+      format("{}");
+    }
+    format("},\n");
+  }
+  format.Outdent();
+  format("},\n");  // entries[]
+  format.Outdent();
+  format("};\n\n");  // _table_
+}
+
+void ParseFunctionGenerator::GenerateArenaString(Formatter& format,
+                                                 const FieldDescriptor* field) {
+  if (HasHasbit(field)) {
+    format("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
+  }
+  std::string default_string =
+      field->default_value_string().empty()
+          ? "::" + ProtobufNamespace(options_) +
+                "::internal::GetEmptyStringAlreadyInited()"
+          : QualifiedClassName(field->containing_type(), options_) +
+                "::" + MakeDefaultName(field) + ".get()";
+  format(
+      "if (arena != nullptr) {\n"
+      "  ptr = ctx->ReadArenaString(ptr, &$1$_, arena);\n"
+      "} else {\n"
+      "  ptr = ::$proto_ns$::internal::InlineGreedyStringParser("
+      "$1$_.MutableNoArenaNoDefault(&$2$), ptr, ctx);\n"
+      "}\n"
+      "const std::string* str = &$1$_.Get(); (void)str;\n",
+      FieldName(field), default_string);
+}
+
+void ParseFunctionGenerator::GenerateStrings(Formatter& format,
+                                             const FieldDescriptor* field,
+                                             bool check_utf8) {
+  FieldOptions::CType ctype = FieldOptions::STRING;
+  if (!options_.opensource_runtime) {
+    // Open source doesn't support other ctypes;
+    ctype = field->options().ctype();
+  }
+  if (!field->is_repeated() && !options_.opensource_runtime &&
+      GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
+      // For now only use arena string for strings with empty defaults.
+      field->default_value_string().empty() &&
+      !field->real_containing_oneof() && ctype == FieldOptions::STRING) {
+    GenerateArenaString(format, field);
+  } else {
+    std::string name;
+    switch (ctype) {
+      case FieldOptions::STRING:
+        name = "GreedyStringParser";
+        break;
+      case FieldOptions::CORD:
+        name = "CordParser";
+        break;
+      case FieldOptions::STRING_PIECE:
+        name = "StringPieceParser";
+        break;
+    }
+    format(
+        "auto str = $1$$2$_$3$();\n"
+        "ptr = ::$proto_ns$::internal::Inline$4$(str, ptr, ctx);\n",
+        HasInternalAccessors(ctype) ? "_internal_" : "",
+        field->is_repeated() && !field->is_packable() ? "add" : "mutable",
+        FieldName(field), name);
+  }
+  if (!check_utf8) return;  // return if this is a bytes field
+  auto level = GetUtf8CheckMode(field, options_);
+  switch (level) {
+    case Utf8CheckMode::kNone:
+      return;
+    case Utf8CheckMode::kVerify:
+      format("#ifndef NDEBUG\n");
+      break;
+    case Utf8CheckMode::kStrict:
+      format("CHK_(");
+      break;
+  }
+  std::string field_name;
+  field_name = "nullptr";
+  if (HasDescriptorMethods(field->file(), options_)) {
+    field_name = StrCat("\"", field->full_name(), "\"");
+  }
+  format("::$proto_ns$::internal::VerifyUTF8(str, $1$)", field_name);
+  switch (level) {
+    case Utf8CheckMode::kNone:
+      return;
+    case Utf8CheckMode::kVerify:
+      format(
+          ";\n"
+          "#endif  // !NDEBUG\n");
+      break;
+    case Utf8CheckMode::kStrict:
+      format(");\n");
+      break;
+  }
+}
+
+void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format,
+                                                 const FieldDescriptor* field) {
+  if (field->is_packable()) {
+    std::string enum_validator;
+    if (field->type() == FieldDescriptor::TYPE_ENUM &&
+        !HasPreservingUnknownEnumSemantics(field)) {
+      enum_validator =
+          StrCat(", ", QualifiedClassName(field->enum_type(), options_),
+                       "_IsValid, &_internal_metadata_, ", field->number());
+      format(
+          "ptr = "
+          "::$proto_ns$::internal::Packed$1$Parser<$unknown_fields_type$>("
+          "_internal_mutable_$2$(), ptr, ctx$3$);\n",
+          DeclaredTypeMethodName(field->type()), FieldName(field),
+          enum_validator);
+    } else {
+      format(
+          "ptr = ::$proto_ns$::internal::Packed$1$Parser("
+          "_internal_mutable_$2$(), ptr, ctx$3$);\n",
+          DeclaredTypeMethodName(field->type()), FieldName(field),
+          enum_validator);
+    }
+  } else {
+    auto field_type = field->type();
+    switch (field_type) {
+      case FieldDescriptor::TYPE_STRING:
+        GenerateStrings(format, field, true /* utf8 */);
+        break;
+      case FieldDescriptor::TYPE_BYTES:
+        GenerateStrings(format, field, false /* utf8 */);
+        break;
+      case FieldDescriptor::TYPE_MESSAGE: {
+        if (field->is_map()) {
+          const FieldDescriptor* val =
+              field->message_type()->FindFieldByName("value");
+          GOOGLE_CHECK(val);
+          if (val->type() == FieldDescriptor::TYPE_ENUM &&
+              !HasPreservingUnknownEnumSemantics(field)) {
+            format(
+                "auto object = "
+                "::$proto_ns$::internal::InitEnumParseWrapper<$unknown_"
+                "fields_type$>("
+                "&$1$_, $2$_IsValid, $3$, &_internal_metadata_);\n"
+                "ptr = ctx->ParseMessage(&object, ptr);\n",
+                FieldName(field), QualifiedClassName(val->enum_type()),
+                field->number());
+          } else {
+            format("ptr = ctx->ParseMessage(&$1$_, ptr);\n", FieldName(field));
+          }
+        } else if (IsLazy(field, options_, scc_analyzer_)) {
+          if (field->real_containing_oneof()) {
+            format(
+                "if (!_internal_has_$1$()) {\n"
+                "  clear_$2$();\n"
+                "  $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n"
+                "      ::$proto_ns$::internal::LazyField>("
+                "GetArenaForAllocation());\n"
+                "  set_has_$1$();\n"
+                "}\n"
+                "ptr = ctx->ParseMessage($2$_.$1$_, ptr);\n",
+                FieldName(field), field->containing_oneof()->name());
+          } else if (HasHasbit(field)) {
+            format(
+                "_Internal::set_has_$1$(&$has_bits$);\n"
+                "ptr = ctx->ParseMessage(&$1$_, ptr);\n",
+                FieldName(field));
+          } else {
+            format("ptr = ctx->ParseMessage(&$1$_, ptr);\n", FieldName(field));
+          }
+        } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
+          if (!field->is_repeated()) {
+            format(
+                "ptr = ctx->ParseMessage(_Internal::mutable_$1$(this), "
+                "ptr);\n",
+                FieldName(field));
+          } else {
+            format(
+                "ptr = ctx->ParseMessage($1$_.AddWeak(reinterpret_cast<const "
+                "::$proto_ns$::MessageLite*>($2$::_$3$_default_instance_ptr_)"
+                "), ptr);\n",
+                FieldName(field), Namespace(field->message_type(), options_),
+                ClassName(field->message_type()));
+          }
+        } else if (IsWeak(field, options_)) {
+          format(
+              "{\n"
+              "  auto* default_ = &reinterpret_cast<const Message&>($1$);\n"
+              "  ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($2$,"
+              " default_), ptr);\n"
+              "}\n",
+              QualifiedDefaultInstanceName(field->message_type(), options_),
+              field->number());
+        } else {
+          format("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n",
+                 field->is_repeated() ? "add" : "mutable", FieldName(field));
+        }
+        break;
+      }
+      default:
+        GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
+                   << " filed type is " << field->type();
+    }
+  }
+}
+
+static bool ShouldRepeat(const FieldDescriptor* descriptor,
+                         WireFormatLite::WireType wiretype) {
+  constexpr int kMaxTwoByteFieldNumber = 16 * 128;
+  return descriptor->number() < kMaxTwoByteFieldNumber &&
+         descriptor->is_repeated() &&
+         (!descriptor->is_packable() ||
+          wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+}
+
+void ParseFunctionGenerator::GenerateFieldBody(
+    Formatter& format, WireFormatLite::WireType wiretype,
+    const FieldDescriptor* field) {
+  uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
+  switch (wiretype) {
+    case WireFormatLite::WIRETYPE_VARINT: {
+      std::string type = PrimitiveTypeName(options_, field->cpp_type());
+      std::string prefix = field->is_repeated() ? "add" : "set";
+      if (field->type() == FieldDescriptor::TYPE_ENUM) {
+        format(
+            "$uint64$ val = ::$proto_ns$::internal::ReadVarint64(&ptr);\n"
+            "CHK_(ptr);\n");
+        if (!HasPreservingUnknownEnumSemantics(field)) {
+          format("if (PROTOBUF_PREDICT_TRUE($1$_IsValid(val))) {\n",
+                 QualifiedClassName(field->enum_type(), options_));
+          format.Indent();
+        }
+        format("_internal_$1$_$2$(static_cast<$3$>(val));\n", prefix,
+               FieldName(field),
+               QualifiedClassName(field->enum_type(), options_));
+        if (!HasPreservingUnknownEnumSemantics(field)) {
+          format.Outdent();
+          format(
+              "} else {\n"
+              "  ::$proto_ns$::internal::WriteVarint("
+              "$1$, val, mutable_unknown_fields());\n"
+              "}\n",
+              field->number());
+        }
+      } else {
+        std::string size = (field->type() == FieldDescriptor::TYPE_SINT32 ||
+                            field->type() == FieldDescriptor::TYPE_UINT32)
+                               ? "32"
+                               : "64";
+        std::string zigzag;
+        if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
+             field->type() == FieldDescriptor::TYPE_SINT64)) {
+          zigzag = "ZigZag";
+        }
+        if (field->is_repeated() || field->real_containing_oneof()) {
+          std::string prefix = field->is_repeated() ? "add" : "set";
+          format(
+              "_internal_$1$_$2$("
+              "::$proto_ns$::internal::ReadVarint$3$$4$(&ptr));\n"
+              "CHK_(ptr);\n",
+              prefix, FieldName(field), zigzag, size);
+        } else {
+          if (HasHasbit(field)) {
+            format("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
+          }
+          format(
+              "$1$_ = ::$proto_ns$::internal::ReadVarint$2$$3$(&ptr);\n"
+              "CHK_(ptr);\n",
+              FieldName(field), zigzag, size);
+        }
+      }
+      break;
+    }
+    case WireFormatLite::WIRETYPE_FIXED32:
+    case WireFormatLite::WIRETYPE_FIXED64: {
+      std::string type = PrimitiveTypeName(options_, field->cpp_type());
+      if (field->is_repeated() || field->real_containing_oneof()) {
+        std::string prefix = field->is_repeated() ? "add" : "set";
+        format(
+            "_internal_$1$_$2$("
+            "::$proto_ns$::internal::UnalignedLoad<$3$>(ptr));\n"
+            "ptr += sizeof($3$);\n",
+            prefix, FieldName(field), type);
+      } else {
+        if (HasHasbit(field)) {
+          format("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
+        }
+        format(
+            "$1$_ = ::$proto_ns$::internal::UnalignedLoad<$2$>(ptr);\n"
+            "ptr += sizeof($2$);\n",
+            FieldName(field), type);
+      }
+      break;
+    }
+    case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+      GenerateLengthDelim(format, field);
+      format("CHK_(ptr);\n");
+      break;
+    }
+    case WireFormatLite::WIRETYPE_START_GROUP: {
+      format(
+          "ptr = ctx->ParseGroup(_internal_$1$_$2$(), ptr, $3$);\n"
+          "CHK_(ptr);\n",
+          field->is_repeated() ? "add" : "mutable", FieldName(field), tag);
+      break;
+    }
+    case WireFormatLite::WIRETYPE_END_GROUP: {
+      GOOGLE_LOG(FATAL) << "Can't have end group field\n";
+      break;
+    }
+  }  // switch (wire_type)
+}
+
+// Returns the tag for this field and in case of repeated packable fields,
+// sets a fallback tag in fallback_tag_ptr.
+static uint32_t ExpectedTag(const FieldDescriptor* field,
+                            uint32_t* fallback_tag_ptr) {
+  uint32_t expected_tag;
+  if (field->is_packable()) {
+    auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
+    expected_tag = WireFormatLite::MakeTag(field->number(), expected_wiretype);
+    GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+    auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+    uint32_t fallback_tag =
+        WireFormatLite::MakeTag(field->number(), fallback_wiretype);
+
+    if (field->is_packed()) std::swap(expected_tag, fallback_tag);
+    *fallback_tag_ptr = fallback_tag;
+  } else {
+    auto expected_wiretype = WireFormat::WireTypeForField(field);
+    expected_tag = WireFormatLite::MakeTag(field->number(), expected_wiretype);
+  }
+  return expected_tag;
+}
+
+void ParseFunctionGenerator::GenerateParseIterationBody(
+    Formatter& format, const Descriptor* descriptor,
+    const std::vector<const FieldDescriptor*>& ordered_fields) {
+  format(
+      "$uint32$ tag;\n"
+      "ptr = ::$proto_ns$::internal::ReadTag(ptr, &tag);\n");
+  if (!ordered_fields.empty()) format("switch (tag >> 3) {\n");
+
+  format.Indent();
+
+  for (const auto* field : ordered_fields) {
+    PrintFieldComment(format, field);
+    format("case $1$:\n", field->number());
+    format.Indent();
+    uint32_t fallback_tag = 0;
+    uint32_t expected_tag = ExpectedTag(field, &fallback_tag);
+    format("if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
+           expected_tag & 0xFF);
+    format.Indent();
+    auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
+    uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
+    int tag_size = io::CodedOutputStream::VarintSize32(tag);
+    bool is_repeat = ShouldRepeat(field, wiretype);
+    if (is_repeat) {
+      format(
+          "ptr -= $1$;\n"
+          "do {\n"
+          "  ptr += $1$;\n",
+          tag_size);
+      format.Indent();
+    }
+    GenerateFieldBody(format, wiretype, field);
+    if (is_repeat) {
+      format.Outdent();
+      format(
+          "  if (!ctx->DataAvailable(ptr)) break;\n"
+          "} while (::$proto_ns$::internal::ExpectTag<$1$>(ptr));\n",
+          tag);
+    }
+    format.Outdent();
+    if (fallback_tag) {
+      format("} else if (static_cast<$uint8$>(tag) == $1$) {\n",
+             fallback_tag & 0xFF);
+      format.Indent();
+      GenerateFieldBody(format, WireFormatLite::GetTagWireType(fallback_tag),
+                        field);
+      format.Outdent();
+    }
+    format.Outdent();
+    format(
+        "  } else goto handle_unusual;\n"
+        "  $continue$;\n");
+  }  // for loop over ordered fields
+
+  // Default case
+  if (!ordered_fields.empty()) format("default: {\n");
+  if (!ordered_fields.empty()) format("handle_unusual:\n");
+  format(
+      "  if ((tag == 0) || ((tag & 7) == 4)) {\n"
+      "    CHK_(ptr);\n"
+      "    ctx->SetLastTag(tag);\n"
+      "    goto success;\n"
+      "  }\n");
+  if (IsMapEntryMessage(descriptor)) {
+    format("  $continue$;\n");
+  } else {
+    if (descriptor->extension_range_count() > 0) {
+      format("if (");
+      for (int i = 0; i < descriptor->extension_range_count(); i++) {
+        const Descriptor::ExtensionRange* range =
+            descriptor->extension_range(i);
+        if (i > 0) format(" ||\n    ");
+
+        uint32_t start_tag = WireFormatLite::MakeTag(
+            range->start, static_cast<WireFormatLite::WireType>(0));
+        uint32_t end_tag = WireFormatLite::MakeTag(
+            range->end, static_cast<WireFormatLite::WireType>(0));
+
+        if (range->end > FieldDescriptor::kMaxNumber) {
+          format("($1$u <= tag)", start_tag);
+        } else {
+          format("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
+        }
+      }
+      format(") {\n");
+      format(
+          "  ptr = _extensions_.ParseField(tag, ptr,\n"
+          "      internal_default_instance(), &_internal_metadata_, ctx);\n"
+          "  CHK_(ptr != nullptr);\n"
+          "  $continue$;\n"
+          "}\n");
+    }
+    format(
+        "  ptr = UnknownFieldParse(tag,\n"
+        "      _internal_metadata_.mutable_unknown_fields<$unknown_"
+        "fields_type$>(),\n"
+        "      ptr, ctx);\n"
+        "  CHK_(ptr != nullptr);\n"
+        "  $continue$;\n");
+  }
+  if (!ordered_fields.empty()) format("}\n");  // default case
+  format.Outdent();
+  if (!ordered_fields.empty()) format("}  // switch\n");
+}
+
+namespace {
+
+std::string FieldParseFunctionName(const FieldDescriptor* field,
+                                   const Options& options,
+                                   uint32_t table_size_log2) {
+  ParseCardinality card =  //
+      field->is_packed()               ? ParseCardinality::kPacked
+      : field->is_repeated()           ? ParseCardinality::kRepeated
+      : field->real_containing_oneof() ? ParseCardinality::kOneof
+                                       : ParseCardinality::kSingular;
+
+  TypeFormat type_format;
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_DOUBLE:
+      type_format = TypeFormat::kFixed64;
+      break;
+
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_FLOAT:
+      type_format = TypeFormat::kFixed32;
+      break;
+
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+      type_format = TypeFormat::kVar64;
+      break;
+
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+      type_format = TypeFormat::kVar32;
+      break;
+
+    case FieldDescriptor::TYPE_SINT64:
+      type_format = TypeFormat::kSInt64;
+      break;
+
+    case FieldDescriptor::TYPE_SINT32:
+      type_format = TypeFormat::kSInt32;
+      break;
+
+    case FieldDescriptor::TYPE_BOOL:
+      type_format = TypeFormat::kBool;
+      break;
+
+    case FieldDescriptor::TYPE_BYTES:
+      type_format = TypeFormat::kBytes;
+      break;
+
+    case FieldDescriptor::TYPE_STRING:
+      switch (GetUtf8CheckMode(field, options)) {
+        case Utf8CheckMode::kNone:
+          type_format = TypeFormat::kBytes;
+          break;
+        case Utf8CheckMode::kStrict:
+          type_format = TypeFormat::kString;
+          break;
+        case Utf8CheckMode::kVerify:
+          type_format = TypeFormat::kStringValidateOnly;
+          break;
+        default:
+          GOOGLE_LOG(DFATAL)
+              << "Mode not handled: "
+              << static_cast<int>(GetUtf8CheckMode(field, options));
+          return "";
+      }
+      break;
+
+    default:
+      GOOGLE_LOG(DFATAL) << "Type not handled: " << field->DebugString();
+      return "";
+  }
+
+  return "::" + ProtobufNamespace(options) + "::internal::" +
+         GetTailCallFieldHandlerName(card, type_format, table_size_log2,
+                                     TagSize(field->number()), options);
+}
+
+}  // namespace
+
+std::string GetTailCallFieldHandlerName(ParseCardinality card,
+                                        TypeFormat type_format,
+                                        int table_size_log2,
+                                        int tag_length_bytes,
+                                        const Options& options) {
+  std::string name;
+
+  switch (card) {
+    case ParseCardinality::kPacked:
+    case ParseCardinality::kRepeated:
+      name = "TcParserBase::";
+      break;
+
+    case ParseCardinality::kSingular:
+    case ParseCardinality::kOneof:
+      switch (type_format) {
+        case TypeFormat::kBytes:
+        case TypeFormat::kString:
+        case TypeFormat::kStringValidateOnly:
+          name = "TcParserBase::";
+          break;
+
+        default:
+          name = StrCat("TcParser<", table_size_log2, ">::");
+          break;
+      }
+  }
+
+  // The field implementation functions are prefixed by cardinality:
+  //   `Singular` for optional or implicit fields.
+  //   `Repeated` for non-packed repeated.
+  //   `Packed` for packed repeated.
+  switch (card) {
+    case ParseCardinality::kSingular:
+      name.append("Singular");
+      break;
+    case ParseCardinality::kOneof:
+      name.append("Oneof");
+      break;
+    case ParseCardinality::kRepeated:
+      name.append("Repeated");
+      break;
+    case ParseCardinality::kPacked:
+      name.append("Packed");
+      break;
+  }
+
+  // Next in the function name is the TypeFormat-specific name.
+  switch (type_format) {
+    case TypeFormat::kFixed64:
+    case TypeFormat::kFixed32:
+      name.append("Fixed");
+      break;
+
+    case TypeFormat::kVar64:
+    case TypeFormat::kVar32:
+    case TypeFormat::kSInt64:
+    case TypeFormat::kSInt32:
+    case TypeFormat::kBool:
+      name.append("Varint");
+      break;
+
+    case TypeFormat::kBytes:
+    case TypeFormat::kString:
+    case TypeFormat::kStringValidateOnly:
+      name.append("String");
+      break;
+
+    default:
+      break;
+  }
+
+  name.append("<");
+
+  // Determine the numeric layout type for the parser to use, independent of
+  // the specific parsing logic used.
+  switch (type_format) {
+    case TypeFormat::kVar64:
+    case TypeFormat::kFixed64:
+      name.append("uint64_t, ");
+      break;
+
+    case TypeFormat::kSInt64:
+      name.append("int64_t, ");
+      break;
+
+    case TypeFormat::kVar32:
+    case TypeFormat::kFixed32:
+      name.append("uint32_t, ");
+      break;
+
+    case TypeFormat::kSInt32:
+      name.append("int32_t, ");
+      break;
+
+    case TypeFormat::kBool:
+      name.append("bool, ");
+      break;
+
+    default:
+      break;
+  }
+
+  name.append(CodedTagType(tag_length_bytes));
+
+  std::string tcpb =
+      StrCat(ProtobufNamespace(options), "::internal::TcParserBase");
+
+  switch (type_format) {
+    case TypeFormat::kVar64:
+    case TypeFormat::kVar32:
+    case TypeFormat::kBool:
+      name.append(StrCat(", ::", tcpb, "::kNoConversion"));
+      break;
+
+    case TypeFormat::kSInt64:
+    case TypeFormat::kSInt32:
+      name.append(StrCat(", ::", tcpb, "::kZigZag"));
+      break;
+
+    case TypeFormat::kBytes:
+      name.append(StrCat(", ::", tcpb, "::kNoUtf8"));
+      break;
+
+    case TypeFormat::kString:
+      name.append(StrCat(", ::", tcpb, "::kUtf8"));
+      break;
+
+    case TypeFormat::kStringValidateOnly:
+      name.append(StrCat(", ::", tcpb, "::kUtf8ValidateOnly"));
+      break;
+
+    default:
+      break;
+  }
+
+  name.append(">");
+  return name;
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h
new file mode 100644
index 0000000..116353a
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h
@@ -0,0 +1,180 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_tctable_decl.h>
+#include <google/protobuf/wire_format_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Helper class for generating tailcall parsing functions.
+struct TailCallTableInfo {
+  TailCallTableInfo(const Descriptor* descriptor, const Options& options,
+                    const std::vector<int>& has_bit_indices,
+                    MessageSCCAnalyzer* scc_analyzer);
+  // Information to generate field entries.
+  struct FieldInfo {
+    const FieldDescriptor* field;
+    google::protobuf::internal::TcFieldData bits;
+    std::string func_name;
+  };
+  // Fields parsed by the table fast-path.
+  std::vector<FieldInfo> fast_path_fields;
+  // Fields parsed by slow-path fallback.
+  std::vector<const FieldDescriptor*> fallback_fields;
+  // Table size.
+  int table_size_log2;
+  // Mask for has-bits of required fields.
+  uint32_t has_hasbits_required_mask;
+  // True if a generated fallback function is required instead of generic.
+  bool use_generated_fallback;
+};
+
+// ParseFunctionGenerator generates the _InternalParse function for a message
+// (and any associated supporting members).
+class ParseFunctionGenerator {
+ public:
+  ParseFunctionGenerator(const Descriptor* descriptor, int max_has_bit_index,
+                         const std::vector<int>& has_bit_indices,
+                         const Options& options,
+                         MessageSCCAnalyzer* scc_analyzer,
+                         const std::map<std::string, std::string>& vars);
+
+  // Emits class-level method declarations to `printer`:
+  void GenerateMethodDecls(io::Printer* printer);
+
+  // Emits out-of-class method implementation definitions to `printer`:
+  void GenerateMethodImpls(io::Printer* printer);
+
+  // Emits class-level data member declarations to `printer`:
+  void GenerateDataDecls(io::Printer* printer);
+
+  // Emits out-of-class data member definitions to `printer`:
+  void GenerateDataDefinitions(io::Printer* printer);
+
+ private:
+  // Generates a fallback function for tailcall table-based parsing.
+  void GenerateTailcallFallbackFunction(Formatter& format);
+
+  // Generates a looping `_InternalParse` function.
+  void GenerateLoopingParseFunction(Formatter& format);
+
+  // Generates the tail-call table definition.
+  void GenerateTailCallTable(Formatter& format);
+
+  // Generates parsing code for an `ArenaString` field.
+  void GenerateArenaString(Formatter& format, const FieldDescriptor* field);
+
+  // Generates parsing code for a string-typed field.
+  void GenerateStrings(Formatter& format, const FieldDescriptor* field,
+                       bool check_utf8);
+
+  // Generates parsing code for a length-delimited field (strings, messages,
+  // etc.).
+  void GenerateLengthDelim(Formatter& format, const FieldDescriptor* field);
+
+  // Generates the parsing code for a known field.
+  void GenerateFieldBody(Formatter& format,
+                         google::protobuf::internal::WireFormatLite::WireType wiretype,
+                         const FieldDescriptor* field);
+
+  // Generates code to parse the next field from the input stream.
+  void GenerateParseIterationBody(
+      Formatter& format, const Descriptor* descriptor,
+      const std::vector<const FieldDescriptor*>& ordered_fields);
+
+  const Descriptor* descriptor_;
+  MessageSCCAnalyzer* scc_analyzer_;
+  const Options& options_;
+  std::map<std::string, std::string> variables_;
+  std::unique_ptr<TailCallTableInfo> tc_table_info_;
+  int num_hasbits_;
+};
+
+// Returns the integer type that holds a tag of the given length (in bytes) when
+// wire-encoded.
+const char* CodedTagType(int tag_size);
+
+enum class ParseCardinality {
+  kSingular,
+  kOneof,
+  kRepeated,
+  kPacked,
+};
+
+// TypeFormat defines parsing types, which encapsulates the expected wire
+// format, conversion or validation, and the in-memory layout.
+enum class TypeFormat {
+  // Fixed types:
+  kFixed64,  // fixed64, sfixed64, double
+  kFixed32,  // fixed32, sfixed32, float
+
+  // Varint types:
+  kVar64,   // int64, uint64
+  kVar32,   // int32, uint32
+  kSInt64,  // sint64
+  kSInt32,  // sint32
+  kBool,    // bool
+
+  // Length-delimited types:
+  kBytes,               // bytes
+  kString,              // string (proto3/UTF-8 strict)
+  kStringValidateOnly,  // string (proto2/UTF-8 validate only)
+};
+
+// Returns the name of a field parser function.
+//
+// These are out-of-line functions generated by
+// parse_function_inc_generator_main.
+std::string GetTailCallFieldHandlerName(ParseCardinality card,
+                                        TypeFormat type_format,
+                                        int table_size_log2,
+                                        int tag_length_bytes,
+                                        const Options& options);
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 10e468b..373f38d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
@@ -81,13 +80,9 @@
     // Check field accessors for a required string:
     TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
     TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
     TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
     TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
               context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
 
     // Check field accessors for a repeated string:
     TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
@@ -105,12 +100,8 @@
     // Check field accessors for a string inside oneof{}:
     TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
     TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
     TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
     TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
 
     // Check field accessors for an optional message:
     TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 042776c..9664586 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -33,6 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
+
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
@@ -152,7 +153,7 @@
       "  return $name$_;\n"
       "}\n"
       "inline $type$ $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
@@ -161,8 +162,8 @@
       "  $name$_ = value;\n"
       "}\n"
       "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$"
       "  _internal_set_$name$(value);\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n");
 }
@@ -217,6 +218,12 @@
   }
 }
 
+void PrimitiveFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_($default$)");
+}
+
 // ===================================================================
 
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
@@ -245,13 +252,13 @@
       "  $field_member$ = value;\n"
       "}\n"
       "inline $type$ $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
       "inline void $classname$::set_$name$($type$ value) {\n"
-      "$annotate_accessor$"
       "  _internal_set_$name$(value);\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n");
 }
@@ -295,7 +302,7 @@
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
-  if (descriptor_->is_packed() &&
+  if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
       HasGeneratedMethods(descriptor_->file(), options_)) {
     format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
   }
@@ -331,12 +338,12 @@
       "  return $name$_.Get(index);\n"
       "}\n"
       "inline $type$ $classname$::$name$(int index) const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$(index);\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, $type$ value) {\n"
-      "$annotate_accessor$"
+      "$annotate_set$"
       "  $name$_.Set(index, value);\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
@@ -344,8 +351,8 @@
       "  $name$_.Add(value);\n"
       "}\n"
       "inline void $classname$::add_$name$($type$ value) {\n"
-      "$annotate_accessor$"
       "  _internal_add_$name$(value);\n"
+      "$annotate_add$"
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
       "}\n"
       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
@@ -354,7 +361,7 @@
       "}\n"
       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
       "$classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_list$"
       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
@@ -364,7 +371,7 @@
       "}\n"
       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
       "$classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "$annotate_mutable_list$"
       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
       "  return _internal_mutable_$name$();\n"
       "}\n");
@@ -403,13 +410,7 @@
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   if (descriptor_->is_packed()) {
-    if (FixedSize(descriptor_->type()) > 0) {
-      format(
-          "if (this->_internal_$name$_size() > 0) {\n"
-          "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
-          "target);\n"
-          "}\n");
-    } else {
+    if (FixedSize(descriptor_->type()) == -1) {
       format(
           "{\n"
           "  int byte_size = "
@@ -419,6 +420,12 @@
           "        $number$, _internal_$name$(), byte_size, target);\n"
           "  }\n"
           "}\n");
+    } else {
+      format(
+          "if (this->_internal_$name$_size() > 0) {\n"
+          "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
+          "target);\n"
+          "}\n");
     }
   } else {
     format(
@@ -454,11 +461,14 @@
         "  total_size += $tag_size$ +\n"
         "    ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
         "        static_cast<$int32$>(data_size));\n"
-        "}\n"
-        "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
-        "_$name$_cached_byte_size_.store(cached_size,\n"
-        "                                std::memory_order_relaxed);\n"
-        "total_size += data_size;\n");
+        "}\n");
+    if (FixedSize(descriptor_->type()) == -1) {
+      format(
+          "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
+          "_$name$_cached_byte_size_.store(cached_size,\n"
+          "                                std::memory_order_relaxed);\n");
+    }
+    format("total_size += data_size;\n");
   } else {
     format(
         "total_size += $tag_size$ *\n"
@@ -470,6 +480,16 @@
   format("}\n");
 }
 
+void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+  if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    format("\n, _$name$_cached_byte_size_(0)");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index fe54ce3..ce0f97d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -51,16 +51,17 @@
   ~PrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
@@ -73,10 +74,10 @@
   ~PrimitiveOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
@@ -89,16 +90,17 @@
   ~RepeatedPrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index a21c4c7..5c7bb68 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -55,14 +55,35 @@
       StrCat(descriptor->default_value_string().length());
   std::string default_variable_string = MakeDefaultName(descriptor);
   (*variables)["default_variable_name"] = default_variable_string;
-  (*variables)["default_variable"] =
+
+  if (!descriptor->default_value_string().empty()) {
+    (*variables)["lazy_variable"] =
+        QualifiedClassName(descriptor->containing_type(), options) +
+        "::" + default_variable_string;
+  }
+
+  (*variables)["default_string"] =
+      descriptor->default_value_string().empty()
+          ? "::" + (*variables)["proto_ns"] +
+                "::internal::GetEmptyStringAlreadyInited()"
+          : (*variables)["lazy_variable"] + ".get()";
+  (*variables)["init_value"] =
       descriptor->default_value_string().empty()
           ? "&::" + (*variables)["proto_ns"] +
                 "::internal::GetEmptyStringAlreadyInited()"
-          : "&" + QualifiedClassName(descriptor->containing_type(), options) +
-                "::" + default_variable_string + ".get()";
+          : "nullptr";
+  (*variables)["default_value_tag"] =
+      "::" + (*variables)["proto_ns"] + "::internal::ArenaStringPtr::" +
+      (descriptor->default_value_string().empty() ? "Empty" : "NonEmpty") +
+      "Default{}";
+  (*variables)["default_variable_or_tag"] =
+      (*variables)[descriptor->default_value_string().empty()
+                       ? "default_value_tag"
+                       : "lazy_variable"];
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
+  (*variables)["setter"] =
+      descriptor->type() == FieldDescriptor::TYPE_BYTES ? "SetBytes" : "Set";
   (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n";
   // NOTE: Escaped here to unblock proto1->proto2 migration.
   // TODO(liujisi): Extend this to apply for other conflicting methods.
@@ -75,9 +96,6 @@
   } else {
     (*variables)["string_piece"] = "::StringPiece";
   }
-
-  (*variables)["lite"] =
-      HasDescriptorMethods(descriptor->file(), options) ? "" : "Lite";
 }
 
 }  // namespace
@@ -86,9 +104,7 @@
 
 StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
                                            const Options& options)
-    : FieldGenerator(descriptor, options),
-      lite_(!HasDescriptorMethods(descriptor->file(), options)),
-      inlined_(IsStringInlined(descriptor, options)) {
+    : FieldGenerator(descriptor, options) {
   SetStringVariables(descriptor, &variables_, options);
 }
 
@@ -96,35 +112,15 @@
 
 void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (inlined_) {
-    format("::$proto_ns$::internal::InlinedStringField $name$_;\n");
-  } else {
-    // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
-    // string fields, even when SupportArenas(descriptor_) == false. Why?  The
-    // simple answer is to avoid unmaintainable complexity. The reflection code
-    // assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
-    // string*, except for the pointer tags and related ownership semantics. We
-    // could modify the runtime code to use string* for the
-    // not-supporting-arenas case, but this would require a way to detect which
-    // type of class was generated (adding overhead and complexity to
-    // GeneratedMessageReflection) and littering the runtime code paths with
-    // conditionals. It's simpler to stick with this but use lightweight
-    // accessors that assume arena == NULL.  There should be very little
-    // overhead anyway because it's just a tagged pointer in-memory.
-    format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n");
-  }
+  format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n");
 }
 
 void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
   Formatter format(printer, variables_);
   if (!descriptor_->default_value_string().empty()) {
-    // We make the default instance public, so it can be initialized by
-    // non-friend code.
     format(
-        "public:\n"
-        "static ::$proto_ns$::internal::ExplicitlyConstructed<std::string>"
-        " $default_variable_name$;\n"
-        "private:\n");
+        "static const ::$proto_ns$::internal::LazyString"
+        " $default_variable_name$;\n");
   }
 }
 
@@ -161,45 +157,21 @@
 
   format(
       "$deprecated_attr$const std::string& ${1$$name$$}$() const;\n"
-      "$deprecated_attr$void ${1$set_$name$$}$(const std::string& value);\n"
-      "$deprecated_attr$void ${1$set_$name$$}$(std::string&& value);\n"
-      "$deprecated_attr$void ${1$set_$name$$}$(const char* value);\n",
+      "template <typename ArgT0 = const std::string&, typename... ArgT>\n"
+      "$deprecated_attr$void ${1$set_$name$$}$(ArgT0&& arg0, ArgT... args);\n",
       descriptor_);
-  if (!options_.opensource_runtime) {
-    format(
-        "$deprecated_attr$void ${1$set_$name$$}$(::StringPiece value);\n",
-        descriptor_);
-  }
   format(
-      "$deprecated_attr$void ${1$set_$name$$}$(const $pointer_type$* "
-      "value, size_t size)"
-      ";\n"
       "$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
-      "$deprecated_attr$std::string* ${1$$release_name$$}$();\n"
+      "PROTOBUF_MUST_USE_RESULT $deprecated_attr$std::string* "
+      "${1$$release_name$$}$();\n"
       "$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
       "$name$);\n",
       descriptor_);
-  if (options_.opensource_runtime) {
-    if (SupportsArenas(descriptor_)) {
-      format(
-          "$GOOGLE_PROTOBUF$_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors "
-          "for\"\n"
-          "\"    string fields are deprecated and will be removed in a\"\n"
-          "\"    future release.\")\n"
-          "std::string* ${1$unsafe_arena_release_$name$$}$();\n"
-          "$GOOGLE_PROTOBUF$_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors "
-          "for\"\n"
-          "\"    string fields are deprecated and will be removed in a\"\n"
-          "\"    future release.\")\n"
-          "void ${1$unsafe_arena_set_allocated_$name$$}$(\n"
-          "    std::string* $name$);\n",
-          descriptor_);
-    }
-  }
   format(
       "private:\n"
       "const std::string& _internal_$name$() const;\n"
-      "void _internal_set_$name$(const std::string& value);\n"
+      "inline PROTOBUF_ALWAYS_INLINE void "
+      "_internal_set_$name$(const std::string& value);\n"
       "std::string* _internal_mutable_$name$();\n"
       "public:\n");
 
@@ -215,233 +187,95 @@
   Formatter format(printer, variables_);
   format(
       "inline const std::string& $classname$::$name$() const {\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "$annotate_get$"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n");
+  if (!descriptor_->default_value_string().empty()) {
+    format(
+        "  if ($name$_.IsDefault(nullptr)) return "
+        "$default_variable_name$.get();\n");
+  }
+  format(
       "  return _internal_$name$();\n"
       "}\n"
-      "inline void $classname$::set_$name$(const std::string& value) {\n"
-      "$annotate_accessor$"
-      "  _internal_set_$name$(value);\n"
+      "template <typename ArgT0, typename... ArgT>\n"
+      "inline PROTOBUF_ALWAYS_INLINE\n"
+      "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
+      " $set_hasbit$\n"
+      " $name$_.$setter$($default_value_tag$, static_cast<ArgT0 &&>(arg0),"
+      " args..., GetArenaForAllocation());\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline std::string* $classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "  std::string* _s = _internal_mutable_$name$();\n"
+      "$annotate_mutable$"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return _internal_mutable_$name$();\n"
+      "  return _s;\n"
+      "}\n"
+      "inline const std::string& $classname$::_internal_$name$() const {\n"
+      "  return $name$_.Get();\n"
+      "}\n"
+      "inline void $classname$::_internal_set_$name$(const std::string& "
+      "value) {\n"
+      "  $set_hasbit$\n"
+      "  $name$_.Set($default_value_tag$, value, GetArenaForAllocation());\n"
       "}\n");
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "inline const std::string& $classname$::_internal_$name$() const {\n"
-        "  return $name$_.Get();\n"
-        "}\n"
-        "inline void $classname$::_internal_set_$name$(const std::string& "
-        "value) {\n"
-        "  $set_hasbit$\n"
-        "  $name$_.Set$lite$($default_variable$, value, GetArena());\n"
-        "}\n"
-        "inline void $classname$::set_$name$(std::string&& value) {\n"
-        "$annotate_accessor$"
-        "  $set_hasbit$\n"
-        "  $name$_.Set$lite$(\n"
-        "    $default_variable$, ::std::move(value), GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
-        "}\n"
-        "inline void $classname$::set_$name$(const char* value) {\n"
-        "$annotate_accessor$"
-        "  $null_check$"
-        "  $set_hasbit$\n"
-        "  $name$_.Set$lite$($default_variable$, $string_piece$(value),\n"
-        "              GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-        "}\n");
-    if (!options_.opensource_runtime) {
-      format(
-          "inline void $classname$::set_$name$(::StringPiece value) {\n"
-          "$annotate_accessor$"
-          "  $set_hasbit$\n"
-          "  $name$_.Set$lite$($default_variable$, value,GetArena());\n"
-          "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
-          "}\n");
-    }
-    format(
-        "inline "
-        "void $classname$::set_$name$(const $pointer_type$* value,\n"
-        "    size_t size) {\n"
-        "$annotate_accessor$"
-        "  $set_hasbit$\n"
-        "  $name$_.Set$lite$($default_variable$, $string_piece$(\n"
-        "      reinterpret_cast<const char*>(value), size), GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-        "}\n"
-        "inline std::string* $classname$::_internal_mutable_$name$() {\n"
-        "  $set_hasbit$\n"
-        "  return $name$_.Mutable($default_variable$, GetArena());\n"
-        "}\n"
-        "inline std::string* $classname$::$release_name$() {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_release:$full_name$)\n");
+  format(
+      "inline std::string* $classname$::_internal_mutable_$name$() {\n"
+      "  $set_hasbit$\n"
+      "  return $name$_.Mutable($default_variable_or_tag$, "
+      "GetArenaForAllocation());\n"
+      "}\n"
+      "inline std::string* $classname$::$release_name$() {\n"
+      "$annotate_release$"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n");
 
-    if (HasHasbit(descriptor_)) {
-      format(
-          "  if (!_internal_has_$name$()) {\n"
-          "    return nullptr;\n"
-          "  }\n"
-          "  $clear_hasbit$\n"
-          "  return $name$_.ReleaseNonDefault("
-          "$default_variable$, GetArena());\n");
-    } else {
-      format(
-          "  return $name$_.Release($default_variable$, GetArena());\n");
-    }
-
+  if (HasHasbit(descriptor_)) {
     format(
-        "}\n"
-        "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
-        "$annotate_accessor$"
-        "  if ($name$ != nullptr) {\n"
-        "    $set_hasbit$\n"
-        "  } else {\n"
-        "    $clear_hasbit$\n"
+        "  if (!_internal_has_$name$()) {\n"
+        "    return nullptr;\n"
         "  }\n"
-        "  $name$_.SetAllocated($default_variable$, $name$,\n"
-        "      GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-        "}\n");
-    if (options_.opensource_runtime) {
-      format(
-          "inline std::string* $classname$::unsafe_arena_release_$name$() {\n"
-          "$annotate_accessor$"
-          "  // "
-          "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
-          "  $DCHK$(GetArena() != nullptr);\n"
-          "  $clear_hasbit$\n"
-          "  return $name$_.UnsafeArenaRelease($default_variable$,\n"
-          "      GetArena());\n"
-          "}\n"
-          "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
-          "$annotate_accessor$"
-          "    std::string* $name$) {\n"
-          "  $DCHK$(GetArena() != nullptr);\n"
-          "  if ($name$ != nullptr) {\n"
-          "    $set_hasbit$\n"
-          "  } else {\n"
-          "    $clear_hasbit$\n"
-          "  }\n"
-          "  $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
-          "      $name$, GetArena());\n"
-          "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
-          "$full_name$)\n"
-          "}\n");
-    }
+        "  $clear_hasbit$\n"
+        "  return $name$_.ReleaseNonDefault($init_value$, "
+        "GetArenaForAllocation());\n");
   } else {
-    // No-arena case.
     format(
-        "inline const std::string& $classname$::_internal_$name$() const {\n"
-        "  return $name$_.GetNoArena();\n"
-        "}\n"
-        "inline void $classname$::_internal_set_$name$(const std::string& "
-        "value) {\n"
-        "  $set_hasbit$\n"
-        "  $name$_.SetNoArena($default_variable$, value);\n"
-        "}\n"
-        "inline void $classname$::set_$name$(std::string&& value) {\n"
-        "$annotate_accessor$"
-        "  $set_hasbit$\n"
-        "  $name$_.SetNoArena(\n"
-        "    $default_variable$, ::std::move(value));\n"
-        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
-        "}\n"
-        "inline void $classname$::set_$name$(const char* value) {\n"
-        "$annotate_accessor$"
-        "  $null_check$"
-        "  $set_hasbit$\n"
-        "  $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
-        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-        "}\n");
-    if (!options_.opensource_runtime) {
-      format(
-          "inline void $classname$::set_$name$(::StringPiece value) {\n"
-          "$annotate_accessor$"
-          "  $set_hasbit$\n"
-          "  $name$_.SetNoArena($default_variable$, value);\n"
-          "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
-          "}\n");
-    }
-    format(
-        "inline "
-        "void $classname$::set_$name$(const $pointer_type$* value, "
-        "size_t size) {\n"
-        "$annotate_accessor$"
-        "  $set_hasbit$\n"
-        "  $name$_.SetNoArena($default_variable$,\n"
-        "      $string_piece$(reinterpret_cast<const char*>(value), size));\n"
-        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-        "}\n"
-        "inline std::string* $classname$::_internal_mutable_$name$() {\n"
-        "  $set_hasbit$\n"
-        "  return $name$_.MutableNoArena($default_variable$);\n"
-        "}\n"
-        "inline std::string* $classname$::$release_name$() {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_release:$full_name$)\n");
-
-    if (HasHasbit(descriptor_)) {
-      format(
-          "  if (!_internal_has_$name$()) {\n"
-          "    return nullptr;\n"
-          "  }\n"
-          "  $clear_hasbit$\n"
-          "  return $name$_.ReleaseNonDefaultNoArena($default_variable$);\n");
-    } else {
-      format(
-          "  $clear_hasbit$\n"
-          "  return $name$_.ReleaseNoArena($default_variable$);\n");
-    }
-
-    format(
-        "}\n"
-        "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
-        "$annotate_accessor$"
-        "  if ($name$ != nullptr) {\n"
-        "    $set_hasbit$\n"
-        "  } else {\n"
-        "    $clear_hasbit$\n"
-        "  }\n"
-        "  $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
-        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-        "}\n");
+        "  return $name$_.Release($init_value$, GetArenaForAllocation());\n");
   }
+
+  format(
+      "}\n"
+      "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
+      "  if ($name$ != nullptr) {\n"
+      "    $set_hasbit$\n"
+      "  } else {\n"
+      "    $clear_hasbit$\n"
+      "  }\n"
+      "  $name$_.SetAllocated($init_value$, $name$,\n"
+      "      GetArenaForAllocation());\n"
+      "$annotate_set$"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
 }
 
 void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   if (!descriptor_->default_value_string().empty()) {
-    // Initialized in GenerateDefaultInstanceAllocator.
     format(
-        "::$proto_ns$::internal::ExplicitlyConstructed<std::string> "
-        "$classname$::$default_variable_name$;\n");
+        "const ::$proto_ns$::internal::LazyString "
+        "$classname$::$default_variable_name$"
+        "{{{$default$, $default_length$}}, {nullptr}};\n");
   }
 }
 
 void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  // Two-dimension specialization here: supporting arenas or not, and default
-  // value is the empty string or not. Complexity here ensures the minimal
-  // number of branches / amount of extraneous code at runtime (given that the
-  // below methods are inlined one-liners)!
-  if (SupportsArenas(descriptor_)) {
-    if (descriptor_->default_value_string().empty()) {
-      format("$name$_.ClearToEmpty($default_variable$, GetArena());\n");
-    } else {
-      format("$name$_.ClearToDefault($default_variable$, GetArena());\n");
-    }
+  if (descriptor_->default_value_string().empty()) {
+    format("$name$_.ClearToEmpty();\n");
   } else {
-    if (descriptor_->default_value_string().empty()) {
-      format("$name$_.ClearToEmptyNoArena($default_variable$);\n");
-    } else {
-      format("$name$_.ClearToDefaultNoArena($default_variable$);\n");
-    }
+    format(
+        "$name$_.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n");
   }
 }
 
@@ -455,81 +289,42 @@
 
   // If we have a hasbit, then the Clear() method of the protocol buffer
   // will have checked that this field is set.  If so, we can avoid redundant
-  // checks against default_variable.
+  // checks against the default variable.
   const bool must_be_present = HasHasbit(descriptor_);
 
-  if (inlined_ && must_be_present) {
-    // Calling mutable_$name$() gives us a string reference and sets the has bit
-    // for $name$ (in proto2).  We may get here when the string field is inlined
-    // but the string's contents have not been changed by the user, so we cannot
-    // make an assertion about the contents of the string and could never make
-    // an assertion about the string instance.
-    //
-    // For non-inlined strings, we distinguish from non-default by comparing
-    // instances, rather than contents.
-    format("$DCHK$(!$name$_.IsDefault($default_variable$));\n");
-  }
-
-  if (SupportsArenas(descriptor_)) {
-    if (descriptor_->default_value_string().empty()) {
-      if (must_be_present) {
-        format("$name$_.ClearNonDefaultToEmpty();\n");
-      } else {
-        format("$name$_.ClearToEmpty($default_variable$, GetArena());\n");
-      }
+  if (descriptor_->default_value_string().empty()) {
+    if (must_be_present) {
+      format("$name$_.ClearNonDefaultToEmpty();\n");
     } else {
-      // Clear to a non-empty default is more involved, as we try to use the
-      // Arena if one is present and may need to reallocate the string.
-      format("$name$_.ClearToDefault($default_variable$, GetArena());\n");
-    }
-  } else if (must_be_present) {
-    // When Arenas are disabled and field presence has been checked, we can
-    // safely treat the ArenaStringPtr as a string*.
-    if (descriptor_->default_value_string().empty()) {
-      format("$name$_.ClearNonDefaultToEmptyNoArena();\n");
-    } else {
-      format("$name$_.UnsafeMutablePointer()->assign(*$default_variable$);\n");
+      format("$name$_.ClearToEmpty();\n");
     }
   } else {
-    if (descriptor_->default_value_string().empty()) {
-      format("$name$_.ClearToEmptyNoArena($default_variable$);\n");
-    } else {
-      format("$name$_.ClearToDefaultNoArena($default_variable$);\n");
-    }
+    // Clear to a non-empty default is more involved, as we try to use the
+    // Arena if one is present and may need to reallocate the string.
+    format(
+        "$name$_.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n ");
   }
 }
 
 void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (SupportsArenas(descriptor_) || descriptor_->real_containing_oneof()) {
-    // TODO(gpike): improve this
-    format("_internal_set_$name$(from._internal_$name$());\n");
-  } else {
-    format(
-        "$set_hasbit$\n"
-        "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
-  }
+  // TODO(gpike): improve this
+  format("_internal_set_$name$(from._internal_$name$());\n");
 }
 
 void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (inlined_) {
-    format("$name$_.Swap(&other->$name$_);\n");
-  } else {
-    format("$name$_.Swap(&other->$name$_, $default_variable$, GetArena());\n");
-  }
+  format(
+      "::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n"
+      "    $init_value$,\n"
+      "    &$name$_, GetArenaForAllocation(),\n"
+      "    &other->$name$_, other->GetArenaForAllocation()\n"
+      ");\n");
 }
 
 void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  // TODO(ckennelly): Construct non-empty strings as part of the initializer
-  // list.
-  if (inlined_ && descriptor_->default_value_string().empty()) {
-    // Automatic initialization will construct the string.
-    return;
-  }
-
-  format("$name$_.UnsafeSetDefault($default_variable$);\n");
+  format("$name$_.UnsafeSetDefault($init_value$);\n");
 }
 
 void StringFieldGenerator::GenerateCopyConstructorCode(
@@ -545,14 +340,10 @@
 
   format.Indent();
 
-  if (SupportsArenas(descriptor_) || descriptor_->real_containing_oneof()) {
-    // TODO(gpike): improve this
-    format(
-        "$name$_.Set$lite$($default_variable$, from._internal_$name$(),\n"
-        "  GetArena());\n");
-  } else {
-    format("$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
-  }
+  // TODO(gpike): improve this
+  format(
+      "$name$_.Set($default_value_tag$, from._internal_$name$(), \n"
+      "  GetArenaForAllocation());\n");
 
   format.Outdent();
   format("}\n");
@@ -560,40 +351,7 @@
 
 void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (inlined_) {
-    // The destructor is automatically invoked.
-    return;
-  }
-
-  format("$name$_.DestroyNoArena($default_variable$);\n");
-}
-
-bool StringFieldGenerator::GenerateArenaDestructorCode(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  if (!inlined_) {
-    return false;
-  }
-
-  format("_this->$name$_.DestroyNoArena($default_variable$);\n");
-  return true;
-}
-
-void StringFieldGenerator::GenerateDefaultInstanceAllocator(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  if (!descriptor_->default_value_string().empty()) {
-    format(
-        "$ns$::$classname$::$default_variable_name$.DefaultConstruct();\n"
-        "*$ns$::$classname$::$default_variable_name$.get_mutable() = "
-        "std::string($default$, $default_length$);\n"
-        "::$proto_ns$::internal::OnShutdownDestroyString(\n"
-        "    $ns$::$classname$::$default_variable_name$.get_mutable());\n");
-  }
-}
-
-bool StringFieldGenerator::MergeFromCodedStreamNeedsArena() const {
-  return !lite_ && !inlined_ && !options_.opensource_runtime;
+  format("$name$_.DestroyNoArena($init_value$);\n");
 }
 
 void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
@@ -619,8 +377,14 @@
       "    this->_internal_$name$());\n");
 }
 
-uint32 StringFieldGenerator::CalculateFieldTag() const {
-  return inlined_ ? 1 : 0;
+void StringFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  if (descriptor_->default_value_string().empty()) {
+    format("$name$_(&::$proto_ns$::internal::fixed_address_empty_string)");
+  } else {
+    format("$name$_(nullptr)");
+  }
 }
 
 // ===================================================================
@@ -628,8 +392,6 @@
 StringOneofFieldGenerator::StringOneofFieldGenerator(
     const FieldDescriptor* descriptor, const Options& options)
     : StringFieldGenerator(descriptor, options) {
-  inlined_ = false;
-
   SetCommonOneofFieldVariables(descriptor, &variables_);
   variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
   variables_["oneof_index"] =
@@ -643,260 +405,88 @@
   Formatter format(printer, variables_);
   format(
       "inline const std::string& $classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
-      "inline void $classname$::set_$name$(const std::string& value) {\n"
-      "$annotate_accessor$"
-      "  _internal_set_$name$(value);\n"
+      "template <typename ArgT0, typename... ArgT>\n"
+      "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
+      "  if (!_internal_has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $field_member$.UnsafeSetDefault($init_value$);\n"
+      "  }\n"
+      "  $field_member$.$setter$($default_value_tag$,"
+      " static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline std::string* $classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "  std::string* _s = _internal_mutable_$name$();\n"
+      "$annotate_mutable$"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return _internal_mutable_$name$();\n"
+      "  return _s;\n"
+      "}\n"
+      "inline const std::string& $classname$::_internal_$name$() const {\n"
+      "  if (_internal_has_$name$()) {\n"
+      "    return $field_member$.Get();\n"
+      "  }\n"
+      "  return $default_string$;\n"
+      "}\n"
+      "inline void $classname$::_internal_set_$name$(const std::string& "
+      "value) {\n"
+      "  if (!_internal_has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $field_member$.UnsafeSetDefault($init_value$);\n"
+      "  }\n"
+      "  $field_member$.Set($default_value_tag$, value, "
+      "GetArenaForAllocation());\n"
       "}\n");
-  if (SupportsArenas(descriptor_)) {
-    format(
-        "inline const std::string& $classname$::_internal_$name$() const {\n"
-        "  if (_internal_has_$name$()) {\n"
-        "    return $field_member$.Get();\n"
-        "  }\n"
-        "  return *$default_variable$;\n"
-        "}\n"
-        "inline void $classname$::_internal_set_$name$(const std::string& "
-        "value) {\n"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.Set$lite$($default_variable$, value, GetArena());\n"
-        "}\n"
-        "inline void $classname$::set_$name$(std::string&& value) {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.Set$lite$(\n"
-        "    $default_variable$, ::std::move(value), GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
-        "}\n"
-        "inline void $classname$::set_$name$(const char* value) {\n"
-        "$annotate_accessor$"
-        "  $null_check$"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.Set$lite$($default_variable$,\n"
-        "      $string_piece$(value), GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-        "}\n");
-    if (!options_.opensource_runtime) {
-      format(
-          "inline void $classname$::set_$name$(::StringPiece value) {\n"
-          "$annotate_accessor$"
-          "  if (!_internal_has_$name$()) {\n"
-          "    clear_$oneof_name$();\n"
-          "    set_has_$name$();\n"
-          "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-          "  }\n"
-          "  $field_member$.Set$lite$($default_variable$, value,\n"
-          "      GetArena());\n"
-          "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
-          "}\n");
-    }
-    format(
-        "inline "
-        "void $classname$::set_$name$(const $pointer_type$* value,\n"
-        "                             size_t size) {\n"
-        "$annotate_accessor$"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.Set$lite$(\n"
-        "      $default_variable$, $string_piece$(\n"
-        "      reinterpret_cast<const char*>(value), size),\n"
-        "      GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-        "}\n"
-        "inline std::string* $classname$::_internal_mutable_$name$() {\n"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  return $field_member$.Mutable($default_variable$, GetArena());\n"
-        "}\n"
-        "inline std::string* $classname$::$release_name$() {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_release:$full_name$)\n"
-        "  if (_internal_has_$name$()) {\n"
-        "    clear_has_$oneof_name$();\n"
-        "    return $field_member$.Release($default_variable$, GetArena());\n"
-        "  } else {\n"
-        "    return nullptr;\n"
-        "  }\n"
-        "}\n"
-        "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
-        "$annotate_accessor$"
-        "  if (has_$oneof_name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "  }\n"
-        "  if ($name$ != nullptr) {\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($name$);\n"
-        "  }\n"
-        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-        "}\n");
-    if (options_.opensource_runtime) {
-      format(
-          "inline std::string* $classname$::unsafe_arena_release_$name$() {\n"
-          "$annotate_accessor$"
-          "  // "
-          "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
-          "  $DCHK$(GetArena() != nullptr);\n"
-          "  if (_internal_has_$name$()) {\n"
-          "    clear_has_$oneof_name$();\n"
-          "    return $field_member$.UnsafeArenaRelease(\n"
-          "        $default_variable$, GetArena());\n"
-          "  } else {\n"
-          "    return nullptr;\n"
-          "  }\n"
-          "}\n"
-          "inline void $classname$::unsafe_arena_set_allocated_$name$("
-          "std::string* $name$) {\n"
-          "$annotate_accessor$"
-          "  $DCHK$(GetArena() != nullptr);\n"
-          "  if (!_internal_has_$name$()) {\n"
-          "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-          "  }\n"
-          "  clear_$oneof_name$();\n"
-          "  if ($name$) {\n"
-          "    set_has_$name$();\n"
-          "    $field_member$.UnsafeArenaSetAllocated($default_variable$, "
-          "$name$, GetArena());\n"
-          "  }\n"
-          "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
-          "$full_name$)\n"
-          "}\n");
-    }
-  } else {
-    // No-arena case.
-    format(
-        "inline const std::string& $classname$::_internal_$name$() const {\n"
-        "  if (_internal_has_$name$()) {\n"
-        "    return $field_member$.GetNoArena();\n"
-        "  }\n"
-        "  return *$default_variable$;\n"
-        "}\n"
-        "inline void $classname$::_internal_set_$name$(const std::string& "
-        "value) {\n"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.SetNoArena($default_variable$, value);\n"
-        "}\n"
-        "inline void $classname$::set_$name$(std::string&& value) {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.SetNoArena($default_variable$, ::std::move(value));\n"
-        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
-        "}\n"
-        "inline void $classname$::set_$name$(const char* value) {\n"
-        "$annotate_accessor$"
-        "  $null_check$"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.SetNoArena($default_variable$,\n"
-        "      $string_piece$(value));\n"
-        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-        "}\n");
-    if (!options_.opensource_runtime) {
-      format(
-          "inline void $classname$::set_$name$(::StringPiece value) {\n"
-          "$annotate_accessor$"
-          "  if (!_internal_has_$name$()) {\n"
-          "    clear_$oneof_name$();\n"
-          "    set_has_$name$();\n"
-          "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-          "  }\n"
-          "  $field_member$.SetNoArena($default_variable$, value);\n"
-          "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
-          "}\n");
-    }
-    format(
-        "inline "
-        "void $classname$::set_$name$(const $pointer_type$* value, size_t "
-        "size) {\n"
-        "$annotate_accessor$"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  $field_member$.SetNoArena($default_variable$, $string_piece$(\n"
-        "      reinterpret_cast<const char*>(value), size));\n"
-        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-        "}\n"
-        "inline std::string* $classname$::_internal_mutable_$name$() {\n"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
-        "  }\n"
-        "  return $field_member$.MutableNoArena($default_variable$);\n"
-        "}\n"
-        "inline std::string* $classname$::$release_name$() {\n"
-        "$annotate_accessor$"
-        "  // @@protoc_insertion_point(field_release:$full_name$)\n"
-        "  if (_internal_has_$name$()) {\n"
-        "    clear_has_$oneof_name$();\n"
-        "    return $field_member$.ReleaseNoArena($default_variable$);\n"
-        "  } else {\n"
-        "    return nullptr;\n"
-        "  }\n"
-        "}\n"
-        "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
-        "$annotate_accessor$"
-        "  if (has_$oneof_name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "  }\n"
-        "  if ($name$ != nullptr) {\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($name$);\n"
-        "  }\n"
-        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-        "}\n");
-  }
+  format(
+      "inline std::string* $classname$::_internal_mutable_$name$() {\n"
+      "  if (!_internal_has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $field_member$.UnsafeSetDefault($init_value$);\n"
+      "  }\n"
+      "  return $field_member$.Mutable(\n"
+      "      $default_variable_or_tag$, GetArenaForAllocation());\n"
+      "}\n"
+      "inline std::string* $classname$::$release_name$() {\n"
+      "$annotate_release$"
+      "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+      "  if (_internal_has_$name$()) {\n"
+      "    clear_has_$oneof_name$();\n"
+      "    return $field_member$.ReleaseNonDefault($init_value$, "
+      "GetArenaForAllocation());\n"
+      "  } else {\n"
+      "    return nullptr;\n"
+      "  }\n"
+      "}\n"
+      "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
+      "  if (has_$oneof_name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "  }\n"
+      "  if ($name$ != nullptr) {\n"
+      "    set_has_$name$();\n"
+      "    $field_member$.UnsafeSetDefault($name$);\n"
+      "    ::$proto_ns$::Arena* arena = GetArenaForAllocation();\n"
+      "    if (arena != nullptr) {\n"
+      "      arena->Own($name$);\n"
+      "    }\n"
+      "  }\n"
+      "$annotate_set$"
+      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+      "}\n");
 }
 
 void StringOneofFieldGenerator::GenerateClearingCode(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
-  if (SupportsArenas(descriptor_)) {
-    format("$field_member$.Destroy($default_variable$, GetArena());\n");
-  } else {
-    format("$field_member$.DestroyNoArena($default_variable$);\n");
-  }
+  format(
+      "$field_member$.Destroy($default_value_tag$, "
+      "GetArenaForAllocation());\n");
 }
 
 void StringOneofFieldGenerator::GenerateMessageClearingCode(
@@ -911,19 +501,7 @@
 
 void StringOneofFieldGenerator::GenerateConstructorCode(
     io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "$ns$::_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n"
-      "    $default_variable$);\n");
-}
-
-void StringOneofFieldGenerator::GenerateDestructorCode(
-    io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format(
-      "if (_internal_has_$name$()) {\n"
-      "  $field_member$.DestroyNoArena($default_variable$);\n"
-      "}\n");
+  // Nothing required here.
 }
 
 // ===================================================================
@@ -1014,9 +592,10 @@
   Formatter format(printer, variables_);
   format(
       "inline std::string* $classname$::add_$name$() {\n"
-      "$annotate_accessor$"
+      "  std::string* _s = _internal_add_$name$();\n"
+      "$annotate_add_mutable$"
       "  // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
-      "  return _internal_add_$name$();\n"
+      "  return _s;\n"
       "}\n");
   if (options_.safe_boundary_check) {
     format(
@@ -1034,39 +613,39 @@
   }
   format(
       "inline const std::string& $classname$::$name$(int index) const {\n"
-      "$annotate_accessor$"
+      "$annotate_get$"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$(index);\n"
       "}\n"
       "inline std::string* $classname$::mutable_$name$(int index) {\n"
-      "$annotate_accessor$"
+      "$annotate_mutable$"
       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
       "  return $name$_.Mutable(index);\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, const std::string& "
       "value) "
       "{\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "  $name$_.Mutable(index)->assign(value);\n"
+      "$annotate_set$"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, std::string&& value) {\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "  $name$_.Mutable(index)->assign(std::move(value));\n"
+      "$annotate_set$"
+      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, const char* value) {\n"
-      "$annotate_accessor$"
       "  $null_check$"
       "  $name$_.Mutable(index)->assign(value);\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
       "}\n");
   if (!options_.opensource_runtime) {
     format(
         "inline void "
         "$classname$::set_$name$(int index, StringPiece value) {\n"
-        "$annotate_accessor$"
         "  $name$_.Mutable(index)->assign(value.data(), value.size());\n"
+        "$annotate_set$"
         "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
         "}\n");
   }
@@ -1074,54 +653,54 @@
       "inline void "
       "$classname$::set_$name$"
       "(int index, const $pointer_type$* value, size_t size) {\n"
-      "$annotate_accessor$"
       "  $name$_.Mutable(index)->assign(\n"
       "    reinterpret_cast<const char*>(value), size);\n"
+      "$annotate_set$"
       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
       "}\n"
       "inline std::string* $classname$::_internal_add_$name$() {\n"
       "  return $name$_.Add();\n"
       "}\n"
       "inline void $classname$::add_$name$(const std::string& value) {\n"
-      "$annotate_accessor$"
       "  $name$_.Add()->assign(value);\n"
+      "$annotate_add$"
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
       "}\n"
       "inline void $classname$::add_$name$(std::string&& value) {\n"
-      "$annotate_accessor$"
       "  $name$_.Add(std::move(value));\n"
+      "$annotate_add$"
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
       "}\n"
       "inline void $classname$::add_$name$(const char* value) {\n"
-      "$annotate_accessor$"
       "  $null_check$"
       "  $name$_.Add()->assign(value);\n"
+      "$annotate_add$"
       "  // @@protoc_insertion_point(field_add_char:$full_name$)\n"
       "}\n");
   if (!options_.opensource_runtime) {
     format(
         "inline void $classname$::add_$name$(StringPiece value) {\n"
-        "$annotate_accessor$"
         "  $name$_.Add()->assign(value.data(), value.size());\n"
+        "$annotate_add$"
         "  // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
         "}\n");
   }
   format(
       "inline void "
       "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
-      "$annotate_accessor$"
       "  $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
+      "$annotate_add$"
       "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
       "}\n"
       "inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
       "$classname$::$name$() const {\n"
-      "$annotate_accessor$"
+      "$annotate_list$"
       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
       "  return $name$_;\n"
       "}\n"
       "inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
       "$classname$::mutable_$name$() {\n"
-      "$annotate_accessor$"
+      "$annotate_mutable_list$"
       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
       "  return &$name$_;\n"
       "}\n");
@@ -1188,6 +767,12 @@
       "}\n");
 }
 
+void RepeatedStringFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index f39a93a..f35cff1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -51,30 +51,21 @@
   ~StringFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateStaticMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMessageClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateDestructorCode(io::Printer* printer) const;
-  bool GenerateArenaDestructorCode(io::Printer* printer) const;
-  void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
-  uint32 CalculateFieldTag() const;
-  bool IsInlined() const { return inlined_; }
-
-  bool MergeFromCodedStreamNeedsArena() const;
-
- protected:
-  const bool lite_;
-  bool inlined_;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateStaticMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMessageClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override;
+  void GenerateDestructorCode(io::Printer* printer) const override;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
@@ -87,15 +78,14 @@
   ~StringOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
 
   // StringFieldGenerator, from which we inherit, overrides this so we need to
   // override it as well.
-  void GenerateMessageClearingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateDestructorCode(io::Printer* printer) const;
+  void GenerateMessageClearingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
@@ -108,16 +98,17 @@
   ~RepeatedStringFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateClearingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
-  void GenerateCopyConstructorCode(io::Printer* printer) const;
-  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
-  void GenerateByteSize(io::Printer* printer) const;
+  void GeneratePrivateMembers(io::Printer* printer) const override;
+  void GenerateAccessorDeclarations(io::Printer* printer) const override;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+  void GenerateClearingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateSwappingCode(io::Printer* printer) const override;
+  void GenerateConstructorCode(io::Printer* printer) const override;
+  void GenerateCopyConstructorCode(io::Printer* printer) const override;
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const override;
+  void GenerateByteSize(io::Printer* printer) const override;
+  void GenerateConstinitInitializer(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 4797108..466a841 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -41,7 +41,7 @@
 
 // Some generic_services option(s) added automatically.
 // See:  http://go/proto2-generic-services-default
-option cc_generic_services = true; // auto-added
+option cc_generic_services = true;  // auto-added
 
 // We don't put this in a package within proto2 because we need to make sure
 // that the generated code doesn't depend on being in the proto2 namespace.
@@ -158,11 +158,11 @@
   optional while conflicting_enum = 1;  // NO_PROTO3
 }  // NO_PROTO3
 
-enum bool {             // NO_PROTO3
-  default = 0;          // NO_PROTO3
-  NOT_EQ = 1;           // NO_PROTO3
-  volatile = 2;         // NO_PROTO3
-  return = 3;           // NO_PROTO3
+enum bool {      // NO_PROTO3
+  default = 0;   // NO_PROTO3
+  NOT_EQ = 1;    // NO_PROTO3
+  volatile = 2;  // NO_PROTO3
+  return = 3;    // NO_PROTO3
 }  // NO_PROTO3
 
 message DummyMessage {}
@@ -173,7 +173,7 @@
 
 extend TestConflictingSymbolNames {  // NO_PROTO3
   optional int32 void = 314253;      // NO_PROTO3
-}                                    // NO_PROTO3
+}  // NO_PROTO3
 
 // Message names that could conflict.
 message Shutdown {}
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.inc b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
index 0bf754c..e929da2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.inc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
@@ -44,12 +44,12 @@
 // correctly and produces the interfaces we expect, which is why this test
 // is written this way.
 
-#include <google/protobuf/compiler/cpp/cpp_unittest.h>
-
+#include <cstdint>
+#include <limits>
 #include <memory>
 #include <vector>
 
-#include <google/protobuf/unittest_no_arena.pb.h>
+#include <google/protobuf/compiler/cpp/cpp_unittest.h>
 #include <google/protobuf/stubs/strutil.h>
 #if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
 // We exclude this large proto from cmake build because it's too large for
@@ -99,7 +99,7 @@
 
   // implements ErrorCollector ---------------------------------------
   void AddError(const std::string& filename, int line, int column,
-                const std::string& message) {
+                const std::string& message) override {
     strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
                               message);
   }
@@ -205,10 +205,10 @@
 TEST(GENERATED_MESSAGE_TEST_NAME, ExtremeSmallIntegerDefault) {
   const UNITTEST::TestExtremeDefaultValues& extreme_default =
       UNITTEST::TestExtremeDefaultValues::default_instance();
-  EXPECT_EQ(~0x7fffffff, kint32min);
-  EXPECT_EQ(PROTOBUF_LONGLONG(~0x7fffffffffffffff), kint64min);
-  EXPECT_EQ(kint32min, extreme_default.really_small_int32());
-  EXPECT_EQ(kint64min, extreme_default.really_small_int64());
+  EXPECT_EQ(std::numeric_limits<int32_t>::min(),
+            extreme_default.really_small_int32());
+  EXPECT_EQ(std::numeric_limits<int64_t>::min(),
+            extreme_default.really_small_int64());
 }
 
 TEST(GENERATED_MESSAGE_TEST_NAME, Accessors) {
@@ -371,7 +371,7 @@
   UNITTEST::TestAllTypes message;
 
   TestUtil::SetAllFields(&message);
-  int64 original_value = message.optional_int64();
+  int64_t original_value = message.optional_int64();
 
   // Clear the field and make sure it shows up as cleared.
   message.clear_optional_int64();
@@ -403,69 +403,6 @@
   EXPECT_EQ("wx", message.repeated_string(0));
 }
 
-TEST(GENERATED_MESSAGE_TEST_NAME, StringMove) {
-  // Verify that we trigger the move behavior on a scalar setter.
-  protobuf_unittest_no_arena::TestAllTypes message;
-  {
-    std::string tmp(32, 'a');
-
-    const char* old_data = tmp.data();
-    message.set_optional_string(std::move(tmp));
-    const char* new_data = message.optional_string().data();
-
-    EXPECT_EQ(old_data, new_data);
-    EXPECT_EQ(std::string(32, 'a'), message.optional_string());
-
-    std::string tmp2(32, 'b');
-    old_data = tmp2.data();
-    message.set_optional_string(std::move(tmp2));
-    new_data = message.optional_string().data();
-
-    EXPECT_EQ(old_data, new_data);
-    EXPECT_EQ(std::string(32, 'b'), message.optional_string());
-  }
-
-  // Verify that we trigger the move behavior on a oneof setter.
-  {
-    std::string tmp(32, 'a');
-
-    const char* old_data = tmp.data();
-    message.set_oneof_string(std::move(tmp));
-    const char* new_data = message.oneof_string().data();
-
-    EXPECT_EQ(old_data, new_data);
-    EXPECT_EQ(std::string(32, 'a'), message.oneof_string());
-
-    std::string tmp2(32, 'b');
-    old_data = tmp2.data();
-    message.set_oneof_string(std::move(tmp2));
-    new_data = message.oneof_string().data();
-
-    EXPECT_EQ(old_data, new_data);
-    EXPECT_EQ(std::string(32, 'b'), message.oneof_string());
-  }
-
-  // Verify that we trigger the move behavior on a repeated setter.
-  {
-    std::string tmp(32, 'a');
-
-    const char* old_data = tmp.data();
-    message.add_repeated_string(std::move(tmp));
-    const char* new_data = message.repeated_string(0).data();
-
-    EXPECT_EQ(old_data, new_data);
-    EXPECT_EQ(std::string(32, 'a'), message.repeated_string(0));
-
-    std::string tmp2(32, 'b');
-    old_data = tmp2.data();
-    message.set_repeated_string(0, std::move(tmp2));
-    new_data = message.repeated_string(0).data();
-
-    EXPECT_EQ(old_data, new_data);
-    EXPECT_EQ(std::string(32, 'b'), message.repeated_string(0));
-  }
-}
-
 
 TEST(GENERATED_MESSAGE_TEST_NAME, CopyFrom) {
   UNITTEST::TestAllTypes message1, message2;
@@ -563,7 +500,7 @@
 
   // Note the address of one of the repeated fields, to verify it was swapped
   // rather than copied.
-  const int32* addr = &message1.repeated_int32().Get(0);
+  const int32_t* addr = &message1.repeated_int32().Get(0);
 
   using std::swap;
   swap(message1, message2);
@@ -713,7 +650,7 @@
 
   // This tests concatenating.
   message2.add_repeated_int32(message1.repeated_int32(1));
-  int32 i = message1.repeated_int32(0);
+  int32_t i = message1.repeated_int32(0);
   message1.clear_repeated_int32();
   message1.add_repeated_int32(i);
 
@@ -730,8 +667,8 @@
   TestUtil::SetAllFields(&message1);
   int size = message1.ByteSizeLong();
   data.resize(size);
-  uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-  uint8* end = message1.SerializeWithCachedSizesToArray(start);
+  uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+  uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
   EXPECT_EQ(size, end - start);
   EXPECT_TRUE(message2.ParseFromString(data));
   TestUtil::ExpectAllFieldsSet(message2);
@@ -744,8 +681,9 @@
   TestUtil::SetPackedFields(&packed_message1);
   int packed_size = packed_message1.ByteSizeLong();
   packed_data.resize(packed_size);
-  uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&packed_data));
-  uint8* end = packed_message1.SerializeWithCachedSizesToArray(start);
+  uint8_t* start =
+      reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&packed_data));
+  uint8_t* end = packed_message1.SerializeWithCachedSizesToArray(start);
   EXPECT_EQ(packed_size, end - start);
   EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
   TestUtil::ExpectPackedFieldsSet(packed_message2);
@@ -1217,7 +1155,7 @@
     void Foo(RpcController* controller,
              const UNITTEST::FooRequest* request,
              UNITTEST::FooResponse* response,
-             Closure* done) {
+             Closure* done) override {
       ASSERT_FALSE(called_);
       called_ = true;
       method_ = "Foo";
@@ -1230,7 +1168,7 @@
     void Bar(RpcController* controller,
              const UNITTEST::BarRequest* request,
              UNITTEST::BarResponse* response,
-             Closure* done) {
+             Closure* done) override {
       ASSERT_FALSE(called_);
       called_ = true;
       method_ = "Bar";
@@ -1273,7 +1211,7 @@
                     RpcController* controller,
                     const Message* request,
                     Message* response,
-                    Closure* done) {
+                    Closure* done) override {
       ASSERT_FALSE(called_);
       called_ = true;
       method_ = method;
@@ -1296,28 +1234,28 @@
 
   class MockController : public RpcController {
    public:
-    void Reset() {
+    void Reset() override {
       ADD_FAILURE() << "Reset() not expected during this test.";
     }
-    bool Failed() const {
+    bool Failed() const override {
       ADD_FAILURE() << "Failed() not expected during this test.";
       return false;
     }
-    std::string ErrorText() const {
+    std::string ErrorText() const override {
       ADD_FAILURE() << "ErrorText() not expected during this test.";
       return "";
     }
-    void StartCancel() {
+    void StartCancel() override {
       ADD_FAILURE() << "StartCancel() not expected during this test.";
     }
-    void SetFailed(const std::string& reason) {
+    void SetFailed(const std::string& reason) override {
       ADD_FAILURE() << "SetFailed() not expected during this test.";
     }
-    bool IsCanceled() const {
+    bool IsCanceled() const override {
       ADD_FAILURE() << "IsCanceled() not expected during this test.";
       return false;
     }
-    void NotifyOnCancel(Closure* callback) {
+    void NotifyOnCancel(Closure* callback) override {
       ADD_FAILURE() << "NotifyOnCancel() not expected during this test.";
     }
   };
@@ -1329,7 +1267,7 @@
       stub_(&mock_channel_),
       done_(::google::protobuf::NewPermanentCallback(&DoNothing)) {}
 
-  virtual void SetUp() {
+  virtual void SetUp() override {
     ASSERT_TRUE(foo_ != NULL);
     ASSERT_TRUE(bar_ != NULL);
   }
@@ -1470,7 +1408,7 @@
    public:
     ExpectUnimplementedController() : called_(false) {}
 
-    void SetFailed(const std::string& reason) {
+    void SetFailed(const std::string& reason) override {
       EXPECT_FALSE(called_);
       called_ = true;
       EXPECT_EQ("Method Foo() not implemented.", reason);
@@ -1492,7 +1430,7 @@
 
 class OneofTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
   }
 
   void ExpectEnumCasesWork(const UNITTEST::TestOneof2 &message) {
@@ -1683,6 +1621,26 @@
   EXPECT_EQ(kHello, message.foo_string());
 }
 
+TEST_F(OneofTest, ArenaSetAllocatedString) {
+  // Check that set_allocated_foo() works for strings.
+  Arena arena;
+  UNITTEST::TestOneof2* message =
+      Arena::CreateMessage<UNITTEST::TestOneof2>(&arena);
+
+  EXPECT_FALSE(message->has_foo_string());
+  const std::string kHello("hello");
+  message->set_foo_string(kHello);
+  EXPECT_TRUE(message->has_foo_string());
+
+  message->set_allocated_foo_string(NULL);
+  EXPECT_FALSE(message->has_foo_string());
+  EXPECT_EQ("", message->foo_string());
+
+  message->set_allocated_foo_string(new std::string(kHello));
+  EXPECT_TRUE(message->has_foo_string());
+  EXPECT_EQ(kHello, message->foo_string());
+}
+
 
 TEST_F(OneofTest, SetMessage) {
   // Check that setting a message field works
@@ -1891,8 +1849,8 @@
 message1.set_foo_int(123);
 int size = message1.ByteSizeLong();
 data.resize(size);
-uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-uint8* end = message1.SerializeWithCachedSizesToArray(start);
+uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
 EXPECT_EQ(size, end - start);
 EXPECT_TRUE(message2.ParseFromString(data));
 EXPECT_EQ(message2.foo_int(), 123);
@@ -1905,8 +1863,8 @@
     message1.set_foo_string("foo");
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_string(), "foo");
@@ -1920,8 +1878,8 @@
     message1.set_foo_bytes("qux");
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_bytes(), "qux");
@@ -1934,8 +1892,8 @@
     message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
@@ -1948,8 +1906,8 @@
     message1.mutable_foo_message()->set_qux_int(234);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_message().qux_int(), 234);
@@ -1962,8 +1920,8 @@
     message1.mutable_foogroup()->set_a(345);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foogroup().a(), 345);
diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
index a16c8b5..b5cac8f4 100644
--- a/src/google/protobuf/compiler/cpp/metadata_test.cc
+++ b/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -30,14 +30,13 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/annotation_test_util.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/descriptor.pb.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
index 978fdf0..86bacf8 100644
--- a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
@@ -65,11 +65,11 @@
   MockErrorCollector() {}
   ~MockErrorCollector() {}
 
-  string text_;
+  std::string text_;
 
   // implements ErrorCollector ---------------------------------------
-  void AddError(const string& filename, int line, int column,
-                const string& message) {
+  void AddError(const std::string& filename, int line, int column,
+                const std::string& message) {
     strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
                                  filename, line, column, message);
   }
@@ -77,14 +77,14 @@
 
 class MockGeneratorContext : public GeneratorContext {
  public:
-  void ExpectFileMatches(const string& virtual_filename,
-                         const string& physical_filename) {
+  void ExpectFileMatches(const std::string& virtual_filename,
+                         const std::string& physical_filename) {
     auto it = files_.find(virtual_filename);
     ASSERT_TRUE(it != files_.end())
       << "Generator failed to generate file: " << virtual_filename;
-    string expected_contents = *it->second;
+    std::string expected_contents = *it->second;
 
-    string actual_contents;
+    std::string actual_contents;
     GOOGLE_CHECK_OK(
         File::GetContentsAsText(TestSourceDir() + "/" + physical_filename,
                           &actual_contents, true))
@@ -97,7 +97,7 @@
 
   // implements GeneratorContext --------------------------------------
 
-  virtual io::ZeroCopyOutputStream* Open(const string& filename) {
+  virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
     auto& map_slot = files_[filename];
     map_slot.reset(new std::string);
     return new io::StringOutputStream(map_slot.get());
@@ -110,7 +110,7 @@
 class GenerateAndTest {
  public:
   GenerateAndTest() {}
-  void Run(const FileDescriptor* proto_file, string file1, string file2) {
+  void Run(const FileDescriptor* proto_file, std::string file1, std::string file2) {
     ASSERT_TRUE(proto_file != NULL) << TestSourceDir();
     ASSERT_TRUE(generator_.Generate(proto_file, parameter_,
                                     &context_, &error_));
@@ -123,14 +123,14 @@
  private:
   Generator generator_;
   MockGeneratorContext context_;
-  string error_;
-  string parameter_;
+  std::string error_;
+  std::string parameter_;
 };
 
 TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) {
   // Skip this whole test if the csharp directory doesn't exist (i.e., a C++11
   // only distribution).
-  string descriptor_file_name =
+  std::string descriptor_file_name =
       "../csharp/src/Google.Protobuf/Reflection/Descriptor.cs";
   if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) {
     return;
diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
index a4e9ff4..225d6dc 100644
--- a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
@@ -47,7 +47,7 @@
 // is inlined in the relevant code. If more control is required, that code can be moved here.
 
 void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
-    string comments = location.leading_comments.empty() ?
+    std::string comments = location.leading_comments.empty() ?
         location.trailing_comments : location.leading_comments;
     if (comments.empty()) {
         return;
@@ -56,7 +56,7 @@
     // node of a summary element, not part of an attribute.
     comments = StringReplace(comments, "&", "&amp;", true);
     comments = StringReplace(comments, "<", "&lt;", true);
-    std::vector<string> lines;
+    std::vector<std::string> lines;
     lines = Split(comments, "\n", false);
     // TODO: We really should work out which part to put in the summary and which to put in the remarks...
     // but that needs to be part of a bigger effort to understand the markdown better anyway.
@@ -66,17 +66,18 @@
     // to preserve the blank lines themselves, as this is relevant in the markdown.
     // Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
     // (We don't skip "just whitespace" lines, either.)
-    for (std::vector<string>::iterator it = lines.begin(); it != lines.end(); ++it) {
-        string line = *it;
-        if (line.empty()) {
-            last_was_empty = true;
-        } else {
-            if (last_was_empty) {
-                printer->Print("///\n");
-            }
-            last_was_empty = false;
-            printer->Print("///$line$\n", "line", *it);
+    for (std::vector<std::string>::iterator it = lines.begin();
+         it != lines.end(); ++it) {
+      std::string line = *it;
+      if (line.empty()) {
+        last_was_empty = true;
+      } else {
+        if (last_was_empty) {
+          printer->Print("///\n");
         }
+        last_was_empty = false;
+        printer->Print("///$line$\n", "line", *it);
+      }
     }
     printer->Print("/// </summary>\n");
 }
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
index 2baefd8..73679ca 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -48,7 +48,7 @@
 namespace csharp {
 
 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
-    SourceGeneratorBase(descriptor->file(), options),
+    SourceGeneratorBase(options),
     descriptor_(descriptor) {
 }
 
@@ -61,12 +61,13 @@
                  "access_level", class_access_level(),
                  "name", descriptor_->name());
   printer->Indent();
-  std::set<string> used_names;
+  std::set<std::string> used_names;
   std::set<int> used_number;
   for (int i = 0; i < descriptor_->value_count(); i++) {
       WriteEnumValueDocComment(printer, descriptor_->value(i));
-      string original_name = descriptor_->value(i)->name();
-      string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
+      std::string original_name = descriptor_->value(i)->name();
+      std::string name =
+          GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
       // Make sure we don't get any duplicate names due to prefix removal.
       while (!used_names.insert(name).second) {
         // It's possible we'll end up giving this warning multiple times, but that's better than not at all.
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
index 9f1a2ea..e282d72 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -51,11 +51,11 @@
   EnumFieldGenerator(const EnumFieldGenerator&) = delete;
   EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
 
-  virtual void GenerateCodecCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
-  virtual void GenerateExtensionCode(io::Printer* printer);
+  virtual void GenerateCodecCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+  virtual void GenerateExtensionCode(io::Printer* printer) override;
 };
 
 class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
@@ -68,10 +68,10 @@
   EnumOneofFieldGenerator(const EnumOneofFieldGenerator&) = delete;
   EnumOneofFieldGenerator& operator=(const EnumOneofFieldGenerator&) = delete;
 
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 454f4cb..477b49e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -51,7 +51,7 @@
 namespace csharp {
 
 void FieldGeneratorBase::SetCommonFieldVariables(
-    std::map<string, string>* variables) {
+    std::map<std::string, std::string>* variables) {
   // Note: this will be valid even though the tag emitted for packed and unpacked versions of
   // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
   // never effects the tag size.
@@ -63,7 +63,7 @@
   uint tag = internal::WireFormat::MakeTag(descriptor_);
   uint8 tag_array[5];
   io::CodedOutputStream::WriteTagToArray(tag, tag_array);
-  string tag_bytes = StrCat(tag_array[0]);
+  std::string tag_bytes = StrCat(tag_array[0]);
   for (int i = 1; i < part_tag_size; i++) {
     tag_bytes += ", " + StrCat(tag_array[i]);
   }
@@ -96,20 +96,20 @@
   (*variables)["default_value"] = default_value();
   (*variables)["capitalized_type_name"] = capitalized_type_name();
   (*variables)["number"] = number();
-  if (has_default_value() && !IsProto2(descriptor_->file())) {
+  if (has_default_value() && !SupportsPresenceApi(descriptor_)) {
     (*variables)["name_def_message"] =
       (*variables)["name"] + "_ = " + (*variables)["default_value"];
   } else {
     (*variables)["name_def_message"] = (*variables)["name"] + "_";
   }
-  if (IsProto2(descriptor_->file())) {
+  if (SupportsPresenceApi(descriptor_)) {
     (*variables)["has_property_check"] = "Has" + (*variables)["property_name"];
     (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"];
     (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
     (*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
     if (presenceIndex_ != -1) {
-      string hasBitsNumber = StrCat(presenceIndex_ / 32);
-      string hasBitsMask = StrCat(1 << (presenceIndex_ % 32));
+      std::string hasBitsNumber = StrCat(presenceIndex_ / 32);
+      std::string hasBitsMask = StrCat(1 << (presenceIndex_ % 32));
       (*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0";
       (*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask;
       (*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask;
@@ -123,9 +123,9 @@
 }
 
 void FieldGeneratorBase::SetCommonOneofFieldVariables(
-    std::map<string, string>* variables) {
+    std::map<std::string, std::string>* variables) {
   (*variables)["oneof_name"] = oneof_name();
-  if (IsProto2(descriptor_->file())) {
+  if (SupportsPresenceApi(descriptor_)) {
     (*variables)["has_property_check"] = "Has" + property_name();
   } else {
     (*variables)["has_property_check"] =
@@ -137,7 +137,7 @@
 
 FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
                                        int presenceIndex, const Options* options)
-    : SourceGeneratorBase(descriptor->file(), options),
+    : SourceGeneratorBase(options),
       descriptor_(descriptor),
       presenceIndex_(presenceIndex) {
   SetCommonFieldVariables(&variables_);
@@ -161,6 +161,18 @@
   // and repeated fields need this default is to not generate any code
 }
 
+void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+  // for some field types the value of "use_parse_context" doesn't matter,
+  // so we fallback to the default implementation.
+  GenerateParsingCode(printer);
+}
+
+void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+  // for some field types the value of "use_write_context" doesn't matter,
+  // so we fallback to the default implementation.
+  GenerateSerializationCode(printer);
+}
+
 void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
   if (descriptor_->options().deprecated()) {
     printer->Print("[global::System.ObsoleteAttribute]\n");
@@ -204,7 +216,7 @@
       if (IsWrapperType(descriptor)) {
         const FieldDescriptor* wrapped_field =
             descriptor->message_type()->field(0);
-        string wrapped_field_type_name = type_name(wrapped_field);
+        std::string wrapped_field_type_name = type_name(wrapped_field);
         // String and ByteString go to the same type; other wrapped types
         // go to the nullable equivalent.
         if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index 594461d..f875fa1 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -61,7 +61,9 @@
   virtual void GenerateMembers(io::Printer* printer) = 0;
   virtual void GenerateMergingCode(io::Printer* printer) = 0;
   virtual void GenerateParsingCode(io::Printer* printer) = 0;
+  virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer) = 0;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0;
 
   virtual void WriteHash(io::Printer* printer) = 0;
@@ -72,14 +74,15 @@
  protected:
   const FieldDescriptor* descriptor_;
   const int presenceIndex_;
-  std::map<string, string> variables_;
+  std::map<std::string, std::string> variables_;
 
   void AddDeprecatedFlag(io::Printer* printer);
   void AddNullCheck(io::Printer* printer);
   void AddNullCheck(io::Printer* printer, const std::string& name);
 
   void AddPublicMemberAttributes(io::Printer* printer);
-  void SetCommonOneofFieldVariables(std::map<string, string>* variables);
+  void SetCommonOneofFieldVariables(
+      std::map<std::string, std::string>* variables);
 
   std::string oneof_property_name();
   std::string oneof_name();
@@ -94,7 +97,7 @@
   std::string capitalized_type_name();
 
  private:
-  void SetCommonFieldVariables(std::map<string, string>* variables);
+  void SetCommonFieldVariables(std::map<std::string, std::string>* variables);
   std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor);
   std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor);
 };
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index b335522..5ce0651 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -48,19 +48,24 @@
 namespace compiler {
 namespace csharp {
 
+Generator::Generator() {}
+Generator::~Generator() {}
+
+uint64_t Generator::GetSupportedFeatures() const {
+  return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
+}
+
 void GenerateFile(const FileDescriptor* file, io::Printer* printer,
                   const Options* options) {
   ReflectionClassGenerator reflectionClassGenerator(file, options);
   reflectionClassGenerator.Generate(printer);
 }
 
-bool Generator::Generate(
-    const FileDescriptor* file,
-    const string& parameter,
-    GeneratorContext* generator_context,
-    string* error) const {
-
-  std::vector<std::pair<string, string> > options;
+bool Generator::Generate(const FileDescriptor* file,
+                         const std::string& parameter,
+                         GeneratorContext* generator_context,
+                         std::string* error) const {
+  std::vector<std::pair<std::string, std::string> > options;
   ParseGeneratorParameter(parameter, &options);
 
   struct Options cli_options;
@@ -81,7 +86,7 @@
     }
   }
 
-  string filename_error = "";
+  std::string filename_error = "";
   std::string filename = GetOutputFile(file,
       cli_options.file_extension,
       cli_options.base_namespace_specified,
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h
index da72e0e..f41f9b8 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.h
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.h
@@ -50,11 +50,14 @@
 // CodeGenerator with the CommandLineInterface in your main() function.
 class PROTOC_EXPORT Generator : public CodeGenerator {
  public:
-  virtual bool Generate(
-      const FileDescriptor* file,
-      const string& parameter,
-      GeneratorContext* generator_context,
-      string* error) const;
+  Generator();
+  ~Generator();
+  bool Generate(
+    const FileDescriptor* file,
+    const std::string& parameter,
+    GeneratorContext* generator_context,
+    std::string* error) const override;
+  uint64_t GetSupportedFeatures() const override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index 98aa246..32ef399 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -143,7 +143,7 @@
 std::string UnderscoresToCamelCase(const std::string& input,
                                    bool cap_next_letter,
                                    bool preserve_period) {
-  string result;
+  std::string result;
   // Note:  I distrust ctype.h due to locales.
   for (int i = 0; i < input.size(); i++) {
     if ('a' <= input[i] && input[i] <= 'z') {
@@ -195,7 +195,7 @@
 // Lower letter                  Alphanumeric              Same as current
 // Upper letter                  Alphanumeric              Lower
 std::string ShoutyToPascalCase(const std::string& input) {
-  string result;
+  std::string result;
   // Simple way of implementing "always start with upper"
   char previous = '_';
   for (int i = 0; i < input.size(); i++) {
@@ -325,7 +325,7 @@
   if (!result.empty()) {
     result += '.';
   }
-  string classname;
+  std::string classname;
   if (file->package().empty()) {
     classname = name;
   } else {
@@ -396,19 +396,20 @@
 std::string GetOutputFile(const FileDescriptor* descriptor,
                           const std::string file_extension,
                           const bool generate_directories,
-                          const std::string base_namespace, string* error) {
-  string relative_filename = GetFileNameBase(descriptor) + file_extension;
+                          const std::string base_namespace,
+                          std::string* error) {
+  std::string relative_filename = GetFileNameBase(descriptor) + file_extension;
   if (!generate_directories) {
     return relative_filename;
   }
-  string ns = GetFileNamespace(descriptor);
-  string namespace_suffix = ns;
+  std::string ns = GetFileNamespace(descriptor);
+  std::string namespace_suffix = ns;
   if (!base_namespace.empty()) {
     // Check that the base_namespace is either equal to or a leading part of
     // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
     // be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
     // to both.
-    string extended_ns = ns + ".";
+    std::string extended_ns = ns + ".";
     if (extended_ns.find(base_namespace + ".") != 0) {
       *error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
       return ""; // This will be ignored, because we've set an error.
@@ -419,7 +420,7 @@
     }
   }
 
-  string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
+  std::string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
   if (!namespace_dir.empty()) {
     namespace_dir += "/";
   }
@@ -515,13 +516,13 @@
         }
       } else {
         if (IsWrapperType(descriptor)) {
-          if (descriptor->containing_oneof()) {
+          if (descriptor->real_containing_oneof()) {
             return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options);
           } else {
             return new WrapperFieldGenerator(descriptor, presenceIndex, options);
           }
         } else {
-          if (descriptor->containing_oneof()) {
+          if (descriptor->real_containing_oneof()) {
             return new MessageOneofFieldGenerator(descriptor, presenceIndex, options);
           } else {
             return new MessageFieldGenerator(descriptor, presenceIndex, options);
@@ -532,7 +533,7 @@
       if (descriptor->is_repeated()) {
         return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options);
       } else {
-        if (descriptor->containing_oneof()) {
+        if (descriptor->real_containing_oneof()) {
           return new EnumOneofFieldGenerator(descriptor, presenceIndex, options);
         } else {
           return new EnumFieldGenerator(descriptor, presenceIndex, options);
@@ -542,7 +543,7 @@
       if (descriptor->is_repeated()) {
         return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options);
       } else {
-        if (descriptor->containing_oneof()) {
+        if (descriptor->real_containing_oneof()) {
           return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options);
         } else {
           return new PrimitiveFieldGenerator(descriptor, presenceIndex, options);
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index 6354e9e..a6009c8 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -138,7 +138,7 @@
   if (!IsDescriptorProto(descriptor->file())) {
     return false;
   }
-  const string name = descriptor->full_name();
+  const std::string name = descriptor->full_name();
   return name == "google.protobuf.FileOptions" ||
       name == "google.protobuf.MessageOptions" ||
       name == "google.protobuf.FieldOptions" ||
@@ -158,6 +158,33 @@
   return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }
 
+inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) {
+  // Unlike most languages, we don't generate Has/Clear members for message
+  // types, because they can always be set to null in C#. They're not really
+  // needed for oneof fields in proto2 either, as everything can be done via
+  // oneof case, but we follow the convention from other languages. Proto3
+  // oneof fields never have Has/Clear members - but will also never have
+  // the explicit optional keyword either.
+  //
+  // None of the built-in helpers (descriptor->has_presence() etc) describe
+  // quite the behavior we want, so the rules are explicit below.
+
+  if (descriptor->is_repeated() ||
+      descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
+    return false;
+  }
+  // has_optional_keyword() has more complex rules for proto2, but that
+  // doesn't matter given the first part of this condition.
+  return IsProto2(descriptor->file()) || descriptor->has_optional_keyword();
+}
+
+inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) {
+  return SupportsPresenceApi(descriptor) &&
+    !IsNullable(descriptor) &&
+    !descriptor->is_extension() &&
+    !descriptor->real_containing_oneof();
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index f3f09ea..44c13e2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -94,15 +94,27 @@
 }
 
 void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  GenerateParsingCode(printer, true);
+}
+
+void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
   printer->Print(
     variables_,
-    "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
+    use_parse_context
+    ? "$name$_.AddEntriesFrom(ref input, _map_$name$_codec);\n"
+    : "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
 }
 
 void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _map_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _map_$name$_codec);\n"
+    : "$name$_.WriteTo(output, _map_$name$_codec);\n");
 }
 
 void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h
index b920b9f..9b5e214 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -51,17 +51,19 @@
   MapFieldGenerator(const MapFieldGenerator&) = delete;
   MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
 
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateFreezingCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateFreezingCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
 
-  virtual void WriteHash(io::Printer* printer);
-  virtual void WriteEquals(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
+  virtual void WriteHash(io::Printer* printer) override;
+  virtual void WriteEquals(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 67f2892..9980874 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -60,7 +60,7 @@
 
 MessageGenerator::MessageGenerator(const Descriptor* descriptor,
                                    const Options* options)
-    : SourceGeneratorBase(descriptor->file(), options),
+    : SourceGeneratorBase(options),
       descriptor_(descriptor),
       has_bit_field_count_(0),
       end_tag_(GetGroupEndTag(descriptor)),
@@ -72,15 +72,13 @@
   std::sort(fields_by_number_.begin(), fields_by_number_.end(),
             CompareFieldNumbers);
 
-  if (IsProto2(descriptor_->file())) {
-    int primitiveCount = 0;
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* field = descriptor_->field(i);
-      if (!IsNullable(field)) {
-        primitiveCount++;
-        if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) {
-          has_bit_field_count_++;
-        }
+  int presence_bit_count = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (RequiresPresenceBit(field)) {
+      presence_bit_count++;
+      if (has_bit_field_count_ == 0 || (presence_bit_count % 32) == 0) {
+        has_bit_field_count_++;
       }
     }
   }
@@ -114,7 +112,7 @@
 }
 
 void MessageGenerator::Generate(io::Printer* printer) {
-  std::map<string, string> vars;
+  std::map<std::string, std::string> vars;
   vars["class_name"] = class_name();
   vars["access_level"] = class_access_level();
 
@@ -127,12 +125,15 @@
     "$access_level$ sealed partial class $class_name$ : ");
 
   if (has_extension_ranges_) {
-    printer->Print(vars, "pb::IExtendableMessage<$class_name$>");
+    printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n");
   }
   else {
-    printer->Print(vars, "pb::IMessage<$class_name$>");
+    printer->Print(vars, "pb::IMessage<$class_name$>\n");
   }
-  printer->Print(" {\n");
+  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+  printer->Print("    , pb::IBufferMessage\n");
+  printer->Print("#endif\n");
+  printer->Print("{\n");
   printer->Indent();
 
   // All static fields and properties
@@ -222,11 +223,12 @@
     printer->Print("\n");
   }
 
-  // oneof properties
-  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
-    vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
-    vars["original_name"] = descriptor_->oneof_decl(i)->name();
+  // oneof properties (for real oneofs, which come before synthetic ones)
+  for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+    vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+    vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
+    vars["original_name"] = oneof->name();
     printer->Print(
       vars,
       "private object $name$_;\n"
@@ -234,8 +236,8 @@
       "public enum $property_name$OneofCase {\n");
     printer->Indent();
     printer->Print("None = 0,\n");
-    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
       printer->Print("$field_property_name$ = $index$,\n",
                      "field_property_name", GetPropertyName(field),
                      "index", StrCat(field->number()));
@@ -372,7 +374,7 @@
 }
 
 void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
-  std::map<string, string> vars;
+  std::map<std::string, std::string> vars;
   WriteGeneratedCodeAttributes(printer);
   vars["class_name"] = class_name();
     printer->Print(
@@ -382,23 +384,24 @@
   for (int i = 0; i < has_bit_field_count_; i++) {
     printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i));
   }
-  // Clone non-oneof fields first
+  // Clone non-oneof fields first (treating optional proto3 fields as non-oneof)
   for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (!descriptor_->field(i)->containing_oneof()) {
-      std::unique_ptr<FieldGeneratorBase> generator(
-        CreateFieldGeneratorInternal(descriptor_->field(i)));
-      generator->GenerateCloningCode(printer);
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->real_containing_oneof()) {
+      continue;
     }
+    std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+    generator->GenerateCloningCode(printer);
   }
-  // Clone just the right field for each oneof
-  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
-    vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
-    vars["property_name"] = UnderscoresToCamelCase(
-        descriptor_->oneof_decl(i)->name(), true);
+  // Clone just the right field for each real oneof
+  for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+    vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+    vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
     printer->Print(vars, "switch (other.$property_name$Case) {\n");
     printer->Indent();
-    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
       std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
       vars["field_property_name"] = GetPropertyName(field);
       printer->Print(
@@ -435,7 +438,7 @@
 }
 
 void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
-    std::map<string, string> vars;
+    std::map<std::string, std::string> vars;
     vars["class_name"] = class_name();
 
     // Equality
@@ -461,9 +464,9 @@
             CreateFieldGeneratorInternal(descriptor_->field(i)));
         generator->WriteEquals(printer);
     }
-    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-        printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
-            "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
+    for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+      printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
+          "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
     }
     if (has_extension_ranges_) {
       printer->Print(
@@ -488,9 +491,9 @@
             CreateFieldGeneratorInternal(descriptor_->field(i)));
         generator->WriteHash(printer);
     }
-    for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-        printer->Print("hash ^= (int) $name$Case_;\n",
-            "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
+    for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+      printer->Print("hash ^= (int) $name$Case_;\n",
+          "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
     }
     if (has_extension_ranges_) {
       printer->Print(
@@ -517,34 +520,26 @@
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
       "public void WriteTo(pb::CodedOutputStream output) {\n");
+  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
   printer->Indent();
-
-  // Serialize all the fields
-  for (int i = 0; i < fields_by_number().size(); i++) {
-    std::unique_ptr<FieldGeneratorBase> generator(
-      CreateFieldGeneratorInternal(fields_by_number()[i]));
-    generator->GenerateSerializationCode(printer);
-  }
-
-  if (has_extension_ranges_) {
-    // Serialize extensions
-    printer->Print(
-      "if (_extensions != null) {\n"
-      "  _extensions.WriteTo(output);\n"
-      "}\n");
-  }
-
-  // Serialize unknown fields
-  printer->Print(
-    "if (_unknownFields != null) {\n"
-    "  _unknownFields.WriteTo(output);\n"
-    "}\n");
-
-  // TODO(jonskeet): Memoize size of frozen messages?
+  printer->Print("output.WriteRawMessage(this);\n");
   printer->Outdent();
-  printer->Print(
-    "}\n"
-    "\n");
+  printer->Print("#else\n");
+  printer->Indent();
+  GenerateWriteToBody(printer, false);
+  printer->Outdent();
+  printer->Print("#endif\n");
+  printer->Print("}\n\n");
+
+  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n");
+  printer->Indent();
+  GenerateWriteToBody(printer, true);
+  printer->Outdent();
+  printer->Print("}\n");
+  printer->Print("#endif\n\n");
+
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
     "public int CalculateSize() {\n");
@@ -573,11 +568,44 @@
   printer->Print("}\n\n");
 }
 
+void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) {
+  // Serialize all the fields
+  for (int i = 0; i < fields_by_number().size(); i++) {
+    std::unique_ptr<FieldGeneratorBase> generator(
+      CreateFieldGeneratorInternal(fields_by_number()[i]));
+    generator->GenerateSerializationCode(printer, use_write_context);
+  }
+
+  if (has_extension_ranges_) {
+    // Serialize extensions
+    printer->Print(
+      use_write_context
+      ? "if (_extensions != null) {\n"
+        "  _extensions.WriteTo(ref output);\n"
+        "}\n"
+      : "if (_extensions != null) {\n"
+        "  _extensions.WriteTo(output);\n"
+        "}\n");
+  }
+
+  // Serialize unknown fields
+  printer->Print(
+    use_write_context
+    ? "if (_unknownFields != null) {\n"
+      "  _unknownFields.WriteTo(ref output);\n"
+      "}\n"
+    : "if (_unknownFields != null) {\n"
+      "  _unknownFields.WriteTo(output);\n"
+      "}\n");
+
+  // TODO(jonskeet): Memoize size of frozen messages?
+}
+
 void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
   // Note:  These are separate from GenerateMessageSerializationMethods()
   //   because they need to be generated even for messages that are optimized
   //   for code size.
-  std::map<string, string> vars;
+  std::map<std::string, std::string> vars;
   vars["class_name"] = class_name();
 
   WriteGeneratedCodeAttributes(printer);
@@ -589,22 +617,24 @@
     "if (other == null) {\n"
     "  return;\n"
     "}\n");
-  // Merge non-oneof fields
+  // Merge non-oneof fields, treating optional proto3 fields as normal fields
   for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (!descriptor_->field(i)->containing_oneof()) {
-      std::unique_ptr<FieldGeneratorBase> generator(
-          CreateFieldGeneratorInternal(descriptor_->field(i)));
-      generator->GenerateMergingCode(printer);
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->real_containing_oneof()) {
+      continue;
     }
+    std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+    generator->GenerateMergingCode(printer);
   }
-  // Merge oneof fields
-  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
-    vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
-    vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+  // Merge oneof fields (for non-synthetic oneofs)
+  for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+    vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+    vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
     printer->Print(vars, "switch (other.$property_name$Case) {\n");
     printer->Indent();
-    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
       vars["field_property_name"] = GetPropertyName(field);
       printer->Print(
         vars,
@@ -630,10 +660,34 @@
   printer->Outdent();
   printer->Print("}\n\n");
 
-
   WriteGeneratedCodeAttributes(printer);
   printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
+  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
   printer->Indent();
+  printer->Print("input.ReadRawMessage(this);\n");
+  printer->Outdent();
+  printer->Print("#else\n");
+  printer->Indent();
+  GenerateMainParseLoop(printer, false);
+  printer->Outdent();
+  printer->Print("#endif\n");
+  printer->Print("}\n\n");
+
+  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print("void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {\n");
+  printer->Indent();
+  GenerateMainParseLoop(printer, true);
+  printer->Outdent();
+  printer->Print("}\n"); // method
+  printer->Print("#endif\n\n");
+
+}
+
+void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) {
+  std::map<std::string, std::string> vars;
+  vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input";
+
   printer->Print(
     "uint tag;\n"
     "while ((tag = input.ReadTag()) != 0) {\n"
@@ -647,16 +701,16 @@
         "end_tag", StrCat(end_tag_));
   }
   if (has_extension_ranges_) {
-    printer->Print(
+    printer->Print(vars,
       "default:\n"
-      "  if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) {\n"
-      "    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
+      "  if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, $maybe_ref_input$)) {\n"
+      "    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
       "  }\n"
       "  break;\n");
   } else {
-    printer->Print(
+    printer->Print(vars,
       "default:\n"
-      "  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
+      "  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
       "  break;\n");
   }
   for (int i = 0; i < fields_by_number().size(); i++) {
@@ -683,7 +737,7 @@
     printer->Indent();
     std::unique_ptr<FieldGeneratorBase> generator(
         CreateFieldGeneratorInternal(field));
-    generator->GenerateParsingCode(printer);
+    generator->GenerateParsingCode(printer, use_parse_context);
     printer->Print("break;\n");
     printer->Outdent();
     printer->Print("}\n");
@@ -692,14 +746,11 @@
   printer->Print("}\n"); // switch
   printer->Outdent();
   printer->Print("}\n"); // while
-  printer->Outdent();
-  printer->Print("}\n\n"); // method
 }
 
 // it's a waste of space to track presence for all values, so we only track them if they're not nullable
 int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
-  if (IsNullable(descriptor) || !IsProto2(descriptor->file()) ||
-      descriptor->is_extension()) {
+  if (!RequiresPresenceBit(descriptor)) {
     return -1;
   }
 
@@ -709,7 +760,7 @@
     if (field == descriptor) {
       return index;
     }
-    if (!IsNullable(field)) {
+    if (RequiresPresenceBit(field)) {
       index++;
     }
   }
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index 5642dc8..d02767e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -66,7 +66,9 @@
   bool has_extension_ranges_;
 
   void GenerateMessageSerializationMethods(io::Printer* printer);
+  void GenerateWriteToBody(io::Printer* printer, bool use_write_context);
   void GenerateMergingMethods(io::Printer* printer);
+  void GenerateMainParseLoop(io::Printer* printer, bool use_parse_context);
 
   int GetPresenceIndex(const FieldDescriptor* descriptor);
   FieldGeneratorBase* CreateFieldGeneratorInternal(
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index 4125798..034fbd9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -53,7 +53,7 @@
                                              int presenceIndex,
                                              const Options *options)
     : FieldGeneratorBase(descriptor, presenceIndex, options) {
-  if (!IsProto2(descriptor_->file())) {
+  if (!SupportsPresenceApi(descriptor_)) {
     variables_["has_property_check"] = name() + "_ != null";
     variables_["has_not_property_check"] = name() + "_ == null";
   }
@@ -77,7 +77,7 @@
     "    $name$_ = value;\n"
     "  }\n"
     "}\n");
-  if (IsProto2(descriptor_->file())) {
+  if (SupportsPresenceApi(descriptor_)) {
     printer->Print(
       variables_,
       "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
@@ -228,7 +228,7 @@
     "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
     "  }\n"
     "}\n");
-  if (IsProto2(descriptor_->file())) {
+  if (SupportsPresenceApi(descriptor_)) {
     printer->Print(
       variables_,
       "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
index 2463d91..1436fe2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -51,19 +51,19 @@
   MessageFieldGenerator(const MessageFieldGenerator&) = delete;
   MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
 
-  virtual void GenerateCodecCode(io::Printer* printer);
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateFreezingCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
-  virtual void GenerateExtensionCode(io::Printer* printer);
+  virtual void GenerateCodecCode(io::Printer* printer) override;
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateFreezingCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+  virtual void GenerateExtensionCode(io::Printer* printer) override;
 
-  virtual void WriteHash(io::Printer* printer);
-  virtual void WriteEquals(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
+  virtual void WriteHash(io::Printer* printer) override;
+  virtual void WriteEquals(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
 };
 
 class MessageOneofFieldGenerator : public MessageFieldGenerator {
@@ -77,11 +77,11 @@
   MessageOneofFieldGenerator& operator=(const MessageOneofFieldGenerator&) =
       delete;
 
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h
index 4485272..67e53b6 100644
--- a/src/google/protobuf/compiler/csharp/csharp_names.h
+++ b/src/google/protobuf/compiler/csharp/csharp_names.h
@@ -60,14 +60,14 @@
 //
 // Returns:
 //   The namespace to use for given file descriptor.
-string PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor);
+std::string PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor);
 
 // Requires:
 //   descriptor != NULL
 //
 // Returns:
 //   The fully-qualified C# class name.
-string PROTOC_EXPORT GetClassName(const Descriptor* descriptor);
+std::string PROTOC_EXPORT GetClassName(const Descriptor* descriptor);
 
 // Requires:
 //   descriptor != NULL
@@ -76,7 +76,8 @@
 //   The fully-qualified name of the C# class that provides
 //   access to the file descriptor. Proto compiler generates
 //   such class for each .proto file processed.
-string PROTOC_EXPORT GetReflectionClassName(const FileDescriptor* descriptor);
+std::string PROTOC_EXPORT
+GetReflectionClassName(const FileDescriptor* descriptor);
 
 // Generates output file name for given file descriptor. If generate_directories
 // is true, the output file will be put under directory corresponding to file's
@@ -92,10 +93,11 @@
 //    The file name to use as output file for given file descriptor. In case
 //    of failure, this function will return empty string and error parameter
 //    will contain the error message.
-string PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor,
-                                   const string file_extension,
-                                   const bool generate_directories,
-                                   const string base_namespace, string* error);
+std::string PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor,
+                                        const std::string file_extension,
+                                        const bool generate_directories,
+                                        const std::string base_namespace,
+                                        std::string* error);
 
 }  // namespace csharp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index eb7f70d..9df1dd6 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -53,7 +53,7 @@
   // TODO(jonskeet): Make this cleaner...
   is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
       && descriptor->type() != FieldDescriptor::TYPE_BYTES;
-  if (!is_value_type && !IsProto2(descriptor_->file())) {
+  if (!is_value_type && !SupportsPresenceApi(descriptor_)) {
     variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
     variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
   }
@@ -63,42 +63,65 @@
 }
 
 void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
-  // TODO(jonskeet): Work out whether we want to prevent the fields from ever being
-  // null, or whether we just handle it, in the cases of bytes and string.
-  // (Basically, should null-handling code be in the getter or the setter?)
+  
+  // Note: in multiple places, this code assumes that all fields
+  // that support presence are either nullable, or use a presence field bit.
+  // Fields which are oneof members are not generated here; they're generated in PrimitiveOneofFieldGenerator below.
+  // Extensions are not generated here either.
+
+
+  // Proto2 allows different default values to be specified. These are retained
+  // via static fields. They don't particularly need to be, but we don't need
+  // to change that. In Proto3 the default value we don't generate these
+  // fields, just using the literal instead.
   if (IsProto2(descriptor_->file())) {
+    // Note: "private readonly static" isn't as idiomatic as
+    // "private static readonly", but changing this now would create a lot of
+    // churn in generated code with near-to-zero benefit.
     printer->Print(
       variables_,
       "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n");
+    variables_["default_value_access"] =
+      variables_["property_name"] + "DefaultValue";
+  } else {
+    variables_["default_value_access"] = variables_["default_value"];
   }
 
+  // Declare the field itself.
   printer->Print(
     variables_,
     "private $type_name$ $name_def_message$;\n");
 
   WritePropertyDocComment(printer, descriptor_);
   AddPublicMemberAttributes(printer);
-  if (IsProto2(descriptor_->file())) {
-    if (presenceIndex_ == -1) {
+
+  // Most of the work is done in the property:
+  // Declare the property itself (the same for all options)
+  printer->Print(variables_, "$access_level$ $type_name$ $property_name$ {\n");
+
+  // Specify the "getter", which may need to check for a presence field.
+  if (SupportsPresenceApi(descriptor_)) {
+    if (IsNullable(descriptor_)) {
       printer->Print(
         variables_,
-        "$access_level$ $type_name$ $property_name$ {\n"
-        "  get { return $name$_ ?? $property_name$DefaultValue; }\n"
-        "  set {\n");
+        "  get { return $name$_ ?? $default_value_access$; }\n");
     } else {
       printer->Print(
         variables_,
-        "$access_level$ $type_name$ $property_name$ {\n"
-        "  get { if ($has_field_check$) { return $name$_; } else { return $property_name$DefaultValue; } }\n"
-        "  set {\n");
+        // Note: it's possible that this could be rewritten as a
+        // conditional ?: expression, but there's no significant benefit
+        // to changing it.
+        "  get { if ($has_field_check$) { return $name$_; } else { return $default_value_access$; } }\n");
     }
   } else {
     printer->Print(
       variables_,
-      "$access_level$ $type_name$ $property_name$ {\n"
-      "  get { return $name$_; }\n"
-      "  set {\n");
+      "  get { return $name$_; }\n");
   }
+
+  // Specify the "setter", which may need to set a field bit as well as the
+  // value.
+  printer->Print("  set {\n");
   if (presenceIndex_ != -1) {
     printer->Print(
       variables_,
@@ -116,8 +139,11 @@
   printer->Print(
     "  }\n"
     "}\n");
-  if (IsProto2(descriptor_->file())) {
-    printer->Print(variables_, "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+
+  // The "HasFoo" property, where required.
+  if (SupportsPresenceApi(descriptor_)) {
+    printer->Print(variables_,
+      "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
     AddPublicMemberAttributes(printer);
     printer->Print(
       variables_,
@@ -133,8 +159,11 @@
         "$has_field_check$; }\n}\n");
     }
   }
-  if (IsProto2(descriptor_->file())) {
-    printer->Print(variables_, "/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
+
+  // The "ClearFoo" method, where required.
+  if (SupportsPresenceApi(descriptor_)) {
+    printer->Print(variables_,
+      "/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
     AddPublicMemberAttributes(printer);
     printer->Print(
       variables_,
@@ -270,7 +299,7 @@
     "    $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
     "  }\n"
     "}\n");
-  if (IsProto2(descriptor_->file())) {
+  if (SupportsPresenceApi(descriptor_)) {
     printer->Print(
       variables_,
       "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
index 5edcc42..a2c1105 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -53,18 +53,18 @@
   PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
   PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
 
-  virtual void GenerateCodecCode(io::Printer* printer);
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
-  virtual void GenerateExtensionCode(io::Printer* printer);
+  virtual void GenerateCodecCode(io::Printer* printer) override;
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+  virtual void GenerateExtensionCode(io::Printer* printer) override;
 
-  virtual void WriteHash(io::Printer* printer);
-  virtual void WriteEquals(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
+  virtual void WriteHash(io::Printer* printer) override;
+  virtual void WriteEquals(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
 
  protected:
   bool is_value_type;
@@ -81,11 +81,11 @@
   PrimitiveOneofFieldGenerator& operator=(const PrimitiveOneofFieldGenerator&) =
       delete;
 
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
index 37154e3..644fbf1 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -53,7 +53,7 @@
 
 ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
                                                    const Options* options)
-    : SourceGeneratorBase(file, options),
+    : SourceGeneratorBase(options),
       file_(file) {
   namespace_ = GetFileNamespace(file);
   reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 73309a7..04bc7bb 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -78,15 +78,27 @@
 }
 
 void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  GenerateParsingCode(printer, true);
+}
+
+void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
   printer->Print(
     variables_,
-    "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+    use_parse_context
+    ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
+    : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
 }
 
 void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+    : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
 }
 
 void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
index c7a632a..2e26570 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -54,18 +54,20 @@
   RepeatedEnumFieldGenerator& operator=(const RepeatedEnumFieldGenerator&) =
       delete;
 
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateFreezingCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
-  virtual void GenerateExtensionCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateFreezingCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+  virtual void GenerateExtensionCode(io::Printer* printer) override;
 
-  virtual void WriteHash(io::Printer* printer);
-  virtual void WriteEquals(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
+  virtual void WriteHash(io::Printer* printer) override;
+  virtual void WriteEquals(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index 4b4b37d..8a93cd1 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -93,15 +93,27 @@
 }
 
 void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  GenerateParsingCode(printer, true);
+}
+
+void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
   printer->Print(
     variables_,
-    "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+    use_parse_context
+    ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
+    : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
 }
 
 void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+    : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
 }
 
 void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
index 74f6874..a2267ad 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -54,18 +54,20 @@
   RepeatedMessageFieldGenerator& operator=(
       const RepeatedMessageFieldGenerator&) = delete;
 
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateFreezingCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
-  virtual void GenerateExtensionCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateFreezingCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+  virtual void GenerateExtensionCode(io::Printer* printer) override;
 
-  virtual void WriteHash(io::Printer* printer);
-  virtual void WriteEquals(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
+  virtual void WriteHash(io::Printer* printer) override;
+  virtual void WriteEquals(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index c1444ea..0eacf91 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -78,15 +78,27 @@
 }
 
 void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  GenerateParsingCode(printer, true);
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
   printer->Print(
     variables_,
-    "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+    use_parse_context
+    ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
+    : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+    : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
index 2a3be48..d432f37 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -50,18 +50,20 @@
   RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) = delete;
   RepeatedPrimitiveFieldGenerator& operator=(const RepeatedPrimitiveFieldGenerator&) = delete;
 
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateFreezingCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
-  virtual void GenerateExtensionCode(io::Printer* printer);
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateFreezingCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+  virtual void GenerateExtensionCode(io::Printer* printer) override;
 
-  virtual void WriteHash(io::Printer* printer);
-  virtual void WriteEquals(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
+  virtual void WriteHash(io::Printer* printer) override;
+  virtual void WriteEquals(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
index ee7502f..7157e6e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -46,9 +46,8 @@
 namespace compiler {
 namespace csharp {
 
-SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor,
-                                         const Options *options)
-    : descriptor_(descriptor), options_(options) {
+SourceGeneratorBase::SourceGeneratorBase(
+    const Options *options) : options_(options) {
 }
 
 SourceGeneratorBase::~SourceGeneratorBase() {
@@ -56,6 +55,10 @@
 
 void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
   printer->Print("[global::System.Diagnostics.DebuggerNonUserCodeAttribute]\n");
+  // The second argument of the [GeneratedCode] attribute could be set to current protoc
+  // version, but that would cause excessive code churn in the pre-generated
+  // code in the repository every time the protobuf version number is updated.
+  printer->Print("[global::System.CodeDom.Compiler.GeneratedCode(\"protoc\", null)]\n");
 }
 
 std::string SourceGeneratorBase::class_access_level() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
index 695c422..17a5269 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
@@ -45,7 +45,7 @@
 
 class SourceGeneratorBase {
  protected:
-  SourceGeneratorBase(const FileDescriptor* descriptor, const Options* options);
+  SourceGeneratorBase(const Options* options);
   virtual ~SourceGeneratorBase();
 
   SourceGeneratorBase(const SourceGeneratorBase&) = delete;
@@ -59,7 +59,6 @@
   void WriteGeneratedCodeAttributes(io::Printer* printer);
 
  private:
-  const FileDescriptor* descriptor_;
   const Options *options_;
 };
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index add20ab..578f54b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -81,7 +81,7 @@
     "    $name$_ = value;\n"
     "  }\n"
     "}\n\n");
-  if (IsProto2(descriptor_->file())) {
+  if (SupportsPresenceApi(descriptor_)) {
     printer->Print(
       variables_,
       "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
@@ -114,20 +114,37 @@
 }
 
 void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  GenerateParsingCode(printer, true);
+}
+
+void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
   printer->Print(
     variables_,
-    "$type_name$ value = _single_$name$_codec.Read(input);\n"
-    "if ($has_not_property_check$ || value != $default_value$) {\n"
-    "  $property_name$ = value;\n"
-    "}\n");
+    use_parse_context
+    ? "$type_name$ value = _single_$name$_codec.Read(ref input);\n"
+      "if ($has_not_property_check$ || value != $default_value$) {\n"
+      "  $property_name$ = value;\n"
+      "}\n"
+    : "$type_name$ value = _single_$name$_codec.Read(input);\n"
+      "if ($has_not_property_check$ || value != $default_value$) {\n"
+      "  $property_name$ = value;\n"
+      "}\n");
 }
 
 void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "if ($has_property_check$) {\n"
-    "  _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
-    "}\n");
+    use_write_context
+    ? "if ($has_property_check$) {\n"
+      "  _single_$name$_codec.WriteTagAndValue(ref output, $property_name$);\n"
+      "}\n"
+    : "if ($has_property_check$) {\n"
+      "  _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
+      "}\n");
 }
 
 void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
@@ -219,7 +236,7 @@
     "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
     "  }\n"
     "}\n");
-  if (IsProto2(descriptor_->file())) {
+  if (SupportsPresenceApi(descriptor_)) {
     printer->Print(
       variables_,
       "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
@@ -248,18 +265,32 @@
 }
 
 void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  GenerateParsingCode(printer, true);
+}
+
+void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
   printer->Print(
     variables_,
-    "$property_name$ = _oneof_$name$_codec.Read(input);\n");
+    use_parse_context
+    ? "$property_name$ = _oneof_$name$_codec.Read(ref input);\n"
+    : "$property_name$ = _oneof_$name$_codec.Read(input);\n");
 }
 
 void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   // TODO: I suspect this is wrong...
   printer->Print(
     variables_,
-    "if ($has_property_check$) {\n"
-    "  _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
-    "}\n");
+    use_write_context
+    ? "if ($has_property_check$) {\n"
+      "  _oneof_$name$_codec.WriteTagAndValue(ref output, ($type_name$) $oneof_name$_);\n"
+      "}\n"
+    : "if ($has_property_check$) {\n"
+      "  _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
+      "}\n");
 }
 
 void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
index 394e27d..57c4f5e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -53,18 +53,20 @@
   WrapperFieldGenerator(const WrapperFieldGenerator&) = delete;
   WrapperFieldGenerator& operator=(const WrapperFieldGenerator&) = delete;
 
-  virtual void GenerateCodecCode(io::Printer* printer);
-  virtual void GenerateCloningCode(io::Printer* printer);
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
-  virtual void GenerateExtensionCode(io::Printer* printer);
+  virtual void GenerateCodecCode(io::Printer* printer) override;
+  virtual void GenerateCloningCode(io::Printer* printer) override;
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+  virtual void GenerateExtensionCode(io::Printer* printer) override;
 
-  virtual void WriteHash(io::Printer* printer);
-  virtual void WriteEquals(io::Printer* printer);
-  virtual void WriteToString(io::Printer* printer);
+  virtual void WriteHash(io::Printer* printer) override;
+  virtual void WriteEquals(io::Printer* printer) override;
+  virtual void WriteToString(io::Printer* printer) override;
 
  private:
   bool is_value_type; // True for int32 etc; false for bytes and string
@@ -80,11 +82,13 @@
   WrapperOneofFieldGenerator(const WrapperOneofFieldGenerator&) = delete;
   WrapperOneofFieldGenerator& operator=(const WrapperOneofFieldGenerator&) = delete;
 
-  virtual void GenerateMembers(io::Printer* printer);
-  virtual void GenerateMergingCode(io::Printer* printer);
-  virtual void GenerateParsingCode(io::Printer* printer);
-  virtual void GenerateSerializationCode(io::Printer* printer);
-  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer) override;
+  virtual void GenerateMergingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer) override;
+  virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+  virtual void GenerateSerializationCode(io::Printer* printer) override;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+  virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
 };
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index 3b42d95..d0b3f4c 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -290,11 +290,11 @@
   std::vector<std::string> canonical_parts;
   std::vector<std::string> parts = Split(
       path, "/", true);  // Note:  Removes empty parts.
-  for (int i = 0; i < parts.size(); i++) {
-    if (parts[i] == ".") {
+  for (const std::string& part : parts) {
+    if (part == ".") {
       // Ignore.
     } else {
-      canonical_parts.push_back(parts[i]);
+      canonical_parts.push_back(part);
     }
   }
   std::string result = Join(canonical_parts, "/");
@@ -464,10 +464,10 @@
     return NULL;
   }
 
-  for (int i = 0; i < mappings_.size(); i++) {
+  for (const auto& mapping : mappings_) {
     std::string temp_disk_file;
-    if (ApplyMapping(virtual_file, mappings_[i].virtual_path,
-                     mappings_[i].disk_path, &temp_disk_file)) {
+    if (ApplyMapping(virtual_file, mapping.virtual_path, mapping.disk_path,
+          &temp_disk_file)) {
       io::ZeroCopyInputStream* stream = OpenDiskFile(temp_disk_file);
       if (stream != NULL) {
         if (disk_file != NULL) {
@@ -490,6 +490,22 @@
 
 io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile(
     const std::string& filename) {
+  struct stat sb;
+  int ret = 0;
+  do {
+    ret = stat(filename.c_str(), &sb);
+  } while (ret != 0 && errno == EINTR);
+#if defined(_WIN32)
+  if (ret == 0 && sb.st_mode & S_IFDIR) {
+    last_error_message_ = "Input file is a directory.";
+    return NULL;
+  }
+#else
+  if (ret == 0 && S_ISDIR(sb.st_mode)) {
+    last_error_message_ = "Input file is a directory.";
+    return NULL;
+  }
+#endif
   int file_descriptor;
   do {
     file_descriptor = open(filename.c_str(), O_RDONLY);
diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h
index db4a876..08a49c5 100644
--- a/src/google/protobuf/compiler/importer.h
+++ b/src/google/protobuf/compiler/importer.h
@@ -202,8 +202,8 @@
   virtual void AddError(const std::string& filename, int line, int column,
                         const std::string& message) = 0;
 
-  virtual void AddWarning(const std::string& filename, int line, int column,
-                          const std::string& message) {}
+  virtual void AddWarning(const std::string& /* filename */, int /* line */,
+                          int /* column */, const std::string& /* message */) {}
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector);
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index dc5c692..daa197f 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -463,13 +463,14 @@
             source_tree_.DiskFileToVirtualFile("../../baz", &virtual_file,
                                                &shadowing_disk_file));
 
-  // "/foo" is not mapped (it should not be misintepreted as being under ".").
+  // "/foo" is not mapped (it should not be misinterpreted as being under ".").
   EXPECT_EQ(DiskSourceTree::NO_MAPPING,
             source_tree_.DiskFileToVirtualFile("/foo", &virtual_file,
                                                &shadowing_disk_file));
 
 #ifdef WIN32
-  // "C:\foo" is not mapped (it should not be misintepreted as being under ".").
+  // "C:\foo" is not mapped (it should not be misinterpreted as being under
+  // ".").
   EXPECT_EQ(DiskSourceTree::NO_MAPPING,
             source_tree_.DiskFileToVirtualFile("C:\\foo", &virtual_file,
                                                &shadowing_disk_file));
diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc
index d74a7ed..fea870f 100644
--- a/src/google/protobuf/compiler/java/java_context.cc
+++ b/src/google/protobuf/compiler/java/java_context.cc
@@ -108,6 +108,7 @@
     InitializeFieldGeneratorInfoForMessage(message->nested_type(i));
   }
   std::vector<const FieldDescriptor*> fields;
+  fields.reserve(message->field_count());
   for (int i = 0; i < message->field_count(); ++i) {
     fields.push_back(message->field(i));
   }
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 5454861..51032c2 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -77,9 +77,10 @@
   WriteEnumDocComment(printer, descriptor_);
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_);
   printer->Print(
-      "public enum $classname$\n"
+      "$deprecation$public enum $classname$\n"
       "    implements com.google.protobuf.ProtocolMessageEnum {\n",
-      "classname", descriptor_->name());
+      "classname", descriptor_->name(), "deprecation",
+      descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "");
   printer->Annotate("classname", descriptor_);
   printer->Indent();
 
@@ -142,9 +143,13 @@
     vars["number"] = StrCat(descriptor_->value(i)->number());
     vars["{"] = "";
     vars["}"] = "";
+    vars["deprecation"] = descriptor_->value(i)->options().deprecated()
+                              ? "@java.lang.Deprecated "
+                              : "";
     WriteEnumValueDocComment(printer, descriptor_->value(i));
     printer->Print(vars,
-                   "public static final int ${$$name$_VALUE$}$ = $number$;\n");
+                   "$deprecation$public static final int ${$$name$_VALUE$}$ = "
+                   "$number$;\n");
     printer->Annotate("{", "}", descriptor_->value(i));
   }
   printer->Print("\n");
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 6322ee5..e68eb77 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -32,6 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_enum_field.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -39,7 +42,6 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
-#include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/io/printer.h>
@@ -61,19 +63,25 @@
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->enum_type());
+  (*variables)["kt_type"] = (*variables)["type"];
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->enum_type());
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["default_number"] =
       StrCat(descriptor->default_value_enum()->number());
   (*variables)["tag"] = StrCat(
-      static_cast<int32>(internal::WireFormat::MakeTag(descriptor)));
+      static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   (*variables)["on_changed"] = "onChanged();";
   // Use deprecated valueOf() method to be compatible with old generated code
   // for v2.5.0/v2.6.1.
@@ -81,7 +89,7 @@
   // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
   (*variables)["for_number"] = "valueOf";
 
-  if (SupportFieldPresence(descriptor)) {
+  if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
@@ -145,7 +153,7 @@
 ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
 
 int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
-  return SupportFieldPresence(descriptor_) ? 1 : 0;
+  return HasHasbit(descriptor_) ? 1 : 0;
 }
 
 int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
@@ -154,7 +162,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -171,7 +179,7 @@
 void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "@java.lang.Override $deprecation$public boolean "
@@ -203,7 +211,7 @@
 void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_ = $default_number$;\n");
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "@java.lang.Override $deprecation$public boolean "
@@ -225,6 +233,7 @@
     printer->Print(variables_,
                    "$deprecation$public Builder "
                    "${$set$capitalized_name$Value$}$(int value) {\n"
+                   "  $set_has_field_bit_builder$\n"
                    "  $name$_ = value;\n"
                    "  $on_changed$\n"
                    "  return this;\n"
@@ -267,6 +276,34 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: $kt_type$\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  if (HasHazzer(descriptor_)) {
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    printer->Print(variables_,
+                   "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                   "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                   "}\n");
+  }
+}
+
 void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode(
     io::Printer* printer) const {
   // noop for enums
@@ -286,7 +323,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if (other.has$capitalized_name$()) {\n"
                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
@@ -304,7 +341,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if ($get_has_field_bit_from_local$) {\n"
                    "  $set_has_field_bit_to_local$;\n"
@@ -388,15 +425,14 @@
 void ImmutableEnumOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -425,16 +461,15 @@
 
 void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -711,7 +746,7 @@
       // list is immutable. If it's immutable, the invariant is that it must
       // either an instance of Collections.emptyList() or it's an ArrayList
       // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
-      // a refererence to the underlying ArrayList. This invariant allows us to
+      // a reference to the underlying ArrayList. This invariant allows us to
       // share instances of lists between protocol buffers avoiding expensive
       // memory allocations. Note, immutable is a strong guarantee here -- not
       // just that the list cannot be modified via the reference but that the
@@ -1036,6 +1071,98 @@
                  "}\n");
 }
 
+void RepeatedImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$ val $kt_name$: "
+                 "com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+                 "  @kotlin.jvm.JvmSynthetic\n"
+                 "  get() = com.google.protobuf.kotlin.DslList(\n"
+                 "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+                 "  )\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: $kt_type$) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "inline operator fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: $kt_type$) {\n"
+                 "  add(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+                 "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+      "  addAll(values)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: $kt_type$) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
 }
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index 95c7db5..82dbd9e 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -60,28 +60,30 @@
   explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
                                        int messageBitIndex, int builderBitIndex,
                                        Context* context);
-  ~ImmutableEnumFieldGenerator();
+  ~ImmutableEnumFieldGenerator() override;
 
   // implements ImmutableFieldGenerator
   // ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(
+      io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -99,15 +101,15 @@
                                    Context* context);
   ~ImmutableEnumOneofFieldGenerator();
 
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator);
@@ -118,28 +120,30 @@
   explicit RepeatedImmutableEnumFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
-  ~RepeatedImmutableEnumFieldGenerator();
+  ~RepeatedImmutableEnumFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(
+      io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index 7966931..dd442fe 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -32,6 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_enum_field_lite.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -39,7 +42,6 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
-#include <google/protobuf/compiler/java/java_enum_field_lite.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/io/printer.h>
@@ -68,22 +70,28 @@
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->enum_type());
+  (*variables)["kt_type"] = (*variables)["type"];
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->enum_type());
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["default_number"] =
       StrCat(descriptor->default_value_enum()->number());
   (*variables)["tag"] = StrCat(
-      static_cast<int32>(internal::WireFormat::MakeTag(descriptor)));
+      static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
-  if (SupportFieldPresence(descriptor)) {
+  if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
 
@@ -103,9 +111,6 @@
         ".getNumber()";
   }
 
-  // For repeated builders, the underlying list tracks mutability state.
-  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
-
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -140,12 +145,12 @@
 ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
 
 int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
-  return SupportFieldPresence(descriptor_) ? 1 : 0;
+  return HasHasbit(descriptor_) ? 1 : 0;
 }
 
 void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -163,7 +168,7 @@
     io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -217,7 +222,7 @@
 
 void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -276,6 +281,34 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: $kt_type$\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  if (HasHazzer(descriptor_)) {
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    printer->Print(variables_,
+                   "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                   "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                   "}\n");
+  }
+}
+
 void ImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
     io::Printer* printer) const {
   if (!IsDefaultValueJavaDefault(descriptor_)) {
@@ -284,7 +317,7 @@
 }
 
 void ImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -319,16 +352,15 @@
 void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -381,7 +413,7 @@
 }
 
 void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -396,16 +428,15 @@
 
 void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -572,9 +603,11 @@
   printer->Print(
       variables_,
       "private void ensure$capitalized_name$IsMutable() {\n"
-      "  if (!$is_mutable$) {\n"
+      // Use a temporary to avoid a redundant iget-object.
+      "  com.google.protobuf.Internal.IntList tmp = $name$_;\n"
+      "  if (!tmp.isModifiable()) {\n"
       "    $name$_ =\n"
-      "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+      "        com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
       "  }\n"
       "}\n");
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER);
@@ -635,7 +668,7 @@
 }
 
 void RepeatedImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -775,6 +808,98 @@
   printer->Print(variables_, "$name$_ = emptyIntList();\n");
 }
 
+void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$ val $kt_name$: "
+                 "com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+                 "  @kotlin.jvm.JvmSynthetic\n"
+                 "  get() = com.google.protobuf.kotlin.DslList(\n"
+                 "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+                 "  )\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: $kt_type$) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "inline operator fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: $kt_type$) {\n"
+                 "  add(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+                 "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+      "  addAll(values)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: $kt_type$) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 std::string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
 }
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h
index b5e9807..6ed11c9 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h
@@ -35,8 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -60,19 +62,20 @@
   explicit ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
                                            int messageBitIndex,
                                            Context* context);
-  ~ImmutableEnumFieldLiteGenerator();
+  ~ImmutableEnumFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
   // ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -90,12 +93,12 @@
  public:
   ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
                                        int messageBitIndex, Context* context);
-  ~ImmutableEnumOneofFieldLiteGenerator();
+  ~ImmutableEnumOneofFieldLiteGenerator() override;
 
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
@@ -106,18 +109,19 @@
  public:
   explicit RepeatedImmutableEnumFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
-  ~RepeatedImmutableEnumFieldLiteGenerator();
+  ~RepeatedImmutableEnumFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
index 69bd26c..aa64c97 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -78,9 +78,10 @@
   WriteEnumDocComment(printer, descriptor_);
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_);
   printer->Print(
-      "public enum $classname$\n"
+      "$deprecation$public enum $classname$\n"
       "    implements com.google.protobuf.Internal.EnumLite {\n",
-      "classname", descriptor_->name());
+      "classname", descriptor_->name(), "deprecation",
+      descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "");
   printer->Annotate("classname", descriptor_);
   printer->Indent();
 
@@ -124,9 +125,13 @@
     vars["number"] = StrCat(descriptor_->value(i)->number());
     vars["{"] = "";
     vars["}"] = "";
+    vars["deprecation"] = descriptor_->value(i)->options().deprecated()
+                              ? "@java.lang.Deprecated "
+                              : "";
     WriteEnumValueDocComment(printer, descriptor_->value(i));
     printer->Print(vars,
-                   "public static final int ${$$name$_VALUE$}$ = $number$;\n");
+                   "$deprecation$public static final int ${$$name$_VALUE$}$ = "
+                   "$number$;\n");
     printer->Annotate("{", "}", descriptor_->value(i));
   }
   printer->Print("\n");
diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h
index ab87890..164edfb 100644
--- a/src/google/protobuf/compiler/java/java_extension.h
+++ b/src/google/protobuf/compiler/java/java_extension.h
@@ -94,9 +94,9 @@
                                        Context* context);
   virtual ~ImmutableExtensionGenerator();
 
-  virtual void Generate(io::Printer* printer);
-  virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
-  virtual int GenerateRegistrationCode(io::Printer* printer);
+  virtual void Generate(io::Printer* printer) override;
+  virtual int GenerateNonNestedInitializationCode(io::Printer* printer) override;
+  virtual int GenerateRegistrationCode(io::Printer* printer) override;
 
  protected:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h
index 410781d..beda4f9 100644
--- a/src/google/protobuf/compiler/java/java_extension_lite.h
+++ b/src/google/protobuf/compiler/java/java_extension_lite.h
@@ -51,13 +51,14 @@
                                            Context* context);
   virtual ~ImmutableExtensionLiteGenerator();
 
-  virtual void Generate(io::Printer* printer);
+  virtual void Generate(io::Printer* printer) override;
 
   // Returns an estimate of the number of bytes the printed code will compile to
-  virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+  virtual int GenerateNonNestedInitializationCode(
+      io::Printer* printer) override;
 
   // Returns an estimate of the number of bytes the printed code will compile to
-  virtual int GenerateRegistrationCode(io::Printer* printer);
+  virtual int GenerateRegistrationCode(io::Printer* printer) override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index f6b9635..8916d13 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -251,12 +251,32 @@
   (*variables)["disambiguated_reason"] = info->disambiguated_reason;
   (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = StrCat(descriptor->number());
+  (*variables)["kt_dsl_builder"] = "_builder";
   // These variables are placeholders to pick out the beginning and ends of
   // identifiers for annotations (when doing so with existing variables would
   // be ambiguous or impossible). They should never be set to anything but the
   // empty string.
   (*variables)["{"] = "";
   (*variables)["}"] = "";
+  (*variables)["kt_name"] =
+      IsForbiddenKotlin(info->name) ? info->name + "_" : info->name;
+  (*variables)["kt_capitalized_name"] = IsForbiddenKotlin(info->name)
+                                            ? info->capitalized_name + "_"
+                                            : info->capitalized_name;
+  if (!descriptor->is_repeated()) {
+    (*variables)["annotation_field_type"] = FieldTypeName(descriptor->type());
+  } else if (GetJavaType(descriptor) == JAVATYPE_MESSAGE &&
+             IsMapEntry(descriptor->message_type())) {
+    (*variables)["annotation_field_type"] =
+        std::string(FieldTypeName(descriptor->type())) + "MAP";
+  } else {
+    (*variables)["annotation_field_type"] =
+        std::string(FieldTypeName(descriptor->type())) + "_LIST";
+    if (descriptor->is_packed()) {
+      (*variables)["annotation_field_type"] =
+          (*variables)["annotation_field_type"] + "_PACKED";
+    }
+  }
 }
 
 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index 9d04dc8..a7c995c 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -35,6 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <string>
@@ -83,6 +84,7 @@
   virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
   virtual void GenerateFieldBuilderInitializationCode(
       io::Printer* printer) const = 0;
+  virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
 
   virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
   virtual void GenerateHashCode(io::Printer* printer) const = 0;
@@ -104,7 +106,8 @@
   virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
   virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
   virtual void GenerateFieldInfo(io::Printer* printer,
-                                 std::vector<uint16>* output) const = 0;
+                                 std::vector<uint16_t>* output) const = 0;
+  virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
 
   virtual std::string GetBoxedType() const = 0;
 
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 2fc7aad..9dbf818 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -76,7 +76,6 @@
 typedef std::set<const FieldDescriptor*, FieldDescriptorCompare>
     FieldDescriptorSet;
 
-
 // Recursively searches the given message to collect extensions.
 // Returns true if all the extensions can be recognized. The extensions will be
 // appended in to the extensions parameter.
@@ -86,9 +85,7 @@
   const Reflection* reflection = message.GetReflection();
 
   // There are unknown fields that could be extensions, thus this call fails.
-  UnknownFieldSet unknown_fields;
-  unknown_fields.MergeFrom(reflection->GetUnknownFields(message));
-  if (unknown_fields.field_count() > 0) return false;
+  if (reflection->GetUnknownFields(message).field_count() > 0) return false;
 
   std::vector<const FieldDescriptor*> fields;
   reflection->ListFields(message, &fields);
@@ -678,6 +675,54 @@
   }
 }
 
+std::string FileGenerator::GetKotlinClassname() {
+  return name_resolver_->GetFileClassName(file_, immutable_api_, true);
+}
+
+void FileGenerator::GenerateKotlinSiblings(
+    const std::string& package_dir, GeneratorContext* context,
+    std::vector<std::string>* file_list,
+    std::vector<std::string>* annotation_list) {
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    const Descriptor* descriptor = file_->message_type(i);
+    MessageGenerator* generator = message_generators_[i].get();
+    auto open_file = [context](const std::string& filename) {
+      return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
+    };
+    std::string filename = package_dir + descriptor->name() + "Kt.kt";
+    file_list->push_back(filename);
+    std::string info_full_path = filename + ".pb.meta";
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    auto output = open_file(filename);
+    io::Printer printer(
+        output.get(), '$',
+        options_.annotate_code ? &annotation_collector : nullptr);
+
+    printer.Print(
+        "//Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+        "// source: $filename$\n"
+        "\n",
+        "filename", descriptor->file()->name());
+    if (!java_package_.empty()) {
+      printer.Print(
+          "package $package$;\n"
+          "\n",
+          "package", java_package_);
+    }
+
+    generator->GenerateKotlinMembers(&printer);
+    generator->GenerateTopLevelKotlinMembers(&printer);
+
+    if (options_.annotate_code) {
+      auto info_output = open_file(info_full_path);
+      annotations.SerializeToZeroCopyStream(info_output.get());
+      annotation_list->push_back(info_full_path);
+    }
+  }
+}
+
 bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor,
                                             bool immutable_api) {
   return true;
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index bb3e4a5..71ee3e8 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -78,6 +78,12 @@
 
   void Generate(io::Printer* printer);
 
+  std::string GetKotlinClassname();
+  void GenerateKotlinSiblings(const std::string& package_dir,
+                              GeneratorContext* generator_context,
+                              std::vector<std::string>* file_list,
+                              std::vector<std::string>* annotation_list);
+
   // If we aren't putting everything into one file, this will write all the
   // files other than the outer file (i.e. one for each message, enum, and
   // service type).
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 11b04b8..29ae2cf 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -58,7 +58,7 @@
 JavaGenerator::JavaGenerator() {}
 JavaGenerator::~JavaGenerator() {}
 
-uint64 JavaGenerator::GetSupportedFeatures() const {
+uint64_t JavaGenerator::GetSupportedFeatures() const {
   return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
 }
 
diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h
index a4e1708..6315e7c 100644
--- a/src/google/protobuf/compiler/java/java_generator.h
+++ b/src/google/protobuf/compiler/java/java_generator.h
@@ -60,7 +60,7 @@
   bool Generate(const FileDescriptor* file, const std::string& parameter,
                 GeneratorContext* context, std::string* error) const override;
 
-  uint64 GetSupportedFeatures() const override;
+  uint64_t GetSupportedFeatures() const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator);
diff --git a/src/google/protobuf/compiler/java/java_generator_factory.h b/src/google/protobuf/compiler/java/java_generator_factory.h
index 16688a5..e64a45d 100644
--- a/src/google/protobuf/compiler/java/java_generator_factory.h
+++ b/src/google/protobuf/compiler/java/java_generator_factory.h
@@ -81,13 +81,13 @@
   virtual ~ImmutableGeneratorFactory();
 
   virtual MessageGenerator* NewMessageGenerator(
-      const Descriptor* descriptor) const;
+      const Descriptor* descriptor) const override;
 
   virtual ExtensionGenerator* NewExtensionGenerator(
-      const FieldDescriptor* descriptor) const;
+      const FieldDescriptor* descriptor) const override;
 
   virtual ServiceGenerator* NewServiceGenerator(
-      const ServiceDescriptor* descriptor) const;
+      const ServiceDescriptor* descriptor) const override;
 
  private:
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index a04ff62..f37ecde 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -35,12 +35,14 @@
 #include <google/protobuf/compiler/java/java_helpers.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <limits>
 #include <unordered_set>
 #include <vector>
 
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -75,8 +77,8 @@
     "class",
 };
 
-const std::unordered_set<string>* kReservedNames =
-    new std::unordered_set<string>({
+const std::unordered_set<std::string>* kReservedNames =
+    new std::unordered_set<std::string>({
         "abstract",   "assert",       "boolean",   "break",      "byte",
         "case",       "catch",        "char",      "class",      "const",
         "continue",   "default",      "do",        "double",     "else",
@@ -191,6 +193,38 @@
   return result;
 }
 
+std::string ToCamelCase(const std::string& input, bool lower_first) {
+  bool capitalize_next = !lower_first;
+  std::string result;
+  result.reserve(input.size());
+
+  for (char i : input) {
+    if (i == '_') {
+      capitalize_next = true;
+    } else if (capitalize_next) {
+      result.push_back(ToUpperCh(i));
+      capitalize_next = false;
+    } else {
+      result.push_back(i);
+    }
+  }
+
+  // Lower-case the first letter.
+  if (lower_first && !result.empty()) {
+    result[0] = ToLowerCh(result[0]);
+  }
+
+  return result;
+}
+
+char ToUpperCh(char ch) {
+  return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch;
+}
+
+char ToLowerCh(char ch) {
+  return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
+}
+
 std::string UnderscoresToCamelCase(const FieldDescriptor* field) {
   return UnderscoresToCamelCase(FieldName(field), false);
 }
@@ -215,6 +249,22 @@
   return name;
 }
 
+bool IsForbiddenKotlin(const std::string& field_name) {
+  // Names that should be avoided as field names in Kotlin.
+  // All Kotlin hard keywords are in this list.
+  const std::unordered_set<std::string>* kKotlinForbiddenNames =
+      new std::unordered_set<std::string>({
+          "as",      "as?",       "break",  "class", "continue", "do",
+          "else",    "false",     "for",    "fun",   "if",       "in",
+          "!in",     "interface", "is",     "!is",   "null",     "object",
+          "package", "return",    "super",  "this",  "throw",    "true",
+          "try",     "typealias", "typeof", "val",   "var",      "when",
+          "while",
+      });
+  return kKotlinForbiddenNames->find(field_name) !=
+         kKotlinForbiddenNames->end();
+}
+
 std::string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
   return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
 }
@@ -227,14 +277,6 @@
   return fieldName;
 }
 
-std::string StripProto(const std::string& filename) {
-  if (HasSuffixString(filename, ".protodevel")) {
-    return StripSuffixString(filename, ".protodevel");
-  } else {
-    return StripSuffixString(filename, ".proto");
-  }
-}
-
 std::string FileClassName(const FileDescriptor* file, bool immutable) {
   ClassNameResolver name_resolver;
   return name_resolver.GetFileClassName(file, immutable);
@@ -308,7 +350,7 @@
 
 std::string FieldConstantName(const FieldDescriptor* field) {
   std::string name = field->name() + "_FIELD_NUMBER";
-  UpperString(&name);
+  ToUpper(&name);
   return name;
 }
 
@@ -428,6 +470,35 @@
   return BoxedPrimitiveTypeName(GetJavaType(descriptor));
 }
 
+const char* KotlinTypeName(JavaType type) {
+  switch (type) {
+    case JAVATYPE_INT:
+      return "kotlin.Int";
+    case JAVATYPE_LONG:
+      return "kotlin.Long";
+    case JAVATYPE_FLOAT:
+      return "kotlin.Float";
+    case JAVATYPE_DOUBLE:
+      return "kotlin.Double";
+    case JAVATYPE_BOOLEAN:
+      return "kotlin.Boolean";
+    case JAVATYPE_STRING:
+      return "kotlin.String";
+    case JAVATYPE_BYTES:
+      return "com.google.protobuf.ByteString";
+    case JAVATYPE_ENUM:
+      return NULL;
+    case JAVATYPE_MESSAGE:
+      return NULL;
+
+      // No default because we want the compiler to complain if any new
+      // JavaTypes are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return NULL;
+}
+
 std::string GetOneofStoredType(const FieldDescriptor* field) {
   const JavaType javaType = GetJavaType(field);
   switch (javaType) {
@@ -505,11 +576,11 @@
       return StrCat(field->default_value_int32());
     case FieldDescriptor::CPPTYPE_UINT32:
       // Need to print as a signed int since Java has no unsigned.
-      return StrCat(static_cast<int32>(field->default_value_uint32()));
+      return StrCat(static_cast<int32_t>(field->default_value_uint32()));
     case FieldDescriptor::CPPTYPE_INT64:
       return StrCat(field->default_value_int64()) + "L";
     case FieldDescriptor::CPPTYPE_UINT64:
-      return StrCat(static_cast<int64>(field->default_value_uint64())) +
+      return StrCat(static_cast<int64_t>(field->default_value_uint64())) +
              "L";
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field->default_value_double();
@@ -901,11 +972,11 @@
 //
 // Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF].
 // There will be no surrogate pairs in the encoded character sequence.
-void WriteUInt32ToUtf16CharSequence(uint32 number,
-                                    std::vector<uint16>* output) {
+void WriteUInt32ToUtf16CharSequence(uint32_t number,
+                                    std::vector<uint16_t>* output) {
   // For values in [0x0000, 0xD7FF], only use one char to encode it.
   if (number < 0xD800) {
-    output->push_back(static_cast<uint16>(number));
+    output->push_back(static_cast<uint16_t>(number));
     return;
   }
   // Encode into multiple chars. All except the last char will be in the range
@@ -915,10 +986,10 @@
   // them.
   while (number >= 0xD800) {
     // [0xE000, 0xFFFF] can represent 13 bits of info.
-    output->push_back(static_cast<uint16>(0xE000 | (number & 0x1FFF)));
+    output->push_back(static_cast<uint16_t>(0xE000 | (number & 0x1FFF)));
     number >>= 13;
   }
-  output->push_back(static_cast<uint16>(number));
+  output->push_back(static_cast<uint16_t>(number));
 }
 
 int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) {
@@ -999,7 +1070,7 @@
 }
 
 // Escape a UTF-16 character to be embedded in a Java string.
-void EscapeUtf16ToString(uint16 code, std::string* output) {
+void EscapeUtf16ToString(uint16_t code, std::string* output) {
   if (code == '\t') {
     output->append("\\t");
   } else if (code == '\b') {
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index e44ad15..5dc25d6 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -35,7 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 
+#include <cstdint>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
@@ -51,6 +53,8 @@
 extern const char kThickSeparator[];
 extern const char kThinSeparator[];
 
+bool IsForbiddenKotlin(const std::string& field_name);
+
 // If annotation_file is non-empty, prints a javax.annotation.Generated
 // annotation to the given Printer. annotation_file will be referenced in the
 // annotation's comments field. delimiter should be the Printer's delimiter
@@ -72,6 +76,13 @@
 
 // Converts a name to camel-case. If cap_first_letter is true, capitalize the
 // first letter.
+std::string ToCamelCase(const std::string& input, bool lower_first);
+
+char ToUpperCh(char ch);
+char ToLowerCh(char ch);
+
+// Converts a name to camel-case. If cap_first_letter is true, capitalize the
+// first letter.
 std::string UnderscoresToCamelCase(const std::string& name,
                                    bool cap_first_letter);
 // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
@@ -95,9 +106,6 @@
 // outermost file scope.
 std::string UniqueFileScopeIdentifier(const Descriptor* descriptor);
 
-// Strips ".proto" or ".protodevel" from the end of a filename.
-std::string StripProto(const std::string& filename);
-
 // Gets the unqualified class name for the file.  For each .proto file, there
 // will be one Java class containing all the immutable messages and another
 // Java class containing all the mutable messages.
@@ -105,21 +113,11 @@
 std::string FileClassName(const FileDescriptor* file, bool immutable = true);
 
 // Returns the file's Java package name.
-std::string FileJavaPackage(const FileDescriptor* file);
 std::string FileJavaPackage(const FileDescriptor* file, bool immutable);
 
 // Returns output directory for the given package name.
 std::string JavaPackageToDir(std::string package_name);
 
-// TODO(xiaofeng): the following methods are kept for they are exposed
-// publicly in //net/proto2/compiler/java/public/names.h. They return
-// immutable names only and should be removed after mutable API is
-// integrated into google3.
-std::string ClassName(const Descriptor* descriptor);
-std::string ClassName(const EnumDescriptor* descriptor);
-std::string ClassName(const ServiceDescriptor* descriptor);
-std::string ClassName(const FileDescriptor* descriptor);
-
 // Comma-separate list of option-specified interfaces implemented by the
 // Message, to follow the "implements" declaration of the Message definition.
 std::string ExtraMessageInterfaces(const Descriptor* descriptor);
@@ -157,6 +155,7 @@
 // Whether we should generate multiple java files for messages.
 inline bool MultipleJavaFiles(const FileDescriptor* descriptor,
                               bool immutable) {
+  (void) immutable;
   return descriptor->options().java_multiple_files();
 }
 
@@ -226,6 +225,10 @@
 // types.
 const char* BoxedPrimitiveTypeName(JavaType type);
 
+// Kotlin source does not distinguish between primitives and non-primitives,
+// but does use Kotlin-specific qualified types for them.
+const char* KotlinTypeName(JavaType type);
+
 // Get the name of the java enum constant representing this type. E.g.,
 // "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full
 // name is "com.google.protobuf.WireFormat.FieldType.INT32".
@@ -242,15 +245,15 @@
 bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field);
 
 // Does this message class have descriptor and reflection methods?
-inline bool HasDescriptorMethods(const Descriptor* descriptor,
+inline bool HasDescriptorMethods(const Descriptor* /* descriptor */,
                                  bool enforce_lite) {
   return !enforce_lite;
 }
-inline bool HasDescriptorMethods(const EnumDescriptor* descriptor,
+inline bool HasDescriptorMethods(const EnumDescriptor* /* descriptor */,
                                  bool enforce_lite) {
   return !enforce_lite;
 }
-inline bool HasDescriptorMethods(const FileDescriptor* descriptor,
+inline bool HasDescriptorMethods(const FileDescriptor* /* descriptor */,
                                  bool enforce_lite) {
   return !enforce_lite;
 }
@@ -358,24 +361,22 @@
   return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }
 
-inline bool SupportFieldPresence(const FieldDescriptor* descriptor) {
-  // Note that while proto3 oneofs do conceptually support present, we return
-  // false for them because they do not offer a public hazzer. Therefore this
-  // method could be named HasHazzer().
-  return !descriptor->is_repeated() &&
-         (descriptor->message_type() || descriptor->has_optional_keyword() ||
-          IsProto2(descriptor->file()));
-}
-
 inline bool IsRealOneof(const FieldDescriptor* descriptor) {
   return descriptor->containing_oneof() &&
          !descriptor->containing_oneof()->is_synthetic();
 }
 
+inline bool HasHazzer(const FieldDescriptor* descriptor) {
+  return !descriptor->is_repeated() &&
+         (descriptor->message_type() || descriptor->has_optional_keyword() ||
+          IsProto2(descriptor->file()) || IsRealOneof(descriptor));
+}
+
 inline bool HasHasbit(const FieldDescriptor* descriptor) {
   // Note that currently message fields inside oneofs have hasbits. This is
   // surprising, as the oneof case should avoid any need for a hasbit. But if
   // you change this method to remove hasbits for oneofs, a few tests fail.
+  // TODO(b/124347790): remove hasbits for oneofs
   return !descriptor->is_repeated() &&
          (descriptor->has_optional_keyword() || IsProto2(descriptor->file()));
 }
@@ -425,15 +426,16 @@
   return "V3";
 }
 
-void WriteUInt32ToUtf16CharSequence(uint32 number, std::vector<uint16>* output);
+void WriteUInt32ToUtf16CharSequence(uint32_t number,
+                                    std::vector<uint16_t>* output);
 
 inline void WriteIntToUtf16CharSequence(int value,
-                                        std::vector<uint16>* output) {
-  WriteUInt32ToUtf16CharSequence(static_cast<uint32>(value), output);
+                                        std::vector<uint16_t>* output) {
+  WriteUInt32ToUtf16CharSequence(static_cast<uint32_t>(value), output);
 }
 
 // Escape a UTF-16 character so it can be embedded in a Java string literal.
-void EscapeUtf16ToString(uint16 code, std::string* output);
+void EscapeUtf16ToString(uint16_t code, std::string* output);
 
 // Only the lowest two bytes of the return value are used. The lowest byte
 // is the integer value of a j/c/g/protobuf/FieldType enum. For the other
diff --git a/src/google/protobuf/compiler/java/java_kotlin_generator.cc b/src/google/protobuf/compiler/java/java_kotlin_generator.cc
new file mode 100644
index 0000000..8d262a0
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_kotlin_generator.cc
@@ -0,0 +1,162 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/java/java_kotlin_generator.h>
+
+#include <google/protobuf/compiler/java/java_file.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_options.h>
+#include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+KotlinGenerator::KotlinGenerator() {}
+KotlinGenerator::~KotlinGenerator() {}
+
+uint64_t KotlinGenerator::GetSupportedFeatures() const {
+  return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
+}
+
+bool KotlinGenerator::Generate(const FileDescriptor* file,
+                               const std::string& parameter,
+                               GeneratorContext* context,
+                               std::string* error) const {
+  // -----------------------------------------------------------------
+  // parse generator options
+
+  std::vector<std::pair<std::string, std::string> > options;
+  ParseGeneratorParameter(parameter, &options);
+  Options file_options;
+
+  for (auto& option : options) {
+    if (option.first == "output_list_file") {
+      file_options.output_list_file = option.second;
+    } else if (option.first == "immutable") {
+      file_options.generate_immutable_code = true;
+    } else if (option.first == "mutable") {
+      *error = "Mutable not supported by Kotlin generator";
+      return false;
+    } else if (option.first == "shared") {
+      file_options.generate_shared_code = true;
+    } else if (option.first == "lite") {
+      file_options.enforce_lite = true;
+    } else if (option.first == "annotate_code") {
+      file_options.annotate_code = true;
+    } else if (option.first == "annotation_list_file") {
+      file_options.annotation_list_file = option.second;
+    } else {
+      *error = "Unknown generator option: " + option.first;
+      return false;
+    }
+  }
+
+  // By default we generate immutable code and shared code for immutable API.
+  if (!file_options.generate_immutable_code &&
+      !file_options.generate_shared_code) {
+    file_options.generate_immutable_code = true;
+    file_options.generate_shared_code = true;
+  }
+
+  std::vector<std::string> all_files;
+  std::vector<std::string> all_annotations;
+
+  std::unique_ptr<FileGenerator> file_generator;
+  if (file_options.generate_immutable_code) {
+    file_generator.reset(
+        new FileGenerator(file, file_options, /* immutable_api = */ true));
+  }
+
+  if (!file_generator->Validate(error)) {
+    return false;
+  }
+
+  auto open_file = [context](const std::string& filename) {
+    return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
+  };
+  std::string package_dir = JavaPackageToDir(file_generator->java_package());
+  std::string kotlin_filename = package_dir;
+  kotlin_filename += file_generator->GetKotlinClassname();
+  kotlin_filename += ".kt";
+  all_files.push_back(kotlin_filename);
+  std::string info_full_path = kotlin_filename + ".pb.meta";
+  if (file_options.annotate_code) {
+    all_annotations.push_back(info_full_path);
+  }
+
+  // Generate main kotlin file.
+  auto output = open_file(kotlin_filename);
+  GeneratedCodeInfo annotations;
+  io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+      &annotations);
+  io::Printer printer(
+      output.get(), '$',
+      file_options.annotate_code ? &annotation_collector : nullptr);
+
+  file_generator->GenerateKotlinSiblings(package_dir, context, &all_files,
+                                         &all_annotations);
+
+  if (file_options.annotate_code) {
+    auto info_output = open_file(info_full_path);
+    annotations.SerializeToZeroCopyStream(info_output.get());
+  }
+
+  // Generate output list if requested.
+  if (!file_options.output_list_file.empty()) {
+    // Generate output list.  This is just a simple text file placed in a
+    // deterministic location which lists the .kt files being generated.
+    auto srclist_raw_output = open_file(file_options.output_list_file);
+    io::Printer srclist_printer(srclist_raw_output.get(), '$');
+    for (auto& all_file : all_files) {
+      srclist_printer.Print("$filename$\n", "filename", all_file);
+    }
+  }
+
+  if (!file_options.annotation_list_file.empty()) {
+    // Generate output list.  This is just a simple text file placed in a
+    // deterministic location which lists the .kt files being generated.
+    auto annotation_list_raw_output =
+        open_file(file_options.annotation_list_file);
+    io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$');
+    for (auto& all_annotation : all_annotations) {
+      annotation_list_printer.Print("$filename$\n", "filename", all_annotation);
+    }
+  }
+
+  return true;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_kotlin_generator.h b/src/google/protobuf/compiler/java/java_kotlin_generator.h
new file mode 100644
index 0000000..66e32b9
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_kotlin_generator.h
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Generates Kotlin code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// CodeGenerator implementation which generates Kotlin code.  If you create your
+// own protocol compiler binary and you want it to support Kotlin output, you
+// can do so by registering an instance of this CodeGenerator with the
+// CommandLineInterface in your main() function.
+class PROTOC_EXPORT KotlinGenerator : public CodeGenerator {
+ public:
+  KotlinGenerator();
+  ~KotlinGenerator() override;
+
+  // implements CodeGenerator ----------------------------------------
+  bool Generate(const FileDescriptor* file, const std::string& parameter,
+                GeneratorContext* context, std::string* error) const override;
+
+  uint64_t GetSupportedFeatures() const override;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(KotlinGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 5db199d..a4ec2ff 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -69,6 +69,17 @@
   }
 }
 
+std::string KotlinTypeName(const FieldDescriptor* field,
+                           ClassNameResolver* name_resolver) {
+  if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+    return name_resolver->GetImmutableClassName(field->message_type());
+  } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+    return name_resolver->GetImmutableClassName(field->enum_type());
+  } else {
+    return KotlinTypeName(GetJavaType(field));
+  }
+}
+
 std::string WireType(const FieldDescriptor* field) {
   return "com.google.protobuf.WireFormat.FieldType." +
          std::string(FieldTypeName(field->type()));
@@ -91,6 +102,8 @@
   (*variables)["key_type"] = TypeName(key, name_resolver, false);
   std::string boxed_key_type = TypeName(key, name_resolver, true);
   (*variables)["boxed_key_type"] = boxed_key_type;
+  (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
+  (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
   // Used for calling the serialization function.
   (*variables)["short_key_type"] =
       boxed_key_type.substr(boxed_key_type.rfind('.') + 1);
@@ -136,6 +149,11 @@
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   (*variables)["on_changed"] = "onChanged();";
 
   // For repeated fields, one bit is used for whether the array is immutable
@@ -651,6 +669,87 @@
   }
 }
 
+void ImmutableMapFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$kt_deprecation$ val $kt_name$: "
+      "com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  @kotlin.jvm.JvmSynthetic\n"
+      "  @JvmName(\"get$kt_capitalized_name$Map\")\n"
+      "  get() = com.google.protobuf.kotlin.DslMap(\n"
+      "    $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
+      "  )\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@JvmName(\"put$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
+      "     $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"set$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
+      "     put(key, value)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"remove$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .remove(key: $kt_key_type$) {\n"
+      "     $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"putAll$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
+      "{\n"
+      "     $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"clear$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .clear() {\n"
+      "     $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+      "   }\n");
+}
+
 void ImmutableMapFieldGenerator::GenerateFieldBuilderInitializationCode(
     io::Printer* printer) const {
   // Nothing to initialize.
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
index 2ff1f76..98d9249 100644
--- a/src/google/protobuf/compiler/java/java_map_field.h
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -43,27 +43,29 @@
   explicit ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
                                       int messageBitIndex, int builderBitIndex,
                                       Context* context);
-  ~ImmutableMapFieldGenerator();
+  ~ImmutableMapFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(
+      io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index 4fa939f..023b4fc 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/compiler/java/java_map_field_lite.h>
 
+#include <cstdint>
+
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
@@ -69,6 +71,17 @@
   }
 }
 
+std::string KotlinTypeName(const FieldDescriptor* field,
+                           ClassNameResolver* name_resolver) {
+  if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+    return name_resolver->GetImmutableClassName(field->message_type());
+  } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+    return name_resolver->GetImmutableClassName(field->enum_type());
+  } else {
+    return KotlinTypeName(GetJavaType(field));
+  }
+}
+
 std::string WireType(const FieldDescriptor* field) {
   return "com.google.protobuf.WireFormat.FieldType." +
          std::string(FieldTypeName(field->type()));
@@ -90,14 +103,20 @@
 
   (*variables)["key_type"] = TypeName(key, name_resolver, false);
   (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+  (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
+  (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
   (*variables)["key_wire_type"] = WireType(key);
   (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
   // We use `x.getClass()` as a null check because it generates less bytecode
   // than an `if (x == null) { throw ... }` statement.
   (*variables)["key_null_check"] =
-      IsReferenceType(keyJavaType) ? "key.getClass();" : "";
+      IsReferenceType(keyJavaType)
+          ? "java.lang.Class<?> keyClass = key.getClass();"
+          : "";
   (*variables)["value_null_check"] =
-      IsReferenceType(valueJavaType) ? "value.getClass();" : "";
+      IsReferenceType(valueJavaType)
+          ? "java.lang.Class<?> valueClass = value.getClass();"
+          : "";
 
   if (GetJavaType(value) == JAVATYPE_ENUM) {
     // We store enums as Integers internally.
@@ -131,6 +150,11 @@
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
 
   (*variables)["default_entry"] =
       (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry";
@@ -501,7 +525,7 @@
 }
 
 void ImmutableMapFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -788,6 +812,87 @@
   }
 }
 
+void ImmutableMapFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$kt_deprecation$ val $kt_name$: "
+      "com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  @kotlin.jvm.JvmSynthetic\n"
+      "  @JvmName(\"get$kt_capitalized_name$Map\")\n"
+      "  get() = com.google.protobuf.kotlin.DslMap(\n"
+      "    $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
+      "  )\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@JvmName(\"put$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
+      "     $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"set$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
+      "     put(key, value)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"remove$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .remove(key: $kt_key_type$) {\n"
+      "     $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"putAll$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
+      "{\n"
+      "     $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
+      "   }\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@JvmName(\"clear$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslMap"
+      "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  .clear() {\n"
+      "     $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+      "   }\n");
+}
+
 void ImmutableMapFieldLiteGenerator::GenerateInitializationCode(
     io::Printer* printer) const {
   // Nothing to initialize.
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h
index 49cbf6c..da046b2 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
 
+#include <cstdint>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -43,18 +45,19 @@
   explicit ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
                                           int messageBitIndex,
                                           Context* context);
-  ~ImmutableMapFieldLiteGenerator();
+  ~ImmutableMapFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 0192e4b..336a08f 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/java/java_message.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <vector>
@@ -210,9 +211,14 @@
       "  com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
       "    internal_$identifier$_fieldAccessorTable;\n");
 
+  // The following bytecode_estimate calculation logic must stay in sync with
+  // the similar logic in the GenerateFieldAccessorTableInitializer method below
+  // to make sure that the generated static final fields are initialized  in the
+  // static initialization block directly.
+  //
   // 6 bytes per field and oneof
   *bytecode_estimate +=
-      10 + 6 * descriptor_->field_count() + 6 * oneofs_.size();
+      10 + 6 * descriptor_->field_count() + 6 * descriptor_->oneof_decl_count();
 }
 
 int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer(
@@ -225,6 +231,10 @@
       "    new java.lang.String[] { ",
       "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
       GeneratedCodeVersionSuffix());
+  // All the bytecode_estimate calculation logic in this method must stay in
+  // sync with the similar logic in the GenerateFieldAccessorTable method
+  // above. See the corresponding comment in GenerateFieldAccessorTable for
+  // details.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
@@ -491,6 +501,7 @@
     printer->Print("public static final int $constant_name$ = $number$;\n",
                    "constant_name", FieldConstantName(descriptor_->field(i)),
                    "number", StrCat(descriptor_->field(i)->number()));
+    printer->Annotate("constant_name", descriptor_->field(i));
     field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
     printer->Print("\n");
   }
@@ -570,6 +581,7 @@
       SortFieldsByNumber(descriptor_));
 
   std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  sorted_extensions.reserve(descriptor_->extension_range_count());
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
@@ -1211,11 +1223,11 @@
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = sorted_fields[i];
-    uint32 tag = WireFormatLite::MakeTag(
+    uint32_t tag = WireFormatLite::MakeTag(
         field->number(), WireFormat::WireTypeForFieldType(field->type()));
 
     printer->Print("case $tag$: {\n", "tag",
-                   StrCat(static_cast<int32>(tag)));
+                   StrCat(static_cast<int32_t>(tag)));
     printer->Indent();
 
     field_generators_.get(field).GenerateParsingCode(printer);
@@ -1228,10 +1240,10 @@
     if (field->is_packable()) {
       // To make packed = true wire compatible, we generate parsing code from a
       // packed version of this field regardless of field->options().packed().
-      uint32 packed_tag = WireFormatLite::MakeTag(
+      uint32_t packed_tag = WireFormatLite::MakeTag(
           field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
       printer->Print("case $tag$: {\n", "tag",
-                     StrCat(static_cast<int32>(packed_tag)));
+                     StrCat(static_cast<int32_t>(packed_tag)));
       printer->Indent();
 
       field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
@@ -1355,6 +1367,277 @@
   }
 }
 
+// ===================================================================
+void ImmutableMessageGenerator::GenerateMutableCopy(io::Printer* printer) {
+  printer->Print(
+      "protected com.google.protobuf.MutableMessage\n"
+      "    internalMutableDefault() {\n"
+      "  return MutableDefaultLoader.get();\n"
+      "}\n"
+      "\n"
+      "private static final class MutableDefaultLoader {\n"
+      "  private static final java.lang.Object defaultOrRuntimeException;\n"
+      "  static {\n"
+      "    java.lang.Object local;\n"
+      "    try {\n"
+      "      local = internalMutableDefault(\"$mutable_name$\");\n"
+      "    } catch (java.lang.RuntimeException e) {\n"
+      "      local = e;\n"
+      "    }\n"
+      "    defaultOrRuntimeException = local;\n"
+      "  }\n"
+      "\n"
+      "  private MutableDefaultLoader() {}\n"
+      "\n"
+      "  public static com.google.protobuf.MutableMessage get() {\n"
+      "    if (defaultOrRuntimeException\n"
+      "         instanceof java.lang.RuntimeException) {\n"
+      "      throw (java.lang.RuntimeException) defaultOrRuntimeException;\n"
+      "    }\n"
+      "    return\n"
+      "        (com.google.protobuf.MutableMessage) "
+      "defaultOrRuntimeException;\n"
+      "  }\n"
+      "}\n",
+      "mutable_name", name_resolver_->GetJavaMutableClassName(descriptor_));
+}
+
+void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const {
+  printer->Print(
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "@com.google.protobuf.kotlin.ProtoDslMarker\n");
+  printer->Print(
+      "class Dsl private constructor(\n"
+      "  private val _builder: $message$.Builder\n"
+      ") {\n"
+      "  companion object {\n"
+      "    @kotlin.jvm.JvmSynthetic\n"
+      "    @kotlin.PublishedApi\n"
+      "    internal fun _create(builder: $message$.Builder): Dsl = "
+      "Dsl(builder)\n"
+      "  }\n"
+      "\n"
+      "  @kotlin.jvm.JvmSynthetic\n"
+      "  @kotlin.PublishedApi\n"
+      "  internal fun _build(): $message$ = _builder.build()\n",
+      "message", name_resolver_->GetClassName(descriptor_, true));
+
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    printer->Print("\n");
+    field_generators_.get(descriptor_->field(i))
+        .GenerateKotlinDslMembers(printer);
+  }
+
+  for (auto oneof : oneofs_) {
+    printer->Print(
+        "val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
+        "  @JvmName(\"get$oneof_capitalized_name$Case\")\n"
+        "  get() = _builder.get$oneof_capitalized_name$Case()\n\n"
+        "fun clear$oneof_capitalized_name$() {\n"
+        "  _builder.clear$oneof_capitalized_name$()\n"
+        "}\n",
+        "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
+        "oneof_capitalized_name",
+        context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
+        name_resolver_->GetClassName(descriptor_, true));
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    GenerateKotlinExtensions(printer);
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableMessageGenerator::GenerateKotlinMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> Unit): "
+      "$message$ "
+      "=\n"
+      "  $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
+      "}._build()\n",
+      "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_),
+      "message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_),
+      "message", name_resolver_->GetClassName(descriptor_, true));
+
+  printer->Print("object $name$Kt {\n", "name", descriptor_->name());
+  printer->Indent();
+  GenerateKotlinDsl(printer);
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+        .GenerateKotlinMembers(printer);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline fun $message$.copy(block: $message_kt$.Dsl.() -> Unit): "
+      "$message$ =\n"
+      "  $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
+      "}._build()\n",
+      "message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
+      name_resolver_->GetKotlinExtensionsClassName(descriptor_));
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+        .GenerateTopLevelKotlinMembers(printer);
+  }
+}
+
+void ImmutableMessageGenerator::GenerateKotlinExtensions(
+    io::Printer* printer) const {
+  std::string message_name = name_resolver_->GetClassName(descriptor_, true);
+
+  printer->Print(
+      "@Suppress(\"UNCHECKED_CAST\")\n"
+      "@kotlin.jvm.JvmSynthetic\n"
+      "operator fun <T> get(extension: "
+      "com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
+      "  return if (extension.isRepeated) {\n"
+      "    get(extension as com.google.protobuf.ExtensionLite<$message$, "
+      "List<*>>) as T\n"
+      "  } else {\n"
+      "    _builder.getExtension(extension)\n"
+      "  }\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
+      "operator fun <E> get(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
+      "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
+      "  return com.google.protobuf.kotlin.ExtensionList(extension, "
+      "_builder.getExtension(extension))\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "operator fun contains(extension: "
+      "com.google.protobuf.ExtensionLite<$message$, *>): "
+      "Boolean {\n"
+      "  return _builder.hasExtension(extension)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "fun clear(extension: com.google.protobuf.ExtensionLite<$message$, *>) "
+      "{\n"
+      "  _builder.clearExtension(extension)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.PublishedApi\n"
+      "internal fun <T> setExtension(extension: "
+      "com.google.protobuf.ExtensionLite<$message$, T>, "
+      "value: T) {\n"
+      "  _builder.setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <T : Comparable<T>> set(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+      "  value: T\n"
+      ") {\n"
+      "  setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun set(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, "
+      "com.google.protobuf.ByteString>,\n"
+      "  value: com.google.protobuf.ByteString\n"
+      ") {\n"
+      "  setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+      "  value: T\n"
+      ") {\n"
+      "  setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.add(value: E) {\n"
+      "  _builder.addExtension(this.extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.plusAssign"
+      "(value: E) {\n"
+      "  add(value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.addAll(values: Iterable<E>) {\n"
+      "  for (value in values) {\n"
+      "    add(value)\n"
+      "  }\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.plusAssign(values: "
+      "Iterable<E>) {\n"
+      "  addAll(values)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.set(index: Int, value: "
+      "E) {\n"
+      "  _builder.setExtension(this.extension, index, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline fun com.google.protobuf.kotlin.ExtensionList<*, "
+      "$message$>.clear() {\n"
+      "  clear(extension)\n"
+      "}\n\n",
+      "message", message_name);
+}
 
 void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
   printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 87b9df5..cafc91e 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -85,6 +85,9 @@
   // Generate code to register all contained extensions with an
   // ExtensionRegistry.
   virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0;
+  virtual void GenerateKotlinDsl(io::Printer* printer) const = 0;
+  virtual void GenerateKotlinMembers(io::Printer* printer) const = 0;
+  virtual void GenerateTopLevelKotlinMembers(io::Printer* printer) const = 0;
 
  protected:
   const Descriptor* descriptor_;
@@ -99,14 +102,17 @@
   ImmutableMessageGenerator(const Descriptor* descriptor, Context* context);
   virtual ~ImmutableMessageGenerator();
 
-  virtual void Generate(io::Printer* printer);
-  virtual void GenerateInterface(io::Printer* printer);
-  virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
-  virtual void GenerateStaticVariables(io::Printer* printer,
-                                       int* bytecode_estimate);
+  void Generate(io::Printer* printer) override;
+  void GenerateInterface(io::Printer* printer) override;
+  void GenerateExtensionRegistrationCode(io::Printer* printer) override;
+  void GenerateStaticVariables(io::Printer* printer,
+                               int* bytecode_estimate) override;
 
   // Returns an estimate of the number of bytes the printed code will compile to
-  virtual int GenerateStaticVariableInitializers(io::Printer* printer);
+  int GenerateStaticVariableInitializers(io::Printer* printer) override;
+  void GenerateKotlinDsl(io::Printer* printer) const override;
+  void GenerateKotlinMembers(io::Printer* printer) const override;
+  void GenerateTopLevelKotlinMembers(io::Printer* printer) const override;
 
  private:
   void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate);
@@ -128,6 +134,8 @@
   void GenerateEqualsAndHashCode(io::Printer* printer);
   void GenerateParser(io::Printer* printer);
   void GenerateParsingConstructor(io::Printer* printer);
+  void GenerateMutableCopy(io::Printer* printer);
+  void GenerateKotlinExtensions(io::Printer* printer) const;
   void GenerateAnyMethods(io::Printer* printer);
 
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index 67273fa..a6d5dfe 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -49,6 +49,7 @@
 namespace compiler {
 namespace java {
 
+
 namespace {
 
 void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
@@ -59,6 +60,7 @@
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
+  (*variables)["kt_type"] = (*variables)["type"];
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
@@ -68,6 +70,11 @@
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   (*variables)["on_changed"] = "onChanged();";
   (*variables)["ver"] = GeneratedCodeVersionSuffix();
   (*variables)["get_parser"] =
@@ -406,6 +413,32 @@
       "}\n");
 }
 
+void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: $kt_type$\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                 "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                 "}\n");
+}
+
 void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode(
     io::Printer* printer) const {
   if (HasHasbit(descriptor_)) {
@@ -944,7 +977,7 @@
       // list is immutable. If it's immutable, the invariant is that it must
       // either an instance of Collections.emptyList() or it's an ArrayList
       // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
-      // a refererence to the underlying ArrayList. This invariant allows us to
+      // a reference to the underlying ArrayList. This invariant allows us to
       // share instances of lists between protocol buffers avoiding expensive
       // memory allocations. Note, immutable is a strong guarantee here -- not
       // just that the list cannot be modified via the reference but that the
@@ -1360,6 +1393,98 @@
   return name_resolver_->GetImmutableClassName(descriptor_->message_type());
 }
 
+void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$ val $kt_name$: "
+                 "com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+                 "  @kotlin.jvm.JvmSynthetic\n"
+                 "  get() = com.google.protobuf.kotlin.DslList(\n"
+                 "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+                 "  )\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: $kt_type$) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "inline operator fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: $kt_type$) {\n"
+                 "  add(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+                 "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+      "  addAll(values)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: $kt_type$) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
index 36fa492..60acb19 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -65,24 +65,25 @@
 
   // implements ImmutableFieldGenerator
   // ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -110,13 +111,13 @@
                                       Context* context);
   ~ImmutableMessageOneofFieldGenerator();
 
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator);
@@ -127,27 +128,29 @@
   explicit RepeatedImmutableMessageFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
-  ~RepeatedImmutableMessageFieldGenerator();
+  ~RepeatedImmutableMessageFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(
+      io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index 41d33ee..adb91a3 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -32,13 +32,15 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/compiler/java/java_message_field_lite.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
@@ -59,6 +61,7 @@
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
+  (*variables)["kt_type"] = (*variables)["type"];
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
@@ -68,6 +71,11 @@
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
   if (HasHasbit(descriptor)) {
@@ -89,9 +97,6 @@
         (*variables)["name"] + "_ != null";
   }
 
-  // For repeated builders, the underlying list tracks mutability state.
-  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
-
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -278,8 +283,34 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: $kt_type$\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                 "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                 "}\n");
+}
+
 void ImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -369,7 +400,7 @@
 }
 
 void ImmutableMessageOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -532,9 +563,11 @@
   printer->Print(
       variables_,
       "private void ensure$capitalized_name$IsMutable() {\n"
-      "  if (!$is_mutable$) {\n"
+      // Use a temporary to avoid a redundant iget-object.
+      "  com.google.protobuf.Internal.ProtobufList<$type$> tmp = $name$_;\n"
+      "  if (!tmp.isModifiable()) {\n"
       "    $name$_ =\n"
-      "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+      "        com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
       "   }\n"
       "}\n"
       "\n");
@@ -732,7 +765,7 @@
 }
 
 void RepeatedImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -750,6 +783,98 @@
   return name_resolver_->GetImmutableClassName(descriptor_->message_type());
 }
 
+void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$ val $kt_name$: "
+                 "com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+                 "  @kotlin.jvm.JvmSynthetic\n"
+                 "  get() = com.google.protobuf.kotlin.DslList(\n"
+                 "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+                 "  )\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: $kt_type$) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "inline operator fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: $kt_type$) {\n"
+                 "  add(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+                 "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+      "  addAll(values)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: $kt_type$) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h
index c0a9b37..8f81f60 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.h
@@ -35,8 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -64,15 +66,16 @@
 
   // implements ImmutableFieldLiteGenerator
   // ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -92,10 +95,10 @@
                                           Context* context);
   ~ImmutableMessageOneofFieldLiteGenerator();
 
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
@@ -106,18 +109,19 @@
  public:
   explicit RepeatedImmutableMessageFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
-  ~RepeatedImmutableMessageFieldLiteGenerator();
+  ~RepeatedImmutableMessageFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 4afffdc..13f003b 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/java/java_message_lite.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <vector>
@@ -471,7 +472,7 @@
 
   // Collect field info into a sequence of UTF-16 chars. It will be embedded
   // as a Java string in the generated code.
-  std::vector<uint16> chars;
+  std::vector<uint16_t> chars;
 
   int flags = 0;
   if (IsProto2(descriptor_->file())) {
@@ -553,7 +554,7 @@
   printer->Print("java.lang.String info =\n");
   std::string line;
   for (size_t i = 0; i < chars.size(); i++) {
-    uint16 code = chars[i];
+    uint16_t code = chars[i];
     EscapeUtf16ToString(code, &line);
     if (line.size() >= 80) {
       printer->Print("    \"$string$\" +\n", "string", line);
@@ -723,6 +724,242 @@
   }
 }
 
+void ImmutableMessageLiteGenerator::GenerateKotlinDsl(
+    io::Printer* printer) const {
+  printer->Print(
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "@com.google.protobuf.kotlin.ProtoDslMarker\n");
+  printer->Print(
+      "class Dsl private constructor(\n"
+      "  private val _builder: $message$.Builder\n"
+      ") {\n"
+      "  companion object {\n"
+      "    @kotlin.jvm.JvmSynthetic\n"
+      "    @kotlin.PublishedApi\n"
+      "    internal fun _create(builder: $message$.Builder): Dsl = "
+      "Dsl(builder)\n"
+      "  }\n"
+      "\n"
+      "  @kotlin.jvm.JvmSynthetic\n"
+      "  @kotlin.PublishedApi\n"
+      "  internal fun _build(): $message$ = _builder.build()\n",
+      "message", name_resolver_->GetClassName(descriptor_, true));
+
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    printer->Print("\n");
+    field_generators_.get(descriptor_->field(i))
+        .GenerateKotlinDslMembers(printer);
+  }
+
+  for (auto oneof : oneofs_) {
+    printer->Print(
+        "val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
+        "  @JvmName(\"get$oneof_capitalized_name$Case\")\n"
+        "  get() = _builder.get$oneof_capitalized_name$Case()\n\n"
+        "fun clear$oneof_capitalized_name$() {\n"
+        "  _builder.clear$oneof_capitalized_name$()\n"
+        "}\n",
+        "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
+        "oneof_capitalized_name",
+        context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
+        name_resolver_->GetClassName(descriptor_, true));
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    GenerateKotlinExtensions(printer);
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableMessageLiteGenerator::GenerateKotlinMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> Unit): "
+      "$message$ =\n"
+      "  $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
+      "}._build()\n",
+      "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_),
+      "message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_),
+      "message", name_resolver_->GetClassName(descriptor_, true));
+
+  printer->Print("object $name$Kt {\n", "name", descriptor_->name());
+  printer->Indent();
+  GenerateKotlinDsl(printer);
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+        .GenerateKotlinMembers(printer);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      "inline fun $message$.copy(block: $message_kt$.Dsl.() -> Unit): "
+      "$message$ =\n"
+      "  $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
+      "}._build()\n",
+      "message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
+      name_resolver_->GetKotlinExtensionsClassName(descriptor_));
+
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    if (IsMapEntry(descriptor_->nested_type(i))) continue;
+    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+        .GenerateTopLevelKotlinMembers(printer);
+  }
+}
+
+void ImmutableMessageLiteGenerator::GenerateKotlinExtensions(
+    io::Printer* printer) const {
+  std::string message_name = name_resolver_->GetClassName(descriptor_, true);
+
+  printer->Print(
+      "@Suppress(\"UNCHECKED_CAST\")\n"
+      "@kotlin.jvm.JvmSynthetic\n"
+      "operator fun <T> get(extension: "
+      "com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
+      "  return if (extension.isRepeated) {\n"
+      "    get(extension as com.google.protobuf.ExtensionLite<$message$, "
+      "List<*>>) as T\n"
+      "  } else {\n"
+      "    _builder.getExtension(extension)\n"
+      "  }\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
+      "operator fun <E> get(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
+      "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
+      "  return com.google.protobuf.kotlin.ExtensionList(extension, "
+      "_builder.getExtension(extension))\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "operator fun contains(extension: "
+      "com.google.protobuf.ExtensionLite<$message$, *>): "
+      "Boolean {\n"
+      "  return _builder.hasExtension(extension)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "fun clear(extension: com.google.protobuf.ExtensionLite<$message$, *>) "
+      "{\n"
+      "  _builder.clearExtension(extension)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.PublishedApi\n"
+      "internal fun <T> setExtension(extension: "
+      "com.google.protobuf.ExtensionLite<$message$, T>, "
+      "value: T) {\n"
+      "  _builder.setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <T : Comparable<T>> set(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+      "  value: T\n"
+      ") {\n"
+      "  setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun set(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, "
+      "com.google.protobuf.ByteString>,\n"
+      "  value: com.google.protobuf.ByteString\n"
+      ") {\n"
+      "  setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+      "  value: T\n"
+      ") {\n"
+      "  setExtension(extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.add(value: E) {\n"
+      "  _builder.addExtension(this.extension, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.plusAssign"
+      "(value: E) {\n"
+      "  add(value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.addAll(values: Iterable<E>) {\n"
+      "  for (value in values) {\n"
+      "    add(value)\n"
+      "  }\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.plusAssign(values: "
+      "Iterable<E>) {\n"
+      "  addAll(values)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+      "$message$>.set(index: Int, value: "
+      "E) {\n"
+      "  _builder.setExtension(this.extension, index, value)\n"
+      "}\n\n",
+      "message", message_name);
+
+  printer->Print(
+      "@kotlin.jvm.JvmSynthetic\n"
+      "inline fun com.google.protobuf.kotlin.ExtensionList<*, "
+      "$message$>.clear() {\n"
+      "  clear(extension)\n"
+      "}\n\n",
+      "message", message_name);
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h
index 5290b1e..0af0cb8 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_lite.h
@@ -50,12 +50,15 @@
   ImmutableMessageLiteGenerator(const Descriptor* descriptor, Context* context);
   virtual ~ImmutableMessageLiteGenerator();
 
-  virtual void Generate(io::Printer* printer);
-  virtual void GenerateInterface(io::Printer* printer);
-  virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
+  virtual void Generate(io::Printer* printer) override;
+  virtual void GenerateInterface(io::Printer* printer) override;
+  virtual void GenerateExtensionRegistrationCode(io::Printer* printer) override;
   virtual void GenerateStaticVariables(io::Printer* printer,
-                                       int* bytecode_estimate);
-  virtual int GenerateStaticVariableInitializers(io::Printer* printer);
+                                       int* bytecode_estimate) override;
+  virtual int GenerateStaticVariableInitializers(io::Printer* printer) override;
+  void GenerateKotlinDsl(io::Printer* printer) const override;
+  void GenerateKotlinMembers(io::Printer* printer) const override;
+  void GenerateTopLevelKotlinMembers(io::Printer* printer) const override;
 
  private:
   void GenerateParseFromMethods(io::Printer* printer);
@@ -66,6 +69,7 @@
   void GenerateParser(io::Printer* printer);
   void GenerateConstructor(io::Printer* printer);
   void GenerateDynamicMethodNewBuildMessageInfo(io::Printer* printer);
+  void GenerateKotlinExtensions(io::Printer* printer) const;
 
   Context* context_;
   ClassNameResolver* name_resolver_;
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc
index 361cfa9..39bf3e2 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.cc
+++ b/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -34,6 +34,8 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_names.h>
+#include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/stubs/substitute.h>
 
 namespace google {
@@ -67,6 +69,17 @@
   return StripPackageName(descriptor->full_name(), descriptor->file());
 }
 
+std::string ClassNameWithoutPackageKotlin(const Descriptor* descriptor) {
+  std::string result = descriptor->name();
+  const Descriptor* temp = descriptor->containing_type();
+
+  while (temp) {
+    result = temp->name() + "Kt." + result;
+    temp = temp->containing_type();
+  }
+  return result;
+}
+
 // Get the name of an enum's Java class without package name prefix.
 std::string ClassNameWithoutPackage(const EnumDescriptor* descriptor,
                                     bool immutable) {
@@ -91,7 +104,7 @@
 }
 
 // Return true if a and b are equals (case insensitive).
-NameEquality CheckNameEquality(const string& a, const string& b) {
+NameEquality CheckNameEquality(const std::string& a, const std::string& b) {
   if (ToUpper(a) == ToUpper(b)) {
     if (a == b) {
       return NameEquality::EXACT_EQUAL;
@@ -160,7 +173,14 @@
 
 std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file,
                                                 bool immutable) {
-  if (immutable) {
+  return GetFileClassName(file, immutable, false);
+}
+
+std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file,
+                                                bool immutable, bool kotlin) {
+  if (kotlin) {
+    return GetFileImmutableClassName(file) + "Kt";
+  } else if (immutable) {
     return GetFileImmutableClassName(file);
   } else {
     return "Mutable" + GetFileImmutableClassName(file);
@@ -200,9 +220,14 @@
 
 std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor,
                                             bool immutable) {
+  return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor,
+                                            bool immutable, bool kotlin) {
   std::string result = FileJavaPackage(descriptor, immutable);
   if (!result.empty()) result += '.';
-  result += GetFileClassName(descriptor, immutable);
+  result += GetFileClassName(descriptor, immutable, kotlin);
   return result;
 }
 
@@ -211,50 +236,79 @@
 std::string ClassNameResolver::GetClassFullName(
     const std::string& name_without_package, const FileDescriptor* file,
     bool immutable, bool is_own_file) {
+  return GetClassFullName(name_without_package, file, immutable, is_own_file,
+                          false);
+}
+
+std::string ClassNameResolver::GetClassFullName(
+    const std::string& name_without_package, const FileDescriptor* file,
+    bool immutable, bool is_own_file, bool kotlin) {
   std::string result;
   if (is_own_file) {
     result = FileJavaPackage(file, immutable);
   } else {
-    result = GetClassName(file, immutable);
+    result = GetClassName(file, immutable, kotlin);
   }
   if (!result.empty()) {
     result += '.';
   }
   result += name_without_package;
+  if (kotlin) result += "Kt";
   return result;
 }
 
 std::string ClassNameResolver::GetClassName(const Descriptor* descriptor,
                                             bool immutable) {
-  return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable),
-                          descriptor->file(), immutable,
-                          MultipleJavaFiles(descriptor->file(), immutable));
+  return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const Descriptor* descriptor,
+                                            bool immutable, bool kotlin) {
+  return GetClassFullName(
+      ClassNameWithoutPackage(descriptor, immutable), descriptor->file(),
+      immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin);
 }
 
 std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor,
                                             bool immutable) {
-  return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable),
-                          descriptor->file(), immutable,
-                          MultipleJavaFiles(descriptor->file(), immutable));
+  return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor,
+                                            bool immutable, bool kotlin) {
+  return GetClassFullName(
+      ClassNameWithoutPackage(descriptor, immutable), descriptor->file(),
+      immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin);
 }
 
 std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor,
                                             bool immutable) {
+  return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor,
+                                            bool immutable, bool kotlin) {
   return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable),
                           descriptor->file(), immutable,
-                          IsOwnFile(descriptor, immutable));
+                          IsOwnFile(descriptor, immutable), kotlin);
 }
 
 // Get the Java Class style full name of a message.
 std::string ClassNameResolver::GetJavaClassFullName(
     const std::string& name_without_package, const FileDescriptor* file,
     bool immutable) {
+  return GetJavaClassFullName(name_without_package, file, immutable, false);
+}
+
+std::string ClassNameResolver::GetJavaClassFullName(
+    const std::string& name_without_package, const FileDescriptor* file,
+    bool immutable, bool kotlin) {
   std::string result;
   if (MultipleJavaFiles(file, immutable)) {
     result = FileJavaPackage(file, immutable);
     if (!result.empty()) result += '.';
   } else {
-    result = GetClassName(file, immutable);
+    result = GetClassName(file, immutable, kotlin);
     if (!result.empty()) result += '$';
   }
   result += StringReplace(name_without_package, ".", "$", true);
@@ -263,10 +317,21 @@
 
 std::string ClassNameResolver::GetExtensionIdentifierName(
     const FieldDescriptor* descriptor, bool immutable) {
-  return GetClassName(descriptor->containing_type(), immutable) + "." +
+  return GetExtensionIdentifierName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetExtensionIdentifierName(
+    const FieldDescriptor* descriptor, bool immutable, bool kotlin) {
+  return GetClassName(descriptor->containing_type(), immutable, kotlin) + "." +
          descriptor->name();
 }
 
+std::string ClassNameResolver::GetKotlinFactoryName(
+    const Descriptor* descriptor) {
+  std::string name = ToCamelCase(descriptor->name(), /* lower_first = */ true);
+  return IsForbiddenKotlin(name) ? name + "_" : name;
+}
+
 std::string ClassNameResolver::GetJavaImmutableClassName(
     const Descriptor* descriptor) {
   return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true),
@@ -279,6 +344,35 @@
                               descriptor->file(), true);
 }
 
+std::string ClassNameResolver::GetKotlinExtensionsClassName(
+    const Descriptor* descriptor) {
+  return GetClassFullName(ClassNameWithoutPackageKotlin(descriptor),
+                          descriptor->file(), true, true, true);
+}
+
+std::string ClassNameResolver::GetJavaMutableClassName(
+    const Descriptor* descriptor) {
+  return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false),
+                              descriptor->file(), false);
+}
+
+std::string ClassNameResolver::GetJavaMutableClassName(
+    const EnumDescriptor* descriptor) {
+  return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false),
+                              descriptor->file(), false);
+}
+
+std::string ClassNameResolver::GetDowngradedFileClassName(
+    const FileDescriptor* file) {
+  return "Downgraded" + GetFileClassName(file, false);
+}
+
+std::string ClassNameResolver::GetDowngradedClassName(
+    const Descriptor* descriptor) {
+  return FileJavaPackage(descriptor->file()) + "." +
+         GetDowngradedFileClassName(descriptor->file()) + "." +
+         ClassNameWithoutPackage(descriptor, false);
+}
 
 }  // namespace java
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h
index b92570c..a688d49 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.h
+++ b/src/google/protobuf/compiler/java/java_name_resolver.h
@@ -60,6 +60,8 @@
 
   // Gets the unqualified outer class name for the file.
   std::string GetFileClassName(const FileDescriptor* file, bool immutable);
+  std::string GetFileClassName(const FileDescriptor* file, bool immutable,
+                               bool kotlin);
   // Gets the unqualified immutable outer class name of a file.
   std::string GetFileImmutableClassName(const FileDescriptor* file);
   // Gets the unqualified default immutable outer class name of a file
@@ -80,9 +82,17 @@
 
   // Gets the fully-qualified class name corresponding to the given descriptor.
   std::string GetClassName(const Descriptor* descriptor, bool immutable);
+  std::string GetClassName(const Descriptor* descriptor, bool immutable,
+                           bool kotlin);
   std::string GetClassName(const EnumDescriptor* descriptor, bool immutable);
+  std::string GetClassName(const EnumDescriptor* descriptor, bool immutable,
+                           bool kotlin);
   std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable);
+  std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable,
+                           bool kotlin);
   std::string GetClassName(const FileDescriptor* descriptor, bool immutable);
+  std::string GetClassName(const FileDescriptor* descriptor, bool immutable,
+                           bool kotlin);
 
   template <class DescriptorType>
   std::string GetImmutableClassName(const DescriptorType* descriptor) {
@@ -96,6 +106,8 @@
   // Gets the fully qualified name of an extension identifier.
   std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor,
                                          bool immutable);
+  std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor,
+                                         bool immutable, bool kotlin);
 
   // Gets the fully qualified name for generated classes in Java convention.
   // Nested classes will be separated using '$' instead of '.'
@@ -103,15 +115,29 @@
   //   com.package.OuterClass$OuterMessage$InnerMessage
   std::string GetJavaImmutableClassName(const Descriptor* descriptor);
   std::string GetJavaImmutableClassName(const EnumDescriptor* descriptor);
+  std::string GetKotlinFactoryName(const Descriptor* descriptor);
+  std::string GetKotlinExtensionsClassName(const Descriptor* descriptor);
+  std::string GetJavaMutableClassName(const Descriptor* descriptor);
+  std::string GetJavaMutableClassName(const EnumDescriptor* descriptor);
+  // Gets the outer class and the actual class for downgraded mutable messages.
+  std::string GetDowngradedFileClassName(const FileDescriptor* file);
+  std::string GetDowngradedClassName(const Descriptor* descriptor);
+
  private:
   // Get the full name of a Java class by prepending the Java package name
   // or outer class name.
   std::string GetClassFullName(const std::string& name_without_package,
                                const FileDescriptor* file, bool immutable,
                                bool is_own_file);
+  std::string GetClassFullName(const std::string& name_without_package,
+                               const FileDescriptor* file, bool immutable,
+                               bool is_own_file, bool kotlin);
   // Get the Java Class style full name of a message.
   std::string GetJavaClassFullName(const std::string& name_without_package,
                                    const FileDescriptor* file, bool immutable);
+  std::string GetJavaClassFullName(const std::string& name_without_package,
+                                   const FileDescriptor* file, bool immutable,
+                                   bool kotlin);
   // Caches the result to provide better performance.
   std::map<const FileDescriptor*, std::string>
       file_immutable_outer_class_names_;
diff --git a/src/google/protobuf/compiler/java/java_names.h b/src/google/protobuf/compiler/java/java_names.h
index 73a340e..313ace4 100644
--- a/src/google/protobuf/compiler/java/java_names.h
+++ b/src/google/protobuf/compiler/java/java_names.h
@@ -93,18 +93,6 @@
 //   Capitalized camel case name field name.
 std::string CapitalizedFieldName(const FieldDescriptor* descriptor);
 
-// Requires:
-//   descriptor != NULL
-// Returns:
-//   Primitive Java type name for the field.
-const char* PrimitiveTypeName(const FieldDescriptor* descriptor);
-
-// Requires:
-//   descriptor != NULL
-// Returns:
-//   Boes primitive Java type name for the field.
-const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor);
-
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index 744b2c8..3bdd53b 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/java/java_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 277c8ca..dfd7188 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -32,6 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_primitive_field.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -41,7 +44,6 @@
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/compiler/java/java_primitive_field.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -52,7 +54,6 @@
 namespace java {
 
 using internal::WireFormat;
-using internal::WireFormatLite;
 
 namespace {
 
@@ -66,6 +67,7 @@
 
   (*variables)["type"] = PrimitiveTypeName(javaType);
   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
+  (*variables)["kt_type"] = KotlinTypeName(javaType);
   (*variables)["field_type"] = (*variables)["type"];
 
   if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
@@ -112,7 +114,7 @@
   (*variables)["capitalized_type"] =
       GetCapitalizedType(descriptor, /* immutable = */ true);
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   if (IsReferenceType(GetJavaType(descriptor))) {
@@ -127,13 +129,18 @@
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   int fixed_size = FixedSize(GetType(descriptor));
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = StrCat(fixed_size);
   }
   (*variables)["on_changed"] = "onChanged();";
 
-  if (SupportFieldPresence(descriptor)) {
+  if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
@@ -195,7 +202,7 @@
 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
 
 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
-  return SupportFieldPresence(descriptor_) ? 1 : 0;
+  return HasHasbit(descriptor_) ? 1 : 0;
 }
 
 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
@@ -204,7 +211,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -217,7 +224,7 @@
     io::Printer* printer) const {
   printer->Print(variables_, "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -241,7 +248,7 @@
     io::Printer* printer) const {
   printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -296,6 +303,34 @@
                  "}\n");
 }
 
+void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: $kt_type$\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  if (HasHazzer(descriptor_)) {
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    printer->Print(variables_,
+                   "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                   "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                   "}\n");
+  }
+}
+
 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
     io::Printer* printer) const {
   // noop for primitives
@@ -317,7 +352,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if (other.has$capitalized_name$()) {\n"
                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
@@ -332,7 +367,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     if (IsDefaultValueJavaDefault(descriptor_)) {
       printer->Print(variables_,
                      "if ($get_has_field_bit_from_local$) {\n"
@@ -496,16 +531,14 @@
 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -521,15 +554,13 @@
 
 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -702,7 +733,7 @@
   // list is immutable. If it's immutable, the invariant is that it must
   // either an instance of Collections.emptyList() or it's an ArrayList
   // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
-  // a refererence to the underlying ArrayList. This invariant allows us to
+  // a reference to the underlying ArrayList. This invariant allows us to
   // share instances of lists between protocol buffers avoiding expensive
   // memory allocations. Note, immutable is a strong guarantee here -- not
   // just that the list cannot be modified via the reference but that the
@@ -794,6 +825,98 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$ val $kt_name$: "
+                 "com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+                 "  @kotlin.jvm.JvmSynthetic\n"
+                 "  get() = com.google.protobuf.kotlin.DslList(\n"
+                 "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+                 "  )\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: $kt_type$) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "inline operator fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: $kt_type$) {\n"
+                 "  add(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+                 "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+      "  addAll(values)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: $kt_type$) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 void RepeatedImmutablePrimitiveFieldGenerator::
     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
   // noop for primitives
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
index db20750..1f0eb8c 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -61,28 +61,30 @@
                                             int messageBitIndex,
                                             int builderBitIndex,
                                             Context* context);
-  ~ImmutablePrimitiveFieldGenerator();
+  ~ImmutablePrimitiveFieldGenerator() override;
 
   // implements ImmutableFieldGenerator
   // ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(
+      io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -101,13 +103,13 @@
                                         int builderBitIndex, Context* context);
   ~ImmutablePrimitiveOneofFieldGenerator();
 
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator);
@@ -119,28 +121,30 @@
   explicit RepeatedImmutablePrimitiveFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
-  virtual ~RepeatedImmutablePrimitiveFieldGenerator();
+  ~RepeatedImmutablePrimitiveFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(
+      io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 65d0bd0..cc589f3 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -32,6 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_primitive_field_lite.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -41,7 +44,6 @@
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/compiler/java/java_primitive_field_lite.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -72,12 +74,13 @@
   JavaType javaType = GetJavaType(descriptor);
   (*variables)["type"] = PrimitiveTypeName(javaType);
   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
+  (*variables)["kt_type"] = KotlinTypeName(javaType);
   (*variables)["field_type"] = (*variables)["type"];
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["capitalized_type"] =
       GetCapitalizedType(descriptor, /* immutable = */ true);
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
@@ -126,7 +129,8 @@
   if (IsReferenceType(javaType)) {
     // We use `x.getClass()` as a null check because it generates less bytecode
     // than an `if (x == null) { throw ... }` statement.
-    (*variables)["null_check"] = "  value.getClass();\n";
+    (*variables)["null_check"] =
+        "  java.lang.Class<?> valueClass = value.getClass();\n";
   } else {
     (*variables)["null_check"] = "";
   }
@@ -134,12 +138,17 @@
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   int fixed_size = FixedSize(GetType(descriptor));
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = StrCat(fixed_size);
   }
 
-  if (SupportFieldPresence(descriptor)) {
+  if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
 
@@ -164,9 +173,6 @@
     }
   }
 
-  // For repeated builders, the underlying list tracks mutability state.
-  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
-
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -190,12 +196,12 @@
 ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
 
 int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
-  return SupportFieldPresence(descriptor_) ? 1 : 0;
+  return HasHasbit(descriptor_) ? 1 : 0;
 }
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -215,7 +221,7 @@
   }
   printer->Print(variables_, "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -261,7 +267,7 @@
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -303,8 +309,36 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void ImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: $kt_type$\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  if (HasHazzer(descriptor_)) {
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    printer->Print(variables_,
+                   "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                   "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                   "}\n");
+  }
+}
+
 void ImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -346,16 +380,14 @@
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -387,7 +419,7 @@
 }
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -396,16 +428,14 @@
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -511,9 +541,11 @@
   printer->Print(
       variables_,
       "private void ensure$capitalized_name$IsMutable() {\n"
-      "  if (!$is_mutable$) {\n"
+      // Use a temporary to avoid a redundant iget-object.
+      "  $field_list_type$ tmp = $name$_;\n"
+      "  if (!tmp.isModifiable()) {\n"
       "    $name$_ =\n"
-      "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+      "        com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
       "   }\n"
       "}\n");
 
@@ -616,8 +648,100 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$ val $kt_name$: "
+                 "com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+                 "  @kotlin.jvm.JvmSynthetic\n"
+                 "  get() = com.google.protobuf.kotlin.DslList(\n"
+                 "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+                 "  )\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: $kt_type$) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "inline operator fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: $kt_type$) {\n"
+                 "  add(value)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+                 "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+                 "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+      "  addAll(values)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: $kt_type$) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
index 5867cee..dfafae3 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
@@ -35,8 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -60,19 +62,20 @@
  public:
   explicit ImmutablePrimitiveFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
-  ~ImmutablePrimitiveFieldLiteGenerator();
+  ~ImmutablePrimitiveFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
   // ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -92,11 +95,11 @@
                                             Context* context);
   ~ImmutablePrimitiveOneofFieldLiteGenerator();
 
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
 
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
@@ -107,18 +110,19 @@
  public:
   explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
-  virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator();
+  ~RepeatedImmutablePrimitiveFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h
index 1c82c16..fa9c92c 100644
--- a/src/google/protobuf/compiler/java/java_service.h
+++ b/src/google/protobuf/compiler/java/java_service.h
@@ -80,7 +80,7 @@
                             Context* context);
   virtual ~ImmutableServiceGenerator();
 
-  virtual void Generate(io::Printer* printer);
+  virtual void Generate(io::Printer* printer) override;
 
  private:
   // Generate the getDescriptorForType() method.
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index f673e68..45943d7 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -36,6 +36,7 @@
 
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_names.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 8e1595b..9ebb771 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -33,6 +33,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_string_field.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -42,7 +45,6 @@
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/compiler/java/java_string_field.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -71,13 +73,15 @@
       "= " + ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["capitalized_type"] = "String";
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["null_check"] =
       "  if (value == null) {\n"
       "    throw new NullPointerException();\n"
       "  }\n";
+  (*variables)["isStringEmpty"] = "com.google.protobuf.GeneratedMessage" +
+                                GeneratedCodeVersionSuffix() + ".isStringEmpty";
   (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" +
                                 GeneratedCodeVersionSuffix() + ".writeString";
   (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" +
@@ -88,9 +92,14 @@
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   (*variables)["on_changed"] = "onChanged();";
 
-  if (SupportFieldPresence(descriptor)) {
+  if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
@@ -110,7 +119,7 @@
     (*variables)["clear_has_field_bit_builder"] = "";
 
     (*variables)["is_field_present_message"] =
-        "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
+       "!" + (*variables)["isStringEmpty"] + "(" + (*variables)["name"] + "_)";
   }
 
   // For repeated builders, one bit is used for whether the array is immutable.
@@ -147,7 +156,7 @@
 ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
 
 int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
-  return SupportFieldPresence(descriptor_) ? 1 : 0;
+  return HasHasbit(descriptor_) ? 1 : 0;
 }
 
 int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
@@ -188,7 +197,7 @@
 // UnmodifiableLazyStringList.
 void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -207,7 +216,7 @@
   printer->Print(variables_, "private volatile java.lang.Object $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -266,7 +275,7 @@
     io::Printer* printer) const {
   printer->Print(variables_,
                  "private java.lang.Object $name$_ $default_init$;\n");
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -365,6 +374,34 @@
                  "}\n");
 }
 
+void ImmutableStringFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: kotlin.String\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  if (HasHazzer(descriptor_)) {
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    printer->Print(variables_,
+                   "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                   "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                   "}\n");
+  }
+}
+
 void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode(
     io::Printer* printer) const {
   // noop for primitives
@@ -384,7 +421,7 @@
 
 void ImmutableStringFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     // Allow a slight breach of abstraction here in order to avoid forcing
     // all string fields to Strings when copying fields from a Message.
     printer->Print(variables_,
@@ -404,7 +441,7 @@
 
 void ImmutableStringFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if ($get_has_field_bit_from_local$) {\n"
                    "  $set_has_field_bit_to_local$;\n"
@@ -484,16 +521,13 @@
 void ImmutableStringOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -551,16 +585,14 @@
 
 void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -801,7 +833,7 @@
   // list is immutable. If it's immutable, the invariant is that it must
   // either an instance of Collections.emptyList() or it's an ArrayList
   // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
-  // a refererence to the underlying ArrayList. This invariant allows us to
+  // a reference to the underlying ArrayList. This invariant allows us to
   // share instances of lists between protocol buffers avoiding expensive
   // memory allocations. Note, immutable is a strong guarantee here -- not
   // just that the list cannot be modified via the reference but that the
@@ -919,6 +951,107 @@
                  "}\n");
 }
 
+void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  // property for List<String>
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+  printer->Print(
+      variables_,
+      "val $kt_name$: "
+      "com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  @kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "  get() = com.google.protobuf.kotlin.DslList(\n"
+      "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+      "  )\n");
+
+  // List<String>.add(String)
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: kotlin.String) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}\n");
+
+  // List<String> += String
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "operator fun com.google.protobuf.kotlin.DslList"
+                 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: kotlin.String) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}\n");
+
+  // List<String>.addAll(Iterable<String>)
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+      "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+      "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+      "}\n");
+
+  // List<String> += Iterable<String>
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+      "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+      "}\n");
+
+  // List<String>[Int] = String
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: kotlin.String) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 void RepeatedImmutableStringFieldGenerator::
     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
   // noop for primitives
diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h
index 1c00ae8..369dcda 100644
--- a/src/google/protobuf/compiler/java/java_string_field.h
+++ b/src/google/protobuf/compiler/java/java_string_field.h
@@ -65,24 +65,25 @@
 
   // implements ImmutableFieldGenerator
   // ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -102,13 +103,13 @@
   ~ImmutableStringOneofFieldGenerator();
 
  private:
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator);
 };
@@ -118,27 +119,29 @@
   explicit RepeatedImmutableStringFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
-  ~RepeatedImmutableStringFieldGenerator();
+  ~RepeatedImmutableStringFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
-  int GetNumBitsForMessage() const;
-  int GetNumBitsForBuilder() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateBuilderClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateParsingCode(io::Printer* printer) const;
-  void GenerateParsingDoneCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  int GetNumBitsForBuilder() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
+  void GenerateBuilderClearCode(io::Printer* printer) const override;
+  void GenerateMergingCode(io::Printer* printer) const override;
+  void GenerateBuildingCode(io::Printer* printer) const override;
+  void GenerateParsingCode(io::Printer* printer) const override;
+  void GenerateParsingDoneCode(io::Printer* printer) const override;
+  void GenerateSerializationCode(io::Printer* printer) const override;
+  void GenerateSerializedSizeCode(io::Printer* printer) const override;
+  void GenerateFieldBuilderInitializationCode(
+      io::Printer* printer) const override;
+  void GenerateEqualsCode(io::Printer* printer) const override;
+  void GenerateHashCode(io::Printer* printer) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index 25e46d9..f22fc4b 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -33,6 +33,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_string_field_lite.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -42,7 +45,6 @@
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/compiler/java/java_string_field_lite.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -72,20 +74,26 @@
       "= " + ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["capitalized_type"] = "java.lang.String";
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   // We use `x.getClass()` as a null check because it generates less bytecode
   // than an `if (x == null) { throw ... }` statement.
-  (*variables)["null_check"] = "  value.getClass();\n";
+  (*variables)["null_check"] =
+      "  java.lang.Class<?> valueClass = value.getClass();\n";
 
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // by the proto compiler
   (*variables)["deprecation"] =
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+  (*variables)["kt_deprecation"] =
+      descriptor->options().deprecated()
+          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+                " is deprecated\") "
+          : "";
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
-  if (SupportFieldPresence(descriptor)) {
+  if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
 
@@ -104,9 +112,6 @@
         "!" + (*variables)["name"] + "_.isEmpty()";
   }
 
-  // For repeated builders, the underlying list tracks mutability state.
-  (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
-
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -130,7 +135,7 @@
 ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
 
 int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
-  return SupportFieldPresence(descriptor_) ? 1 : 0;
+  return HasHasbit(descriptor_) ? 1 : 0;
 }
 
 // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
@@ -160,7 +165,7 @@
 //     shouldn't be necessary or used on devices.
 void ImmutableStringFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -179,7 +184,7 @@
   printer->Print(variables_, "private java.lang.String $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -241,7 +246,7 @@
 
 void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -304,8 +309,36 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+                 "$kt_deprecation$var $kt_name$: kotlin.String\n"
+                 "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+                 "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+                 "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+                 "  set(value) {\n"
+                 "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+                 "  }\n");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "fun ${$clear$kt_capitalized_name$$}$() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}\n");
+
+  if (HasHazzer(descriptor_)) {
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    printer->Print(variables_,
+                   "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+                   "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+                   "}\n");
+  }
+}
+
 void ImmutableStringFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -340,17 +373,14 @@
 void ImmutableStringOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -412,7 +442,7 @@
 }
 
 void ImmutableStringOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -421,16 +451,14 @@
 
 void ImmutableStringOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -567,9 +595,12 @@
   printer->Print(
       variables_,
       "private void ensure$capitalized_name$IsMutable() {\n"
-      "  if (!$is_mutable$) {\n"
+      // Use a temporary to avoid a redundant iget-object.
+      "  com.google.protobuf.Internal.ProtobufList<java.lang.String> tmp =\n"
+      "      $name$_;"
+      "  if (!tmp.isModifiable()) {\n"
       "    $name$_ =\n"
-      "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+      "        com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
       "   }\n"
       "}\n");
 
@@ -706,8 +737,109 @@
   printer->Annotate("{", "}", descriptor_);
 }
 
+void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "/**\n"
+      " * An uninstantiable, behaviorless type to represent the field in\n"
+      " * generics.\n"
+      " */\n"
+      "@kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+      " : com.google.protobuf.kotlin.DslProxy()\n");
+
+  // property for List<String>
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+  printer->Print(
+      variables_,
+      "val $kt_name$: "
+      "com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
+      "  @kotlin.OptIn"
+      "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+      "  get() = com.google.protobuf.kotlin.DslList(\n"
+      "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+      "  )\n");
+
+  // List<String>.add(String)
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+                 "add(value: kotlin.String) {\n"
+                 "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+                 "}\n");
+
+  // List<String> += String
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+                 "inline operator fun com.google.protobuf.kotlin.DslList"
+                 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+                 "plusAssign(value: kotlin.String) {\n"
+                 "  add(value)\n"
+                 "}\n");
+
+  // List<String>.addAll(Iterable<String>)
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+      "fun com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+      "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+      "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+      "}\n");
+
+  // List<String> += Iterable<String>
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+      "inline operator fun com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+      "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+      "  addAll(values)\n"
+      "}\n");
+
+  // List<String>[Int] = String
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+                               /* builder */ false);
+  printer->Print(
+      variables_,
+      "@kotlin.jvm.JvmSynthetic\n"
+      "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+      "operator fun com.google.protobuf.kotlin.DslList"
+      "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+      "set(index: kotlin.Int, value: kotlin.String) {\n"
+      "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+      "}");
+
+  WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+                               /* builder */ false);
+  printer->Print(variables_,
+                 "@kotlin.jvm.JvmSynthetic\n"
+                 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+                 "fun com.google.protobuf.kotlin.DslList"
+                 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+                 "clear() {\n"
+                 "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+                 "}");
+}
+
 void RepeatedImmutableStringFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h
index b67135c..85ec602 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.h
@@ -36,8 +36,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -61,19 +63,20 @@
   explicit ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
                                              int messageBitIndex,
                                              Context* context);
-  ~ImmutableStringFieldLiteGenerator();
+  ~ImmutableStringFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
   // ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  protected:
   const FieldDescriptor* descriptor_;
@@ -90,13 +93,13 @@
  public:
   ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
                                          int messageBitIndex, Context* context);
-  ~ImmutableStringOneofFieldLiteGenerator();
+  ~ImmutableStringOneofFieldLiteGenerator() override;
 
  private:
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
 };
@@ -106,18 +109,19 @@
  public:
   explicit RepeatedImmutableStringFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
-  ~RepeatedImmutableStringFieldLiteGenerator();
+  ~RepeatedImmutableStringFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
-  int GetNumBitsForMessage() const;
-  void GenerateInterfaceMembers(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer) const;
-  void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateInitializationCode(io::Printer* printer) const;
+  int GetNumBitsForMessage() const override;
+  void GenerateInterfaceMembers(io::Printer* printer) const override;
+  void GenerateMembers(io::Printer* printer) const override;
+  void GenerateBuilderMembers(io::Printer* printer) const override;
+  void GenerateInitializationCode(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const override;
+  void GenerateKotlinDslMembers(io::Printer* printer) const override;
 
-  std::string GetBoxedType() const;
+  std::string GetBoxedType() const override;
 
  private:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index c1216f8..1db96f8 100644
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -28,9 +28,19 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <google/protobuf/compiler/js/js_generator.h>
-
 #include <assert.h>
+#include <google/protobuf/compiler/js/js_generator.h>
+#include <google/protobuf/compiler/js/well_known_types_embed.h>
+#include <google/protobuf/compiler/scc.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/stubs/strutil.h>
+
 #include <algorithm>
 #include <limits>
 #include <map>
@@ -39,17 +49,6 @@
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/compiler/js/well_known_types_embed.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -95,19 +94,6 @@
   return false;
 }
 
-bool StrEndsWith(StringPiece sp, StringPiece x) {
-  return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
-}
-
-// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
-// suffix stripped.
-// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
-std::string StripProto(const std::string& filename) {
-  const char* suffix =
-      StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
-  return StripSuffixString(filename, suffix);
-}
-
 std::string GetSnakeFilename(const std::string& filename) {
   std::string snake_name = filename;
   ReplaceCharacters(&snake_name, "/", '_');
@@ -182,8 +168,8 @@
   if (descriptor == NULL) {
     return "";
   }
-  std::string result = StripPrefixString(
-      descriptor->full_name(), descriptor->file()->package());
+  std::string result =
+      StripPrefixString(descriptor->full_name(), descriptor->file()->package());
   // Add a leading dot if one is not already present.
   if (!result.empty() && result[0] != '.') {
     result = "." + result;
@@ -420,7 +406,7 @@
           GetSnakeFilename(scc->GetRepresentative()->file()->name()));
       (*long_name_dict)[scc->GetRepresentative()] =
           StrCat(snake_name, "_long_sccs_",
-                       static_cast<uint64>((*long_name_dict).size()));
+                 static_cast<uint64>((*long_name_dict).size()));
     }
     filename_base = (*long_name_dict)[scc->GetRepresentative()];
   }
@@ -440,9 +426,7 @@
 }
 
 // Returns the message/response ID, if set.
-std::string GetMessageId(const Descriptor* desc) {
-  return std::string();
-}
+std::string GetMessageId(const Descriptor* desc) { return std::string(); }
 
 bool IgnoreExtensionField(const FieldDescriptor* field) {
   // Exclude descriptor extensions from output "to avoid clutter" (from original
@@ -453,7 +437,6 @@
          file->name() == "google/protobuf/descriptor.proto";
 }
 
-
 // Used inside Google only -- do not remove.
 bool IsResponse(const Descriptor* desc) { return false; }
 
@@ -461,12 +444,12 @@
   return IgnoreExtensionField(field);
 }
 
-
 // Do we ignore this message type?
 bool IgnoreMessage(const Descriptor* d) { return d->options().map_entry(); }
 
 // Does JSPB ignore this entire oneof? True only if all fields are ignored.
 bool IgnoreOneof(const OneofDescriptor* oneof) {
+  if (oneof->is_synthetic()) return true;
   for (int i = 0; i < oneof->field_count(); i++) {
     if (!IgnoreField(oneof->field(i))) {
       return false;
@@ -545,7 +528,6 @@
   return name;
 }
 
-
 std::string JSOneofName(const OneofDescriptor* oneof) {
   return ToUpperCamel(ParseLowerUnderscore(oneof->name()));
 }
@@ -576,6 +558,7 @@
   int index = -1;
   for (int i = 0; i < oneof->containing_type()->oneof_decl_count(); i++) {
     const OneofDescriptor* o = oneof->containing_type()->oneof_decl(i);
+    if (o->is_synthetic()) continue;
     // If at least one field in this oneof is not JSPB-ignored, count the oneof.
     for (int j = 0; j < o->field_count(); j++) {
       const FieldDescriptor* f = o->field(j);
@@ -794,6 +777,11 @@
   return PostProcessFloat(result);
 }
 
+bool InRealOneof(const FieldDescriptor* field) {
+  return field->containing_oneof() &&
+         !field->containing_oneof()->is_synthetic();
+}
+
 // Return true if this is an integral field that should be represented as string
 // in JS.
 bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) {
@@ -820,23 +808,19 @@
 
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
-      return MaybeNumberString(field,
-                               StrCat(field->default_value_int32()));
+      return MaybeNumberString(field, StrCat(field->default_value_int32()));
     case FieldDescriptor::CPPTYPE_UINT32:
       // The original codegen is in Java, and Java protobufs store unsigned
       // integer values as signed integer values. In order to exactly match the
       // output, we need to reinterpret as base-2 signed. Ugh.
       return MaybeNumberString(
-          field,
-          StrCat(static_cast<int32>(field->default_value_uint32())));
+          field, StrCat(static_cast<int32>(field->default_value_uint32())));
     case FieldDescriptor::CPPTYPE_INT64:
-      return MaybeNumberString(field,
-                               StrCat(field->default_value_int64()));
+      return MaybeNumberString(field, StrCat(field->default_value_int64()));
     case FieldDescriptor::CPPTYPE_UINT64:
       // See above note for uint32 -- reinterpreting as signed.
       return MaybeNumberString(
-          field,
-          StrCat(static_cast<int64>(field->default_value_uint64())));
+          field, StrCat(static_cast<int64>(field->default_value_uint64())));
     case FieldDescriptor::CPPTYPE_ENUM:
       return StrCat(field->default_value_enum()->number());
     case FieldDescriptor::CPPTYPE_BOOL:
@@ -851,9 +835,10 @@
         bool is_valid = EscapeJSString(field->default_value_string(), &out);
         if (!is_valid) {
           // TODO(b/115551870): Decide whether this should be a hard error.
-          GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name()
-                       << " was truncated since it contained invalid UTF-8 or"
-                          " codepoints outside the basic multilingual plane.";
+          GOOGLE_LOG(WARNING)
+              << "The default value for field " << field->full_name()
+              << " was truncated since it contained invalid UTF-8 or"
+                 " codepoints outside the basic multilingual plane.";
         }
         return "\"" + out + "\"";
       } else {  // Bytes
@@ -1116,7 +1101,6 @@
          JSBinaryReadWriteMethodName(field, /* is_writer = */ true);
 }
 
-
 std::string JSTypeTag(const FieldDescriptor* desc) {
   switch (desc->type()) {
     case FieldDescriptor::TYPE_DOUBLE:
@@ -1151,7 +1135,6 @@
   return "";
 }
 
-
 bool HasRepeatedFields(const GeneratorOptions& options,
                        const Descriptor* desc) {
   for (int i = 0; i < desc->field_count(); i++) {
@@ -1173,7 +1156,7 @@
 
 bool HasOneofFields(const Descriptor* desc) {
   for (int i = 0; i < desc->field_count(); i++) {
-    if (desc->field(i)->containing_oneof()) {
+    if (InRealOneof(desc->field(i))) {
       return true;
     }
   }
@@ -1411,15 +1394,9 @@
 // generate extra methods (clearFoo() and hasFoo()) for this field.
 bool HasFieldPresence(const GeneratorOptions& options,
                       const FieldDescriptor* field) {
-  if (field->is_repeated() || field->is_map()) {
-    // We say repeated fields and maps don't have presence, but we still do
-    // generate clearFoo() methods for them through a special case elsewhere.
-    return false;
-  }
-
-  return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
-         field->containing_oneof() != NULL ||
-         field->file()->syntax() == FileDescriptor::SYNTAX_PROTO2;
+  // This returns false for repeated fields and maps, but we still do
+  // generate clearFoo() methods for these through a special case elsewhere.
+  return field->has_presence();
 }
 
 // We use this to implement the semantics that same file can be generated
@@ -1646,6 +1623,8 @@
       "/**\n"
       " * @fileoverview\n"
       " * @enhanceable\n"
+      // TODO(b/152440355): requireType/requires diverged from internal version.
+      " * @suppress {missingRequire} reports error on implicit type usages.\n"
       " * @suppress {messageConventions} JS Compiler reports an "
       "error if a variable or\n"
       " *     field starts with 'MSG_' and isn't a translatable "
@@ -1653,6 +1632,8 @@
       " * @public\n"
       " */\n"
       "// GENERATED CODE -- DO NOT EDIT!\n"
+      "/* eslint-disable */\n"
+      "// @ts-nocheck\n"
       "\n");
 }
 
@@ -1908,16 +1889,13 @@
   }
 }
 
-bool NamespaceOnly(const Descriptor* desc) {
-  return false;
-}
+bool NamespaceOnly(const Descriptor* desc) { return false; }
 
 void Generator::FindRequiresForMessage(const GeneratorOptions& options,
                                        const Descriptor* desc,
                                        std::set<std::string>* required,
                                        std::set<std::string>* forwards,
                                        bool* have_message) const {
-
   if (!NamespaceOnly(desc)) {
     *have_message = true;
     for (int i = 0; i < desc->field_count(); i++) {
@@ -1966,7 +1944,8 @@
 void Generator::FindRequiresForExtension(
     const GeneratorOptions& options, const FieldDescriptor* field,
     std::set<std::string>* required, std::set<std::string>* forwards) const {
-  if (field->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") {
+  if (field->containing_type()->full_name() !=
+      "google.protobuf.bridge.MessageSet") {
     required->insert(GetMessagePath(options, field->containing_type()));
   }
   FindRequiresForField(options, field, required, forwards);
@@ -2006,7 +1985,6 @@
     printer->Print("\n");
     GenerateClassFieldInfo(options, printer, desc);
 
-
     GenerateClassToObject(options, printer, desc);
     // These must come *before* the extension-field info generation in
     // GenerateClassRegistration so that references to the binary
@@ -2090,7 +2068,8 @@
     const Descriptor* desc) const {
   if (!NamespaceOnly(desc)) {
     GenerateClassConstructor(options, printer, desc);
-    if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") {
+    if (IsExtendable(desc) &&
+        desc->full_name() != "google.protobuf.bridge.MessageSet") {
       GenerateClassExtensionFieldInfo(options, printer, desc);
     }
   }
@@ -2530,7 +2509,6 @@
       GenerateExtension(options, printer, extension);
     }
   }
-
 }
 
 void Generator::GenerateClassFields(const GeneratorOptions& options,
@@ -2676,7 +2654,7 @@
                               /* singular_if_not_packed = */ false),
         "class", GetMessagePath(options, field->containing_type()),
         "settername", "set" + JSGetterName(options, field), "oneoftag",
-        (field->containing_oneof() ? "Oneof" : ""), "repeatedtag",
+        (InRealOneof(field) ? "Oneof" : ""), "repeatedtag",
         (field->is_repeated() ? "Repeated" : ""));
     printer->Annotate("settername", field);
 
@@ -2686,16 +2664,14 @@
         "\n"
         "\n",
         "index", JSFieldIndex(field), "oneofgroup",
-        (field->containing_oneof() ? (", " + JSOneofArray(options, field))
-                                   : ""));
+        (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""));
 
     if (field->is_repeated()) {
       GenerateRepeatedMessageHelperMethods(options, printer, field);
     }
 
   } else {
-    bool untyped =
-        false;
+    bool untyped = false;
 
     // Simple (primitive) field, either singular or repeated.
 
@@ -2811,8 +2787,7 @@
           "  return jspb.Message.set$oneoftag$Field(this, $index$",
           "class", GetMessagePath(options, field->containing_type()),
           "settername", "set" + JSGetterName(options, field), "oneoftag",
-          (field->containing_oneof() ? "Oneof" : ""), "index",
-          JSFieldIndex(field));
+          (InRealOneof(field) ? "Oneof" : ""), "index", JSFieldIndex(field));
       printer->Annotate("settername", field);
       printer->Print(
           "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);\n"
@@ -2822,8 +2797,7 @@
           "type",
           untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
           "typeclose", untyped ? ")" : "", "oneofgroup",
-          (field->containing_oneof() ? (", " + JSOneofArray(options, field))
-                                     : ""),
+          (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""),
           "rptvalueinit", (field->is_repeated() ? " || []" : ""));
     }
 
@@ -2899,8 +2873,8 @@
             "$index$$maybeoneofgroup$, ",
         "class", GetMessagePath(options, field->containing_type()),
         "clearername", "clear" + JSGetterName(options, field),
-        "maybeoneof", (field->containing_oneof() ? "Oneof" : ""),
-        "maybeoneofgroup", (field->containing_oneof()
+        "maybeoneof", (InRealOneof(field) ? "Oneof" : ""),
+        "maybeoneofgroup", (InRealOneof(field)
                             ? (", " + JSOneofArray(options, field))
                             : ""),
         "index", JSFieldIndex(field));
@@ -2965,7 +2939,7 @@
       "\n",
       "type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "",
       "typeclose", untyped ? ")" : "", "oneofgroup",
-      (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
+      (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""),
       "rptvalueinit", "");
   // clang-format on
 }
@@ -2994,8 +2968,8 @@
       "\n"
       "\n",
       "index", JSFieldIndex(field), "oneofgroup",
-      (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
-      "ctor", GetMessagePath(options, field->message_type()));
+      (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), "ctor",
+      GetMessagePath(options, field->message_type()));
 }
 
 void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
@@ -3046,7 +3020,6 @@
   }
 }
 
-
 void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
                                                io::Printer* printer,
                                                const Descriptor* desc) const {
@@ -3076,36 +3049,36 @@
       "$class$.deserializeBinaryFromReader = function(msg, reader) {\n"
       "  while (reader.nextField()) {\n",
       "class", GetMessagePath(options, desc));
+  printer->Print(
+      "    if (reader.isEndGroup()) {\n"
+      "      break;\n"
+      "    }\n"
+      "    var field = reader.getFieldNumber();\n"
+      "    switch (field) {\n");
+
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (!IgnoreField(desc->field(i))) {
+      GenerateClassDeserializeBinaryField(options, printer, desc->field(i));
+    }
+  }
+
+  printer->Print("    default:\n");
+  if (IsExtendable(desc)) {
     printer->Print(
-        "    if (reader.isEndGroup()) {\n"
+        "      jspb.Message.readBinaryExtension(msg, reader,\n"
+        "        $extobj$Binary,\n"
+        "        $class$.prototype.getExtension,\n"
+        "        $class$.prototype.setExtension);\n"
         "      break;\n"
-        "    }\n"
-        "    var field = reader.getFieldNumber();\n"
-        "    switch (field) {\n");
-
-    for (int i = 0; i < desc->field_count(); i++) {
-      if (!IgnoreField(desc->field(i))) {
-        GenerateClassDeserializeBinaryField(options, printer, desc->field(i));
-      }
-    }
-
-    printer->Print("    default:\n");
-    if (IsExtendable(desc)) {
-      printer->Print(
-          "      jspb.Message.readBinaryExtension(msg, reader,\n"
-          "        $extobj$Binary,\n"
-          "        $class$.prototype.getExtension,\n"
-          "        $class$.prototype.setExtension);\n"
-          "      break;\n"
-          "    }\n",
-          "extobj", JSExtensionsObjectName(options, desc->file(), desc),
-          "class", GetMessagePath(options, desc));
-    } else {
-      printer->Print(
-          "      reader.skipField();\n"
-          "      break;\n"
-          "    }\n");
-    }
+        "    }\n",
+        "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class",
+        GetMessagePath(options, desc));
+  } else {
+    printer->Print(
+        "      reader.skipField();\n"
+        "      break;\n"
+        "    }\n");
+  }
 
   printer->Print(
       "  }\n"
@@ -3163,6 +3136,15 @@
           (field->type() == FieldDescriptor::TYPE_GROUP)
               ? (StrCat(field->number()) + ", ")
               : "");
+    } else if (field->is_packable()) {
+      printer->Print(
+          "      var values = /** @type {$fieldtype$} */ "
+          "(reader.isDelimited() "
+          "? reader.readPacked$reader$() : [reader.read$reader$()]);\n",
+          "fieldtype",
+          JSFieldTypeAnnotation(options, field, false, true,
+                                /* singular_if_not_packed */ false, BYTES_U8),
+          "reader", JSBinaryReaderMethodType(field));
     } else {
       printer->Print(
           "      var value = /** @type {$fieldtype$} */ "
@@ -3174,7 +3156,14 @@
           JSBinaryReadWriteMethodName(field, /* is_writer = */ false));
     }
 
-    if (field->is_repeated() && !field->is_packed()) {
+    if (field->is_packable()) {
+      printer->Print(
+          "      for (var i = 0; i < values.length; i++) {\n"
+          "        msg.add$name$(values[i]);\n"
+          "      }\n",
+          "name",
+          JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true));
+    } else if (field->is_repeated()) {
       printer->Print(
           "      msg.add$name$(value);\n", "name",
           JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true));
@@ -3374,9 +3363,8 @@
   for (auto i : valid_index) {
     const EnumValueDescriptor* value = enumdesc->value(i);
     printer->Print("  $name$: $value$$comma$\n", "name",
-                   ToEnumCase(value->name()), "value",
-                   StrCat(value->number()), "comma",
-                   (i == valid_index.back()) ? "" : ",");
+                   ToEnumCase(value->name()), "value", StrCat(value->number()),
+                   "comma", (i == valid_index.back()) ? "" : ",");
     printer->Annotate("name", value);
   }
 
@@ -3417,8 +3405,7 @@
       "!Object} */ (\n"
       "         $toObject$),\n"
       "    $repeated$);\n",
-      "index", StrCat(field->number()), "name", extension_object_name,
-      "ctor",
+      "index", StrCat(field->number()), "name", extension_object_name, "ctor",
       (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
            ? SubmessageTypeRef(options, field)
            : std::string("null")),
@@ -3725,7 +3712,6 @@
     return false;
   }
 
-
   if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) {
     // All output should go in a single file.
     std::string filename = options.output_dir + "/" + options.library +
diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h
index 49f19f6..e452020 100644
--- a/src/google/protobuf/compiler/js/js_generator.h
+++ b/src/google/protobuf/compiler/js/js_generator.h
@@ -125,10 +125,10 @@
   std::string extension;
   // Create a separate output file for each input file?
   bool one_output_file_per_input_file;
-  // If true, we should append annotations as commen on the last line for
+  // If true, we should append annotations as comments on the last line for
   // generated .js file. Annotations used by tools like https://kythe.io
   // to provide cross-references between .js and .proto files. Annotations
-  // are enced as base64 proto of GeneratedCodeInfo message (see
+  // are encoded as base64 proto of GeneratedCodeInfo message (see
   // descriptor.proto).
   bool annotate_code;
 };
@@ -142,18 +142,21 @@
   Generator() {}
   virtual ~Generator() {}
 
-  virtual bool Generate(const FileDescriptor* file,
-                        const std::string& parameter, GeneratorContext* context,
-                        std::string* error) const {
+  bool Generate(const FileDescriptor* file, const std::string& parameter,
+                GeneratorContext* context, std::string* error) const override {
     *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
     return false;
   }
 
-  virtual bool HasGenerateAll() const { return true; }
+  bool HasGenerateAll() const override { return true; }
 
-  virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
-                           const std::string& parameter,
-                           GeneratorContext* context, std::string* error) const;
+  bool GenerateAll(const std::vector<const FileDescriptor*>& files,
+                   const std::string& parameter, GeneratorContext* context,
+                   std::string* error) const override;
+
+  uint64 GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
 
  private:
   void GenerateHeader(const GeneratorOptions& options,
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 5239e09..7cb7a63 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -28,10 +28,9 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: kenton@google.com (Kenton Varda)
-
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/java/java_kotlin_generator.h>
 #include <google/protobuf/compiler/js/js_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/compiler/python/python_generator.h>
@@ -66,6 +65,11 @@
   cli.RegisterGenerator("--java_out", "--java_opt", &java_generator,
                         "Generate Java source file.");
 
+  // Proto2 Kotlin
+  java::KotlinGenerator kt_generator;
+  cli.RegisterGenerator("--kotlin_out", "--kotlin_opt", &kt_generator,
+                        "Generate Kotlin file.");
+
 
   // Proto2 Python
   python::Generator py_generator;
@@ -87,10 +91,10 @@
   cli.RegisterGenerator("--csharp_out", "--csharp_opt", &csharp_generator,
                         "Generate C# source file.");
 
-  // Objective C
+  // Objective-C
   objectivec::ObjectiveCGenerator objc_generator;
   cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator,
-                        "Generate Objective C header and source.");
+                        "Generate Objective-C header and source.");
 
   // JavaScript
   js::Generator js_generator;
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 8b82901..1fce106 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -34,6 +34,7 @@
 
 #include <stdlib.h>
 
+#include <cstdint>
 #include <iostream>
 #include <memory>
 #include <vector>
@@ -87,12 +88,12 @@
 
 MockCodeGenerator::~MockCodeGenerator() {}
 
-uint64 MockCodeGenerator::GetSupportedFeatures() const {
-  uint64 all_features = CodeGenerator::FEATURE_PROTO3_OPTIONAL;
+uint64_t MockCodeGenerator::GetSupportedFeatures() const {
+  uint64_t all_features = CodeGenerator::FEATURE_PROTO3_OPTIONAL;
   return all_features & ~suppressed_features_;
 }
 
-void MockCodeGenerator::SuppressFeatures(uint64 features) {
+void MockCodeGenerator::SuppressFeatures(uint64_t features) {
   suppressed_features_ = features;
 }
 
@@ -119,7 +120,7 @@
 
   std::vector<std::string> insertion_list;
   if (!insertions.empty()) {
-    SplitStringUsing(insertions, ",", &insertion_list);
+    insertion_list = Split(insertions, ",", true);
   }
 
   EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2);
@@ -166,17 +167,36 @@
                         &file_content, true));
   std::string meta_content;
   GOOGLE_CHECK_OK(File::GetContents(
-      output_directory + "/" + GetOutputFileName(name, file) + ".meta",
+      output_directory + "/" + GetOutputFileName(name, file) + ".pb.meta",
       &meta_content, true));
   GeneratedCodeInfo annotations;
   GOOGLE_CHECK(TextFormat::ParseFromString(meta_content, &annotations));
-  ASSERT_EQ(3, annotations.annotation_size());
+  ASSERT_EQ(7, annotations.annotation_size());
+
   CheckSingleAnnotation("first_annotation", "first", file_content,
                         annotations.annotation(0));
+  CheckSingleAnnotation("first_path",
+                        "test_generator: first_insert,\n foo.proto,\n "
+                        "MockCodeGenerator_Annotate,\n foo.proto\n",
+                        file_content, annotations.annotation(1));
+  CheckSingleAnnotation("first_path",
+                        "test_plugin: first_insert,\n foo.proto,\n "
+                        "MockCodeGenerator_Annotate,\n foo.proto\n",
+                        file_content, annotations.annotation(2));
   CheckSingleAnnotation("second_annotation", "second", file_content,
-                        annotations.annotation(1));
+                        annotations.annotation(3));
+  // This annotated text has changed because it was inserted at an indented
+  // insertion point.
+  CheckSingleAnnotation("second_path",
+                        "test_generator: second_insert,\n   foo.proto,\n   "
+                        "MockCodeGenerator_Annotate,\n   foo.proto\n",
+                        file_content, annotations.annotation(4));
+  CheckSingleAnnotation("second_path",
+                        "test_plugin: second_insert,\n   foo.proto,\n   "
+                        "MockCodeGenerator_Annotate,\n   foo.proto\n",
+                        file_content, annotations.annotation(5));
   CheckSingleAnnotation("third_annotation", "third", file_content,
-                        annotations.annotation(2));
+                        annotations.annotation(6));
 }
 
 bool MockCodeGenerator::Generate(const FileDescriptor* file,
@@ -229,18 +249,33 @@
     }
   }
 
-  if (HasPrefixString(parameter, "insert=")) {
-    std::vector<std::string> insert_into;
-    SplitStringUsing(StripPrefixString(parameter, "insert="), ",",
-                     &insert_into);
+  bool insert_endlines = HasPrefixString(parameter, "insert_endlines=");
+  if (insert_endlines || HasPrefixString(parameter, "insert=")) {
+    std::vector<std::string> insert_into = Split(
+        StripPrefixString(
+            parameter, insert_endlines ? "insert_endlines=" : "insert="),
+        ",", true);
 
     for (size_t i = 0; i < insert_into.size(); i++) {
       {
-        std::unique_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
-            GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
+        google::protobuf::GeneratedCodeInfo info;
+        std::string content =
+            GetOutputFileContent(name_, "first_insert", file, context);
+        if (insert_endlines) {
+          GlobalReplaceSubstring(",", ",\n", &content);
+        }
+        if (annotate) {
+          auto* annotation = info.add_annotation();
+          annotation->set_begin(0);
+          annotation->set_end(content.size());
+          annotation->set_source_file("first_path");
+        }
+        std::unique_ptr<io::ZeroCopyOutputStream> output(
+            context->OpenForInsertWithGeneratedCodeInfo(
+                GetOutputFileName(insert_into[i], file),
+                kFirstInsertionPointName, info));
         io::Printer printer(output.get(), '$');
-        printer.PrintRaw(
-            GetOutputFileContent(name_, "first_insert", file, context));
+        printer.PrintRaw(content);
         if (printer.failed()) {
           *error = "MockCodeGenerator detected write error.";
           return false;
@@ -248,12 +283,24 @@
       }
 
       {
+        google::protobuf::GeneratedCodeInfo info;
+        std::string content =
+            GetOutputFileContent(name_, "second_insert", file, context);
+        if (insert_endlines) {
+          GlobalReplaceSubstring(",", ",\n", &content);
+        }
+        if (annotate) {
+          auto* annotation = info.add_annotation();
+          annotation->set_begin(0);
+          annotation->set_end(content.size());
+          annotation->set_source_file("second_path");
+        }
         std::unique_ptr<io::ZeroCopyOutputStream> output(
-            context->OpenForInsert(GetOutputFileName(insert_into[i], file),
-                                   kSecondInsertionPointName));
+            context->OpenForInsertWithGeneratedCodeInfo(
+                GetOutputFileName(insert_into[i], file),
+                kSecondInsertionPointName, info));
         io::Printer printer(output.get(), '$');
-        printer.PrintRaw(
-            GetOutputFileContent(name_, "second_insert", file, context));
+        printer.PrintRaw(content);
         if (printer.failed()) {
           *error = "MockCodeGenerator detected write error.";
           return false;
@@ -272,17 +319,17 @@
     printer.PrintRaw(GetOutputFileContent(name_, parameter, file, context));
     std::string annotate_suffix = "_annotation";
     if (annotate) {
-      printer.Print("$p$", "p", "first");
+      printer.Print("$p$\n", "p", "first");
       printer.Annotate("p", "first" + annotate_suffix);
     }
     printer.PrintRaw(kFirstInsertionPoint);
     if (annotate) {
-      printer.Print("$p$", "p", "second");
+      printer.Print("$p$\n", "p", "second");
       printer.Annotate("p", "second" + annotate_suffix);
     }
     printer.PrintRaw(kSecondInsertionPoint);
     if (annotate) {
-      printer.Print("$p$", "p", "third");
+      printer.Print("$p$\n", "p", "third");
       printer.Annotate("p", "third" + annotate_suffix);
     }
 
@@ -292,9 +339,9 @@
     }
     if (annotate) {
       std::unique_ptr<io::ZeroCopyOutputStream> meta_output(
-          context->Open(GetOutputFileName(name_, file) + ".meta"));
+          context->Open(GetOutputFileName(name_, file) + ".pb.meta"));
       if (!TextFormat::Print(annotations, meta_output.get())) {
-        *error = "MockCodeGenerator couldn't write .meta";
+        *error = "MockCodeGenerator couldn't write .pb.meta";
         return false;
       }
     }
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 70a840e..6e10105 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -33,6 +33,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
 #define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
 
+#include <cstdint>
 #include <string>
 
 #include <google/protobuf/compiler/code_generator.h>
@@ -56,7 +57,9 @@
 // If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines
 // into the files generated by other MockCodeGenerators instead of creating
 // its own file.  NAMES is a comma-separated list of the names of those other
-// MockCodeGenerators.
+// MockCodeGenerators.  If the parameter is "insert_endlines=NAMES", the
+// MockCodeGenerator will insert data guaranteed to contain more than one
+// endline into the files generated by NAMES.
 //
 // MockCodeGenerator will also modify its behavior slightly if the input file
 // contains a message type with one of the following names:
@@ -109,12 +112,12 @@
   bool Generate(const FileDescriptor* file, const std::string& parameter,
                 GeneratorContext* context, std::string* error) const override;
 
-  uint64 GetSupportedFeatures() const override;
-  void SuppressFeatures(uint64 features);
+  uint64_t GetSupportedFeatures() const override;
+  void SuppressFeatures(uint64_t features);
 
  private:
   std::string name_;
-  uint64 suppressed_features_ = 0;
+  uint64_t suppressed_features_ = 0;
 
   static std::string GetOutputFileContent(const std::string& generator_name,
                                           const std::string& parameter,
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
index f296768..12c475f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -65,7 +65,7 @@
       base_values_.push_back(value);
       value_names.insert(EnumValueName(value));
     } else {
-      string value_name(EnumValueName(value));
+      std::string value_name(EnumValueName(value));
       if (value_names.find(value_name) != value_names.end()) {
         alias_values_to_skip_.insert(value);
       } else {
@@ -79,7 +79,7 @@
 EnumGenerator::~EnumGenerator() {}
 
 void EnumGenerator::GenerateHeader(io::Printer* printer) {
-  string enum_comments;
+  std::string enum_comments;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
     enum_comments = BuildCommentsString(location, true);
@@ -129,7 +129,7 @@
     }
     SourceLocation location;
     if (all_values_[i]->GetSourceLocation(&location)) {
-      string comments = BuildCommentsString(location, true).c_str();
+      std::string comments = BuildCommentsString(location, true).c_str();
       if (comments.length() > 0) {
         if (i > 0) {
           printer->Print("\n");
@@ -172,11 +172,11 @@
   // will be zero.
   TextFormatDecodeData text_format_decode_data;
   int enum_value_description_key = -1;
-  string text_blob;
+  std::string text_blob;
 
   for (int i = 0; i < all_values_.size(); i++) {
     ++enum_value_description_key;
-    string short_name(EnumValueShortName(all_values_[i]));
+    std::string short_name(EnumValueShortName(all_values_[i]));
     text_blob += short_name + '\0';
     if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
       text_format_decode_data.AddString(enum_value_description_key, short_name,
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
index 50a6564..1d5741a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
@@ -53,14 +53,14 @@
   void GenerateHeader(io::Printer* printer);
   void GenerateSource(io::Printer* printer);
 
-  const string& name() const { return name_; }
+  const std::string& name() const { return name_; }
 
  private:
   const EnumDescriptor* descriptor_;
   std::vector<const EnumValueDescriptor*> base_values_;
   std::vector<const EnumValueDescriptor*> all_values_;
   std::set<const EnumValueDescriptor*> alias_values_to_skip_;
-  const string name_;
+  const std::string name_;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index 9890d0a..ff69f39 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -44,8 +44,8 @@
 namespace {
 
 void SetEnumVariables(const FieldDescriptor* descriptor,
-                      std::map<string, string>* variables) {
-  string type = EnumName(descriptor->enum_type());
+                      std::map<std::string, std::string>* variables) {
+  std::string type = EnumName(descriptor->enum_type());
   (*variables)["storage_type"] = type;
   // For non repeated fields, if it was defined in a different file, the
   // property decls need to use "enum NAME" rather than just "NAME" to support
@@ -104,26 +104,26 @@
       "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
       "  GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
       "  GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
-      "  return GPBGetMessageInt32Field(message, field);\n"
+      "  return GPBGetMessageRawEnumField(message, field);\n"
       "}\n"
       "\n"
       "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n"
       "  GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
       "  GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
-      "  GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);\n"
+      "  GPBSetMessageRawEnumField(message, field, value);\n"
       "}\n"
       "\n");
 }
 
 void EnumFieldGenerator::DetermineForwardDeclarations(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // If it is an enum defined in a different file, then we'll need a forward
   // declaration for it.  When it is in our file, all the enums are output
   // before the message, so it will be declared before it is needed.
   if (descriptor_->file() != descriptor_->enum_type()->file()) {
     // Enum name is already in "storage_type".
-    const string& name = variable("storage_type");
+    const std::string& name = variable("storage_type");
     fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")");
   }
 }
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
index 5a69c97..3fb0a9f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -48,9 +48,12 @@
   EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
 
  public:
-  virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
-  virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
-  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
+  virtual void GenerateCFunctionDeclarations(
+      io::Printer* printer) const override;
+  virtual void GenerateCFunctionImplementations(
+      io::Printer* printer) const override;
+  virtual void DetermineForwardDeclarations(
+      std::set<std::string>* fwd_decls) const override;
 
  protected:
   EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
@@ -62,7 +65,7 @@
                                               const Options& options);
 
  public:
-  virtual void FinishInitialization();
+  virtual void FinishInitialization() override;
 
  protected:
   RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index b514b8a..9cebcb2 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -41,7 +41,7 @@
 namespace compiler {
 namespace objectivec {
 
-ExtensionGenerator::ExtensionGenerator(const string& root_class_name,
+ExtensionGenerator::ExtensionGenerator(const std::string& root_class_name,
                                        const FieldDescriptor* descriptor)
     : method_name_(ExtensionMethodName(descriptor)),
       root_class_and_method_name_(root_class_name + "_" + method_name_),
@@ -59,7 +59,7 @@
 ExtensionGenerator::~ExtensionGenerator() {}
 
 void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
-  std::map<string, string> vars;
+  std::map<std::string, std::string> vars;
   vars["method_name"] = method_name_;
   if (IsRetainedName(method_name_)) {
     vars["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
@@ -82,13 +82,13 @@
 
 void ExtensionGenerator::GenerateStaticVariablesInitialization(
     io::Printer* printer) {
-  std::map<string, string> vars;
+  std::map<std::string, std::string> vars;
   vars["root_class_and_method_name"] = root_class_and_method_name_;
-  const string containing_type = ClassName(descriptor_->containing_type());
+  const std::string containing_type = ClassName(descriptor_->containing_type());
   vars["extended_type"] = ObjCClass(containing_type);
   vars["number"] = StrCat(descriptor_->number());
 
-  std::vector<string> options;
+  std::vector<std::string> options;
   if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
   if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
   if (descriptor_->containing_type()->options().message_set_wire_format()) {
@@ -110,8 +110,8 @@
   } else {
     vars["default"] = DefaultValue(descriptor_);
   }
-  string type = GetCapitalizedType(descriptor_);
-  vars["extension_type"] = string("GPBDataType") + type;
+  std::string type = GetCapitalizedType(descriptor_);
+  vars["extension_type"] = std::string("GPBDataType") + type;
 
   if (objc_type == OBJECTIVECTYPE_ENUM) {
     vars["enum_desc_func_name"] =
@@ -134,12 +134,12 @@
 }
 
 void ExtensionGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<string>* fwd_decls) {
-  string extended_type = ClassName(descriptor_->containing_type());
+    std::set<std::string>* fwd_decls) {
+  std::string extended_type = ClassName(descriptor_->containing_type());
   fwd_decls->insert(ObjCClassDeclaration(extended_type));
   ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
   if (objc_type == OBJECTIVECTYPE_MESSAGE) {
-    string message_type = ClassName(descriptor_->message_type());
+    std::string message_type = ClassName(descriptor_->message_type());
     fwd_decls->insert(ObjCClassDeclaration(message_type));
   }
 }
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
index 1bc19d8..d412f4a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
@@ -41,7 +41,7 @@
 
 class ExtensionGenerator {
  public:
-  ExtensionGenerator(const string& root_class_name,
+  ExtensionGenerator(const std::string& root_class_name,
                      const FieldDescriptor* descriptor);
   ~ExtensionGenerator();
 
@@ -51,11 +51,11 @@
   void GenerateMembersHeader(io::Printer* printer);
   void GenerateStaticVariablesInitialization(io::Printer* printer);
   void GenerateRegistrationSource(io::Printer* printer);
-  void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls);
+  void DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls);
 
  private:
-  string method_name_;
-  string root_class_and_method_name_;
+  std::string method_name_;
+  std::string root_class_and_method_name_;
   const FieldDescriptor* descriptor_;
 };
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index 829f425..eb23fee 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -48,16 +48,16 @@
 namespace {
 
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             std::map<string, string>* variables) {
-  string camel_case_name = FieldName(descriptor);
-  string raw_field_name;
+                             std::map<std::string, std::string>* variables) {
+  std::string camel_case_name = FieldName(descriptor);
+  std::string raw_field_name;
   if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
     raw_field_name = descriptor->message_type()->name();
   } else {
     raw_field_name = descriptor->name();
   }
   // The logic here has to match -[GGPBFieldDescriptor textFormatName].
-  const string un_camel_case_name(
+  const std::string un_camel_case_name(
       UnCamelCaseFieldName(camel_case_name, descriptor));
   const bool needs_custom_name = (raw_field_name != un_camel_case_name);
 
@@ -67,10 +67,10 @@
   } else {
     (*variables)["comments"] = "\n";
   }
-  const string& classname = ClassName(descriptor->containing_type());
+  const std::string& classname = ClassName(descriptor->containing_type());
   (*variables)["classname"] = classname;
   (*variables)["name"] = camel_case_name;
-  const string& capitalized_name = FieldNameCapitalized(descriptor);
+  const std::string& capitalized_name = FieldNameCapitalized(descriptor);
   (*variables)["capitalized_name"] = capitalized_name;
   (*variables)["raw_field_name"] = raw_field_name;
   (*variables)["field_number_name"] =
@@ -78,7 +78,7 @@
   (*variables)["field_number"] = StrCat(descriptor->number());
   (*variables)["field_type"] = GetCapitalizedType(descriptor);
   (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
-  std::vector<string> field_flags;
+  std::vector<std::string> field_flags;
   if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
   if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
   if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
@@ -91,6 +91,14 @@
   if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
     field_flags.push_back("GPBFieldHasEnumDescriptor");
   }
+  // It will clear on a zero value if...
+  //  - not repeated/map
+  //  - doesn't have presence
+  bool clear_on_zero =
+      (!descriptor->is_repeated() && !descriptor->has_presence());
+  if (clear_on_zero) {
+    field_flags.push_back("GPBFieldClearHasIvarOnZero");
+  }
 
   (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
 
@@ -177,12 +185,12 @@
 }
 
 void FieldGenerator::DetermineForwardDeclarations(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   // Nothing
 }
 
 void FieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   // Nothing
 }
 
@@ -238,13 +246,18 @@
 }
 
 void FieldGenerator::SetOneofIndexBase(int index_base) {
-  if (descriptor_->containing_oneof() != NULL) {
-    int index = descriptor_->containing_oneof()->index() + index_base;
+  const OneofDescriptor* oneof = descriptor_->real_containing_oneof();
+  if (oneof != NULL) {
+    int index = oneof->index() + index_base;
     // Flip the sign to mark it as a oneof.
     variables_["has_index"] = StrCat(-index);
   }
 }
 
+bool FieldGenerator::WantsHasProperty(void) const {
+  return descriptor_->has_presence() && !descriptor_->real_containing_oneof();
+}
+
 void FieldGenerator::FinishInitialization(void) {
   // If "property_type" wasn't set, make it "storage_type".
   if ((variables_.find("property_type") == variables_.end()) &&
@@ -289,20 +302,8 @@
   }
 }
 
-bool SingleFieldGenerator::WantsHasProperty(void) const {
-  if (descriptor_->containing_oneof() != NULL) {
-    // If in a oneof, it uses the oneofcase instead of a has bit.
-    return false;
-  }
-  if (HasFieldPresence(descriptor_->file())) {
-    // In proto1/proto2, every field has a has_$name$() method.
-    return true;
-  }
-  return false;
-}
-
 bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
-  if (descriptor_->containing_oneof() != NULL) {
+  if (descriptor_->real_containing_oneof()) {
     // The oneof tracks what is set instead.
     return false;
   }
@@ -402,13 +403,8 @@
   printer->Print("\n");
 }
 
-bool RepeatedFieldGenerator::WantsHasProperty(void) const {
-  // Consumer check the array size/existence rather than a has bit.
-  return false;
-}
-
 bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
-  return false;  // The array having anything is what is used.
+  return false;  // The array (or map/dict) having anything is what is used.
 }
 
 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
index 68c470a..ad8e55a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -65,8 +65,10 @@
   virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
 
   // Exposed for subclasses, should always call it on the parent class also.
-  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
-  virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(
+      std::set<std::string>* fwd_decls) const;
+  virtual void DetermineObjectiveCClassDefinitions(
+      std::set<std::string>* fwd_decls) const;
 
   // Used during generation, not intended to be extended by subclasses.
   void GenerateFieldDescription(
@@ -81,25 +83,26 @@
   virtual void SetExtraRuntimeHasBitsBase(int index_base);
   void SetOneofIndexBase(int index_base);
 
-  string variable(const char* key) const {
+  std::string variable(const char* key) const {
     return variables_.find(key)->second;
   }
 
   bool needs_textformat_name_support() const {
-    const string& field_flags = variable("fieldflags");
-    return field_flags.find("GPBFieldTextFormatNameCustom") != string::npos;
+    const std::string& field_flags = variable("fieldflags");
+    return field_flags.find("GPBFieldTextFormatNameCustom") !=
+           std::string::npos;
   }
-  string generated_objc_name() const { return variable("name"); }
-  string raw_field_name() const { return variable("raw_field_name"); }
+  std::string generated_objc_name() const { return variable("name"); }
+  std::string raw_field_name() const { return variable("raw_field_name"); }
 
  protected:
   FieldGenerator(const FieldDescriptor* descriptor, const Options& options);
 
   virtual void FinishInitialization(void);
-  virtual bool WantsHasProperty(void) const = 0;
+  bool WantsHasProperty(void) const;
 
   const FieldDescriptor* descriptor_;
-  std::map<string, string> variables_;
+  std::map<std::string, std::string> variables_;
 };
 
 class SingleFieldGenerator : public FieldGenerator {
@@ -109,17 +112,16 @@
   SingleFieldGenerator(const SingleFieldGenerator&) = delete;
   SingleFieldGenerator& operator=(const SingleFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
-  virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
 
-  virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+  virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
 
-  virtual bool RuntimeUsesHasBit(void) const;
+  virtual bool RuntimeUsesHasBit(void) const override;
 
  protected:
   SingleFieldGenerator(const FieldDescriptor* descriptor,
                        const Options& options);
-  virtual bool WantsHasProperty(void) const;
 };
 
 // Subclass with common support for when the field ends up as an ObjC Object.
@@ -130,8 +132,8 @@
   ObjCObjFieldGenerator(const ObjCObjFieldGenerator&) = delete;
   ObjCObjFieldGenerator& operator=(const ObjCObjFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
-  virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
 
  protected:
   ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
@@ -145,18 +147,17 @@
   RepeatedFieldGenerator(const RepeatedFieldGenerator&) = delete;
   RepeatedFieldGenerator& operator=(const RepeatedFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
-  virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
 
-  virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+  virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
 
-  virtual bool RuntimeUsesHasBit(void) const;
+  virtual bool RuntimeUsesHasBit(void) const override;
 
  protected:
   RepeatedFieldGenerator(const FieldDescriptor* descriptor,
                          const Options& options);
-  virtual void FinishInitialization(void);
-  virtual bool WantsHasProperty(void) const;
+  virtual void FinishInitialization(void) override;
 };
 
 // Convenience class which constructs FieldGenerators for a Descriptor.
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index db58249..be2be2c 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -52,7 +52,7 @@
 namespace {
 
 // This is also found in GPBBootstrap.h, and needs to be kept in sync.
-const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30003;
+const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30004;
 
 const char* kHeaderExtension = ".pbobjc.h";
 
@@ -185,22 +185,22 @@
 
 }  // namespace
 
-FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
     : file_(file),
       root_class_name_(FileClassName(file)),
       is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)),
       options_(options) {
   for (int i = 0; i < file_->enum_type_count(); i++) {
-    EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
+    EnumGenerator* generator = new EnumGenerator(file_->enum_type(i));
     enum_generators_.emplace_back(generator);
   }
   for (int i = 0; i < file_->message_type_count(); i++) {
-    MessageGenerator *generator =
+    MessageGenerator* generator =
         new MessageGenerator(root_class_name_, file_->message_type(i), options_);
     message_generators_.emplace_back(generator);
   }
   for (int i = 0; i < file_->extension_count(); i++) {
-    ExtensionGenerator *generator =
+    ExtensionGenerator* generator =
         new ExtensionGenerator(root_class_name_, file_->extension(i));
     extension_generators_.emplace_back(generator);
   }
@@ -208,16 +208,16 @@
 
 FileGenerator::~FileGenerator() {}
 
-void FileGenerator::GenerateHeader(io::Printer *printer) {
-  std::set<string> headers;
+void FileGenerator::GenerateHeader(io::Printer* printer) {
+  std::vector<std::string> headers;
   // Generated files bundled with the library get minimal imports, everything
   // else gets the wrapper so everything is usable.
   if (is_bundled_proto_) {
-    headers.insert("GPBRootObject.h");
-    headers.insert("GPBMessage.h");
-    headers.insert("GPBDescriptor.h");
+    headers.push_back("GPBDescriptor.h");
+    headers.push_back("GPBMessage.h");
+    headers.push_back("GPBRootObject.h");
   } else {
-    headers.insert("GPBProtocolBuffers.h");
+    headers.push_back("GPBProtocolBuffers.h");
   }
   PrintFileRuntimePreamble(printer, headers);
 
@@ -242,8 +242,9 @@
     ImportWriter import_writer(
         options_.generate_for_named_framework,
         options_.named_framework_to_proto_path_mappings_path,
+        options_.runtime_import_prefix,
         is_bundled_proto_);
-    const string header_extension(kHeaderExtension);
+    const std::string header_extension(kHeaderExtension);
     for (int i = 0; i < file_->public_dependency_count(); i++) {
       import_writer.AddFile(file_->public_dependency(i), header_extension);
     }
@@ -263,11 +264,11 @@
       "CF_EXTERN_C_BEGIN\n"
       "\n");
 
-  std::set<string> fwd_decls;
+  std::set<std::string> fwd_decls;
   for (const auto& generator : message_generators_) {
     generator->DetermineForwardDeclarations(&fwd_decls);
   }
-  for (std::set<string>::const_iterator i(fwd_decls.begin());
+  for (std::set<std::string>::const_iterator i(fwd_decls.begin());
        i != fwd_decls.end(); ++i) {
     printer->Print("$value$;\n", "value", *i);
   }
@@ -335,10 +336,10 @@
       "// @@protoc_insertion_point(global_scope)\n");
 }
 
-void FileGenerator::GenerateSource(io::Printer *printer) {
+void FileGenerator::GenerateSource(io::Printer* printer) {
   // #import the runtime support.
-  std::set<string> headers;
-  headers.insert("GPBProtocolBuffers_RuntimeSupport.h");
+  std::vector<std::string> headers;
+  headers.push_back("GPBProtocolBuffers_RuntimeSupport.h");
   PrintFileRuntimePreamble(printer, headers);
 
   // Enums use atomic in the generated code, so add the system import as needed.
@@ -355,15 +356,16 @@
     ImportWriter import_writer(
         options_.generate_for_named_framework,
         options_.named_framework_to_proto_path_mappings_path,
+        options_.runtime_import_prefix,
         is_bundled_proto_);
-    const string header_extension(kHeaderExtension);
+    const std::string header_extension(kHeaderExtension);
 
     // #import the header for this proto file.
     import_writer.AddFile(file_, header_extension);
 
     // #import the headers for anything that a plain dependency of this proto
     // file (that means they were just an include, not a "public" include).
-    std::set<string> public_import_names;
+    std::set<std::string> public_import_names;
     for (int i = 0; i < file_->public_dependency_count(); i++) {
       public_import_names.insert(file_->public_dependency(i)->name());
     }
@@ -379,7 +381,7 @@
     // imported so it can get merged into the root's extensions registry.
     // See the Note by CollectMinimalFileDepsContainingExtensions before
     // changing this.
-    for (std::vector<const FileDescriptor *>::iterator iter =
+    for (std::vector<const FileDescriptor*>::iterator iter =
              deps_with_extensions.begin();
          iter != deps_with_extensions.end(); ++iter) {
       if (!IsDirectDependency(*iter, file_)) {
@@ -398,7 +400,7 @@
     }
   }
 
-  std::set<string> fwd_decls;
+  std::set<std::string> fwd_decls;
   for (const auto& generator : message_generators_) {
     generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
   }
@@ -419,7 +421,7 @@
       "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
   if (includes_oneof) {
     // The generated code for oneof's uses direct ivar access, suppress the
-    // warning incase developer turn that on in the context they compile the
+    // warning in case developer turn that on in the context they compile the
     // generated code.
     printer->Print(
         "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n");
@@ -496,10 +498,10 @@
     } else {
       printer->Print(
           "// Merge in the imports (direct or indirect) that defined extensions.\n");
-      for (std::vector<const FileDescriptor *>::iterator iter =
+      for (std::vector<const FileDescriptor*>::iterator iter =
                deps_with_extensions.begin();
            iter != deps_with_extensions.end(); ++iter) {
-        const string root_class_name(FileClassName((*iter)));
+        const std::string root_class_name(FileClassName((*iter)));
         printer->Print(
             "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
             "dependency", root_class_name);
@@ -529,7 +531,7 @@
 
   // File descriptor only needed if there are messages to use it.
   if (!message_generators_.empty()) {
-    std::map<string, string> vars;
+    std::map<std::string, std::string> vars;
     vars["root_class_name"] = root_class_name_;
     vars["package"] = file_->package();
     vars["objc_prefix"] = FileClassPrefix(file_);
@@ -590,48 +592,16 @@
 // files. This currently only supports the runtime coming from a framework
 // as defined by the official CocoaPod.
 void FileGenerator::PrintFileRuntimePreamble(
-    io::Printer* printer, const std::set<string>& headers_to_import) const {
+    io::Printer* printer,
+    const std::vector<std::string>& headers_to_import) const {
   printer->Print(
       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
       "// source: $filename$\n"
       "\n",
       "filename", file_->name());
-
-  const string framework_name(ProtobufLibraryFrameworkName);
-  const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
-
-  printer->Print(
-      "// This CPP symbol can be defined to use imports that match up to the framework\n"
-      "// imports needed when using CocoaPods.\n"
-      "#if !defined($cpp_symbol$)\n"
-      " #define $cpp_symbol$ 0\n"
-      "#endif\n"
-      "\n"
-      "#if $cpp_symbol$\n",
-      "cpp_symbol", cpp_symbol);
-
-
-  for (std::set<string>::const_iterator iter = headers_to_import.begin();
-       iter != headers_to_import.end(); ++iter) {
-    printer->Print(
-        " #import <$framework_name$/$header$>\n",
-        "header", *iter,
-        "framework_name", framework_name);
-  }
-
-  printer->Print(
-      "#else\n");
-
-  for (std::set<string>::const_iterator iter = headers_to_import.begin();
-       iter != headers_to_import.end(); ++iter) {
-    printer->Print(
-        " #import \"$header$\"\n",
-        "header", *iter);
-  }
-
-  printer->Print(
-      "#endif\n"
-      "\n");
+  ImportWriter::PrintRuntimeImports(
+      printer, headers_to_import, options_.runtime_import_prefix, true);
+  printer->Print("\n");
 }
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
index fd57263..87258a3 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -58,11 +58,9 @@
   void GenerateSource(io::Printer* printer);
   void GenerateHeader(io::Printer* printer);
 
-  const string& RootClassName() const { return root_class_name_; }
-
  private:
   const FileDescriptor* file_;
-  string root_class_name_;
+  std::string root_class_name_;
   bool is_bundled_proto_;
 
   std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
@@ -72,7 +70,8 @@
   const Options options_;
 
   void PrintFileRuntimePreamble(
-      io::Printer* printer, const std::set<string>& headers_to_import) const;
+      io::Printer* printer,
+      const std::vector<std::string>& headers_to_import) const;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
index 25338ad..d5a2b6b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -28,7 +28,10 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include <fstream>
 #include <iostream>
+#include <string>
+#include <unordered_set>
 #include <google/protobuf/compiler/objectivec/objectivec_generator.h>
 #include <google/protobuf/compiler/objectivec/objectivec_file.h>
 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
@@ -50,17 +53,17 @@
 }
 
 bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
-                                   const string& parameter,
+                                   const std::string& parameter,
                                    GeneratorContext* context,
-                                   string* error) const {
+                                   std::string* error) const {
   *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
   return false;
 }
 
-bool ObjectiveCGenerator::GenerateAll(const std::vector<const FileDescriptor*>& files,
-                                      const string& parameter,
-                                      GeneratorContext* context,
-                                      string* error) const {
+bool ObjectiveCGenerator::GenerateAll(
+    const std::vector<const FileDescriptor*>& files,
+    const std::string& parameter, GeneratorContext* context,
+    std::string* error) const {
   // -----------------------------------------------------------------
   // Parse generator options. These options are passed to the compiler using the
   // --objc_opt flag. The options are passed as a comma separated list of
@@ -71,7 +74,7 @@
 
   Options generation_options;
 
-  std::vector<std::pair<string, string> > options;
+  std::vector<std::pair<std::string, std::string> > options;
   ParseGeneratorParameter(parameter, &options);
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "expected_prefixes_path") {
@@ -93,8 +96,11 @@
       // A semicolon delimited string that lists the paths of .proto files to
       // exclude from the package prefix validations (expected_prefixes_path).
       // This is provided as an "out", to skip some files being checked.
-      SplitStringUsing(options[i].second, ";",
-                       &generation_options.expected_prefixes_suppressions);
+      for (StringPiece split_piece : Split(
+               options[i].second, ";", true)) {
+        generation_options.expected_prefixes_suppressions.push_back(
+            std::string(split_piece));
+      }
     } else if (options[i].first == "generate_for_named_framework") {
       // The name of the framework that protos are being generated for. This
       // will cause the #import statements to be framework based using this
@@ -120,13 +126,48 @@
       // Any number of files can be listed for a framework, just separate them
       // with commas.
       //
-      // There can be multiple lines listing the same frameworkName incase it
+      // There can be multiple lines listing the same frameworkName in case it
       // has a lot of proto files included in it; having multiple lines makes
       // things easier to read. If a proto file is not configured in the
       // mappings file, it will use the default framework name if one was passed
       // with generate_for_named_framework, or the relative path to it's include
       // path otherwise.
       generation_options.named_framework_to_proto_path_mappings_path = options[i].second;
+    } else if (options[i].first == "runtime_import_prefix") {
+      // Path to use as a prefix on #imports of runtime provided headers in the
+      // generated files. When integrating ObjC protos into a build system,
+      // this can be used to avoid having to add the runtime directory to the
+      // header search path since the generate #import will be more complete.
+      generation_options.runtime_import_prefix =
+          StripSuffixString(options[i].second, "/");
+    } else if (options[i].first == "use_package_as_prefix") {
+      // Controls how the symbols should be prefixed to avoid symbols
+      // collisions. The objc_class_prefix file option is always honored, this
+      // is just what to do if that isn't set. The available options are:
+      //   "no": Not prefixed (the existing mode).
+      //   "yes": Make a prefix out of the proto package.
+      std::string upper_value(options[i].second);
+      UpperString(&upper_value);
+      if (upper_value == "NO") {
+        SetUseProtoPackageAsDefaultPrefix(false);
+      } else if (upper_value == "YES") {
+        SetUseProtoPackageAsDefaultPrefix(true);
+      } else {
+        *error = "error: Unknown use_package_as_prefix: " + options[i].second;
+        return false;
+      }
+    } else if (options[i].first == "proto_package_prefix_exceptions_path") {
+      // Path to find a file containing the list of proto package names that are
+      // exceptions when use_package_as_prefix is enabled. This can be used to
+      // migrate packages one at a time to use_package_as_prefix since there
+      // are likely code updates needed with each one.
+      //
+      // The format of the file is:
+      //   - An entry is a line of "proto.package.name".
+      //   - Comments start with "#".
+      //   - A comment can go on a line after a expected package/prefix pair.
+      //     (i.e. - "some.proto.package # comment")
+      SetProtoPackagePrefixExceptionList(options[i].second);
     } else {
       *error = "error: Unknown generator option: " + options[i].first;
       return false;
@@ -135,6 +176,25 @@
 
   // -----------------------------------------------------------------
 
+  // These are not official generation options and could be removed/changed in
+  // the future and doing that won't count as a breaking change.
+  bool headers_only = getenv("GPB_OBJC_HEADERS_ONLY") != NULL;
+  std::unordered_set<std::string> skip_impls;
+  if (getenv("GPB_OBJC_SKIP_IMPLS_FILE") != NULL) {
+    std::ifstream skip_file(getenv("GPB_OBJC_SKIP_IMPLS_FILE"));
+    if (skip_file.is_open()) {
+      std::string line;
+      while (std::getline(skip_file, line)) {
+        skip_impls.insert(line);
+      }
+    } else {
+      *error = "error: Failed to open GPB_OBJC_SKIP_IMPLS_FILE file";
+      return false;
+    }
+  }
+
+  // -----------------------------------------------------------------
+
   // Validate the objc prefix/package pairings.
   if (!ValidateObjCClassPrefixes(files, generation_options, error)) {
     // *error will have been filled in.
@@ -144,7 +204,7 @@
   for (int i = 0; i < files.size(); i++) {
     const FileDescriptor* file = files[i];
     FileGenerator file_generator(file, generation_options);
-    string filepath = FilePath(file);
+    std::string filepath = FilePath(file);
 
     // Generate header.
     {
@@ -155,7 +215,7 @@
     }
 
     // Generate m file.
-    {
+    if (!headers_only && skip_impls.count(file->name()) == 0) {
       std::unique_ptr<io::ZeroCopyOutputStream> output(
           context->Open(filepath + ".pbobjc.m"));
       io::Printer printer(output.get(), '$');
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
index d10efc2..1dbc666 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -57,15 +57,16 @@
   ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete;
 
   // implements CodeGenerator ----------------------------------------
-  bool HasGenerateAll() const;
-  bool Generate(const FileDescriptor* file,
-                const string& parameter,
-                GeneratorContext* context,
-                string* error) const;
+  bool HasGenerateAll() const override;
+  bool Generate(const FileDescriptor* file, const std::string& parameter,
+                GeneratorContext* context, std::string* error) const override;
   bool GenerateAll(const std::vector<const FileDescriptor*>& files,
-                   const string& parameter,
-                   GeneratorContext* context,
-                   string* error) const;
+                   const std::string& parameter, GeneratorContext* context,
+                   std::string* error) const override;
+
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 638d7b7..78491d2 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -41,6 +41,7 @@
 #include <unordered_set>
 #include <vector>
 
+#include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
 #include <google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -70,6 +71,102 @@
 #endif
 }  // namespace port
 
+namespace {
+
+class SimpleLineCollector : public LineConsumer {
+ public:
+  SimpleLineCollector(std::unordered_set<std::string>* inout_set)
+      : set_(inout_set) {}
+
+  virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override {
+    set_->insert(std::string(line));
+    return true;
+  }
+
+ private:
+  std::unordered_set<std::string>* set_;
+};
+
+class PrefixModeStorage {
+ public:
+  PrefixModeStorage();
+
+  bool use_package_name() const { return use_package_name_; }
+  void set_use_package_name(bool on_or_off) { use_package_name_ = on_or_off; }
+
+  const std::string exception_path() const { return exception_path_; }
+  void set_exception_path(const std::string& path) {
+    exception_path_ = path;
+    exceptions_.clear();
+  }
+
+  bool is_package_exempted(const std::string& package);
+
+ private:
+  bool use_package_name_;
+  std::string exception_path_;
+  std::unordered_set<std::string> exceptions_;
+};
+
+PrefixModeStorage::PrefixModeStorage() {
+  // Even thought there are generation options, have an env back door since some
+  // of these helpers could be used in other plugins.
+
+  const char* use_package_cstr = getenv("GPB_OBJC_USE_PACKAGE_AS_PREFIX");
+  use_package_name_ =
+    (use_package_cstr && (std::string("YES") == ToUpper(use_package_cstr)));
+
+  const char* exception_path = getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH");
+  if (exception_path) {
+    exception_path_ = exception_path;
+  }
+}
+
+bool PrefixModeStorage::is_package_exempted(const std::string& package) {
+  if (exceptions_.empty() && !exception_path_.empty()) {
+    std::string error_str;
+    SimpleLineCollector collector(&exceptions_);
+    if (!ParseSimpleFile(exception_path_, &collector, &error_str)) {
+      if (error_str.empty()) {
+        error_str = std::string("protoc:0: warning: Failed to parse")
+           + std::string(" package prefix exceptions file: ")
+           + exception_path_;
+      }
+      std::cerr << error_str << std::endl;
+      std::cerr.flush();
+      exceptions_.clear();
+    }
+
+    // If the file was empty put something in it so it doesn't get reloaded over
+    // and over.
+    if (exceptions_.empty()) {
+      exceptions_.insert("<not a real package>");
+    }
+  }
+
+  return exceptions_.count(package) != 0;
+}
+
+PrefixModeStorage g_prefix_mode;
+
+}  // namespace
+
+bool UseProtoPackageAsDefaultPrefix() {
+  return g_prefix_mode.use_package_name();
+}
+
+void SetUseProtoPackageAsDefaultPrefix(bool on_or_off) {
+  g_prefix_mode.set_use_package_name(on_or_off);
+}
+
+std::string GetProtoPackagePrefixExceptionList() {
+  return g_prefix_mode.exception_path();
+}
+
+void SetProtoPackagePrefixExceptionList(const std::string& file_path) {
+  g_prefix_mode.set_exception_path(file_path);
+}
+
 Options::Options() {
   // Default is the value of the env for the package prefixes.
   const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
@@ -78,14 +175,16 @@
   }
   const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
   if (suppressions) {
-    SplitStringUsing(suppressions, ";", &expected_prefixes_suppressions);
+    expected_prefixes_suppressions =
+        Split(suppressions, ";", true);
   }
 }
 
 namespace {
 
-std::unordered_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
-  std::unordered_set<string> result;
+std::unordered_set<std::string> MakeWordsMap(const char* const words[],
+                                             size_t num_words) {
+  std::unordered_set<std::string> result;
   for (int i = 0; i < num_words; i++) {
     result.insert(words[i]);
   }
@@ -94,7 +193,7 @@
 
 const char* const kUpperSegmentsList[] = {"url", "http", "https"};
 
-std::unordered_set<string> kUpperSegments =
+std::unordered_set<std::string> kUpperSegments =
     MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
 
 bool ascii_isnewline(char c) {
@@ -104,9 +203,10 @@
 // Internal helper for name handing.
 // Do not expose this outside of helpers, stick to having functions for specific
 // cases (ClassName(), FieldName()), so there is always consistent suffix rules.
-string UnderscoresToCamelCase(const string& input, bool first_capitalized) {
-  std::vector<string> values;
-  string current;
+std::string UnderscoresToCamelCase(const std::string& input,
+                                   bool first_capitalized) {
+  std::vector<std::string> values;
+  std::string current;
 
   bool last_char_was_number = false;
   bool last_char_was_lower = false;
@@ -144,10 +244,11 @@
   }
   values.push_back(current);
 
-  string result;
+  std::string result;
   bool first_segment_forces_upper = false;
-  for (std::vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
-    string value = *i;
+  for (std::vector<std::string>::iterator i = values.begin(); i != values.end();
+       ++i) {
+    std::string value = *i;
     bool all_upper = (kUpperSegments.count(value) > 0);
     if (all_upper && (result.length() == 0)) {
       first_segment_forces_upper = true;
@@ -208,6 +309,10 @@
   // Not a keyword, but will break you
   "NULL",
 
+  // C88+ specs call for these to be macros, so depending on what they are
+  // defined to be it can lead to odd errors for some Xcode/SDK versions.
+  "stdin", "stdout", "stderr",
+
   // Objective-C Runtime typedefs
   // From <obc/runtime.h>
   "Category", "Ivar", "Method", "Protocol",
@@ -233,7 +338,7 @@
 // but this verifies and allows for future expansion if we decide to redefine what a
 // reserved C identifier is (for example the GNU list
 // https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html )
-bool IsReservedCIdentifier(const string& input) {
+bool IsReservedCIdentifier(const std::string& input) {
   if (input.length() > 2) {
     if (input.at(0) == '_') {
       if (isupper(input.at(1)) || input.at(1) == '_') {
@@ -244,15 +349,15 @@
   return false;
 }
 
-string SanitizeNameForObjC(const string& prefix,
-                           const string& input,
-                           const string& extension,
-                           string* out_suffix_added) {
-  static const std::unordered_set<string> kReservedWords =
+std::string SanitizeNameForObjC(const std::string& prefix,
+                           const std::string& input,
+                           const std::string& extension,
+                           std::string* out_suffix_added) {
+  static const std::unordered_set<std::string> kReservedWords =
       MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
-  static const std::unordered_set<string> kNSObjectMethods =
+  static const std::unordered_set<std::string> kNSObjectMethods =
       MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList));
-  string sanitized;
+  std::string sanitized;
   // We add the prefix in the cases where the string is missing a prefix.
   // We define "missing a prefix" as where 'input':
   // a) Doesn't start with the prefix or
@@ -277,7 +382,7 @@
   return sanitized;
 }
 
-string NameFromFieldDescriptor(const FieldDescriptor* field) {
+std::string NameFromFieldDescriptor(const FieldDescriptor* field) {
   if (field->type() == FieldDescriptor::TYPE_GROUP) {
     return field->message_type()->name();
   } else {
@@ -285,9 +390,10 @@
   }
 }
 
-void PathSplit(const string& path, string* directory, string* basename) {
-  string::size_type last_slash = path.rfind('/');
-  if (last_slash == string::npos) {
+void PathSplit(const std::string& path, std::string* directory,
+               std::string* basename) {
+  std::string::size_type last_slash = path.rfind('/');
+  if (last_slash == std::string::npos) {
     if (directory) {
       *directory = "";
     }
@@ -304,7 +410,7 @@
   }
 }
 
-bool IsSpecialName(const string& name, const string* special_names,
+bool IsSpecialName(const std::string& name, const std::string* special_names,
                    size_t count) {
   for (size_t i = 0; i < count; ++i) {
     size_t length = special_names[i].length();
@@ -322,7 +428,7 @@
   return false;
 }
 
-string GetZeroEnumNameForFlagType(const FlagType flag_type) {
+std::string GetZeroEnumNameForFlagType(const FlagType flag_type) {
   switch(flag_type) {
     case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
       return "GPBDescriptorInitializationFlag_None";
@@ -336,7 +442,7 @@
   }
 }
 
-string GetEnumNameForFlagType(const FlagType flag_type) {
+std::string GetEnumNameForFlagType(const FlagType flag_type) {
   switch(flag_type) {
     case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
       return "GPBDescriptorInitializationFlags";
@@ -346,25 +452,26 @@
       return "GPBFieldFlags";
     default:
       GOOGLE_LOG(FATAL) << "Can't get here.";
-      return string();
+      return std::string();
+  }
+}
+
+void MaybeUnQuote(StringPiece* input) {
+  if ((input->length() >= 2) &&
+      ((*input->data() == '\'' || *input->data() == '"')) &&
+      ((*input)[input->length() - 1] == *input->data())) {
+    input->remove_prefix(1);
+    input->remove_suffix(1);
   }
 }
 
 }  // namespace
 
 // Escape C++ trigraphs by escaping question marks to \?
-string EscapeTrigraphs(const string& to_escape) {
+std::string EscapeTrigraphs(const std::string& to_escape) {
   return StringReplace(to_escape, "?", "\\?", true);
 }
 
-string StripProto(const string& filename) {
-  if (HasSuffixString(filename, ".protodevel")) {
-    return StripSuffixString(filename, ".protodevel");
-  } else {
-    return StripSuffixString(filename, ".proto");
-  }
-}
-
 void TrimWhitespace(StringPiece* input) {
   while (!input->empty() && ascii_isspace(*input->data())) {
     input->remove_prefix(1);
@@ -374,38 +481,68 @@
   }
 }
 
-
-bool IsRetainedName(const string& name) {
+bool IsRetainedName(const std::string& name) {
   // List of prefixes from
   // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
-  static const string retained_names[] = {"new", "alloc", "copy",
-                                          "mutableCopy"};
+  static const std::string retained_names[] = {"new", "alloc", "copy",
+                                               "mutableCopy"};
   return IsSpecialName(name, retained_names,
                        sizeof(retained_names) / sizeof(retained_names[0]));
 }
 
-bool IsInitName(const string& name) {
-  static const string init_names[] = {"init"};
+bool IsInitName(const std::string& name) {
+  static const std::string init_names[] = {"init"};
   return IsSpecialName(name, init_names,
                        sizeof(init_names) / sizeof(init_names[0]));
 }
 
-string BaseFileName(const FileDescriptor* file) {
-  string basename;
+std::string BaseFileName(const FileDescriptor* file) {
+  std::string basename;
   PathSplit(file->name(), NULL, &basename);
   return basename;
 }
 
-string FileClassPrefix(const FileDescriptor* file) {
-  // Default is empty string, no need to check has_objc_class_prefix.
-  string result = file->options().objc_class_prefix();
+std::string FileClassPrefix(const FileDescriptor* file) {
+  // Always honor the file option.
+  if (file->options().has_objc_class_prefix()) {
+    return file->options().objc_class_prefix();
+  }
+
+  // If package prefix isn't enabled or no package, done.
+  if (!g_prefix_mode.use_package_name() || file->package().empty()) {
+    return "";
+  }
+
+  // If the package is in the exceptions list, done.
+  if (g_prefix_mode.is_package_exempted(file->package())) {
+    return "";
+  }
+
+  // Transform the package into a prefix: use the dot segments as part,
+  // camelcase each one and then join them with underscores, and add an
+  // underscore at the end.
+  std::string result;
+  const std::vector<std::string> segments = Split(file->package(), ".", true);
+  for (const auto& segment : segments) {
+    const std::string part = UnderscoresToCamelCase(segment, true);
+    if (part.empty()) {
+      continue;
+    }
+    if (!result.empty()) {
+      result.append("_");
+    }
+    result.append(part);
+  }
+  if (!result.empty()) {
+    result.append("_");
+  }
   return result;
 }
 
-string FilePath(const FileDescriptor* file) {
-  string output;
-  string basename;
-  string directory;
+std::string FilePath(const FileDescriptor* file) {
+  std::string output;
+  std::string basename;
+  std::string directory;
   PathSplit(file->name(), &directory, &basename);
   if (directory.length() > 0) {
     output = directory + "/";
@@ -419,10 +556,10 @@
   return output;
 }
 
-string FilePathBasename(const FileDescriptor* file) {
-  string output;
-  string basename;
-  string directory;
+std::string FilePathBasename(const FileDescriptor* file) {
+  std::string output;
+  std::string basename;
+  std::string directory;
   PathSplit(file->name(), &directory, &basename);
   basename = StripProto(basename);
 
@@ -432,16 +569,17 @@
   return output;
 }
 
-string FileClassName(const FileDescriptor* file) {
-  const string prefix = FileClassPrefix(file);
-  const string name = UnderscoresToCamelCase(StripProto(BaseFileName(file)), true) + "Root";
+std::string FileClassName(const FileDescriptor* file) {
+  const std::string prefix = FileClassPrefix(file);
+  const std::string name =
+      UnderscoresToCamelCase(StripProto(BaseFileName(file)), true) + "Root";
   // There aren't really any reserved words that end in "Root", but playing
   // it safe and checking.
   return SanitizeNameForObjC(prefix, name, "_RootClass", NULL);
 }
 
-string ClassNameWorker(const Descriptor* descriptor) {
-  string name;
+std::string ClassNameWorker(const Descriptor* descriptor) {
+  std::string name;
   if (descriptor->containing_type() != NULL) {
     name = ClassNameWorker(descriptor->containing_type());
     name += "_";
@@ -449,8 +587,8 @@
   return name + descriptor->name();
 }
 
-string ClassNameWorker(const EnumDescriptor* descriptor) {
-  string name;
+std::string ClassNameWorker(const EnumDescriptor* descriptor) {
+  std::string name;
   if (descriptor->containing_type() != NULL) {
     name = ClassNameWorker(descriptor->containing_type());
     name += "_";
@@ -458,19 +596,20 @@
   return name + descriptor->name();
 }
 
-string ClassName(const Descriptor* descriptor) {
+std::string ClassName(const Descriptor* descriptor) {
   return ClassName(descriptor, NULL);
 }
 
-string ClassName(const Descriptor* descriptor, string* out_suffix_added) {
+std::string ClassName(const Descriptor* descriptor,
+                      std::string* out_suffix_added) {
   // 1. Message names are used as is (style calls for CamelCase, trust it).
   // 2. Check for reserved word at the very end and then suffix things.
-  const string prefix = FileClassPrefix(descriptor->file());
-  const string name = ClassNameWorker(descriptor);
+  const std::string prefix = FileClassPrefix(descriptor->file());
+  const std::string name = ClassNameWorker(descriptor);
   return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added);
 }
 
-string EnumName(const EnumDescriptor* descriptor) {
+std::string EnumName(const EnumDescriptor* descriptor) {
   // 1. Enum names are used as is (style calls for CamelCase, trust it).
   // 2. Check for reserved word at the every end and then suffix things.
   //      message Fixed {
@@ -479,27 +618,28 @@
   //      ...
   //      }
   //    yields Fixed_Class, Fixed_Size.
-  const string prefix = FileClassPrefix(descriptor->file());
-  const string name = ClassNameWorker(descriptor);
+  const std::string prefix = FileClassPrefix(descriptor->file());
+  const std::string name = ClassNameWorker(descriptor);
   return SanitizeNameForObjC(prefix, name, "_Enum", NULL);
 }
 
-string EnumValueName(const EnumValueDescriptor* descriptor) {
+std::string EnumValueName(const EnumValueDescriptor* descriptor) {
   // Because of the Switch enum compatibility, the name on the enum has to have
   // the suffix handing, so it slightly diverges from how nested classes work.
   //   enum Fixed {
   //     FOO = 1
   //   }
   // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo).
-  const string class_name = EnumName(descriptor->type());
-  const string value_str = UnderscoresToCamelCase(descriptor->name(), true);
-  const string name = class_name + "_" + value_str;
+  const std::string class_name = EnumName(descriptor->type());
+  const std::string value_str =
+      UnderscoresToCamelCase(descriptor->name(), true);
+  const std::string name = class_name + "_" + value_str;
   // There aren't really any reserved words with an underscore and a leading
   // capital letter, but playing it safe and checking.
   return SanitizeNameForObjC("", name, "_Value", NULL);
 }
 
-string EnumValueShortName(const EnumValueDescriptor* descriptor) {
+std::string EnumValueShortName(const EnumValueDescriptor* descriptor) {
   // Enum value names (EnumValueName above) are the enum name turned into
   // a class name and then the value name is CamelCased and concatenated; the
   // whole thing then gets sanitized for reserved words.
@@ -512,14 +652,14 @@
   // So the right way to get the short name is to take the full enum name
   // and then strip off the enum name (leaving the value name and anything
   // done by sanitize).
-  const string class_name = EnumName(descriptor->type());
-  const string long_name_prefix = class_name + "_";
-  const string long_name = EnumValueName(descriptor);
+  const std::string class_name = EnumName(descriptor->type());
+  const std::string long_name_prefix = class_name + "_";
+  const std::string long_name = EnumValueName(descriptor);
   return StripPrefixString(long_name, long_name_prefix);
 }
 
-string UnCamelCaseEnumShortName(const string& name) {
-  string result;
+std::string UnCamelCaseEnumShortName(const std::string& name) {
+  std::string result;
   for (int i = 0; i < name.size(); i++) {
     char c = name[i];
     if (i > 0 && ascii_isupper(c)) {
@@ -530,15 +670,15 @@
   return result;
 }
 
-string ExtensionMethodName(const FieldDescriptor* descriptor) {
-  const string name = NameFromFieldDescriptor(descriptor);
-  const string result = UnderscoresToCamelCase(name, false);
+std::string ExtensionMethodName(const FieldDescriptor* descriptor) {
+  const std::string name = NameFromFieldDescriptor(descriptor);
+  const std::string result = UnderscoresToCamelCase(name, false);
   return SanitizeNameForObjC("", result, "_Extension", NULL);
 }
 
-string FieldName(const FieldDescriptor* field) {
-  const string name = NameFromFieldDescriptor(field);
-  string result = UnderscoresToCamelCase(name, false);
+std::string FieldName(const FieldDescriptor* field) {
+  const std::string name = NameFromFieldDescriptor(field);
+  std::string result = UnderscoresToCamelCase(name, false);
   if (field->is_repeated() && !field->is_map()) {
     // Add "Array" before do check for reserved worlds.
     result += "Array";
@@ -551,50 +691,50 @@
   return SanitizeNameForObjC("", result, "_p", NULL);
 }
 
-string FieldNameCapitalized(const FieldDescriptor* field) {
+std::string FieldNameCapitalized(const FieldDescriptor* field) {
   // Want the same suffix handling, so upcase the first letter of the other
   // name.
-  string result = FieldName(field);
+  std::string result = FieldName(field);
   if (result.length() > 0) {
     result[0] = ascii_toupper(result[0]);
   }
   return result;
 }
 
-string OneofEnumName(const OneofDescriptor* descriptor) {
+std::string OneofEnumName(const OneofDescriptor* descriptor) {
   const Descriptor* fieldDescriptor = descriptor->containing_type();
-  string name = ClassName(fieldDescriptor);
+  std::string name = ClassName(fieldDescriptor);
   name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase";
   // No sanitize needed because the OS never has names that end in _OneOfCase.
   return name;
 }
 
-string OneofName(const OneofDescriptor* descriptor) {
-  string name = UnderscoresToCamelCase(descriptor->name(), false);
+std::string OneofName(const OneofDescriptor* descriptor) {
+  std::string name = UnderscoresToCamelCase(descriptor->name(), false);
   // No sanitize needed because it gets OneOfCase added and that shouldn't
   // ever conflict.
   return name;
 }
 
-string OneofNameCapitalized(const OneofDescriptor* descriptor) {
+std::string OneofNameCapitalized(const OneofDescriptor* descriptor) {
   // Use the common handling and then up-case the first letter.
-  string result = OneofName(descriptor);
+  std::string result = OneofName(descriptor);
   if (result.length() > 0) {
     result[0] = ascii_toupper(result[0]);
   }
   return result;
 }
 
-string ObjCClass(const string& class_name) {
-  return string("GPBObjCClass(") + class_name + ")";
+std::string ObjCClass(const std::string& class_name) {
+  return std::string("GPBObjCClass(") + class_name + ")";
 }
 
-string ObjCClassDeclaration(const string& class_name) {
-  return string("GPBObjCClassDeclaration(") + class_name + ");";
+std::string ObjCClassDeclaration(const std::string& class_name) {
+  return std::string("GPBObjCClassDeclaration(") + class_name + ");";
 }
 
-string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) {
-  string worker(name);
+std::string UnCamelCaseFieldName(const std::string& name, const FieldDescriptor* field) {
+  std::string worker(name);
   if (HasSuffixString(worker, "_p")) {
     worker = StripSuffixString(worker, "_p");
   }
@@ -609,7 +749,7 @@
     }
     return worker;
   } else {
-    string result;
+    std::string result;
     for (int i = 0; i < worker.size(); i++) {
       char c = worker[i];
       if (ascii_isupper(c)) {
@@ -625,7 +765,7 @@
   }
 }
 
-string GetCapitalizedType(const FieldDescriptor* field) {
+std::string GetCapitalizedType(const FieldDescriptor* field) {
   switch (field->type()) {
     case FieldDescriptor::TYPE_INT32:
       return "Int32";
@@ -668,7 +808,7 @@
   // Some compilers report reaching end of function even though all cases of
   // the enum are handed in the switch.
   GOOGLE_LOG(FATAL) << "Can't get here.";
-  return string();
+  return std::string();
 }
 
 ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
@@ -742,7 +882,8 @@
   return !IsPrimitiveType(field);
 }
 
-static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) {
+static std::string HandleExtremeFloatingPoint(std::string val,
+                                              bool add_float_suffix) {
   if (val == "nan") {
     return "NAN";
   } else if (val == "inf") {
@@ -751,16 +892,16 @@
     return "-INFINITY";
   } else {
     // float strings with ., e or E need to have f appended
-    if (add_float_suffix &&
-        (val.find(".") != string::npos || val.find("e") != string::npos ||
-         val.find("E") != string::npos)) {
+    if (add_float_suffix && (val.find(".") != std::string::npos ||
+                             val.find("e") != std::string::npos ||
+                             val.find("E") != std::string::npos)) {
       val += "f";
     }
     return val;
   }
 }
 
-string GPBGenericValueFieldName(const FieldDescriptor* field) {
+std::string GPBGenericValueFieldName(const FieldDescriptor* field) {
   // Returns the field within the GPBGenericValue union to use for the given
   // field.
   if (field->is_repeated()) {
@@ -796,11 +937,11 @@
   // Some compilers report reaching end of function even though all cases of
   // the enum are handed in the switch.
   GOOGLE_LOG(FATAL) << "Can't get here.";
-  return string();
+  return std::string();
 }
 
 
-string DefaultValue(const FieldDescriptor* field) {
+std::string DefaultValue(const FieldDescriptor* field) {
   // Repeated fields don't have defaults.
   if (field->is_repeated()) {
     return "nil";
@@ -835,7 +976,7 @@
       return field->default_value_bool() ? "YES" : "NO";
     case FieldDescriptor::CPPTYPE_STRING: {
       const bool has_default_value = field->has_default_value();
-      const string& default_string = field->default_value_string();
+      const std::string& default_string = field->default_value_string();
       if (!has_default_value || default_string.length() == 0) {
         // If the field is defined as being the empty string,
         // then we will just assign to nil, as the empty string is the
@@ -852,7 +993,7 @@
         // Must convert to a standard byte order for packing length into
         // a cstring.
         uint32 length = ghtonl(default_string.length());
-        string bytes((const char*)&length, sizeof(length));
+        std::string bytes((const char*)&length, sizeof(length));
         bytes.append(default_string);
         return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
       } else {
@@ -868,7 +1009,7 @@
   // Some compilers report reaching end of function even though all cases of
   // the enum are handed in the switch.
   GOOGLE_LOG(FATAL) << "Can't get here.";
-  return string();
+  return std::string();
 }
 
 bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
@@ -901,7 +1042,7 @@
     case FieldDescriptor::CPPTYPE_BOOL:
       return field->default_value_bool();
     case FieldDescriptor::CPPTYPE_STRING: {
-      const string& default_string = field->default_value_string();
+      const std::string& default_string = field->default_value_string();
       return default_string.length() != 0;
     }
     case FieldDescriptor::CPPTYPE_ENUM:
@@ -916,14 +1057,14 @@
   return false;
 }
 
-string BuildFlagsString(const FlagType flag_type,
-                        const std::vector<string>& strings) {
+std::string BuildFlagsString(const FlagType flag_type,
+                             const std::vector<std::string>& strings) {
   if (strings.empty()) {
     return GetZeroEnumNameForFlagType(flag_type);
   } else if (strings.size() == 1) {
     return strings[0];
   }
-  string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
+  std::string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
   for (size_t i = 0; i != strings.size(); ++i) {
     if (i > 0) {
       string.append(" | ");
@@ -934,12 +1075,12 @@
   return string;
 }
 
-string BuildCommentsString(const SourceLocation& location,
+std::string BuildCommentsString(const SourceLocation& location,
                            bool prefer_single_line) {
-  const string& comments = location.leading_comments.empty()
+  const std::string& comments = location.leading_comments.empty()
                                ? location.trailing_comments
                                : location.leading_comments;
-  std::vector<string> lines;
+  std::vector<std::string> lines;
   lines = Split(comments, "\n", false);
   while (!lines.empty() && lines.back().empty()) {
     lines.pop_back();
@@ -949,10 +1090,10 @@
     return "";
   }
 
-  string prefix;
-  string suffix;
-  string final_comments;
-  string epilogue;
+  std::string prefix;
+  std::string suffix;
+  std::string final_comments;
+  std::string epilogue;
 
   bool add_leading_space = false;
 
@@ -968,7 +1109,7 @@
   }
 
   for (int i = 0; i < lines.size(); i++) {
-    string line = StripPrefixString(lines[i], " ");
+    std::string line = StripPrefixString(lines[i], " ");
     // HeaderDoc and appledoc use '\' and '@' for markers; escape them.
     line = StringReplace(line, "\\", "\\\\", true);
     line = StringReplace(line, "@", "\\@", true);
@@ -992,9 +1133,9 @@
 // use a different value; so it isn't as simple as a option.
 const char* const ProtobufLibraryFrameworkName = "Protobuf";
 
-string ProtobufFrameworkImportSymbol(const string& framework_name) {
+std::string ProtobufFrameworkImportSymbol(const std::string& framework_name) {
   // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS
-  string result = string("GPB_USE_");
+  std::string result = std::string("GPB_USE_");
   result += ToUpper(framework_name);
   result += "_FRAMEWORK_IMPORTS";
   return result;
@@ -1004,7 +1145,7 @@
   // We don't check the name prefix or proto package because some files
   // (descriptor.proto), aren't shipped generated by the library, so this
   // seems to be the safest way to only catch the ones shipped.
-  const string name = file->name();
+  const std::string name = file->name();
   if (name == "google/protobuf/any.proto" ||
       name == "google/protobuf/api.proto" ||
       name == "google/protobuf/duration.proto" ||
@@ -1043,36 +1184,37 @@
 
 class ExpectedPrefixesCollector : public LineConsumer {
  public:
-  ExpectedPrefixesCollector(std::map<string, string>* inout_package_to_prefix_map)
+  ExpectedPrefixesCollector(std::map<std::string, std::string>* inout_package_to_prefix_map)
       : prefix_map_(inout_package_to_prefix_map) {}
 
-  virtual bool ConsumeLine(const StringPiece& line, string* out_error);
+  virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override;
 
  private:
-  std::map<string, string>* prefix_map_;
+  std::map<std::string, std::string>* prefix_map_;
 };
 
 bool ExpectedPrefixesCollector::ConsumeLine(
-    const StringPiece& line, string* out_error) {
+    const StringPiece& line, std::string* out_error) {
   int offset = line.find('=');
   if (offset == StringPiece::npos) {
-    *out_error = string("Expected prefixes file line without equal sign: '") +
-                 string(line) + "'.";
+    *out_error = std::string("Expected prefixes file line without equal sign: '") +
+                 std::string(line) + "'.";
     return false;
   }
   StringPiece package = line.substr(0, offset);
   StringPiece prefix = line.substr(offset + 1);
   TrimWhitespace(&package);
   TrimWhitespace(&prefix);
+  MaybeUnQuote(&prefix);
   // Don't really worry about error checking the package/prefix for
   // being valid.  Assume the file is validated when it is created/edited.
-  (*prefix_map_)[string(package)] = string(prefix);
+  (*prefix_map_)[std::string(package)] = std::string(prefix);
   return true;
 }
 
-bool LoadExpectedPackagePrefixes(const Options &generation_options,
-                                 std::map<string, string>* prefix_map,
-                                 string* out_error) {
+bool LoadExpectedPackagePrefixes(const Options& generation_options,
+                                 std::map<std::string, std::string>* prefix_map,
+                                 std::string* out_error) {
   if (generation_options.expected_prefixes_path.empty()) {
     return true;
   }
@@ -1083,23 +1225,29 @@
 }
 
 bool ValidateObjCClassPrefix(
-    const FileDescriptor* file,
-    const string& expected_prefixes_path,
-    const std::map<string, string>& expected_package_prefixes,
-    string* out_error) {
-  const string prefix = file->options().objc_class_prefix();
-  const string package = file->package();
+    const FileDescriptor* file, const std::string& expected_prefixes_path,
+    const std::map<std::string, std::string>& expected_package_prefixes,
+    std::string* out_error) {
+  // Reminder: An explicit prefix option of "" is valid in case the default
+  // prefixing is set to use the proto package and a file needs to be generated
+  // without any prefix at all (for legacy reasons).
+
+  bool has_prefix = file->options().has_objc_class_prefix();
+  bool have_expected_prefix_file = !expected_prefixes_path.empty();
+
+  const std::string prefix = file->options().objc_class_prefix();
+  const std::string package = file->package();
 
   // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
   // error cases, so it seems to be ok to use as a back door for warnings.
 
   // Check: Error - See if there was an expected prefix for the package and
   // report if it doesn't match (wrong or missing).
-  std::map<string, string>::const_iterator package_match =
+  std::map<std::string, std::string>::const_iterator package_match =
       expected_package_prefixes.find(package);
   if (package_match != expected_package_prefixes.end()) {
     // There was an entry, and...
-    if (package_match->second == prefix) {
+    if (has_prefix && package_match->second == prefix) {
       // ...it matches.  All good, out of here!
       return true;
     } else {
@@ -1107,7 +1255,7 @@
       *out_error = "error: Expected 'option objc_class_prefix = \"" +
                    package_match->second + "\";' for package '" + package +
                    "' in '" + file->name() + "'";
-      if (prefix.length()) {
+      if (has_prefix) {
         *out_error += "; but found '" + prefix + "' instead";
       }
       *out_error += ".";
@@ -1116,25 +1264,79 @@
   }
 
   // If there was no prefix option, we're done at this point.
-  if (prefix.empty()) {
-    // No prefix, nothing left to check.
+  if (!has_prefix) {
     return true;
   }
 
+  // When the prefix is non empty, check it against the expected entries.
+  if (!prefix.empty() && have_expected_prefix_file) {
+    // For a non empty prefix, look for any other package that uses the prefix.
+    std::string other_package_for_prefix;
+    for (std::map<std::string, std::string>::const_iterator i =
+             expected_package_prefixes.begin();
+         i != expected_package_prefixes.end(); ++i) {
+      if (i->second == prefix) {
+        other_package_for_prefix = i->first;
+        break;
+      }
+    }
+
+    // Check: Warning - If the file does not have a package, check whether the
+    // prefix was declared is being used by another package or not. This is
+    // a special case for empty packages.
+    if (package.empty()) {
+      // The file does not have a package and ...
+      if (other_package_for_prefix.empty()) {
+        // ... no other package has declared that prefix.
+        std::cerr
+             << "protoc:0: warning: File '" << file->name() << "' has no "
+             << "package. Consider adding a new package to the proto and adding '"
+             << "new.package = " << prefix << "' to the expected prefixes file ("
+             << expected_prefixes_path << ")." << std::endl;
+        std::cerr.flush();
+      } else {
+        // ... another package has declared the same prefix.
+        std::cerr
+             << "protoc:0: warning: File '" << file->name() << "' has no package "
+             << "and package '" << other_package_for_prefix << "' already uses '"
+             << prefix << "' as its prefix. Consider either adding a new package "
+             << "to the proto, or reusing one of the packages already using this "
+             << "prefix in the expected prefixes file ("
+             << expected_prefixes_path << ")." << std::endl;
+        std::cerr.flush();
+      }
+      return true;
+    }
+
+    // Check: Error - Make sure the prefix wasn't expected for a different
+    // package (overlap is allowed, but it has to be listed as an expected
+    // overlap).
+    if (!other_package_for_prefix.empty()) {
+      *out_error =
+          "error: Found 'option objc_class_prefix = \"" + prefix +
+          "\";' in '" + file->name() +
+          "'; that prefix is already used for 'package " +
+          other_package_for_prefix + ";'. It can only be reused by listing " +
+          "it in the expected file (" +
+          expected_prefixes_path + ").";
+      return false;  // Only report first usage of the prefix.
+    }
+  } // !prefix.empty()
+
   // Check: Warning - Make sure the prefix is is a reasonable value according
   // to Apple's rules (the checks above implicitly whitelist anything that
   // doesn't meet these rules).
-  if (!ascii_isupper(prefix[0])) {
-    std::cerr << std::endl
+  if (!prefix.empty() && !ascii_isupper(prefix[0])) {
+    std::cerr
          << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
          << " it should start with a capital letter." << std::endl;
     std::cerr.flush();
   }
-  if (prefix.length() < 3) {
+  if (!prefix.empty() && prefix.length() < 3) {
     // Apple reserves 2 character prefixes for themselves. They do use some
     // 3 character prefixes, but they haven't updated the rules/docs.
-    std::cerr << std::endl
+    std::cerr
          << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
          << " Apple recommends they should be at least 3 characters long."
@@ -1142,60 +1344,10 @@
     std::cerr.flush();
   }
 
-  // Look for any other package that uses the same prefix.
-  string other_package_for_prefix;
-  for (std::map<string, string>::const_iterator i = expected_package_prefixes.begin();
-       i != expected_package_prefixes.end(); ++i) {
-    if (i->second == prefix) {
-      other_package_for_prefix = i->first;
-      break;
-    }
-  }
-
-  // Check: Warning - If the file does not have a package, check whether
-  // the prefix declared is being used by another package or not.
-  if (package.empty()) {
-    // The file does not have a package and ...
-    if (other_package_for_prefix.empty()) {
-      // ... no other package has declared that prefix.
-      std::cerr << std::endl
-           << "protoc:0: warning: File '" << file->name() << "' has no "
-           << "package. Consider adding a new package to the proto and adding '"
-           << "new.package = " << prefix << "' to the expected prefixes file ("
-           << expected_prefixes_path << ")." << std::endl;
-      std::cerr.flush();
-    } else {
-      // ... another package has declared the same prefix.
-      std::cerr << std::endl
-           << "protoc:0: warning: File '" << file->name() << "' has no package "
-           << "and package '" << other_package_for_prefix << "' already uses '"
-           << prefix << "' as its prefix. Consider either adding a new package "
-           << "to the proto, or reusing one of the packages already using this "
-           << "prefix in the expected prefixes file ("
-           << expected_prefixes_path << ")." << std::endl;
-      std::cerr.flush();
-    }
-    return true;
-  }
-
-  // Check: Error - Make sure the prefix wasn't expected for a different
-  // package (overlap is allowed, but it has to be listed as an expected
-  // overlap).
-  if (!other_package_for_prefix.empty()) {
-    *out_error =
-        "error: Found 'option objc_class_prefix = \"" + prefix +
-        "\";' in '" + file->name() +
-        "'; that prefix is already used for 'package " +
-        other_package_for_prefix + ";'. It can only be reused by listing " +
-        "it in the expected file (" +
-        expected_prefixes_path + ").";
-    return false;  // Only report first usage of the prefix.
-  }
-
   // Check: Warning - If the given package/prefix pair wasn't expected, issue a
-  // warning issue a warning suggesting it gets added to the file.
-  if (!expected_package_prefixes.empty()) {
-    std::cerr << std::endl
+  // warning suggesting it gets added to the file.
+  if (have_expected_prefix_file) {
+    std::cerr
          << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
          << " consider adding it to the expected prefixes file ("
@@ -1210,9 +1362,15 @@
 
 bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
                                const Options& generation_options,
-                               string* out_error) {
+                               std::string* out_error) {
+  // Allow a '-' as the path for the expected prefixes to completely disable
+  // even the most basic of checks.
+  if (generation_options.expected_prefixes_path == "-") {
+    return true;
+  }
+
   // Load the expected package prefixes, if available, to validate against.
-  std::map<string, string> expected_package_prefixes;
+  std::map<std::string, std::string> expected_package_prefixes;
   if (!LoadExpectedPackagePrefixes(generation_options,
                                    &expected_package_prefixes,
                                    out_error)) {
@@ -1246,8 +1404,8 @@
 TextFormatDecodeData::~TextFormatDecodeData() { }
 
 void TextFormatDecodeData::AddString(int32 key,
-                                     const string& input_for_decode,
-                                     const string& desired_output) {
+                                     const std::string& input_for_decode,
+                                     const std::string& desired_output) {
   for (std::vector<DataEntry>::const_iterator i = entries_.begin();
        i != entries_.end(); ++i) {
     if (i->first == key) {
@@ -1259,12 +1417,12 @@
     }
   }
 
-  const string& data = TextFormatDecodeData::DecodeDataForString(
+  const std::string& data = TextFormatDecodeData::DecodeDataForString(
       input_for_decode, desired_output);
   entries_.push_back(DataEntry(key, data));
 }
 
-string TextFormatDecodeData::Data() const {
+std::string TextFormatDecodeData::Data() const {
   std::ostringstream data_stringstream;
 
   if (num_entries() > 0) {
@@ -1295,20 +1453,20 @@
     Push();
     need_underscore_ = true;
   }
-  string Finish() {
+  std::string Finish() {
     Push();
     return decode_data_;
   }
 
  private:
-  static const uint8 kAddUnderscore = 0x80;
+  static constexpr uint8 kAddUnderscore = 0x80;
 
-  static const uint8 kOpAsIs        = 0x00;
-  static const uint8 kOpFirstUpper  = 0x40;
-  static const uint8 kOpFirstLower  = 0x20;
-  static const uint8 kOpAllUpper    = 0x60;
+  static constexpr uint8 kOpAsIs = 0x00;
+  static constexpr uint8 kOpFirstUpper = 0x40;
+  static constexpr uint8 kOpFirstLower = 0x20;
+  static constexpr uint8 kOpAllUpper = 0x60;
 
-  static const int kMaxSegmentLen     = 0x1f;
+  static constexpr int kMaxSegmentLen = 0x1f;
 
   void AddChar(const char desired) {
     ++segment_len_;
@@ -1351,7 +1509,7 @@
   uint8 op_;
   int segment_len_;
 
-  string decode_data_;
+  std::string decode_data_;
 };
 
 bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
@@ -1392,8 +1550,8 @@
 
 // If decode data can't be generated, a directive for the raw string
 // is used instead.
-string DirectDecodeString(const string& str) {
-  string result;
+std::string DirectDecodeString(const std::string& str) {
+  std::string result;
   result += (char)'\0';  // Marker for full string.
   result += str;
   result += (char)'\0';  // End of string.
@@ -1403,8 +1561,8 @@
 }  // namespace
 
 // static
-string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode,
-                                                 const string& desired_output) {
+std::string TextFormatDecodeData::DecodeDataForString(
+    const std::string& input_for_decode, const std::string& desired_output) {
   if (input_for_decode.empty() || desired_output.empty()) {
     std::cerr << "error: got empty string for making TextFormat data, input: \""
          << input_for_decode << "\", desired: \"" << desired_output << "\"."
@@ -1412,8 +1570,8 @@
     std::cerr.flush();
     abort();
   }
-  if ((input_for_decode.find('\0') != string::npos) ||
-      (desired_output.find('\0') != string::npos)) {
+  if ((input_for_decode.find('\0') != std::string::npos) ||
+      (desired_output.find('\0') != std::string::npos)) {
     std::cerr << "error: got a null char in a string for making TextFormat data,"
          << " input: \"" << CEscape(input_for_decode) << "\", desired: \""
          << CEscape(desired_output) << "\"." << std::endl;
@@ -1468,21 +1626,21 @@
   bool Finish();
 
   int last_line() const { return line_; }
-  string error_str() const { return error_str_; }
+  std::string error_str() const { return error_str_; }
 
  private:
   bool ParseLoop();
 
   LineConsumer* line_consumer_;
   int line_;
-  string error_str_;
+  std::string error_str_;
   StringPiece p_;
-  string leftover_;
+  std::string leftover_;
 };
 
 bool Parser::ParseChunk(StringPiece chunk) {
   if (!leftover_.empty()) {
-    leftover_ += string(chunk);
+    leftover_ += std::string(chunk);
     p_ = StringPiece(leftover_);
   } else {
     p_ = chunk;
@@ -1491,7 +1649,7 @@
   if (p_.empty()) {
     leftover_.clear();
   } else {
-    leftover_ = string(p_);
+    leftover_ = std::string(p_);
   }
   return result;
 }
@@ -1531,15 +1689,15 @@
 
 LineConsumer::~LineConsumer() {}
 
-bool ParseSimpleFile(
-    const string& path, LineConsumer* line_consumer, string* out_error) {
+bool ParseSimpleFile(const std::string& path, LineConsumer* line_consumer,
+                     std::string* out_error) {
   int fd;
   do {
     fd = posix::open(path.c_str(), O_RDONLY);
   } while (fd < 0 && errno == EINTR);
   if (fd < 0) {
-    *out_error =
-        string("error: Unable to open \"") + path + "\", " + strerror(errno);
+    *out_error = std::string("error: Unable to open \"") + path + "\", " +
+                 strerror(errno);
     return false;
   }
   io::FileInputStream file_stream(fd);
@@ -1555,7 +1713,7 @@
 
     if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
       *out_error =
-          string("error: ") + path +
+          std::string("error: ") + path +
           " Line " + StrCat(parser.last_line()) + ", " + parser.error_str();
       return false;
     }
@@ -1564,29 +1722,28 @@
 }
 
 ImportWriter::ImportWriter(
-  const string& generate_for_named_framework,
-  const string& named_framework_to_proto_path_mappings_path,
-  bool include_wkt_imports)
+    const std::string& generate_for_named_framework,
+    const std::string& named_framework_to_proto_path_mappings_path,
+    const std::string& runtime_import_prefix, bool include_wkt_imports)
     : generate_for_named_framework_(generate_for_named_framework),
       named_framework_to_proto_path_mappings_path_(
           named_framework_to_proto_path_mappings_path),
+      runtime_import_prefix_(runtime_import_prefix),
       include_wkt_imports_(include_wkt_imports),
-      need_to_parse_mapping_file_(true) {
-}
+      need_to_parse_mapping_file_(true) {}
 
 ImportWriter::~ImportWriter() {}
 
 void ImportWriter::AddFile(const FileDescriptor* file,
-                           const string& header_extension) {
+                           const std::string& header_extension) {
   if (IsProtobufLibraryBundledProtoFile(file)) {
     // The imports of the WKTs are only needed within the library itself,
     // in other cases, they get skipped because the generated code already
     // import GPBProtocolBuffers.h and hence proves them.
     if (include_wkt_imports_) {
-      const string header_name =
-        "GPB" + FilePathBasename(file) + header_extension;
-      protobuf_framework_imports_.push_back(header_name);
-      protobuf_non_framework_imports_.push_back(header_name);
+      const std::string header_name =
+          "GPB" + FilePathBasename(file) + header_extension;
+      protobuf_imports_.push_back(header_name);
     }
     return;
   }
@@ -1596,7 +1753,7 @@
     ParseFrameworkMappings();
   }
 
-  std::map<string, string>::iterator proto_lookup =
+  std::map<std::string, std::string>::iterator proto_lookup =
       proto_file_to_framework_name_.find(file->name());
   if (proto_lookup != proto_file_to_framework_name_.end()) {
     other_framework_imports_.push_back(
@@ -1616,36 +1773,10 @@
 }
 
 void ImportWriter::Print(io::Printer* printer) const {
-  assert(protobuf_non_framework_imports_.size() ==
-         protobuf_framework_imports_.size());
-
   bool add_blank_line = false;
 
-  if (!protobuf_framework_imports_.empty()) {
-    const string framework_name(ProtobufLibraryFrameworkName);
-    const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
-
-    printer->Print(
-        "#if $cpp_symbol$\n",
-        "cpp_symbol", cpp_symbol);
-    for (std::vector<string>::const_iterator iter = protobuf_framework_imports_.begin();
-         iter != protobuf_framework_imports_.end(); ++iter) {
-      printer->Print(
-          " #import <$framework_name$/$header$>\n",
-          "framework_name", framework_name,
-          "header", *iter);
-    }
-    printer->Print(
-        "#else\n");
-    for (std::vector<string>::const_iterator iter = protobuf_non_framework_imports_.begin();
-         iter != protobuf_non_framework_imports_.end(); ++iter) {
-      printer->Print(
-          " #import \"$header$\"\n",
-          "header", *iter);
-    }
-    printer->Print(
-        "#endif\n");
-
+  if (!protobuf_imports_.empty()) {
+    PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_);
     add_blank_line = true;
   }
 
@@ -1654,7 +1785,8 @@
       printer->Print("\n");
     }
 
-    for (std::vector<string>::const_iterator iter = other_framework_imports_.begin();
+    for (std::vector<std::string>::const_iterator iter =
+             other_framework_imports_.begin();
          iter != other_framework_imports_.end(); ++iter) {
       printer->Print(
           "#import <$header$>\n",
@@ -1669,7 +1801,7 @@
       printer->Print("\n");
     }
 
-    for (std::vector<string>::const_iterator iter = other_imports_.begin();
+    for (std::vector<std::string>::const_iterator iter = other_imports_.begin();
          iter != other_imports_.end(); ++iter) {
       printer->Print(
           "#import \"$header$\"\n",
@@ -1678,6 +1810,54 @@
   }
 }
 
+void ImportWriter::PrintRuntimeImports(
+    io::Printer* printer, const std::vector<std::string>& header_to_import,
+    const std::string& runtime_import_prefix, bool default_cpp_symbol) {
+  // Given an override, use that.
+  if (!runtime_import_prefix.empty()) {
+    for (const auto& header : header_to_import) {
+      printer->Print(
+          " #import \"$import_prefix$/$header$\"\n",
+          "import_prefix", runtime_import_prefix,
+          "header", header);
+    }
+    return;
+  }
+
+  const std::string framework_name(ProtobufLibraryFrameworkName);
+  const std::string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
+
+  if (default_cpp_symbol) {
+    printer->Print(
+        "// This CPP symbol can be defined to use imports that match up to the framework\n"
+        "// imports needed when using CocoaPods.\n"
+        "#if !defined($cpp_symbol$)\n"
+        " #define $cpp_symbol$ 0\n"
+        "#endif\n"
+        "\n",
+        "cpp_symbol", cpp_symbol);
+  }
+
+  printer->Print(
+      "#if $cpp_symbol$\n",
+      "cpp_symbol", cpp_symbol);
+  for (const auto& header : header_to_import) {
+    printer->Print(
+        " #import <$framework_name$/$header$>\n",
+        "framework_name", framework_name,
+        "header", header);
+  }
+  printer->Print(
+      "#else\n");
+  for (const auto& header : header_to_import) {
+    printer->Print(
+        " #import \"$header$\"\n",
+        "header", header);
+  }
+  printer->Print(
+      "#endif\n");
+}
+
 void ImportWriter::ParseFrameworkMappings() {
   need_to_parse_mapping_file_ = false;
   if (named_framework_to_proto_path_mappings_path_.empty()) {
@@ -1685,7 +1865,7 @@
   }
 
   ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
-  string parse_error;
+  std::string parse_error;
   if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_,
                        &collector, &parse_error)) {
     std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_
@@ -1695,12 +1875,12 @@
 }
 
 bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
-    const StringPiece& line, string* out_error) {
+    const StringPiece& line, std::string* out_error) {
   int offset = line.find(':');
   if (offset == StringPiece::npos) {
     *out_error =
-        string("Framework/proto file mapping line without colon sign: '") +
-        string(line) + "'.";
+        std::string("Framework/proto file mapping line without colon sign: '") +
+        std::string(line) + "'.";
     return false;
   }
   StringPiece framework_name = line.substr(0, offset);
@@ -1717,12 +1897,12 @@
     StringPiece proto_file = proto_file_list.substr(start, offset - start);
     TrimWhitespace(&proto_file);
     if (!proto_file.empty()) {
-      std::map<string, string>::iterator existing_entry =
-          map_->find(string(proto_file));
+      std::map<std::string, std::string>::iterator existing_entry =
+          map_->find(std::string(proto_file));
       if (existing_entry != map_->end()) {
         std::cerr << "warning: duplicate proto file reference, replacing "
                      "framework entry for '"
-                  << string(proto_file) << "' with '" << string(framework_name)
+                  << std::string(proto_file) << "' with '" << std::string(framework_name)
                   << "' (was '" << existing_entry->second << "')." << std::endl;
         std::cerr.flush();
       }
@@ -1730,11 +1910,11 @@
       if (proto_file.find(' ') != StringPiece::npos) {
         std::cerr << "note: framework mapping file had a proto file with a "
                      "space in, hopefully that isn't a missing comma: '"
-                  << string(proto_file) << "'" << std::endl;
+                  << std::string(proto_file) << "'" << std::endl;
         std::cerr.flush();
       }
 
-      (*map_)[string(proto_file)] = string(framework_name);
+      (*map_)[std::string(proto_file)] = std::string(framework_name);
     }
 
     start = offset + 1;
@@ -1743,7 +1923,6 @@
   return true;
 }
 
-
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index c6a2c77..02615e0 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -46,89 +46,96 @@
 namespace compiler {
 namespace objectivec {
 
+// Get/Set if the proto package should be used to make the default prefix for
+// symbols. This will then impact most of the type naming apis below. It is done
+// as a global to not break any other generator reusing the methods since they
+// are exported.
+bool PROTOC_EXPORT UseProtoPackageAsDefaultPrefix();
+void PROTOC_EXPORT SetUseProtoPackageAsDefaultPrefix(bool on_or_off);
+// Get/Set the path to a file to load as exceptions when
+// `UseProtoPackageAsDefaultPrefixUseProtoPackageAsDefaultPrefix()` is `true`.
+// And empty string means there should be no exceptions loaded.
+std::string PROTOC_EXPORT GetProtoPackagePrefixExceptionList();
+void PROTOC_EXPORT SetProtoPackagePrefixExceptionList(
+    const std::string& file_path);
+
 // Generator options (see objectivec_generator.cc for a description of each):
 struct Options {
   Options();
-  string expected_prefixes_path;
-  std::vector<string> expected_prefixes_suppressions;
-  string generate_for_named_framework;
-  string named_framework_to_proto_path_mappings_path;
+  std::string expected_prefixes_path;
+  std::vector<std::string> expected_prefixes_suppressions;
+  std::string generate_for_named_framework;
+  std::string named_framework_to_proto_path_mappings_path;
+  std::string runtime_import_prefix;
 };
 
 // Escape C++ trigraphs by escaping question marks to "\?".
-string PROTOC_EXPORT EscapeTrigraphs(const string& to_escape);
-
-// Strips ".proto" or ".protodevel" from the end of a filename.
-string PROTOC_EXPORT StripProto(const string& filename);
+std::string PROTOC_EXPORT EscapeTrigraphs(const std::string& to_escape);
 
 // Remove white space from either end of a StringPiece.
 void PROTOC_EXPORT TrimWhitespace(StringPiece* input);
 
 // Returns true if the name requires a ns_returns_not_retained attribute applied
 // to it.
-bool PROTOC_EXPORT IsRetainedName(const string& name);
+bool PROTOC_EXPORT IsRetainedName(const std::string& name);
 
 // Returns true if the name starts with "init" and will need to have special
 // handling under ARC.
-bool PROTOC_EXPORT IsInitName(const string& name);
+bool PROTOC_EXPORT IsInitName(const std::string& name);
 
-// Gets the objc_class_prefix.
-string PROTOC_EXPORT FileClassPrefix(const FileDescriptor* file);
+// Gets the objc_class_prefix or the prefix made from the proto package.
+std::string PROTOC_EXPORT FileClassPrefix(const FileDescriptor* file);
 
 // Gets the path of the file we're going to generate (sans the .pb.h
 // extension).  The path will be dependent on the objectivec package
 // declared in the proto package.
-string PROTOC_EXPORT FilePath(const FileDescriptor* file);
+std::string PROTOC_EXPORT FilePath(const FileDescriptor* file);
 
 // Just like FilePath(), but without the directory part.
-string PROTOC_EXPORT FilePathBasename(const FileDescriptor* file);
+std::string PROTOC_EXPORT FilePathBasename(const FileDescriptor* file);
 
 // Gets the name of the root class we'll generate in the file.  This class
 // is not meant for external consumption, but instead contains helpers that
 // the rest of the classes need
-string PROTOC_EXPORT FileClassName(const FileDescriptor* file);
+std::string PROTOC_EXPORT FileClassName(const FileDescriptor* file);
 
 // These return the fully-qualified class name corresponding to the given
 // descriptor.
-string PROTOC_EXPORT ClassName(const Descriptor* descriptor);
-string PROTOC_EXPORT ClassName(const Descriptor* descriptor,
-                               string* out_suffix_added);
-string PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor);
+std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor);
+std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor,
+                                    std::string* out_suffix_added);
+std::string PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor);
 
 // Returns the fully-qualified name of the enum value corresponding to the
 // the descriptor.
-string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor);
+std::string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor);
 
 // Returns the name of the enum value corresponding to the descriptor.
-string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor);
+std::string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor);
 
 // Reverse what an enum does.
-string PROTOC_EXPORT UnCamelCaseEnumShortName(const string& name);
+std::string PROTOC_EXPORT UnCamelCaseEnumShortName(const std::string& name);
 
 // Returns the name to use for the extension (used as the method off the file's
 // Root class).
-string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor);
+std::string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor);
 
 // Returns the transformed field name.
-string PROTOC_EXPORT FieldName(const FieldDescriptor* field);
-string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field);
+std::string PROTOC_EXPORT FieldName(const FieldDescriptor* field);
+std::string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field);
 
 // Returns the transformed oneof name.
-string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor);
-string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor);
-string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor);
+std::string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor);
+std::string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor);
+std::string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor);
 
 // Returns a symbol that can be used in C code to refer to an Objective C
 // class without initializing the class.
-string PROTOC_EXPORT ObjCClass(const string& class_name);
+std::string PROTOC_EXPORT ObjCClass(const std::string& class_name);
 
 // Declares an Objective C class without initializing the class so that it can
 // be refrerred to by ObjCClass.
-string PROTOC_EXPORT ObjCClassDeclaration(const string& class_name);
-
-inline bool HasFieldPresence(const FileDescriptor* file) {
-  return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
-}
+std::string PROTOC_EXPORT ObjCClassDeclaration(const std::string& class_name);
 
 inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
   return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
@@ -139,8 +146,8 @@
 }
 
 // Reverse of the above.
-string PROTOC_EXPORT UnCamelCaseFieldName(const string& name,
-                                          const FieldDescriptor* field);
+std::string PROTOC_EXPORT UnCamelCaseFieldName(const std::string& name,
+                                               const FieldDescriptor* field);
 
 enum ObjectiveCType {
   OBJECTIVECTYPE_INT32,
@@ -162,11 +169,11 @@
   FLAGTYPE_FIELD
 };
 
-template<class TDescriptor>
-string GetOptionalDeprecatedAttribute(
-    const TDescriptor* descriptor,
-    const FileDescriptor* file = NULL,
-    bool preSpace = true, bool postNewline = false) {
+template <class TDescriptor>
+std::string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor,
+                                           const FileDescriptor* file = NULL,
+                                           bool preSpace = true,
+                                           bool postNewline = false) {
   bool isDeprecated = descriptor->options().deprecated();
   // The file is only passed when checking Messages & Enums, so those types
   // get tagged. At the moment, it doesn't seem to make sense to tag every
@@ -177,7 +184,7 @@
     isDeprecated = isFileLevelDeprecation;
   }
   if (isDeprecated) {
-    string message;
+    std::string message;
     const FileDescriptor* sourceFile = descriptor->file();
     if (isFileLevelDeprecation) {
       message = sourceFile->name() + " is deprecated.";
@@ -186,7 +193,7 @@
                 sourceFile->name() + ").";
     }
 
-    string result = string("GPB_DEPRECATED_MSG(\"") + message + "\")";
+    std::string result = std::string("GPB_DEPRECATED_MSG(\"") + message + "\")";
     if (preSpace) {
       result.insert(0, " ");
     }
@@ -199,7 +206,7 @@
   }
 }
 
-string PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field);
+std::string PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field);
 
 ObjectiveCType PROTOC_EXPORT
 GetObjectiveCType(FieldDescriptor::Type field_type);
@@ -211,25 +218,26 @@
 bool PROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field);
 bool PROTOC_EXPORT IsReferenceType(const FieldDescriptor* field);
 
-string PROTOC_EXPORT GPBGenericValueFieldName(const FieldDescriptor* field);
-string PROTOC_EXPORT DefaultValue(const FieldDescriptor* field);
+std::string PROTOC_EXPORT
+GPBGenericValueFieldName(const FieldDescriptor* field);
+std::string PROTOC_EXPORT DefaultValue(const FieldDescriptor* field);
 bool PROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field);
 
-string PROTOC_EXPORT BuildFlagsString(const FlagType type,
-                                      const std::vector<string>& strings);
+std::string PROTOC_EXPORT
+BuildFlagsString(const FlagType type, const std::vector<std::string>& strings);
 
 // Builds HeaderDoc/appledoc style comments out of the comments in the .proto
 // file.
-string PROTOC_EXPORT BuildCommentsString(const SourceLocation& location,
-                                         bool prefer_single_line);
+std::string PROTOC_EXPORT BuildCommentsString(const SourceLocation& location,
+                                              bool prefer_single_line);
 
 // The name the commonly used by the library when built as a framework.
 // This lines up to the name used in the CocoaPod.
 extern PROTOC_EXPORT const char* const ProtobufLibraryFrameworkName;
 // Returns the CPP symbol name to use as the gate for framework style imports
 // for the given framework name to use.
-string PROTOC_EXPORT
-ProtobufFrameworkImportSymbol(const string& framework_name);
+std::string PROTOC_EXPORT
+ProtobufFrameworkImportSymbol(const std::string& framework_name);
 
 // Checks if the file is one of the proto's bundled with the library.
 bool PROTOC_EXPORT
@@ -238,9 +246,9 @@
 // Checks the prefix for the given files and outputs any warnings as needed. If
 // there are flat out errors, then out_error is filled in with the first error
 // and the result is false.
-bool PROTOC_EXPORT
-ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
-                          const Options& generation_options, string* out_error);
+bool PROTOC_EXPORT ValidateObjCClassPrefixes(
+    const std::vector<const FileDescriptor*>& files,
+    const Options& generation_options, std::string* out_error);
 
 // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
 // the input into the expected output.
@@ -252,16 +260,16 @@
   TextFormatDecodeData(const TextFormatDecodeData&) = delete;
   TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete;
 
-  void AddString(int32 key, const string& input_for_decode,
-                 const string& desired_output);
+  void AddString(int32 key, const std::string& input_for_decode,
+                 const std::string& desired_output);
   size_t num_entries() const { return entries_.size(); }
-  string Data() const;
+  std::string Data() const;
 
-  static string DecodeDataForString(const string& input_for_decode,
-                                    const string& desired_output);
+  static std::string DecodeDataForString(const std::string& input_for_decode,
+                                         const std::string& desired_output);
 
  private:
-  typedef std::pair<int32, string> DataEntry;
+  typedef std::pair<int32, std::string> DataEntry;
   std::vector<DataEntry> entries_;
 };
 
@@ -270,49 +278,55 @@
  public:
   LineConsumer();
   virtual ~LineConsumer();
-  virtual bool ConsumeLine(const StringPiece& line, string* out_error) = 0;
+  virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) = 0;
 };
 
-bool PROTOC_EXPORT ParseSimpleFile(const string& path,
+bool PROTOC_EXPORT ParseSimpleFile(const std::string& path,
                                    LineConsumer* line_consumer,
-                                   string* out_error);
+                                   std::string* out_error);
 
 // Helper class for parsing framework import mappings and generating
 // import statements.
 class PROTOC_EXPORT ImportWriter {
  public:
-  ImportWriter(const string& generate_for_named_framework,
-               const string& named_framework_to_proto_path_mappings_path,
+  ImportWriter(const std::string& generate_for_named_framework,
+               const std::string& named_framework_to_proto_path_mappings_path,
+               const std::string& runtime_import_prefix,
                bool include_wkt_imports);
   ~ImportWriter();
 
-  void AddFile(const FileDescriptor* file, const string& header_extension);
-  void Print(io::Printer *printer) const;
+  void AddFile(const FileDescriptor* file, const std::string& header_extension);
+  void Print(io::Printer* printer) const;
+
+  static void PrintRuntimeImports(io::Printer* printer,
+                                  const std::vector<std::string>& header_to_import,
+                                  const std::string& runtime_import_prefix,
+                                  bool default_cpp_symbol = false);
 
  private:
   class ProtoFrameworkCollector : public LineConsumer {
    public:
-    ProtoFrameworkCollector(std::map<string, string>* inout_proto_file_to_framework_name)
+    ProtoFrameworkCollector(std::map<std::string, std::string>* inout_proto_file_to_framework_name)
         : map_(inout_proto_file_to_framework_name) {}
 
-    virtual bool ConsumeLine(const StringPiece& line, string* out_error);
+    virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override;
 
    private:
-    std::map<string, string>* map_;
+    std::map<std::string, std::string>* map_;
   };
 
   void ParseFrameworkMappings();
 
-  const string generate_for_named_framework_;
-  const string named_framework_to_proto_path_mappings_path_;
+  const std::string generate_for_named_framework_;
+  const std::string named_framework_to_proto_path_mappings_path_;
+  const std::string runtime_import_prefix_;
   const bool include_wkt_imports_;
-  std::map<string, string> proto_file_to_framework_name_;
+  std::map<std::string, std::string> proto_file_to_framework_name_;
   bool need_to_parse_mapping_file_;
 
-  std::vector<string> protobuf_framework_imports_;
-  std::vector<string> protobuf_non_framework_imports_;
-  std::vector<string> other_framework_imports_;
-  std::vector<string> other_imports_;
+  std::vector<std::string> protobuf_imports_;
+  std::vector<std::string> other_framework_imports_;
+  std::vector<std::string> other_imports_;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
index dc1cef5..0aef94f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
@@ -39,21 +39,21 @@
 namespace {
 
 TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) {
-  string input_for_decode("abcdefghIJ");
-  string desired_output_for_decode;
-  string expected;
-  string result;
+  std::string input_for_decode("abcdefghIJ");
+  std::string desired_output_for_decode;
+  std::string expected;
+  std::string result;
 
   // Different data, can't transform.
 
   desired_output_for_decode = "zbcdefghIJ";
-  expected = string("\0zbcdefghIJ\0", 12);
+  expected = std::string("\0zbcdefghIJ\0", 12);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
 
   desired_output_for_decode = "abcdezghIJ";
-  expected = string("\0abcdezghIJ\0", 12);
+  expected = std::string("\0abcdezghIJ\0", 12);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
@@ -61,7 +61,7 @@
   // Shortened data, can't transform.
 
   desired_output_for_decode = "abcdefghI";
-  expected = string("\0abcdefghI\0", 11);
+  expected = std::string("\0abcdefghI\0", 11);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
@@ -69,32 +69,32 @@
   // Extra data, can't transform.
 
   desired_output_for_decode = "abcdefghIJz";
-  expected = string("\0abcdefghIJz\0", 13);
+  expected = std::string("\0abcdefghIJz\0", 13);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
 }
 
 TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) {
-  string input_for_decode("abcdefghIJ");
-  string desired_output_for_decode;
-  string expected;
-  string result;
+  std::string input_for_decode("abcdefghIJ");
+  std::string desired_output_for_decode;
+  std::string expected;
+  std::string result;
 
   desired_output_for_decode = "abcdefghIJ";
-  expected = string("\x0A\x0", 2);
+  expected = std::string("\x0A\x0", 2);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
 
   desired_output_for_decode = "_AbcdefghIJ";
-  expected = string("\xCA\x0", 2);
+  expected = std::string("\xCA\x0", 2);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
 
   desired_output_for_decode = "ABCD__EfghI_j";
-  expected = string("\x64\x80\xC5\xA1\x0", 5);
+  expected = std::string("\x64\x80\xC5\xA1\x0", 5);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
@@ -105,7 +105,7 @@
       "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
   desired_output_for_decode =
       "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000";
-  expected = string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
+  expected = std::string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
   EXPECT_EQ(expected, result);
@@ -128,7 +128,7 @@
 
   // Null char in the string.
 
-  string str_with_null_char("ab\0c", 4);
+  std::string str_with_null_char("ab\0c", 4);
   EXPECT_EXIT(
       TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"),
       ::testing::KilledBySignal(SIGABRT),
@@ -160,7 +160,7 @@
       0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0,
       0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0,
   };
-  string expected((const char*)expected_data, sizeof(expected_data));
+  std::string expected((const char*)expected_data, sizeof(expected_data));
 
   EXPECT_EQ(expected, decode_data.Data());
 }
@@ -196,7 +196,7 @@
       //   underscore, as is + 3 (00 op)
       0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
   };
-  string expected((const char*)expected_data, sizeof(expected_data));
+  std::string expected((const char*)expected_data, sizeof(expected_data));
 
   EXPECT_EQ(expected, decode_data.Data());
 }
@@ -221,7 +221,7 @@
 
   // Null char in the string.
 
-  string str_with_null_char("ab\0c", 4);
+  std::string str_with_null_char("ab\0c", 4);
   EXPECT_EXIT(
       decode_data.AddString(1, str_with_null_char, "def"),
       ::testing::KilledBySignal(SIGABRT),
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index 3b8eaa0..746224f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -85,9 +85,9 @@
                                      const Options& options)
     : RepeatedFieldGenerator(descriptor, options) {
   const FieldDescriptor* key_descriptor =
-      descriptor->message_type()->FindFieldByName("key");
+      descriptor->message_type()->map_key();
   const FieldDescriptor* value_descriptor =
-      descriptor->message_type()->FindFieldByName("value");
+      descriptor->message_type()->map_value();
   value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options));
 
   // Pull over some variables_ from the value.
@@ -96,20 +96,21 @@
   variables_["default_name"] = value_field_generator_->variable("default_name");
 
   // Build custom field flags.
-  std::vector<string> field_flags;
+  std::vector<std::string> field_flags;
   field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor));
   // Pull over the current text format custom name values that was calculated.
   if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") !=
-      string::npos) {
+      std::string::npos) {
     field_flags.push_back("GPBFieldTextFormatNameCustom");
   }
   // Pull over some info from the value's flags.
-  const string& value_field_flags =
+  const std::string& value_field_flags =
       value_field_generator_->variable("fieldflags");
-  if (value_field_flags.find("GPBFieldHasDefaultValue") != string::npos) {
+  if (value_field_flags.find("GPBFieldHasDefaultValue") != std::string::npos) {
     field_flags.push_back("GPBFieldHasDefaultValue");
   }
-  if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
+  if (value_field_flags.find("GPBFieldHasEnumDescriptor") !=
+      std::string::npos) {
     field_flags.push_back("GPBFieldHasEnumDescriptor");
   }
 
@@ -127,7 +128,7 @@
         "NSMutableDictionary<NSString*, " +
         value_field_generator_->variable("storage_type") + "*>";
   } else {
-    string class_name("GPB");
+    std::string class_name("GPB");
     class_name += MapEntryTypeName(key_descriptor, true);
     class_name += MapEntryTypeName(value_descriptor, false);
     class_name += "Dictionary";
@@ -160,19 +161,19 @@
 }
 
 void MapFieldGenerator::DetermineForwardDeclarations(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   const FieldDescriptor* value_descriptor =
       descriptor_->message_type()->FindFieldByName("value");
   if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
-    const string& value_storage_type =
+    const std::string& value_storage_type =
         value_field_generator_->variable("storage_type");
     fwd_decls->insert("@class " + value_storage_type);
   }
 }
 
 void MapFieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   // Class name is already in "storage_type".
   const FieldDescriptor* value_descriptor =
       descriptor_->message_type()->FindFieldByName("value");
@@ -182,7 +183,6 @@
   }
 }
 
-
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
index da18d57..84eac61 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -45,7 +45,7 @@
                                               const Options& options);
 
  public:
-  virtual void FinishInitialization(void);
+  virtual void FinishInitialization(void) override;
 
   MapFieldGenerator(const MapFieldGenerator&) = delete;
   MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
@@ -54,8 +54,10 @@
   MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   virtual ~MapFieldGenerator();
 
-  virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
-  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
+  virtual void DetermineObjectiveCClassDefinitions(
+      std::set<std::string>* fwd_decls) const override;
+  virtual void DetermineForwardDeclarations(
+      std::set<std::string>* fwd_decls) const override;
 
  private:
   std::unique_ptr<FieldGenerator> value_field_generator_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index b5d8128..3a00113 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -170,22 +170,21 @@
 }
 }  // namespace
 
-MessageGenerator::MessageGenerator(const string& root_classname,
+MessageGenerator::MessageGenerator(const std::string& root_classname,
                                    const Descriptor* descriptor,
                                    const Options& options)
     : root_classname_(root_classname),
       descriptor_(descriptor),
       field_generators_(descriptor, options),
       class_name_(ClassName(descriptor_)),
-      deprecated_attribute_(
-          GetOptionalDeprecatedAttribute(descriptor, descriptor->file(), false, true)) {
-
+      deprecated_attribute_(GetOptionalDeprecatedAttribute(
+          descriptor, descriptor->file(), false, true)) {
   for (int i = 0; i < descriptor_->extension_count(); i++) {
     extension_generators_.emplace_back(
         new ExtensionGenerator(class_name_, descriptor_->extension(i)));
   }
 
-  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+  for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
     OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
     oneof_generators_.emplace_back(generator);
   }
@@ -217,7 +216,8 @@
   }
 }
 
-void MessageGenerator::DetermineForwardDeclarations(std::set<string>* fwd_decls) {
+void MessageGenerator::DetermineForwardDeclarations(
+    std::set<std::string>* fwd_decls) {
   if (!IsMapEntryMessage(descriptor_)) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
@@ -231,7 +231,8 @@
   }
 }
 
-void MessageGenerator::DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) {
+void MessageGenerator::DetermineObjectiveCClassDefinitions(
+    std::set<std::string>* fwd_decls) {
   if (!IsMapEntryMessage(descriptor_)) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
@@ -250,7 +251,7 @@
 
   const Descriptor* containing_descriptor = descriptor_->containing_type();
   if (containing_descriptor != NULL) {
-    string containing_class = ClassName(containing_descriptor);
+    std::string containing_class = ClassName(containing_descriptor);
     fwd_decls->insert(ObjCClassDeclaration(containing_class));
   }
 }
@@ -325,7 +326,7 @@
     generator->GenerateCaseEnum(printer);
   }
 
-  string message_comments;
+  std::string message_comments;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
     message_comments = BuildCommentsString(location, false);
@@ -339,11 +340,12 @@
       "deprecated_attribute", deprecated_attribute_,
       "comments", message_comments);
 
-  std::vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
+  std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
-    if (field->containing_oneof() != NULL) {
-      const int oneof_index = field->containing_oneof()->index();
+    const OneofDescriptor* oneof = field->real_containing_oneof();
+    if (oneof) {
+      const int oneof_index = oneof->index();
       if (!seen_oneofs[oneof_index]) {
         seen_oneofs[oneof_index] = 1;
         oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
@@ -443,7 +445,7 @@
     field_generators_.SetOneofIndexBase(sizeof_has_storage);
     // sizeof_has_storage needs enough bits for the single fields that aren't in
     // any oneof, and then one int32 for each oneof (to store the field number).
-    sizeof_has_storage += descriptor_->oneof_decl_count();
+    sizeof_has_storage += oneof_generators_.size();
 
     printer->Print(
         "\n"
@@ -472,7 +474,7 @@
     TextFormatDecodeData text_format_decode_data;
     bool has_fields = descriptor_->field_count() > 0;
     bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
-    string field_description_type;
+    std::string field_description_type;
     if (need_defaults) {
       field_description_type = "GPBMessageFieldDescriptionWithDefault";
     } else {
@@ -502,7 +504,7 @@
       printer->Outdent();
     }
 
-    std::map<string, string> vars;
+    std::map<std::string, std::string> vars;
     vars["classname"] = class_name_;
     vars["rootclassname"] = root_classname_;
     vars["fields"] = has_fields ? "fields" : "NULL";
@@ -513,8 +515,9 @@
       vars["fields_count"] = "0";
     }
 
-    std::vector<string> init_flags;
+    std::vector<std::string> init_flags;
     init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
+    init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
     if (need_defaults) {
       init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
     }
@@ -549,7 +552,7 @@
           "first_has_index", oneof_generators_[0]->HasIndexAsString());
     }
     if (text_format_decode_data.num_entries() != 0) {
-      const string text_format_data_str(text_format_decode_data.Data());
+      const std::string text_format_data_str(text_format_decode_data.Data());
       printer->Print(
           "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
           "    static const char *extraTextFormatInfo =");
@@ -579,13 +582,13 @@
           "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
     }
     if (descriptor_->containing_type() != NULL) {
-      string containing_class = ClassName(descriptor_->containing_type());
-      string parent_class_ref = ObjCClass(containing_class);
+      std::string containing_class = ClassName(descriptor_->containing_type());
+      std::string parent_class_ref = ObjCClass(containing_class);
       printer->Print(
           "    [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
           "parent_class_ref", parent_class_ref);
     }
-    string suffix_added;
+    std::string suffix_added;
     ClassName(descriptor_, &suffix_added);
     if (!suffix_added.empty()) {
       printer->Print(
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
index 138e620..01108d2 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -50,9 +50,8 @@
 
 class MessageGenerator {
  public:
-  MessageGenerator(const string& root_classname,
-                   const Descriptor* descriptor,
-                   const Options& options);
+  MessageGenerator(const std::string& root_classname,
+                   const Descriptor* descriptor, const Options& options);
   ~MessageGenerator();
 
   MessageGenerator(const MessageGenerator&) = delete;
@@ -63,8 +62,8 @@
   void GenerateMessageHeader(io::Printer* printer);
   void GenerateSource(io::Printer* printer);
   void GenerateExtensionRegistrationSource(io::Printer* printer);
-  void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls);
-  void DetermineForwardDeclarations(std::set<string>* fwd_decls);
+  void DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls);
+  void DetermineForwardDeclarations(std::set<std::string>* fwd_decls);
 
   // Checks if the message or a nested message includes a oneof definition.
   bool IncludesOneOfDefinition() const;
@@ -81,11 +80,11 @@
   void GenerateDescriptionOneFieldSource(io::Printer* printer,
                                          const FieldDescriptor* field);
 
-  const string root_classname_;
+  const std::string root_classname_;
   const Descriptor* descriptor_;
   FieldGeneratorMap field_generators_;
-  const string class_name_;
-  const string deprecated_attribute_;
+  const std::string class_name_;
+  const std::string deprecated_attribute_;
   std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
   std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
   std::vector<std::unique_ptr<MessageGenerator>> nested_message_generators_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
index 2730e75..299a20b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -44,9 +44,10 @@
 namespace {
 
 void SetMessageVariables(const FieldDescriptor* descriptor,
-                         std::map<string, string>* variables) {
-  const string& message_type = ClassName(descriptor->message_type());
-  const string& containing_class = ClassName(descriptor->containing_type());
+                         std::map<std::string, std::string>* variables) {
+  const std::string& message_type = ClassName(descriptor->message_type());
+  const std::string& containing_class =
+      ClassName(descriptor->containing_type());
   (*variables)["type"] = message_type;
   (*variables)["containing_class"] = containing_class;
   (*variables)["storage_type"] = message_type;
@@ -66,27 +67,17 @@
 MessageFieldGenerator::~MessageFieldGenerator() {}
 
 void MessageFieldGenerator::DetermineForwardDeclarations(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // Class name is already in "storage_type".
   fwd_decls->insert("@class " + variable("storage_type"));
 }
 
 void MessageFieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   fwd_decls->insert(ObjCClassDeclaration(variable("storage_type")));
 }
 
-bool MessageFieldGenerator::WantsHasProperty(void) const {
-  if (descriptor_->containing_oneof() != NULL) {
-    // If in a oneof, it uses the oneofcase instead of a has bit.
-    return false;
-  }
-  // In both proto2 & proto3, message fields have a has* property to tell
-  // when it is a non default value.
-  return true;
-}
-
 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
     const FieldDescriptor* descriptor, const Options& options)
     : RepeatedFieldGenerator(descriptor, options) {
@@ -99,14 +90,14 @@
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 
 void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // Class name is already in "storage_type".
   fwd_decls->insert("@class " + variable("storage_type"));
 }
 
 void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<string>* fwd_decls) const {
+    std::set<std::string>* fwd_decls) const {
   fwd_decls->insert(ObjCClassDeclaration(variable("storage_type")));
 }
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
index 692f94c..01799a1 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -52,11 +52,12 @@
   MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
 
   virtual ~MessageFieldGenerator();
-  virtual bool WantsHasProperty(void) const;
 
  public:
-  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
-  virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(
+      std::set<std::string>* fwd_decls) const override;
+  virtual void DetermineObjectiveCClassDefinitions(
+      std::set<std::string>* fwd_decls) const override;
 };
 
 class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
@@ -72,8 +73,10 @@
   RepeatedMessageFieldGenerator operator=(const RepeatedMessageFieldGenerator&) = delete;
 
  public:
-  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
-  virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(
+      std::set<std::string>* fwd_decls) const override;
+  virtual void DetermineObjectiveCClassDefinitions(
+      std::set<std::string>* fwd_decls) const override;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
index 5b37c4e..1bef293 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -50,7 +50,7 @@
   const Descriptor* msg_descriptor = descriptor_->containing_type();
   variables_["owning_message_class"] = ClassName(msg_descriptor);
 
-  string comments;
+  std::string comments;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
     comments = BuildCommentsString(location, true);
@@ -76,10 +76,10 @@
   printer->Print(
       variables_,
       "$enum_name$_GPBUnsetOneOfCase = 0,\n");
-  string enum_name = variables_["enum_name"];
+  std::string enum_name = variables_["enum_name"];
   for (int j = 0; j < descriptor_->field_count(); j++) {
     const FieldDescriptor* field = descriptor_->field(j);
-    string field_name = FieldNameCapitalized(field);
+    std::string field_name = FieldNameCapitalized(field);
     printer->Print(
         "$enum_name$_$field_name$ = $field_number$,\n",
         "enum_name", enum_name,
@@ -120,17 +120,17 @@
   printer->Print(
       variables_,
       "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
-      "  GPBDescriptor *descriptor = [message descriptor];\n"
+      "  GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
       "  GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n"
-      "  GPBMaybeClearOneof(message, oneof, $index$, 0);\n"
+      "  GPBClearOneof(message, oneof);\n"
       "}\n");
 }
 
-string OneofGenerator::DescriptorName(void) const {
+std::string OneofGenerator::DescriptorName(void) const {
   return variables_.find("name")->second;
 }
 
-string OneofGenerator::HasIndexAsString(void) const {
+std::string OneofGenerator::HasIndexAsString(void) const {
   return variables_.find("index")->second;
 }
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
index 852ef02..034f07f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -60,12 +60,12 @@
   void GeneratePropertyImplementation(io::Printer* printer);
   void GenerateClearFunctionImplementation(io::Printer* printer);
 
-  string DescriptorName(void) const;
-  string HasIndexAsString(void) const;
+  std::string DescriptorName(void) const;
+  std::string HasIndexAsString(void) const;
 
  private:
   const OneofDescriptor* descriptor_;
-  std::map<string, string> variables_;
+  std::map<std::string, std::string> variables_;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
index 0511b37..e198c5c 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -116,7 +116,7 @@
 }
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           std::map<string, string>* variables) {
+                           std::map<std::string, std::string>* variables) {
   std::string primitive_name = PrimitiveTypeName(descriptor);
   (*variables)["type"] = primitive_name;
   (*variables)["storage_type"] = primitive_name;
@@ -172,7 +172,7 @@
     : RepeatedFieldGenerator(descriptor, options) {
   SetPrimitiveVariables(descriptor, &variables_);
 
-  string base_name = PrimitiveArrayTypeName(descriptor);
+  std::string base_name = PrimitiveArrayTypeName(descriptor);
   if (base_name.length()) {
     variables_["array_storage_type"] = "GPB" + base_name + "Array";
   } else {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
index 642f2d6..a9f30f6 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -52,10 +52,10 @@
   PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
   PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
 
-  virtual int ExtraRuntimeHasBitsNeeded(void) const;
-  virtual void SetExtraRuntimeHasBitsBase(int index_base);
+  virtual int ExtraRuntimeHasBitsNeeded(void) const override;
+  virtual void SetExtraRuntimeHasBitsBase(int index_base) override;
 };
 
 class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index d92cd55..b8659b7 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -38,6 +38,7 @@
 
 #include <float.h>
 
+#include <cstdint>
 #include <limits>
 #include <unordered_map>
 #include <unordered_set>
@@ -96,19 +97,19 @@
   static const char kSuffix[] = "Entry";
   result.reserve(field_name.size() + sizeof(kSuffix));
   bool cap_next = true;
-  for (int i = 0; i < field_name.size(); ++i) {
-    if (field_name[i] == '_') {
+  for (const char field_name_char : field_name) {
+    if (field_name_char == '_') {
       cap_next = true;
     } else if (cap_next) {
       // Note: Do not use ctype.h due to locales.
-      if ('a' <= field_name[i] && field_name[i] <= 'z') {
-        result.push_back(field_name[i] - 'a' + 'A');
+      if ('a' <= field_name_char && field_name_char <= 'z') {
+        result.push_back(field_name_char - 'a' + 'A');
       } else {
-        result.push_back(field_name[i]);
+        result.push_back(field_name_char);
       }
       cap_next = false;
     } else {
-      result.push_back(field_name[i]);
+      result.push_back(field_name_char);
     }
   }
   result.append(kSuffix);
@@ -130,8 +131,8 @@
     return false;
   }
   // Must not contains underscore.
-  for (int i = 1; i < name.length(); i++) {
-    if (name[i] == '_') {
+  for (const char c : name) {
+    if (c == '_') {
       return false;
     }
   }
@@ -139,8 +140,7 @@
 }
 
 bool IsUpperUnderscore(const std::string& name) {
-  for (int i = 0; i < name.length(); i++) {
-    const char c = name[i];
+  for (const char c : name) {
     if (!IsUppercase(c) && c != '_' && !IsNumber(c)) {
       return false;
     }
@@ -149,8 +149,7 @@
 }
 
 bool IsLowerUnderscore(const std::string& name) {
-  for (int i = 0; i < name.length(); i++) {
-    const char c = name[i];
+  for (const char c : name) {
     if (!IsLowercase(c) && c != '_' && !IsNumber(c)) {
       return false;
     }
@@ -243,8 +242,9 @@
 
 bool Parser::ConsumeInteger(int* output, const char* error) {
   if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
-    uint64 value = 0;
-    if (!io::Tokenizer::ParseInteger(input_->current().text, kint32max,
+    uint64_t value = 0;
+    if (!io::Tokenizer::ParseInteger(input_->current().text,
+                                     std::numeric_limits<int32_t>::max(),
                                      &value)) {
       AddError("Integer out of range.");
       // We still return true because we did, in fact, parse an integer.
@@ -260,19 +260,19 @@
 
 bool Parser::ConsumeSignedInteger(int* output, const char* error) {
   bool is_negative = false;
-  uint64 max_value = kint32max;
+  uint64_t max_value = std::numeric_limits<int32_t>::max();
   if (TryConsume("-")) {
     is_negative = true;
     max_value += 1;
   }
-  uint64 value = 0;
+  uint64_t value = 0;
   DO(ConsumeInteger64(max_value, &value, error));
   if (is_negative) value *= -1;
   *output = value;
   return true;
 }
 
-bool Parser::ConsumeInteger64(uint64 max_value, uint64* output,
+bool Parser::ConsumeInteger64(uint64_t max_value, uint64_t* output,
                               const char* error) {
   if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
     if (!io::Tokenizer::ParseInteger(input_->current().text, max_value,
@@ -296,8 +296,9 @@
     return true;
   } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
     // Also accept integers.
-    uint64 value = 0;
-    if (!io::Tokenizer::ParseInteger(input_->current().text, kuint64max,
+    uint64_t value = 0;
+    if (!io::Tokenizer::ParseInteger(input_->current().text,
+                                     std::numeric_limits<uint64_t>::max(),
                                      &value)) {
       AddError("Integer out of range.");
       // We still return true because we did, in fact, parse a number.
@@ -829,8 +830,9 @@
 // tag number can only be determined after all options have been parsed.
 void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
   const bool is_message_set = IsMessageSetWireFormatMessage(*message);
-  const int max_extension_number =
-      is_message_set ? kint32max : FieldDescriptor::kMaxNumber + 1;
+  const int max_extension_number = is_message_set
+                                       ? std::numeric_limits<int32_t>::max()
+                                       : FieldDescriptor::kMaxNumber + 1;
   for (int i = 0; i < message->extension_range_size(); ++i) {
     if (message->extension_range(i).end() == kMaxRangeSentinel) {
       message->mutable_extension_range(i)->set_end(max_extension_number);
@@ -843,8 +845,9 @@
 // tag number can only be determined after all options have been parsed.
 void AdjustReservedRangesWithMaxEndNumber(DescriptorProto* message) {
   const bool is_message_set = IsMessageSetWireFormatMessage(*message);
-  const int max_field_number =
-      is_message_set ? kint32max : FieldDescriptor::kMaxNumber + 1;
+  const int max_field_number = is_message_set
+                                   ? std::numeric_limits<int32_t>::max()
+                                   : FieldDescriptor::kMaxNumber + 1;
   for (int i = 0; i < message->reserved_range_size(); ++i) {
     if (message->reserved_range(i).end() == kMaxRangeSentinel) {
       message->mutable_reserved_range(i)->set_end(max_field_number);
@@ -1260,11 +1263,11 @@
     case FieldDescriptorProto::TYPE_SINT64:
     case FieldDescriptorProto::TYPE_SFIXED32:
     case FieldDescriptorProto::TYPE_SFIXED64: {
-      uint64 max_value = kint64max;
+      uint64_t max_value = std::numeric_limits<int64_t>::max();
       if (field->type() == FieldDescriptorProto::TYPE_INT32 ||
           field->type() == FieldDescriptorProto::TYPE_SINT32 ||
           field->type() == FieldDescriptorProto::TYPE_SFIXED32) {
-        max_value = kint32max;
+        max_value = std::numeric_limits<int32_t>::max();
       }
 
       // These types can be negative.
@@ -1274,7 +1277,7 @@
         ++max_value;
       }
       // Parse the integer to verify that it is not out-of-range.
-      uint64 value;
+      uint64_t value;
       DO(ConsumeInteger64(max_value, &value,
                           "Expected integer for field default value."));
       // And stringify it again.
@@ -1286,10 +1289,10 @@
     case FieldDescriptorProto::TYPE_UINT64:
     case FieldDescriptorProto::TYPE_FIXED32:
     case FieldDescriptorProto::TYPE_FIXED64: {
-      uint64 max_value = kuint64max;
+      uint64_t max_value = std::numeric_limits<uint64_t>::max();
       if (field->type() == FieldDescriptorProto::TYPE_UINT32 ||
           field->type() == FieldDescriptorProto::TYPE_FIXED32) {
-        max_value = kuint32max;
+        max_value = std::numeric_limits<uint32_t>::max();
       }
 
       // Numeric, not negative.
@@ -1297,7 +1300,7 @@
         AddError("Unsigned field can't have negative default value.");
       }
       // Parse the integer to verify that it is not out-of-range.
-      uint64 value;
+      uint64_t value;
       DO(ConsumeInteger64(max_value, &value,
                           "Expected integer for field default value."));
       // And stringify it again.
@@ -1529,15 +1532,17 @@
       }
 
       case io::Tokenizer::TYPE_INTEGER: {
-        uint64 value;
-        uint64 max_value =
-            is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
+        uint64_t value;
+        uint64_t max_value =
+            is_negative
+                ? static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1
+                : std::numeric_limits<uint64_t>::max();
         DO(ConsumeInteger64(max_value, &value, "Expected integer."));
         if (is_negative) {
           value_location.AddPath(
               UninterpretedOption::kNegativeIntValueFieldNumber);
           uninterpreted_option->set_negative_int_value(
-              static_cast<int64>(-value));
+              static_cast<int64_t>(-value));
         } else {
           value_location.AddPath(
               UninterpretedOption::kPositiveIntValueFieldNumber);
@@ -1775,12 +1780,12 @@
   DO(Consume("reserved"));
   if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
     LocationRecorder location(message_location,
-                              DescriptorProto::kReservedNameFieldNumber);
+                              EnumDescriptorProto::kReservedNameFieldNumber);
     location.StartAt(start_token);
     return ParseReservedNames(message, location);
   } else {
     LocationRecorder location(message_location,
-                              DescriptorProto::kReservedRangeFieldNumber);
+                              EnumDescriptorProto::kReservedRangeFieldNumber);
     location.StartAt(start_token);
     return ParseReservedNumbers(message, location);
   }
@@ -2208,7 +2213,6 @@
   return true;
 }
 
-
 bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
                                 const FileDescriptorProto* containing_file,
                                 const int optionsFieldNumber,
@@ -2338,8 +2342,8 @@
 }
 
 bool Parser::ParseImport(RepeatedPtrField<std::string>* dependency,
-                         RepeatedField<int32>* public_dependency,
-                         RepeatedField<int32>* weak_dependency,
+                         RepeatedField<int32_t>* public_dependency,
+                         RepeatedField<int32_t>* weak_dependency,
                          const LocationRecorder& root_location,
                          const FileDescriptorProto* containing_file) {
   LocationRecorder location(root_location,
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index e8afdbc..b5a5df8 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -37,14 +37,17 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
 #define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
 #include <utility>
+
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/repeated_field.h>
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -172,7 +175,8 @@
   bool ConsumeSignedInteger(int* output, const char* error);
   // Consume a 64-bit integer and store its value in "output".  If the value
   // is greater than max_value, an error will be reported.
-  bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
+  bool ConsumeInteger64(uint64_t max_value, uint64_t* output,
+                        const char* error);
   // Consume a number and store its value in "output".  This will accept
   // tokens of either INTEGER or FLOAT type.
   bool ConsumeNumber(double* output, const char* error);
@@ -323,8 +327,8 @@
                     const LocationRecorder& root_location,
                     const FileDescriptorProto* containing_file);
   bool ParseImport(RepeatedPtrField<std::string>* dependency,
-                   RepeatedField<int32>* public_dependency,
-                   RepeatedField<int32>* weak_dependency,
+                   RepeatedField<int32_t>* public_dependency,
+                   RepeatedField<int32_t>* weak_dependency,
                    const LocationRecorder& root_location,
                    const FileDescriptorProto* containing_file);
 
@@ -519,7 +523,6 @@
     return syntax_identifier_ == "proto3";
   }
 
-
   bool ValidateEnum(const EnumDescriptorProto* proto);
 
   // =================================================================
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 4a3a228..c942393 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -41,6 +41,7 @@
 
 #include <google/protobuf/test_util2.h>
 #include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/any.pb.h>
 #include <google/protobuf/unittest_custom_options.pb.h>
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -87,7 +88,7 @@
   // implements ErrorCollector ---------------------------------------
   void AddError(const std::string& filename, const std::string& element_name,
                 const Message* descriptor, ErrorLocation location,
-                const std::string& message) {
+                const std::string& message) override {
     int line, column;
     if (location == DescriptorPool::ErrorCollector::IMPORT) {
       source_locations_.FindImport(descriptor, element_name, &line, &column);
@@ -2183,7 +2184,7 @@
 void StripFieldTypeName(DescriptorProto* proto) {
   for (int i = 0; i < proto->field_size(); ++i) {
     std::string type_name = proto->field(i).type_name();
-    std::string::size_type pos = type_name.find_last_of(".");
+    std::string::size_type pos = type_name.find_last_of('.');
     if (pos != std::string::npos) {
       proto->mutable_field(i)->mutable_type_name()->assign(
           type_name.begin() + pos + 1, type_name.end());
@@ -2276,6 +2277,11 @@
   FileDescriptorProto import_proto;
   import->CopyTo(&import_proto);
   ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
+
+  FileDescriptorProto any_import;
+  google::protobuf::Any::descriptor()->file()->CopyTo(&any_import);
+  ASSERT_TRUE(pool_.BuildFile(any_import) != nullptr);
+
   const FileDescriptor* actual = pool_.BuildFile(parsed);
   ASSERT_TRUE(actual != NULL);
   parsed.Clear();
@@ -2582,7 +2588,7 @@
     return true;
   }
 
-  virtual void TearDown() {
+  virtual void TearDown() override {
     EXPECT_TRUE(spans_.empty()) << "Forgot to call HasSpan() for:\n"
                                 << spans_.begin()->second->DebugString();
   }
@@ -3133,6 +3139,43 @@
   EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
 }
 
+TEST_F(SourceInfoTest, EnumReservedRange) {
+  EXPECT_TRUE(
+      Parse("enum TestEnum {\n"
+            "  $a$reserved $b$1$c$ to $d$10$e$;$f$\n"
+            "}"));
+
+  const EnumDescriptorProto::EnumReservedRange& bar =
+      file_.enum_type(0).reserved_range(0);
+
+  EXPECT_TRUE(HasSpan('a', 'f', file_.enum_type(0), "reserved_range"));
+  EXPECT_TRUE(HasSpan('b', 'e', bar));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "start"));
+  EXPECT_TRUE(HasSpan('d', 'e', bar, "end"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, EnumReservedName) {
+  EXPECT_TRUE(
+      Parse("enum TestEnum {\n"
+            "  $a$reserved $b$'foo'$c$;$d$\n"
+            "}"));
+
+  const EnumDescriptorProto& bar = file_.enum_type(0);
+
+  EXPECT_TRUE(HasSpan('a', 'd', bar, "reserved_name"));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "reserved_name", 0));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
 TEST_F(SourceInfoTest, NestedEnums) {
   EXPECT_TRUE(
       Parse("message Foo {\n"
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
index 16ec9aa..84bafdd 100644
--- a/src/google/protobuf/compiler/php/php_generator.cc
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -48,26 +48,27 @@
 const std::string kDescriptorDirName = "Google/Protobuf/Internal";
 const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal";
 const char* const kReservedNames[] = {
-    "abstract",   "and",        "array",        "as",           "break",
-    "callable",   "case",       "catch",        "class",        "clone",
-    "const",      "continue",   "declare",      "default",      "die",
-    "do",         "echo",       "else",         "elseif",       "empty",
-    "enddeclare", "endfor",     "endforeach",   "endif",        "endswitch",
-    "endwhile",   "eval",       "exit",         "extends",      "final",
-    "for",        "foreach",    "function",     "global",       "goto",
-    "if",         "implements", "include",      "include_once", "instanceof",
-    "insteadof",  "interface",  "isset",        "list",         "namespace",
-    "new",        "or",         "print",        "private",      "protected",
-    "public",     "require",    "require_once", "return",       "static",
-    "switch",     "throw",      "trait",        "try",          "unset",
-    "use",        "var",        "while",        "xor",          "int",
-    "float",      "bool",       "string",       "true",         "false",
-    "null",       "void",       "iterable"};
+    "abstract",     "and",        "array",      "as",         "break",
+    "callable",     "case",       "catch",      "class",      "clone",
+    "const",        "continue",   "declare",    "default",    "die",
+    "do",           "echo",       "else",       "elseif",     "empty",
+    "enddeclare",   "endfor",     "endforeach", "endif",      "endswitch",
+    "endwhile",     "eval",       "exit",       "extends",    "final",
+    "finally",      "fn",         "for",        "foreach",    "function",
+    "global",       "goto",       "if",         "implements", "include",
+    "include_once", "instanceof", "insteadof",  "interface",  "isset",
+    "list",         "match",      "namespace",  "new",        "or",
+    "print",        "private",    "protected",  "public",     "require",
+    "require_once", "return",     "static",     "switch",     "throw",
+    "trait",        "try",        "unset",      "use",        "var",
+    "while",        "xor",        "yield",      "int",        "float",
+    "bool",         "string",     "true",       "false",      "null",
+    "void",         "iterable"};
 const char* const kValidConstantNames[] = {
     "int",   "float", "bool", "string",   "true",
     "false", "null",  "void", "iterable",
 };
-const int kReservedNamesSize = 73;
+const int kReservedNamesSize = 77;
 const int kValidConstantNamesSize = 9;
 const int kFieldSetter = 1;
 const int kFieldGetter = 2;
@@ -78,35 +79,40 @@
 namespace compiler {
 namespace php {
 
+struct Options {
+  bool is_descriptor = false;
+  bool aggregate_metadata = false;
+  bool gen_c_wkt = false;
+  std::set<string> aggregate_metadata_prefixes;
+};
+
+namespace {
+
 // Forward decls.
-std::string PhpName(const std::string& full_name, bool is_descriptor);
-std::string DefaultForField(FieldDescriptor* field);
+std::string PhpName(const std::string& full_name, const Options& options);
 std::string IntToString(int32 value);
-std::string FilenameToClassname(const string& filename);
+std::string FilenameToClassname(const std::string& filename);
 std::string GeneratedMetadataFileName(const FileDescriptor* file,
-                                      bool is_descriptor);
-std::string LabelForField(FieldDescriptor* field);
-std::string TypeName(FieldDescriptor* field);
-std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter);
-std::string BinaryToHex(const string& binary);
+                                      const Options& options);
+std::string UnderscoresToCamelCase(const std::string& name,
+                                   bool cap_first_letter);
 void Indent(io::Printer* printer);
 void Outdent(io::Printer* printer);
-void GenerateAddFilesToPool(const FileDescriptor* file,
-                            const std::set<string>& aggregate_metadata_prefixes,
+void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
                             io::Printer* printer);
 void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
-                               int is_descriptor);
+                               const Options& options);
 void GenerateMessageConstructorDocComment(io::Printer* printer,
                                           const Descriptor* message,
-                                          int is_descriptor);
+                                          const Options& options);
 void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
-                             int is_descriptor, int function_type);
+                             const Options& options, int function_type);
 void GenerateWrapperFieldGetterDocComment(io::Printer* printer,
                                           const FieldDescriptor* field);
 void GenerateWrapperFieldSetterDocComment(io::Printer* printer,
                                           const FieldDescriptor* field);
 void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
-                            int is_descriptor);
+                            const Options& options);
 void GenerateEnumValueDocComment(io::Printer* printer,
                                  const EnumValueDescriptor* value);
 void GenerateServiceDocComment(io::Printer* printer,
@@ -114,12 +120,12 @@
 void GenerateServiceMethodDocComment(io::Printer* printer,
                               const MethodDescriptor* method);
 
-std::string ReservedNamePrefix(const string& classname,
+std::string ReservedNamePrefix(const std::string& classname,
                                 const FileDescriptor* file) {
   bool is_reserved = false;
 
-  string lower = classname;
-  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+  std::string lower = classname;
+  std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
 
   for (int i = 0; i < kReservedNamesSize; i++) {
     if (lower == kReservedNames[i]) {
@@ -140,8 +146,8 @@
 }
 
 template <typename DescriptorType>
-std::string DescriptorFullName(const DescriptorType* desc, bool is_descriptor) {
-  if (is_descriptor) {
+std::string DescriptorFullName(const DescriptorType* desc, bool is_internal) {
+  if (is_internal) {
     return StringReplace(desc->full_name(),
                          "google.protobuf",
                          "google.protobuf.internal", false);
@@ -151,9 +157,9 @@
 }
 
 template <typename DescriptorType>
-std::string ClassNamePrefix(const string& classname,
+std::string ClassNamePrefix(const std::string& classname,
                             const DescriptorType* desc) {
-  const string& prefix = (desc->file()->options()).php_class_prefix();
+  const std::string& prefix = (desc->file()->options()).php_class_prefix();
   if (!prefix.empty()) {
     return prefix;
   }
@@ -178,18 +184,6 @@
   return ClassNamePrefix(classname, desc) + classname;
 }
 
-std::string GeneratedClassName(const Descriptor* desc) {
-  return GeneratedClassNameImpl(desc);
-}
-
-std::string GeneratedClassName(const EnumDescriptor* desc) {
-  return GeneratedClassNameImpl(desc);
-}
-
-std::string GeneratedClassName(const ServiceDescriptor* desc) {
-  return GeneratedClassNameImpl(desc);
-}
-
 template <typename DescriptorType>
 std::string LegacyGeneratedClassName(const DescriptorType* desc) {
   std::string classname = desc->name();
@@ -201,9 +195,9 @@
   return ClassNamePrefix(classname, desc) + classname;
 }
 
-std::string ClassNamePrefix(const string& classname) {
-  string lower = classname;
-  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+std::string ClassNamePrefix(const std::string& classname) {
+  std::string lower = classname;
+  std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
 
   for (int i = 0; i < kReservedNamesSize; i++) {
     if (lower == kReservedNames[i]) {
@@ -214,11 +208,11 @@
   return "";
 }
 
-std::string ConstantNamePrefix(const string& classname) {
+std::string ConstantNamePrefix(const std::string& classname) {
   bool is_reserved = false;
 
-  string lower = classname;
-  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+  std::string lower = classname;
+  std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
 
   for (int i = 0; i < kReservedNamesSize; i++) {
     if (lower == kReservedNames[i]) {
@@ -242,9 +236,10 @@
 }
 
 template <typename DescriptorType>
-std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) {
+std::string RootPhpNamespace(const DescriptorType* desc,
+                             const Options& options) {
   if (desc->file()->options().has_php_namespace()) {
-    const string& php_namespace = desc->file()->options().php_namespace();
+    const std::string& php_namespace = desc->file()->options().php_namespace();
     if (!php_namespace.empty()) {
       return php_namespace;
     }
@@ -252,15 +247,15 @@
   }
 
   if (!desc->file()->package().empty()) {
-    return PhpName(desc->file()->package(), is_descriptor);
+    return PhpName(desc->file()->package(), options);
   }
   return "";
 }
 
 template <typename DescriptorType>
-std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
-  string classname = GeneratedClassNameImpl(desc);
-  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+std::string FullClassName(const DescriptorType* desc, const Options& options) {
+  std::string classname = GeneratedClassNameImpl(desc);
+  std::string php_namespace = RootPhpNamespace(desc, options);
   if (!php_namespace.empty()) {
     return php_namespace + "\\" + classname;
   }
@@ -268,17 +263,25 @@
 }
 
 template <typename DescriptorType>
-std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) {
-  string classname = LegacyGeneratedClassName(desc);
-  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return FullClassName(desc, options);
+}
+
+template <typename DescriptorType>
+std::string LegacyFullClassName(const DescriptorType* desc,
+                                const Options& options) {
+  std::string classname = LegacyGeneratedClassName(desc);
+  std::string php_namespace = RootPhpNamespace(desc, options);
   if (!php_namespace.empty()) {
     return php_namespace + "\\" + classname;
   }
   return classname;
 }
 
-std::string PhpName(const std::string& full_name, bool is_descriptor) {
-  if (is_descriptor) {
+std::string PhpName(const std::string& full_name, const Options& options) {
+  if (options.is_descriptor) {
     return kDescriptorPackageName;
   }
 
@@ -327,8 +330,8 @@
 }
 
 std::string GeneratedMetadataFileName(const FileDescriptor* file,
-                                      bool is_descriptor) {
-  const string& proto_file = file->name();
+                                      const Options& options) {
+  const std::string& proto_file = file->name();
   int start_index = 0;
   int first_index = proto_file.find_first_of("/", start_index);
   std::string result = "";
@@ -337,7 +340,7 @@
   if (proto_file == kEmptyFile) {
     return kEmptyMetadataFile;
   }
-  if (is_descriptor) {
+  if (options.is_descriptor) {
     return kDescriptorMetadataFile;
   }
 
@@ -351,7 +354,7 @@
   }
 
   if (file->options().has_php_metadata_namespace()) {
-    const string& php_metadata_namespace =
+    const std::string& php_metadata_namespace =
         file->options().php_metadata_namespace();
     if (!php_metadata_namespace.empty() && php_metadata_namespace != "\\") {
       result += php_metadata_namespace;
@@ -362,7 +365,7 @@
     }
   } else {
     result += "GPBMetadata/";
-    while (first_index != string::npos) {
+    while (first_index != std::string::npos) {
       segment = UnderscoresToCamelCase(
           file_no_suffix.substr(start_index, first_index - start_index), true);
       result += ReservedNamePrefix(segment, file) + segment + "/";
@@ -373,7 +376,7 @@
 
   // Append file name.
   int file_name_start = file_no_suffix.find_last_of("/");
-  if (file_name_start == string::npos) {
+  if (file_name_start == std::string::npos) {
     file_name_start = 0;
   } else {
     file_name_start += 1;
@@ -384,10 +387,17 @@
   return result + ReservedNamePrefix(segment, file) + segment + ".php";
 }
 
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
+                                      bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return GeneratedMetadataFileName(file, options);
+}
+
 template <typename DescriptorType>
 std::string GeneratedClassFileName(const DescriptorType* desc,
-                                     bool is_descriptor) {
-  std::string result = FullClassName(desc, is_descriptor);
+                                   const Options& options) {
+  std::string result = FullClassName(desc, options);
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
       result[i] = '/';
@@ -398,8 +408,8 @@
 
 template <typename DescriptorType>
 std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
-                                     bool is_descriptor) {
-  std::string result = LegacyFullClassName(desc, is_descriptor);
+                                         const Options& options) {
+  std::string result = LegacyFullClassName(desc, options);
 
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
@@ -410,8 +420,8 @@
 }
 
 std::string GeneratedServiceFileName(const ServiceDescriptor* service,
-                                    bool is_descriptor) {
-  std::string result = FullClassName(service, is_descriptor) + "Interface";
+                                     const Options& options) {
+  std::string result = FullClassName(service, options) + "Interface";
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
       result[i] = '/';
@@ -435,35 +445,12 @@
   }
 }
 
-std::string TypeName(const FieldDescriptor* field) {
-  switch (field->type()) {
-    case FieldDescriptor::TYPE_INT32: return "int32";
-    case FieldDescriptor::TYPE_INT64: return "int64";
-    case FieldDescriptor::TYPE_UINT32: return "uint32";
-    case FieldDescriptor::TYPE_UINT64: return "uint64";
-    case FieldDescriptor::TYPE_SINT32: return "sint32";
-    case FieldDescriptor::TYPE_SINT64: return "sint64";
-    case FieldDescriptor::TYPE_FIXED32: return "fixed32";
-    case FieldDescriptor::TYPE_FIXED64: return "fixed64";
-    case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
-    case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
-    case FieldDescriptor::TYPE_DOUBLE: return "double";
-    case FieldDescriptor::TYPE_FLOAT: return "float";
-    case FieldDescriptor::TYPE_BOOL: return "bool";
-    case FieldDescriptor::TYPE_ENUM: return "enum";
-    case FieldDescriptor::TYPE_STRING: return "string";
-    case FieldDescriptor::TYPE_BYTES: return "bytes";
-    case FieldDescriptor::TYPE_MESSAGE: return "message";
-    case FieldDescriptor::TYPE_GROUP: return "group";
-    default: assert(false); return "";
-  }
-}
-
-std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+std::string PhpSetterTypeName(const FieldDescriptor* field,
+                              const Options& options) {
   if (field->is_map()) {
     return "array|\\Google\\Protobuf\\Internal\\MapField";
   }
-  string type;
+  std::string type;
   switch (field->type()) {
     case FieldDescriptor::TYPE_INT32:
     case FieldDescriptor::TYPE_UINT32:
@@ -492,7 +479,7 @@
       type = "string";
       break;
     case FieldDescriptor::TYPE_MESSAGE:
-      type = "\\" + FullClassName(field->message_type(), is_descriptor);
+      type = "\\" + FullClassName(field->message_type(), options);
       break;
     case FieldDescriptor::TYPE_GROUP:
       return "null";
@@ -509,7 +496,15 @@
   return type;
 }
 
-std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+std::string PhpSetterTypeName(const FieldDescriptor* field,
+                              bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return PhpSetterTypeName(field, options);
+}
+
+std::string PhpGetterTypeName(const FieldDescriptor* field,
+                              const Options& options) {
   if (field->is_map()) {
     return "\\Google\\Protobuf\\Internal\\MapField";
   }
@@ -534,26 +529,44 @@
     case FieldDescriptor::TYPE_STRING:
     case FieldDescriptor::TYPE_BYTES: return "string";
     case FieldDescriptor::TYPE_MESSAGE:
-      return "\\" + FullClassName(field->message_type(), is_descriptor);
+      return "\\" + FullClassName(field->message_type(), options);
     case FieldDescriptor::TYPE_GROUP: return "null";
     default: assert(false); return "";
   }
 }
 
-std::string EnumOrMessageSuffix(
-    const FieldDescriptor* field, bool is_descriptor) {
+std::string PhpGetterTypeName(const FieldDescriptor* field,
+                              bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return PhpGetterTypeName(field, options);
+}
+
+std::string EnumOrMessageSuffix(const FieldDescriptor* field,
+                                const Options& options) {
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-    return ", '" + DescriptorFullName(field->message_type(), is_descriptor) + "'";
+    return ", '" +
+           DescriptorFullName(field->message_type(), options.is_descriptor) +
+           "'";
   }
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
-    return ", '" + DescriptorFullName(field->enum_type(), is_descriptor) + "'";
+    return ", '" +
+           DescriptorFullName(field->enum_type(), options.is_descriptor) + "'";
   }
   return "";
 }
 
+std::string EnumOrMessageSuffix(const FieldDescriptor* field,
+                                bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return EnumOrMessageSuffix(field, options);
+}
+
 // Converts a name to camel-case. If cap_first_letter is true, capitalize the
 // first letter.
-std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter) {
+std::string UnderscoresToCamelCase(const std::string& name,
+                                   bool cap_first_letter) {
   std::string result;
   for (int i = 0; i < name.size(); i++) {
     if ('a' <= name[i] && name[i] <= 'z') {
@@ -587,27 +600,6 @@
   return result;
 }
 
-std::string BinaryToHex(const string& binary) {
-  string dest;
-  size_t i;
-  unsigned char symbol[16] = {
-    '0', '1', '2', '3',
-    '4', '5', '6', '7',
-    '8', '9', 'a', 'b',
-    'c', 'd', 'e', 'f',
-  };
-
-  dest.resize(binary.size() * 2);
-  char* append_ptr = &dest[0];
-
-  for (i = 0; i < binary.size(); i++) {
-    *append_ptr++ = symbol[(binary[i] & 0xf0) >> 4];
-    *append_ptr++ = symbol[binary[i] & 0x0f];
-  }
-
-  return dest;
-}
-
 void Indent(io::Printer* printer) {
   printer->Indent();
   printer->Indent();
@@ -618,27 +610,23 @@
 }
 
 void GenerateField(const FieldDescriptor* field, io::Printer* printer,
-                   bool is_descriptor) {
+                   const Options& options) {
   if (field->is_repeated()) {
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
+    GenerateFieldDocComment(printer, field, options, kFieldProperty);
     printer->Print(
         "private $^name^;\n",
         "name", field->name());
-  } else if (field->containing_oneof()) {
+  } else if (field->real_containing_oneof()) {
     // Oneof fields are handled by GenerateOneofField.
     return;
   } else {
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
+    std::string initial_value =
+        field->has_presence() ? "null" : DefaultForField(field);
+    GenerateFieldDocComment(printer, field, options, kFieldProperty);
     printer->Print(
-        "protected $^name^ = ^default^;\n",
+        "protected $^name^ = ^initial_value^;\n",
         "name", field->name(),
-        "default", DefaultForField(field));
-  }
-
-  if (is_descriptor) {
-    printer->Print(
-        "private $has_^name^ = false;\n",
-        "name", field->name());
+        "initial_value", initial_value);
   }
 }
 
@@ -650,29 +638,72 @@
       "name", oneof->name());
 }
 
-void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
+void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
                            io::Printer* printer) {
-  const OneofDescriptor* oneof = field->containing_oneof();
+  const OneofDescriptor* oneof = field->real_containing_oneof();
 
   // Generate getter.
+  GenerateFieldDocComment(printer, field, options, kFieldGetter);
+
+  // deprecation
+  std::string deprecation_trigger = (field->options().deprecated()) ? "@trigger_error('" +
+      field->name() + " is deprecated.', E_USER_DEPRECATED);\n        " : "";
+
+  // Emit getter.
   if (oneof != NULL) {
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
     printer->Print(
         "public function get^camel_name^()\n"
         "{\n"
-        "    return $this->readOneof(^number^);\n"
+        "    ^deprecation_trigger^return $this->readOneof(^number^);\n"
         "}\n\n",
         "camel_name", UnderscoresToCamelCase(field->name(), true),
-        "number", IntToString(field->number()));
-  } else {
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
+        "number", IntToString(field->number()),
+        "deprecation_trigger", deprecation_trigger);
+  } else if (field->has_presence() && !field->message_type()) {
     printer->Print(
         "public function get^camel_name^()\n"
         "{\n"
-        "    return $this->^name^;\n"
+        "    ^deprecation_trigger^return isset($this->^name^) ? $this->^name^ : ^default_value^;\n"
         "}\n\n",
-        "camel_name", UnderscoresToCamelCase(field->name(), true), "name",
-        field->name());
+        "camel_name", UnderscoresToCamelCase(field->name(), true),
+        "name", field->name(),
+        "default_value", DefaultForField(field),
+        "deprecation_trigger", deprecation_trigger);
+  } else {
+    printer->Print(
+        "public function get^camel_name^()\n"
+        "{\n"
+        "    ^deprecation_trigger^return $this->^name^;\n"
+        "}\n\n",
+        "camel_name", UnderscoresToCamelCase(field->name(), true),
+        "name", field->name(),
+        "deprecation_trigger", deprecation_trigger);
+  }
+
+  // Emit hazzers/clear.
+  if (oneof) {
+    printer->Print(
+        "public function has^camel_name^()\n"
+        "{\n"
+        "    ^deprecation_trigger^return $this->hasOneof(^number^);\n"
+        "}\n\n",
+        "camel_name", UnderscoresToCamelCase(field->name(), true),
+        "number", IntToString(field->number()),
+        "deprecation_trigger", deprecation_trigger);
+  } else if (field->has_presence()) {
+    printer->Print(
+        "public function has^camel_name^()\n"
+        "{\n"
+        "    ^deprecation_trigger^return isset($this->^name^);\n"
+        "}\n\n"
+        "public function clear^camel_name^()\n"
+        "{\n"
+        "    ^deprecation_trigger^unset($this->^name^);\n"
+        "}\n\n",
+        "camel_name", UnderscoresToCamelCase(field->name(), true),
+        "name", field->name(),
+        "default_value", DefaultForField(field),
+        "deprecation_trigger", deprecation_trigger);
   }
 
   // For wrapper types, generate an additional getXXXUnwrapped getter
@@ -684,14 +715,15 @@
     printer->Print(
         "public function get^camel_name^Unwrapped()\n"
         "{\n"
-        "    return $this->readWrapperValue(\"^field_name^\");\n"
+        "    ^deprecation_trigger^return $this->readWrapperValue(\"^field_name^\");\n"
         "}\n\n",
         "camel_name", UnderscoresToCamelCase(field->name(), true),
-        "field_name", field->name());
+        "field_name", field->name(),
+        "deprecation_trigger", deprecation_trigger);
   }
 
   // Generate setter.
-  GenerateFieldDocComment(printer, field, is_descriptor, kFieldSetter);
+  GenerateFieldDocComment(printer, field, options, kFieldSetter);
   printer->Print(
       "public function set^camel_name^($var)\n"
       "{\n",
@@ -699,6 +731,13 @@
 
   Indent(printer);
 
+  if (field->options().deprecated()) {
+      printer->Print(
+          "^deprecation_trigger^",
+          "deprecation_trigger", deprecation_trigger
+      );
+  }
+
   // Type check.
   if (field->is_map()) {
     const Descriptor* map_entry = field->message_type();
@@ -714,12 +753,12 @@
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(value->message_type(), is_descriptor) + "::class");
+          FullClassName(value->message_type(), options) + "::class");
     } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(value->enum_type(), is_descriptor) + "::class");
+          FullClassName(value->enum_type(), options) + "::class");
     } else {
       printer->Print(");\n");
     }
@@ -732,23 +771,23 @@
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(field->message_type(), is_descriptor) + "::class");
+          FullClassName(field->message_type(), options) + "::class");
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(field->enum_type(), is_descriptor) + "::class");
+          FullClassName(field->enum_type(), options) + "::class");
     } else {
       printer->Print(");\n");
     }
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     printer->Print(
         "GPBUtil::checkMessage($var, \\^class_name^::class);\n",
-        "class_name", LegacyFullClassName(field->message_type(), is_descriptor));
+        "class_name", FullClassName(field->message_type(), options));
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
     printer->Print(
         "GPBUtil::checkEnum($var, \\^class_name^::class);\n",
-        "class_name", LegacyFullClassName(field->enum_type(), is_descriptor));
+        "class_name", FullClassName(field->enum_type(), options));
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
     printer->Print(
         "GPBUtil::checkString($var, ^utf8^);\n",
@@ -774,13 +813,6 @@
         "name", field->name());
   }
 
-  // Set has bit for proto2 only.
-  if (is_descriptor) {
-    printer->Print(
-        "$this->has_^field_name^ = true;\n",
-        "field_name", field->name());
-  }
-
   printer->Print("\nreturn $this;\n");
 
   Outdent(printer);
@@ -803,17 +835,6 @@
         "camel_name", UnderscoresToCamelCase(field->name(), true),
         "field_name", field->name());
   }
-
-  // Generate has method for proto2 only.
-  if (is_descriptor) {
-    printer->Print(
-        "public function has^camel_name^()\n"
-        "{\n"
-        "    return $this->has_^field_name^;\n"
-        "}\n\n",
-        "camel_name", UnderscoresToCamelCase(field->name(), true),
-        "field_name", field->name());
-  }
 }
 
 void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
@@ -845,15 +866,16 @@
   );
 }
 
-void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
-                           io::Printer* printer) {
+void GenerateMessageToPool(const std::string& name_prefix,
+                           const Descriptor* message, io::Printer* printer) {
   // Don't generate MapEntry messages -- we use the PHP extension's native
   // support for map fields instead.
   if (message->options().map_entry()) {
     return;
   }
-  string class_name = (name_prefix.empty() ? "" : name_prefix + "\\") +
-    ReservedNamePrefix(message->name(), message->file()) + message->name();
+  std::string class_name =
+      (name_prefix.empty() ? "" : name_prefix + "\\") +
+      ReservedNamePrefix(message->name(), message->file()) + message->name();
 
   printer->Print(
       "$pool->addMessage('^message^', "
@@ -878,7 +900,7 @@
           "value", ToUpper(val->type_name()),
           "number", StrCat(field->number()),
           "other", EnumOrMessageSuffix(val, true));
-    } else if (!field->containing_oneof()) {
+    } else if (!field->real_containing_oneof()) {
       printer->Print(
           "->^label^('^field^', "
           "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
@@ -891,7 +913,7 @@
   }
 
   // oneofs.
-  for (int i = 0; i < message->oneof_decl_count(); i++) {
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     printer->Print("->oneof(^name^)\n",
                    "name", oneof->name());
@@ -926,19 +948,15 @@
   }
 }
 
-void GenerateAddFileToPool(
-    const FileDescriptor* file,
-    bool is_descriptor,
-    bool aggregate_metadata,
-    const std::set<string>& aggregate_metadata_prefixes,
-    io::Printer* printer) {
+void GenerateAddFileToPool(const FileDescriptor* file, const Options& options,
+                           io::Printer* printer) {
   printer->Print(
       "public static $is_initialized = false;\n\n"
       "public static function initOnce() {\n");
   Indent(printer);
 
-  if (aggregate_metadata) {
-    GenerateAddFilesToPool(file, aggregate_metadata_prefixes, printer);
+  if (options.aggregate_metadata) {
+    GenerateAddFilesToPool(file, options, printer);
   } else {
     printer->Print(
         "$pool = \\Google\\Protobuf\\Internal\\"
@@ -947,7 +965,7 @@
         "  return;\n"
         "}\n");
 
-    if (is_descriptor) {
+    if (options.is_descriptor) {
       for (int i = 0; i < file->message_type_count(); i++) {
         GenerateMessageToPool("", file->message_type(i), printer);
       }
@@ -967,7 +985,7 @@
           continue;
         }
         std::string dependency_filename =
-            GeneratedMetadataFileName(file->dependency(i), is_descriptor);
+            GeneratedMetadataFileName(file->dependency(i), options);
         printer->Print(
             "\\^name^::initOnce();\n",
             "name", FilenameToClassname(dependency_filename));
@@ -979,8 +997,9 @@
       file->CopyTo(file_proto);
 
       // Filter out descriptor.proto as it cannot be depended on for now.
-      RepeatedPtrField<string>* dependency = file_proto->mutable_dependency();
-      for (RepeatedPtrField<string>::iterator it = dependency->begin();
+      RepeatedPtrField<std::string>* dependency =
+          file_proto->mutable_dependency();
+      for (RepeatedPtrField<std::string>::iterator it = dependency->begin();
            it != dependency->end(); ++it) {
         if (*it != kDescriptorFile) {
           dependency->erase(it);
@@ -997,19 +1016,31 @@
         it->clear_extension();
       }
 
-      string files_data;
+      std::string files_data;
       files.SerializeToString(&files_data);
 
-      printer->Print("$pool->internalAddGeneratedFile(hex2bin(\n");
+      printer->Print("$pool->internalAddGeneratedFile(\n");
       Indent(printer);
+      printer->Print("'");
 
-      printer->Print(
-          "\"^data^\"\n",
-          "data", BinaryToHex(files_data));
+      for (auto ch : files_data) {
+        switch (ch) {
+          case '\\':
+            printer->Print(R"(\\)");
+            break;
+          case '\'':
+            printer->Print(R"(\')");
+            break;
+          default:
+            printer->Print("^char^", "char", std::string(1, ch));
+            break;
+        }
+      }
 
+      printer->Print("'\n");
       Outdent(printer);
       printer->Print(
-          "), true);\n\n");
+          ", true);\n\n");
     }
     printer->Print(
         "static::$is_initialized = true;\n");
@@ -1052,14 +1083,13 @@
   }
 }
 
-static bool NeedsUnwrapping(
-    const FileDescriptor* file,
-    const std::set<string>& aggregate_metadata_prefixes) {
+static bool NeedsUnwrapping(const FileDescriptor* file,
+                            const Options& options) {
   bool has_aggregate_metadata_prefix = false;
-  if (aggregate_metadata_prefixes.empty()) {
+  if (options.aggregate_metadata_prefixes.empty()) {
     has_aggregate_metadata_prefix = true;
   } else {
-    for (const auto& prefix : aggregate_metadata_prefixes) {
+    for (const auto& prefix : options.aggregate_metadata_prefixes) {
       if (HasPrefixString(file->package(), prefix)) {
         has_aggregate_metadata_prefix = true;
         break;
@@ -1070,10 +1100,8 @@
   return has_aggregate_metadata_prefix;
 }
 
-void GenerateAddFilesToPool(
-    const FileDescriptor* file,
-    const std::set<string>& aggregate_metadata_prefixes,
-    io::Printer* printer) {
+void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
+                            io::Printer* printer) {
   printer->Print(
       "$pool = \\Google\\Protobuf\\Internal\\"
       "DescriptorPool::getGeneratedPool();\n"
@@ -1102,15 +1130,16 @@
       }
     }
 
-    bool needs_aggregate = NeedsUnwrapping(file, aggregate_metadata_prefixes);
+    bool needs_aggregate = NeedsUnwrapping(file, options);
 
     if (needs_aggregate) {
       auto file_proto = sorted_file_set.add_file();
       file->CopyTo(file_proto);
 
       // Filter out descriptor.proto as it cannot be depended on for now.
-      RepeatedPtrField<string>* dependency = file_proto->mutable_dependency();
-      for (RepeatedPtrField<string>::iterator it = dependency->begin();
+      RepeatedPtrField<std::string>* dependency =
+          file_proto->mutable_dependency();
+      for (RepeatedPtrField<std::string>::iterator it = dependency->begin();
            it != dependency->end(); ++it) {
         if (*it != kDescriptorFile) {
           dependency->erase(it);
@@ -1127,34 +1156,45 @@
         it->clear_extension();
       }
     } else {
-      std::string dependency_filename =
-          GeneratedMetadataFileName(file, false);
+      std::string dependency_filename = GeneratedMetadataFileName(file, false);
       printer->Print(
           "\\^name^::initOnce();\n",
           "name", FilenameToClassname(dependency_filename));
     }
   }
 
-  string files_data;
+  std::string files_data;
   sorted_file_set.SerializeToString(&files_data);
 
-  printer->Print("$pool->internalAddGeneratedFile(hex2bin(\n");
+  printer->Print("$pool->internalAddGeneratedFile(\n");
   Indent(printer);
+  printer->Print("'");
 
-  printer->Print(
-      "\"^data^\"\n",
-      "data", BinaryToHex(files_data));
+  for (auto ch : files_data) {
+    switch (ch) {
+      case '\\':
+        printer->Print(R"(\\)");
+        break;
+      case '\'':
+        printer->Print(R"(\')");
+        break;
+      default:
+        printer->Print("^char^", "char", std::string(1, ch));
+        break;
+    }
+  }
 
+  printer->Print("'\n");
   Outdent(printer);
   printer->Print(
-      "), true);\n");
+      ", true);\n");
 
   printer->Print(
       "static::$is_initialized = true;\n");
 }
 
-void GenerateUseDeclaration(bool is_descriptor, io::Printer* printer) {
-  if (!is_descriptor) {
+void GenerateUseDeclaration(const Options& options, io::Printer* printer) {
+  if (!options.is_descriptor) {
     printer->Print(
         "use Google\\Protobuf\\Internal\\GPBType;\n"
         "use Google\\Protobuf\\Internal\\RepeatedField;\n"
@@ -1178,7 +1218,7 @@
     "filename", file->name());
 }
 
-std::string FilenameToClassname(const string& filename) {
+std::string FilenameToClassname(const std::string& filename) {
   int lastindex = filename.find_last_of(".");
   std::string result = filename.substr(0, lastindex);
   for (int i = 0; i < result.size(); i++) {
@@ -1189,12 +1229,9 @@
   return result;
 }
 
-void GenerateMetadataFile(const FileDescriptor* file,
-                          bool is_descriptor,
-                          bool aggregate_metadata,
-                          const std::set<string>& aggregate_metadata_prefixes,
+void GenerateMetadataFile(const FileDescriptor* file, const Options& options,
                           GeneratorContext* generator_context) {
-  std::string filename = GeneratedMetadataFileName(file, is_descriptor);
+  std::string filename = GeneratedMetadataFileName(file, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1204,7 +1241,7 @@
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (lastindex != string::npos) {
+  if (lastindex != std::string::npos) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
@@ -1221,32 +1258,30 @@
   }
   Indent(&printer);
 
-  GenerateAddFileToPool(file, is_descriptor, aggregate_metadata,
-                        aggregate_metadata_prefixes, &printer);
+  GenerateAddFileToPool(file, options, &printer);
 
   Outdent(&printer);
   printer.Print("}\n\n");
 }
 
 template <typename DescriptorType>
-void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc,
-                         bool is_descriptor,
-                         GeneratorContext* generator_context) {
-
-  std::string filename = LegacyGeneratedClassFileName(desc, is_descriptor);
+void LegacyGenerateClassFile(const FileDescriptor* file,
+                             const DescriptorType* desc, const Options& options,
+                             GeneratorContext* generator_context) {
+  std::string filename = LegacyGeneratedClassFileName(desc, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
 
   GenerateHead(file, &printer);
 
-  std::string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  std::string php_namespace = RootPhpNamespace(desc, options);
   if (!php_namespace.empty()) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", php_namespace);
   }
-  std::string newname = FullClassName(desc, is_descriptor);
+  std::string newname = FullClassName(desc, options);
   printer.Print("if (false) {\n");
   Indent(&printer);
   printer.Print("/**\n");
@@ -1262,13 +1297,14 @@
       "new", GeneratedClassNameImpl(desc));
   printer.Print("@trigger_error('^old^ is deprecated and will be removed in "
       "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n",
-      "old", LegacyFullClassName(desc, is_descriptor),
+      "old", LegacyFullClassName(desc, options),
       "fullname", newname);
 }
 
 void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
-                      bool is_descriptor, GeneratorContext* generator_context) {
-  std::string filename = GeneratedClassFileName(en, is_descriptor);
+                      const Options& options,
+                      GeneratorContext* generator_context) {
+  std::string filename = GeneratedClassFileName(en, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1278,7 +1314,7 @@
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (lastindex != string::npos) {
+  if (lastindex != std::string::npos) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
@@ -1288,9 +1324,9 @@
     printer.Print("use UnexpectedValueException;\n\n");
   }
 
-  GenerateEnumDocComment(&printer, en, is_descriptor);
+  GenerateEnumDocComment(&printer, en, options);
 
-  if (lastindex != string::npos) {
+  if (lastindex != std::string::npos) {
     fullname = fullname.substr(lastindex + 1);
   }
 
@@ -1365,14 +1401,13 @@
     printer.Print(
         "class_alias(^new^::class, \\^old^::class);\n\n",
         "new", fullname,
-        "old", LegacyFullClassName(en, is_descriptor));
-    LegacyGenerateClassFile(file, en, is_descriptor, generator_context);
+        "old", LegacyFullClassName(en, options));
+    LegacyGenerateClassFile(file, en, options, generator_context);
   }
 }
 
 void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
-                         bool is_descriptor,
-                         bool aggregate_metadata,
+                         const Options& options,
                          GeneratorContext* generator_context) {
   // Don't generate MapEntry messages -- we use the PHP extension's native
   // support for map fields instead.
@@ -1380,7 +1415,7 @@
     return;
   }
 
-  std::string filename = GeneratedClassFileName(message, is_descriptor);
+  std::string filename = GeneratedClassFileName(message, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1390,43 +1425,57 @@
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (lastindex != string::npos) {
+  if (lastindex != std::string::npos) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
   }
 
-  GenerateUseDeclaration(is_descriptor, &printer);
+  GenerateUseDeclaration(options, &printer);
 
-  GenerateMessageDocComment(&printer, message, is_descriptor);
-  if (lastindex != string::npos) {
+  GenerateMessageDocComment(&printer, message, options);
+  if (lastindex != std::string::npos) {
     fullname = fullname.substr(lastindex + 1);
   }
 
+  std::string base;
+
+  switch (message->well_known_type()) {
+    case Descriptor::WELLKNOWNTYPE_ANY:
+      base = "\\Google\\Protobuf\\Internal\\AnyBase";
+      break;
+    case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
+      base = "\\Google\\Protobuf\\Internal\\TimestampBase";
+      break;
+    default:
+      base = "\\Google\\Protobuf\\Internal\\Message";
+      break;
+  }
+
   printer.Print(
-      "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
+      "class ^name^ extends ^base^\n"
       "{\n",
+      "base", base,
       "name", fullname);
   Indent(&printer);
 
   // Field and oneof definitions.
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
-    GenerateField(field, &printer, is_descriptor);
+    GenerateField(field, &printer, options);
   }
-  for (int i = 0; i < message->oneof_decl_count(); i++) {
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     GenerateOneofField(oneof, &printer);
   }
   printer.Print("\n");
 
-  GenerateMessageConstructorDocComment(&printer, message, is_descriptor);
+  GenerateMessageConstructorDocComment(&printer, message, options);
   printer.Print(
       "public function __construct($data = NULL) {\n");
   Indent(&printer);
 
-  std::string metadata_filename =
-      GeneratedMetadataFileName(file, is_descriptor);
+  std::string metadata_filename = GeneratedMetadataFileName(file, options);
   std::string metadata_fullname = FilenameToClassname(metadata_filename);
   printer.Print(
       "\\^fullname^::initOnce();\n",
@@ -1441,9 +1490,9 @@
   // Field and oneof accessors.
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
-    GenerateFieldAccessor(field, is_descriptor, &printer);
+    GenerateFieldAccessor(field, options, &printer);
   }
-  for (int i = 0; i < message->oneof_decl_count(); i++) {
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     printer.Print(
       "/**\n"
@@ -1467,26 +1516,24 @@
     printer.Print(
         "class_alias(^new^::class, \\^old^::class);\n\n",
         "new", fullname,
-        "old", LegacyFullClassName(message, is_descriptor));
-    LegacyGenerateClassFile(file, message, is_descriptor, generator_context);
+        "old", LegacyFullClassName(message, options));
+    LegacyGenerateClassFile(file, message, options, generator_context);
   }
 
   // Nested messages and enums.
   for (int i = 0; i < message->nested_type_count(); i++) {
-    GenerateMessageFile(file, message->nested_type(i), is_descriptor,
-                        aggregate_metadata,
+    GenerateMessageFile(file, message->nested_type(i), options,
                         generator_context);
   }
   for (int i = 0; i < message->enum_type_count(); i++) {
-    GenerateEnumFile(file, message->enum_type(i), is_descriptor,
-                     generator_context);
+    GenerateEnumFile(file, message->enum_type(i), options, generator_context);
   }
 }
 
-void GenerateServiceFile(const FileDescriptor* file,
-  const ServiceDescriptor* service, bool is_descriptor,
-  GeneratorContext* generator_context) {
-  std::string filename = GeneratedServiceFileName(service, is_descriptor);
+void GenerateServiceFile(
+    const FileDescriptor* file, const ServiceDescriptor* service,
+    const Options& options, GeneratorContext* generator_context) {
+  std::string filename = GeneratedServiceFileName(service, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1498,7 +1545,7 @@
 
   if (!file->options().php_namespace().empty() ||
       (!file->options().has_php_namespace() && !file->package().empty()) ||
-      lastindex != string::npos) {
+      lastindex != std::string::npos) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
@@ -1506,13 +1553,13 @@
 
   GenerateServiceDocComment(&printer, service);
 
-  if (lastindex != string::npos) {
-      printer.Print(
+  if (lastindex != std::string::npos) {
+    printer.Print(
         "interface ^name^\n"
         "{\n",
         "name", fullname.substr(lastindex + 1));
   } else {
-      printer.Print(
+    printer.Print(
         "interface ^name^\n"
         "{\n",
         "name", fullname);
@@ -1530,37 +1577,31 @@
   printer.Print("}\n\n");
 }
 
-void GenerateFile(const FileDescriptor* file, bool is_descriptor,
-                  bool aggregate_metadata,
-                  const std::set<string>& aggregate_metadata_prefixes,
+void GenerateFile(const FileDescriptor* file, const Options& options,
                   GeneratorContext* generator_context) {
-  GenerateMetadataFile(file, is_descriptor, aggregate_metadata,
-                       aggregate_metadata_prefixes, generator_context);
+  GenerateMetadataFile(file, options, generator_context);
 
   for (int i = 0; i < file->message_type_count(); i++) {
-    GenerateMessageFile(file, file->message_type(i), is_descriptor,
-                        aggregate_metadata,
+    GenerateMessageFile(file, file->message_type(i), options,
                         generator_context);
   }
   for (int i = 0; i < file->enum_type_count(); i++) {
-    GenerateEnumFile(file, file->enum_type(i), is_descriptor,
-                     generator_context);
+    GenerateEnumFile(file, file->enum_type(i), options, generator_context);
   }
   if (file->options().php_generic_services()) {
     for (int i = 0; i < file->service_count(); i++) {
-      GenerateServiceFile(file, file->service(i), is_descriptor,
-                          generator_context);
+      GenerateServiceFile(file, file->service(i), options, generator_context);
     }
   }
 }
 
-static string EscapePhpdoc(const string& input) {
-  string result;
+static std::string EscapePhpdoc(const std::string& input) {
+  std::string result;
   result.reserve(input.size() * 2);
 
   char prev = '*';
 
-  for (string::size_type i = 0; i < input.size(); i++) {
+  for (std::string::size_type i = 0; i < input.size(); i++) {
     char c = input[i];
     switch (c) {
       case '*':
@@ -1599,8 +1640,9 @@
 static void GenerateDocCommentBodyForLocation(
     io::Printer* printer, const SourceLocation& location, bool trailingNewline,
     int indentCount) {
-  string comments = location.leading_comments.empty() ?
-      location.trailing_comments : location.leading_comments;
+  std::string comments = location.leading_comments.empty()
+                             ? location.trailing_comments
+                             : location.leading_comments;
   if (!comments.empty()) {
     // TODO(teboring):  Ideally we should parse the comment text as Markdown and
     //   write it back as HTML, but this requires a Markdown parser.  For now
@@ -1610,7 +1652,7 @@
     // HTML-escape them so that they don't accidentally close the doc comment.
     comments = EscapePhpdoc(comments);
 
-    std::vector<string> lines = Split(comments, "\n", true);
+    std::vector<std::string> lines = Split(comments, "\n", true);
     while (!lines.empty() && lines.back().empty()) {
       lines.pop_back();
     }
@@ -1641,31 +1683,31 @@
   }
 }
 
-static string FirstLineOf(const string& value) {
-  string result = value;
+static std::string FirstLineOf(const std::string& value) {
+  std::string result = value;
 
-  string::size_type pos = result.find_first_of('\n');
-  if (pos != string::npos) {
+  std::string::size_type pos = result.find_first_of('\n');
+  if (pos != std::string::npos) {
     result.erase(pos);
   }
 
   return result;
 }
 
-void GenerateMessageDocComment(io::Printer* printer,
-                               const Descriptor* message, int is_descriptor) {
+void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
+                               const Options& options) {
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, message);
   printer->Print(
     " * Generated from protobuf message <code>^messagename^</code>\n"
     " */\n",
-    "fullname", EscapePhpdoc(FullClassName(message, is_descriptor)),
+    "fullname", EscapePhpdoc(FullClassName(message, options)),
     "messagename", EscapePhpdoc(message->full_name()));
 }
 
 void GenerateMessageConstructorDocComment(io::Printer* printer,
                                           const Descriptor* message,
-                                          int is_descriptor) {
+                                          const Options& options) {
   // In theory we should have slightly different comments for setters, getters,
   // etc., but in practice everyone already knows the difference between these
   // so it's redundant information.
@@ -1683,7 +1725,7 @@
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
     printer->Print(" *     @type ^php_type^ $^var^\n",
-      "php_type", PhpSetterTypeName(field, is_descriptor),
+      "php_type", PhpSetterTypeName(field, options),
       "var", field->name());
     SourceLocation location;
     if (field->GetSourceLocation(&location)) {
@@ -1705,7 +1747,7 @@
 }
 
 void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
-                             int is_descriptor, int function_type) {
+                             const Options& options, int function_type) {
   // In theory we should have slightly different comments for setters, getters,
   // etc., but in practice everyone already knows the difference between these
   // so it's redundant information.
@@ -1721,11 +1763,17 @@
     "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
   if (function_type == kFieldSetter) {
     printer->Print(" * @param ^php_type^ $var\n",
-      "php_type", PhpSetterTypeName(field, is_descriptor));
+      "php_type", PhpSetterTypeName(field, options));
     printer->Print(" * @return $this\n");
   } else if (function_type == kFieldGetter) {
-    printer->Print(" * @return ^php_type^\n",
-      "php_type", PhpGetterTypeName(field, is_descriptor));
+    bool can_return_null = field->has_presence() &&
+                           field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
+    printer->Print(" * @return ^php_type^^maybe_null^\n",
+      "php_type", PhpGetterTypeName(field, options),
+      "maybe_null", can_return_null ? "|null" : "");
+  }
+  if (field->options().deprecated()) {
+    printer->Print(" * @deprecated\n");
   }
   printer->Print(" */\n");
 }
@@ -1754,7 +1802,7 @@
   printer->Print("/**\n");
   printer->Print(
       " * Sets the field by wrapping a primitive type in a ^message_name^ object.\n\n",
-      "message_name", LegacyFullClassName(field->message_type(), false));
+      "message_name", FullClassName(field->message_type(), false));
   GenerateDocCommentBody(printer, field);
   printer->Print(
     " * Generated from protobuf field <code>^def^</code>\n",
@@ -1766,7 +1814,7 @@
 }
 
 void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
-                            int is_descriptor) {
+                            const Options& options) {
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, enum_);
   printer->Print(
@@ -1786,7 +1834,7 @@
 }
 
 void GenerateServiceMethodDocComment(io::Printer* printer,
-                              const MethodDescriptor* method) {
+                                     const MethodDescriptor* method) {
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, method);
   printer->Print(
@@ -1802,35 +1850,439 @@
     "return_type", EscapePhpdoc(FullClassName(method->output_type(), false)));
 }
 
-bool Generator::Generate(const FileDescriptor* file, const string& parameter,
-                         GeneratorContext* generator_context,
-                         string* error) const {
-  return Generate(file, false, false, std::set<string>(),
-                  generator_context, error);
+std::string FilenameCName(const FileDescriptor* file) {
+  std::string c_name = file->name();
+  c_name = StringReplace(c_name, ".", "_", true);
+  c_name = StringReplace(c_name, "/", "_", true);
+  return c_name;
 }
 
-bool Generator::Generate(
-    const FileDescriptor* file,
-    bool is_descriptor,
-    bool aggregate_metadata,
-    const std::set<string>& aggregate_metadata_prefixes,
-    GeneratorContext* generator_context,
-    string* error) const {
-  if (is_descriptor && file->name() != kDescriptorFile) {
+void GenerateCEnum(const EnumDescriptor* desc, io::Printer* printer) {
+  std::string c_name = desc->full_name();
+  c_name = StringReplace(c_name, ".", "_", true);
+  std::string php_name = FullClassName(desc, Options());
+  php_name = StringReplace(php_name, "\\", "\\\\", true);
+  printer->Print(
+      "/* $c_name$ */\n"
+      "\n"
+      "zend_class_entry* $c_name$_ce;\n"
+      "\n"
+      "PHP_METHOD($c_name$, name) {\n"
+      "  $file_c_name$_AddDescriptor();\n"
+      "  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n"
+      "  const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n"
+      "  const char *name;\n"
+      "  zend_long value;\n"
+      "  if (zend_parse_parameters(ZEND_NUM_ARGS(), \"l\", &value) ==\n"
+      "      FAILURE) {\n"
+      "    return;\n"
+      "  }\n"
+      "  name = upb_enumdef_iton(e, value);\n"
+      "  if (!name) {\n"
+      "    zend_throw_exception_ex(NULL, 0,\n"
+      "                            \"$php_name$ has no name \"\n"
+      "                            \"defined for value \" ZEND_LONG_FMT \".\",\n"
+      "                            value);\n"
+      "    return;\n"
+      "  }\n"
+      "  RETURN_STRING(name);\n"
+      "}\n"
+      "\n"
+      "PHP_METHOD($c_name$, value) {\n"
+      "  $file_c_name$_AddDescriptor();\n"
+      "  const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n"
+      "  const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n"
+      "  char *name = NULL;\n"
+      "  size_t name_len;\n"
+      "  int32_t num;\n"
+      "  if (zend_parse_parameters(ZEND_NUM_ARGS(), \"s\", &name,\n"
+      "                            &name_len) == FAILURE) {\n"
+      "    return;\n"
+      "  }\n"
+      "  if (!upb_enumdef_ntoi(e, name, name_len, &num)) {\n"
+      "    zend_throw_exception_ex(NULL, 0,\n"
+      "                            \"$php_name$ has no value \"\n"
+      "                            \"defined for name %s.\",\n"
+      "                            name);\n"
+      "    return;\n"
+      "  }\n"
+      "  RETURN_LONG(num);\n"
+      "}\n"
+      "\n"
+      "static zend_function_entry $c_name$_phpmethods[] = {\n"
+      "  PHP_ME($c_name$, name, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+      "  PHP_ME($c_name$, value, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+      "  ZEND_FE_END\n"
+      "};\n"
+      "\n"
+      "static void $c_name$_ModuleInit() {\n"
+      "  zend_class_entry tmp_ce;\n"
+      "\n"
+      "  INIT_CLASS_ENTRY(tmp_ce, \"$php_name$\",\n"
+      "                   $c_name$_phpmethods);\n"
+      "\n"
+      "  $c_name$_ce = zend_register_internal_class(&tmp_ce);\n",
+      "name", desc->full_name(),
+      "file_c_name", FilenameCName(desc->file()),
+      "c_name", c_name,
+      "php_name", php_name);
+
+  for (int i = 0; i < desc->value_count(); i++) {
+    const EnumValueDescriptor* value = desc->value(i);
+    printer->Print(
+        "  zend_declare_class_constant_long($c_name$_ce, \"$name$\",\n"
+        "                                   strlen(\"$name$\"), $num$);\n",
+        "c_name", c_name,
+        "name", value->name(),
+        "num", std::to_string(value->number()));
+  }
+
+  printer->Print(
+      "}\n"
+      "\n");
+}
+
+void GenerateCMessage(const Descriptor* message, io::Printer* printer) {
+  std::string c_name = message->full_name();
+  c_name = StringReplace(c_name, ".", "_", true);
+  std::string php_name = FullClassName(message, Options());
+  php_name = StringReplace(php_name, "\\", "\\\\", true);
+  printer->Print(
+      "/* $c_name$ */\n"
+      "\n"
+      "zend_class_entry* $c_name$_ce;\n"
+      "\n"
+      "static PHP_METHOD($c_name$, __construct) {\n"
+      "  $file_c_name$_AddDescriptor();\n"
+      "  zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n"
+      "}\n"
+      "\n",
+      "file_c_name", FilenameCName(message->file()),
+      "c_name", c_name);
+
+  for (int i = 0; i < message->field_count(); i++) {
+    auto field = message->field(i);
+    printer->Print(
+      "static PHP_METHOD($c_name$, get$camel_name$) {\n"
+      "  Message* intern = (Message*)Z_OBJ_P(getThis());\n"
+      "  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,\n"
+      "                                           \"$name$\");\n"
+      "  zval ret;\n"
+      "  Message_get(intern, f, &ret);\n"
+      "  RETURN_COPY_VALUE(&ret);\n"
+      "}\n"
+      "\n"
+      "static PHP_METHOD($c_name$, set$camel_name$) {\n"
+      "  Message* intern = (Message*)Z_OBJ_P(getThis());\n"
+      "  const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,\n"
+      "                                           \"$name$\");\n"
+      "  zval *val;\n"
+      "  if (zend_parse_parameters(ZEND_NUM_ARGS(), \"z\", &val)\n"
+      "      == FAILURE) {\n"
+      "    return;\n"
+      "  }\n"
+      "  Message_set(intern, f, val);\n"
+      "  RETURN_COPY(getThis());\n"
+      "}\n"
+      "\n",
+      "c_name", c_name,
+      "name", field->name(),
+      "camel_name", UnderscoresToCamelCase(field->name(), true));
+  }
+
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+    auto oneof = message->oneof_decl(i);
+    printer->Print(
+      "static PHP_METHOD($c_name$, get$camel_name$) {\n"
+      "  Message* intern = (Message*)Z_OBJ_P(getThis());\n"
+      "  const upb_oneofdef *oneof = upb_msgdef_ntooz(intern->desc->msgdef,\n"
+      "                                              \"$name$\");\n"
+      "  const upb_fielddef *field = upb_msg_whichoneof(intern->msg, oneof);\n"
+      "  RETURN_STRING(field ? upb_fielddef_name(field) : \"\");\n"
+      "}\n",
+      "c_name", c_name,
+      "name", oneof->name(),
+      "camel_name", UnderscoresToCamelCase(oneof->name(), true));
+  }
+
+  switch (message->well_known_type()) {
+    case Descriptor::WELLKNOWNTYPE_ANY:
+      printer->Print(
+          "ZEND_BEGIN_ARG_INFO_EX(arginfo_is, 0, 0, 1)\n"
+          "  ZEND_ARG_INFO(0, proto)\n"
+          "ZEND_END_ARG_INFO()\n"
+          "\n"
+      );
+      break;
+    case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
+      printer->Print(
+          "ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1)\n"
+          "  ZEND_ARG_INFO(0, datetime)\n"
+          "ZEND_END_ARG_INFO()\n"
+          "\n"
+      );
+      break;
+    default:
+      break;
+  }
+
+  printer->Print(
+      "static zend_function_entry $c_name$_phpmethods[] = {\n"
+      "  PHP_ME($c_name$, __construct, arginfo_construct, ZEND_ACC_PUBLIC)\n",
+      "c_name", c_name);
+
+  for (int i = 0; i < message->field_count(); i++) {
+    auto field = message->field(i);
+    printer->Print(
+      "  PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n"
+      "  PHP_ME($c_name$, set$camel_name$, arginfo_setter, ZEND_ACC_PUBLIC)\n",
+      "c_name", c_name,
+      "camel_name", UnderscoresToCamelCase(field->name(), true));
+  }
+
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+    auto oneof = message->oneof_decl(i);
+    printer->Print(
+      "  PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n",
+      "c_name", c_name,
+      "camel_name", UnderscoresToCamelCase(oneof->name(), true));
+  }
+
+  // Extra hand-written functions added to the well-known types.
+  switch (message->well_known_type()) {
+    case Descriptor::WELLKNOWNTYPE_ANY:
+      printer->Print(
+        "  PHP_ME($c_name$, is, arginfo_is, ZEND_ACC_PUBLIC)\n"
+        "  PHP_ME($c_name$, pack, arginfo_setter, ZEND_ACC_PUBLIC)\n"
+        "  PHP_ME($c_name$, unpack, arginfo_void, ZEND_ACC_PUBLIC)\n",
+        "c_name", c_name);
+      break;
+    case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
+      printer->Print(
+        "  PHP_ME($c_name$, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC)\n"
+        "  PHP_ME($c_name$, toDateTime, arginfo_void, ZEND_ACC_PUBLIC)\n",
+        "c_name", c_name);
+      break;
+    default:
+      break;
+  } 
+
+  printer->Print(
+      "  ZEND_FE_END\n"
+      "};\n"
+      "\n"
+      "static void $c_name$_ModuleInit() {\n"
+      "  zend_class_entry tmp_ce;\n"
+      "\n"
+      "  INIT_CLASS_ENTRY(tmp_ce, \"$php_name$\",\n"
+      "                   $c_name$_phpmethods);\n"
+      "\n"
+      "  $c_name$_ce = zend_register_internal_class(&tmp_ce);\n"
+      "  $c_name$_ce->ce_flags |= ZEND_ACC_FINAL;\n"
+      "  $c_name$_ce->create_object = Message_create;\n"
+      "  zend_do_inheritance($c_name$_ce, message_ce);\n"
+      "}\n"
+      "\n",
+      "c_name", c_name,
+      "php_name", php_name);
+
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    GenerateCMessage(message->nested_type(i), printer);
+  }
+  for (int i = 0; i < message->enum_type_count(); i++) {
+    GenerateCEnum(message->enum_type(i), printer);
+  }
+}
+
+void GenerateEnumCInit(const EnumDescriptor* desc, io::Printer* printer) {
+  std::string c_name = desc->full_name();
+  c_name = StringReplace(c_name, ".", "_", true);
+
+  printer->Print(
+      "  $c_name$_ModuleInit();\n",
+      "c_name", c_name);
+}
+
+void GenerateCInit(const Descriptor* message, io::Printer* printer) {
+  std::string c_name = message->full_name();
+  c_name = StringReplace(c_name, ".", "_", true);
+
+  printer->Print(
+      "  $c_name$_ModuleInit();\n",
+      "c_name", c_name);
+
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    GenerateCInit(message->nested_type(i), printer);
+  }
+  for (int i = 0; i < message->enum_type_count(); i++) {
+    GenerateEnumCInit(message->enum_type(i), printer);
+  }
+}
+
+void GenerateCWellKnownTypes(const std::vector<const FileDescriptor*>& files,
+                             GeneratorContext* context) {
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      context->Open("../ext/google/protobuf/wkt.inc"));
+  io::Printer printer(output.get(), '$');
+
+  printer.Print(
+      "// This file is generated from the .proto files for the well-known\n"
+      "// types. Do not edit!\n\n");
+
+  printer.Print(
+      "ZEND_BEGIN_ARG_INFO_EX(arginfo_lookup, 0, 0, 1)\n"
+      "  ZEND_ARG_INFO(0, key)\n"
+      "ZEND_END_ARG_INFO()\n"
+      "\n"
+  );
+
+  for (auto file : files) {
+    printer.Print(
+        "static void $c_name$_AddDescriptor();\n",
+        "c_name", FilenameCName(file));
+  }
+
+  for (auto file : files) {
+    std::string c_name = FilenameCName(file);
+    std::string metadata_filename = GeneratedMetadataFileName(file, Options());
+    std::string metadata_classname = FilenameToClassname(metadata_filename);
+    std::string metadata_c_name =
+        StringReplace(metadata_classname, "\\", "_", true);
+    metadata_classname = StringReplace(metadata_classname, "\\", "\\\\", true);
+    FileDescriptorProto file_proto;
+    file->CopyTo(&file_proto);
+    std::string serialized;
+    file_proto.SerializeToString(&serialized);
+    printer.Print(
+        "/* $filename$ */\n"
+        "\n"
+        "zend_class_entry* $metadata_c_name$_ce;\n"
+        "\n"
+        "const char $c_name$_descriptor [$size$] = {\n",
+        "filename", file->name(),
+        "c_name", c_name,
+        "metadata_c_name", metadata_c_name,
+        "size", std::to_string(serialized.size()));
+
+    for (size_t i = 0; i < serialized.size();) {
+      for (size_t j = 0; j < 25 && i < serialized.size(); ++i, ++j) {
+        printer.Print("'$ch$', ", "ch", CEscape(serialized.substr(i, 1)));
+      }
+      printer.Print("\n");
+    }
+
+    printer.Print(
+        "};\n"
+        "\n"
+        "static void $c_name$_AddDescriptor() {\n"
+        "  if (DescriptorPool_HasFile(\"$filename$\")) return;\n",
+        "filename", file->name(),
+        "c_name", c_name,
+        "metadata_c_name", metadata_c_name);
+
+    for (int i = 0; i < file->dependency_count(); i++) {
+      std::string dep_c_name = FilenameCName(file->dependency(i));
+      printer.Print(
+          "  $dep_c_name$_AddDescriptor();\n",
+          "dep_c_name", dep_c_name);
+    }
+
+    printer.Print(
+        "  DescriptorPool_AddDescriptor(\"$filename$\", $c_name$_descriptor,\n"
+        "                               sizeof($c_name$_descriptor));\n"
+        "}\n"
+        "\n"
+        "static PHP_METHOD($metadata_c_name$, initOnce) {\n"
+        "  $c_name$_AddDescriptor();\n"
+        "}\n"
+        "\n"
+        "static zend_function_entry $metadata_c_name$_methods[] = {\n"
+        "  PHP_ME($metadata_c_name$, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+        "  ZEND_FE_END\n"
+        "};\n"
+        "\n"
+        "static void $metadata_c_name$_ModuleInit() {\n"
+        "  zend_class_entry tmp_ce;\n"
+        "\n"
+        "  INIT_CLASS_ENTRY(tmp_ce, \"$metadata_classname$\",\n"
+        "                   $metadata_c_name$_methods);\n"
+        "\n"
+        "  $metadata_c_name$_ce = zend_register_internal_class(&tmp_ce);\n"
+        "}\n"
+        "\n",
+        "filename", file->name(),
+        "c_name", c_name,
+        "metadata_c_name", metadata_c_name,
+        "metadata_classname", metadata_classname);
+    for (int i = 0; i < file->message_type_count(); i++) {
+      GenerateCMessage(file->message_type(i), &printer);
+    }
+    for (int i = 0; i < file->enum_type_count(); i++) {
+      GenerateCEnum(file->enum_type(i), &printer);
+    }
+  }
+
+  printer.Print(
+      "static void WellKnownTypes_ModuleInit() {\n");
+
+  for (auto file : files) {
+    std::string metadata_filename = GeneratedMetadataFileName(file, Options());
+    std::string metadata_classname = FilenameToClassname(metadata_filename);
+    std::string metadata_c_name =
+        StringReplace(metadata_classname, "\\", "_", true);
+    printer.Print(
+        "  $metadata_c_name$_ModuleInit();\n",
+        "metadata_c_name", metadata_c_name);
+    for (int i = 0; i < file->message_type_count(); i++) {
+      GenerateCInit(file->message_type(i), &printer);
+    }
+    for (int i = 0; i < file->enum_type_count(); i++) {
+      GenerateEnumCInit(file->enum_type(i), &printer);
+    }
+  }
+
+  printer.Print(
+      "}\n");
+}
+
+}  // namespace
+
+std::string GeneratedClassName(const Descriptor* desc) {
+  return GeneratedClassNameImpl(desc);
+}
+
+std::string GeneratedClassName(const EnumDescriptor* desc) {
+  return GeneratedClassNameImpl(desc);
+}
+
+std::string GeneratedClassName(const ServiceDescriptor* desc) {
+  return GeneratedClassNameImpl(desc);
+}
+
+bool Generator::Generate(const FileDescriptor* file,
+                         const std::string& parameter,
+                         GeneratorContext* generator_context,
+                         std::string* error) const {
+  return Generate(file, Options(), generator_context, error);
+}
+
+bool Generator::Generate(const FileDescriptor* file, const Options& options,
+                         GeneratorContext* generator_context,
+                         std::string* error) const {
+  if (options.is_descriptor && file->name() != kDescriptorFile) {
     *error =
         "Can only generate PHP code for google/protobuf/descriptor.proto.\n";
     return false;
   }
 
-  if (!is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+  if (!options.is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
     *error =
         "Can only generate PHP code for proto3 .proto files.\n"
         "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
     return false;
   }
 
-  GenerateFile(file, is_descriptor, aggregate_metadata,
-               aggregate_metadata_prefixes, generator_context);
+  GenerateFile(file, options, generator_context);
 
   return true;
 }
@@ -1839,35 +2291,31 @@
                             const std::string& parameter,
                             GeneratorContext* generator_context,
                             std::string* error) const {
-  bool is_descriptor = false;
-  bool aggregate_metadata = false;
-  std::set<string> aggregate_metadata_prefixes;
+  Options options;
 
   for (const auto& option : Split(parameter, ",", true)) {
     const std::vector<std::string> option_pair = Split(option, "=", true);
     if (HasPrefixString(option_pair[0], "aggregate_metadata")) {
-      string options_string = option_pair[1];
-      const std::vector<std::string> options =
-          Split(options_string, "#", false);
-      aggregate_metadata = true;
-      for (int i = 0; i < options.size(); i++) {
-        aggregate_metadata_prefixes.insert(options[i]);
-        GOOGLE_LOG(INFO) << options[i];
+      options.aggregate_metadata = true;
+      for (const auto& prefix : Split(option_pair[1], "#", false)) {
+        options.aggregate_metadata_prefixes.emplace(prefix);
+        GOOGLE_LOG(INFO) << prefix;
       }
-    }
-    if (option_pair[0] == "internal") {
-      is_descriptor = true;
+    } else if (option_pair[0] == "internal") {
+      options.is_descriptor = true;
+    } else if (option_pair[0] == "internal_generate_c_wkt") {
+      GenerateCWellKnownTypes(files, generator_context);
+    } else {
+      GOOGLE_LOG(FATAL) << "Unknown codegen option: " << option_pair[0];
     }
   }
 
   for (auto file : files) {
-    if (!Generate(
-             file, is_descriptor, aggregate_metadata,
-             aggregate_metadata_prefixes,
-             generator_context, error)) {
+    if (!Generate(file, options, generator_context, error)) {
       return false;
     }
   }
+
   return true;
 }
 
diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h
index ca9d23a..17cb59c 100644
--- a/src/google/protobuf/compiler/php/php_generator.h
+++ b/src/google/protobuf/compiler/php/php_generator.h
@@ -43,26 +43,31 @@
 namespace compiler {
 namespace php {
 
+struct Options;
+
 class PROTOC_EXPORT Generator : public CodeGenerator {
  public:
   virtual bool Generate(
       const FileDescriptor* file,
-      const string& parameter,
+      const std::string& parameter,
       GeneratorContext* generator_context,
-      string* error) const override;
+      std::string* error) const override;
 
   bool GenerateAll(const std::vector<const FileDescriptor*>& files,
                    const std::string& parameter,
                    GeneratorContext* generator_context,
                    std::string* error) const override;
+
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
+
  private:
   bool Generate(
       const FileDescriptor* file,
-      bool is_descriptor,
-      bool aggregate_metadata,
-      const std::set<string>& aggregate_metadata_prefixes,
+      const Options& options,
       GeneratorContext* generator_context,
-      string* error) const;
+      std::string* error) const;
 };
 
 // To skip reserved keywords in php, some generated classname are prefixed.
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 7306cf4..e1dacae 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -72,25 +72,35 @@
 
   // implements GeneratorContext --------------------------------------
 
-  virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
+  virtual io::ZeroCopyOutputStream* Open(const std::string& filename) override {
     CodeGeneratorResponse::File* file = response_->add_file();
     file->set_name(filename);
     return new io::StringOutputStream(file->mutable_content());
   }
 
   virtual io::ZeroCopyOutputStream* OpenForInsert(
-      const std::string& filename, const std::string& insertion_point) {
+      const std::string& filename, const std::string& insertion_point) override {
     CodeGeneratorResponse::File* file = response_->add_file();
     file->set_name(filename);
     file->set_insertion_point(insertion_point);
     return new io::StringOutputStream(file->mutable_content());
   }
 
-  void ListParsedFiles(std::vector<const FileDescriptor*>* output) {
+  virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
+      const std::string& filename, const std::string& insertion_point,
+      const google::protobuf::GeneratedCodeInfo& info) override {
+    CodeGeneratorResponse::File* file = response_->add_file();
+    file->set_name(filename);
+    file->set_insertion_point(insertion_point);
+    *file->mutable_generated_code_info() = info;
+    return new io::StringOutputStream(file->mutable_content());
+  }
+
+  void ListParsedFiles(std::vector<const FileDescriptor*>* output) override {
     *output = parsed_files_;
   }
 
-  void GetCompilerVersion(Version* version) const {
+  void GetCompilerVersion(Version* version) const override {
     *version = compiler_version_;
   }
 
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 6739215..fec62ed 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -14,88 +14,71 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
-class VersionDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Version> _instance;
-} _Version_default_instance_;
-class CodeGeneratorRequestDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorRequest> _instance;
-} _CodeGeneratorRequest_default_instance_;
-class CodeGeneratorResponse_FileDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> _instance;
-} _CodeGeneratorResponse_File_default_instance_;
-class CodeGeneratorResponseDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorResponse> _instance;
-} _CodeGeneratorResponse_default_instance_;
+constexpr Version::Version(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : suffix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , major_(0)
+  , minor_(0)
+  , patch_(0){}
+struct VersionDefaultTypeInternal {
+  constexpr VersionDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~VersionDefaultTypeInternal() {}
+  union {
+    Version _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT VersionDefaultTypeInternal _Version_default_instance_;
+constexpr CodeGeneratorRequest::CodeGeneratorRequest(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_to_generate_()
+  , proto_file_()
+  , parameter_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , compiler_version_(nullptr){}
+struct CodeGeneratorRequestDefaultTypeInternal {
+  constexpr CodeGeneratorRequestDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorRequestDefaultTypeInternal() {}
+  union {
+    CodeGeneratorRequest _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
+constexpr CodeGeneratorResponse_File::CodeGeneratorResponse_File(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , insertion_point_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , content_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , generated_code_info_(nullptr){}
+struct CodeGeneratorResponse_FileDefaultTypeInternal {
+  constexpr CodeGeneratorResponse_FileDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorResponse_FileDefaultTypeInternal() {}
+  union {
+    CodeGeneratorResponse_File _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
+constexpr CodeGeneratorResponse::CodeGeneratorResponse(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_()
+  , error_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , supported_features_(uint64_t{0u}){}
+struct CodeGeneratorResponseDefaultTypeInternal {
+  constexpr CodeGeneratorResponseDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorResponseDefaultTypeInternal() {}
+  union {
+    CodeGeneratorResponse _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest::InitAsDefaultInstance();
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}};
-
-static void InitDefaultsscc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse::InitAsDefaultInstance();
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}};
-
-static void InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File::InitAsDefaultInstance();
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {}};
-
-static void InitDefaultsscc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::Version();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::compiler::Version::InitAsDefaultInstance();
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr;
@@ -135,9 +118,11 @@
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, name_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, insertion_point_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, content_),
+  PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, generated_code_info_),
   0,
   1,
   2,
+  3,
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _has_bits_),
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -153,8 +138,8 @@
 static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
   { 0, 9, sizeof(PROTOBUF_NAMESPACE_ID::compiler::Version)},
   { 13, 22, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)},
-  { 26, 34, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)},
-  { 37, 45, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)},
+  { 26, 35, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)},
+  { 39, 47, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)},
 };
 
 static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
@@ -174,36 +159,34 @@
   "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf."
   "FileDescriptorProto\022;\n\020compiler_version\030"
   "\003 \001(\0132!.google.protobuf.compiler.Version"
-  "\"\200\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001("
+  "\"\301\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001("
   "\t\022\032\n\022supported_features\030\002 \001(\004\022B\n\004file\030\017 "
   "\003(\01324.google.protobuf.compiler.CodeGener"
-  "atorResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022"
+  "atorResponse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t\022"
   "\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001("
-  "\t\"8\n\007Feature\022\020\n\014FEATURE_NONE\020\000\022\033\n\027FEATUR"
-  "E_PROTO3_OPTIONAL\020\001Bg\n\034com.google.protob"
-  "uf.compilerB\014PluginProtosZ9github.com/go"
-  "lang/protobuf/protoc-gen-go/plugin;plugi"
-  "n_go"
+  "\t\022\?\n\023generated_code_info\030\020 \001(\0132\".google."
+  "protobuf.GeneratedCodeInfo\"8\n\007Feature\022\020\n"
+  "\014FEATURE_NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTION"
+  "AL\020\001BW\n\034com.google.protobuf.compilerB\014Pl"
+  "uginProtosZ)google.golang.org/protobuf/t"
+  "ypes/pluginpb"
   ;
 static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = {
   &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_sccs[4] = {
-  &scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", 724,
-  &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_sccs, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 4, 1,
+  false, false, 773, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", 
+  &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 1, 4,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, 4, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
+  file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor() {
@@ -230,8 +213,6 @@
 
 // ===================================================================
 
-void Version::InitAsDefaultInstance() {
-}
 class Version::_Internal {
  public:
   using HasBits = decltype(std::declval<Version>()._has_bits_);
@@ -249,10 +230,13 @@
   }
 };
 
-Version::Version(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Version::Version(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.Version)
 }
 Version::Version(const Version& from)
@@ -261,8 +245,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_suffix()) {
-    suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_suffix(),
-      GetArena());
+    suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_suffix(), 
+      GetArenaForAllocation());
   }
   ::memcpy(&major_, &from.major_,
     static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
@@ -270,22 +254,23 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.Version)
 }
 
-void Version::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&major_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&patch_) -
-      reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+inline void Version::SharedCtor() {
+suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&major_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
+    reinterpret_cast<char*>(&major_)) + sizeof(patch_));
 }
 
 Version::~Version() {
   // @@protoc_insertion_point(destructor:google.protobuf.compiler.Version)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Version::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Version::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   suffix_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -298,11 +283,6 @@
 void Version::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Version& Version::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Version::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
@@ -326,11 +306,9 @@
 const char* Version::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 major = 1;
       case 1:
@@ -369,7 +347,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -481,25 +460,22 @@
   return total_size;
 }
 
-void Version::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.Version)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Version* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Version>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.Version)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.Version)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Version::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Version::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Version::GetClassData() const { return &_class_data_; }
+
+void Version::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Version *>(to)->MergeFrom(
+      static_cast<const Version &>(from));
 }
 
+
 void Version::MergeFrom(const Version& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.Version)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -519,13 +495,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void Version::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.Version)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Version::CopyFrom(const Version& from) {
@@ -541,9 +511,13 @@
 
 void Version::InternalSwap(Version* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
-  suffix_.Swap(&other->suffix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &suffix_, GetArenaForAllocation(),
+      &other->suffix_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Version, patch_)
       + sizeof(Version::patch_)
@@ -553,16 +527,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Version::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[0]);
 }
 
-
 // ===================================================================
 
-void CodeGeneratorRequest::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< PROTOBUF_NAMESPACE_ID::compiler::Version*>(
-      PROTOBUF_NAMESPACE_ID::compiler::Version::internal_default_instance());
-}
 class CodeGeneratorRequest::_Internal {
  public:
   using HasBits = decltype(std::declval<CodeGeneratorRequest>()._has_bits_);
@@ -582,12 +553,15 @@
 void CodeGeneratorRequest::clear_proto_file() {
   proto_file_.Clear();
 }
-CodeGeneratorRequest::CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+CodeGeneratorRequest::CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   file_to_generate_(arena),
   proto_file_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest)
 }
 CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
@@ -598,8 +572,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_parameter()) {
-    parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_parameter(),
-      GetArena());
+    parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_parameter(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_compiler_version()) {
     compiler_version_ = new PROTOBUF_NAMESPACE_ID::compiler::Version(*from.compiler_version_);
@@ -609,20 +583,20 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
 }
 
-void CodeGeneratorRequest::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  compiler_version_ = nullptr;
+inline void CodeGeneratorRequest::SharedCtor() {
+parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+compiler_version_ = nullptr;
 }
 
 CodeGeneratorRequest::~CodeGeneratorRequest() {
   // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void CodeGeneratorRequest::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void CodeGeneratorRequest::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   parameter_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete compiler_version_;
 }
@@ -636,11 +610,6 @@
 void CodeGeneratorRequest::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorRequest::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
@@ -667,11 +636,9 @@
 const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated string file_to_generate = 1;
       case 1:
@@ -721,7 +688,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -842,25 +810,22 @@
   return total_size;
 }
 
-void CodeGeneratorRequest::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
-  GOOGLE_DCHECK_NE(&from, this);
-  const CodeGeneratorRequest* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<CodeGeneratorRequest>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorRequest)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorRequest)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData CodeGeneratorRequest::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    CodeGeneratorRequest::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*CodeGeneratorRequest::GetClassData() const { return &_class_data_; }
+
+void CodeGeneratorRequest::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<CodeGeneratorRequest *>(to)->MergeFrom(
+      static_cast<const CodeGeneratorRequest &>(from));
 }
 
+
 void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -875,13 +840,7 @@
       _internal_mutable_compiler_version()->PROTOBUF_NAMESPACE_ID::compiler::Version::MergeFrom(from._internal_compiler_version());
     }
   }
-}
-
-void CodeGeneratorRequest::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
@@ -898,23 +857,26 @@
 
 void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   file_to_generate_.InternalSwap(&other->file_to_generate_);
   proto_file_.InternalSwap(&other->proto_file_);
-  parameter_.Swap(&other->parameter_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &parameter_, GetArenaForAllocation(),
+      &other->parameter_, other->GetArenaForAllocation()
+  );
   swap(compiler_version_, other->compiler_version_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorRequest::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1]);
 }
 
-
 // ===================================================================
 
-void CodeGeneratorResponse_File::InitAsDefaultInstance() {
-}
 class CodeGeneratorResponse_File::_Internal {
  public:
   using HasBits = decltype(std::declval<CodeGeneratorResponse_File>()._has_bits_);
@@ -927,12 +889,27 @@
   static void set_has_content(HasBits* has_bits) {
     (*has_bits)[0] |= 4u;
   }
+  static const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info(const CodeGeneratorResponse_File* msg);
+  static void set_has_generated_code_info(HasBits* has_bits) {
+    (*has_bits)[0] |= 8u;
+  }
 };
 
-CodeGeneratorResponse_File::CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo&
+CodeGeneratorResponse_File::_Internal::generated_code_info(const CodeGeneratorResponse_File* msg) {
+  return *msg->generated_code_info_;
+}
+void CodeGeneratorResponse_File::clear_generated_code_info() {
+  if (generated_code_info_ != nullptr) generated_code_info_->Clear();
+  _has_bits_[0] &= ~0x00000008u;
+}
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
 CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
@@ -941,40 +918,47 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_insertion_point()) {
-    insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_insertion_point(),
-      GetArena());
+    insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_insertion_point(), 
+      GetArenaForAllocation());
   }
   content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_content()) {
-    content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_content(),
-      GetArena());
+    content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_content(), 
+      GetArenaForAllocation());
+  }
+  if (from._internal_has_generated_code_info()) {
+    generated_code_info_ = new PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo(*from.generated_code_info_);
+  } else {
+    generated_code_info_ = nullptr;
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
 
-void CodeGeneratorResponse_File::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+inline void CodeGeneratorResponse_File::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+generated_code_info_ = nullptr;
 }
 
 CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
   // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void CodeGeneratorResponse_File::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void CodeGeneratorResponse_File::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   insertion_point_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   content_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete generated_code_info_;
 }
 
 void CodeGeneratorResponse_File::ArenaDtor(void* object) {
@@ -986,11 +970,6 @@
 void CodeGeneratorResponse_File::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorResponse_File::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
@@ -999,7 +978,7 @@
   (void) cached_has_bits;
 
   cached_has_bits = _has_bits_[0];
-  if (cached_has_bits & 0x00000007u) {
+  if (cached_has_bits & 0x0000000fu) {
     if (cached_has_bits & 0x00000001u) {
       name_.ClearNonDefaultToEmpty();
     }
@@ -1009,6 +988,10 @@
     if (cached_has_bits & 0x00000004u) {
       content_.ClearNonDefaultToEmpty();
     }
+    if (cached_has_bits & 0x00000008u) {
+      GOOGLE_DCHECK(generated_code_info_ != nullptr);
+      generated_code_info_->Clear();
+    }
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
@@ -1017,11 +1000,9 @@
 const char* CodeGeneratorResponse_File::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -1056,9 +1037,17 @@
           CHK_(ptr);
         } else goto handle_unusual;
         continue;
+      // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+      case 16:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 130)) {
+          ptr = ctx->ParseMessage(_internal_mutable_generated_code_info(), ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1116,6 +1105,14 @@
         15, this->_internal_content(), target);
   }
 
+  // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+  if (cached_has_bits & 0x00000008u) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+      InternalWriteMessage(
+        16, _Internal::generated_code_info(this), target, stream);
+  }
+
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
         _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
@@ -1133,7 +1130,7 @@
   (void) cached_has_bits;
 
   cached_has_bits = _has_bits_[0];
-  if (cached_has_bits & 0x00000007u) {
+  if (cached_has_bits & 0x0000000fu) {
     // optional string name = 1;
     if (cached_has_bits & 0x00000001u) {
       total_size += 1 +
@@ -1155,6 +1152,13 @@
           this->_internal_content());
     }
 
+    // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+    if (cached_has_bits & 0x00000008u) {
+      total_size += 2 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
+          *generated_code_info_);
+    }
+
   }
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
     return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
@@ -1165,30 +1169,27 @@
   return total_size;
 }
 
-void CodeGeneratorResponse_File::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
-  GOOGLE_DCHECK_NE(&from, this);
-  const CodeGeneratorResponse_File* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<CodeGeneratorResponse_File>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse.File)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse.File)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData CodeGeneratorResponse_File::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    CodeGeneratorResponse_File::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*CodeGeneratorResponse_File::GetClassData() const { return &_class_data_; }
+
+void CodeGeneratorResponse_File::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<CodeGeneratorResponse_File *>(to)->MergeFrom(
+      static_cast<const CodeGeneratorResponse_File &>(from));
 }
 
+
 void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._has_bits_[0];
-  if (cached_has_bits & 0x00000007u) {
+  if (cached_has_bits & 0x0000000fu) {
     if (cached_has_bits & 0x00000001u) {
       _internal_set_name(from._internal_name());
     }
@@ -1198,14 +1199,11 @@
     if (cached_has_bits & 0x00000004u) {
       _internal_set_content(from._internal_content());
     }
+    if (cached_has_bits & 0x00000008u) {
+      _internal_mutable_generated_code_info()->PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo::MergeFrom(from._internal_generated_code_info());
+    }
   }
-}
-
-void CodeGeneratorResponse_File::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) {
@@ -1221,22 +1219,34 @@
 
 void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  insertion_point_.Swap(&other->insertion_point_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  content_.Swap(&other->content_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &insertion_point_, GetArenaForAllocation(),
+      &other->insertion_point_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &content_, GetArenaForAllocation(),
+      &other->content_, other->GetArenaForAllocation()
+  );
+  swap(generated_code_info_, other->generated_code_info_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse_File::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[2]);
 }
 
-
 // ===================================================================
 
-void CodeGeneratorResponse::InitAsDefaultInstance() {
-}
 class CodeGeneratorResponse::_Internal {
  public:
   using HasBits = decltype(std::declval<CodeGeneratorResponse>()._has_bits_);
@@ -1248,11 +1258,14 @@
   }
 };
 
-CodeGeneratorResponse::CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+CodeGeneratorResponse::CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   file_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse)
 }
 CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
@@ -1262,27 +1275,27 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_error()) {
-    error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_error(),
-      GetArena());
+    error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_error(), 
+      GetArenaForAllocation());
   }
   supported_features_ = from.supported_features_;
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
 }
 
-void CodeGeneratorResponse::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  supported_features_ = PROTOBUF_ULONGLONG(0);
+inline void CodeGeneratorResponse::SharedCtor() {
+error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+supported_features_ = uint64_t{0u};
 }
 
 CodeGeneratorResponse::~CodeGeneratorResponse() {
   // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void CodeGeneratorResponse::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void CodeGeneratorResponse::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   error_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -1295,11 +1308,6 @@
 void CodeGeneratorResponse::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorResponse::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
@@ -1312,7 +1320,7 @@
   if (cached_has_bits & 0x00000001u) {
     error_.ClearNonDefaultToEmpty();
   }
-  supported_features_ = PROTOBUF_ULONGLONG(0);
+  supported_features_ = uint64_t{0u};
   _has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
@@ -1320,11 +1328,9 @@
 const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string error = 1;
       case 1:
@@ -1359,7 +1365,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1460,25 +1467,22 @@
   return total_size;
 }
 
-void CodeGeneratorResponse::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
-  GOOGLE_DCHECK_NE(&from, this);
-  const CodeGeneratorResponse* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<CodeGeneratorResponse>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData CodeGeneratorResponse::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    CodeGeneratorResponse::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*CodeGeneratorResponse::GetClassData() const { return &_class_data_; }
+
+void CodeGeneratorResponse::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<CodeGeneratorResponse *>(to)->MergeFrom(
+      static_cast<const CodeGeneratorResponse &>(from));
 }
 
+
 void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -1493,13 +1497,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void CodeGeneratorResponse::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
@@ -1515,18 +1513,23 @@
 
 void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   file_.InternalSwap(&other->file_);
-  error_.Swap(&other->error_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &error_, GetArenaForAllocation(),
+      &other->error_, other->GetArenaForAllocation()
+  );
   swap(supported_features_, other->supported_features_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[3]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 80ebc07..e1ede97 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -53,7 +52,7 @@
 struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[4]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -61,20 +60,20 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+PROTOC_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
 class CodeGeneratorRequest;
-class CodeGeneratorRequestDefaultTypeInternal;
+struct CodeGeneratorRequestDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
 class CodeGeneratorResponse;
-class CodeGeneratorResponseDefaultTypeInternal;
+struct CodeGeneratorResponseDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
 class CodeGeneratorResponse_File;
-class CodeGeneratorResponse_FileDefaultTypeInternal;
+struct CodeGeneratorResponse_FileDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
 class Version;
-class VersionDefaultTypeInternal;
+struct VersionDefaultTypeInternal;
 PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
@@ -106,17 +105,18 @@
     CodeGeneratorResponse_Feature_descriptor(), enum_t_value);
 }
 inline bool CodeGeneratorResponse_Feature_Parse(
-    const std::string& name, CodeGeneratorResponse_Feature* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, CodeGeneratorResponse_Feature* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<CodeGeneratorResponse_Feature>(
     CodeGeneratorResponse_Feature_descriptor(), name, value);
 }
 // ===================================================================
 
-class PROTOC_EXPORT Version PROTOBUF_FINAL :
+class PROTOC_EXPORT Version final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ {
  public:
-  inline Version() : Version(nullptr) {};
-  virtual ~Version();
+  inline Version() : Version(nullptr) {}
+  ~Version() override;
+  explicit constexpr Version(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Version(const Version& from);
   Version(Version&& from) noexcept
@@ -129,8 +129,9 @@
     return *this;
   }
   inline Version& operator=(Version&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -148,14 +149,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Version& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Version& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Version* internal_default_instance() {
     return reinterpret_cast<const Version*>(
                &_Version_default_instance_);
@@ -168,7 +169,7 @@
   }
   inline void Swap(Version* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -176,23 +177,26 @@
   }
   void UnsafeArenaSwap(Version* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Version* New() const final {
-    return CreateMaybeMessage<Version>(nullptr);
+    return new Version();
   }
 
   Version* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Version>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Version& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Version& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -203,8 +207,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Version* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -212,20 +216,17 @@
     return "google.protobuf.compiler.Version";
   }
   protected:
-  explicit Version(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Version(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -244,25 +245,14 @@
   public:
   void clear_suffix();
   const std::string& suffix() const;
-  void set_suffix(const std::string& value);
-  void set_suffix(std::string&& value);
-  void set_suffix(const char* value);
-  void set_suffix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_suffix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_suffix();
-  std::string* release_suffix();
+  PROTOBUF_MUST_USE_RESULT std::string* release_suffix();
   void set_allocated_suffix(std::string* suffix);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_suffix();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_suffix(
-      std::string* suffix);
   private:
   const std::string& _internal_suffix() const;
-  void _internal_set_suffix(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_suffix(const std::string& value);
   std::string* _internal_mutable_suffix();
   public:
 
@@ -322,11 +312,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOC_EXPORT CodeGeneratorRequest PROTOBUF_FINAL :
+class PROTOC_EXPORT CodeGeneratorRequest final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ {
  public:
-  inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {};
-  virtual ~CodeGeneratorRequest();
+  inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {}
+  ~CodeGeneratorRequest() override;
+  explicit constexpr CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorRequest(const CodeGeneratorRequest& from);
   CodeGeneratorRequest(CodeGeneratorRequest&& from) noexcept
@@ -339,8 +330,9 @@
     return *this;
   }
   inline CodeGeneratorRequest& operator=(CodeGeneratorRequest&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -358,14 +350,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const CodeGeneratorRequest& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const CodeGeneratorRequest& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorRequest* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorRequest*>(
                &_CodeGeneratorRequest_default_instance_);
@@ -378,7 +370,7 @@
   }
   inline void Swap(CodeGeneratorRequest* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -386,23 +378,26 @@
   }
   void UnsafeArenaSwap(CodeGeneratorRequest* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline CodeGeneratorRequest* New() const final {
-    return CreateMaybeMessage<CodeGeneratorRequest>(nullptr);
+    return new CodeGeneratorRequest();
   }
 
   CodeGeneratorRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<CodeGeneratorRequest>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const CodeGeneratorRequest& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const CodeGeneratorRequest& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -413,8 +408,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(CodeGeneratorRequest* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -422,20 +417,17 @@
     return "google.protobuf.compiler.CodeGeneratorRequest";
   }
   protected:
-  explicit CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -496,25 +488,14 @@
   public:
   void clear_parameter();
   const std::string& parameter() const;
-  void set_parameter(const std::string& value);
-  void set_parameter(std::string&& value);
-  void set_parameter(const char* value);
-  void set_parameter(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_parameter(ArgT0&& arg0, ArgT... args);
   std::string* mutable_parameter();
-  std::string* release_parameter();
+  PROTOBUF_MUST_USE_RESULT std::string* release_parameter();
   void set_allocated_parameter(std::string* parameter);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_parameter();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_parameter(
-      std::string* parameter);
   private:
   const std::string& _internal_parameter() const;
-  void _internal_set_parameter(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_parameter(const std::string& value);
   std::string* _internal_mutable_parameter();
   public:
 
@@ -525,7 +506,7 @@
   public:
   void clear_compiler_version();
   const PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version() const;
-  PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
   PROTOBUF_NAMESPACE_ID::compiler::Version* mutable_compiler_version();
   void set_allocated_compiler_version(PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version);
   private:
@@ -553,11 +534,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL :
+class PROTOC_EXPORT CodeGeneratorResponse_File final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ {
  public:
-  inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {};
-  virtual ~CodeGeneratorResponse_File();
+  inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {}
+  ~CodeGeneratorResponse_File() override;
+  explicit constexpr CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
   CodeGeneratorResponse_File(CodeGeneratorResponse_File&& from) noexcept
@@ -570,8 +552,9 @@
     return *this;
   }
   inline CodeGeneratorResponse_File& operator=(CodeGeneratorResponse_File&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -589,14 +572,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const CodeGeneratorResponse_File& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const CodeGeneratorResponse_File& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorResponse_File* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorResponse_File*>(
                &_CodeGeneratorResponse_File_default_instance_);
@@ -609,7 +592,7 @@
   }
   inline void Swap(CodeGeneratorResponse_File* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -617,23 +600,26 @@
   }
   void UnsafeArenaSwap(CodeGeneratorResponse_File* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline CodeGeneratorResponse_File* New() const final {
-    return CreateMaybeMessage<CodeGeneratorResponse_File>(nullptr);
+    return new CodeGeneratorResponse_File();
   }
 
   CodeGeneratorResponse_File* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<CodeGeneratorResponse_File>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const CodeGeneratorResponse_File& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const CodeGeneratorResponse_File& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -644,8 +630,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(CodeGeneratorResponse_File* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -653,20 +639,17 @@
     return "google.protobuf.compiler.CodeGeneratorResponse.File";
   }
   protected:
-  explicit CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -676,6 +659,7 @@
     kNameFieldNumber = 1,
     kInsertionPointFieldNumber = 2,
     kContentFieldNumber = 15,
+    kGeneratedCodeInfoFieldNumber = 16,
   };
   // optional string name = 1;
   bool has_name() const;
@@ -684,25 +668,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -713,25 +686,14 @@
   public:
   void clear_insertion_point();
   const std::string& insertion_point() const;
-  void set_insertion_point(const std::string& value);
-  void set_insertion_point(std::string&& value);
-  void set_insertion_point(const char* value);
-  void set_insertion_point(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_insertion_point(ArgT0&& arg0, ArgT... args);
   std::string* mutable_insertion_point();
-  std::string* release_insertion_point();
+  PROTOBUF_MUST_USE_RESULT std::string* release_insertion_point();
   void set_allocated_insertion_point(std::string* insertion_point);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_insertion_point();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_insertion_point(
-      std::string* insertion_point);
   private:
   const std::string& _internal_insertion_point() const;
-  void _internal_set_insertion_point(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_insertion_point(const std::string& value);
   std::string* _internal_mutable_insertion_point();
   public:
 
@@ -742,28 +704,35 @@
   public:
   void clear_content();
   const std::string& content() const;
-  void set_content(const std::string& value);
-  void set_content(std::string&& value);
-  void set_content(const char* value);
-  void set_content(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_content(ArgT0&& arg0, ArgT... args);
   std::string* mutable_content();
-  std::string* release_content();
+  PROTOBUF_MUST_USE_RESULT std::string* release_content();
   void set_allocated_content(std::string* content);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_content();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_content(
-      std::string* content);
   private:
   const std::string& _internal_content() const;
-  void _internal_set_content(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_content(const std::string& value);
   std::string* _internal_mutable_content();
   public:
 
+  // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+  bool has_generated_code_info() const;
+  private:
+  bool _internal_has_generated_code_info() const;
+  public:
+  void clear_generated_code_info();
+  const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info() const;
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info();
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* mutable_generated_code_info();
+  void set_allocated_generated_code_info(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info);
+  private:
+  const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& _internal_generated_code_info() const;
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* _internal_mutable_generated_code_info();
+  public:
+  void unsafe_arena_set_allocated_generated_code_info(
+      PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info);
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* unsafe_arena_release_generated_code_info();
+
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
  private:
   class _Internal;
@@ -776,15 +745,17 @@
   ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
   ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr insertion_point_;
   ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr content_;
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info_;
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 };
 // -------------------------------------------------------------------
 
-class PROTOC_EXPORT CodeGeneratorResponse PROTOBUF_FINAL :
+class PROTOC_EXPORT CodeGeneratorResponse final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ {
  public:
-  inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {};
-  virtual ~CodeGeneratorResponse();
+  inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {}
+  ~CodeGeneratorResponse() override;
+  explicit constexpr CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse(const CodeGeneratorResponse& from);
   CodeGeneratorResponse(CodeGeneratorResponse&& from) noexcept
@@ -797,8 +768,9 @@
     return *this;
   }
   inline CodeGeneratorResponse& operator=(CodeGeneratorResponse&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -816,14 +788,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const CodeGeneratorResponse& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const CodeGeneratorResponse& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorResponse* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorResponse*>(
                &_CodeGeneratorResponse_default_instance_);
@@ -836,7 +808,7 @@
   }
   inline void Swap(CodeGeneratorResponse* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -844,23 +816,26 @@
   }
   void UnsafeArenaSwap(CodeGeneratorResponse* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline CodeGeneratorResponse* New() const final {
-    return CreateMaybeMessage<CodeGeneratorResponse>(nullptr);
+    return new CodeGeneratorResponse();
   }
 
   CodeGeneratorResponse* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<CodeGeneratorResponse>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const CodeGeneratorResponse& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const CodeGeneratorResponse& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -871,8 +846,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(CodeGeneratorResponse* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -880,20 +855,17 @@
     return "google.protobuf.compiler.CodeGeneratorResponse";
   }
   protected:
-  explicit CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -924,7 +896,7 @@
       "Incorrect type passed to function Feature_Name.");
     return CodeGeneratorResponse_Feature_Name(enum_t_value);
   }
-  static inline bool Feature_Parse(const std::string& name,
+  static inline bool Feature_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       Feature* value) {
     return CodeGeneratorResponse_Feature_Parse(name, value);
   }
@@ -961,25 +933,14 @@
   public:
   void clear_error();
   const std::string& error() const;
-  void set_error(const std::string& value);
-  void set_error(std::string&& value);
-  void set_error(const char* value);
-  void set_error(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_error(ArgT0&& arg0, ArgT... args);
   std::string* mutable_error();
-  std::string* release_error();
+  PROTOBUF_MUST_USE_RESULT std::string* release_error();
   void set_allocated_error(std::string* error);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_error();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_error(
-      std::string* error);
   private:
   const std::string& _internal_error() const;
-  void _internal_set_error(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_error(const std::string& value);
   std::string* _internal_mutable_error();
   public:
 
@@ -1114,51 +1075,35 @@
   return _internal_has_suffix();
 }
 inline void Version::clear_suffix() {
-  suffix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  suffix_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& Version::suffix() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix)
   return _internal_suffix();
 }
-inline void Version::set_suffix(const std::string& value) {
-  _internal_set_suffix(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Version::set_suffix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix)
 }
 inline std::string* Version::mutable_suffix() {
+  std::string* _s = _internal_mutable_suffix();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix)
-  return _internal_mutable_suffix();
+  return _s;
 }
 inline const std::string& Version::_internal_suffix() const {
   return suffix_.Get();
 }
 inline void Version::_internal_set_suffix(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Version::set_suffix(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  suffix_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix)
-}
-inline void Version::set_suffix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix)
-}
-inline void Version::set_suffix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix)
+  suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Version::_internal_mutable_suffix() {
   _has_bits_[0] |= 0x00000001u;
-  return suffix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return suffix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Version::release_suffix() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix)
@@ -1166,7 +1111,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return suffix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return suffix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Version::set_allocated_suffix(std::string* suffix) {
   if (suffix != nullptr) {
@@ -1175,28 +1120,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   suffix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), suffix,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix)
 }
-inline std::string* Version::unsafe_arena_release_suffix() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.compiler.Version.suffix)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return suffix_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Version::unsafe_arena_set_allocated_suffix(
-    std::string* suffix) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (suffix != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  suffix_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      suffix, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.Version.suffix)
-}
 
 // -------------------------------------------------------------------
 
@@ -1213,8 +1139,9 @@
   file_to_generate_.Clear();
 }
 inline std::string* CodeGeneratorRequest::add_file_to_generate() {
+  std::string* _s = _internal_add_file_to_generate();
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-  return _internal_add_file_to_generate();
+  return _s;
 }
 inline const std::string& CodeGeneratorRequest::_internal_file_to_generate(int index) const {
   return file_to_generate_.Get(index);
@@ -1228,12 +1155,12 @@
   return file_to_generate_.Mutable(index);
 }
 inline void CodeGeneratorRequest::set_file_to_generate(int index, const std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
   file_to_generate_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
 inline void CodeGeneratorRequest::set_file_to_generate(int index, std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
   file_to_generate_.Mutable(index)->assign(std::move(value));
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
 inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
   GOOGLE_DCHECK(value != nullptr);
@@ -1285,51 +1212,35 @@
   return _internal_has_parameter();
 }
 inline void CodeGeneratorRequest::clear_parameter() {
-  parameter_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  parameter_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& CodeGeneratorRequest::parameter() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   return _internal_parameter();
 }
-inline void CodeGeneratorRequest::set_parameter(const std::string& value) {
-  _internal_set_parameter(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorRequest::set_parameter(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
 inline std::string* CodeGeneratorRequest::mutable_parameter() {
+  std::string* _s = _internal_mutable_parameter();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  return _internal_mutable_parameter();
+  return _s;
 }
 inline const std::string& CodeGeneratorRequest::_internal_parameter() const {
   return parameter_.Get();
 }
 inline void CodeGeneratorRequest::_internal_set_parameter(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void CodeGeneratorRequest::set_parameter(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  parameter_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-inline void CodeGeneratorRequest::set_parameter(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-inline void CodeGeneratorRequest::set_parameter(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorRequest::_internal_mutable_parameter() {
   _has_bits_[0] |= 0x00000001u;
-  return parameter_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return parameter_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorRequest::release_parameter() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
@@ -1337,7 +1248,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return parameter_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return parameter_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void CodeGeneratorRequest::set_allocated_parameter(std::string* parameter) {
   if (parameter != nullptr) {
@@ -1346,28 +1257,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   parameter_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), parameter,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
-inline std::string* CodeGeneratorRequest::unsafe_arena_release_parameter() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return parameter_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void CodeGeneratorRequest::unsafe_arena_set_allocated_parameter(
-    std::string* parameter) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (parameter != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  parameter_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      parameter, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
 
 // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
 inline int CodeGeneratorRequest::_internal_proto_file_size() const {
@@ -1396,8 +1288,9 @@
   return proto_file_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+  PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _add = _internal_add_proto_file();
   // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return _internal_add_proto_file();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >&
 CodeGeneratorRequest::proto_file() const {
@@ -1420,8 +1313,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::_internal_compiler_version() const {
   const PROTOBUF_NAMESPACE_ID::compiler::Version* p = compiler_version_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::compiler::Version*>(
-      &PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::compiler::Version&>(
+      PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::compiler_version() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
@@ -1429,7 +1322,7 @@
 }
 inline void CodeGeneratorRequest::unsafe_arena_set_allocated_compiler_version(
     PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(compiler_version_);
   }
   compiler_version_ = compiler_version;
@@ -1441,10 +1334,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
 }
 inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::release_compiler_version() {
-  auto temp = unsafe_arena_release_compiler_version();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000002u;
+  PROTOBUF_NAMESPACE_ID::compiler::Version* temp = compiler_version_;
+  compiler_version_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::unsafe_arena_release_compiler_version() {
@@ -1457,23 +1358,24 @@
 inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::_internal_mutable_compiler_version() {
   _has_bits_[0] |= 0x00000002u;
   if (compiler_version_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::compiler::Version>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::compiler::Version>(GetArenaForAllocation());
     compiler_version_ = p;
   }
   return compiler_version_;
 }
 inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
+  PROTOBUF_NAMESPACE_ID::compiler::Version* _msg = _internal_mutable_compiler_version();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
-  return _internal_mutable_compiler_version();
+  return _msg;
 }
 inline void CodeGeneratorRequest::set_allocated_compiler_version(PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete compiler_version_;
   }
   if (compiler_version) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(compiler_version);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::compiler::Version>::GetOwningArena(compiler_version);
     if (message_arena != submessage_arena) {
       compiler_version = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, compiler_version, submessage_arena);
@@ -1499,51 +1401,35 @@
   return _internal_has_name();
 }
 inline void CodeGeneratorResponse_File::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& CodeGeneratorResponse_File::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   return _internal_name();
 }
-inline void CodeGeneratorResponse_File::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse_File::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
 inline std::string* CodeGeneratorResponse_File::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& CodeGeneratorResponse_File::_internal_name() const {
   return name_.Get();
 }
 inline void CodeGeneratorResponse_File::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void CodeGeneratorResponse_File::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-inline void CodeGeneratorResponse_File::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-inline void CodeGeneratorResponse_File::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse_File::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse_File::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
@@ -1551,7 +1437,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void CodeGeneratorResponse_File::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -1560,28 +1446,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
-inline std::string* CodeGeneratorResponse_File::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
 
 // optional string insertion_point = 2;
 inline bool CodeGeneratorResponse_File::_internal_has_insertion_point() const {
@@ -1592,51 +1459,35 @@
   return _internal_has_insertion_point();
 }
 inline void CodeGeneratorResponse_File::clear_insertion_point() {
-  insertion_point_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  insertion_point_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000002u;
 }
 inline const std::string& CodeGeneratorResponse_File::insertion_point() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   return _internal_insertion_point();
 }
-inline void CodeGeneratorResponse_File::set_insertion_point(const std::string& value) {
-  _internal_set_insertion_point(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse_File::set_insertion_point(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
 inline std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+  std::string* _s = _internal_mutable_insertion_point();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  return _internal_mutable_insertion_point();
+  return _s;
 }
 inline const std::string& CodeGeneratorResponse_File::_internal_insertion_point() const {
   return insertion_point_.Get();
 }
 inline void CodeGeneratorResponse_File::_internal_set_insertion_point(const std::string& value) {
   _has_bits_[0] |= 0x00000002u;
-  insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void CodeGeneratorResponse_File::set_insertion_point(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  insertion_point_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-inline void CodeGeneratorResponse_File::set_insertion_point(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse_File::_internal_mutable_insertion_point() {
   _has_bits_[0] |= 0x00000002u;
-  return insertion_point_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return insertion_point_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse_File::release_insertion_point() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
@@ -1644,7 +1495,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000002u;
-  return insertion_point_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return insertion_point_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void CodeGeneratorResponse_File::set_allocated_insertion_point(std::string* insertion_point) {
   if (insertion_point != nullptr) {
@@ -1653,28 +1504,9 @@
     _has_bits_[0] &= ~0x00000002u;
   }
   insertion_point_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), insertion_point,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
-inline std::string* CodeGeneratorResponse_File::unsafe_arena_release_insertion_point() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000002u;
-  return insertion_point_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_insertion_point(
-    std::string* insertion_point) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (insertion_point != nullptr) {
-    _has_bits_[0] |= 0x00000002u;
-  } else {
-    _has_bits_[0] &= ~0x00000002u;
-  }
-  insertion_point_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      insertion_point, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
 
 // optional string content = 15;
 inline bool CodeGeneratorResponse_File::_internal_has_content() const {
@@ -1685,51 +1517,35 @@
   return _internal_has_content();
 }
 inline void CodeGeneratorResponse_File::clear_content() {
-  content_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  content_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000004u;
 }
 inline const std::string& CodeGeneratorResponse_File::content() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   return _internal_content();
 }
-inline void CodeGeneratorResponse_File::set_content(const std::string& value) {
-  _internal_set_content(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse_File::set_content(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
 inline std::string* CodeGeneratorResponse_File::mutable_content() {
+  std::string* _s = _internal_mutable_content();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  return _internal_mutable_content();
+  return _s;
 }
 inline const std::string& CodeGeneratorResponse_File::_internal_content() const {
   return content_.Get();
 }
 inline void CodeGeneratorResponse_File::_internal_set_content(const std::string& value) {
   _has_bits_[0] |= 0x00000004u;
-  content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void CodeGeneratorResponse_File::set_content(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  content_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-inline void CodeGeneratorResponse_File::set_content(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-inline void CodeGeneratorResponse_File::set_content(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse_File::_internal_mutable_content() {
   _has_bits_[0] |= 0x00000004u;
-  return content_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return content_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse_File::release_content() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
@@ -1737,7 +1553,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000004u;
-  return content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void CodeGeneratorResponse_File::set_allocated_content(std::string* content) {
   if (content != nullptr) {
@@ -1746,27 +1562,96 @@
     _has_bits_[0] &= ~0x00000004u;
   }
   content_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), content,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
-inline std::string* CodeGeneratorResponse_File::unsafe_arena_release_content() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000004u;
-  return content_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
+
+// optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+inline bool CodeGeneratorResponse_File::_internal_has_generated_code_info() const {
+  bool value = (_has_bits_[0] & 0x00000008u) != 0;
+  PROTOBUF_ASSUME(!value || generated_code_info_ != nullptr);
+  return value;
 }
-inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_content(
-    std::string* content) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (content != nullptr) {
-    _has_bits_[0] |= 0x00000004u;
-  } else {
-    _has_bits_[0] &= ~0x00000004u;
+inline bool CodeGeneratorResponse_File::has_generated_code_info() const {
+  return _internal_has_generated_code_info();
+}
+inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::_internal_generated_code_info() const {
+  const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* p = generated_code_info_;
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo&>(
+      PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_);
+}
+inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::generated_code_info() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+  return _internal_generated_code_info();
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_generated_code_info(
+    PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) {
+  if (GetArenaForAllocation() == nullptr) {
+    delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_);
   }
-  content_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      content, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  generated_code_info_ = generated_code_info;
+  if (generated_code_info) {
+    _has_bits_[0] |= 0x00000008u;
+  } else {
+    _has_bits_[0] &= ~0x00000008u;
+  }
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+}
+inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::release_generated_code_info() {
+  _has_bits_[0] &= ~0x00000008u;
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_;
+  generated_code_info_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
+    temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
+  return temp;
+}
+inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::unsafe_arena_release_generated_code_info() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+  _has_bits_[0] &= ~0x00000008u;
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_;
+  generated_code_info_ = nullptr;
+  return temp;
+}
+inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::_internal_mutable_generated_code_info() {
+  _has_bits_[0] |= 0x00000008u;
+  if (generated_code_info_ == nullptr) {
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo>(GetArenaForAllocation());
+    generated_code_info_ = p;
+  }
+  return generated_code_info_;
+}
+inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::mutable_generated_code_info() {
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* _msg = _internal_mutable_generated_code_info();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+  return _msg;
+}
+inline void CodeGeneratorResponse_File::set_allocated_generated_code_info(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) {
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_);
+  }
+  if (generated_code_info) {
+    ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<
+            ::PROTOBUF_NAMESPACE_ID::MessageLite>::GetOwningArena(
+                reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info));
+    if (message_arena != submessage_arena) {
+      generated_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
+          message_arena, generated_code_info, submessage_arena);
+    }
+    _has_bits_[0] |= 0x00000008u;
+  } else {
+    _has_bits_[0] &= ~0x00000008u;
+  }
+  generated_code_info_ = generated_code_info;
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
 }
 
 // -------------------------------------------------------------------
@@ -1782,51 +1667,35 @@
   return _internal_has_error();
 }
 inline void CodeGeneratorResponse::clear_error() {
-  error_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  error_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& CodeGeneratorResponse::error() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
   return _internal_error();
 }
-inline void CodeGeneratorResponse::set_error(const std::string& value) {
-  _internal_set_error(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse::set_error(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
 inline std::string* CodeGeneratorResponse::mutable_error() {
+  std::string* _s = _internal_mutable_error();
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
-  return _internal_mutable_error();
+  return _s;
 }
 inline const std::string& CodeGeneratorResponse::_internal_error() const {
   return error_.Get();
 }
 inline void CodeGeneratorResponse::_internal_set_error(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void CodeGeneratorResponse::set_error(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  error_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-inline void CodeGeneratorResponse::set_error(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-inline void CodeGeneratorResponse::set_error(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
+  error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse::_internal_mutable_error() {
   _has_bits_[0] |= 0x00000001u;
-  return error_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return error_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* CodeGeneratorResponse::release_error() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
@@ -1834,7 +1703,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return error_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return error_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void CodeGeneratorResponse::set_allocated_error(std::string* error) {
   if (error != nullptr) {
@@ -1843,28 +1712,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   error_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), error,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
-inline std::string* CodeGeneratorResponse::unsafe_arena_release_error() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.compiler.CodeGeneratorResponse.error)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return error_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void CodeGeneratorResponse::unsafe_arena_set_allocated_error(
-    std::string* error) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (error != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  error_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      error, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
 
 // optional uint64 supported_features = 2;
 inline bool CodeGeneratorResponse::_internal_has_supported_features() const {
@@ -1875,7 +1725,7 @@
   return _internal_has_supported_features();
 }
 inline void CodeGeneratorResponse::clear_supported_features() {
-  supported_features_ = PROTOBUF_ULONGLONG(0);
+  supported_features_ = uint64_t{0u};
   _has_bits_[0] &= ~0x00000002u;
 }
 inline ::PROTOBUF_NAMESPACE_ID::uint64 CodeGeneratorResponse::_internal_supported_features() const {
@@ -1924,8 +1774,9 @@
   return file_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+  PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* _add = _internal_add_file();
   // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return _internal_add_file();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >&
 CodeGeneratorResponse::file() const {
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index 492b896..9242aac 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -50,7 +50,7 @@
 option java_package = "com.google.protobuf.compiler";
 option java_outer_classname = "PluginProtos";
 
-option go_package = "github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go";
+option go_package = "google.golang.org/protobuf/types/pluginpb";
 
 import "google/protobuf/descriptor.proto";
 
@@ -173,6 +173,11 @@
 
     // The file contents.
     optional string content = 15;
+
+    // Information describing the file content being inserted. If an insertion
+    // point is used, this information will be appropriately offset and inserted
+    // into the code generation metadata for the generated files.
+    optional GeneratedCodeInfo generated_code_info = 16;
   }
   repeated File file = 15;
 }
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 8762818..95de716 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -69,18 +69,6 @@
 
 namespace {
 
-bool StrEndsWith(StringPiece sp, StringPiece x) {
-  return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
-}
-
-// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
-// suffix stripped.
-// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
-std::string StripProto(const std::string& filename) {
-  const char* suffix =
-      StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
-  return StripSuffixString(filename, suffix);
-}
 
 // Returns the Python module name expected for a given .proto filename.
 std::string ModuleName(const std::string& filename) {
@@ -106,11 +94,12 @@
 
 // Keywords reserved by the Python language.
 const char* const kKeywords[] = {
-    "False",   "None",     "True",     "and",    "as",    "assert", "break",
-    "class",   "continue", "def",      "del",    "elif",  "else",   "except",
-    "finally", "for",      "from",     "global", "if",    "import", "in",
-    "is",      "lambda",   "nonlocal", "not",    "or",    "pass",   "raise",
-    "return",  "try",      "while",    "with",   "yield", "print",
+    "False",  "None",     "True",  "and",    "as",       "assert",
+    "async",  "await",    "break", "class",  "continue", "def",
+    "del",    "elif",     "else",  "except", "finally",  "for",
+    "from",   "global",   "if",    "import", "in",       "is",
+    "lambda", "nonlocal", "not",   "or",     "pass",     "raise",
+    "return", "try",      "while", "with",   "yield",    "print",
 };
 const char* const* kKeywordsEnd =
     kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
@@ -125,7 +114,7 @@
   return false;
 }
 
-inline bool IsPythonKeyword(const string& name) {
+inline bool IsPythonKeyword(const std::string& name) {
   return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd);
 }
 
@@ -183,7 +172,7 @@
       "# -*- coding: utf-8 -*-\n"
       "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
       "# source: $filename$\n"
-      "\n",
+      "\"\"\"Generated protocol buffer code.\"\"\"\n",
       "filename", file->name());
   if (HasTopLevelEnums(file)) {
     printer->Print(
@@ -301,7 +290,7 @@
 
 Generator::~Generator() {}
 
-uint64 Generator::GetSupportedFeatures() const {
+uint64_t Generator::GetSupportedFeatures() const {
   return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
 }
 
@@ -324,7 +313,6 @@
     }
   }
 
-
   // Completely serialize all Generate() calls on this instance.  The
   // thread-safety constraints of the CodeGenerator interface aren't clear so
   // just be as conservative as possible.  It's easier to relax this later if
@@ -584,7 +572,7 @@
   for (int i = 0; i < file_->extension_count(); ++i) {
     const FieldDescriptor& extension_field = *file_->extension(i);
     std::string constant_name = extension_field.name() + "_FIELD_NUMBER";
-    UpperString(&constant_name);
+    ToUpper(&constant_name);
     printer_->Print("$constant_name$ = $number$\n", "constant_name",
                     constant_name, "number",
                     StrCat(extension_field.number()));
@@ -687,7 +675,8 @@
     const ServiceDescriptor& descriptor) const {
   std::string name = ModuleLevelServiceDescriptorName(descriptor);
   if (!pure_python_workable_) {
-    name = "'" + descriptor.full_name() + "'";
+    name = "_descriptor.ServiceDescriptor(full_name='" +
+           descriptor.full_name() + "')";
   }
   printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key",
                   kDescriptorKey, "descriptor_name", name);
@@ -884,7 +873,8 @@
   if (pure_python_workable_) {
     m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
   } else {
-    m["descriptor_name"] = "'" + message_descriptor.full_name() + "'";
+    m["descriptor_name"] = "_descriptor.Descriptor(full_name='" +
+                           message_descriptor.full_name() + "')";
   }
   printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n");
   std::string module_name = ModuleName(file_->name());
@@ -1066,7 +1056,7 @@
 }
 
 // Prints statements setting the message_type and enum_type fields in the
-// Python descriptor objects we've already output in ths file.  We must
+// Python descriptor objects we've already output in the file.  We must
 // do this in a separate step due to circular references (otherwise, we'd
 // just set everything in the initial assignment statements).
 void Generator::FixForeignFieldsInDescriptors() const {
@@ -1262,7 +1252,7 @@
   // The C++ implementation doesn't guard against this either.  Leaving
   // it for now...
   std::string name = NamePrefixedWithNestedTypes(descriptor, "_");
-  UpperString(&name);
+  ToUpper(&name);
   // Module-private for now.  Easy to make public later; almost impossible
   // to make private later.
   name = "_" + name;
@@ -1292,7 +1282,7 @@
 std::string Generator::ModuleLevelServiceDescriptorName(
     const ServiceDescriptor& descriptor) const {
   std::string name = descriptor.name();
-  UpperString(&name);
+  ToUpper(&name);
   name = "_" + name;
   if (descriptor.file() != file_) {
     name = ModuleAlias(descriptor.file()->name()) + "." + name;
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index fb1aee1..ed1c995 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -73,7 +73,7 @@
                 GeneratorContext* generator_context,
                 std::string* error) const override;
 
-  uint64 GetSupportedFeatures() const override;
+  uint64_t GetSupportedFeatures() const override;
 
  private:
   void PrintImports() const;
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index 8d7ef98..76ceef3 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/compiler/python/python_generator.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index 8c0aed1..cca69de 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -77,6 +77,10 @@
 }
 
 std::string LabelForField(const FieldDescriptor* field) {
+  if (field->has_optional_keyword() &&
+      field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    return "proto3_optional";
+  }
   switch (field->label()) {
     case FieldDescriptor::LABEL_OPTIONAL: return "optional";
     case FieldDescriptor::LABEL_REQUIRED: return "required";
@@ -109,7 +113,7 @@
   }
 }
 
-string StringifySyntax(FileDescriptor::Syntax syntax) {
+std::string StringifySyntax(FileDescriptor::Syntax syntax) {
   switch (syntax) {
     case FileDescriptor::SYNTAX_PROTO2:
       return "proto2";
@@ -143,7 +147,7 @@
       return NumberToString(field->default_value_enum()->number());
     case FieldDescriptor::CPPTYPE_STRING: {
       std::ostringstream os;
-      string default_str = field->default_value_string();
+      std::string default_str = field->default_value_string();
 
       if (field->type() == FieldDescriptor::TYPE_STRING) {
         os << "\"" << default_str << "\"";
@@ -216,6 +220,11 @@
                      DefaultValueForField(field));
     }
 
+    if (field->has_json_name()) {
+      printer->Print(", json_name: \"$json_name$\"", "json_name",
+                    field->json_name());
+    }
+
     printer->Print("\n");
   }
 }
@@ -238,8 +247,7 @@
 bool GenerateMessage(const Descriptor* message, io::Printer* printer,
                      std::string* error) {
   if (message->extension_range_count() > 0 || message->extension_count() > 0) {
-    *error = "Extensions are not yet supported for proto2 .proto files.";
-    return false;
+    GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files.";
   }
 
   // Don't generate MapEntry messages -- we use the Ruby extension's native
@@ -255,12 +263,12 @@
 
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
-    if (!field->containing_oneof()) {
+    if (!field->real_containing_oneof()) {
       GenerateField(field, printer);
     }
   }
 
-  for (int i = 0; i < message->oneof_decl_count(); i++) {
+  for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     GenerateOneof(oneof, printer);
   }
@@ -409,7 +417,7 @@
 
     // If :: is in the package use the Ruby formatted name as-is
     //    -> A::B::C
-    // otherwise, use the dot seperator
+    // otherwise, use the dot separator
     //    -> A.B.C
     if (package_name.find("::") != std::string::npos) {
       need_change_to_module = false;
@@ -422,14 +430,14 @@
   }
 
   // Use the appropriate delimiter
-  string delimiter = need_change_to_module ? "." : "::";
+  std::string delimiter = need_change_to_module ? "." : "::";
   int delimiter_size = need_change_to_module ? 1 : 2;
 
   // Extract each module name and indent
   while (!package_name.empty()) {
     size_t dot_index = package_name.find(delimiter);
-    string component;
-    if (dot_index == string::npos) {
+    std::string component;
+    if (dot_index == std::string::npos) {
       component = package_name;
       package_name = "";
     } else {
@@ -458,7 +466,7 @@
 }
 
 bool UsesTypeFromFile(const Descriptor* message, const FileDescriptor* file,
-                      string* error) {
+                      std::string* error) {
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
     if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
@@ -495,7 +503,7 @@
 bool MaybeEmitDependency(const FileDescriptor* import,
                          const FileDescriptor* from,
                          io::Printer* printer,
-                         string* error) {
+                         std::string* error) {
   if (from->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
       import->syntax() == FileDescriptor::SYNTAX_PROTO2) {
     for (int i = 0; i < from->message_type_count(); i++) {
@@ -520,7 +528,7 @@
 }
 
 bool GenerateFile(const FileDescriptor* file, io::Printer* printer,
-                  string* error) {
+                  std::string* error) {
   printer->Print(
     "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "# source: $filename$\n"
@@ -539,8 +547,7 @@
   // TODO: Remove this when ruby supports extensions for proto2 syntax.
   if (file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
       file->extension_count() > 0) {
-    *error = "Extensions are not yet supported for proto2 .proto files.";
-    return false;
+    GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files.";
   }
 
   printer->Print("Google::Protobuf::DescriptorPool.generated_pool.build do\n");
@@ -576,9 +583,9 @@
 
 bool Generator::Generate(
     const FileDescriptor* file,
-    const string& parameter,
+    const std::string& parameter,
     GeneratorContext* generator_context,
-    string* error) const {
+    std::string* error) const {
 
   if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
       file->syntax() != FileDescriptor::SYNTAX_PROTO2) {
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h
index 731a81a..647bb83 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.h
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -49,11 +49,12 @@
 // Ruby output, you can do so by registering an instance of this
 // CodeGenerator with the CommandLineInterface in your main() function.
 class PROTOC_EXPORT Generator : public CodeGenerator {
-  virtual bool Generate(
-      const FileDescriptor* file,
-      const string& parameter,
-      GeneratorContext* generator_context,
-      string* error) const;
+  bool Generate(const FileDescriptor* file, const std::string& parameter,
+                GeneratorContext* generator_context,
+                std::string* error) const override;
+  uint64_t GetSupportedFeatures() const override {
+    return FEATURE_PROTO3_OPTIONAL;
+  }
 };
 
 }  // namespace ruby
@@ -64,4 +65,3 @@
 #include <google/protobuf/port_undef.inc>
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
-
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
index d93a68d..27439a7 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -46,7 +46,7 @@
 namespace ruby {
 namespace {
 
-string FindRubyTestDir() {
+std::string FindRubyTestDir() {
   return TestSourceDir() + "/google/protobuf/compiler/ruby";
 }
 
@@ -58,7 +58,7 @@
 // extensions to the point where we can do this test in a more automated way.
 
 void RubyTest(string proto_file) {
-  string ruby_tests = FindRubyTestDir();
+  std::string ruby_tests = FindRubyTestDir();
 
   google::protobuf::compiler::CommandLineInterface cli;
   cli.SetInputsAreProtoPathRelative(true);
@@ -67,7 +67,7 @@
   cli.RegisterGenerator("--ruby_out", &ruby_generator, "");
 
   // Copy generated_code.proto to the temporary test directory.
-  string test_input;
+  std::string test_input;
   GOOGLE_CHECK_OK(File::GetContents(
       ruby_tests + proto_file + ".proto",
       &test_input,
@@ -78,9 +78,9 @@
       true));
 
   // Invoke the proto compiler (we will be inside TestTempDir() at this point).
-  string ruby_out = "--ruby_out=" + TestTempDir();
-  string proto_path = "--proto_path=" + TestTempDir();
-  string proto_target = TestTempDir() + proto_file + ".proto";
+  std::string ruby_out = "--ruby_out=" + TestTempDir();
+  std::string proto_path = "--proto_path=" + TestTempDir();
+  std::string proto_target = TestTempDir() + proto_file + ".proto";
   const char* argv[] = {
     "protoc",
     ruby_out.c_str(),
@@ -91,12 +91,12 @@
   EXPECT_EQ(0, cli.Run(4, argv));
 
   // Load the generated output and compare to the expected result.
-  string output;
+  std::string output;
   GOOGLE_CHECK_OK(File::GetContentsAsText(
       TestTempDir() + proto_file + "_pb.rb",
       &output,
       true));
-  string expected_output;
+  std::string expected_output;
   GOOGLE_CHECK_OK(File::GetContentsAsText(
       ruby_tests + proto_file + "_pb.rb",
       &expected_output,
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
index 5ae0261..72e1d71 100644
--- a/src/google/protobuf/compiler/zip_writer.cc
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -34,6 +34,9 @@
 // Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
 
 #include <google/protobuf/compiler/zip_writer.h>
+
+#include <cstdint>
+
 #include <google/protobuf/io/coded_stream.h>
 
 namespace google {
@@ -42,9 +45,9 @@
 
 // January 1, 1980 as a DOS date.
 // see https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
-static const uint16 kDosEpoch = 1 << 5 | 1;
+static const uint16_t kDosEpoch = 1 << 5 | 1;
 
-static const uint32 kCRC32Table[256] = {
+static const uint32_t kCRC32Table[256] = {
     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
     0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
     0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
@@ -89,8 +92,8 @@
     0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
     0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
 
-static uint32 ComputeCRC32(const std::string& buf) {
-  uint32 x = ~0U;
+static uint32_t ComputeCRC32(const std::string& buf) {
+  uint32_t x = ~0U;
   for (int i = 0; i < buf.size(); ++i) {
     unsigned char c = buf[i];
     x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8);
@@ -98,10 +101,10 @@
   return ~x;
 }
 
-static void WriteShort(io::CodedOutputStream* out, uint16 val) {
-  uint8 p[2];
-  p[0] = static_cast<uint8>(val);
-  p[1] = static_cast<uint8>(val >> 8);
+static void WriteShort(io::CodedOutputStream* out, uint16_t val) {
+  uint8_t p[2];
+  p[0] = static_cast<uint8_t>(val);
+  p[1] = static_cast<uint8_t>(val >> 8);
   out->WriteRaw(p, 2);
 }
 
@@ -114,7 +117,7 @@
   FileInfo info;
 
   info.name = filename;
-  uint16 filename_size = filename.size();
+  uint16_t filename_size = filename.size();
   info.offset = raw_output_->ByteCount();
   info.size = contents.size();
   info.crc32 = ComputeCRC32(contents);
@@ -141,17 +144,17 @@
 }
 
 bool ZipWriter::WriteDirectory() {
-  uint16 num_entries = files_.size();
-  uint32 dir_ofs = raw_output_->ByteCount();
+  uint16_t num_entries = files_.size();
+  uint32_t dir_ofs = raw_output_->ByteCount();
 
   // write central directory
   io::CodedOutputStream output(raw_output_);
   for (int i = 0; i < num_entries; ++i) {
     const std::string& filename = files_[i].name;
-    uint16 filename_size = filename.size();
-    uint32 crc32 = files_[i].crc32;
-    uint32 size = files_[i].size;
-    uint32 offset = files_[i].offset;
+    uint16_t filename_size = filename.size();
+    uint32_t crc32 = files_[i].crc32;
+    uint32_t size = files_[i].size;
+    uint32_t offset = files_[i].offset;
 
     output.WriteLittleEndian32(0x02014b50);  // magic
     WriteShort(&output, 10);                 // version made by
@@ -172,7 +175,7 @@
     output.WriteLittleEndian32(offset);      // local header offset
     output.WriteString(filename);            // file name
   }
-  uint32 dir_len = output.ByteCount();
+  uint32_t dir_len = output.ByteCount();
 
   // write end of central directory marker
   output.WriteLittleEndian32(0x06054b50);  // magic
diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
index 3a8903a..0a8a773 100644
--- a/src/google/protobuf/compiler/zip_writer.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -30,7 +30,9 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
+#include <cstdint>
 #include <vector>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 
@@ -49,9 +51,9 @@
  private:
   struct FileInfo {
     std::string name;
-    uint32 offset;
-    uint32 size;
-    uint32 crc32;
+    uint32_t offset;
+    uint32_t size;
+    uint32_t crc32;
   };
 
   io::ZeroCopyOutputStream* raw_output_;
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 1ec38c1..bedb5b3 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -49,6 +49,7 @@
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/any.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/tokenizer.h>
@@ -254,14 +255,14 @@
   std::string result;
   result.reserve(input.size());
 
-  for (int i = 0; i < input.size(); i++) {
-    if (input[i] == '_') {
+  for (char character : input) {
+    if (character == '_') {
       capitalize_next = true;
     } else if (capitalize_next) {
-      result.push_back(ToUpper(input[i]));
+      result.push_back(ToUpper(character));
       capitalize_next = false;
     } else {
-      result.push_back(input[i]);
+      result.push_back(character);
     }
   }
 
@@ -278,14 +279,14 @@
   std::string result;
   result.reserve(input.size());
 
-  for (int i = 0; i < input.size(); i++) {
-    if (input[i] == '_') {
+  for (char character : input) {
+    if (character == '_') {
       capitalize_next = true;
     } else if (capitalize_next) {
-      result.push_back(ToUpper(input[i]));
+      result.push_back(ToUpper(character));
       capitalize_next = false;
     } else {
-      result.push_back(input[i]);
+      result.push_back(character);
     }
   }
 
@@ -297,14 +298,14 @@
   std::string result;
   result.reserve(input.size());
 
-  for (int i = 0; i < input.size(); i++) {
-    if (input[i] == '_') {
+  for (char character : input) {
+    if (character == '_') {
       next_upper = true;
     } else {
       if (next_upper) {
-        result.push_back(ToUpper(input[i]));
+        result.push_back(ToUpper(character));
       } else {
-        result.push_back(ToLower(input[i]));
+        result.push_back(ToLower(character));
       }
       next_upper = false;
     }
@@ -318,9 +319,9 @@
  public:
   PrefixRemover(StringPiece prefix) {
     // Strip underscores and lower-case the prefix.
-    for (int i = 0; i < prefix.size(); i++) {
-      if (prefix[i] != '_') {
-        prefix_ += ascii_tolower(prefix[i]);
+    for (char character : prefix) {
+      if (character != '_') {
+        prefix_ += ascii_tolower(character);
       }
     }
   }
@@ -383,19 +384,8 @@
 // hash-maps for each object.
 //
 // The keys to these hash-maps are (parent, name) or (parent, number) pairs.
-//
-// TODO(kenton):  Use StringPiece rather than const char* in keys?  It would
-//   be a lot cleaner but we'd just have to convert it back to const char*
-//   for the open source release.
 
-typedef std::pair<const void*, const char*> PointerStringPair;
-
-struct PointerStringPairEqual {
-  inline bool operator()(const PointerStringPair& a,
-                         const PointerStringPair& b) const {
-    return a.first == b.first && strcmp(a.second, b.second) == 0;
-  }
-};
+typedef std::pair<const void*, StringPiece> PointerStringPair;
 
 typedef std::pair<const Descriptor*, int> DescriptorIntPair;
 typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
@@ -419,16 +409,16 @@
   static const size_t min_buckets = 8;
 #endif
   inline bool operator()(const PairType& a, const PairType& b) const {
-    return a.first < b.first || (a.first == b.first && a.second < b.second);
+    return a < b;
   }
 };
 
 struct PointerStringPairHash {
   size_t operator()(const PointerStringPair& p) const {
     static const size_t prime = 16777619;
-    hash<const char*> cstring_hash;
+    hash<StringPiece> string_hash;
     return reinterpret_cast<size_t>(p.first) * prime ^
-           static_cast<size_t>(cstring_hash(p.second));
+           static_cast<size_t>(string_hash(p.second));
   }
 
 #ifdef _MSC_VER
@@ -438,28 +428,25 @@
 #endif
   inline bool operator()(const PointerStringPair& a,
                          const PointerStringPair& b) const {
-    if (a.first < b.first) return true;
-    if (a.first > b.first) return false;
-    return strcmp(a.second, b.second) < 0;
+    return a < b;
   }
 };
 
 
 const Symbol kNullSymbol;
 
-typedef HASH_MAP<const char*, Symbol, HASH_FXN<const char*>, streq>
+typedef HASH_MAP<StringPiece, Symbol, HASH_FXN<StringPiece>>
     SymbolsByNameMap;
 
-typedef HASH_MAP<PointerStringPair, Symbol, PointerStringPairHash,
-                 PointerStringPairEqual>
+typedef HASH_MAP<PointerStringPair, Symbol, PointerStringPairHash>
     SymbolsByParentMap;
 
-typedef HASH_MAP<const char*, const FileDescriptor*, HASH_FXN<const char*>,
-                 streq>
+typedef HASH_MAP<StringPiece, const FileDescriptor*,
+                 HASH_FXN<StringPiece>>
     FilesByNameMap;
 
 typedef HASH_MAP<PointerStringPair, const FieldDescriptor*,
-                 PointerStringPairHash, PointerStringPairEqual>
+                 PointerStringPairHash>
     FieldsByNameMap;
 
 typedef HASH_MAP<DescriptorIntPair, const FieldDescriptor*,
@@ -485,16 +472,15 @@
   const char* kOptionNames[] = {
       "FileOptions",      "MessageOptions", "FieldOptions",  "EnumOptions",
       "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"};
-  for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) {
+  for (const char* option_name : kOptionNames) {
     // descriptor.proto has a different package name in opensource. We allow
     // both so the opensource protocol compiler can also compile internal
     // proto3 files with custom options. See: b/27567912
     allowed_proto3_extendees->insert(std::string("google.protobuf.") +
-                                     kOptionNames[i]);
+                                     option_name);
     // Split the word to trick the opensource processing scripts so they
     // will keep the original package name.
-    allowed_proto3_extendees->insert(std::string("proto") + "2." +
-                                     kOptionNames[i]);
+    allowed_proto3_extendees->insert(std::string("proto") + "2." + option_name);
   }
   return allowed_proto3_extendees;
 }
@@ -590,16 +576,16 @@
 
   // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
   // if not found.
-  inline Symbol FindSymbol(const std::string& key) const;
+  inline Symbol FindSymbol(StringPiece key) const;
 
   // This implements the body of DescriptorPool::Find*ByName().  It should
   // really be a private method of DescriptorPool, but that would require
   // declaring Symbol in descriptor.h, which would drag all kinds of other
   // stuff into the header.  Yay C++.
-  Symbol FindByNameHelper(const DescriptorPool* pool, const std::string& name);
+  Symbol FindByNameHelper(const DescriptorPool* pool, StringPiece name);
 
   // These return nullptr if not found.
-  inline const FileDescriptor* FindFile(const std::string& key) const;
+  inline const FileDescriptor* FindFile(StringPiece key) const;
   inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
                                               int number) const;
   inline void FindAllExtensions(const Descriptor* extendee,
@@ -633,7 +619,7 @@
 
   // Allocate a string which will be destroyed when the pool is destroyed.
   // The string is initialized to the given value for convenience.
-  std::string* AllocateString(const std::string& value);
+  std::string* AllocateString(StringPiece value);
 
   // Allocate empty string which will be destroyed when the pool is destroyed.
   std::string* AllocateEmptyString();
@@ -720,18 +706,18 @@
   // Find symbols.  These return a null Symbol (symbol.IsNull() is true)
   // if not found.
   inline Symbol FindNestedSymbol(const void* parent,
-                                 const std::string& name) const;
+                                 StringPiece name) const;
   inline Symbol FindNestedSymbolOfType(const void* parent,
-                                       const std::string& name,
+                                       StringPiece name,
                                        const Symbol::Type type) const;
 
   // These return nullptr if not found.
   inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
                                                   int number) const;
   inline const FieldDescriptor* FindFieldByLowercaseName(
-      const void* parent, const std::string& lowercase_name) const;
+      const void* parent, StringPiece lowercase_name) const;
   inline const FieldDescriptor* FindFieldByCamelcaseName(
-      const void* parent, const std::string& camelcase_name) const;
+      const void* parent, StringPiece camelcase_name) const;
   inline const EnumValueDescriptor* FindEnumValueByNumber(
       const EnumDescriptor* parent, int number) const;
   // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
@@ -800,13 +786,7 @@
   mutable internal::WrappedMutex unknown_enum_values_mu_;
 };
 
-DescriptorPool::Tables::Tables()
-    // Start some hash-map and hash-set objects with a small # of buckets
-    : known_bad_files_(3),
-      known_bad_symbols_(3),
-      extensions_loaded_from_db_(3),
-      symbols_by_name_(3),
-      files_by_name_(3) {
+DescriptorPool::Tables::Tables() {
   well_known_types_.insert({
       {"google.protobuf.DoubleValue", Descriptor::WELLKNOWNTYPE_DOUBLEVALUE},
       {"google.protobuf.FloatValue", Descriptor::WELLKNOWNTYPE_FLOATVALUE},
@@ -830,16 +810,8 @@
 DescriptorPool::Tables::~Tables() { GOOGLE_DCHECK(checkpoints_.empty()); }
 
 FileDescriptorTables::FileDescriptorTables()
-    // Initialize all the hash tables to start out with a small # of buckets.
-    : symbols_by_parent_(3),
-      fields_by_lowercase_name_(3),
-      fields_by_lowercase_name_tmp_(new FieldsByNameMap()),
-      fields_by_camelcase_name_(3),
-      fields_by_camelcase_name_tmp_(new FieldsByNameMap()),
-      fields_by_number_(3),
-      enum_values_by_number_(3),
-      unknown_enum_values_by_number_(3),
-      locations_by_path_(3) {}
+    : fields_by_lowercase_name_tmp_(new FieldsByNameMap()),
+      fields_by_camelcase_name_tmp_(new FieldsByNameMap()) {}
 
 FileDescriptorTables::~FileDescriptorTables() {}
 
@@ -869,15 +841,15 @@
   GOOGLE_DCHECK(!checkpoints_.empty());
   const CheckPoint& checkpoint = checkpoints_.back();
 
-  for (int i = checkpoint.pending_symbols_before_checkpoint;
+  for (size_t i = checkpoint.pending_symbols_before_checkpoint;
        i < symbols_after_checkpoint_.size(); i++) {
     symbols_by_name_.erase(symbols_after_checkpoint_[i]);
   }
-  for (int i = checkpoint.pending_files_before_checkpoint;
+  for (size_t i = checkpoint.pending_files_before_checkpoint;
        i < files_after_checkpoint_.size(); i++) {
     files_by_name_.erase(files_after_checkpoint_[i]);
   }
-  for (int i = checkpoint.pending_extensions_before_checkpoint;
+  for (size_t i = checkpoint.pending_extensions_before_checkpoint;
        i < extensions_after_checkpoint_.size(); i++) {
     extensions_.erase(extensions_after_checkpoint_[i]);
   }
@@ -898,8 +870,8 @@
 
 // -------------------------------------------------------------------
 
-inline Symbol DescriptorPool::Tables::FindSymbol(const std::string& key) const {
-  const Symbol* result = FindOrNull(symbols_by_name_, key.c_str());
+inline Symbol DescriptorPool::Tables::FindSymbol(StringPiece key) const {
+  const Symbol* result = FindOrNull(symbols_by_name_, key);
   if (result == nullptr) {
     return kNullSymbol;
   } else {
@@ -908,9 +880,9 @@
 }
 
 inline Symbol FileDescriptorTables::FindNestedSymbol(
-    const void* parent, const std::string& name) const {
-  const Symbol* result = FindOrNull(
-      symbols_by_parent_, PointerStringPair(parent, name.c_str()));
+    const void* parent, StringPiece name) const {
+  const Symbol* result =
+      FindOrNull(symbols_by_parent_, PointerStringPair(parent, name));
   if (result == nullptr) {
     return kNullSymbol;
   } else {
@@ -919,15 +891,14 @@
 }
 
 inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
-    const void* parent, const std::string& name,
-    const Symbol::Type type) const {
+    const void* parent, StringPiece name, const Symbol::Type type) const {
   Symbol result = FindNestedSymbol(parent, name);
   if (result.type != type) return kNullSymbol;
   return result;
 }
 
 Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
-                                                const std::string& name) {
+                                                StringPiece name) {
   if (pool->mutex_ != nullptr) {
     // Fast path: the Symbol is already cached.  This is just a hash lookup.
     ReaderMutexLock lock(pool->mutex_);
@@ -959,8 +930,8 @@
 }
 
 inline const FileDescriptor* DescriptorPool::Tables::FindFile(
-    const std::string& key) const {
-  return FindPtrOrNull(files_by_name_, key.c_str());
+    StringPiece key) const {
+  return FindPtrOrNull(files_by_name_, key);
 }
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
@@ -997,12 +968,12 @@
 }
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
-    const void* parent, const std::string& lowercase_name) const {
+    const void* parent, StringPiece lowercase_name) const {
   internal::call_once(
       fields_by_lowercase_name_once_,
       &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic, this);
   return FindPtrOrNull(fields_by_lowercase_name_,
-                            PointerStringPair(parent, lowercase_name.c_str()));
+                            PointerStringPair(parent, lowercase_name));
 }
 
 void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
@@ -1021,12 +992,12 @@
 }
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
-    const void* parent, const std::string& camelcase_name) const {
+    const void* parent, StringPiece camelcase_name) const {
   internal::call_once(
       fields_by_camelcase_name_once_,
       FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic, this);
   return FindPtrOrNull(fields_by_camelcase_name_,
-                            PointerStringPair(parent, camelcase_name.c_str()));
+                            PointerStringPair(parent, camelcase_name));
 }
 
 inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
@@ -1105,7 +1076,7 @@
 
 bool DescriptorPool::Tables::AddSymbol(const std::string& full_name,
                                        Symbol symbol) {
-  if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
+  if (InsertIfNotPresent(&symbols_by_name_, full_name, symbol)) {
     symbols_after_checkpoint_.push_back(full_name.c_str());
     return true;
   } else {
@@ -1121,7 +1092,7 @@
 }
 
 bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
-  if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) {
+  if (InsertIfNotPresent(&files_by_name_, file->name(), file)) {
     files_after_checkpoint_.push_back(file->name().c_str());
     return true;
   } else {
@@ -1196,7 +1167,7 @@
   return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type) * count));
 }
 
-std::string* DescriptorPool::Tables::AllocateString(const std::string& value) {
+std::string* DescriptorPool::Tables::AllocateString(StringPiece value) {
   std::string* result = new std::string(value);
   strings_.emplace_back(result);
   return result;
@@ -1308,16 +1279,16 @@
   enforce_dependencies_ = false;
 }
 
-void DescriptorPool::AddUnusedImportTrackFile(const std::string& file_name,
+void DescriptorPool::AddUnusedImportTrackFile(ConstStringParam file_name,
                                               bool is_error) {
-  unused_import_track_files_[file_name] = is_error;
+  unused_import_track_files_[std::string(file_name)] = is_error;
 }
 
 void DescriptorPool::ClearUnusedImportTrackFiles() {
   unused_import_track_files_.clear();
 }
 
-bool DescriptorPool::InternalIsFileLoaded(const std::string& filename) const {
+bool DescriptorPool::InternalIsFileLoaded(ConstStringParam filename) const {
   MutexLockMaybe lock(mutex_);
   return tables_->FindFile(filename) != nullptr;
 }
@@ -1341,6 +1312,10 @@
 
 }  // anonymous namespace
 
+DescriptorDatabase* DescriptorPool::internal_generated_database() {
+  return GeneratedDatabase();
+}
+
 DescriptorPool* DescriptorPool::internal_generated_pool() {
   static DescriptorPool* generated_pool =
       internal::OnShutdownDelete(NewGeneratedPool());
@@ -1390,7 +1365,7 @@
 //   there's nothing more important to do (read: never).
 
 const FileDescriptor* DescriptorPool::FindFileByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   MutexLockMaybe lock(mutex_);
   if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
@@ -1410,7 +1385,7 @@
 }
 
 const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
-    const std::string& symbol_name) const {
+    ConstStringParam symbol_name) const {
   MutexLockMaybe lock(mutex_);
   if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
@@ -1431,13 +1406,13 @@
 }
 
 const Descriptor* DescriptorPool::FindMessageTypeByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   return (result.type == Symbol::MESSAGE) ? result.descriptor : nullptr;
 }
 
 const FieldDescriptor* DescriptorPool::FindFieldByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   if (result.type == Symbol::FIELD &&
       !result.field_descriptor->is_extension()) {
@@ -1448,7 +1423,7 @@
 }
 
 const FieldDescriptor* DescriptorPool::FindExtensionByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   if (result.type == Symbol::FIELD && result.field_descriptor->is_extension()) {
     return result.field_descriptor;
@@ -1458,32 +1433,32 @@
 }
 
 const OneofDescriptor* DescriptorPool::FindOneofByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : nullptr;
 }
 
 const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   return (result.type == Symbol::ENUM) ? result.enum_descriptor : nullptr;
 }
 
 const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   return (result.type == Symbol::ENUM_VALUE) ? result.enum_value_descriptor
                                              : nullptr;
 }
 
 const ServiceDescriptor* DescriptorPool::FindServiceByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   return (result.type == Symbol::SERVICE) ? result.service_descriptor : nullptr;
 }
 
 const MethodDescriptor* DescriptorPool::FindMethodByName(
-    const std::string& name) const {
+    ConstStringParam name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   return (result.type == Symbol::METHOD) ? result.method_descriptor : nullptr;
 }
@@ -1540,7 +1515,7 @@
 }
 
 const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
-    const Descriptor* extendee, const std::string& printable_name) const {
+    const Descriptor* extendee, ConstStringParam printable_name) const {
   if (extendee->extension_range_count() == 0) return nullptr;
   const FieldDescriptor* result = FindExtensionByName(printable_name);
   if (result != nullptr && result->containing_type() == extendee) {
@@ -1582,8 +1557,7 @@
     std::vector<int> numbers;
     if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
                                                     &numbers)) {
-      for (int i = 0; i < numbers.size(); ++i) {
-        int number = numbers[i];
+      for (int number : numbers) {
         if (tables_->FindExtension(extendee, number) == nullptr) {
           TryFindExtensionInFallbackDatabase(extendee, number);
         }
@@ -1611,7 +1585,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindFieldByLowercaseName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByLowercaseName(this, key);
   if (result == nullptr || result->is_extension()) {
@@ -1622,7 +1596,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindFieldByCamelcaseName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByCamelcaseName(this, key);
   if (result == nullptr || result->is_extension()) {
@@ -1632,8 +1606,7 @@
   }
 }
 
-const FieldDescriptor* Descriptor::FindFieldByName(
-    const std::string& key) const {
+const FieldDescriptor* Descriptor::FindFieldByName(ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
   if (!result.IsNull() && !result.field_descriptor->is_extension()) {
@@ -1643,8 +1616,7 @@
   }
 }
 
-const OneofDescriptor* Descriptor::FindOneofByName(
-    const std::string& key) const {
+const OneofDescriptor* Descriptor::FindOneofByName(ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF);
   if (!result.IsNull()) {
@@ -1655,7 +1627,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindExtensionByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
   if (!result.IsNull() && result.field_descriptor->is_extension()) {
@@ -1666,7 +1638,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindExtensionByLowercaseName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByLowercaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
@@ -1677,7 +1649,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByCamelcaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
@@ -1687,8 +1659,7 @@
   }
 }
 
-const Descriptor* Descriptor::FindNestedTypeByName(
-    const std::string& key) const {
+const Descriptor* Descriptor::FindNestedTypeByName(ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
   if (!result.IsNull()) {
@@ -1699,7 +1670,7 @@
 }
 
 const EnumDescriptor* Descriptor::FindEnumTypeByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
   if (!result.IsNull()) {
@@ -1710,7 +1681,7 @@
 }
 
 const EnumValueDescriptor* Descriptor::FindEnumValueByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
   if (!result.IsNull()) {
@@ -1720,8 +1691,20 @@
   }
 }
 
+const FieldDescriptor* Descriptor::map_key() const {
+  if (!options().map_entry()) return nullptr;
+  GOOGLE_DCHECK_EQ(field_count(), 2);
+  return field(0);
+}
+
+const FieldDescriptor* Descriptor::map_value() const {
+  if (!options().map_entry()) return nullptr;
+  GOOGLE_DCHECK_EQ(field_count(), 2);
+  return field(1);
+}
+
 const EnumValueDescriptor* EnumDescriptor::FindValueByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
   if (!result.IsNull()) {
@@ -1741,7 +1724,7 @@
 }
 
 const MethodDescriptor* ServiceDescriptor::FindMethodByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result =
       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
   if (!result.IsNull()) {
@@ -1752,7 +1735,7 @@
 }
 
 const Descriptor* FileDescriptor::FindMessageTypeByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
   if (!result.IsNull()) {
     return result.descriptor;
@@ -1762,7 +1745,7 @@
 }
 
 const EnumDescriptor* FileDescriptor::FindEnumTypeByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
   if (!result.IsNull()) {
     return result.enum_descriptor;
@@ -1772,7 +1755,7 @@
 }
 
 const EnumValueDescriptor* FileDescriptor::FindEnumValueByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result =
       tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
   if (!result.IsNull()) {
@@ -1783,7 +1766,7 @@
 }
 
 const ServiceDescriptor* FileDescriptor::FindServiceByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
   if (!result.IsNull()) {
     return result.service_descriptor;
@@ -1793,7 +1776,7 @@
 }
 
 const FieldDescriptor* FileDescriptor::FindExtensionByName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
   if (!result.IsNull() && result.field_descriptor->is_extension()) {
     return result.field_descriptor;
@@ -1803,7 +1786,7 @@
 }
 
 const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
     return nullptr;
@@ -1813,7 +1796,7 @@
 }
 
 const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
-    const std::string& key) const {
+    ConstStringParam key) const {
   const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
     return nullptr;
@@ -1870,22 +1853,23 @@
 // -------------------------------------------------------------------
 
 bool DescriptorPool::TryFindFileInFallbackDatabase(
-    const std::string& name) const {
+    StringPiece name) const {
   if (fallback_database_ == nullptr) return false;
 
-  if (tables_->known_bad_files_.count(name) > 0) return false;
+  auto name_string = std::string(name);
+  if (tables_->known_bad_files_.count(name_string) > 0) return false;
 
   FileDescriptorProto file_proto;
-  if (!fallback_database_->FindFileByName(name, &file_proto) ||
+  if (!fallback_database_->FindFileByName(name_string, &file_proto) ||
       BuildFileFromDatabase(file_proto) == nullptr) {
-    tables_->known_bad_files_.insert(name);
+    tables_->known_bad_files_.insert(std::move(name_string));
     return false;
   }
   return true;
 }
 
-bool DescriptorPool::IsSubSymbolOfBuiltType(const std::string& name) const {
-  std::string prefix = name;
+bool DescriptorPool::IsSubSymbolOfBuiltType(StringPiece name) const {
+  auto prefix = std::string(name);
   for (;;) {
     std::string::size_type dot_pos = prefix.find_last_of('.');
     if (dot_pos == std::string::npos) {
@@ -1907,10 +1891,11 @@
 }
 
 bool DescriptorPool::TryFindSymbolInFallbackDatabase(
-    const std::string& name) const {
+    StringPiece name) const {
   if (fallback_database_ == nullptr) return false;
 
-  if (tables_->known_bad_symbols_.count(name) > 0) return false;
+  auto name_string = std::string(name);
+  if (tables_->known_bad_symbols_.count(name_string) > 0) return false;
 
   FileDescriptorProto file_proto;
   if (  // We skip looking in the fallback database if the name is a sub-symbol
@@ -1932,7 +1917,7 @@
       IsSubSymbolOfBuiltType(name)
 
       // Look up file containing this symbol in fallback database.
-      || !fallback_database_->FindFileContainingSymbol(name, &file_proto)
+      || !fallback_database_->FindFileContainingSymbol(name_string, &file_proto)
 
       // Check if we've already built this file. If so, it apparently doesn't
       // contain the symbol we're looking for.  Some DescriptorDatabases
@@ -1941,7 +1926,7 @@
 
       // Build the file.
       || BuildFileFromDatabase(file_proto) == nullptr) {
-    tables_->known_bad_symbols_.insert(name);
+    tables_->known_bad_symbols_.insert(std::move(name_string));
     return false;
   }
 
@@ -2279,34 +2264,34 @@
   const Reflection* reflection = options.GetReflection();
   std::vector<const FieldDescriptor*> fields;
   reflection->ListFields(options, &fields);
-  for (int i = 0; i < fields.size(); i++) {
+  for (const FieldDescriptor* field : fields) {
     int count = 1;
     bool repeated = false;
-    if (fields[i]->is_repeated()) {
-      count = reflection->FieldSize(options, fields[i]);
+    if (field->is_repeated()) {
+      count = reflection->FieldSize(options, field);
       repeated = true;
     }
     for (int j = 0; j < count; j++) {
       std::string fieldval;
-      if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
         std::string tmp;
         TextFormat::Printer printer;
         printer.SetInitialIndentLevel(depth + 1);
-        printer.PrintFieldValueToString(options, fields[i], repeated ? j : -1,
+        printer.PrintFieldValueToString(options, field, repeated ? j : -1,
                                         &tmp);
         fieldval.append("{\n");
         fieldval.append(tmp);
         fieldval.append(depth * 2, ' ');
         fieldval.append("}");
       } else {
-        TextFormat::PrintFieldValueToString(options, fields[i],
-                                            repeated ? j : -1, &fieldval);
+        TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1,
+                                            &fieldval);
       }
       std::string name;
-      if (fields[i]->is_extension()) {
-        name = "(." + fields[i]->full_name() + ")";
+      if (field->is_extension()) {
+        name = "(." + field->full_name() + ")";
       } else {
-        name = fields[i]->name();
+        name = field->name();
       }
       option_entries->push_back(name + " = " + fieldval);
     }
@@ -2363,9 +2348,8 @@
   std::string prefix(depth * 2, ' ');
   std::vector<std::string> all_options;
   if (RetrieveOptions(depth, options, pool, &all_options)) {
-    for (int i = 0; i < all_options.size(); i++) {
-      strings::SubstituteAndAppend(output, "$0option $1;\n", prefix,
-                                all_options[i]);
+    for (const std::string& option : all_options) {
+      strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, option);
     }
   }
   return !all_options.empty();
@@ -2395,8 +2379,9 @@
   void AddPreComment(std::string* output) {
     if (have_source_loc_) {
       // Detached leading comments.
-      for (int i = 0; i < source_loc_.leading_detached_comments.size(); ++i) {
-        *output += FormatComment(source_loc_.leading_detached_comments[i]);
+      for (const std::string& leading_detached_comment :
+           source_loc_.leading_detached_comments) {
+        *output += FormatComment(leading_detached_comment);
         *output += "\n";
       }
       // Attached leading comments.
@@ -2418,8 +2403,7 @@
     StripWhitespace(&stripped_comment);
     std::vector<std::string> lines = Split(stripped_comment, "\n");
     std::string output;
-    for (int i = 0; i < lines.size(); ++i) {
-      const std::string& line = lines[i];
+    for (const std::string& line : lines) {
       strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
     }
     return output;
@@ -2593,7 +2577,7 @@
     enum_type(i)->DebugString(depth, contents, debug_string_options);
   }
   for (int i = 0; i < field_count(); i++) {
-    if (field(i)->containing_oneof() == nullptr) {
+    if (field(i)->real_containing_oneof() == nullptr) {
       field(i)->DebugString(depth, contents, debug_string_options);
     } else if (field(i)->containing_oneof()->field(0) == field(i)) {
       // This is the first field in this oneof, so print the whole oneof.
@@ -2628,6 +2612,8 @@
       const Descriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start + 1) {
         strings::SubstituteAndAppend(contents, "$0, ", range->start);
+      } else if (range->end > FieldDescriptor::kMaxNumber) {
+        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end - 1);
@@ -2701,7 +2687,7 @@
   std::string label = StrCat(kLabelToName[this->label()], " ");
 
   // Label is omitted for maps, oneof, and plain proto3 fields.
-  if (is_map() || containing_oneof() ||
+  if (is_map() || real_containing_oneof() ||
       (is_optional() && !has_optional_keyword())) {
     label.clear();
   }
@@ -2723,7 +2709,7 @@
   if (has_json_name_) {
     if (!bracketed) {
       bracketed = true;
-      contents->append("[");
+      contents->append(" [");
     } else {
       contents->append(", ");
     }
@@ -2831,6 +2817,8 @@
       const EnumDescriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start) {
         strings::SubstituteAndAppend(contents, "$0, ", range->start);
+      } else if (range->end == INT_MAX) {
+        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end);
@@ -3440,7 +3428,6 @@
     void SetUInt64(int number, uint64 value, FieldDescriptor::Type type,
                    UnknownFieldSet* unknown_fields);
 
-
     // A helper function that adds an error at the specified location of the
     // option we're currently interpreting, and returns false.
     bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
@@ -3510,7 +3497,7 @@
     return pool->enforce_weak_;
   }
   static inline bool get_is_placeholder(const Descriptor* descriptor) {
-    return descriptor->is_placeholder_;
+    return descriptor != nullptr && descriptor->is_placeholder_;
   }
   static inline void assert_mutex_held(const DescriptorPool* pool) {
     if (pool->mutex_ != nullptr) {
@@ -3863,16 +3850,16 @@
   return result;
 }
 
-static bool ValidateQualifiedName(const std::string& name) {
+static bool ValidateQualifiedName(StringPiece name) {
   bool last_was_period = false;
 
-  for (int i = 0; i < name.size(); i++) {
+  for (char character : name) {
     // I don't trust isalnum() due to locales.  :(
-    if (('a' <= name[i] && name[i] <= 'z') ||
-        ('A' <= name[i] && name[i] <= 'Z') ||
-        ('0' <= name[i] && name[i] <= '9') || (name[i] == '_')) {
+    if (('a' <= character && character <= 'z') ||
+        ('A' <= character && character <= 'Z') ||
+        ('0' <= character && character <= '9') || (character == '_')) {
       last_was_period = false;
-    } else if (name[i] == '.') {
+    } else if (character == '.') {
       if (last_was_period) return false;
       last_was_period = true;
     } else {
@@ -3883,14 +3870,14 @@
   return !name.empty() && !last_was_period;
 }
 
-Symbol DescriptorPool::NewPlaceholder(const std::string& name,
+Symbol DescriptorPool::NewPlaceholder(StringPiece name,
                                       PlaceholderType placeholder_type) const {
   MutexLockMaybe lock(mutex_);
   return NewPlaceholderWithMutexHeld(name, placeholder_type);
 }
 
 Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
-    const std::string& name, PlaceholderType placeholder_type) const {
+    StringPiece name, PlaceholderType placeholder_type) const {
   if (mutex_) {
     mutex_->AssertHeld();
   }
@@ -3988,13 +3975,13 @@
 }
 
 FileDescriptor* DescriptorPool::NewPlaceholderFile(
-    const std::string& name) const {
+    StringPiece name) const {
   MutexLockMaybe lock(mutex_);
   return NewPlaceholderFileWithMutexHeld(name);
 }
 
 FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
-    const std::string& name) const {
+    StringPiece name) const {
   if (mutex_) {
     mutex_->AssertHeld();
   }
@@ -4022,6 +4009,11 @@
   // Use its file as the parent instead.
   if (parent == nullptr) parent = file_;
 
+  if (full_name.find('\0') != std::string::npos) {
+    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + full_name + "\" contains null character.");
+    return false;
+  }
   if (tables_->AddSymbol(full_name, symbol)) {
     if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
       // This is only possible if there was already an error adding something of
@@ -4052,7 +4044,8 @@
       // Symbol seems to have been defined in a different file.
       AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
                "\"" + full_name + "\" is already defined in file \"" +
-                   other_file->name() + "\".");
+                   (other_file == nullptr ? "null" : other_file->name()) +
+                   "\".");
     }
     return false;
   }
@@ -4061,6 +4054,11 @@
 void DescriptorBuilder::AddPackage(const std::string& name,
                                    const Message& proto,
                                    const FileDescriptor* file) {
+  if (name.find('\0') != std::string::npos) {
+    AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + name + "\" contains null character.");
+    return;
+  }
   if (tables_->AddSymbol(name, Symbol(file))) {
     // Success.  Also add parent package, if any.
     std::string::size_type dot_pos = name.find_last_of('.');
@@ -4095,11 +4093,11 @@
     AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
              "Missing name.");
   } else {
-    for (int i = 0; i < name.size(); i++) {
+    for (char character : name) {
       // I don't trust isalnum() due to locales.  :(
-      if ((name[i] < 'a' || 'z' < name[i]) &&
-          (name[i] < 'A' || 'Z' < name[i]) &&
-          (name[i] < '0' || '9' < name[i]) && (name[i] != '_')) {
+      if ((character < 'a' || 'z' < character) &&
+          (character < 'A' || 'Z' < character) &&
+          (character < '0' || '9' < character) && (character != '_')) {
         AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
                  "\"" + name + "\" is not a valid identifier.");
       }
@@ -4205,13 +4203,13 @@
 void DescriptorBuilder::AddRecursiveImportError(
     const FileDescriptorProto& proto, int from_here) {
   std::string error_message("File recursively imports itself: ");
-  for (int i = from_here; i < tables_->pending_files_.size(); i++) {
+  for (size_t i = from_here; i < tables_->pending_files_.size(); i++) {
     error_message.append(tables_->pending_files_[i]);
     error_message.append(" -> ");
   }
   error_message.append(proto.name());
 
-  if (from_here < tables_->pending_files_.size() - 1) {
+  if (static_cast<size_t>(from_here) < tables_->pending_files_.size() - 1) {
     AddError(tables_->pending_files_[from_here + 1], proto,
              DescriptorPool::ErrorCollector::IMPORT, error_message);
   } else {
@@ -4284,7 +4282,7 @@
   //   mid-file, but that's pretty ugly, and I'm pretty sure there are
   //   some languages out there that do not allow recursive dependencies
   //   at all.
-  for (int i = 0; i < tables_->pending_files_.size(); i++) {
+  for (size_t i = 0; i < tables_->pending_files_.size(); i++) {
     if (tables_->pending_files_[i] == proto.name()) {
       AddRecursiveImportError(proto, i);
       return nullptr;
@@ -4374,6 +4372,12 @@
   }
   result->pool_ = pool_;
 
+  if (result->name().find('\0') != std::string::npos) {
+    AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + result->name() + "\" contains null character.");
+    return nullptr;
+  }
+
   // Add to tables.
   if (!tables_->AddFile(result)) {
     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
@@ -4883,6 +4887,7 @@
                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
                    "Messages can't have default values.");
           result->has_default_value_ = false;
+          result->default_generated_instance_ = nullptr;
           break;
       }
 
@@ -4929,6 +4934,7 @@
           result->default_value_string_ = &internal::GetEmptyString();
           break;
         case FieldDescriptor::CPPTYPE_MESSAGE:
+          result->default_generated_instance_ = nullptr;
           break;
       }
     }
@@ -5942,12 +5948,12 @@
 
 static std::string ToLowercaseWithoutUnderscores(const std::string& name) {
   std::string result;
-  for (int i = 0; i < name.size(); ++i) {
-    if (name[i] != '_') {
-      if (name[i] >= 'A' && name[i] <= 'Z') {
-        result.push_back(name[i] - 'A' + 'a');
+  for (char character : name) {
+    if (character != '_') {
+      if (character >= 'A' && character <= 'Z') {
+        result.push_back(character - 'A' + 'a');
       } else {
-        result.push_back(name[i]);
+        result.push_back(character);
       }
     }
   }
@@ -6131,7 +6137,7 @@
 
   // json_name option is not allowed on extension fields. Note that the
   // json_name field in FieldDescriptorProto is always populated by protoc
-  // when it sends descriptor data to plugins (caculated from field name if
+  // when it sends descriptor data to plugins (calculated from field name if
   // the option is not explicitly set) so we can't rely on its presence to
   // determine whether the json_name option is set on the field. Here we
   // compare it against the default calculated json_name value and consider
@@ -6222,8 +6228,8 @@
     return false;
   }
 
-  const FieldDescriptor* key = message->field(0);
-  const FieldDescriptor* value = message->field(1);
+  const FieldDescriptor* key = message->map_key();
+  const FieldDescriptor* value = message->map_value();
   if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
       key->name() != "key") {
     return false;
@@ -6380,7 +6386,6 @@
 
 DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {}
 
-
 bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
     OptionsToInterpret* options_to_interpret) {
   // Note that these may be in different pools, so we can't use the same
@@ -6461,7 +6466,6 @@
     }
   }
 
-
   return !failed;
 }
 
@@ -6704,10 +6708,10 @@
     if (matched) {
       // see if this location is in the range to remove
       bool loc_matches = true;
-      if (loc->path_size() < pathv.size()) {
+      if (loc->path_size() < static_cast<int64>(pathv.size())) {
         loc_matches = false;
       } else {
-        for (int j = 0; j < pathv.size(); j++) {
+        for (size_t j = 0; j < pathv.size(); j++) {
           if (loc->path(j) != pathv[j]) {
             loc_matches = false;
             break;
@@ -7064,6 +7068,18 @@
  public:
   DescriptorBuilder* builder_;
 
+  const Descriptor* FindAnyType(const Message& message,
+                                const std::string& prefix,
+                                const std::string& name) const override {
+    if (prefix != internal::kTypeGoogleApisComPrefix &&
+        prefix != internal::kTypeGoogleProdComPrefix) {
+      return nullptr;
+    }
+    assert_mutex_held(builder_->pool_);
+    Symbol result = builder_->FindSymbol(name);
+    return result.type == Symbol::MESSAGE ? result.descriptor : nullptr;
+  }
+
   const FieldDescriptor* FindExtension(Message* message,
                                        const std::string& name) const override {
     assert_mutex_held(builder_->pool_);
@@ -7268,9 +7284,9 @@
   }
 }
 
-Symbol DescriptorPool::CrossLinkOnDemandHelper(const std::string& name,
+Symbol DescriptorPool::CrossLinkOnDemandHelper(StringPiece name,
                                                bool expecting_enum) const {
-  std::string lookup_name = name;
+  auto lookup_name = std::string(name);
   if (!lookup_name.empty() && lookup_name[0] == '.') {
     lookup_name = lookup_name.substr(1);
   }
@@ -7398,7 +7414,7 @@
   descriptor_ = descriptor;
 }
 
-void LazyDescriptor::SetLazy(const std::string& name,
+void LazyDescriptor::SetLazy(StringPiece name,
                              const FileDescriptor* file) {
   // verify Init() has been called and Set hasn't been called yet.
   GOOGLE_CHECK(!descriptor_);
@@ -7434,3 +7450,5 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 322d5a4..0625b50 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -54,6 +54,7 @@
 #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__
 #define GOOGLE_PROTOBUF_DESCRIPTOR_H__
 
+#include <atomic>
 #include <map>
 #include <memory>
 #include <set>
@@ -63,6 +64,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/mutex.h>
 #include <google/protobuf/stubs/once.h>
+#include <google/protobuf/port.h>
 #include <google/protobuf/port_def.inc>
 
 // TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
@@ -202,7 +204,7 @@
   // build time if the symbol wasn't found and building of the file containing
   // that type is delayed because lazily_build_dependencies_ is set on the pool.
   // Should not be called after Set() has been called.
-  void SetLazy(const std::string& name, const FileDescriptor* file);
+  void SetLazy(StringPiece name, const FileDescriptor* file);
 
   // Returns the current value of the descriptor, thread-safe. If SetLazy(...)
   // has been called, will do a one-time cross link of the type specified,
@@ -320,20 +322,20 @@
   // exists.
   const FieldDescriptor* FindFieldByNumber(int number) const;
   // Looks up a field by name.  Returns nullptr if no such field exists.
-  const FieldDescriptor* FindFieldByName(const std::string& name) const;
+  const FieldDescriptor* FindFieldByName(ConstStringParam name) const;
 
   // Looks up a field by lowercased name (as returned by lowercase_name()).
   // This lookup may be ambiguous if multiple field names differ only by case,
   // in which case the field returned is chosen arbitrarily from the matches.
   const FieldDescriptor* FindFieldByLowercaseName(
-      const std::string& lowercase_name) const;
+      ConstStringParam lowercase_name) const;
 
   // Looks up a field by camel-case name (as returned by camelcase_name()).
   // This lookup may be ambiguous if multiple field names differ in a way that
   // leads them to have identical camel-case names, in which case the field
   // returned is chosen arbitrarily from the matches.
   const FieldDescriptor* FindFieldByCamelcaseName(
-      const std::string& camelcase_name) const;
+      ConstStringParam camelcase_name) const;
 
   // The number of oneofs in this message type.
   int oneof_decl_count() const;
@@ -346,7 +348,7 @@
   const OneofDescriptor* oneof_decl(int index) const;
 
   // Looks up a oneof by name.  Returns nullptr if no such oneof exists.
-  const OneofDescriptor* FindOneofByName(const std::string& name) const;
+  const OneofDescriptor* FindOneofByName(ConstStringParam name) const;
 
   // Nested type stuff -----------------------------------------------
 
@@ -358,7 +360,7 @@
 
   // Looks up a nested type by name.  Returns nullptr if no such nested type
   // exists.
-  const Descriptor* FindNestedTypeByName(const std::string& name) const;
+  const Descriptor* FindNestedTypeByName(ConstStringParam name) const;
 
   // Enum stuff ------------------------------------------------------
 
@@ -370,11 +372,11 @@
 
   // Looks up an enum type by name.  Returns nullptr if no such enum type
   // exists.
-  const EnumDescriptor* FindEnumTypeByName(const std::string& name) const;
+  const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const;
 
   // Looks up an enum value by name, among all enum types in this message.
   // Returns nullptr if no such value exists.
-  const EnumValueDescriptor* FindEnumValueByName(const std::string& name) const;
+  const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const;
 
   // Extensions ------------------------------------------------------
 
@@ -438,17 +440,17 @@
 
   // Looks up a named extension (which extends some *other* message type)
   // defined within this message type's scope.
-  const FieldDescriptor* FindExtensionByName(const std::string& name) const;
+  const FieldDescriptor* FindExtensionByName(ConstStringParam name) const;
 
   // Similar to FindFieldByLowercaseName(), but finds extensions defined within
   // this message type's scope.
   const FieldDescriptor* FindExtensionByLowercaseName(
-      const std::string& name) const;
+      ConstStringParam name) const;
 
   // Similar to FindFieldByCamelcaseName(), but finds extensions defined within
   // this message type's scope.
   const FieldDescriptor* FindExtensionByCamelcaseName(
-      const std::string& name) const;
+      ConstStringParam name) const;
 
   // Reserved fields -------------------------------------------------
 
@@ -478,7 +480,7 @@
   const std::string& reserved_name(int index) const;
 
   // Returns true if the field name is reserved.
-  bool IsReservedName(const std::string& name) const;
+  bool IsReservedName(ConstStringParam name) const;
 
   // Source Location ---------------------------------------------------
 
@@ -487,6 +489,16 @@
   // |*out_location| unchanged iff location information was not available.
   bool GetSourceLocation(SourceLocation* out_location) const;
 
+  // Maps --------------------------------------------------------------
+
+  // Returns the FieldDescriptor for the "key" field. If this isn't a map entry
+  // field, returns nullptr.
+  const FieldDescriptor* map_key() const;
+
+  // Returns the FieldDescriptor for the "value" field. If this isn't a map
+  // entry field, returns nullptr.
+  const FieldDescriptor* map_value() const;
+
  private:
   typedef MessageOptions OptionsType;
 
@@ -693,13 +705,14 @@
   // .proto file. Excludes singular proto3 fields that do not have a label.
   bool has_optional_keyword() const;
 
-  // Returns true if this is a non-oneof field that tracks presence.
-  // This includes all "required" and "optional" fields in the .proto file,
-  // but excludes oneof fields and singular proto3 fields without "optional".
+  // Returns true if this field tracks presence, ie. does the field
+  // distinguish between "unset" and "present with default value."
+  // This includes required, optional, and oneof fields. It excludes maps,
+  // repeated fields, and singular proto3 fields without "optional".
   //
-  // In implementations that use hasbits, this method will probably indicate
-  // whether this field uses a hasbit.
-  bool is_singular_with_presence() const;
+  // For fields where has_presence() == true, the return value of
+  // Reflection::HasField() is semantically meaningful.
+  bool has_presence() const;
 
   // Index of this field within the message's field array, or the file or
   // extension scope's extensions array.
@@ -827,6 +840,7 @@
   // Allows access to GetLocationPath for annotations.
   friend class io::Printer;
   friend class compiler::cpp::Formatter;
+  friend class Reflection;
 
   // Fill the json_name field of FieldDescriptorProto.
   void CopyJsonNameTo(FieldDescriptorProto* proto) const;
@@ -894,6 +908,7 @@
 
     mutable const EnumValueDescriptor* default_value_enum_;
     const std::string* default_value_string_;
+    mutable std::atomic<const Message*> default_generated_instance_;
   };
 
   static const CppType kTypeToCppTypeMap[MAX_TYPE + 1];
@@ -1018,7 +1033,7 @@
   const EnumValueDescriptor* value(int index) const;
 
   // Looks up a value by name.  Returns nullptr if no such value exists.
-  const EnumValueDescriptor* FindValueByName(const std::string& name) const;
+  const EnumValueDescriptor* FindValueByName(ConstStringParam name) const;
   // Looks up a value by number.  Returns nullptr if no such value exists.  If
   // multiple values have this number, the first one defined is returned.
   const EnumValueDescriptor* FindValueByNumber(int number) const;
@@ -1076,7 +1091,7 @@
   const std::string& reserved_name(int index) const;
 
   // Returns true if the field name is reserved.
-  bool IsReservedName(const std::string& name) const;
+  bool IsReservedName(ConstStringParam name) const;
 
   // Source Location ---------------------------------------------------
 
@@ -1223,6 +1238,7 @@
   friend class EnumDescriptor;
   friend class DescriptorPool;
   friend class FileDescriptorTables;
+  friend class Reflection;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor);
 };
 
@@ -1255,7 +1271,7 @@
   const MethodDescriptor* method(int index) const;
 
   // Look up a MethodDescriptor by name.
-  const MethodDescriptor* FindMethodByName(const std::string& name) const;
+  const MethodDescriptor* FindMethodByName(ConstStringParam name) const;
   // See Descriptor::CopyTo().
   void CopyTo(ServiceDescriptorProto* proto) const;
 
@@ -1475,26 +1491,27 @@
   Syntax syntax() const;
   static const char* SyntaxName(Syntax syntax);
 
-  // Find a top-level message type by name.  Returns nullptr if not found.
-  const Descriptor* FindMessageTypeByName(const std::string& name) const;
+  // Find a top-level message type by name (not full_name).  Returns nullptr if
+  // not found.
+  const Descriptor* FindMessageTypeByName(ConstStringParam name) const;
   // Find a top-level enum type by name.  Returns nullptr if not found.
-  const EnumDescriptor* FindEnumTypeByName(const std::string& name) const;
+  const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const;
   // Find an enum value defined in any top-level enum by name.  Returns nullptr
   // if not found.
-  const EnumValueDescriptor* FindEnumValueByName(const std::string& name) const;
+  const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const;
   // Find a service definition by name.  Returns nullptr if not found.
-  const ServiceDescriptor* FindServiceByName(const std::string& name) const;
+  const ServiceDescriptor* FindServiceByName(ConstStringParam name) const;
   // Find a top-level extension definition by name.  Returns nullptr if not
   // found.
-  const FieldDescriptor* FindExtensionByName(const std::string& name) const;
+  const FieldDescriptor* FindExtensionByName(ConstStringParam name) const;
   // Similar to FindExtensionByName(), but searches by lowercased-name.  See
   // Descriptor::FindFieldByLowercaseName().
   const FieldDescriptor* FindExtensionByLowercaseName(
-      const std::string& name) const;
+      ConstStringParam name) const;
   // Similar to FindExtensionByName(), but searches by camelcased-name.  See
   // Descriptor::FindFieldByCamelcaseName().
   const FieldDescriptor* FindExtensionByCamelcaseName(
-      const std::string& name) const;
+      ConstStringParam name) const;
 
   // See Descriptor::CopyTo().
   // Notes:
@@ -1657,28 +1674,28 @@
 
   // Find a FileDescriptor in the pool by file name.  Returns nullptr if not
   // found.
-  const FileDescriptor* FindFileByName(const std::string& name) const;
+  const FileDescriptor* FindFileByName(ConstStringParam name) const;
 
   // Find the FileDescriptor in the pool which defines the given symbol.
   // If any of the Find*ByName() methods below would succeed, then this is
   // equivalent to calling that method and calling the result's file() method.
   // Otherwise this returns nullptr.
   const FileDescriptor* FindFileContainingSymbol(
-      const std::string& symbol_name) const;
+      ConstStringParam symbol_name) const;
 
   // Looking up descriptors ------------------------------------------
   // These find descriptors by fully-qualified name.  These will find both
   // top-level descriptors and nested descriptors.  They return nullptr if not
   // found.
 
-  const Descriptor* FindMessageTypeByName(const std::string& name) const;
-  const FieldDescriptor* FindFieldByName(const std::string& name) const;
-  const FieldDescriptor* FindExtensionByName(const std::string& name) const;
-  const OneofDescriptor* FindOneofByName(const std::string& name) const;
-  const EnumDescriptor* FindEnumTypeByName(const std::string& name) const;
-  const EnumValueDescriptor* FindEnumValueByName(const std::string& name) const;
-  const ServiceDescriptor* FindServiceByName(const std::string& name) const;
-  const MethodDescriptor* FindMethodByName(const std::string& name) const;
+  const Descriptor* FindMessageTypeByName(ConstStringParam name) const;
+  const FieldDescriptor* FindFieldByName(ConstStringParam name) const;
+  const FieldDescriptor* FindExtensionByName(ConstStringParam name) const;
+  const OneofDescriptor* FindOneofByName(ConstStringParam name) const;
+  const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const;
+  const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const;
+  const ServiceDescriptor* FindServiceByName(ConstStringParam name) const;
+  const MethodDescriptor* FindMethodByName(ConstStringParam name) const;
 
   // Finds an extension of the given type by number.  The extendee must be
   // a member of this DescriptorPool or one of its underlays.
@@ -1691,7 +1708,7 @@
   // or one of its underlays.  Returns nullptr if there is no known message
   // extension with the given printable name.
   const FieldDescriptor* FindExtensionByPrintableName(
-      const Descriptor* extendee, const std::string& printable_name) const;
+      const Descriptor* extendee, ConstStringParam printable_name) const;
 
   // Finds extensions of extendee. The extensions will be appended to
   // out in an undefined order. Only extensions defined directly in
@@ -1831,6 +1848,11 @@
   // the underlay takes precedence.
   static DescriptorPool* internal_generated_pool();
 
+  // For internal use only:  Gets a non-const pointer to the generated
+  // descriptor database.
+  // Only used for testing.
+  static DescriptorDatabase* internal_generated_database();
+
   // For internal use only:  Changes the behavior of BuildFile() such that it
   // allows the file to make reference to message types declared in other files
   // which it did not officially declare as dependencies.
@@ -1840,7 +1862,7 @@
   // Delay the building of dependencies of a file descriptor until absolutely
   // necessary, like when message_type() is called on a field that is defined
   // in that dependency's file. This will cause functional issues if a proto
-  // or one of it's dependencies has errors. Should only be enabled for the
+  // or one of its dependencies has errors. Should only be enabled for the
   // generated_pool_ (because no descriptor build errors are guaranteed by
   // the compilation generation process), testing, or if a lack of descriptor
   // build errors can be guaranteed for a pool.
@@ -1859,11 +1881,11 @@
   // For internal (unit test) use only:  Returns true if a FileDescriptor has
   // been constructed for the given file, false otherwise.  Useful for testing
   // lazy descriptor initialization behavior.
-  bool InternalIsFileLoaded(const std::string& filename) const;
+  bool InternalIsFileLoaded(ConstStringParam filename) const;
 
   // Add a file to unused_import_track_files_. DescriptorBuilder will log
   // warnings or errors for those files if there is any unused import.
-  void AddUnusedImportTrackFile(const std::string& file_name,
+  void AddUnusedImportTrackFile(ConstStringParam file_name,
                                 bool is_error = false);
   void ClearUnusedImportTrackFiles();
 
@@ -1882,14 +1904,14 @@
   // Return true if the given name is a sub-symbol of any non-package
   // descriptor that already exists in the descriptor pool.  (The full
   // definition of such types is already known.)
-  bool IsSubSymbolOfBuiltType(const std::string& name) const;
+  bool IsSubSymbolOfBuiltType(StringPiece name) const;
 
   // Tries to find something in the fallback database and link in the
   // corresponding proto file.  Returns true if successful, in which case
   // the caller should search for the thing again.  These are declared
   // const because they are called by (semantically) const methods.
-  bool TryFindFileInFallbackDatabase(const std::string& name) const;
-  bool TryFindSymbolInFallbackDatabase(const std::string& name) const;
+  bool TryFindFileInFallbackDatabase(StringPiece name) const;
+  bool TryFindSymbolInFallbackDatabase(StringPiece name) const;
   bool TryFindExtensionInFallbackDatabase(const Descriptor* containing_type,
                                           int field_number) const;
 
@@ -1910,13 +1932,12 @@
   // symbol is defined if necessary. Will create a placeholder if the type
   // doesn't exist in the fallback database, or the file doesn't build
   // successfully.
-  Symbol CrossLinkOnDemandHelper(const std::string& name,
+  Symbol CrossLinkOnDemandHelper(StringPiece name,
                                  bool expecting_enum) const;
 
   // Create a placeholder FileDescriptor of the specified name
-  FileDescriptor* NewPlaceholderFile(const std::string& name) const;
-  FileDescriptor* NewPlaceholderFileWithMutexHeld(
-      const std::string& name) const;
+  FileDescriptor* NewPlaceholderFile(StringPiece name) const;
+  FileDescriptor* NewPlaceholderFileWithMutexHeld(StringPiece name) const;
 
   enum PlaceholderType {
     PLACEHOLDER_MESSAGE,
@@ -1924,9 +1945,9 @@
     PLACEHOLDER_EXTENDABLE_MESSAGE
   };
   // Create a placeholder Descriptor of the specified name
-  Symbol NewPlaceholder(const std::string& name,
+  Symbol NewPlaceholder(StringPiece name,
                         PlaceholderType placeholder_type) const;
-  Symbol NewPlaceholderWithMutexHeld(const std::string& name,
+  Symbol NewPlaceholderWithMutexHeld(StringPiece name,
                                      PlaceholderType placeholder_type) const;
 
   // If fallback_database_ is nullptr, this is nullptr.  Otherwise, this is a
@@ -2109,9 +2130,9 @@
   return FindReservedRangeContainingNumber(number) != nullptr;
 }
 
-inline bool Descriptor::IsReservedName(const std::string& name) const {
+inline bool Descriptor::IsReservedName(ConstStringParam name) const {
   for (int i = 0; i < reserved_name_count(); i++) {
-    if (name == reserved_name(i)) {
+    if (name == static_cast<ConstStringParam>(reserved_name(i))) {
       return true;
     }
   }
@@ -2128,9 +2149,9 @@
   return FindReservedRangeContainingNumber(number) != nullptr;
 }
 
-inline bool EnumDescriptor::IsReservedName(const std::string& name) const {
+inline bool EnumDescriptor::IsReservedName(ConstStringParam name) const {
   for (int i = 0; i < reserved_name_count(); i++) {
-    if (name == reserved_name(i)) {
+    if (name == static_cast<ConstStringParam>(reserved_name(i))) {
       return true;
     }
   }
@@ -2182,10 +2203,9 @@
              : nullptr;
 }
 
-inline bool FieldDescriptor::is_singular_with_presence() const {
+inline bool FieldDescriptor::has_presence() const {
   if (is_repeated()) return false;
-  if (real_containing_oneof()) return false;
-  return cpp_type() == CPPTYPE_MESSAGE || proto3_optional_ ||
+  return cpp_type() == CPPTYPE_MESSAGE || containing_oneof() ||
          file()->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }
 
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 471351c..86df896 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -14,554 +14,441 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto;
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class FileDescriptorSetDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FileDescriptorSet> _instance;
-} _FileDescriptorSet_default_instance_;
-class FileDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FileDescriptorProto> _instance;
-} _FileDescriptorProto_default_instance_;
-class DescriptorProto_ExtensionRangeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DescriptorProto_ExtensionRange> _instance;
-} _DescriptorProto_ExtensionRange_default_instance_;
-class DescriptorProto_ReservedRangeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DescriptorProto_ReservedRange> _instance;
-} _DescriptorProto_ReservedRange_default_instance_;
-class DescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DescriptorProto> _instance;
-} _DescriptorProto_default_instance_;
-class ExtensionRangeOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ExtensionRangeOptions> _instance;
-} _ExtensionRangeOptions_default_instance_;
-class FieldDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FieldDescriptorProto> _instance;
-} _FieldDescriptorProto_default_instance_;
-class OneofDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<OneofDescriptorProto> _instance;
-} _OneofDescriptorProto_default_instance_;
-class EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumDescriptorProto_EnumReservedRange> _instance;
-} _EnumDescriptorProto_EnumReservedRange_default_instance_;
-class EnumDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumDescriptorProto> _instance;
-} _EnumDescriptorProto_default_instance_;
-class EnumValueDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumValueDescriptorProto> _instance;
-} _EnumValueDescriptorProto_default_instance_;
-class ServiceDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ServiceDescriptorProto> _instance;
-} _ServiceDescriptorProto_default_instance_;
-class MethodDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<MethodDescriptorProto> _instance;
-} _MethodDescriptorProto_default_instance_;
-class FileOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FileOptions> _instance;
-} _FileOptions_default_instance_;
-class MessageOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<MessageOptions> _instance;
-} _MessageOptions_default_instance_;
-class FieldOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FieldOptions> _instance;
-} _FieldOptions_default_instance_;
-class OneofOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<OneofOptions> _instance;
-} _OneofOptions_default_instance_;
-class EnumOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumOptions> _instance;
-} _EnumOptions_default_instance_;
-class EnumValueOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumValueOptions> _instance;
-} _EnumValueOptions_default_instance_;
-class ServiceOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ServiceOptions> _instance;
-} _ServiceOptions_default_instance_;
-class MethodOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<MethodOptions> _instance;
-} _MethodOptions_default_instance_;
-class UninterpretedOption_NamePartDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UninterpretedOption_NamePart> _instance;
-} _UninterpretedOption_NamePart_default_instance_;
-class UninterpretedOptionDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UninterpretedOption> _instance;
-} _UninterpretedOption_default_instance_;
-class SourceCodeInfo_LocationDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<SourceCodeInfo_Location> _instance;
-} _SourceCodeInfo_Location_default_instance_;
-class SourceCodeInfoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<SourceCodeInfo> _instance;
-} _SourceCodeInfo_default_instance_;
-class GeneratedCodeInfo_AnnotationDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<GeneratedCodeInfo_Annotation> _instance;
-} _GeneratedCodeInfo_Annotation_default_instance_;
-class GeneratedCodeInfoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<GeneratedCodeInfo> _instance;
-} _GeneratedCodeInfo_default_instance_;
+constexpr FileDescriptorSet::FileDescriptorSet(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_(){}
+struct FileDescriptorSetDefaultTypeInternal {
+  constexpr FileDescriptorSetDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FileDescriptorSetDefaultTypeInternal() {}
+  union {
+    FileDescriptorSet _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
+constexpr FileDescriptorProto::FileDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : dependency_()
+  , message_type_()
+  , enum_type_()
+  , service_()
+  , extension_()
+  , public_dependency_()
+  , weak_dependency_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , syntax_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , source_code_info_(nullptr){}
+struct FileDescriptorProtoDefaultTypeInternal {
+  constexpr FileDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FileDescriptorProtoDefaultTypeInternal() {}
+  union {
+    FileDescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
+constexpr DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_(nullptr)
+  , start_(0)
+  , end_(0){}
+struct DescriptorProto_ExtensionRangeDefaultTypeInternal {
+  constexpr DescriptorProto_ExtensionRangeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DescriptorProto_ExtensionRangeDefaultTypeInternal() {}
+  union {
+    DescriptorProto_ExtensionRange _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
+constexpr DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : start_(0)
+  , end_(0){}
+struct DescriptorProto_ReservedRangeDefaultTypeInternal {
+  constexpr DescriptorProto_ReservedRangeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DescriptorProto_ReservedRangeDefaultTypeInternal() {}
+  union {
+    DescriptorProto_ReservedRange _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
+constexpr DescriptorProto::DescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : field_()
+  , nested_type_()
+  , enum_type_()
+  , extension_range_()
+  , extension_()
+  , oneof_decl_()
+  , reserved_range_()
+  , reserved_name_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct DescriptorProtoDefaultTypeInternal {
+  constexpr DescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DescriptorProtoDefaultTypeInternal() {}
+  union {
+    DescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
+constexpr ExtensionRangeOptions::ExtensionRangeOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_(){}
+struct ExtensionRangeOptionsDefaultTypeInternal {
+  constexpr ExtensionRangeOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ExtensionRangeOptionsDefaultTypeInternal() {}
+  union {
+    ExtensionRangeOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
+constexpr FieldDescriptorProto::FieldDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , extendee_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , type_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , default_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , json_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , number_(0)
+  , oneof_index_(0)
+  , proto3_optional_(false)
+  , label_(1)
+
+  , type_(1)
+{}
+struct FieldDescriptorProtoDefaultTypeInternal {
+  constexpr FieldDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldDescriptorProtoDefaultTypeInternal() {}
+  union {
+    FieldDescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
+constexpr OneofDescriptorProto::OneofDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct OneofDescriptorProtoDefaultTypeInternal {
+  constexpr OneofDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~OneofDescriptorProtoDefaultTypeInternal() {}
+  union {
+    OneofDescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
+constexpr EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : start_(0)
+  , end_(0){}
+struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal {
+  constexpr EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() {}
+  union {
+    EnumDescriptorProto_EnumReservedRange _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_;
+constexpr EnumDescriptorProto::EnumDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_()
+  , reserved_range_()
+  , reserved_name_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct EnumDescriptorProtoDefaultTypeInternal {
+  constexpr EnumDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumDescriptorProtoDefaultTypeInternal() {}
+  union {
+    EnumDescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
+constexpr EnumValueDescriptorProto::EnumValueDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , number_(0){}
+struct EnumValueDescriptorProtoDefaultTypeInternal {
+  constexpr EnumValueDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumValueDescriptorProtoDefaultTypeInternal() {}
+  union {
+    EnumValueDescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
+constexpr ServiceDescriptorProto::ServiceDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : method_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct ServiceDescriptorProtoDefaultTypeInternal {
+  constexpr ServiceDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ServiceDescriptorProtoDefaultTypeInternal() {}
+  union {
+    ServiceDescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
+constexpr MethodDescriptorProto::MethodDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , input_type_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , output_type_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , client_streaming_(false)
+  , server_streaming_(false){}
+struct MethodDescriptorProtoDefaultTypeInternal {
+  constexpr MethodDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MethodDescriptorProtoDefaultTypeInternal() {}
+  union {
+    MethodDescriptorProto _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
+constexpr FileOptions::FileOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , java_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , java_outer_classname_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , go_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , objc_class_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , csharp_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , swift_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , php_class_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , php_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , php_metadata_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , ruby_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , java_multiple_files_(false)
+  , java_generate_equals_and_hash_(false)
+  , java_string_check_utf8_(false)
+  , cc_generic_services_(false)
+  , java_generic_services_(false)
+  , py_generic_services_(false)
+  , php_generic_services_(false)
+  , deprecated_(false)
+  , optimize_for_(1)
+
+  , cc_enable_arenas_(true){}
+struct FileOptionsDefaultTypeInternal {
+  constexpr FileOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FileOptionsDefaultTypeInternal() {}
+  union {
+    FileOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
+constexpr MessageOptions::MessageOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , message_set_wire_format_(false)
+  , no_standard_descriptor_accessor_(false)
+  , deprecated_(false)
+  , map_entry_(false){}
+struct MessageOptionsDefaultTypeInternal {
+  constexpr MessageOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MessageOptionsDefaultTypeInternal() {}
+  union {
+    MessageOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
+constexpr FieldOptions::FieldOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , ctype_(0)
+
+  , packed_(false)
+  , lazy_(false)
+  , deprecated_(false)
+  , weak_(false)
+  , jstype_(0)
+{}
+struct FieldOptionsDefaultTypeInternal {
+  constexpr FieldOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldOptionsDefaultTypeInternal() {}
+  union {
+    FieldOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
+constexpr OneofOptions::OneofOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_(){}
+struct OneofOptionsDefaultTypeInternal {
+  constexpr OneofOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~OneofOptionsDefaultTypeInternal() {}
+  union {
+    OneofOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
+constexpr EnumOptions::EnumOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , allow_alias_(false)
+  , deprecated_(false){}
+struct EnumOptionsDefaultTypeInternal {
+  constexpr EnumOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumOptionsDefaultTypeInternal() {}
+  union {
+    EnumOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
+constexpr EnumValueOptions::EnumValueOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , deprecated_(false){}
+struct EnumValueOptionsDefaultTypeInternal {
+  constexpr EnumValueOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumValueOptionsDefaultTypeInternal() {}
+  union {
+    EnumValueOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
+constexpr ServiceOptions::ServiceOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , deprecated_(false){}
+struct ServiceOptionsDefaultTypeInternal {
+  constexpr ServiceOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ServiceOptionsDefaultTypeInternal() {}
+  union {
+    ServiceOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
+constexpr MethodOptions::MethodOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , deprecated_(false)
+  , idempotency_level_(0)
+{}
+struct MethodOptionsDefaultTypeInternal {
+  constexpr MethodOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MethodOptionsDefaultTypeInternal() {}
+  union {
+    MethodOptions _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
+constexpr UninterpretedOption_NamePart::UninterpretedOption_NamePart(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_part_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , is_extension_(false){}
+struct UninterpretedOption_NamePartDefaultTypeInternal {
+  constexpr UninterpretedOption_NamePartDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UninterpretedOption_NamePartDefaultTypeInternal() {}
+  union {
+    UninterpretedOption_NamePart _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
+constexpr UninterpretedOption::UninterpretedOption(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_()
+  , identifier_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , string_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , aggregate_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , positive_int_value_(uint64_t{0u})
+  , negative_int_value_(int64_t{0})
+  , double_value_(0){}
+struct UninterpretedOptionDefaultTypeInternal {
+  constexpr UninterpretedOptionDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UninterpretedOptionDefaultTypeInternal() {}
+  union {
+    UninterpretedOption _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
+constexpr SourceCodeInfo_Location::SourceCodeInfo_Location(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : path_()
+  , _path_cached_byte_size_(0)
+  , span_()
+  , _span_cached_byte_size_(0)
+  , leading_detached_comments_()
+  , leading_comments_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , trailing_comments_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct SourceCodeInfo_LocationDefaultTypeInternal {
+  constexpr SourceCodeInfo_LocationDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~SourceCodeInfo_LocationDefaultTypeInternal() {}
+  union {
+    SourceCodeInfo_Location _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
+constexpr SourceCodeInfo::SourceCodeInfo(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : location_(){}
+struct SourceCodeInfoDefaultTypeInternal {
+  constexpr SourceCodeInfoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~SourceCodeInfoDefaultTypeInternal() {}
+  union {
+    SourceCodeInfo _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
+constexpr GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : path_()
+  , _path_cached_byte_size_(0)
+  , source_file_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , begin_(0)
+  , end_(0){}
+struct GeneratedCodeInfo_AnnotationDefaultTypeInternal {
+  constexpr GeneratedCodeInfo_AnnotationDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~GeneratedCodeInfo_AnnotationDefaultTypeInternal() {}
+  union {
+    GeneratedCodeInfo_Annotation _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
+constexpr GeneratedCodeInfo::GeneratedCodeInfo(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : annotation_(){}
+struct GeneratedCodeInfoDefaultTypeInternal {
+  constexpr GeneratedCodeInfoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~GeneratedCodeInfoDefaultTypeInternal() {}
+  union {
+    GeneratedCodeInfo _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::DescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 6, 0, InitDefaultsscc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DescriptorProto_ReservedRange_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::EnumDescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 3, 0, InitDefaultsscc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_EnumReservedRange_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::EnumOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumValueOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::EnumValueOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FieldDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::FieldDescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FieldOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::FieldOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FileDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::FileDescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 6, 0, InitDefaultsscc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FileDescriptorSet_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FileDescriptorSet();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::FileDescriptorSet::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FileOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::FileOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_Annotation_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::MessageOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::MessageOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::MethodDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::MethodDescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::MethodOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::MethodOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::OneofDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::OneofDescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::OneofOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::OneofOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ServiceOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::ServiceOptions::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::SourceCodeInfo();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::SourceCodeInfo::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_Location_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UninterpretedOption_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UninterpretedOption();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::UninterpretedOption::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UninterpretedOption_NamePart_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[27];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[6];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr;
@@ -1103,106 +990,78 @@
   "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
   "tion\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_"
   "SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002J\004\010&\020"
-  "\'\"\362\001\n\016MessageOptions\022&\n\027message_set_wire"
+  "\'\"\204\002\n\016MessageOptions\022&\n\027message_set_wire"
   "_format\030\001 \001(\010:\005false\022.\n\037no_standard_desc"
   "riptor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecat"
   "ed\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024un"
   "interpreted_option\030\347\007 \003(\0132$.google.proto"
-  "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\010\020\t"
-  "J\004\010\t\020\n\"\236\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#"
-  ".google.protobuf.FieldOptions.CType:\006STR"
-  "ING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.go"
-  "ogle.protobuf.FieldOptions.JSType:\tJS_NO"
-  "RMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030"
-  "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni"
-  "nterpreted_option\030\347\007 \003(\0132$.google.protob"
-  "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN"
-  "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JSTyp"
-  "e\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NU"
-  "MBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005\"^\n\014OneofOptions\022"
-  "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
-  "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
-  "\223\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\n"
-  "deprecated\030\003 \001(\010:\005false\022C\n\024uninterpreted"
-  "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
-  "pretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"}\n\020EnumVal"
-  "ueOptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024"
-  "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
-  "tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016"
-  "ServiceOptions\022\031\n\ndeprecated\030! \001(\010:\005fals"
+  "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005"
+  "J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020\n\"\236\003\n\014FieldOption"
+  "s\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Field"
+  "Options.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n"
+  "\006jstype\030\006 \001(\0162$.google.protobuf.FieldOpt"
+  "ions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005fa"
+  "lse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n"
+  " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
+  "(\0132$.google.protobuf.UninterpretedOption"
+  "\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRIN"
+  "G_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS"
+  "_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020"
+  "\005\"^\n\014OneofOptions\022C\n\024uninterpreted_optio"
+  "n\030\347\007 \003(\0132$.google.protobuf.Uninterpreted"
+  "Option*\t\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptions\022\023\n\013all"
+  "ow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fals"
   "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl"
   "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200"
-  "\002\"\255\002\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:"
-  "\005false\022_\n\021idempotency_level\030\" \001(\0162/.goog"
-  "le.protobuf.MethodOptions.IdempotencyLev"
-  "el:\023IDEMPOTENCY_UNKNOWN\022C\n\024uninterpreted"
-  "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
-  "pretedOption\"P\n\020IdempotencyLevel\022\027\n\023IDEM"
-  "POTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_EFFECTS\020\001\022\016"
-  "\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterpre"
-  "tedOption\022;\n\004name\030\002 \003(\0132-.google.protobu"
-  "f.UninterpretedOption.NamePart\022\030\n\020identi"
-  "fier_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004"
-  " \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014doub"
-  "le_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017"
-  "aggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tnam"
-  "e_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016S"
-  "ourceCodeInfo\022:\n\010location\030\001 \003(\0132(.google"
-  ".protobuf.SourceCodeInfo.Location\032\206\001\n\010Lo"
-  "cation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002"
-  "\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trailing"
-  "_comments\030\004 \001(\t\022!\n\031leading_detached_comm"
-  "ents\030\006 \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nanno"
-  "tation\030\001 \003(\0132-.google.protobuf.Generated"
-  "CodeInfo.Annotation\032O\n\nAnnotation\022\020\n\004pat"
-  "h\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begi"
-  "n\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B\217\001\n\023com.google.prot"
-  "obufB\020DescriptorProtosH\001Z>github.com/gol"
-  "ang/protobuf/protoc-gen-go/descriptor;de"
-  "scriptor\370\001\001\242\002\003GPB\252\002\032Google.Protobuf.Refl"
+  "\002J\004\010\005\020\006\"}\n\020EnumValueOptions\022\031\n\ndeprecate"
+  "d\030\001 \001(\010:\005false\022C\n\024uninterpreted_option\030\347"
+  "\007 \003(\0132$.google.protobuf.UninterpretedOpt"
+  "ion*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndepr"
+  "ecated\030! \001(\010:\005false\022C\n\024uninterpreted_opt"
+  "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
+  "edOption*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodOptions\022\031\n"
+  "\ndeprecated\030! \001(\010:\005false\022_\n\021idempotency_"
+  "level\030\" \001(\0162/.google.protobuf.MethodOpti"
+  "ons.IdempotencyLevel:\023IDEMPOTENCY_UNKNOW"
+  "N\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl"
+  "e.protobuf.UninterpretedOption\"P\n\020Idempo"
+  "tencyLevel\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017N"
+  "O_SIDE_EFFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200"
+  "\200\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003("
+  "\0132-.google.protobuf.UninterpretedOption."
+  "NamePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022po"
+  "sitive_int_value\030\004 \001(\004\022\032\n\022negative_int_v"
+  "alue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014stri"
+  "ng_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\032"
+  "3\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_ext"
+  "ension\030\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010locat"
+  "ion\030\001 \003(\0132(.google.protobuf.SourceCodeIn"
+  "fo.Location\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002"
+  "\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments"
+  "\030\003 \001(\t\022\031\n\021trailing_comments\030\004 \001(\t\022!\n\031lea"
+  "ding_detached_comments\030\006 \003(\t\"\247\001\n\021Generat"
+  "edCodeInfo\022A\n\nannotation\030\001 \003(\0132-.google."
+  "protobuf.GeneratedCodeInfo.Annotation\032O\n"
+  "\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source_"
+  "file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B~"
+  "\n\023com.google.protobufB\020DescriptorProtosH"
+  "\001Z-google.golang.org/protobuf/types/desc"
+  "riptorpb\370\001\001\242\002\003GPB\252\002\032Google.Protobuf.Refl"
   "ection"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_sccs[27] = {
-  &scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", 6046,
-  &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_sccs, descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_deps, 27, 0,
+  false, false, 6046, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", 
+  &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, nullptr, 0, 27,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto, 27, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto, file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
+  file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto, file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fdescriptor_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fdescriptor_2eproto(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Type_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
@@ -1375,17 +1234,18 @@
 
 // ===================================================================
 
-void FileDescriptorSet::InitAsDefaultInstance() {
-}
 class FileDescriptorSet::_Internal {
  public:
 };
 
-FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   file_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorSet)
 }
 FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
@@ -1395,18 +1255,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet)
 }
 
-void FileDescriptorSet::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto.base);
+inline void FileDescriptorSet::SharedCtor() {
 }
 
 FileDescriptorSet::~FileDescriptorSet() {
   // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void FileDescriptorSet::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void FileDescriptorSet::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void FileDescriptorSet::ArenaDtor(void* object) {
@@ -1418,11 +1278,6 @@
 void FileDescriptorSet::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FileDescriptorSet& FileDescriptorSet::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FileDescriptorSet::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet)
@@ -1436,11 +1291,9 @@
 
 const char* FileDescriptorSet::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.FileDescriptorProto file = 1;
       case 1:
@@ -1456,7 +1309,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1522,36 +1376,27 @@
   return total_size;
 }
 
-void FileDescriptorSet::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorSet)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FileDescriptorSet* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<FileDescriptorSet>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorSet)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorSet)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FileDescriptorSet::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    FileDescriptorSet::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FileDescriptorSet::GetClassData() const { return &_class_data_; }
+
+void FileDescriptorSet::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<FileDescriptorSet *>(to)->MergeFrom(
+      static_cast<const FileDescriptorSet &>(from));
 }
 
+
 void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   file_.MergeFrom(from.file_);
-}
-
-void FileDescriptorSet::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorSet)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) {
@@ -1568,23 +1413,18 @@
 
 void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   file_.InternalSwap(&other->file_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorSet::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[0]);
 }
 
-
 // ===================================================================
 
-void FileDescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::FileOptions*>(
-      PROTOBUF_NAMESPACE_ID::FileOptions::internal_default_instance());
-  PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_._instance.get_mutable()->source_code_info_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceCodeInfo*>(
-      PROTOBUF_NAMESPACE_ID::SourceCodeInfo::internal_default_instance());
-}
 class FileDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<FileDescriptorProto>()._has_bits_);
@@ -1615,8 +1455,9 @@
 FileDescriptorProto::_Internal::source_code_info(const FileDescriptorProto* msg) {
   return *msg->source_code_info_;
 }
-FileDescriptorProto::FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+FileDescriptorProto::FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   dependency_(arena),
   message_type_(arena),
   enum_type_(arena),
@@ -1625,7 +1466,9 @@
   public_dependency_(arena),
   weak_dependency_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorProto)
 }
 FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
@@ -1641,18 +1484,18 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_package()) {
-    package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_package(),
-      GetArena());
+    package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_package(), 
+      GetArenaForAllocation());
   }
   syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_syntax()) {
-    syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_syntax(),
-      GetArena());
+    syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_syntax(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::FileOptions(*from.options_);
@@ -1667,24 +1510,25 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto)
 }
 
-void FileDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&source_code_info_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(source_code_info_));
+inline void FileDescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&source_code_info_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(source_code_info_));
 }
 
 FileDescriptorProto::~FileDescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void FileDescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void FileDescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   package_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   syntax_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
@@ -1701,11 +1545,6 @@
 void FileDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FileDescriptorProto& FileDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FileDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto)
@@ -1747,11 +1586,9 @@
 const char* FileDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -1896,7 +1733,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -2141,25 +1979,22 @@
   return total_size;
 }
 
-void FileDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FileDescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<FileDescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FileDescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    FileDescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FileDescriptorProto::GetClassData() const { return &_class_data_; }
+
+void FileDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<FileDescriptorProto *>(to)->MergeFrom(
+      static_cast<const FileDescriptorProto &>(from));
 }
 
+
 void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -2188,13 +2023,7 @@
       _internal_mutable_source_code_info()->PROTOBUF_NAMESPACE_ID::SourceCodeInfo::MergeFrom(from._internal_source_code_info());
     }
   }
-}
-
-void FileDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) {
@@ -2217,7 +2046,7 @@
 
 void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   dependency_.InternalSwap(&other->dependency_);
   message_type_.InternalSwap(&other->message_type_);
@@ -2226,9 +2055,21 @@
   extension_.InternalSwap(&other->extension_);
   public_dependency_.InternalSwap(&other->public_dependency_);
   weak_dependency_.InternalSwap(&other->weak_dependency_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  package_.Swap(&other->package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  syntax_.Swap(&other->syntax_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &package_, GetArenaForAllocation(),
+      &other->package_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &syntax_, GetArenaForAllocation(),
+      &other->syntax_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(FileDescriptorProto, source_code_info_)
       + sizeof(FileDescriptorProto::source_code_info_)
@@ -2238,16 +2079,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[1]);
 }
 
-
 // ===================================================================
 
-void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions*>(
-      PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions::internal_default_instance());
-}
 class DescriptorProto_ExtensionRange::_Internal {
  public:
   using HasBits = decltype(std::declval<DescriptorProto_ExtensionRange>()._has_bits_);
@@ -2267,10 +2105,13 @@
 DescriptorProto_ExtensionRange::_Internal::options(const DescriptorProto_ExtensionRange* msg) {
   return *msg->options_;
 }
-DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ExtensionRange)
 }
 DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from)
@@ -2288,21 +2129,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange)
 }
 
-void DescriptorProto_ExtensionRange::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(&options_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(end_));
+inline void DescriptorProto_ExtensionRange::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(end_));
 }
 
 DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() {
   // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void DescriptorProto_ExtensionRange::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void DescriptorProto_ExtensionRange::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   if (this != internal_default_instance()) delete options_;
 }
 
@@ -2315,11 +2157,6 @@
 void DescriptorProto_ExtensionRange::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DescriptorProto_ExtensionRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange)
@@ -2344,11 +2181,9 @@
 const char* DescriptorProto_ExtensionRange::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
@@ -2375,7 +2210,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -2472,25 +2308,22 @@
   return total_size;
 }
 
-void DescriptorProto_ExtensionRange::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
-  GOOGLE_DCHECK_NE(&from, this);
-  const DescriptorProto_ExtensionRange* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<DescriptorProto_ExtensionRange>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ExtensionRange)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ExtensionRange)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DescriptorProto_ExtensionRange::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    DescriptorProto_ExtensionRange::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DescriptorProto_ExtensionRange::GetClassData() const { return &_class_data_; }
+
+void DescriptorProto_ExtensionRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<DescriptorProto_ExtensionRange *>(to)->MergeFrom(
+      static_cast<const DescriptorProto_ExtensionRange &>(from));
 }
 
+
 void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -2507,13 +2340,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void DescriptorProto_ExtensionRange::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRange& from) {
@@ -2532,7 +2359,7 @@
 
 void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_)
@@ -2543,14 +2370,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ExtensionRange::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[2]);
 }
 
-
 // ===================================================================
 
-void DescriptorProto_ReservedRange::InitAsDefaultInstance() {
-}
 class DescriptorProto_ReservedRange::_Internal {
  public:
   using HasBits = decltype(std::declval<DescriptorProto_ReservedRange>()._has_bits_);
@@ -2562,10 +2388,13 @@
   }
 };
 
-DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ReservedRange)
 }
 DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from)
@@ -2578,20 +2407,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange)
 }
 
-void DescriptorProto_ReservedRange::SharedCtor() {
-  ::memset(&start_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&start_)) + sizeof(end_));
+inline void DescriptorProto_ReservedRange::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&start_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&start_)) + sizeof(end_));
 }
 
 DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() {
   // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void DescriptorProto_ReservedRange::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void DescriptorProto_ReservedRange::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void DescriptorProto_ReservedRange::ArenaDtor(void* object) {
@@ -2603,11 +2434,6 @@
 void DescriptorProto_ReservedRange::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DescriptorProto_ReservedRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange)
@@ -2628,11 +2454,9 @@
 const char* DescriptorProto_ReservedRange::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
@@ -2652,7 +2476,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -2734,25 +2559,22 @@
   return total_size;
 }
 
-void DescriptorProto_ReservedRange::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
-  GOOGLE_DCHECK_NE(&from, this);
-  const DescriptorProto_ReservedRange* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<DescriptorProto_ReservedRange>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ReservedRange)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ReservedRange)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DescriptorProto_ReservedRange::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    DescriptorProto_ReservedRange::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DescriptorProto_ReservedRange::GetClassData() const { return &_class_data_; }
+
+void DescriptorProto_ReservedRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<DescriptorProto_ReservedRange *>(to)->MergeFrom(
+      static_cast<const DescriptorProto_ReservedRange &>(from));
 }
 
+
 void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -2766,13 +2588,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void DescriptorProto_ReservedRange::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ReservedRange)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) {
@@ -2788,7 +2604,7 @@
 
 void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, end_)
@@ -2799,16 +2615,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ReservedRange::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[3]);
 }
 
-
 // ===================================================================
 
-void DescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::MessageOptions*>(
-      PROTOBUF_NAMESPACE_ID::MessageOptions::internal_default_instance());
-}
 class DescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<DescriptorProto>()._has_bits_);
@@ -2825,8 +2638,9 @@
 DescriptorProto::_Internal::options(const DescriptorProto* msg) {
   return *msg->options_;
 }
-DescriptorProto::DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+DescriptorProto::DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   field_(arena),
   nested_type_(arena),
   enum_type_(arena),
@@ -2836,7 +2650,9 @@
   reserved_range_(arena),
   reserved_name_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto)
 }
 DescriptorProto::DescriptorProto(const DescriptorProto& from)
@@ -2853,8 +2669,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::MessageOptions(*from.options_);
@@ -2864,20 +2680,20 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto)
 }
 
-void DescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+inline void DescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 DescriptorProto::~DescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void DescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void DescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete options_;
 }
@@ -2891,11 +2707,6 @@
 void DescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DescriptorProto& DescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto)
@@ -2928,11 +2739,9 @@
 const char* DescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -3054,7 +2863,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -3265,25 +3075,22 @@
   return total_size;
 }
 
-void DescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const DescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<DescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    DescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DescriptorProto::GetClassData() const { return &_class_data_; }
+
+void DescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<DescriptorProto *>(to)->MergeFrom(
+      static_cast<const DescriptorProto &>(from));
 }
 
+
 void DescriptorProto::MergeFrom(const DescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -3304,13 +3111,7 @@
       _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::MessageOptions::MergeFrom(from._internal_options());
     }
   }
-}
-
-void DescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void DescriptorProto::CopyFrom(const DescriptorProto& from) {
@@ -3335,7 +3136,7 @@
 
 void DescriptorProto::InternalSwap(DescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   field_.InternalSwap(&other->field_);
   nested_type_.InternalSwap(&other->nested_type_);
@@ -3345,29 +3146,35 @@
   oneof_decl_.InternalSwap(&other->oneof_decl_);
   reserved_range_.InternalSwap(&other->reserved_range_);
   reserved_name_.InternalSwap(&other->reserved_name_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   swap(options_, other->options_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[4]);
 }
 
-
 // ===================================================================
 
-void ExtensionRangeOptions::InitAsDefaultInstance() {
-}
 class ExtensionRangeOptions::_Internal {
  public:
 };
 
-ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.ExtensionRangeOptions)
 }
 ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from)
@@ -3378,18 +3185,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions)
 }
 
-void ExtensionRangeOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
+inline void ExtensionRangeOptions::SharedCtor() {
 }
 
 ExtensionRangeOptions::~ExtensionRangeOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.ExtensionRangeOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void ExtensionRangeOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void ExtensionRangeOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void ExtensionRangeOptions::ArenaDtor(void* object) {
@@ -3401,11 +3208,6 @@
 void ExtensionRangeOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ExtensionRangeOptions& ExtensionRangeOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ExtensionRangeOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions)
@@ -3420,11 +3222,9 @@
 
 const char* ExtensionRangeOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
@@ -3440,7 +3240,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -3518,37 +3319,28 @@
   return total_size;
 }
 
-void ExtensionRangeOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ExtensionRangeOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const ExtensionRangeOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<ExtensionRangeOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ExtensionRangeOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ExtensionRangeOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ExtensionRangeOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    ExtensionRangeOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ExtensionRangeOptions::GetClassData() const { return &_class_data_; }
+
+void ExtensionRangeOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<ExtensionRangeOptions *>(to)->MergeFrom(
+      static_cast<const ExtensionRangeOptions &>(from));
 }
 
+
 void ExtensionRangeOptions::MergeFrom(const ExtensionRangeOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ExtensionRangeOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
-}
-
-void ExtensionRangeOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ExtensionRangeOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void ExtensionRangeOptions::CopyFrom(const ExtensionRangeOptions& from) {
@@ -3569,22 +3361,19 @@
 
 void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ExtensionRangeOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[5]);
 }
 
-
 // ===================================================================
 
-void FieldDescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::FieldOptions*>(
-      PROTOBUF_NAMESPACE_ID::FieldOptions::internal_default_instance());
-}
 class FieldDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<FieldDescriptorProto>()._has_bits_);
@@ -3628,10 +3417,13 @@
 FieldDescriptorProto::_Internal::options(const FieldDescriptorProto* msg) {
   return *msg->options_;
 }
-FieldDescriptorProto::FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+FieldDescriptorProto::FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldDescriptorProto)
 }
 FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
@@ -3640,28 +3432,28 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_extendee()) {
-    extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_extendee(),
-      GetArena());
+    extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_extendee(), 
+      GetArenaForAllocation());
   }
   type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_type_name()) {
-    type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_type_name(),
-      GetArena());
+    type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_name(), 
+      GetArenaForAllocation());
   }
   default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_default_value()) {
-    default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_default_value(),
-      GetArena());
+    default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_default_value(), 
+      GetArenaForAllocation());
   }
   json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_json_name()) {
-    json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_json_name(),
-      GetArena());
+    json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_json_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::FieldOptions(*from.options_);
@@ -3674,28 +3466,29 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto)
 }
 
-void FieldDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&proto3_optional_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(proto3_optional_));
-  label_ = 1;
-  type_ = 1;
+inline void FieldDescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&proto3_optional_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(proto3_optional_));
+label_ = 1;
+type_ = 1;
 }
 
 FieldDescriptorProto::~FieldDescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.FieldDescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void FieldDescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void FieldDescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   extendee_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   type_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
@@ -3713,11 +3506,6 @@
 void FieldDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FieldDescriptorProto& FieldDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FieldDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto)
@@ -3764,11 +3552,9 @@
 const char* FieldDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -3882,7 +3668,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -4103,25 +3890,22 @@
   return total_size;
 }
 
-void FieldDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldDescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FieldDescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<FieldDescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldDescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldDescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FieldDescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    FieldDescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FieldDescriptorProto::GetClassData() const { return &_class_data_; }
+
+void FieldDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<FieldDescriptorProto *>(to)->MergeFrom(
+      static_cast<const FieldDescriptorProto &>(from));
 }
 
+
 void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -4165,13 +3949,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void FieldDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldDescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) {
@@ -4190,13 +3968,33 @@
 
 void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  extendee_.Swap(&other->extendee_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  type_name_.Swap(&other->type_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  default_value_.Swap(&other->default_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  json_name_.Swap(&other->json_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &extendee_, GetArenaForAllocation(),
+      &other->extendee_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &type_name_, GetArenaForAllocation(),
+      &other->type_name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &default_value_, GetArenaForAllocation(),
+      &other->default_value_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &json_name_, GetArenaForAllocation(),
+      &other->json_name_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, proto3_optional_)
       + sizeof(FieldDescriptorProto::proto3_optional_)
@@ -4208,16 +4006,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[6]);
 }
 
-
 // ===================================================================
 
-void OneofDescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::OneofOptions*>(
-      PROTOBUF_NAMESPACE_ID::OneofOptions::internal_default_instance());
-}
 class OneofDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<OneofDescriptorProto>()._has_bits_);
@@ -4234,10 +4029,13 @@
 OneofDescriptorProto::_Internal::options(const OneofDescriptorProto* msg) {
   return *msg->options_;
 }
-OneofDescriptorProto::OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+OneofDescriptorProto::OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofDescriptorProto)
 }
 OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from)
@@ -4246,8 +4044,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::OneofOptions(*from.options_);
@@ -4257,20 +4055,20 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto)
 }
 
-void OneofDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+inline void OneofDescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 OneofDescriptorProto::~OneofDescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.OneofDescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void OneofDescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void OneofDescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete options_;
 }
@@ -4284,11 +4082,6 @@
 void OneofDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const OneofDescriptorProto& OneofDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void OneofDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto)
@@ -4313,11 +4106,9 @@
 const char* OneofDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -4339,7 +4130,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -4427,25 +4219,22 @@
   return total_size;
 }
 
-void OneofDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofDescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const OneofDescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<OneofDescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.OneofDescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.OneofDescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData OneofDescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    OneofDescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*OneofDescriptorProto::GetClassData() const { return &_class_data_; }
+
+void OneofDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<OneofDescriptorProto *>(to)->MergeFrom(
+      static_cast<const OneofDescriptorProto &>(from));
 }
 
+
 void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -4458,13 +4247,7 @@
       _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::OneofOptions::MergeFrom(from._internal_options());
     }
   }
-}
-
-void OneofDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.OneofDescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) {
@@ -4483,21 +4266,24 @@
 
 void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   swap(options_, other->options_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata OneofDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[7]);
 }
 
-
 // ===================================================================
 
-void EnumDescriptorProto_EnumReservedRange::InitAsDefaultInstance() {
-}
 class EnumDescriptorProto_EnumReservedRange::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumDescriptorProto_EnumReservedRange>()._has_bits_);
@@ -4509,10 +4295,13 @@
   }
 };
 
-EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange)
 }
 EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from)
@@ -4525,20 +4314,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange)
 }
 
-void EnumDescriptorProto_EnumReservedRange::SharedCtor() {
-  ::memset(&start_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&start_)) + sizeof(end_));
+inline void EnumDescriptorProto_EnumReservedRange::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&start_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&start_)) + sizeof(end_));
 }
 
 EnumDescriptorProto_EnumReservedRange::~EnumDescriptorProto_EnumReservedRange() {
   // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto.EnumReservedRange)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void EnumDescriptorProto_EnumReservedRange::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void EnumDescriptorProto_EnumReservedRange::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void EnumDescriptorProto_EnumReservedRange::ArenaDtor(void* object) {
@@ -4550,11 +4341,6 @@
 void EnumDescriptorProto_EnumReservedRange::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumDescriptorProto_EnumReservedRange& EnumDescriptorProto_EnumReservedRange::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumDescriptorProto_EnumReservedRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
@@ -4575,11 +4361,9 @@
 const char* EnumDescriptorProto_EnumReservedRange::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
@@ -4599,7 +4383,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -4681,25 +4466,22 @@
   return total_size;
 }
 
-void EnumDescriptorProto_EnumReservedRange::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
-  GOOGLE_DCHECK_NE(&from, this);
-  const EnumDescriptorProto_EnumReservedRange* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<EnumDescriptorProto_EnumReservedRange>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumDescriptorProto.EnumReservedRange)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumDescriptorProto.EnumReservedRange)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumDescriptorProto_EnumReservedRange::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    EnumDescriptorProto_EnumReservedRange::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumDescriptorProto_EnumReservedRange::GetClassData() const { return &_class_data_; }
+
+void EnumDescriptorProto_EnumReservedRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<EnumDescriptorProto_EnumReservedRange *>(to)->MergeFrom(
+      static_cast<const EnumDescriptorProto_EnumReservedRange &>(from));
 }
 
+
 void EnumDescriptorProto_EnumReservedRange::MergeFrom(const EnumDescriptorProto_EnumReservedRange& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -4713,13 +4495,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void EnumDescriptorProto_EnumReservedRange::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void EnumDescriptorProto_EnumReservedRange::CopyFrom(const EnumDescriptorProto_EnumReservedRange& from) {
@@ -4735,7 +4511,7 @@
 
 void EnumDescriptorProto_EnumReservedRange::InternalSwap(EnumDescriptorProto_EnumReservedRange* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, end_)
@@ -4746,16 +4522,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto_EnumReservedRange::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[8]);
 }
 
-
 // ===================================================================
 
-void EnumDescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::EnumOptions*>(
-      PROTOBUF_NAMESPACE_ID::EnumOptions::internal_default_instance());
-}
 class EnumDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumDescriptorProto>()._has_bits_);
@@ -4772,13 +4545,16 @@
 EnumDescriptorProto::_Internal::options(const EnumDescriptorProto* msg) {
   return *msg->options_;
 }
-EnumDescriptorProto::EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+EnumDescriptorProto::EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   value_(arena),
   reserved_range_(arena),
   reserved_name_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto)
 }
 EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
@@ -4790,8 +4566,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::EnumOptions(*from.options_);
@@ -4801,20 +4577,20 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto)
 }
 
-void EnumDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+inline void EnumDescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 EnumDescriptorProto::~EnumDescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void EnumDescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void EnumDescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete options_;
 }
@@ -4828,11 +4604,6 @@
 void EnumDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumDescriptorProto& EnumDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto)
@@ -4860,11 +4631,9 @@
 const char* EnumDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -4926,7 +4695,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -5062,25 +4832,22 @@
   return total_size;
 }
 
-void EnumDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const EnumDescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<EnumDescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumDescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumDescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumDescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    EnumDescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumDescriptorProto::GetClassData() const { return &_class_data_; }
+
+void EnumDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<EnumDescriptorProto *>(to)->MergeFrom(
+      static_cast<const EnumDescriptorProto &>(from));
 }
 
+
 void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -5096,13 +4863,7 @@
       _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::EnumOptions::MergeFrom(from._internal_options());
     }
   }
-}
-
-void EnumDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumDescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) {
@@ -5122,26 +4883,27 @@
 
 void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   value_.InternalSwap(&other->value_);
   reserved_range_.InternalSwap(&other->reserved_range_);
   reserved_name_.InternalSwap(&other->reserved_name_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   swap(options_, other->options_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[9]);
 }
 
-
 // ===================================================================
 
-void EnumValueDescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::EnumValueOptions*>(
-      PROTOBUF_NAMESPACE_ID::EnumValueOptions::internal_default_instance());
-}
 class EnumValueDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumValueDescriptorProto>()._has_bits_);
@@ -5161,10 +4923,13 @@
 EnumValueDescriptorProto::_Internal::options(const EnumValueDescriptorProto* msg) {
   return *msg->options_;
 }
-EnumValueDescriptorProto::EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+EnumValueDescriptorProto::EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueDescriptorProto)
 }
 EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from)
@@ -5173,8 +4938,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::EnumValueOptions(*from.options_);
@@ -5185,22 +4950,23 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto)
 }
 
-void EnumValueDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&number_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(number_));
+inline void EnumValueDescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&number_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(number_));
 }
 
 EnumValueDescriptorProto::~EnumValueDescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.EnumValueDescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void EnumValueDescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void EnumValueDescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete options_;
 }
@@ -5214,11 +4980,6 @@
 void EnumValueDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumValueDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto)
@@ -5244,11 +5005,9 @@
 const char* EnumValueDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -5278,7 +5037,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -5379,25 +5139,22 @@
   return total_size;
 }
 
-void EnumValueDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueDescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const EnumValueDescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<EnumValueDescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueDescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueDescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumValueDescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    EnumValueDescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumValueDescriptorProto::GetClassData() const { return &_class_data_; }
+
+void EnumValueDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<EnumValueDescriptorProto *>(to)->MergeFrom(
+      static_cast<const EnumValueDescriptorProto &>(from));
 }
 
+
 void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -5414,13 +5171,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void EnumValueDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueDescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) {
@@ -5439,9 +5190,13 @@
 
 void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, number_)
       + sizeof(EnumValueDescriptorProto::number_)
@@ -5451,16 +5206,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValueDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[10]);
 }
 
-
 // ===================================================================
 
-void ServiceDescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::ServiceOptions*>(
-      PROTOBUF_NAMESPACE_ID::ServiceOptions::internal_default_instance());
-}
 class ServiceDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<ServiceDescriptorProto>()._has_bits_);
@@ -5477,11 +5229,14 @@
 ServiceDescriptorProto::_Internal::options(const ServiceDescriptorProto* msg) {
   return *msg->options_;
 }
-ServiceDescriptorProto::ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+ServiceDescriptorProto::ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   method_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceDescriptorProto)
 }
 ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from)
@@ -5491,8 +5246,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::ServiceOptions(*from.options_);
@@ -5502,20 +5257,20 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto)
 }
 
-void ServiceDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+inline void ServiceDescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 ServiceDescriptorProto::~ServiceDescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.ServiceDescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void ServiceDescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void ServiceDescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete options_;
 }
@@ -5529,11 +5284,6 @@
 void ServiceDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ServiceDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto)
@@ -5559,11 +5309,9 @@
 const char* ServiceDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -5597,7 +5345,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -5700,25 +5449,22 @@
   return total_size;
 }
 
-void ServiceDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceDescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const ServiceDescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<ServiceDescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceDescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceDescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ServiceDescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    ServiceDescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ServiceDescriptorProto::GetClassData() const { return &_class_data_; }
+
+void ServiceDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<ServiceDescriptorProto *>(to)->MergeFrom(
+      static_cast<const ServiceDescriptorProto &>(from));
 }
 
+
 void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -5732,13 +5478,7 @@
       _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::ServiceOptions::MergeFrom(from._internal_options());
     }
   }
-}
-
-void ServiceDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceDescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) {
@@ -5758,24 +5498,25 @@
 
 void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   method_.InternalSwap(&other->method_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   swap(options_, other->options_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ServiceDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[11]);
 }
 
-
 // ===================================================================
 
-void MethodDescriptorProto::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::MethodOptions*>(
-      PROTOBUF_NAMESPACE_ID::MethodOptions::internal_default_instance());
-}
 class MethodDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<MethodDescriptorProto>()._has_bits_);
@@ -5804,10 +5545,13 @@
 MethodDescriptorProto::_Internal::options(const MethodDescriptorProto* msg) {
   return *msg->options_;
 }
-MethodDescriptorProto::MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+MethodDescriptorProto::MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodDescriptorProto)
 }
 MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
@@ -5816,18 +5560,18 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_input_type()) {
-    input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_input_type(),
-      GetArena());
+    input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_input_type(), 
+      GetArenaForAllocation());
   }
   output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_output_type()) {
-    output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_output_type(),
-      GetArena());
+    output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_output_type(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_options()) {
     options_ = new PROTOBUF_NAMESPACE_ID::MethodOptions(*from.options_);
@@ -5840,24 +5584,25 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto)
 }
 
-void MethodDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&server_streaming_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(server_streaming_));
+inline void MethodDescriptorProto::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&server_streaming_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(server_streaming_));
 }
 
 MethodDescriptorProto::~MethodDescriptorProto() {
   // @@protoc_insertion_point(destructor:google.protobuf.MethodDescriptorProto)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void MethodDescriptorProto::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void MethodDescriptorProto::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   input_type_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   output_type_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
@@ -5873,11 +5618,6 @@
 void MethodDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const MethodDescriptorProto& MethodDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void MethodDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto)
@@ -5911,11 +5651,9 @@
 const char* MethodDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -5975,7 +5713,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -6119,25 +5858,22 @@
   return total_size;
 }
 
-void MethodDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodDescriptorProto)
-  GOOGLE_DCHECK_NE(&from, this);
-  const MethodDescriptorProto* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<MethodDescriptorProto>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodDescriptorProto)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodDescriptorProto)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData MethodDescriptorProto::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    MethodDescriptorProto::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*MethodDescriptorProto::GetClassData() const { return &_class_data_; }
+
+void MethodDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<MethodDescriptorProto *>(to)->MergeFrom(
+      static_cast<const MethodDescriptorProto &>(from));
 }
 
+
 void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -6163,13 +5899,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void MethodDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodDescriptorProto)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) {
@@ -6188,11 +5918,23 @@
 
 void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  input_type_.Swap(&other->input_type_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  output_type_.Swap(&other->output_type_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &input_type_, GetArenaForAllocation(),
+      &other->input_type_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &output_type_, GetArenaForAllocation(),
+      &other->output_type_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, server_streaming_)
       + sizeof(MethodDescriptorProto::server_streaming_)
@@ -6202,14 +5944,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MethodDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[12]);
 }
 
-
 // ===================================================================
 
-void FileOptions::InitAsDefaultInstance() {
-}
 class FileOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<FileOptions>()._has_bits_);
@@ -6275,12 +6016,15 @@
   }
 };
 
-FileOptions::FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+FileOptions::FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FileOptions)
 }
 FileOptions::FileOptions(const FileOptions& from)
@@ -6291,53 +6035,53 @@
   _extensions_.MergeFrom(from._extensions_);
   java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_java_package()) {
-    java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_java_package(),
-      GetArena());
+    java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_java_package(), 
+      GetArenaForAllocation());
   }
   java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_java_outer_classname()) {
-    java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_java_outer_classname(),
-      GetArena());
+    java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_java_outer_classname(), 
+      GetArenaForAllocation());
   }
   go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_go_package()) {
-    go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_go_package(),
-      GetArena());
+    go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_go_package(), 
+      GetArenaForAllocation());
   }
   objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_objc_class_prefix()) {
-    objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_objc_class_prefix(),
-      GetArena());
+    objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_objc_class_prefix(), 
+      GetArenaForAllocation());
   }
   csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_csharp_namespace()) {
-    csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_csharp_namespace(),
-      GetArena());
+    csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_csharp_namespace(), 
+      GetArenaForAllocation());
   }
   swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_swift_prefix()) {
-    swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_swift_prefix(),
-      GetArena());
+    swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_swift_prefix(), 
+      GetArenaForAllocation());
   }
   php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_php_class_prefix()) {
-    php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_php_class_prefix(),
-      GetArena());
+    php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_class_prefix(), 
+      GetArenaForAllocation());
   }
   php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_php_namespace()) {
-    php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_php_namespace(),
-      GetArena());
+    php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_namespace(), 
+      GetArenaForAllocation());
   }
   php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_php_metadata_namespace()) {
-    php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_php_metadata_namespace(),
-      GetArena());
+    php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_metadata_namespace(), 
+      GetArenaForAllocation());
   }
   ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_ruby_package()) {
-    ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_ruby_package(),
-      GetArena());
+    ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_ruby_package(), 
+      GetArenaForAllocation());
   }
   ::memcpy(&java_multiple_files_, &from.java_multiple_files_,
     static_cast<size_t>(reinterpret_cast<char*>(&cc_enable_arenas_) -
@@ -6345,33 +6089,34 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions)
 }
 
-void FileOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&java_multiple_files_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&deprecated_) -
-      reinterpret_cast<char*>(&java_multiple_files_)) + sizeof(deprecated_));
-  optimize_for_ = 1;
-  cc_enable_arenas_ = true;
+inline void FileOptions::SharedCtor() {
+java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&java_multiple_files_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
+    reinterpret_cast<char*>(&java_multiple_files_)) + sizeof(deprecated_));
+optimize_for_ = 1;
+cc_enable_arenas_ = true;
 }
 
 FileOptions::~FileOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.FileOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void FileOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void FileOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   java_package_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   java_outer_classname_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   go_package_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
@@ -6393,11 +6138,6 @@
 void FileOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FileOptions& FileOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FileOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions)
@@ -6461,11 +6201,9 @@
 const char* FileOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string java_package = 1;
       case 1:
@@ -6675,7 +6413,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -7044,26 +6783,22 @@
   return total_size;
 }
 
-void FileOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FileOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<FileOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FileOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    FileOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FileOptions::GetClassData() const { return &_class_data_; }
+
+void FileOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<FileOptions *>(to)->MergeFrom(
+      static_cast<const FileOptions &>(from));
 }
 
+
 void FileOptions::MergeFrom(const FileOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -7137,13 +6872,8 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void FileOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void FileOptions::CopyFrom(const FileOptions& from) {
@@ -7164,20 +6894,60 @@
 
 void FileOptions::InternalSwap(FileOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  java_package_.Swap(&other->java_package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  java_outer_classname_.Swap(&other->java_outer_classname_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  go_package_.Swap(&other->go_package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  objc_class_prefix_.Swap(&other->objc_class_prefix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  csharp_namespace_.Swap(&other->csharp_namespace_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  swift_prefix_.Swap(&other->swift_prefix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  php_class_prefix_.Swap(&other->php_class_prefix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  php_namespace_.Swap(&other->php_namespace_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  php_metadata_namespace_.Swap(&other->php_metadata_namespace_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  ruby_package_.Swap(&other->ruby_package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &java_package_, GetArenaForAllocation(),
+      &other->java_package_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &java_outer_classname_, GetArenaForAllocation(),
+      &other->java_outer_classname_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &go_package_, GetArenaForAllocation(),
+      &other->go_package_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &objc_class_prefix_, GetArenaForAllocation(),
+      &other->objc_class_prefix_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &csharp_namespace_, GetArenaForAllocation(),
+      &other->csharp_namespace_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &swift_prefix_, GetArenaForAllocation(),
+      &other->swift_prefix_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &php_class_prefix_, GetArenaForAllocation(),
+      &other->php_class_prefix_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &php_namespace_, GetArenaForAllocation(),
+      &other->php_namespace_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &php_metadata_namespace_, GetArenaForAllocation(),
+      &other->php_metadata_namespace_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &ruby_package_, GetArenaForAllocation(),
+      &other->ruby_package_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(FileOptions, deprecated_)
       + sizeof(FileOptions::deprecated_)
@@ -7189,14 +6959,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[13]);
 }
 
-
 // ===================================================================
 
-void MessageOptions::InitAsDefaultInstance() {
-}
 class MessageOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<MessageOptions>()._has_bits_);
@@ -7214,12 +6983,15 @@
   }
 };
 
-MessageOptions::MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+MessageOptions::MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.MessageOptions)
 }
 MessageOptions::MessageOptions(const MessageOptions& from)
@@ -7234,21 +7006,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions)
 }
 
-void MessageOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(&message_set_wire_format_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&map_entry_) -
-      reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
+inline void MessageOptions::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&message_set_wire_format_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&map_entry_) -
+    reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
 }
 
 MessageOptions::~MessageOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void MessageOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void MessageOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void MessageOptions::ArenaDtor(void* object) {
@@ -7260,11 +7033,6 @@
 void MessageOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const MessageOptions& MessageOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void MessageOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions)
@@ -7284,11 +7052,9 @@
 const char* MessageOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool message_set_wire_format = 1 [default = false];
       case 1:
@@ -7336,7 +7102,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -7463,26 +7230,22 @@
   return total_size;
 }
 
-void MessageOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MessageOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const MessageOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<MessageOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MessageOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MessageOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData MessageOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    MessageOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*MessageOptions::GetClassData() const { return &_class_data_; }
+
+void MessageOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<MessageOptions *>(to)->MergeFrom(
+      static_cast<const MessageOptions &>(from));
 }
 
+
 void MessageOptions::MergeFrom(const MessageOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -7503,13 +7266,8 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void MessageOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MessageOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void MessageOptions::CopyFrom(const MessageOptions& from) {
@@ -7530,8 +7288,8 @@
 
 void MessageOptions::InternalSwap(MessageOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -7543,14 +7301,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MessageOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[14]);
 }
 
-
 // ===================================================================
 
-void FieldOptions::InitAsDefaultInstance() {
-}
 class FieldOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<FieldOptions>()._has_bits_);
@@ -7574,12 +7331,15 @@
   }
 };
 
-FieldOptions::FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+FieldOptions::FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldOptions)
 }
 FieldOptions::FieldOptions(const FieldOptions& from)
@@ -7594,21 +7354,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions)
 }
 
-void FieldOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(&ctype_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&jstype_) -
-      reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
+inline void FieldOptions::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&ctype_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&jstype_) -
+    reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
 }
 
 FieldOptions::~FieldOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void FieldOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void FieldOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void FieldOptions::ArenaDtor(void* object) {
@@ -7620,11 +7381,6 @@
 void FieldOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FieldOptions& FieldOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FieldOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions)
@@ -7647,11 +7403,9 @@
 const char* FieldOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
       case 1:
@@ -7723,7 +7477,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -7876,26 +7631,22 @@
   return total_size;
 }
 
-void FieldOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FieldOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<FieldOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FieldOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    FieldOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FieldOptions::GetClassData() const { return &_class_data_; }
+
+void FieldOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<FieldOptions *>(to)->MergeFrom(
+      static_cast<const FieldOptions &>(from));
 }
 
+
 void FieldOptions::MergeFrom(const FieldOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -7922,13 +7673,8 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void FieldOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void FieldOptions::CopyFrom(const FieldOptions& from) {
@@ -7949,8 +7695,8 @@
 
 void FieldOptions::InternalSwap(FieldOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -7962,24 +7708,26 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[15]);
 }
 
-
 // ===================================================================
 
-void OneofOptions::InitAsDefaultInstance() {
-}
 class OneofOptions::_Internal {
  public:
 };
 
-OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofOptions)
 }
 OneofOptions::OneofOptions(const OneofOptions& from)
@@ -7990,18 +7738,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofOptions)
 }
 
-void OneofOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
+inline void OneofOptions::SharedCtor() {
 }
 
 OneofOptions::~OneofOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.OneofOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void OneofOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void OneofOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void OneofOptions::ArenaDtor(void* object) {
@@ -8013,11 +7761,6 @@
 void OneofOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const OneofOptions& OneofOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void OneofOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofOptions)
@@ -8032,11 +7775,9 @@
 
 const char* OneofOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
@@ -8052,7 +7793,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8130,37 +7872,28 @@
   return total_size;
 }
 
-void OneofOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const OneofOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<OneofOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.OneofOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.OneofOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData OneofOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    OneofOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*OneofOptions::GetClassData() const { return &_class_data_; }
+
+void OneofOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<OneofOptions *>(to)->MergeFrom(
+      static_cast<const OneofOptions &>(from));
 }
 
+
 void OneofOptions::MergeFrom(const OneofOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
-}
-
-void OneofOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.OneofOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void OneofOptions::CopyFrom(const OneofOptions& from) {
@@ -8181,20 +7914,19 @@
 
 void OneofOptions::InternalSwap(OneofOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata OneofOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[16]);
 }
 
-
 // ===================================================================
 
-void EnumOptions::InitAsDefaultInstance() {
-}
 class EnumOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumOptions>()._has_bits_);
@@ -8206,12 +7938,15 @@
   }
 };
 
-EnumOptions::EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+EnumOptions::EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumOptions)
 }
 EnumOptions::EnumOptions(const EnumOptions& from)
@@ -8226,21 +7961,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions)
 }
 
-void EnumOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(&allow_alias_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&deprecated_) -
-      reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
+inline void EnumOptions::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&allow_alias_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
+    reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
 }
 
 EnumOptions::~EnumOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void EnumOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void EnumOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void EnumOptions::ArenaDtor(void* object) {
@@ -8252,11 +7988,6 @@
 void EnumOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumOptions& EnumOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions)
@@ -8276,11 +8007,9 @@
 const char* EnumOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool allow_alias = 2;
       case 2:
@@ -8312,7 +8041,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8417,26 +8147,22 @@
   return total_size;
 }
 
-void EnumOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const EnumOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<EnumOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    EnumOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumOptions::GetClassData() const { return &_class_data_; }
+
+void EnumOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<EnumOptions *>(to)->MergeFrom(
+      static_cast<const EnumOptions &>(from));
 }
 
+
 void EnumOptions::MergeFrom(const EnumOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -8451,13 +8177,8 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void EnumOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void EnumOptions::CopyFrom(const EnumOptions& from) {
@@ -8478,8 +8199,8 @@
 
 void EnumOptions::InternalSwap(EnumOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -8491,14 +8212,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[17]);
 }
 
-
 // ===================================================================
 
-void EnumValueOptions::InitAsDefaultInstance() {
-}
 class EnumValueOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumValueOptions>()._has_bits_);
@@ -8507,12 +8227,15 @@
   }
 };
 
-EnumValueOptions::EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+EnumValueOptions::EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueOptions)
 }
 EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
@@ -8525,19 +8248,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions)
 }
 
-void EnumValueOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  deprecated_ = false;
+inline void EnumValueOptions::SharedCtor() {
+deprecated_ = false;
 }
 
 EnumValueOptions::~EnumValueOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.EnumValueOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void EnumValueOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void EnumValueOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void EnumValueOptions::ArenaDtor(void* object) {
@@ -8549,11 +8272,6 @@
 void EnumValueOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumValueOptions& EnumValueOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumValueOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions)
@@ -8571,11 +8289,9 @@
 const char* EnumValueOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 1 [default = false];
       case 1:
@@ -8599,7 +8315,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8691,26 +8408,22 @@
   return total_size;
 }
 
-void EnumValueOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const EnumValueOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<EnumValueOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumValueOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    EnumValueOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumValueOptions::GetClassData() const { return &_class_data_; }
+
+void EnumValueOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<EnumValueOptions *>(to)->MergeFrom(
+      static_cast<const EnumValueOptions &>(from));
 }
 
+
 void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -8718,13 +8431,8 @@
   if (from._internal_has_deprecated()) {
     _internal_set_deprecated(from._internal_deprecated());
   }
-}
-
-void EnumValueOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void EnumValueOptions::CopyFrom(const EnumValueOptions& from) {
@@ -8745,22 +8453,21 @@
 
 void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   swap(deprecated_, other->deprecated_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValueOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[18]);
 }
 
-
 // ===================================================================
 
-void ServiceOptions::InitAsDefaultInstance() {
-}
 class ServiceOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<ServiceOptions>()._has_bits_);
@@ -8769,12 +8476,15 @@
   }
 };
 
-ServiceOptions::ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+ServiceOptions::ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceOptions)
 }
 ServiceOptions::ServiceOptions(const ServiceOptions& from)
@@ -8787,19 +8497,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions)
 }
 
-void ServiceOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  deprecated_ = false;
+inline void ServiceOptions::SharedCtor() {
+deprecated_ = false;
 }
 
 ServiceOptions::~ServiceOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.ServiceOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void ServiceOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void ServiceOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void ServiceOptions::ArenaDtor(void* object) {
@@ -8811,11 +8521,6 @@
 void ServiceOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ServiceOptions& ServiceOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ServiceOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions)
@@ -8833,11 +8538,9 @@
 const char* ServiceOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33:
@@ -8861,7 +8564,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8953,26 +8657,22 @@
   return total_size;
 }
 
-void ServiceOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const ServiceOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<ServiceOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ServiceOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    ServiceOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ServiceOptions::GetClassData() const { return &_class_data_; }
+
+void ServiceOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<ServiceOptions *>(to)->MergeFrom(
+      static_cast<const ServiceOptions &>(from));
 }
 
+
 void ServiceOptions::MergeFrom(const ServiceOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -8980,13 +8680,8 @@
   if (from._internal_has_deprecated()) {
     _internal_set_deprecated(from._internal_deprecated());
   }
-}
-
-void ServiceOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void ServiceOptions::CopyFrom(const ServiceOptions& from) {
@@ -9007,22 +8702,21 @@
 
 void ServiceOptions::InternalSwap(ServiceOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   swap(deprecated_, other->deprecated_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ServiceOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[19]);
 }
 
-
 // ===================================================================
 
-void MethodOptions::InitAsDefaultInstance() {
-}
 class MethodOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<MethodOptions>()._has_bits_);
@@ -9034,12 +8728,15 @@
   }
 };
 
-MethodOptions::MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+MethodOptions::MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   _extensions_(arena),
   uninterpreted_option_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodOptions)
 }
 MethodOptions::MethodOptions(const MethodOptions& from)
@@ -9054,21 +8751,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions)
 }
 
-void MethodOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(&deprecated_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&idempotency_level_) -
-      reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
+inline void MethodOptions::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&deprecated_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&idempotency_level_) -
+    reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
 }
 
 MethodOptions::~MethodOptions() {
   // @@protoc_insertion_point(destructor:google.protobuf.MethodOptions)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void MethodOptions::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void MethodOptions::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void MethodOptions::ArenaDtor(void* object) {
@@ -9080,11 +8778,6 @@
 void MethodOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const MethodOptions& MethodOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void MethodOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions)
@@ -9107,11 +8800,9 @@
 const char* MethodOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33:
@@ -9147,7 +8838,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -9254,26 +8946,22 @@
   return total_size;
 }
 
-void MethodOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodOptions)
-  GOOGLE_DCHECK_NE(&from, this);
-  const MethodOptions* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<MethodOptions>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodOptions)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodOptions)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData MethodOptions::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    MethodOptions::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*MethodOptions::GetClassData() const { return &_class_data_; }
+
+void MethodOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<MethodOptions *>(to)->MergeFrom(
+      static_cast<const MethodOptions &>(from));
 }
 
+
 void MethodOptions::MergeFrom(const MethodOptions& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions)
   GOOGLE_DCHECK_NE(&from, this);
-  _extensions_.MergeFrom(from._extensions_);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -9288,13 +8976,8 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void MethodOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodOptions)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void MethodOptions::CopyFrom(const MethodOptions& from) {
@@ -9315,8 +8998,8 @@
 
 void MethodOptions::InternalSwap(MethodOptions* other) {
   using std::swap;
-  _extensions_.Swap(&other->_extensions_);
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _extensions_.InternalSwap(&other->_extensions_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
@@ -9328,14 +9011,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MethodOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[20]);
 }
 
-
 // ===================================================================
 
-void UninterpretedOption_NamePart::InitAsDefaultInstance() {
-}
 class UninterpretedOption_NamePart::_Internal {
  public:
   using HasBits = decltype(std::declval<UninterpretedOption_NamePart>()._has_bits_);
@@ -9350,10 +9032,13 @@
   }
 };
 
-UninterpretedOption_NamePart::UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+UninterpretedOption_NamePart::UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption.NamePart)
 }
 UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from)
@@ -9362,27 +9047,27 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_name_part()) {
-    name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name_part(),
-      GetArena());
+    name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name_part(), 
+      GetArenaForAllocation());
   }
   is_extension_ = from.is_extension_;
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart)
 }
 
-void UninterpretedOption_NamePart::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  is_extension_ = false;
+inline void UninterpretedOption_NamePart::SharedCtor() {
+name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+is_extension_ = false;
 }
 
 UninterpretedOption_NamePart::~UninterpretedOption_NamePart() {
   // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption.NamePart)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void UninterpretedOption_NamePart::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void UninterpretedOption_NamePart::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_part_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -9395,11 +9080,6 @@
 void UninterpretedOption_NamePart::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UninterpretedOption_NamePart::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart)
@@ -9419,11 +9099,9 @@
 const char* UninterpretedOption_NamePart::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // required string name_part = 1;
       case 1:
@@ -9446,7 +9124,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -9545,25 +9224,22 @@
   return total_size;
 }
 
-void UninterpretedOption_NamePart::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
-  GOOGLE_DCHECK_NE(&from, this);
-  const UninterpretedOption_NamePart* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<UninterpretedOption_NamePart>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption.NamePart)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption.NamePart)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UninterpretedOption_NamePart::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    UninterpretedOption_NamePart::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UninterpretedOption_NamePart::GetClassData() const { return &_class_data_; }
+
+void UninterpretedOption_NamePart::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<UninterpretedOption_NamePart *>(to)->MergeFrom(
+      static_cast<const UninterpretedOption_NamePart &>(from));
 }
 
+
 void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -9577,13 +9253,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void UninterpretedOption_NamePart::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption.NamePart)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& from) {
@@ -9600,21 +9270,24 @@
 
 void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
-  name_part_.Swap(&other->name_part_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_part_, GetArenaForAllocation(),
+      &other->name_part_, other->GetArenaForAllocation()
+  );
   swap(is_extension_, other->is_extension_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption_NamePart::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[21]);
 }
 
-
 // ===================================================================
 
-void UninterpretedOption::InitAsDefaultInstance() {
-}
 class UninterpretedOption::_Internal {
  public:
   using HasBits = decltype(std::declval<UninterpretedOption>()._has_bits_);
@@ -9638,11 +9311,14 @@
   }
 };
 
-UninterpretedOption::UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+UninterpretedOption::UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   name_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption)
 }
 UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
@@ -9652,18 +9328,18 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_identifier_value()) {
-    identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_identifier_value(),
-      GetArena());
+    identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_identifier_value(), 
+      GetArenaForAllocation());
   }
   string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_string_value()) {
-    string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_string_value(),
-      GetArena());
+    string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_string_value(), 
+      GetArenaForAllocation());
   }
   aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_aggregate_value()) {
-    aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_aggregate_value(),
-      GetArena());
+    aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_aggregate_value(), 
+      GetArenaForAllocation());
   }
   ::memcpy(&positive_int_value_, &from.positive_int_value_,
     static_cast<size_t>(reinterpret_cast<char*>(&double_value_) -
@@ -9671,24 +9347,25 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption)
 }
 
-void UninterpretedOption::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base);
-  identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&positive_int_value_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&double_value_) -
-      reinterpret_cast<char*>(&positive_int_value_)) + sizeof(double_value_));
+inline void UninterpretedOption::SharedCtor() {
+identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&positive_int_value_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&double_value_) -
+    reinterpret_cast<char*>(&positive_int_value_)) + sizeof(double_value_));
 }
 
 UninterpretedOption::~UninterpretedOption() {
   // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void UninterpretedOption::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void UninterpretedOption::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   identifier_value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   string_value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   aggregate_value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
@@ -9703,11 +9380,6 @@
 void UninterpretedOption::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UninterpretedOption& UninterpretedOption::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UninterpretedOption::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption)
@@ -9740,11 +9412,9 @@
 const char* UninterpretedOption::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
       case 2:
@@ -9814,7 +9484,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -9969,25 +9640,22 @@
   return total_size;
 }
 
-void UninterpretedOption::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption)
-  GOOGLE_DCHECK_NE(&from, this);
-  const UninterpretedOption* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<UninterpretedOption>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UninterpretedOption::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    UninterpretedOption::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UninterpretedOption::GetClassData() const { return &_class_data_; }
+
+void UninterpretedOption::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<UninterpretedOption *>(to)->MergeFrom(
+      static_cast<const UninterpretedOption &>(from));
 }
 
+
 void UninterpretedOption::MergeFrom(const UninterpretedOption& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -10014,13 +9682,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void UninterpretedOption::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void UninterpretedOption::CopyFrom(const UninterpretedOption& from) {
@@ -10037,12 +9699,24 @@
 
 void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   name_.InternalSwap(&other->name_);
-  identifier_value_.Swap(&other->identifier_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  string_value_.Swap(&other->string_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  aggregate_value_.Swap(&other->aggregate_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &identifier_value_, GetArenaForAllocation(),
+      &other->identifier_value_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &string_value_, GetArenaForAllocation(),
+      &other->string_value_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &aggregate_value_, GetArenaForAllocation(),
+      &other->aggregate_value_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(UninterpretedOption, double_value_)
       + sizeof(UninterpretedOption::double_value_)
@@ -10052,14 +9726,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[22]);
 }
 
-
 // ===================================================================
 
-void SourceCodeInfo_Location::InitAsDefaultInstance() {
-}
 class SourceCodeInfo_Location::_Internal {
  public:
   using HasBits = decltype(std::declval<SourceCodeInfo_Location>()._has_bits_);
@@ -10071,13 +9744,16 @@
   }
 };
 
-SourceCodeInfo_Location::SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+SourceCodeInfo_Location::SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   path_(arena),
   span_(arena),
   leading_detached_comments_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo.Location)
 }
 SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from)
@@ -10089,31 +9765,31 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_leading_comments()) {
-    leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_leading_comments(),
-      GetArena());
+    leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_leading_comments(), 
+      GetArenaForAllocation());
   }
   trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_trailing_comments()) {
-    trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_trailing_comments(),
-      GetArena());
+    trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_trailing_comments(), 
+      GetArenaForAllocation());
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location)
 }
 
-void SourceCodeInfo_Location::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base);
-  leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+inline void SourceCodeInfo_Location::SharedCtor() {
+leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 SourceCodeInfo_Location::~SourceCodeInfo_Location() {
   // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo.Location)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void SourceCodeInfo_Location::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void SourceCodeInfo_Location::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   leading_comments_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   trailing_comments_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
@@ -10127,11 +9803,6 @@
 void SourceCodeInfo_Location::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void SourceCodeInfo_Location::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location)
@@ -10158,11 +9829,9 @@
 const char* SourceCodeInfo_Location::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1:
@@ -10224,7 +9893,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -10380,25 +10050,22 @@
   return total_size;
 }
 
-void SourceCodeInfo_Location::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo.Location)
-  GOOGLE_DCHECK_NE(&from, this);
-  const SourceCodeInfo_Location* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<SourceCodeInfo_Location>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo.Location)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo.Location)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SourceCodeInfo_Location::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    SourceCodeInfo_Location::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SourceCodeInfo_Location::GetClassData() const { return &_class_data_; }
+
+void SourceCodeInfo_Location::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<SourceCodeInfo_Location *>(to)->MergeFrom(
+      static_cast<const SourceCodeInfo_Location &>(from));
 }
 
+
 void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -10414,13 +10081,7 @@
       _internal_set_trailing_comments(from._internal_trailing_comments());
     }
   }
-}
-
-void SourceCodeInfo_Location::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo.Location)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) {
@@ -10436,33 +10097,43 @@
 
 void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   path_.InternalSwap(&other->path_);
   span_.InternalSwap(&other->span_);
   leading_detached_comments_.InternalSwap(&other->leading_detached_comments_);
-  leading_comments_.Swap(&other->leading_comments_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  trailing_comments_.Swap(&other->trailing_comments_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &leading_comments_, GetArenaForAllocation(),
+      &other->leading_comments_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &trailing_comments_, GetArenaForAllocation(),
+      &other->trailing_comments_, other->GetArenaForAllocation()
+  );
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo_Location::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[23]);
 }
 
-
 // ===================================================================
 
-void SourceCodeInfo::InitAsDefaultInstance() {
-}
 class SourceCodeInfo::_Internal {
  public:
 };
 
-SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   location_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo)
 }
 SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
@@ -10472,18 +10143,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo)
 }
 
-void SourceCodeInfo::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
+inline void SourceCodeInfo::SharedCtor() {
 }
 
 SourceCodeInfo::~SourceCodeInfo() {
   // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void SourceCodeInfo::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void SourceCodeInfo::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void SourceCodeInfo::ArenaDtor(void* object) {
@@ -10495,11 +10166,6 @@
 void SourceCodeInfo::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const SourceCodeInfo& SourceCodeInfo::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void SourceCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo)
@@ -10513,11 +10179,9 @@
 
 const char* SourceCodeInfo::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
       case 1:
@@ -10533,7 +10197,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -10599,36 +10264,27 @@
   return total_size;
 }
 
-void SourceCodeInfo::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  const SourceCodeInfo* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<SourceCodeInfo>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SourceCodeInfo::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    SourceCodeInfo::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SourceCodeInfo::GetClassData() const { return &_class_data_; }
+
+void SourceCodeInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<SourceCodeInfo *>(to)->MergeFrom(
+      static_cast<const SourceCodeInfo &>(from));
 }
 
+
 void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   location_.MergeFrom(from.location_);
-}
-
-void SourceCodeInfo::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) {
@@ -10644,19 +10300,18 @@
 
 void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   location_.InternalSwap(&other->location_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[24]);
 }
 
-
 // ===================================================================
 
-void GeneratedCodeInfo_Annotation::InitAsDefaultInstance() {
-}
 class GeneratedCodeInfo_Annotation::_Internal {
  public:
   using HasBits = decltype(std::declval<GeneratedCodeInfo_Annotation>()._has_bits_);
@@ -10671,11 +10326,14 @@
   }
 };
 
-GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   path_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo.Annotation)
 }
 GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from)
@@ -10685,8 +10343,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (from._internal_has_source_file()) {
-    source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_source_file(),
-      GetArena());
+    source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_source_file(), 
+      GetArenaForAllocation());
   }
   ::memcpy(&begin_, &from.begin_,
     static_cast<size_t>(reinterpret_cast<char*>(&end_) -
@@ -10694,22 +10352,23 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo.Annotation)
 }
 
-void GeneratedCodeInfo_Annotation::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base);
-  source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&begin_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&begin_)) + sizeof(end_));
+inline void GeneratedCodeInfo_Annotation::SharedCtor() {
+source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&begin_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&begin_)) + sizeof(end_));
 }
 
 GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() {
   // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo.Annotation)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void GeneratedCodeInfo_Annotation::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void GeneratedCodeInfo_Annotation::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   source_file_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -10722,11 +10381,6 @@
 void GeneratedCodeInfo_Annotation::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const GeneratedCodeInfo_Annotation& GeneratedCodeInfo_Annotation::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void GeneratedCodeInfo_Annotation::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation)
@@ -10751,11 +10405,9 @@
 const char* GeneratedCodeInfo_Annotation::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1:
@@ -10796,7 +10448,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -10919,25 +10572,22 @@
   return total_size;
 }
 
-void GeneratedCodeInfo_Annotation::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
-  GOOGLE_DCHECK_NE(&from, this);
-  const GeneratedCodeInfo_Annotation* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<GeneratedCodeInfo_Annotation>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo.Annotation)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo.Annotation)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData GeneratedCodeInfo_Annotation::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    GeneratedCodeInfo_Annotation::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GeneratedCodeInfo_Annotation::GetClassData() const { return &_class_data_; }
+
+void GeneratedCodeInfo_Annotation::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<GeneratedCodeInfo_Annotation *>(to)->MergeFrom(
+      static_cast<const GeneratedCodeInfo_Annotation &>(from));
 }
 
+
 void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -10955,13 +10605,7 @@
     }
     _has_bits_[0] |= cached_has_bits;
   }
-}
-
-void GeneratedCodeInfo_Annotation::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void GeneratedCodeInfo_Annotation::CopyFrom(const GeneratedCodeInfo_Annotation& from) {
@@ -10977,10 +10621,14 @@
 
 void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(_has_bits_[0], other->_has_bits_[0]);
   path_.InternalSwap(&other->path_);
-  source_file_.Swap(&other->source_file_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &source_file_, GetArenaForAllocation(),
+      &other->source_file_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, end_)
       + sizeof(GeneratedCodeInfo_Annotation::end_)
@@ -10990,23 +10638,25 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[25]);
 }
 
-
 // ===================================================================
 
-void GeneratedCodeInfo::InitAsDefaultInstance() {
-}
 class GeneratedCodeInfo::_Internal {
  public:
 };
 
-GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   annotation_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo)
 }
 GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from)
@@ -11016,18 +10666,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo)
 }
 
-void GeneratedCodeInfo::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
+inline void GeneratedCodeInfo::SharedCtor() {
 }
 
 GeneratedCodeInfo::~GeneratedCodeInfo() {
   // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void GeneratedCodeInfo::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void GeneratedCodeInfo::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void GeneratedCodeInfo::ArenaDtor(void* object) {
@@ -11039,11 +10689,6 @@
 void GeneratedCodeInfo::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const GeneratedCodeInfo& GeneratedCodeInfo::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void GeneratedCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo)
@@ -11057,11 +10702,9 @@
 
 const char* GeneratedCodeInfo::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
       case 1:
@@ -11077,7 +10720,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -11143,36 +10787,27 @@
   return total_size;
 }
 
-void GeneratedCodeInfo::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  const GeneratedCodeInfo* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<GeneratedCodeInfo>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData GeneratedCodeInfo::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    GeneratedCodeInfo::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GeneratedCodeInfo::GetClassData() const { return &_class_data_; }
+
+void GeneratedCodeInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<GeneratedCodeInfo *>(to)->MergeFrom(
+      static_cast<const GeneratedCodeInfo &>(from));
 }
 
+
 void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   annotation_.MergeFrom(from.annotation_);
-}
-
-void GeneratedCodeInfo::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void GeneratedCodeInfo::CopyFrom(const GeneratedCodeInfo& from) {
@@ -11188,15 +10823,16 @@
 
 void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   annotation_.InternalSwap(&other->annotation_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[26]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 4a6dbf4..b72cdea 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -46,7 +45,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fdescriptor_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[27]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -54,88 +53,88 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class DescriptorProto;
-class DescriptorProtoDefaultTypeInternal;
+struct DescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
 class DescriptorProto_ExtensionRange;
-class DescriptorProto_ExtensionRangeDefaultTypeInternal;
+struct DescriptorProto_ExtensionRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
 class DescriptorProto_ReservedRange;
-class DescriptorProto_ReservedRangeDefaultTypeInternal;
+struct DescriptorProto_ReservedRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
 class EnumDescriptorProto;
-class EnumDescriptorProtoDefaultTypeInternal;
+struct EnumDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
 class EnumDescriptorProto_EnumReservedRange;
-class EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal;
+struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_;
 class EnumOptions;
-class EnumOptionsDefaultTypeInternal;
+struct EnumOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
 class EnumValueDescriptorProto;
-class EnumValueDescriptorProtoDefaultTypeInternal;
+struct EnumValueDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
 class EnumValueOptions;
-class EnumValueOptionsDefaultTypeInternal;
+struct EnumValueOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
 class ExtensionRangeOptions;
-class ExtensionRangeOptionsDefaultTypeInternal;
+struct ExtensionRangeOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
 class FieldDescriptorProto;
-class FieldDescriptorProtoDefaultTypeInternal;
+struct FieldDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
 class FieldOptions;
-class FieldOptionsDefaultTypeInternal;
+struct FieldOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
 class FileDescriptorProto;
-class FileDescriptorProtoDefaultTypeInternal;
+struct FileDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
 class FileDescriptorSet;
-class FileDescriptorSetDefaultTypeInternal;
+struct FileDescriptorSetDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
 class FileOptions;
-class FileOptionsDefaultTypeInternal;
+struct FileOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
 class GeneratedCodeInfo;
-class GeneratedCodeInfoDefaultTypeInternal;
+struct GeneratedCodeInfoDefaultTypeInternal;
 PROTOBUF_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
 class GeneratedCodeInfo_Annotation;
-class GeneratedCodeInfo_AnnotationDefaultTypeInternal;
+struct GeneratedCodeInfo_AnnotationDefaultTypeInternal;
 PROTOBUF_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
 class MessageOptions;
-class MessageOptionsDefaultTypeInternal;
+struct MessageOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
 class MethodDescriptorProto;
-class MethodDescriptorProtoDefaultTypeInternal;
+struct MethodDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
 class MethodOptions;
-class MethodOptionsDefaultTypeInternal;
+struct MethodOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
 class OneofDescriptorProto;
-class OneofDescriptorProtoDefaultTypeInternal;
+struct OneofDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
 class OneofOptions;
-class OneofOptionsDefaultTypeInternal;
+struct OneofOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
 class ServiceDescriptorProto;
-class ServiceDescriptorProtoDefaultTypeInternal;
+struct ServiceDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
 class ServiceOptions;
-class ServiceOptionsDefaultTypeInternal;
+struct ServiceOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
 class SourceCodeInfo;
-class SourceCodeInfoDefaultTypeInternal;
+struct SourceCodeInfoDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
 class SourceCodeInfo_Location;
-class SourceCodeInfo_LocationDefaultTypeInternal;
+struct SourceCodeInfo_LocationDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
 class UninterpretedOption;
-class UninterpretedOptionDefaultTypeInternal;
+struct UninterpretedOptionDefaultTypeInternal;
 PROTOBUF_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
 class UninterpretedOption_NamePart;
-class UninterpretedOption_NamePartDefaultTypeInternal;
+struct UninterpretedOption_NamePartDefaultTypeInternal;
 PROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -204,7 +203,7 @@
     FieldDescriptorProto_Type_descriptor(), enum_t_value);
 }
 inline bool FieldDescriptorProto_Type_Parse(
-    const std::string& name, FieldDescriptorProto_Type* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Type* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Type>(
     FieldDescriptorProto_Type_descriptor(), name, value);
 }
@@ -228,7 +227,7 @@
     FieldDescriptorProto_Label_descriptor(), enum_t_value);
 }
 inline bool FieldDescriptorProto_Label_Parse(
-    const std::string& name, FieldDescriptorProto_Label* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Label* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Label>(
     FieldDescriptorProto_Label_descriptor(), name, value);
 }
@@ -252,7 +251,7 @@
     FileOptions_OptimizeMode_descriptor(), enum_t_value);
 }
 inline bool FileOptions_OptimizeMode_Parse(
-    const std::string& name, FileOptions_OptimizeMode* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FileOptions_OptimizeMode* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FileOptions_OptimizeMode>(
     FileOptions_OptimizeMode_descriptor(), name, value);
 }
@@ -276,7 +275,7 @@
     FieldOptions_CType_descriptor(), enum_t_value);
 }
 inline bool FieldOptions_CType_Parse(
-    const std::string& name, FieldOptions_CType* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_CType* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_CType>(
     FieldOptions_CType_descriptor(), name, value);
 }
@@ -300,7 +299,7 @@
     FieldOptions_JSType_descriptor(), enum_t_value);
 }
 inline bool FieldOptions_JSType_Parse(
-    const std::string& name, FieldOptions_JSType* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_JSType* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_JSType>(
     FieldOptions_JSType_descriptor(), name, value);
 }
@@ -324,17 +323,18 @@
     MethodOptions_IdempotencyLevel_descriptor(), enum_t_value);
 }
 inline bool MethodOptions_IdempotencyLevel_Parse(
-    const std::string& name, MethodOptions_IdempotencyLevel* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, MethodOptions_IdempotencyLevel* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<MethodOptions_IdempotencyLevel>(
     MethodOptions_IdempotencyLevel_descriptor(), name, value);
 }
 // ===================================================================
 
-class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL :
+class PROTOBUF_EXPORT FileDescriptorSet final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorSet) */ {
  public:
-  inline FileDescriptorSet() : FileDescriptorSet(nullptr) {};
-  virtual ~FileDescriptorSet();
+  inline FileDescriptorSet() : FileDescriptorSet(nullptr) {}
+  ~FileDescriptorSet() override;
+  explicit constexpr FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorSet(const FileDescriptorSet& from);
   FileDescriptorSet(FileDescriptorSet&& from) noexcept
@@ -347,8 +347,9 @@
     return *this;
   }
   inline FileDescriptorSet& operator=(FileDescriptorSet&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -366,14 +367,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const FileDescriptorSet& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const FileDescriptorSet& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileDescriptorSet* internal_default_instance() {
     return reinterpret_cast<const FileDescriptorSet*>(
                &_FileDescriptorSet_default_instance_);
@@ -386,7 +387,7 @@
   }
   inline void Swap(FileDescriptorSet* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -394,23 +395,26 @@
   }
   void UnsafeArenaSwap(FileDescriptorSet* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline FileDescriptorSet* New() const final {
-    return CreateMaybeMessage<FileDescriptorSet>(nullptr);
+    return new FileDescriptorSet();
   }
 
   FileDescriptorSet* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<FileDescriptorSet>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const FileDescriptorSet& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const FileDescriptorSet& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -421,8 +425,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(FileDescriptorSet* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -430,20 +434,17 @@
     return "google.protobuf.FileDescriptorSet";
   }
   protected:
-  explicit FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -483,11 +484,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT FileDescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT FileDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorProto) */ {
  public:
-  inline FileDescriptorProto() : FileDescriptorProto(nullptr) {};
-  virtual ~FileDescriptorProto();
+  inline FileDescriptorProto() : FileDescriptorProto(nullptr) {}
+  ~FileDescriptorProto() override;
+  explicit constexpr FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorProto(const FileDescriptorProto& from);
   FileDescriptorProto(FileDescriptorProto&& from) noexcept
@@ -500,8 +502,9 @@
     return *this;
   }
   inline FileDescriptorProto& operator=(FileDescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -519,14 +522,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const FileDescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const FileDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const FileDescriptorProto*>(
                &_FileDescriptorProto_default_instance_);
@@ -539,7 +542,7 @@
   }
   inline void Swap(FileDescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -547,23 +550,26 @@
   }
   void UnsafeArenaSwap(FileDescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline FileDescriptorProto* New() const final {
-    return CreateMaybeMessage<FileDescriptorProto>(nullptr);
+    return new FileDescriptorProto();
   }
 
   FileDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<FileDescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const FileDescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const FileDescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -574,8 +580,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(FileDescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -583,20 +589,17 @@
     return "google.protobuf.FileDescriptorProto";
   }
   protected:
-  explicit FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -763,25 +766,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -792,25 +784,14 @@
   public:
   void clear_package();
   const std::string& package() const;
-  void set_package(const std::string& value);
-  void set_package(std::string&& value);
-  void set_package(const char* value);
-  void set_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_package();
-  std::string* release_package();
+  PROTOBUF_MUST_USE_RESULT std::string* release_package();
   void set_allocated_package(std::string* package);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_package();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_package(
-      std::string* package);
   private:
   const std::string& _internal_package() const;
-  void _internal_set_package(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_package(const std::string& value);
   std::string* _internal_mutable_package();
   public:
 
@@ -821,25 +802,14 @@
   public:
   void clear_syntax();
   const std::string& syntax() const;
-  void set_syntax(const std::string& value);
-  void set_syntax(std::string&& value);
-  void set_syntax(const char* value);
-  void set_syntax(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_syntax(ArgT0&& arg0, ArgT... args);
   std::string* mutable_syntax();
-  std::string* release_syntax();
+  PROTOBUF_MUST_USE_RESULT std::string* release_syntax();
   void set_allocated_syntax(std::string* syntax);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_syntax();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_syntax(
-      std::string* syntax);
   private:
   const std::string& _internal_syntax() const;
-  void _internal_set_syntax(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_syntax(const std::string& value);
   std::string* _internal_mutable_syntax();
   public:
 
@@ -850,7 +820,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::FileOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::FileOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::FileOptions* release_options();
   PROTOBUF_NAMESPACE_ID::FileOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::FileOptions* options);
   private:
@@ -868,7 +838,7 @@
   public:
   void clear_source_code_info();
   const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info() const;
-  PROTOBUF_NAMESPACE_ID::SourceCodeInfo* release_source_code_info();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceCodeInfo* release_source_code_info();
   PROTOBUF_NAMESPACE_ID::SourceCodeInfo* mutable_source_code_info();
   void set_allocated_source_code_info(PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info);
   private:
@@ -904,11 +874,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT DescriptorProto_ExtensionRange PROTOBUF_FINAL :
+class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ExtensionRange) */ {
  public:
-  inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {};
-  virtual ~DescriptorProto_ExtensionRange();
+  inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {}
+  ~DescriptorProto_ExtensionRange() override;
+  explicit constexpr DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from);
   DescriptorProto_ExtensionRange(DescriptorProto_ExtensionRange&& from) noexcept
@@ -921,8 +892,9 @@
     return *this;
   }
   inline DescriptorProto_ExtensionRange& operator=(DescriptorProto_ExtensionRange&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -940,14 +912,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const DescriptorProto_ExtensionRange& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const DescriptorProto_ExtensionRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto_ExtensionRange* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto_ExtensionRange*>(
                &_DescriptorProto_ExtensionRange_default_instance_);
@@ -960,7 +932,7 @@
   }
   inline void Swap(DescriptorProto_ExtensionRange* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -968,23 +940,26 @@
   }
   void UnsafeArenaSwap(DescriptorProto_ExtensionRange* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline DescriptorProto_ExtensionRange* New() const final {
-    return CreateMaybeMessage<DescriptorProto_ExtensionRange>(nullptr);
+    return new DescriptorProto_ExtensionRange();
   }
 
   DescriptorProto_ExtensionRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<DescriptorProto_ExtensionRange>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const DescriptorProto_ExtensionRange& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const DescriptorProto_ExtensionRange& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -995,8 +970,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(DescriptorProto_ExtensionRange* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1004,20 +979,17 @@
     return "google.protobuf.DescriptorProto.ExtensionRange";
   }
   protected:
-  explicit DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1035,7 +1007,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* release_options();
   PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options);
   private:
@@ -1088,11 +1060,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT DescriptorProto_ReservedRange PROTOBUF_FINAL :
+class PROTOBUF_EXPORT DescriptorProto_ReservedRange final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ReservedRange) */ {
  public:
-  inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {};
-  virtual ~DescriptorProto_ReservedRange();
+  inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {}
+  ~DescriptorProto_ReservedRange() override;
+  explicit constexpr DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from);
   DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&& from) noexcept
@@ -1105,8 +1078,9 @@
     return *this;
   }
   inline DescriptorProto_ReservedRange& operator=(DescriptorProto_ReservedRange&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1124,14 +1098,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const DescriptorProto_ReservedRange& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const DescriptorProto_ReservedRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto_ReservedRange* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto_ReservedRange*>(
                &_DescriptorProto_ReservedRange_default_instance_);
@@ -1144,7 +1118,7 @@
   }
   inline void Swap(DescriptorProto_ReservedRange* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1152,23 +1126,26 @@
   }
   void UnsafeArenaSwap(DescriptorProto_ReservedRange* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline DescriptorProto_ReservedRange* New() const final {
-    return CreateMaybeMessage<DescriptorProto_ReservedRange>(nullptr);
+    return new DescriptorProto_ReservedRange();
   }
 
   DescriptorProto_ReservedRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<DescriptorProto_ReservedRange>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const DescriptorProto_ReservedRange& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const DescriptorProto_ReservedRange& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1179,8 +1156,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(DescriptorProto_ReservedRange* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1188,20 +1165,17 @@
     return "google.protobuf.DescriptorProto.ReservedRange";
   }
   protected:
-  explicit DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1252,11 +1226,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT DescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT DescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto) */ {
  public:
-  inline DescriptorProto() : DescriptorProto(nullptr) {};
-  virtual ~DescriptorProto();
+  inline DescriptorProto() : DescriptorProto(nullptr) {}
+  ~DescriptorProto() override;
+  explicit constexpr DescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto(const DescriptorProto& from);
   DescriptorProto(DescriptorProto&& from) noexcept
@@ -1269,8 +1244,9 @@
     return *this;
   }
   inline DescriptorProto& operator=(DescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1288,14 +1264,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const DescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const DescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto*>(
                &_DescriptorProto_default_instance_);
@@ -1308,7 +1284,7 @@
   }
   inline void Swap(DescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1316,23 +1292,26 @@
   }
   void UnsafeArenaSwap(DescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline DescriptorProto* New() const final {
-    return CreateMaybeMessage<DescriptorProto>(nullptr);
+    return new DescriptorProto();
   }
 
   DescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<DescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const DescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const DescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1343,8 +1322,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(DescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1352,20 +1331,17 @@
     return "google.protobuf.DescriptorProto";
   }
   protected:
-  explicit DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1543,25 +1519,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -1572,7 +1537,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::MessageOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::MessageOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::MessageOptions* release_options();
   PROTOBUF_NAMESPACE_ID::MessageOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::MessageOptions* options);
   private:
@@ -1606,11 +1571,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT ExtensionRangeOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ {
  public:
-  inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {};
-  virtual ~ExtensionRangeOptions();
+  inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {}
+  ~ExtensionRangeOptions() override;
+  explicit constexpr ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ExtensionRangeOptions(const ExtensionRangeOptions& from);
   ExtensionRangeOptions(ExtensionRangeOptions&& from) noexcept
@@ -1623,8 +1589,9 @@
     return *this;
   }
   inline ExtensionRangeOptions& operator=(ExtensionRangeOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1642,14 +1609,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const ExtensionRangeOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const ExtensionRangeOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ExtensionRangeOptions* internal_default_instance() {
     return reinterpret_cast<const ExtensionRangeOptions*>(
                &_ExtensionRangeOptions_default_instance_);
@@ -1662,7 +1629,7 @@
   }
   inline void Swap(ExtensionRangeOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1670,23 +1637,26 @@
   }
   void UnsafeArenaSwap(ExtensionRangeOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline ExtensionRangeOptions* New() const final {
-    return CreateMaybeMessage<ExtensionRangeOptions>(nullptr);
+    return new ExtensionRangeOptions();
   }
 
   ExtensionRangeOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<ExtensionRangeOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const ExtensionRangeOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const ExtensionRangeOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1697,8 +1667,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(ExtensionRangeOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1706,20 +1676,17 @@
     return "google.protobuf.ExtensionRangeOptions";
   }
   protected:
-  explicit ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1762,11 +1729,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT FieldDescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT FieldDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ {
  public:
-  inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {};
-  virtual ~FieldDescriptorProto();
+  inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {}
+  ~FieldDescriptorProto() override;
+  explicit constexpr FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldDescriptorProto(const FieldDescriptorProto& from);
   FieldDescriptorProto(FieldDescriptorProto&& from) noexcept
@@ -1779,8 +1747,9 @@
     return *this;
   }
   inline FieldDescriptorProto& operator=(FieldDescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1798,14 +1767,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const FieldDescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const FieldDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const FieldDescriptorProto*>(
                &_FieldDescriptorProto_default_instance_);
@@ -1818,7 +1787,7 @@
   }
   inline void Swap(FieldDescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1826,23 +1795,26 @@
   }
   void UnsafeArenaSwap(FieldDescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline FieldDescriptorProto* New() const final {
-    return CreateMaybeMessage<FieldDescriptorProto>(nullptr);
+    return new FieldDescriptorProto();
   }
 
   FieldDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<FieldDescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const FieldDescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const FieldDescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1853,8 +1825,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(FieldDescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1862,20 +1834,17 @@
     return "google.protobuf.FieldDescriptorProto";
   }
   protected:
-  explicit FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1936,7 +1905,7 @@
       "Incorrect type passed to function Type_Name.");
     return FieldDescriptorProto_Type_Name(enum_t_value);
   }
-  static inline bool Type_Parse(const std::string& name,
+  static inline bool Type_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       Type* value) {
     return FieldDescriptorProto_Type_Parse(name, value);
   }
@@ -1968,7 +1937,7 @@
       "Incorrect type passed to function Label_Name.");
     return FieldDescriptorProto_Label_Name(enum_t_value);
   }
-  static inline bool Label_Parse(const std::string& name,
+  static inline bool Label_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       Label* value) {
     return FieldDescriptorProto_Label_Parse(name, value);
   }
@@ -1995,25 +1964,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -2024,25 +1982,14 @@
   public:
   void clear_extendee();
   const std::string& extendee() const;
-  void set_extendee(const std::string& value);
-  void set_extendee(std::string&& value);
-  void set_extendee(const char* value);
-  void set_extendee(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_extendee(ArgT0&& arg0, ArgT... args);
   std::string* mutable_extendee();
-  std::string* release_extendee();
+  PROTOBUF_MUST_USE_RESULT std::string* release_extendee();
   void set_allocated_extendee(std::string* extendee);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_extendee();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_extendee(
-      std::string* extendee);
   private:
   const std::string& _internal_extendee() const;
-  void _internal_set_extendee(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_extendee(const std::string& value);
   std::string* _internal_mutable_extendee();
   public:
 
@@ -2053,25 +2000,14 @@
   public:
   void clear_type_name();
   const std::string& type_name() const;
-  void set_type_name(const std::string& value);
-  void set_type_name(std::string&& value);
-  void set_type_name(const char* value);
-  void set_type_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_type_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_type_name();
-  std::string* release_type_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_type_name();
   void set_allocated_type_name(std::string* type_name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_type_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_type_name(
-      std::string* type_name);
   private:
   const std::string& _internal_type_name() const;
-  void _internal_set_type_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_name(const std::string& value);
   std::string* _internal_mutable_type_name();
   public:
 
@@ -2082,25 +2018,14 @@
   public:
   void clear_default_value();
   const std::string& default_value() const;
-  void set_default_value(const std::string& value);
-  void set_default_value(std::string&& value);
-  void set_default_value(const char* value);
-  void set_default_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_default_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_default_value();
-  std::string* release_default_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_default_value();
   void set_allocated_default_value(std::string* default_value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_default_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_default_value(
-      std::string* default_value);
   private:
   const std::string& _internal_default_value() const;
-  void _internal_set_default_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_default_value(const std::string& value);
   std::string* _internal_mutable_default_value();
   public:
 
@@ -2111,25 +2036,14 @@
   public:
   void clear_json_name();
   const std::string& json_name() const;
-  void set_json_name(const std::string& value);
-  void set_json_name(std::string&& value);
-  void set_json_name(const char* value);
-  void set_json_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_json_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_json_name();
-  std::string* release_json_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_json_name();
   void set_allocated_json_name(std::string* json_name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_json_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_json_name(
-      std::string* json_name);
   private:
   const std::string& _internal_json_name() const;
-  void _internal_set_json_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_json_name(const std::string& value);
   std::string* _internal_mutable_json_name();
   public:
 
@@ -2140,7 +2054,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::FieldOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::FieldOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::FieldOptions* release_options();
   PROTOBUF_NAMESPACE_ID::FieldOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::FieldOptions* options);
   private:
@@ -2240,11 +2154,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT OneofDescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT OneofDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofDescriptorProto) */ {
  public:
-  inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {};
-  virtual ~OneofDescriptorProto();
+  inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {}
+  ~OneofDescriptorProto() override;
+  explicit constexpr OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofDescriptorProto(const OneofDescriptorProto& from);
   OneofDescriptorProto(OneofDescriptorProto&& from) noexcept
@@ -2257,8 +2172,9 @@
     return *this;
   }
   inline OneofDescriptorProto& operator=(OneofDescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -2276,14 +2192,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const OneofDescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const OneofDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const OneofDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const OneofDescriptorProto*>(
                &_OneofDescriptorProto_default_instance_);
@@ -2296,7 +2212,7 @@
   }
   inline void Swap(OneofDescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -2304,23 +2220,26 @@
   }
   void UnsafeArenaSwap(OneofDescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline OneofDescriptorProto* New() const final {
-    return CreateMaybeMessage<OneofDescriptorProto>(nullptr);
+    return new OneofDescriptorProto();
   }
 
   OneofDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<OneofDescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const OneofDescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const OneofDescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -2331,8 +2250,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(OneofDescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -2340,20 +2259,17 @@
     return "google.protobuf.OneofDescriptorProto";
   }
   protected:
-  explicit OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -2370,25 +2286,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -2399,7 +2304,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::OneofOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::OneofOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::OneofOptions* release_options();
   PROTOBUF_NAMESPACE_ID::OneofOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::OneofOptions* options);
   private:
@@ -2425,11 +2330,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange PROTOBUF_FINAL :
+class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto.EnumReservedRange) */ {
  public:
-  inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {};
-  virtual ~EnumDescriptorProto_EnumReservedRange();
+  inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {}
+  ~EnumDescriptorProto_EnumReservedRange() override;
+  explicit constexpr EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from);
   EnumDescriptorProto_EnumReservedRange(EnumDescriptorProto_EnumReservedRange&& from) noexcept
@@ -2442,8 +2348,9 @@
     return *this;
   }
   inline EnumDescriptorProto_EnumReservedRange& operator=(EnumDescriptorProto_EnumReservedRange&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -2461,14 +2368,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const EnumDescriptorProto_EnumReservedRange& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const EnumDescriptorProto_EnumReservedRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumDescriptorProto_EnumReservedRange* internal_default_instance() {
     return reinterpret_cast<const EnumDescriptorProto_EnumReservedRange*>(
                &_EnumDescriptorProto_EnumReservedRange_default_instance_);
@@ -2481,7 +2388,7 @@
   }
   inline void Swap(EnumDescriptorProto_EnumReservedRange* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -2489,23 +2396,26 @@
   }
   void UnsafeArenaSwap(EnumDescriptorProto_EnumReservedRange* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline EnumDescriptorProto_EnumReservedRange* New() const final {
-    return CreateMaybeMessage<EnumDescriptorProto_EnumReservedRange>(nullptr);
+    return new EnumDescriptorProto_EnumReservedRange();
   }
 
   EnumDescriptorProto_EnumReservedRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<EnumDescriptorProto_EnumReservedRange>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const EnumDescriptorProto_EnumReservedRange& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const EnumDescriptorProto_EnumReservedRange& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -2516,8 +2426,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(EnumDescriptorProto_EnumReservedRange* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -2525,20 +2435,17 @@
     return "google.protobuf.EnumDescriptorProto.EnumReservedRange";
   }
   protected:
-  explicit EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -2589,11 +2496,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT EnumDescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT EnumDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto) */ {
  public:
-  inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {};
-  virtual ~EnumDescriptorProto();
+  inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {}
+  ~EnumDescriptorProto() override;
+  explicit constexpr EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto(const EnumDescriptorProto& from);
   EnumDescriptorProto(EnumDescriptorProto&& from) noexcept
@@ -2606,8 +2514,9 @@
     return *this;
   }
   inline EnumDescriptorProto& operator=(EnumDescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -2625,14 +2534,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const EnumDescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const EnumDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const EnumDescriptorProto*>(
                &_EnumDescriptorProto_default_instance_);
@@ -2645,7 +2554,7 @@
   }
   inline void Swap(EnumDescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -2653,23 +2562,26 @@
   }
   void UnsafeArenaSwap(EnumDescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline EnumDescriptorProto* New() const final {
-    return CreateMaybeMessage<EnumDescriptorProto>(nullptr);
+    return new EnumDescriptorProto();
   }
 
   EnumDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<EnumDescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const EnumDescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const EnumDescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -2680,8 +2592,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(EnumDescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -2689,20 +2601,17 @@
     return "google.protobuf.EnumDescriptorProto";
   }
   protected:
-  explicit EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -2784,25 +2693,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -2813,7 +2711,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::EnumOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::EnumOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::EnumOptions* release_options();
   PROTOBUF_NAMESPACE_ID::EnumOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumOptions* options);
   private:
@@ -2842,11 +2740,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT EnumValueDescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT EnumValueDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueDescriptorProto) */ {
  public:
-  inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {};
-  virtual ~EnumValueDescriptorProto();
+  inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {}
+  ~EnumValueDescriptorProto() override;
+  explicit constexpr EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueDescriptorProto(const EnumValueDescriptorProto& from);
   EnumValueDescriptorProto(EnumValueDescriptorProto&& from) noexcept
@@ -2859,8 +2758,9 @@
     return *this;
   }
   inline EnumValueDescriptorProto& operator=(EnumValueDescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -2878,14 +2778,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const EnumValueDescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const EnumValueDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValueDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const EnumValueDescriptorProto*>(
                &_EnumValueDescriptorProto_default_instance_);
@@ -2898,7 +2798,7 @@
   }
   inline void Swap(EnumValueDescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -2906,23 +2806,26 @@
   }
   void UnsafeArenaSwap(EnumValueDescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline EnumValueDescriptorProto* New() const final {
-    return CreateMaybeMessage<EnumValueDescriptorProto>(nullptr);
+    return new EnumValueDescriptorProto();
   }
 
   EnumValueDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<EnumValueDescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const EnumValueDescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const EnumValueDescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -2933,8 +2836,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(EnumValueDescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -2942,20 +2845,17 @@
     return "google.protobuf.EnumValueDescriptorProto";
   }
   protected:
-  explicit EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -2973,25 +2873,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -3002,7 +2891,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::EnumValueOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::EnumValueOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::EnumValueOptions* release_options();
   PROTOBUF_NAMESPACE_ID::EnumValueOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumValueOptions* options);
   private:
@@ -3042,11 +2931,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT ServiceDescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT ServiceDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceDescriptorProto) */ {
  public:
-  inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {};
-  virtual ~ServiceDescriptorProto();
+  inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {}
+  ~ServiceDescriptorProto() override;
+  explicit constexpr ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceDescriptorProto(const ServiceDescriptorProto& from);
   ServiceDescriptorProto(ServiceDescriptorProto&& from) noexcept
@@ -3059,8 +2949,9 @@
     return *this;
   }
   inline ServiceDescriptorProto& operator=(ServiceDescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -3078,14 +2969,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const ServiceDescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const ServiceDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ServiceDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const ServiceDescriptorProto*>(
                &_ServiceDescriptorProto_default_instance_);
@@ -3098,7 +2989,7 @@
   }
   inline void Swap(ServiceDescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -3106,23 +2997,26 @@
   }
   void UnsafeArenaSwap(ServiceDescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline ServiceDescriptorProto* New() const final {
-    return CreateMaybeMessage<ServiceDescriptorProto>(nullptr);
+    return new ServiceDescriptorProto();
   }
 
   ServiceDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<ServiceDescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const ServiceDescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const ServiceDescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -3133,8 +3027,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(ServiceDescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -3142,20 +3036,17 @@
     return "google.protobuf.ServiceDescriptorProto";
   }
   protected:
-  explicit ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -3191,25 +3082,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -3220,7 +3100,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::ServiceOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::ServiceOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::ServiceOptions* release_options();
   PROTOBUF_NAMESPACE_ID::ServiceOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::ServiceOptions* options);
   private:
@@ -3247,11 +3127,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT MethodDescriptorProto PROTOBUF_FINAL :
+class PROTOBUF_EXPORT MethodDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodDescriptorProto) */ {
  public:
-  inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {};
-  virtual ~MethodDescriptorProto();
+  inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {}
+  ~MethodDescriptorProto() override;
+  explicit constexpr MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodDescriptorProto(const MethodDescriptorProto& from);
   MethodDescriptorProto(MethodDescriptorProto&& from) noexcept
@@ -3264,8 +3145,9 @@
     return *this;
   }
   inline MethodDescriptorProto& operator=(MethodDescriptorProto&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -3283,14 +3165,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const MethodDescriptorProto& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const MethodDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MethodDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const MethodDescriptorProto*>(
                &_MethodDescriptorProto_default_instance_);
@@ -3303,7 +3185,7 @@
   }
   inline void Swap(MethodDescriptorProto* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -3311,23 +3193,26 @@
   }
   void UnsafeArenaSwap(MethodDescriptorProto* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline MethodDescriptorProto* New() const final {
-    return CreateMaybeMessage<MethodDescriptorProto>(nullptr);
+    return new MethodDescriptorProto();
   }
 
   MethodDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<MethodDescriptorProto>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const MethodDescriptorProto& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const MethodDescriptorProto& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -3338,8 +3223,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(MethodDescriptorProto* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -3347,20 +3232,17 @@
     return "google.protobuf.MethodDescriptorProto";
   }
   protected:
-  explicit MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -3381,25 +3263,14 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -3410,25 +3281,14 @@
   public:
   void clear_input_type();
   const std::string& input_type() const;
-  void set_input_type(const std::string& value);
-  void set_input_type(std::string&& value);
-  void set_input_type(const char* value);
-  void set_input_type(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_input_type(ArgT0&& arg0, ArgT... args);
   std::string* mutable_input_type();
-  std::string* release_input_type();
+  PROTOBUF_MUST_USE_RESULT std::string* release_input_type();
   void set_allocated_input_type(std::string* input_type);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_input_type();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_input_type(
-      std::string* input_type);
   private:
   const std::string& _internal_input_type() const;
-  void _internal_set_input_type(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_input_type(const std::string& value);
   std::string* _internal_mutable_input_type();
   public:
 
@@ -3439,25 +3299,14 @@
   public:
   void clear_output_type();
   const std::string& output_type() const;
-  void set_output_type(const std::string& value);
-  void set_output_type(std::string&& value);
-  void set_output_type(const char* value);
-  void set_output_type(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_output_type(ArgT0&& arg0, ArgT... args);
   std::string* mutable_output_type();
-  std::string* release_output_type();
+  PROTOBUF_MUST_USE_RESULT std::string* release_output_type();
   void set_allocated_output_type(std::string* output_type);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_output_type();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_output_type(
-      std::string* output_type);
   private:
   const std::string& _internal_output_type() const;
-  void _internal_set_output_type(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_output_type(const std::string& value);
   std::string* _internal_mutable_output_type();
   public:
 
@@ -3468,7 +3317,7 @@
   public:
   void clear_options();
   const PROTOBUF_NAMESPACE_ID::MethodOptions& options() const;
-  PROTOBUF_NAMESPACE_ID::MethodOptions* release_options();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::MethodOptions* release_options();
   PROTOBUF_NAMESPACE_ID::MethodOptions* mutable_options();
   void set_allocated_options(PROTOBUF_NAMESPACE_ID::MethodOptions* options);
   private:
@@ -3524,11 +3373,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT FileOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT FileOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileOptions) */ {
  public:
-  inline FileOptions() : FileOptions(nullptr) {};
-  virtual ~FileOptions();
+  inline FileOptions() : FileOptions(nullptr) {}
+  ~FileOptions() override;
+  explicit constexpr FileOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileOptions(const FileOptions& from);
   FileOptions(FileOptions&& from) noexcept
@@ -3541,8 +3391,9 @@
     return *this;
   }
   inline FileOptions& operator=(FileOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -3560,14 +3411,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const FileOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const FileOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileOptions* internal_default_instance() {
     return reinterpret_cast<const FileOptions*>(
                &_FileOptions_default_instance_);
@@ -3580,7 +3431,7 @@
   }
   inline void Swap(FileOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -3588,23 +3439,26 @@
   }
   void UnsafeArenaSwap(FileOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline FileOptions* New() const final {
-    return CreateMaybeMessage<FileOptions>(nullptr);
+    return new FileOptions();
   }
 
   FileOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<FileOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const FileOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const FileOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -3615,8 +3469,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(FileOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -3624,20 +3478,17 @@
     return "google.protobuf.FileOptions";
   }
   protected:
-  explicit FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -3668,7 +3519,7 @@
       "Incorrect type passed to function OptimizeMode_Name.");
     return FileOptions_OptimizeMode_Name(enum_t_value);
   }
-  static inline bool OptimizeMode_Parse(const std::string& name,
+  static inline bool OptimizeMode_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       OptimizeMode* value) {
     return FileOptions_OptimizeMode_Parse(name, value);
   }
@@ -3723,25 +3574,14 @@
   public:
   void clear_java_package();
   const std::string& java_package() const;
-  void set_java_package(const std::string& value);
-  void set_java_package(std::string&& value);
-  void set_java_package(const char* value);
-  void set_java_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_java_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_java_package();
-  std::string* release_java_package();
+  PROTOBUF_MUST_USE_RESULT std::string* release_java_package();
   void set_allocated_java_package(std::string* java_package);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_java_package();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_java_package(
-      std::string* java_package);
   private:
   const std::string& _internal_java_package() const;
-  void _internal_set_java_package(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_java_package(const std::string& value);
   std::string* _internal_mutable_java_package();
   public:
 
@@ -3752,25 +3592,14 @@
   public:
   void clear_java_outer_classname();
   const std::string& java_outer_classname() const;
-  void set_java_outer_classname(const std::string& value);
-  void set_java_outer_classname(std::string&& value);
-  void set_java_outer_classname(const char* value);
-  void set_java_outer_classname(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_java_outer_classname(ArgT0&& arg0, ArgT... args);
   std::string* mutable_java_outer_classname();
-  std::string* release_java_outer_classname();
+  PROTOBUF_MUST_USE_RESULT std::string* release_java_outer_classname();
   void set_allocated_java_outer_classname(std::string* java_outer_classname);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_java_outer_classname();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_java_outer_classname(
-      std::string* java_outer_classname);
   private:
   const std::string& _internal_java_outer_classname() const;
-  void _internal_set_java_outer_classname(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_java_outer_classname(const std::string& value);
   std::string* _internal_mutable_java_outer_classname();
   public:
 
@@ -3781,25 +3610,14 @@
   public:
   void clear_go_package();
   const std::string& go_package() const;
-  void set_go_package(const std::string& value);
-  void set_go_package(std::string&& value);
-  void set_go_package(const char* value);
-  void set_go_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_go_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_go_package();
-  std::string* release_go_package();
+  PROTOBUF_MUST_USE_RESULT std::string* release_go_package();
   void set_allocated_go_package(std::string* go_package);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_go_package();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_go_package(
-      std::string* go_package);
   private:
   const std::string& _internal_go_package() const;
-  void _internal_set_go_package(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_go_package(const std::string& value);
   std::string* _internal_mutable_go_package();
   public:
 
@@ -3810,25 +3628,14 @@
   public:
   void clear_objc_class_prefix();
   const std::string& objc_class_prefix() const;
-  void set_objc_class_prefix(const std::string& value);
-  void set_objc_class_prefix(std::string&& value);
-  void set_objc_class_prefix(const char* value);
-  void set_objc_class_prefix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_objc_class_prefix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_objc_class_prefix();
-  std::string* release_objc_class_prefix();
+  PROTOBUF_MUST_USE_RESULT std::string* release_objc_class_prefix();
   void set_allocated_objc_class_prefix(std::string* objc_class_prefix);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_objc_class_prefix();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_objc_class_prefix(
-      std::string* objc_class_prefix);
   private:
   const std::string& _internal_objc_class_prefix() const;
-  void _internal_set_objc_class_prefix(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_objc_class_prefix(const std::string& value);
   std::string* _internal_mutable_objc_class_prefix();
   public:
 
@@ -3839,25 +3646,14 @@
   public:
   void clear_csharp_namespace();
   const std::string& csharp_namespace() const;
-  void set_csharp_namespace(const std::string& value);
-  void set_csharp_namespace(std::string&& value);
-  void set_csharp_namespace(const char* value);
-  void set_csharp_namespace(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_csharp_namespace(ArgT0&& arg0, ArgT... args);
   std::string* mutable_csharp_namespace();
-  std::string* release_csharp_namespace();
+  PROTOBUF_MUST_USE_RESULT std::string* release_csharp_namespace();
   void set_allocated_csharp_namespace(std::string* csharp_namespace);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_csharp_namespace();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_csharp_namespace(
-      std::string* csharp_namespace);
   private:
   const std::string& _internal_csharp_namespace() const;
-  void _internal_set_csharp_namespace(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_csharp_namespace(const std::string& value);
   std::string* _internal_mutable_csharp_namespace();
   public:
 
@@ -3868,25 +3664,14 @@
   public:
   void clear_swift_prefix();
   const std::string& swift_prefix() const;
-  void set_swift_prefix(const std::string& value);
-  void set_swift_prefix(std::string&& value);
-  void set_swift_prefix(const char* value);
-  void set_swift_prefix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_swift_prefix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_swift_prefix();
-  std::string* release_swift_prefix();
+  PROTOBUF_MUST_USE_RESULT std::string* release_swift_prefix();
   void set_allocated_swift_prefix(std::string* swift_prefix);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_swift_prefix();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_swift_prefix(
-      std::string* swift_prefix);
   private:
   const std::string& _internal_swift_prefix() const;
-  void _internal_set_swift_prefix(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_swift_prefix(const std::string& value);
   std::string* _internal_mutable_swift_prefix();
   public:
 
@@ -3897,25 +3682,14 @@
   public:
   void clear_php_class_prefix();
   const std::string& php_class_prefix() const;
-  void set_php_class_prefix(const std::string& value);
-  void set_php_class_prefix(std::string&& value);
-  void set_php_class_prefix(const char* value);
-  void set_php_class_prefix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_php_class_prefix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_php_class_prefix();
-  std::string* release_php_class_prefix();
+  PROTOBUF_MUST_USE_RESULT std::string* release_php_class_prefix();
   void set_allocated_php_class_prefix(std::string* php_class_prefix);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_php_class_prefix();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_php_class_prefix(
-      std::string* php_class_prefix);
   private:
   const std::string& _internal_php_class_prefix() const;
-  void _internal_set_php_class_prefix(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_class_prefix(const std::string& value);
   std::string* _internal_mutable_php_class_prefix();
   public:
 
@@ -3926,25 +3700,14 @@
   public:
   void clear_php_namespace();
   const std::string& php_namespace() const;
-  void set_php_namespace(const std::string& value);
-  void set_php_namespace(std::string&& value);
-  void set_php_namespace(const char* value);
-  void set_php_namespace(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_php_namespace(ArgT0&& arg0, ArgT... args);
   std::string* mutable_php_namespace();
-  std::string* release_php_namespace();
+  PROTOBUF_MUST_USE_RESULT std::string* release_php_namespace();
   void set_allocated_php_namespace(std::string* php_namespace);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_php_namespace();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_php_namespace(
-      std::string* php_namespace);
   private:
   const std::string& _internal_php_namespace() const;
-  void _internal_set_php_namespace(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_namespace(const std::string& value);
   std::string* _internal_mutable_php_namespace();
   public:
 
@@ -3955,25 +3718,14 @@
   public:
   void clear_php_metadata_namespace();
   const std::string& php_metadata_namespace() const;
-  void set_php_metadata_namespace(const std::string& value);
-  void set_php_metadata_namespace(std::string&& value);
-  void set_php_metadata_namespace(const char* value);
-  void set_php_metadata_namespace(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_php_metadata_namespace(ArgT0&& arg0, ArgT... args);
   std::string* mutable_php_metadata_namespace();
-  std::string* release_php_metadata_namespace();
+  PROTOBUF_MUST_USE_RESULT std::string* release_php_metadata_namespace();
   void set_allocated_php_metadata_namespace(std::string* php_metadata_namespace);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_php_metadata_namespace();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_php_metadata_namespace(
-      std::string* php_metadata_namespace);
   private:
   const std::string& _internal_php_metadata_namespace() const;
-  void _internal_set_php_metadata_namespace(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_metadata_namespace(const std::string& value);
   std::string* _internal_mutable_php_metadata_namespace();
   public:
 
@@ -3984,25 +3736,14 @@
   public:
   void clear_ruby_package();
   const std::string& ruby_package() const;
-  void set_ruby_package(const std::string& value);
-  void set_ruby_package(std::string&& value);
-  void set_ruby_package(const char* value);
-  void set_ruby_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_ruby_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_ruby_package();
-  std::string* release_ruby_package();
+  PROTOBUF_MUST_USE_RESULT std::string* release_ruby_package();
   void set_allocated_ruby_package(std::string* ruby_package);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_ruby_package();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_ruby_package(
-      std::string* ruby_package);
   private:
   const std::string& _internal_ruby_package() const;
-  void _internal_set_ruby_package(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_ruby_package(const std::string& value);
   std::string* _internal_mutable_ruby_package();
   public:
 
@@ -4173,11 +3914,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT MessageOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT MessageOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MessageOptions) */ {
  public:
-  inline MessageOptions() : MessageOptions(nullptr) {};
-  virtual ~MessageOptions();
+  inline MessageOptions() : MessageOptions(nullptr) {}
+  ~MessageOptions() override;
+  explicit constexpr MessageOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MessageOptions(const MessageOptions& from);
   MessageOptions(MessageOptions&& from) noexcept
@@ -4190,8 +3932,9 @@
     return *this;
   }
   inline MessageOptions& operator=(MessageOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -4209,14 +3952,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const MessageOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const MessageOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MessageOptions* internal_default_instance() {
     return reinterpret_cast<const MessageOptions*>(
                &_MessageOptions_default_instance_);
@@ -4229,7 +3972,7 @@
   }
   inline void Swap(MessageOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -4237,23 +3980,26 @@
   }
   void UnsafeArenaSwap(MessageOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline MessageOptions* New() const final {
-    return CreateMaybeMessage<MessageOptions>(nullptr);
+    return new MessageOptions();
   }
 
   MessageOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<MessageOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const MessageOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const MessageOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -4264,8 +4010,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(MessageOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -4273,20 +4019,17 @@
     return "google.protobuf.MessageOptions";
   }
   protected:
-  explicit MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -4390,11 +4133,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT FieldOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT FieldOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions) */ {
  public:
-  inline FieldOptions() : FieldOptions(nullptr) {};
-  virtual ~FieldOptions();
+  inline FieldOptions() : FieldOptions(nullptr) {}
+  ~FieldOptions() override;
+  explicit constexpr FieldOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldOptions(const FieldOptions& from);
   FieldOptions(FieldOptions&& from) noexcept
@@ -4407,8 +4151,9 @@
     return *this;
   }
   inline FieldOptions& operator=(FieldOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -4426,14 +4171,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const FieldOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const FieldOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldOptions* internal_default_instance() {
     return reinterpret_cast<const FieldOptions*>(
                &_FieldOptions_default_instance_);
@@ -4446,7 +4191,7 @@
   }
   inline void Swap(FieldOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -4454,23 +4199,26 @@
   }
   void UnsafeArenaSwap(FieldOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline FieldOptions* New() const final {
-    return CreateMaybeMessage<FieldOptions>(nullptr);
+    return new FieldOptions();
   }
 
   FieldOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<FieldOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const FieldOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const FieldOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -4481,8 +4229,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(FieldOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -4490,20 +4238,17 @@
     return "google.protobuf.FieldOptions";
   }
   protected:
-  explicit FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -4534,7 +4279,7 @@
       "Incorrect type passed to function CType_Name.");
     return FieldOptions_CType_Name(enum_t_value);
   }
-  static inline bool CType_Parse(const std::string& name,
+  static inline bool CType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       CType* value) {
     return FieldOptions_CType_Parse(name, value);
   }
@@ -4566,7 +4311,7 @@
       "Incorrect type passed to function JSType_Name.");
     return FieldOptions_JSType_Name(enum_t_value);
   }
-  static inline bool JSType_Parse(const std::string& name,
+  static inline bool JSType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       JSType* value) {
     return FieldOptions_JSType_Parse(name, value);
   }
@@ -4701,11 +4446,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT OneofOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofOptions) */ {
  public:
-  inline OneofOptions() : OneofOptions(nullptr) {};
-  virtual ~OneofOptions();
+  inline OneofOptions() : OneofOptions(nullptr) {}
+  ~OneofOptions() override;
+  explicit constexpr OneofOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofOptions(const OneofOptions& from);
   OneofOptions(OneofOptions&& from) noexcept
@@ -4718,8 +4464,9 @@
     return *this;
   }
   inline OneofOptions& operator=(OneofOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -4737,14 +4484,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const OneofOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const OneofOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const OneofOptions* internal_default_instance() {
     return reinterpret_cast<const OneofOptions*>(
                &_OneofOptions_default_instance_);
@@ -4757,7 +4504,7 @@
   }
   inline void Swap(OneofOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -4765,23 +4512,26 @@
   }
   void UnsafeArenaSwap(OneofOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline OneofOptions* New() const final {
-    return CreateMaybeMessage<OneofOptions>(nullptr);
+    return new OneofOptions();
   }
 
   OneofOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<OneofOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const OneofOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const OneofOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -4792,8 +4542,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(OneofOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -4801,20 +4551,17 @@
     return "google.protobuf.OneofOptions";
   }
   protected:
-  explicit OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -4857,11 +4604,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT EnumOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT EnumOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumOptions) */ {
  public:
-  inline EnumOptions() : EnumOptions(nullptr) {};
-  virtual ~EnumOptions();
+  inline EnumOptions() : EnumOptions(nullptr) {}
+  ~EnumOptions() override;
+  explicit constexpr EnumOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumOptions(const EnumOptions& from);
   EnumOptions(EnumOptions&& from) noexcept
@@ -4874,8 +4622,9 @@
     return *this;
   }
   inline EnumOptions& operator=(EnumOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -4893,14 +4642,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const EnumOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const EnumOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumOptions* internal_default_instance() {
     return reinterpret_cast<const EnumOptions*>(
                &_EnumOptions_default_instance_);
@@ -4913,7 +4662,7 @@
   }
   inline void Swap(EnumOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -4921,23 +4670,26 @@
   }
   void UnsafeArenaSwap(EnumOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline EnumOptions* New() const final {
-    return CreateMaybeMessage<EnumOptions>(nullptr);
+    return new EnumOptions();
   }
 
   EnumOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<EnumOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const EnumOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const EnumOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -4948,8 +4700,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(EnumOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -4957,20 +4709,17 @@
     return "google.protobuf.EnumOptions";
   }
   protected:
-  explicit EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -5044,11 +4793,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT EnumValueOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT EnumValueOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueOptions) */ {
  public:
-  inline EnumValueOptions() : EnumValueOptions(nullptr) {};
-  virtual ~EnumValueOptions();
+  inline EnumValueOptions() : EnumValueOptions(nullptr) {}
+  ~EnumValueOptions() override;
+  explicit constexpr EnumValueOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueOptions(const EnumValueOptions& from);
   EnumValueOptions(EnumValueOptions&& from) noexcept
@@ -5061,8 +4811,9 @@
     return *this;
   }
   inline EnumValueOptions& operator=(EnumValueOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -5080,14 +4831,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const EnumValueOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const EnumValueOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValueOptions* internal_default_instance() {
     return reinterpret_cast<const EnumValueOptions*>(
                &_EnumValueOptions_default_instance_);
@@ -5100,7 +4851,7 @@
   }
   inline void Swap(EnumValueOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -5108,23 +4859,26 @@
   }
   void UnsafeArenaSwap(EnumValueOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline EnumValueOptions* New() const final {
-    return CreateMaybeMessage<EnumValueOptions>(nullptr);
+    return new EnumValueOptions();
   }
 
   EnumValueOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<EnumValueOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const EnumValueOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const EnumValueOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -5135,8 +4889,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(EnumValueOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -5144,20 +4898,17 @@
     return "google.protobuf.EnumValueOptions";
   }
   protected:
-  explicit EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -5216,11 +4967,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT ServiceOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT ServiceOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceOptions) */ {
  public:
-  inline ServiceOptions() : ServiceOptions(nullptr) {};
-  virtual ~ServiceOptions();
+  inline ServiceOptions() : ServiceOptions(nullptr) {}
+  ~ServiceOptions() override;
+  explicit constexpr ServiceOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceOptions(const ServiceOptions& from);
   ServiceOptions(ServiceOptions&& from) noexcept
@@ -5233,8 +4985,9 @@
     return *this;
   }
   inline ServiceOptions& operator=(ServiceOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -5252,14 +5005,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const ServiceOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const ServiceOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ServiceOptions* internal_default_instance() {
     return reinterpret_cast<const ServiceOptions*>(
                &_ServiceOptions_default_instance_);
@@ -5272,7 +5025,7 @@
   }
   inline void Swap(ServiceOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -5280,23 +5033,26 @@
   }
   void UnsafeArenaSwap(ServiceOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline ServiceOptions* New() const final {
-    return CreateMaybeMessage<ServiceOptions>(nullptr);
+    return new ServiceOptions();
   }
 
   ServiceOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<ServiceOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const ServiceOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const ServiceOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -5307,8 +5063,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(ServiceOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -5316,20 +5072,17 @@
     return "google.protobuf.ServiceOptions";
   }
   protected:
-  explicit ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -5388,11 +5141,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT MethodOptions PROTOBUF_FINAL :
+class PROTOBUF_EXPORT MethodOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodOptions) */ {
  public:
-  inline MethodOptions() : MethodOptions(nullptr) {};
-  virtual ~MethodOptions();
+  inline MethodOptions() : MethodOptions(nullptr) {}
+  ~MethodOptions() override;
+  explicit constexpr MethodOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodOptions(const MethodOptions& from);
   MethodOptions(MethodOptions&& from) noexcept
@@ -5405,8 +5159,9 @@
     return *this;
   }
   inline MethodOptions& operator=(MethodOptions&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -5424,14 +5179,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const MethodOptions& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const MethodOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MethodOptions* internal_default_instance() {
     return reinterpret_cast<const MethodOptions*>(
                &_MethodOptions_default_instance_);
@@ -5444,7 +5199,7 @@
   }
   inline void Swap(MethodOptions* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -5452,23 +5207,26 @@
   }
   void UnsafeArenaSwap(MethodOptions* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline MethodOptions* New() const final {
-    return CreateMaybeMessage<MethodOptions>(nullptr);
+    return new MethodOptions();
   }
 
   MethodOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<MethodOptions>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const MethodOptions& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const MethodOptions& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -5479,8 +5237,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(MethodOptions* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -5488,20 +5246,17 @@
     return "google.protobuf.MethodOptions";
   }
   protected:
-  explicit MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -5532,7 +5287,7 @@
       "Incorrect type passed to function IdempotencyLevel_Name.");
     return MethodOptions_IdempotencyLevel_Name(enum_t_value);
   }
-  static inline bool IdempotencyLevel_Parse(const std::string& name,
+  static inline bool IdempotencyLevel_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       IdempotencyLevel* value) {
     return MethodOptions_IdempotencyLevel_Parse(name, value);
   }
@@ -5607,11 +5362,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT UninterpretedOption_NamePart PROTOBUF_FINAL :
+class PROTOBUF_EXPORT UninterpretedOption_NamePart final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption.NamePart) */ {
  public:
-  inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {};
-  virtual ~UninterpretedOption_NamePart();
+  inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {}
+  ~UninterpretedOption_NamePart() override;
+  explicit constexpr UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from);
   UninterpretedOption_NamePart(UninterpretedOption_NamePart&& from) noexcept
@@ -5624,8 +5380,9 @@
     return *this;
   }
   inline UninterpretedOption_NamePart& operator=(UninterpretedOption_NamePart&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -5643,14 +5400,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const UninterpretedOption_NamePart& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const UninterpretedOption_NamePart& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UninterpretedOption_NamePart* internal_default_instance() {
     return reinterpret_cast<const UninterpretedOption_NamePart*>(
                &_UninterpretedOption_NamePart_default_instance_);
@@ -5663,7 +5420,7 @@
   }
   inline void Swap(UninterpretedOption_NamePart* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -5671,23 +5428,26 @@
   }
   void UnsafeArenaSwap(UninterpretedOption_NamePart* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline UninterpretedOption_NamePart* New() const final {
-    return CreateMaybeMessage<UninterpretedOption_NamePart>(nullptr);
+    return new UninterpretedOption_NamePart();
   }
 
   UninterpretedOption_NamePart* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<UninterpretedOption_NamePart>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const UninterpretedOption_NamePart& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const UninterpretedOption_NamePart& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -5698,8 +5458,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(UninterpretedOption_NamePart* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -5707,20 +5467,17 @@
     return "google.protobuf.UninterpretedOption.NamePart";
   }
   protected:
-  explicit UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -5737,25 +5494,14 @@
   public:
   void clear_name_part();
   const std::string& name_part() const;
-  void set_name_part(const std::string& value);
-  void set_name_part(std::string&& value);
-  void set_name_part(const char* value);
-  void set_name_part(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name_part(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name_part();
-  std::string* release_name_part();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name_part();
   void set_allocated_name_part(std::string* name_part);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name_part();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name_part(
-      std::string* name_part);
   private:
   const std::string& _internal_name_part() const;
-  void _internal_set_name_part(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name_part(const std::string& value);
   std::string* _internal_mutable_name_part();
   public:
 
@@ -5790,11 +5536,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT UninterpretedOption PROTOBUF_FINAL :
+class PROTOBUF_EXPORT UninterpretedOption final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption) */ {
  public:
-  inline UninterpretedOption() : UninterpretedOption(nullptr) {};
-  virtual ~UninterpretedOption();
+  inline UninterpretedOption() : UninterpretedOption(nullptr) {}
+  ~UninterpretedOption() override;
+  explicit constexpr UninterpretedOption(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption(const UninterpretedOption& from);
   UninterpretedOption(UninterpretedOption&& from) noexcept
@@ -5807,8 +5554,9 @@
     return *this;
   }
   inline UninterpretedOption& operator=(UninterpretedOption&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -5826,14 +5574,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const UninterpretedOption& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const UninterpretedOption& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UninterpretedOption* internal_default_instance() {
     return reinterpret_cast<const UninterpretedOption*>(
                &_UninterpretedOption_default_instance_);
@@ -5846,7 +5594,7 @@
   }
   inline void Swap(UninterpretedOption* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -5854,23 +5602,26 @@
   }
   void UnsafeArenaSwap(UninterpretedOption* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline UninterpretedOption* New() const final {
-    return CreateMaybeMessage<UninterpretedOption>(nullptr);
+    return new UninterpretedOption();
   }
 
   UninterpretedOption* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<UninterpretedOption>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const UninterpretedOption& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const UninterpretedOption& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -5881,8 +5632,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(UninterpretedOption* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -5890,20 +5641,17 @@
     return "google.protobuf.UninterpretedOption";
   }
   protected:
-  explicit UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -5945,25 +5693,14 @@
   public:
   void clear_identifier_value();
   const std::string& identifier_value() const;
-  void set_identifier_value(const std::string& value);
-  void set_identifier_value(std::string&& value);
-  void set_identifier_value(const char* value);
-  void set_identifier_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_identifier_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_identifier_value();
-  std::string* release_identifier_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_identifier_value();
   void set_allocated_identifier_value(std::string* identifier_value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_identifier_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_identifier_value(
-      std::string* identifier_value);
   private:
   const std::string& _internal_identifier_value() const;
-  void _internal_set_identifier_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_identifier_value(const std::string& value);
   std::string* _internal_mutable_identifier_value();
   public:
 
@@ -5974,25 +5711,14 @@
   public:
   void clear_string_value();
   const std::string& string_value() const;
-  void set_string_value(const std::string& value);
-  void set_string_value(std::string&& value);
-  void set_string_value(const char* value);
-  void set_string_value(const void* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_string_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_string_value();
-  std::string* release_string_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_string_value();
   void set_allocated_string_value(std::string* string_value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_string_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_string_value(
-      std::string* string_value);
   private:
   const std::string& _internal_string_value() const;
-  void _internal_set_string_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_string_value(const std::string& value);
   std::string* _internal_mutable_string_value();
   public:
 
@@ -6003,25 +5729,14 @@
   public:
   void clear_aggregate_value();
   const std::string& aggregate_value() const;
-  void set_aggregate_value(const std::string& value);
-  void set_aggregate_value(std::string&& value);
-  void set_aggregate_value(const char* value);
-  void set_aggregate_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_aggregate_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_aggregate_value();
-  std::string* release_aggregate_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_aggregate_value();
   void set_allocated_aggregate_value(std::string* aggregate_value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_aggregate_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_aggregate_value(
-      std::string* aggregate_value);
   private:
   const std::string& _internal_aggregate_value() const;
-  void _internal_set_aggregate_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_aggregate_value(const std::string& value);
   std::string* _internal_mutable_aggregate_value();
   public:
 
@@ -6084,11 +5799,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT SourceCodeInfo_Location PROTOBUF_FINAL :
+class PROTOBUF_EXPORT SourceCodeInfo_Location final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo.Location) */ {
  public:
-  inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {};
-  virtual ~SourceCodeInfo_Location();
+  inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {}
+  ~SourceCodeInfo_Location() override;
+  explicit constexpr SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
   SourceCodeInfo_Location(SourceCodeInfo_Location&& from) noexcept
@@ -6101,8 +5817,9 @@
     return *this;
   }
   inline SourceCodeInfo_Location& operator=(SourceCodeInfo_Location&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -6120,14 +5837,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const SourceCodeInfo_Location& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const SourceCodeInfo_Location& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceCodeInfo_Location* internal_default_instance() {
     return reinterpret_cast<const SourceCodeInfo_Location*>(
                &_SourceCodeInfo_Location_default_instance_);
@@ -6140,7 +5857,7 @@
   }
   inline void Swap(SourceCodeInfo_Location* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -6148,23 +5865,26 @@
   }
   void UnsafeArenaSwap(SourceCodeInfo_Location* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline SourceCodeInfo_Location* New() const final {
-    return CreateMaybeMessage<SourceCodeInfo_Location>(nullptr);
+    return new SourceCodeInfo_Location();
   }
 
   SourceCodeInfo_Location* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<SourceCodeInfo_Location>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const SourceCodeInfo_Location& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const SourceCodeInfo_Location& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -6175,8 +5895,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(SourceCodeInfo_Location* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -6184,20 +5904,17 @@
     return "google.protobuf.SourceCodeInfo.Location";
   }
   protected:
-  explicit SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -6285,25 +6002,14 @@
   public:
   void clear_leading_comments();
   const std::string& leading_comments() const;
-  void set_leading_comments(const std::string& value);
-  void set_leading_comments(std::string&& value);
-  void set_leading_comments(const char* value);
-  void set_leading_comments(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_leading_comments(ArgT0&& arg0, ArgT... args);
   std::string* mutable_leading_comments();
-  std::string* release_leading_comments();
+  PROTOBUF_MUST_USE_RESULT std::string* release_leading_comments();
   void set_allocated_leading_comments(std::string* leading_comments);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_leading_comments();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_leading_comments(
-      std::string* leading_comments);
   private:
   const std::string& _internal_leading_comments() const;
-  void _internal_set_leading_comments(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_leading_comments(const std::string& value);
   std::string* _internal_mutable_leading_comments();
   public:
 
@@ -6314,25 +6020,14 @@
   public:
   void clear_trailing_comments();
   const std::string& trailing_comments() const;
-  void set_trailing_comments(const std::string& value);
-  void set_trailing_comments(std::string&& value);
-  void set_trailing_comments(const char* value);
-  void set_trailing_comments(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_trailing_comments(ArgT0&& arg0, ArgT... args);
   std::string* mutable_trailing_comments();
-  std::string* release_trailing_comments();
+  PROTOBUF_MUST_USE_RESULT std::string* release_trailing_comments();
   void set_allocated_trailing_comments(std::string* trailing_comments);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_trailing_comments();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_trailing_comments(
-      std::string* trailing_comments);
   private:
   const std::string& _internal_trailing_comments() const;
-  void _internal_set_trailing_comments(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_trailing_comments(const std::string& value);
   std::string* _internal_mutable_trailing_comments();
   public:
 
@@ -6356,11 +6051,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL :
+class PROTOBUF_EXPORT SourceCodeInfo final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo) */ {
  public:
-  inline SourceCodeInfo() : SourceCodeInfo(nullptr) {};
-  virtual ~SourceCodeInfo();
+  inline SourceCodeInfo() : SourceCodeInfo(nullptr) {}
+  ~SourceCodeInfo() override;
+  explicit constexpr SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo(const SourceCodeInfo& from);
   SourceCodeInfo(SourceCodeInfo&& from) noexcept
@@ -6373,8 +6069,9 @@
     return *this;
   }
   inline SourceCodeInfo& operator=(SourceCodeInfo&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -6392,14 +6089,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const SourceCodeInfo& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const SourceCodeInfo& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceCodeInfo* internal_default_instance() {
     return reinterpret_cast<const SourceCodeInfo*>(
                &_SourceCodeInfo_default_instance_);
@@ -6412,7 +6109,7 @@
   }
   inline void Swap(SourceCodeInfo* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -6420,23 +6117,26 @@
   }
   void UnsafeArenaSwap(SourceCodeInfo* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline SourceCodeInfo* New() const final {
-    return CreateMaybeMessage<SourceCodeInfo>(nullptr);
+    return new SourceCodeInfo();
   }
 
   SourceCodeInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<SourceCodeInfo>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const SourceCodeInfo& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const SourceCodeInfo& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -6447,8 +6147,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(SourceCodeInfo* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -6456,20 +6156,17 @@
     return "google.protobuf.SourceCodeInfo";
   }
   protected:
-  explicit SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -6511,11 +6208,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation PROTOBUF_FINAL :
+class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo.Annotation) */ {
  public:
-  inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {};
-  virtual ~GeneratedCodeInfo_Annotation();
+  inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {}
+  ~GeneratedCodeInfo_Annotation() override;
+  explicit constexpr GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from);
   GeneratedCodeInfo_Annotation(GeneratedCodeInfo_Annotation&& from) noexcept
@@ -6528,8 +6226,9 @@
     return *this;
   }
   inline GeneratedCodeInfo_Annotation& operator=(GeneratedCodeInfo_Annotation&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -6547,14 +6246,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const GeneratedCodeInfo_Annotation& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const GeneratedCodeInfo_Annotation& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const GeneratedCodeInfo_Annotation* internal_default_instance() {
     return reinterpret_cast<const GeneratedCodeInfo_Annotation*>(
                &_GeneratedCodeInfo_Annotation_default_instance_);
@@ -6567,7 +6266,7 @@
   }
   inline void Swap(GeneratedCodeInfo_Annotation* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -6575,23 +6274,26 @@
   }
   void UnsafeArenaSwap(GeneratedCodeInfo_Annotation* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline GeneratedCodeInfo_Annotation* New() const final {
-    return CreateMaybeMessage<GeneratedCodeInfo_Annotation>(nullptr);
+    return new GeneratedCodeInfo_Annotation();
   }
 
   GeneratedCodeInfo_Annotation* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<GeneratedCodeInfo_Annotation>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const GeneratedCodeInfo_Annotation& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const GeneratedCodeInfo_Annotation& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -6602,8 +6304,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(GeneratedCodeInfo_Annotation* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -6611,20 +6313,17 @@
     return "google.protobuf.GeneratedCodeInfo.Annotation";
   }
   protected:
-  explicit GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -6665,25 +6364,14 @@
   public:
   void clear_source_file();
   const std::string& source_file() const;
-  void set_source_file(const std::string& value);
-  void set_source_file(std::string&& value);
-  void set_source_file(const char* value);
-  void set_source_file(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_source_file(ArgT0&& arg0, ArgT... args);
   std::string* mutable_source_file();
-  std::string* release_source_file();
+  PROTOBUF_MUST_USE_RESULT std::string* release_source_file();
   void set_allocated_source_file(std::string* source_file);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_source_file();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_source_file(
-      std::string* source_file);
   private:
   const std::string& _internal_source_file() const;
-  void _internal_set_source_file(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_source_file(const std::string& value);
   std::string* _internal_mutable_source_file();
   public:
 
@@ -6731,11 +6419,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL :
+class PROTOBUF_EXPORT GeneratedCodeInfo final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo) */ {
  public:
-  inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {};
-  virtual ~GeneratedCodeInfo();
+  inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {}
+  ~GeneratedCodeInfo() override;
+  explicit constexpr GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo(const GeneratedCodeInfo& from);
   GeneratedCodeInfo(GeneratedCodeInfo&& from) noexcept
@@ -6748,8 +6437,9 @@
     return *this;
   }
   inline GeneratedCodeInfo& operator=(GeneratedCodeInfo&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -6767,14 +6457,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const GeneratedCodeInfo& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const GeneratedCodeInfo& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const GeneratedCodeInfo* internal_default_instance() {
     return reinterpret_cast<const GeneratedCodeInfo*>(
                &_GeneratedCodeInfo_default_instance_);
@@ -6787,7 +6477,7 @@
   }
   inline void Swap(GeneratedCodeInfo* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -6795,23 +6485,26 @@
   }
   void UnsafeArenaSwap(GeneratedCodeInfo* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline GeneratedCodeInfo* New() const final {
-    return CreateMaybeMessage<GeneratedCodeInfo>(nullptr);
+    return new GeneratedCodeInfo();
   }
 
   GeneratedCodeInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<GeneratedCodeInfo>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const GeneratedCodeInfo& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const GeneratedCodeInfo& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -6822,8 +6515,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(GeneratedCodeInfo* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -6831,20 +6524,17 @@
     return "google.protobuf.GeneratedCodeInfo";
   }
   protected:
-  explicit GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -6925,8 +6615,9 @@
   return file_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* FileDescriptorSet::add_file() {
+  PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _add = _internal_add_file();
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
-  return _internal_add_file();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >&
 FileDescriptorSet::file() const {
@@ -6947,51 +6638,35 @@
   return _internal_has_name();
 }
 inline void FileDescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& FileDescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
   return _internal_name();
 }
-inline void FileDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name)
 }
 inline std::string* FileDescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& FileDescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void FileDescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.name)
-}
-inline void FileDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
-}
-inline void FileDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name)
@@ -6999,7 +6674,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileDescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -7008,28 +6683,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
 }
-inline std::string* FileDescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileDescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileDescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.name)
-}
 
 // optional string package = 2;
 inline bool FileDescriptorProto::_internal_has_package() const {
@@ -7040,51 +6696,35 @@
   return _internal_has_package();
 }
 inline void FileDescriptorProto::clear_package() {
-  package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  package_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000002u;
 }
 inline const std::string& FileDescriptorProto::package() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
   return _internal_package();
 }
-inline void FileDescriptorProto::set_package(const std::string& value) {
-  _internal_set_package(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileDescriptorProto::set_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package)
 }
 inline std::string* FileDescriptorProto::mutable_package() {
+  std::string* _s = _internal_mutable_package();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package)
-  return _internal_mutable_package();
+  return _s;
 }
 inline const std::string& FileDescriptorProto::_internal_package() const {
   return package_.Get();
 }
 inline void FileDescriptorProto::_internal_set_package(const std::string& value) {
   _has_bits_[0] |= 0x00000002u;
-  package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileDescriptorProto::set_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  package_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.package)
-}
-inline void FileDescriptorProto::set_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
-}
-inline void FileDescriptorProto::set_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
+  package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileDescriptorProto::_internal_mutable_package() {
   _has_bits_[0] |= 0x00000002u;
-  return package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileDescriptorProto::release_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package)
@@ -7092,7 +6732,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000002u;
-  return package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileDescriptorProto::set_allocated_package(std::string* package) {
   if (package != nullptr) {
@@ -7101,28 +6741,9 @@
     _has_bits_[0] &= ~0x00000002u;
   }
   package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), package,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
 }
-inline std::string* FileDescriptorProto::unsafe_arena_release_package() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileDescriptorProto.package)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000002u;
-  return package_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileDescriptorProto::unsafe_arena_set_allocated_package(
-    std::string* package) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (package != nullptr) {
-    _has_bits_[0] |= 0x00000002u;
-  } else {
-    _has_bits_[0] &= ~0x00000002u;
-  }
-  package_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      package, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.package)
-}
 
 // repeated string dependency = 3;
 inline int FileDescriptorProto::_internal_dependency_size() const {
@@ -7135,8 +6756,9 @@
   dependency_.Clear();
 }
 inline std::string* FileDescriptorProto::add_dependency() {
+  std::string* _s = _internal_add_dependency();
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency)
-  return _internal_add_dependency();
+  return _s;
 }
 inline const std::string& FileDescriptorProto::_internal_dependency(int index) const {
   return dependency_.Get(index);
@@ -7150,12 +6772,12 @@
   return dependency_.Mutable(index);
 }
 inline void FileDescriptorProto::set_dependency(int index, const std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
   dependency_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
 }
 inline void FileDescriptorProto::set_dependency(int index, std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
   dependency_.Mutable(index)->assign(std::move(value));
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
 }
 inline void FileDescriptorProto::set_dependency(int index, const char* value) {
   GOOGLE_DCHECK(value != nullptr);
@@ -7322,8 +6944,9 @@
   return message_type_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::DescriptorProto* FileDescriptorProto::add_message_type() {
+  PROTOBUF_NAMESPACE_ID::DescriptorProto* _add = _internal_add_message_type();
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
-  return _internal_add_message_type();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >&
 FileDescriptorProto::message_type() const {
@@ -7361,8 +6984,9 @@
   return enum_type_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
+  PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _add = _internal_add_enum_type();
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
-  return _internal_add_enum_type();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >&
 FileDescriptorProto::enum_type() const {
@@ -7400,8 +7024,9 @@
   return service_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* FileDescriptorProto::add_service() {
+  PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* _add = _internal_add_service();
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
-  return _internal_add_service();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >&
 FileDescriptorProto::service() const {
@@ -7439,8 +7064,9 @@
   return extension_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* FileDescriptorProto::add_extension() {
+  PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _add = _internal_add_extension();
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
-  return _internal_add_extension();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >&
 FileDescriptorProto::extension() const {
@@ -7463,8 +7089,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::FileOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::FileOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::FileOptions&>(
+      PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
@@ -7472,7 +7098,7 @@
 }
 inline void FileDescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::FileOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -7484,10 +7110,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000008u;
+  PROTOBUF_NAMESPACE_ID::FileOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::unsafe_arena_release_options() {
@@ -7500,23 +7134,24 @@
 inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000008u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::FileOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::FileOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::FileOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void FileDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::FileOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::FileOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -7544,8 +7179,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::_internal_source_code_info() const {
   const PROTOBUF_NAMESPACE_ID::SourceCodeInfo* p = source_code_info_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceCodeInfo*>(
-      &PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceCodeInfo&>(
+      PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
@@ -7553,7 +7188,7 @@
 }
 inline void FileDescriptorProto::unsafe_arena_set_allocated_source_code_info(
     PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_code_info_);
   }
   source_code_info_ = source_code_info;
@@ -7565,10 +7200,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
 }
 inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
-  auto temp = unsafe_arena_release_source_code_info();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000010u;
+  PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = source_code_info_;
+  source_code_info_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::unsafe_arena_release_source_code_info() {
@@ -7581,23 +7224,24 @@
 inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::_internal_mutable_source_code_info() {
   _has_bits_[0] |= 0x00000010u;
   if (source_code_info_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(GetArenaForAllocation());
     source_code_info_ = p;
   }
   return source_code_info_;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+  PROTOBUF_NAMESPACE_ID::SourceCodeInfo* _msg = _internal_mutable_source_code_info();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
-  return _internal_mutable_source_code_info();
+  return _msg;
 }
 inline void FileDescriptorProto::set_allocated_source_code_info(PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete source_code_info_;
   }
   if (source_code_info) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(source_code_info);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::SourceCodeInfo>::GetOwningArena(source_code_info);
     if (message_arena != submessage_arena) {
       source_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_code_info, submessage_arena);
@@ -7619,51 +7263,35 @@
   return _internal_has_syntax();
 }
 inline void FileDescriptorProto::clear_syntax() {
-  syntax_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  syntax_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000004u;
 }
 inline const std::string& FileDescriptorProto::syntax() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
   return _internal_syntax();
 }
-inline void FileDescriptorProto::set_syntax(const std::string& value) {
-  _internal_set_syntax(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileDescriptorProto::set_syntax(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
 }
 inline std::string* FileDescriptorProto::mutable_syntax() {
+  std::string* _s = _internal_mutable_syntax();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax)
-  return _internal_mutable_syntax();
+  return _s;
 }
 inline const std::string& FileDescriptorProto::_internal_syntax() const {
   return syntax_.Get();
 }
 inline void FileDescriptorProto::_internal_set_syntax(const std::string& value) {
   _has_bits_[0] |= 0x00000004u;
-  syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileDescriptorProto::set_syntax(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  syntax_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.syntax)
-}
-inline void FileDescriptorProto::set_syntax(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
-}
-inline void FileDescriptorProto::set_syntax(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
+  syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileDescriptorProto::_internal_mutable_syntax() {
   _has_bits_[0] |= 0x00000004u;
-  return syntax_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return syntax_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileDescriptorProto::release_syntax() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax)
@@ -7671,7 +7299,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000004u;
-  return syntax_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return syntax_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileDescriptorProto::set_allocated_syntax(std::string* syntax) {
   if (syntax != nullptr) {
@@ -7680,28 +7308,9 @@
     _has_bits_[0] &= ~0x00000004u;
   }
   syntax_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), syntax,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
 }
-inline std::string* FileDescriptorProto::unsafe_arena_release_syntax() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileDescriptorProto.syntax)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000004u;
-  return syntax_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileDescriptorProto::unsafe_arena_set_allocated_syntax(
-    std::string* syntax) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (syntax != nullptr) {
-    _has_bits_[0] |= 0x00000004u;
-  } else {
-    _has_bits_[0] &= ~0x00000004u;
-  }
-  syntax_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      syntax, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.syntax)
-}
 
 // -------------------------------------------------------------------
 
@@ -7778,8 +7387,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions&>(
+      PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.options)
@@ -7787,7 +7396,7 @@
 }
 inline void DescriptorProto_ExtensionRange::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -7799,10 +7408,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options)
 }
 inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000001u;
+  PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::unsafe_arena_release_options() {
@@ -7815,23 +7432,24 @@
 inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000001u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.ExtensionRange.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void DescriptorProto_ExtensionRange::set_allocated_options(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -7917,51 +7535,35 @@
   return _internal_has_name();
 }
 inline void DescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& DescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
   return _internal_name();
 }
-inline void DescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void DescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name)
 }
 inline std::string* DescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& DescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void DescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void DescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.DescriptorProto.name)
-}
-inline void DescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
-}
-inline void DescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* DescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* DescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name)
@@ -7969,7 +7571,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void DescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -7978,28 +7580,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
 }
-inline std::string* DescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.DescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void DescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.name)
-}
 
 // repeated .google.protobuf.FieldDescriptorProto field = 2;
 inline int DescriptorProto::_internal_field_size() const {
@@ -8031,8 +7614,9 @@
   return field_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::add_field() {
+  PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _add = _internal_add_field();
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
-  return _internal_add_field();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >&
 DescriptorProto::field() const {
@@ -8070,8 +7654,9 @@
   return extension_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::add_extension() {
+  PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _add = _internal_add_extension();
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
-  return _internal_add_extension();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >&
 DescriptorProto::extension() const {
@@ -8109,8 +7694,9 @@
   return nested_type_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::DescriptorProto* DescriptorProto::add_nested_type() {
+  PROTOBUF_NAMESPACE_ID::DescriptorProto* _add = _internal_add_nested_type();
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
-  return _internal_add_nested_type();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >&
 DescriptorProto::nested_type() const {
@@ -8148,8 +7734,9 @@
   return enum_type_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* DescriptorProto::add_enum_type() {
+  PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _add = _internal_add_enum_type();
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
-  return _internal_add_enum_type();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >&
 DescriptorProto::enum_type() const {
@@ -8187,8 +7774,9 @@
   return extension_range_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
+  PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* _add = _internal_add_extension_range();
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
-  return _internal_add_extension_range();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >&
 DescriptorProto::extension_range() const {
@@ -8226,8 +7814,9 @@
   return oneof_decl_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
+  PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* _add = _internal_add_oneof_decl();
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
-  return _internal_add_oneof_decl();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >&
 DescriptorProto::oneof_decl() const {
@@ -8250,8 +7839,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::MessageOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::MessageOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::MessageOptions&>(
+      PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
@@ -8259,7 +7848,7 @@
 }
 inline void DescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::MessageOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -8271,10 +7860,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000002u;
+  PROTOBUF_NAMESPACE_ID::MessageOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::unsafe_arena_release_options() {
@@ -8287,23 +7884,24 @@
 inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000002u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::MessageOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::MessageOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::MessageOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void DescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::MessageOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::MessageOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -8346,8 +7944,9 @@
   return reserved_range_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+  PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* _add = _internal_add_reserved_range();
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
-  return _internal_add_reserved_range();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >&
 DescriptorProto::reserved_range() const {
@@ -8366,8 +7965,9 @@
   reserved_name_.Clear();
 }
 inline std::string* DescriptorProto::add_reserved_name() {
+  std::string* _s = _internal_add_reserved_name();
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name)
-  return _internal_add_reserved_name();
+  return _s;
 }
 inline const std::string& DescriptorProto::_internal_reserved_name(int index) const {
   return reserved_name_.Get(index);
@@ -8381,12 +7981,12 @@
   return reserved_name_.Mutable(index);
 }
 inline void DescriptorProto::set_reserved_name(int index, const std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
   reserved_name_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
 }
 inline void DescriptorProto::set_reserved_name(int index, std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
   reserved_name_.Mutable(index)->assign(std::move(value));
+  // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
 }
 inline void DescriptorProto::set_reserved_name(int index, const char* value) {
   GOOGLE_DCHECK(value != nullptr);
@@ -8463,8 +8063,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ExtensionRangeOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 ExtensionRangeOptions::uninterpreted_option() const {
@@ -8485,51 +8086,35 @@
   return _internal_has_name();
 }
 inline void FieldDescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& FieldDescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
   return _internal_name();
 }
-inline void FieldDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FieldDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name)
 }
 inline std::string* FieldDescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& FieldDescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void FieldDescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FieldDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.name)
-}
-inline void FieldDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
-}
-inline void FieldDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name)
@@ -8537,7 +8122,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FieldDescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -8546,28 +8131,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
 }
-inline std::string* FieldDescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FieldDescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FieldDescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.name)
-}
 
 // optional int32 number = 3;
 inline bool FieldDescriptorProto::_internal_has_number() const {
@@ -8664,51 +8230,35 @@
   return _internal_has_type_name();
 }
 inline void FieldDescriptorProto::clear_type_name() {
-  type_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  type_name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000004u;
 }
 inline const std::string& FieldDescriptorProto::type_name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name)
   return _internal_type_name();
 }
-inline void FieldDescriptorProto::set_type_name(const std::string& value) {
-  _internal_set_type_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FieldDescriptorProto::set_type_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name)
 }
 inline std::string* FieldDescriptorProto::mutable_type_name() {
+  std::string* _s = _internal_mutable_type_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name)
-  return _internal_mutable_type_name();
+  return _s;
 }
 inline const std::string& FieldDescriptorProto::_internal_type_name() const {
   return type_name_.Get();
 }
 inline void FieldDescriptorProto::_internal_set_type_name(const std::string& value) {
   _has_bits_[0] |= 0x00000004u;
-  type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FieldDescriptorProto::set_type_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  type_name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.type_name)
-}
-inline void FieldDescriptorProto::set_type_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
-}
-inline void FieldDescriptorProto::set_type_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
+  type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::_internal_mutable_type_name() {
   _has_bits_[0] |= 0x00000004u;
-  return type_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return type_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::release_type_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name)
@@ -8716,7 +8266,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000004u;
-  return type_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return type_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FieldDescriptorProto::set_allocated_type_name(std::string* type_name) {
   if (type_name != nullptr) {
@@ -8725,28 +8275,9 @@
     _has_bits_[0] &= ~0x00000004u;
   }
   type_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
 }
-inline std::string* FieldDescriptorProto::unsafe_arena_release_type_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FieldDescriptorProto.type_name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000004u;
-  return type_name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FieldDescriptorProto::unsafe_arena_set_allocated_type_name(
-    std::string* type_name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (type_name != nullptr) {
-    _has_bits_[0] |= 0x00000004u;
-  } else {
-    _has_bits_[0] &= ~0x00000004u;
-  }
-  type_name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      type_name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
-}
 
 // optional string extendee = 2;
 inline bool FieldDescriptorProto::_internal_has_extendee() const {
@@ -8757,51 +8288,35 @@
   return _internal_has_extendee();
 }
 inline void FieldDescriptorProto::clear_extendee() {
-  extendee_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  extendee_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000002u;
 }
 inline const std::string& FieldDescriptorProto::extendee() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
   return _internal_extendee();
 }
-inline void FieldDescriptorProto::set_extendee(const std::string& value) {
-  _internal_set_extendee(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FieldDescriptorProto::set_extendee(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee)
 }
 inline std::string* FieldDescriptorProto::mutable_extendee() {
+  std::string* _s = _internal_mutable_extendee();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee)
-  return _internal_mutable_extendee();
+  return _s;
 }
 inline const std::string& FieldDescriptorProto::_internal_extendee() const {
   return extendee_.Get();
 }
 inline void FieldDescriptorProto::_internal_set_extendee(const std::string& value) {
   _has_bits_[0] |= 0x00000002u;
-  extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FieldDescriptorProto::set_extendee(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  extendee_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.extendee)
-}
-inline void FieldDescriptorProto::set_extendee(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
-}
-inline void FieldDescriptorProto::set_extendee(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
+  extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::_internal_mutable_extendee() {
   _has_bits_[0] |= 0x00000002u;
-  return extendee_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return extendee_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::release_extendee() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee)
@@ -8809,7 +8324,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000002u;
-  return extendee_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return extendee_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FieldDescriptorProto::set_allocated_extendee(std::string* extendee) {
   if (extendee != nullptr) {
@@ -8818,28 +8333,9 @@
     _has_bits_[0] &= ~0x00000002u;
   }
   extendee_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), extendee,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
 }
-inline std::string* FieldDescriptorProto::unsafe_arena_release_extendee() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FieldDescriptorProto.extendee)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000002u;
-  return extendee_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FieldDescriptorProto::unsafe_arena_set_allocated_extendee(
-    std::string* extendee) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (extendee != nullptr) {
-    _has_bits_[0] |= 0x00000002u;
-  } else {
-    _has_bits_[0] &= ~0x00000002u;
-  }
-  extendee_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      extendee, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
-}
 
 // optional string default_value = 7;
 inline bool FieldDescriptorProto::_internal_has_default_value() const {
@@ -8850,51 +8346,35 @@
   return _internal_has_default_value();
 }
 inline void FieldDescriptorProto::clear_default_value() {
-  default_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  default_value_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000008u;
 }
 inline const std::string& FieldDescriptorProto::default_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value)
   return _internal_default_value();
 }
-inline void FieldDescriptorProto::set_default_value(const std::string& value) {
-  _internal_set_default_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FieldDescriptorProto::set_default_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000008u;
+ default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value)
 }
 inline std::string* FieldDescriptorProto::mutable_default_value() {
+  std::string* _s = _internal_mutable_default_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value)
-  return _internal_mutable_default_value();
+  return _s;
 }
 inline const std::string& FieldDescriptorProto::_internal_default_value() const {
   return default_value_.Get();
 }
 inline void FieldDescriptorProto::_internal_set_default_value(const std::string& value) {
   _has_bits_[0] |= 0x00000008u;
-  default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FieldDescriptorProto::set_default_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000008u;
-  default_value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.default_value)
-}
-inline void FieldDescriptorProto::set_default_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000008u;
-  default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
-}
-inline void FieldDescriptorProto::set_default_value(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000008u;
-  default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
+  default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::_internal_mutable_default_value() {
   _has_bits_[0] |= 0x00000008u;
-  return default_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return default_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::release_default_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value)
@@ -8902,7 +8382,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000008u;
-  return default_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return default_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FieldDescriptorProto::set_allocated_default_value(std::string* default_value) {
   if (default_value != nullptr) {
@@ -8911,28 +8391,9 @@
     _has_bits_[0] &= ~0x00000008u;
   }
   default_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), default_value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
 }
-inline std::string* FieldDescriptorProto::unsafe_arena_release_default_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FieldDescriptorProto.default_value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000008u;
-  return default_value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FieldDescriptorProto::unsafe_arena_set_allocated_default_value(
-    std::string* default_value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (default_value != nullptr) {
-    _has_bits_[0] |= 0x00000008u;
-  } else {
-    _has_bits_[0] &= ~0x00000008u;
-  }
-  default_value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      default_value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
-}
 
 // optional int32 oneof_index = 9;
 inline bool FieldDescriptorProto::_internal_has_oneof_index() const {
@@ -8971,51 +8432,35 @@
   return _internal_has_json_name();
 }
 inline void FieldDescriptorProto::clear_json_name() {
-  json_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  json_name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000010u;
 }
 inline const std::string& FieldDescriptorProto::json_name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
   return _internal_json_name();
 }
-inline void FieldDescriptorProto::set_json_name(const std::string& value) {
-  _internal_set_json_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FieldDescriptorProto::set_json_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000010u;
+ json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
 }
 inline std::string* FieldDescriptorProto::mutable_json_name() {
+  std::string* _s = _internal_mutable_json_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name)
-  return _internal_mutable_json_name();
+  return _s;
 }
 inline const std::string& FieldDescriptorProto::_internal_json_name() const {
   return json_name_.Get();
 }
 inline void FieldDescriptorProto::_internal_set_json_name(const std::string& value) {
   _has_bits_[0] |= 0x00000010u;
-  json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FieldDescriptorProto::set_json_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000010u;
-  json_name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.json_name)
-}
-inline void FieldDescriptorProto::set_json_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000010u;
-  json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
-}
-inline void FieldDescriptorProto::set_json_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000010u;
-  json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
+  json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::_internal_mutable_json_name() {
   _has_bits_[0] |= 0x00000010u;
-  return json_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return json_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FieldDescriptorProto::release_json_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name)
@@ -9023,7 +8468,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000010u;
-  return json_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return json_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FieldDescriptorProto::set_allocated_json_name(std::string* json_name) {
   if (json_name != nullptr) {
@@ -9032,28 +8477,9 @@
     _has_bits_[0] &= ~0x00000010u;
   }
   json_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), json_name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
 }
-inline std::string* FieldDescriptorProto::unsafe_arena_release_json_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FieldDescriptorProto.json_name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000010u;
-  return json_name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FieldDescriptorProto::unsafe_arena_set_allocated_json_name(
-    std::string* json_name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (json_name != nullptr) {
-    _has_bits_[0] |= 0x00000010u;
-  } else {
-    _has_bits_[0] &= ~0x00000010u;
-  }
-  json_name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      json_name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
-}
 
 // optional .google.protobuf.FieldOptions options = 8;
 inline bool FieldDescriptorProto::_internal_has_options() const {
@@ -9070,8 +8496,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::FieldOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::FieldOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::FieldOptions&>(
+      PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
@@ -9079,7 +8505,7 @@
 }
 inline void FieldDescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::FieldOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -9091,10 +8517,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000020u;
+  PROTOBUF_NAMESPACE_ID::FieldOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::unsafe_arena_release_options() {
@@ -9107,23 +8541,24 @@
 inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000020u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::FieldOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::FieldOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::FieldOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void FieldDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::FieldOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::FieldOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -9177,51 +8612,35 @@
   return _internal_has_name();
 }
 inline void OneofDescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& OneofDescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
   return _internal_name();
 }
-inline void OneofDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void OneofDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name)
 }
 inline std::string* OneofDescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& OneofDescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void OneofDescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void OneofDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.OneofDescriptorProto.name)
-}
-inline void OneofDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
-}
-inline void OneofDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* OneofDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* OneofDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name)
@@ -9229,7 +8648,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void OneofDescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -9238,28 +8657,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
 }
-inline std::string* OneofDescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.OneofDescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void OneofDescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.OneofDescriptorProto.name)
-}
 
 // optional .google.protobuf.OneofOptions options = 2;
 inline bool OneofDescriptorProto::_internal_has_options() const {
@@ -9276,8 +8676,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::OneofOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::OneofOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::OneofOptions&>(
+      PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options)
@@ -9285,7 +8685,7 @@
 }
 inline void OneofDescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::OneofOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -9297,10 +8697,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.OneofDescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000002u;
+  PROTOBUF_NAMESPACE_ID::OneofOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::unsafe_arena_release_options() {
@@ -9313,23 +8721,24 @@
 inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000002u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::OneofOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::OneofOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::OneofOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void OneofDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::OneofOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::OneofOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -9415,51 +8824,35 @@
   return _internal_has_name();
 }
 inline void EnumDescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& EnumDescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
   return _internal_name();
 }
-inline void EnumDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void EnumDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
 }
 inline std::string* EnumDescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& EnumDescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void EnumDescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void EnumDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumDescriptorProto.name)
-}
-inline void EnumDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
-}
-inline void EnumDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* EnumDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* EnumDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name)
@@ -9467,7 +8860,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void EnumDescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -9476,28 +8869,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
 }
-inline std::string* EnumDescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.EnumDescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void EnumDescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumDescriptorProto.name)
-}
 
 // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
 inline int EnumDescriptorProto::_internal_value_size() const {
@@ -9529,8 +8903,9 @@
   return value_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
+  PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* _add = _internal_add_value();
   // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
-  return _internal_add_value();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >&
 EnumDescriptorProto::value() const {
@@ -9553,8 +8928,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::EnumOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::EnumOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::EnumOptions&>(
+      PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
@@ -9562,7 +8937,7 @@
 }
 inline void EnumDescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::EnumOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -9574,10 +8949,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumDescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000002u;
+  PROTOBUF_NAMESPACE_ID::EnumOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::unsafe_arena_release_options() {
@@ -9590,23 +8973,24 @@
 inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000002u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::EnumOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::EnumOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::EnumOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void EnumDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::EnumOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -9649,8 +9033,9 @@
   return reserved_range_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* EnumDescriptorProto::add_reserved_range() {
+  PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* _add = _internal_add_reserved_range();
   // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_range)
-  return _internal_add_reserved_range();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >&
 EnumDescriptorProto::reserved_range() const {
@@ -9669,8 +9054,9 @@
   reserved_name_.Clear();
 }
 inline std::string* EnumDescriptorProto::add_reserved_name() {
+  std::string* _s = _internal_add_reserved_name();
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.EnumDescriptorProto.reserved_name)
-  return _internal_add_reserved_name();
+  return _s;
 }
 inline const std::string& EnumDescriptorProto::_internal_reserved_name(int index) const {
   return reserved_name_.Get(index);
@@ -9684,12 +9070,12 @@
   return reserved_name_.Mutable(index);
 }
 inline void EnumDescriptorProto::set_reserved_name(int index, const std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name)
   reserved_name_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name)
 }
 inline void EnumDescriptorProto::set_reserved_name(int index, std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name)
   reserved_name_.Mutable(index)->assign(std::move(value));
+  // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name)
 }
 inline void EnumDescriptorProto::set_reserved_name(int index, const char* value) {
   GOOGLE_DCHECK(value != nullptr);
@@ -9745,51 +9131,35 @@
   return _internal_has_name();
 }
 inline void EnumValueDescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& EnumValueDescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
   return _internal_name();
 }
-inline void EnumValueDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void EnumValueDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name)
 }
 inline std::string* EnumValueDescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& EnumValueDescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void EnumValueDescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void EnumValueDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValueDescriptorProto.name)
-}
-inline void EnumValueDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
-}
-inline void EnumValueDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* EnumValueDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* EnumValueDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name)
@@ -9797,7 +9167,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void EnumValueDescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -9806,28 +9176,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
 }
-inline std::string* EnumValueDescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.EnumValueDescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void EnumValueDescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
-}
 
 // optional int32 number = 2;
 inline bool EnumValueDescriptorProto::_internal_has_number() const {
@@ -9872,8 +9223,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::EnumValueOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::EnumValueOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::EnumValueOptions&>(
+      PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
@@ -9881,7 +9232,7 @@
 }
 inline void EnumValueDescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::EnumValueOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -9893,10 +9244,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000002u;
+  PROTOBUF_NAMESPACE_ID::EnumValueOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::unsafe_arena_release_options() {
@@ -9909,23 +9268,24 @@
 inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000002u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::EnumValueOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::EnumValueOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::EnumValueOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void EnumValueDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumValueOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::EnumValueOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -9951,51 +9311,35 @@
   return _internal_has_name();
 }
 inline void ServiceDescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& ServiceDescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
   return _internal_name();
 }
-inline void ServiceDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void ServiceDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name)
 }
 inline std::string* ServiceDescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& ServiceDescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void ServiceDescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void ServiceDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.ServiceDescriptorProto.name)
-}
-inline void ServiceDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
-}
-inline void ServiceDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* ServiceDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* ServiceDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name)
@@ -10003,7 +9347,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void ServiceDescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -10012,28 +9356,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
 }
-inline std::string* ServiceDescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.ServiceDescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void ServiceDescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.ServiceDescriptorProto.name)
-}
 
 // repeated .google.protobuf.MethodDescriptorProto method = 2;
 inline int ServiceDescriptorProto::_internal_method_size() const {
@@ -10065,8 +9390,9 @@
   return method_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
+  PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* _add = _internal_add_method();
   // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
-  return _internal_add_method();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >&
 ServiceDescriptorProto::method() const {
@@ -10089,8 +9415,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::ServiceOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::ServiceOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::ServiceOptions&>(
+      PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
@@ -10098,7 +9424,7 @@
 }
 inline void ServiceDescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::ServiceOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -10110,10 +9436,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.ServiceDescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000002u;
+  PROTOBUF_NAMESPACE_ID::ServiceOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::unsafe_arena_release_options() {
@@ -10126,23 +9460,24 @@
 inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000002u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::ServiceOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::ServiceOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::ServiceOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void ServiceDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::ServiceOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::ServiceOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -10168,51 +9503,35 @@
   return _internal_has_name();
 }
 inline void MethodDescriptorProto::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& MethodDescriptorProto::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
   return _internal_name();
 }
-inline void MethodDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void MethodDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name)
 }
 inline std::string* MethodDescriptorProto::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& MethodDescriptorProto::_internal_name() const {
   return name_.Get();
 }
 inline void MethodDescriptorProto::_internal_set_name(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void MethodDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.name)
-}
-inline void MethodDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
-}
-inline void MethodDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* MethodDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* MethodDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name)
@@ -10220,7 +9539,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void MethodDescriptorProto::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -10229,28 +9548,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
 }
-inline std::string* MethodDescriptorProto::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.MethodDescriptorProto.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void MethodDescriptorProto::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.MethodDescriptorProto.name)
-}
 
 // optional string input_type = 2;
 inline bool MethodDescriptorProto::_internal_has_input_type() const {
@@ -10261,51 +9561,35 @@
   return _internal_has_input_type();
 }
 inline void MethodDescriptorProto::clear_input_type() {
-  input_type_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  input_type_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000002u;
 }
 inline const std::string& MethodDescriptorProto::input_type() const {
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type)
   return _internal_input_type();
 }
-inline void MethodDescriptorProto::set_input_type(const std::string& value) {
-  _internal_set_input_type(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void MethodDescriptorProto::set_input_type(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type)
 }
 inline std::string* MethodDescriptorProto::mutable_input_type() {
+  std::string* _s = _internal_mutable_input_type();
   // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type)
-  return _internal_mutable_input_type();
+  return _s;
 }
 inline const std::string& MethodDescriptorProto::_internal_input_type() const {
   return input_type_.Get();
 }
 inline void MethodDescriptorProto::_internal_set_input_type(const std::string& value) {
   _has_bits_[0] |= 0x00000002u;
-  input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void MethodDescriptorProto::set_input_type(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  input_type_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.input_type)
-}
-inline void MethodDescriptorProto::set_input_type(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
-}
-inline void MethodDescriptorProto::set_input_type(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
+  input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* MethodDescriptorProto::_internal_mutable_input_type() {
   _has_bits_[0] |= 0x00000002u;
-  return input_type_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return input_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* MethodDescriptorProto::release_input_type() {
   // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type)
@@ -10313,7 +9597,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000002u;
-  return input_type_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return input_type_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void MethodDescriptorProto::set_allocated_input_type(std::string* input_type) {
   if (input_type != nullptr) {
@@ -10322,28 +9606,9 @@
     _has_bits_[0] &= ~0x00000002u;
   }
   input_type_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), input_type,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
 }
-inline std::string* MethodDescriptorProto::unsafe_arena_release_input_type() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.MethodDescriptorProto.input_type)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000002u;
-  return input_type_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void MethodDescriptorProto::unsafe_arena_set_allocated_input_type(
-    std::string* input_type) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (input_type != nullptr) {
-    _has_bits_[0] |= 0x00000002u;
-  } else {
-    _has_bits_[0] &= ~0x00000002u;
-  }
-  input_type_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      input_type, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
-}
 
 // optional string output_type = 3;
 inline bool MethodDescriptorProto::_internal_has_output_type() const {
@@ -10354,51 +9619,35 @@
   return _internal_has_output_type();
 }
 inline void MethodDescriptorProto::clear_output_type() {
-  output_type_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  output_type_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000004u;
 }
 inline const std::string& MethodDescriptorProto::output_type() const {
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type)
   return _internal_output_type();
 }
-inline void MethodDescriptorProto::set_output_type(const std::string& value) {
-  _internal_set_output_type(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void MethodDescriptorProto::set_output_type(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type)
 }
 inline std::string* MethodDescriptorProto::mutable_output_type() {
+  std::string* _s = _internal_mutable_output_type();
   // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type)
-  return _internal_mutable_output_type();
+  return _s;
 }
 inline const std::string& MethodDescriptorProto::_internal_output_type() const {
   return output_type_.Get();
 }
 inline void MethodDescriptorProto::_internal_set_output_type(const std::string& value) {
   _has_bits_[0] |= 0x00000004u;
-  output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void MethodDescriptorProto::set_output_type(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  output_type_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.output_type)
-}
-inline void MethodDescriptorProto::set_output_type(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
-}
-inline void MethodDescriptorProto::set_output_type(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
+  output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* MethodDescriptorProto::_internal_mutable_output_type() {
   _has_bits_[0] |= 0x00000004u;
-  return output_type_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return output_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* MethodDescriptorProto::release_output_type() {
   // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type)
@@ -10406,7 +9655,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000004u;
-  return output_type_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return output_type_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void MethodDescriptorProto::set_allocated_output_type(std::string* output_type) {
   if (output_type != nullptr) {
@@ -10415,28 +9664,9 @@
     _has_bits_[0] &= ~0x00000004u;
   }
   output_type_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), output_type,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
 }
-inline std::string* MethodDescriptorProto::unsafe_arena_release_output_type() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.MethodDescriptorProto.output_type)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000004u;
-  return output_type_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void MethodDescriptorProto::unsafe_arena_set_allocated_output_type(
-    std::string* output_type) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (output_type != nullptr) {
-    _has_bits_[0] |= 0x00000004u;
-  } else {
-    _has_bits_[0] &= ~0x00000004u;
-  }
-  output_type_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      output_type, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
-}
 
 // optional .google.protobuf.MethodOptions options = 4;
 inline bool MethodDescriptorProto::_internal_has_options() const {
@@ -10453,8 +9683,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::_internal_options() const {
   const PROTOBUF_NAMESPACE_ID::MethodOptions* p = options_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::MethodOptions*>(
-      &PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::MethodOptions&>(
+      PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::options() const {
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
@@ -10462,7 +9692,7 @@
 }
 inline void MethodDescriptorProto::unsafe_arena_set_allocated_options(
     PROTOBUF_NAMESPACE_ID::MethodOptions* options) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_);
   }
   options_ = options;
@@ -10474,10 +9704,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.MethodDescriptorProto.options)
 }
 inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::release_options() {
-  auto temp = unsafe_arena_release_options();
-  if (GetArena() != nullptr) {
+  _has_bits_[0] &= ~0x00000008u;
+  PROTOBUF_NAMESPACE_ID::MethodOptions* temp = options_;
+  options_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::unsafe_arena_release_options() {
@@ -10490,23 +9728,24 @@
 inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::_internal_mutable_options() {
   _has_bits_[0] |= 0x00000008u;
   if (options_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::MethodOptions>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::MethodOptions>(GetArenaForAllocation());
     options_ = p;
   }
   return options_;
 }
 inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::mutable_options() {
+  PROTOBUF_NAMESPACE_ID::MethodOptions* _msg = _internal_mutable_options();
   // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
-  return _internal_mutable_options();
+  return _msg;
 }
 inline void MethodDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::MethodOptions* options) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete options_;
   }
   if (options) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options);
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::MethodOptions>::GetOwningArena(options);
     if (message_arena != submessage_arena) {
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
@@ -10588,51 +9827,35 @@
   return _internal_has_java_package();
 }
 inline void FileOptions::clear_java_package() {
-  java_package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  java_package_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& FileOptions::java_package() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package)
   return _internal_java_package();
 }
-inline void FileOptions::set_java_package(const std::string& value) {
-  _internal_set_java_package(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_java_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package)
 }
 inline std::string* FileOptions::mutable_java_package() {
+  std::string* _s = _internal_mutable_java_package();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package)
-  return _internal_mutable_java_package();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_java_package() const {
   return java_package_.Get();
 }
 inline void FileOptions::_internal_set_java_package(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_java_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  java_package_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_package)
-}
-inline void FileOptions::set_java_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
-}
-inline void FileOptions::set_java_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
+  java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_java_package() {
   _has_bits_[0] |= 0x00000001u;
-  return java_package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return java_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_java_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package)
@@ -10640,7 +9863,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return java_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return java_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_java_package(std::string* java_package) {
   if (java_package != nullptr) {
@@ -10649,28 +9872,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   java_package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), java_package,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
 }
-inline std::string* FileOptions::unsafe_arena_release_java_package() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.java_package)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return java_package_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_java_package(
-    std::string* java_package) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (java_package != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  java_package_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      java_package, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.java_package)
-}
 
 // optional string java_outer_classname = 8;
 inline bool FileOptions::_internal_has_java_outer_classname() const {
@@ -10681,51 +9885,35 @@
   return _internal_has_java_outer_classname();
 }
 inline void FileOptions::clear_java_outer_classname() {
-  java_outer_classname_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  java_outer_classname_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000002u;
 }
 inline const std::string& FileOptions::java_outer_classname() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname)
   return _internal_java_outer_classname();
 }
-inline void FileOptions::set_java_outer_classname(const std::string& value) {
-  _internal_set_java_outer_classname(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_java_outer_classname(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname)
 }
 inline std::string* FileOptions::mutable_java_outer_classname() {
+  std::string* _s = _internal_mutable_java_outer_classname();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname)
-  return _internal_mutable_java_outer_classname();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_java_outer_classname() const {
   return java_outer_classname_.Get();
 }
 inline void FileOptions::_internal_set_java_outer_classname(const std::string& value) {
   _has_bits_[0] |= 0x00000002u;
-  java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_java_outer_classname(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  java_outer_classname_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_outer_classname)
-}
-inline void FileOptions::set_java_outer_classname(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname)
-}
-inline void FileOptions::set_java_outer_classname(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
+  java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_java_outer_classname() {
   _has_bits_[0] |= 0x00000002u;
-  return java_outer_classname_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return java_outer_classname_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_java_outer_classname() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname)
@@ -10733,7 +9921,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000002u;
-  return java_outer_classname_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return java_outer_classname_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_java_outer_classname(std::string* java_outer_classname) {
   if (java_outer_classname != nullptr) {
@@ -10742,28 +9930,9 @@
     _has_bits_[0] &= ~0x00000002u;
   }
   java_outer_classname_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), java_outer_classname,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
 }
-inline std::string* FileOptions::unsafe_arena_release_java_outer_classname() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.java_outer_classname)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000002u;
-  return java_outer_classname_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_java_outer_classname(
-    std::string* java_outer_classname) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (java_outer_classname != nullptr) {
-    _has_bits_[0] |= 0x00000002u;
-  } else {
-    _has_bits_[0] &= ~0x00000002u;
-  }
-  java_outer_classname_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      java_outer_classname, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.java_outer_classname)
-}
 
 // optional bool java_multiple_files = 10 [default = false];
 inline bool FileOptions::_internal_has_java_multiple_files() const {
@@ -10887,51 +10056,35 @@
   return _internal_has_go_package();
 }
 inline void FileOptions::clear_go_package() {
-  go_package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  go_package_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000004u;
 }
 inline const std::string& FileOptions::go_package() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package)
   return _internal_go_package();
 }
-inline void FileOptions::set_go_package(const std::string& value) {
-  _internal_set_go_package(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_go_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
 }
 inline std::string* FileOptions::mutable_go_package() {
+  std::string* _s = _internal_mutable_go_package();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package)
-  return _internal_mutable_go_package();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_go_package() const {
   return go_package_.Get();
 }
 inline void FileOptions::_internal_set_go_package(const std::string& value) {
   _has_bits_[0] |= 0x00000004u;
-  go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_go_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  go_package_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.go_package)
-}
-inline void FileOptions::set_go_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
-}
-inline void FileOptions::set_go_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
+  go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_go_package() {
   _has_bits_[0] |= 0x00000004u;
-  return go_package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return go_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_go_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package)
@@ -10939,7 +10092,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000004u;
-  return go_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return go_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_go_package(std::string* go_package) {
   if (go_package != nullptr) {
@@ -10948,28 +10101,9 @@
     _has_bits_[0] &= ~0x00000004u;
   }
   go_package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), go_package,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
 }
-inline std::string* FileOptions::unsafe_arena_release_go_package() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.go_package)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000004u;
-  return go_package_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_go_package(
-    std::string* go_package) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (go_package != nullptr) {
-    _has_bits_[0] |= 0x00000004u;
-  } else {
-    _has_bits_[0] &= ~0x00000004u;
-  }
-  go_package_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      go_package, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.go_package)
-}
 
 // optional bool cc_generic_services = 16 [default = false];
 inline bool FileOptions::_internal_has_cc_generic_services() const {
@@ -11148,51 +10282,35 @@
   return _internal_has_objc_class_prefix();
 }
 inline void FileOptions::clear_objc_class_prefix() {
-  objc_class_prefix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  objc_class_prefix_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000008u;
 }
 inline const std::string& FileOptions::objc_class_prefix() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
   return _internal_objc_class_prefix();
 }
-inline void FileOptions::set_objc_class_prefix(const std::string& value) {
-  _internal_set_objc_class_prefix(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_objc_class_prefix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000008u;
+ objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
 }
 inline std::string* FileOptions::mutable_objc_class_prefix() {
+  std::string* _s = _internal_mutable_objc_class_prefix();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
-  return _internal_mutable_objc_class_prefix();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_objc_class_prefix() const {
   return objc_class_prefix_.Get();
 }
 inline void FileOptions::_internal_set_objc_class_prefix(const std::string& value) {
   _has_bits_[0] |= 0x00000008u;
-  objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_objc_class_prefix(std::string&& value) {
-  _has_bits_[0] |= 0x00000008u;
-  objc_class_prefix_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.objc_class_prefix)
-}
-inline void FileOptions::set_objc_class_prefix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000008u;
-  objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
-}
-inline void FileOptions::set_objc_class_prefix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000008u;
-  objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+  objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_objc_class_prefix() {
   _has_bits_[0] |= 0x00000008u;
-  return objc_class_prefix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return objc_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_objc_class_prefix() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix)
@@ -11200,7 +10318,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000008u;
-  return objc_class_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return objc_class_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_objc_class_prefix(std::string* objc_class_prefix) {
   if (objc_class_prefix != nullptr) {
@@ -11209,28 +10327,9 @@
     _has_bits_[0] &= ~0x00000008u;
   }
   objc_class_prefix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), objc_class_prefix,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
 }
-inline std::string* FileOptions::unsafe_arena_release_objc_class_prefix() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.objc_class_prefix)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000008u;
-  return objc_class_prefix_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_objc_class_prefix(
-    std::string* objc_class_prefix) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (objc_class_prefix != nullptr) {
-    _has_bits_[0] |= 0x00000008u;
-  } else {
-    _has_bits_[0] &= ~0x00000008u;
-  }
-  objc_class_prefix_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      objc_class_prefix, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
-}
 
 // optional string csharp_namespace = 37;
 inline bool FileOptions::_internal_has_csharp_namespace() const {
@@ -11241,51 +10340,35 @@
   return _internal_has_csharp_namespace();
 }
 inline void FileOptions::clear_csharp_namespace() {
-  csharp_namespace_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  csharp_namespace_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000010u;
 }
 inline const std::string& FileOptions::csharp_namespace() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace)
   return _internal_csharp_namespace();
 }
-inline void FileOptions::set_csharp_namespace(const std::string& value) {
-  _internal_set_csharp_namespace(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_csharp_namespace(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000010u;
+ csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace)
 }
 inline std::string* FileOptions::mutable_csharp_namespace() {
+  std::string* _s = _internal_mutable_csharp_namespace();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace)
-  return _internal_mutable_csharp_namespace();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_csharp_namespace() const {
   return csharp_namespace_.Get();
 }
 inline void FileOptions::_internal_set_csharp_namespace(const std::string& value) {
   _has_bits_[0] |= 0x00000010u;
-  csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_csharp_namespace(std::string&& value) {
-  _has_bits_[0] |= 0x00000010u;
-  csharp_namespace_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.csharp_namespace)
-}
-inline void FileOptions::set_csharp_namespace(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000010u;
-  csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace)
-}
-inline void FileOptions::set_csharp_namespace(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000010u;
-  csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace)
+  csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_csharp_namespace() {
   _has_bits_[0] |= 0x00000010u;
-  return csharp_namespace_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return csharp_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_csharp_namespace() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace)
@@ -11293,7 +10376,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000010u;
-  return csharp_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return csharp_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_csharp_namespace(std::string* csharp_namespace) {
   if (csharp_namespace != nullptr) {
@@ -11302,28 +10385,9 @@
     _has_bits_[0] &= ~0x00000010u;
   }
   csharp_namespace_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), csharp_namespace,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
 }
-inline std::string* FileOptions::unsafe_arena_release_csharp_namespace() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.csharp_namespace)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000010u;
-  return csharp_namespace_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_csharp_namespace(
-    std::string* csharp_namespace) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (csharp_namespace != nullptr) {
-    _has_bits_[0] |= 0x00000010u;
-  } else {
-    _has_bits_[0] &= ~0x00000010u;
-  }
-  csharp_namespace_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      csharp_namespace, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.csharp_namespace)
-}
 
 // optional string swift_prefix = 39;
 inline bool FileOptions::_internal_has_swift_prefix() const {
@@ -11334,51 +10398,35 @@
   return _internal_has_swift_prefix();
 }
 inline void FileOptions::clear_swift_prefix() {
-  swift_prefix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  swift_prefix_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000020u;
 }
 inline const std::string& FileOptions::swift_prefix() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.swift_prefix)
   return _internal_swift_prefix();
 }
-inline void FileOptions::set_swift_prefix(const std::string& value) {
-  _internal_set_swift_prefix(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_swift_prefix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000020u;
+ swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.swift_prefix)
 }
 inline std::string* FileOptions::mutable_swift_prefix() {
+  std::string* _s = _internal_mutable_swift_prefix();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.swift_prefix)
-  return _internal_mutable_swift_prefix();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_swift_prefix() const {
   return swift_prefix_.Get();
 }
 inline void FileOptions::_internal_set_swift_prefix(const std::string& value) {
   _has_bits_[0] |= 0x00000020u;
-  swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_swift_prefix(std::string&& value) {
-  _has_bits_[0] |= 0x00000020u;
-  swift_prefix_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.swift_prefix)
-}
-inline void FileOptions::set_swift_prefix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000020u;
-  swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.swift_prefix)
-}
-inline void FileOptions::set_swift_prefix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000020u;
-  swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.swift_prefix)
+  swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_swift_prefix() {
   _has_bits_[0] |= 0x00000020u;
-  return swift_prefix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return swift_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_swift_prefix() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.swift_prefix)
@@ -11386,7 +10434,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000020u;
-  return swift_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return swift_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_swift_prefix(std::string* swift_prefix) {
   if (swift_prefix != nullptr) {
@@ -11395,28 +10443,9 @@
     _has_bits_[0] &= ~0x00000020u;
   }
   swift_prefix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), swift_prefix,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.swift_prefix)
 }
-inline std::string* FileOptions::unsafe_arena_release_swift_prefix() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.swift_prefix)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000020u;
-  return swift_prefix_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_swift_prefix(
-    std::string* swift_prefix) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (swift_prefix != nullptr) {
-    _has_bits_[0] |= 0x00000020u;
-  } else {
-    _has_bits_[0] &= ~0x00000020u;
-  }
-  swift_prefix_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      swift_prefix, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.swift_prefix)
-}
 
 // optional string php_class_prefix = 40;
 inline bool FileOptions::_internal_has_php_class_prefix() const {
@@ -11427,51 +10456,35 @@
   return _internal_has_php_class_prefix();
 }
 inline void FileOptions::clear_php_class_prefix() {
-  php_class_prefix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  php_class_prefix_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000040u;
 }
 inline const std::string& FileOptions::php_class_prefix() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_class_prefix)
   return _internal_php_class_prefix();
 }
-inline void FileOptions::set_php_class_prefix(const std::string& value) {
-  _internal_set_php_class_prefix(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_php_class_prefix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000040u;
+ php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_class_prefix)
 }
 inline std::string* FileOptions::mutable_php_class_prefix() {
+  std::string* _s = _internal_mutable_php_class_prefix();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_class_prefix)
-  return _internal_mutable_php_class_prefix();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_php_class_prefix() const {
   return php_class_prefix_.Get();
 }
 inline void FileOptions::_internal_set_php_class_prefix(const std::string& value) {
   _has_bits_[0] |= 0x00000040u;
-  php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_php_class_prefix(std::string&& value) {
-  _has_bits_[0] |= 0x00000040u;
-  php_class_prefix_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_class_prefix)
-}
-inline void FileOptions::set_php_class_prefix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000040u;
-  php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_class_prefix)
-}
-inline void FileOptions::set_php_class_prefix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000040u;
-  php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_class_prefix)
+  php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_php_class_prefix() {
   _has_bits_[0] |= 0x00000040u;
-  return php_class_prefix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return php_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_php_class_prefix() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_class_prefix)
@@ -11479,7 +10492,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000040u;
-  return php_class_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return php_class_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_php_class_prefix(std::string* php_class_prefix) {
   if (php_class_prefix != nullptr) {
@@ -11488,28 +10501,9 @@
     _has_bits_[0] &= ~0x00000040u;
   }
   php_class_prefix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), php_class_prefix,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_class_prefix)
 }
-inline std::string* FileOptions::unsafe_arena_release_php_class_prefix() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.php_class_prefix)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000040u;
-  return php_class_prefix_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_php_class_prefix(
-    std::string* php_class_prefix) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (php_class_prefix != nullptr) {
-    _has_bits_[0] |= 0x00000040u;
-  } else {
-    _has_bits_[0] &= ~0x00000040u;
-  }
-  php_class_prefix_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      php_class_prefix, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.php_class_prefix)
-}
 
 // optional string php_namespace = 41;
 inline bool FileOptions::_internal_has_php_namespace() const {
@@ -11520,51 +10514,35 @@
   return _internal_has_php_namespace();
 }
 inline void FileOptions::clear_php_namespace() {
-  php_namespace_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  php_namespace_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000080u;
 }
 inline const std::string& FileOptions::php_namespace() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_namespace)
   return _internal_php_namespace();
 }
-inline void FileOptions::set_php_namespace(const std::string& value) {
-  _internal_set_php_namespace(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_php_namespace(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000080u;
+ php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_namespace)
 }
 inline std::string* FileOptions::mutable_php_namespace() {
+  std::string* _s = _internal_mutable_php_namespace();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_namespace)
-  return _internal_mutable_php_namespace();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_php_namespace() const {
   return php_namespace_.Get();
 }
 inline void FileOptions::_internal_set_php_namespace(const std::string& value) {
   _has_bits_[0] |= 0x00000080u;
-  php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_php_namespace(std::string&& value) {
-  _has_bits_[0] |= 0x00000080u;
-  php_namespace_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_namespace)
-}
-inline void FileOptions::set_php_namespace(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000080u;
-  php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_namespace)
-}
-inline void FileOptions::set_php_namespace(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000080u;
-  php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_namespace)
+  php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_php_namespace() {
   _has_bits_[0] |= 0x00000080u;
-  return php_namespace_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return php_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_php_namespace() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace)
@@ -11572,7 +10550,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000080u;
-  return php_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return php_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_php_namespace(std::string* php_namespace) {
   if (php_namespace != nullptr) {
@@ -11581,28 +10559,9 @@
     _has_bits_[0] &= ~0x00000080u;
   }
   php_namespace_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), php_namespace,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_namespace)
 }
-inline std::string* FileOptions::unsafe_arena_release_php_namespace() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.php_namespace)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000080u;
-  return php_namespace_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_php_namespace(
-    std::string* php_namespace) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (php_namespace != nullptr) {
-    _has_bits_[0] |= 0x00000080u;
-  } else {
-    _has_bits_[0] &= ~0x00000080u;
-  }
-  php_namespace_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      php_namespace, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.php_namespace)
-}
 
 // optional string php_metadata_namespace = 44;
 inline bool FileOptions::_internal_has_php_metadata_namespace() const {
@@ -11613,51 +10572,35 @@
   return _internal_has_php_metadata_namespace();
 }
 inline void FileOptions::clear_php_metadata_namespace() {
-  php_metadata_namespace_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  php_metadata_namespace_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000100u;
 }
 inline const std::string& FileOptions::php_metadata_namespace() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_metadata_namespace)
   return _internal_php_metadata_namespace();
 }
-inline void FileOptions::set_php_metadata_namespace(const std::string& value) {
-  _internal_set_php_metadata_namespace(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_php_metadata_namespace(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000100u;
+ php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_metadata_namespace)
 }
 inline std::string* FileOptions::mutable_php_metadata_namespace() {
+  std::string* _s = _internal_mutable_php_metadata_namespace();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_metadata_namespace)
-  return _internal_mutable_php_metadata_namespace();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_php_metadata_namespace() const {
   return php_metadata_namespace_.Get();
 }
 inline void FileOptions::_internal_set_php_metadata_namespace(const std::string& value) {
   _has_bits_[0] |= 0x00000100u;
-  php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_php_metadata_namespace(std::string&& value) {
-  _has_bits_[0] |= 0x00000100u;
-  php_metadata_namespace_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_metadata_namespace)
-}
-inline void FileOptions::set_php_metadata_namespace(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000100u;
-  php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_metadata_namespace)
-}
-inline void FileOptions::set_php_metadata_namespace(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000100u;
-  php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_metadata_namespace)
+  php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_php_metadata_namespace() {
   _has_bits_[0] |= 0x00000100u;
-  return php_metadata_namespace_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return php_metadata_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_php_metadata_namespace() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_metadata_namespace)
@@ -11665,7 +10608,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000100u;
-  return php_metadata_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return php_metadata_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_php_metadata_namespace(std::string* php_metadata_namespace) {
   if (php_metadata_namespace != nullptr) {
@@ -11674,28 +10617,9 @@
     _has_bits_[0] &= ~0x00000100u;
   }
   php_metadata_namespace_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), php_metadata_namespace,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_metadata_namespace)
 }
-inline std::string* FileOptions::unsafe_arena_release_php_metadata_namespace() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.php_metadata_namespace)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000100u;
-  return php_metadata_namespace_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_php_metadata_namespace(
-    std::string* php_metadata_namespace) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (php_metadata_namespace != nullptr) {
-    _has_bits_[0] |= 0x00000100u;
-  } else {
-    _has_bits_[0] &= ~0x00000100u;
-  }
-  php_metadata_namespace_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      php_metadata_namespace, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.php_metadata_namespace)
-}
 
 // optional string ruby_package = 45;
 inline bool FileOptions::_internal_has_ruby_package() const {
@@ -11706,51 +10630,35 @@
   return _internal_has_ruby_package();
 }
 inline void FileOptions::clear_ruby_package() {
-  ruby_package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ruby_package_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000200u;
 }
 inline const std::string& FileOptions::ruby_package() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.ruby_package)
   return _internal_ruby_package();
 }
-inline void FileOptions::set_ruby_package(const std::string& value) {
-  _internal_set_ruby_package(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileOptions::set_ruby_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000200u;
+ ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.ruby_package)
 }
 inline std::string* FileOptions::mutable_ruby_package() {
+  std::string* _s = _internal_mutable_ruby_package();
   // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.ruby_package)
-  return _internal_mutable_ruby_package();
+  return _s;
 }
 inline const std::string& FileOptions::_internal_ruby_package() const {
   return ruby_package_.Get();
 }
 inline void FileOptions::_internal_set_ruby_package(const std::string& value) {
   _has_bits_[0] |= 0x00000200u;
-  ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void FileOptions::set_ruby_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000200u;
-  ruby_package_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.ruby_package)
-}
-inline void FileOptions::set_ruby_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000200u;
-  ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.ruby_package)
-}
-inline void FileOptions::set_ruby_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000200u;
-  ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.ruby_package)
+  ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* FileOptions::_internal_mutable_ruby_package() {
   _has_bits_[0] |= 0x00000200u;
-  return ruby_package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return ruby_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* FileOptions::release_ruby_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.ruby_package)
@@ -11758,7 +10666,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000200u;
-  return ruby_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return ruby_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void FileOptions::set_allocated_ruby_package(std::string* ruby_package) {
   if (ruby_package != nullptr) {
@@ -11767,28 +10675,9 @@
     _has_bits_[0] &= ~0x00000200u;
   }
   ruby_package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ruby_package,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.ruby_package)
 }
-inline std::string* FileOptions::unsafe_arena_release_ruby_package() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.FileOptions.ruby_package)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000200u;
-  return ruby_package_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void FileOptions::unsafe_arena_set_allocated_ruby_package(
-    std::string* ruby_package) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (ruby_package != nullptr) {
-    _has_bits_[0] |= 0x00000200u;
-  } else {
-    _has_bits_[0] &= ~0x00000200u;
-  }
-  ruby_package_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      ruby_package, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileOptions.ruby_package)
-}
 
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int FileOptions::_internal_uninterpreted_option_size() const {
@@ -11820,8 +10709,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FileOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 FileOptions::uninterpreted_option() const {
@@ -11975,8 +10865,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 MessageOptions::uninterpreted_option() const {
@@ -12188,8 +11079,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 FieldOptions::uninterpreted_option() const {
@@ -12231,8 +11123,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* OneofOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.OneofOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 OneofOptions::uninterpreted_option() const {
@@ -12330,8 +11223,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 EnumOptions::uninterpreted_option() const {
@@ -12401,8 +11295,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 EnumValueOptions::uninterpreted_option() const {
@@ -12472,8 +11367,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 ServiceOptions::uninterpreted_option() const {
@@ -12572,8 +11468,9 @@
   return uninterpreted_option_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option();
   // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
-  return _internal_add_uninterpreted_option();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >&
 MethodOptions::uninterpreted_option() const {
@@ -12594,51 +11491,35 @@
   return _internal_has_name_part();
 }
 inline void UninterpretedOption_NamePart::clear_name_part() {
-  name_part_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_part_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& UninterpretedOption_NamePart::name_part() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part)
   return _internal_name_part();
 }
-inline void UninterpretedOption_NamePart::set_name_part(const std::string& value) {
-  _internal_set_name_part(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void UninterpretedOption_NamePart::set_name_part(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part)
 }
 inline std::string* UninterpretedOption_NamePart::mutable_name_part() {
+  std::string* _s = _internal_mutable_name_part();
   // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part)
-  return _internal_mutable_name_part();
+  return _s;
 }
 inline const std::string& UninterpretedOption_NamePart::_internal_name_part() const {
   return name_part_.Get();
 }
 inline void UninterpretedOption_NamePart::_internal_set_name_part(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void UninterpretedOption_NamePart::set_name_part(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_part_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.NamePart.name_part)
-}
-inline void UninterpretedOption_NamePart::set_name_part(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part)
-}
-inline void UninterpretedOption_NamePart::set_name_part(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
+  name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption_NamePart::_internal_mutable_name_part() {
   _has_bits_[0] |= 0x00000001u;
-  return name_part_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_part_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption_NamePart::release_name_part() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part)
@@ -12646,7 +11527,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return name_part_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_part_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void UninterpretedOption_NamePart::set_allocated_name_part(std::string* name_part) {
   if (name_part != nullptr) {
@@ -12655,28 +11536,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   name_part_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name_part,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
 }
-inline std::string* UninterpretedOption_NamePart::unsafe_arena_release_name_part() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.UninterpretedOption.NamePart.name_part)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return name_part_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void UninterpretedOption_NamePart::unsafe_arena_set_allocated_name_part(
-    std::string* name_part) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name_part != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  name_part_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name_part, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
-}
 
 // required bool is_extension = 2;
 inline bool UninterpretedOption_NamePart::_internal_has_is_extension() const {
@@ -12740,8 +11602,9 @@
   return name_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
+  PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* _add = _internal_add_name();
   // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
-  return _internal_add_name();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >&
 UninterpretedOption::name() const {
@@ -12758,51 +11621,35 @@
   return _internal_has_identifier_value();
 }
 inline void UninterpretedOption::clear_identifier_value() {
-  identifier_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  identifier_value_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& UninterpretedOption::identifier_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value)
   return _internal_identifier_value();
 }
-inline void UninterpretedOption::set_identifier_value(const std::string& value) {
-  _internal_set_identifier_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void UninterpretedOption::set_identifier_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value)
 }
 inline std::string* UninterpretedOption::mutable_identifier_value() {
+  std::string* _s = _internal_mutable_identifier_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value)
-  return _internal_mutable_identifier_value();
+  return _s;
 }
 inline const std::string& UninterpretedOption::_internal_identifier_value() const {
   return identifier_value_.Get();
 }
 inline void UninterpretedOption::_internal_set_identifier_value(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void UninterpretedOption::set_identifier_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  identifier_value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.identifier_value)
-}
-inline void UninterpretedOption::set_identifier_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
-}
-inline void UninterpretedOption::set_identifier_value(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
+  identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption::_internal_mutable_identifier_value() {
   _has_bits_[0] |= 0x00000001u;
-  return identifier_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return identifier_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption::release_identifier_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value)
@@ -12810,7 +11657,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return identifier_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return identifier_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void UninterpretedOption::set_allocated_identifier_value(std::string* identifier_value) {
   if (identifier_value != nullptr) {
@@ -12819,28 +11666,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   identifier_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), identifier_value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
 }
-inline std::string* UninterpretedOption::unsafe_arena_release_identifier_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.UninterpretedOption.identifier_value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return identifier_value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void UninterpretedOption::unsafe_arena_set_allocated_identifier_value(
-    std::string* identifier_value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (identifier_value != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  identifier_value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      identifier_value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
-}
 
 // optional uint64 positive_int_value = 4;
 inline bool UninterpretedOption::_internal_has_positive_int_value() const {
@@ -12851,7 +11679,7 @@
   return _internal_has_positive_int_value();
 }
 inline void UninterpretedOption::clear_positive_int_value() {
-  positive_int_value_ = PROTOBUF_ULONGLONG(0);
+  positive_int_value_ = uint64_t{0u};
   _has_bits_[0] &= ~0x00000008u;
 }
 inline ::PROTOBUF_NAMESPACE_ID::uint64 UninterpretedOption::_internal_positive_int_value() const {
@@ -12879,7 +11707,7 @@
   return _internal_has_negative_int_value();
 }
 inline void UninterpretedOption::clear_negative_int_value() {
-  negative_int_value_ = PROTOBUF_LONGLONG(0);
+  negative_int_value_ = int64_t{0};
   _has_bits_[0] &= ~0x00000010u;
 }
 inline ::PROTOBUF_NAMESPACE_ID::int64 UninterpretedOption::_internal_negative_int_value() const {
@@ -12935,51 +11763,35 @@
   return _internal_has_string_value();
 }
 inline void UninterpretedOption::clear_string_value() {
-  string_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  string_value_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000002u;
 }
 inline const std::string& UninterpretedOption::string_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value)
   return _internal_string_value();
 }
-inline void UninterpretedOption::set_string_value(const std::string& value) {
-  _internal_set_string_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void UninterpretedOption::set_string_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ string_value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value)
 }
 inline std::string* UninterpretedOption::mutable_string_value() {
+  std::string* _s = _internal_mutable_string_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value)
-  return _internal_mutable_string_value();
+  return _s;
 }
 inline const std::string& UninterpretedOption::_internal_string_value() const {
   return string_value_.Get();
 }
 inline void UninterpretedOption::_internal_set_string_value(const std::string& value) {
   _has_bits_[0] |= 0x00000002u;
-  string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void UninterpretedOption::set_string_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  string_value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.string_value)
-}
-inline void UninterpretedOption::set_string_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
-}
-inline void UninterpretedOption::set_string_value(const void* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
+  string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption::_internal_mutable_string_value() {
   _has_bits_[0] |= 0x00000002u;
-  return string_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return string_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption::release_string_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value)
@@ -12987,7 +11799,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000002u;
-  return string_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return string_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void UninterpretedOption::set_allocated_string_value(std::string* string_value) {
   if (string_value != nullptr) {
@@ -12996,28 +11808,9 @@
     _has_bits_[0] &= ~0x00000002u;
   }
   string_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), string_value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
 }
-inline std::string* UninterpretedOption::unsafe_arena_release_string_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.UninterpretedOption.string_value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000002u;
-  return string_value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void UninterpretedOption::unsafe_arena_set_allocated_string_value(
-    std::string* string_value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (string_value != nullptr) {
-    _has_bits_[0] |= 0x00000002u;
-  } else {
-    _has_bits_[0] &= ~0x00000002u;
-  }
-  string_value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      string_value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.UninterpretedOption.string_value)
-}
 
 // optional string aggregate_value = 8;
 inline bool UninterpretedOption::_internal_has_aggregate_value() const {
@@ -13028,51 +11821,35 @@
   return _internal_has_aggregate_value();
 }
 inline void UninterpretedOption::clear_aggregate_value() {
-  aggregate_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  aggregate_value_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000004u;
 }
 inline const std::string& UninterpretedOption::aggregate_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value)
   return _internal_aggregate_value();
 }
-inline void UninterpretedOption::set_aggregate_value(const std::string& value) {
-  _internal_set_aggregate_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void UninterpretedOption::set_aggregate_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
 }
 inline std::string* UninterpretedOption::mutable_aggregate_value() {
+  std::string* _s = _internal_mutable_aggregate_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value)
-  return _internal_mutable_aggregate_value();
+  return _s;
 }
 inline const std::string& UninterpretedOption::_internal_aggregate_value() const {
   return aggregate_value_.Get();
 }
 inline void UninterpretedOption::_internal_set_aggregate_value(const std::string& value) {
   _has_bits_[0] |= 0x00000004u;
-  aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void UninterpretedOption::set_aggregate_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  aggregate_value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.aggregate_value)
-}
-inline void UninterpretedOption::set_aggregate_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
-}
-inline void UninterpretedOption::set_aggregate_value(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
+  aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption::_internal_mutable_aggregate_value() {
   _has_bits_[0] |= 0x00000004u;
-  return aggregate_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return aggregate_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* UninterpretedOption::release_aggregate_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value)
@@ -13080,7 +11857,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000004u;
-  return aggregate_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return aggregate_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void UninterpretedOption::set_allocated_aggregate_value(std::string* aggregate_value) {
   if (aggregate_value != nullptr) {
@@ -13089,28 +11866,9 @@
     _has_bits_[0] &= ~0x00000004u;
   }
   aggregate_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), aggregate_value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
 }
-inline std::string* UninterpretedOption::unsafe_arena_release_aggregate_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.UninterpretedOption.aggregate_value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000004u;
-  return aggregate_value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void UninterpretedOption::unsafe_arena_set_allocated_aggregate_value(
-    std::string* aggregate_value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (aggregate_value != nullptr) {
-    _has_bits_[0] |= 0x00000004u;
-  } else {
-    _has_bits_[0] &= ~0x00000004u;
-  }
-  aggregate_value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      aggregate_value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
-}
 
 // -------------------------------------------------------------------
 
@@ -13219,51 +11977,35 @@
   return _internal_has_leading_comments();
 }
 inline void SourceCodeInfo_Location::clear_leading_comments() {
-  leading_comments_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  leading_comments_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& SourceCodeInfo_Location::leading_comments() const {
   // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments)
   return _internal_leading_comments();
 }
-inline void SourceCodeInfo_Location::set_leading_comments(const std::string& value) {
-  _internal_set_leading_comments(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void SourceCodeInfo_Location::set_leading_comments(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
 }
 inline std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+  std::string* _s = _internal_mutable_leading_comments();
   // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments)
-  return _internal_mutable_leading_comments();
+  return _s;
 }
 inline const std::string& SourceCodeInfo_Location::_internal_leading_comments() const {
   return leading_comments_.Get();
 }
 inline void SourceCodeInfo_Location::_internal_set_leading_comments(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void SourceCodeInfo_Location::set_leading_comments(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  leading_comments_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.leading_comments)
-}
-inline void SourceCodeInfo_Location::set_leading_comments(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments)
-}
-inline void SourceCodeInfo_Location::set_leading_comments(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
+  leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* SourceCodeInfo_Location::_internal_mutable_leading_comments() {
   _has_bits_[0] |= 0x00000001u;
-  return leading_comments_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return leading_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* SourceCodeInfo_Location::release_leading_comments() {
   // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments)
@@ -13271,7 +12013,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return leading_comments_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return leading_comments_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void SourceCodeInfo_Location::set_allocated_leading_comments(std::string* leading_comments) {
   if (leading_comments != nullptr) {
@@ -13280,28 +12022,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   leading_comments_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), leading_comments,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
 }
-inline std::string* SourceCodeInfo_Location::unsafe_arena_release_leading_comments() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.SourceCodeInfo.Location.leading_comments)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return leading_comments_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void SourceCodeInfo_Location::unsafe_arena_set_allocated_leading_comments(
-    std::string* leading_comments) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (leading_comments != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  leading_comments_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      leading_comments, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
-}
 
 // optional string trailing_comments = 4;
 inline bool SourceCodeInfo_Location::_internal_has_trailing_comments() const {
@@ -13312,51 +12035,35 @@
   return _internal_has_trailing_comments();
 }
 inline void SourceCodeInfo_Location::clear_trailing_comments() {
-  trailing_comments_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  trailing_comments_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000002u;
 }
 inline const std::string& SourceCodeInfo_Location::trailing_comments() const {
   // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments)
   return _internal_trailing_comments();
 }
-inline void SourceCodeInfo_Location::set_trailing_comments(const std::string& value) {
-  _internal_set_trailing_comments(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void SourceCodeInfo_Location::set_trailing_comments(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
 }
 inline std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+  std::string* _s = _internal_mutable_trailing_comments();
   // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-  return _internal_mutable_trailing_comments();
+  return _s;
 }
 inline const std::string& SourceCodeInfo_Location::_internal_trailing_comments() const {
   return trailing_comments_.Get();
 }
 inline void SourceCodeInfo_Location::_internal_set_trailing_comments(const std::string& value) {
   _has_bits_[0] |= 0x00000002u;
-  trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void SourceCodeInfo_Location::set_trailing_comments(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  trailing_comments_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-}
-inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-}
-inline void SourceCodeInfo_Location::set_trailing_comments(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+  trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* SourceCodeInfo_Location::_internal_mutable_trailing_comments() {
   _has_bits_[0] |= 0x00000002u;
-  return trailing_comments_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return trailing_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* SourceCodeInfo_Location::release_trailing_comments() {
   // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments)
@@ -13364,7 +12071,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000002u;
-  return trailing_comments_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return trailing_comments_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void SourceCodeInfo_Location::set_allocated_trailing_comments(std::string* trailing_comments) {
   if (trailing_comments != nullptr) {
@@ -13373,28 +12080,9 @@
     _has_bits_[0] &= ~0x00000002u;
   }
   trailing_comments_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), trailing_comments,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
 }
-inline std::string* SourceCodeInfo_Location::unsafe_arena_release_trailing_comments() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000002u;
-  return trailing_comments_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void SourceCodeInfo_Location::unsafe_arena_set_allocated_trailing_comments(
-    std::string* trailing_comments) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (trailing_comments != nullptr) {
-    _has_bits_[0] |= 0x00000002u;
-  } else {
-    _has_bits_[0] &= ~0x00000002u;
-  }
-  trailing_comments_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      trailing_comments, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-}
 
 // repeated string leading_detached_comments = 6;
 inline int SourceCodeInfo_Location::_internal_leading_detached_comments_size() const {
@@ -13407,8 +12095,9 @@
   leading_detached_comments_.Clear();
 }
 inline std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+  std::string* _s = _internal_add_leading_detached_comments();
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
-  return _internal_add_leading_detached_comments();
+  return _s;
 }
 inline const std::string& SourceCodeInfo_Location::_internal_leading_detached_comments(int index) const {
   return leading_detached_comments_.Get(index);
@@ -13422,12 +12111,12 @@
   return leading_detached_comments_.Mutable(index);
 }
 inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
   leading_detached_comments_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
 }
 inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
   leading_detached_comments_.Mutable(index)->assign(std::move(value));
+  // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
 }
 inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
   GOOGLE_DCHECK(value != nullptr);
@@ -13504,8 +12193,9 @@
   return location_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+  PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* _add = _internal_add_location();
   // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
-  return _internal_add_location();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >&
 SourceCodeInfo::location() const {
@@ -13573,51 +12263,35 @@
   return _internal_has_source_file();
 }
 inline void GeneratedCodeInfo_Annotation::clear_source_file() {
-  source_file_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  source_file_.ClearToEmpty();
   _has_bits_[0] &= ~0x00000001u;
 }
 inline const std::string& GeneratedCodeInfo_Annotation::source_file() const {
   // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
   return _internal_source_file();
 }
-inline void GeneratedCodeInfo_Annotation::set_source_file(const std::string& value) {
-  _internal_set_source_file(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void GeneratedCodeInfo_Annotation::set_source_file(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
 }
 inline std::string* GeneratedCodeInfo_Annotation::mutable_source_file() {
+  std::string* _s = _internal_mutable_source_file();
   // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-  return _internal_mutable_source_file();
+  return _s;
 }
 inline const std::string& GeneratedCodeInfo_Annotation::_internal_source_file() const {
   return source_file_.Get();
 }
 inline void GeneratedCodeInfo_Annotation::_internal_set_source_file(const std::string& value) {
   _has_bits_[0] |= 0x00000001u;
-  source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void GeneratedCodeInfo_Annotation::set_source_file(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  source_file_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-}
-inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-}
-inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+  source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* GeneratedCodeInfo_Annotation::_internal_mutable_source_file() {
   _has_bits_[0] |= 0x00000001u;
-  return source_file_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return source_file_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* GeneratedCodeInfo_Annotation::release_source_file() {
   // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
@@ -13625,7 +12299,7 @@
     return nullptr;
   }
   _has_bits_[0] &= ~0x00000001u;
-  return source_file_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return source_file_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(std::string* source_file) {
   if (source_file != nullptr) {
@@ -13634,28 +12308,9 @@
     _has_bits_[0] &= ~0x00000001u;
   }
   source_file_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), source_file,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
 }
-inline std::string* GeneratedCodeInfo_Annotation::unsafe_arena_release_source_file() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  _has_bits_[0] &= ~0x00000001u;
-  return source_file_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void GeneratedCodeInfo_Annotation::unsafe_arena_set_allocated_source_file(
-    std::string* source_file) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (source_file != nullptr) {
-    _has_bits_[0] |= 0x00000001u;
-  } else {
-    _has_bits_[0] &= ~0x00000001u;
-  }
-  source_file_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      source_file, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-}
 
 // optional int32 begin = 3;
 inline bool GeneratedCodeInfo_Annotation::_internal_has_begin() const {
@@ -13747,8 +12402,9 @@
   return annotation_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() {
+  PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* _add = _internal_add_annotation();
   // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation)
-  return _internal_add_annotation();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >&
 GeneratedCodeInfo::annotation() const {
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index d29fdec..156e410 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -41,7 +41,7 @@
 
 package google.protobuf;
 
-option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor";
+option go_package = "google.golang.org/protobuf/types/descriptorpb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "DescriptorProtos";
 option csharp_namespace = "Google.Protobuf.Reflection";
@@ -348,17 +348,17 @@
   optional string java_package = 1;
 
 
-  // If set, all the classes from the .proto file are wrapped in a single
-  // outer class with the given name.  This applies to both Proto1
-  // (equivalent to the old "--one_java_file" option) and Proto2 (where
-  // a .proto always translates to a single class, but you may want to
-  // explicitly choose the class name).
+  // Controls the name of the wrapper Java class generated for the .proto file.
+  // That class will always contain the .proto file's getDescriptor() method as
+  // well as any top-level extensions defined in the .proto file.
+  // If java_multiple_files is disabled, then all the other classes from the
+  // .proto file will be nested inside the single wrapper outer class.
   optional string java_outer_classname = 8;
 
-  // If set true, then the Java code generator will generate a separate .java
+  // If enabled, then the Java code generator will generate a separate .java
   // file for each top-level message, enum, and service defined in the .proto
-  // file.  Thus, these types will *not* be nested inside the outer class
-  // named by java_outer_classname.  However, the outer class will still be
+  // file.  Thus, these types will *not* be nested inside the wrapper class
+  // named by java_outer_classname.  However, the wrapper class will still be
   // generated to contain the file's getDescriptor() method as well as any
   // top-level extensions defined in the file.
   optional bool java_multiple_files = 10 [default = false];
@@ -496,6 +496,8 @@
   // this is a formalization for deprecating messages.
   optional bool deprecated = 3 [default = false];
 
+  reserved 4, 5, 6;
+
   // Whether the message is an automatically generated map entry type for the
   // maps field.
   //
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index 30f8bde..5f53cd1 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -37,10 +37,10 @@
 #include <set>
 
 #include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/stl_util.h>
 
+
 namespace google {
 namespace protobuf {
 
@@ -146,6 +146,52 @@
   return true;
 }
 
+namespace {
+
+// Returns true if and only if all characters in the name are alphanumerics,
+// underscores, or periods.
+bool ValidateSymbolName(StringPiece name) {
+  for (char c : name) {
+    // I don't trust ctype.h due to locales.  :(
+    if (c != '.' && c != '_' && (c < '0' || c > '9') && (c < 'A' || c > 'Z') &&
+        (c < 'a' || c > 'z')) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// Find the last key in the container which sorts less than or equal to the
+// symbol name.  Since upper_bound() returns the *first* key that sorts
+// *greater* than the input, we want the element immediately before that.
+template <typename Container, typename Key>
+typename Container::const_iterator FindLastLessOrEqual(
+    const Container* container, const Key& key) {
+  auto iter = container->upper_bound(key);
+  if (iter != container->begin()) --iter;
+  return iter;
+}
+
+// As above, but using std::upper_bound instead.
+template <typename Container, typename Key, typename Cmp>
+typename Container::const_iterator FindLastLessOrEqual(
+    const Container* container, const Key& key, const Cmp& cmp) {
+  auto iter = std::upper_bound(container->begin(), container->end(), key, cmp);
+  if (iter != container->begin()) --iter;
+  return iter;
+}
+
+// True if either the arguments are equal or super_symbol identifies a
+// parent symbol of sub_symbol (e.g. "foo.bar" is a parent of
+// "foo.bar.baz", but not a parent of "foo.barbaz").
+bool IsSubSymbol(StringPiece sub_symbol, StringPiece super_symbol) {
+  return sub_symbol == super_symbol ||
+         (HasPrefixString(super_symbol, sub_symbol) &&
+          super_symbol[sub_symbol.size()] == '.');
+}
+
+}  // namespace
+
 template <typename Value>
 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
     const std::string& name, Value value) {
@@ -161,8 +207,7 @@
 
   // Try to look up the symbol to make sure a super-symbol doesn't already
   // exist.
-  typename std::map<std::string, Value>::iterator iter =
-      FindLastLessOrEqual(name);
+  auto iter = FindLastLessOrEqual(&by_symbol_, name);
 
   if (iter == by_symbol_.end()) {
     // Apparently the map is currently empty.  Just insert and be done with it.
@@ -252,8 +297,7 @@
 template <typename Value>
 Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol(
     const std::string& name) {
-  typename std::map<std::string, Value>::iterator iter =
-      FindLastLessOrEqual(name);
+  auto iter = FindLastLessOrEqual(&by_symbol_, name);
 
   return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name))
              ? iter->second
@@ -294,40 +338,6 @@
   }
 }
 
-template <typename Value>
-typename std::map<std::string, Value>::iterator
-SimpleDescriptorDatabase::DescriptorIndex<Value>::FindLastLessOrEqual(
-    const std::string& name) {
-  // Find the last key in the map which sorts less than or equal to the
-  // symbol name.  Since upper_bound() returns the *first* key that sorts
-  // *greater* than the input, we want the element immediately before that.
-  typename std::map<std::string, Value>::iterator iter =
-      by_symbol_.upper_bound(name);
-  if (iter != by_symbol_.begin()) --iter;
-  return iter;
-}
-
-template <typename Value>
-bool SimpleDescriptorDatabase::DescriptorIndex<Value>::IsSubSymbol(
-    const std::string& sub_symbol, const std::string& super_symbol) {
-  return sub_symbol == super_symbol ||
-         (HasPrefixString(super_symbol, sub_symbol) &&
-          super_symbol[sub_symbol.size()] == '.');
-}
-
-template <typename Value>
-bool SimpleDescriptorDatabase::DescriptorIndex<Value>::ValidateSymbolName(
-    const std::string& name) {
-  for (int i = 0; i < name.size(); i++) {
-    // I don't trust ctype.h due to locales.  :(
-    if (name[i] != '.' && name[i] != '_' && (name[i] < '0' || name[i] > '9') &&
-        (name[i] < 'A' || name[i] > 'Z') && (name[i] < 'a' || name[i] > 'z')) {
-      return false;
-    }
-  }
-  return true;
-}
-
 // -------------------------------------------------------------------
 
 bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
@@ -378,19 +388,173 @@
 
 // -------------------------------------------------------------------
 
-EncodedDescriptorDatabase::EncodedDescriptorDatabase() {}
-EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
-  for (int i = 0; i < files_to_delete_.size(); i++) {
-    operator delete(files_to_delete_[i]);
-  }
-}
+class EncodedDescriptorDatabase::DescriptorIndex {
+ public:
+  using Value = std::pair<const void*, int>;
+  // Helpers to recursively add particular descriptors and all their contents
+  // to the index.
+  template <typename FileProto>
+  bool AddFile(const FileProto& file, Value value);
+
+  Value FindFile(StringPiece filename);
+  Value FindSymbol(StringPiece name);
+  Value FindSymbolOnlyFlat(StringPiece name) const;
+  Value FindExtension(StringPiece containing_type, int field_number);
+  bool FindAllExtensionNumbers(StringPiece containing_type,
+                               std::vector<int>* output);
+  void FindAllFileNames(std::vector<std::string>* output) const;
+
+ private:
+  friend class EncodedDescriptorDatabase;
+
+  bool AddSymbol(StringPiece symbol);
+
+  template <typename DescProto>
+  bool AddNestedExtensions(StringPiece filename,
+                           const DescProto& message_type);
+  template <typename FieldProto>
+  bool AddExtension(StringPiece filename, const FieldProto& field);
+
+  // All the maps below have two representations:
+  //  - a std::set<> where we insert initially.
+  //  - a std::vector<> where we flatten the structure on demand.
+  // The initial tree helps avoid O(N) behavior of inserting into a sorted
+  // vector, while the vector reduces the heap requirements of the data
+  // structure.
+
+  void EnsureFlat();
+
+  using String = std::string;
+
+  String EncodeString(StringPiece str) const { return String(str); }
+  StringPiece DecodeString(const String& str, int) const { return str; }
+
+  struct EncodedEntry {
+    // Do not use `Value` here to avoid the padding of that object.
+    const void* data;
+    int size;
+    // Keep the package here instead of each SymbolEntry to save space.
+    String encoded_package;
+
+    Value value() const { return {data, size}; }
+  };
+  std::vector<EncodedEntry> all_values_;
+
+  struct FileEntry {
+    int data_offset;
+    String encoded_name;
+
+    StringPiece name(const DescriptorIndex& index) const {
+      return index.DecodeString(encoded_name, data_offset);
+    }
+  };
+  struct FileCompare {
+    const DescriptorIndex& index;
+
+    bool operator()(const FileEntry& a, const FileEntry& b) const {
+      return a.name(index) < b.name(index);
+    }
+    bool operator()(const FileEntry& a, StringPiece b) const {
+      return a.name(index) < b;
+    }
+    bool operator()(StringPiece a, const FileEntry& b) const {
+      return a < b.name(index);
+    }
+  };
+  std::set<FileEntry, FileCompare> by_name_{FileCompare{*this}};
+  std::vector<FileEntry> by_name_flat_;
+
+  struct SymbolEntry {
+    int data_offset;
+    String encoded_symbol;
+
+    StringPiece package(const DescriptorIndex& index) const {
+      return index.DecodeString(index.all_values_[data_offset].encoded_package,
+                                data_offset);
+    }
+    StringPiece symbol(const DescriptorIndex& index) const {
+      return index.DecodeString(encoded_symbol, data_offset);
+    }
+
+    std::string AsString(const DescriptorIndex& index) const {
+      auto p = package(index);
+      return StrCat(p, p.empty() ? "" : ".", symbol(index));
+    }
+  };
+
+  struct SymbolCompare {
+    const DescriptorIndex& index;
+
+    std::string AsString(const SymbolEntry& entry) const {
+      return entry.AsString(index);
+    }
+    static StringPiece AsString(StringPiece str) { return str; }
+
+    std::pair<StringPiece, StringPiece> GetParts(
+        const SymbolEntry& entry) const {
+      auto package = entry.package(index);
+      if (package.empty()) return {entry.symbol(index), StringPiece{}};
+      return {package, entry.symbol(index)};
+    }
+    std::pair<StringPiece, StringPiece> GetParts(
+        StringPiece str) const {
+      return {str, {}};
+    }
+
+    template <typename T, typename U>
+    bool operator()(const T& lhs, const U& rhs) const {
+      auto lhs_parts = GetParts(lhs);
+      auto rhs_parts = GetParts(rhs);
+
+      // Fast path to avoid making the whole string for common cases.
+      if (int res =
+              lhs_parts.first.substr(0, rhs_parts.first.size())
+                  .compare(rhs_parts.first.substr(0, lhs_parts.first.size()))) {
+        // If the packages already differ, exit early.
+        return res < 0;
+      } else if (lhs_parts.first.size() == rhs_parts.first.size()) {
+        return lhs_parts.second < rhs_parts.second;
+      }
+      return AsString(lhs) < AsString(rhs);
+    }
+  };
+  std::set<SymbolEntry, SymbolCompare> by_symbol_{SymbolCompare{*this}};
+  std::vector<SymbolEntry> by_symbol_flat_;
+
+  struct ExtensionEntry {
+    int data_offset;
+    String encoded_extendee;
+    StringPiece extendee(const DescriptorIndex& index) const {
+      return index.DecodeString(encoded_extendee, data_offset).substr(1);
+    }
+    int extension_number;
+  };
+  struct ExtensionCompare {
+    const DescriptorIndex& index;
+
+    bool operator()(const ExtensionEntry& a, const ExtensionEntry& b) const {
+      return std::make_tuple(a.extendee(index), a.extension_number) <
+             std::make_tuple(b.extendee(index), b.extension_number);
+    }
+    bool operator()(const ExtensionEntry& a,
+                    std::tuple<StringPiece, int> b) const {
+      return std::make_tuple(a.extendee(index), a.extension_number) < b;
+    }
+    bool operator()(std::tuple<StringPiece, int> a,
+                    const ExtensionEntry& b) const {
+      return a < std::make_tuple(b.extendee(index), b.extension_number);
+    }
+  };
+  std::set<ExtensionEntry, ExtensionCompare> by_extension_{
+      ExtensionCompare{*this}};
+  std::vector<ExtensionEntry> by_extension_flat_;
+};
 
 bool EncodedDescriptorDatabase::Add(const void* encoded_file_descriptor,
                                     int size) {
-  google::protobuf::Arena arena;
-  auto* file = google::protobuf::Arena::CreateMessage<FileDescriptorProto>(&arena);
-  if (file->ParseFromArray(encoded_file_descriptor, size)) {
-    return index_.AddFile(*file, std::make_pair(encoded_file_descriptor, size));
+  FileDescriptorProto file;
+  if (file.ParseFromArray(encoded_file_descriptor, size)) {
+    return index_->AddFile(file, std::make_pair(encoded_file_descriptor, size));
   } else {
     GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
                   "EncodedDescriptorDatabase::Add().";
@@ -408,22 +572,22 @@
 
 bool EncodedDescriptorDatabase::FindFileByName(const std::string& filename,
                                                FileDescriptorProto* output) {
-  return MaybeParse(index_.FindFile(filename), output);
+  return MaybeParse(index_->FindFile(filename), output);
 }
 
 bool EncodedDescriptorDatabase::FindFileContainingSymbol(
     const std::string& symbol_name, FileDescriptorProto* output) {
-  return MaybeParse(index_.FindSymbol(symbol_name), output);
+  return MaybeParse(index_->FindSymbol(symbol_name), output);
 }
 
 bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
     const std::string& symbol_name, std::string* output) {
-  std::pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
+  auto encoded_file = index_->FindSymbol(symbol_name);
   if (encoded_file.first == NULL) return false;
 
   // Optimization:  The name should be the first field in the encoded message.
   //   Try to just read it directly.
-  io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
+  io::CodedInputStream input(static_cast<const uint8*>(encoded_file.first),
                              encoded_file.second);
 
   const uint32 kNameTag = internal::WireFormatLite::MakeTag(
@@ -447,18 +611,261 @@
 bool EncodedDescriptorDatabase::FindFileContainingExtension(
     const std::string& containing_type, int field_number,
     FileDescriptorProto* output) {
-  return MaybeParse(index_.FindExtension(containing_type, field_number),
+  return MaybeParse(index_->FindExtension(containing_type, field_number),
                     output);
 }
 
 bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
     const std::string& extendee_type, std::vector<int>* output) {
-  return index_.FindAllExtensionNumbers(extendee_type, output);
+  return index_->FindAllExtensionNumbers(extendee_type, output);
 }
 
+template <typename FileProto>
+bool EncodedDescriptorDatabase::DescriptorIndex::AddFile(const FileProto& file,
+                                                         Value value) {
+  // We push `value` into the array first. This is important because the AddXXX
+  // functions below will expect it to be there.
+  all_values_.push_back({value.first, value.second, {}});
+
+  if (!ValidateSymbolName(file.package())) {
+    GOOGLE_LOG(ERROR) << "Invalid package name: " << file.package();
+    return false;
+  }
+  all_values_.back().encoded_package = EncodeString(file.package());
+
+  if (!InsertIfNotPresent(
+          &by_name_, FileEntry{static_cast<int>(all_values_.size() - 1),
+                               EncodeString(file.name())}) ||
+      std::binary_search(by_name_flat_.begin(), by_name_flat_.end(),
+                         file.name(), by_name_.key_comp())) {
+    GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
+    return false;
+  }
+
+  for (const auto& message_type : file.message_type()) {
+    if (!AddSymbol(message_type.name())) return false;
+    if (!AddNestedExtensions(file.name(), message_type)) return false;
+  }
+  for (const auto& enum_type : file.enum_type()) {
+    if (!AddSymbol(enum_type.name())) return false;
+  }
+  for (const auto& extension : file.extension()) {
+    if (!AddSymbol(extension.name())) return false;
+    if (!AddExtension(file.name(), extension)) return false;
+  }
+  for (const auto& service : file.service()) {
+    if (!AddSymbol(service.name())) return false;
+  }
+
+  return true;
+}
+
+template <typename Iter, typename Iter2, typename Index>
+static bool CheckForMutualSubsymbols(StringPiece symbol_name, Iter* iter,
+                                     Iter2 end, const Index& index) {
+  if (*iter != end) {
+    if (IsSubSymbol((*iter)->AsString(index), symbol_name)) {
+      GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name
+                 << "\" conflicts with the existing symbol \""
+                 << (*iter)->AsString(index) << "\".";
+      return false;
+    }
+
+    // OK, that worked.  Now we have to make sure that no symbol in the map is
+    // a sub-symbol of the one we are inserting.  The only symbol which could
+    // be so is the first symbol that is greater than the new symbol.  Since
+    // |iter| points at the last symbol that is less than or equal, we just have
+    // to increment it.
+    ++*iter;
+
+    if (*iter != end && IsSubSymbol(symbol_name, (*iter)->AsString(index))) {
+      GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name
+                 << "\" conflicts with the existing symbol \""
+                 << (*iter)->AsString(index) << "\".";
+      return false;
+    }
+  }
+  return true;
+}
+
+bool EncodedDescriptorDatabase::DescriptorIndex::AddSymbol(
+    StringPiece symbol) {
+  SymbolEntry entry = {static_cast<int>(all_values_.size() - 1),
+                       EncodeString(symbol)};
+  std::string entry_as_string = entry.AsString(*this);
+
+  // We need to make sure not to violate our map invariant.
+
+  // If the symbol name is invalid it could break our lookup algorithm (which
+  // relies on the fact that '.' sorts before all other characters that are
+  // valid in symbol names).
+  if (!ValidateSymbolName(symbol)) {
+    GOOGLE_LOG(ERROR) << "Invalid symbol name: " << entry_as_string;
+    return false;
+  }
+
+  auto iter = FindLastLessOrEqual(&by_symbol_, entry);
+  if (!CheckForMutualSubsymbols(entry_as_string, &iter, by_symbol_.end(),
+                                *this)) {
+    return false;
+  }
+
+  // Same, but on by_symbol_flat_
+  auto flat_iter =
+      FindLastLessOrEqual(&by_symbol_flat_, entry, by_symbol_.key_comp());
+  if (!CheckForMutualSubsymbols(entry_as_string, &flat_iter,
+                                by_symbol_flat_.end(), *this)) {
+    return false;
+  }
+
+  // OK, no conflicts.
+
+  // Insert the new symbol using the iterator as a hint, the new entry will
+  // appear immediately before the one the iterator is pointing at.
+  by_symbol_.insert(iter, entry);
+
+  return true;
+}
+
+template <typename DescProto>
+bool EncodedDescriptorDatabase::DescriptorIndex::AddNestedExtensions(
+    StringPiece filename, const DescProto& message_type) {
+  for (const auto& nested_type : message_type.nested_type()) {
+    if (!AddNestedExtensions(filename, nested_type)) return false;
+  }
+  for (const auto& extension : message_type.extension()) {
+    if (!AddExtension(filename, extension)) return false;
+  }
+  return true;
+}
+
+template <typename FieldProto>
+bool EncodedDescriptorDatabase::DescriptorIndex::AddExtension(
+    StringPiece filename, const FieldProto& field) {
+  if (!field.extendee().empty() && field.extendee()[0] == '.') {
+    // The extension is fully-qualified.  We can use it as a lookup key in
+    // the by_symbol_ table.
+    if (!InsertIfNotPresent(
+            &by_extension_,
+            ExtensionEntry{static_cast<int>(all_values_.size() - 1),
+                           EncodeString(field.extendee()), field.number()}) ||
+        std::binary_search(
+            by_extension_flat_.begin(), by_extension_flat_.end(),
+            std::make_pair(field.extendee().substr(1), field.number()),
+            by_extension_.key_comp())) {
+      GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
+                    "extend "
+                 << field.extendee() << " { " << field.name() << " = "
+                 << field.number() << " } from:" << filename;
+      return false;
+    }
+  } else {
+    // Not fully-qualified.  We can't really do anything here, unfortunately.
+    // We don't consider this an error, though, because the descriptor is
+    // valid.
+  }
+  return true;
+}
+
+std::pair<const void*, int>
+EncodedDescriptorDatabase::DescriptorIndex::FindSymbol(StringPiece name) {
+  EnsureFlat();
+  return FindSymbolOnlyFlat(name);
+}
+
+std::pair<const void*, int>
+EncodedDescriptorDatabase::DescriptorIndex::FindSymbolOnlyFlat(
+    StringPiece name) const {
+  auto iter =
+      FindLastLessOrEqual(&by_symbol_flat_, name, by_symbol_.key_comp());
+
+  return iter != by_symbol_flat_.end() &&
+                 IsSubSymbol(iter->AsString(*this), name)
+             ? all_values_[iter->data_offset].value()
+             : Value();
+}
+
+std::pair<const void*, int>
+EncodedDescriptorDatabase::DescriptorIndex::FindExtension(
+    StringPiece containing_type, int field_number) {
+  EnsureFlat();
+
+  auto it = std::lower_bound(
+      by_extension_flat_.begin(), by_extension_flat_.end(),
+      std::make_tuple(containing_type, field_number), by_extension_.key_comp());
+  return it == by_extension_flat_.end() ||
+                 it->extendee(*this) != containing_type ||
+                 it->extension_number != field_number
+             ? std::make_pair(nullptr, 0)
+             : all_values_[it->data_offset].value();
+}
+
+template <typename T, typename Less>
+static void MergeIntoFlat(std::set<T, Less>* s, std::vector<T>* flat) {
+  if (s->empty()) return;
+  std::vector<T> new_flat(s->size() + flat->size());
+  std::merge(s->begin(), s->end(), flat->begin(), flat->end(), &new_flat[0],
+             s->key_comp());
+  *flat = std::move(new_flat);
+  s->clear();
+}
+
+void EncodedDescriptorDatabase::DescriptorIndex::EnsureFlat() {
+  all_values_.shrink_to_fit();
+  // Merge each of the sets into their flat counterpart.
+  MergeIntoFlat(&by_name_, &by_name_flat_);
+  MergeIntoFlat(&by_symbol_, &by_symbol_flat_);
+  MergeIntoFlat(&by_extension_, &by_extension_flat_);
+}
+
+bool EncodedDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers(
+    StringPiece containing_type, std::vector<int>* output) {
+  EnsureFlat();
+
+  bool success = false;
+  auto it = std::lower_bound(
+      by_extension_flat_.begin(), by_extension_flat_.end(),
+      std::make_tuple(containing_type, 0), by_extension_.key_comp());
+  for (;
+       it != by_extension_flat_.end() && it->extendee(*this) == containing_type;
+       ++it) {
+    output->push_back(it->extension_number);
+    success = true;
+  }
+
+  return success;
+}
+
+void EncodedDescriptorDatabase::DescriptorIndex::FindAllFileNames(
+    std::vector<std::string>* output) const {
+  output->resize(by_name_.size() + by_name_flat_.size());
+  int i = 0;
+  for (const auto& entry : by_name_) {
+    (*output)[i] = std::string(entry.name(*this));
+    i++;
+  }
+  for (const auto& entry : by_name_flat_) {
+    (*output)[i] = std::string(entry.name(*this));
+    i++;
+  }
+}
+
+std::pair<const void*, int>
+EncodedDescriptorDatabase::DescriptorIndex::FindFile(
+    StringPiece filename) {
+  EnsureFlat();
+
+  auto it = std::lower_bound(by_name_flat_.begin(), by_name_flat_.end(),
+                             filename, by_name_.key_comp());
+  return it == by_name_flat_.end() || it->name(*this) != filename
+             ? std::make_pair(nullptr, 0)
+             : all_values_[it->data_offset].value();
+}
+
+
 bool EncodedDescriptorDatabase::FindAllFileNames(
     std::vector<std::string>* output) {
-  index_.FindAllFileNames(output);
+  index_->FindAllFileNames(output);
   return true;
 }
 
@@ -468,6 +875,15 @@
   return output->ParseFromArray(encoded_file.first, encoded_file.second);
 }
 
+EncodedDescriptorDatabase::EncodedDescriptorDatabase()
+    : index_(new DescriptorIndex()) {}
+
+EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
+  for (void* p : files_to_delete_) {
+    operator delete(p);
+  }
+}
+
 // ===================================================================
 
 DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
@@ -515,8 +931,8 @@
   std::vector<const FieldDescriptor*> extensions;
   pool_.FindAllExtensions(extendee, &extensions);
 
-  for (int i = 0; i < extensions.size(); ++i) {
-    output->push_back(extensions[i]->number());
+  for (const FieldDescriptor* extension : extensions) {
+    output->push_back(extension->number());
   }
 
   return true;
@@ -536,8 +952,8 @@
 
 bool MergedDescriptorDatabase::FindFileByName(const std::string& filename,
                                               FileDescriptorProto* output) {
-  for (int i = 0; i < sources_.size(); i++) {
-    if (sources_[i]->FindFileByName(filename, output)) {
+  for (DescriptorDatabase* source : sources_) {
+    if (source->FindFileByName(filename, output)) {
       return true;
     }
   }
@@ -546,14 +962,14 @@
 
 bool MergedDescriptorDatabase::FindFileContainingSymbol(
     const std::string& symbol_name, FileDescriptorProto* output) {
-  for (int i = 0; i < sources_.size(); i++) {
+  for (size_t i = 0; i < sources_.size(); i++) {
     if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) {
       // The symbol was found in source i.  However, if one of the previous
       // sources defines a file with the same name (which presumably doesn't
       // contain the symbol, since it wasn't found in that source), then we
       // must hide it from the caller.
       FileDescriptorProto temp;
-      for (int j = 0; j < i; j++) {
+      for (size_t j = 0; j < i; j++) {
         if (sources_[j]->FindFileByName(output->name(), &temp)) {
           // Found conflicting file in a previous source.
           return false;
@@ -568,7 +984,7 @@
 bool MergedDescriptorDatabase::FindFileContainingExtension(
     const std::string& containing_type, int field_number,
     FileDescriptorProto* output) {
-  for (int i = 0; i < sources_.size(); i++) {
+  for (size_t i = 0; i < sources_.size(); i++) {
     if (sources_[i]->FindFileContainingExtension(containing_type, field_number,
                                                  output)) {
       // The symbol was found in source i.  However, if one of the previous
@@ -576,7 +992,7 @@
       // contain the symbol, since it wasn't found in that source), then we
       // must hide it from the caller.
       FileDescriptorProto temp;
-      for (int j = 0; j < i; j++) {
+      for (size_t j = 0; j < i; j++) {
         if (sources_[j]->FindFileByName(output->name(), &temp)) {
           // Found conflicting file in a previous source.
           return false;
@@ -594,8 +1010,8 @@
   std::vector<int> results;
   bool success = false;
 
-  for (int i = 0; i < sources_.size(); i++) {
-    if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
+  for (DescriptorDatabase* source : sources_) {
+    if (source->FindAllExtensionNumbers(extendee_type, &results)) {
       std::copy(results.begin(), results.end(),
                 std::insert_iterator<std::set<int> >(merged_results,
                                                      merged_results.begin()));
diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
index 4009f33..5fb593e 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -187,9 +187,6 @@
   bool FindAllFileNames(std::vector<std::string>* output) override;
 
  private:
-  // So that it can use DescriptorIndex.
-  friend class EncodedDescriptorDatabase;
-
   // An index mapping file names, symbol names, and extension numbers to
   // some sort of values.
   template <typename Value>
@@ -266,21 +263,6 @@
     // That symbol cannot be a super-symbol of the search key since if it were,
     // then it would be a match, and we're assuming the match key doesn't exist.
     // Therefore, step 2 will correctly return no match.
-
-    // Find the last entry in the by_symbol_ map whose key is less than or
-    // equal to the given name.
-    typename std::map<std::string, Value>::iterator FindLastLessOrEqual(
-        const std::string& name);
-
-    // True if either the arguments are equal or super_symbol identifies a
-    // parent symbol of sub_symbol (e.g. "foo.bar" is a parent of
-    // "foo.bar.baz", but not a parent of "foo.barbaz").
-    bool IsSubSymbol(const std::string& sub_symbol,
-                     const std::string& super_symbol);
-
-    // Returns true if and only if all characters in the name are alphanumerics,
-    // underscores, or periods.
-    bool ValidateSymbolName(const std::string& name);
   };
 
   DescriptorIndex<const FileDescriptorProto*> index_;
@@ -332,8 +314,10 @@
   bool FindAllFileNames(std::vector<std::string>* output) override;
 
  private:
-  SimpleDescriptorDatabase::DescriptorIndex<std::pair<const void*, int> >
-      index_;
+  class DescriptorIndex;
+  // Keep DescriptorIndex by pointer to hide the implementation to keep a
+  // cleaner header.
+  std::unique_ptr<DescriptorIndex> index_;
   std::vector<void*> files_to_delete_;
 
   // If encoded_file.first is non-NULL, parse the data into *output and return
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 8653193..fba0b95 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -34,20 +34,21 @@
 //
 // This file makes extensive use of RFC 3092.  :)
 
+#include <google/protobuf/descriptor_database.h>
+
 #include <algorithm>
 #include <memory>
 
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor_database.h>
-#include <google/protobuf/text_format.h>
-
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/text_format.h>
 #include <gmock/gmock.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
+
 namespace google {
 namespace protobuf {
 namespace {
@@ -546,7 +547,7 @@
   db.Add(f);
   db.Add(b);
 
-  std::vector<string> packages;
+  std::vector<std::string> packages;
   EXPECT_TRUE(db.FindAllPackageNames(&packages));
   EXPECT_THAT(packages, ::testing::UnorderedElementsAre("foo", ""));
 }
@@ -566,7 +567,7 @@
   db.Add(f);
   db.Add(b);
 
-  std::vector<string> messages;
+  std::vector<std::string> messages;
   EXPECT_TRUE(db.FindAllMessageNames(&messages));
   EXPECT_THAT(messages, ::testing::UnorderedElementsAre("foo.Foo", "Bar"));
 }
@@ -798,6 +799,7 @@
   }
 }
 
+
 }  // anonymous namespace
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 4b8bbc1..a7e5db2 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -38,13 +38,13 @@
 #include <memory>
 #include <vector>
 
+#include <google/protobuf/any.pb.h>
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/compiler/parser.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_custom_options.pb.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/unittest_lazy_dependencies.pb.h>
 #include <google/protobuf/unittest_proto3_arena.pb.h>
@@ -58,6 +58,7 @@
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/substitute.h>
 
 
@@ -204,7 +205,7 @@
   // implements ErrorCollector ---------------------------------------
   void AddError(const std::string& filename, const std::string& element_name,
                 const Message* descriptor, ErrorLocation location,
-                const std::string& message) {
+                const std::string& message) override {
     const char* location_name = nullptr;
     switch (location) {
       case NAME:
@@ -249,7 +250,7 @@
   // implements ErrorCollector ---------------------------------------
   void AddWarning(const std::string& filename, const std::string& element_name,
                   const Message* descriptor, ErrorLocation location,
-                  const std::string& message) {
+                  const std::string& message) override {
     const char* location_name = nullptr;
     switch (location) {
       case NAME:
@@ -287,9 +288,8 @@
         break;
     }
 
-    strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n",
-                                       filename, element_name, location_name,
-                                       message);
+    strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", filename,
+                              element_name, location_name, message);
   }
 };
 
@@ -298,7 +298,7 @@
 // Test simple files.
 class FileDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   // in "foo.proto"
@@ -479,7 +479,7 @@
 
 
 TEST_F(FileDescriptorTest, BuildAgain) {
-  // Test that if te call BuildFile again on the same input we get the same
+  // Test that if we call BuildFile again on the same input we get the same
   // FileDescriptor back.
   FileDescriptorProto file;
   foo_file_->CopyTo(&file);
@@ -564,7 +564,7 @@
 class SimpleErrorCollector : public io::ErrorCollector {
  public:
   // implements ErrorCollector ---------------------------------------
-  void AddError(int line, int column, const std::string& message) {
+  void AddError(int line, int column, const std::string& message) override {
     last_error_ = StringPrintf("%d:%d:", line, column) + message;
   }
 
@@ -613,7 +613,7 @@
 // Test simple flat messages and fields.
 class DescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   // in "foo.proto"
@@ -999,6 +999,22 @@
   EXPECT_TRUE(map_->message_type()->options().map_entry());
 }
 
+TEST_F(DescriptorTest, GetMap) {
+  const Descriptor* map_desc = map_->message_type();
+  const FieldDescriptor* map_key = map_desc->map_key();
+  ASSERT_TRUE(map_key != nullptr);
+  EXPECT_EQ(map_key->name(), "key");
+  EXPECT_EQ(map_key->number(), 1);
+
+  const FieldDescriptor* map_value = map_desc->map_value();
+  ASSERT_TRUE(map_value != nullptr);
+  EXPECT_EQ(map_value->name(), "value");
+  EXPECT_EQ(map_value->number(), 2);
+
+  EXPECT_EQ(message_->map_key(), nullptr);
+  EXPECT_EQ(message_->map_value(), nullptr);
+}
+
 TEST_F(DescriptorTest, FieldHasDefault) {
   EXPECT_FALSE(foo_->has_default_value());
   EXPECT_FALSE(bar_->has_default_value());
@@ -1039,7 +1055,7 @@
 // Test simple flat messages and fields.
 class OneofDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   package garply;
@@ -1130,7 +1146,7 @@
 
 class StylizedFieldNamesTest : public testing::Test {
  protected:
-  void SetUp() {
+  void SetUp() override {
     FileDescriptorProto file;
     file.set_name("foo.proto");
 
@@ -1299,7 +1315,7 @@
 // Test enum descriptors.
 class EnumDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   // in "foo.proto"
@@ -1450,7 +1466,7 @@
 // Test service descriptors.
 class ServiceDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following messages and service:
     //    // in "foo.proto"
     //    message FooRequest  {}
@@ -1611,7 +1627,7 @@
 // Test nested types.
 class NestedDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   // in "foo.proto"
@@ -1825,7 +1841,7 @@
 // Test extensions.
 class ExtensionDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   enum Baz {}
@@ -1835,12 +1851,17 @@
     //     extensions 10 to 19;
     //     extensions 30 to 39;
     //   }
-    //   extends Foo with optional int32 foo_int32 = 10;
-    //   extends Foo with repeated TestEnum foo_enum = 19;
+    //   extend Foo {
+    //     optional int32 foo_int32 = 10;
+    //   }
+    //   extend Foo {
+    //     repeated TestEnum foo_enum = 19;
+    //   }
     //   message Bar {
-    //     extends Foo with optional Qux foo_message = 30;
-    //     // (using Qux as the group type)
-    //     extends Foo with repeated group foo_group = 39;
+    //     extend Foo {
+    //       optional Qux foo_message = 30;
+    //       repeated Qux foo_group = 39;  // (but internally set to TYPE_GROUP)
+    //     }
     //   }
 
     FileDescriptorProto foo_file;
@@ -2050,10 +2071,88 @@
 
 // ===================================================================
 
+// Ensure that overlapping extension ranges are not allowed.
+TEST(OverlappingExtensionRangeTest, ExtensionRangeInternal) {
+  // Build descriptors for the following definitions:
+  //
+  //   message Foo {
+  //     extensions 10 to 19;
+  //     extensions 15;
+  //   }
+  FileDescriptorProto foo_file;
+  foo_file.set_name("foo.proto");
+
+  DescriptorProto* foo = AddMessage(&foo_file, "Foo");
+  AddExtensionRange(foo, 10, 20);
+  AddExtensionRange(foo, 15, 16);
+
+  DescriptorPool pool;
+  MockErrorCollector error_collector;
+  // The extensions ranges are invalid, so the proto shouldn't build.
+  ASSERT_TRUE(pool.BuildFileCollectingErrors(foo_file, &error_collector) ==
+              nullptr);
+  ASSERT_EQ(
+      "foo.proto: Foo: NUMBER: Extension range 15 to 15 overlaps with "
+      "already-defined range 10 to 19.\n",
+      error_collector.text_);
+}
+
+TEST(OverlappingExtensionRangeTest, ExtensionRangeAfter) {
+  // Build descriptors for the following definitions:
+  //
+  //   message Foo {
+  //     extensions 10 to 19;
+  //     extensions 15 to 24;
+  //   }
+  FileDescriptorProto foo_file;
+  foo_file.set_name("foo.proto");
+
+  DescriptorProto* foo = AddMessage(&foo_file, "Foo");
+  AddExtensionRange(foo, 10, 20);
+  AddExtensionRange(foo, 15, 25);
+
+  DescriptorPool pool;
+  MockErrorCollector error_collector;
+  // The extensions ranges are invalid, so the proto shouldn't build.
+  ASSERT_TRUE(pool.BuildFileCollectingErrors(foo_file, &error_collector) ==
+              nullptr);
+  ASSERT_EQ(
+      "foo.proto: Foo: NUMBER: Extension range 15 to 24 overlaps with "
+      "already-defined range 10 to 19.\n",
+      error_collector.text_);
+}
+
+TEST(OverlappingExtensionRangeTest, ExtensionRangeBefore) {
+  // Build descriptors for the following definitions:
+  //
+  //   message Foo {
+  //     extensions 10 to 19;
+  //     extensions 5 to 14;
+  //   }
+  FileDescriptorProto foo_file;
+  foo_file.set_name("foo.proto");
+
+  DescriptorProto* foo = AddMessage(&foo_file, "Foo");
+  AddExtensionRange(foo, 10, 20);
+  AddExtensionRange(foo, 5, 15);
+
+  DescriptorPool pool;
+  MockErrorCollector error_collector;
+  // The extensions ranges are invalid, so the proto shouldn't build.
+  ASSERT_TRUE(pool.BuildFileCollectingErrors(foo_file, &error_collector) ==
+              nullptr);
+  ASSERT_EQ(
+      "foo.proto: Foo: NUMBER: Extension range 5 to 14 overlaps with "
+      "already-defined range 10 to 19.\n",
+      error_collector.text_);
+}
+
+// ===================================================================
+
 // Test reserved fields.
 class ReservedDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   message Foo {
@@ -2131,7 +2230,7 @@
 // Test reserved enum fields.
 class ReservedEnumDescriptorTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // Build descriptors for the following definitions:
     //
     //   enum Foo {
@@ -2576,11 +2675,9 @@
   ASSERT_TRUE(message->field(10)->has_default_value());
 
   EXPECT_EQ(-1, message->field(0)->default_value_int32());
-  EXPECT_EQ(-PROTOBUF_ULONGLONG(1000000000000),
-            message->field(1)->default_value_int64());
+  EXPECT_EQ(int64{-1000000000000}, message->field(1)->default_value_int64());
   EXPECT_EQ(42, message->field(2)->default_value_uint32());
-  EXPECT_EQ(PROTOBUF_ULONGLONG(2000000000000),
-            message->field(3)->default_value_uint64());
+  EXPECT_EQ(uint64{2000000000000}, message->field(3)->default_value_uint64());
   EXPECT_EQ(4.5, message->field(4)->default_value_float());
   EXPECT_EQ(10e100, message->field(5)->default_value_double());
   EXPECT_TRUE(message->field(6)->default_value_bool());
@@ -2659,7 +2756,7 @@
   DescriptorPoolMode mode() { return std::get<0>(GetParam()); }
   const char* syntax() { return std::get<1>(GetParam()); }
 
-  virtual void SetUp() {
+  virtual void SetUp() override {
     FileDescriptorProto foo_proto, bar_proto;
 
     switch (mode()) {
@@ -2993,11 +3090,11 @@
       file->FindServiceByName("TestServiceWithCustomOptions");
   const MethodDescriptor* method = service->FindMethodByName("Foo");
 
-  EXPECT_EQ(PROTOBUF_LONGLONG(9876543210),
+  EXPECT_EQ(int64{9876543210},
             file->options().GetExtension(protobuf_unittest::file_opt1));
   EXPECT_EQ(-56,
             message->options().GetExtension(protobuf_unittest::message_opt1));
-  EXPECT_EQ(PROTOBUF_LONGLONG(8765432109),
+  EXPECT_EQ(int64{8765432109},
             field->options().GetExtension(protobuf_unittest::field_opt1));
   EXPECT_EQ(42,  // Check that we get the default for an option we don't set.
             field->options().GetExtension(protobuf_unittest::field_opt2));
@@ -3005,7 +3102,7 @@
   EXPECT_EQ(-789, enm->options().GetExtension(protobuf_unittest::enum_opt1));
   EXPECT_EQ(123, enm->value(1)->options().GetExtension(
                      protobuf_unittest::enum_value_opt1));
-  EXPECT_EQ(PROTOBUF_LONGLONG(-9876543210),
+  EXPECT_EQ(int64{-9876543210},
             service->options().GetExtension(protobuf_unittest::service_opt1));
   EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
             method->options().GetExtension(protobuf_unittest::method_opt1));
@@ -3134,6 +3231,11 @@
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
+  // We have to import the Any dependency.
+  FileDescriptorProto any_proto;
+  google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
+  ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
+
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
@@ -3192,6 +3294,10 @@
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
+  FileDescriptorProto any_proto;
+  google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
+  ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
+
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
@@ -3269,6 +3375,10 @@
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
+  FileDescriptorProto any_proto;
+  google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
+  ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
+
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
@@ -3349,6 +3459,10 @@
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
+  FileDescriptorProto any_proto;
+  google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
+  ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
+
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
@@ -3449,6 +3563,10 @@
                                   message_set_extension)
                 .s());
 
+  protobuf_unittest::AggregateMessageSetElement any_payload;
+  ASSERT_TRUE(file_options.any().UnpackTo(&any_payload));
+  EXPECT_EQ("EmbeddedMessageSetElement", any_payload.s());
+
   // Simple tests for all the other types of annotations
   EXPECT_EQ("MessageAnnotation",
             msg->options().GetExtension(protobuf_unittest::msgopt).s());
@@ -3471,6 +3589,10 @@
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
+  FileDescriptorProto any_proto;
+  google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
+  ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
+
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
@@ -3772,6 +3894,45 @@
       "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
 }
 
+// 'str' is a static C-style string that may contain '\0'
+#define STATIC_STR(str) std::string((str), sizeof(str) - 1)
+
+TEST_F(ValidationErrorTest, NullCharSymbolName) {
+  BuildFileWithErrors(
+      "name: \"bar.proto\" "
+      "package: \"foo\""
+      "message_type { "
+      "  name: '\\000\\001\\013.Bar' "
+      "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "} "
+      "}",
+      STATIC_STR("bar.proto: foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a "
+                 "valid identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: "
+                 "foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a valid "
+                 "identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: "
+                 "foo.\0\x1\v.Bar.foo: NAME: \"foo.\0\x1\v.Bar.foo\" contains "
+                 "null character.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"foo.\0\x1\v.Bar\" contains null character.\n"));
+}
+
+TEST_F(ValidationErrorTest, NullCharFileName) {
+  BuildFileWithErrors(
+      "name: \"bar\\000\\001\\013.proto\" "
+      "package: \"outer.foo\"",
+      STATIC_STR("bar\0\x1\v.proto: bar\0\x1\v.proto: NAME: "
+                 "\"bar\0\x1\v.proto\" contains null character.\n"));
+}
+
+TEST_F(ValidationErrorTest, NullCharPackageName) {
+  BuildFileWithErrors(
+      "name: \"bar.proto\" "
+      "package: \"\\000\\001\\013.\"",
+      STATIC_STR("bar.proto: \0\x1\v.: NAME: \"\0\x1\v.\" contains null "
+                 "character.\n"));
+}
+
 TEST_F(ValidationErrorTest, MissingFileName) {
   BuildFileWithErrors("",
 
@@ -3987,6 +4148,32 @@
       file->DebugString());
 }
 
+TEST_F(ValidationErrorTest, DebugStringReservedRangeMax) {
+  const FileDescriptor* file = BuildFile(strings::Substitute(
+      "name: \"foo.proto\" "
+      "enum_type { "
+      "  name: \"Bar\""
+      "  value { name:\"BAR\" number:1 }"
+      "  reserved_range { start: 5 end: $0 }"
+      "}"
+      "message_type {"
+      "  name: \"Foo\""
+      "  reserved_range { start: 5 end: $1 }"
+      "}",
+      std::numeric_limits<int>::max(), FieldDescriptor::kMaxNumber + 1));
+
+  ASSERT_EQ(
+      "syntax = \"proto2\";\n\n"
+      "enum Bar {\n"
+      "  BAR = 1;\n"
+      "  reserved 5 to max;\n"
+      "}\n\n"
+      "message Foo {\n"
+      "  reserved 5 to max;\n"
+      "}\n\n",
+      file->DebugString());
+}
+
 TEST_F(ValidationErrorTest, EnumReservedFieldError) {
   BuildFileWithErrors(
       "name: \"foo.proto\" "
@@ -6547,7 +6734,7 @@
 
   SimpleDescriptorDatabase database_;
 
-  virtual void SetUp() {
+  virtual void SetUp() override {
     AddToDatabase(
         &database_,
         "name: 'foo.proto' "
@@ -6579,7 +6766,7 @@
 
     // implements DescriptorDatabase ---------------------------------
     bool FindFileByName(const std::string& filename,
-                        FileDescriptorProto* output) {
+                        FileDescriptorProto* output) override {
       // error.proto and error2.proto cyclically import each other.
       if (filename == "error.proto") {
         output->Clear();
@@ -6596,12 +6783,12 @@
       }
     }
     bool FindFileContainingSymbol(const std::string& symbol_name,
-                                  FileDescriptorProto* output) {
+                                  FileDescriptorProto* output) override {
       return false;
     }
     bool FindFileContainingExtension(const std::string& containing_type,
                                      int field_number,
-                                     FileDescriptorProto* output) {
+                                     FileDescriptorProto* output) override {
       return false;
     }
   };
@@ -6624,18 +6811,18 @@
 
     // implements DescriptorDatabase ---------------------------------
     bool FindFileByName(const std::string& filename,
-                        FileDescriptorProto* output) {
+                        FileDescriptorProto* output) override {
       ++call_count_;
       return wrapped_db_->FindFileByName(filename, output);
     }
     bool FindFileContainingSymbol(const std::string& symbol_name,
-                                  FileDescriptorProto* output) {
+                                  FileDescriptorProto* output) override {
       ++call_count_;
       return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
     }
     bool FindFileContainingExtension(const std::string& containing_type,
                                      int field_number,
-                                     FileDescriptorProto* output) {
+                                     FileDescriptorProto* output) override {
       ++call_count_;
       return wrapped_db_->FindFileContainingExtension(containing_type,
                                                       field_number, output);
@@ -6655,16 +6842,16 @@
 
     // implements DescriptorDatabase ---------------------------------
     bool FindFileByName(const std::string& filename,
-                        FileDescriptorProto* output) {
+                        FileDescriptorProto* output) override {
       return wrapped_db_->FindFileByName(filename, output);
     }
     bool FindFileContainingSymbol(const std::string& symbol_name,
-                                  FileDescriptorProto* output) {
+                                  FileDescriptorProto* output) override {
       return FindFileByName("foo.proto", output);
     }
     bool FindFileContainingExtension(const std::string& containing_type,
                                      int field_number,
-                                     FileDescriptorProto* output) {
+                                     FileDescriptorProto* output) override {
       return FindFileByName("foo.proto", output);
     }
   };
@@ -6940,7 +7127,7 @@
 
   // implements DescriptorDatabase ---------------------------------
   bool FindFileByName(const std::string& filename,
-                      FileDescriptorProto* output) {
+                      FileDescriptorProto* output) override {
     int file_num = -1;
     FullMatch(filename, "file", ".proto", &file_num);
     if (file_num > -1) {
@@ -6950,7 +7137,7 @@
     }
   }
   bool FindFileContainingSymbol(const std::string& symbol_name,
-                                FileDescriptorProto* output) {
+                                FileDescriptorProto* output) override {
     int file_num = -1;
     FullMatch(symbol_name, "Message", "", &file_num);
     if (file_num > 0) {
@@ -6961,7 +7148,7 @@
   }
   bool FindFileContainingExtension(const std::string& containing_type,
                                    int field_number,
-                                   FileDescriptorProto* output) {
+                                   FileDescriptorProto* output) override {
     return false;
   }
 
@@ -7047,7 +7234,7 @@
   virtual void AddError(const std::string& filename,
                         const std::string& element_name, const Message* message,
                         ErrorLocation location,
-                        const std::string& error_message) {
+                        const std::string& error_message) override {
     GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " ["
                << element_name << "]: " << error_message;
   }
@@ -7062,7 +7249,7 @@
   SingletonSourceTree(const std::string& filename, const std::string& contents)
       : filename_(filename), contents_(contents) {}
 
-  virtual io::ZeroCopyInputStream* Open(const std::string& filename) {
+  virtual io::ZeroCopyInputStream* Open(const std::string& filename) override {
     return filename == filename_
                ? new io::ArrayInputStream(contents_.data(), contents_.size())
                : nullptr;
@@ -7168,8 +7355,8 @@
 
   static std::string PrintSourceLocation(const SourceLocation& loc) {
     return strings::Substitute("$0:$1-$2:$3", 1 + loc.start_line,
-                                     1 + loc.start_column, 1 + loc.end_line,
-                                     1 + loc.end_column);
+                            1 + loc.start_column, 1 + loc.end_line,
+                            1 + loc.end_column);
   }
 
  private:
@@ -7184,9 +7371,9 @@
   DescriptorPool pool_;
 
   // tag number of all custom options in above test file
-  static const int kCustomOptionFieldNumber = 10101;
+  static constexpr int kCustomOptionFieldNumber = 10101;
   // tag number of field "a" in message type "A" in above test file
-  static const int kAFieldNumber = 1;
+  static constexpr int kAFieldNumber = 1;
 };
 
 // TODO(adonovan): implement support for option fields and for
@@ -8071,3 +8258,5 @@
 }  // namespace descriptor_unittest
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 2682662..13fc338 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -14,26 +14,23 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class DurationDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Duration> _instance;
-} _Duration_default_instance_;
+constexpr Duration::Duration(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : seconds_(int64_t{0})
+  , nanos_(0){}
+struct DurationDefaultTypeInternal {
+  constexpr DurationDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DurationDefaultTypeInternal() {}
+  union {
+    Duration _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DurationDefaultTypeInternal _Duration_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Duration_google_2fprotobuf_2fduration_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Duration_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Duration();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Duration::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Duration_google_2fprotobuf_2fduration_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Duration_google_2fprotobuf_2fduration_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fduration_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
@@ -58,40 +55,39 @@
 const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
   "\n\036google/protobuf/duration.proto\022\017google"
   ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r"
-  "\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu"
-  "rationProtoP\001Z*github.com/golang/protobu"
-  "f/ptypes/duration\370\001\001\242\002\003GPB\252\002\036Google.Prot"
-  "obuf.WellKnownTypesb\006proto3"
+  "\n\005nanos\030\002 \001(\005B\203\001\n\023com.google.protobufB\rD"
+  "urationProtoP\001Z1google.golang.org/protob"
+  "uf/types/known/durationpb\370\001\001\242\002\003GPB\252\002\036Goo"
+  "gle.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fduration_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fduration_2eproto_sccs[1] = {
-  &scc_info_Duration_google_2fprotobuf_2fduration_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fduration_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, "google/protobuf/duration.proto", 227,
-  &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, descriptor_table_google_2fprotobuf_2fduration_2eproto_sccs, descriptor_table_google_2fprotobuf_2fduration_2eproto_deps, 1, 0,
+  false, false, 235, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, "google/protobuf/duration.proto", 
+  &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fduration_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fduration_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
+  file_level_metadata_google_2fprotobuf_2fduration_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fduration_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fduration_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void Duration::InitAsDefaultInstance() {
-}
 class Duration::_Internal {
  public:
 };
 
-Duration::Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Duration::Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Duration)
 }
 Duration::Duration(const Duration& from)
@@ -103,20 +99,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Duration)
 }
 
-void Duration::SharedCtor() {
-  ::memset(&seconds_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&nanos_) -
-      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
+inline void Duration::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
+    reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
 }
 
 Duration::~Duration() {
   // @@protoc_insertion_point(destructor:google.protobuf.Duration)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Duration::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Duration::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void Duration::ArenaDtor(void* object) {
@@ -128,11 +126,6 @@
 void Duration::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Duration& Duration::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Duration_google_2fprotobuf_2fduration_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Duration::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
@@ -148,11 +141,9 @@
 
 const char* Duration::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1:
@@ -170,7 +161,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -197,13 +189,13 @@
   (void) cached_has_bits;
 
   // int64 seconds = 1;
-  if (this->seconds() != 0) {
+  if (this->_internal_seconds() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->_internal_seconds(), target);
   }
 
   // int32 nanos = 2;
-  if (this->nanos() != 0) {
+  if (this->_internal_nanos() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_nanos(), target);
   }
@@ -225,14 +217,14 @@
   (void) cached_has_bits;
 
   // int64 seconds = 1;
-  if (this->seconds() != 0) {
+  if (this->_internal_seconds() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size(
         this->_internal_seconds());
   }
 
   // int32 nanos = 2;
-  if (this->nanos() != 0) {
+  if (this->_internal_nanos() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
         this->_internal_nanos());
@@ -247,41 +239,32 @@
   return total_size;
 }
 
-void Duration::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Duration* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Duration>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Duration)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Duration)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Duration::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Duration::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Duration::GetClassData() const { return &_class_data_; }
+
+void Duration::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Duration *>(to)->MergeFrom(
+      static_cast<const Duration &>(from));
 }
 
+
 void Duration::MergeFrom(const Duration& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.seconds() != 0) {
+  if (from._internal_seconds() != 0) {
     _internal_set_seconds(from._internal_seconds());
   }
-  if (from.nanos() != 0) {
+  if (from._internal_nanos() != 0) {
     _internal_set_nanos(from._internal_nanos());
   }
-}
-
-void Duration::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Duration)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Duration::CopyFrom(const Duration& from) {
@@ -297,7 +280,7 @@
 
 void Duration::InternalSwap(Duration* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Duration, nanos_)
       + sizeof(Duration::nanos_)
@@ -307,10 +290,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Duration::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fduration_2eproto_getter, &descriptor_table_google_2fprotobuf_2fduration_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fduration_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index fcc2103..7a5caa0 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -45,7 +44,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -53,10 +52,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class Duration;
-class DurationDefaultTypeInternal;
+struct DurationDefaultTypeInternal;
 PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -66,11 +65,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT Duration PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Duration final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ {
  public:
-  inline Duration() : Duration(nullptr) {};
-  virtual ~Duration();
+  inline Duration() : Duration(nullptr) {}
+  ~Duration() override;
+  explicit constexpr Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Duration(const Duration& from);
   Duration(Duration&& from) noexcept
@@ -83,8 +83,9 @@
     return *this;
   }
   inline Duration& operator=(Duration&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -95,14 +96,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Duration& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Duration& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Duration* internal_default_instance() {
     return reinterpret_cast<const Duration*>(
                &_Duration_default_instance_);
@@ -115,7 +116,7 @@
   }
   inline void Swap(Duration* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -123,23 +124,26 @@
   }
   void UnsafeArenaSwap(Duration* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Duration* New() const final {
-    return CreateMaybeMessage<Duration>(nullptr);
+    return new Duration();
   }
 
   Duration* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Duration>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Duration& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Duration& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -150,8 +154,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Duration* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -159,20 +163,17 @@
     return "google.protobuf.Duration";
   }
   protected:
-  explicit Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fduration_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fduration_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -225,7 +226,7 @@
 
 // int64 seconds = 1;
 inline void Duration::clear_seconds() {
-  seconds_ = PROTOBUF_LONGLONG(0);
+  seconds_ = int64_t{0};
 }
 inline ::PROTOBUF_NAMESPACE_ID::int64 Duration::_internal_seconds() const {
   return seconds_;
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
index 99cb102..81c3e36 100644
--- a/src/google/protobuf/duration.proto
+++ b/src/google/protobuf/duration.proto
@@ -34,7 +34,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
-option go_package = "github.com/golang/protobuf/ptypes/duration";
+option go_package = "google.golang.org/protobuf/types/known/durationpb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "DurationProto";
 option java_multiple_files = true;
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index fd52371..0bfb94a 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -67,6 +67,7 @@
 #include <algorithm>
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <unordered_map>
 
 #include <google/protobuf/descriptor.pb.h>
@@ -197,44 +198,6 @@
   return 0;
 }
 
-// Compute the byte size of in-memory representation of the oneof fields
-// in default oneof instance.
-int OneofFieldSpaceUsed(const FieldDescriptor* field) {
-  typedef FieldDescriptor FD;  // avoid line wrapping
-  switch (field->cpp_type()) {
-    case FD::CPPTYPE_INT32:
-      return sizeof(int32);
-    case FD::CPPTYPE_INT64:
-      return sizeof(int64);
-    case FD::CPPTYPE_UINT32:
-      return sizeof(uint32);
-    case FD::CPPTYPE_UINT64:
-      return sizeof(uint64);
-    case FD::CPPTYPE_DOUBLE:
-      return sizeof(double);
-    case FD::CPPTYPE_FLOAT:
-      return sizeof(float);
-    case FD::CPPTYPE_BOOL:
-      return sizeof(bool);
-    case FD::CPPTYPE_ENUM:
-      return sizeof(int);
-
-    case FD::CPPTYPE_MESSAGE:
-      return sizeof(Message*);
-
-    case FD::CPPTYPE_STRING:
-      switch (field->options().ctype()) {
-        default:
-        case FieldOptions::STRING:
-          return sizeof(ArenaStringPtr);
-      }
-      break;
-  }
-
-  GOOGLE_LOG(DFATAL) << "Can't get here.";
-  return 0;
-}
-
 inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; }
 
 static const int kSafeAlignment = sizeof(uint64);
@@ -256,42 +219,21 @@
 
 class DynamicMessage : public Message {
  public:
-  struct TypeInfo {
-    int size;
-    int has_bits_offset;
-    int oneof_case_offset;
-    int extensions_offset;
-
-    // Not owned by the TypeInfo.
-    DynamicMessageFactory* factory;  // The factory that created this object.
-    const DescriptorPool* pool;      // The factory's DescriptorPool.
-    const Descriptor* type;          // Type of this DynamicMessage.
-
-    // Warning:  The order in which the following pointers are defined is
-    //   important (the prototype must be deleted *before* the offsets).
-    std::unique_ptr<uint32[]> offsets;
-    std::unique_ptr<uint32[]> has_bits_indices;
-    std::unique_ptr<const Reflection> reflection;
-    // Don't use a unique_ptr to hold the prototype: the destructor for
-    // DynamicMessage needs to know whether it is the prototype, and does so by
-    // looking back at this field. This would assume details about the
-    // implementation of unique_ptr.
-    const DynamicMessage* prototype;
-    int weak_field_map_offset;  // The offset for the weak_field_map;
-
-    TypeInfo() : prototype(NULL) {}
-
-    ~TypeInfo() { delete prototype; }
-  };
-
-  DynamicMessage(const TypeInfo* type_info);
+  explicit DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info);
 
   // This should only be used by GetPrototypeNoLock() to avoid dead lock.
-  DynamicMessage(TypeInfo* type_info, bool lock_factory);
+  DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory);
 
   ~DynamicMessage();
 
   // Called on the prototype after construction to initialize message fields.
+  // Cross linking the default instances allows for fast reflection access of
+  // unset message fields. Without it we would have to go to the MessageFactory
+  // to get the prototype, which is a much more expensive operation.
+  //
+  // Generated messages do not cross-link to avoid dynamic initialization of the
+  // global instances.
+  // Instead, they keep the default instances in the FieldDescriptor objects.
   void CrossLinkPrototypes();
 
   // implements Message ----------------------------------------------
@@ -304,6 +246,9 @@
 
   Metadata GetMetadata() const override;
 
+#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
+  static void operator delete(DynamicMessage* msg, std::destroying_delete_t);
+#else
   // We actually allocate more memory than sizeof(*this) when this
   // class's memory is allocated via the global operator new. Thus, we need to
   // manually call the global operator delete. Calling the destructor is taken
@@ -312,21 +257,18 @@
 #ifndef _MSC_VER
   static void operator delete(void* ptr) { ::operator delete(ptr); }
 #endif  // !_MSC_VER
+#endif
 
  private:
-  DynamicMessage(const TypeInfo* type_info, Arena* arena);
+  DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
+                 Arena* arena);
 
   void SharedCtor(bool lock_factory);
 
   // Needed to get the offset of the internal metadata member.
   friend class DynamicMessageFactory;
 
-  inline bool is_prototype() const {
-    return type_info_->prototype == this ||
-           // If type_info_->prototype is NULL, then we must be constructing
-           // the prototype now, which means we must be the prototype.
-           type_info_->prototype == NULL;
-  }
+  bool is_prototype() const;
 
   inline void* OffsetToPointer(int offset) {
     return reinterpret_cast<uint8*>(this) + offset;
@@ -335,27 +277,53 @@
     return reinterpret_cast<const uint8*>(this) + offset;
   }
 
-  const TypeInfo* type_info_;
-  Arena* const arena_;
+  const DynamicMessageFactory::TypeInfo* type_info_;
   mutable std::atomic<int> cached_byte_size_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
 };
 
-DynamicMessage::DynamicMessage(const TypeInfo* type_info)
-    : type_info_(type_info), arena_(NULL), cached_byte_size_(0) {
+struct DynamicMessageFactory::TypeInfo {
+  int size;
+  int has_bits_offset;
+  int oneof_case_offset;
+  int extensions_offset;
+
+  // Not owned by the TypeInfo.
+  DynamicMessageFactory* factory;  // The factory that created this object.
+  const DescriptorPool* pool;      // The factory's DescriptorPool.
+  const Descriptor* type;          // Type of this DynamicMessage.
+
+  // Warning:  The order in which the following pointers are defined is
+  //   important (the prototype must be deleted *before* the offsets).
+  std::unique_ptr<uint32[]> offsets;
+  std::unique_ptr<uint32[]> has_bits_indices;
+  std::unique_ptr<const Reflection> reflection;
+  // Don't use a unique_ptr to hold the prototype: the destructor for
+  // DynamicMessage needs to know whether it is the prototype, and does so by
+  // looking back at this field. This would assume details about the
+  // implementation of unique_ptr.
+  const DynamicMessage* prototype;
+  int weak_field_map_offset;  // The offset for the weak_field_map;
+
+  TypeInfo() : prototype(nullptr) {}
+
+  ~TypeInfo() { delete prototype; }
+};
+
+DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info)
+    : type_info_(type_info), cached_byte_size_(0) {
   SharedCtor(true);
 }
 
-DynamicMessage::DynamicMessage(const TypeInfo* type_info, Arena* arena)
-    : Message(arena),
-      type_info_(type_info),
-      arena_(arena),
-      cached_byte_size_(0) {
+DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
+                               Arena* arena)
+    : Message(arena), type_info_(type_info), cached_byte_size_(0) {
   SharedCtor(true);
 }
 
-DynamicMessage::DynamicMessage(TypeInfo* type_info, bool lock_factory)
-    : type_info_(type_info), arena_(NULL), cached_byte_size_(0) {
+DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info,
+                               bool lock_factory)
+    : type_info_(type_info), cached_byte_size_(0) {
   // The prototype in type_info has to be set before creating the prototype
   // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
   // creating prototype for Foo, prototype of the map entry will also be
@@ -386,7 +354,8 @@
   }
 
   if (type_info_->extensions_offset != -1) {
-    new (OffsetToPointer(type_info_->extensions_offset)) ExtensionSet(arena_);
+    new (OffsetToPointer(type_info_->extensions_offset))
+        ExtensionSet(GetArenaForAllocation());
   }
   for (int i = 0; i < descriptor->field_count(); i++) {
     const FieldDescriptor* field = descriptor->field(i);
@@ -395,13 +364,13 @@
       continue;
     }
     switch (field->cpp_type()) {
-#define HANDLE_TYPE(CPPTYPE, TYPE)                         \
-  case FieldDescriptor::CPPTYPE_##CPPTYPE:                 \
-    if (!field->is_repeated()) {                           \
-      new (field_ptr) TYPE(field->default_value_##TYPE()); \
-    } else {                                               \
-      new (field_ptr) RepeatedField<TYPE>(arena_);         \
-    }                                                      \
+#define HANDLE_TYPE(CPPTYPE, TYPE)                                  \
+  case FieldDescriptor::CPPTYPE_##CPPTYPE:                          \
+    if (!field->is_repeated()) {                                    \
+      new (field_ptr) TYPE(field->default_value_##TYPE());          \
+    } else {                                                        \
+      new (field_ptr) RepeatedField<TYPE>(GetArenaForAllocation()); \
+    }                                                               \
     break;
 
       HANDLE_TYPE(INT32, int32);
@@ -417,7 +386,7 @@
         if (!field->is_repeated()) {
           new (field_ptr) int(field->default_value_enum()->number());
         } else {
-          new (field_ptr) RepeatedField<int>(arena_);
+          new (field_ptr) RepeatedField<int>(GetArenaForAllocation());
         }
         break;
 
@@ -426,19 +395,15 @@
           default:  // TODO(kenton):  Support other string reps.
           case FieldOptions::STRING:
             if (!field->is_repeated()) {
-              const std::string* default_value;
-              if (is_prototype()) {
-                default_value = &field->default_value_string();
-              } else {
-                default_value = &(reinterpret_cast<const ArenaStringPtr*>(
-                                      type_info_->prototype->OffsetToPointer(
-                                          type_info_->offsets[i]))
-                                      ->Get());
-              }
+              const std::string* default_value =
+                  field->default_value_string().empty()
+                      ? &internal::GetEmptyStringAlreadyInited()
+                      : nullptr;
               ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
               asp->UnsafeSetDefault(default_value);
             } else {
-              new (field_ptr) RepeatedPtrField<std::string>(arena_);
+              new (field_ptr)
+                  RepeatedPtrField<std::string>(GetArenaForAllocation());
             }
             break;
         }
@@ -453,20 +418,30 @@
             // when the constructor is called inside GetPrototype(), in which
             // case we have already locked the factory.
             if (lock_factory) {
-              if (arena_ != NULL) {
+              if (GetArenaForAllocation() != nullptr) {
                 new (field_ptr) DynamicMapField(
                     type_info_->factory->GetPrototype(field->message_type()),
-                    arena_);
+                    GetArenaForAllocation());
+                if (GetOwningArena() != nullptr) {
+                  // Needs to destroy the mutex member.
+                  GetOwningArena()->OwnDestructor(
+                      static_cast<DynamicMapField*>(field_ptr));
+                }
               } else {
                 new (field_ptr) DynamicMapField(
                     type_info_->factory->GetPrototype(field->message_type()));
               }
             } else {
-              if (arena_ != NULL) {
+              if (GetArenaForAllocation() != nullptr) {
                 new (field_ptr)
                     DynamicMapField(type_info_->factory->GetPrototypeNoLock(
                                         field->message_type()),
-                                    arena_);
+                                    GetArenaForAllocation());
+                if (GetOwningArena() != nullptr) {
+                  // Needs to destroy the mutex member.
+                  GetOwningArena()->OwnDestructor(
+                      static_cast<DynamicMapField*>(field_ptr));
+                }
               } else {
                 new (field_ptr)
                     DynamicMapField(type_info_->factory->GetPrototypeNoLock(
@@ -474,7 +449,7 @@
               }
             }
           } else {
-            new (field_ptr) RepeatedPtrField<Message>(arena_);
+            new (field_ptr) RepeatedPtrField<Message>(GetArenaForAllocation());
           }
         }
         break;
@@ -483,6 +458,22 @@
   }
 }
 
+bool DynamicMessage::is_prototype() const {
+  return type_info_->prototype == this ||
+         // If type_info_->prototype is NULL, then we must be constructing
+         // the prototype now, which means we must be the prototype.
+         type_info_->prototype == nullptr;
+}
+
+#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
+void DynamicMessage::operator delete(DynamicMessage* msg,
+                                     std::destroying_delete_t) {
+  const size_t size = msg->type_info_->size;
+  msg->~DynamicMessage();
+  ::operator delete(msg, size);
+}
+#endif
+
 DynamicMessage::~DynamicMessage() {
   const Descriptor* descriptor = type_info_->type;
 
@@ -508,7 +499,7 @@
       void* field_ptr =
           OffsetToPointer(type_info_->oneof_case_offset +
                           sizeof(uint32) * field->containing_oneof()->index());
-      if (*(reinterpret_cast<const uint32*>(field_ptr)) == field->number()) {
+      if (*(reinterpret_cast<const int32*>(field_ptr)) == field->number()) {
         field_ptr = OffsetToPointer(
             type_info_->offsets[descriptor->field_count() +
                                 field->containing_oneof()->index()]);
@@ -516,11 +507,11 @@
           switch (field->options().ctype()) {
             default:
             case FieldOptions::STRING: {
-              const std::string* default_value =
-                  &(reinterpret_cast<const ArenaStringPtr*>(
-                        reinterpret_cast<const uint8*>(type_info_->prototype) +
-                        type_info_->offsets[i])
-                        ->Get());
+              // Oneof string fields are never set as a default instance.
+              // We just need to pass some arbitrary default string to make it
+              // work. This allows us to not have the real default accessible
+              // from reflection.
+              const std::string* default_value = nullptr;
               reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
                   default_value, NULL);
               break;
@@ -577,10 +568,10 @@
         default:  // TODO(kenton):  Support other string reps.
         case FieldOptions::STRING: {
           const std::string* default_value =
-              &(reinterpret_cast<const ArenaStringPtr*>(
-                    type_info_->prototype->OffsetToPointer(
-                        type_info_->offsets[i]))
-                    ->Get());
+              reinterpret_cast<const ArenaStringPtr*>(
+                  type_info_->prototype->OffsetToPointer(
+                      type_info_->offsets[i]))
+                  ->GetPointer();
           reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
                                                                 NULL);
           break;
@@ -609,6 +600,7 @@
     const FieldDescriptor* field = descriptor->field(i);
     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !field->options().weak() && !InRealOneof(field) &&
         !field->is_repeated()) {
       // For fields with message types, we need to cross-link with the
       // prototype for the field's type.
@@ -651,27 +643,14 @@
 
 // ===================================================================
 
-struct DynamicMessageFactory::PrototypeMap {
-  typedef std::unordered_map<const Descriptor*, const DynamicMessage::TypeInfo*>
-      Map;
-  Map map_;
-};
-
 DynamicMessageFactory::DynamicMessageFactory()
-    : pool_(NULL),
-      delegate_to_generated_factory_(false),
-      prototypes_(new PrototypeMap) {}
+    : pool_(nullptr), delegate_to_generated_factory_(false) {}
 
 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
-    : pool_(pool),
-      delegate_to_generated_factory_(false),
-      prototypes_(new PrototypeMap) {}
+    : pool_(pool), delegate_to_generated_factory_(false) {}
 
 DynamicMessageFactory::~DynamicMessageFactory() {
-  for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
-       iter != prototypes_->map_.end(); ++iter) {
-    DeleteDefaultOneofInstance(iter->second->type, iter->second->offsets.get(),
-                               iter->second->prototype);
+  for (auto iter = prototypes_.begin(); iter != prototypes_.end(); ++iter) {
     delete iter->second;
   }
 }
@@ -688,13 +667,13 @@
     return MessageFactory::generated_factory()->GetPrototype(type);
   }
 
-  const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
+  const TypeInfo** target = &prototypes_[type];
   if (*target != NULL) {
     // Already exists.
     return (*target)->prototype;
   }
 
-  DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
+  TypeInfo* type_info = new TypeInfo;
   *target = type_info;
 
   type_info->type = type;
@@ -771,7 +750,6 @@
   // All the fields.
   //
   // TODO(b/31226269):  Optimize the order of fields to minimize padding.
-  int num_weak_fields = 0;
   for (int i = 0; i < type->field_count(); i++) {
     // Make sure field is aligned to avoid bus errors.
     // Oneof fields do not use any space.
@@ -806,14 +784,16 @@
     if (type->oneof_decl(i)->is_synthetic()) continue;
     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      int field_size = OneofFieldSpaceUsed(field);
-      size = AlignTo(size, std::min(kSafeAlignment, field_size));
-      offsets[field->index()] = size;
-      size += field_size;
+      // oneof fields are not accessed through offsets, but we still have the
+      // entry from a legacy implementation. This should be removed at some
+      // point.
+      // Mark the field to prevent unintentional access through reflection.
+      // Don't use the top bit because that is for unused fields.
+      offsets[field->index()] = internal::kInvalidFieldOffsetTag;
     }
   }
-  size = AlignOffset(size);
-  // Allocate the prototype + oneof fields.
+
+  // Allocate the prototype fields.
   void* base = operator new(size);
   memset(base, 0, size);
 
@@ -821,12 +801,6 @@
   // of dynamic message to avoid dead lock.
   DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
 
-  if (real_oneof_count > 0 || num_weak_fields > 0) {
-    // Construct default oneof instance.
-    ConstructDefaultOneofInstance(type_info->type, type_info->offsets.get(),
-                                  prototype);
-  }
-
   internal::ReflectionSchema schema = {
       type_info->prototype,
       type_info->offsets.get(),
@@ -847,71 +821,6 @@
   return prototype;
 }
 
-void DynamicMessageFactory::ConstructDefaultOneofInstance(
-    const Descriptor* type, const uint32 offsets[],
-    void* default_oneof_or_weak_instance) {
-  for (int i = 0; i < type->oneof_decl_count(); i++) {
-    if (type->oneof_decl(i)->is_synthetic()) continue;
-    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      void* field_ptr =
-          reinterpret_cast<uint8*>(default_oneof_or_weak_instance) +
-          offsets[field->index()];
-      switch (field->cpp_type()) {
-#define HANDLE_TYPE(CPPTYPE, TYPE)                       \
-  case FieldDescriptor::CPPTYPE_##CPPTYPE:               \
-    new (field_ptr) TYPE(field->default_value_##TYPE()); \
-    break;
-
-        HANDLE_TYPE(INT32, int32);
-        HANDLE_TYPE(INT64, int64);
-        HANDLE_TYPE(UINT32, uint32);
-        HANDLE_TYPE(UINT64, uint64);
-        HANDLE_TYPE(DOUBLE, double);
-        HANDLE_TYPE(FLOAT, float);
-        HANDLE_TYPE(BOOL, bool);
-#undef HANDLE_TYPE
-
-        case FieldDescriptor::CPPTYPE_ENUM:
-          new (field_ptr) int(field->default_value_enum()->number());
-          break;
-        case FieldDescriptor::CPPTYPE_STRING:
-          switch (field->options().ctype()) {
-            default:
-            case FieldOptions::STRING:
-              ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
-              asp->UnsafeSetDefault(&field->default_value_string());
-              break;
-          }
-          break;
-
-        case FieldDescriptor::CPPTYPE_MESSAGE: {
-          new (field_ptr) Message*(NULL);
-          break;
-        }
-      }
-    }
-  }
-}
-
-void DynamicMessageFactory::DeleteDefaultOneofInstance(
-    const Descriptor* type, const uint32 offsets[],
-    const void* default_oneof_instance) {
-  for (int i = 0; i < type->oneof_decl_count(); i++) {
-    if (type->oneof_decl(i)->is_synthetic()) continue;
-    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
-        switch (field->options().ctype()) {
-          default:
-          case FieldOptions::STRING:
-            break;
-        }
-      }
-    }
-  }
-}
-
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index 9bd609f..b85e00f 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -40,6 +40,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <unordered_map>
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
@@ -128,28 +129,13 @@
   const DescriptorPool* pool_;
   bool delegate_to_generated_factory_;
 
-  // This struct just contains a hash_map.  We can't #include <hash_map> from
-  // this header due to hacks needed for hash_map portability in the open source
-  // release.  Namely, stubs/hash.h, which defines hash_map portably, is not a
-  // public header (for good reason), but dynamic_message.h is, and public
-  // headers may only #include other public headers.
-  struct PrototypeMap;
-  std::unique_ptr<PrototypeMap> prototypes_;
+  struct TypeInfo;
+  std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
   mutable internal::WrappedMutex prototypes_mutex_;
 
   friend class DynamicMessage;
   const Message* GetPrototypeNoLock(const Descriptor* type);
 
-  // Construct default oneof instance for reflection usage if oneof
-  // is defined.
-  static void ConstructDefaultOneofInstance(const Descriptor* type,
-                                            const uint32 offsets[],
-                                            void* default_oneof_instance);
-  // Delete default oneof instance. Called by ~DynamicMessageFactory.
-  static void DeleteDefaultOneofInstance(const Descriptor* type,
-                                         const uint32 offsets[],
-                                         const void* default_oneof_instance);
-
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
 };
 
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index 6db6f5c..e22926e 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -74,7 +74,7 @@
 
   DynamicMessageTest() : factory_(&pool_) {}
 
-  virtual void SetUp() {
+  virtual void SetUp() override {
     // We want to make sure that DynamicMessage works (particularly with
     // extensions) even if we use descriptors that are *not* from compiled-in
     // types, so we make copies of the descriptors for unittest.proto and
@@ -252,7 +252,7 @@
 }
 
 TEST_P(DynamicMessageTest, SpaceUsed) {
-  // Test that SpaceUsed() works properly
+  // Test that SpaceUsedLong() works properly
 
   // Since we share the implementation with generated messages, we don't need
   // to test very much here.  Just make sure it appears to be working.
@@ -261,10 +261,10 @@
   Message* message = prototype_->New(GetParam() ? &arena : NULL);
   TestUtil::ReflectionTester reflection_tester(descriptor_);
 
-  int initial_space_used = message->SpaceUsed();
+  size_t initial_space_used = message->SpaceUsedLong();
 
   reflection_tester.SetAllFieldsViaReflection(message);
-  EXPECT_LT(initial_space_used, message->SpaceUsed());
+  EXPECT_LT(initial_space_used, message->SpaceUsedLong());
 
   if (!GetParam()) {
     delete message;
@@ -286,6 +286,7 @@
   // Return without freeing: should not leak.
 }
 
+
 TEST_F(DynamicMessageTest, Proto3) {
   Message* message = proto3_prototype_->New();
   const Reflection* refl = message->GetReflection();
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 855db18..c86ecc1 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -14,26 +14,21 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class EmptyDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Empty> _instance;
-} _Empty_default_instance_;
+constexpr Empty::Empty(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){}
+struct EmptyDefaultTypeInternal {
+  constexpr EmptyDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EmptyDefaultTypeInternal() {}
+  union {
+    Empty _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EmptyDefaultTypeInternal _Empty_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Empty_google_2fprotobuf_2fempty_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Empty_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Empty();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Empty::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Empty_google_2fprotobuf_2fempty_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Empty_google_2fprotobuf_2fempty_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fempty_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
@@ -55,40 +50,39 @@
 
 const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
   "\n\033google/protobuf/empty.proto\022\017google.pr"
-  "otobuf\"\007\n\005EmptyBv\n\023com.google.protobufB\n"
-  "EmptyProtoP\001Z\'github.com/golang/protobuf"
-  "/ptypes/empty\370\001\001\242\002\003GPB\252\002\036Google.Protobuf"
-  ".WellKnownTypesb\006proto3"
+  "otobuf\"\007\n\005EmptyB}\n\023com.google.protobufB\n"
+  "EmptyProtoP\001Z.google.golang.org/protobuf"
+  "/types/known/emptypb\370\001\001\242\002\003GPB\252\002\036Google.P"
+  "rotobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fempty_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fempty_2eproto_sccs[1] = {
-  &scc_info_Empty_google_2fprotobuf_2fempty_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fempty_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, "google/protobuf/empty.proto", 183,
-  &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, descriptor_table_google_2fprotobuf_2fempty_2eproto_sccs, descriptor_table_google_2fprotobuf_2fempty_2eproto_deps, 1, 0,
+  false, false, 190, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, "google/protobuf/empty.proto", 
+  &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fempty_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fempty_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
+  file_level_metadata_google_2fprotobuf_2fempty_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fempty_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fempty_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void Empty::InitAsDefaultInstance() {
-}
 class Empty::_Internal {
  public:
 };
 
-Empty::Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Empty::Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Empty)
 }
 Empty::Empty(const Empty& from)
@@ -97,17 +91,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Empty)
 }
 
-void Empty::SharedCtor() {
+inline void Empty::SharedCtor() {
 }
 
 Empty::~Empty() {
   // @@protoc_insertion_point(destructor:google.protobuf.Empty)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Empty::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Empty::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void Empty::ArenaDtor(void* object) {
@@ -119,11 +114,6 @@
 void Empty::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Empty& Empty::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Empty_google_2fprotobuf_2fempty_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Empty::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)
@@ -136,12 +126,11 @@
 
 const char* Empty::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -190,35 +179,26 @@
   return total_size;
 }
 
-void Empty::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Empty* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Empty>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Empty)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Empty)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Empty::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Empty::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Empty::GetClassData() const { return &_class_data_; }
+
+void Empty::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Empty *>(to)->MergeFrom(
+      static_cast<const Empty &>(from));
 }
 
+
 void Empty::MergeFrom(const Empty& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-}
-
-void Empty::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Empty)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Empty::CopyFrom(const Empty& from) {
@@ -234,14 +214,15 @@
 
 void Empty::InternalSwap(Empty* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Empty::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fempty_2eproto_getter, &descriptor_table_google_2fprotobuf_2fempty_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fempty_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index 8172d7a..64a3bde 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -45,7 +44,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -53,10 +52,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class Empty;
-class EmptyDefaultTypeInternal;
+struct EmptyDefaultTypeInternal;
 PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -66,11 +65,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT Empty PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Empty final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ {
  public:
-  inline Empty() : Empty(nullptr) {};
-  virtual ~Empty();
+  inline Empty() : Empty(nullptr) {}
+  ~Empty() override;
+  explicit constexpr Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Empty(const Empty& from);
   Empty(Empty&& from) noexcept
@@ -83,8 +83,9 @@
     return *this;
   }
   inline Empty& operator=(Empty&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -95,14 +96,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Empty& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Empty& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Empty* internal_default_instance() {
     return reinterpret_cast<const Empty*>(
                &_Empty_default_instance_);
@@ -115,7 +116,7 @@
   }
   inline void Swap(Empty* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -123,23 +124,26 @@
   }
   void UnsafeArenaSwap(Empty* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Empty* New() const final {
-    return CreateMaybeMessage<Empty>(nullptr);
+    return new Empty();
   }
 
   Empty* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Empty>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Empty& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Empty& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -150,8 +154,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Empty* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -159,20 +163,17 @@
     return "google.protobuf.Empty";
   }
   protected:
-  explicit Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fempty_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fempty_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
index 03cacd2..5f992de 100644
--- a/src/google/protobuf/empty.proto
+++ b/src/google/protobuf/empty.proto
@@ -33,7 +33,7 @@
 package google.protobuf;
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-option go_package = "github.com/golang/protobuf/ptypes/empty";
+option go_package = "google.golang.org/protobuf/types/known/emptypb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "EmptyProto";
 option java_multiple_files = true;
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 3b1441e..bad23a6 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -180,7 +180,6 @@
   Register(containing_type, number, info);
 }
 
-
 // ===================================================================
 // Constructors and basic methods.
 
@@ -192,14 +191,6 @@
                ? NULL
                : Arena::CreateArray<KeyValue>(arena_, flat_capacity_)} {}
 
-ExtensionSet::ExtensionSet()
-    : arena_(NULL),
-      flat_capacity_(0),
-      flat_size_(0),
-      map_{flat_capacity_ == 0
-               ? NULL
-               : Arena::CreateArray<KeyValue>(arena_, flat_capacity_)} {}
-
 ExtensionSet::~ExtensionSet() {
   // Deletes all allocated extensions.
   if (arena_ == NULL) {
@@ -625,7 +616,11 @@
     ClearExtension(number);
     return;
   }
-  Arena* message_arena = message->GetArena();
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  GOOGLE_DCHECK(message->GetOwningArena() == nullptr ||
+         message->GetOwningArena() == arena_);
+#endif  // PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  Arena* message_arena = message->GetOwningArena();
   Extension* extension;
   if (MaybeNewExtension(number, descriptor, &extension)) {
     extension->type = type;
@@ -1063,11 +1058,12 @@
 }
 
 void ExtensionSet::Swap(ExtensionSet* x) {
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  if (GetArena() != nullptr && GetArena() == x->GetArena()) {
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
   if (GetArena() == x->GetArena()) {
-    using std::swap;
-    swap(flat_capacity_, x->flat_capacity_);
-    swap(flat_size_, x->flat_size_);
-    swap(map_, x->map_);
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+    InternalSwap(x);
   } else {
     // TODO(cfallin, rohananil): We maybe able to optimize a case where we are
     // swapping from heap to arena-allocated extension set, by just Own()'ing
@@ -1081,54 +1077,69 @@
   }
 }
 
+void ExtensionSet::InternalSwap(ExtensionSet* other) {
+  using std::swap;
+  swap(arena_, other->arena_);
+  swap(flat_capacity_, other->flat_capacity_);
+  swap(flat_size_, other->flat_size_);
+  swap(map_, other->map_);
+}
+
 void ExtensionSet::SwapExtension(ExtensionSet* other, int number) {
   if (this == other) return;
+
+  if (GetArena() == other->GetArena()) {
+    UnsafeShallowSwapExtension(other, number);
+    return;
+  }
+
   Extension* this_ext = FindOrNull(number);
   Extension* other_ext = other->FindOrNull(number);
 
-  if (this_ext == NULL && other_ext == NULL) {
-    return;
-  }
+  if (this_ext == other_ext) return;
 
-  if (this_ext != NULL && other_ext != NULL) {
-    if (GetArena() == other->GetArena()) {
-      using std::swap;
-      swap(*this_ext, *other_ext);
-    } else {
-      // TODO(cfallin, rohananil): We could further optimize these cases,
-      // especially avoid creation of ExtensionSet, and move MergeFrom logic
-      // into Extensions itself (which takes arena as an argument).
-      // We do it this way to reuse the copy-across-arenas logic already
-      // implemented in ExtensionSet's MergeFrom.
-      ExtensionSet temp;
-      temp.InternalExtensionMergeFrom(number, *other_ext);
-      Extension* temp_ext = temp.FindOrNull(number);
-      other_ext->Clear();
-      other->InternalExtensionMergeFrom(number, *this_ext);
-      this_ext->Clear();
-      InternalExtensionMergeFrom(number, *temp_ext);
-    }
-    return;
-  }
-
-  if (this_ext == NULL) {
-    if (GetArena() == other->GetArena()) {
-      *Insert(number).first = *other_ext;
-    } else {
-      InternalExtensionMergeFrom(number, *other_ext);
-    }
+  if (this_ext != nullptr && other_ext != nullptr) {
+    // TODO(cfallin, rohananil): We could further optimize these cases,
+    // especially avoid creation of ExtensionSet, and move MergeFrom logic
+    // into Extensions itself (which takes arena as an argument).
+    // We do it this way to reuse the copy-across-arenas logic already
+    // implemented in ExtensionSet's MergeFrom.
+    ExtensionSet temp;
+    temp.InternalExtensionMergeFrom(number, *other_ext);
+    Extension* temp_ext = temp.FindOrNull(number);
+    other_ext->Clear();
+    other->InternalExtensionMergeFrom(number, *this_ext);
+    this_ext->Clear();
+    InternalExtensionMergeFrom(number, *temp_ext);
+  } else if (this_ext == nullptr) {
+    InternalExtensionMergeFrom(number, *other_ext);
+    if (other->GetArena() == nullptr) other_ext->Free();
     other->Erase(number);
-    return;
-  }
-
-  if (other_ext == NULL) {
-    if (GetArena() == other->GetArena()) {
-      *other->Insert(number).first = *this_ext;
-    } else {
-      other->InternalExtensionMergeFrom(number, *this_ext);
-    }
+  } else {
+    other->InternalExtensionMergeFrom(number, *this_ext);
+    if (GetArena() == nullptr) this_ext->Free();
     Erase(number);
-    return;
+  }
+}
+
+void ExtensionSet::UnsafeShallowSwapExtension(ExtensionSet* other, int number) {
+  if (this == other) return;
+
+  Extension* this_ext = FindOrNull(number);
+  Extension* other_ext = other->FindOrNull(number);
+
+  if (this_ext == other_ext) return;
+
+  GOOGLE_DCHECK_EQ(GetArena(), other->GetArena());
+
+  if (this_ext != nullptr && other_ext != nullptr) {
+    std::swap(*this_ext, *other_ext);
+  } else if (this_ext == nullptr) {
+    *Insert(number).first = *other_ext;
+    other->Erase(number);
+  } else {
+    *other->Insert(number).first = *this_ext;
+    Erase(number);
   }
 }
 
@@ -1463,9 +1474,9 @@
   return ParseMessageSetLite(input, &finder, &skipper);
 }
 
-uint8* ExtensionSet::_InternalSerialize(int start_field_number,
-                                        int end_field_number, uint8* target,
-                                        io::EpsCopyOutputStream* stream) const {
+uint8* ExtensionSet::_InternalSerializeImpl(
+    int start_field_number, int end_field_number, uint8* target,
+    io::EpsCopyOutputStream* stream) const {
   if (PROTOBUF_PREDICT_FALSE(is_large())) {
     const auto& end = map_.large->end();
     for (auto it = map_.large->lower_bound(start_field_number);
@@ -1729,7 +1740,7 @@
 }
 
 // This function deletes all allocated objects. This function should be only
-// called if the Extension was created with an arena.
+// called if the Extension was created without an arena.
 void ExtensionSet::Extension::Free() {
   if (is_repeated) {
     switch (cpp_type(type)) {
@@ -1870,29 +1881,30 @@
     return;
   }
 
-  const auto old_flat_capacity = flat_capacity_;
-
+  auto new_flat_capacity = flat_capacity_;
   do {
-    flat_capacity_ = flat_capacity_ == 0 ? 1 : flat_capacity_ * 4;
-  } while (flat_capacity_ < minimum_new_capacity);
+    new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4;
+  } while (new_flat_capacity < minimum_new_capacity);
 
   const KeyValue* begin = flat_begin();
   const KeyValue* end = flat_end();
-  if (flat_capacity_ > kMaximumFlatCapacity) {
-    // Switch to LargeMap
-    map_.large = Arena::Create<LargeMap>(arena_);
-    LargeMap::iterator hint = map_.large->begin();
+  AllocatedData new_map;
+  if (new_flat_capacity > kMaximumFlatCapacity) {
+    new_map.large = Arena::Create<LargeMap>(arena_);
+    LargeMap::iterator hint = new_map.large->begin();
     for (const KeyValue* it = begin; it != end; ++it) {
-      hint = map_.large->insert(hint, {it->first, it->second});
+      hint = new_map.large->insert(hint, {it->first, it->second});
     }
-    flat_size_ = 0;
   } else {
-    map_.flat = Arena::CreateArray<KeyValue>(arena_, flat_capacity_);
-    std::copy(begin, end, map_.flat);
+    new_map.flat = Arena::CreateArray<KeyValue>(arena_, new_flat_capacity);
+    std::copy(begin, end, new_map.flat);
   }
+
   if (arena_ == nullptr) {
-    DeleteFlatMap(begin, old_flat_capacity);
+    DeleteFlatMap(begin, flat_capacity_);
   }
+  flat_capacity_ = new_flat_capacity;
+  map_ = new_map;
 }
 
 // static
@@ -2145,3 +2157,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index b30a960..e3d1669 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -173,7 +173,7 @@
 // off to the ExtensionSet for parsing.  Etc.
 class PROTOBUF_EXPORT ExtensionSet {
  public:
-  ExtensionSet();
+  constexpr ExtensionSet();
   explicit ExtensionSet(Arena* arena);
   ~ExtensionSet();
 
@@ -282,12 +282,13 @@
   void UnsafeArenaSetAllocatedMessage(int number, FieldType type,
                                       const FieldDescriptor* descriptor,
                                       MessageLite* message);
-  MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
+  PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseMessage(
+      int number, const MessageLite& prototype);
   MessageLite* UnsafeArenaReleaseMessage(int number,
                                          const MessageLite& prototype);
 
-  MessageLite* ReleaseMessage(const FieldDescriptor* descriptor,
-                              MessageFactory* factory);
+  PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseMessage(
+      const FieldDescriptor* descriptor, MessageFactory* factory);
   MessageLite* UnsafeArenaReleaseMessage(const FieldDescriptor* descriptor,
                                          MessageFactory* factory);
 #undef desc
@@ -354,7 +355,7 @@
 #undef desc
 
   void RemoveLast(int number);
-  MessageLite* ReleaseLast(int number);
+  PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseLast(int number);
   void SwapElements(int number, int index1, int index2);
 
   // -----------------------------------------------------------------
@@ -369,7 +370,9 @@
   void Clear();
   void MergeFrom(const ExtensionSet& other);
   void Swap(ExtensionSet* other);
+  void InternalSwap(ExtensionSet* other);
   void SwapExtension(ExtensionSet* other, int number);
+  void UnsafeShallowSwapExtension(ExtensionSet* other, int number);
   bool IsInitialized() const;
 
   // Parses a single extension from the input. The input should start out
@@ -469,7 +472,14 @@
   // Returns a pointer past the last written byte.
   uint8* _InternalSerialize(int start_field_number, int end_field_number,
                             uint8* target,
-                            io::EpsCopyOutputStream* stream) const;
+                            io::EpsCopyOutputStream* stream) const {
+    if (flat_size_ == 0) {
+      assert(!is_large());
+      return target;
+    }
+    return _InternalSerializeImpl(start_field_number, end_field_number, target,
+                                  stream);
+  }
 
   // Like above but serializes in MessageSet format.
   void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const {
@@ -510,6 +520,10 @@
   int SpaceUsedExcludingSelf() const;
 
  private:
+  // Implementation of _InternalSerialize for non-empty map_.
+  uint8* _InternalSerializeImpl(int start_field_number, int end_field_number,
+                                uint8* target,
+                                io::EpsCopyOutputStream* stream) const;
   // Interface of a lazily parsed singular message extension.
   class PROTOBUF_EXPORT LazyMessageExtension {
    public:
@@ -522,7 +536,8 @@
     virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
     virtual void SetAllocatedMessage(MessageLite* message) = 0;
     virtual void UnsafeArenaSetAllocatedMessage(MessageLite* message) = 0;
-    virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
+    virtual PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseMessage(
+        const MessageLite& prototype) = 0;
     virtual MessageLite* UnsafeArenaReleaseMessage(
         const MessageLite& prototype) = 0;
 
@@ -850,6 +865,9 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
 };
 
+constexpr ExtensionSet::ExtensionSet()
+    : arena_(nullptr), flat_capacity_(0), flat_size_(0), map_{nullptr} {}
+
 // These are just for convenience...
 inline void ExtensionSet::SetString(int number, FieldType type,
                                     std::string value,
@@ -1245,8 +1263,8 @@
                                              ExtensionSet* set) {
     set->UnsafeArenaSetAllocatedMessage(number, field_type, NULL, message);
   }
-  static inline MutableType Release(int number, FieldType /* field_type */,
-                                    ExtensionSet* set) {
+  static inline PROTOBUF_MUST_USE_RESULT MutableType
+  Release(int number, FieldType /* field_type */, ExtensionSet* set) {
     return static_cast<Type*>(
         set->ReleaseMessage(number, Type::default_instance()));
   }
@@ -1325,7 +1343,9 @@
 // ExtensionIdentifier
 
 // This is the type of actual extension objects.  E.g. if you have:
-//   extends Foo with optional int32 bar = 1234;
+//   extend Foo {
+//     optional int32 bar = 1234;
+//   }
 // then "bar" will be defined in C++ as:
 //   ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>, 5, false> bar(1234);
 //
@@ -1459,9 +1479,11 @@
   template <typename _proto_TypeTraits,                                       \
             ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,         \
             bool _is_packed>                                                  \
-  inline typename _proto_TypeTraits::Singular::MutableType ReleaseExtension(  \
-      const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<           \
-          CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {       \
+  inline PROTOBUF_MUST_USE_RESULT                                             \
+      typename _proto_TypeTraits::Singular::MutableType                       \
+      ReleaseExtension(                                                       \
+          const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<       \
+              CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {   \
     return _proto_TypeTraits::Release(id.number(), _field_type,               \
                                       &_extensions_);                         \
   }                                                                           \
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 86e710c..76ac076 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -534,3 +534,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/extension_set_inl.h b/src/google/protobuf/extension_set_inl.h
index 9957f8b..074784b 100644
--- a/src/google/protobuf/extension_set_inl.h
+++ b/src/google/protobuf/extension_set_inl.h
@@ -207,6 +207,7 @@
     internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
   std::string payload;
   uint32 type_id = 0;
+  bool payload_read = false;
   while (!ctx->Done(&ptr)) {
     uint32 tag = static_cast<uint8>(*ptr++);
     if (tag == WireFormatLite::kMessageSetTypeIdTag) {
@@ -214,7 +215,7 @@
       ptr = ParseBigVarint(ptr, &tmp);
       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
       type_id = tmp;
-      if (!payload.empty()) {
+      if (payload_read) {
         ExtensionInfo extension;
         bool was_packed_on_wire;
         if (!FindExtension(2, type_id, containing_type, ctx, &extension,
@@ -253,6 +254,7 @@
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ptr = ctx->ReadString(ptr, size, &payload);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        payload_read = true;
       }
     } else {
       ptr = ReadTag(ptr - 1, &tag);
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 4bdd736..7971fe5 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -46,13 +46,15 @@
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/wire_format.h>
-
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/stl_util.h>
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
 
 namespace google {
 namespace protobuf {
@@ -196,7 +198,8 @@
   // ReleaseExtension will return the underlying object even after
   // ClearExtension is called.
   message.SetAllocatedExtension(
-      unittest::TestMessageSetExtension1::message_set_extension, extension);
+      unittest::TestMessageSetExtension1::message_set_extension,
+      released_extension);
   message.ClearExtension(
       unittest::TestMessageSetExtension1::message_set_extension);
   released_extension = message.ReleaseExtension(
@@ -514,7 +517,7 @@
   unittest::TestAllExtensions source;
   unittest::TestAllTypes destination;
   TestUtil::SetAllExtensions(&source);
-  int size = source.ByteSize();
+  size_t size = source.ByteSizeLong();
   std::string data;
   data.resize(size);
   uint8* target = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
@@ -535,7 +538,7 @@
   unittest::TestAllExtensions source;
   unittest::TestAllTypes destination;
   TestUtil::SetAllExtensions(&source);
-  int size = source.ByteSize();
+  size_t size = source.ByteSizeLong();
   std::string data;
   data.resize(size);
   {
@@ -558,7 +561,7 @@
   unittest::TestPackedExtensions source;
   unittest::TestPackedTypes destination;
   TestUtil::SetPackedExtensions(&source);
-  int size = source.ByteSize();
+  size_t size = source.ByteSizeLong();
   std::string data;
   data.resize(size);
   uint8* target = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
@@ -579,7 +582,7 @@
   unittest::TestPackedExtensions source;
   unittest::TestPackedTypes destination;
   TestUtil::SetPackedExtensions(&source);
-  int size = source.ByteSize();
+  size_t size = source.ByteSizeLong();
   std::string data;
   data.resize(size);
   {
@@ -739,12 +742,12 @@
 #define TEST_SCALAR_EXTENSIONS_SPACE_USED(type, value)                       \
   do {                                                                       \
     unittest::TestAllExtensions message;                                     \
-    const int base_size = message.SpaceUsed();                               \
+    const int base_size = message.SpaceUsedLong();                           \
     message.SetExtension(unittest::optional_##type##_extension, value);      \
     int min_expected_size =                                                  \
         base_size +                                                          \
         sizeof(message.GetExtension(unittest::optional_##type##_extension)); \
-    EXPECT_LE(min_expected_size, message.SpaceUsed());                       \
+    EXPECT_LE(min_expected_size, message.SpaceUsedLong());                   \
   } while (0)
 
   TEST_SCALAR_EXTENSIONS_SPACE_USED(int32, 101);
@@ -763,36 +766,36 @@
 #undef TEST_SCALAR_EXTENSIONS_SPACE_USED
   {
     unittest::TestAllExtensions message;
-    const int base_size = message.SpaceUsed();
+    const int base_size = message.SpaceUsedLong();
     message.SetExtension(unittest::optional_nested_enum_extension,
                          unittest::TestAllTypes::FOO);
     int min_expected_size =
         base_size +
         sizeof(message.GetExtension(unittest::optional_nested_enum_extension));
-    EXPECT_LE(min_expected_size, message.SpaceUsed());
+    EXPECT_LE(min_expected_size, message.SpaceUsedLong());
   }
   {
     // Strings may cause extra allocations depending on their length; ensure
     // that gets included as well.
     unittest::TestAllExtensions message;
-    const int base_size = message.SpaceUsed();
+    const int base_size = message.SpaceUsedLong();
     const std::string s(
         "this is a fairly large string that will cause some "
         "allocation in order to store it in the extension");
     message.SetExtension(unittest::optional_string_extension, s);
     int min_expected_size = base_size + s.length();
-    EXPECT_LE(min_expected_size, message.SpaceUsed());
+    EXPECT_LE(min_expected_size, message.SpaceUsedLong());
   }
   {
     // Messages also have additional allocation that need to be counted.
     unittest::TestAllExtensions message;
-    const int base_size = message.SpaceUsed();
+    const int base_size = message.SpaceUsedLong();
     unittest::ForeignMessage foreign;
     foreign.set_c(42);
     message.MutableExtension(unittest::optional_foreign_message_extension)
         ->CopyFrom(foreign);
-    int min_expected_size = base_size + foreign.SpaceUsed();
-    EXPECT_LE(min_expected_size, message.SpaceUsed());
+    int min_expected_size = base_size + foreign.SpaceUsedLong();
+    EXPECT_LE(min_expected_size, message.SpaceUsedLong());
   }
 
   // Repeated primitive extensions will increase space used by at least a
@@ -802,26 +805,26 @@
   //   - Adds a value to the repeated extension, then clears it, establishing
   //     the base size.
   //   - Adds a small number of values, testing that it doesn't increase the
-  //     SpaceUsed()
+  //     SpaceUsedLong()
   //   - Adds a large number of values (requiring allocation in the repeated
-  //     field), and ensures that that allocation is included in SpaceUsed()
+  //     field), and ensures that that allocation is included in SpaceUsedLong()
 #define TEST_REPEATED_EXTENSIONS_SPACE_USED(type, cpptype, value)             \
   do {                                                                        \
     unittest::TestAllExtensions message;                                      \
-    const int base_size = message.SpaceUsed();                                \
-    int min_expected_size = sizeof(RepeatedField<cpptype>) + base_size;       \
+    const size_t base_size = message.SpaceUsedLong();                         \
+    size_t min_expected_size = sizeof(RepeatedField<cpptype>) + base_size;    \
     message.AddExtension(unittest::repeated_##type##_extension, value);       \
     message.ClearExtension(unittest::repeated_##type##_extension);            \
-    const int empty_repeated_field_size = message.SpaceUsed();                \
+    const size_t empty_repeated_field_size = message.SpaceUsedLong();         \
     EXPECT_LE(min_expected_size, empty_repeated_field_size) << #type;         \
     message.AddExtension(unittest::repeated_##type##_extension, value);       \
     message.AddExtension(unittest::repeated_##type##_extension, value);       \
-    EXPECT_EQ(empty_repeated_field_size, message.SpaceUsed()) << #type;       \
+    EXPECT_EQ(empty_repeated_field_size, message.SpaceUsedLong()) << #type;   \
     message.ClearExtension(unittest::repeated_##type##_extension);            \
-    const int old_capacity =                                                  \
+    const size_t old_capacity =                                               \
         message.GetRepeatedExtension(unittest::repeated_##type##_extension)   \
             .Capacity();                                                      \
-    EXPECT_GE(old_capacity, kMinRepeatedFieldAllocationSize);                 \
+    EXPECT_GE(old_capacity, kRepeatedFieldLowerClampLimit);                   \
     for (int i = 0; i < 16; ++i) {                                            \
       message.AddExtension(unittest::repeated_##type##_extension, value);     \
     }                                                                         \
@@ -832,7 +835,7 @@
                  .Capacity() -                                                \
              old_capacity) +                                                  \
         empty_repeated_field_size;                                            \
-    EXPECT_LE(expected_size, message.SpaceUsed()) << #type;                   \
+    EXPECT_LE(expected_size, message.SpaceUsedLong()) << #type;               \
   } while (0)
 
   TEST_REPEATED_EXTENSIONS_SPACE_USED(int32, int32, 101);
@@ -854,8 +857,9 @@
   // Repeated strings
   {
     unittest::TestAllExtensions message;
-    const int base_size = message.SpaceUsed();
-    int min_expected_size = sizeof(RepeatedPtrField<std::string>) + base_size;
+    const size_t base_size = message.SpaceUsedLong();
+    size_t min_expected_size =
+        sizeof(RepeatedPtrField<std::string>) + base_size;
     const std::string value(256, 'x');
     // Once items are allocated, they may stick around even when cleared so
     // without the hardcore memory management accessors there isn't a notion of
@@ -864,14 +868,14 @@
       message.AddExtension(unittest::repeated_string_extension, value);
     }
     min_expected_size +=
-        (sizeof(value) + value.size()) * (16 - kMinRepeatedFieldAllocationSize);
-    EXPECT_LE(min_expected_size, message.SpaceUsed());
+        (sizeof(value) + value.size()) * (16 - kRepeatedFieldLowerClampLimit);
+    EXPECT_LE(min_expected_size, message.SpaceUsedLong());
   }
   // Repeated messages
   {
     unittest::TestAllExtensions message;
-    const int base_size = message.SpaceUsed();
-    int min_expected_size =
+    const size_t base_size = message.SpaceUsedLong();
+    size_t min_expected_size =
         sizeof(RepeatedPtrField<unittest::ForeignMessage>) + base_size;
     unittest::ForeignMessage prototype;
     prototype.set_c(2);
@@ -880,8 +884,8 @@
           ->CopyFrom(prototype);
     }
     min_expected_size +=
-        (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed();
-    EXPECT_LE(min_expected_size, message.SpaceUsed());
+        (16 - kRepeatedFieldLowerClampLimit) * prototype.SpaceUsedLong();
+    EXPECT_LE(min_expected_size, message.SpaceUsedLong());
   }
 }
 
@@ -1104,8 +1108,6 @@
     ASSERT_EQ(msg_const_iter->bb(), 1234);
   }
 
-  // Test range-based for as well, but only if compiled as C++11.
-#if __cplusplus >= 201103L
   // Test one primitive field.
   for (auto& x :
        *message.MutableRepeatedExtension(unittest::repeated_int32_extension)) {
@@ -1133,7 +1135,6 @@
            unittest::repeated_nested_message_extension)) {
     ASSERT_EQ(x.bb(), 4321);
   }
-#endif
 }
 
 // From b/12926163
@@ -1326,6 +1327,11 @@
   EXPECT_TRUE(msg.GetExtension(protobuf_unittest::optional_bool_extension));
 }
 
+TEST(ExtensionSetTest, ConstInit) {
+  PROTOBUF_CONSTINIT static ExtensionSet set{};
+  EXPECT_EQ(set.NumExtensions(), 0);
+}
+
 }  // namespace
 }  // namespace internal
 }  // namespace protobuf
diff --git a/python/google/protobuf/python_protobuf.h b/src/google/protobuf/field_access_listener.cc
similarity index 72%
rename from python/google/protobuf/python_protobuf.h
rename to src/google/protobuf/field_access_listener.cc
index 8db1ffb..56e175a 100644
--- a/python/google/protobuf/python_protobuf.h
+++ b/src/google/protobuf/field_access_listener.cc
@@ -28,30 +28,25 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: qrczak@google.com (Marcin Kowalczyk)
-//
-// This module exposes the C proto inside the given Python proto, in
-// case the Python proto is implemented with a C proto.
+#include <google/protobuf/field_access_listener.h>
 
-#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
-#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
-
-#include <Python.h>
+#include <google/protobuf/stubs/once.h>
 
 namespace google {
 namespace protobuf {
 
-class Message;
+internal::once_flag FieldAccessListener::register_once_ = {};
+FieldAccessListener* FieldAccessListener::field_listener_ = nullptr;
 
-namespace python {
+FieldAccessListener* FieldAccessListener::GetListener() {
+  return field_listener_;
+}
 
-// Return the pointer to the C proto inside the given Python proto,
-// or NULL when this is not a Python proto implemented with a C proto.
-const Message* GetCProtoInsidePyProto(PyObject* msg);
-Message* MutableCProtoInsidePyProto(PyObject* msg);
+void FieldAccessListener::RegisterListener(FieldAccessListener* listener) {
+  // TODO(danilak): Add a GOOGLE_DCHECK for message_injector_ to be nullptr and update
+  // tests.
+  internal::call_once(register_once_, [&] { field_listener_ = listener; });
+}
 
-}  // namespace python
 }  // namespace protobuf
 }  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
diff --git a/src/google/protobuf/field_access_listener.h b/src/google/protobuf/field_access_listener.h
new file mode 100644
index 0000000..660ad73
--- /dev/null
+++ b/src/google/protobuf/field_access_listener.h
@@ -0,0 +1,246 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
+#define GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
+
+#include <cstddef>
+#include <functional>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/repeated_field.h>
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template <typename T>
+struct ResolvedType {
+  using type = T;
+};
+}  // namespace internal
+// Tracks the events of field accesses for all protos
+// that are built with --inject_field_listener_events. This is a global
+// interface which you must implement yourself and register with
+// RegisterListener() function. All events consist of Descriptors,
+// FieldAccessTypes and the underlying storage for tracking the memory which is
+// accessed where possible and makes sense. Users are responsible for the
+// implementations to be thread safe.
+class FieldAccessListener {
+ public:
+  FieldAccessListener() = default;
+  virtual ~FieldAccessListener() = default;
+
+  // The memory annotations of the proto fields that are touched by the
+  // accessors. They are returned as if the operation completes.
+  struct DataAnnotation {
+    DataAnnotation() = default;
+    DataAnnotation(const void* other_address, size_t other_size)
+        : address(other_address), size(other_size) {}
+    const void* address = nullptr;
+    size_t size = 0;
+  };
+  using AddressInfo = std::vector<DataAnnotation>;
+  using AddressInfoExtractor = std::function<AddressInfo()>;
+
+  enum class FieldAccessType {
+    kAdd,          // add_<field>(f)
+    kAddMutable,   // add_<field>()
+    kGet,          // <field>() and <repeated_field>(i)
+    kClear,        // clear_<field>()
+    kHas,          // has_<field>()
+    kList,         // <repeated_field>()
+    kMutable,      // mutable_<field>()
+    kMutableList,  // mutable_<repeated_field>()
+    kRelease,      // release_<field>()
+    kSet,          // set_<field>() and set_<repeated_field>(i)
+    kSize,         // <repeated_field>_size()
+  };
+
+  static FieldAccessListener* GetListener();
+
+  // Registers the field listener, can be called only once, |listener| must
+  // outlive all proto accesses (in most cases, the lifetime of the program).
+  static void RegisterListener(FieldAccessListener* listener);
+
+  // All field accessors noted in FieldAccessType have this call.
+  // |extractor| extracts the address info from the field
+  virtual void OnFieldAccess(const AddressInfoExtractor& extractor,
+                             const FieldDescriptor* descriptor,
+                             FieldAccessType access_type) = 0;
+
+  // Side effect calls.
+  virtual void OnDeserializationAccess(const Message* message) = 0;
+  virtual void OnSerializationAccess(const Message* message) = 0;
+  virtual void OnReflectionAccess(const Descriptor* descriptor) = 0;
+  virtual void OnByteSizeAccess(const Message* message) = 0;
+  // We can probably add more if we need to, like {Merge,Copy}{From}Access.
+
+  // Extracts all the addresses from the underlying fields.
+  template <typename T>
+  AddressInfo ExtractFieldInfo(const T* field_value);
+
+
+ private:
+  template <typename T>
+  AddressInfo ExtractFieldInfoSpecific(const T* field_value,
+                                       internal::ResolvedType<T>);
+
+  AddressInfo ExtractFieldInfoSpecific(const Message* field_value,
+                                       internal::ResolvedType<Message>);
+
+  AddressInfo ExtractFieldInfoSpecific(const std::string* field_value,
+                                       internal::ResolvedType<std::string>);
+
+  AddressInfo ExtractFieldInfoSpecific(
+      const internal::ArenaStringPtr* field_value,
+      internal::ResolvedType<internal::ArenaStringPtr>);
+
+  template <typename T>
+  AddressInfo ExtractFieldInfoSpecific(
+      const RepeatedField<T>* field_value,
+      internal::ResolvedType<RepeatedField<T>>);
+
+  template <typename T>
+  AddressInfo ExtractFieldInfoSpecific(
+      const RepeatedPtrField<T>* field_value,
+      internal::ResolvedType<RepeatedPtrField<T>>);
+
+  template <typename K, typename V>
+  AddressInfo ExtractFieldInfoSpecific(const Map<K, V>* field_value,
+                                       internal::ResolvedType<Map<K, V>>);
+
+  static internal::once_flag register_once_;
+  static FieldAccessListener* field_listener_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldAccessListener);
+};
+
+template <typename T>
+inline FieldAccessListener::AddressInfo FieldAccessListener::ExtractFieldInfo(
+    const T* field_value) {
+  return ExtractFieldInfoSpecific(field_value, internal::ResolvedType<T>());
+}
+
+
+template <typename T>
+inline FieldAccessListener::AddressInfo
+FieldAccessListener::ExtractFieldInfoSpecific(const T* field_value,
+                                              internal::ResolvedType<T>) {
+  static_assert(std::is_trivial<T>::value,
+                "This overload should be chosen only for trivial types");
+  return FieldAccessListener::AddressInfo{FieldAccessListener::DataAnnotation(
+      static_cast<const void*>(field_value), sizeof(*field_value))};
+}
+
+inline FieldAccessListener::AddressInfo
+FieldAccessListener::ExtractFieldInfoSpecific(
+    const std::string* field_value, internal::ResolvedType<std::string>) {
+  return FieldAccessListener::AddressInfo{FieldAccessListener::DataAnnotation(
+      static_cast<const void*>(field_value->c_str()), field_value->length())};
+}
+
+inline FieldAccessListener::AddressInfo
+FieldAccessListener::ExtractFieldInfoSpecific(
+    const internal::ArenaStringPtr* field_value,
+    internal::ResolvedType<internal::ArenaStringPtr>) {
+  return FieldAccessListener::ExtractFieldInfoSpecific(
+      field_value->GetPointer(), internal::ResolvedType<std::string>());
+}
+
+template <typename T>
+inline FieldAccessListener::AddressInfo
+FieldAccessListener::ExtractFieldInfoSpecific(
+    const RepeatedField<T>* field_value,
+    internal::ResolvedType<RepeatedField<T>>) {
+  // TODO(jianzhouzh): This can cause data races. Synchronize this if needed.
+  FieldAccessListener::AddressInfo address_info;
+  address_info.reserve(field_value->size());
+  for (int i = 0, ie = field_value->size(); i < ie; ++i) {
+    auto sub = ExtractFieldInfoSpecific(&field_value->Get(i),
+                                        internal::ResolvedType<T>());
+    address_info.insert(address_info.end(), sub.begin(), sub.end());
+  }
+  return address_info;
+}
+
+template <typename T>
+inline FieldAccessListener::AddressInfo
+FieldAccessListener::ExtractFieldInfoSpecific(
+    const RepeatedPtrField<T>* field_value,
+    internal::ResolvedType<RepeatedPtrField<T>>) {
+  FieldAccessListener::AddressInfo address_info;
+  // TODO(jianzhouzh): This can cause data races. Synchronize this if needed.
+  address_info.reserve(field_value->size());
+  for (int i = 0, ie = field_value->size(); i < ie; ++i) {
+    auto sub = ExtractFieldInfoSpecific(&field_value->Get(i),
+                                        internal::ResolvedType<T>());
+    address_info.insert(address_info.end(), sub.begin(), sub.end());
+  }
+  return address_info;
+}
+
+template <typename K, typename V>
+inline FieldAccessListener::AddressInfo
+FieldAccessListener::ExtractFieldInfoSpecific(
+    const Map<K, V>* field_value, internal::ResolvedType<Map<K, V>>) {
+  // TODO(jianzhouzh): This can cause data races. Synchronize this if needed.
+  FieldAccessListener::AddressInfo address_info;
+  address_info.reserve(field_value->size());
+  for (auto it = field_value->begin(); it != field_value->end(); ++it) {
+    auto sub_first =
+        ExtractFieldInfoSpecific(&it->first, internal::ResolvedType<K>());
+    auto sub_second =
+        ExtractFieldInfoSpecific(&it->second, internal::ResolvedType<V>());
+    address_info.insert(address_info.end(), sub_first.begin(), sub_first.end());
+    address_info.insert(address_info.end(), sub_second.begin(),
+                        sub_second.end());
+  }
+  return address_info;
+}
+
+inline FieldAccessListener::AddressInfo
+FieldAccessListener::ExtractFieldInfoSpecific(const Message* field_value,
+                                              internal::ResolvedType<Message>) {
+  // TODO(jianzhouzh): implement and adjust all annotations in the compiler.
+  return {};
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 42e077f..a76cff2 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -14,26 +14,22 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class FieldMaskDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FieldMask> _instance;
-} _FieldMask_default_instance_;
+constexpr FieldMask::FieldMask(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : paths_(){}
+struct FieldMaskDefaultTypeInternal {
+  constexpr FieldMaskDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldMaskDefaultTypeInternal() {}
+  union {
+    FieldMask _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FieldMask();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::FieldMask::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
@@ -57,41 +53,40 @@
 const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
   "\n google/protobuf/field_mask.proto\022\017goog"
   "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB"
-  "\214\001\n\023com.google.protobufB\016FieldMaskProtoP"
-  "\001Z9google.golang.org/genproto/protobuf/f"
-  "ield_mask;field_mask\370\001\001\242\002\003GPB\252\002\036Google.P"
-  "rotobuf.WellKnownTypesb\006proto3"
+  "\205\001\n\023com.google.protobufB\016FieldMaskProtoP"
+  "\001Z2google.golang.org/protobuf/types/know"
+  "n/fieldmaskpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf"
+  ".WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_sccs[1] = {
-  &scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, "google/protobuf/field_mask.proto", 230,
-  &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_sccs, descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_deps, 1, 0,
+  false, false, 223, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, "google/protobuf/field_mask.proto", 
+  &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
+  file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void FieldMask::InitAsDefaultInstance() {
-}
 class FieldMask::_Internal {
  public:
 };
 
-FieldMask::FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+FieldMask::FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   paths_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldMask)
 }
 FieldMask::FieldMask(const FieldMask& from)
@@ -101,18 +96,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldMask)
 }
 
-void FieldMask::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base);
+inline void FieldMask::SharedCtor() {
 }
 
 FieldMask::~FieldMask() {
   // @@protoc_insertion_point(destructor:google.protobuf.FieldMask)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void FieldMask::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void FieldMask::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void FieldMask::ArenaDtor(void* object) {
@@ -124,11 +119,6 @@
 void FieldMask::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FieldMask& FieldMask::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FieldMask::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
@@ -142,11 +132,9 @@
 
 const char* FieldMask::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated string paths = 1;
       case 1:
@@ -164,7 +152,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -233,36 +222,27 @@
   return total_size;
 }
 
-void FieldMask::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FieldMask* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<FieldMask>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldMask)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldMask)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FieldMask::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    FieldMask::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FieldMask::GetClassData() const { return &_class_data_; }
+
+void FieldMask::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<FieldMask *>(to)->MergeFrom(
+      static_cast<const FieldMask &>(from));
 }
 
+
 void FieldMask::MergeFrom(const FieldMask& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   paths_.MergeFrom(from.paths_);
-}
-
-void FieldMask::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldMask)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void FieldMask::CopyFrom(const FieldMask& from) {
@@ -278,15 +258,16 @@
 
 void FieldMask::InternalSwap(FieldMask* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   paths_.InternalSwap(&other->paths_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldMask::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_getter, &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index f5f1ff2..2c690fa 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -45,7 +44,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -53,10 +52,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class FieldMask;
-class FieldMaskDefaultTypeInternal;
+struct FieldMaskDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -66,11 +65,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT FieldMask PROTOBUF_FINAL :
+class PROTOBUF_EXPORT FieldMask final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ {
  public:
-  inline FieldMask() : FieldMask(nullptr) {};
-  virtual ~FieldMask();
+  inline FieldMask() : FieldMask(nullptr) {}
+  ~FieldMask() override;
+  explicit constexpr FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldMask(const FieldMask& from);
   FieldMask(FieldMask&& from) noexcept
@@ -83,8 +83,9 @@
     return *this;
   }
   inline FieldMask& operator=(FieldMask&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -95,14 +96,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const FieldMask& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const FieldMask& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldMask* internal_default_instance() {
     return reinterpret_cast<const FieldMask*>(
                &_FieldMask_default_instance_);
@@ -115,7 +116,7 @@
   }
   inline void Swap(FieldMask* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -123,23 +124,26 @@
   }
   void UnsafeArenaSwap(FieldMask* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline FieldMask* New() const final {
-    return CreateMaybeMessage<FieldMask>(nullptr);
+    return new FieldMask();
   }
 
   FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<FieldMask>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const FieldMask& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const FieldMask& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -150,8 +154,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(FieldMask* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -159,20 +163,17 @@
     return "google.protobuf.FieldMask";
   }
   protected:
-  explicit FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -238,8 +239,9 @@
   paths_.Clear();
 }
 inline std::string* FieldMask::add_paths() {
+  std::string* _s = _internal_add_paths();
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
-  return _internal_add_paths();
+  return _s;
 }
 inline const std::string& FieldMask::_internal_paths(int index) const {
   return paths_.Get(index);
@@ -253,12 +255,12 @@
   return paths_.Mutable(index);
 }
 inline void FieldMask::set_paths(int index, const std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
   paths_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
 }
 inline void FieldMask::set_paths(int index, std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
   paths_.Mutable(index)->assign(std::move(value));
+  // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
 }
 inline void FieldMask::set_paths(int index, const char* value) {
   GOOGLE_DCHECK(value != nullptr);
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
index baac874..6b5104f 100644
--- a/src/google/protobuf/field_mask.proto
+++ b/src/google/protobuf/field_mask.proto
@@ -37,7 +37,7 @@
 option java_outer_classname = "FieldMaskProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
-option go_package = "google.golang.org/genproto/protobuf/field_mask;field_mask";
+option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb";
 option cc_enable_arenas = true;
 
 // `FieldMask` represents a set of symbolic field paths, for example:
diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h
index c25e51b..5debc0a 100644
--- a/src/google/protobuf/generated_enum_reflection.h
+++ b/src/google/protobuf/generated_enum_reflection.h
@@ -43,6 +43,7 @@
 
 #include <google/protobuf/generated_enum_util.h>
 #include <google/protobuf/port.h>
+#include <google/protobuf/stubs/strutil.h>
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -71,10 +72,10 @@
 // an enum name of the given type, returning true and filling in value on
 // success, or returning false and leaving value unchanged on failure.
 PROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
-                                    const std::string& name, int* value);
+                                    ConstStringParam name, int* value);
 
 template <typename EnumType>
-bool ParseNamedEnum(const EnumDescriptor* descriptor, const std::string& name,
+bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
                     EnumType* value) {
   int tmp;
   if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
diff --git a/src/google/protobuf/generated_enum_util.cc b/src/google/protobuf/generated_enum_util.cc
index d0c25a9..df7583e 100644
--- a/src/google/protobuf/generated_enum_util.cc
+++ b/src/google/protobuf/generated_enum_util.cc
@@ -83,7 +83,7 @@
 bool InitializeEnumStrings(
     const EnumEntry* enums, const int* sorted_indices, size_t size,
     internal::ExplicitlyConstructed<std::string>* enum_strings) {
-  for (int i = 0; i < size; ++i) {
+  for (size_t i = 0; i < size; ++i) {
     enum_strings[i].Construct(enums[sorted_indices[i]].name);
     internal::OnShutdownDestroyString(enum_strings[i].get_mutable());
   }
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 6ee8c98..f50352f 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -43,13 +43,13 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/map_field.h>
 #include <google/protobuf/map_field_inl.h>
 #include <google/protobuf/stubs/mutex.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -61,7 +61,6 @@
 using google::protobuf::internal::ExtensionSet;
 using google::protobuf::internal::GenericTypeHandler;
 using google::protobuf::internal::GetEmptyString;
-using google::protobuf::internal::InlinedStringField;
 using google::protobuf::internal::InternalMetadata;
 using google::protobuf::internal::LazyField;
 using google::protobuf::internal::MapFieldBase;
@@ -77,11 +76,22 @@
 
 namespace {
 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
+
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+Message* MaybeForceCopy(Arena* arena, Message* msg) {
+  if (arena != nullptr || msg == nullptr) return msg;
+
+  Message* copy = msg->New();
+  copy->MergeFrom(*msg);
+  delete msg;
+  return copy;
+}
+#endif  // PROTOBUF_FORCE_COPY_IN_RELEASE
 }  // anonymous namespace
 
 namespace internal {
 
-bool ParseNamedEnum(const EnumDescriptor* descriptor, const std::string& name,
+bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
                     int* value) {
   const EnumValueDescriptor* d = descriptor->FindValueByName(name);
   if (d == nullptr) return false;
@@ -171,6 +181,12 @@
              << value->full_name();
 }
 
+inline void CheckInvalidAccess(const internal::ReflectionSchema& schema,
+                               const FieldDescriptor* field) {
+  GOOGLE_CHECK(!schema.IsFieldStripped(field))
+      << "invalid access to a stripped field " << field->full_name();
+}
+
 #define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \
   if (!(CONDITION))                                       \
   ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION)
@@ -230,6 +246,16 @@
       ->mutable_unknown_fields<UnknownFieldSet>();
 }
 
+bool Reflection::IsLazilyVerifiedLazyField(const FieldDescriptor* field) const {
+  return field->options().lazy();
+}
+
+bool Reflection::IsEagerlyVerifiedLazyField(
+    const FieldDescriptor* field) const {
+  return (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+          schema_.IsEagerlyVerifiedLazyField(field));
+}
+
 size_t Reflection::SpaceUsedLong(const Message& message) const {
   // object_size_ already includes the in-memory representation of each field
   // in the message, so we only need to account for additional memory used by
@@ -306,22 +332,16 @@
           switch (field->options().ctype()) {
             default:  // TODO(kenton):  Support other string reps.
             case FieldOptions::STRING: {
-              if (IsInlined(field)) {
-                const std::string* ptr =
-                    &GetField<InlinedStringField>(message, field).GetNoArena();
-                total_size += StringSpaceUsedExcludingSelfLong(*ptr);
-                break;
-              }
+              const std::string* ptr =
+                  GetField<ArenaStringPtr>(message, field).GetPointer();
 
               // Initially, the string points to the default value stored
               // in the prototype. Only count the string if it has been
               // changed from the default value.
-              const std::string* default_ptr =
-                  &DefaultRaw<ArenaStringPtr>(field).Get();
-              const std::string* ptr =
-                  &GetField<ArenaStringPtr>(message, field).Get();
-
-              if (ptr != default_ptr) {
+              // Except oneof fields, those never point to a default instance,
+              // and there is no default instance to point to.
+              if (schema_.InRealOneof(field) ||
+                  ptr != DefaultRaw<ArenaStringPtr>(field).GetPointer()) {
                 // string fields are represented by just a pointer, so also
                 // include sizeof(string) as well.
                 total_size +=
@@ -350,6 +370,176 @@
   return total_size;
 }
 
+namespace internal {
+
+class SwapFieldHelper {
+ public:
+  template <bool unsafe_shallow_swap>
+  static void SwapRepeatedStringField(const Reflection* r, Message* lhs,
+                                      Message* rhs,
+                                      const FieldDescriptor* field);
+
+  template <bool unsafe_shallow_swap>
+  static void SwapStringField(const Reflection* r, Message* lhs, Message* rhs,
+                              const FieldDescriptor* field);
+
+  static void SwapArenaStringPtr(const std::string* default_ptr,
+                                 ArenaStringPtr* lhs, Arena* lhs_arena,
+                                 ArenaStringPtr* rhs, Arena* rhs_arena);
+
+  template <bool unsafe_shallow_swap>
+  static void SwapRepeatedMessageField(const Reflection* r, Message* lhs,
+                                       Message* rhs,
+                                       const FieldDescriptor* field);
+
+  template <bool unsafe_shallow_swap>
+  static void SwapMessageField(const Reflection* r, Message* lhs, Message* rhs,
+                               const FieldDescriptor* field);
+
+  static void SwapMessage(const Reflection* r, Message* lhs, Arena* lhs_arena,
+                          Message* rhs, Arena* rhs_arena,
+                          const FieldDescriptor* field);
+};
+
+template <bool unsafe_shallow_swap>
+void SwapFieldHelper::SwapRepeatedStringField(const Reflection* r, Message* lhs,
+                                              Message* rhs,
+                                              const FieldDescriptor* field) {
+  switch (field->options().ctype()) {
+    default:
+    case FieldOptions::STRING: {
+      auto* lhs_string = r->MutableRaw<RepeatedPtrFieldBase>(lhs, field);
+      auto* rhs_string = r->MutableRaw<RepeatedPtrFieldBase>(rhs, field);
+      if (unsafe_shallow_swap) {
+        lhs_string->InternalSwap(rhs_string);
+      } else {
+        lhs_string->Swap<GenericTypeHandler<std::string>>(rhs_string);
+      }
+      break;
+    }
+  }
+}
+
+template <bool unsafe_shallow_swap>
+void SwapFieldHelper::SwapStringField(const Reflection* r, Message* lhs,
+                                      Message* rhs,
+                                      const FieldDescriptor* field) {
+  switch (field->options().ctype()) {
+    default:
+    case FieldOptions::STRING: {
+      ArenaStringPtr* lhs_string = r->MutableRaw<ArenaStringPtr>(lhs, field);
+      ArenaStringPtr* rhs_string = r->MutableRaw<ArenaStringPtr>(rhs, field);
+      if (unsafe_shallow_swap) {
+        ArenaStringPtr::UnsafeShallowSwap(lhs_string, rhs_string);
+      } else {
+        SwapFieldHelper::SwapArenaStringPtr(
+            r->DefaultRaw<ArenaStringPtr>(field).GetPointer(),  //
+            lhs_string, lhs->GetArenaForAllocation(),           //
+            rhs_string, rhs->GetArenaForAllocation());
+      }
+      break;
+    }
+  }
+}
+
+void SwapFieldHelper::SwapArenaStringPtr(const std::string* default_ptr,
+                                         ArenaStringPtr* lhs, Arena* lhs_arena,
+                                         ArenaStringPtr* rhs,
+                                         Arena* rhs_arena) {
+  if (lhs_arena == rhs_arena) {
+    ArenaStringPtr::InternalSwap(default_ptr, lhs, lhs_arena, rhs, rhs_arena);
+  } else if (lhs->IsDefault(default_ptr) && rhs->IsDefault(default_ptr)) {
+    // Nothing to do.
+  } else if (lhs->IsDefault(default_ptr)) {
+    lhs->Set(default_ptr, rhs->Get(), lhs_arena);
+    // rhs needs to be destroyed before overwritten.
+    rhs->Destroy(default_ptr, rhs_arena);
+    rhs->UnsafeSetDefault(default_ptr);
+  } else if (rhs->IsDefault(default_ptr)) {
+    rhs->Set(default_ptr, lhs->Get(), rhs_arena);
+    // lhs needs to be destroyed before overwritten.
+    lhs->Destroy(default_ptr, lhs_arena);
+    lhs->UnsafeSetDefault(default_ptr);
+  } else {
+    std::string temp = lhs->Get();
+    lhs->Set(default_ptr, rhs->Get(), lhs_arena);
+    rhs->Set(default_ptr, std::move(temp), rhs_arena);
+  }
+}
+
+template <bool unsafe_shallow_swap>
+void SwapFieldHelper::SwapRepeatedMessageField(const Reflection* r,
+                                               Message* lhs, Message* rhs,
+                                               const FieldDescriptor* field) {
+  if (IsMapFieldInApi(field)) {
+    auto* lhs_map = r->MutableRaw<MapFieldBase>(lhs, field);
+    auto* rhs_map = r->MutableRaw<MapFieldBase>(rhs, field);
+    if (unsafe_shallow_swap) {
+      lhs_map->UnsafeShallowSwap(rhs_map);
+    } else {
+      lhs_map->Swap(rhs_map);
+    }
+  } else {
+    auto* lhs_rm = r->MutableRaw<RepeatedPtrFieldBase>(lhs, field);
+    auto* rhs_rm = r->MutableRaw<RepeatedPtrFieldBase>(rhs, field);
+    if (unsafe_shallow_swap) {
+      lhs_rm->InternalSwap(rhs_rm);
+    } else {
+      lhs_rm->Swap<GenericTypeHandler<Message>>(rhs_rm);
+    }
+  }
+}
+
+template <bool unsafe_shallow_swap>
+void SwapFieldHelper::SwapMessageField(const Reflection* r, Message* lhs,
+                                       Message* rhs,
+                                       const FieldDescriptor* field) {
+  if (unsafe_shallow_swap) {
+    std::swap(*r->MutableRaw<Message*>(lhs, field),
+              *r->MutableRaw<Message*>(rhs, field));
+  } else {
+    SwapMessage(r, lhs, lhs->GetArenaForAllocation(), rhs,
+                rhs->GetArenaForAllocation(), field);
+  }
+}
+
+void SwapFieldHelper::SwapMessage(const Reflection* r, Message* lhs,
+                                  Arena* lhs_arena, Message* rhs,
+                                  Arena* rhs_arena,
+                                  const FieldDescriptor* field) {
+  Message** lhs_sub = r->MutableRaw<Message*>(lhs, field);
+  Message** rhs_sub = r->MutableRaw<Message*>(rhs, field);
+
+  if (*lhs_sub == *rhs_sub) return;
+
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  if (lhs_arena != nullptr && lhs_arena == rhs_arena) {
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
+  if (lhs_arena == rhs_arena) {
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+    std::swap(*lhs_sub, *rhs_sub);
+    return;
+  }
+
+  if (*lhs_sub != nullptr && *rhs_sub != nullptr) {
+    (*lhs_sub)->GetReflection()->Swap(*lhs_sub, *rhs_sub);
+  } else if (*lhs_sub == nullptr && r->HasBit(*rhs, field)) {
+    *lhs_sub = (*rhs_sub)->New(lhs_arena);
+    (*lhs_sub)->CopyFrom(**rhs_sub);
+    r->ClearField(rhs, field);
+    // Ensures has bit is unchanged after ClearField.
+    r->SetBit(rhs, field);
+  } else if (*rhs_sub == nullptr && r->HasBit(*lhs, field)) {
+    *rhs_sub = (*lhs_sub)->New(rhs_arena);
+    (*rhs_sub)->CopyFrom(**lhs_sub);
+    r->ClearField(lhs, field);
+    // Ensures has bit is unchanged after ClearField.
+    r->SetBit(lhs, field);
+  }
+}
+
+}  // namespace internal
+
 void Reflection::SwapField(Message* message1, Message* message2,
                            const FieldDescriptor* field) const {
   if (field->is_repeated()) {
@@ -371,24 +561,12 @@
 #undef SWAP_ARRAYS
 
       case FieldDescriptor::CPPTYPE_STRING:
-        switch (field->options().ctype()) {
-          default:  // TODO(kenton):  Support other string reps.
-          case FieldOptions::STRING:
-            MutableRaw<RepeatedPtrFieldBase>(message1, field)
-                ->Swap<GenericTypeHandler<std::string> >(
-                    MutableRaw<RepeatedPtrFieldBase>(message2, field));
-            break;
-        }
+        internal::SwapFieldHelper::SwapRepeatedStringField<false>(
+            this, message1, message2, field);
         break;
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        if (IsMapFieldInApi(field)) {
-          MutableRaw<MapFieldBase>(message1, field)
-              ->Swap(MutableRaw<MapFieldBase>(message2, field));
-        } else {
-          MutableRaw<RepeatedPtrFieldBase>(message1, field)
-              ->Swap<GenericTypeHandler<Message> >(
-                  MutableRaw<RepeatedPtrFieldBase>(message2, field));
-        }
+        internal::SwapFieldHelper::SwapRepeatedMessageField<false>(
+            this, message1, message2, field);
         break;
 
       default:
@@ -412,60 +590,13 @@
       SWAP_VALUES(ENUM, int);
 #undef SWAP_VALUES
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        if (GetArena(message1) == GetArena(message2)) {
-          std::swap(*MutableRaw<Message*>(message1, field),
-                    *MutableRaw<Message*>(message2, field));
-        } else {
-          Message** sub_msg1 = MutableRaw<Message*>(message1, field);
-          Message** sub_msg2 = MutableRaw<Message*>(message2, field);
-          if (*sub_msg1 == nullptr && *sub_msg2 == nullptr) break;
-          if (*sub_msg1 && *sub_msg2) {
-            (*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2);
-            break;
-          }
-          if (*sub_msg1 == nullptr) {
-            *sub_msg1 = (*sub_msg2)->New(message1->GetArena());
-            (*sub_msg1)->CopyFrom(**sub_msg2);
-            ClearField(message2, field);
-          } else {
-            *sub_msg2 = (*sub_msg1)->New(message2->GetArena());
-            (*sub_msg2)->CopyFrom(**sub_msg1);
-            ClearField(message1, field);
-          }
-        }
+        internal::SwapFieldHelper::SwapMessageField<false>(this, message1,
+                                                           message2, field);
         break;
 
       case FieldDescriptor::CPPTYPE_STRING:
-        switch (field->options().ctype()) {
-          default:  // TODO(kenton):  Support other string reps.
-          case FieldOptions::STRING: {
-            Arena* arena1 = GetArena(message1);
-            Arena* arena2 = GetArena(message2);
-
-            if (IsInlined(field)) {
-              InlinedStringField* string1 =
-                  MutableRaw<InlinedStringField>(message1, field);
-              InlinedStringField* string2 =
-                  MutableRaw<InlinedStringField>(message2, field);
-              string1->Swap(string2);
-              break;
-            }
-
-            ArenaStringPtr* string1 =
-                MutableRaw<ArenaStringPtr>(message1, field);
-            ArenaStringPtr* string2 =
-                MutableRaw<ArenaStringPtr>(message2, field);
-            const std::string* default_ptr =
-                &DefaultRaw<ArenaStringPtr>(field).Get();
-            if (arena1 == arena2) {
-              string1->Swap(string2, default_ptr, arena1);
-            } else {
-              const std::string temp = string1->Get();
-              string1->Set(default_ptr, string2->Get(), arena1);
-              string2->Set(default_ptr, temp, arena2);
-            }
-          } break;
-        }
+        internal::SwapFieldHelper::SwapStringField<false>(this, message1,
+                                                          message2, field);
         break;
 
       default:
@@ -474,20 +605,69 @@
   }
 }
 
+void Reflection::UnsafeShallowSwapField(Message* message1, Message* message2,
+                                        const FieldDescriptor* field) const {
+  GOOGLE_DCHECK_EQ(message1->GetArenaForAllocation(),
+            message2->GetArenaForAllocation());
+
+  if (!field->is_repeated()) {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      internal::SwapFieldHelper::SwapMessageField<true>(this, message1,
+                                                        message2, field);
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+      internal::SwapFieldHelper::SwapStringField<true>(this, message1, message2,
+                                                       field);
+    } else {
+      SwapField(message1, message2, field);
+    }
+    return;
+  }
+
+  switch (field->cpp_type()) {
+#define SHALLOW_SWAP_ARRAYS(CPPTYPE, TYPE)                                \
+  case FieldDescriptor::CPPTYPE_##CPPTYPE:                                \
+    MutableRaw<RepeatedField<TYPE>>(message1, field)                      \
+        ->InternalSwap(MutableRaw<RepeatedField<TYPE>>(message2, field)); \
+    break;
+
+    SHALLOW_SWAP_ARRAYS(INT32, int32);
+    SHALLOW_SWAP_ARRAYS(INT64, int64);
+    SHALLOW_SWAP_ARRAYS(UINT32, uint32);
+    SHALLOW_SWAP_ARRAYS(UINT64, uint64);
+    SHALLOW_SWAP_ARRAYS(FLOAT, float);
+    SHALLOW_SWAP_ARRAYS(DOUBLE, double);
+    SHALLOW_SWAP_ARRAYS(BOOL, bool);
+    SHALLOW_SWAP_ARRAYS(ENUM, int);
+#undef SHALLOW_SWAP_ARRAYS
+
+    case FieldDescriptor::CPPTYPE_STRING:
+      internal::SwapFieldHelper::SwapRepeatedStringField<true>(this, message1,
+                                                               message2, field);
+      break;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      internal::SwapFieldHelper::SwapRepeatedMessageField<true>(
+          this, message1, message2, field);
+      break;
+
+    default:
+      GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+  }
+}
+
 void Reflection::SwapOneofField(Message* message1, Message* message2,
                                 const OneofDescriptor* oneof_descriptor) const {
   GOOGLE_DCHECK(!oneof_descriptor->is_synthetic());
   uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor);
   uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor);
 
-  int32 temp_int32;
-  int64 temp_int64;
-  uint32 temp_uint32;
-  uint64 temp_uint64;
-  float temp_float;
-  double temp_double;
-  bool temp_bool;
-  int temp_int;
+  int32 temp_int32 = 0;
+  int64 temp_int64 = 0;
+  uint32 temp_uint32 = 0;
+  uint64 temp_uint64 = 0;
+  float temp_float = 0;
+  double temp_double = 0;
+  bool temp_bool = false;
+  int temp_int = 0;
   Message* temp_message = nullptr;
   std::string temp_string;
 
@@ -590,6 +770,45 @@
   }
 }
 
+void Reflection::UnsafeShallowSwapOneofField(
+    Message* message1, Message* message2,
+    const OneofDescriptor* oneof_descriptor) const {
+  GOOGLE_DCHECK_EQ(message1->GetArenaForAllocation(),
+            message2->GetArenaForAllocation());
+
+  uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor);
+  const FieldDescriptor* field1 =
+      oneof_case1 > 0 ? descriptor_->FindFieldByNumber(oneof_case1) : nullptr;
+  uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor);
+  const FieldDescriptor* field2 =
+      oneof_case2 > 0 ? descriptor_->FindFieldByNumber(oneof_case2) : nullptr;
+
+  if ((field1 != nullptr &&
+       field1->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) ||
+      (field2 != nullptr &&
+       field2->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) {
+    // Fallback to SwapOneofField for non-message fields.
+    SwapOneofField(message1, message2, oneof_descriptor);
+    return;
+  }
+
+  Message* temp_message =
+      oneof_case1 > 0 ? UnsafeArenaReleaseMessage(message1, field1) : nullptr;
+
+  if (oneof_case2 > 0) {
+    UnsafeArenaSetAllocatedMessage(
+        message1, UnsafeArenaReleaseMessage(message2, field2), field2);
+  } else {
+    ClearOneof(message1, oneof_descriptor);
+  }
+
+  if (oneof_case1 > 0) {
+    UnsafeArenaSetAllocatedMessage(message2, temp_message, field1);
+  } else {
+    ClearOneof(message2, oneof_descriptor);
+  }
+}
+
 void Reflection::Swap(Message* message1, Message* message2) const {
   if (message1 == message2) return;
 
@@ -613,19 +832,48 @@
 
   // Check that both messages are in the same arena (or both on the heap). We
   // need to copy all data if not, due to ownership semantics.
-  if (GetArena(message1) != GetArena(message2)) {
-    // Slow copy path.
-    // Use our arena as temp space, if available.
-    Message* temp = message1->New(GetArena(message1));
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  if (message1->GetOwningArena() == nullptr ||
+      message1->GetOwningArena() != message2->GetOwningArena()) {
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
+  if (message1->GetOwningArena() != message2->GetOwningArena()) {
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+    // One of the two is guaranteed to have an arena.  Switch things around
+    // to guarantee that message1 has an arena.
+    Arena* arena = message1->GetOwningArena();
+    if (arena == nullptr) {
+      arena = message2->GetOwningArena();
+      std::swap(message1, message2);  // Swapping names for pointers!
+    }
+
+    Message* temp = message1->New(arena);
     temp->MergeFrom(*message2);
     message2->CopyFrom(*message1);
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+    message1->CopyFrom(*temp);
+    if (arena == nullptr) delete temp;
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
     Swap(message1, temp);
-    if (GetArena(message1) == nullptr) {
-      delete temp;
-    }
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
     return;
   }
 
+  for (int i = 0; i <= last_non_weak_field_index_; i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (schema_.InRealOneof(field)) continue;
+    if (schema_.IsFieldStripped(field)) continue;
+    SwapField(message1, message2, field);
+  }
+  const int oneof_decl_count = descriptor_->oneof_decl_count();
+  for (int i = 0; i < oneof_decl_count; i++) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+    if (!oneof->is_synthetic()) {
+      SwapOneofField(message1, message2, oneof);
+    }
+  }
+
+  // Swapping bits need to happen after swapping fields, because the latter may
+  // depend on the has bit information.
   if (schema_.HasHasbits()) {
     uint32* has_bits1 = MutableHasBits(message1);
     uint32* has_bits2 = MutableHasBits(message2);
@@ -646,19 +894,6 @@
     }
   }
 
-  for (int i = 0; i <= last_non_weak_field_index_; i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    if (schema_.InRealOneof(field)) continue;
-    SwapField(message1, message2, field);
-  }
-  const int oneof_decl_count = descriptor_->oneof_decl_count();
-  for (int i = 0; i < oneof_decl_count; i++) {
-    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
-    if (!oneof->is_synthetic()) {
-      SwapOneofField(message1, message2, oneof);
-    }
-  }
-
   if (schema_.HasExtensionSet()) {
     MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
   }
@@ -666,7 +901,8 @@
   MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
 }
 
-void Reflection::SwapFields(
+template <bool unsafe_shallow_swap>
+void Reflection::SwapFieldsImpl(
     Message* message1, Message* message2,
     const std::vector<const FieldDescriptor*>& fields) const {
   if (message1 == message2) return;
@@ -691,12 +927,16 @@
 
   std::set<int> swapped_oneof;
 
-  const int fields_size = static_cast<int>(fields.size());
-  for (int i = 0; i < fields_size; i++) {
-    const FieldDescriptor* field = fields[i];
+  for (const auto* field : fields) {
+    CheckInvalidAccess(schema_, field);
     if (field->is_extension()) {
-      MutableExtensionSet(message1)->SwapExtension(
-          MutableExtensionSet(message2), field->number());
+      if (unsafe_shallow_swap) {
+        MutableExtensionSet(message1)->UnsafeShallowSwapExtension(
+            MutableExtensionSet(message2), field->number());
+      } else {
+        MutableExtensionSet(message1)->SwapExtension(
+            MutableExtensionSet(message2), field->number());
+      }
     } else {
       if (schema_.InRealOneof(field)) {
         int oneof_index = field->containing_oneof()->index();
@@ -705,26 +945,49 @@
           continue;
         }
         swapped_oneof.insert(oneof_index);
-        SwapOneofField(message1, message2, field->containing_oneof());
+        if (unsafe_shallow_swap) {
+          UnsafeShallowSwapOneofField(message1, message2,
+                                      field->containing_oneof());
+        } else {
+          SwapOneofField(message1, message2, field->containing_oneof());
+        }
       } else {
+        // Swap field.
+        if (unsafe_shallow_swap) {
+          UnsafeShallowSwapField(message1, message2, field);
+        } else {
+          SwapField(message1, message2, field);
+        }
         // Swap has bit for non-repeated fields.  We have already checked for
-        // oneof already.
+        // oneof already. This has to be done after SwapField, because SwapField
+        // may depend on the information in has bits.
         if (!field->is_repeated()) {
           SwapBit(message1, message2, field);
         }
-        // Swap field.
-        SwapField(message1, message2, field);
       }
     }
   }
 }
 
+void Reflection::SwapFields(
+    Message* message1, Message* message2,
+    const std::vector<const FieldDescriptor*>& fields) const {
+  SwapFieldsImpl<false>(message1, message2, fields);
+}
+
+void Reflection::UnsafeShallowSwapFields(
+    Message* message1, Message* message2,
+    const std::vector<const FieldDescriptor*>& fields) const {
+  SwapFieldsImpl<true>(message1, message2, fields);
+}
+
 // -------------------------------------------------------------------
 
 bool Reflection::HasField(const Message& message,
                           const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(HasField);
   USAGE_CHECK_SINGULAR(HasField);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     return GetExtensionSet(message).Has(field->number());
@@ -741,6 +1004,7 @@
                           const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(FieldSize);
   USAGE_CHECK_REPEATED(FieldSize);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     return GetExtensionSet(message).ExtensionSize(field->number());
@@ -785,6 +1049,7 @@
 void Reflection::ClearField(Message* message,
                             const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(ClearField);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     MutableExtensionSet(message)->ClearExtension(field->number());
@@ -821,18 +1086,11 @@
           switch (field->options().ctype()) {
             default:  // TODO(kenton):  Support other string reps.
             case FieldOptions::STRING: {
-              if (IsInlined(field)) {
-                const std::string* default_ptr =
-                    &DefaultRaw<InlinedStringField>(field).GetNoArena();
-                MutableRaw<InlinedStringField>(message, field)
-                    ->SetNoArena(default_ptr, *default_ptr);
-                break;
-              }
-
               const std::string* default_ptr =
-                  &DefaultRaw<ArenaStringPtr>(field).Get();
+                  DefaultRaw<ArenaStringPtr>(field).GetPointer();
               MutableRaw<ArenaStringPtr>(message, field)
-                  ->SetAllocated(default_ptr, nullptr, GetArena(message));
+                  ->SetAllocated(default_ptr, nullptr,
+                                 message->GetArenaForAllocation());
               break;
             }
           }
@@ -840,10 +1098,10 @@
         }
 
         case FieldDescriptor::CPPTYPE_MESSAGE:
-          if (!schema_.HasHasbits()) {
+          if (schema_.HasBitIndex(field) == static_cast<uint32>(-1)) {
             // Proto3 does not have has-bits and we need to set a message field
             // to nullptr in order to indicate its un-presence.
-            if (GetArena(message) == nullptr) {
+            if (message->GetArenaForAllocation() == nullptr) {
               delete *MutableRaw<Message*>(message, field);
             }
             *MutableRaw<Message*>(message, field) = nullptr;
@@ -899,6 +1157,7 @@
                             const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(RemoveLast);
   USAGE_CHECK_REPEATED(RemoveLast);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     MutableExtensionSet(message)->RemoveLast(field->number());
@@ -946,26 +1205,34 @@
 Message* Reflection::ReleaseLast(Message* message,
                                  const FieldDescriptor* field) const {
   USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
+  Message* released;
   if (field->is_extension()) {
-    return static_cast<Message*>(
+    released = static_cast<Message*>(
         MutableExtensionSet(message)->ReleaseLast(field->number()));
   } else {
     if (IsMapFieldInApi(field)) {
-      return MutableRaw<MapFieldBase>(message, field)
-          ->MutableRepeatedField()
-          ->ReleaseLast<GenericTypeHandler<Message> >();
+      released = MutableRaw<MapFieldBase>(message, field)
+                     ->MutableRepeatedField()
+                     ->ReleaseLast<GenericTypeHandler<Message>>();
     } else {
-      return MutableRaw<RepeatedPtrFieldBase>(message, field)
-          ->ReleaseLast<GenericTypeHandler<Message> >();
+      released = MutableRaw<RepeatedPtrFieldBase>(message, field)
+                     ->ReleaseLast<GenericTypeHandler<Message>>();
     }
   }
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  return MaybeForceCopy(message->GetArenaForAllocation(), released);
+#else   // PROTOBUF_FORCE_COPY_IN_RELEASE
+  return released;
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
 }
 
 void Reflection::SwapElements(Message* message, const FieldDescriptor* field,
                               int index1, int index2) const {
   USAGE_CHECK_MESSAGE_TYPE(Swap);
   USAGE_CHECK_REPEATED(Swap);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     MutableExtensionSet(message)->SwapElements(field->number(), index1, index2);
@@ -1030,8 +1297,9 @@
 }  // namespace internal
 using internal::CreateUnknownEnumValues;
 
-void Reflection::ListFields(const Message& message,
-                            std::vector<const FieldDescriptor*>* output) const {
+void Reflection::ListFieldsMayFailOnStripped(
+    const Message& message, bool should_fail,
+    std::vector<const FieldDescriptor*>* output) const {
   output->clear();
 
   // Optimization:  The default instance never has any fields set.
@@ -1046,8 +1314,12 @@
       schema_.HasHasbits() ? GetHasBits(message) : nullptr;
   const uint32* const has_bits_indices = schema_.has_bit_indices_;
   output->reserve(descriptor_->field_count());
-  for (int i = 0; i <= last_non_weak_field_index_; i++) {
+  const int last_non_weak_field_index = last_non_weak_field_index_;
+  for (int i = 0; i <= last_non_weak_field_index; i++) {
     const FieldDescriptor* field = descriptor_->field(i);
+    if (!should_fail && schema_.IsFieldStripped(field)) {
+      continue;
+    }
     if (field->is_repeated()) {
       if (FieldSize(message, field) > 0) {
         output->push_back(field);
@@ -1058,10 +1330,12 @@
         const uint32* const oneof_case_array = GetConstPointerAtOffset<uint32>(
             &message, schema_.oneof_case_offset_);
         // Equivalent to: HasOneofField(message, field)
-        if (oneof_case_array[containing_oneof->index()] == field->number()) {
+        if (static_cast<int64>(oneof_case_array[containing_oneof->index()]) ==
+            field->number()) {
           output->push_back(field);
         }
-      } else if (has_bits) {
+      } else if (has_bits && has_bits_indices[i] != static_cast<uint32>(-1)) {
+        CheckInvalidAccess(schema_, field);
         // Equivalent to: HasBit(message, field)
         if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) {
           output->push_back(field);
@@ -1080,6 +1354,16 @@
   std::sort(output->begin(), output->end(), FieldNumberSorter());
 }
 
+void Reflection::ListFields(const Message& message,
+                            std::vector<const FieldDescriptor*>* output) const {
+  ListFieldsMayFailOnStripped(message, true, output);
+}
+
+void Reflection::ListFieldsOmitStripped(
+    const Message& message, std::vector<const FieldDescriptor*>* output) const {
+  ListFieldsMayFailOnStripped(message, false, output);
+}
+
 // -------------------------------------------------------------------
 
 #undef DEFINE_PRIMITIVE_ACCESSORS
@@ -1090,6 +1374,8 @@
     if (field->is_extension()) {                                               \
       return GetExtensionSet(message).Get##TYPENAME(                           \
           field->number(), field->default_value_##PASSTYPE());                 \
+    } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { \
+      return field->default_value_##PASSTYPE();                                \
     } else {                                                                   \
       return GetField<TYPE>(message, field);                                   \
     }                                                                          \
@@ -1159,14 +1445,17 @@
     return GetExtensionSet(message).GetString(field->number(),
                                               field->default_value_string());
   } else {
+    if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
+      return field->default_value_string();
+    }
     switch (field->options().ctype()) {
       default:  // TODO(kenton):  Support other string reps.
       case FieldOptions::STRING: {
-        if (IsInlined(field)) {
-          return GetField<InlinedStringField>(message, field).GetNoArena();
+        if (auto* value =
+                GetField<ArenaStringPtr>(message, field).GetPointer()) {
+          return *value;
         }
-
-        return GetField<ArenaStringPtr>(message, field).Get();
+        return field->default_value_string();
       }
     }
   }
@@ -1180,14 +1469,17 @@
     return GetExtensionSet(message).GetString(field->number(),
                                               field->default_value_string());
   } else {
+    if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
+      return field->default_value_string();
+    }
     switch (field->options().ctype()) {
       default:  // TODO(kenton):  Support other string reps.
       case FieldOptions::STRING: {
-        if (IsInlined(field)) {
-          return GetField<InlinedStringField>(message, field).GetNoArena();
+        if (auto* value =
+                GetField<ArenaStringPtr>(message, field).GetPointer()) {
+          return *value;
         }
-
-        return GetField<ArenaStringPtr>(message, field).Get();
+        return field->default_value_string();
       }
     }
   }
@@ -1204,22 +1496,22 @@
     switch (field->options().ctype()) {
       default:  // TODO(kenton):  Support other string reps.
       case FieldOptions::STRING: {
-        if (IsInlined(field)) {
-          MutableField<InlinedStringField>(message, field)
-              ->SetNoArena(nullptr, std::move(value));
-          break;
-        }
-
+        // Oneof string fields are never set as a default instance.
+        // We just need to pass some arbitrary default string to make it work.
+        // This allows us to not have the real default accessible from
+        // reflection.
         const std::string* default_ptr =
-            &DefaultRaw<ArenaStringPtr>(field).Get();
+            schema_.InRealOneof(field)
+                ? nullptr
+                : DefaultRaw<ArenaStringPtr>(field).GetPointer();
         if (schema_.InRealOneof(field) && !HasOneofField(*message, field)) {
           ClearOneof(message, field->containing_oneof());
           MutableField<ArenaStringPtr>(message, field)
               ->UnsafeSetDefault(default_ptr);
         }
         MutableField<ArenaStringPtr>(message, field)
-            ->Mutable(default_ptr, GetArena(message))
-            ->assign(std::move(value));
+            ->Set(default_ptr, std::move(value),
+                  message->GetArenaForAllocation());
         break;
       }
     }
@@ -1311,6 +1603,8 @@
   if (field->is_extension()) {
     value = GetExtensionSet(message).GetEnum(
         field->number(), field->default_value_enum()->number());
+  } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
+    value = field->default_value_enum()->number();
   } else {
     value = GetField<int>(message, field);
   }
@@ -1445,10 +1739,45 @@
 
 // -------------------------------------------------------------------
 
+const Message* Reflection::GetDefaultMessageInstance(
+    const FieldDescriptor* field) const {
+  // If we are using the generated factory, we cache the prototype in the field
+  // descriptor for faster access.
+  // The default instances of generated messages are not cross-linked, which
+  // means they contain null pointers on their message fields and can't be used
+  // to get the default of submessages.
+  if (message_factory_ == MessageFactory::generated_factory()) {
+    auto& ptr = field->default_generated_instance_;
+    auto* res = ptr.load(std::memory_order_acquire);
+    if (res == nullptr) {
+      // First time asking for this field's default. Load it and cache it.
+      res = message_factory_->GetPrototype(field->message_type());
+      ptr.store(res, std::memory_order_release);
+    }
+    return res;
+  }
+
+  // For other factories, we try the default's object field.
+  // In particular, the DynamicMessageFactory will cross link the default
+  // instances to allow for this. But only do this for real fields.
+  // This is an optimization to avoid going to GetPrototype() below, as that
+  // requires a lock and a map lookup.
+  if (!field->is_extension() && !field->options().weak() &&
+      !IsLazyField(field) && !schema_.InRealOneof(field)) {
+    auto* res = DefaultRaw<const Message*>(field);
+    if (res != nullptr) {
+      return res;
+    }
+  }
+  // Otherwise, just go to the factory.
+  return message_factory_->GetPrototype(field->message_type());
+}
+
 const Message& Reflection::GetMessage(const Message& message,
                                       const FieldDescriptor* field,
                                       MessageFactory* factory) const {
   USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (factory == nullptr) factory = message_factory_;
 
@@ -1456,9 +1785,12 @@
     return static_cast<const Message&>(GetExtensionSet(message).GetMessage(
         field->number(), field->message_type(), factory));
   } else {
+    if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
+      return *GetDefaultMessageInstance(field);
+    }
     const Message* result = GetRaw<const Message*>(message, field);
     if (result == nullptr) {
-      result = DefaultRaw<const Message*>(field);
+      result = GetDefaultMessageInstance(field);
     }
     return *result;
   }
@@ -1468,6 +1800,7 @@
                                     const FieldDescriptor* field,
                                     MessageFactory* factory) const {
   USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (factory == nullptr) factory = message_factory_;
 
@@ -1483,16 +1816,16 @@
       if (!HasOneofField(*message, field)) {
         ClearOneof(message, field->containing_oneof());
         result_holder = MutableField<Message*>(message, field);
-        const Message* default_message = DefaultRaw<const Message*>(field);
-        *result_holder = default_message->New(message->GetArena());
+        const Message* default_message = GetDefaultMessageInstance(field);
+        *result_holder = default_message->New(message->GetArenaForAllocation());
       }
     } else {
       SetBit(message, field);
     }
 
     if (*result_holder == nullptr) {
-      const Message* default_message = DefaultRaw<const Message*>(field);
-      *result_holder = default_message->New(message->GetArena());
+      const Message* default_message = GetDefaultMessageInstance(field);
+      *result_holder = default_message->New(message->GetArenaForAllocation());
     }
     result = *result_holder;
     return result;
@@ -1503,6 +1836,7 @@
     Message* message, Message* sub_message,
     const FieldDescriptor* field) const {
   USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     MutableExtensionSet(message)->UnsafeArenaSetAllocatedMessage(
@@ -1525,7 +1859,7 @@
       SetBit(message, field);
     }
     Message** sub_message_holder = MutableRaw<Message*>(message, field);
-    if (GetArena(message) == nullptr) {
+    if (message->GetArenaForAllocation() == nullptr) {
       delete *sub_message_holder;
     }
     *sub_message_holder = sub_message;
@@ -1534,16 +1868,23 @@
 
 void Reflection::SetAllocatedMessage(Message* message, Message* sub_message,
                                      const FieldDescriptor* field) const {
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  GOOGLE_DCHECK(sub_message->GetOwningArena() == nullptr ||
+         sub_message->GetOwningArena() == message->GetArenaForAllocation());
+#endif  // PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  CheckInvalidAccess(schema_, field);
+
   // If message and sub-message are in different memory ownership domains
   // (different arenas, or one is on heap and one is not), then we may need to
   // do a copy.
   if (sub_message != nullptr &&
-      sub_message->GetArena() != message->GetArena()) {
-    if (sub_message->GetArena() == nullptr && message->GetArena() != nullptr) {
+      sub_message->GetOwningArena() != message->GetArenaForAllocation()) {
+    if (sub_message->GetOwningArena() == nullptr &&
+        message->GetArenaForAllocation() != nullptr) {
       // Case 1: parent is on an arena and child is heap-allocated. We can add
       // the child to the arena's Own() list to free on arena destruction, then
       // set our pointer.
-      message->GetArena()->Own(sub_message);
+      message->GetArenaForAllocation()->Own(sub_message);
       UnsafeArenaSetAllocatedMessage(message, sub_message, field);
     } else {
       // Case 2: all other cases. We need to make a copy. MutableMessage() will
@@ -1562,6 +1903,7 @@
                                                const FieldDescriptor* field,
                                                MessageFactory* factory) const {
   USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (factory == nullptr) factory = message_factory_;
 
@@ -1590,8 +1932,13 @@
 Message* Reflection::ReleaseMessage(Message* message,
                                     const FieldDescriptor* field,
                                     MessageFactory* factory) const {
+  CheckInvalidAccess(schema_, field);
+
   Message* released = UnsafeArenaReleaseMessage(message, field, factory);
-  if (GetArena(message) != nullptr && released != nullptr) {
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  released = MaybeForceCopy(message->GetArenaForAllocation(), released);
+#endif  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (message->GetArenaForAllocation() != nullptr && released != nullptr) {
     Message* copy_from_arena = released->New();
     copy_from_arena->CopyFrom(*released);
     released = copy_from_arena;
@@ -1603,6 +1950,7 @@
                                               const FieldDescriptor* field,
                                               int index) const {
   USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     return static_cast<const Message&>(
@@ -1623,6 +1971,7 @@
                                             const FieldDescriptor* field,
                                             int index) const {
   USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     return static_cast<Message*>(
@@ -1643,6 +1992,7 @@
 Message* Reflection::AddMessage(Message* message, const FieldDescriptor* field,
                                 MessageFactory* factory) const {
   USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (factory == nullptr) factory = message_factory_;
 
@@ -1670,7 +2020,7 @@
       } else {
         prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
       }
-      result = prototype->New(message->GetArena());
+      result = prototype->New(message->GetArenaForAllocation());
       // We can guarantee here that repeated and result are either both heap
       // allocated or arena owned. So it is safe to call the unsafe version
       // of AddAllocated.
@@ -1685,6 +2035,7 @@
                                      const FieldDescriptor* field,
                                      Message* new_entry) const {
   USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
+  CheckInvalidAccess(schema_, field);
 
   if (field->is_extension()) {
     MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry);
@@ -1706,6 +2057,8 @@
                                           int ctype,
                                           const Descriptor* desc) const {
   USAGE_CHECK_REPEATED("MutableRawRepeatedField");
+  CheckInvalidAccess(schema_, field);
+
   if (field->cpp_type() != cpptype &&
       (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM ||
        cpptype != FieldDescriptor::CPPTYPE_INT32))
@@ -1788,6 +2141,15 @@
       ->InsertOrLookupMapValue(key, val);
 }
 
+bool Reflection::LookupMapValue(const Message& message,
+                                const FieldDescriptor* field, const MapKey& key,
+                                MapValueConstRef* val) const {
+  USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue",
+              "Field is not a map field.");
+  val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+  return GetRaw<MapFieldBase>(message, field).LookupMapValue(key, val);
+}
+
 bool Reflection::DeleteMapValue(Message* message, const FieldDescriptor* field,
                                 const MapKey& key) const {
   USAGE_CHECK(IsMapFieldInApi(field), "DeleteMapValue",
@@ -1858,16 +2220,11 @@
 template <typename Type>
 const Type& Reflection::GetRaw(const Message& message,
                                const FieldDescriptor* field) const {
-  if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
-    return DefaultRaw<Type>(field);
-  }
+  GOOGLE_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field))
+      << "Field = " << field->full_name();
   return GetConstRefAtOffset<Type>(message, schema_.GetFieldOffset(field));
 }
 
-bool Reflection::IsInlined(const FieldDescriptor* field) const {
-  return schema_.IsFieldInlined(field);
-}
-
 template <typename Type>
 Type* Reflection::MutableRaw(Message* message,
                              const FieldDescriptor* field) const {
@@ -1908,10 +2265,6 @@
                                           schema_.GetExtensionSetOffset());
 }
 
-Arena* Reflection::GetArena(Message* message) const {
-  return GetInternalMetadata(*message).arena();
-}
-
 const InternalMetadata& Reflection::GetInternalMetadata(
     const Message& message) const {
   return GetConstRefAtOffset<InternalMetadata>(message,
@@ -1927,10 +2280,13 @@
 bool Reflection::HasBit(const Message& message,
                         const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!field->options().weak());
-  if (schema_.HasBitIndex(field) != -1) {
+  if (schema_.HasBitIndex(field) != static_cast<uint32>(-1)) {
     return IsIndexInHasBitSet(GetHasBits(message), schema_.HasBitIndex(field));
   }
 
+  // Intentionally check here because HasBitIndex(field) != -1 means valid.
+  CheckInvalidAccess(schema_, field);
+
   // proto3: no has-bits. All fields present except messages, which are
   // present only if their message-field pointer is non-null.
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
@@ -1951,11 +2307,6 @@
       case FieldDescriptor::CPPTYPE_STRING:
         switch (field->options().ctype()) {
           default: {
-            if (IsInlined(field)) {
-              return !GetField<InlinedStringField>(message, field)
-                          .GetNoArena()
-                          .empty();
-            }
             return GetField<ArenaStringPtr>(message, field).Get().size() > 0;
           }
         }
@@ -1988,7 +2339,7 @@
 void Reflection::SetBit(Message* message, const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!field->options().weak());
   const uint32 index = schema_.HasBitIndex(field);
-  if (index == -1) return;
+  if (index == static_cast<uint32>(-1)) return;
   MutableHasBits(message)[index / 32] |=
       (static_cast<uint32>(1) << (index % 32));
 }
@@ -1996,10 +2347,8 @@
 void Reflection::ClearBit(Message* message,
                           const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!field->options().weak());
-  if (!schema_.HasHasbits()) {
-    return;
-  }
   const uint32 index = schema_.HasBitIndex(field);
+  if (index == static_cast<uint32>(-1)) return;
   MutableHasBits(message)[index / 32] &=
       ~(static_cast<uint32>(1) << (index % 32));
 }
@@ -2033,7 +2382,8 @@
 
 bool Reflection::HasOneofField(const Message& message,
                                const FieldDescriptor* field) const {
-  return (GetOneofCase(message, field->containing_oneof()) == field->number());
+  return (GetOneofCase(message, field->containing_oneof()) ==
+          static_cast<uint32>(field->number()));
 }
 
 void Reflection::SetOneofCase(Message* message,
@@ -2060,16 +2410,18 @@
   uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
   if (oneof_case > 0) {
     const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
-    if (GetArena(message) == nullptr) {
+    if (message->GetArenaForAllocation() == nullptr) {
       switch (field->cpp_type()) {
         case FieldDescriptor::CPPTYPE_STRING: {
           switch (field->options().ctype()) {
             default:  // TODO(kenton):  Support other string reps.
             case FieldOptions::STRING: {
-              const std::string* default_ptr =
-                  &DefaultRaw<ArenaStringPtr>(field).Get();
+              // Oneof string fields are never set as a default instance.
+              // We just need to pass some arbitrary default string to make it
+              // work. This allows us to not have the real default accessible
+              // from reflection.
               MutableField<ArenaStringPtr>(message, field)
-                  ->Destroy(default_ptr, GetArena(message));
+                  ->Destroy(nullptr, message->GetArenaForAllocation());
               break;
             }
           }
@@ -2340,6 +2692,8 @@
   std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_;
 };
 
+void AddDescriptors(const DescriptorTable* table);
+
 void AssignDescriptorsImpl(const DescriptorTable* table, bool eager) {
   // Ensure the file descriptor is added to the pool.
   {
@@ -2398,11 +2752,8 @@
 }
 
 void AddDescriptorsImpl(const DescriptorTable* table) {
-  // Reflection refers to the default instances so make sure they are
-  // initialized.
-  for (int i = 0; i < table->num_sccs; i++) {
-    internal::InitSCC(table->init_default_instances[i]);
-  }
+  // Reflection refers to the default fields so make sure they are initialized.
+  internal::InitProtobufDefaults();
 
   // Ensure all dependent descriptors are registered to the generated descriptor
   // pool and message factory.
@@ -2417,6 +2768,16 @@
   MessageFactory::InternalRegisterGeneratedFile(table);
 }
 
+void AddDescriptors(const DescriptorTable* table) {
+  // AddDescriptors is not thread safe. Callers need to ensure calls are
+  // properly serialized. This function is only called pre-main by global
+  // descriptors and we can assume single threaded access or it's called
+  // by AssignDescriptorImpl which uses a mutex to sequence calls.
+  if (table->is_initialized) return;
+  table->is_initialized = true;
+  AddDescriptorsImpl(table);
+}
+
 }  // namespace
 
 // Separate function because it needs to be a friend of
@@ -2432,19 +2793,24 @@
 
 namespace internal {
 
+Metadata AssignDescriptors(const DescriptorTable* (*table)(),
+                           internal::once_flag* once,
+                           const Metadata& metadata) {
+  call_once(*once, [=] {
+    auto* t = table();
+    AssignDescriptorsImpl(t, t->is_eager);
+  });
+
+  return metadata;
+}
+
 void AssignDescriptors(const DescriptorTable* table, bool eager) {
   if (!eager) eager = table->is_eager;
   call_once(*table->once, AssignDescriptorsImpl, table, eager);
 }
 
-void AddDescriptors(const DescriptorTable* table) {
-  // AddDescriptors is not thread safe. Callers need to ensure calls are
-  // properly serialized. This function is only called pre-main by global
-  // descriptors and we can assume single threaded access or it's called
-  // by AssignDescriptorImpl which uses a mutex to sequence calls.
-  if (table->is_initialized) return;
-  table->is_initialized = true;
-  AddDescriptorsImpl(table);
+AddDescriptorsRunner::AddDescriptorsRunner(const DescriptorTable* table) {
+  AddDescriptors(table);
 }
 
 void RegisterFileLevelMetadata(const DescriptorTable* table) {
@@ -2468,3 +2834,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index e2eae77..1771b474 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -42,8 +42,6 @@
 #include <vector>
 #include <google/protobuf/stubs/casts.h>
 #include <google/protobuf/stubs/common.h>
-// TODO(jasonh): Remove this once the compiler change to directly include this
-// is released to components.
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/generated_enum_reflection.h>
 #include <google/protobuf/stubs/once.h>
@@ -59,7 +57,6 @@
 
 namespace google {
 namespace protobuf {
-class DescriptorPool;
 class MapKey;
 class MapValueRef;
 class MessageLayoutInspector;
@@ -148,17 +145,6 @@
     }
   }
 
-  bool IsFieldInlined(const FieldDescriptor* field) const {
-    if (InRealOneof(field)) {
-      size_t offset =
-          static_cast<size_t>(field->containing_type()->field_count() +
-                              field->containing_oneof()->index());
-      return Inlined(offsets_[offset], field->type());
-    } else {
-      return Inlined(offsets_[field->index()], field->type());
-    }
-  }
-
   uint32 GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
     return static_cast<uint32>(oneof_case_offset_) +
            static_cast<uint32>(static_cast<size_t>(oneof_descriptor->index()) *
@@ -212,6 +198,30 @@
            OffsetValue(offsets_[field->index()], field->type());
   }
 
+  // Returns true if the field is implicitly backed by LazyField.
+  bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const {
+    GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE);
+    (void)field;
+    return false;
+  }
+
+  // Returns true if the field's accessor is called by any external code (aka,
+  // non proto library code).
+  bool IsFieldUsed(const FieldDescriptor* field) const {
+    (void)field;
+    return true;
+  }
+
+  bool IsFieldStripped(const FieldDescriptor* field) const {
+    (void)field;
+    return false;
+  }
+
+  bool IsMessageStripped(const Descriptor* descriptor) const {
+    (void)descriptor;
+    return false;
+  }
+
 
   bool HasWeakFields() const { return weak_field_map_offset_ > 0; }
 
@@ -232,24 +242,12 @@
   int weak_field_map_offset_;
 
   // We tag offset values to provide additional data about fields (such as
-  // inlined).
+  // "unused" or "lazy").
   static uint32 OffsetValue(uint32 v, FieldDescriptor::Type type) {
-    if (type == FieldDescriptor::TYPE_STRING ||
-        type == FieldDescriptor::TYPE_BYTES) {
-      return v & ~1u;
-    } else {
-      return v;
+    if (type == FieldDescriptor::TYPE_MESSAGE) {
+      return v & 0x7FFFFFFEu;
     }
-  }
-
-  static bool Inlined(uint32 v, FieldDescriptor::Type type) {
-    if (type == FieldDescriptor::TYPE_STRING ||
-        type == FieldDescriptor::TYPE_BYTES) {
-      return v & 1u;
-    } else {
-      // Non string/byte fields are not inlined.
-      return false;
-    }
+    return v & 0x7FFFFFFFu;
   }
 };
 
@@ -265,29 +263,35 @@
   int object_size;
 };
 
-struct SCCInfoBase;
-
+// This struct tries to reduce unnecessary padding.
+// The num_xxx might not be close to their respective pointer, but this saves
+// padding.
 struct PROTOBUF_EXPORT DescriptorTable {
   mutable bool is_initialized;
   bool is_eager;
+  int size;  // of serialized descriptor
   const char* descriptor;
   const char* filename;
-  int size;  // of serialized descriptor
   once_flag* once;
-  SCCInfoBase* const* init_default_instances;
   const DescriptorTable* const* deps;
-  int num_sccs;
   int num_deps;
+  int num_messages;
   const MigrationSchema* schemas;
   const Message* const* default_instances;
   const uint32* offsets;
   // update the following descriptor arrays.
   Metadata* file_level_metadata;
-  int num_messages;
   const EnumDescriptor** file_level_enum_descriptors;
   const ServiceDescriptor** file_level_service_descriptors;
 };
 
+enum {
+  // Tag used on offsets for fields that don't have a real offset.
+  // For example, weak message fields go into the WeakFieldMap and not in an
+  // actual field.
+  kInvalidFieldOffsetTag = 0x40000000u,
+};
+
 // AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool
 // and uses it to populate all of the global variables which store pointers to
 // the descriptor objects.  It also constructs the reflection objects.  It is
@@ -296,18 +300,23 @@
 void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table,
                                        bool eager = false);
 
-// AddDescriptors() is a file-level procedure which adds the encoded
-// FileDescriptorProto for this .proto file to the global DescriptorPool for
-// generated files (DescriptorPool::generated_pool()). It ordinarily runs at
-// static initialization time, but is not used at all in LITE_RUNTIME mode.
-// AddDescriptors() is *not* thread-safe.
-void PROTOBUF_EXPORT AddDescriptors(const DescriptorTable* table);
+// Overload used to implement GetMetadataStatic in the generated code.
+// See comments in compiler/cpp/internal/file.cc as to why.
+// It takes a `Metadata` and returns it to allow for tail calls and reduce
+// binary size.
+Metadata PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* (*table)(),
+                                           internal::once_flag* once,
+                                           const Metadata& metadata);
 
 // These cannot be in lite so we put them in the reflection.
 PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8* base, uint32 offset,
                                                uint32 tag, uint32 has_offset,
                                                io::CodedOutputStream* output);
 
+struct PROTOBUF_EXPORT AddDescriptorsRunner {
+  explicit AddDescriptorsRunner(const DescriptorTable* table);
+};
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index 1c9d408..0b6ed8e 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -48,6 +48,8 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/map_unittest.pb.h>
 #include <google/protobuf/test_util.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/arena.h>
@@ -55,9 +57,21 @@
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 
+class GeneratedMessageReflectionTestHelper {
+ public:
+  static void UnsafeShallowSwapFields(
+      Message* lhs, Message* rhs,
+      const std::vector<const FieldDescriptor*>& fields) {
+    lhs->GetReflection()->UnsafeShallowSwapFields(lhs, rhs, fields);
+  }
+};
+
 namespace {
 
 // Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
@@ -186,6 +200,38 @@
   EXPECT_EQ(532819, message2.optional_int32());
 }
 
+TEST(GeneratedMessageReflectionTest, SwapWithLhsCleared) {
+  unittest::TestAllTypes message1;
+  unittest::TestAllTypes message2;
+
+  TestUtil::SetAllFields(&message1);
+
+  // For proto2 message, for message field, Clear only reset hasbits, but
+  // doesn't delete the underlying field.
+  message1.Clear();
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  TestUtil::ExpectClear(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapWithRhsCleared) {
+  unittest::TestAllTypes message1;
+  unittest::TestAllTypes message2;
+
+  TestUtil::SetAllFields(&message2);
+
+  // For proto2 message, for message field, Clear only reset hasbits, but
+  // doesn't delete the underlying field.
+  message2.Clear();
+
+  const Reflection* reflection = message1.GetReflection();
+  reflection->Swap(&message1, &message2);
+
+  TestUtil::ExpectClear(message1);
+}
+
 TEST(GeneratedMessageReflectionTest, SwapExtensions) {
   unittest::TestAllExtensions message1;
   unittest::TestAllExtensions message2;
@@ -263,6 +309,39 @@
   TestUtil::ExpectClear(message2);
 }
 
+TEST(GeneratedMessageReflectionTest, SwapFieldsAllOnDifferentArena) {
+  Arena arena1, arena2;
+  auto* message1 = Arena::CreateMessage<unittest::TestAllTypes>(&arena1);
+  auto* message2 = Arena::CreateMessage<unittest::TestAllTypes>(&arena2);
+
+  TestUtil::SetAllFields(message2);
+
+  std::vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1->GetReflection();
+  reflection->ListFields(*message2, &fields);
+  reflection->SwapFields(message1, message2, fields);
+
+  TestUtil::ExpectAllFieldsSet(*message1);
+  TestUtil::ExpectClear(*message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapFieldsAllOnArenaHeap) {
+  Arena arena;
+  auto* message1 = Arena::CreateMessage<unittest::TestAllTypes>(&arena);
+  std::unique_ptr<unittest::TestAllTypes> message2(
+      Arena::CreateMessage<unittest::TestAllTypes>(nullptr));
+
+  TestUtil::SetAllFields(message2.get());
+
+  std::vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1->GetReflection();
+  reflection->ListFields(*message2, &fields);
+  reflection->SwapFields(message1, message2.get(), fields);
+
+  TestUtil::ExpectAllFieldsSet(*message1);
+  TestUtil::ExpectClear(*message2);
+}
+
 TEST(GeneratedMessageReflectionTest, SwapFieldsAllExtension) {
   unittest::TestAllExtensions message1;
   unittest::TestAllExtensions message2;
@@ -278,6 +357,125 @@
   TestUtil::ExpectAllExtensionsSet(message2);
 }
 
+TEST(GeneratedMessageReflectionTest, SwapFieldsAllExtensionArenaHeap) {
+  Arena arena;
+
+  std::unique_ptr<unittest::TestAllExtensions> message1(
+      Arena::CreateMessage<unittest::TestAllExtensions>(nullptr));
+  auto* message2 = Arena::CreateMessage<unittest::TestAllExtensions>(&arena);
+
+  TestUtil::SetAllExtensions(message1.get());
+
+  std::vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1->GetReflection();
+  reflection->ListFields(*message1, &fields);
+  reflection->SwapFields(message1.get(), message2, fields);
+
+  TestUtil::ExpectExtensionsClear(*message1);
+  TestUtil::ExpectAllExtensionsSet(*message2);
+}
+
+TEST(GeneratedMessageReflectionTest, UnsafeShallowSwapFieldsAll) {
+  Arena arena;
+  auto* message1 = Arena::CreateMessage<unittest::TestAllTypes>(&arena);
+  auto* message2 = Arena::CreateMessage<unittest::TestAllTypes>(&arena);
+
+  TestUtil::SetAllFields(message2);
+
+  auto* kept_nested_message_ptr = message2->mutable_optional_nested_message();
+  auto* kept_foreign_message_ptr = message2->mutable_optional_foreign_message();
+  auto* kept_repeated_nested_message_ptr =
+      message2->mutable_repeated_nested_message(0);
+  auto* kept_repeated_foreign_message_ptr =
+      message2->mutable_repeated_foreign_message(0);
+
+  std::vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1->GetReflection();
+  reflection->ListFields(*message2, &fields);
+  GeneratedMessageReflectionTestHelper::UnsafeShallowSwapFields(
+      message1, message2, fields);
+
+  TestUtil::ExpectAllFieldsSet(*message1);
+  TestUtil::ExpectClear(*message2);
+
+  // Expects the swap to be shallow. Expects pointer stability to the element of
+  // the repeated fields (not the container).
+  EXPECT_EQ(kept_nested_message_ptr,
+            message1->mutable_optional_nested_message());
+  EXPECT_EQ(kept_foreign_message_ptr,
+            message1->mutable_optional_foreign_message());
+  EXPECT_EQ(kept_repeated_nested_message_ptr,
+            message1->mutable_repeated_nested_message(0));
+  EXPECT_EQ(kept_repeated_foreign_message_ptr,
+            message1->mutable_repeated_foreign_message(0));
+}
+
+TEST(GeneratedMessageReflectionTest, UnsafeShallowSwapFieldsMap) {
+  Arena arena;
+  auto* message1 = Arena::CreateMessage<unittest::TestMap>(&arena);
+  auto* message2 = Arena::CreateMessage<unittest::TestMap>(&arena);
+
+  MapTestUtil::SetMapFields(message2);
+
+  auto* kept_map_int32_fm_ptr =
+      &(*message2->mutable_map_int32_foreign_message())[0];
+
+  std::vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1->GetReflection();
+  reflection->ListFields(*message2, &fields);
+  GeneratedMessageReflectionTestHelper::UnsafeShallowSwapFields(
+      message1, message2, fields);
+
+  MapTestUtil::ExpectMapFieldsSet(*message1);
+  MapTestUtil::ExpectClear(*message2);
+
+  // Expects the swap to be shallow.
+  EXPECT_EQ(kept_map_int32_fm_ptr,
+            &(*message1->mutable_map_int32_foreign_message())[0]);
+}
+
+TEST(GeneratedMessageReflectionTest, UnsafeShallowSwapFieldsAllExtension) {
+  Arena arena;
+  auto* message1 = Arena::CreateMessage<unittest::TestAllExtensions>(&arena);
+  auto* message2 = Arena::CreateMessage<unittest::TestAllExtensions>(&arena);
+
+  TestUtil::SetAllExtensions(message1);
+
+  auto* kept_nested_message_ext_ptr =
+      message1->MutableExtension(unittest::optional_nested_message_extension);
+  auto* kept_foreign_message_ext_ptr =
+      message1->MutableExtension(unittest::optional_foreign_message_extension);
+  auto* kept_repeated_nested_message_ext_ptr =
+      message1->MutableRepeatedExtension(
+          unittest::repeated_nested_message_extension);
+  auto* kept_repeated_foreign_message_ext_ptr =
+      message1->MutableRepeatedExtension(
+          unittest::repeated_foreign_message_extension);
+
+  std::vector<const FieldDescriptor*> fields;
+  const Reflection* reflection = message1->GetReflection();
+  reflection->ListFields(*message1, &fields);
+  GeneratedMessageReflectionTestHelper::UnsafeShallowSwapFields(
+      message1, message2, fields);
+
+  TestUtil::ExpectExtensionsClear(*message1);
+  TestUtil::ExpectAllExtensionsSet(*message2);
+
+  // Expects the swap to be shallow.
+  EXPECT_EQ(
+      kept_nested_message_ext_ptr,
+      message2->MutableExtension(unittest::optional_nested_message_extension));
+  EXPECT_EQ(
+      kept_foreign_message_ext_ptr,
+      message2->MutableExtension(unittest::optional_foreign_message_extension));
+  EXPECT_EQ(kept_repeated_nested_message_ext_ptr,
+            message2->MutableRepeatedExtension(
+                unittest::repeated_nested_message_extension));
+  EXPECT_EQ(kept_repeated_foreign_message_ext_ptr,
+            message2->MutableRepeatedExtension(
+                unittest::repeated_foreign_message_extension));
+}
+
 TEST(GeneratedMessageReflectionTest, SwapOneof) {
   unittest::TestOneof2 message1, message2;
   TestUtil::SetOneof1(&message1);
@@ -317,6 +515,46 @@
   TestUtil::ExpectOneofSet1(message2);
 }
 
+TEST(GeneratedMessageReflectionTest, UnsafeShallowSwapFieldsOneof) {
+  Arena arena;
+  auto* message1 = Arena::CreateMessage<unittest::TestOneof2>(&arena);
+  auto* message2 = Arena::CreateMessage<unittest::TestOneof2>(&arena);
+  TestUtil::SetOneof1(message1);
+
+  std::vector<const FieldDescriptor*> fields;
+  const Descriptor* descriptor = message1->GetDescriptor();
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields.push_back(descriptor->field(i));
+  }
+  GeneratedMessageReflectionTestHelper::UnsafeShallowSwapFields(
+      message1, message2, fields);
+
+  TestUtil::ExpectOneofClear(*message1);
+  TestUtil::ExpectOneofSet1(*message2);
+}
+
+TEST(GeneratedMessageReflectionTest,
+     UnsafeShallowSwapFieldsOneofExpectShallow) {
+  Arena arena;
+  auto* message1 = Arena::CreateMessage<unittest::TestOneof2>(&arena);
+  auto* message2 = Arena::CreateMessage<unittest::TestOneof2>(&arena);
+  TestUtil::SetOneof1(message1);
+  message1->mutable_foo_message()->set_qux_int(1000);
+  auto* kept_foo_ptr = message1->mutable_foo_message();
+
+  std::vector<const FieldDescriptor*> fields;
+  const Descriptor* descriptor = message1->GetDescriptor();
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields.push_back(descriptor->field(i));
+  }
+  GeneratedMessageReflectionTestHelper::UnsafeShallowSwapFields(
+      message1, message2, fields);
+
+  EXPECT_TRUE(message2->has_foo_message());
+  EXPECT_EQ(message2->foo_message().qux_int(), 1000);
+  EXPECT_EQ(kept_foo_ptr, message2->mutable_foo_message());
+}
+
 TEST(GeneratedMessageReflectionTest, RemoveLast) {
   unittest::TestAllTypes message;
   TestUtil::ReflectionTester reflection_tester(
@@ -358,6 +596,7 @@
   ASSERT_EQ(2, message.repeated_foreign_message_size());
   const protobuf_unittest::ForeignMessage* expected =
       message.mutable_repeated_foreign_message(1);
+  (void)expected;  // unused in somce configurations
   std::unique_ptr<Message> released(message.GetReflection()->ReleaseLast(
       &message, descriptor->FindFieldByName("repeated_foreign_message")));
   EXPECT_EQ(expected, released.get());
@@ -486,6 +725,7 @@
                   ->FindKnownExtensionByName(extension1->full_name()) == NULL);
 }
 
+
 TEST(GeneratedMessageReflectionTest, SetAllocatedMessageTest) {
   unittest::TestAllTypes from_message1;
   unittest::TestAllTypes from_message2;
@@ -780,6 +1020,7 @@
                                                               &to_message);
   const Message& sub_message = reflection->GetMessage(
       to_message, descriptor->FindFieldByName("foo_lazy_message"));
+  (void)sub_message;  // unused in somce configurations
   released = reflection->ReleaseMessage(
       &to_message, descriptor->FindFieldByName("foo_lazy_message"));
   EXPECT_TRUE(released != NULL);
@@ -797,6 +1038,7 @@
 
   const Message& sub_message2 = reflection->GetMessage(
       to_message, descriptor->FindFieldByName("foo_message"));
+  (void)sub_message2;  // unused in somce configurations
   released = reflection->ReleaseMessage(
       &to_message, descriptor->FindFieldByName("foo_message"));
   EXPECT_TRUE(released != NULL);
@@ -916,6 +1158,7 @@
   const Reflection* reflection = message.GetReflection();
   const Message& sub_message = reflection->GetMessage(
       message, descriptor->FindFieldByName("foo_lazy_message"));
+  (void)sub_message;  // unused in somce configurations
   Message* released = reflection->ReleaseMessage(
       &message, descriptor->FindFieldByName("foo_lazy_message"));
 
diff --git a/src/google/protobuf/generated_message_table_driven.h b/src/google/protobuf/generated_message_table_driven.h
index 1394ab1..def4a1f 100644
--- a/src/google/protobuf/generated_message_table_driven.h
+++ b/src/google/protobuf/generated_message_table_driven.h
@@ -73,9 +73,7 @@
   TYPE_STRING_STRING_PIECE = 20,
   TYPE_BYTES_CORD = 21,
   TYPE_BYTES_STRING_PIECE = 22,
-  TYPE_STRING_INLINED = 23,
-  TYPE_BYTES_INLINED = 24,
-  TYPE_MAP = 25,
+  TYPE_MAP = 23,
 };
 
 static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
@@ -102,12 +100,11 @@
     kNumTypeClasses  // must be last enum
   };
   // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
-  // and also distinquish the same types if they have different wire format.
+  // and also distinguish the same types if they have different wire format.
   enum {
     kCordType = 19,
     kStringPieceType = 20,
-    kInlinedType = 21,
-    kNumTypes = 21,
+    kNumTypes = 20,
     kSpecial = kNumTypes * kNumTypeClasses,
   };
 
@@ -120,7 +117,7 @@
 // ParseTableField is kept small to help simplify instructions for computing
 // offsets, as we will always need this information to parse a field.
 // Additional data, needed for some types, is stored in
-// AuxillaryParseTableField.
+// AuxiliaryParseTableField.
 struct ParseTableField {
   uint32 offset;
   // The presence_index ordinarily represents a has_bit index, but for fields
@@ -138,7 +135,7 @@
 
 struct ParseTable;
 
-union AuxillaryParseTableField {
+union AuxiliaryParseTableField {
   typedef bool (*EnumValidator)(int);
 
   // Enums
@@ -169,20 +166,20 @@
   };
   map_aux maps;
 
-  AuxillaryParseTableField() = default;
-  constexpr AuxillaryParseTableField(AuxillaryParseTableField::enum_aux e)
+  AuxiliaryParseTableField() = default;
+  constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::enum_aux e)
       : enums(e) {}
-  constexpr AuxillaryParseTableField(AuxillaryParseTableField::message_aux m)
+  constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::message_aux m)
       : messages(m) {}
-  constexpr AuxillaryParseTableField(AuxillaryParseTableField::string_aux s)
+  constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::string_aux s)
       : strings(s) {}
-  constexpr AuxillaryParseTableField(AuxillaryParseTableField::map_aux m)
+  constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::map_aux m)
       : maps(m) {}
 };
 
 struct ParseTable {
   const ParseTableField* fields;
-  const AuxillaryParseTableField* aux;
+  const AuxiliaryParseTableField* aux;
   int max_field_number;
   // TODO(ckennelly): Do something with this padding.
 
@@ -206,12 +203,22 @@
 static_assert(sizeof(ParseTableField) <= 16, "ParseTableField is too large");
 // The tables must be composed of POD components to ensure link-time
 // initialization.
-static_assert(std::is_pod<ParseTableField>::value, "");
-static_assert(std::is_pod<AuxillaryParseTableField>::value, "");
-static_assert(std::is_pod<AuxillaryParseTableField::enum_aux>::value, "");
-static_assert(std::is_pod<AuxillaryParseTableField::message_aux>::value, "");
-static_assert(std::is_pod<AuxillaryParseTableField::string_aux>::value, "");
-static_assert(std::is_pod<ParseTable>::value, "");
+static_assert(std::is_standard_layout<ParseTableField>::value, "");
+static_assert(std::is_trivial<ParseTableField>::value, "");
+static_assert(std::is_standard_layout<AuxiliaryParseTableField>::value, "");
+static_assert(std::is_trivial<AuxiliaryParseTableField>::value, "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
+static_assert(std::is_trivial<AuxiliaryParseTableField::enum_aux>::value, "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
+static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value,
+              "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
+static_assert(std::is_trivial<AuxiliaryParseTableField::string_aux>::value, "");
+static_assert(std::is_standard_layout<ParseTable>::value, "");
+static_assert(std::is_trivial<ParseTable>::value, "");
 
 // TODO(ckennelly): Consolidate these implementations into a single one, using
 // dynamic dispatch to the appropriate unknown field handler.
@@ -256,7 +263,7 @@
   SerializeInternal(base, field_table + 1, num_fields, output);
 }
 
-uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
+PROTOBUF_EXPORT uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
                                 int32 num_fields, bool is_deterministic,
                                 uint8* buffer);
 
diff --git a/src/google/protobuf/generated_message_table_driven_lite.h b/src/google/protobuf/generated_message_table_driven_lite.h
index ae13b36..32cc16e 100644
--- a/src/google/protobuf/generated_message_table_driven_lite.h
+++ b/src/google/protobuf/generated_message_table_driven_lite.h
@@ -31,12 +31,10 @@
 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
 
-#include <google/protobuf/generated_message_table_driven.h>
-
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/implicit_weak_message.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/wire_format_lite.h>
 #include <type_traits>
@@ -51,7 +49,6 @@
 
 enum StringType {
   StringType_STRING = 0,
-  StringType_INLINED = 3
 };
 
 // Logically a superset of StringType, consisting of all field types that
@@ -60,8 +57,7 @@
   ProcessingType_STRING = 0,
   ProcessingType_CORD = 1,
   ProcessingType_STRING_PIECE = 2,
-  ProcessingType_INLINED = 3,
-  ProcessingType_MESSAGE = 4,
+  ProcessingType_MESSAGE = 3,
 };
 
 enum Cardinality {
@@ -91,9 +87,7 @@
 
 template <typename Type>
 inline Type* AddField(MessageLite* msg, int64 offset) {
-  static_assert(std::is_pod<Type>::value ||
-                    std::is_same<Type, InlinedStringField>::value,
-                "Do not assign");
+  static_assert(std::is_trivial<Type>::value, "Do not assign");
 
   RepeatedField<Type>* repeated = Raw<RepeatedField<Type>>(msg, offset);
   return repeated->Add();
@@ -109,8 +103,7 @@
 
 template <typename Type>
 inline void AddField(MessageLite* msg, int64 offset, Type value) {
-  static_assert(std::is_pod<Type>::value,
-                "Do not assign");
+  static_assert(std::is_trivial<Type>::value, "Do not assign");
   *AddField<Type>(msg, offset) = value;
 }
 
@@ -131,8 +124,7 @@
 template <typename Type>
 inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index,
                      int64 offset, Type value) {
-  static_assert(std::is_pod<Type>::value,
-                "Do not assign");
+  static_assert(std::is_trivial<Type>::value, "Do not assign");
   *MutableField<Type>(msg, has_bits, has_bit_index, offset) = value;
 }
 
@@ -158,12 +150,7 @@
     case WireFormatLite::TYPE_STRING:
     case WireFormatLite::TYPE_BYTES:
       Raw<ArenaStringPtr>(msg, field.offset)
-          ->Destroy(&GetEmptyStringAlreadyInited(), arena);
-      break;
-
-    case TYPE_STRING_INLINED:
-    case TYPE_BYTES_INLINED:
-      Raw<InlinedStringField>(msg, field.offset)->DestroyNoArena(NULL);
+          ->Destroy(ArenaStringPtr::EmptyDefault{}, arena);
       break;
 
     default:
@@ -182,7 +169,7 @@
 inline void ResetOneofField(const ParseTable& table, int field_number,
                             Arena* arena, MessageLite* msg, uint32* oneof_case,
                             int64 offset, const void* default_ptr) {
-  if (*oneof_case == field_number) {
+  if (static_cast<int64>(*oneof_case) == field_number) {
     // The oneof is already set to the right type, so there is no need to clear
     // it.
     return;
@@ -198,10 +185,6 @@
       Raw<ArenaStringPtr>(msg, offset)
           ->UnsafeSetDefault(static_cast<const std::string*>(default_ptr));
       break;
-    case ProcessingType_INLINED:
-      new (Raw<InlinedStringField>(msg, offset))
-          InlinedStringField(*static_cast<const std::string*>(default_ptr));
-      break;
     case ProcessingType_MESSAGE:
       MessageLite** submessage = Raw<MessageLite*>(msg, offset);
       const MessageLite* prototype =
@@ -226,35 +209,12 @@
 #endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
 
   switch (ctype) {
-    case StringType_INLINED: {
-      InlinedStringField* s = nullptr;
-      switch (cardinality) {
-        case Cardinality_SINGULAR:
-          // TODO(ckennelly): Is this optimal?
-          s = MutableField<InlinedStringField>(msg, has_bits, has_bit_index,
-                                               offset);
-          break;
-        case Cardinality_REPEATED:
-          s = AddField<InlinedStringField>(msg, offset);
-          break;
-        case Cardinality_ONEOF:
-          s = Raw<InlinedStringField>(msg, offset);
-          break;
-      }
-      GOOGLE_DCHECK(s != nullptr);
-      std::string* value = s->MutableNoArena(NULL);
-      if (PROTOBUF_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) {
-        return false;
-      }
-      utf8_string_data = *value;
-      break;
-    }
     case StringType_STRING: {
       switch (cardinality) {
         case Cardinality_SINGULAR: {
           ArenaStringPtr* field = MutableField<ArenaStringPtr>(
               msg, has_bits, has_bit_index, offset);
-          std::string* value = field->Mutable(
+          std::string* value = field->MutableNoCopy(
               static_cast<const std::string*>(default_ptr), arena);
           if (PROTOBUF_PREDICT_FALSE(
                   !WireFormatLite::ReadString(input, value))) {
@@ -272,7 +232,7 @@
         } break;
         case Cardinality_ONEOF: {
           ArenaStringPtr* field = Raw<ArenaStringPtr>(msg, offset);
-          std::string* value = field->Mutable(
+          std::string* value = field->MutableNoCopy(
               static_cast<const std::string*>(default_ptr), arena);
           if (PROTOBUF_PREDICT_FALSE(
                   !WireFormatLite::ReadString(input, value))) {
@@ -310,7 +270,7 @@
     return false;
   }
 
-  AuxillaryParseTableField::EnumValidator validator =
+  AuxiliaryParseTableField::EnumValidator validator =
       table.aux[field_number].enums.validator;
   if (validator == nullptr || validator(value)) {
     switch (cardinality) {
@@ -482,23 +442,6 @@
           }
           break;
         }
-        case TYPE_BYTES_INLINED:
-#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-        case TYPE_STRING_INLINED:
-#endif  // !GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-        {
-          Arena* const arena = msg->GetArena();
-          const void* default_ptr = table.aux[field_number].strings.default_ptr;
-
-          if (PROTOBUF_PREDICT_FALSE(
-                  (!HandleString<UnknownFieldHandler, Cardinality_SINGULAR,
-                                 false, StringType_INLINED>(
-                      input, msg, arena, has_bits, presence_index, offset,
-                      default_ptr, nullptr)))) {
-            return false;
-          }
-          break;
-        }
         case WireFormatLite::TYPE_BYTES | kOneofMask:
 #ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
         case WireFormatLite::TYPE_STRING | kOneofMask:
@@ -522,10 +465,8 @@
           break;
         }
         case (WireFormatLite::TYPE_BYTES) | kRepeatedMask:
-        case TYPE_BYTES_INLINED | kRepeatedMask:
 #ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
         case (WireFormatLite::TYPE_STRING) | kRepeatedMask:
-        case TYPE_STRING_INLINED | kRepeatedMask:
 #endif  // !GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
         {
           Arena* const arena = msg->GetArena();
@@ -555,7 +496,6 @@
           }
           break;
         }
-        case TYPE_STRING_INLINED | kRepeatedMask:
         case (WireFormatLite::TYPE_STRING) | kRepeatedMask: {
           Arena* const arena = msg->GetArena();
           const void* default_ptr = table.aux[field_number].strings.default_ptr;
@@ -713,22 +653,6 @@
 
           break;
         }
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-        case TYPE_STRING_INLINED: {
-          Arena* const arena = msg->GetArena();
-          const void* default_ptr = table.aux[field_number].strings.default_ptr;
-          const char* field_name = table.aux[field_number].strings.field_name;
-
-          if (PROTOBUF_PREDICT_FALSE(
-                  (!HandleString<UnknownFieldHandler, Cardinality_SINGULAR,
-                                 true, StringType_INLINED>(
-                      input, msg, arena, has_bits, presence_index, offset,
-                      default_ptr, field_name)))) {
-            return false;
-          }
-          break;
-        }
-#endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
         case TYPE_MAP: {
           if (PROTOBUF_PREDICT_FALSE(!(*table.aux[field_number].maps.parse_map)(
                   input, Raw<void>(msg, offset)))) {
@@ -751,8 +675,6 @@
       GOOGLE_DCHECK_NE(processing_type, kRepeatedMask);
       GOOGLE_DCHECK_EQ(0, processing_type & kOneofMask);
 
-      GOOGLE_DCHECK_NE(TYPE_BYTES_INLINED | kRepeatedMask, processing_type);
-      GOOGLE_DCHECK_NE(TYPE_STRING_INLINED | kRepeatedMask, processing_type);
 
       // Mask out kRepeatedMask bit, allowing the jump table to be smaller.
       switch (static_cast<WireFormatLite::FieldType>(processing_type ^
@@ -795,7 +717,7 @@
             return false;
           }
 
-          AuxillaryParseTableField::EnumValidator validator =
+          AuxiliaryParseTableField::EnumValidator validator =
               table.aux[field_number].enums.validator;
           RepeatedField<int>* values = Raw<RepeatedField<int>>(msg, offset);
 
@@ -848,7 +770,7 @@
       }
     }
   }
-}
+}  // NOLINT(readability/fn_size)
 
 template <typename UnknownFieldHandler>
 bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
diff --git a/src/google/protobuf/generated_message_tctable_decl.h b/src/google/protobuf/generated_message_tctable_decl.h
new file mode 100644
index 0000000..9d2bc40d
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_decl.h
@@ -0,0 +1,123 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file contains declarations needed in generated headers for messages
+// that use tail-call table parsing. Everything in this file is for internal
+// use only.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
+
+#include <cstdint>
+#include <type_traits>
+
+#include <google/protobuf/parse_context.h>
+#include <google/protobuf/message_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Additional information about this field:
+struct TcFieldData {
+  constexpr TcFieldData() : data(0) {}
+  constexpr TcFieldData(uint16_t coded_tag, uint8_t hasbit_idx, uint16_t offset)
+      : data(static_cast<uint64_t>(offset) << 48 |
+             static_cast<uint64_t>(hasbit_idx) << 16 | coded_tag) {}
+
+  uint16_t coded_tag() const { return static_cast<uint16_t>(data); }
+  uint8_t hasbit_idx() const { return static_cast<uint8_t>(data >> 16); }
+  uint16_t offset() const { return static_cast<uint16_t>(data >> 48); }
+
+  uint64_t data;
+};
+
+struct TailCallParseTableBase;
+
+// TailCallParseFunc is the function pointer type used in the tailcall table.
+typedef const char* (*TailCallParseFunc)(MessageLite* msg, const char* ptr,
+                                         ParseContext* ctx,
+                                         const TailCallParseTableBase* table,
+                                         uint64_t hasbits, TcFieldData data);
+
+// Base class for message-level table with info for the tail-call parser.
+struct TailCallParseTableBase {
+  // Common attributes for message layout:
+  uint16_t has_bits_offset;
+  uint16_t extension_offset;
+  uint32_t extension_range_low;
+  uint32_t extension_range_high;
+  uint32_t has_bits_required_mask;
+  const MessageLite* default_instance;
+
+  // Handler for fields which are not handled by table dispatch.
+  TailCallParseFunc fallback;
+
+  // Table entry for fast-path tailcall dispatch handling.
+  struct FieldEntry {
+    // Target function for dispatch:
+    TailCallParseFunc target;
+    // Field data used during parse:
+    TcFieldData bits;
+  };
+  // There is always at least one table entry.
+  const FieldEntry* table() const {
+    return reinterpret_cast<const FieldEntry*>(this + 1);
+  }
+};
+
+static_assert(sizeof(TailCallParseTableBase::FieldEntry) <= 16,
+              "Field entry is too big.");
+
+template <size_t kTableSizeLog2>
+struct TailCallParseTable {
+  TailCallParseTableBase header;
+
+  // Entries for each field.
+  //
+  // Fields are indexed by the lowest bits of their field number. The field
+  // number is masked to fit inside the table. Note that the parsing logic
+  // generally calls `TailCallParseTableBase::table()` instead of accessing
+  // this field directly.
+  TailCallParseTableBase::FieldEntry entries[(1 << kTableSizeLog2)];
+};
+
+static_assert(std::is_standard_layout<TailCallParseTable<1>>::value,
+              "TailCallParseTable must be standard layout.");
+
+static_assert(offsetof(TailCallParseTable<1>, entries) ==
+                  sizeof(TailCallParseTableBase),
+              "Table entries must be laid out after TailCallParseTableBase.");
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
diff --git a/python/google/protobuf/python_protobuf.h b/src/google/protobuf/generated_message_tctable_full.cc
similarity index 72%
copy from python/google/protobuf/python_protobuf.h
copy to src/google/protobuf/generated_message_tctable_full.cc
index 8db1ffb..634c663 100644
--- a/python/google/protobuf/python_protobuf.h
+++ b/src/google/protobuf/generated_message_tctable_full.cc
@@ -28,30 +28,26 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: qrczak@google.com (Marcin Kowalczyk)
-//
-// This module exposes the C proto inside the given Python proto, in
-// case the Python proto is implemented with a C proto.
+#include <cstdint>
 
-#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
-#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
+#include <google/protobuf/parse_context.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_tctable_impl.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/unknown_field_set.h>
 
-#include <Python.h>
+// clang-format off
+#include <google/protobuf/port_def.inc>
+// clang-format on
 
 namespace google {
 namespace protobuf {
+namespace internal {
 
-class Message;
+const char* TcParserBase::GenericFallback(PROTOBUF_TC_PARAM_DECL) {
+  return GenericFallbackImpl<Message, UnknownFieldSet>(PROTOBUF_TC_PARAM_PASS);
+}
 
-namespace python {
-
-// Return the pointer to the C proto inside the given Python proto,
-// or NULL when this is not a Python proto implemented with a C proto.
-const Message* GetCProtoInsidePyProto(PyObject* msg);
-Message* MutableCProtoInsidePyProto(PyObject* msg);
-
-}  // namespace python
+}  // namespace internal
 }  // namespace protobuf
 }  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h
new file mode 100644
index 0000000..07879bd
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_impl.h
@@ -0,0 +1,260 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
+
+#include <cstdint>
+#include <type_traits>
+
+#include <google/protobuf/parse_context.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_tctable_decl.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/metadata_lite.h>
+#include <google/protobuf/port.h>
+#include <google/protobuf/wire_format_lite.h>
+
+// Must come last:
+#include <google/protobuf/port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+class UnknownFieldSet;
+
+namespace internal {
+
+// PROTOBUF_TC_PARAM_DECL are the parameters for tailcall functions.
+//
+// Note that this is performance sensitive: changing the parameters will change
+// the registers used by the ABI calling convention, which subsequently affects
+// register selection logic inside the function.
+#define PROTOBUF_TC_PARAM_DECL                                 \
+  ::google::protobuf::MessageLite *msg, const char *ptr,                 \
+      ::google::protobuf::internal::ParseContext *ctx,                   \
+      const ::google::protobuf::internal::TailCallParseTableBase *table, \
+      uint64_t hasbits, ::google::protobuf::internal::TcFieldData data
+
+// PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL.
+#define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, table, hasbits, data
+
+class TcParserBase {
+ public:
+  static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL);
+  static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL);
+
+  template <typename FieldType, typename TagType>
+  PROTOBUF_NOINLINE static const char* SingularParseMessage(
+      PROTOBUF_TC_PARAM_DECL) {
+    if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+      return table->fallback(PROTOBUF_TC_PARAM_PASS);
+    }
+    ptr += sizeof(TagType);
+    hasbits |= (uint64_t{1} << data.hasbit_idx());
+    auto& field = RefAt<FieldType*>(msg, data.offset());
+    if (field == nullptr) {
+      auto arena = ctx->data().arena;
+      if (Arena::is_arena_constructable<FieldType>::value) {
+        field = Arena::CreateMessage<FieldType>(arena);
+      } else {
+        field = Arena::Create<FieldType>(arena);
+      }
+    }
+    SyncHasbits(msg, hasbits, table);
+    return ctx->ParseMessage(field, ptr);
+  }
+
+  template <typename FieldType, typename TagType>
+  PROTOBUF_NOINLINE static const char* RepeatedParseMessage(
+      PROTOBUF_TC_PARAM_DECL) {
+    if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+      return table->fallback(PROTOBUF_TC_PARAM_PASS);
+    }
+    ptr += sizeof(TagType);
+    auto& field = RefAt<RepeatedPtrField<FieldType>>(msg, data.offset());
+    SyncHasbits(msg, hasbits, table);
+    ptr = ctx->ParseMessage(field.Add(), ptr);
+    return ptr;
+  }
+
+  template <typename LayoutType, typename TagType>
+  static const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL);
+  template <typename LayoutType, typename TagType>
+  static const char* PackedFixed(PROTOBUF_TC_PARAM_DECL);
+
+  enum VarintDecode { kNoConversion = 0, kZigZag = 1 };
+  template <typename FieldType, typename TagType, VarintDecode zigzag>
+  static const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL);
+  template <typename FieldType, typename TagType, VarintDecode zigzag>
+  static const char* PackedVarint(PROTOBUF_TC_PARAM_DECL);
+
+  enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
+  template <typename TagType, Utf8Type utf8>
+  static const char* SingularString(PROTOBUF_TC_PARAM_DECL);
+  template <typename TagType, Utf8Type utf8>
+  static const char* RepeatedString(PROTOBUF_TC_PARAM_DECL);
+
+ protected:
+  template <typename T>
+  static T& RefAt(void* x, size_t offset) {
+    T* target = reinterpret_cast<T*>(static_cast<char*>(x) + offset);
+    GOOGLE_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(target) % alignof(T));
+    return *target;
+  }
+
+  static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
+      MessageLite* msg, uint64_t hasbits, const TailCallParseTableBase* table) {
+    const uint32_t has_bits_offset = table->has_bits_offset;
+    if (has_bits_offset) {
+      // Only the first 32 has-bits are updated. Nothing above those is stored,
+      // but e.g. messages without has-bits update the upper bits.
+      RefAt<uint32_t>(msg, has_bits_offset) = static_cast<uint32_t>(hasbits);
+    }
+  }
+
+  static inline PROTOBUF_ALWAYS_INLINE const char* Return(
+      PROTOBUF_TC_PARAM_DECL) {
+    SyncHasbits(msg, hasbits, table);
+    return ptr;
+  }
+
+  static inline PROTOBUF_ALWAYS_INLINE const char* Error(
+      PROTOBUF_TC_PARAM_DECL) {
+    SyncHasbits(msg, hasbits, table);
+    return nullptr;
+  }
+
+  class ScopedArenaSwap final {
+   public:
+    ScopedArenaSwap(MessageLite* msg, ParseContext* ctx)
+        : ctx_(ctx), saved_(ctx->data().arena) {
+      ctx_->data().arena = msg->GetArenaForAllocation();
+    }
+    ScopedArenaSwap(const ScopedArenaSwap&) = delete;
+    ~ScopedArenaSwap() { ctx_->data().arena = saved_; }
+
+   private:
+    ParseContext* const ctx_;
+    Arena* const saved_;
+  };
+
+  template <class MessageBaseT, class UnknownFieldsT>
+  static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) {
+#define CHK_(x) \
+  if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr /* NOLINT */
+
+    SyncHasbits(msg, hasbits, table);
+    uint32_t tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+    if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) {
+      ctx->SetLastTag(tag);
+      return ptr;
+    }
+    uint32_t num = tag >> 3;
+    if (table->extension_range_low <= num &&
+        num <= table->extension_range_high) {
+      return RefAt<ExtensionSet>(msg, table->extension_offset)
+          .ParseField(tag, ptr,
+                      static_cast<const MessageBaseT*>(table->default_instance),
+                      &msg->_internal_metadata_, ctx);
+    }
+    return UnknownFieldParse(
+        tag, msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(),
+        ptr, ctx);
+#undef CHK_
+  }
+};
+
+// TcParser implements most of the parsing logic for tailcall tables.
+//
+// This is templated on lg2(table size), since dispatching depends upon the size
+// of the table. The template parameter avoids runtime overhead for computing
+// the table entry index.
+template <uint32_t kPowerOf2>
+struct TcParser final : TcParserBase {
+  // Dispatch to the designated parse function
+  inline PROTOBUF_ALWAYS_INLINE static const char* TagDispatch(
+      PROTOBUF_TC_PARAM_DECL) {
+    const auto coded_tag = UnalignedLoad<uint16_t>(ptr);
+    constexpr size_t kIdxMask = ((1 << (kPowerOf2)) - 1);
+    const size_t idx = (coded_tag >> 3) & kIdxMask;
+    data = table->table()[idx].bits;
+    data.data ^= coded_tag;
+    PROTOBUF_MUSTTAIL return table->table()[idx].target(PROTOBUF_TC_PARAM_PASS);
+  }
+
+  // We can only safely call from field to next field if the call is optimized
+  // to a proper tail call. Otherwise we blow through stack. Clang and gcc
+  // reliably do this optimization in opt mode, but do not perform this in debug
+  // mode. Luckily the structure of the algorithm is such that it's always
+  // possible to just return and use the enclosing parse loop as a trampoline.
+  static const char* TailCall(PROTOBUF_TC_PARAM_DECL) {
+    constexpr bool always_return = !PROTOBUF_TAILCALL;
+    if (always_return || !ctx->DataAvailable(ptr)) {
+      PROTOBUF_MUSTTAIL return Return(PROTOBUF_TC_PARAM_PASS);
+    }
+    PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_PASS);
+  }
+
+  static const char* ParseLoop(MessageLite* msg, const char* ptr,
+                               ParseContext* ctx,
+                               const TailCallParseTableBase* table) {
+    ScopedArenaSwap saved(msg, ctx);
+    const uint32_t has_bits_offset = table->has_bits_offset;
+    while (!ctx->Done(&ptr)) {
+      uint64_t hasbits = 0;
+      if (has_bits_offset) hasbits = RefAt<uint32_t>(msg, has_bits_offset);
+      ptr = TagDispatch(msg, ptr, ctx, table, hasbits, {});
+      if (ptr == nullptr) break;
+      if (ctx->LastTag() != 1) break;  // Ended on terminating tag
+    }
+    return ptr;
+  }
+
+  template <typename LayoutType, typename TagType>
+  static const char* SingularFixed(PROTOBUF_TC_PARAM_DECL);
+
+  template <typename FieldType, typename TagType, VarintDecode zigzag>
+  static const char* SingularVarint(PROTOBUF_TC_PARAM_DECL);
+};
+
+// Declare helper functions:
+#include <google/protobuf/generated_message_tctable_impl.inc>
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
+#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
diff --git a/src/google/protobuf/generated_message_tctable_impl.inc b/src/google/protobuf/generated_message_tctable_impl.inc
new file mode 100644
index 0000000..e6e5dd5
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_impl.inc
@@ -0,0 +1,255 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// clang-format off
+#ifdef PROTOBUF_TCT_SOURCE
+template const char* TcParser<1>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<1>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<2>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<3>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<4>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParser<5>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::PackedVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+template const char* TcParserBase::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+#else
+extern template const char* TcParser<1>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedFixed<uint64_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedFixed<uint32_t, uint8_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<uint64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<uint32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<int64_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<int32_t, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<bool, uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::SingularString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedString<uint8_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedFixed<uint64_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedFixed<uint32_t, uint16_t>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<uint64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<uint32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<int64_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<int32_t, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kZigZag>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<1>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<2>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<3>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<4>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParser<5>::SingularVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::PackedVarint<bool, uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoConversion>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kNoUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::SingularString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+extern template const char* TcParserBase::RepeatedString<uint16_t, ::PROTOBUF_NAMESPACE_ID::internal::TcParserBase::kUtf8ValidateOnly>(PROTOBUF_TC_PARAM_DECL);
+#endif
+// clang-format on
diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc
new file mode 100644
index 0000000..f8a09f4
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
@@ -0,0 +1,442 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <cstdint>
+
+#include <google/protobuf/parse_context.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_tctable_decl.h>
+#include <google/protobuf/generated_message_tctable_impl.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/wire_format_lite.h>
+
+// clang-format off
+#include <google/protobuf/port_def.inc>
+// clang-format on
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+const char* TcParserBase::GenericFallbackLite(PROTOBUF_TC_PARAM_DECL) {
+  return GenericFallbackImpl<MessageLite, std::string>(PROTOBUF_TC_PARAM_PASS);
+}
+
+namespace {
+
+// Offset returns the address `offset` bytes after `base`.
+inline void* Offset(void* base, uint32_t offset) {
+  return static_cast<uint8*>(base) + offset;
+}
+
+// InvertPacked changes tag bits from the given wire type to length
+// delimited. This is the difference expected between packed and non-packed
+// repeated fields.
+template <WireFormatLite::WireType Wt>
+inline PROTOBUF_ALWAYS_INLINE void InvertPacked(TcFieldData& data) {
+  data.data ^= Wt ^ WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+}
+
+}  // namespace
+
+//////////////////////////////////////////////////////////////////////////////
+// Fixed fields
+//////////////////////////////////////////////////////////////////////////////
+
+template <uint32_t kPowerOf2>
+template <typename LayoutType, typename TagType>
+const char* TcParser<kPowerOf2>::SingularFixed(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    return table->fallback(PROTOBUF_TC_PARAM_PASS);
+  }
+  ptr += sizeof(TagType);  // Consume tag
+  hasbits |= (uint64_t{1} << data.hasbit_idx());
+  std::memcpy(Offset(msg, data.offset()), ptr, sizeof(LayoutType));
+  ptr += sizeof(LayoutType);
+  // TailCall syncs any pending hasbits:
+  PROTOBUF_MUSTTAIL return TailCall(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename LayoutType, typename TagType>
+const char* TcParserBase::RepeatedFixed(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    // Check if the field can be parsed as packed repeated:
+    constexpr WireFormatLite::WireType fallback_wt =
+        sizeof(LayoutType) == 4 ? WireFormatLite::WIRETYPE_FIXED32
+                                : WireFormatLite::WIRETYPE_FIXED64;
+    InvertPacked<fallback_wt>(data);
+    if (static_cast<TagType>(data.coded_tag()) == 0) {
+      return PackedFixed<LayoutType, TagType>(PROTOBUF_TC_PARAM_PASS);
+    } else {
+      return table->fallback(PROTOBUF_TC_PARAM_PASS);
+    }
+  }
+  auto& field = RefAt<RepeatedField<LayoutType>>(msg, data.offset());
+  int idx = field.size();
+  auto elem = field.Add();
+  int space = field.Capacity() - idx;
+  idx = 0;
+  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  do {
+    ptr += sizeof(TagType);
+    std::memcpy(elem + (idx++), ptr, sizeof(LayoutType));
+    ptr += sizeof(LayoutType);
+    if (idx >= space) break;
+    if (!ctx->DataAvailable(ptr)) break;
+  } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+  field.AddNAlreadyReserved(idx - 1);
+  return Return(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename LayoutType, typename TagType>
+const char* TcParserBase::PackedFixed(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    // Try parsing as non-packed repeated:
+    constexpr WireFormatLite::WireType fallback_wt =
+        sizeof(LayoutType) == 4 ? WireFormatLite::WIRETYPE_FIXED32
+                                : WireFormatLite::WIRETYPE_FIXED64;
+    InvertPacked<fallback_wt>(data);
+    if (static_cast<TagType>(data.coded_tag()) == 0) {
+      return RepeatedFixed<LayoutType, TagType>(PROTOBUF_TC_PARAM_PASS);
+    } else {
+      return table->fallback(PROTOBUF_TC_PARAM_PASS);
+    }
+  }
+  ptr += sizeof(TagType);
+  // Since ctx->ReadPackedFixed does not use TailCall<> or Return<>, sync any
+  // pending hasbits now:
+  SyncHasbits(msg, hasbits, table);
+  auto& field = RefAt<RepeatedField<LayoutType>>(msg, data.offset());
+  int size = ReadSize(&ptr);
+  // TODO(dlj): add a tailcalling variant of ReadPackedFixed.
+  return ctx->ReadPackedFixed(ptr, size,
+                              static_cast<RepeatedField<LayoutType>*>(&field));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Varint fields
+//////////////////////////////////////////////////////////////////////////////
+
+namespace {
+
+inline PROTOBUF_ALWAYS_INLINE std::pair<const char*, uint64_t>
+Parse64FallbackPair(const char* p, int64_t res1) {
+  auto ptr = reinterpret_cast<const int8_t*>(p);
+
+  // The algorithm relies on sign extension for each byte to set all high bits
+  // when the varint continues. It also relies on asserting all of the lower
+  // bits for each successive byte read. This allows the result to be aggregated
+  // using a bitwise AND. For example:
+  //
+  //          8       1          64     57 ... 24     17  16      9  8       1
+  // ptr[0] = 1aaa aaaa ; res1 = 1111 1111 ... 1111 1111  1111 1111  1aaa aaaa
+  // ptr[1] = 1bbb bbbb ; res2 = 1111 1111 ... 1111 1111  11bb bbbb  b111 1111
+  // ptr[2] = 1ccc cccc ; res3 = 0000 0000 ... 000c cccc  cc11 1111  1111 1111
+  //                             ---------------------------------------------
+  //        res1 & res2 & res3 = 0000 0000 ... 000c cccc  ccbb bbbb  baaa aaaa
+  //
+  // On x86-64, a shld from a single register filled with enough 1s in the high
+  // bits can accomplish all this in one instruction. It so happens that res1
+  // has 57 high bits of ones, which is enough for the largest shift done.
+  GOOGLE_DCHECK_EQ(res1 >> 7, -1);
+  uint64_t ones = res1;  // save the high 1 bits from res1 (input to SHLD)
+  uint64_t byte;         // the "next" 7-bit chunk, shifted (result from SHLD)
+  int64_t res2, res3;    // accumulated result chunks
+#define SHLD(n) byte = ((byte << (n * 7)) | (ones >> (64 - (n * 7))))
+
+  int sign_bit;
+#if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__)
+  // For the first two rounds (ptr[1] and ptr[2]), micro benchmarks show a
+  // substantial improvement from capturing the sign from the condition code
+  // register on x86-64.
+#define SHLD_SIGN(n)                  \
+  asm("shldq %3, %2, %1"              \
+      : "=@ccs"(sign_bit), "+r"(byte) \
+      : "r"(ones), "i"(n * 7))
+#else
+  // Generic fallback:
+#define SHLD_SIGN(n)                           \
+  do {                                         \
+    SHLD(n);                                   \
+    sign_bit = static_cast<int64_t>(byte) < 0; \
+  } while (0)
+#endif
+
+  byte = ptr[1];
+  SHLD_SIGN(1);
+  res2 = byte;
+  if (!sign_bit) goto done2;
+  byte = ptr[2];
+  SHLD_SIGN(2);
+  res3 = byte;
+  if (!sign_bit) goto done3;
+
+#undef SHLD_SIGN
+
+  // For the remainder of the chunks, check the sign of the AND result.
+  byte = ptr[3];
+  SHLD(3);
+  res1 &= byte;
+  if (res1 >= 0) goto done4;
+  byte = ptr[4];
+  SHLD(4);
+  res2 &= byte;
+  if (res2 >= 0) goto done5;
+  byte = ptr[5];
+  SHLD(5);
+  res3 &= byte;
+  if (res3 >= 0) goto done6;
+  byte = ptr[6];
+  SHLD(6);
+  res1 &= byte;
+  if (res1 >= 0) goto done7;
+  byte = ptr[7];
+  SHLD(7);
+  res2 &= byte;
+  if (res2 >= 0) goto done8;
+  byte = ptr[8];
+  SHLD(8);
+  res3 &= byte;
+  if (res3 >= 0) goto done9;
+
+#undef SHLD
+
+  // For valid 64bit varints, the 10th byte/ptr[9] should be exactly 1. In this
+  // case, the continuation bit of ptr[8] already set the top bit of res3
+  // correctly, so all we have to do is check that the expected case is true.
+  byte = ptr[9];
+  if (PROTOBUF_PREDICT_TRUE(byte == 1)) goto done10;
+
+  // A value of 0, however, represents an over-serialized varint. This case
+  // should not happen, but if does (say, due to a nonconforming serializer),
+  // deassert the continuation bit that came from ptr[8].
+  if (byte == 0) {
+    res3 ^= static_cast<uint64_t>(1) << 63;
+    goto done10;
+  }
+
+  // If the 10th byte/ptr[9] itself has any other value, then it is too big to
+  // fit in 64 bits. If the continue bit is set, it is an unterminated varint.
+  return {nullptr, 0};
+
+#define DONE(n) done##n : return {p + n, res1 & res2 & res3};
+done2:
+  return {p + 2, res1 & res2};
+  DONE(3)
+  DONE(4)
+  DONE(5)
+  DONE(6)
+  DONE(7)
+  DONE(8)
+  DONE(9)
+  DONE(10)
+#undef DONE
+}
+
+inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p,
+                                                      uint64_t* value) {
+  int64_t byte = static_cast<int8_t>(*p);
+  if (PROTOBUF_PREDICT_TRUE(byte >= 0)) {
+    *value = byte;
+    return p + 1;
+  } else {
+    auto tmp = Parse64FallbackPair(p, byte);
+    if (PROTOBUF_PREDICT_TRUE(tmp.first)) *value = tmp.second;
+    return tmp.first;
+  }
+}
+
+}  // namespace
+
+template <uint32_t kPowerOf2>
+template <typename FieldType, typename TagType,
+          TcParserBase::VarintDecode zigzag>
+const char* TcParser<kPowerOf2>::SingularVarint(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    return table->fallback(PROTOBUF_TC_PARAM_PASS);
+  }
+  ptr += sizeof(TagType);  // Consume tag
+  hasbits |= (uint64_t{1} << data.hasbit_idx());
+  uint64_t tmp;
+  ptr = ParseVarint(ptr, &tmp);
+  if (ptr == nullptr) {
+    return Error(PROTOBUF_TC_PARAM_PASS);
+  }
+  RefAt<FieldType>(msg, data.offset()) = static_cast<FieldType>(
+      zigzag ? google::protobuf::internal::WireFormatLite::ZigZagDecode64(tmp) : tmp);
+  PROTOBUF_MUSTTAIL return TailCall(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename FieldType, typename TagType,
+          TcParserBase::VarintDecode zigzag>
+PROTOBUF_NOINLINE const char* TcParserBase::RepeatedVarint(
+    PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    // Try parsing as non-packed repeated:
+    InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data);
+    if (static_cast<TagType>(data.coded_tag()) == 0) {
+      return PackedVarint<FieldType, TagType, zigzag>(PROTOBUF_TC_PARAM_PASS);
+    } else {
+      return table->fallback(PROTOBUF_TC_PARAM_PASS);
+    }
+  }
+  auto& field = RefAt<RepeatedField<FieldType>>(msg, data.offset());
+  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  do {
+    ptr += sizeof(TagType);
+    uint64_t tmp;
+    ptr = ParseVarint(ptr, &tmp);
+    if (ptr == nullptr) {
+      return Error(PROTOBUF_TC_PARAM_PASS);
+    }
+    field.Add(zigzag ? google::protobuf::internal::WireFormatLite::ZigZagDecode64(tmp)
+                     : tmp);
+    if (!ctx->DataAvailable(ptr)) {
+      break;
+    }
+  } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+  return Return(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename FieldType, typename TagType,
+          TcParserBase::VarintDecode zigzag>
+PROTOBUF_NOINLINE const char* TcParserBase::PackedVarint(
+    PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data);
+    if (static_cast<TagType>(data.coded_tag()) == 0) {
+      return RepeatedVarint<FieldType, TagType, zigzag>(PROTOBUF_TC_PARAM_PASS);
+    } else {
+      return table->fallback(PROTOBUF_TC_PARAM_PASS);
+    }
+  }
+  ptr += sizeof(TagType);
+  // Since ctx->ReadPackedVarint does not use TailCall or Return, sync any
+  // pending hasbits now:
+  SyncHasbits(msg, hasbits, table);
+  auto* field = &RefAt<RepeatedField<FieldType>>(msg, data.offset());
+  return ctx->ReadPackedVarint(ptr, [field](uint64_t varint) {
+    FieldType val;
+    if (zigzag) {
+      if (sizeof(FieldType) == 8) {
+        val = WireFormatLite::ZigZagDecode64(varint);
+      } else {
+        val = WireFormatLite::ZigZagDecode32(varint);
+      }
+    } else {
+      val = varint;
+    }
+    field->Add(val);
+  });
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// String/bytes fields
+//////////////////////////////////////////////////////////////////////////////
+
+// Defined in wire_format_lite.cc
+void PrintUTF8ErrorLog(const char* field_name, const char* operation_str,
+                       bool emit_stacktrace);
+
+namespace {
+
+PROTOBUF_NOINLINE
+const char* SingularStringParserFallback(ArenaStringPtr* s, const char* ptr,
+                                         EpsCopyInputStream* stream) {
+  int size = ReadSize(&ptr);
+  if (!ptr) return nullptr;
+  return stream->ReadString(
+      ptr, size, s->MutableNoArenaNoDefault(&GetEmptyStringAlreadyInited()));
+}
+
+}  // namespace
+
+template <typename TagType, TcParserBase::Utf8Type utf8>
+const char* TcParserBase::SingularString(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    return table->fallback(PROTOBUF_TC_PARAM_PASS);
+  }
+  ptr += sizeof(TagType);
+  hasbits |= (uint64_t{1} << data.hasbit_idx());
+  auto& field = RefAt<ArenaStringPtr>(msg, data.offset());
+  auto arena = ctx->data().arena;
+  if (arena) {
+    ptr = ctx->ReadArenaString(ptr, &field, arena);
+  } else {
+    ptr = SingularStringParserFallback(&field, ptr, ctx);
+  }
+  if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
+  switch (utf8) {
+    case kNoUtf8:
+#ifdef NDEBUG
+    case kUtf8ValidateOnly:
+#endif
+      return Return(PROTOBUF_TC_PARAM_PASS);
+    default:
+      if (PROTOBUF_PREDICT_TRUE(IsStructurallyValidUTF8(field.Get()))) {
+        return Return(PROTOBUF_TC_PARAM_PASS);
+      }
+      PrintUTF8ErrorLog("unknown", "parsing", false);
+      return utf8 == kUtf8 ? Error(PROTOBUF_TC_PARAM_PASS)
+                           : Return(PROTOBUF_TC_PARAM_PASS);
+  }
+}
+
+template <typename TagType, TcParserBase::Utf8Type utf8>
+const char* TcParserBase::RepeatedString(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(static_cast<TagType>(data.coded_tag()) != 0)) {
+    return table->fallback(PROTOBUF_TC_PARAM_PASS);
+  }
+  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  auto& field = RefAt<RepeatedPtrField<std::string>>(msg, data.offset());
+  do {
+    ptr += sizeof(TagType);
+    std::string* str = field.Add();
+    ptr = InlineGreedyStringParser(str, ptr, ctx);
+    if (ptr == nullptr) {
+      return Error(PROTOBUF_TC_PARAM_PASS);
+    }
+    if (utf8 != kNoUtf8) {
+      if (PROTOBUF_PREDICT_FALSE(!IsStructurallyValidUTF8(*str))) {
+        PrintUTF8ErrorLog("unknown", "parsing", false);
+        if (utf8 == kUtf8) return Error(PROTOBUF_TC_PARAM_PASS);
+      }
+    }
+    if (!ctx->DataAvailable(ptr)) break;
+  } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+  return Return(PROTOBUF_TC_PARAM_PASS);
+}
+
+#define PROTOBUF_TCT_SOURCE
+#include <google/protobuf/generated_message_tctable_impl.inc>
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 15eb9d6..605fa98 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -34,14 +34,8 @@
 
 #include <google/protobuf/generated_message_util.h>
 
+#include <atomic>
 #include <limits>
-
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-// We're only using this as a standard way for getting the thread id.
-// We're not using any thread functionality.
-#include <thread>  // NOLINT
-#endif             // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
 #include <vector>
 
 #include <google/protobuf/io/coded_stream.h>
@@ -51,11 +45,14 @@
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/port_def.inc>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/wire_format_lite.h>
 
+// Must be included last
+#include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
+
 
 namespace google {
 namespace protobuf {
@@ -65,22 +62,33 @@
   static_cast<const MessageLite*>(message)->~MessageLite();
 }
 void DestroyString(const void* s) {
-  static_cast<const std::string*>(s)->~string();
+  static_cast<const std::string*>(s)->~basic_string();
 }
 
-ExplicitlyConstructed<std::string> fixed_address_empty_string;
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY ExplicitlyConstructed<std::string>
+        fixed_address_empty_string{};  // NOLINT
 
 
+PROTOBUF_CONSTINIT std::atomic<bool> init_protobuf_defaults_state{false};
 static bool InitProtobufDefaultsImpl() {
   fixed_address_empty_string.DefaultConstruct();
   OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
+
+
+  init_protobuf_defaults_state.store(true, std::memory_order_release);
   return true;
 }
 
-void InitProtobufDefaults() {
+void InitProtobufDefaultsSlow() {
   static bool is_inited = InitProtobufDefaultsImpl();
   (void)is_inited;
 }
+// Force the initialization of the empty string.
+// Normally, registration would do it, but we don't have any guarantee that
+// there is any object with reflection.
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static std::true_type init_empty_string =
+    (InitProtobufDefaultsSlow(), std::true_type{});
 
 size_t StringSpaceUsedExcludingSelfLong(const std::string& str) {
   const void* start = &str;
@@ -246,10 +254,6 @@
     : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
 
 
-template <>
-struct PrimitiveTypeHelper<FieldMetadata::kInlinedType>
-    : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
-
 // We want to serialize to both CodedOutputStream and directly into byte arrays
 // without duplicating the code. In fact we might want extra output channels in
 // the future.
@@ -408,15 +412,6 @@
   }
 };
 
-template <>
-struct SingularFieldHelper<FieldMetadata::kInlinedType> {
-  template <typename O>
-  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
-    WriteTagTo(md.tag, output);
-    SerializeTo<FieldMetadata::kInlinedType>(&Get<std::string>(field), output);
-  }
-};
-
 template <int type>
 struct RepeatedFieldHelper {
   template <typename O>
@@ -489,10 +484,6 @@
 };
 
 
-template <>
-struct RepeatedFieldHelper<FieldMetadata::kInlinedType>
-    : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
-
 template <int type>
 struct PackedFieldHelper {
   template <typename O>
@@ -528,9 +519,6 @@
 template <>
 struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
     : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
-template <>
-struct PackedFieldHelper<FieldMetadata::kInlinedType>
-    : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
 
 template <int type>
 struct OneOfFieldHelper {
@@ -541,15 +529,6 @@
 };
 
 
-template <>
-struct OneOfFieldHelper<FieldMetadata::kInlinedType> {
-  template <typename O>
-  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
-    SingularFieldHelper<FieldMetadata::kInlinedType>::Serialize(
-        Get<const std::string*>(field), md, output);
-  }
-};
-
 void SerializeNotImplemented(int field) {
   GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
 }
@@ -590,11 +569,6 @@
 }
 
 
-template <>
-bool IsNull<FieldMetadata::kInlinedType>(const void* ptr) {
-  return static_cast<const std::string*>(ptr)->empty();
-}
-
 #define SERIALIZERS_FOR_TYPE(type)                                            \
   case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence):                    \
     if (!IsPresent(base, field_metadata.has_offset)) continue;                \
@@ -642,7 +616,6 @@
       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
-      SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
 
       // Special cases
       case FieldMetadata::kSpecial:
@@ -687,7 +660,6 @@
       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
       SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
-      SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
       // Special cases
       case FieldMetadata::kSpecial: {
         io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
@@ -746,8 +718,12 @@
 MessageLite* GetOwnedMessageInternal(Arena* message_arena,
                                      MessageLite* submessage,
                                      Arena* submessage_arena) {
-  GOOGLE_DCHECK(submessage->GetArena() == submessage_arena);
+  GOOGLE_DCHECK(Arena::InternalHelper<MessageLite>::GetOwningArena(submessage) ==
+         submessage_arena);
   GOOGLE_DCHECK(message_arena != submessage_arena);
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  GOOGLE_DCHECK_EQ(submessage_arena, nullptr);
+#endif  // PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
   if (message_arena != NULL && submessage_arena == NULL) {
     message_arena->Own(submessage);
     return submessage;
@@ -758,74 +734,8 @@
   }
 }
 
-namespace {
-
-void InitSCC_DFS(SCCInfoBase* scc) {
-  if (scc->visit_status.load(std::memory_order_relaxed) !=
-      SCCInfoBase::kUninitialized)
-    return;
-  scc->visit_status.store(SCCInfoBase::kRunning, std::memory_order_relaxed);
-  // Each base is followed by an array of void*, containing first pointers to
-  // SCCInfoBase and then pointers-to-pointers to SCCInfoBase.
-  auto deps = reinterpret_cast<void**>(scc + 1);
-  auto strong_deps = reinterpret_cast<SCCInfoBase* const*>(deps);
-  for (int i = 0; i < scc->num_deps; ++i) {
-    if (strong_deps[i]) InitSCC_DFS(strong_deps[i]);
-  }
-  auto implicit_weak_deps =
-      reinterpret_cast<SCCInfoBase** const*>(deps + scc->num_deps);
-  for (int i = 0; i < scc->num_implicit_weak_deps; ++i) {
-    if (*implicit_weak_deps[i]) {
-      InitSCC_DFS(*implicit_weak_deps[i]);
-    }
-  }
-  scc->init_func();
-  // Mark done (note we use memory order release here), other threads could
-  // now see this as initialized and thus the initialization must have happened
-  // before.
-  scc->visit_status.store(SCCInfoBase::kInitialized, std::memory_order_release);
-}
-
-}  // namespace
-
-void InitSCCImpl(SCCInfoBase* scc) {
-  static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
-  // Either the default in case no initialization is running or the id of the
-  // thread that is currently initializing.
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  static std::atomic<std::thread::id> runner;
-  auto me = std::this_thread::get_id();
-#else
-  // This is a lightweight replacement for std::thread::id. std::thread does not
-  // work on Windows XP SP2 with the latest VC++ libraries, because it utilizes
-  // the Concurrency Runtime that is only supported on Windows XP SP3 and above.
-  static std::atomic_llong runner(-1);
-  auto me = ::GetCurrentThreadId();
-#endif  // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-  // This will only happen because the constructor will call InitSCC while
-  // constructing the default instance.
-  if (runner.load(std::memory_order_relaxed) == me) {
-    // Because we're in the process of constructing the default instance.
-    // We can be assured that we're already exploring this SCC.
-    GOOGLE_CHECK_EQ(scc->visit_status.load(std::memory_order_relaxed),
-             SCCInfoBase::kRunning);
-    return;
-  }
-  InitProtobufDefaults();
-  mu.Lock();
-  runner.store(me, std::memory_order_relaxed);
-  InitSCC_DFS(scc);
-
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  runner.store(std::thread::id{}, std::memory_order_relaxed);
-#else
-  runner.store(-1, std::memory_order_relaxed);
-#endif  // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-  mu.Unlock();
-}
-
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 7cae4e1..94c6c29 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -85,7 +85,17 @@
 }
 
 
-PROTOBUF_EXPORT void InitProtobufDefaults();
+// This fastpath inlines a single branch instead of having to make the
+// InitProtobufDefaults function call.
+// It also generates less inlined code than a function-scope static initializer.
+PROTOBUF_EXPORT extern std::atomic<bool> init_protobuf_defaults_state;
+PROTOBUF_EXPORT void InitProtobufDefaultsSlow();
+PROTOBUF_EXPORT inline void InitProtobufDefaults() {
+  if (PROTOBUF_PREDICT_FALSE(
+          !init_protobuf_defaults_state.load(std::memory_order_acquire))) {
+    InitProtobufDefaultsSlow();
+  }
+}
 
 // This used by proto1
 PROTOBUF_EXPORT inline const std::string& GetEmptyString() {
@@ -182,64 +192,6 @@
   std::atomic<int> size_{0};
 };
 
-// SCCInfo represents information of a strongly connected component of
-// mutual dependent messages.
-struct PROTOBUF_EXPORT SCCInfoBase {
-  // We use 0 for the Initialized state, because test eax,eax, jnz is smaller
-  // and is subject to macro fusion.
-  enum {
-    kInitialized = 0,  // final state
-    kRunning = 1,
-    kUninitialized = -1,  // initial state
-  };
-#if defined(_MSC_VER) && !defined(__clang__)
-  // MSVC doesn't make std::atomic constant initialized. This union trick
-  // makes it so.
-  union {
-    int visit_status_to_make_linker_init;
-    std::atomic<int> visit_status;
-  };
-#else
-  std::atomic<int> visit_status;
-#endif
-  int num_deps;
-  int num_implicit_weak_deps;
-  void (*init_func)();
-  // This is followed by an array  of num_deps
-  // const SCCInfoBase* deps[];
-};
-
-// Zero-length arrays are a language extension available in GCC and Clang but
-// not MSVC.
-#ifdef __GNUC__
-#define PROTOBUF_ARRAY_SIZE(n) (n)
-#else
-#define PROTOBUF_ARRAY_SIZE(n) ((n) ? (n) : 1)
-#endif
-
-template <int N>
-struct SCCInfo {
-  SCCInfoBase base;
-  // Semantically this is const SCCInfo<T>* which is is a templated type.
-  // The obvious inheriting from SCCInfoBase mucks with struct initialization.
-  // Attempts showed the compiler was generating dynamic initialization code.
-  // This deps array consists of base.num_deps pointers to SCCInfoBase followed
-  // by base.num_implicit_weak_deps pointers to SCCInfoBase*. We need the extra
-  // pointer indirection for implicit weak fields. We cannot use a union type
-  // here, since that would prevent the array from being linker-initialized.
-  void* deps[PROTOBUF_ARRAY_SIZE(N)];
-};
-
-#undef PROTOBUF_ARRAY_SIZE
-
-PROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc);
-
-inline void InitSCC(SCCInfoBase* scc) {
-  auto status = scc->visit_status.load(std::memory_order_acquire);
-  if (PROTOBUF_PREDICT_FALSE(status != SCCInfoBase::kInitialized))
-    InitSCCImpl(scc);
-}
-
 PROTOBUF_EXPORT void DestroyMessage(const void* message);
 PROTOBUF_EXPORT void DestroyString(const void* s);
 // Destroy (not delete) the message
diff --git a/src/google/protobuf/has_bits.h b/src/google/protobuf/has_bits.h
index 540cac2..66d3cd4 100644
--- a/src/google/protobuf/has_bits.h
+++ b/src/google/protobuf/has_bits.h
@@ -47,17 +47,17 @@
 template <size_t doublewords>
 class HasBits {
  public:
-  HasBits() PROTOBUF_ALWAYS_INLINE { Clear(); }
+  PROTOBUF_NDEBUG_INLINE constexpr HasBits() : has_bits_{} {}
 
-  void Clear() PROTOBUF_ALWAYS_INLINE {
+  PROTOBUF_NDEBUG_INLINE void Clear() {
     memset(has_bits_, 0, sizeof(has_bits_));
   }
 
-  uint32& operator[](int index) PROTOBUF_ALWAYS_INLINE {
+  PROTOBUF_NDEBUG_INLINE uint32& operator[](int index) {
     return has_bits_[index];
   }
 
-  const uint32& operator[](int index) const PROTOBUF_ALWAYS_INLINE {
+  PROTOBUF_NDEBUG_INLINE const uint32& operator[](int index) const {
     return has_bits_[index];
   }
 
diff --git a/src/google/protobuf/implicit_weak_message.cc b/src/google/protobuf/implicit_weak_message.cc
index 5390616..528cf95 100644
--- a/src/google/protobuf/implicit_weak_message.cc
+++ b/src/google/protobuf/implicit_weak_message.cc
@@ -63,3 +63,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/implicit_weak_message.h b/src/google/protobuf/implicit_weak_message.h
index a2ae99d..bfa6a81 100644
--- a/src/google/protobuf/implicit_weak_message.h
+++ b/src/google/protobuf/implicit_weak_message.h
@@ -100,7 +100,7 @@
 class ImplicitWeakTypeHandler {
  public:
   typedef MessageLite Type;
-  static const bool Moveable = false;
+  static constexpr bool Moveable = false;
 
   static inline MessageLite* NewFromPrototype(const MessageLite* prototype,
                                               Arena* arena = NULL) {
@@ -129,7 +129,7 @@
 template <typename T>
 struct WeakRepeatedPtrField {
   using TypeHandler = internal::ImplicitWeakTypeHandler<T>;
-  WeakRepeatedPtrField() : weak() {}
+  constexpr WeakRepeatedPtrField() : weak() {}
   explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {}
   ~WeakRepeatedPtrField() { weak.template Destroy<TypeHandler>(); }
 
diff --git a/src/google/protobuf/inlined_string_field.h b/src/google/protobuf/inlined_string_field.h
deleted file mode 100644
index 991c0e1..0000000
--- a/src/google/protobuf/inlined_string_field.h
+++ /dev/null
@@ -1,260 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
-#define GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
-
-#include <string>
-#include <utility>
-
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-#ifdef SWIG
-#error "You cannot SWIG proto headers"
-#endif
-
-namespace google {
-namespace protobuf {
-
-class Arena;
-
-namespace internal {
-
-// InlinedStringField wraps a std::string instance and exposes an API similar to
-// ArenaStringPtr's wrapping of a std::string* instance.  As std::string is
-// never allocated on the Arena, we expose only the *NoArena methods of
-// ArenaStringPtr.
-//
-// default_value parameters are taken for consistency with ArenaStringPtr, but
-// are not used for most methods.  With inlining, these should be removed from
-// the generated binary.
-class PROTOBUF_EXPORT InlinedStringField {
- public:
-  InlinedStringField() PROTOBUF_ALWAYS_INLINE;
-  explicit InlinedStringField(const std::string& default_value);
-
-  void AssignWithDefault(const std::string* default_value,
-                         const InlinedStringField& from) PROTOBUF_ALWAYS_INLINE;
-
-  void ClearToEmpty(const std::string* default_value,
-                    Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    ClearToEmptyNoArena(default_value);
-  }
-  void ClearNonDefaultToEmpty() PROTOBUF_ALWAYS_INLINE {
-    ClearNonDefaultToEmptyNoArena();
-  }
-  void ClearToEmptyNoArena(const std::string* /*default_value*/)
-      PROTOBUF_ALWAYS_INLINE {
-    ClearNonDefaultToEmptyNoArena();
-  }
-  void ClearNonDefaultToEmptyNoArena() PROTOBUF_ALWAYS_INLINE;
-
-  void ClearToDefault(const std::string* default_value,
-                      Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    ClearToDefaultNoArena(default_value);
-  }
-  void ClearToDefaultNoArena(const std::string* default_value)
-      PROTOBUF_ALWAYS_INLINE;
-
-  void Destroy(const std::string* default_value,
-               Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    DestroyNoArena(default_value);
-  }
-  void DestroyNoArena(const std::string* default_value) PROTOBUF_ALWAYS_INLINE;
-
-  const std::string& Get() const PROTOBUF_ALWAYS_INLINE { return GetNoArena(); }
-  const std::string& GetNoArena() const PROTOBUF_ALWAYS_INLINE;
-
-  std::string* Mutable(const std::string* default_value,
-                       Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    return MutableNoArena(default_value);
-  }
-  std::string* MutableNoArena(const std::string* default_value)
-      PROTOBUF_ALWAYS_INLINE;
-
-  std::string* Release(const std::string* default_value, Arena* /*arena*/) {
-    return ReleaseNoArena(default_value);
-  }
-  std::string* ReleaseNonDefault(const std::string* default_value,
-                                 Arena* /*arena*/) {
-    return ReleaseNonDefaultNoArena(default_value);
-  }
-  std::string* ReleaseNoArena(const std::string* default_value) {
-    return ReleaseNonDefaultNoArena(default_value);
-  }
-  std::string* ReleaseNonDefaultNoArena(const std::string* default_value);
-
-  void Set(const std::string* default_value, StringPiece value,
-           Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    SetNoArena(default_value, value);
-  }
-  void SetLite(const std::string* default_value, StringPiece value,
-               Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    SetNoArena(default_value, value);
-  }
-  void SetNoArena(const std::string* default_value,
-                  StringPiece value) PROTOBUF_ALWAYS_INLINE;
-
-  void Set(const std::string* default_value, const std::string& value,
-           Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    SetNoArena(default_value, value);
-  }
-  void SetLite(const std::string* default_value, const std::string& value,
-               Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE {
-    SetNoArena(default_value, value);
-  }
-  void SetNoArena(const std::string* default_value,
-                  const std::string& value) PROTOBUF_ALWAYS_INLINE;
-
-  void SetNoArena(const std::string* default_value,
-                  std::string&& value) PROTOBUF_ALWAYS_INLINE;
-  void SetAllocated(const std::string* default_value, std::string* value,
-                    Arena* /*arena*/) {
-    SetAllocatedNoArena(default_value, value);
-  }
-  void SetAllocatedNoArena(const std::string* default_value,
-                           std::string* value);
-  void Swap(InlinedStringField* from) PROTOBUF_ALWAYS_INLINE;
-  std::string* UnsafeMutablePointer();
-  void UnsafeSetDefault(const std::string* default_value);
-  std::string* UnsafeArenaRelease(const std::string* default_value,
-                                  Arena* arena);
-  void UnsafeArenaSetAllocated(const std::string* default_value,
-                               std::string* value, Arena* arena);
-
-  bool IsDefault(const std::string* /*default_value*/) { return false; }
-
- private:
-  std::string value_;
-};
-
-inline InlinedStringField::InlinedStringField() {}
-
-inline InlinedStringField::InlinedStringField(const std::string& default_value)
-    : value_(default_value) {}
-
-inline void InlinedStringField::AssignWithDefault(
-    const std::string* /*default_value*/, const InlinedStringField& from) {
-  value_ = from.value_;
-}
-
-inline const std::string& InlinedStringField::GetNoArena() const {
-  return value_;
-}
-
-inline std::string* InlinedStringField::MutableNoArena(const std::string*) {
-  return &value_;
-}
-
-inline void InlinedStringField::SetAllocatedNoArena(
-    const std::string* default_value, std::string* value) {
-  if (value == NULL) {
-    value_.assign(*default_value);
-  } else {
-    value_.assign(std::move(*value));
-    delete value;
-  }
-}
-
-inline void InlinedStringField::DestroyNoArena(const std::string*) {
-  // This is invoked from the generated message's ArenaDtor, which is used to
-  // clean up objects not allocated on the Arena.
-  this->~InlinedStringField();
-}
-
-inline void InlinedStringField::ClearNonDefaultToEmptyNoArena() {
-  value_.clear();
-}
-
-inline void InlinedStringField::ClearToDefaultNoArena(
-    const std::string* default_value) {
-  value_.assign(*default_value);
-}
-
-inline std::string* InlinedStringField::ReleaseNonDefaultNoArena(
-    const std::string* default_value) {
-  std::string* released = new std::string(*default_value);
-  value_.swap(*released);
-  return released;
-}
-
-inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/,
-                                           StringPiece value) {
-  value_.assign(value.data(), value.length());
-}
-
-inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/,
-                                           const std::string& value) {
-  value_.assign(value);
-}
-
-inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/,
-                                           std::string&& value) {
-  value_.assign(std::move(value));
-}
-
-inline void InlinedStringField::Swap(InlinedStringField* from) {
-  value_.swap(from->value_);
-}
-
-inline std::string* InlinedStringField::UnsafeMutablePointer() {
-  return &value_;
-}
-
-inline void InlinedStringField::UnsafeSetDefault(
-    const std::string* default_value) {
-  value_.assign(*default_value);
-}
-
-inline std::string* InlinedStringField::UnsafeArenaRelease(
-    const std::string* default_value, Arena* /*arena*/) {
-  return ReleaseNoArena(default_value);
-}
-
-inline void InlinedStringField::UnsafeArenaSetAllocated(
-    const std::string* default_value, std::string* value, Arena* /*arena*/) {
-  if (value == NULL) {
-    value_.assign(*default_value);
-  } else {
-    value_.assign(*value);
-  }
-}
-
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 59d86f9..a318da4 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -312,7 +312,7 @@
   uint8 bytes[sizeof(*value)];
 
   const uint8* ptr;
-  if (BufferSize() >= sizeof(*value)) {
+  if (BufferSize() >= static_cast<int64>(sizeof(*value))) {
     // Fast path:  Enough bytes in the buffer to read directly.
     ptr = buffer_;
     Advance(sizeof(*value));
@@ -329,7 +329,7 @@
   uint8 bytes[sizeof(*value)];
 
   const uint8* ptr;
-  if (BufferSize() >= sizeof(*value)) {
+  if (BufferSize() >= static_cast<int64>(sizeof(*value))) {
     // Fast path:  Enough bytes in the buffer to read directly.
     ptr = buffer_;
     Advance(sizeof(*value));
@@ -351,7 +351,7 @@
 const uint8* DecodeVarint64KnownSize(const uint8* buffer, uint64* value) {
   GOOGLE_DCHECK_GT(N, 0);
   uint64 result = static_cast<uint64>(buffer[N - 1]) << (7 * (N - 1));
-  for (int i = 0, offset = 0; i < N - 1; i++, offset += 7) {
+  for (size_t i = 0, offset = 0; i < N - 1; i++, offset += 7) {
     result += static_cast<uint64>(buffer[i] - 0x80) << offset;
   }
   *value = result;
@@ -951,6 +951,28 @@
   return WriteStringToArray(str, target);
 }
 
+uint8* CodedOutputStream::WriteVarint32ToArrayOutOfLineHelper(uint32 value,
+                                                              uint8* target) {
+  GOOGLE_DCHECK_GE(value, 0x80);
+  target[0] |= static_cast<uint8>(0x80);
+  value >>= 7;
+  target[1] = static_cast<uint8>(value);
+  if (value < 0x80) {
+    return target + 2;
+  }
+  target += 2;
+  do {
+    // Turn on continuation bit in the byte we just wrote.
+    target[-1] |= static_cast<uint8>(0x80);
+    value >>= 7;
+    *target = static_cast<uint8>(value);
+    ++target;
+  } while (value >= 0x80);
+  return target;
+}
+
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 5f9feb8..30dc91a 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -120,18 +120,26 @@
 #include <type_traits>
 #include <utility>
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 // Assuming windows is always little-endian.
 #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
 #define PROTOBUF_LITTLE_ENDIAN 1
 #endif
-#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
 // If MSVC has "/RTCc" set, it will complain about truncating casts at
 // runtime.  This file contains some intentional truncating casts.
 #pragma runtime_checks("c", off)
 #endif
 #else
-#include <sys/param.h>  // __BYTE_ORDER
+#ifdef __APPLE__
+#include <machine/endian.h>  // __BYTE_ORDER
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>  // __BYTE_ORDER
+#else
+#if !defined(__QNX__)
+#include <endian.h>  // __BYTE_ORDER
+#endif
+#endif
 #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) ||    \
      (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \
     !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
@@ -391,13 +399,6 @@
   // This is unrelated to PushLimit()/PopLimit().
   void SetTotalBytesLimit(int total_bytes_limit);
 
-  PROTOBUF_DEPRECATED_MSG(
-      "Please use the single parameter version of SetTotalBytesLimit(). The "
-      "second parameter is ignored.")
-  void SetTotalBytesLimit(int total_bytes_limit, int) {
-    SetTotalBytesLimit(total_bytes_limit);
-  }
-
   // The Total Bytes Limit minus the Current Position, or -1 if the total bytes
   // limit is INT_MAX.
   int BytesUntilTotalBytesLimit() const;
@@ -847,11 +848,11 @@
   }
 
   static constexpr int TagSize(uint32 tag) {
-    return (tag < (1 << 7))
-               ? 1
-               : (tag < (1 << 14))
-                     ? 2
-                     : (tag < (1 << 21)) ? 3 : (tag < (1 << 28)) ? 4 : 5;
+    return (tag < (1 << 7))    ? 1
+           : (tag < (1 << 14)) ? 2
+           : (tag < (1 << 21)) ? 3
+           : (tag < (1 << 28)) ? 4
+                               : 5;
   }
 
   PROTOBUF_ALWAYS_INLINE uint8* WriteTag(uint32 num, uint32 wt, uint8* ptr) {
@@ -900,23 +901,25 @@
   PROTOBUF_ALWAYS_INLINE static uint8* UnsafeVarint(T value, uint8* ptr) {
     static_assert(std::is_unsigned<T>::value,
                   "Varint serialization must be unsigned");
+    ptr[0] = static_cast<uint8>(value);
     if (value < 0x80) {
-      ptr[0] = static_cast<uint8>(value);
       return ptr + 1;
     }
-    ptr[0] = static_cast<uint8>(value | 0x80);
+    // Turn on continuation bit in the byte we just wrote.
+    ptr[0] |= static_cast<uint8>(0x80);
     value >>= 7;
+    ptr[1] = static_cast<uint8>(value);
     if (value < 0x80) {
-      ptr[1] = static_cast<uint8>(value);
       return ptr + 2;
     }
-    ptr++;
+    ptr += 2;
     do {
-      *ptr = static_cast<uint8>(value | 0x80);
+      // Turn on continuation bit in the byte we just wrote.
+      ptr[-1] |= static_cast<uint8>(0x80);
       value >>= 7;
+      *ptr = static_cast<uint8>(value);
       ++ptr;
-    } while (PROTOBUF_PREDICT_FALSE(value >= 0x80));
-    *ptr++ = static_cast<uint8>(value);
+    } while (value >= 0x80);
     return ptr;
   }
 
@@ -960,7 +963,7 @@
   // buffers to ensure there is no error as of yet.
   uint8* FlushAndResetBuffer(uint8*);
 
-  // The following functions mimick the old CodedOutputStream behavior as close
+  // The following functions mimic the old CodedOutputStream behavior as close
   // as possible. They flush the current state to the stream, behave as
   // the old CodedOutputStream and then return to normal operation.
   bool Skip(int count, uint8** pp);
@@ -1145,6 +1148,9 @@
   void WriteVarint32(uint32 value);
   // Like WriteVarint32()  but writing directly to the target array.
   static uint8* WriteVarint32ToArray(uint32 value, uint8* target);
+  // Like WriteVarint32()  but writing directly to the target array, and with the
+  // less common-case paths being out of line rather than inlined.
+  static uint8* WriteVarint32ToArrayOutOfLine(uint32 value, uint8* target);
   // Write an unsigned integer with Varint encoding.
   void WriteVarint64(uint64 value);
   // Like WriteVarint64()  but writing directly to the target array.
@@ -1159,7 +1165,7 @@
   // This is identical to WriteVarint32(), but optimized for writing tags.
   // In particular, if the input is a compile-time constant, this method
   // compiles down to a couple instructions.
-  // Always inline because otherwise the aformentioned optimization can't work,
+  // Always inline because otherwise the aforementioned optimization can't work,
   // but GCC by default doesn't want to inline this.
   void WriteTag(uint32 value);
   // Like WriteTag()  but writing directly to the target array.
@@ -1177,12 +1183,11 @@
   // Compile-time equivalent of VarintSize32().
   template <uint32 Value>
   struct StaticVarintSize32 {
-    static const size_t value =
-        (Value < (1 << 7))
-            ? 1
-            : (Value < (1 << 14))
-                  ? 2
-                  : (Value < (1 << 21)) ? 3 : (Value < (1 << 28)) ? 4 : 5;
+    static const size_t value = (Value < (1 << 7))    ? 1
+                                : (Value < (1 << 14)) ? 2
+                                : (Value < (1 << 21)) ? 3
+                                : (Value < (1 << 28)) ? 4
+                                                      : 5;
   };
 
   // Returns the total number of bytes written since this object was created.
@@ -1260,6 +1265,8 @@
   static void SetDefaultSerializationDeterministic() {
     default_serialization_deterministic_.store(true, std::memory_order_relaxed);
   }
+  // REQUIRES: value >= 0x80, and that (value & 7f) has been written to *target.
+  static uint8* WriteVarint32ToArrayOutOfLineHelper(uint32 value, uint8* target);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
 };
 
@@ -1590,6 +1597,16 @@
   return EpsCopyOutputStream::UnsafeVarint(value, target);
 }
 
+inline uint8* CodedOutputStream::WriteVarint32ToArrayOutOfLine(uint32 value,
+                                                               uint8* target) {
+  target[0] = static_cast<uint8>(value);
+  if (value < 0x80) {
+    return target + 1;
+  } else {
+    return WriteVarint32ToArrayOutOfLineHelper(value, target);
+  }
+}
+
 inline uint8* CodedOutputStream::WriteVarint64ToArray(uint64 value,
                                                       uint8* target) {
   return EpsCopyOutputStream::UnsafeVarint(value, target);
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 7a80aed..671bde9 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -51,11 +51,6 @@
 
 #include <google/protobuf/port_def.inc>
 
-// This declares an unsigned long long integer literal in a portable way.
-// (The original macro is way too big and ruins my formatting.)
-#undef ULL
-#define ULL(x) PROTOBUF_ULONGLONG(x)
-
 
 namespace google {
 namespace protobuf {
@@ -132,7 +127,7 @@
 class CodedStreamTest : public testing::Test {
  protected:
   // Buffer used during most of the tests. This assumes tests run sequentially.
-  static const int kBufferSize = 1024 * 64;
+  static constexpr int kBufferSize = 1024 * 64;
   static uint8 buffer_[kBufferSize];
 };
 
@@ -168,24 +163,25 @@
     {{0xbe, 0xf7, 0x92, 0x84, 0x0b},
      5,  // 2961488830
      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-         (ULL(0x0b) << 28)},
+         (uint64_t{0x0bu} << 28)},
 
     // 64-bit
     {{0xbe, 0xf7, 0x92, 0x84, 0x1b},
      5,  // 7256456126
      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-         (ULL(0x1b) << 28)},
+         (uint64_t{0x1bu} << 28)},
     {{0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49},
      8,  // 41256202580718336
      (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
-         (ULL(0x43) << 28) | (ULL(0x49) << 35) | (ULL(0x24) << 42) |
-         (ULL(0x49) << 49)},
+         (uint64_t{0x43u} << 28) | (uint64_t{0x49u} << 35) |
+         (uint64_t{0x24u} << 42) | (uint64_t{0x49u} << 49)},
     // 11964378330978735131
     {{0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01},
      10,
      (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
-         (ULL(0x3b) << 28) | (ULL(0x56) << 35) | (ULL(0x00) << 42) |
-         (ULL(0x05) << 49) | (ULL(0x26) << 56) | (ULL(0x01) << 63)},
+         (uint64_t{0x3bu} << 28) | (uint64_t{0x56u} << 35) |
+         (uint64_t{0x00u} << 42) | (uint64_t{0x05u} << 49) |
+         (uint64_t{0x26u} << 56) | (uint64_t{0x01u} << 63)},
 };
 
 TEST_2D(CodedStreamTest, ReadVarint32, kVarintCases, kBlockSizes) {
@@ -313,7 +309,7 @@
 }
 
 TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) {
-  if (kVarintCases_case.value > ULL(0x00000000FFFFFFFF)) {
+  if (kVarintCases_case.value > uint64_t{0x00000000FFFFFFFFu}) {
     // Skip this test for the 64-bit values.
     return;
   }
@@ -500,8 +496,8 @@
     {128u, 2},
     {758923u, 3},
     {4000000000u, 5},
-    {ULL(41256202580718336), 8},
-    {ULL(11964378330978735131), 10},
+    {uint64_t{41256202580718336u}, 8},
+    {uint64_t{11964378330978735131u}, 10},
 };
 
 TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) {
@@ -569,8 +565,10 @@
 };
 
 Fixed64Case kFixed64Cases[] = {
-    {{0xef, 0xcd, 0xab, 0x90, 0x12, 0x34, 0x56, 0x78}, ULL(0x7856341290abcdef)},
-    {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, ULL(0x8877665544332211)},
+    {{0xef, 0xcd, 0xab, 0x90, 0x12, 0x34, 0x56, 0x78},
+     uint64_t{0x7856341290abcdefu}},
+    {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88},
+     uint64_t{0x8877665544332211u}},
 };
 
 TEST_2D(CodedStreamTest, ReadLittleEndian32, kFixed32Cases, kBlockSizes) {
@@ -743,7 +741,7 @@
 
   {
     CodedInputStream coded_input(&input);
-    coded_input.SetTotalBytesLimit(sizeof(kRawBytes), sizeof(kRawBytes));
+    coded_input.SetTotalBytesLimit(sizeof(kRawBytes));
     EXPECT_EQ(sizeof(kRawBytes), coded_input.BytesUntilTotalBytesLimit());
 
     std::string str;
@@ -866,7 +864,7 @@
 
   {
     CodedInputStream coded_input(&input);
-    coded_input.SetTotalBytesLimit(16, 16);
+    coded_input.SetTotalBytesLimit(16);
 
     std::string str;
     EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
@@ -888,7 +886,7 @@
   {
     CodedInputStream coded_input(&input);
     coded_input.PushLimit(sizeof(buffer_));
-    coded_input.SetTotalBytesLimit(16, 16);
+    coded_input.SetTotalBytesLimit(16);
 
     std::string str;
     EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
@@ -910,7 +908,7 @@
   {
     CodedInputStream coded_input(&input);
     coded_input.PushLimit(16);
-    coded_input.SetTotalBytesLimit(sizeof(buffer_), sizeof(buffer_));
+    coded_input.SetTotalBytesLimit(sizeof(buffer_));
     EXPECT_EQ(sizeof(buffer_), coded_input.BytesUntilTotalBytesLimit());
 
     std::string str;
@@ -1182,7 +1180,7 @@
 TEST_F(CodedStreamTest, TotalBytesLimit) {
   ArrayInputStream input(buffer_, sizeof(buffer_));
   CodedInputStream coded_input(&input);
-  coded_input.SetTotalBytesLimit(16, -1);
+  coded_input.SetTotalBytesLimit(16);
   EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit());
 
   std::string str;
@@ -1202,7 +1200,7 @@
                       "A protocol message was rejected because it was too big",
                       errors[0]);
 
-  coded_input.SetTotalBytesLimit(32, -1);
+  coded_input.SetTotalBytesLimit(32);
   EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit());
   EXPECT_TRUE(coded_input.ReadString(&str, 16));
   EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit());
@@ -1215,7 +1213,7 @@
   CodedInputStream coded_input(&input);
 
   // Set both total_bytes_limit and a regular limit at 16 bytes.
-  coded_input.SetTotalBytesLimit(16, -1);
+  coded_input.SetTotalBytesLimit(16);
   CodedInputStream::Limit limit = coded_input.PushLimit(16);
 
   // Read 16 bytes.
@@ -1344,3 +1342,5 @@
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index 86e2126..ad6bb5f 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -298,7 +298,7 @@
   return true;
 }
 void GzipOutputStream::BackUp(int count) {
-  GOOGLE_CHECK_GE(zcontext_.avail_in, count);
+  GOOGLE_CHECK_GE(zcontext_.avail_in, static_cast<uInt>(count));
   zcontext_.avail_in -= count;
 }
 int64_t GzipOutputStream::ByteCount() const {
diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
index b1ce1d3..cc704b9 100644
--- a/src/google/protobuf/io/gzip_stream.h
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -80,10 +80,10 @@
   inline int ZlibErrorCode() const { return zerror_; }
 
   // implements ZeroCopyInputStream ----------------------------------
-  bool Next(const void** data, int* size);
-  void BackUp(int count);
-  bool Skip(int count);
-  int64_t ByteCount() const;
+  bool Next(const void** data, int* size) override;
+  void BackUp(int count) override;
+  bool Skip(int count) override;
+  int64_t ByteCount() const override;
 
  private:
   Format format_;
@@ -167,9 +167,9 @@
   bool Close();
 
   // implements ZeroCopyOutputStream ---------------------------------
-  bool Next(void** data, int* size);
-  void BackUp(int count);
-  int64_t ByteCount() const;
+  bool Next(void** data, int* size) override;
+  void BackUp(int count) override;
+  int64_t ByteCount() const override;
 
  private:
   ZeroCopyOutputStream* sub_stream_;
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index f8d4d2b..230960c 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -296,7 +296,7 @@
     }
     push_back(c);
   }
-  if (arg_index != args.size()) {
+  if (arg_index != static_cast<int>(args.size())) {
     GOOGLE_LOG(FATAL) << " Unused arguments. " << save;
   }
   if (!annotations.empty()) {
@@ -305,7 +305,7 @@
 }
 
 const char* Printer::WriteVariable(
-    const std::vector<string>& args,
+    const std::vector<std::string>& args,
     const std::map<std::string, std::string>& vars, const char* format,
     int* arg_index, std::vector<AnnotationCollector::Annotation>* annotations) {
   auto start = format;
@@ -324,7 +324,7 @@
     GOOGLE_CHECK(std::isdigit(start[1]));
     GOOGLE_CHECK_EQ(end - start, 2);
     int idx = start[1] - '1';
-    if (idx < 0 || idx >= args.size()) {
+    if (idx < 0 || static_cast<size_t>(idx) >= args.size()) {
       GOOGLE_LOG(FATAL) << "Annotation ${" << idx + 1 << "$ is out of bounds.";
     }
     if (idx > *arg_index) {
@@ -358,10 +358,10 @@
       start_var, static_cast<std::string::size_type>(end_var - start_var)};
   std::string sub;
   if (std::isdigit(var_name[0])) {
-    GOOGLE_CHECK_EQ(var_name.size(), 1);  // No need for multi-digits
+    GOOGLE_CHECK_EQ(var_name.size(), 1U);  // No need for multi-digits
     int idx = var_name[0] - '1';   // Start counting at 1
     GOOGLE_CHECK_GE(idx, 0);
-    if (idx >= args.size()) {
+    if (static_cast<size_t>(idx) >= args.size()) {
       GOOGLE_LOG(FATAL) << "Argument $" << idx + 1 << "$ is out of bounds.";
     }
     if (idx > *arg_index) {
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index 64336eb..d4051e2 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -65,7 +65,7 @@
 
   // TODO(gerbens) I don't see why we need virtuals here. Just a vector of
   // range, payload pairs stored in a context should suffice.
-  virtual void AddAnnotationNew(Annotation& a) {}
+  virtual void AddAnnotationNew(Annotation& /* a */) {}
 
   virtual ~AnnotationCollector() {}
 };
@@ -84,7 +84,7 @@
   // Override for AnnotationCollector::AddAnnotation.
   virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
                              const std::string& file_path,
-                             const std::vector<int>& path) {
+                             const std::vector<int>& path) override {
     typename AnnotationProto::Annotation* annotation =
         annotation_proto_->add_annotation();
     for (int i = 0; i < path.size(); ++i) {
@@ -95,7 +95,7 @@
     annotation->set_end(end_offset);
   }
   // Override for AnnotationCollector::AddAnnotation.
-  virtual void AddAnnotationNew(Annotation& a) {
+  virtual void AddAnnotationNew(Annotation& a) override {
     auto* annotation = annotation_proto_->add_annotation();
     annotation->ParseFromString(a.second);
     annotation->set_begin(a.first.first);
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index ca45d67..ed54d1d 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -573,7 +573,7 @@
   EXPECT_TRUE(printer.failed());
 
   // Buffer should contain the first 17 bytes written.
-  EXPECT_EQ("0123456789abcdef<", string(buffer, sizeof(buffer)));
+  EXPECT_EQ("0123456789abcdef<", std::string(buffer, sizeof(buffer)));
 }
 
 TEST(Printer, WriteFailureExact) {
@@ -595,7 +595,7 @@
   EXPECT_TRUE(printer.failed());
 
   // Buffer should contain the first 16 bytes written.
-  EXPECT_EQ("0123456789abcdef", string(buffer, sizeof(buffer)));
+  EXPECT_EQ("0123456789abcdef", std::string(buffer, sizeof(buffer)));
 }
 
 TEST(Printer, FormatInternal) {
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index ff83946..129b488 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -888,7 +888,8 @@
       // token, but Tokenizer still think it's integer.
       return false;
     }
-    if (digit > max_value || result > (max_value - digit) / base) {
+    if (static_cast<uint64>(digit) > max_value ||
+        result > (max_value - digit) / base) {
       // Overflow.
       return false;
     }
@@ -918,7 +919,8 @@
     ++end;
   }
 
-  GOOGLE_LOG_IF(DFATAL, end - start != text.size() || *start == '-')
+  GOOGLE_LOG_IF(DFATAL,
+         static_cast<size_t>(end - start) != text.size() || *start == '-')
       << " Tokenizer::ParseFloat() passed text that could not have been"
          " tokenized as a float: "
       << CEscape(text);
@@ -940,14 +942,15 @@
     tmp = 0x00e08080 | ((code_point & 0xf000) << 4) |
           ((code_point & 0x0fc0) << 2) | (code_point & 0x003f);
     len = 3;
-  } else if (code_point <= 0x1fffff) {
+  } else if (code_point <= 0x10ffff) {
     tmp = 0xf0808080 | ((code_point & 0x1c0000) << 6) |
           ((code_point & 0x03f000) << 4) | ((code_point & 0x000fc0) << 2) |
           (code_point & 0x003f);
     len = 4;
   } else {
-    // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
-    // normally only defined up to there as well.
+    // Unicode code points end at 0x10FFFF, so this is out-of-range.
+    // ConsumeString permits hex values up to 0x1FFFFF, and FetchUnicodePoint
+    // doesn't perform a range check.
     StringAppendF(output, "\\U%08x", code_point);
     return;
   }
@@ -1113,8 +1116,8 @@
 
 template <typename CharacterClass>
 static bool AllInClass(const std::string& s) {
-  for (int i = 0; i < s.size(); ++i) {
-    if (!CharacterClass::InClass(s[i])) return false;
+  for (const char character : s) {
+    if (!CharacterClass::InClass(character)) return false;
   }
   return true;
 }
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 551516e..3be00f1 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -78,8 +78,8 @@
   // Indicates that there was a warning in the input at the given line and
   // column numbers.  The numbers are zero-based, so you may want to add
   // 1 to each before printing them.
-  virtual void AddWarning(int line, ColumnNumber column,
-                          const std::string& message) {}
+  virtual void AddWarning(int /* line */, ColumnNumber /* column */,
+                          const std::string& /* message */) {}
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index b14eddf..91c440c 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -808,8 +808,11 @@
   Tokenizer::ParseString("'\\ud852XX'", &output);
   EXPECT_EQ("\xed\xa1\x92XX", output);
   // Malformed escape: Demons may fly out of the nose.
-  Tokenizer::ParseString("\\u0", &output);
+  Tokenizer::ParseString("'\\u0'", &output);
   EXPECT_EQ("u0", output);
+  // Beyond the range of valid UTF-32 code units.
+  Tokenizer::ParseString("'\\U00110000\\U00200000\\UFFFFFFFF'", &output);
+  EXPECT_EQ("\\U00110000\\U00200000\\Uffffffff", output);
 
   // Test invalid strings that will never be tokenized as strings.
 #ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
index 4b1bf80..52617e9 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -165,25 +165,14 @@
 // ===================================================================
 
 FileOutputStream::FileOutputStream(int file_descriptor, int block_size)
-    : copying_output_(file_descriptor), impl_(&copying_output_, block_size) {}
-
-FileOutputStream::~FileOutputStream() { impl_.Flush(); }
+    : CopyingOutputStreamAdaptor(&copying_output_),
+      copying_output_(file_descriptor) {}
 
 bool FileOutputStream::Close() {
-  bool flush_succeeded = impl_.Flush();
+  bool flush_succeeded = Flush();
   return copying_output_.Close() && flush_succeeded;
 }
 
-bool FileOutputStream::Flush() { return impl_.Flush(); }
-
-bool FileOutputStream::Next(void** data, int* size) {
-  return impl_.Next(data, size);
-}
-
-void FileOutputStream::BackUp(int count) { impl_.BackUp(count); }
-
-int64_t FileOutputStream::ByteCount() const { return impl_.ByteCount(); }
-
 FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream(
     int file_descriptor)
     : file_(file_descriptor),
@@ -191,6 +180,8 @@
       is_closed_(false),
       errno_(0) {}
 
+FileOutputStream::~FileOutputStream() { Flush(); }
+
 FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() {
   if (close_on_delete_) {
     if (!Close()) {
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h
index b23a86d..0206e38 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl.h
@@ -48,7 +48,6 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 
-
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -140,13 +139,14 @@
 // harming performance.  Also, it's conceivable that FileOutputStream could
 // someday be enhanced to use zero-copy file descriptors on OSs which
 // support them.
-class PROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
+class PROTOBUF_EXPORT FileOutputStream : public CopyingOutputStreamAdaptor {
  public:
   // Creates a stream that writes to the given Unix file descriptor.
   // If a block_size is given, it specifies the size of the buffers
   // that should be returned by Next().  Otherwise, a reasonable default
   // is used.
   explicit FileOutputStream(int file_descriptor, int block_size = -1);
+
   ~FileOutputStream() override;
 
   // Flushes any buffers and closes the underlying file.  Returns false if
@@ -154,11 +154,6 @@
   // Even if an error occurs, the file descriptor is closed when this returns.
   bool Close();
 
-  // Flushes FileOutputStream's buffers but does not close the
-  // underlying file. No special measures are taken to ensure that
-  // underlying operating system file object is synchronized to disk.
-  bool Flush();
-
   // By default, the file descriptor is not closed when the stream is
   // destroyed.  Call SetCloseOnDelete(true) to change that.  WARNING:
   // This leaves no way for the caller to detect if close() fails.  If
@@ -172,11 +167,6 @@
   // fail.
   int GetErrno() const { return copying_output_.GetErrno(); }
 
-  // implements ZeroCopyOutputStream ---------------------------------
-  bool Next(void** data, int* size) override;
-  void BackUp(int count) override;
-  int64_t ByteCount() const override;
-
  private:
   class PROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream {
    public:
@@ -203,7 +193,6 @@
   };
 
   CopyingFileOutputStream copying_output_;
-  CopyingOutputStreamAdaptor impl_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
 };
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index 51cda2a..0eeeb0e 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -140,29 +140,25 @@
 
 bool StringOutputStream::Next(void** data, int* size) {
   GOOGLE_CHECK(target_ != NULL);
-  int old_size = target_->size();
+  size_t old_size = target_->size();
 
   // Grow the string.
+  size_t new_size;
   if (old_size < target_->capacity()) {
     // Resize the string to match its capacity, since we can get away
     // without a memory allocation this way.
-    STLStringResizeUninitialized(target_, target_->capacity());
+    new_size = target_->capacity();
   } else {
-    // Size has reached capacity, try to double the size.
-    if (old_size > std::numeric_limits<int>::max() / 2) {
-      // Can not double the size otherwise it is going to cause integer
-      // overflow in the expression below: old_size * 2 ";
-      GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for "
-                 << "StringOutputStream.";
-      return false;
-    }
-    // Double the size, also make sure that the new size is at least
-    // kMinimumSize.
-    STLStringResizeUninitialized(
-        target_,
-        std::max(old_size * 2,
-                 kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
+    // Size has reached capacity, try to double it.
+    new_size = old_size * 2;
   }
+  // Avoid integer overflow in returned '*size'.
+  new_size = std::min(new_size, old_size + std::numeric_limits<int>::max());
+  // Increase the size, also make sure that it is at least kMinimumSize.
+  STLStringResizeUninitialized(
+      target_,
+      std::max(new_size,
+               kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
 
   *data = mutable_string_data(target_) + old_size;
   *size = target_->size() - old_size;
@@ -172,7 +168,7 @@
 void StringOutputStream::BackUp(int count) {
   GOOGLE_CHECK_GE(count, 0);
   GOOGLE_CHECK(target_ != NULL);
-  GOOGLE_CHECK_LE(count, target_->size());
+  GOOGLE_CHECK_LE(static_cast<size_t>(count), target_->size());
   target_->resize(target_->size() - count);
 }
 
@@ -346,6 +342,37 @@
   return position_ + buffer_used_;
 }
 
+bool CopyingOutputStreamAdaptor::WriteAliasedRaw(const void* data, int size) {
+  if (size >= buffer_size_) {
+    if (!Flush() || !copying_stream_->Write(data, size)) {
+      return false;
+    }
+    GOOGLE_DCHECK_EQ(buffer_used_, 0);
+    position_ += size;
+    return true;
+  }
+
+  void* out;
+  int out_size;
+  while (true) {
+    if (!Next(&out, &out_size)) {
+      return false;
+    }
+
+    if (size <= out_size) {
+      std::memcpy(out, data, size);
+      BackUp(out_size - size);
+      return true;
+    }
+
+    std::memcpy(out, data, out_size);
+    data = static_cast<const char*>(data) + out_size;
+    size -= out_size;
+  }
+  return true;
+}
+
+
 bool CopyingOutputStreamAdaptor::WriteBuffer() {
   if (failed_) {
     // Already failed on a previous write.
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
index 26572cc..cfe81d2 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -150,7 +150,7 @@
   int64_t ByteCount() const override;
 
  private:
-  static const int kMinimumSize = 16;
+  static constexpr size_t kMinimumSize = 16;
 
   std::string* target_;
 
@@ -307,6 +307,8 @@
   bool Next(void** data, int* size) override;
   void BackUp(int count) override;
   int64_t ByteCount() const override;
+  bool WriteAliasedRaw(const void* data, int size) override;
+  bool AllowsAliasing() const override { return true; }
 
  private:
   // Write the current buffer, if it is present.
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index bec9df0..cc53949 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -112,7 +112,7 @@
   // that it matches the string.
   void ReadString(ZeroCopyInputStream* input, const std::string& str);
   // Writes some text to the output stream in a particular order.  Returns
-  // the number of bytes written, incase the caller needs that to set up an
+  // the number of bytes written, in case the caller needs that to set up an
   // input stream.
   int WriteStuff(ZeroCopyOutputStream* output);
   // Reads text from an input stream and expects it to match what
@@ -712,6 +712,21 @@
   }
 }
 
+// Verifies that outputs up to kint32max can be created.
+TEST_F(IoTest, LargeOutput) {
+  std::string str;
+  StringOutputStream output(&str);
+  void* unused_data;
+  int size;
+  // Repeatedly calling Next should eventually grow the buffer to kint32max.
+  do {
+    EXPECT_TRUE(output.Next(&unused_data, &size));
+  } while (str.size() < std::numeric_limits<int>::max());
+  // Further increases should be possible.
+  output.Next(&unused_data, &size);
+  EXPECT_GT(size, 0);
+}
+
 
 // To test files, we create a temporary file, write, read, truncate, repeat.
 TEST_F(IoTest, FileIo) {
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index cd5ccc4..deb5f06 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -41,6 +41,8 @@
 #include <google/protobuf/test_util_lite.h>
 #include <google/protobuf/unittest_lite.pb.h>
 #include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/wire_format_lite.h>
 #include <gtest/gtest.h>
@@ -613,7 +615,7 @@
     protobuf_unittest::TestMapLite message1, message2;
     std::string data;
     MapLiteTestUtil::SetMapFields(&message1);
-    int size = message1.ByteSize();
+    size_t size = message1.ByteSizeLong();
     data.resize(size);
     ::google::protobuf::uint8* start = reinterpret_cast<::google::protobuf::uint8*>(::google::protobuf::string_as_array(&data));
     ::google::protobuf::uint8* end = message1.SerializeWithCachedSizesToArray(start);
@@ -630,7 +632,7 @@
     // Test the generated SerializeWithCachedSizes()
     protobuf_unittest::TestMapLite message1, message2;
     MapLiteTestUtil::SetMapFields(&message1);
-    int size = message1.ByteSize();
+    size_t size = message1.ByteSizeLong();
     std::string data;
     data.resize(size);
     {
@@ -1187,5 +1189,84 @@
   EXPECT_EQ(protobuf_unittest::DupEnum::FOO2, value);
 }
 
+
+TEST(Lite, CodedInputStreamRollback) {
+  {
+    protobuf_unittest::TestAllTypesLite m;
+    m.set_optional_bytes(std::string(30, 'a'));
+    std::string serialized = m.SerializeAsString();
+    serialized += '\014';
+    serialized += std::string(3, ' ');
+    io::ArrayInputStream is(serialized.data(), serialized.size(),
+                            serialized.size() - 6);
+    {
+      io::CodedInputStream cis(&is);
+      m.Clear();
+      m.MergePartialFromCodedStream(&cis);
+      EXPECT_TRUE(cis.LastTagWas(12));
+      EXPECT_FALSE(cis.ConsumedEntireMessage());
+      // Should leave is with 3 spaces;
+    }
+    const void* data;
+    int size;
+    ASSERT_TRUE(is.Next(&data, &size));
+    ASSERT_EQ(size, 3);
+    EXPECT_EQ(memcmp(data, "   ", 3), 0);
+  }
+  {
+    protobuf_unittest::TestPackedTypesLite m;
+    constexpr int kCount = 30;
+    for (int i = 0; i < kCount; i++) m.add_packed_fixed32(i);
+    std::string serialized = m.SerializeAsString();
+    serialized += '\014';
+    serialized += std::string(3, ' ');
+    // Buffer breaks in middle of a fixed32.
+    io::ArrayInputStream is(serialized.data(), serialized.size(),
+                            serialized.size() - 7);
+    {
+      io::CodedInputStream cis(&is);
+      m.Clear();
+      m.MergePartialFromCodedStream(&cis);
+      EXPECT_TRUE(cis.LastTagWas(12));
+      EXPECT_FALSE(cis.ConsumedEntireMessage());
+      // Should leave is with 3 spaces;
+    }
+    ASSERT_EQ(m.packed_fixed32_size(), kCount);
+    for (int i = 0; i < kCount; i++) EXPECT_EQ(m.packed_fixed32(i), i);
+    const void* data;
+    int size;
+    ASSERT_TRUE(is.Next(&data, &size));
+    ASSERT_EQ(size, 3);
+    EXPECT_EQ(memcmp(data, "   ", 3), 0);
+  }
+  {
+    protobuf_unittest::TestPackedTypesLite m;
+    constexpr int kCount = 30;
+    // Make sure we output 2 byte varints
+    for (int i = 0; i < kCount; i++) m.add_packed_fixed32(128 + i);
+    std::string serialized = m.SerializeAsString();
+    serialized += '\014';
+    serialized += std::string(3, ' ');
+    // Buffer breaks in middle of a 2 byte varint.
+    io::ArrayInputStream is(serialized.data(), serialized.size(),
+                            serialized.size() - 5);
+    {
+      io::CodedInputStream cis(&is);
+      m.Clear();
+      m.MergePartialFromCodedStream(&cis);
+      EXPECT_TRUE(cis.LastTagWas(12));
+      EXPECT_FALSE(cis.ConsumedEntireMessage());
+      // Should leave is with 3 spaces;
+    }
+    ASSERT_EQ(m.packed_fixed32_size(), kCount);
+    for (int i = 0; i < kCount; i++) EXPECT_EQ(m.packed_fixed32(i), i + 128);
+    const void* data;
+    int size;
+    ASSERT_TRUE(is.Next(&data, &size));
+    ASSERT_EQ(size, 3);
+    EXPECT_EQ(memcmp(data, "   ", 3), 0);
+  }
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/unittest_no_arena_import.proto b/src/google/protobuf/map.cc
similarity index 87%
rename from src/google/protobuf/unittest_no_arena_import.proto
rename to src/google/protobuf/map.cc
index 6f3f04f..d60a9a2 100644
--- a/src/google/protobuf/unittest_no_arena_import.proto
+++ b/src/google/protobuf/map.cc
@@ -28,12 +28,14 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+#include <google/protobuf/map.h>
 
-package proto2_arena_unittest;
+namespace google {
+namespace protobuf {
+namespace internal {
 
-option cc_enable_arenas = false;
+void* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {nullptr};
 
-message ImportNoArenaNestedMessage {
-  optional int32 d = 1;
-}
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 8b656ab..df84e1e 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -37,13 +37,19 @@
 #ifndef GOOGLE_PROTOBUF_MAP_H__
 #define GOOGLE_PROTOBUF_MAP_H__
 
+#include <functional>
 #include <initializer_list>
 #include <iterator>
 #include <limits>  // To support Visual Studio 2008
-#include <set>
+#include <map>
+#include <string>
 #include <type_traits>
 #include <utility>
 
+#if defined(__cpp_lib_string_view)
+#include <string_view>
+#endif  // defined(__cpp_lib_string_view)
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/arena.h>
 #include <google/protobuf/generated_enum_util.h>
@@ -70,12 +76,12 @@
 namespace internal {
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType key_wire_type,
-          WireFormatLite::FieldType value_wire_type, int default_enum_value>
+          WireFormatLite::FieldType value_wire_type>
 class MapFieldLite;
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType key_wire_type,
-          WireFormatLite::FieldType value_wire_type, int default_enum_value>
+          WireFormatLite::FieldType value_wire_type>
 class MapField;
 
 template <typename Key, typename T>
@@ -99,8 +105,8 @@
   using size_type = size_t;
   using difference_type = ptrdiff_t;
 
-  MapAllocator() : arena_(nullptr) {}
-  explicit MapAllocator(Arena* arena) : arena_(arena) {}
+  constexpr MapAllocator() : arena_(nullptr) {}
+  explicit constexpr MapAllocator(Arena* arena) : arena_(arena) {}
   template <typename X>
   MapAllocator(const MapAllocator<X>& allocator)  // NOLINT(runtime/explicit)
       : arena_(allocator.arena()) {}
@@ -127,8 +133,7 @@
     }
   }
 
-#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \
-    !defined(GOOGLE_PROTOBUF_OS_NACL) &&                            \
+#if !defined(GOOGLE_PROTOBUF_OS_APPLE) && !defined(GOOGLE_PROTOBUF_OS_NACL) && \
     !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN)
   template <class NodeType, class... Args>
   void construct(NodeType* p, Args&&... args) {
@@ -177,42 +182,147 @@
 
  private:
   using DestructorSkippable_ = void;
-  Arena* const arena_;
+  Arena* arena_;
 };
 
+template <typename T>
+using KeyForTree =
+    typename std::conditional<std::is_scalar<T>::value, T,
+                              std::reference_wrapper<const T>>::type;
+
+// Default case: Not transparent.
+// We use std::hash<key_type>/std::less<key_type> and all the lookup functions
+// only accept `key_type`.
+template <typename key_type>
+struct TransparentSupport {
+  using hash = std::hash<key_type>;
+  using less = std::less<key_type>;
+
+  static bool Equals(const key_type& a, const key_type& b) { return a == b; }
+
+  template <typename K>
+  using key_arg = key_type;
+};
+
+#if defined(__cpp_lib_string_view)
+// If std::string_view is available, we add transparent support for std::string
+// keys. We use std::hash<std::string_view> as it supports the input types we
+// care about. The lookup functions accept arbitrary `K`. This will include any
+// key type that is convertible to std::string_view.
+template <>
+struct TransparentSupport<std::string> {
+  static std::string_view ImplicitConvert(std::string_view str) { return str; }
+  // If the element is not convertible to std::string_view, try to convert to
+  // std::string first.
+  // The template makes this overload lose resolution when both have the same
+  // rank otherwise.
+  template <typename = void>
+  static std::string_view ImplicitConvert(const std::string& str) {
+    return str;
+  }
+
+  struct hash : private std::hash<std::string_view> {
+    using is_transparent = void;
+
+    template <typename T>
+    size_t operator()(const T& str) const {
+      return base()(ImplicitConvert(str));
+    }
+
+   private:
+    const std::hash<std::string_view>& base() const { return *this; }
+  };
+  struct less {
+    using is_transparent = void;
+
+    template <typename T, typename U>
+    bool operator()(const T& t, const U& u) const {
+      return ImplicitConvert(t) < ImplicitConvert(u);
+    }
+  };
+
+  template <typename T, typename U>
+  static bool Equals(const T& t, const U& u) {
+    return ImplicitConvert(t) == ImplicitConvert(u);
+  }
+
+  template <typename K>
+  using key_arg = K;
+};
+#endif  // defined(__cpp_lib_string_view)
+
 template <typename Key>
-struct DerefCompare {
-  bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
-};
+using TreeForMap =
+    std::map<KeyForTree<Key>, void*, typename TransparentSupport<Key>::less,
+             MapAllocator<std::pair<const KeyForTree<Key>, void*>>>;
 
-// This class is used to get trivially destructible views of std::string and
-// MapKey, which are the only non-trivially destructible allowed key types.
+inline bool TableEntryIsEmpty(void* const* table, size_t b) {
+  return table[b] == nullptr;
+}
+inline bool TableEntryIsNonEmptyList(void* const* table, size_t b) {
+  return table[b] != nullptr && table[b] != table[b ^ 1];
+}
+inline bool TableEntryIsTree(void* const* table, size_t b) {
+  return !TableEntryIsEmpty(table, b) && !TableEntryIsNonEmptyList(table, b);
+}
+inline bool TableEntryIsList(void* const* table, size_t b) {
+  return !TableEntryIsTree(table, b);
+}
+
+// This captures all numeric types.
+inline size_t MapValueSpaceUsedExcludingSelfLong(bool) { return 0; }
+inline size_t MapValueSpaceUsedExcludingSelfLong(const std::string& str) {
+  return StringSpaceUsedExcludingSelfLong(str);
+}
+template <typename T,
+          typename = decltype(std::declval<const T&>().SpaceUsedLong())>
+size_t MapValueSpaceUsedExcludingSelfLong(const T& message) {
+  return message.SpaceUsedLong() - sizeof(T);
+}
+
+constexpr size_t kGlobalEmptyTableSize = 1;
+PROTOBUF_EXPORT extern void* const kGlobalEmptyTable[kGlobalEmptyTableSize];
+
+// Space used for the table, trees, and nodes.
+// Does not include the indirect space used. Eg the data of a std::string.
 template <typename Key>
-class KeyView {
- public:
-  KeyView(const Key& key) : key_(&key) {}  // NOLINT(runtime/explicit)
+PROTOBUF_NOINLINE size_t SpaceUsedInTable(void** table, size_t num_buckets,
+                                          size_t num_elements,
+                                          size_t sizeof_node) {
+  size_t size = 0;
+  // The size of the table.
+  size += sizeof(void*) * num_buckets;
+  // All the nodes.
+  size += sizeof_node * num_elements;
+  // For each tree, count the overhead of the those nodes.
+  // Two buckets at a time because we only care about trees.
+  for (size_t b = 0; b < num_buckets; b += 2) {
+    if (internal::TableEntryIsTree(table, b)) {
+      using Tree = TreeForMap<Key>;
+      Tree* tree = static_cast<Tree*>(table[b]);
+      // Estimated cost of the red-black tree nodes, 3 pointers plus a
+      // bool (plus alignment, so 4 pointers).
+      size += tree->size() *
+              (sizeof(typename Tree::value_type) + sizeof(void*) * 4);
+    }
+  }
+  return size;
+}
 
-  const Key& get() const { return *key_; }
-  // Allows implicit conversions to `const Key&`, which allows us to use the
-  // hasher defined for Key.
-  operator const Key&() const { return get(); }  // NOLINT(runtime/explicit)
+template <typename Map,
+          typename = typename std::enable_if<
+              !std::is_scalar<typename Map::key_type>::value ||
+              !std::is_scalar<typename Map::mapped_type>::value>::type>
+size_t SpaceUsedInValues(const Map* map) {
+  size_t size = 0;
+  for (const auto& v : *map) {
+    size += internal::MapValueSpaceUsedExcludingSelfLong(v.first) +
+            internal::MapValueSpaceUsedExcludingSelfLong(v.second);
+  }
+  return size;
+}
 
-  bool operator==(const KeyView& other) const { return get() == other.get(); }
-  bool operator==(const Key& other) const { return get() == other; }
-  bool operator<(const KeyView& other) const { return get() < other.get(); }
-  bool operator<(const Key& other) const { return get() < other; }
-
- private:
-  const Key* key_;
-};
-
-// Allows the InnerMap type to support skippable destruction.
-template <typename Key>
-struct GetTrivialKey {
-  using type =
-      typename std::conditional<std::is_trivially_destructible<Key>::value, Key,
-                                KeyView<Key>>::type;
-};
+inline size_t SpaceUsedInValues(const void*) { return 0; }
 
 }  // namespace internal
 
@@ -227,6 +337,8 @@
   MapPair(const Key& other_first, const T& other_second)
       : first(other_first), second(other_second) {}
   explicit MapPair(const Key& other_first) : first(other_first), second() {}
+  explicit MapPair(Key&& other_first)
+      : first(std::move(other_first)), second() {}
   MapPair(const MapPair& other) : first(other.first), second(other.second) {}
 
   ~MapPair() {}
@@ -268,27 +380,24 @@
   using const_reference = const value_type&;
 
   using size_type = size_t;
-  using hasher = hash<Key>;
+  using hasher = typename internal::TransparentSupport<Key>::hash;
 
-  Map() : arena_(nullptr), default_enum_value_(0) { Init(); }
-  explicit Map(Arena* arena) : arena_(arena), default_enum_value_(0) { Init(); }
+  constexpr Map() : elements_(nullptr) {}
+  explicit Map(Arena* arena) : elements_(arena) {}
 
-  Map(const Map& other)
-      : arena_(nullptr), default_enum_value_(other.default_enum_value_) {
-    Init();
-    insert(other.begin(), other.end());
-  }
+  Map(const Map& other) : Map() { insert(other.begin(), other.end()); }
 
   Map(Map&& other) noexcept : Map() {
-    if (other.arena_) {
+    if (other.arena() != nullptr) {
       *this = other;
     } else {
       swap(other);
     }
   }
+
   Map& operator=(Map&& other) noexcept {
     if (this != &other) {
-      if (arena_ != other.arena_) {
+      if (arena() != other.arena()) {
         *this = other;
       } else {
         swap(other);
@@ -298,45 +407,14 @@
   }
 
   template <class InputIt>
-  Map(const InputIt& first, const InputIt& last)
-      : arena_(nullptr), default_enum_value_(0) {
-    Init();
+  Map(const InputIt& first, const InputIt& last) : Map() {
     insert(first, last);
   }
 
-  ~Map() {
-    clear();
-    if (arena_ == nullptr) {
-      delete elements_;
-    }
-  }
+  ~Map() {}
 
  private:
-  void Init() { elements_ = Arena::CreateMessage<InnerMap>(arena_, 0u); }
-
-  // InnerMap's key type is TrivialKey and its value type is value_type*.  We
-  // use a custom class here and for Node, below, to ensure that k_ is at offset
-  // 0, allowing safe conversion from pointer to Node to pointer to TrivialKey,
-  // and vice versa when appropriate.  We use GetTrivialKey to adapt Key to
-  // be a trivially destructible view if Key is not already trivially
-  // destructible.  This view points into the Key inside v_ once it's
-  // initialized.
-  using TrivialKey = typename internal::GetTrivialKey<Key>::type;
-  class KeyValuePair {
-   public:
-    KeyValuePair(const TrivialKey& k, value_type* v) : k_(k), v_(v) {}
-
-    const TrivialKey& key() const { return k_; }
-    TrivialKey& key() { return k_; }
-    value_type* value() const { return v_; }
-    value_type*& value() { return v_; }
-
-   private:
-    TrivialKey k_;
-    value_type* v_;
-  };
-
-  using Allocator = internal::MapAllocator<KeyValuePair>;
+  using Allocator = internal::MapAllocator<void*>;
 
   // InnerMap is a generic hash-based map.  It doesn't contain any
   // protocol-buffer-specific logic.  It is a chaining hash map with the
@@ -367,32 +445,23 @@
   // 8. Mutations to a map do not invalidate the map's iterators, pointers to
   //    elements, or references to elements.
   // 9. Except for erase(iterator), any non-const method can reorder iterators.
-  // 10. InnerMap's key is TrivialKey, which is either Key, if Key is trivially
-  //    destructible, or a trivially destructible view of Key otherwise. This
-  //    allows InnerMap's destructor to be skipped when InnerMap is
-  //    arena-allocated.
+  // 10. InnerMap uses KeyForTree<Key> when using the Tree representation, which
+  //    is either `Key`, if Key is a scalar, or `reference_wrapper<const Key>`
+  //    otherwise. This avoids unnecessary copies of string keys, for example.
   class InnerMap : private hasher {
    public:
-    using Value = value_type*;
-
-    explicit InnerMap(size_type n) : InnerMap(nullptr, n) {}
-    InnerMap(Arena* arena, size_type n)
+    explicit constexpr InnerMap(Arena* arena)
         : hasher(),
           num_elements_(0),
-          seed_(Seed()),
-          table_(nullptr),
-          alloc_(arena) {
-      n = TableSize(n);
-      table_ = CreateEmptyTable(n);
-      num_buckets_ = index_of_first_non_null_ = n;
-      static_assert(
-          std::is_trivially_destructible<KeyValuePair>::value,
-          "We require KeyValuePair to be trivially destructible so that we can "
-          "skip InnerMap's destructor when it's arena allocated.");
-    }
+          num_buckets_(internal::kGlobalEmptyTableSize),
+          seed_(0),
+          index_of_first_non_null_(internal::kGlobalEmptyTableSize),
+          table_(const_cast<void**>(internal::kGlobalEmptyTable)),
+          alloc_(arena) {}
 
     ~InnerMap() {
-      if (table_ != nullptr) {
+      if (alloc_.arena() == nullptr &&
+          num_buckets_ != internal::kGlobalEmptyTableSize) {
         clear();
         Dealloc<void*>(table_, num_buckets_);
       }
@@ -403,27 +472,22 @@
 
     // Linked-list nodes, as one would expect for a chaining hash table.
     struct Node {
-      KeyValuePair kv;
+      value_type kv;
       Node* next;
     };
 
-    // This is safe only if the given pointer is known to point to a Key that is
-    // part of a Node.
-    static Node* NodePtrFromKeyPtr(TrivialKey* k) {
-      return reinterpret_cast<Node*>(k);
-    }
-
-    static TrivialKey* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
-
-    // Trees.  The payload type is pointer to Key, so that we can query the tree
-    // with Keys that are not in any particular data structure.  When we insert,
-    // though, the pointer is always pointing to a Key that is inside a Node.
-    using KeyPtrAllocator =
-        typename Allocator::template rebind<TrivialKey*>::other;
-    using Tree = std::set<TrivialKey*, internal::DerefCompare<TrivialKey>,
-                          KeyPtrAllocator>;
+    // Trees. The payload type is a copy of Key, so that we can query the tree
+    // with Keys that are not in any particular data structure.
+    // The value is a void* pointing to Node. We use void* instead of Node* to
+    // avoid code bloat. That way there is only one instantiation of the tree
+    // class per key type.
+    using Tree = internal::TreeForMap<Key>;
     using TreeIterator = typename Tree::iterator;
 
+    static Node* NodeFromTreeIterator(TreeIterator it) {
+      return static_cast<Node*>(it->second);
+    }
+
     // iterator and const_iterator are instantiations of iterator_base.
     template <typename KeyValueType>
     class iterator_base {
@@ -455,7 +519,7 @@
           : node_(n), m_(m), bucket_index_(index) {}
 
       iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index)
-          : node_(NodePtrFromKeyPtr(*tree_it)), m_(m), bucket_index_(index) {
+          : node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) {
         // Invariant: iterators that use buckets with trees have an even
         // bucket_index_.
         GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0u);
@@ -475,7 +539,7 @@
           } else if (m_->TableEntryIsTree(bucket_index_)) {
             Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
             GOOGLE_DCHECK(!tree->empty());
-            node_ = NodePtrFromKeyPtr(*tree->begin());
+            node_ = NodeFromTreeIterator(tree->begin());
             break;
           }
         }
@@ -503,7 +567,7 @@
             if (++tree_it == tree->end()) {
               SearchFrom(bucket_index_ + 2);
             } else {
-              node_ = NodePtrFromKeyPtr(*tree_it);
+              node_ = NodeFromTreeIterator(tree_it);
             }
           }
         } else {
@@ -541,8 +605,8 @@
         // Well, bucket_index_ still might be correct, but probably
         // not.  Revalidate just to be sure.  This case is rare enough that we
         // don't worry about potential optimizations, such as having a custom
-        // find-like method that compares Node* instead of TrivialKey.
-        iterator_base i(m_->find(*KeyPtrFromNodePtr(node_), it));
+        // find-like method that compares Node* instead of the key.
+        iterator_base i(m_->find(node_->kv.first, it));
         bucket_index_ = i.bucket_index_;
         return m_->TableEntryIsList(bucket_index_);
       }
@@ -553,8 +617,19 @@
     };
 
    public:
-    using iterator = iterator_base<KeyValuePair>;
-    using const_iterator = iterator_base<const KeyValuePair>;
+    using iterator = iterator_base<value_type>;
+    using const_iterator = iterator_base<const value_type>;
+
+    Arena* arena() const { return alloc_.arena(); }
+
+    void Swap(InnerMap* other) {
+      std::swap(num_elements_, other->num_elements_);
+      std::swap(num_buckets_, other->num_buckets_);
+      std::swap(seed_, other->seed_);
+      std::swap(index_of_first_non_null_, other->index_of_first_non_null_);
+      std::swap(table_, other->table_);
+      std::swap(alloc_, other->alloc_);
+    }
 
     iterator begin() { return iterator(this); }
     iterator end() { return iterator(); }
@@ -577,7 +652,7 @@
           table_[b] = table_[b + 1] = nullptr;
           typename Tree::iterator tree_it = tree->begin();
           do {
-            Node* node = NodePtrFromKeyPtr(*tree_it);
+            Node* node = NodeFromTreeIterator(tree_it);
             typename Tree::iterator next = tree_it;
             ++next;
             tree->erase(tree_it);
@@ -600,31 +675,20 @@
     size_type size() const { return num_elements_; }
     bool empty() const { return size() == 0; }
 
-    iterator find(const TrivialKey& k) { return iterator(FindHelper(k).first); }
-    const_iterator find(const TrivialKey& k) const { return find(k, nullptr); }
-    bool contains(const TrivialKey& k) const { return find(k) != end(); }
-
-    // In traditional C++ style, this performs "insert if not present."
-    std::pair<iterator, bool> insert(const KeyValuePair& kv) {
-      std::pair<const_iterator, size_type> p = FindHelper(kv.key());
-      // Case 1: key was already present.
-      if (p.first.node_ != nullptr)
-        return std::make_pair(iterator(p.first), false);
-      // Case 2: insert.
-      if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
-        p = FindHelper(kv.key());
-      }
-      const size_type b = p.second;  // bucket number
-      Node* node = Alloc<Node>(1);
-      alloc_.construct(&node->kv, kv);
-      iterator result = InsertUnique(b, node);
-      ++num_elements_;
-      return std::make_pair(result, true);
+    template <typename K>
+    iterator find(const K& k) {
+      return iterator(FindHelper(k).first);
     }
 
-    // The same, but if an insertion is necessary then the value portion of the
-    // inserted key-value pair is left uninitialized.
-    std::pair<iterator, bool> insert(const TrivialKey& k) {
+    template <typename K>
+    const_iterator find(const K& k) const {
+      return FindHelper(k).first;
+    }
+
+    // Insert the key into the map, if not present. In that case, the value will
+    // be value initialized.
+    template <typename K>
+    std::pair<iterator, bool> insert(K&& k) {
       std::pair<const_iterator, size_type> p = FindHelper(k);
       // Case 1: key was already present.
       if (p.first.node_ != nullptr)
@@ -634,20 +698,30 @@
         p = FindHelper(k);
       }
       const size_type b = p.second;  // bucket number
-      Node* node = Alloc<Node>(1);
-      using KeyAllocator =
-          typename Allocator::template rebind<TrivialKey>::other;
-      KeyAllocator(alloc_).construct(&node->kv.key(), k);
+      Node* node;
+      // If K is not key_type, make the conversion to key_type explicit.
+      using TypeToInit = typename std::conditional<
+          std::is_same<typename std::decay<K>::type, key_type>::value, K&&,
+          key_type>::type;
+      if (alloc_.arena() == nullptr) {
+        node = new Node{value_type(static_cast<TypeToInit>(std::forward<K>(k))),
+                        nullptr};
+      } else {
+        node = Alloc<Node>(1);
+        Arena::CreateInArenaStorage(
+            const_cast<Key*>(&node->kv.first), alloc_.arena(),
+            static_cast<TypeToInit>(std::forward<K>(k)));
+        Arena::CreateInArenaStorage(&node->kv.second, alloc_.arena());
+      }
+
       iterator result = InsertUnique(b, node);
       ++num_elements_;
       return std::make_pair(result, true);
     }
 
-    // Returns iterator so that outer map can update the TrivialKey to point to
-    // the Key inside value_type in case TrivialKey is a view type.
-    iterator operator[](const TrivialKey& k) {
-      KeyValuePair kv(k, Value());
-      return insert(kv).first;
+    template <typename K>
+    value_type& operator[](K&& k) {
+      return *insert(std::forward<K>(k)).first;
     }
 
     void erase(iterator it) {
@@ -664,7 +738,7 @@
       } else {
         GOOGLE_DCHECK(TableEntryIsTree(b));
         Tree* tree = static_cast<Tree*>(table_[b]);
-        tree->erase(*tree_it);
+        tree->erase(tree_it);
         if (tree->empty()) {
           // Force b to be the minimum of b and b ^ 1.  This is important
           // only because we want index_of_first_non_null_ to be correct.
@@ -683,20 +757,27 @@
       }
     }
 
+    size_t SpaceUsedInternal() const {
+      return internal::SpaceUsedInTable<Key>(table_, num_buckets_,
+                                             num_elements_, sizeof(Node));
+    }
+
    private:
-    const_iterator find(const TrivialKey& k, TreeIterator* it) const {
+    const_iterator find(const Key& k, TreeIterator* it) const {
       return FindHelper(k, it).first;
     }
-    std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k) const {
+    template <typename K>
+    std::pair<const_iterator, size_type> FindHelper(const K& k) const {
       return FindHelper(k, nullptr);
     }
-    std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k,
+    template <typename K>
+    std::pair<const_iterator, size_type> FindHelper(const K& k,
                                                     TreeIterator* it) const {
       size_type b = BucketNumber(k);
       if (TableEntryIsNonEmptyList(b)) {
         Node* node = static_cast<Node*>(table_[b]);
         do {
-          if (IsMatch(*KeyPtrFromNodePtr(node), k)) {
+          if (internal::TransparentSupport<Key>::Equals(node->kv.first, k)) {
             return std::make_pair(const_iterator(node, this, b), b);
           } else {
             node = node->next;
@@ -706,8 +787,7 @@
         GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
         b &= ~static_cast<size_t>(1);
         Tree* tree = static_cast<Tree*>(table_[b]);
-        TrivialKey* key = const_cast<TrivialKey*>(&k);
-        typename Tree::iterator tree_it = tree->find(key);
+        auto tree_it = tree->find(k);
         if (tree_it != tree->end()) {
           if (it != nullptr) *it = tree_it;
           return std::make_pair(const_iterator(tree_it, this, b), b);
@@ -728,7 +808,7 @@
       // or whatever.  But it's probably cheap enough to recompute that here;
       // it's likely that we're inserting into an empty or short list.
       iterator result;
-      GOOGLE_DCHECK(find(*KeyPtrFromNodePtr(node)) == end());
+      GOOGLE_DCHECK(find(node->kv.first) == end());
       if (TableEntryIsEmpty(b)) {
         result = InsertUniqueInList(b, node);
       } else if (TableEntryIsNonEmptyList(b)) {
@@ -752,9 +832,30 @@
       return result;
     }
 
+    // Returns whether we should insert after the head of the list. For
+    // non-optimized builds, we randomly decide whether to insert right at the
+    // head of the list or just after the head. This helps add a little bit of
+    // non-determinism to the map ordering.
+    bool ShouldInsertAfterHead(void* node) {
+#ifdef NDEBUG
+      (void)node;
+      return false;
+#else
+      // Doing modulo with a prime mixes the bits more.
+      return (reinterpret_cast<uintptr_t>(node) ^ seed_) % 13 > 6;
+#endif
+    }
+
     // Helper for InsertUnique.  Handles the case where bucket b is a
     // not-too-long linked list.
     iterator InsertUniqueInList(size_type b, Node* node) {
+      if (table_[b] != nullptr && ShouldInsertAfterHead(node)) {
+        Node* first = static_cast<Node*>(table_[b]);
+        node->next = first->next;
+        first->next = node;
+        return iterator(node, this, b);
+      }
+
       node->next = static_cast<Node*>(table_[b]);
       table_[b] = static_cast<void*>(node);
       return iterator(node, this, b);
@@ -767,7 +868,7 @@
       // Maintain the invariant that node->next is null for all Nodes in Trees.
       node->next = nullptr;
       return iterator(
-          static_cast<Tree*>(table_[b])->insert(KeyPtrFromNodePtr(node)).first,
+          static_cast<Tree*>(table_[b])->insert({node->kv.first, node}).first,
           this, b & ~static_cast<size_t>(1));
     }
 
@@ -814,6 +915,15 @@
 
     // Resize to the given number of buckets.
     void Resize(size_t new_num_buckets) {
+      if (num_buckets_ == internal::kGlobalEmptyTableSize) {
+        // This is the global empty array.
+        // Just overwrite with a new one. No need to transfer or free anything.
+        num_buckets_ = index_of_first_non_null_ = kMinTableSize;
+        table_ = CreateEmptyTable(num_buckets_);
+        seed_ = Seed();
+        return;
+      }
+
       GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize);
       void** const old_table = table_;
       const size_type old_table_size = num_buckets_;
@@ -822,9 +932,9 @@
       const size_type start = index_of_first_non_null_;
       index_of_first_non_null_ = num_buckets_;
       for (size_type i = start; i < old_table_size; i++) {
-        if (TableEntryIsNonEmptyList(old_table, i)) {
+        if (internal::TableEntryIsNonEmptyList(old_table, i)) {
           TransferList(old_table, i);
-        } else if (TableEntryIsTree(old_table, i)) {
+        } else if (internal::TableEntryIsTree(old_table, i)) {
           TransferTree(old_table, i++);
         }
       }
@@ -835,7 +945,7 @@
       Node* node = static_cast<Node*>(table[index]);
       do {
         Node* next = node->next;
-        InsertUnique(BucketNumber(*KeyPtrFromNodePtr(node)), node);
+        InsertUnique(BucketNumber(node->kv.first), node);
         node = next;
       } while (node != nullptr);
     }
@@ -844,8 +954,8 @@
       Tree* tree = static_cast<Tree*>(table[index]);
       typename Tree::iterator tree_it = tree->begin();
       do {
-        Node* node = NodePtrFromKeyPtr(*tree_it);
-        InsertUnique(BucketNumber(**tree_it), node);
+        InsertUnique(BucketNumber(std::cref(tree_it->first).get()),
+                     NodeFromTreeIterator(tree_it));
       } while (++tree_it != tree->end());
       DestroyTree(tree);
     }
@@ -860,42 +970,23 @@
     }
 
     bool TableEntryIsEmpty(size_type b) const {
-      return TableEntryIsEmpty(table_, b);
+      return internal::TableEntryIsEmpty(table_, b);
     }
     bool TableEntryIsNonEmptyList(size_type b) const {
-      return TableEntryIsNonEmptyList(table_, b);
+      return internal::TableEntryIsNonEmptyList(table_, b);
     }
     bool TableEntryIsTree(size_type b) const {
-      return TableEntryIsTree(table_, b);
+      return internal::TableEntryIsTree(table_, b);
     }
     bool TableEntryIsList(size_type b) const {
-      return TableEntryIsList(table_, b);
-    }
-    static bool TableEntryIsEmpty(void* const* table, size_type b) {
-      return table[b] == nullptr;
-    }
-    static bool TableEntryIsNonEmptyList(void* const* table, size_type b) {
-      return table[b] != nullptr && table[b] != table[b ^ 1];
-    }
-    static bool TableEntryIsTree(void* const* table, size_type b) {
-      return !TableEntryIsEmpty(table, b) &&
-             !TableEntryIsNonEmptyList(table, b);
-    }
-    static bool TableEntryIsList(void* const* table, size_type b) {
-      return !TableEntryIsTree(table, b);
+      return internal::TableEntryIsList(table_, b);
     }
 
     void TreeConvert(size_type b) {
       GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1));
-      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
-      Tree* tree = tree_allocator.allocate(1);
-      // We want to use the three-arg form of construct, if it exists, but we
-      // create a temporary and use the two-arg construct that's known to exist.
-      // It's clunky, but the compiler should be able to generate more-or-less
-      // the same code.
-      tree_allocator.construct(
-          tree, Tree(typename Tree::key_compare(), KeyPtrAllocator(alloc_)));
-      // Now the tree is ready to use.
+      Tree* tree =
+          Arena::Create<Tree>(alloc_.arena(), typename Tree::key_compare(),
+                              typename Tree::allocator_type(alloc_));
       size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree);
       GOOGLE_DCHECK_EQ(count, tree->size());
       table_[b] = table_[b ^ 1] = static_cast<void*>(tree);
@@ -907,7 +998,7 @@
       size_type count = 0;
       Node* node = static_cast<Node*>(table_[b]);
       while (node != nullptr) {
-        tree->insert(KeyPtrFromNodePtr(node));
+        tree->insert({node->kv.first, node});
         ++count;
         Node* next = node->next;
         node->next = nullptr;
@@ -931,13 +1022,17 @@
       return count >= kMaxLength;
     }
 
-    size_type BucketNumber(const TrivialKey& k) const {
-      size_type h = hash_function()(k);
-      return (h + seed_) & (num_buckets_ - 1);
-    }
+    template <typename K>
+    size_type BucketNumber(const K& k) const {
+      // We xor the hash value against the random seed so that we effectively
+      // have a random hash function.
+      uint64 h = hash_function()(k) ^ seed_;
 
-    bool IsMatch(const TrivialKey& k0, const TrivialKey& k1) const {
-      return k0 == k1;
+      // We use the multiplication method to determine the bucket number from
+      // the hash value. The constant kPhi (suggested by Knuth) is roughly
+      // (sqrt(5) - 1) / 2 * 2^64.
+      constexpr uint64 kPhi = uint64{0x9e3779b97f4a7c15};
+      return ((kPhi * h) >> 32) & (num_buckets_ - 1);
     }
 
     // Return a power of two no less than max(kMinTableSize, n).
@@ -963,14 +1058,15 @@
     }
 
     void DestroyNode(Node* node) {
-      alloc_.destroy(&node->kv);
-      Dealloc<Node>(node, 1);
+      if (alloc_.arena() == nullptr) {
+        delete node;
+      }
     }
 
     void DestroyTree(Tree* tree) {
-      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
-      tree_allocator.destroy(tree);
-      tree_allocator.deallocate(tree, 1);
+      if (alloc_.arena() == nullptr) {
+        delete tree;
+      }
     }
 
     void** CreateEmptyTable(size_type n) {
@@ -983,11 +1079,14 @@
 
     // Return a randomish value.
     size_type Seed() const {
-      size_type s = static_cast<size_type>(reinterpret_cast<uintptr_t>(this));
+      // We get a little bit of randomness from the address of the map. The
+      // lower bits are not very random, due to alignment, so we discard them
+      // and shift the higher bits into their place.
+      size_type s = reinterpret_cast<uintptr_t>(this) >> 12;
 #if defined(__x86_64__) && defined(__GNUC__) && \
     !defined(GOOGLE_PROTOBUF_NO_RDTSC)
       uint32 hi, lo;
-      asm("rdtsc" : "=a"(lo), "=d"(hi));
+      asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
       s += ((static_cast<uint64>(hi) << 32) | lo);
 #endif
       return s;
@@ -1006,6 +1105,10 @@
     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap);
   };  // end of class InnerMap
 
+  template <typename LookupKey>
+  using key_arg = typename internal::TransparentSupport<
+      key_type>::template key_arg<LookupKey>;
+
  public:
   // Iterators
   class const_iterator {
@@ -1021,7 +1124,7 @@
     const_iterator() {}
     explicit const_iterator(const InnerIt& it) : it_(it) {}
 
-    const_reference operator*() const { return *it_->value(); }
+    const_reference operator*() const { return *it_; }
     const_pointer operator->() const { return &(operator*()); }
 
     const_iterator& operator++() {
@@ -1054,7 +1157,7 @@
     iterator() {}
     explicit iterator(const InnerIt& it) : it_(it) {}
 
-    reference operator*() const { return *it_->value(); }
+    reference operator*() const { return *it_; }
     pointer operator->() const { return &(operator*()); }
 
     iterator& operator++() {
@@ -1081,58 +1184,67 @@
     InnerIt it_;
   };
 
-  iterator begin() { return iterator(elements_->begin()); }
-  iterator end() { return iterator(elements_->end()); }
-  const_iterator begin() const {
-    return const_iterator(iterator(elements_->begin()));
-  }
-  const_iterator end() const {
-    return const_iterator(iterator(elements_->end()));
-  }
+  iterator begin() { return iterator(elements_.begin()); }
+  iterator end() { return iterator(elements_.end()); }
+  const_iterator begin() const { return const_iterator(elements_.begin()); }
+  const_iterator end() const { return const_iterator(elements_.end()); }
   const_iterator cbegin() const { return begin(); }
   const_iterator cend() const { return end(); }
 
   // Capacity
-  size_type size() const { return elements_->size(); }
+  size_type size() const { return elements_.size(); }
   bool empty() const { return size() == 0; }
 
   // Element access
-  T& operator[](const key_type& key) {
-    typename InnerMap::iterator it = (*elements_)[key];
-    value_type** value = &it->value();
-    if (*value == nullptr) {
-      *value = CreateValueTypeInternal(key);
-      // We need to update the key in case it's a view type.
-      it->key() = (*value)->first;
-      internal::MapValueInitializer<is_proto_enum<T>::value, T>::Initialize(
-          (*value)->second, default_enum_value_);
-    }
-    return (*value)->second;
+  template <typename K = key_type>
+  T& operator[](const key_arg<K>& key) {
+    return elements_[key].second;
   }
-  const T& at(const key_type& key) const {
+  template <
+      typename K = key_type,
+      // Disable for integral types to reduce code bloat.
+      typename = typename std::enable_if<!std::is_integral<K>::value>::type>
+  T& operator[](key_arg<K>&& key) {
+    return elements_[std::forward<K>(key)].second;
+  }
+
+  template <typename K = key_type>
+  const T& at(const key_arg<K>& key) const {
     const_iterator it = find(key);
-    GOOGLE_CHECK(it != end()) << "key not found: " << key;
+    GOOGLE_CHECK(it != end()) << "key not found: " << static_cast<Key>(key);
     return it->second;
   }
-  T& at(const key_type& key) {
+
+  template <typename K = key_type>
+  T& at(const key_arg<K>& key) {
     iterator it = find(key);
-    GOOGLE_CHECK(it != end()) << "key not found: " << key;
+    GOOGLE_CHECK(it != end()) << "key not found: " << static_cast<Key>(key);
     return it->second;
   }
 
   // Lookup
-  size_type count(const key_type& key) const {
-    const_iterator it = find(key);
-    GOOGLE_DCHECK(it == end() || key == it->first);
-    return it == end() ? 0 : 1;
+  template <typename K = key_type>
+  size_type count(const key_arg<K>& key) const {
+    return find(key) == end() ? 0 : 1;
   }
-  const_iterator find(const key_type& key) const {
-    return const_iterator(iterator(elements_->find(key)));
+
+  template <typename K = key_type>
+  const_iterator find(const key_arg<K>& key) const {
+    return const_iterator(elements_.find(key));
   }
-  iterator find(const key_type& key) { return iterator(elements_->find(key)); }
-  bool contains(const Key& key) const { return elements_->contains(key); }
+  template <typename K = key_type>
+  iterator find(const key_arg<K>& key) {
+    return iterator(elements_.find(key));
+  }
+
+  template <typename K = key_type>
+  bool contains(const key_arg<K>& key) const {
+    return find(key) != end();
+  }
+
+  template <typename K = key_type>
   std::pair<const_iterator, const_iterator> equal_range(
-      const key_type& key) const {
+      const key_arg<K>& key) const {
     const_iterator it = find(key);
     if (it == end()) {
       return std::pair<const_iterator, const_iterator>(it, it);
@@ -1141,7 +1253,9 @@
       return std::pair<const_iterator, const_iterator>(begin, it);
     }
   }
-  std::pair<iterator, iterator> equal_range(const key_type& key) {
+
+  template <typename K = key_type>
+  std::pair<iterator, iterator> equal_range(const key_arg<K>& key) {
     iterator it = find(key);
     if (it == end()) {
       return std::pair<iterator, iterator>(it, it);
@@ -1154,11 +1268,9 @@
   // insert
   std::pair<iterator, bool> insert(const value_type& value) {
     std::pair<typename InnerMap::iterator, bool> p =
-        elements_->insert(value.first);
+        elements_.insert(value.first);
     if (p.second) {
-      p.first->value() = CreateValueTypeInternal(value);
-      // We need to update the key in case it's a view type.
-      p.first->key() = p.first->value()->first;
+      p.first->second = value.second;
     }
     return std::pair<iterator, bool>(iterator(p.first), p.second);
   }
@@ -1176,7 +1288,8 @@
   }
 
   // Erase and clear
-  size_type erase(const key_type& key) {
+  template <typename K = key_type>
+  size_type erase(const key_arg<K>& key) {
     iterator it = find(key);
     if (it == end()) {
       return 0;
@@ -1186,12 +1299,8 @@
     }
   }
   iterator erase(iterator pos) {
-    value_type* value = pos.operator->();
     iterator i = pos++;
-    elements_->erase(i.it_);
-    // Note: we need to delete the value after erasing from the inner map
-    // because the inner map's key may be a view of the value's key.
-    if (arena_ == nullptr) delete value;
+    elements_.erase(i.it_);
     return pos;
   }
   void erase(iterator first, iterator last) {
@@ -1199,7 +1308,7 @@
       first = erase(first);
     }
   }
-  void clear() { erase(begin(), end()); }
+  void clear() { elements_.clear(); }
 
   // Assign
   Map& operator=(const Map& other) {
@@ -1211,9 +1320,8 @@
   }
 
   void swap(Map& other) {
-    if (arena_ == other.arena_) {
-      std::swap(default_enum_value_, other.default_enum_value_);
-      std::swap(elements_, other.elements_);
+    if (arena() == other.arena()) {
+      InternalSwap(other);
     } else {
       // TODO(zuguang): optimize this. The temporary copy can be allocated
       // in the same arena as the other message, and the "other = copy" can
@@ -1224,53 +1332,27 @@
     }
   }
 
+  void InternalSwap(Map& other) { elements_.Swap(&other.elements_); }
+
   // Access to hasher.  Currently this returns a copy, but it may
   // be modified to return a const reference in the future.
-  hasher hash_function() const { return elements_->hash_function(); }
+  hasher hash_function() const { return elements_.hash_function(); }
+
+  size_t SpaceUsedExcludingSelfLong() const {
+    if (empty()) return 0;
+    return elements_.SpaceUsedInternal() + internal::SpaceUsedInValues(this);
+  }
 
  private:
-  // Set default enum value only for proto2 map field whose value is enum type.
-  void SetDefaultEnumValue(int default_enum_value) {
-    default_enum_value_ = default_enum_value;
-  }
-
-  value_type* CreateValueTypeInternal(const Key& key) {
-    if (arena_ == nullptr) {
-      return new value_type(key);
-    } else {
-      value_type* value = reinterpret_cast<value_type*>(
-          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
-      Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_, key);
-      Arena::CreateInArenaStorage(&value->second, arena_);
-      return value;
-    }
-  }
-
-  value_type* CreateValueTypeInternal(const value_type& value) {
-    if (arena_ == nullptr) {
-      return new value_type(value);
-    } else {
-      value_type* p = reinterpret_cast<value_type*>(
-          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
-      Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_,
-                                  value.first);
-      Arena::CreateInArenaStorage(&p->second, arena_);
-      p->second = value.second;
-      return p;
-    }
-  }
-
-  Arena* arena_;
-  int default_enum_value_;
-  InnerMap* elements_;
+  Arena* arena() const { return elements_.arena(); }
+  InnerMap elements_;
 
   friend class Arena;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
   template <typename Derived, typename K, typename V,
             internal::WireFormatLite::FieldType key_wire_type,
-            internal::WireFormatLite::FieldType value_wire_type,
-            int default_enum_value>
+            internal::WireFormatLite::FieldType value_wire_type>
   friend class internal::MapFieldLite;
 };
 
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index c516742..87bc000 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -51,7 +51,7 @@
 namespace internal {
 template <typename Derived, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+          WireFormatLite::FieldType kValueFieldType>
 class MapField;
 }
 }  // namespace protobuf
@@ -86,34 +86,30 @@
 //
 // The in-memory types of primitive types can be inferred from its proto type,
 // while we need to explicitly specify the cpp type if proto type is
-// TYPE_MESSAGE to infer the in-memory type.  Moreover, default_enum_value is
-// used to initialize enum field in proto2.
+// TYPE_MESSAGE to infer the in-memory type.
 template <typename Derived, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-class MapEntry
-    : public MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
-                          kValueFieldType, default_enum_value> {
+          WireFormatLite::FieldType kValueFieldType>
+class MapEntry : public MapEntryImpl<Derived, Message, Key, Value,
+                                     kKeyFieldType, kValueFieldType> {
  public:
-  MapEntry() : _internal_metadata_(NULL) {}
+  constexpr MapEntry() : _internal_metadata_() {}
   explicit MapEntry(Arena* arena)
       : MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
-                     kValueFieldType, default_enum_value>(arena),
+                     kValueFieldType>(arena),
         _internal_metadata_(arena) {}
   ~MapEntry() {
-    Message::_internal_metadata_.Delete<UnknownFieldSet>();
+    Message::_internal_metadata_.template Delete<UnknownFieldSet>();
     _internal_metadata_.Delete<UnknownFieldSet>();
   }
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
 
+  typedef typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
+                                kValueFieldType>::KeyTypeHandler KeyTypeHandler;
   typedef
       typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
-                            kValueFieldType, default_enum_value>::KeyTypeHandler
-          KeyTypeHandler;
-  typedef typename MapEntryImpl<
-      Derived, Message, Key, Value, kKeyFieldType, kValueFieldType,
-      default_enum_value>::ValueTypeHandler ValueTypeHandler;
+                            kValueFieldType>::ValueTypeHandler ValueTypeHandler;
   size_t SpaceUsedLong() const override {
     size_t size = sizeof(Derived);
     size += KeyTypeHandler::SpaceUsedInMapEntryLong(this->key_);
@@ -126,8 +122,7 @@
  private:
   friend class ::PROTOBUF_NAMESPACE_ID::Arena;
   template <typename C, typename K, typename V,
-            WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType,
-            int default_enum>
+            WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType>
   friend class internal::MapField;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
@@ -136,26 +131,24 @@
 // Specialization for the full runtime
 template <typename Derived, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-struct MapEntryHelper<MapEntry<Derived, Key, Value, kKeyFieldType,
-                               kValueFieldType, default_enum_value> >
-    : MapEntryHelper<MapEntryLite<Derived, Key, Value, kKeyFieldType,
-                                  kValueFieldType, default_enum_value> > {
+          WireFormatLite::FieldType kValueFieldType>
+struct MapEntryHelper<
+    MapEntry<Derived, Key, Value, kKeyFieldType, kValueFieldType> >
+    : MapEntryHelper<
+          MapEntryLite<Derived, Key, Value, kKeyFieldType, kValueFieldType> > {
   explicit MapEntryHelper(const MapPair<Key, Value>& map_pair)
-      : MapEntryHelper<MapEntryLite<Derived, Key, Value, kKeyFieldType,
-                                    kValueFieldType, default_enum_value> >(
+      : MapEntryHelper<
+            MapEntryLite<Derived, Key, Value, kKeyFieldType, kValueFieldType> >(
             map_pair) {}
 };
 
 template <typename Derived, typename K, typename V,
-          WireFormatLite::FieldType key, WireFormatLite::FieldType value,
-          int default_enum>
-struct DeconstructMapEntry<MapEntry<Derived, K, V, key, value, default_enum> > {
+          WireFormatLite::FieldType key, WireFormatLite::FieldType value>
+struct DeconstructMapEntry<MapEntry<Derived, K, V, key, value> > {
   typedef K Key;
   typedef V Value;
-  static const WireFormatLite::FieldType kKeyFieldType = key;
-  static const WireFormatLite::FieldType kValueFieldType = value;
-  static const int default_enum_value = default_enum;
+  static constexpr WireFormatLite::FieldType kKeyFieldType = key;
+  static constexpr WireFormatLite::FieldType kValueFieldType = value;
 };
 
 }  // namespace internal
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 7125ba1..609d025 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -55,11 +55,11 @@
 namespace internal {
 template <typename Derived, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+          WireFormatLite::FieldType kValueFieldType>
 class MapEntry;
 template <typename Derived, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+          WireFormatLite::FieldType kValueFieldType>
 class MapFieldLite;
 }  // namespace internal
 }  // namespace protobuf
@@ -93,11 +93,7 @@
 template <typename T>
 struct MoveHelper<false, false, true, T> {  // strings and similar
   static void Move(T* src, T* dest) {
-#if __cplusplus >= 201103L
     *dest = std::move(*src);
-#else
-    dest->swap(*src);
-#endif
   }
 };
 
@@ -144,7 +140,7 @@
 // the eventual code to the template code.
 template <typename Derived, typename Base, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+          WireFormatLite::FieldType kValueFieldType>
 class MapEntryImpl : public Base {
  public:
   typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs;
@@ -185,24 +181,20 @@
   typedef Value EntryValueType;
   static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType;
   static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType;
-  static const int kEntryDefaultEnumValue = default_enum_value;
 
-  MapEntryImpl() {
-    KeyTypeHandler::Initialize(&key_, NULL);
-    ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value,
-                                                   NULL);
-    _has_bits_[0] = 0;
-  }
+  constexpr MapEntryImpl()
+      : key_(KeyTypeHandler::Constinit()),
+        value_(ValueTypeHandler::Constinit()),
+        _has_bits_{} {}
 
-  explicit MapEntryImpl(Arena* arena) : Base(arena) {
-    KeyTypeHandler::Initialize(&key_, arena);
-    ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value,
-                                                   arena);
-    _has_bits_[0] = 0;
-  }
+  explicit MapEntryImpl(Arena* arena)
+      : Base(arena),
+        key_(KeyTypeHandler::Constinit()),
+        value_(ValueTypeHandler::Constinit()),
+        _has_bits_{} {}
 
   ~MapEntryImpl() {
-    if (Base::GetArena() != NULL) return;
+    if (Base::GetArenaForAllocation() != NULL) return;
     KeyTypeHandler::DeleteNoArena(key_);
     ValueTypeHandler::DeleteNoArena(value_);
   }
@@ -213,16 +205,16 @@
     return KeyTypeHandler::GetExternalReference(key_);
   }
   virtual inline const ValueMapEntryAccessorType& value() const {
-    return ValueTypeHandler::DefaultIfNotInitialized(
-        value_, Derived::internal_default_instance()->value_);
+    return ValueTypeHandler::DefaultIfNotInitialized(value_);
   }
   inline KeyMapEntryAccessorType* mutable_key() {
     set_has_key();
-    return KeyTypeHandler::EnsureMutable(&key_, Base::GetArena());
+    return KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
   }
   inline ValueMapEntryAccessorType* mutable_value() {
     set_has_value();
-    return ValueTypeHandler::EnsureMutable(&value_, Base::GetArena());
+    return ValueTypeHandler::EnsureMutable(&value_,
+                                           Base::GetArenaForAllocation());
   }
 
   // implements MessageLite =========================================
@@ -266,13 +258,8 @@
 
   size_t ByteSizeLong() const override {
     size_t size = 0;
-    size += has_key() ? kTagSize +
-                            static_cast<size_t>(KeyTypeHandler::ByteSize(key()))
-                      : 0;
-    size += has_value()
-                ? kTagSize +
-                      static_cast<size_t>(ValueTypeHandler::ByteSize(value()))
-                : 0;
+    size += kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key()));
+    size += kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value()));
     return size;
   }
 
@@ -315,13 +302,14 @@
   void MergeFromInternal(const MapEntryImpl& from) {
     if (from._has_bits_[0]) {
       if (from.has_key()) {
-        KeyTypeHandler::EnsureMutable(&key_, Base::GetArena());
-        KeyTypeHandler::Merge(from.key(), &key_, Base::GetArena());
+        KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
+        KeyTypeHandler::Merge(from.key(), &key_, Base::GetArenaForAllocation());
         set_has_key();
       }
       if (from.has_value()) {
-        ValueTypeHandler::EnsureMutable(&value_, Base::GetArena());
-        ValueTypeHandler::Merge(from.value(), &value_, Base::GetArena());
+        ValueTypeHandler::EnsureMutable(&value_, Base::GetArenaForAllocation());
+        ValueTypeHandler::Merge(from.value(), &value_,
+                                Base::GetArenaForAllocation());
         set_has_value();
       }
     }
@@ -329,19 +317,12 @@
 
  public:
   void Clear() override {
-    KeyTypeHandler::Clear(&key_, Base::GetArena());
-    ValueTypeHandler::ClearMaybeByDefaultEnum(&value_, Base::GetArena(),
-                                              default_enum_value);
+    KeyTypeHandler::Clear(&key_, Base::GetArenaForAllocation());
+    ValueTypeHandler::Clear(&value_, Base::GetArenaForAllocation());
     clear_has_key();
     clear_has_value();
   }
 
-  static void InitAsDefaultInstance() {
-    Derived* d = const_cast<Derived*>(Derived::internal_default_instance());
-    KeyTypeHandler::AssignDefaultValue(&d->key_);
-    ValueTypeHandler::AssignDefaultValue(&d->value_);
-  }
-
   // Parsing using MergePartialFromCodedStream, above, is not as
   // efficient as it could be.  This helper class provides a speedier way.
   template <typename MapField, typename Map>
@@ -349,7 +330,8 @@
    public:
     explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
     ~Parser() {
-      if (entry_ != nullptr && entry_->GetArena() == nullptr) delete entry_;
+      if (entry_ != nullptr && entry_->GetArenaForAllocation() == nullptr)
+        delete entry_;
     }
 
     // This does what the typical MergePartialFromCodedStream() is expected to
@@ -525,10 +507,10 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   template <typename C, typename K, typename V, WireFormatLite::FieldType,
-            WireFormatLite::FieldType, int>
+            WireFormatLite::FieldType>
   friend class internal::MapEntry;
   template <typename C, typename K, typename V, WireFormatLite::FieldType,
-            WireFormatLite::FieldType, int>
+            WireFormatLite::FieldType>
   friend class internal::MapFieldLite;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
@@ -536,17 +518,16 @@
 
 template <typename T, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-class MapEntryLite
-    : public MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
-                          kValueFieldType, default_enum_value> {
+          WireFormatLite::FieldType kValueFieldType>
+class MapEntryLite : public MapEntryImpl<T, MessageLite, Key, Value,
+                                         kKeyFieldType, kValueFieldType> {
  public:
   typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
-                       kValueFieldType, default_enum_value>
+                       kValueFieldType>
       SuperType;
-  MapEntryLite() {}
+  constexpr MapEntryLite() {}
   explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
-  ~MapEntryLite() { MessageLite::_internal_metadata_.Delete<std::string>(); }
+  ~MapEntryLite() { MessageLite::_internal_metadata_.template Delete<std::string>(); }
   void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }
 
  private:
@@ -559,13 +540,12 @@
 struct DeconstructMapEntry;
 
 template <typename T, typename K, typename V, WireFormatLite::FieldType key,
-          WireFormatLite::FieldType value, int default_enum>
-struct DeconstructMapEntry<MapEntryLite<T, K, V, key, value, default_enum> > {
+          WireFormatLite::FieldType value>
+struct DeconstructMapEntry<MapEntryLite<T, K, V, key, value> > {
   typedef K Key;
   typedef V Value;
   static const WireFormatLite::FieldType kKeyFieldType = key;
   static const WireFormatLite::FieldType kValueFieldType = value;
-  static const int default_enum_value = default_enum;
 };
 
 // Helpers for deterministic serialization =============================
@@ -636,9 +616,9 @@
 
 template <typename T, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-struct MapEntryHelper<MapEntryLite<T, Key, Value, kKeyFieldType,
-                                   kValueFieldType, default_enum_value> > {
+          WireFormatLite::FieldType kValueFieldType>
+struct MapEntryHelper<
+    MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType> > {
   // Provide utilities to parse/serialize key/value.  Provide utilities to
   // manipulate internal stored type.
   typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index d61fddd..d94b278 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -44,20 +44,44 @@
 }
 
 const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
+  ConstAccess();
   SyncRepeatedFieldWithMap();
   return *reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
 }
 
 RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
+  MutableAccess();
   SyncRepeatedFieldWithMap();
   SetRepeatedDirty();
   return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
 }
 
+void MapFieldBase::Swap(MapFieldBase* other) {
+  // TODO(teboring): This is incorrect when on different arenas.
+  InternalSwap(other);
+}
+
+void MapFieldBase::UnsafeShallowSwap(MapFieldBase* other) {
+  GOOGLE_DCHECK_EQ(arena_, other->arena_);
+  InternalSwap(other);
+}
+
+void MapFieldBase::InternalSwap(MapFieldBase* other) {
+  std::swap(arena_, other->arena_);
+  std::swap(repeated_field_, other->repeated_field_);
+  // a relaxed swap of the atomic
+  auto other_state = other->state_.load(std::memory_order_relaxed);
+  auto this_state = state_.load(std::memory_order_relaxed);
+  other->state_.store(this_state, std::memory_order_relaxed);
+  state_.store(other_state, std::memory_order_relaxed);
+}
+
 size_t MapFieldBase::SpaceUsedExcludingSelfLong() const {
+  ConstAccess();
   mutex_.Lock();
   size_t size = SpaceUsedExcludingSelfNoLock();
   mutex_.Unlock();
+  ConstAccess();
   return size;
 }
 
@@ -70,6 +94,7 @@
 }
 
 bool MapFieldBase::IsMapValid() const {
+  ConstAccess();
   // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
   // executed before state_ is checked.
   int state = state_.load(std::memory_order_acquire);
@@ -77,23 +102,27 @@
 }
 
 bool MapFieldBase::IsRepeatedFieldValid() const {
+  ConstAccess();
   int state = state_.load(std::memory_order_acquire);
   return state != STATE_MODIFIED_MAP;
 }
 
 void MapFieldBase::SetMapDirty() {
+  MutableAccess();
   // These are called by (non-const) mutator functions. So by our API it's the
   // callers responsibility to have these calls properly ordered.
   state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
 }
 
 void MapFieldBase::SetRepeatedDirty() {
+  MutableAccess();
   // These are called by (non-const) mutator functions. So by our API it's the
   // callers responsibility to have these calls properly ordered.
   state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
 }
 
 void MapFieldBase::SyncRepeatedFieldWithMap() const {
+  ConstAccess();
   // acquire here matches with release below to ensure that we can only see a
   // value of CLEAN after all previous changes have been synced.
   switch (state_.load(std::memory_order_acquire)) {
@@ -106,22 +135,20 @@
         state_.store(CLEAN, std::memory_order_release);
       }
       mutex_.Unlock();
+      ConstAccess();
       break;
     case CLEAN:
       mutex_.Lock();
       // Double check state
       if (state_.load(std::memory_order_relaxed) == CLEAN) {
         if (repeated_field_ == nullptr) {
-          if (arena_ == nullptr) {
-            repeated_field_ = new RepeatedPtrField<Message>();
-          } else {
-            repeated_field_ =
-                Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
-          }
+          repeated_field_ =
+              Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
         }
         state_.store(CLEAN, std::memory_order_release);
       }
       mutex_.Unlock();
+      ConstAccess();
       break;
     default:
       break;
@@ -135,6 +162,7 @@
 }
 
 void MapFieldBase::SyncMapWithRepeatedField() const {
+  ConstAccess();
   // acquire here matches with release below to ensure that we can only see a
   // value of CLEAN after all previous changes have been synced.
   if (state_.load(std::memory_order_acquire) == STATE_MODIFIED_REPEATED) {
@@ -146,6 +174,7 @@
       state_.store(CLEAN, std::memory_order_release);
     }
     mutex_.Unlock();
+    ConstAccess();
   }
 }
 
@@ -159,11 +188,11 @@
       default_entry_(default_entry) {}
 
 DynamicMapField::~DynamicMapField() {
-  // DynamicMapField owns map values. Need to delete them before clearing
-  // the map.
-  for (Map<MapKey, MapValueRef>::iterator iter = map_.begin();
-       iter != map_.end(); ++iter) {
-    iter->second.DeleteData();
+  if (arena_ != nullptr) return;
+  // DynamicMapField owns map values. Need to delete them before clearing the
+  // map.
+  for (auto& kv : map_) {
+    kv.second.DeleteData();
   }
   map_.clear();
 }
@@ -196,8 +225,7 @@
 }
 
 void DynamicMapField::AllocateMapValue(MapValueRef* map_val) {
-  const FieldDescriptor* val_des =
-      default_entry_->GetDescriptor()->FindFieldByName("value");
+  const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value();
   map_val->SetType(val_des->cpp_type());
   // Allocate memory for the MapValueRef, and initialize to
   // default value.
@@ -246,6 +274,19 @@
   return false;
 }
 
+bool DynamicMapField::LookupMapValue(const MapKey& map_key,
+                                     MapValueConstRef* val) const {
+  const Map<MapKey, MapValueRef>& map = GetMap();
+  Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
+  if (iter == map.end()) {
+    return false;
+  }
+  // map_key is already in the map. Make sure (*map)[map_key] is not called.
+  // [] may reorder the map and iterators.
+  val->CopyFrom(iter->second);
+  return true;
+}
+
 bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
   MapFieldBase::SyncMapWithRepeatedField();
   Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
@@ -300,7 +341,7 @@
 
     // Copy map value
     const FieldDescriptor* field_descriptor =
-        default_entry_->GetDescriptor()->FindFieldByName("value");
+        default_entry_->GetDescriptor()->map_value();
     switch (field_descriptor->cpp_type()) {
       case FieldDescriptor::CPPTYPE_INT32: {
         map_val->SetInt32Value(other_it->second.GetInt32Value());
@@ -360,18 +401,11 @@
 
 void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
   const Reflection* reflection = default_entry_->GetReflection();
-  const FieldDescriptor* key_des =
-      default_entry_->GetDescriptor()->FindFieldByName("key");
-  const FieldDescriptor* val_des =
-      default_entry_->GetDescriptor()->FindFieldByName("value");
+  const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key();
+  const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value();
   if (MapFieldBase::repeated_field_ == NULL) {
-    if (MapFieldBase::arena_ == NULL) {
-      MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
-    } else {
-      MapFieldBase::repeated_field_ =
-          Arena::CreateMessage<RepeatedPtrField<Message> >(
-              MapFieldBase::arena_);
-    }
+    MapFieldBase::repeated_field_ =
+        Arena::CreateMessage<RepeatedPtrField<Message> >(MapFieldBase::arena_);
   }
 
   MapFieldBase::repeated_field_->Clear();
@@ -448,10 +482,8 @@
 void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
   Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
   const Reflection* reflection = default_entry_->GetReflection();
-  const FieldDescriptor* key_des =
-      default_entry_->GetDescriptor()->FindFieldByName("key");
-  const FieldDescriptor* val_des =
-      default_entry_->GetDescriptor()->FindFieldByName("value");
+  const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key();
+  const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value();
   // DynamicMapField owns map values. Need to delete them before clearing
   // the map.
   if (MapFieldBase::arena_ == nullptr) {
@@ -580,3 +612,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 002c266..7f52cc7 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -32,6 +32,7 @@
 #define GOOGLE_PROTOBUF_MAP_FIELD_H__
 
 #include <atomic>
+#include <functional>
 
 #include <google/protobuf/arena.h>
 #include <google/protobuf/descriptor.h>
@@ -71,8 +72,8 @@
 // map key.
 class PROTOBUF_EXPORT MapKey {
  public:
-  MapKey() : type_(0) {}
-  MapKey(const MapKey& other) : type_(0) { CopyFrom(other); }
+  MapKey() : type_() {}
+  MapKey(const MapKey& other) : type_() { CopyFrom(other); }
 
   MapKey& operator=(const MapKey& other) {
     CopyFrom(other);
@@ -86,12 +87,12 @@
   }
 
   FieldDescriptor::CppType type() const {
-    if (type_ == 0) {
+    if (type_ == FieldDescriptor::CppType()) {
       GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
                  << "MapKey::type MapKey is not initialized. "
                  << "Call set methods to initialize MapKey.";
     }
-    return (FieldDescriptor::CppType)type_;
+    return type_;
   }
 
   void SetInt64Value(int64 value) {
@@ -260,9 +261,57 @@
   }
 
   // type_ is 0 or a valid FieldDescriptor::CppType.
-  int type_;
+  // Use "CppType()" to indicate zero.
+  FieldDescriptor::CppType type_;
 };
 
+}  // namespace protobuf
+}  // namespace google
+namespace std {
+template <>
+struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
+  size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const {
+    switch (map_key.type()) {
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE:
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT:
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM:
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Unsupported";
+        break;
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING:
+        return hash<std::string>()(map_key.GetStringValue());
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: {
+        auto value = map_key.GetInt64Value();
+        return hash<decltype(value)>()(value);
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: {
+        auto value = map_key.GetInt32Value();
+        return hash<decltype(value)>()(map_key.GetInt32Value());
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: {
+        auto value = map_key.GetUInt64Value();
+        return hash<decltype(value)>()(map_key.GetUInt64Value());
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: {
+        auto value = map_key.GetUInt32Value();
+        return hash<decltype(value)>()(map_key.GetUInt32Value());
+      }
+      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: {
+        return hash<bool>()(map_key.GetBoolValue());
+      }
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return 0;
+  }
+  bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1,
+                  const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const {
+    return map_key1 < map_key2;
+  }
+};
+}  // namespace std
+
+namespace google {
+namespace protobuf {
 namespace internal {
 
 class ContendedMapCleanTest;
@@ -271,19 +320,23 @@
 
 // This class provides access to map field using reflection, which is the same
 // as those provided for RepeatedPtrField<Message>. It is used for internal
-// reflection implentation only. Users should never use this directly.
+// reflection implementation only. Users should never use this directly.
 class PROTOBUF_EXPORT MapFieldBase {
  public:
   MapFieldBase()
       : arena_(NULL), repeated_field_(NULL), state_(STATE_MODIFIED_MAP) {}
+
+  // This constructor is for constant initialized global instances.
+  // It uses a linker initialized mutex, so it is not compatible with regular
+  // runtime instances.
+  // Except in MSVC, where we can't have a constinit mutex.
+  explicit constexpr MapFieldBase(ConstantInitialized)
+      : arena_(nullptr),
+        repeated_field_(nullptr),
+        mutex_(GOOGLE_PROTOBUF_LINKER_INITIALIZED),
+        state_(STATE_MODIFIED_MAP) {}
   explicit MapFieldBase(Arena* arena)
-      : arena_(arena), repeated_field_(NULL), state_(STATE_MODIFIED_MAP) {
-    // Mutex's destructor needs to be called explicitly to release resources
-    // acquired in its constructor.
-    if (arena) {
-      arena->OwnDestructor(&mutex_);
-    }
-  }
+      : arena_(arena), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {}
   virtual ~MapFieldBase();
 
   // Returns reference to internal repeated field. Data written using
@@ -298,6 +351,10 @@
   virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
   virtual bool InsertOrLookupMapValue(const MapKey& map_key,
                                       MapValueRef* val) = 0;
+  virtual bool LookupMapValue(const MapKey& map_key,
+                              MapValueConstRef* val) const = 0;
+  bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
+
   // Returns whether changes to the map are reflected in the repeated field.
   bool IsRepeatedFieldValid() const;
   // Insures operations after won't get executed before calling this.
@@ -308,7 +365,8 @@
   virtual void MapBegin(MapIterator* map_iter) const = 0;
   virtual void MapEnd(MapIterator* map_iter) const = 0;
   virtual void MergeFrom(const MapFieldBase& other) = 0;
-  virtual void Swap(MapFieldBase* other) = 0;
+  virtual void Swap(MapFieldBase* other);
+  virtual void UnsafeShallowSwap(MapFieldBase* other);
   // Sync Map with repeated field and returns the size of map.
   virtual int size() const = 0;
   virtual void Clear() = 0;
@@ -338,12 +396,33 @@
   // Tells MapFieldBase that there is new change to Map.
   void SetMapDirty();
 
-  // Tells MapFieldBase that there is new change to RepeatedPTrField.
+  // Tells MapFieldBase that there is new change to RepeatedPtrField.
   void SetRepeatedDirty();
 
   // Provides derived class the access to repeated field.
   void* MutableRepeatedPtrField() const;
 
+  void InternalSwap(MapFieldBase* other);
+
+  // Support thread sanitizer (tsan) by making const / mutable races
+  // more apparent.  If one thread calls MutableAccess() while another
+  // thread calls either ConstAccess() or MutableAccess(), on the same
+  // MapFieldBase-derived object, and there is no synchronization going
+  // on between them, tsan will alert.
+#if defined(__SANITIZE_THREAD__) || defined(THREAD_SANITIZER)
+  void ConstAccess() const { GOOGLE_CHECK_EQ(seq1_, seq2_); }
+  void MutableAccess() {
+    if (seq1_ & 1) {
+      seq2_ = ++seq1_;
+    } else {
+      seq1_ = ++seq2_;
+    }
+  }
+  unsigned int seq1_ = 0, seq2_ = 0;
+#else
+  void ConstAccess() const {}
+  void MutableAccess() {}
+#endif
   enum State {
     STATE_MODIFIED_MAP = 0,       // map has newly added data that has not been
                                   // synchronized to repeated field
@@ -364,6 +443,7 @@
   friend class ContendedMapCleanTest;
   friend class GeneratedMessageReflection;
   friend class MapFieldAccessor;
+  friend class ::PROTOBUF_NAMESPACE_ID::Reflection;
   friend class ::PROTOBUF_NAMESPACE_ID::DynamicMessage;
 
   // Virtual helper methods for MapIterator. MapIterator doesn't have the
@@ -395,6 +475,12 @@
 class TypeDefinedMapFieldBase : public MapFieldBase {
  public:
   TypeDefinedMapFieldBase() {}
+
+  // This constructor is for constant initialized global instances.
+  // It uses a linker initialized mutex, so it is not compatible with regular
+  // runtime instances.
+  explicit constexpr TypeDefinedMapFieldBase(ConstantInitialized tag)
+      : MapFieldBase(tag) {}
   explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
   ~TypeDefinedMapFieldBase() override {}
   void MapBegin(MapIterator* map_iter) const override;
@@ -420,11 +506,11 @@
 };
 
 // This class provides access to map field using generated api. It is used for
-// internal generated message implentation only. Users should never use this
+// internal generated message implementation only. Users should never use this
 // directly.
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value = 0>
+          WireFormatLite::FieldType kValueFieldType>
 class MapField : public TypeDefinedMapFieldBase<Key, T> {
   // Provide utilities to parse/serialize key/value.  Provide utilities to
   // manipulate internal stored type.
@@ -435,15 +521,14 @@
   typedef Derived EntryType;
 
   // Define abbreviation for parent MapFieldLite
-  typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType,
-                       default_enum_value>
+  typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType>
       MapFieldLiteType;
 
   // Enum needs to be handled differently from other types because it has
   // different exposed type in Map's api and repeated field's api. For
   // details see the comment in the implementation of
   // SyncMapWithRepeatedFieldNoLock.
-  static const bool kIsValueEnum = ValueTypeHandler::kIsEnum;
+  static constexpr bool kIsValueEnum = ValueTypeHandler::kIsEnum;
   typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
 
  public:
@@ -451,12 +536,21 @@
   typedef Map<Key, T> MapType;
 
   MapField() {}
+
+  // This constructor is for constant initialized global instances.
+  // It uses a linker initialized mutex, so it is not compatible with regular
+  // runtime instances.
+  explicit constexpr MapField(ConstantInitialized tag)
+      : TypeDefinedMapFieldBase<Key, T>(tag), impl_() {}
   explicit MapField(Arena* arena)
       : TypeDefinedMapFieldBase<Key, T>(arena), impl_(arena) {}
 
   // Implement MapFieldBase
   bool ContainsMapKey(const MapKey& map_key) const override;
   bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override;
+  bool LookupMapValue(const MapKey& map_key,
+                      MapValueConstRef* val) const override;
+  bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
   bool DeleteMapValue(const MapKey& map_key) override;
 
   const Map<Key, T>& GetMap() const override {
@@ -475,6 +569,8 @@
   void Clear() override;
   void MergeFrom(const MapFieldBase& other) override;
   void Swap(MapFieldBase* other) override;
+  void UnsafeShallowSwap(MapFieldBase* other) override;
+  void InternalSwap(MapField* other);
 
   // Used in the implementation of parsing. Caller should take the ownership iff
   // arena_ is NULL.
@@ -521,10 +617,9 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType key_wire_type,
-          WireFormatLite::FieldType value_wire_type, int default_enum_value>
+          WireFormatLite::FieldType value_wire_type>
 bool AllAreInitialized(
-    const MapField<Derived, Key, T, key_wire_type, value_wire_type,
-                   default_enum_value>& field) {
+    const MapField<Derived, Key, T, key_wire_type, value_wire_type>& field) {
   const auto& t = field.GetMap();
   for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
        ++it) {
@@ -535,12 +630,10 @@
 
 template <typename T, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-struct MapEntryToMapField<MapEntry<T, Key, Value, kKeyFieldType,
-                                   kValueFieldType, default_enum_value>> {
-  typedef MapField<T, Key, Value, kKeyFieldType, kValueFieldType,
-                   default_enum_value>
-      MapFieldType;
+          WireFormatLite::FieldType kValueFieldType>
+struct MapEntryToMapField<
+    MapEntry<T, Key, Value, kKeyFieldType, kValueFieldType>> {
+  typedef MapField<T, Key, Value, kKeyFieldType, kValueFieldType> MapFieldType;
 };
 
 class PROTOBUF_EXPORT DynamicMapField
@@ -553,9 +646,13 @@
   // Implement MapFieldBase
   bool ContainsMapKey(const MapKey& map_key) const override;
   bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override;
+  bool LookupMapValue(const MapKey& map_key,
+                      MapValueConstRef* val) const override;
+  bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
   bool DeleteMapValue(const MapKey& map_key) override;
   void MergeFrom(const MapFieldBase& other) override;
   void Swap(MapFieldBase* other) override;
+  void UnsafeShallowSwap(MapFieldBase* other) override { Swap(other); }
 
   const Map<MapKey, MapValueRef>& GetMap() const override;
   Map<MapKey, MapValueRef>* MutableMap() override;
@@ -579,10 +676,103 @@
 
 }  // namespace internal
 
-// MapValueRef points to a map value.
-class PROTOBUF_EXPORT MapValueRef {
+// MapValueConstRef points to a map value. Users can NOT modify
+// the map value.
+class PROTOBUF_EXPORT MapValueConstRef {
  public:
-  MapValueRef() : data_(NULL), type_(0) {}
+  MapValueConstRef() : data_(nullptr), type_() {}
+
+  int64 GetInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+               "MapValueConstRef::GetInt64Value");
+    return *reinterpret_cast<int64*>(data_);
+  }
+  uint64 GetUInt64Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+               "MapValueConstRef::GetUInt64Value");
+    return *reinterpret_cast<uint64*>(data_);
+  }
+  int32 GetInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+               "MapValueConstRef::GetInt32Value");
+    return *reinterpret_cast<int32*>(data_);
+  }
+  uint32 GetUInt32Value() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+               "MapValueConstRef::GetUInt32Value");
+    return *reinterpret_cast<uint32*>(data_);
+  }
+  bool GetBoolValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueConstRef::GetBoolValue");
+    return *reinterpret_cast<bool*>(data_);
+  }
+  int GetEnumValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue");
+    return *reinterpret_cast<int*>(data_);
+  }
+  const std::string& GetStringValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+               "MapValueConstRef::GetStringValue");
+    return *reinterpret_cast<std::string*>(data_);
+  }
+  float GetFloatValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
+               "MapValueConstRef::GetFloatValue");
+    return *reinterpret_cast<float*>(data_);
+  }
+  double GetDoubleValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
+               "MapValueConstRef::GetDoubleValue");
+    return *reinterpret_cast<double*>(data_);
+  }
+
+  const Message& GetMessageValue() const {
+    TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
+               "MapValueConstRef::GetMessageValue");
+    return *reinterpret_cast<Message*>(data_);
+  }
+
+ protected:
+  // data_ point to a map value. MapValueConstRef does not
+  // own this value.
+  void* data_;
+  // type_ is 0 or a valid FieldDescriptor::CppType.
+  // Use "CppType()" to indicate zero.
+  FieldDescriptor::CppType type_;
+
+  FieldDescriptor::CppType type() const {
+    if (type_ == FieldDescriptor::CppType() || data_ == nullptr) {
+      GOOGLE_LOG(FATAL)
+          << "Protocol Buffer map usage error:\n"
+          << "MapValueConstRef::type MapValueConstRef is not initialized.";
+    }
+    return type_;
+  }
+
+ private:
+  template <typename Derived, typename K, typename V,
+            internal::WireFormatLite::FieldType key_wire_type,
+            internal::WireFormatLite::FieldType value_wire_type>
+  friend class internal::MapField;
+  template <typename K, typename V>
+  friend class internal::TypeDefinedMapFieldBase;
+  friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
+  friend class Reflection;
+  friend class internal::DynamicMapField;
+
+  void SetType(FieldDescriptor::CppType type) { type_ = type; }
+  void SetValue(const void* val) { data_ = const_cast<void*>(val); }
+  void CopyFrom(const MapValueConstRef& other) {
+    type_ = other.type_;
+    data_ = other.data_;
+  }
+};
+
+// MapValueRef points to a map value. Users are able to modify
+// the map value.
+class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef {
+ public:
+  MapValueRef() {}
 
   void SetInt64Value(int64 value) {
     TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::SetInt64Value");
@@ -622,49 +812,6 @@
     *reinterpret_cast<double*>(data_) = value;
   }
 
-  int64 GetInt64Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::GetInt64Value");
-    return *reinterpret_cast<int64*>(data_);
-  }
-  uint64 GetUInt64Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapValueRef::GetUInt64Value");
-    return *reinterpret_cast<uint64*>(data_);
-  }
-  int32 GetInt32Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapValueRef::GetInt32Value");
-    return *reinterpret_cast<int32*>(data_);
-  }
-  uint32 GetUInt32Value() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapValueRef::GetUInt32Value");
-    return *reinterpret_cast<uint32*>(data_);
-  }
-  bool GetBoolValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueRef::GetBoolValue");
-    return *reinterpret_cast<bool*>(data_);
-  }
-  int GetEnumValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::GetEnumValue");
-    return *reinterpret_cast<int*>(data_);
-  }
-  const std::string& GetStringValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::GetStringValue");
-    return *reinterpret_cast<std::string*>(data_);
-  }
-  float GetFloatValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::GetFloatValue");
-    return *reinterpret_cast<float*>(data_);
-  }
-  double GetDoubleValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, "MapValueRef::GetDoubleValue");
-    return *reinterpret_cast<double*>(data_);
-  }
-
-  const Message& GetMessageValue() const {
-    TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
-               "MapValueRef::GetMessageValue");
-    return *reinterpret_cast<Message*>(data_);
-  }
-
   Message* MutableMessageValue() {
     TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
                "MapValueRef::MutableMessageValue");
@@ -672,31 +819,8 @@
   }
 
  private:
-  template <typename Derived, typename K, typename V,
-            internal::WireFormatLite::FieldType key_wire_type,
-            internal::WireFormatLite::FieldType value_wire_type,
-            int default_enum_value>
-  friend class internal::MapField;
-  template <typename K, typename V>
-  friend class internal::TypeDefinedMapFieldBase;
-  friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
-  friend class Reflection;
   friend class internal::DynamicMapField;
 
-  void SetType(FieldDescriptor::CppType type) { type_ = type; }
-
-  FieldDescriptor::CppType type() const {
-    if (type_ == 0 || data_ == NULL) {
-      GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
-                 << "MapValueRef::type MapValueRef is not initialized.";
-    }
-    return (FieldDescriptor::CppType)type_;
-  }
-  void SetValue(const void* val) { data_ = const_cast<void*>(val); }
-  void CopyFrom(const MapValueRef& other) {
-    type_ = other.type_;
-    data_ = other.data_;
-  }
   // Only used in DynamicMapField
   void DeleteData() {
     switch (type_) {
@@ -718,11 +842,6 @@
 #undef HANDLE_TYPE
     }
   }
-  // data_ point to a map value. MapValueRef does not
-  // own this value.
-  void* data_;
-  // type_ is 0 or a valid FieldDescriptor::CppType.
-  int type_;
 };
 
 #undef TYPE_CHECK
@@ -777,8 +896,7 @@
   friend class internal::DynamicMapField;
   template <typename Derived, typename Key, typename T,
             internal::WireFormatLite::FieldType kKeyFieldType,
-            internal::WireFormatLite::FieldType kValueFieldType,
-            int default_enum_value>
+            internal::WireFormatLite::FieldType kValueFieldType>
   friend class internal::MapField;
 
   // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
@@ -796,40 +914,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
-template <>
-struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
-  size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const {
-    switch (map_key.type()) {
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE:
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT:
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM:
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE:
-        GOOGLE_LOG(FATAL) << "Unsupported";
-        break;
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING:
-        return hash<std::string>()(map_key.GetStringValue());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64:
-        return hash<int64>()(map_key.GetInt64Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32:
-        return hash<int32>()(map_key.GetInt32Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64:
-        return hash<uint64>()(map_key.GetUInt64Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32:
-        return hash<uint32>()(map_key.GetUInt32Value());
-      case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL:
-        return hash<bool>()(map_key.GetBoolValue());
-    }
-    GOOGLE_LOG(FATAL) << "Can't get here.";
-    return 0;
-  }
-  bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1,
-                  const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const {
-    return map_key1 < map_key2;
-  }
-};
-GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
-
 #include <google/protobuf/port_undef.inc>
 
 #endif  // GOOGLE_PROTOBUF_MAP_FIELD_H__
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 7baaa5f..a42b4fc 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -164,18 +164,16 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-int MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-             default_enum_value>::size() const {
+          WireFormatLite::FieldType kValueFieldType>
+int MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::size() const {
   MapFieldBase::SyncMapWithRepeatedField();
   return static_cast<int>(impl_.GetMap().size());
 }
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::Clear() {
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Clear() {
   if (this->MapFieldBase::repeated_field_ != nullptr) {
     RepeatedPtrField<EntryType>* repeated_field =
         reinterpret_cast<RepeatedPtrField<EntryType>*>(
@@ -192,9 +190,9 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::SetMapIteratorValue(MapIterator* map_iter)
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType,
+              kValueFieldType>::SetMapIteratorValue(MapIterator* map_iter)
     const {
   const Map<Key, T>& map = impl_.GetMap();
   typename Map<Key, T>::const_iterator iter =
@@ -206,9 +204,9 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::ContainsMapKey(const MapKey& map_key) const {
+          WireFormatLite::FieldType kValueFieldType>
+bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::ContainsMapKey(
+    const MapKey& map_key) const {
   const Map<Key, T>& map = impl_.GetMap();
   const Key& key = UnwrapMapKey<Key>(map_key);
   typename Map<Key, T>::const_iterator iter = map.find(key);
@@ -217,10 +215,10 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::InsertOrLookupMapValue(const MapKey& map_key,
-                                                          MapValueRef* val) {
+          WireFormatLite::FieldType kValueFieldType>
+bool MapField<Derived, Key, T, kKeyFieldType,
+              kValueFieldType>::InsertOrLookupMapValue(const MapKey& map_key,
+                                                       MapValueRef* val) {
   // Always use mutable map because users may change the map value by
   // MapValueRef.
   Map<Key, T>* map = MutableMap();
@@ -238,18 +236,35 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::DeleteMapValue(const MapKey& map_key) {
+          WireFormatLite::FieldType kValueFieldType>
+bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::LookupMapValue(
+    const MapKey& map_key, MapValueConstRef* val) const {
+  const Map<Key, T>& map = GetMap();
+  const Key& key = UnwrapMapKey<Key>(map_key);
+  typename Map<Key, T>::const_iterator iter = map.find(key);
+  if (map.end() == iter) {
+    return false;
+  }
+  // Key is already in the map. Make sure (*map)[key] is not called.
+  // [] may reorder the map and iterators.
+  val->SetValue(&(iter->second));
+  return true;
+}
+
+template <typename Derived, typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType>
+bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::DeleteMapValue(
+    const MapKey& map_key) {
   const Key& key = UnwrapMapKey<Key>(map_key);
   return MutableMap()->erase(key);
 }
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::MergeFrom(const MapFieldBase& other) {
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::MergeFrom(
+    const MapFieldBase& other) {
   MapFieldBase::SyncMapWithRepeatedField();
   const MapField& other_field = static_cast<const MapField&>(other);
   other_field.SyncMapWithRepeatedField();
@@ -259,32 +274,40 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::Swap(MapFieldBase* other) {
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Swap(
+    MapFieldBase* other) {
+  MapFieldBase::Swap(other);
   MapField* other_field = down_cast<MapField*>(other);
-  std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_);
   impl_.Swap(&other_field->impl_);
-  // a relaxed swap of the atomic
-  auto other_state = other_field->state_.load(std::memory_order_relaxed);
-  auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed);
-  other_field->state_.store(this_state, std::memory_order_relaxed);
-  this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed);
 }
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType,
+              kValueFieldType>::UnsafeShallowSwap(MapFieldBase* other) {
+  InternalSwap(down_cast<MapField*>(other));
+}
+
+template <typename Derived, typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::InternalSwap(
+    MapField* other) {
+  MapFieldBase::InternalSwap(other);
+  impl_.InternalSwap(&other->impl_);
+}
+
+template <typename Derived, typename Key, typename T,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType,
+              kValueFieldType>::SyncRepeatedFieldWithMapNoLock() const {
   if (this->MapFieldBase::repeated_field_ == NULL) {
-    if (this->MapFieldBase::arena_ == NULL) {
-      this->MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
-    } else {
-      this->MapFieldBase::repeated_field_ =
-          Arena::CreateMessage<RepeatedPtrField<Message> >(
-              this->MapFieldBase::arena_);
-    }
+    this->MapFieldBase::repeated_field_ =
+        Arena::CreateMessage<RepeatedPtrField<Message> >(
+            this->MapFieldBase::arena_);
   }
   const Map<Key, T>& map = impl_.GetMap();
   RepeatedPtrField<EntryType>* repeated_field =
@@ -311,9 +334,9 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-              default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
+          WireFormatLite::FieldType kValueFieldType>
+void MapField<Derived, Key, T, kKeyFieldType,
+              kValueFieldType>::SyncMapWithRepeatedFieldNoLock() const {
   Map<Key, T>* map = const_cast<MapField*>(this)->impl_.MutableMap();
   RepeatedPtrField<EntryType>* repeated_field =
       reinterpret_cast<RepeatedPtrField<EntryType>*>(
@@ -334,20 +357,15 @@
 
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-size_t MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
-                default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
+          WireFormatLite::FieldType kValueFieldType>
+size_t MapField<Derived, Key, T, kKeyFieldType,
+                kValueFieldType>::SpaceUsedExcludingSelfNoLock() const {
   size_t size = 0;
   if (this->MapFieldBase::repeated_field_ != NULL) {
     size += this->MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong();
   }
-  Map<Key, T>* map = const_cast<MapField*>(this)->impl_.MutableMap();
-  size += sizeof(*map);
-  for (typename Map<Key, T>::iterator it = map->begin(); it != map->end();
-       ++it) {
-    size += KeyTypeHandler::SpaceUsedInMapLong(it->first);
-    size += ValueTypeHandler::SpaceUsedInMapLong(it->second);
-  }
+  size += impl_.GetMap().SpaceUsedExcludingSelfLong();
+
   return size;
 }
 }  // namespace internal
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
index d641d17..46658d4 100644
--- a/src/google/protobuf/map_field_lite.h
+++ b/src/google/protobuf/map_field_lite.h
@@ -50,11 +50,11 @@
 namespace internal {
 
 // This class provides access to map field using generated api. It is used for
-// internal generated message implentation only. Users should never use this
+// internal generated message implementation only. Users should never use this
 // directly.
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType key_wire_type,
-          WireFormatLite::FieldType value_wire_type, int default_enum_value = 0>
+          WireFormatLite::FieldType value_wire_type>
 class MapFieldLite {
   // Define message type for internal repeated field.
   typedef Derived EntryType;
@@ -63,9 +63,9 @@
   typedef Map<Key, T> MapType;
   typedef EntryType EntryTypeTrait;
 
-  MapFieldLite() { SetDefaultEnumValue(); }
+  constexpr MapFieldLite() {}
 
-  explicit MapFieldLite(Arena* arena) : map_(arena) { SetDefaultEnumValue(); }
+  explicit MapFieldLite(Arena* arena) : map_(arena) {}
 
   // Accessors
   const Map<Key, T>& GetMap() const { return map_; }
@@ -81,16 +81,12 @@
     }
   }
   void Swap(MapFieldLite* other) { map_.swap(other->map_); }
-
-  // Set default enum value only for proto2 map field whose value is enum type.
-  void SetDefaultEnumValue() {
-    MutableMap()->SetDefaultEnumValue(default_enum_value);
-  }
+  void InternalSwap(MapFieldLite* other) { map_.InternalSwap(other->map_); }
 
   // Used in the implementation of parsing. Caller should take the ownership iff
   // arena_ is NULL.
   EntryType* NewEntry() const {
-    return Arena::CreateMessage<EntryType>(map_.arena_);
+    return Arena::CreateMessage<EntryType>(map_.arena());
   }
   // Used in the implementation of serializing enum value type. Caller should
   // take the ownership iff arena_ is NULL.
@@ -154,10 +150,9 @@
 // We want the C++ compiler to inline this or not as it sees fit.
 template <typename Derived, typename Key, typename T,
           WireFormatLite::FieldType key_wire_type,
-          WireFormatLite::FieldType value_wire_type, int default_enum_value>
-bool AllAreInitialized(
-    const MapFieldLite<Derived, Key, T, key_wire_type, value_wire_type,
-                       default_enum_value>& field) {
+          WireFormatLite::FieldType value_wire_type>
+bool AllAreInitialized(const MapFieldLite<Derived, Key, T, key_wire_type,
+                                          value_wire_type>& field) {
   const auto& t = field.GetMap();
   for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
        ++it) {
@@ -171,13 +166,12 @@
 
 template <typename T, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
-          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
-struct MapEntryToMapField<MapEntryLite<T, Key, Value, kKeyFieldType,
-                                       kValueFieldType, default_enum_value>> {
-  typedef MapFieldLite<MapEntryLite<T, Key, Value, kKeyFieldType,
-                                    kValueFieldType, default_enum_value>,
-                       Key, Value, kKeyFieldType, kValueFieldType,
-                       default_enum_value>
+          WireFormatLite::FieldType kValueFieldType>
+struct MapEntryToMapField<
+    MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>> {
+  typedef MapFieldLite<
+      MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>, Key, Value,
+      kKeyFieldType, kValueFieldType>
       MapFieldType;
 };
 
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 05f83e2..982a34f 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -45,6 +45,9 @@
 #include <google/protobuf/repeated_field.h>
 #include <gtest/gtest.h>
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 
@@ -77,6 +80,10 @@
                               MapValueRef* val) override {
     return false;
   }
+  bool LookupMapValue(const MapKey& map_key,
+                      MapValueConstRef* val) const override {
+    return false;
+  }
   bool DeleteMapValue(const MapKey& map_key) override { return false; }
   bool EqualIterator(const MapIterator& a,
                      const MapIterator& b) const override {
@@ -93,25 +100,32 @@
   void CopyIterator(MapIterator* this_iterator,
                     const MapIterator& other_iterator) const override {}
   void IncreaseIterator(MapIterator* map_iter) const override {}
+
+  Arena* GetArenaForInternalRepeatedField() {
+    auto* repeated_field = MutableRepeatedField();
+    return repeated_field->GetArena();
+  }
 };
 
-class MapFieldBasePrimitiveTest : public ::testing::Test {
+class MapFieldBasePrimitiveTest : public testing::TestWithParam<bool> {
  protected:
   typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
   typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
-                   WireFormatLite::TYPE_INT32, false>
+                   WireFormatLite::TYPE_INT32>
       MapFieldType;
 
-  MapFieldBasePrimitiveTest() {
+  MapFieldBasePrimitiveTest()
+      : arena_(GetParam() ? new Arena() : nullptr),
+        map_field_(arena_.get()),
+        map_field_base_(map_field_.get()) {
     // Get descriptors
     map_descriptor_ = unittest::TestMap::descriptor()
                           ->FindFieldByName("map_int32_int32")
                           ->message_type();
-    key_descriptor_ = map_descriptor_->FindFieldByName("key");
-    value_descriptor_ = map_descriptor_->FindFieldByName("value");
+    key_descriptor_ = map_descriptor_->map_key();
+    value_descriptor_ = map_descriptor_->map_value();
 
     // Build map field
-    map_field_.reset(new MapFieldType);
     map_field_base_ = map_field_.get();
     map_ = map_field_->MutableMap();
     initial_value_map_[0] = 100;
@@ -120,7 +134,8 @@
     EXPECT_EQ(2, map_->size());
   }
 
-  std::unique_ptr<MapFieldType> map_field_;
+  std::unique_ptr<Arena> arena_;
+  ArenaHolder<MapFieldType> map_field_;
   MapFieldBase* map_field_base_;
   Map<int32, int32>* map_;
   const Descriptor* map_descriptor_;
@@ -129,11 +144,15 @@
   std::map<int32, int32> initial_value_map_;  // copy of initial values inserted
 };
 
-TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
+INSTANTIATE_TEST_SUITE_P(MapFieldBasePrimitiveTestInstance,
+                         MapFieldBasePrimitiveTest,
+                         testing::Values(true, false));
+
+TEST_P(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
   EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
 }
 
-TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
+TEST_P(MapFieldBasePrimitiveTest, GetRepeatedField) {
   const RepeatedPtrField<Message>& repeated =
       reinterpret_cast<const RepeatedPtrField<Message>&>(
           map_field_base_->GetRepeatedField());
@@ -146,7 +165,7 @@
   }
 }
 
-TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
+TEST_P(MapFieldBasePrimitiveTest, MutableRepeatedField) {
   RepeatedPtrField<Message>* repeated =
       reinterpret_cast<RepeatedPtrField<Message>*>(
           map_field_base_->MutableRepeatedField());
@@ -159,7 +178,7 @@
   }
 }
 
-TEST_F(MapFieldBasePrimitiveTest, Arena) {
+TEST_P(MapFieldBasePrimitiveTest, Arena) {
   // Allocate a large initial block to avoid mallocs during hooked test.
   std::vector<char> arena_block(128 * 1024);
   ArenaOptions options;
@@ -191,25 +210,34 @@
 
     // Trigger conversion to repeated field.
     EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
+
+    EXPECT_EQ(map_field->GetArenaForInternalRepeatedField(), &arena);
   }
 }
 
+TEST_P(MapFieldBasePrimitiveTest, EnforceNoArena) {
+  std::unique_ptr<MapFieldBaseStub> map_field(
+      Arena::CreateMessage<MapFieldBaseStub>(nullptr));
+  EXPECT_EQ(map_field->GetArenaForInternalRepeatedField(), nullptr);
+}
+
 namespace {
 enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
 }  // anonymous namespace
 
-class MapFieldStateTest : public testing::TestWithParam<State> {
- public:
+class MapFieldStateTest
+    : public testing::TestWithParam<std::tuple<State, bool>> {
  protected:
   typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
   typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
-                   WireFormatLite::TYPE_INT32, false>
+                   WireFormatLite::TYPE_INT32>
       MapFieldType;
-  MapFieldStateTest() : state_(GetParam()) {
+  MapFieldStateTest()
+      : arena_(std::get<1>(GetParam()) ? new Arena() : nullptr),
+        map_field_(arena_.get()),
+        map_field_base_(map_field_.get()),
+        state_(std::get<0>(GetParam())) {
     // Build map field
-    map_field_.reset(new MapFieldType());
-    map_field_base_ = map_field_.get();
-
     Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
     switch (state_) {
       case CLEAN:
@@ -290,13 +318,16 @@
     }
   }
 
-  std::unique_ptr<MapFieldType> map_field_;
+  std::unique_ptr<Arena> arena_;
+  ArenaHolder<MapFieldType> map_field_;
   MapFieldBase* map_field_base_;
   State state_;
 };
 
 INSTANTIATE_TEST_SUITE_P(MapFieldStateTestInstance, MapFieldStateTest,
-                         ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
+                         testing::Combine(testing::Values(CLEAN, MAP_DIRTY,
+                                                          REPEATED_DIRTY),
+                                          testing::Values(true, false)));
 
 TEST_P(MapFieldStateTest, GetMap) {
   map_field_->GetMap();
@@ -317,10 +348,10 @@
 }
 
 TEST_P(MapFieldStateTest, MergeFromClean) {
-  MapFieldType other;
-  AddOneStillClean(&other);
+  ArenaHolder<MapFieldType> other(arena_.get());
+  AddOneStillClean(other.get());
 
-  map_field_->MergeFrom(other);
+  map_field_->MergeFrom(*other);
 
   if (state_ != MAP_DIRTY) {
     Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
@@ -328,14 +359,14 @@
     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
   }
 
-  Expect(&other, CLEAN, 1, 1, false);
+  Expect(other.get(), CLEAN, 1, 1, false);
 }
 
 TEST_P(MapFieldStateTest, MergeFromMapDirty) {
-  MapFieldType other;
-  MakeMapDirty(&other);
+  ArenaHolder<MapFieldType> other(arena_.get());
+  MakeMapDirty(other.get());
 
-  map_field_->MergeFrom(other);
+  map_field_->MergeFrom(*other);
 
   if (state_ != MAP_DIRTY) {
     Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
@@ -343,14 +374,14 @@
     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
   }
 
-  Expect(&other, MAP_DIRTY, 1, 0, true);
+  Expect(other.get(), MAP_DIRTY, 1, 0, true);
 }
 
 TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
-  MapFieldType other;
-  MakeRepeatedDirty(&other);
+  ArenaHolder<MapFieldType> other(arena_.get());
+  MakeRepeatedDirty(other.get());
 
-  map_field_->MergeFrom(other);
+  map_field_->MergeFrom(*other);
 
   if (state_ != MAP_DIRTY) {
     Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
@@ -358,26 +389,26 @@
     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
   }
 
-  Expect(&other, CLEAN, 1, 1, false);
+  Expect(other.get(), CLEAN, 1, 1, false);
 }
 
 TEST_P(MapFieldStateTest, SwapClean) {
-  MapFieldType other;
-  AddOneStillClean(&other);
+  ArenaHolder<MapFieldType> other(arena_.get());
+  AddOneStillClean(other.get());
 
-  map_field_->Swap(&other);
+  map_field_->Swap(other.get());
 
   Expect(map_field_.get(), CLEAN, 1, 1, false);
 
   switch (state_) {
     case CLEAN:
-      Expect(&other, CLEAN, 1, 1, false);
+      Expect(other.get(), CLEAN, 1, 1, false);
       break;
     case MAP_DIRTY:
-      Expect(&other, MAP_DIRTY, 1, 0, true);
+      Expect(other.get(), MAP_DIRTY, 1, 0, true);
       break;
     case REPEATED_DIRTY:
-      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      Expect(other.get(), REPEATED_DIRTY, 0, 1, false);
       break;
     default:
       break;
@@ -385,22 +416,22 @@
 }
 
 TEST_P(MapFieldStateTest, SwapMapDirty) {
-  MapFieldType other;
-  MakeMapDirty(&other);
+  ArenaHolder<MapFieldType> other(arena_.get());
+  MakeMapDirty(other.get());
 
-  map_field_->Swap(&other);
+  map_field_->Swap(other.get());
 
   Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
 
   switch (state_) {
     case CLEAN:
-      Expect(&other, CLEAN, 1, 1, false);
+      Expect(other.get(), CLEAN, 1, 1, false);
       break;
     case MAP_DIRTY:
-      Expect(&other, MAP_DIRTY, 1, 0, true);
+      Expect(other.get(), MAP_DIRTY, 1, 0, true);
       break;
     case REPEATED_DIRTY:
-      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      Expect(other.get(), REPEATED_DIRTY, 0, 1, false);
       break;
     default:
       break;
@@ -408,22 +439,22 @@
 }
 
 TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
-  MapFieldType other;
-  MakeRepeatedDirty(&other);
+  ArenaHolder<MapFieldType> other(arena_.get());
+  MakeRepeatedDirty(other.get());
 
-  map_field_->Swap(&other);
+  map_field_->Swap(other.get());
 
   Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
 
   switch (state_) {
     case CLEAN:
-      Expect(&other, CLEAN, 1, 1, false);
+      Expect(other.get(), CLEAN, 1, 1, false);
       break;
     case MAP_DIRTY:
-      Expect(&other, MAP_DIRTY, 1, 0, true);
+      Expect(other.get(), MAP_DIRTY, 1, 0, true);
       break;
     case REPEATED_DIRTY:
-      Expect(&other, REPEATED_DIRTY, 0, 1, false);
+      Expect(other.get(), REPEATED_DIRTY, 0, 1, false);
       break;
     default:
       break;
@@ -474,6 +505,22 @@
   }
 }
 
+class MyMapField
+    : public MapField<unittest::TestMap_MapInt32Int32Entry_DoNotUse, int32,
+                      int32, internal::WireFormatLite::TYPE_INT32,
+                      internal::WireFormatLite::TYPE_INT32> {
+ public:
+  constexpr MyMapField()
+      : MyMapField::MapField(internal::ConstantInitialized{}) {}
+};
+
+TEST(MapFieldTest, ConstInit) {
+  // This tests that `MapField` and all its base classes can be constant
+  // initialized.
+  PROTOBUF_CONSTINIT static MyMapField field;  // NOLINT
+  EXPECT_EQ(field.size(), 0);
+}
+
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto
index 0135fff..cc00dee 100644
--- a/src/google/protobuf/map_lite_unittest.proto
+++ b/src/google/protobuf/map_lite_unittest.proto
@@ -30,55 +30,52 @@
 
 syntax = "proto2";
 
+package protobuf_unittest;
+
+import "google/protobuf/unittest_lite.proto";
+
 option cc_enable_arenas = true;
 option optimize_for = LITE_RUNTIME;
 
-import "google/protobuf/unittest_lite.proto";
-import "google/protobuf/unittest_no_arena_lite.proto";
-
-package protobuf_unittest;
-
 message TestMapLite {
-  map<int32   , int32   > map_int32_int32       = 1;
-  map<int64   , int64   > map_int64_int64       = 2;
-  map<uint32  , uint32  > map_uint32_uint32     = 3;
-  map<uint64  , uint64  > map_uint64_uint64     = 4;
-  map<sint32  , sint32  > map_sint32_sint32     = 5;
-  map<sint64  , sint64  > map_sint64_sint64     = 6;
-  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
-  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<int32, int32> map_int32_int32 = 1;
+  map<int64, int64> map_int64_int64 = 2;
+  map<uint32, uint32> map_uint32_uint32 = 3;
+  map<uint64, uint64> map_uint64_uint64 = 4;
+  map<sint32, sint32> map_sint32_sint32 = 5;
+  map<sint64, sint64> map_sint64_sint64 = 6;
+  map<fixed32, fixed32> map_fixed32_fixed32 = 7;
+  map<fixed64, fixed64> map_fixed64_fixed64 = 8;
   map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
   map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
-  map<int32   , float   > map_int32_float       = 11;
-  map<int32   , double  > map_int32_double      = 12;
-  map<bool    , bool    > map_bool_bool         = 13;
-  map<string  , string  > map_string_string     = 14;
-  map<int32   , bytes   > map_int32_bytes       = 15;
-  map<int32   , MapEnumLite> map_int32_enum     = 16;
-  map<int32   , ForeignMessageLite> map_int32_foreign_message = 17;
+  map<int32, float> map_int32_float = 11;
+  map<int32, double> map_int32_double = 12;
+  map<bool, bool> map_bool_bool = 13;
+  map<string, string> map_string_string = 14;
+  map<int32, bytes> map_int32_bytes = 15;
+  map<int32, MapEnumLite> map_int32_enum = 16;
+  map<int32, ForeignMessageLite> map_int32_foreign_message = 17;
   map<int32, int32> teboring = 18;
 }
 
 message TestArenaMapLite {
-  map<int32   , int32   > map_int32_int32       = 1;
-  map<int64   , int64   > map_int64_int64       = 2;
-  map<uint32  , uint32  > map_uint32_uint32     = 3;
-  map<uint64  , uint64  > map_uint64_uint64     = 4;
-  map<sint32  , sint32  > map_sint32_sint32     = 5;
-  map<sint64  , sint64  > map_sint64_sint64     = 6;
-  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
-  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<int32, int32> map_int32_int32 = 1;
+  map<int64, int64> map_int64_int64 = 2;
+  map<uint32, uint32> map_uint32_uint32 = 3;
+  map<uint64, uint64> map_uint64_uint64 = 4;
+  map<sint32, sint32> map_sint32_sint32 = 5;
+  map<sint64, sint64> map_sint64_sint64 = 6;
+  map<fixed32, fixed32> map_fixed32_fixed32 = 7;
+  map<fixed64, fixed64> map_fixed64_fixed64 = 8;
   map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
   map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
-  map<int32   , float   > map_int32_float       = 11;
-  map<int32   , double  > map_int32_double      = 12;
-  map<bool    , bool    > map_bool_bool         = 13;
-  map<string  , string  > map_string_string     = 14;
-  map<int32   , bytes   > map_int32_bytes       = 15;
-  map<int32   , MapEnumLite> map_int32_enum     = 16;
-  map<int32   , ForeignMessageArenaLite> map_int32_foreign_message = 17;
-  map<int32, .protobuf_unittest_no_arena.ForeignMessageLite>
-      map_int32_foreign_message_no_arena = 18;
+  map<int32, float> map_int32_float = 11;
+  map<int32, double> map_int32_double = 12;
+  map<bool, bool> map_bool_bool = 13;
+  map<string, string> map_string_string = 14;
+  map<int32, bytes> map_int32_bytes = 15;
+  map<int32, MapEnumLite> map_int32_enum = 16;
+  map<int32, ForeignMessageArenaLite> map_int32_foreign_message = 17;
 }
 
 // Test embedded message with required fields
@@ -107,9 +104,9 @@
 }
 
 enum Proto2MapEnumPlusExtraLite {
-  E_PROTO2_MAP_ENUM_FOO_LITE   = 0;
-  E_PROTO2_MAP_ENUM_BAR_LITE   = 1;
-  E_PROTO2_MAP_ENUM_BAZ_LITE   = 2;
+  E_PROTO2_MAP_ENUM_FOO_LITE = 0;
+  E_PROTO2_MAP_ENUM_BAR_LITE = 1;
+  E_PROTO2_MAP_ENUM_BAZ_LITE = 2;
   E_PROTO2_MAP_ENUM_EXTRA_LITE = 3;
 }
 
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 01512a0..1414fc3 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -80,6 +80,7 @@
 #include <google/protobuf/stubs/substitute.h>
 
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -194,6 +195,62 @@
   ExpectSingleElement(key, value2);
 }
 
+struct MoveTestKey {
+  MoveTestKey(int data, int* copies) : data(data), copies(copies) {}
+
+  MoveTestKey(const MoveTestKey& other)
+      : data(other.data), copies(other.copies) {
+    ++*copies;
+  }
+
+  MoveTestKey(MoveTestKey&& other) noexcept
+      : data(other.data), copies(other.copies) {}
+
+  friend bool operator==(const MoveTestKey& lhs, const MoveTestKey& rhs) {
+    return lhs.data == rhs.data;
+  }
+  friend bool operator<(const MoveTestKey& lhs, const MoveTestKey& rhs) {
+    return lhs.data < rhs.data;
+  }
+
+  int data;
+  int* copies;
+};
+
+}  // namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+namespace std {
+
+template <>  // NOLINT
+struct hash<google::protobuf::internal::MoveTestKey> {
+  size_t operator()(const google::protobuf::internal::MoveTestKey& key) const {
+    return hash<int>{}(key.data);
+  }
+};
+}  // namespace std
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+TEST_F(MapImplTest, OperatorBracketRValue) {
+  Arena arena;
+  for (Arena* arena_to_use : {&arena, static_cast<Arena*>(nullptr)}) {
+    int copies = 0;
+    Map<MoveTestKey, int> map(arena_to_use);
+    MoveTestKey key1(1, &copies);
+    EXPECT_EQ(copies, 0);
+    map[key1] = 0;
+    EXPECT_EQ(copies, 1);
+    map[MoveTestKey(2, &copies)] = 2;
+    EXPECT_EQ(copies, 1);
+  }
+}
+
 TEST_F(MapImplTest, OperatorBracketNonExist) {
   int32 key = 0;
   int32 default_value = 0;
@@ -234,9 +291,10 @@
                "  Actual   : int64");
 
   MapValueRef value;
-  EXPECT_DEATH(value.SetFloatValue(0.1),
-               "Protocol Buffer map usage error:\n"
-               "MapValueRef::type MapValueRef is not initialized.");
+  EXPECT_DEATH(
+      value.SetFloatValue(0.1),
+      "Protocol Buffer map usage error:\n"
+      "MapValue[Const]*Ref::type MapValue[Const]*Ref is not initialized.");
 }
 
 #endif  // PROTOBUF_HAS_DEATH_TEST
@@ -980,6 +1038,154 @@
   EXPECT_EQ(it1.GetKey().GetInt32Value(), it2.GetKey().GetInt32Value());
 }
 
+TEST_F(MapImplTest, SpaceUsed) {
+  constexpr size_t kMinCap = 8;
+
+  Map<int32, int32> m;
+  // An newly constructed map should have no space used.
+  EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), 0);
+
+  size_t capacity = kMinCap;
+  for (int i = 0; i < 100; ++i) {
+    m[i];
+    static constexpr double kMaxLoadFactor = .75;
+    if (m.size() >= capacity * kMaxLoadFactor) {
+      capacity *= 2;
+    }
+    EXPECT_EQ(m.SpaceUsedExcludingSelfLong(),
+              sizeof(void*) * capacity +
+                  m.size() * sizeof(std::pair<std::pair<int32, int32>, void*>));
+  }
+
+  // Test string, and non-scalar keys.
+  Map<std::string, int32> m2;
+  std::string str = "Some arbitrarily large string";
+  m2[str] = 1;
+  EXPECT_EQ(m2.SpaceUsedExcludingSelfLong(),
+            sizeof(void*) * kMinCap +
+                sizeof(std::pair<std::pair<std::string, int32>, void*>) +
+                internal::StringSpaceUsedExcludingSelfLong(str));
+
+  // Test messages, and non-scalar values.
+  Map<int32, TestAllTypes> m3;
+  m3[0].set_optional_string(str);
+  EXPECT_EQ(m3.SpaceUsedExcludingSelfLong(),
+            sizeof(void*) * kMinCap +
+                sizeof(std::pair<std::pair<int32, TestAllTypes>, void*>) +
+                m3[0].SpaceUsedLong() - sizeof(m3[0]));
+}
+
+// Attempts to verify that a map with keys a and b has a random ordering. This
+// function returns true if it succeeds in observing both possible orderings.
+bool MapOrderingIsRandom(int a, int b) {
+  bool saw_a_first = false;
+  bool saw_b_first = false;
+
+  for (int i = 0; i < 50; ++i) {
+    Map<int32, int32> m;
+    m[a] = 0;
+    m[b] = 0;
+    int32 first_element = m.begin()->first;
+    if (first_element == a) saw_a_first = true;
+    if (first_element == b) saw_b_first = true;
+    if (saw_a_first && saw_b_first) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// This test verifies that the iteration order is reasonably random even for
+// small maps. Currently we only have sufficient randomness for debug builds and
+// builds where we can use the RDTSC instruction, so we only test for those
+// builds.
+#if defined(__x86_64__) && defined(__GNUC__) && \
+    !defined(GOOGLE_PROTOBUF_NO_RDTSC)
+TEST_F(MapImplTest, RandomOrdering) {
+  for (int i = 0; i < 10; ++i) {
+    for (int j = i + 1; j < 10; ++j) {
+      EXPECT_TRUE(MapOrderingIsRandom(i, j))
+          << "Map with keys " << i << " and " << j
+          << " has deterministic ordering";
+    }
+  }
+}
+#endif
+
+template <typename Key>
+void TestTransparent(const Key& key, const Key& miss_key) {
+  Map<std::string, int> m;
+  const auto& cm = m;
+
+  m.insert({"ABC", 1});
+
+  const auto abc_it = m.begin();
+
+  m.insert({"DEF", 2});
+
+  using testing::Pair;
+  using testing::UnorderedElementsAre;
+
+  EXPECT_EQ(m.at(key), 1);
+  EXPECT_EQ(cm.at(key), 1);
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  EXPECT_DEATH(m.at(miss_key), "");
+  EXPECT_DEATH(cm.at(miss_key), "");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+  EXPECT_EQ(m.count(key), 1);
+  EXPECT_EQ(cm.count(key), 1);
+  EXPECT_EQ(m.count(miss_key), 0);
+  EXPECT_EQ(cm.count(miss_key), 0);
+
+  EXPECT_EQ(m.find(key), abc_it);
+  EXPECT_EQ(cm.find(key), abc_it);
+  EXPECT_EQ(m.find(miss_key), m.end());
+  EXPECT_EQ(cm.find(miss_key), cm.end());
+
+  EXPECT_TRUE(m.contains(key));
+  EXPECT_TRUE(cm.contains(key));
+  EXPECT_FALSE(m.contains(miss_key));
+  EXPECT_FALSE(cm.contains(miss_key));
+
+  EXPECT_THAT(m.equal_range(key), Pair(abc_it, std::next(abc_it)));
+  EXPECT_THAT(cm.equal_range(key), Pair(abc_it, std::next(abc_it)));
+  EXPECT_THAT(m.equal_range(miss_key), Pair(m.end(), m.end()));
+  EXPECT_THAT(cm.equal_range(miss_key), Pair(m.end(), m.end()));
+
+  EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 1), Pair("DEF", 2)));
+  EXPECT_EQ(m.erase(key), 1);
+  EXPECT_THAT(m, UnorderedElementsAre(Pair("DEF", 2)));
+  EXPECT_EQ(m.erase(key), 0);
+  EXPECT_EQ(m.erase(miss_key), 0);
+  EXPECT_THAT(m, UnorderedElementsAre(Pair("DEF", 2)));
+
+  m[key];
+  EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 0), Pair("DEF", 2)));
+  m[key] = 1;
+  EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 1), Pair("DEF", 2)));
+}
+
+TEST_F(MapImplTest, TransparentLookupForString) {
+  TestTransparent("ABC", "LKJ");
+  TestTransparent(std::string("ABC"), std::string("LKJ"));
+#if defined(__cpp_lib_string_view)
+  TestTransparent(std::string_view("ABC"), std::string_view("LKJ"));
+#endif  // defined(__cpp_lib_string_view)
+
+  // std::reference_wrapper
+  std::string abc = "ABC", lkj = "LKJ";
+  TestTransparent(std::ref(abc), std::ref(lkj));
+  TestTransparent(std::cref(abc), std::cref(lkj));
+}
+
+TEST_F(MapImplTest, ConstInit) {
+  PROTOBUF_CONSTINIT static Map<int, int> map;  // NOLINT
+  EXPECT_TRUE(map.empty());
+}
+
 // Map Field Reflection Test ========================================
 
 static int Func(int i, int j) { return i * j; }
@@ -1265,19 +1471,19 @@
   std::unique_ptr<Message> entry_int32_int32(
       MessageFactory::generated_factory()
           ->GetPrototype(fd_map_int32_int32->message_type())
-          ->New());
+          ->New(message.GetArena()));
   std::unique_ptr<Message> entry_int32_double(
       MessageFactory::generated_factory()
           ->GetPrototype(fd_map_int32_double->message_type())
-          ->New());
+          ->New(message.GetArena()));
   std::unique_ptr<Message> entry_string_string(
       MessageFactory::generated_factory()
           ->GetPrototype(fd_map_string_string->message_type())
-          ->New());
+          ->New(message.GetArena()));
   std::unique_ptr<Message> entry_int32_foreign_message(
       MessageFactory::generated_factory()
           ->GetPrototype(fd_map_int32_foreign_message->message_type())
-          ->New());
+          ->New(message.GetArena()));
 
   EXPECT_EQ(10, mf_int32_int32.size());
   EXPECT_EQ(10, mmf_int32_int32.size());
@@ -1684,6 +1890,15 @@
     EXPECT_EQ(int32_value9a, int32_value0b);
     EXPECT_EQ(int32_value0a, int32_value9b);
   }
+
+  // TODO(b/181148674): After supporting arena agnostic delete or let map entry
+  // handle heap allocation, this could be removed.
+  if (message.GetArena() != nullptr) {
+    entry_int32_int32.release();
+    entry_int32_double.release();
+    entry_string_string.release();
+    entry_int32_foreign_message.release();
+  }
 }
 
 TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) {
@@ -1847,6 +2062,39 @@
   EXPECT_FALSE(message.IsInitialized());
 }
 
+class MyMapEntry
+    : public internal::MapEntry<MyMapEntry, ::google::protobuf::int32, ::google::protobuf::int32,
+                                internal::WireFormatLite::TYPE_INT32,
+                                internal::WireFormatLite::TYPE_INT32> {
+ public:
+  constexpr MyMapEntry() {}
+  MyMapEntry(Arena*) { std::abort(); }
+  Metadata GetMetadata() const override { std::abort(); }
+  static bool ValidateKey(void*) { return true; }
+  static bool ValidateValue(void*) { return true; }
+};
+
+class MyMapEntryLite
+    : public internal::MapEntryLite<MyMapEntryLite, ::google::protobuf::int32, ::google::protobuf::int32,
+                                    internal::WireFormatLite::TYPE_INT32,
+                                    internal::WireFormatLite::TYPE_INT32> {
+ public:
+  constexpr MyMapEntryLite() {}
+  explicit MyMapEntryLite(Arena*) { std::abort(); }
+  static bool ValidateKey(void*) { return true; }
+  static bool ValidateValue(void*) { return true; }
+};
+
+TEST(MapEntryTest, ConstInit) {
+  // This verifies that `MapEntry`, `MapEntryLite` and `MapEntryImpl` can be
+  // constant initialized.
+  PROTOBUF_CONSTINIT static MyMapEntry entry{};
+  EXPECT_NE(entry.SpaceUsed(), 0);
+
+  PROTOBUF_CONSTINIT static MyMapEntryLite entry_lite{};  // NOLINT
+  EXPECT_TRUE(entry_lite.IsInitialized());
+}
+
 // Generated Message Test ===========================================
 
 TEST(GeneratedMapFieldTest, Accessors) {
@@ -2139,7 +2387,7 @@
   unittest::TestMap message1, message2;
   std::string data;
   MapTestUtil::SetMapFields(&message1);
-  int size = message1.ByteSize();
+  size_t size = message1.ByteSizeLong();
   data.resize(size);
   uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
   uint8* end = message1.SerializeWithCachedSizesToArray(start);
@@ -2152,7 +2400,7 @@
 TEST(GeneratedMapFieldTest, SerializationToStream) {
   unittest::TestMap message1, message2;
   MapTestUtil::SetMapFields(&message1);
-  int size = message1.ByteSize();
+  size_t size = message1.ByteSizeLong();
   std::string data;
   data.resize(size);
   {
@@ -2167,6 +2415,21 @@
   MapTestUtil::ExpectMapFieldsSet(message2);
 }
 
+TEST(GeneratedMapFieldTest, ParseFailsIfMalformed) {
+  unittest::TestMapSubmessage o, p;
+  auto m = o.mutable_test_map()->mutable_map_int32_foreign_message();
+  (*m)[0].set_c(-1);
+  std::string serialized;
+  EXPECT_TRUE(o.SerializeToString(&serialized));
+
+  // Should parse correctly.
+  EXPECT_TRUE(p.ParseFromString(serialized));
+
+  // Overwriting the last byte to 0xFF results in malformed wire.
+  serialized[serialized.size() - 1] = 0xFF;
+  EXPECT_FALSE(p.ParseFromString(serialized));
+}
+
 
 TEST(GeneratedMapFieldTest, SameTypeMaps) {
   const Descriptor* map1 = unittest::TestSameTypeMap::descriptor()
@@ -2369,7 +2632,7 @@
 
   EXPECT_TRUE(TextFormat::ParseFromString(text, &message));
   EXPECT_EQ(1, message.map_int32_foreign_message().size());
-  EXPECT_EQ(11, message.ByteSize());
+  EXPECT_EQ(11, message.ByteSizeLong());
 }
 
 TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) {
@@ -2406,47 +2669,68 @@
   EXPECT_TRUE(map_message.IsInitialized());
 }
 
-TEST(GeneratedMapFieldTest, MessagesMustMerge) {
+TEST(GeneratedMapFieldTest, SpaceUsed) {
   unittest::TestRequiredMessageMap map_message;
-  unittest::TestRequired with_dummy4;
-  with_dummy4.set_a(97);
-  with_dummy4.set_b(0);
-  with_dummy4.set_c(0);
-  with_dummy4.set_dummy4(98);
+  const size_t initial = map_message.SpaceUsed();
+  const size_t space_used_message = unittest::TestRequired().SpaceUsed();
 
-  EXPECT_TRUE(with_dummy4.IsInitialized());
-  (*map_message.mutable_map_field())[0] = with_dummy4;
-  EXPECT_TRUE(map_message.IsInitialized());
-  std::string s = map_message.SerializeAsString();
-
-  // Modify s so that there are two values in the entry for key 0.
-  // The first will have no value for c.  The second will have no value for a.
-  // Those are required fields.  Also, make some other little changes, to
-  // ensure we are merging the two values (because they're messages).
-  ASSERT_EQ(s.size() - 2, s[1]);  // encoding of the length of what follows
-  std::string encoded_val(s.data() + 4, s.data() + s.size());
-  // In s, change the encoding of c to an encoding of dummy32.
-  s[s.size() - 3] -= 8;
-  // Make encoded_val slightly different from what's in s.
-  encoded_val[encoded_val.size() - 1] += 33;  // Encode c = 33.
-  for (int i = 0; i < encoded_val.size(); i++) {
-    if (encoded_val[i] == 97) {
-      // Encode b = 91 instead of a = 97.  But this won't matter, because
-      // we also encode b = 0 right after this.  The point is to leave out
-      // a required field, and make sure the parser doesn't complain, because
-      // every required field is set after the merge of the two values.
-      encoded_val[i - 1] += 16;
-      encoded_val[i] = 91;
-    } else if (encoded_val[i] == 98) {
-      // Encode dummy5 = 99 instead of dummy4 = 98.
-      encoded_val[i - 1] += 8;  // The tag for dummy5 is 8 more.
-      encoded_val[i]++;
-      break;
-    }
+  auto& m = *map_message.mutable_map_field();
+  constexpr int kNumValues = 100;
+  for (int i = 0; i < kNumValues; ++i) {
+    m[i];
   }
 
-  s += encoded_val;            // Add the second message.
-  s[1] += encoded_val.size();  // Adjust encoded size.
+  // The exact value will depend on internal state, like collisions,
+  // so we can't predict it. But we can predict a lower bound.
+  size_t lower_bound =
+      initial + kNumValues * (space_used_message + sizeof(int32) +
+                              /* Node::next */ sizeof(void*) +
+                              /* table entry */ sizeof(void*));
+
+  EXPECT_LE(lower_bound, map_message.SpaceUsed());
+}
+
+TEST(GeneratedMapFieldTest, MessagesMustMerge) {
+  unittest::TestRequiredMessageMap map_message;
+
+  unittest::TestRequired with_dummy4;
+  with_dummy4.set_a(97);
+  with_dummy4.set_b(91);
+  with_dummy4.set_dummy4(98);
+  EXPECT_FALSE(with_dummy4.IsInitialized());
+  (*map_message.mutable_map_field())[0] = with_dummy4;
+  EXPECT_FALSE(map_message.IsInitialized());
+
+  unittest::TestRequired with_dummy5;
+  with_dummy5.set_b(0);
+  with_dummy5.set_c(33);
+  with_dummy5.set_dummy5(99);
+  EXPECT_FALSE(with_dummy5.IsInitialized());
+  (*map_message.mutable_map_field())[0] = with_dummy5;
+  EXPECT_FALSE(map_message.IsInitialized());
+
+  // The wire format of MapEntry is straightforward (*) and can be manually
+  // constructed to force merging of two uninitialized messages that would
+  // result in an initialized message.
+  //
+  // (*) http://google3/net/proto2/internal/map_test.cc?l=2433&rcl=310012028
+  std::string dummy4_s = with_dummy4.SerializePartialAsString();
+  std::string dummy5_s = with_dummy5.SerializePartialAsString();
+  int payload_size = dummy4_s.size() + dummy5_s.size();
+  // Makes sure the payload size fits into one byte.
+  ASSERT_LT(payload_size, 128);
+
+  std::string s(6, 0);
+  char* p = &s[0];
+  *p++ = WireFormatLite::MakeTag(1, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+  // Length: 2B for key tag & val and 2B for val tag and length of the following
+  // payload.
+  *p++ = 4 + payload_size;
+  *p++ = WireFormatLite::MakeTag(1, WireFormatLite::WIRETYPE_VARINT);
+  *p++ = 0;
+  *p++ = WireFormatLite::MakeTag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+  *p++ = payload_size;
+  StrAppend(&s, dummy4_s, dummy5_s);
 
   // Test key then value then value.
   int key = 0;
@@ -2481,7 +2765,7 @@
   MapReflectionTester reflection_tester(unittest::TestMap::descriptor());
   reflection_tester.SetMapFieldsViaReflection(&message);
 
-  EXPECT_LT(0, message.GetReflection()->SpaceUsed(message));
+  EXPECT_LT(0, message.GetReflection()->SpaceUsedLong(message));
 }
 
 TEST(GeneratedMapFieldReflectionTest, Accessors) {
@@ -2767,7 +3051,7 @@
 }
 
 TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
-  // Test that SpaceUsed() works properly
+  // Test that SpaceUsedLong() works properly
 
   // Since we share the implementation with generated messages, we don't need
   // to test very much here.  Just make sure it appears to be working.
@@ -2775,10 +3059,10 @@
   std::unique_ptr<Message> message(map_prototype_->New());
   MapReflectionTester reflection_tester(map_descriptor_);
 
-  int initial_space_used = message->SpaceUsed();
+  int initial_space_used = message->SpaceUsedLong();
 
   reflection_tester.SetMapFieldsViaReflection(message.get());
-  EXPECT_LT(initial_space_used, message->SpaceUsed());
+  EXPECT_LT(initial_space_used, message->SpaceUsedLong());
 }
 
 TEST_F(MapFieldInDynamicMessageTest, RecursiveMap) {
@@ -2952,9 +3236,9 @@
   unittest::TestMap message;
   MapTestUtil::SetMapFields(&message);
 
-  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  EXPECT_EQ(message.ByteSizeLong(), WireFormat::ByteSize(message));
   message.Clear();
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
   EXPECT_EQ(0, WireFormat::ByteSize(message));
 }
 
@@ -2967,7 +3251,7 @@
 
   // Serialize using the generated code.
   {
-    message.ByteSize();
+    message.ByteSizeLong();
     io::StringOutputStream raw_output(&generated_data);
     io::CodedOutputStream output(&raw_output);
     message.SerializeWithCachedSizes(&output);
@@ -2978,15 +3262,14 @@
   {
     io::StringOutputStream raw_output(&dynamic_data);
     io::CodedOutputStream output(&raw_output);
-    int size = WireFormat::ByteSize(message);
+    size_t size = WireFormat::ByteSize(message);
     WireFormat::SerializeWithCachedSizes(message, size, &output);
     ASSERT_FALSE(output.HadError());
   }
 
-  // Should be the same.
-  // Don't use EXPECT_EQ here because we're comparing raw binary data and
-  // we really don't want it dumped to stdout on failure.
-  EXPECT_TRUE(dynamic_data == generated_data);
+  // Should parse to the same message.
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, generated_data));
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, dynamic_data));
 }
 
 TEST(WireFormatForMapFieldTest, SerializeMapDynamicMessage) {
@@ -3026,7 +3309,7 @@
   std::string expected_serialized_data;
   dynamic_message->SerializeToString(&expected_serialized_data);
   int expected_size = expected_serialized_data.size();
-  EXPECT_EQ(dynamic_message->ByteSize(), expected_size);
+  EXPECT_EQ(dynamic_message->ByteSizeLong(), expected_size);
 
   std::unique_ptr<Message> message2;
   message2.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New());
@@ -3040,27 +3323,27 @@
   reflection->RemoveLast(dynamic_message.get(), field);
   dynamic_message->MergeFrom(*message2);
   dynamic_message->MergeFrom(*message2);
-  // The map field is marked as STATE_MODIFIED_REPEATED, ByteSize() will use
+  // The map field is marked as STATE_MODIFIED_REPEATED, ByteSizeLong() will use
   // repeated field which have duplicate keys to calculate.
-  int duplicate_size = dynamic_message->ByteSize();
+  size_t duplicate_size = dynamic_message->ByteSizeLong();
   EXPECT_TRUE(duplicate_size > expected_size);
   std::string duplicate_serialized_data;
   dynamic_message->SerializeToString(&duplicate_serialized_data);
-  EXPECT_EQ(dynamic_message->ByteSize(), duplicate_serialized_data.size());
+  EXPECT_EQ(dynamic_message->ByteSizeLong(), duplicate_serialized_data.size());
 
   // Force the map field to mark with map CLEAN
   EXPECT_EQ(reflection_tester.MapSize(*dynamic_message, "map_int32_int32"), 2);
-  // The map field is marked as CLEAN, ByteSize() will use map which do not
+  // The map field is marked as CLEAN, ByteSizeLong() will use map which do not
   // have duplicate keys to calculate.
-  int size = dynamic_message->ByteSize();
+  int size = dynamic_message->ByteSizeLong();
   EXPECT_EQ(expected_size, size);
 
   // Protobuf used to have a bug for serialize when map it marked CLEAN. It used
-  // repeated field to calculate ByteSize but use map to serialize the real
-  // data, thus the ByteSize may bigger than real serialized size. A crash might
-  // be happen at SerializeToString(). Or an "unexpect end group" warning was
-  // raised at parse back if user use SerializeWithCachedSizes() which avoids
-  // size check at serialize.
+  // repeated field to calculate ByteSizeLong but use map to serialize the real
+  // data, thus the ByteSizeLong may bigger than real serialized size. A crash
+  // might be happen at SerializeToString(). Or an "unexpected end group"
+  // warning was raised at parse back if user use SerializeWithCachedSizes()
+  // which avoids size check at serialize.
   std::string serialized_data;
   dynamic_message->SerializeToString(&serialized_data);
   EXPECT_EQ(serialized_data, expected_serialized_data);
@@ -3118,7 +3401,7 @@
 template <typename T>
 static std::string DeterministicSerializationWithSerializePartialToCodedStream(
     const T& t) {
-  const int size = t.ByteSize();
+  const size_t size = t.ByteSizeLong();
   std::string result(size, '\0');
   io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
   io::CodedOutputStream output_stream(&array_stream);
@@ -3132,7 +3415,7 @@
 template <typename T>
 static std::string DeterministicSerializationWithSerializeToCodedStream(
     const T& t) {
-  const int size = t.ByteSize();
+  const size_t size = t.ByteSizeLong();
   std::string result(size, '\0');
   io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
   io::CodedOutputStream output_stream(&array_stream);
@@ -3145,7 +3428,7 @@
 
 template <typename T>
 static std::string DeterministicSerialization(const T& t) {
-  const int size = t.ByteSize();
+  const size_t size = t.ByteSizeLong();
   std::string result(size, '\0');
   io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
   {
@@ -3161,20 +3444,6 @@
   return result;
 }
 
-// Helper to test the serialization of the first arg against a golden file.
-static void TestDeterministicSerialization(const protobuf_unittest::TestMaps& t,
-                                           const std::string& filename) {
-  std::string expected;
-  GOOGLE_CHECK_OK(File::GetContents(
-      TestUtil::GetTestDataPath("net/proto2/internal/testdata/" + filename),
-      &expected, true));
-  const std::string actual = DeterministicSerialization(t);
-  EXPECT_EQ(expected, actual);
-  protobuf_unittest::TestMaps u;
-  EXPECT_TRUE(u.ParseFromString(actual));
-  EXPECT_TRUE(util::MessageDifferencer::Equals(u, t));
-}
-
 // Helper for MapSerializationTest.  Return a 7-bit ASCII string.
 static std::string ConstructKey(uint64 n) {
   std::string s(n % static_cast<uint64>(9), '\0');
@@ -3219,7 +3488,17 @@
     frog = frog * multiplier + i;
     frog ^= (frog >> 41);
   }
-  TestDeterministicSerialization(t, "golden_message_maps");
+
+  // Verifies if two consecutive calls to deterministic serialization produce
+  // the same bytes. Deterministic serialization means the same serialization
+  // bytes in the same binary.
+  const std::string s1 = DeterministicSerialization(t);
+  const std::string s2 = DeterministicSerialization(t);
+  EXPECT_EQ(s1, s2);
+
+  protobuf_unittest::TestMaps u;
+  EXPECT_TRUE(u.ParseFromString(s1));
+  EXPECT_TRUE(util::MessageDifferencer::Equals(u, t));
 }
 
 TEST(MapSerializationTest, DeterministicSubmessage) {
@@ -3273,6 +3552,7 @@
                                                   "testdata/map_test_data.txt"),
                         &expected_text, true));
 
+  CleanStringLineEndings(&expected_text, false);
   EXPECT_EQ(message->DebugString(), expected_text);
 }
 
@@ -3474,6 +3754,22 @@
   MapTestUtil::ExpectMapFieldsSet(message2);
 }
 
+TEST(ArenaTest, DynamicMapFieldOnArenaMemoryLeak) {
+  auto* desc = unittest::TestMap::descriptor();
+  auto* field = desc->FindFieldByName("map_int32_int32");
+
+  Arena arena;
+  DynamicMessageFactory factory;
+  auto* message = factory.GetPrototype(desc)->New(&arena);
+  auto* reflection = message->GetReflection();
+  reflection->AddMessage(message, field);
+
+  // Force internal syncing, which initializes the mutex.
+  MapReflectionTester reflection_tester(unittest::TestMap::descriptor());
+  int size = reflection_tester.MapSize(*message, "map_int32_int32");
+  EXPECT_EQ(size, 1);
+}
+
 TEST(MoveTest, MoveConstructorWorks) {
   Map<int32, TestAllTypes> original_map;
   original_map[42].mutable_optional_nested_message()->set_bb(42);
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index 9787d3d..c3b84d1 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -238,6 +238,51 @@
   EXPECT_FALSE(map_int32_enum_val_ == nullptr);
   EXPECT_FALSE(map_int32_foreign_message_key_ == nullptr);
   EXPECT_FALSE(map_int32_foreign_message_val_ == nullptr);
+
+  std::vector<const FieldDescriptor*> all_map_descriptors = {
+      map_int32_int32_key_,
+      map_int32_int32_val_,
+      map_int64_int64_key_,
+      map_int64_int64_val_,
+      map_uint32_uint32_key_,
+      map_uint32_uint32_val_,
+      map_uint64_uint64_key_,
+      map_uint64_uint64_val_,
+      map_sint32_sint32_key_,
+      map_sint32_sint32_val_,
+      map_sint64_sint64_key_,
+      map_sint64_sint64_val_,
+      map_fixed32_fixed32_key_,
+      map_fixed32_fixed32_val_,
+      map_fixed64_fixed64_key_,
+      map_fixed64_fixed64_val_,
+      map_sfixed32_sfixed32_key_,
+      map_sfixed32_sfixed32_val_,
+      map_sfixed64_sfixed64_key_,
+      map_sfixed64_sfixed64_val_,
+      map_int32_float_key_,
+      map_int32_float_val_,
+      map_int32_double_key_,
+      map_int32_double_val_,
+      map_bool_bool_key_,
+      map_bool_bool_val_,
+      map_string_string_key_,
+      map_string_string_val_,
+      map_int32_bytes_key_,
+      map_int32_bytes_val_,
+      map_int32_enum_key_,
+      map_int32_enum_val_,
+      map_int32_foreign_message_key_,
+      map_int32_foreign_message_val_};
+  for (const FieldDescriptor* fdesc : all_map_descriptors) {
+    GOOGLE_CHECK(fdesc->containing_type() != nullptr) << fdesc->name();
+    if (fdesc->name() == "key") {
+      EXPECT_EQ(fdesc->containing_type()->map_key(), fdesc);
+    } else {
+      EXPECT_EQ(fdesc->name(), "value");
+      EXPECT_EQ(fdesc->containing_type()->map_value(), fdesc);
+    }
+  }
 }
 
 // Shorthand to get a FieldDescriptor for a field of unittest::TestMap.
@@ -450,20 +495,27 @@
 
   Message* sub_foreign_message = nullptr;
   MapValueRef map_val;
+  MapValueConstRef map_val_const;
 
   // Add first element.
   MapKey map_key;
   map_key.SetInt32Value(0);
+  EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int32_int32"),
+                                          map_key, &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_int32"),
                                                  map_key, &map_val));
   map_val.SetInt32Value(0);
 
   map_key.SetInt64Value(0);
+  EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int64_int64"),
+                                          map_key, &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int64_int64"),
                                                  map_key, &map_val));
   map_val.SetInt64Value(0);
 
   map_key.SetUInt32Value(0);
+  EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_uint32_uint32"),
+                                          map_key, &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(
       message, F("map_uint32_uint32"), map_key, &map_val));
   map_val.SetUInt32Value(0);
@@ -514,26 +566,36 @@
   map_val.SetDoubleValue(0.0);
 
   map_key.SetBoolValue(false);
+  EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_bool_bool"), map_key,
+                                          &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_bool_bool"),
                                                  map_key, &map_val));
   map_val.SetBoolValue(false);
 
   map_key.SetStringValue("0");
+  EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_string_string"),
+                                          map_key, &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(
       message, F("map_string_string"), map_key, &map_val));
   map_val.SetStringValue("0");
 
   map_key.SetInt32Value(0);
+  EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int32_bytes"),
+                                          map_key, &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_bytes"),
                                                  map_key, &map_val));
   map_val.SetStringValue("0");
 
   map_key.SetInt32Value(0);
+  EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int32_enum"),
+                                          map_key, &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_enum"),
                                                  map_key, &map_val));
   map_val.SetEnumValue(map_enum_bar_->number());
 
   map_key.SetInt32Value(0);
+  EXPECT_FALSE(reflection->LookupMapValue(
+      *message, F("map_int32_foreign_message"), map_key, &map_val_const));
   EXPECT_TRUE(reflection->InsertOrLookupMapValue(
       message, F("map_int32_foreign_message"), map_key, &map_val));
   sub_foreign_message = map_val.MutableMessageValue();
@@ -888,6 +950,7 @@
   const Reflection* reflection = message.GetReflection();
   const Message* sub_message;
   MapKey map_key;
+  MapValueConstRef map_value_const_ref;
 
   // -----------------------------------------------------------------
 
@@ -926,6 +989,9 @@
       map_key.SetInt32Value(key);
       EXPECT_TRUE(
           reflection->ContainsMapKey(message, F("map_int32_int32"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_int32"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetInt32Value(), val);
     }
   }
   {
@@ -945,6 +1011,9 @@
       map_key.SetInt64Value(key);
       EXPECT_TRUE(
           reflection->ContainsMapKey(message, F("map_int64_int64"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int64_int64"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetInt64Value(), val);
     }
   }
   {
@@ -964,6 +1033,9 @@
       map_key.SetUInt32Value(key);
       EXPECT_TRUE(
           reflection->ContainsMapKey(message, F("map_uint32_uint32"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_uint32_uint32"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetUInt32Value(), val);
     }
   }
   {
@@ -982,6 +1054,9 @@
       map_key.SetUInt64Value(key);
       EXPECT_TRUE(
           reflection->ContainsMapKey(message, F("map_uint64_uint64"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_uint64_uint64"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetUInt64Value(), val);
     }
   }
   {
@@ -1000,6 +1075,9 @@
       map_key.SetInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_sint32_sint32"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_sint32_sint32"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetInt32Value(), val);
     }
   }
   {
@@ -1018,6 +1096,9 @@
       map_key.SetInt64Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_sint64_sint64"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_sint64_sint64"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetInt64Value(), val);
     }
   }
   {
@@ -1036,6 +1117,9 @@
       map_key.SetUInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_fixed32_fixed32"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_fixed32_fixed32"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetUInt32Value(), val);
     }
   }
   {
@@ -1054,6 +1138,9 @@
       map_key.SetUInt64Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_fixed64_fixed64"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_fixed64_fixed64"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetUInt64Value(), val);
     }
   }
   {
@@ -1072,6 +1159,9 @@
       map_key.SetInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_sfixed32_sfixed32"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(
+          message, F("map_sfixed32_sfixed32"), map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetInt32Value(), val);
     }
   }
   {
@@ -1090,6 +1180,9 @@
       map_key.SetInt64Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_sfixed64_sfixed64"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(
+          message, F("map_sfixed64_sfixed64"), map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetInt64Value(), val);
     }
   }
   {
@@ -1108,6 +1201,9 @@
       map_key.SetInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_float"),
                                                  map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_float"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetFloatValue(), val);
     }
   }
   {
@@ -1126,6 +1222,9 @@
       map_key.SetInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_double"),
                                                  map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_double"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetDoubleValue(), val);
     }
   }
   {
@@ -1144,6 +1243,9 @@
       map_key.SetBoolValue(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_bool_bool"),
                                                  map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_bool_bool"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetBoolValue(), val);
     }
   }
   {
@@ -1162,6 +1264,9 @@
       map_key.SetStringValue(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_string_string"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_string_string"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetStringValue(), val);
     }
   }
   {
@@ -1180,6 +1285,9 @@
       map_key.SetInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_bytes"),
                                                  map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_bytes"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetStringValue(), val);
     }
   }
   {
@@ -1198,6 +1306,9 @@
       map_key.SetInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_enum"),
                                                  map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_enum"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(map_value_const_ref.GetEnumValue(), val->number());
     }
   }
   {
@@ -1218,6 +1329,12 @@
       map_key.SetInt32Value(key);
       EXPECT_EQ(true, reflection->ContainsMapKey(
                           message, F("map_int32_foreign_message"), map_key));
+      EXPECT_TRUE(reflection->LookupMapValue(message,
+                                             F("map_int32_foreign_message"),
+                                             map_key, &map_value_const_ref));
+      EXPECT_EQ(foreign_message.GetReflection()->GetInt32(
+                    map_value_const_ref.GetMessageValue(), foreign_c_),
+                val);
     }
   }
 }
diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
index 70145b7..655aec8 100644
--- a/src/google/protobuf/map_test_util_impl.h
+++ b/src/google/protobuf/map_test_util_impl.h
@@ -167,7 +167,6 @@
   (*message->mutable_map_int32_bytes())[0] = "0";
   (*message->mutable_map_int32_enum())[0] = enum_value0;
   (*message->mutable_map_int32_foreign_message())[0].set_c(0);
-  (*message->mutable_map_int32_foreign_message_no_arena())[0].set_c(0);
 
   // Add second element
   (*message->mutable_map_int32_int32())[1] = 1;
@@ -187,7 +186,6 @@
   (*message->mutable_map_int32_bytes())[1] = "1";
   (*message->mutable_map_int32_enum())[1] = enum_value1;
   (*message->mutable_map_int32_foreign_message())[1].set_c(1);
-  (*message->mutable_map_int32_foreign_message_no_arena())[1].set_c(1);
 }
 
 template <typename MapMessage>
@@ -333,7 +331,6 @@
   EXPECT_EQ(2, message.map_int32_bytes().size());
   EXPECT_EQ(2, message.map_int32_enum().size());
   EXPECT_EQ(2, message.map_int32_foreign_message().size());
-  EXPECT_EQ(2, message.map_int32_foreign_message_no_arena().size());
 
   EXPECT_EQ(0, message.map_int32_int32().at(0));
   EXPECT_EQ(0, message.map_int64_int64().at(0));
@@ -352,7 +349,6 @@
   EXPECT_EQ("0", message.map_int32_bytes().at(0));
   EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
   EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
-  EXPECT_EQ(0, message.map_int32_foreign_message_no_arena().at(0).c());
 
   EXPECT_EQ(1, message.map_int32_int32().at(1));
   EXPECT_EQ(1, message.map_int64_int64().at(1));
@@ -371,7 +367,6 @@
   EXPECT_EQ("1", message.map_int32_bytes().at(1));
   EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
   EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
-  EXPECT_EQ(1, message.map_int32_foreign_message_no_arena().at(1).c());
 }
 
 template <typename EnumType, EnumType enum_value, typename MapMessage>
@@ -410,7 +405,7 @@
   EXPECT_EQ("", message.map_string_string().at("0"));
   EXPECT_EQ("", message.map_int32_bytes().at(0));
   EXPECT_EQ(enum_value, message.map_int32_enum().at(0));
-  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+  EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSizeLong());
 }
 
 template <typename EnumType, EnumType enum_value0, EnumType enum_value1,
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index f59348e..e718790 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -59,29 +59,6 @@
   typedef FalseType type;
 };
 
-// In proto2 Map, enum needs to be initialized to given default value, while
-// other types' default value can be inferred from the type.
-template <bool IsEnum, typename Type>
-class MapValueInitializer {
- public:
-  static inline void Initialize(Type& type, int default_enum_value);
-};
-
-template <typename Type>
-class MapValueInitializer<true, Type> {
- public:
-  static inline void Initialize(Type& value, int default_enum_value) {
-    value = static_cast<Type>(default_enum_value);
-  }
-};
-
-template <typename Type>
-class MapValueInitializer<false, Type> {
- public:
-  static inline void Initialize(Type& /* value */,
-                                int /* default_enum_value */) {}
-};
-
 template <typename Type, bool is_arena_constructable>
 class MapArenaMessageCreator {
  public:
@@ -155,13 +132,13 @@
   typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
                                           Type>::TypeOnMemory TypeOnMemory;
   // Corresponding wire type for field type.
-  static const WireFormatLite::WireType kWireType =
+  static constexpr WireFormatLite::WireType kWireType =
       MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
   // Whether wire type is for message.
-  static const bool kIsMessage =
+  static constexpr bool kIsMessage =
       MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
   // Whether wire type is for enum.
-  static const bool kIsEnum =
+  static constexpr bool kIsEnum =
       MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsEnum;
 
   // Functions used in parsing and serialization. ===================
@@ -180,25 +157,15 @@
   static inline void DeleteNoArena(const Type* x);
   static inline void Merge(const Type& from, Type** to, Arena* arena);
   static inline void Clear(Type** value, Arena* arena);
-  static inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena,
-                                             int default_enum_value);
-  static inline void Initialize(Type** x, Arena* arena);
+  static constexpr TypeOnMemory Constinit();
 
-  static inline void InitializeMaybeByDefaultEnum(Type** x,
-                                                  int default_enum_value,
-                                                  Arena* arena);
   static inline Type* EnsureMutable(Type** value, Arena* arena);
   // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
   // those already calculate in sizeof(MapField).
   static inline size_t SpaceUsedInMapEntryLong(const Type* value);
-  // Return bytes used by value in Map.
-  static inline size_t SpaceUsedInMapLong(const Type& value);
-  // Assign default value to given instance.
-  static inline void AssignDefaultValue(Type** value);
   // Return default instance if value is not initialized when calling const
   // reference accessor.
-  static inline const Type& DefaultIfNotInitialized(const Type* value,
-                                                    const Type* default_value);
+  static inline const Type& DefaultIfNotInitialized(const Type* value);
   // Check if all required fields have values set.
   static inline bool IsInitialized(Type* value);
 };
@@ -235,21 +202,12 @@
     static inline void Merge(const MapEntryAccessorType& from,                \
                              TypeOnMemory* to, Arena* arena);                 \
     static inline void Clear(TypeOnMemory* value, Arena* arena);              \
-    static inline void ClearMaybeByDefaultEnum(TypeOnMemory* value,           \
-                                               Arena* arena,                  \
-                                               int default_enum);             \
     static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value);  \
-    static inline size_t SpaceUsedInMapLong(const TypeOnMemory& value);       \
-    static inline size_t SpaceUsedInMapLong(const std::string& value);        \
-    static inline void AssignDefaultValue(TypeOnMemory* value);               \
     static inline const MapEntryAccessorType& DefaultIfNotInitialized(        \
-        const TypeOnMemory& value, const TypeOnMemory& default_value);        \
+        const TypeOnMemory& value);                                           \
     static inline bool IsInitialized(const TypeOnMemory& value);              \
     static void DeleteNoArena(TypeOnMemory& value);                           \
-    static inline void Initialize(TypeOnMemory* value, Arena* arena);         \
-    static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value,      \
-                                                    int default_enum_value,   \
-                                                    Arena* arena);            \
+    static constexpr TypeOnMemory Constinit();                                \
     static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value,    \
                                                       Arena* arena);          \
   };
@@ -547,23 +505,11 @@
 }
 
 template <typename Type>
-size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::SpaceUsedInMapLong(
-    const Type& value) {
-  return value.SpaceUsedLong();
-}
-
-template <typename Type>
 inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
     Type** value, Arena* /* arena */) {
   if (*value != NULL) (*value)->Clear();
 }
 template <typename Type>
-inline void
-MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ClearMaybeByDefaultEnum(
-    Type** value, Arena* /* arena */, int /* default_enum_value */) {
-  if (*value != NULL) (*value)->Clear();
-}
-template <typename Type>
 inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
     const Type& from, Type** to, Arena* /* arena */) {
   (*to)->MergeFrom(from);
@@ -576,22 +522,9 @@
 }
 
 template <typename Type>
-inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
-                           Type>::AssignDefaultValue(Type** value) {
-  *value = const_cast<Type*>(Type::internal_default_instance());
-}
-
-template <typename Type>
-inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Initialize(
-    Type** x, Arena* /* arena */) {
-  *x = NULL;
-}
-
-template <typename Type>
-inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
-    InitializeMaybeByDefaultEnum(Type** x, int /* default_enum_value */,
-                                 Arena* /* arena */) {
-  *x = NULL;
+constexpr auto MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Constinit()
+    -> TypeOnMemory {
+  return nullptr;
 }
 
 template <typename Type>
@@ -608,8 +541,8 @@
 template <typename Type>
 inline const Type&
 MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DefaultIfNotInitialized(
-    const Type* value, const Type* default_value) {
-  return value != NULL ? *value : *default_value;
+    const Type* value) {
+  return value != NULL ? *value : *Type::internal_default_instance();
 }
 
 template <typename Type>
@@ -635,27 +568,9 @@
     return sizeof(value);                                                     \
   }                                                                           \
   template <typename Type>                                                    \
-  inline size_t                                                               \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong( \
-      const TypeOnMemory& value) {                                            \
-    return sizeof(value);                                                     \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline size_t                                                               \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong( \
-      const std::string& value) {                                             \
-    return sizeof(value);                                                     \
-  }                                                                           \
-  template <typename Type>                                                    \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear(  \
-      TypeOnMemory* value, Arena* arena) {                                    \
-    value->ClearToEmpty(&internal::GetEmptyStringAlreadyInited(), arena);     \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::        \
-      ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena,              \
-                              int /* default_enum */) {                       \
-    Clear(value, arena);                                                      \
+      TypeOnMemory* value, Arena* /* arena */) {                              \
+    value->ClearToEmpty();                                                    \
   }                                                                           \
   template <typename Type>                                                    \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge(  \
@@ -668,34 +583,23 @@
     value.DestroyNoArena(&internal::GetEmptyStringAlreadyInited());           \
   }                                                                           \
   template <typename Type>                                                    \
-  inline void                                                                 \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::AssignDefaultValue( \
-      TypeOnMemory* /* value */) {}                                           \
-  template <typename Type>                                                    \
-  inline void                                                                 \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize(         \
-      TypeOnMemory* value, Arena* /* arena */) {                              \
-    value->UnsafeSetDefault(&internal::GetEmptyStringAlreadyInited());        \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::        \
-      InitializeMaybeByDefaultEnum(                                           \
-          TypeOnMemory* value, int /* default_enum_value */, Arena* arena) {  \
-    Initialize(value, arena);                                                 \
+  constexpr auto                                                              \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit()         \
+      ->TypeOnMemory {                                                        \
+    return TypeOnMemory(&internal::fixed_address_empty_string);               \
   }                                                                           \
   template <typename Type>                                                    \
   inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,            \
                                  Type>::MapEntryAccessorType*                 \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable(      \
       TypeOnMemory* value, Arena* arena) {                                    \
-    return value->Mutable(&internal::GetEmptyStringAlreadyInited(), arena);   \
+    return value->Mutable(ArenaStringPtr::EmptyDefault{}, arena);             \
   }                                                                           \
   template <typename Type>                                                    \
   inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,      \
                                        Type>::MapEntryAccessorType&           \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::                    \
-      DefaultIfNotInitialized(const TypeOnMemory& value,                      \
-                              const TypeOnMemory& /* default_value */) {      \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType,                            \
+                 Type>::DefaultIfNotInitialized(const TypeOnMemory& value) {  \
     return value.Get();                                                       \
   }                                                                           \
   template <typename Type>                                                    \
@@ -708,81 +612,58 @@
 STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
 #undef STRING_OR_BYTES_HANDLER_FUNCTIONS
 
-#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType)                                \
-  template <typename Type>                                                    \
-  inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,      \
-                                       Type>::MapEntryAccessorType&           \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType,                            \
-                 Type>::GetExternalReference(const TypeOnMemory& value) {     \
-    return value;                                                             \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline size_t MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::      \
-      SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) {              \
-    return 0;                                                                 \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline size_t                                                               \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong( \
-      const TypeOnMemory& /* value */) {                                      \
-    return sizeof(Type);                                                      \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear(  \
-      TypeOnMemory* value, Arena* /* arena */) {                              \
-    *value = 0;                                                               \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::        \
-      ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* /* arena */,        \
-                              int default_enum_value) {                       \
-    *value = static_cast<TypeOnMemory>(default_enum_value);                   \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge(  \
-      const MapEntryAccessorType& from, TypeOnMemory* to,                     \
-      Arena* /* arena */) {                                                   \
-    *to = from;                                                               \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,                \
-                             Type>::DeleteNoArena(TypeOnMemory& /* x */) {}   \
-  template <typename Type>                                                    \
-  inline void                                                                 \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::AssignDefaultValue( \
-      TypeOnMemory* /* value */) {}                                           \
-  template <typename Type>                                                    \
-  inline void                                                                 \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize(         \
-      TypeOnMemory* value, Arena* /* arena */) {                              \
-    *value = 0;                                                               \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::        \
-      InitializeMaybeByDefaultEnum(                                           \
-          TypeOnMemory* value, int default_enum_value, Arena* /* arena */) {  \
-    *value = static_cast<TypeOnMemory>(default_enum_value);                   \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,            \
-                                 Type>::MapEntryAccessorType*                 \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable(      \
-      TypeOnMemory* value, Arena* /* arena */) {                              \
-    return value;                                                             \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,      \
-                                       Type>::MapEntryAccessorType&           \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::                    \
-      DefaultIfNotInitialized(const TypeOnMemory& value,                      \
-                              const TypeOnMemory& /* default_value */) {      \
-    return value;                                                             \
-  }                                                                           \
-  template <typename Type>                                                    \
-  inline bool                                                                 \
-  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized(      \
-      const TypeOnMemory& /* value */) {                                      \
-    return true;                                                              \
+#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType)                               \
+  template <typename Type>                                                   \
+  inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,     \
+                                       Type>::MapEntryAccessorType&          \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType,                           \
+                 Type>::GetExternalReference(const TypeOnMemory& value) {    \
+    return value;                                                            \
+  }                                                                          \
+  template <typename Type>                                                   \
+  inline size_t MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::     \
+      SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) {             \
+    return 0;                                                                \
+  }                                                                          \
+  template <typename Type>                                                   \
+  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
+      TypeOnMemory* value, Arena* /* arena */) {                             \
+    *value = 0;                                                              \
+  }                                                                          \
+  template <typename Type>                                                   \
+  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
+      const MapEntryAccessorType& from, TypeOnMemory* to,                    \
+      Arena* /* arena */) {                                                  \
+    *to = from;                                                              \
+  }                                                                          \
+  template <typename Type>                                                   \
+  inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,               \
+                             Type>::DeleteNoArena(TypeOnMemory& /* x */) {}  \
+  template <typename Type>                                                   \
+  constexpr auto                                                             \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit()        \
+      ->TypeOnMemory {                                                       \
+    return 0;                                                                \
+  }                                                                          \
+  template <typename Type>                                                   \
+  inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,           \
+                                 Type>::MapEntryAccessorType*                \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable(     \
+      TypeOnMemory* value, Arena* /* arena */) {                             \
+    return value;                                                            \
+  }                                                                          \
+  template <typename Type>                                                   \
+  inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,     \
+                                       Type>::MapEntryAccessorType&          \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType,                           \
+                 Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \
+    return value;                                                            \
+  }                                                                          \
+  template <typename Type>                                                   \
+  inline bool                                                                \
+  MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized(     \
+      const TypeOnMemory& /* value */) {                                     \
+    return true;                                                             \
   }
 PRIMITIVE_HANDLER_FUNCTIONS(INT64)
 PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index 836dc10..263ef61 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -33,7 +33,6 @@
 option cc_enable_arenas = true;
 
 import "google/protobuf/unittest.proto";
-import "google/protobuf/unittest_no_arena.proto";
 
 // We don't put this in a package within proto2 because we need to make sure
 // that the generated code doesn't depend on being in the proto2 namespace.
@@ -42,25 +41,25 @@
 
 // Tests maps.
 message TestMap {
-  map<int32   , int32   > map_int32_int32       = 1;
-  map<int64   , int64   > map_int64_int64       = 2;
-  map<uint32  , uint32  > map_uint32_uint32     = 3;
-  map<uint64  , uint64  > map_uint64_uint64     = 4;
-  map<sint32  , sint32  > map_sint32_sint32     = 5;
-  map<sint64  , sint64  > map_sint64_sint64     = 6;
-  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
-  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<int32, int32> map_int32_int32 = 1;
+  map<int64, int64> map_int64_int64 = 2;
+  map<uint32, uint32> map_uint32_uint32 = 3;
+  map<uint64, uint64> map_uint64_uint64 = 4;
+  map<sint32, sint32> map_sint32_sint32 = 5;
+  map<sint64, sint64> map_sint64_sint64 = 6;
+  map<fixed32, fixed32> map_fixed32_fixed32 = 7;
+  map<fixed64, fixed64> map_fixed64_fixed64 = 8;
   map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
   map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
-  map<int32   , float   > map_int32_float       = 11;
-  map<int32   , double  > map_int32_double      = 12;
-  map<bool    , bool    > map_bool_bool         = 13;
-  map<string  , string  > map_string_string     = 14;
-  map<int32   , bytes   > map_int32_bytes       = 15;
-  map<int32   , MapEnum > map_int32_enum        = 16;
-  map<int32   , ForeignMessage> map_int32_foreign_message = 17;
-  map<string  , ForeignMessage> map_string_foreign_message = 18;
-  map<int32   , TestAllTypes> map_int32_all_types = 19;
+  map<int32, float> map_int32_float = 11;
+  map<int32, double> map_int32_double = 12;
+  map<bool, bool> map_bool_bool = 13;
+  map<string, string> map_string_string = 14;
+  map<int32, bytes> map_int32_bytes = 15;
+  map<int32, MapEnum> map_int32_enum = 16;
+  map<int32, ForeignMessage> map_int32_foreign_message = 17;
+  map<string, ForeignMessage> map_string_foreign_message = 18;
+  map<int32, TestAllTypes> map_int32_all_types = 19;
 }
 
 message TestMapSubmessage {
@@ -90,33 +89,29 @@
 }
 
 message TestArenaMap {
-  map<int32   , int32   > map_int32_int32       = 1;
-  map<int64   , int64   > map_int64_int64       = 2;
-  map<uint32  , uint32  > map_uint32_uint32     = 3;
-  map<uint64  , uint64  > map_uint64_uint64     = 4;
-  map<sint32  , sint32  > map_sint32_sint32     = 5;
-  map<sint64  , sint64  > map_sint64_sint64     = 6;
-  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
-  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<int32, int32> map_int32_int32 = 1;
+  map<int64, int64> map_int64_int64 = 2;
+  map<uint32, uint32> map_uint32_uint32 = 3;
+  map<uint64, uint64> map_uint64_uint64 = 4;
+  map<sint32, sint32> map_sint32_sint32 = 5;
+  map<sint64, sint64> map_sint64_sint64 = 6;
+  map<fixed32, fixed32> map_fixed32_fixed32 = 7;
+  map<fixed64, fixed64> map_fixed64_fixed64 = 8;
   map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
   map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
-  map<int32   , float   > map_int32_float       = 11;
-  map<int32   , double  > map_int32_double      = 12;
-  map<bool    , bool    > map_bool_bool         = 13;
-  map<string  , string  > map_string_string     = 14;
-  map<int32   , bytes   > map_int32_bytes       = 15;
-  map<int32   , MapEnum > map_int32_enum        = 16;
-  map<int32   , ForeignMessage> map_int32_foreign_message = 17;
-  map<int32, .protobuf_unittest_no_arena.ForeignMessage>
-      map_int32_foreign_message_no_arena = 18;
+  map<int32, float> map_int32_float = 11;
+  map<int32, double> map_int32_double = 12;
+  map<bool, bool> map_bool_bool = 13;
+  map<string, string> map_string_string = 14;
+  map<int32, bytes> map_int32_bytes = 15;
+  map<int32, MapEnum> map_int32_enum = 16;
+  map<int32, ForeignMessage> map_int32_foreign_message = 17;
 }
 
 // Previously, message containing enum called Type cannot be used as value of
 // map field.
 message MessageContainingEnumCalledType {
-  enum Type {
-    TYPE_FOO = 0;
-  }
+  enum Type { TYPE_FOO = 0; }
   map<string, MessageContainingEnumCalledType> type = 1;
 }
 
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index d35dfff..744bbc6 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -79,15 +79,15 @@
 using internal::WireFormatLite;
 
 void Message::MergeFrom(const Message& from) {
-  const Descriptor* descriptor = GetDescriptor();
-  GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
-      << ": Tried to merge from a message with a different type.  "
-         "to: "
-      << descriptor->full_name()
-      << ", "
-         "from: "
-      << from.GetDescriptor()->full_name();
-  ReflectionOps::Merge(from, this);
+  auto* class_to = GetClassData();
+  auto* class_from = from.GetClassData();
+  auto* merge_to_from = class_to ? class_to->merge_to_from : nullptr;
+  if (class_to == nullptr || class_to != class_from) {
+    merge_to_from = [](Message* to, const Message& from) {
+      ReflectionOps::Merge(from, to);
+    };
+  }
+  merge_to_from(this, from);
 }
 
 void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
@@ -95,15 +95,40 @@
 }
 
 void Message::CopyFrom(const Message& from) {
-  const Descriptor* descriptor = GetDescriptor();
-  GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
-      << ": Tried to copy from a message with a different type. "
-         "to: "
-      << descriptor->full_name()
-      << ", "
-         "from: "
-      << from.GetDescriptor()->full_name();
-  ReflectionOps::Copy(from, this);
+  if (&from == this) return;
+
+  auto* class_to = GetClassData();
+  auto* class_from = from.GetClassData();
+  auto* copy_to_from = class_to ? class_to->copy_to_from : nullptr;
+
+  if (class_to == nullptr || class_to != class_from) {
+    const Descriptor* descriptor = GetDescriptor();
+    GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
+        << ": Tried to copy from a message with a different type. "
+           "to: "
+        << descriptor->full_name()
+        << ", "
+           "from: "
+        << from.GetDescriptor()->full_name();
+    copy_to_from = [](Message* to, const Message& from) {
+      ReflectionOps::Copy(from, to);
+    };
+  }
+  copy_to_from(this, from);
+}
+
+void Message::CopyWithSizeCheck(Message* to, const Message& from) {
+#ifndef NDEBUG
+  size_t from_size = from.ByteSizeLong();
+#endif
+  to->Clear();
+#ifndef NDEBUG
+  GOOGLE_CHECK_EQ(from_size, from.ByteSizeLong())
+      << "Source of CopyFrom changed when clearing target.  Either "
+         "source is a nested message in target (not allowed), or "
+         "another thread is modifying the source.";
+#endif
+  to->GetClassData()->merge_to_from(to, from);
 }
 
 std::string Message::GetTypeName() const {
@@ -162,6 +187,10 @@
   return GetReflection()->SpaceUsedLong(*this);
 }
 
+uint64 Message::GetInvariantPerBuild(uint64 salt) {
+  return salt;
+}
+
 // =============================================================================
 // MessageFactory
 
@@ -171,10 +200,10 @@
 
 
 #define HASH_MAP std::unordered_map
-#define HASH_FXN hash
+#define STR_HASH_FXN hash<::google::protobuf::StringPiece>
 
 
-class GeneratedMessageFactory : public MessageFactory {
+class GeneratedMessageFactory final : public MessageFactory {
  public:
   static GeneratedMessageFactory* singleton();
 
@@ -186,8 +215,8 @@
 
  private:
   // Only written at static init time, so does not require locking.
-  HASH_MAP<const char*, const google::protobuf::internal::DescriptorTable*,
-           HASH_FXN<const char*>, streq>
+  HASH_MAP<StringPiece, const google::protobuf::internal::DescriptorTable*,
+           STR_HASH_FXN>
       file_map_;
 
   internal::WrappedMutex mutex_;
@@ -342,20 +371,12 @@
 PROTOBUF_NOINLINE
 #endif
     Arena*
-    GenericTypeHandler<Message>::GetArena(Message* value) {
-  return value->GetArena();
-}
-template <>
-#if defined(_MSC_VER) && (_MSC_VER >= 1800)
-// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue
-// #240
-PROTOBUF_NOINLINE
-#endif
-    void*
-    GenericTypeHandler<Message>::GetMaybeArenaPointer(Message* value) {
-  return value->GetMaybeArenaPointer();
+    GenericTypeHandler<Message>::GetOwningArena(Message* value) {
+  return value->GetOwningArena();
 }
 }  // namespace internal
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index b6156b8..df8e895 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -144,7 +144,9 @@
 // Defined in other files.
 class AssignDescriptorsHelper;
 class DynamicMessageFactory;
+class GeneratedMessageReflectionTestHelper;
 class MapKey;
+class MapValueConstRef;
 class MapValueRef;
 class MapIterator;
 class MapReflectionTester;
@@ -152,6 +154,7 @@
 namespace internal {
 struct DescriptorTable;
 class MapFieldBase;
+class SwapFieldHelper;
 }
 class UnknownFieldSet;  // unknown_field_set.h
 namespace io {
@@ -162,6 +165,7 @@
 }  // namespace io
 namespace python {
 class MapReflectionFriend;  // scalar_map_container.h
+class MessageReflectionFriend;
 }
 namespace expr {
 class CelMapReflectionFriend;  // field_backed_map_impl.cc
@@ -170,6 +174,9 @@
 namespace internal {
 class MapFieldPrinterHelper;  // text_format.cc
 }
+namespace util {
+class MessageDifferencer;
+}
 
 
 namespace internal {
@@ -222,9 +229,12 @@
 // optimized for speed will want to override these with faster implementations,
 // but classes optimized for code size may be happy with keeping them.  See
 // the optimize_for option in descriptor.proto.
+//
+// Users must not derive from this class. Only the protocol compiler and
+// the internal library are allowed to create subclasses.
 class PROTOBUF_EXPORT Message : public MessageLite {
  public:
-  inline Message() {}
+  constexpr Message() {}
 
   // Basic Operations ------------------------------------------------
 
@@ -356,8 +366,32 @@
   // to implement GetDescriptor() and GetReflection() above.
   virtual Metadata GetMetadata() const = 0;
 
-  inline explicit Message(Arena* arena) : MessageLite(arena) {}
+  struct ClassData {
+    // Note: The order of arguments (to, then from) is chosen so that the ABI
+    // of this function is the same as the CopyFrom method.  That is, the
+    // hidden "this" parameter comes first.
+    void (*copy_to_from)(Message* to, const Message& from_msg);
+    void (*merge_to_from)(Message* to, const Message& from_msg);
+  };
+  // GetClassData() returns a pointer to a ClassData struct which
+  // exists in global memory and is unique to each subclass.  This uniqueness
+  // property is used in order to quickly determine whether two messages are
+  // of the same type.
+  // TODO(jorg): change to pure virtual
+  virtual const ClassData* GetClassData() const { return nullptr; }
 
+  // CopyWithSizeCheck calls Clear() and then MergeFrom(), and in debug
+  // builds, checks that calling Clear() on the destination message doesn't
+  // alter the size of the source.  It assumes the messages are known to be
+  // of the same type, and thus uses GetClassData().
+  static void CopyWithSizeCheck(Message* to, const Message& from);
+
+  inline explicit Message(Arena* arena, bool is_message_owned = false)
+      : MessageLite(arena, is_message_owned) {}
+
+
+ protected:
+  static uint64 GetInvariantPerBuild(uint64 salt);
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
@@ -466,7 +500,8 @@
   void RemoveLast(Message* message, const FieldDescriptor* field) const;
   // Removes the last element of a repeated message field, and returns the
   // pointer to the caller.  Caller takes ownership of the returned pointer.
-  Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
+  PROTOBUF_MUST_USE_RESULT Message* ReleaseLast(
+      Message* message, const FieldDescriptor* field) const;
 
   // Swap the complete contents of two messages.
   void Swap(Message* message1, Message* message2) const;
@@ -581,12 +616,20 @@
   // the compiled-in class for this type, NOT DynamicMessage.
   Message* MutableMessage(Message* message, const FieldDescriptor* field,
                           MessageFactory* factory = nullptr) const;
+
   // Replaces the message specified by 'field' with the already-allocated object
   // sub_message, passing ownership to the message.  If the field contained a
   // message, that message is deleted.  If sub_message is nullptr, the field is
   // cleared.
   void SetAllocatedMessage(Message* message, Message* sub_message,
                            const FieldDescriptor* field) const;
+
+  // Similar to `SetAllocatedMessage`, but omits all internal safety and
+  // ownership checks.  This method should only be used when the objects are on
+  // the same arena or paired with a call to `UnsafeArenaReleaseMessage`.
+  void UnsafeArenaSetAllocatedMessage(Message* message, Message* sub_message,
+                                      const FieldDescriptor* field) const;
+
   // Releases the message specified by 'field' and returns the pointer,
   // ReleaseMessage() will return the message the message object if it exists.
   // Otherwise, it may or may not return nullptr.  In any case, if the return
@@ -594,8 +637,16 @@
   // If the field existed (HasField() is true), then the returned pointer will
   // be the same as the pointer returned by MutableMessage().
   // This function has the same effect as ClearField().
-  Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
-                          MessageFactory* factory = nullptr) const;
+  PROTOBUF_MUST_USE_RESULT Message* ReleaseMessage(
+      Message* message, const FieldDescriptor* field,
+      MessageFactory* factory = nullptr) const;
+
+  // Similar to `ReleaseMessage`, but omits all internal safety and ownership
+  // checks.  This method should only be used when the objects are on the same
+  // arena or paired with a call to `UnsafeArenaSetAllocatedMessage`.
+  Message* UnsafeArenaReleaseMessage(Message* message,
+                                     const FieldDescriptor* field,
+                                     MessageFactory* factory = nullptr) const;
 
 
   // Repeated field getters ------------------------------------------
@@ -737,8 +788,7 @@
   // long as the message is not destroyed.
   //
   // Note that to use this method users need to include the header file
-  // "net/proto2/public/reflection.h" (which defines the RepeatedFieldRef
-  // class templates).
+  // "reflection.h" (which defines the RepeatedFieldRef class templates).
   template <typename T>
   RepeatedFieldRef<T> GetRepeatedFieldRef(const Message& message,
                                           const FieldDescriptor* field) const;
@@ -750,7 +800,7 @@
       Message* message, const FieldDescriptor* field) const;
 
   // DEPRECATED. Please use Get(Mutable)RepeatedFieldRef() for repeated field
-  // access. The following repeated field accesors will be removed in the
+  // access. The following repeated field accessors will be removed in the
   // future.
   //
   // Repeated field accessors  -------------------------------------------------
@@ -909,6 +959,40 @@
   const internal::RepeatedFieldAccessor* RepeatedFieldAccessor(
       const FieldDescriptor* field) const;
 
+  // Lists all fields of the message which are currently set, except for unknown
+  // fields and stripped fields. See ListFields for details.
+  void ListFieldsOmitStripped(
+      const Message& message,
+      std::vector<const FieldDescriptor*>* output) const;
+
+  bool IsMessageStripped(const Descriptor* descriptor) const {
+    return schema_.IsMessageStripped(descriptor);
+  }
+
+  friend class TextFormat;
+
+  void ListFieldsMayFailOnStripped(
+      const Message& message, bool should_fail,
+      std::vector<const FieldDescriptor*>* output) const;
+
+  // Returns true if the message field is backed by a LazyField.
+  //
+  // A message field may be backed by a LazyField without the user annotation
+  // ([lazy = true]). While the user-annotated LazyField is lazily verified on
+  // first touch (i.e. failure on access rather than parsing if the LazyField is
+  // not initialized), the inferred LazyField is eagerly verified to avoid lazy
+  // parsing error at the cost of lower efficiency. When reflecting a message
+  // field, use this API instead of checking field->options().lazy().
+  bool IsLazyField(const FieldDescriptor* field) const {
+    return IsLazilyVerifiedLazyField(field) ||
+           IsEagerlyVerifiedLazyField(field);
+  }
+
+  bool IsLazilyVerifiedLazyField(const FieldDescriptor* field) const;
+  bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const;
+
+  friend class FastReflectionMessageMutator;
+
   const Descriptor* const descriptor_;
   const internal::ReflectionSchema schema_;
   const DescriptorPool* const descriptor_pool_;
@@ -926,13 +1010,17 @@
   friend class ::PROTOBUF_NAMESPACE_ID::MessageLayoutInspector;
   friend class ::PROTOBUF_NAMESPACE_ID::AssignDescriptorsHelper;
   friend class DynamicMessageFactory;
+  friend class GeneratedMessageReflectionTestHelper;
   friend class python::MapReflectionFriend;
+  friend class python::MessageReflectionFriend;
+  friend class util::MessageDifferencer;
 #define GOOGLE_PROTOBUF_HAS_CEL_MAP_REFLECTION_FRIEND
   friend class expr::CelMapReflectionFriend;
   friend class internal::MapFieldReflectionTest;
   friend class internal::MapKeySorter;
   friend class internal::WireFormat;
   friend class internal::ReflectionOps;
+  friend class internal::SwapFieldHelper;
   // Needed for implementing text format for map.
   friend class internal::MapFieldPrinterHelper;
 
@@ -956,10 +1044,19 @@
 
   // If key is in map field: Saves the value pointer to val and returns
   // false. If key in not in map field: Insert the key into map, saves
-  // value pointer to val and returns true.
+  // value pointer to val and returns true. Users are able to modify the
+  // map value by MapValueRef.
   bool InsertOrLookupMapValue(Message* message, const FieldDescriptor* field,
                               const MapKey& key, MapValueRef* val) const;
 
+  // If key is in map field: Saves the value pointer to val and returns true.
+  // Returns false if key is not in map field. Users are NOT able to modify
+  // the value by MapValueConstRef.
+  bool LookupMapValue(const Message& message, const FieldDescriptor* field,
+                      const MapKey& key, MapValueConstRef* val) const;
+  bool LookupMapValue(const Message&, const FieldDescriptor*, const MapKey&,
+                      MapValueRef*) const = delete;
+
   // Delete and returns true if key is in the map field. Returns false
   // otherwise.
   bool DeleteMapValue(Message* message, const FieldDescriptor* field,
@@ -1002,24 +1099,25 @@
   template <typename Type>
   const Type& DefaultRaw(const FieldDescriptor* field) const;
 
+  const Message* GetDefaultMessageInstance(const FieldDescriptor* field) const;
+
   inline const uint32* GetHasBits(const Message& message) const;
   inline uint32* MutableHasBits(Message* message) const;
   inline uint32 GetOneofCase(const Message& message,
                              const OneofDescriptor* oneof_descriptor) const;
   inline uint32* MutableOneofCase(
       Message* message, const OneofDescriptor* oneof_descriptor) const;
-  inline const internal::ExtensionSet& GetExtensionSet(
-      const Message& message) const;
+  inline bool HasExtensionSet(const Message& /* message */) const {
+    return schema_.HasExtensionSet();
+  }
+  const internal::ExtensionSet& GetExtensionSet(const Message& message) const;
   internal::ExtensionSet* MutableExtensionSet(Message* message) const;
-  inline Arena* GetArena(Message* message) const;
 
   inline const internal::InternalMetadata& GetInternalMetadata(
       const Message& message) const;
 
   internal::InternalMetadata* MutableInternalMetadata(Message* message) const;
 
-  inline bool IsInlined(const FieldDescriptor* field) const;
-
   inline bool HasBit(const Message& message,
                      const FieldDescriptor* field) const;
   inline void SetBit(Message* message, const FieldDescriptor* field) const;
@@ -1027,14 +1125,33 @@
   inline void SwapBit(Message* message1, Message* message2,
                       const FieldDescriptor* field) const;
 
+  // Shallow-swap fields listed in fields vector of two messages. It is the
+  // caller's responsibility to make sure shallow swap is safe.
+  void UnsafeShallowSwapFields(
+      Message* message1, Message* message2,
+      const std::vector<const FieldDescriptor*>& fields) const;
+
   // This function only swaps the field. Should swap corresponding has_bit
   // before or after using this function.
   void SwapField(Message* message1, Message* message2,
                  const FieldDescriptor* field) const;
 
+  // Unsafe but shallow version of SwapField.
+  void UnsafeShallowSwapField(Message* message1, Message* message2,
+                              const FieldDescriptor* field) const;
+
+  template <bool unsafe_shallow_swap>
+  void SwapFieldsImpl(Message* message1, Message* message2,
+                      const std::vector<const FieldDescriptor*>& fields) const;
+
   void SwapOneofField(Message* message1, Message* message2,
                       const OneofDescriptor* oneof_descriptor) const;
 
+  // Unsafe but shallow version of SwapOneofField.
+  void UnsafeShallowSwapOneofField(
+      Message* message1, Message* message2,
+      const OneofDescriptor* oneof_descriptor) const;
+
   inline bool HasOneofField(const Message& message,
                             const FieldDescriptor* field) const;
   inline void SetOneofCase(Message* message,
@@ -1084,13 +1201,6 @@
   void AddEnumValueInternal(Message* message, const FieldDescriptor* field,
                             int value) const;
 
-  Message* UnsafeArenaReleaseMessage(Message* message,
-                                     const FieldDescriptor* field,
-                                     MessageFactory* factory = nullptr) const;
-
-  void UnsafeArenaSetAllocatedMessage(Message* message, Message* sub_message,
-                                      const FieldDescriptor* field) const;
-
   friend inline  // inline so nobody can call this function.
       void
       RegisterAllTypesInternal(const Metadata* file_level_metadata, int size);
@@ -1215,7 +1325,8 @@
 #if PROTOBUF_RTTI
   return dynamic_cast<const T*>(from);
 #else
-  bool ok = T::default_instance().GetReflection() == from->GetReflection();
+  bool ok = from != nullptr &&
+            T::default_instance().GetReflection() == from->GetReflection();
   return ok ? down_cast<const T*>(from) : nullptr;
 #endif
 }
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 5b1db7b..f137675 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -313,11 +313,11 @@
   return ParseFrom<kParsePartial>(internal::BoundedZCIS{input, size});
 }
 
-bool MessageLite::ParseFromString(const std::string& data) {
+bool MessageLite::ParseFromString(ConstStringParam data) {
   return ParseFrom<kParse>(data);
 }
 
-bool MessageLite::ParsePartialFromString(const std::string& data) {
+bool MessageLite::ParsePartialFromString(ConstStringParam data) {
   return ParseFrom<kParsePartial>(data);
 }
 
@@ -329,7 +329,7 @@
   return ParseFrom<kParsePartial>(as_string_view(data, size));
 }
 
-bool MessageLite::MergeFromString(const std::string& data) {
+bool MessageLite::MergeFromString(ConstStringParam data) {
   return ParseFrom<kMerge>(data);
 }
 
@@ -389,7 +389,7 @@
   }
   int final_byte_count = output->ByteCount();
 
-  if (final_byte_count - original_byte_count != size) {
+  if (final_byte_count - original_byte_count != static_cast<int64>(size)) {
     ByteSizeConsistencyError(size, ByteSizeLong(),
                              final_byte_count - original_byte_count, *this);
   }
@@ -488,7 +488,7 @@
                << " exceeded maximum protobuf size of 2GB: " << byte_size;
     return false;
   }
-  if (size < byte_size) return false;
+  if (size < static_cast<int64>(byte_size)) return false;
   uint8* start = reinterpret_cast<uint8*>(data);
   SerializeToArrayImpl(*this, start, byte_size);
   return true;
@@ -529,6 +529,23 @@
   *to = from;
 }
 
+// Non-inline variants of std::string specializations for
+// various InternalMetadata routines.
+template <>
+void InternalMetadata::DoClear<std::string>() {
+  mutable_unknown_fields<std::string>()->clear();
+}
+
+template <>
+void InternalMetadata::DoMergeFrom<std::string>(const std::string& other) {
+  mutable_unknown_fields<std::string>()->append(other);
+}
+
+template <>
+void InternalMetadata::DoSwap<std::string>(std::string* other) {
+  mutable_unknown_fields<std::string>()->swap(*other);
+}
+
 }  // namespace internal
 
 
@@ -581,3 +598,5 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index d2cea5d..f82bd0c 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -64,6 +64,10 @@
 template <typename T>
 class RepeatedPtrField;
 
+class FastReflectionMessageMutator;
+class FastReflectionStringSetter;
+class Reflection;
+
 namespace io {
 
 class CodedInputStream;
@@ -74,13 +78,27 @@
 }  // namespace io
 namespace internal {
 
+class SwapFieldHelper;
+
+// Tag type used to invoke the constinit constructor overload of some classes.
+// Such constructors are internal implementation details of the library.
+struct ConstantInitialized {
+  explicit ConstantInitialized() = default;
+};
+
 // See parse_context.h for explanation
 class ParseContext;
 
+class ExtensionSet;
+class LazyField;
 class RepeatedPtrFieldBase;
+class TcParserBase;
 class WireFormatLite;
 class WeakFieldMap;
 
+template <typename Type>
+class GenericTypeHandler;  // defined in repeated_field.h
+
 // We compute sizes as size_t but cache them as int.  This function converts a
 // computed size to a cached size.  Since we don't proceed with serialization
 // if the total size was > INT_MAX, it is not important what this function
@@ -139,7 +157,7 @@
  private:
   // Prefer c++14 aligned_storage, but for compatibility this will do.
   union AlignedUnion {
-    char space[sizeof(T)];
+    alignas(T) char space[sizeof(T)];
     int64 align_to_int64;
     void* align_to_ptr;
   } union_;
@@ -151,7 +169,7 @@
     fixed_address_empty_string;
 
 
-PROTOBUF_EXPORT inline const std::string& GetEmptyStringAlreadyInited() {
+PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() {
   return fixed_address_empty_string.get();
 }
 
@@ -182,9 +200,12 @@
 // is best when you only have a small number of message types linked
 // into your binary, in which case the size of the protocol buffers
 // runtime itself is the biggest problem.
+//
+// Users must not derive from this class. Only the protocol compiler and
+// the internal library are allowed to create subclasses.
 class PROTOBUF_EXPORT MessageLite {
  public:
-  inline MessageLite() {}
+  constexpr MessageLite() {}
   virtual ~MessageLite() = default;
 
   // Basic Operations ------------------------------------------------
@@ -200,12 +221,8 @@
   // if arena is a NULL. Default implementation for backwards compatibility.
   virtual MessageLite* New(Arena* arena) const;
 
-  // Get the arena, if any, associated with this message. Virtual method
-  // required for generic operations but most arena-related operations should
-  // use the GetArena() generated-code method. Default implementation
-  // to reduce code size by avoiding the need for per-type implementations
-  // when types do not implement arena support.
-  Arena* GetArena() const { return _internal_metadata_.arena(); }
+  // Same as GetOwningArena.
+  Arena* GetArena() const { return GetOwningArena(); }
 
   // Get a pointer that may be equal to this message's arena, or may not be.
   // If the value returned by this method is equal to some arena pointer, then
@@ -264,28 +281,35 @@
   // format.  A successful return does not indicate the entire input is
   // consumed, ensure you call ConsumedEntireMessage() to check that if
   // applicable.
-  bool ParseFromCodedStream(io::CodedInputStream* input);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCodedStream(
+      io::CodedInputStream* input);
   // Like ParseFromCodedStream(), but accepts messages that are missing
   // required fields.
-  bool ParsePartialFromCodedStream(io::CodedInputStream* input);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCodedStream(
+      io::CodedInputStream* input);
   // Read a protocol buffer from the given zero-copy input stream.  If
   // successful, the entire input will be consumed.
-  bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromZeroCopyStream(
+      io::ZeroCopyInputStream* input);
   // Like ParseFromZeroCopyStream(), but accepts messages that are missing
   // required fields.
-  bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromZeroCopyStream(
+      io::ZeroCopyInputStream* input);
   // Parse a protocol buffer from a file descriptor.  If successful, the entire
   // input will be consumed.
-  bool ParseFromFileDescriptor(int file_descriptor);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromFileDescriptor(
+      int file_descriptor);
   // Like ParseFromFileDescriptor(), but accepts messages that are missing
   // required fields.
-  bool ParsePartialFromFileDescriptor(int file_descriptor);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromFileDescriptor(
+      int file_descriptor);
   // Parse a protocol buffer from a C++ istream.  If successful, the entire
   // input will be consumed.
-  bool ParseFromIstream(std::istream* input);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromIstream(std::istream* input);
   // Like ParseFromIstream(), but accepts messages that are missing
   // required fields.
-  bool ParsePartialFromIstream(std::istream* input);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromIstream(
+      std::istream* input);
   // Read a protocol buffer from the given zero-copy input stream, expecting
   // the message to be exactly "size" bytes long.  If successful, exactly
   // this many bytes will have been consumed from the input.
@@ -294,25 +318,29 @@
   // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
   // missing required fields.
   bool MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
-  bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromBoundedZeroCopyStream(
+      io::ZeroCopyInputStream* input, int size);
   // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
   // missing required fields.
-  bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
-                                             int size);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromBoundedZeroCopyStream(
+      io::ZeroCopyInputStream* input, int size);
   // Parses a protocol buffer contained in a string. Returns true on success.
   // This function takes a string in the (non-human-readable) binary wire
   // format, matching the encoding output by MessageLite::SerializeToString().
   // If you'd like to convert a human-readable string into a protocol buffer
   // object, see google::protobuf::TextFormat::ParseFromString().
-  bool ParseFromString(const std::string& data);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data);
   // Like ParseFromString(), but accepts messages that are missing
   // required fields.
-  bool ParsePartialFromString(const std::string& data);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString(
+      ConstStringParam data);
   // Parse a protocol buffer contained in an array of bytes.
-  bool ParseFromArray(const void* data, int size);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data,
+                                                       int size);
   // Like ParseFromArray(), but accepts messages that are missing
   // required fields.
-  bool ParsePartialFromArray(const void* data, int size);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromArray(const void* data,
+                                                              int size);
 
 
   // Reads a protocol buffer from the stream and merges it into this
@@ -336,7 +364,7 @@
   bool MergePartialFromCodedStream(io::CodedInputStream* input);
 
   // Merge a protocol buffer contained in a string.
-  bool MergeFromString(const std::string& data);
+  bool MergeFromString(ConstStringParam data);
 
 
   // Serialization ---------------------------------------------------
@@ -447,7 +475,19 @@
     return Arena::CreateMaybeMessage<T>(arena);
   }
 
-  inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {}
+  inline explicit MessageLite(Arena* arena, bool is_message_owned = false)
+      : _internal_metadata_(arena, is_message_owned) {}
+
+  // Returns the arena, if any, that directly owns this message and its internal
+  // memory (Arena::Own is different in that the arena doesn't directly own the
+  // internal memory). This method is used in proto's implementation for
+  // swapping, moving and setting allocated, for deciding whether the ownership
+  // of this message or its internal memory could be changed.
+  Arena* GetOwningArena() const { return _internal_metadata_.owning_arena(); }
+
+  // Returns the arena, used for allocating internal objects(e.g., child
+  // messages, etc), or owning incoming objects (e.g., set allocated).
+  Arena* GetArenaForAllocation() const { return _internal_metadata_.arena(); }
 
   internal::InternalMetadata _internal_metadata_;
 
@@ -482,9 +522,21 @@
   // TODO(gerbens) make this a pure abstract function
   virtual const void* InternalGetTable() const { return NULL; }
 
-  friend class internal::WireFormatLite;
+  friend class FastReflectionMessageMutator;
+  friend class FastReflectionStringSetter;
   friend class Message;
+  friend class Reflection;
+  friend class internal::ExtensionSet;
+  friend class internal::LazyField;
+  friend class internal::SwapFieldHelper;
+  friend class internal::TcParserBase;
   friend class internal::WeakFieldMap;
+  friend class internal::WireFormatLite;
+
+  template <typename Type>
+  friend class Arena::InternalHelper;
+  template <typename Type>
+  friend class internal::GenericTypeHandler;
 
   void LogInitializationErrorMessage() const;
 
diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc
index 46ae35d..408c233 100644
--- a/src/google/protobuf/message_unittest.inc
+++ b/src/google/protobuf/message_unittest.inc
@@ -35,11 +35,11 @@
 // This file needs to be included as .inc as it depends on certain macros being
 // defined prior to its inclusion.
 
-#include <google/protobuf/message.h>
-
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+
+#include <google/protobuf/message.h>
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
@@ -48,7 +48,6 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/test_util2.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream.h>
@@ -57,8 +56,11 @@
 #include <google/protobuf/arena.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/generated_message_reflection.h>
+#include <gmock/gmock.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/io/io_win32.h>
 
 
@@ -208,6 +210,171 @@
       errors[0]);
 }
 
+TEST(MESSAGE_TEST_NAME, ParseFailsIfSubmessageNotInitialized) {
+  UNITTEST::TestRequiredForeign source, message;
+  source.mutable_optional_message()->set_dummy2(100);
+  std::string serialized = source.SerializePartialAsString();
+
+  EXPECT_TRUE(message.ParsePartialFromString(serialized));
+  EXPECT_FALSE(message.IsInitialized());
+
+  std::vector<std::string> errors;
+  {
+    ScopedMemoryLog log;
+    EXPECT_FALSE(message.ParseFromString(source.SerializePartialAsString()));
+    errors = log.GetMessages(ERROR);
+  }
+
+  EXPECT_THAT(
+      errors,
+      testing::ElementsAre(
+          "Can't parse message of type \"" +
+          std::string(UNITTEST_PACKAGE_NAME) +
+          ".TestRequiredForeign\" because it is missing required fields: "
+          "optional_message.a, optional_message.b, optional_message.c"));
+}
+
+TEST(MESSAGE_TEST_NAME, ParseFailsIfExtensionNotInitialized) {
+  UNITTEST::TestChildExtension source, message;
+  auto* r = source.mutable_optional_extension()->MutableExtension(
+      UNITTEST::TestRequired::single);
+  r->set_dummy2(100);
+  std::string serialized = source.SerializePartialAsString();
+
+  EXPECT_TRUE(message.ParsePartialFromString(serialized));
+  EXPECT_FALSE(message.IsInitialized());
+
+  std::vector<std::string> errors;
+  {
+    ScopedMemoryLog log;
+    EXPECT_FALSE(message.ParseFromString(source.SerializePartialAsString()));
+    errors = log.GetMessages(ERROR);
+  }
+
+  EXPECT_THAT(errors,
+              testing::ElementsAre(strings::Substitute(
+                  "Can't parse message of type \"$0.TestChildExtension\" "
+                  "because it is missing required fields: "
+                  "optional_extension.($0.TestRequired.single).a, "
+                  "optional_extension.($0.TestRequired.single).b, "
+                  "optional_extension.($0.TestRequired.single).c",
+                  UNITTEST_PACKAGE_NAME)));
+}
+
+TEST(MESSAGE_TEST_NAME, ParseFailsIfSubmessageTruncated) {
+  UNITTEST::NestedTestAllTypes o, p;
+  constexpr int kDepth = 5;
+  auto* child = o.mutable_child();
+  for (int i = 0; i < kDepth; i++) {
+    child = child->mutable_child();
+  }
+  TestUtil::SetAllFields(child->mutable_payload());
+
+  std::string serialized;
+  EXPECT_TRUE(o.SerializeToString(&serialized));
+
+  // Should parse correctly.
+  EXPECT_TRUE(p.ParseFromString(serialized));
+
+  constexpr int kMaxTruncate = 50;
+  ASSERT_GT(serialized.size(), kMaxTruncate);
+
+  for (int i = 1; i < kMaxTruncate; i += 3) {
+    EXPECT_FALSE(
+        p.ParseFromString(serialized.substr(0, serialized.size() - i)));
+  }
+}
+
+TEST(MESSAGE_TEST_NAME, ParseFailsIfWireMalformed) {
+  UNITTEST::NestedTestAllTypes o, p;
+  constexpr int kDepth = 5;
+  auto* child = o.mutable_child();
+  for (int i = 0; i < kDepth; i++) {
+    child = child->mutable_child();
+  }
+  // -1 becomes \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1
+  child->mutable_payload()->set_optional_int32(-1);
+
+  std::string serialized;
+  EXPECT_TRUE(o.SerializeToString(&serialized));
+
+  // Should parse correctly.
+  EXPECT_TRUE(p.ParseFromString(serialized));
+
+  // Overwriting the last byte to 0xFF results in malformed wire.
+  serialized[serialized.size() - 1] = 0xFF;
+  EXPECT_FALSE(p.ParseFromString(serialized));
+}
+
+TEST(MESSAGE_TEST_NAME, ParseFailsIfOneofWireMalformed) {
+  UNITTEST::NestedTestAllTypes o, p;
+  constexpr int kDepth = 5;
+  auto* child = o.mutable_child();
+  for (int i = 0; i < kDepth; i++) {
+    child = child->mutable_child();
+  }
+  // -1 becomes \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1
+  child->mutable_payload()->mutable_oneof_nested_message()->set_bb(-1);
+
+  std::string serialized;
+  EXPECT_TRUE(o.SerializeToString(&serialized));
+
+  // Should parse correctly.
+  EXPECT_TRUE(p.ParseFromString(serialized));
+
+  // Overwriting the last byte to 0xFF results in malformed wire.
+  serialized[serialized.size() - 1] = 0xFF;
+  EXPECT_FALSE(p.ParseFromString(serialized));
+}
+
+TEST(MESSAGE_TEST_NAME, ParseFailsIfExtensionWireMalformed) {
+  UNITTEST::TestChildExtension o, p;
+  auto* m = o.mutable_optional_extension()->MutableExtension(
+      UNITTEST::optional_nested_message_extension);
+
+  // -1 becomes \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1
+  m->set_bb(-1);
+
+  std::string serialized;
+  EXPECT_TRUE(o.SerializeToString(&serialized));
+
+  // Should parse correctly.
+  EXPECT_TRUE(p.ParseFromString(serialized));
+
+  // Overwriting the last byte to 0xFF results in malformed wire.
+  serialized[serialized.size() - 1] = 0xFF;
+  EXPECT_FALSE(p.ParseFromString(serialized));
+}
+
+TEST(MESSAGE_TEST_NAME, Swap) {
+  UNITTEST::NestedTestAllTypes o;
+  constexpr int kDepth = 5;
+  auto* child = o.mutable_child();
+  for (int i = 0; i < kDepth; i++) {
+    child = child->mutable_child();
+  }
+  TestUtil::SetAllFields(child->mutable_payload());
+
+  std::string serialized;
+  EXPECT_TRUE(o.SerializeToString(&serialized));
+
+  {
+    Arena arena;
+    UNITTEST::NestedTestAllTypes* p1 =
+        Arena::CreateMessage<UNITTEST::NestedTestAllTypes>(&arena);
+
+    // Should parse correctly.
+    EXPECT_TRUE(p1->ParseFromString(serialized));
+
+    UNITTEST::NestedTestAllTypes* p2 =
+        Arena::CreateMessage<UNITTEST::NestedTestAllTypes>(&arena);
+
+    p1->Swap(p2);
+
+    EXPECT_EQ(o.SerializeAsString(), p2->SerializeAsString());
+  }
+}
+
 TEST(MESSAGE_TEST_NAME, BypassInitializationCheckOnParse) {
   UNITTEST::TestRequired message;
   io::ArrayInputStream raw_input(nullptr, 0);
@@ -235,6 +402,10 @@
                 test_all_types_pointer_const));
   EXPECT_EQ(nullptr, DynamicCastToGenerated<const UNITTEST::TestRequired>(
                          test_all_types_pointer_const));
+
+  Message* test_all_types_pointer_nullptr = nullptr;
+  EXPECT_EQ(nullptr, DynamicCastToGenerated<UNITTEST::TestAllTypes>(
+                         test_all_types_pointer_nullptr));
 }
 
 #ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet.
@@ -370,6 +541,18 @@
   EXPECT_EQ("c", errors[2]);
 }
 
+TEST(MESSAGE_TEST_NAME, ReleaseMustUseResult) {
+  UNITTEST::TestAllTypes message;
+  auto* f = new UNITTEST::ForeignMessage();
+  f->set_c(1000);
+  message.set_allocated_optional_foreign_message(f);
+  auto* mf = message.mutable_optional_foreign_message();
+  EXPECT_EQ(mf, f);
+  std::unique_ptr<UNITTEST::ForeignMessage> rf(
+      message.release_optional_foreign_message());
+  EXPECT_NE(rf.get(), nullptr);
+}
+
 TEST(MESSAGE_TEST_NAME, ParseFailsOnInvalidMessageEnd) {
   UNITTEST::TestAllTypes message;
 
@@ -548,6 +731,34 @@
   EXPECT_TRUE(msg.IsInitialized());
 }
 
+TEST(MESSAGE_TEST_NAME, IsInitializedSplitBytestream) {
+  UNITTEST::TestRequired ab, c;
+  ab.set_a(1);
+  ab.set_b(2);
+  c.set_c(3);
+
+  // The protobuf represented by the concatenated string has all required
+  // fields (a,b,c) set.
+  std::string bytes =
+      ab.SerializePartialAsString() + c.SerializePartialAsString();
+
+  UNITTEST::TestRequired concatenated;
+  EXPECT_TRUE(concatenated.ParsePartialFromString(bytes));
+  EXPECT_TRUE(concatenated.IsInitialized());
+
+  UNITTEST::TestRequiredForeign fab, fc;
+  fab.mutable_optional_message()->set_a(1);
+  fab.mutable_optional_message()->set_b(2);
+  fc.mutable_optional_message()->set_c(3);
+
+  bytes =
+      fab.SerializePartialAsString() + fc.SerializePartialAsString();
+
+  UNITTEST::TestRequiredForeign fconcatenated;
+  EXPECT_TRUE(fconcatenated.ParsePartialFromString(bytes));
+  EXPECT_TRUE(fconcatenated.IsInitialized());
+}
+
 TEST(MESSAGE_FACTORY_TEST_NAME, GeneratedFactoryLookup) {
   EXPECT_EQ(MessageFactory::generated_factory()->GetPrototype(
                 UNITTEST::TestAllTypes::descriptor()),
@@ -629,5 +840,37 @@
 }
 
 
+TEST(MESSAGE_TEST_NAME, CheckSerializationWhenInterleavedExtensions) {
+  UNITTEST::TestExtensionRangeSerialize in_message;
+
+  in_message.set_foo_one(1);
+  in_message.set_foo_two(2);
+  in_message.set_foo_three(3);
+  in_message.set_foo_four(4);
+
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_one, 1);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_two, 2);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_three, 3);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_four, 4);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_five, 5);
+
+  std::string buffer;
+  in_message.SerializeToString(&buffer);
+
+  UNITTEST::TestExtensionRangeSerialize out_message;
+  out_message.ParseFromString(buffer);
+
+  EXPECT_EQ(1, out_message.foo_one());
+  EXPECT_EQ(2, out_message.foo_two());
+  EXPECT_EQ(3, out_message.foo_three());
+  EXPECT_EQ(4, out_message.foo_four());
+
+  EXPECT_EQ(1, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_one));
+  EXPECT_EQ(2, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_two));
+  EXPECT_EQ(3, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_three));
+  EXPECT_EQ(4, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_four));
+  EXPECT_EQ(5, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_five));
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h
index dc4ec95..0b90f28 100644
--- a/src/google/protobuf/metadata_lite.h
+++ b/src/google/protobuf/metadata_lite.h
@@ -47,29 +47,47 @@
 namespace internal {
 
 // This is the representation for messages that support arena allocation. It
-// uses a tagged pointer to either store the Arena pointer, if there are no
-// unknown fields, or a pointer to a block of memory with both the Arena pointer
-// and the UnknownFieldSet, if there are unknown fields. This optimization
-// allows for "zero-overhead" storage of the Arena pointer, relative to the
-// above baseline implementation.
+// uses a tagged pointer to either store the owning Arena pointer, if there are
+// no unknown fields, or a pointer to a block of memory with both the owning
+// Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides,
+// it also uses the tag to distinguish whether the owning Arena pointer is also
+// used by sub-structure allocation. This optimization allows for
+// "zero-overhead" storage of the Arena pointer, relative to the above baseline
+// implementation.
 //
-// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
-// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
-// pointer.
+// The tagged pointer uses the least two significant bits to disambiguate cases.
+// It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a
+// UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena
+// allocation and bit 1 == 1 to indicate heap allocation.
 class InternalMetadata {
  public:
-  InternalMetadata() : ptr_(nullptr) {}
-  explicit InternalMetadata(Arena* arena) : ptr_(arena) {}
+  constexpr InternalMetadata() : ptr_(0) {}
+  explicit InternalMetadata(Arena* arena, bool is_message_owned = false)
+      : ptr_(is_message_owned
+                 ? reinterpret_cast<intptr_t>(arena) | kMessageOwnedArenaTagMask
+                 : reinterpret_cast<intptr_t>(arena)) {
+    GOOGLE_DCHECK(!is_message_owned || arena != nullptr);
+  }
+
+  ~InternalMetadata() {
+    if (HasMessageOwnedArenaTag()) {
+      delete arena();
+    }
+  }
 
   template <typename T>
   void Delete() {
     // Note that Delete<> should be called not more than once.
-    if (have_unknown_fields() && arena() == NULL) {
-      delete PtrValue<Container<T>>();
+    if (have_unknown_fields()) {
+      DeleteOutOfLineHelper<T>();
     }
   }
 
-  PROTOBUF_ALWAYS_INLINE Arena* arena() const {
+  PROTOBUF_NDEBUG_INLINE Arena* owning_arena() const {
+    return HasMessageOwnedArenaTag() ? nullptr : arena();
+  }
+
+  PROTOBUF_NDEBUG_INLINE Arena* arena() const {
     if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
       return PtrValue<ContainerBase>()->arena;
     } else {
@@ -77,14 +95,16 @@
     }
   }
 
-  PROTOBUF_ALWAYS_INLINE bool have_unknown_fields() const {
-    return PtrTag() == kTagContainer;
+  PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const {
+    return HasUnknownFieldsTag();
   }
 
-  PROTOBUF_ALWAYS_INLINE void* raw_arena_ptr() const { return ptr_; }
+  PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const {
+    return reinterpret_cast<void*>(ptr_);
+  }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE const T& unknown_fields(
+  PROTOBUF_NDEBUG_INLINE const T& unknown_fields(
       const T& (*default_instance)()) const {
     if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
       return PtrValue<Container<T>>()->unknown_fields;
@@ -94,7 +114,7 @@
   }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE T* mutable_unknown_fields() {
+  PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() {
     if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) {
       return &PtrValue<Container<T>>()->unknown_fields;
     } else {
@@ -103,7 +123,7 @@
   }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE void Swap(InternalMetadata* other) {
+  PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) {
     // Semantics here are that we swap only the unknown fields, not the arena
     // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
     // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
@@ -115,42 +135,45 @@
     }
   }
 
+  PROTOBUF_NDEBUG_INLINE void InternalSwap(InternalMetadata* other) {
+    std::swap(ptr_, other->ptr_);
+  }
+
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE void MergeFrom(const InternalMetadata& other) {
+  PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) {
     if (other.have_unknown_fields()) {
       DoMergeFrom<T>(other.unknown_fields<T>(nullptr));
     }
   }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE void Clear() {
+  PROTOBUF_NDEBUG_INLINE void Clear() {
     if (have_unknown_fields()) {
       DoClear<T>();
     }
   }
 
  private:
-  void* ptr_;
+  intptr_t ptr_;
 
   // Tagged pointer implementation.
-  enum {
-    // ptr_ is an Arena*.
-    kTagArena = 0,
-    // ptr_ is a Container*.
-    kTagContainer = 1,
-  };
-  static const intptr_t kPtrTagMask = 1;
-  static const intptr_t kPtrValueMask = ~kPtrTagMask;
+  static constexpr intptr_t kUnknownFieldsTagMask = 1;
+  static constexpr intptr_t kMessageOwnedArenaTagMask = 2;
+  static constexpr intptr_t kPtrTagMask =
+      kUnknownFieldsTagMask | kMessageOwnedArenaTagMask;
+  static constexpr intptr_t kPtrValueMask = ~kPtrTagMask;
 
   // Accessors for pointer tag and pointer value.
-  PROTOBUF_ALWAYS_INLINE int PtrTag() const {
-    return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
+  PROTOBUF_ALWAYS_INLINE bool HasUnknownFieldsTag() const {
+    return ptr_ & kUnknownFieldsTagMask;
+  }
+  PROTOBUF_ALWAYS_INLINE bool HasMessageOwnedArenaTag() const {
+    return ptr_ & kMessageOwnedArenaTagMask;
   }
 
   template <typename U>
   U* PtrValue() const {
-    return reinterpret_cast<U*>(reinterpret_cast<intptr_t>(ptr_) &
-                                kPtrValueMask);
+    return reinterpret_cast<U*>(ptr_ & kPtrValueMask);
   }
 
   // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
@@ -164,14 +187,21 @@
   };
 
   template <typename T>
+  PROTOBUF_NOINLINE void DeleteOutOfLineHelper() {
+    if (arena() == NULL) {
+      delete PtrValue<Container<T>>();
+    }
+  }
+
+  template <typename T>
   PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
     Arena* my_arena = arena();
     Container<T>* container = Arena::Create<Container<T>>(my_arena);
+    intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask;
     // Two-step assignment works around a bug in clang's static analyzer:
     // https://bugs.llvm.org/show_bug.cgi?id=34198.
-    ptr_ = container;
-    ptr_ = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(ptr_) |
-                                   kTagContainer);
+    ptr_ = reinterpret_cast<intptr_t>(container);
+    ptr_ |= kUnknownFieldsTagMask | message_owned_arena_tag;
     container->arena = my_arena;
     return &(container->unknown_fields);
   }
@@ -179,17 +209,17 @@
   // Templated functions.
 
   template <typename T>
-  void DoClear() {
+  PROTOBUF_NOINLINE void DoClear() {
     mutable_unknown_fields<T>()->Clear();
   }
 
   template <typename T>
-  void DoMergeFrom(const T& other) {
+  PROTOBUF_NOINLINE void DoMergeFrom(const T& other) {
     mutable_unknown_fields<T>()->MergeFrom(other);
   }
 
   template <typename T>
-  void DoSwap(T* other) {
+  PROTOBUF_NOINLINE void DoSwap(T* other) {
     mutable_unknown_fields<T>()->Swap(other);
   }
 };
@@ -197,20 +227,12 @@
 // String Template specializations.
 
 template <>
-inline void InternalMetadata::DoClear<std::string>() {
-  mutable_unknown_fields<std::string>()->clear();
-}
-
+PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>();
 template <>
-inline void InternalMetadata::DoMergeFrom<std::string>(
-    const std::string& other) {
-  mutable_unknown_fields<std::string>()->append(other);
-}
-
+PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>(
+    const std::string& other);
 template <>
-inline void InternalMetadata::DoSwap<std::string>(std::string* other) {
-  mutable_unknown_fields<std::string>()->swap(*other);
-}
+PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other);
 
 // This helper RAII class is needed to efficiently parse unknown fields. We
 // should only call mutable_unknown_fields if there are actual unknown fields.
diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc
index ea23d28..2582cfe 100644
--- a/src/google/protobuf/no_field_presence_test.cc
+++ b/src/google/protobuf/no_field_presence_test.cc
@@ -567,7 +567,7 @@
   message.Clear();
   message.set_oneof_string("test");
   message.clear_oneof_string();
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
 }
 
 }  // namespace
diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc
index ea4ed19..1bf5ef8 100644
--- a/src/google/protobuf/parse_context.cc
+++ b/src/google/protobuf/parse_context.cc
@@ -48,7 +48,7 @@
 namespace {
 
 // Only call if at start of tag.
-bool ParseEndsInSlopRegion(const char* begin, int overrun, int d) {
+bool ParseEndsInSlopRegion(const char* begin, int overrun, int depth) {
   constexpr int kSlopBytes = EpsCopyInputStream::kSlopBytes;
   GOOGLE_DCHECK(overrun >= 0);
   GOOGLE_DCHECK(overrun <= kSlopBytes);
@@ -79,11 +79,11 @@
         break;
       }
       case 3: {  // start group
-        d++;
+        depth++;
         break;
       }
       case 4: {                    // end group
-        if (--d < 0) return true;  // We exit early
+        if (--depth < 0) return true;  // We exit early
         break;
       }
       case 5: {  // fixed32
@@ -99,7 +99,7 @@
 
 }  // namespace
 
-const char* EpsCopyInputStream::Next(int overrun, int d) {
+const char* EpsCopyInputStream::NextBuffer(int overrun, int depth) {
   if (next_chunk_ == nullptr) return nullptr;  // We've reached end of stream.
   if (next_chunk_ != buffer_) {
     GOOGLE_DCHECK(size_ > kSlopBytes);
@@ -115,7 +115,7 @@
   // buffer_.
   std::memmove(buffer_, buffer_end_, kSlopBytes);
   if (overall_limit_ > 0 &&
-      (d < 0 || !ParseEndsInSlopRegion(buffer_, overrun, d))) {
+      (depth < 0 || !ParseEndsInSlopRegion(buffer_, overrun, depth))) {
     const void* data;
     // ZeroCopyInputStream indicates Next may return 0 size buffers. Hence
     // we loop.
@@ -154,11 +154,22 @@
   return buffer_;
 }
 
-std::pair<const char*, bool> EpsCopyInputStream::DoneFallback(const char* ptr,
-                                                              int d) {
-  GOOGLE_DCHECK(ptr >= limit_end_);
-  int overrun = ptr - buffer_end_;
-  GOOGLE_DCHECK(overrun <= kSlopBytes);  // Guaranteed by parse loop.
+const char* EpsCopyInputStream::Next() {
+  GOOGLE_DCHECK(limit_ > kSlopBytes);
+  auto p = NextBuffer(0 /* immaterial */, -1);
+  if (p == nullptr) {
+    limit_end_ = buffer_end_;
+    // Distinguish ending on a pushed limit or ending on end-of-stream.
+    SetEndOfStream();
+    return nullptr;
+  }
+  limit_ -= buffer_end_ - p;  // Adjust limit_ relative to new anchor
+  limit_end_ = buffer_end_ + std::min(0, limit_);
+  return p;
+}
+
+std::pair<const char*, bool> EpsCopyInputStream::DoneFallback(int overrun,
+                                                              int depth) {
   // Did we exceeded the limit (parse error).
   if (PROTOBUF_PREDICT_FALSE(overrun > limit_)) return {nullptr, true};
   GOOGLE_DCHECK(overrun != limit_);  // Guaranteed by caller.
@@ -171,25 +182,26 @@
   // At this point we know the following assertion holds.
   GOOGLE_DCHECK(limit_ > 0);
   GOOGLE_DCHECK(limit_end_ == buffer_end_);  // because limit_ > 0
+  const char* p;
   do {
     // We are past the end of buffer_end_, in the slop region.
     GOOGLE_DCHECK(overrun >= 0);
-    auto p = Next(overrun, d);
+    p = NextBuffer(overrun, depth);
     if (p == nullptr) {
       // We are at the end of the stream
       if (PROTOBUF_PREDICT_FALSE(overrun != 0)) return {nullptr, true};
       GOOGLE_DCHECK(limit_ > 0);
       limit_end_ = buffer_end_;
-      // Distinquish ending on a pushed limit or ending on end-of-stream.
+      // Distinguish ending on a pushed limit or ending on end-of-stream.
       SetEndOfStream();
-      return {ptr, true};
+      return {buffer_end_, true};
     }
     limit_ -= buffer_end_ - p;  // Adjust limit_ relative to new anchor
-    ptr = p + overrun;
-    overrun = ptr - buffer_end_;
+    p += overrun;
+    overrun = p - buffer_end_;
   } while (overrun >= 0);
   limit_end_ = buffer_end_ + std::min(0, limit_);
-  return {ptr, false};
+  return {p, false};
 }
 
 const char* EpsCopyInputStream::SkipFallback(const char* ptr, int size) {
@@ -222,18 +234,6 @@
 }
 
 
-template <typename Tag, typename T>
-const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr,
-                                                  Tag expected_tag,
-                                                  RepeatedField<T>* out) {
-  do {
-    out->Add(UnalignedLoad<T>(ptr));
-    ptr += sizeof(T);
-    if (PROTOBUF_PREDICT_FALSE(ptr >= limit_end_)) return ptr;
-  } while (UnalignedLoad<Tag>(ptr) == expected_tag&& ptr += sizeof(Tag));
-  return ptr;
-}
-
 template <int>
 void byteswap(void* p);
 template <>
@@ -247,42 +247,6 @@
   *static_cast<uint64*>(p) = bswap_64(*static_cast<uint64*>(p));
 }
 
-template <typename T>
-const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size,
-                                                RepeatedField<T>* out) {
-  int nbytes = buffer_end_ + kSlopBytes - ptr;
-  while (size > nbytes) {
-    int num = nbytes / sizeof(T);
-    int old_entries = out->size();
-    out->Reserve(old_entries + num);
-    int block_size = num * sizeof(T);
-    auto dst = out->AddNAlreadyReserved(num);
-#ifdef PROTOBUF_LITTLE_ENDIAN
-    std::memcpy(dst, ptr, block_size);
-#else
-    for (int i = 0; i < num; i++)
-      dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T));
-#endif
-    ptr += block_size;
-    size -= block_size;
-    if (DoneWithCheck(&ptr, -1)) return nullptr;
-    nbytes = buffer_end_ + kSlopBytes - ptr;
-  }
-  int num = size / sizeof(T);
-  int old_entries = out->size();
-  out->Reserve(old_entries + num);
-  int block_size = num * sizeof(T);
-  auto dst = out->AddNAlreadyReserved(num);
-#ifdef PROTOBUF_LITTLE_ENDIAN
-  std::memcpy(dst, ptr, block_size);
-#else
-  for (int i = 0; i < num; i++) dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T));
-#endif
-  ptr += block_size;
-  if (size != block_size) return nullptr;
-  return ptr;
-}
-
 const char* EpsCopyInputStream::InitFrom(io::ZeroCopyInputStream* zcis) {
   zcis_ = zcis;
   const void* data;
@@ -312,6 +276,18 @@
   return buffer_;
 }
 
+const char* ParseContext::ReadSizeAndPushLimitAndDepth(const char* ptr,
+                                                       int* old_limit) {
+  int size = ReadSize(&ptr);
+  if (PROTOBUF_PREDICT_FALSE(!ptr)) {
+    *old_limit = 0;  // Make sure this isn't uninitialized even on error return
+    return nullptr;
+  }
+  *old_limit = PushLimit(ptr, size);
+  if (--depth_ < 0) return nullptr;
+  return ptr;
+}
+
 const char* ParseContext::ParseMessage(MessageLite* msg, const char* ptr) {
   return ParseMessage<MessageLite>(msg, ptr);
 }
@@ -577,3 +553,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h
index c83eed9..d858191 100644
--- a/src/google/protobuf/parse_context.h
+++ b/src/google/protobuf/parse_context.h
@@ -166,6 +166,10 @@
     }
     return AppendStringFallback(ptr, size, s);
   }
+  // Implemented in arenastring.cc
+  PROTOBUF_MUST_USE_RESULT const char* ReadArenaString(const char* ptr,
+                                                       ArenaStringPtr* s,
+                                                       Arena* arena);
 
   template <typename Tag, typename T>
   PROTOBUF_MUST_USE_RESULT const char* ReadRepeatedFixed(const char* ptr,
@@ -208,9 +212,16 @@
   bool DoneWithCheck(const char** ptr, int d) {
     GOOGLE_DCHECK(*ptr);
     if (PROTOBUF_PREDICT_TRUE(*ptr < limit_end_)) return false;
-    // No need to fetch buffer if we ended on a limit in the slop region
-    if ((*ptr - buffer_end_) == limit_) return true;
-    auto res = DoneFallback(*ptr, d);
+    int overrun = static_cast<int>(*ptr - buffer_end_);
+    GOOGLE_DCHECK_LE(overrun, kSlopBytes);  // Guaranteed by parse loop.
+    if (overrun ==
+        limit_) {  //  No need to flip buffers if we ended on a limit.
+      // If we actually overrun the buffer and next_chunk_ is null. It means
+      // the stream ended and we passed the stream end.
+      if (overrun > 0 && next_chunk_ == nullptr) *ptr = nullptr;
+      return true;
+    }
+    auto res = DoneFallback(overrun, d);
     *ptr = res.first;
     return res.second;
   }
@@ -276,8 +287,26 @@
   // systems. TODO(gerbens) do we need to set this as build flag?
   enum { kSafeStringSize = 50000000 };
 
-  std::pair<const char*, bool> DoneFallback(const char* ptr, int d);
-  const char* Next(int overrun, int d);
+  // Advances to next buffer chunk returns a pointer to the same logical place
+  // in the stream as set by overrun. Overrun indicates the position in the slop
+  // region the parse was left (0 <= overrun <= kSlopBytes). Returns true if at
+  // limit, at which point the returned pointer maybe null if there was an
+  // error. The invariant of this function is that it's guaranteed that
+  // kSlopBytes bytes can be accessed from the returned ptr. This function might
+  // advance more buffers than one in the underlying ZeroCopyInputStream.
+  std::pair<const char*, bool> DoneFallback(int overrun, int depth);
+  // Advances to the next buffer, at most one call to Next() on the underlying
+  // ZeroCopyInputStream is made. This function DOES NOT match the returned
+  // pointer to where in the slop region the parse ends, hence no overrun
+  // parameter. This is useful for string operations where you always copy
+  // to the end of the buffer (including the slop region).
+  const char* Next();
+  // overrun is the location in the slop region the stream currently is
+  // (0 <= overrun <= kSlopBytes). To prevent flipping to the next buffer of
+  // the ZeroCopyInputStream in the case the parse will end in the last
+  // kSlopBytes of the current buffer. depth is the current depth of nested
+  // groups (or negative if the use case does not need careful tracking).
+  inline const char* NextBuffer(int overrun, int depth);
   const char* SkipFallback(const char* ptr, int size);
   const char* AppendStringFallback(const char* ptr, int size, std::string* str);
   const char* ReadStringFallback(const char* ptr, int size, std::string* str);
@@ -296,16 +325,17 @@
     int chunk_size = buffer_end_ + kSlopBytes - ptr;
     do {
       GOOGLE_DCHECK(size > chunk_size);
+      if (next_chunk_ == nullptr) return nullptr;
       append(ptr, chunk_size);
       ptr += chunk_size;
       size -= chunk_size;
-      // DoneFallBack asserts it isn't called when exactly on the limit. If this
-      // happens we fail the parse, as we are at the limit and still more bytes
-      // to read.
-      if (limit_ == kSlopBytes) return nullptr;
-      auto res = DoneFallback(ptr, -1);
-      if (res.second) return nullptr;  // If done we passed the limit
-      ptr = res.first;
+      // TODO(gerbens) Next calls NextBuffer which generates buffers with
+      // overlap and thus incurs cost of copying the slop regions. This is not
+      // necessary for reading strings. We should just call Next buffers.
+      if (limit_ <= kSlopBytes) return nullptr;
+      ptr = Next();
+      if (ptr == nullptr) return nullptr;  // passed the limit
+      ptr += kSlopBytes;
       chunk_size = buffer_end_ + kSlopBytes - ptr;
     } while (size > chunk_size);
     append(ptr, size);
@@ -319,11 +349,18 @@
   // implicit weak messages. We keep these methods private and friend them.
   template <typename A>
   const char* AppendUntilEnd(const char* ptr, const A& append) {
-    while (!DoneWithCheck(&ptr, -1)) {
-      append(ptr, limit_end_ - ptr);
-      ptr = limit_end_;
+    if (ptr - buffer_end_ > limit_) return nullptr;
+    while (limit_ > kSlopBytes) {
+      size_t chunk_size = buffer_end_ + kSlopBytes - ptr;
+      append(ptr, chunk_size);
+      ptr = Next();
+      if (ptr == nullptr) return limit_end_;
+      ptr += kSlopBytes;
     }
-    return ptr;
+    auto end = buffer_end_ + limit_;
+    GOOGLE_DCHECK(end >= ptr);
+    append(ptr, end - ptr);
+    return end;
   }
 
   PROTOBUF_MUST_USE_RESULT const char* AppendString(const char* ptr,
@@ -343,6 +380,7 @@
   struct Data {
     const DescriptorPool* pool = nullptr;
     MessageFactory* factory = nullptr;
+    Arena* arena = nullptr;
   };
 
   template <typename... T>
@@ -354,7 +392,6 @@
   void TrackCorrectEnding() { group_depth_ = 0; }
 
   bool Done(const char** ptr) { return DoneWithCheck(ptr, group_depth_); }
-  bool DoneNoSlopCheck(const char** ptr) { return DoneWithCheck(ptr, -1); }
 
   int depth() const { return depth_; }
 
@@ -368,7 +405,7 @@
   const char* ParseMessage(Message* msg, const char* ptr);
 
   template <typename T>
-  PROTOBUF_MUST_USE_RESULT PROTOBUF_ALWAYS_INLINE const char* ParseGroup(
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NDEBUG_INLINE const char* ParseGroup(
       T* msg, const char* ptr, uint32 tag) {
     if (--depth_ < 0) return nullptr;
     group_depth_++;
@@ -380,6 +417,17 @@
   }
 
  private:
+  // Out-of-line routine to save space in ParseContext::ParseMessage<T>
+  //   int old;
+  //   ptr = ReadSizeAndPushLimitAndDepth(ptr, &old)
+  // is equivalent to:
+  //   int size = ReadSize(&ptr);
+  //   if (!ptr) return nullptr;
+  //   int old = PushLimit(ptr, size);
+  //   if (--depth_ < 0) return nullptr;
+  PROTOBUF_MUST_USE_RESULT const char* ReadSizeAndPushLimitAndDepth(
+      const char* ptr, int* old_limit);
+
   // The context keeps an internal stack to keep track of the recursive
   // part of the parse state.
   // Current depth of the active parser, depth counts down.
@@ -395,7 +443,7 @@
 template <uint32 tag>
 bool ExpectTag(const char* ptr) {
   if (tag < 128) {
-    return *ptr == tag;
+    return *ptr == static_cast<char>(tag);
   } else {
     static_assert(tag < 128 * 128, "We only expect tags for 1 or 2 bytes");
     char buf[2] = {static_cast<char>(tag | 0x80), static_cast<char>(tag >> 7)};
@@ -607,31 +655,109 @@
 template <typename T>
 PROTOBUF_MUST_USE_RESULT const char* ParseContext::ParseMessage(
     T* msg, const char* ptr) {
-  int size = ReadSize(&ptr);
-  if (!ptr) return nullptr;
-  auto old = PushLimit(ptr, size);
-  if (--depth_ < 0) return nullptr;
-  ptr = msg->_InternalParse(ptr, this);
-  if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr;
+  int old;
+  ptr = ReadSizeAndPushLimitAndDepth(ptr, &old);
+  ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr;
   depth_++;
   if (!PopLimit(old)) return nullptr;
   return ptr;
 }
 
+template <typename Tag, typename T>
+const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr,
+                                                  Tag expected_tag,
+                                                  RepeatedField<T>* out) {
+  do {
+    out->Add(UnalignedLoad<T>(ptr));
+    ptr += sizeof(T);
+    if (PROTOBUF_PREDICT_FALSE(ptr >= limit_end_)) return ptr;
+  } while (UnalignedLoad<Tag>(ptr) == expected_tag && (ptr += sizeof(Tag)));
+  return ptr;
+}
+
+template <typename T>
+const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size,
+                                                RepeatedField<T>* out) {
+  int nbytes = buffer_end_ + kSlopBytes - ptr;
+  while (size > nbytes) {
+    int num = nbytes / sizeof(T);
+    int old_entries = out->size();
+    out->Reserve(old_entries + num);
+    int block_size = num * sizeof(T);
+    auto dst = out->AddNAlreadyReserved(num);
+#ifdef PROTOBUF_LITTLE_ENDIAN
+    std::memcpy(dst, ptr, block_size);
+#else
+    for (int i = 0; i < num; i++)
+      dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T));
+#endif
+    size -= block_size;
+    if (limit_ <= kSlopBytes) return nullptr;
+    ptr = Next();
+    if (ptr == nullptr) return nullptr;
+    ptr += kSlopBytes - (nbytes - block_size);
+    nbytes = buffer_end_ + kSlopBytes - ptr;
+  }
+  int num = size / sizeof(T);
+  int old_entries = out->size();
+  out->Reserve(old_entries + num);
+  int block_size = num * sizeof(T);
+  auto dst = out->AddNAlreadyReserved(num);
+#ifdef PROTOBUF_LITTLE_ENDIAN
+  std::memcpy(dst, ptr, block_size);
+#else
+  for (int i = 0; i < num; i++) dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T));
+#endif
+  ptr += block_size;
+  if (size != block_size) return nullptr;
+  return ptr;
+}
+
+template <typename Add>
+const char* ReadPackedVarintArray(const char* ptr, const char* end, Add add) {
+  while (ptr < end) {
+    uint64 varint;
+    ptr = VarintParse(ptr, &varint);
+    if (ptr == nullptr) return nullptr;
+    add(varint);
+  }
+  return ptr;
+}
+
 template <typename Add>
 const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) {
   int size = ReadSize(&ptr);
   if (ptr == nullptr) return nullptr;
-  auto old = PushLimit(ptr, size);
-  if (old < 0) return nullptr;
-  while (!DoneWithCheck(&ptr, -1)) {
-    uint64 varint;
-    ptr = VarintParse(ptr, &varint);
-    if (!ptr) return nullptr;
-    add(varint);
+  int chunk_size = buffer_end_ - ptr;
+  while (size > chunk_size) {
+    ptr = ReadPackedVarintArray(ptr, buffer_end_, add);
+    if (ptr == nullptr) return nullptr;
+    int overrun = ptr - buffer_end_;
+    GOOGLE_DCHECK(overrun >= 0 && overrun <= kSlopBytes);
+    if (size - chunk_size <= kSlopBytes) {
+      // The current buffer contains all the information needed, we don't need
+      // to flip buffers. However we must parse from a buffer with enough space
+      // so we are not prone to a buffer overflow.
+      char buf[kSlopBytes + 10] = {};
+      std::memcpy(buf, buffer_end_, kSlopBytes);
+      GOOGLE_CHECK_LE(size - chunk_size, kSlopBytes);
+      auto end = buf + (size - chunk_size);
+      auto res = ReadPackedVarintArray(buf + overrun, end, add);
+      if (res == nullptr || res != end) return nullptr;
+      return buffer_end_ + (res - buf);
+    }
+    size -= overrun + chunk_size;
+    GOOGLE_DCHECK_GT(size, 0);
+    // We must flip buffers
+    if (limit_ <= kSlopBytes) return nullptr;
+    ptr = Next();
+    if (ptr == nullptr) return nullptr;
+    ptr += overrun;
+    chunk_size = buffer_end_ - ptr;
   }
-  if (!PopLimit(old)) return nullptr;
-  return ptr;
+  auto end = ptr + size;
+  ptr = ReadPackedVarintArray(ptr, end, add);
+  return end == ptr ? ptr : nullptr;
 }
 
 // Helper for verification of utf8
@@ -744,11 +870,9 @@
     void* object, const char* ptr, ParseContext* ctx);
 
 template <typename T>
-PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-PROTOBUF_MUST_USE_RESULT const
-    char* PackedEnumParser(void* object, const char* ptr, ParseContext* ctx,
-                           bool (*is_valid)(int), InternalMetadata* metadata,
-                           int field_num) {
+PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser(
+    void* object, const char* ptr, ParseContext* ctx, bool (*is_valid)(int),
+    InternalMetadata* metadata, int field_num) {
   return ctx->ReadPackedVarint(
       ptr, [object, is_valid, metadata, field_num](uint64 val) {
         if (is_valid(val)) {
@@ -760,12 +884,10 @@
 }
 
 template <typename T>
-PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-PROTOBUF_MUST_USE_RESULT const
-    char* PackedEnumParserArg(void* object, const char* ptr, ParseContext* ctx,
-                              bool (*is_valid)(const void*, int),
-                              const void* data, InternalMetadata* metadata,
-                              int field_num) {
+PROTOBUF_MUST_USE_RESULT const char* PackedEnumParserArg(
+    void* object, const char* ptr, ParseContext* ctx,
+    bool (*is_valid)(const void*, int), const void* data,
+    InternalMetadata* metadata, int field_num) {
   return ctx->ReadPackedVarint(
       ptr, [object, is_valid, data, metadata, field_num](uint64 val) {
         if (is_valid(data, val)) {
diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h
index 555fd4e..4c09eb1 100644
--- a/src/google/protobuf/port.h
+++ b/src/google/protobuf/port.h
@@ -37,7 +37,4 @@
 #define GOOGLE_PROTOBUF_PORT_H__
 
 
-#include <google/protobuf/stubs/port.h>
-
-
 #endif  // GOOGLE_PROTOBUF_PORT_H__
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index 81080c8..82e98d9 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -48,99 +48,85 @@
 // detect/prohibit anytime it is #included twice without a corresponding
 // #undef.
 
-// These macros are private and should always be
-// ::util::RetrieveErrorSpace(*this) headers. If any of these errors fire, you
-// should either properly #include port_undef.h at the end of your header that
-// #includes port.h, or don't #include port.h twice in a .cc file.
-#ifdef PROTOBUF_NAMESPACE
-#error PROTOBUF_NAMESPACE was previously defined
+// The definitions in this file are intended to be portable across Clang,
+// GCC, and MSVC. Function-like macros are usable without an #ifdef guard.
+// Syntax macros (for example, attributes) are always defined, although
+// they may be empty.
+
+// Portable fallbacks for C++20 feature test macros:
+// https://en.cppreference.com/w/cpp/feature_test
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(x) 0
+#define PROTOBUF_has_cpp_attribute_DEFINED_
 #endif
-#ifdef PROTOBUF_NAMESPACE_ID
-#error PROTOBUF_NAMESPACE_ID was previously defined
+
+// Portable fallback for Clang's __has_feature macro:
+// https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension
+#ifndef __has_feature
+#define __has_feature(x) 0
+#define PROTOBUF_has_feature_DEFINED_
 #endif
-#ifdef PROTOBUF_ALWAYS_INLINE
-#error PROTOBUF_ALWAYS_INLINE was previously defined
+
+// Portable fallback for Clang's __has_warning macro:
+#ifndef __has_warning
+#define __has_warning(x) 0
+#define PROTOBUF_has_warning_DEFINED_
 #endif
-#ifdef PROTOBUF_COLD
-#error PROTOBUF_COLD was previously defined
+
+// Portable fallbacks for the __has_attribute macro (GCC and Clang):
+// https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#define PROTOBUF_has_attribute_DEFINED_
 #endif
-#ifdef PROTOBUF_NOINLINE
-#error PROTOBUF_NOINLINE was previously defined
+
+// Portable fallback for __has_builtin (GCC and Clang):
+// https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin
+// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fbuiltin.html
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#define PROTOBUF_has_builtin_DEFINED_
 #endif
-#ifdef PROTOBUF_SECTION_VARIABLE
-#error PROTOBUF_SECTION_VARIABLE was previously defined
+
+// Portable check for GCC minimum version:
+// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) \
+    && defined(__GNUC_PATCHLEVEL__)
+#  define PROTOBUF_GNUC_MIN(x, y) \
+  (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
+#else
+#  define PROTOBUF_GNUC_MIN(x, y) 0
 #endif
-#ifdef PROTOBUF_DEPRECATED
-#error PROTOBUF_DEPRECATED was previously defined
-#endif
-#ifdef PROTOBUF_DEPRECATED_MSG
-#error PROTOBUF_DEPRECATED_MSG was previously defined
-#endif
-#ifdef PROTOBUF_FUNC_ALIGN
-#error PROTOBUF_FUNC_ALIGN was previously defined
-#endif
-#ifdef PROTOBUF_RETURNS_NONNULL
-#error PROTOBUF_RETURNS_NONNULL was previously defined
-#endif
-#ifdef PROTOBUF_ATTRIBUTE_REINITIALIZES
-#error PROTOBUF_ATTRIBUTE_REINITIALIZES was previously defined
-#endif
-#ifdef PROTOBUF_RTTI
-#error PROTOBUF_RTTI was previously defined
-#endif
+
+// Future versions of protobuf will include breaking changes to some APIs.
+// This macro can be set to enable these API changes ahead of time, so that
+// user code can be updated before upgrading versions of protobuf.
+// #define PROTOBUF_FUTURE_BREAKING_CHANGES 1
+
 #ifdef PROTOBUF_VERSION
 #error PROTOBUF_VERSION was previously defined
 #endif
-#ifdef PROTOBUF_VERSION_SUFFIX
-#error PROTOBUF_VERSION_SUFFIX was previously defined
-#endif
+#define PROTOBUF_VERSION 3017003
+
 #ifdef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC
 #error PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC was previously defined
 #endif
+#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3017000
+
 #ifdef PROTOBUF_MIN_PROTOC_VERSION
 #error PROTOBUF_MIN_PROTOC_VERSION was previously defined
 #endif
-#ifdef PROTOBUF_PREDICT_TRUE
-#error PROTOBUF_PREDICT_TRUE was previously defined
-#endif
-#ifdef PROTOBUF_PREDICT_FALSE
-#error PROTOBUF_PREDICT_FALSE was previously defined
-#endif
-#ifdef PROTOBUF_FIELD_OFFSET
-#error PROTOBUF_FIELD_OFFSET was previously defined
-#endif
-#ifdef PROTOBUF_LL_FORMAT
-#error PROTOBUF_LL_FORMAT was previously defined
-#endif
-#ifdef PROTOBUF_GUARDED_BY
-#error PROTOBUF_GUARDED_BY was previously defined
-#endif
-#ifdef PROTOBUF_LONGLONG
-#error PROTOBUF_LONGLONG was previously defined
-#endif
-#ifdef PROTOBUF_ULONGLONG
-#error PROTOBUF_ULONGLONG was previously defined
-#endif
-#ifdef PROTOBUF_FALLTHROUGH_INTENDED
-#error PROTOBUF_FALLTHROUGH_INTENDED was previously defined
-#endif
-#ifdef PROTOBUF_EXPORT
-#error PROTOBUF_EXPORT was previously defined
-#endif
-#ifdef PROTOC_EXPORT
-#error PROTOC_EXPORT was previously defined
-#endif
-#ifdef PROTOBUF_MUST_USE_RESULT
-#error PROTOBUF_MUST_USE_RESULT was previously defined
-#endif
-#ifdef PROTOBUF_UNUSED
-#error PROTOBUF_UNUSED was previously defined
-#endif
-#ifdef PROTOBUF_FINAL
-#error PROTOBUF_FINAL was previously defined
-#endif
+#define PROTOBUF_MIN_PROTOC_VERSION 3017000
 
+#ifdef PROTOBUF_VERSION_SUFFIX
+#error PROTOBUF_VERSION_SUFFIX was previously defined
+#endif
+#define PROTOBUF_VERSION_SUFFIX ""
 
+#if defined(PROTOBUF_NAMESPACE) || defined(PROTOBUF_NAMESPACE_ID)
+#error PROTOBUF_NAMESPACE or PROTOBUF_NAMESPACE_ID was previously defined
+#endif
 #define PROTOBUF_NAMESPACE "google::protobuf"
 #define PROTOBUF_NAMESPACE_ID google::protobuf
 #define PROTOBUF_NAMESPACE_OPEN \
@@ -150,178 +136,188 @@
   } /* namespace protobuf */     \
   } /* namespace google */
 
-#if defined(__GNUC__) || defined(__clang__)
-#define PROTOBUF_DEPRECATED __attribute__((deprecated))
-#define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated))
-#define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-#elif defined(_MSC_VER)
-#define PROTOBUF_DEPRECATED __declspec(deprecated)
-#define PROTOBUF_DEPRECATED_ENUM
-#define PROTOBUF_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
+#ifdef PROTOBUF_ALWAYS_INLINE
+#error PROTOBUF_ALWAYS_INLINE was previously defined
 #endif
-
-#define PROTOBUF_SECTION_VARIABLE(x)
-#define PROTOBUF_MUST_USE_RESULT
-
-// ----------------------------------------------------------------------------
-// Annotations:  Some parts of the code have been annotated in ways that might
-//   be useful to some compilers or tools, but are not supported universally.
-//   You can #define these annotations yourself if the default implementation
-//   is not right for you.
-
-#ifdef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-#define PROTOBUF_ALWAYS_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-#else
-#if defined(__GNUC__) && \
-    (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
 // For functions we want to force inline.
-// Introduced in gcc 3.1.
-#define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline))
+#if defined(PROTOBUF_NO_INLINE)
+# define PROTOBUF_ALWAYS_INLINE
+#elif PROTOBUF_GNUC_MIN(3, 1)
+# define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline))
+#elif defined(_MSC_VER)
+# define PROTOBUF_ALWAYS_INLINE __forceinline
 #else
-// Other compilers will have to figure it out for themselves.
-#define PROTOBUF_ALWAYS_INLINE
-#endif
+# define PROTOBUF_ALWAYS_INLINE
 #endif
 
-#ifdef GOOGLE_ATTRIBUTE_NOINLINE
-#define PROTOBUF_NOINLINE GOOGLE_ATTRIBUTE_NOINLINE
+#ifdef PROTOBUF_NDEBUG_INLINE
+#error PROTOBUF_NDEBUG_INLINE was previously defined
+#endif
+// Avoid excessive inlining in non-optimized builds. Without other optimizations
+// the inlining is not going to provide benefits anyway and the huge resulting
+// functions, especially in the proto-generated serialization functions, produce
+// stack frames so large that many tests run into stack overflows (b/32192897).
+#if defined(NDEBUG) || (defined(_MSC_VER) && !defined(_DEBUG))
+# define PROTOBUF_NDEBUG_INLINE PROTOBUF_ALWAYS_INLINE
 #else
-#if defined(__GNUC__) && \
-    (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-// For functions we want to force not inline.
-// Introduced in gcc 3.1.
-#define PROTOBUF_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+# define PROTOBUF_NDEBUG_INLINE
+#endif
+
+// Note that PROTOBUF_NOINLINE is an attribute applied to functions, to prevent
+// them from being inlined by the compiler. This is different from
+// PROTOBUF_NO_INLINE, which is a user-supplied macro that disables forced
+// inlining by PROTOBUF_(ALWAYS|NDEBUG)_INLINE.
+#ifdef PROTOBUF_NOINLINE
+#error PROTOBUF_NOINLINE was previously defined
+#endif
+#if PROTOBUF_GNUC_MIN(3, 1)
+# define PROTOBUF_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER)
 // Seems to have been around since at least Visual Studio 2005
-#define PROTOBUF_NOINLINE __declspec(noinline)
-#else
-// Other compilers will have to figure it out for themselves.
-#define PROTOBUF_NOINLINE
-#endif
+# define PROTOBUF_NOINLINE __declspec(noinline)
 #endif
 
-#ifdef GOOGLE_ATTRIBUTE_FUNC_ALIGN
-#define PROTOBUF_FUNC_ALIGN GOOGLE_ATTRIBUTE_FUNC_ALIGN
+#ifdef PROTOBUF_MUSTTAIL
+#error PROTOBUF_MUSTTAIL was previously defined
+#endif
+#ifdef PROTOBUF_TAILCALL
+#error PROTOBUF_TAILCALL was previously defined
+#endif
+#if __has_cpp_attribute(clang::musttail) && \
+  !defined(_ARCH_PPC) && !defined(__wasm__)
+#  ifndef PROTO2_OPENSOURCE
+// Compilation fails on powerpc64le: b/187985113
+#  endif
+#define PROTOBUF_MUSTTAIL [[clang::musttail]]
+#define PROTOBUF_TAILCALL true
 #else
-#if defined(__clang__) || \
-    defined(__GNUC__) &&  \
-        (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
-// Function alignment attribute introduced in gcc 4.3
+#define PROTOBUF_MUSTTAIL
+#define PROTOBUF_TAILCALL false
+#endif
+
+#ifdef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED
+#error PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED was previously defined
+#endif
+#if __has_attribute(exclusive_locks_required)
+#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...) \
+  __attribute__((exclusive_locks_required(__VA_ARGS__)))
+#else
+#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...)
+#endif
+
+#ifdef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS
+#error PROTOBUF_NO_THREAD_SAFETY_ANALYSIS was previously defined
+#endif
+#if __has_attribute(no_thread_safety_analysis)
+#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS \
+  __attribute__((no_thread_safety_analysis))
+#else
+#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS
+#endif
+
+#ifdef PROTOBUF_GUARDED_BY
+#error PROTOBUF_GUARDED_BY was previously defined
+#endif
+#if __has_attribute(guarded_by)
+#define PROTOBUF_GUARDED_BY(x) __attribute__((guarded_by(x)))
+#else
+#define PROTOBUF_GUARDED_BY(x)
+#endif
+
+#ifdef PROTOBUF_LOCKS_EXCLUDED
+#error PROTOBUF_LOCKS_EXCLUDED was previously defined
+#endif
+#if __has_attribute(locks_excluded)
+#define PROTOBUF_LOCKS_EXCLUDED(...) \
+  __attribute__((locks_excluded(__VA_ARGS__)))
+#else
+#define PROTOBUF_LOCKS_EXCLUDED(...)
+#endif
+
+#ifdef PROTOBUF_COLD
+#error PROTOBUF_COLD was previously defined
+#endif
+#if __has_attribute(cold) || PROTOBUF_GNUC_MIN(4, 3)
+# define PROTOBUF_COLD __attribute__((cold))
+#else
+# define PROTOBUF_COLD
+#endif
+
+#ifdef PROTOBUF_SECTION_VARIABLE
+#error PROTOBUF_SECTION_VARIABLE was previously defined
+#endif
+#define PROTOBUF_SECTION_VARIABLE(x)
+
+#if defined(PROTOBUF_DEPRECATED)
+#error PROTOBUF_DEPRECATED was previously defined
+#endif
+#if defined(PROTOBUF_DEPRECATED_MSG)
+#error PROTOBUF_DEPRECATED_MSG was previously defined
+#endif
+#if __has_attribute(deprecated) || PROTOBUF_GNUC_MIN(3, 0)
+# define PROTOBUF_DEPRECATED __attribute__((deprecated))
+# define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
+#elif defined(_MSC_VER)
+# define PROTOBUF_DEPRECATED __declspec(deprecated)
+# define PROTOBUF_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
+#else
+# define PROTOBUF_DEPRECATED
+# define PROTOBUF_DEPRECATED_MSG(msg)
+#endif
+
+#if defined(PROTOBUF_DEPRECATED_ENUM)
+#error PROTOBUF_DEPRECATED_ENUM was previously defined
+#endif
+#if defined(__clang__) || PROTOBUF_GNUC_MIN(6, 0)
+// https://gcc.gnu.org/gcc-6/changes.html
+# define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated))
+#else
+# define PROTOBUF_DEPRECATED_ENUM
+#endif
+
+#ifdef PROTOBUF_FUNC_ALIGN
+#error PROTOBUF_FUNC_ALIGN was previously defined
+#endif
+#if __has_attribute(aligned) || PROTOBUF_GNUC_MIN(4, 3)
 #define PROTOBUF_FUNC_ALIGN(bytes) __attribute__((aligned(bytes)))
 #else
 #define PROTOBUF_FUNC_ALIGN(bytes)
 #endif
-#endif
 
-#ifdef GOOGLE_PREDICT_TRUE
-#define PROTOBUF_PREDICT_TRUE GOOGLE_PREDICT_TRUE
-#else
-#ifdef __GNUC__
-// Provided at least since GCC 3.0.
-#define PROTOBUF_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
-#else
-#define PROTOBUF_PREDICT_TRUE(x) (x)
+#ifdef PROTOBUF_RETURNS_NONNULL
+#error PROTOBUF_RETURNS_NONNULL was previously defined
 #endif
-#endif
-
-#ifdef GOOGLE_PREDICT_FALSE
-#define PROTOBUF_PREDICT_FALSE GOOGLE_PREDICT_FALSE
-#else
-#ifdef __GNUC__
-// Provided at least since GCC 3.0.
-#define PROTOBUF_PREDICT_FALSE(x) (__builtin_expect(x, 0))
-#else
-#define PROTOBUF_PREDICT_FALSE(x) (x)
-#endif
-#endif
-
-#ifdef GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL
-#define PROTOBUF_RETURNS_NONNULL GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL
-#else
-#ifdef __GNUC__
+#if __has_attribute(returns_nonnull) || PROTOBUF_GNUC_MIN(4, 9)
 #define PROTOBUF_RETURNS_NONNULL __attribute__((returns_nonnull))
 #else
 #define PROTOBUF_RETURNS_NONNULL
 #endif
-#endif
 
-#if defined(__has_cpp_attribute)
+#ifdef PROTOBUF_ATTRIBUTE_REINITIALIZES
+#error PROTOBUF_ATTRIBUTE_REINITIALIZES was previously defined
+#endif
 #if __has_cpp_attribute(clang::reinitializes)
 #define PROTOBUF_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
-#endif
-#endif
-#ifndef PROTOBUF_ATTRIBUTE_REINITIALIZES
+#else
 #define PROTOBUF_ATTRIBUTE_REINITIALIZES
 #endif
 
-#define PROTOBUF_GUARDED_BY(x)
-#define PROTOBUF_COLD
-
-// Copied from ABSL.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
-#define PROTOBUF_FALLTHROUGH_INTENDED [[clang::fallthrough]]
-#endif
-#elif defined(__GNUC__) && __GNUC__ >= 7
-#define PROTOBUF_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
-#endif
-
-#ifndef PROTOBUF_FALLTHROUGH_INTENDED
-#define PROTOBUF_FALLTHROUGH_INTENDED
-#endif
-
-#if defined(__has_cpp_attribute)
-#define HAS_ATTRIBUTE(attr) __has_cpp_attribute(attr)
-#else
-#define HAS_ATTRIBUTE(attr) 0
-#endif
-
-#if HAS_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
-#define PROTOBUF_UNUSED __attribute__((__unused__))
-#else
-#define PROTOBUF_UNUSED
-#endif
-
-#undef HAS_ATTRIBUTE
-
-#ifdef _MSC_VER
-#define PROTOBUF_LONGLONG(x) x##I64
-#define PROTOBUF_ULONGLONG(x) x##UI64
-#define PROTOBUF_LL_FORMAT "I64"  // As in printf("%I64d", ...)
-#else
-// By long long, we actually mean int64.
-#define PROTOBUF_LONGLONG(x) x##LL
-#define PROTOBUF_ULONGLONG(x) x##ULL
-// Used to format real long long integers.
-#define PROTOBUF_LL_FORMAT \
-  "ll"  // As in "%lld". Note that "q" is poor form also.
-#endif
-
-
-// Shared google3/opensource definitions. //////////////////////////////////////
-
-#define PROTOBUF_VERSION 3011004
-#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3011000
-#define PROTOBUF_MIN_PROTOC_VERSION 3011000
-#define PROTOBUF_VERSION_SUFFIX ""
-
 // The minimum library version which works with the current version of the
 // headers.
-#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3011000
+#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3017000
 
+#ifdef PROTOBUF_RTTI
+#error PROTOBUF_RTTI was previously defined
+#endif
 #if defined(GOOGLE_PROTOBUF_NO_RTTI) && GOOGLE_PROTOBUF_NO_RTTI
 #define PROTOBUF_RTTI 0
-#elif defined(__has_feature)
-// https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension
-#define PROTOBUF_RTTI __has_feature(cxx_rtti)
-#elif !defined(__cxx_rtti)
-// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros#C.2B.2B98
-#define PROTOBUF_RTTI 0
-#elif defined(__GNUC__) && !defined(__GXX_RTTI)
-#https:  // gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
-#define PROTOBUF_RTTI 0
-#else
+#elif __has_feature(cxx_rtti)
 #define PROTOBUF_RTTI 1
+#elif defined(__cxx_rtti)
+// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros#C.2B.2B98
+#define PROTOBUF_RTTI 1
+#else
+#define PROTOBUF_RTTI 0
 #endif
 
 // Returns the offset of the given field within the given aggregate type.
@@ -332,17 +328,19 @@
 // which the offsets of the direct fields of a class are non-constant.
 // Fields inherited from superclasses *can* have non-constant offsets,
 // but that's not what this macro will be used for.
+#ifdef PROTOBUF_FIELD_OFFSET
+#error PROTOBUF_FIELD_OFFSET was previously defined
+#endif
 #if defined(__clang__)
 // For Clang we use __builtin_offsetof() and suppress the warning,
 // to avoid Control Flow Integrity and UBSan vptr sanitizers from
-// crashing while trying to validate the invalid reinterpet_casts.
+// crashing while trying to validate the invalid reinterpret_casts.
 #define PROTOBUF_FIELD_OFFSET(TYPE, FIELD)                   \
   _Pragma("clang diagnostic push")                           \
   _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
   __builtin_offsetof(TYPE, FIELD)                            \
   _Pragma("clang diagnostic pop")
-#elif defined(__GNUC__) && \
-          (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#elif PROTOBUF_GNUC_MIN(4, 8)
 #define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) __builtin_offsetof(TYPE, FIELD)
 #else  // defined(__clang__)
 // Note that we calculate relative to the pointer value 16 here since if we
@@ -355,243 +353,92 @@
                          reinterpret_cast<const char*>(16))
 #endif
 
-#if defined(PROTOBUF_USE_DLLS)
-  #if defined(_MSC_VER)
-    #ifdef LIBPROTOBUF_EXPORTS
-    #define PROTOBUF_EXPORT __declspec(dllexport)
-    #else
-    #define PROTOBUF_EXPORT __declspec(dllimport)
-    #endif
-    #ifdef LIBPROTOC_EXPORTS
-    #define PROTOC_EXPORT __declspec(dllexport)
-    #else
-    #define PROTOC_EXPORT __declspec(dllimport)
-    #endif
-  #else  // defined(_MSC_VER)
-    #ifdef LIBPROTOBUF_EXPORTS
-      #define PROTOBUF_EXPORT __attribute__((visibility("default")))
-    #else
-      #define PROTOBUF_EXPORT
-    #endif
-    #ifdef LIBPROTOC_EXPORTS
-      #define PROTOC_EXPORT   __attribute__((visibility("default")))
-    #else
-      #define PROTOC_EXPORT
-    #endif
-  #endif
-#else  // defined(PROTOBUF_USE_DLLS)
-  #define PROTOBUF_EXPORT
-  #define PROTOC_EXPORT
+#ifdef PROTOBUF_EXPORT
+#error PROTOBUF_EXPORT was previously defined
 #endif
 
+#if defined(PROTOBUF_USE_DLLS) && defined(_MSC_VER)
+# if defined(LIBPROTOBUF_EXPORTS)
+#  define PROTOBUF_EXPORT __declspec(dllexport)
+#  define PROTOBUF_EXPORT_TEMPLATE_DECLARE
+#  define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllexport)
+# else
+#  define PROTOBUF_EXPORT __declspec(dllimport)
+#  define PROTOBUF_EXPORT_TEMPLATE_DECLARE
+#  define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllimport)
+# endif  // defined(LIBPROTOBUF_EXPORTS)
+#elif defined(PROTOBUF_USE_DLLS) && defined(LIBPROTOBUF_EXPORTS)
+# define PROTOBUF_EXPORT __attribute__((visibility("default")))
+# define PROTOBUF_EXPORT_TEMPLATE_DECLARE __attribute__((visibility("default")))
+# define PROTOBUF_EXPORT_TEMPLATE_DEFINE
+#else
+# define PROTOBUF_EXPORT
+# define PROTOBUF_EXPORT_TEMPLATE_DECLARE
+# define PROTOBUF_EXPORT_TEMPLATE_DEFINE
+#endif
 
-// This portion provides macros for using FOO_EXPORT macros with explicit
-// template instantiation declarations and definitions.
-// Generally, the FOO_EXPORT macros are used at declarations,
-// and GCC requires them to be used at explicit instantiation declarations,
-// but MSVC requires __declspec(dllexport) to be used at the explicit
-// instantiation definitions instead.
+#ifdef PROTOC_EXPORT
+#error PROTOC_EXPORT was previously defined
+#endif
 
-// Usage
-//
-// In a header file, write:
-//
-//  extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(FOO_EXPORT) foo<bar>;
-//
-// In a source file, write:
-//
-//  template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(FOO_EXPORT) foo<bar>;
-//
-// Where FOO_EXPORT is either PROTOBUF_EXPORT or PROTOC_EXPORT
+#if defined(PROTOBUF_USE_DLLS) && defined(_MSC_VER)
+# if defined(LIBPROTOC_EXPORTS)
+#  define PROTOC_EXPORT __declspec(dllexport)
+# else
+#  define PROTOC_EXPORT __declspec(dllimport)
+# endif  // defined(LIBPROTOC_EXPORTS)
+#elif defined(PROTOBUF_USE_DLLS) && defined(LIBPROTOBUF_EXPORTS)
+# define PROTOC_EXPORT __attribute__((visibility("default")))
+#else
+# define PROTOC_EXPORT
+#endif
 
-// Implementation notes
-//
-// The implementation of these macros uses some subtle macro semantics to
-// detect what the provided FOO_EXPORT value was defined as and then
-// to dispatch to appropriate macro definitions.  Unfortunately,
-// MSVC's C preprocessor is rather non-compliant and requires special
-// care to make it work.
-//
-// Issue 1.
-//
-//   #define F(x)
-//   F()
-//
-// MSVC emits warning C4003 ("not enough actual parameters for macro
-// 'F'), even though it's a valid macro invocation.  This affects the
-// macros below that take just an "export" parameter, because export
-// may be empty.
-//
-// As a workaround, we can add a dummy parameter and arguments:
-//
-//   #define F(x,_)
-//   F(,)
-//
-// Issue 2.
-//
-//   #define F(x) G##x
-//   #define Gj() ok
-//   F(j())
-//
-// The correct replacement for "F(j())" is "ok", but MSVC replaces it
-// with "Gj()".  As a workaround, we can pass the result to an
-// identity macro to force MSVC to look for replacements again.  (This
-// is why PROTOBUF_EXPORT_TEMPLATE_STYLE_3 exists.)
+#if defined(PROTOBUF_PREDICT_TRUE) || defined(PROTOBUF_PREDICT_FALSE)
+#error PROTOBUF_PREDICT_(TRUE|FALSE) was previously defined
+#endif
+#if PROTOBUF_GNUC_MIN(3, 0)
+# define PROTOBUF_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+# define PROTOBUF_PREDICT_FALSE(x) (__builtin_expect((x), 0))
+#else
+# define PROTOBUF_PREDICT_TRUE(x) (x)
+# define PROTOBUF_PREDICT_FALSE(x) (x)
+#endif
 
-#define PROTOBUF_EXPORT_TEMPLATE_DECLARE(export) \
-  PROTOBUF_EXPORT_TEMPLATE_INVOKE( \
-    DECLARE, PROTOBUF_EXPORT_TEMPLATE_STYLE(export, ), export)
-#define PROTOBUF_EXPORT_TEMPLATE_DEFINE(export) \
-  PROTOBUF_EXPORT_TEMPLATE_INVOKE( \
-    DEFINE, PROTOBUF_EXPORT_TEMPLATE_STYLE(export, ), export)
+#ifdef PROTOBUF_MUST_USE_RESULT
+#error PROTOBUF_MUST_USE_RESULT was previously defined
+#endif
+# define PROTOBUF_MUST_USE_RESULT
 
-// INVOKE is an internal helper macro to perform parameter replacements
-// and token pasting to chain invoke another macro.  E.g.,
-//     PROTOBUF_EXPORT_TEMPLATE_INVOKE(DECLARE, DEFAULT, FOO_EXPORT)
-// will export to call
-//     PROTOBUF_EXPORT_TEMPLATE_DECLARE_DEFAULT(FOO_EXPORT, )
-// (but with FOO_EXPORT expanded too).
-#define PROTOBUF_EXPORT_TEMPLATE_INVOKE(which, style, export) \
-  PROTOBUF_EXPORT_TEMPLATE_INVOKE_2(which, style, export)
-#define PROTOBUF_EXPORT_TEMPLATE_INVOKE_2(which, style, export) \
-  PROTOBUF_EXPORT_TEMPLATE_##which##_##style(export, )
+#ifdef PROTOBUF_MUST_USE_EXTRACT_RESULT
+#error PROTOBUF_MUST_USE_EXTRACT_RESULT was previously defined
+#endif
 
-// Default style is to apply the FOO_EXPORT macro at declaration sites.
-#define PROTOBUF_EXPORT_TEMPLATE_DECLARE_DEFAULT(export, _) export
-#define PROTOBUF_EXPORT_TEMPLATE_DEFINE_DEFAULT(export, _)
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+#error PROTOBUF_FORCE_COPY_IN_RELEASE was previously defined
+#endif
 
-// The "MSVC hack" style is used when FOO_EXPORT is defined
-// as __declspec(dllexport), which MSVC requires to be used at
-// definition sites instead.
-#define PROTOBUF_EXPORT_TEMPLATE_DECLARE_MSVC_HACK(export, _)
-#define PROTOBUF_EXPORT_TEMPLATE_DEFINE_MSVC_HACK(export, _) export
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+#error PROTOBUF_FORCE_COPY_IN_SWAP was previously defined
+#endif
 
-// PROTOBUF_EXPORT_TEMPLATE_STYLE is an internal helper macro that identifies
-// which export style needs to be used for the provided FOO_EXPORT macro
-// definition.  "", "__attribute__(...)", and "__declspec(dllimport)" are
-// mapped to "DEFAULT"; while "__declspec(dllexport)" is mapped to "MSVC_HACK".
-//
-// It's implemented with token pasting to transform the __attribute__ and
-// __declspec annotations into macro invocations.  E.g., if FOO_EXPORT is
-// defined as "__declspec(dllimport)", it undergoes the following sequence of
-// macro substitutions:
-//     PROTOBUF_EXPORT_TEMPLATE_STYLE(FOO_EXPORT, )
-//     PROTOBUF_EXPORT_TEMPLATE_STYLE_2(__declspec(dllimport), )
-//     PROTOBUF_EXPORT_TEMPLATE_STYLE_3(
-//       PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport))
-//     PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport)
-//     PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport
-//     DEFAULT
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE(export, _) \
-  PROTOBUF_EXPORT_TEMPLATE_STYLE_2(export, )
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE_2(export, _) \
-  PROTOBUF_EXPORT_TEMPLATE_STYLE_3(                 \
-      PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA##export)
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE_3(style) style
-
-// Internal helper macros for PROTOBUF_EXPORT_TEMPLATE_STYLE.
-//
-// XXX: C++ reserves all identifiers containing "__" for the implementation,
-// but "__attribute__" and "__declspec" already contain "__" and the token-paste
-// operator can only add characters; not remove them.  To minimize the risk of
-// conflict with implementations, we include "foj3FJo5StF0OvIzl7oMxA" (a random
-// 128-bit string, encoded in Base64) in the macro name.
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA DEFAULT
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__(...) \
-  DEFAULT
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec(arg) \
-  PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_##arg
-
-// Internal helper macros for PROTOBUF_EXPORT_TEMPLATE_STYLE.
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport MSVC_HACK
-#define PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport DEFAULT
-
-// Sanity checks.
-//
-// PROTOBUF_EXPORT_TEMPLATE_TEST uses the same macro invocation pattern as
-// PROTOBUF_EXPORT_TEMPLATE_DECLARE and PROTOBUF_EXPORT_TEMPLATE_DEFINE do to
-// check that they're working correctly.  When they're working correctly, the
-// sequence of macro replacements should go something like:
-//
-//     PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
-//
-//     static_assert(PROTOBUF_EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
-//         PROTOBUF_EXPORT_TEMPLATE_STYLE(__declspec(dllimport), ),
-//         __declspec(dllimport)), "__declspec(dllimport)");
-//
-//     static_assert(PROTOBUF_EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
-//         DEFAULT, __declspec(dllimport)), "__declspec(dllimport)");
-//
-//     static_assert(PROTOBUF_EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(
-//         __declspec(dllimport)), "__declspec(dllimport)");
-//
-//     static_assert(true, "__declspec(dllimport)");
-//
-// When they're not working correctly, a syntax error should occur instead.
-#define PROTOBUF_EXPORT_TEMPLATE_TEST(want, export)                        \
-  static_assert(PROTOBUF_EXPORT_TEMPLATE_INVOKE(                           \
-                    TEST_##want, PROTOBUF_EXPORT_TEMPLATE_STYLE(export, ), \
-                    export), #export)
-#define PROTOBUF_EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(...) true
-#define PROTOBUF_EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK(...) true
-
-PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, );
-PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default"))));
-PROTOBUF_EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport));
-PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
-
-#undef PROTOBUF_EXPORT_TEMPLATE_TEST
-#undef PROTOBUF_EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT
-#undef PROTOBUF_EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK
-
-// Windows declares several inconvenient macro names.  We #undef them and then
-// restore them in port_undef.inc.
-#ifdef _MSC_VER
-#pragma push_macro("ERROR")
-#undef ERROR
-#pragma push_macro("GetMessage")
-#undef GetMessage
-#pragma push_macro("IGNORE")
-#undef IGNORE
-#pragma push_macro("IN")
-#undef IN
-#pragma push_macro("OUT")
-#undef OUT
-#pragma push_macro("OPTIONAL")
-#undef OPTIONAL
-#pragma push_macro("min")
-#undef min
-#pragma push_macro("max")
-#undef max
-#endif  // _MSC_VER
-
-#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
-// Don't let the YES/NO Objective-C Macros interfere with proto identifiers with
-// the same name.
-#pragma push_macro("YES")
-#undef YES
-#pragma push_macro("NO")
-#undef NO
-#endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
-
-#if defined(__clang__)
-#pragma clang diagnostic push
-// TODO(gerbens) ideally we cleanup the code. But a cursory try shows many
-// violations. So let's ignore for now.
-#pragma clang diagnostic ignored "-Wshorten-64-to-32"
-#elif defined(__GNUC__)
-// GCC does not allow disabling diagnostics within an expression:
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60875, so we disable this one
-// globally even though it's only used for PROTOBUF_FIELD_OFFSET.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#ifdef PROTOBUF_FALLTHROUGH_INTENDED
+#error PROTOBUF_FALLTHROUGH_INTENDED was previously defined
+#endif
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define PROTOBUF_FALLTHROUGH_INTENDED [[clang::fallthrough]]
+#elif PROTOBUF_GNUC_MIN(7, 0)
+#define PROTOBUF_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
+#else
+#define PROTOBUF_FALLTHROUGH_INTENDED
 #endif
 
 // PROTOBUF_ASSUME(pred) tells the compiler that it can assume pred is true. To
 // be safe, we also validate the assumption with a GOOGLE_DCHECK in unoptimized
 // builds. The macro does not do anything useful if the compiler does not
 // support __builtin_assume.
-#ifdef __has_builtin
+#ifdef PROTOBUF_ASSUME
+#error PROTOBUF_ASSUME was previously defined
+#endif
 #if __has_builtin(__builtin_assume)
 #define PROTOBUF_ASSUME(pred) \
   GOOGLE_DCHECK(pred);               \
@@ -599,9 +446,6 @@
 #else
 #define PROTOBUF_ASSUME(pred) GOOGLE_DCHECK(pred)
 #endif
-#else
-#define PROTOBUF_ASSUME(pred) GOOGLE_DCHECK(pred)
-#endif
 
 // Specify memory alignment for structs, classes, etc.
 // Use like:
@@ -624,13 +468,242 @@
 // definition: visibility (used for exporting functions/classes) is one of
 // these attributes. This means that it is not possible to use alignas() with a
 // class that is marked as exported.
+#ifdef PROTOBUF_ALIGNAS
+#error PROTOBUF_ALIGNAS was previously defined
+#endif
 #if defined(_MSC_VER)
 #define PROTOBUF_ALIGNAS(byte_alignment) __declspec(align(byte_alignment))
-#elif defined(__GNUC__)
+#elif PROTOBUF_GNUC_MIN(3, 0)
 #define PROTOBUF_ALIGNAS(byte_alignment) \
   __attribute__((aligned(byte_alignment)))
 #else
 #define PROTOBUF_ALIGNAS(byte_alignment) alignas(byte_alignment)
 #endif
 
+#ifdef PROTOBUF_FINAL
+#error PROTOBUF_FINAL was previously defined
+#endif
 #define PROTOBUF_FINAL final
+
+#ifdef PROTOBUF_THREAD_LOCAL
+#error PROTOBUF_THREAD_LOCAL was previously defined
+#endif
+#if defined(_MSC_VER)
+#define PROTOBUF_THREAD_LOCAL __declspec(thread)
+#else
+#define PROTOBUF_THREAD_LOCAL __thread
+#endif
+
+// For enabling message owned arena, one major blocker is semantic change from
+// moving to copying when there is ownership transfer (e.g., move ctor, swap,
+// set allocated, release). This change not only causes performance regression
+// but also breaks users code (e.g., dangling reference). For top-level
+// messages, since it owns the arena, we can mitigate the issue by transferring
+// ownership of arena. However, we cannot do that for nested messages. In order
+// to tell how many usages of nested messages affected by message owned arena,
+// we need to simulate the arena ownership.
+// This experiment is purely for the purpose of gathering data. All code guarded
+// by this flag is supposed to be removed after this experiment.
+#define PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT
+#ifdef PROTOBUF_CONSTINIT
+#error PROTOBUF_CONSTINIT was previously defined
+#endif
+#if defined(__cpp_constinit) && !PROTOBUF_GNUC_MIN(3, 0) && !defined(_MSC_VER)
+// Our use of constinit does not yet work with GCC:
+// https://github.com/protocolbuffers/protobuf/issues/8310
+// Does not work yet with Visual Studio 2019 Update 16.10
+#define PROTOBUF_CONSTINIT constinit
+#elif __has_cpp_attribute(clang::require_constant_initialization)
+#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]]
+#else
+#define PROTOBUF_CONSTINIT
+#endif
+
+// Some globals with an empty non-trivial destructor are annotated with
+// no_destroy for performance reasons. It reduces the cost of these globals in
+// non-opt mode and under sanitizers.
+#ifdef PROTOBUF_ATTRIBUTE_NO_DESTROY
+#error PROTOBUF_ATTRIBUTE_NO_DESTROY was previously defined
+#endif
+#if __has_cpp_attribute(clang::no_destroy)
+#define PROTOBUF_ATTRIBUTE_NO_DESTROY [[clang::no_destroy]]
+#else
+#define PROTOBUF_ATTRIBUTE_NO_DESTROY
+#endif
+
+// Protobuf extensions and reflection require registration of the protos linked
+// in the binary. Not until everything is registered does the runtime have a
+// complete view on all protos. When code is using reflection or extensions
+// in between registration calls this can lead to surprising behavior. By
+// having the registration run first we mitigate this scenario.
+// Highest priority is 101. We use 102 to allow code that really wants to
+// higher priority to still beat us.
+#ifdef PROTOBUF_ATTRIBUTE_INIT_PRIORITY
+#error PROTOBUF_ATTRIBUTE_INIT_PRIORITY was previously defined
+#endif
+#if PROTOBUF_GNUC_MIN(3, 0) && (!defined(__APPLE__) || defined(__clang__))
+#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY __attribute__((init_priority((102))))
+#else
+#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY
+#endif
+
+#ifdef PROTOBUF_PRAGMA_INIT_SEG
+#error PROTOBUF_PRAGMA_INIT_SEG was previously defined
+#endif
+#if _MSC_VER
+#define PROTOBUF_PRAGMA_INIT_SEG __pragma(init_seg(lib))
+#else
+#define PROTOBUF_PRAGMA_INIT_SEG
+#endif
+
+#ifdef PROTOBUF_ATTRIBUTE_WEAK
+#error PROTOBUF_ATTRIBUTE_WEAK was previously defined
+#endif
+#if __has_attribute(weak) && !defined(__MINGW32__)
+#define PROTOBUF_ATTRIBUTE_WEAK __attribute__((weak))
+#else
+#define PROTOBUF_ATTRIBUTE_WEAK
+#endif
+
+// Macros to detect sanitizers.
+#ifdef PROTOBUF_ASAN
+#error PROTOBUF_ASAN was previously defined
+#endif
+#ifdef PROTOBUF_MSAN
+#error PROTOBUF_MSAN was previously defined
+#endif
+#ifdef PROTOBUF_TSAN
+#error PROTOBUF_TSAN was previously defined
+#endif
+#if defined(__clang__)
+#  if __has_feature(address_sanitizer)
+#    define PROTOBUF_ASAN 1
+#  endif
+#  if __has_feature(thread_sanitizer)
+#    define PROTOBUF_TSAN 1
+#  endif
+#  if __has_feature(memory_sanitizer)
+#    define PROTOBUF_MSAN 1
+#  endif
+#elif PROTOBUF_GNUC_MIN(3, 0)
+#  define PROTOBUF_ASAN __SANITIZE_ADDRESS__
+#  define PROTOBUF_TSAN __SANITIZE_THREAD__
+#endif
+
+#ifdef PROTOBUF_UNUSED
+#error PROTOBUF_UNUSED was previously defined
+#endif
+#if __has_cpp_attribute(unused) || \
+    (PROTOBUF_GNUC_MIN(3, 0) && !defined(__clang__))
+#define PROTOBUF_UNUSED __attribute__((__unused__))
+#else
+#define PROTOBUF_UNUSED
+#endif
+
+// Windows declares several inconvenient macro names.  We #undef them and then
+// restore them in port_undef.inc.
+#ifdef _MSC_VER
+#pragma push_macro("CREATE_NEW")
+#undef CREATE_NEW
+#pragma push_macro("DELETE")
+#undef DELETE
+#pragma push_macro("DOUBLE_CLICK")
+#undef DOUBLE_CLICK
+#pragma push_macro("ERROR")
+#undef ERROR
+#pragma push_macro("ERROR_BUSY")
+#undef ERROR_BUSY
+#pragma push_macro("ERROR_INSTALL_FAILED")
+#undef ERROR_INSTALL_FAILED
+#pragma push_macro("ERROR_NOT_FOUND")
+#undef ERROR_NOT_FOUND
+#pragma push_macro("GetMessage")
+#undef GetMessage
+#pragma push_macro("IGNORE")
+#undef IGNORE
+#pragma push_macro("IN")
+#undef IN
+#pragma push_macro("INPUT_KEYBOARD")
+#undef INPUT_KEYBOARD
+#pragma push_macro("NO_ERROR")
+#undef NO_ERROR
+#pragma push_macro("OUT")
+#undef OUT
+#pragma push_macro("OPTIONAL")
+#undef OPTIONAL
+#pragma push_macro("min")
+#undef min
+#pragma push_macro("max")
+#undef max
+#pragma push_macro("NEAR")
+#undef NEAR
+#pragma push_macro("NO_DATA")
+#undef NO_DATA
+#pragma push_macro("REASON_UNKNOWN")
+#undef REASON_UNKNOWN
+#pragma push_macro("SERVICE_DISABLED")
+#undef SERVICE_DISABLED
+#pragma push_macro("SEVERITY_ERROR")
+#undef SEVERITY_ERROR
+#pragma push_macro("STRICT")
+#undef STRICT
+#pragma push_macro("timezone")
+#undef timezone
+#endif  // _MSC_VER
+
+#if defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER)
+// Don't let Objective-C Macros interfere with proto identifiers with the same
+// name.
+#pragma push_macro("DEBUG")
+#undef DEBUG
+#endif // defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER)
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+// TODO(gerbens) ideally we cleanup the code. But a cursory try shows many
+// violations. So let's ignore for now.
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+#elif PROTOBUF_GNUC_MIN(3, 0)
+// GCC does not allow disabling diagnostics within an expression:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60875, so we disable this one
+// globally even though it's only used for PROTOBUF_FIELD_OFFSET.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#endif
+
+// Silence some MSVC warnings in all our code.
+#if _MSC_VER
+#pragma warning(push)
+// For non-trivial unions
+#pragma warning(disable : 4582)
+#pragma warning(disable : 4583)
+// For init_seg(lib)
+#pragma warning(disable : 4073)
+// To silence the fact that we will pop this push from another file
+#pragma warning(disable : 5031)
+#endif
+
+// We don't want code outside port_def doing complex testing, so
+// remove our portable condition test macros to nudge folks away from
+// using it themselves.
+#ifdef PROTOBUF_has_cpp_attribute_DEFINED_
+#  undef __has_cpp_attribute
+#  undef PROTOBUF_has_cpp_attribute_DEFINED_
+#endif
+#ifdef PROTOBUF_has_feature_DEFINED_
+#  undef __has_feature
+#  undef PROTOBUF_has_feature_DEFINED_
+#endif
+#ifdef PROTOBUF_has_warning_DEFINED_
+#  undef __has_warning
+#  undef PROTOBUF_has_warning_DEFINED_
+#endif
+#ifdef PROTOBUF_has_attribute_DEFINED_
+#  undef __has_attribute
+#  undef PROTOBUF_has_attribute_DEFINED_
+#endif
+#ifdef PROTOBUF_has_builtin_DEFINED_
+#  undef __has_builtin
+#  undef PROTOBUF_has_builtin_DEFINED_
+#endif
+#undef PROTOBUF_GNUC_MIN
diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc
index 68339f6..4e956d4 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -37,6 +37,9 @@
 #undef PROTOBUF_NAMESPACE
 #undef PROTOBUF_NAMESPACE_ID
 #undef PROTOBUF_ALWAYS_INLINE
+#undef PROTOBUF_NDEBUG_INLINE
+#undef PROTOBUF_MUSTTAIL
+#undef PROTOBUF_TAILCALL
 #undef PROTOBUF_COLD
 #undef PROTOBUF_NOINLINE
 #undef PROTOBUF_SECTION_VARIABLE
@@ -54,14 +57,13 @@
 #undef PROTOBUF_MIN_PROTOC_VERSION
 #undef PROTOBUF_PREDICT_TRUE
 #undef PROTOBUF_PREDICT_FALSE
-#undef PROTOBUF_LONGLONG
-#undef PROTOBUF_ULONGLONG
-#undef PROTOBUF_LL_FORMAT
-#undef PROTOBUF_GUARDED_BY
 #undef PROTOBUF_FALLTHROUGH_INTENDED
 #undef PROTOBUF_EXPORT
 #undef PROTOC_EXPORT
 #undef PROTOBUF_MUST_USE_RESULT
+#undef PROTOBUF_MUST_USE_EXTRACT_RESULT
+#undef PROTOBUF_FORCE_COPY_IN_RELEASE
+#undef PROTOBUF_FORCE_COPY_IN_SWAP
 #undef PROTOBUF_NAMESPACE_OPEN
 #undef PROTOBUF_NAMESPACE_CLOSE
 #undef PROTOBUF_UNUSED
@@ -69,36 +71,55 @@
 #undef PROTOBUF_EXPORT_TEMPLATE_DECLARE
 #undef PROTOBUF_EXPORT_TEMPLATE_DEFINE
 #undef PROTOBUF_ALIGNAS
-#undef PROTOBUF_EXPORT_TEMPLATE_INVOKE_2
-#undef PROTOBUF_EXPORT_TEMPLATE_DECLARE_DEFAULT
-#undef PROTOBUF_EXPORT_TEMPLATE_DEFINE_DEFAULT
-#undef PROTOBUF_EXPORT_TEMPLATE_DECLARE_MSVC_HACK
-#undef PROTOBUF_EXPORT_TEMPLATE_DEFINE_MSVC_HACK
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_2
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_3
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport
-#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport
 #undef PROTOBUF_FINAL
+#undef PROTOBUF_THREAD_LOCAL
+#undef PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT
+#undef PROTOBUF_CONSTINIT
+#undef PROTOBUF_ATTRIBUTE_WEAK
+#undef PROTOBUF_ATTRIBUTE_NO_DESTROY
+#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY
+#undef PROTOBUF_PRAGMA_INIT_SEG
+#undef PROTOBUF_ASAN
+#undef PROTOBUF_MSAN
+#undef PROTOBUF_TSAN
+#undef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED
+#undef PROTOBUF_LOCKS_EXCLUDED
+#undef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS
+#undef PROTOBUF_GUARDED_BY
+
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+#undef PROTOBUF_FUTURE_BREAKING_CHANGES
+#endif
 
 // Restore macro that may have been #undef'd in port_def.inc.
 #ifdef _MSC_VER
+#pragma pop_macro("CREATE_NEW")
+#pragma pop_macro("DELETE")
+#pragma pop_macro("DOUBLE_CLICK")
 #pragma pop_macro("ERROR")
+#pragma pop_macro("ERROR_BUSY")
+#pragma pop_macro("ERROR_INSTALL_FAILED")
+#pragma pop_macro("ERROR_NOT_FOUND")
 #pragma pop_macro("GetMessage")
 #pragma pop_macro("IGNORE")
 #pragma pop_macro("IN")
+#pragma pop_macro("INPUT_KEYBOARD")
 #pragma pop_macro("OUT")
 #pragma pop_macro("OPTIONAL")
 #pragma pop_macro("min")
 #pragma pop_macro("max")
+#pragma pop_macro("NEAR")
+#pragma pop_macro("NO_DATA")
+#pragma pop_macro("NO_ERROR")
+#pragma pop_macro("REASON_UNKNOWN")
+#pragma pop_macro("SERVICE_DISABLED")
+#pragma pop_macro("SEVERITY_ERROR")
+#pragma pop_macro("STRICT")
+#pragma pop_macro("timezone")
 #endif
 
 #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
-#pragma pop_macro("YES")
-#pragma pop_macro("NO")
+#pragma pop_macro("DEBUG")
 #endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
 
 #if defined(__clang__)
@@ -106,3 +127,8 @@
 #elif defined(__GNUC__)
 #pragma GCC diagnostic pop
 #endif
+
+// Pop the warning(push) from port_def.inc
+#if _MSC_VER
+#pragma warning(pop)
+#endif
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 1ac4e13..ed21a88 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -137,7 +137,7 @@
   // The intermediate message has everything in its "unknown fields".
   proto2_preserve_unknown_enum_unittest::MyMessage message2 = message;
   message2.DiscardUnknownFields();
-  EXPECT_EQ(0, message2.ByteSize());
+  EXPECT_EQ(0, message2.ByteSizeLong());
 
   // But when we pass it to the correct structure, all values are there.
   serialized.clear();
@@ -165,7 +165,7 @@
   proto2_preserve_unknown_enum_unittest::MyMessage message2;
   message2.CopyFrom(*message);
   message2.DiscardUnknownFields();
-  EXPECT_EQ(0, message2.ByteSize());
+  EXPECT_EQ(0, message2.ByteSizeLong());
 
   // But when we pass it to the correct structure, all values are there.
   serialized.clear();
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index 8e6e015..5588f91 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -40,11 +40,29 @@
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/strutil.h>
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
+using proto3_arena_unittest::ForeignMessage;
 using proto3_arena_unittest::TestAllTypes;
 
 namespace google {
 namespace protobuf {
+
+namespace internal {
+
+class Proto3ArenaTestHelper {
+ public:
+  template <typename T>
+  static Arena* GetOwningArena(const T& msg) {
+    return msg.GetOwningArena();
+  }
+};
+
+}  // namespace internal
+
 namespace {
 // We selectively set/check a few representative fields rather than all fields
 // as this test is only expected to cover the basics of arena support.
@@ -137,11 +155,70 @@
   // We can modify this UnknownFieldSet.
   unknown_fields->AddVarint(1, 2);
   // And the unknown fields should be changed.
-  ASSERT_NE(original.ByteSize(), arena_message->ByteSize());
+  ASSERT_NE(original.ByteSizeLong(), arena_message->ByteSizeLong());
   ASSERT_FALSE(
       arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
 }
 
+TEST(Proto3ArenaTest, GetArena) {
+  Arena arena;
+
+  // Tests arena-allocated message and submessages.
+  auto* arena_message1 = Arena::CreateMessage<TestAllTypes>(&arena);
+  auto* arena_submessage1 = arena_message1->mutable_optional_foreign_message();
+  auto* arena_repeated_submessage1 =
+      arena_message1->add_repeated_foreign_message();
+  EXPECT_EQ(&arena, arena_message1->GetArena());
+  EXPECT_EQ(&arena, arena_submessage1->GetArena());
+  EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena());
+
+  // Tests attached heap-allocated messages.
+  auto* arena_message2 = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message2->set_allocated_optional_foreign_message(new ForeignMessage());
+  arena_message2->mutable_repeated_foreign_message()->AddAllocated(
+      new ForeignMessage());
+  const auto& submessage2 = arena_message2->optional_foreign_message();
+  const auto& repeated_submessage2 =
+      arena_message2->repeated_foreign_message(0);
+  EXPECT_EQ(nullptr, submessage2.GetArena());
+  EXPECT_EQ(nullptr, repeated_submessage2.GetArena());
+
+  // Tests message created by Arena::Create.
+  auto* arena_message3 = Arena::Create<TestAllTypes>(&arena);
+  EXPECT_EQ(nullptr, arena_message3->GetArena());
+}
+
+TEST(Proto3ArenaTest, GetArenaWithUnknown) {
+  Arena arena;
+
+  // Tests arena-allocated message and submessages.
+  auto* arena_message1 = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message1->GetReflection()->MutableUnknownFields(arena_message1);
+  auto* arena_submessage1 = arena_message1->mutable_optional_foreign_message();
+  arena_submessage1->GetReflection()->MutableUnknownFields(arena_submessage1);
+  auto* arena_repeated_submessage1 =
+      arena_message1->add_repeated_foreign_message();
+  arena_repeated_submessage1->GetReflection()->MutableUnknownFields(
+      arena_repeated_submessage1);
+  EXPECT_EQ(&arena, arena_message1->GetArena());
+  EXPECT_EQ(&arena, arena_submessage1->GetArena());
+  EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena());
+
+  // Tests attached heap-allocated messages.
+  auto* arena_message2 = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message2->set_allocated_optional_foreign_message(new ForeignMessage());
+  arena_message2->mutable_repeated_foreign_message()->AddAllocated(
+      new ForeignMessage());
+  auto* submessage2 = arena_message2->mutable_optional_foreign_message();
+  submessage2->GetReflection()->MutableUnknownFields(submessage2);
+  auto* repeated_submessage2 =
+      arena_message2->mutable_repeated_foreign_message(0);
+  repeated_submessage2->GetReflection()->MutableUnknownFields(
+      repeated_submessage2);
+  EXPECT_EQ(nullptr, submessage2->GetArena());
+  EXPECT_EQ(nullptr, repeated_submessage2->GetArena());
+}
+
 TEST(Proto3ArenaTest, Swap) {
   Arena arena1;
   Arena arena2;
@@ -202,7 +279,7 @@
   msg.set_optional_int32(0);
   EXPECT_TRUE(msg.has_optional_int32());
 
-  string serialized;
+  std::string serialized;
   msg.SerializeToString(&serialized);
   EXPECT_GT(serialized.size(), 0);
 
@@ -217,19 +294,54 @@
 
   for (int i = 0; i < d->field_count(); i++) {
     const FieldDescriptor* f = d->field(i);
-    EXPECT_TRUE(f->has_optional_keyword()) << f->full_name();
-    EXPECT_TRUE(f->is_singular_with_presence()) << f->full_name();
-    EXPECT_TRUE(f->containing_oneof()) << f->full_name();
+    if (HasPrefixString(f->name(), "singular")) {
+      EXPECT_FALSE(f->has_optional_keyword()) << f->full_name();
+      EXPECT_FALSE(f->has_presence()) << f->full_name();
+      EXPECT_FALSE(f->containing_oneof()) << f->full_name();
+    } else {
+      EXPECT_TRUE(f->has_optional_keyword()) << f->full_name();
+      EXPECT_TRUE(f->has_presence()) << f->full_name();
+      EXPECT_TRUE(f->containing_oneof()) << f->full_name();
+    }
   }
 }
 
+TEST(Proto3OptionalTest, Extensions) {
+  const DescriptorPool* p = DescriptorPool::generated_pool();
+  const FieldDescriptor* no_optional = p->FindExtensionByName(
+      "protobuf_unittest.Proto3OptionalExtensions.ext_no_optional");
+  const FieldDescriptor* with_optional = p->FindExtensionByName(
+      "protobuf_unittest.Proto3OptionalExtensions.ext_with_optional");
+  GOOGLE_CHECK(no_optional);
+  GOOGLE_CHECK(with_optional);
+  EXPECT_FALSE(no_optional->has_optional_keyword());
+  EXPECT_TRUE(with_optional->has_optional_keyword());
+
+  const Descriptor* d = protobuf_unittest::Proto3OptionalExtensions::descriptor();
+  EXPECT_TRUE(d->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_no_optional));
+  EXPECT_TRUE(d->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_with_optional));
+  EXPECT_EQ(8, d->options().GetExtension(
+                   protobuf_unittest::Proto3OptionalExtensions::ext_no_optional));
+  EXPECT_EQ(16,
+            d->options().GetExtension(
+                protobuf_unittest::Proto3OptionalExtensions::ext_with_optional));
+
+  const Descriptor* d2 = protobuf_unittest::TestProto3Optional::descriptor();
+  EXPECT_FALSE(d2->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_no_optional));
+  EXPECT_FALSE(d2->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_with_optional));
+}
+
 TEST(Proto3OptionalTest, OptionalField) {
   protobuf_unittest::TestProto3Optional msg;
   EXPECT_FALSE(msg.has_optional_int32());
   msg.set_optional_int32(0);
   EXPECT_TRUE(msg.has_optional_int32());
 
-  string serialized;
+  std::string serialized;
   msg.SerializeToString(&serialized);
   EXPECT_GT(serialized.size(), 0);
 
@@ -286,6 +398,47 @@
   EXPECT_TRUE(r->GetOneofFieldDescriptor(msg, o) == nullptr);
 }
 
+// It's a regression test for b/160665543.
+TEST(Proto3OptionalTest, ClearNonOptionalMessageField) {
+  protobuf_unittest::TestProto3OptionalMessage msg;
+  msg.mutable_nested_message();
+  const google::protobuf::Descriptor* d = msg.GetDescriptor();
+  const google::protobuf::Reflection* r = msg.GetReflection();
+  const google::protobuf::FieldDescriptor* f = d->FindFieldByName("nested_message");
+  r->ClearField(&msg, f);
+}
+
+TEST(Proto3OptionalTest, ClearOptionalMessageField) {
+  protobuf_unittest::TestProto3OptionalMessage msg;
+  msg.mutable_optional_nested_message();
+  const google::protobuf::Descriptor* d = msg.GetDescriptor();
+  const google::protobuf::Reflection* r = msg.GetReflection();
+  const google::protobuf::FieldDescriptor* f =
+      d->FindFieldByName("optional_nested_message");
+  r->ClearField(&msg, f);
+}
+
+TEST(Proto3OptionalTest, SwapNonOptionalMessageField) {
+  protobuf_unittest::TestProto3OptionalMessage msg1;
+  protobuf_unittest::TestProto3OptionalMessage msg2;
+  msg1.mutable_nested_message();
+  const google::protobuf::Descriptor* d = msg1.GetDescriptor();
+  const google::protobuf::Reflection* r = msg1.GetReflection();
+  const google::protobuf::FieldDescriptor* f = d->FindFieldByName("nested_message");
+  r->SwapFields(&msg1, &msg2, {f});
+}
+
+TEST(Proto3OptionalTest, SwapOptionalMessageField) {
+  protobuf_unittest::TestProto3OptionalMessage msg1;
+  protobuf_unittest::TestProto3OptionalMessage msg2;
+  msg1.mutable_optional_nested_message();
+  const google::protobuf::Descriptor* d = msg1.GetDescriptor();
+  const google::protobuf::Reflection* r = msg1.GetReflection();
+  const google::protobuf::FieldDescriptor* f =
+      d->FindFieldByName("optional_nested_message");
+  r->SwapFields(&msg1, &msg2, {f});
+}
+
 void SetAllFieldsZero(protobuf_unittest::TestProto3Optional* msg) {
   msg->set_optional_int32(0);
   msg->set_optional_int64(0);
@@ -470,16 +623,8 @@
 TEST(Proto3OptionalTest, PlainFields) {
   const Descriptor* d = TestAllTypes::descriptor();
 
-  for (int i = 0; i < d->field_count(); i++) {
-    const FieldDescriptor* f = d->field(i);
-    EXPECT_FALSE(f->has_optional_keyword()) << f->full_name();
-    if (f->is_optional() && f->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
-      EXPECT_FALSE(f->is_singular_with_presence()) << f->full_name();
-    }
-  }
-
-  EXPECT_FALSE(
-      d->FindFieldByName("oneof_nested_message")->is_singular_with_presence());
+  EXPECT_FALSE(d->FindFieldByName("optional_int32")->has_presence());
+  EXPECT_TRUE(d->FindFieldByName("oneof_nested_message")->has_presence());
 }
 
 }  // namespace
diff --git a/src/google/protobuf/proto3_lite_unittest.inc b/src/google/protobuf/proto3_lite_unittest.inc
index 4cf9cf8..85f428a 100644
--- a/src/google/protobuf/proto3_lite_unittest.inc
+++ b/src/google/protobuf/proto3_lite_unittest.inc
@@ -130,6 +130,17 @@
   EXPECT_EQ(msg1.ByteSize(), msg2.ByteSize() + 1);
 }
 
+TEST(LITE_TEST_NAME, OneofHazzers) {
+  TestAllTypes msg;
+  msg.set_oneof_uint32(1);
+  msg.set_oneof_string("test");
+
+  EXPECT_EQ(true, msg.has_oneof_string());
+  EXPECT_EQ(false, msg.has_oneof_uint32());
+  EXPECT_EQ(false, msg.has_oneof_bytes());
+  EXPECT_EQ(false, msg.has_oneof_nested_message());
+}
+
 }  // namespace
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index 6b1e5f2..bb41fba 100644
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -392,13 +392,18 @@
 
 // Implement (Mutable)RepeatedFieldRef::iterator
 template <typename T>
-class RepeatedFieldRefIterator
-    : public std::iterator<std::forward_iterator_tag, T> {
+class RepeatedFieldRefIterator {
   typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
   typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
   typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
 
  public:
+  using iterator_category = std::forward_iterator_tag;
+  using value_type = T;
+  using pointer = T*;
+  using reference = T&;
+  using difference_type = std::ptrdiff_t;
+
   // Constructor for non-message fields.
   RepeatedFieldRefIterator(const void* data,
                            const RepeatedFieldAccessor* accessor, bool begin)
@@ -471,7 +476,7 @@
 // RepeatedFieldAccessor type, etc.
 template <typename T>
 struct PrimitiveTraits {
-  static const bool is_primitive = false;
+  static constexpr bool is_primitive = false;
 };
 #define DEFINE_PRIMITIVE(TYPE, type)                 \
   template <>                                        \
@@ -497,7 +502,8 @@
   typedef T AccessorValueType;
   typedef T IteratorValueType;
   typedef T* IteratorPointerType;
-  static const FieldDescriptor::CppType cpp_type = PrimitiveTraits<T>::cpp_type;
+  static constexpr FieldDescriptor::CppType cpp_type =
+      PrimitiveTraits<T>::cpp_type;
   static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
 };
 
@@ -510,7 +516,7 @@
   typedef int32 AccessorValueType;
   typedef T IteratorValueType;
   typedef int32* IteratorPointerType;
-  static const FieldDescriptor::CppType cpp_type =
+  static constexpr FieldDescriptor::CppType cpp_type =
       FieldDescriptor::CPPTYPE_ENUM;
   static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
 };
@@ -523,7 +529,7 @@
   typedef std::string AccessorValueType;
   typedef const std::string IteratorValueType;
   typedef const std::string* IteratorPointerType;
-  static const FieldDescriptor::CppType cpp_type =
+  static constexpr FieldDescriptor::CppType cpp_type =
       FieldDescriptor::CPPTYPE_STRING;
   static const Descriptor* GetMessageFieldDescriptor() { return NULL; }
 };
@@ -547,7 +553,7 @@
   typedef Message AccessorValueType;
   typedef const T& IteratorValueType;
   typedef const T* IteratorPointerType;
-  static const FieldDescriptor::CppType cpp_type =
+  static constexpr FieldDescriptor::CppType cpp_type =
       FieldDescriptor::CPPTYPE_MESSAGE;
   static const Descriptor* GetMessageFieldDescriptor() {
     return MessageDescriptorGetter<T>::get();
diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc
index 5eee1dd..5380797 100644
--- a/src/google/protobuf/reflection_ops.cc
+++ b/src/google/protobuf/reflection_ops.cc
@@ -43,7 +43,6 @@
 #include <google/protobuf/map_field.h>
 #include <google/protobuf/map_field_inl.h>
 #include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/stubs/strutil.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -85,10 +84,8 @@
                           google::protobuf::MessageFactory::generated_factory());
 
   std::vector<const FieldDescriptor*> fields;
-  from_reflection->ListFields(from, &fields);
-  for (int i = 0; i < fields.size(); i++) {
-    const FieldDescriptor* field = fields[i];
-
+  from_reflection->ListFieldsOmitStripped(from, &fields);
+  for (const FieldDescriptor* field : fields) {
     if (field->is_repeated()) {
       // Use map reflection if both are in map status and have the
       // same map type to avoid sync with repeated field.
@@ -180,14 +177,76 @@
   const Reflection* reflection = GetReflectionOrDie(*message);
 
   std::vector<const FieldDescriptor*> fields;
-  reflection->ListFields(*message, &fields);
-  for (int i = 0; i < fields.size(); i++) {
-    reflection->ClearField(message, fields[i]);
+  reflection->ListFieldsOmitStripped(*message, &fields);
+  for (const FieldDescriptor* field : fields) {
+    reflection->ClearField(message, field);
   }
 
   reflection->MutableUnknownFields(message)->Clear();
 }
 
+bool ReflectionOps::IsInitialized(const Message& message, bool check_fields,
+                                  bool check_descendants) {
+  const Descriptor* descriptor = message.GetDescriptor();
+  const Reflection* reflection = GetReflectionOrDie(message);
+  if (const int field_count = descriptor->field_count()) {
+    const FieldDescriptor* begin = descriptor->field(0);
+    const FieldDescriptor* end = begin + field_count;
+    GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1);
+
+    if (check_fields) {
+      // Check required fields of this message.
+      for (const FieldDescriptor* field = begin; field != end; ++field) {
+        if (field->is_required() && !reflection->HasField(message, field)) {
+          return false;
+        }
+      }
+    }
+
+    if (check_descendants) {
+      for (const FieldDescriptor* field = begin; field != end; ++field) {
+        if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+          const Descriptor* message_type = field->message_type();
+          if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) {
+            if (message_type->field(1)->cpp_type() ==
+                FieldDescriptor::CPPTYPE_MESSAGE) {
+              const MapFieldBase* map_field =
+                  reflection->GetMapData(message, field);
+              if (map_field->IsMapValid()) {
+                MapIterator it(const_cast<Message*>(&message), field);
+                MapIterator end(const_cast<Message*>(&message), field);
+                for (map_field->MapBegin(&it), map_field->MapEnd(&end);
+                     it != end; ++it) {
+                  if (!it.GetValueRef().GetMessageValue().IsInitialized()) {
+                    return false;
+                  }
+                }
+              }
+            }
+          } else if (field->is_repeated()) {
+            const int size = reflection->FieldSize(message, field);
+            for (int j = 0; j < size; j++) {
+              if (!reflection->GetRepeatedMessage(message, field, j)
+                       .IsInitialized()) {
+                return false;
+              }
+            }
+          } else if (reflection->HasField(message, field)) {
+            if (!reflection->GetMessage(message, field).IsInitialized()) {
+              return false;
+            }
+          }
+        }
+      }
+    }
+  }
+  if (check_descendants && reflection->HasExtensionSet(message) &&
+      !reflection->GetExtensionSet(message).IsInitialized()) {
+    return false;
+  }
+  return true;
+}
+
 bool ReflectionOps::IsInitialized(const Message& message) {
   const Descriptor* descriptor = message.GetDescriptor();
   const Reflection* reflection = GetReflectionOrDie(message);
@@ -206,9 +265,10 @@
 
   // Check that sub-messages are initialized.
   std::vector<const FieldDescriptor*> fields;
-  reflection->ListFields(message, &fields);
-  for (int i = 0; i < fields.size(); i++) {
-    const FieldDescriptor* field = fields[i];
+  // Should be safe to skip stripped fields because required fields are not
+  // stripped.
+  reflection->ListFieldsOmitStripped(message, &fields);
+  for (const FieldDescriptor* field : fields) {
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
 
       if (field->is_map()) {
@@ -266,8 +326,7 @@
   // messages present.
   std::vector<const FieldDescriptor*> fields;
   reflection->ListFields(*message, &fields);
-  for (int i = 0; i < fields.size(); i++) {
-    const FieldDescriptor* field = fields[i];
+  for (const FieldDescriptor* field : fields) {
     // Skip over non-message fields.
     if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
       continue;
@@ -337,9 +396,8 @@
 
   // Check sub-messages.
   std::vector<const FieldDescriptor*> fields;
-  reflection->ListFields(message, &fields);
-  for (int i = 0; i < fields.size(); i++) {
-    const FieldDescriptor* field = fields[i];
+  reflection->ListFieldsOmitStripped(message, &fields);
+  for (const FieldDescriptor* field : fields) {
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
 
       if (field->is_repeated()) {
@@ -360,21 +418,37 @@
   }
 }
 
-void GenericSwap(Message* m1, Message* m2) {
-  Arena* m2_arena = m2->GetArena();
-  GOOGLE_DCHECK(m1->GetArena() != m2_arena);
+void GenericSwap(Message* lhs, Message* rhs) {
+#ifndef PROTOBUF_FORCE_COPY_IN_SWAP
+  GOOGLE_DCHECK(Arena::InternalHelper<Message>::GetOwningArena(lhs) !=
+         Arena::InternalHelper<Message>::GetOwningArena(rhs));
+  GOOGLE_DCHECK(Arena::InternalHelper<Message>::GetOwningArena(lhs) != nullptr ||
+         Arena::InternalHelper<Message>::GetOwningArena(rhs) != nullptr);
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
+  // At least one of these must have an arena, so make `rhs` point to it.
+  Arena* arena = Arena::InternalHelper<Message>::GetOwningArena(rhs);
+  if (arena == nullptr) {
+    std::swap(lhs, rhs);
+    arena = Arena::InternalHelper<Message>::GetOwningArena(rhs);
+  }
 
-  // Copy semantics in this case. We try to improve efficiency by placing the
-  // temporary on |m2|'s arena so that messages are copied twice rather than
-  // three times.
-  Message* tmp = m2->New(m2_arena);
-  std::unique_ptr<Message> tmp_deleter(m2_arena == nullptr ? tmp : nullptr);
-  tmp->CheckTypeAndMergeFrom(*m1);
-  m1->Clear();
-  m1->CheckTypeAndMergeFrom(*m2);
-  m2->GetReflection()->Swap(tmp, m2);
+  // Improve efficiency by placing the temporary on an arena so that messages
+  // are copied twice rather than three times.
+  Message* tmp = rhs->New(arena);
+  tmp->CheckTypeAndMergeFrom(*lhs);
+  lhs->Clear();
+  lhs->CheckTypeAndMergeFrom(*rhs);
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  rhs->Clear();
+  rhs->CheckTypeAndMergeFrom(*tmp);
+  if (arena == nullptr) delete tmp;
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
+  rhs->GetReflection()->Swap(tmp, rhs);
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
 }
 
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/reflection_ops.h b/src/google/protobuf/reflection_ops.h
index b30c050..fb98714 100644
--- a/src/google/protobuf/reflection_ops.h
+++ b/src/google/protobuf/reflection_ops.h
@@ -66,6 +66,8 @@
   static void Merge(const Message& from, Message* to);
   static void Clear(Message* message);
   static bool IsInitialized(const Message& message);
+  static bool IsInitialized(const Message& message, bool check_fields,
+                            bool check_descendants);
   static void DiscardUnknownFields(Message* message);
 
   // Finds all unset required fields in the message and adds their full
diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
index be2073d..8c4da21 100644
--- a/src/google/protobuf/reflection_ops_unittest.cc
+++ b/src/google/protobuf/reflection_ops_unittest.cc
@@ -340,12 +340,20 @@
   unittest::TestRequired message;
 
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
   message.set_a(1);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
   message.set_b(2);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
   message.set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 TEST(ReflectionOpsTest, ForeignIsInitialized) {
@@ -354,26 +362,35 @@
   // Starts out initialized because the foreign message is itself an optional
   // field.
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Once we create that field, the message is no longer initialized.
   message.mutable_optional_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize it.  Now we're initialized.
   message.mutable_optional_message()->set_a(1);
   message.mutable_optional_message()->set_b(2);
   message.mutable_optional_message()->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Add a repeated version of the message.  No longer initialized.
   unittest::TestRequired* sub_message = message.add_repeated_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize that repeated version.
   sub_message->set_a(1);
   sub_message->set_b(2);
   sub_message->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 TEST(ReflectionOpsTest, ExtensionIsInitialized) {
@@ -382,42 +399,62 @@
   // Starts out initialized because the foreign message is itself an optional
   // field.
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Once we create that field, the message is no longer initialized.
   message.MutableExtension(unittest::TestRequired::single);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize it.  Now we're initialized.
   message.MutableExtension(unittest::TestRequired::single)->set_a(1);
   message.MutableExtension(unittest::TestRequired::single)->set_b(2);
   message.MutableExtension(unittest::TestRequired::single)->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   // Add a repeated version of the message.  No longer initialized.
   message.AddExtension(unittest::TestRequired::multi);
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   // Initialize that repeated version.
   message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1);
   message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2);
   message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 TEST(ReflectionOpsTest, OneofIsInitialized) {
   unittest::TestRequiredOneof message;
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   message.mutable_foo_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
 
   message.set_foo_int(1);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 
   message.mutable_foo_message();
   EXPECT_FALSE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
   message.mutable_foo_message()->set_required_double(0.1);
   EXPECT_TRUE(ReflectionOps::IsInitialized(message));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
+  EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
 }
 
 static std::string FindInitializationErrors(const Message& message) {
@@ -498,8 +535,8 @@
 
     TestUtil::ExpectAllFieldsSet(message);
     TestUtil::ExpectClear(*arena_message);
-    // The temp shouldn't be allocated on the arena in this case.
-    EXPECT_EQ(arena.SpaceUsed(), initial_arena_size);
+    // The temp should be allocated on the arena in this case.
+    EXPECT_GT(arena.SpaceUsed(), initial_arena_size);
   }
 }
 
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index bc70be5..addd26ce 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -56,10 +56,12 @@
   }
   Rep* old_rep = rep_;
   Arena* arena = GetArena();
-  new_size = std::max(kMinRepeatedFieldAllocationSize,
+  new_size = std::max(internal::kRepeatedFieldLowerClampLimit,
                       std::max(total_size_ * 2, new_size));
-  GOOGLE_CHECK_LE(new_size, (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
-                         sizeof(old_rep->elements[0]))
+  GOOGLE_CHECK_LE(
+      static_cast<int64>(new_size),
+      static_cast<int64>((std::numeric_limits<size_t>::max() - kRepHeaderSize) /
+                         sizeof(old_rep->elements[0])))
       << "Requested size is too large to fit into size_t.";
   size_t bytes = kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size;
   if (arena == NULL) {
@@ -96,6 +98,15 @@
   }
 }
 
+void* RepeatedPtrFieldBase::AddOutOfLineHelper(void* obj) {
+  if (!rep_ || rep_->allocated_size == total_size_) {
+    InternalExtend(1);  // Equivalent to "Reserve(total_size_ + 1)"
+  }
+  ++rep_->allocated_size;
+  rep_->elements[current_size_++] = obj;
+  return obj;
+}
+
 void RepeatedPtrFieldBase::CloseGap(int start, int num) {
   if (rep_ == NULL) return;
   // Close up a gap of "num" elements starting at offset "start".
@@ -123,22 +134,16 @@
 }  // namespace internal
 
 
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedField<bool>;
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedField<int32>;
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedField<uint32>;
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedField<int64>;
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedField<uint64>;
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedField<float>;
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedField<double>;
-template class PROTOBUF_EXPORT_TEMPLATE_DEFINE(PROTOBUF_EXPORT)
-    RepeatedPtrField<std::string>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<bool>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<int32>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<uint32>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<int64>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<uint64>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<float>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<double>;
+template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedPtrField<std::string>;
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index e74ffc7..c8fe933 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -66,6 +66,7 @@
 #include <type_traits>
 
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 #ifdef SWIG
@@ -84,8 +85,18 @@
 namespace internal {
 
 class MergePartialFromCodedStreamHelper;
+class SwapFieldHelper;
 
-static const int kMinRepeatedFieldAllocationSize = 4;
+// kRepeatedFieldLowerClampLimit is the smallest size that will be allocated
+// when growing a repeated field.
+constexpr int kRepeatedFieldLowerClampLimit = 4;
+
+// kRepeatedFieldUpperClampLimit is the lowest signed integer value that
+// overflows when multiplied by 2 (which is undefined behavior). Sizes above
+// this will clamp to the maximum int value instead of following exponential
+// growth when growing a repeated field.
+constexpr int kRepeatedFieldUpperClampLimit =
+    (std::numeric_limits<int>::max() / 2) + 1;
 
 // A utility function for logging that doesn't need any template types.
 void LogIndexOutOfBounds(int index, int size);
@@ -159,11 +170,16 @@
       "We only support types that have an alignment smaller than Arena");
 
  public:
-  RepeatedField();
+  constexpr RepeatedField();
   explicit RepeatedField(Arena* arena);
+
   RepeatedField(const RepeatedField& other);
-  template <typename Iter>
-  RepeatedField(Iter begin, const Iter& end);
+
+  template <typename Iter,
+            typename = typename std::enable_if<std::is_constructible<
+                Element, decltype(*std::declval<Iter>())>::value>::type>
+  RepeatedField(Iter begin, Iter end);
+
   ~RepeatedField();
 
   RepeatedField& operator=(const RepeatedField& other);
@@ -206,6 +222,10 @@
   void MergeFrom(const RepeatedField& other);
   void CopyFrom(const RepeatedField& other);
 
+  // Replaces the contents with RepeatedField(begin, end).
+  template <typename Iter>
+  void Assign(Iter begin, Iter end);
+
   // Reserve space to expand the field to at least the given size.  If the
   // array is grown, it will always be at least doubled in size.
   void Reserve(int new_size);
@@ -309,7 +329,7 @@
   inline void InternalSwap(RepeatedField* other);
 
  private:
-  static const int kInitialSize = 0;
+  static constexpr int kInitialSize = 0;
   // A note on the representation here (see also comment below for
   // RepeatedPtrFieldBase's struct Rep):
   //
@@ -324,13 +344,12 @@
   int total_size_;
   struct Rep {
     Arena* arena;
-    Element elements[1];
+    // Here we declare a huge array as a way of approximating C's "flexible
+    // array member" feature without relying on undefined behavior.
+    Element elements[(std::numeric_limits<int>::max() - 2 * sizeof(Arena*)) /
+                     sizeof(Element)];
   };
-  // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on
-  // the struct. We can not use sizeof(Arena*) as well because there might be
-  // a "gap" after the field arena and before the field elements (e.g., when
-  // Element is double and pointer is 32bit).
-  static const size_t kRepHeaderSize;
+  static constexpr size_t kRepHeaderSize = offsetof(Rep, elements);
 
   // If total_size_ == 0 this points to an Arena otherwise it points to the
   // elements member of a Rep struct. Using this invariant allows the storage of
@@ -371,14 +390,14 @@
   void CopyArray(Element* to, const Element* from, int size);
 
   // Internal helper to delete all elements and deallocate the storage.
-  // If Element has a trivial destructor (for example, if it's a fundamental
-  // type, like int32), the loop will be removed by the optimizer.
   void InternalDeallocate(Rep* rep, int size) {
     if (rep != NULL) {
       Element* e = &rep->elements[0];
-      Element* limit = &rep->elements[size];
-      for (; e < limit; e++) {
-        e->~Element();
+      if (!std::is_trivial<Element>::value) {
+        Element* limit = &rep->elements[size];
+        for (; e < limit; e++) {
+          e->~Element();
+        }
       }
       if (rep->arena == NULL) {
 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
@@ -390,11 +409,92 @@
       }
     }
   }
-};
 
-template <typename Element>
-const size_t RepeatedField<Element>::kRepHeaderSize =
-    reinterpret_cast<size_t>(&reinterpret_cast<Rep*>(16)->elements[0]) - 16;
+  // This class is a performance wrapper around RepeatedField::Add(const T&)
+  // function. In general unless a RepeatedField is a local stack variable LLVM
+  // has a hard time optimizing Add. The machine code tends to be
+  // loop:
+  // mov %size, dword ptr [%repeated_field]       // load
+  // cmp %size, dword ptr [%repeated_field + 4]
+  // jae fallback
+  // mov %buffer, qword ptr [%repeated_field + 8]
+  // mov dword [%buffer + %size * 4], %value
+  // inc %size                                    // increment
+  // mov dword ptr [%repeated_field], %size       // store
+  // jmp loop
+  //
+  // This puts a load/store in each iteration of the important loop variable
+  // size. It's a pretty bad compile that happens even in simple cases, but
+  // largely the presence of the fallback path disturbs the compilers mem-to-reg
+  // analysis.
+  //
+  // This class takes ownership of a repeated field for the duration of it's
+  // lifetime. The repeated field should not be accessed during this time, ie.
+  // only access through this class is allowed. This class should always be a
+  // function local stack variable. Intended use
+  //
+  // void AddSequence(const int* begin, const int* end, RepeatedField<int>* out)
+  // {
+  //   RepeatedFieldAdder<int> adder(out);  // Take ownership of out
+  //   for (auto it = begin; it != end; ++it) {
+  //     adder.Add(*it);
+  //   }
+  // }
+  //
+  // Typically due to the fact adder is a local stack variable. The compiler
+  // will be successful in mem-to-reg transformation and the machine code will
+  // be loop: cmp %size, %capacity jae fallback mov dword ptr [%buffer + %size *
+  // 4], %val inc %size jmp loop
+  //
+  // The first version executes at 7 cycles per iteration while the second
+  // version near 1 or 2 cycles.
+  template <int = 0, bool = std::is_trivial<Element>::value>
+  class FastAdderImpl {
+   public:
+    explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) {
+      index_ = repeated_field_->current_size_;
+      capacity_ = repeated_field_->total_size_;
+      buffer_ = repeated_field_->unsafe_elements();
+    }
+    ~FastAdderImpl() { repeated_field_->current_size_ = index_; }
+
+    void Add(Element val) {
+      if (index_ == capacity_) {
+        repeated_field_->current_size_ = index_;
+        repeated_field_->Reserve(index_ + 1);
+        capacity_ = repeated_field_->total_size_;
+        buffer_ = repeated_field_->unsafe_elements();
+      }
+      buffer_[index_++] = val;
+    }
+
+   private:
+    RepeatedField* repeated_field_;
+    int index_;
+    int capacity_;
+    Element* buffer_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl);
+  };
+
+  // FastAdder is a wrapper for adding fields. The specialization above handles
+  // POD types more efficiently than RepeatedField.
+  template <int I>
+  class FastAdderImpl<I, false> {
+   public:
+    explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) {}
+    void Add(const Element& val) { repeated_field_->Add(val); }
+
+   private:
+    RepeatedField* repeated_field_;
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl);
+  };
+
+  using FastAdder = FastAdderImpl<>;
+
+  friend class TestRepeatedFieldHelper;
+  friend class ::google::protobuf::internal::ParseContext;
+};
 
 namespace internal {
 template <typename It>
@@ -410,8 +510,7 @@
 // shouldn't be necessary, but our compiler doesn't optimize std::copy very
 // effectively.
 template <typename Element,
-          bool HasTrivialCopy =
-              std::is_pod<Element>::value>
+          bool HasTrivialCopy = std::is_trivial<Element>::value>
 struct ElementCopier {
   void operator()(Element* to, const Element* from, int array_size);
 };
@@ -487,7 +586,7 @@
 //   };
 class PROTOBUF_EXPORT RepeatedPtrFieldBase {
  protected:
-  RepeatedPtrFieldBase();
+  constexpr RepeatedPtrFieldBase();
   explicit RepeatedPtrFieldBase(Arena* arena);
   ~RepeatedPtrFieldBase() {
 #ifndef NDEBUG
@@ -497,12 +596,10 @@
 #endif
   }
 
- public:
   // Must be called from destructor.
   template <typename TypeHandler>
   void Destroy();
 
- protected:
   bool empty() const;
   int size() const;
 
@@ -557,6 +654,14 @@
 
   int Capacity() const;
 
+  template <typename TypeHandler>
+  static inline typename TypeHandler::Type* copy(
+      typename TypeHandler::Type* value) {
+    auto* new_value = TypeHandler::NewFromPrototype(value, nullptr);
+    TypeHandler::Merge(*value, new_value);
+    return new_value;
+  }
+
   // Used for constructing iterators.
   void* const* raw_data() const;
   void** raw_mutable_data() const;
@@ -567,7 +672,7 @@
   const typename TypeHandler::Type* const* data() const;
 
   template <typename TypeHandler>
-  PROTOBUF_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other);
+  PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other);
 
   void SwapElements(int index1, int index2);
 
@@ -590,7 +695,7 @@
   void UnsafeArenaAddAllocated(typename TypeHandler::Type* value);
 
   template <typename TypeHandler>
-  typename TypeHandler::Type* ReleaseLast() {
+  PROTOBUF_MUST_USE_RESULT typename TypeHandler::Type* ReleaseLast() {
     typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
     return ReleaseLastInternal<TypeHandler>(t);
   }
@@ -604,7 +709,7 @@
   template <typename TypeHandler>
   void AddCleared(typename TypeHandler::Type* value);
   template <typename TypeHandler>
-  typename TypeHandler::Type* ReleaseCleared();
+  PROTOBUF_MUST_USE_RESULT typename TypeHandler::Type* ReleaseCleared();
 
   template <typename TypeHandler>
   void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type);
@@ -629,7 +734,7 @@
   inline Arena* GetArena() const { return arena_; }
 
  private:
-  static const int kInitialSize = 0;
+  static constexpr int kInitialSize = 0;
   // A few notes on internal representation:
   //
   // We use an indirected approach, with struct Rep, to keep
@@ -646,9 +751,12 @@
   int total_size_;
   struct Rep {
     int allocated_size;
-    void* elements[1];
+    // Here we declare a huge array as a way of approximating C's "flexible
+    // array member" feature without relying on undefined behavior.
+    void* elements[(std::numeric_limits<int>::max() - 2 * sizeof(int)) /
+                   sizeof(void*)];
   };
-  static const size_t kRepHeaderSize = sizeof(Rep) - sizeof(void*);
+  static constexpr size_t kRepHeaderSize = offsetof(Rep, elements);
   Rep* rep_;
 
   template <typename TypeHandler>
@@ -668,8 +776,9 @@
                                                                   int));
 
   template <typename TypeHandler>
-  void MergeFromInnerLoop(void** our_elems, void** other_elems, int length,
-                          int already_allocated);
+  PROTOBUF_NOINLINE void MergeFromInnerLoop(void** our_elems,
+                                            void** other_elems, int length,
+                                            int already_allocated);
 
   // Internal helper: extend array space if necessary to contain |extend_amount|
   // more elements, and return a pointer to the element immediately following
@@ -677,10 +786,16 @@
   // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0.
   void** InternalExtend(int extend_amount);
 
+  // Internal helper for Add: add "obj" as the next element in the
+  // array, including potentially resizing the array with Reserve if
+  // needed
+  void* AddOutOfLineHelper(void* obj);
+
   // The reflection implementation needs to call protected methods directly,
   // reinterpreting pointers as being to Message instead of a specific Message
   // subclass.
   friend class ::PROTOBUF_NAMESPACE_ID::Reflection;
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::SwapFieldHelper;
 
   // ExtensionSet stores repeated message extensions as
   // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to implement
@@ -693,6 +808,7 @@
   // reinterpreting pointers as being to Message instead of a specific Message
   // subclass.
   friend class MapFieldBase;
+  friend class MapFieldBaseStub;
 
   // The table-driven MergePartialFromCodedStream implementation needs to
   // operate on RepeatedPtrField<MessageLite>.
@@ -723,11 +839,8 @@
       delete value;
     }
   }
-  static inline Arena* GetArena(GenericType* value) {
-    return Arena::GetArena<Type>(value);
-  }
-  static inline void* GetMaybeArenaPointer(GenericType* value) {
-    return Arena::GetArena<Type>(value);
+  static inline Arena* GetOwningArena(GenericType* value) {
+    return Arena::GetOwningArena<Type>(value);
   }
 
   static inline void Clear(GenericType* value) { value->Clear(); }
@@ -756,13 +869,9 @@
 MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
     const MessageLite* prototype, Arena* arena);
 template <>
-inline Arena* GenericTypeHandler<MessageLite>::GetArena(MessageLite* value) {
-  return value->GetArena();
-}
-template <>
-inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
+inline Arena* GenericTypeHandler<MessageLite>::GetOwningArena(
     MessageLite* value) {
-  return value->GetMaybeArenaPointer();
+  return value->GetOwningArena();
 }
 template <>
 void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
@@ -782,9 +891,7 @@
 PROTOBUF_EXPORT Message* GenericTypeHandler<Message>::NewFromPrototype(
     const Message* prototype, Arena* arena);
 template <>
-PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetArena(Message* value);
-template <>
-PROTOBUF_EXPORT void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
+PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetOwningArena(
     Message* value);
 
 class StringTypeHandler {
@@ -802,10 +909,7 @@
                                               Arena* arena) {
     return New(arena);
   }
-  static inline Arena* GetArena(std::string*) { return NULL; }
-  static inline void* GetMaybeArenaPointer(std::string* /* value */) {
-    return NULL;
-  }
+  static inline Arena* GetOwningArena(std::string*) { return nullptr; }
   static inline void Delete(std::string* value, Arena* arena) {
     if (arena == NULL) {
       delete value;
@@ -827,12 +931,16 @@
 template <typename Element>
 class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
  public:
-  RepeatedPtrField();
+  constexpr RepeatedPtrField();
   explicit RepeatedPtrField(Arena* arena);
 
   RepeatedPtrField(const RepeatedPtrField& other);
-  template <typename Iter>
-  RepeatedPtrField(Iter begin, const Iter& end);
+
+  template <typename Iter,
+            typename = typename std::enable_if<std::is_constructible<
+                Element, decltype(*std::declval<Iter>())>::value>::type>
+  RepeatedPtrField(Iter begin, Iter end);
+
   ~RepeatedPtrField();
 
   RepeatedPtrField& operator=(const RepeatedPtrField& other);
@@ -847,6 +955,10 @@
   Element* Mutable(int index);
   Element* Add();
   void Add(Element&& value);
+  // Append elements in the range [begin, end) after reserving
+  // the appropriate number of elements.
+  template <typename Iter>
+  void Add(Iter begin, Iter end);
 
   const Element& operator[](int index) const { return Get(index); }
   Element& operator[](int index) { return *Mutable(index); }
@@ -867,6 +979,10 @@
   void MergeFrom(const RepeatedPtrField& other);
   void CopyFrom(const RepeatedPtrField& other);
 
+  // Replaces the contents with RepeatedPtrField(begin, end).
+  template <typename Iter>
+  void Assign(Iter begin, Iter end);
+
   // Reserve space to expand the field to at least the given size.  This only
   // resizes the pointer array; it doesn't allocate any objects.  If the
   // array is grown, it will always be at least doubled in size.
@@ -965,7 +1081,7 @@
   // If this RepeatedPtrField is on an arena, an object copy is required to pass
   // ownership back to the user (for compatible semantics). Use
   // UnsafeArenaReleaseLast() if this behavior is undesired.
-  Element* ReleaseLast();
+  PROTOBUF_MUST_USE_RESULT Element* ReleaseLast();
 
   // Add an already-allocated object, skipping arena-ownership checks. The user
   // must guarantee that the given object is in the same arena as this
@@ -1035,7 +1151,7 @@
   //
   // This method cannot be called when the repeated field is on an arena; doing
   // so will trigger a GOOGLE_DCHECK-failure.
-  Element* ReleaseCleared();
+  PROTOBUF_MUST_USE_RESULT Element* ReleaseCleared();
 
   // Removes the element referenced by position.
   //
@@ -1087,7 +1203,7 @@
 // implementation ====================================================
 
 template <typename Element>
-inline RepeatedField<Element>::RepeatedField()
+constexpr RepeatedField<Element>::RepeatedField()
     : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {}
 
 template <typename Element>
@@ -1105,14 +1221,20 @@
 }
 
 template <typename Element>
-template <typename Iter>
-RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
+template <typename Iter, typename>
+RepeatedField<Element>::RepeatedField(Iter begin, Iter end)
     : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {
   Add(begin, end);
 }
 
 template <typename Element>
 RepeatedField<Element>::~RepeatedField() {
+#ifndef NDEBUG
+  // Try to trigger segfault / asan failure in non-opt builds. If arena_
+  // lifetime has ended before the destructor.
+  auto arena = GetArena();
+  if (arena) (void)arena->SpaceAllocated();
+#endif
   if (total_size_ > 0) {
     InternalDeallocate(rep(), total_size_);
   }
@@ -1240,14 +1362,26 @@
 
 template <typename Element>
 inline void RepeatedField<Element>::Add(const Element& value) {
-  if (current_size_ == total_size_) Reserve(total_size_ + 1);
-  elements()[current_size_++] = value;
+  uint32 size = current_size_;
+  if (static_cast<int>(size) == total_size_) {
+    // value could reference an element of the array. Reserving new space will
+    // invalidate the reference. So we must make a copy first.
+    auto tmp = value;
+    Reserve(total_size_ + 1);
+    elements()[size] = std::move(tmp);
+  } else {
+    elements()[size] = value;
+  }
+  current_size_ = size + 1;
 }
 
 template <typename Element>
 inline Element* RepeatedField<Element>::Add() {
-  if (current_size_ == total_size_) Reserve(total_size_ + 1);
-  return &elements()[current_size_++];
+  uint32 size = current_size_;
+  if (static_cast<int>(size) == total_size_) Reserve(total_size_ + 1);
+  auto ptr = &elements()[size];
+  current_size_ = size + 1;
+  return ptr;
 }
 
 template <typename Element>
@@ -1269,9 +1403,8 @@
     std::copy(begin, end, elements() + size());
     current_size_ = reserve + size();
   } else {
-    for (; begin != end; ++begin) {
-      Add(*begin);
-    }
+    FastAdder fast_adder(this);
+    for (; begin != end; ++begin) fast_adder.Add(*begin);
   }
 }
 
@@ -1325,6 +1458,13 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline void RepeatedField<Element>::Assign(Iter begin, Iter end) {
+  Clear();
+  Add(begin, end);
+}
+
+template <typename Element>
 inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
     const_iterator position) {
   return erase(position, position + 1);
@@ -1353,7 +1493,6 @@
 template <typename Element>
 inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) {
   GOOGLE_DCHECK(this != other);
-  GOOGLE_DCHECK(GetArena() == other->GetArena());
 
   // Swap all fields at once.
   static_assert(std::is_standard_layout<RepeatedField<Element>>::value,
@@ -1368,7 +1507,11 @@
 template <typename Element>
 void RepeatedField<Element>::Swap(RepeatedField* other) {
   if (this == other) return;
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  if (GetArena() != nullptr && GetArena() == other->GetArena()) {
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
   if (GetArena() == other->GetArena()) {
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
     InternalSwap(other);
   } else {
     RepeatedField<Element> temp(other->GetArena());
@@ -1425,6 +1568,30 @@
   return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0;
 }
 
+namespace internal {
+// Returns the new size for a reserved field based on its 'total_size' and the
+// requested 'new_size'. The result is clamped to the closed interval:
+//   [internal::kMinRepeatedFieldAllocationSize,
+//    std::numeric_limits<int>::max()]
+// Requires:
+//     new_size > total_size &&
+//     (total_size == 0 ||
+//      total_size >= kRepeatedFieldLowerClampLimit)
+inline int CalculateReserveSize(int total_size, int new_size) {
+  if (new_size < kRepeatedFieldLowerClampLimit) {
+    // Clamp to smallest allowed size.
+    return kRepeatedFieldLowerClampLimit;
+  }
+  if (total_size < kRepeatedFieldUpperClampLimit) {
+    return std::max(total_size * 2, new_size);
+  } else {
+    // Clamp to largest allowed size.
+    GOOGLE_DCHECK_GT(new_size, kRepeatedFieldUpperClampLimit);
+    return std::numeric_limits<int>::max();
+  }
+}
+}  // namespace internal
+
 // Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
 // amount of code bloat.
 template <typename Element>
@@ -1433,8 +1600,7 @@
   Rep* old_rep = total_size_ > 0 ? rep() : NULL;
   Rep* new_rep;
   Arena* arena = GetArena();
-  new_size = std::max(internal::kMinRepeatedFieldAllocationSize,
-                      std::max(total_size_ * 2, new_size));
+  new_size = internal::CalculateReserveSize(total_size_, new_size);
   GOOGLE_DCHECK_LE(
       static_cast<size_t>(new_size),
       (std::numeric_limits<size_t>::max() - kRepHeaderSize) / sizeof(Element))
@@ -1448,6 +1614,10 @@
   }
   new_rep->arena = arena;
   int old_total_size = total_size_;
+  // Already known: new_size >= internal::kMinRepeatedFieldAllocationSize
+  // Maintain invariant:
+  //     total_size_ == 0 ||
+  //     total_size_ >= internal::kMinRepeatedFieldAllocationSize
   total_size_ = new_size;
   arena_or_elements_ = new_rep->elements;
   // Invoke placement-new on newly allocated elements. We shouldn't have to do
@@ -1516,7 +1686,7 @@
 
 namespace internal {
 
-inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
+constexpr RepeatedPtrFieldBase::RepeatedPtrFieldBase()
     : arena_(NULL), current_size_(0), total_size_(0), rep_(NULL) {}
 
 inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(Arena* arena)
@@ -1542,7 +1712,11 @@
 
 template <typename TypeHandler>
 inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
-  if (other->GetArena() == GetArena()) {
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  if (GetArena() != nullptr && GetArena() == other->GetArena()) {
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
+  if (GetArena() == other->GetArena()) {
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
     InternalSwap(other);
   } else {
     SwapFallback<TypeHandler>(other);
@@ -1551,7 +1725,11 @@
 
 template <typename TypeHandler>
 void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+  GOOGLE_DCHECK(GetArena() == nullptr || other->GetArena() != GetArena());
+#else   // PROTOBUF_FORCE_COPY_IN_SWAP
   GOOGLE_DCHECK(other->GetArena() != GetArena());
+#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
 
   // Copy semantics in this case. We try to improve efficiency by placing the
   // temporary on |other|'s arena so that messages are copied twice rather than
@@ -1611,14 +1789,10 @@
   if (rep_ != NULL && current_size_ < rep_->allocated_size) {
     return cast<TypeHandler>(rep_->elements[current_size_++]);
   }
-  if (!rep_ || rep_->allocated_size == total_size_) {
-    Reserve(total_size_ + 1);
-  }
-  ++rep_->allocated_size;
   typename TypeHandler::Type* result =
       TypeHandler::NewFromPrototype(prototype, arena_);
-  rep_->elements[current_size_++] = result;
-  return result;
+  return reinterpret_cast<typename TypeHandler::Type*>(
+      AddOutOfLineHelper(result));
 }
 
 template <typename TypeHandler,
@@ -1692,9 +1866,19 @@
 void RepeatedPtrFieldBase::MergeFromInnerLoop(void** our_elems,
                                               void** other_elems, int length,
                                               int already_allocated) {
-  // Split into two loops, over ranges [0, allocated) and [allocated, length),
-  // to avoid a branch within the loop.
-  for (int i = 0; i < already_allocated && i < length; i++) {
+  if (already_allocated < length) {
+    Arena* arena = GetArena();
+    typename TypeHandler::Type* elem_prototype =
+        reinterpret_cast<typename TypeHandler::Type*>(other_elems[0]);
+    for (int i = already_allocated; i < length; i++) {
+      // Allocate a new empty element that we'll merge into below
+      typename TypeHandler::Type* new_elem =
+          TypeHandler::NewFromPrototype(elem_prototype, arena);
+      our_elems[i] = new_elem;
+    }
+  }
+  // Main loop that does the actual merging
+  for (int i = 0; i < length; i++) {
     // Already allocated: use existing element.
     typename TypeHandler::Type* other_elem =
         reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
@@ -1702,16 +1886,6 @@
         reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]);
     TypeHandler::Merge(*other_elem, new_elem);
   }
-  Arena* arena = GetArena();
-  for (int i = already_allocated; i < length; i++) {
-    // Not allocated: alloc a new element first, then merge it.
-    typename TypeHandler::Type* other_elem =
-        reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
-    typename TypeHandler::Type* new_elem =
-        TypeHandler::NewFromPrototype(other_elem, arena);
-    TypeHandler::Merge(*other_elem, new_elem);
-    our_elems[i] = new_elem;
-  }
 }
 
 template <typename TypeHandler>
@@ -1778,7 +1952,7 @@
 void RepeatedPtrFieldBase::AddAllocatedInternal(
     typename TypeHandler::Type* value, std::true_type) {
   Arena* element_arena =
-      reinterpret_cast<Arena*>(TypeHandler::GetMaybeArenaPointer(value));
+      reinterpret_cast<Arena*>(TypeHandler::GetOwningArena(value));
   Arena* arena = GetArena();
   if (arena == element_arena && rep_ && rep_->allocated_size < total_size_) {
     // Fast path: underlying arena representation (tagged pointer) is equal to
@@ -1794,8 +1968,7 @@
     current_size_ = current_size_ + 1;
     rep_->allocated_size = rep_->allocated_size + 1;
   } else {
-    AddAllocatedSlowWithCopy<TypeHandler>(value, TypeHandler::GetArena(value),
-                                          arena);
+    AddAllocatedSlowWithCopy<TypeHandler>(value, element_arena, arena);
   }
 }
 
@@ -1805,6 +1978,9 @@
     // Pass value_arena and my_arena to avoid duplicate virtual call (value) or
     // load (mine).
     typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena) {
+#ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
+  GOOGLE_DCHECK(value_arena == nullptr || value_arena == my_arena);
+#endif  // PROTOBUF_INTERNAL_USE_MUST_USE_RESULT
   // Ensure that either the value is in the same arena, or if not, we do the
   // appropriate thing: Own() it (if it's on heap and we're in an arena) or copy
   // it to our arena/heap (otherwise).
@@ -1879,14 +2055,15 @@
   typename TypeHandler::Type* result = UnsafeArenaReleaseLast<TypeHandler>();
   // Now perform a copy if we're on an arena.
   Arena* arena = GetArena();
-  if (arena == NULL) {
-    return result;
-  } else {
-    typename TypeHandler::Type* new_result =
-        TypeHandler::NewFromPrototype(result, NULL);
-    TypeHandler::Merge(*result, new_result);
-    return new_result;
-  }
+
+  typename TypeHandler::Type* new_result;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  new_result = copy<TypeHandler>(result);
+  if (arena == nullptr) delete result;
+#else   // PROTOBUF_FORCE_COPY_IN_RELEASE
+  new_result = (arena == nullptr) ? result : copy<TypeHandler>(result);
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
+  return new_result;
 }
 
 // ReleaseLast() for types that *do not* implement merge/copy behavior -- this
@@ -1896,7 +2073,7 @@
 template <typename TypeHandler>
 inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLastInternal(
     std::false_type) {
-  GOOGLE_DCHECK(GetArena() == NULL)
+  GOOGLE_DCHECK(GetArena() == nullptr)
       << "ReleaseLast() called on a RepeatedPtrField that is on an arena, "
       << "with a type that does not implement MergeFrom. This is unsafe; "
       << "please implement MergeFrom for your type.";
@@ -1927,7 +2104,7 @@
     typename TypeHandler::Type* value) {
   GOOGLE_DCHECK(GetArena() == NULL)
       << "AddCleared() can only be used on a RepeatedPtrField not on an arena.";
-  GOOGLE_DCHECK(TypeHandler::GetArena(value) == NULL)
+  GOOGLE_DCHECK(TypeHandler::GetOwningArena(value) == nullptr)
       << "AddCleared() can only accept values not on an arena.";
   if (!rep_ || rep_->allocated_size == total_size_) {
     Reserve(total_size_ + 1);
@@ -1959,7 +2136,8 @@
     : public internal::StringTypeHandler {};
 
 template <typename Element>
-inline RepeatedPtrField<Element>::RepeatedPtrField() : RepeatedPtrFieldBase() {}
+constexpr RepeatedPtrField<Element>::RepeatedPtrField()
+    : RepeatedPtrFieldBase() {}
 
 template <typename Element>
 inline RepeatedPtrField<Element>::RepeatedPtrField(Arena* arena)
@@ -1973,16 +2151,9 @@
 }
 
 template <typename Element>
-template <typename Iter>
-inline RepeatedPtrField<Element>::RepeatedPtrField(Iter begin,
-                                                   const Iter& end) {
-  int reserve = internal::CalculateReserve(begin, end);
-  if (reserve != -1) {
-    Reserve(reserve);
-  }
-  for (; begin != end; ++begin) {
-    *Add() = *begin;
-  }
+template <typename Iter, typename>
+inline RepeatedPtrField<Element>::RepeatedPtrField(Iter begin, Iter end) {
+  Add(begin, end);
 }
 
 template <typename Element>
@@ -2068,6 +2239,18 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline void RepeatedPtrField<Element>::Add(Iter begin, Iter end) {
+  int reserve = internal::CalculateReserve(begin, end);
+  if (reserve != -1) {
+    Reserve(size() + reserve);
+  }
+  for (; begin != end; ++begin) {
+    *Add() = *begin;
+  }
+}
+
+template <typename Element>
 inline void RepeatedPtrField<Element>::RemoveLast() {
   RepeatedPtrFieldBase::RemoveLast<TypeHandler>();
 }
@@ -2080,7 +2263,7 @@
   for (int i = 0; i < num; ++i) {
     RepeatedPtrFieldBase::Delete<TypeHandler>(start + i);
   }
-  ExtractSubrange(start, num, NULL);
+  UnsafeArenaExtractSubrange(start, num, nullptr);
 }
 
 template <typename Element>
@@ -2100,28 +2283,45 @@
   GOOGLE_DCHECK_GE(num, 0);
   GOOGLE_DCHECK_LE(start + num, size());
 
-  if (num > 0) {
-    // Save the values of the removed elements if requested.
-    if (elements != NULL) {
-      if (GetArena() != NULL) {
-        // If we're on an arena, we perform a copy for each element so that the
-        // returned elements are heap-allocated.
-        for (int i = 0; i < num; ++i) {
-          Element* element =
-              RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
-          typename TypeHandler::Type* new_value =
-              TypeHandler::NewFromPrototype(element, NULL);
-          TypeHandler::Merge(*element, new_value);
-          elements[i] = new_value;
-        }
-      } else {
-        for (int i = 0; i < num; ++i) {
-          elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
-        }
-      }
-    }
+  if (num == 0) return;
+
+#ifdef PROTOBUF_MUST_USE_EXTRACT_RESULT
+  GOOGLE_DCHECK_NE(elements, nullptr)
+      << "Releasing elements without transferring ownership is an unsafe "
+         "operation.  Use UnsafeArenaExtractSubrange.";
+#endif
+  if (elements == nullptr) {
     CloseGap(start, num);
+    return;
   }
+
+  Arena* arena = GetArena();
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  // Always copy.
+  for (int i = 0; i < num; ++i) {
+    elements[i] = copy<TypeHandler>(
+        RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start));
+  }
+  if (arena == nullptr) {
+    for (int i = 0; i < num; ++i) {
+      delete RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+    }
+  }
+#else   // PROTOBUF_FORCE_COPY_IN_RELEASE
+  // If we're on an arena, we perform a copy for each element so that the
+  // returned elements are heap-allocated. Otherwise, just forward it.
+  if (arena != nullptr) {
+    for (int i = 0; i < num; ++i) {
+      elements[i] = copy<TypeHandler>(
+          RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start));
+    }
+  } else {
+    for (int i = 0; i < num; ++i) {
+      elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+    }
+  }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
+  CloseGap(start, num);
 }
 
 // ExtractSubrange() implementation for types that do not implement merge/copy
@@ -2174,6 +2374,13 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline void RepeatedPtrField<Element>::Assign(Iter begin, Iter end) {
+  Clear();
+  Add(begin, end);
+}
+
+template <typename Element>
 inline typename RepeatedPtrField<Element>::iterator
 RepeatedPtrField<Element>::erase(const_iterator position) {
   return erase(position, position + 1);
@@ -2456,17 +2663,14 @@
 
 void RepeatedPtrFieldBase::InternalSwap(RepeatedPtrFieldBase* other) {
   GOOGLE_DCHECK(this != other);
-  GOOGLE_DCHECK(GetArena() == other->GetArena());
 
   // Swap all fields at once.
   static_assert(std::is_standard_layout<RepeatedPtrFieldBase>::value,
                 "offsetof() requires standard layout before c++17");
   internal::memswap<offsetof(RepeatedPtrFieldBase, rep_) + sizeof(this->rep_) -
-                    offsetof(RepeatedPtrFieldBase, current_size_)>(
-      reinterpret_cast<char*>(this) +
-          offsetof(RepeatedPtrFieldBase, current_size_),
-      reinterpret_cast<char*>(other) +
-          offsetof(RepeatedPtrFieldBase, current_size_));
+                    offsetof(RepeatedPtrFieldBase, arena_)>(
+      reinterpret_cast<char*>(this) + offsetof(RepeatedPtrFieldBase, arena_),
+      reinterpret_cast<char*>(other) + offsetof(RepeatedPtrFieldBase, arena_));
 }
 
 }  // namespace internal
@@ -2536,9 +2740,14 @@
 namespace internal {
 // A back inserter for RepeatedField objects.
 template <typename T>
-class RepeatedFieldBackInsertIterator
-    : public std::iterator<std::output_iterator_tag, T> {
+class RepeatedFieldBackInsertIterator {
  public:
+  using iterator_category = std::output_iterator_tag;
+  using value_type = T;
+  using pointer = void;
+  using reference = void;
+  using difference_type = std::ptrdiff_t;
+
   explicit RepeatedFieldBackInsertIterator(
       RepeatedField<T>* const mutable_field)
       : field_(mutable_field) {}
@@ -2558,9 +2767,14 @@
 
 // A back inserter for RepeatedPtrField objects.
 template <typename T>
-class RepeatedPtrFieldBackInsertIterator
-    : public std::iterator<std::output_iterator_tag, T> {
+class RepeatedPtrFieldBackInsertIterator {
  public:
+  using iterator_category = std::output_iterator_tag;
+  using value_type = T;
+  using pointer = void;
+  using reference = void;
+  using difference_type = std::ptrdiff_t;
+
   RepeatedPtrFieldBackInsertIterator(RepeatedPtrField<T>* const mutable_field)
       : field_(mutable_field) {}
   RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) {
@@ -2589,9 +2803,14 @@
 // A back inserter for RepeatedPtrFields that inserts by transferring ownership
 // of a pointer.
 template <typename T>
-class AllocatedRepeatedPtrFieldBackInsertIterator
-    : public std::iterator<std::output_iterator_tag, T> {
+class AllocatedRepeatedPtrFieldBackInsertIterator {
  public:
+  using iterator_category = std::output_iterator_tag;
+  using value_type = T;
+  using pointer = void;
+  using reference = void;
+  using difference_type = std::ptrdiff_t;
+
   explicit AllocatedRepeatedPtrFieldBackInsertIterator(
       RepeatedPtrField<T>* const mutable_field)
       : field_(mutable_field) {}
@@ -2613,9 +2832,14 @@
 // Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one
 // uses the UnsafeArenaAddAllocated instead.
 template <typename T>
-class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator
-    : public std::iterator<std::output_iterator_tag, T> {
+class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator {
  public:
+  using iterator_category = std::output_iterator_tag;
+  using value_type = T;
+  using pointer = void;
+  using reference = void;
+  using difference_type = std::ptrdiff_t;
+
   explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator(
       RepeatedPtrField<T>* const mutable_field)
       : field_(mutable_field) {}
@@ -2697,21 +2921,14 @@
 }
 
 // Extern declarations of common instantiations to reduce library bloat.
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
-    RepeatedField<bool>;
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
-    RepeatedField<int32>;
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
-    RepeatedField<uint32>;
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
-    RepeatedField<int64>;
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
-    RepeatedField<uint64>;
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
-    RepeatedField<float>;
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
-    RepeatedField<double>;
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE(PROTOBUF_EXPORT)
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<bool>;
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<int32>;
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<uint32>;
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<int64>;
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<uint64>;
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<float>;
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<double>;
+extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE
     RepeatedPtrField<std::string>;
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index ca5452b..46b9e6d 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -38,6 +38,8 @@
 #include <google/protobuf/repeated_field.h>
 
 #include <algorithm>
+#include <cstdlib>
+#include <iterator>
 #include <limits>
 #include <list>
 #include <sstream>
@@ -53,6 +55,9 @@
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/stl_util.h>
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 namespace {
@@ -60,6 +65,11 @@
 using ::protobuf_unittest::TestAllTypes;
 using ::testing::ElementsAre;
 
+TEST(RepeatedField, ConstInit) {
+  PROTOBUF_CONSTINIT static RepeatedField<int> field{};  // NOLINT
+  EXPECT_TRUE(field.empty());
+}
+
 // Test operations on a small RepeatedField.
 TEST(RepeatedField, Small) {
   RepeatedField<int> field;
@@ -268,6 +278,76 @@
   EXPECT_TRUE(field.empty());
 }
 
+TEST(RepeatedField, ReserveNothing) {
+  RepeatedField<int> field;
+  EXPECT_EQ(0, field.Capacity());
+
+  field.Reserve(-1);
+  EXPECT_EQ(0, field.Capacity());
+}
+
+TEST(RepeatedField, ReserveLowerClamp) {
+  const int clamped_value = internal::CalculateReserveSize(0, 1);
+  EXPECT_EQ(internal::kRepeatedFieldLowerClampLimit, clamped_value);
+  EXPECT_EQ(clamped_value, internal::CalculateReserveSize(clamped_value, 2));
+}
+
+TEST(RepeatedField, ReserveGrowth) {
+  // Make sure the field capacity doubles in size on repeated reservation.
+  for (int size = internal::kRepeatedFieldLowerClampLimit, i = 0; i < 4;
+       ++i, size *= 2) {
+    EXPECT_EQ(size * 2, internal::CalculateReserveSize(size, size + 1));
+  }
+}
+
+TEST(RepeatedField, ReserveLarge) {
+  const int old_size = 10;
+  // This is a size we won't get by doubling:
+  const int new_size = old_size * 3 + 1;
+
+  // Reserving more than 2x current capacity should grow directly to that size.
+  EXPECT_EQ(new_size, internal::CalculateReserveSize(old_size, new_size));
+}
+
+TEST(RepeatedField, ReserveHuge) {
+  // Largest value that does not clamp to the large limit:
+  constexpr int non_clamping_limit = std::numeric_limits<int>::max() / 2;
+  ASSERT_LT(2 * non_clamping_limit, std::numeric_limits<int>::max());
+  EXPECT_LT(internal::CalculateReserveSize(non_clamping_limit,
+                                           non_clamping_limit + 1),
+            std::numeric_limits<int>::max());
+
+  // Smallest size that *will* clamp to the upper limit:
+  constexpr int min_clamping_size = std::numeric_limits<int>::max() / 2 + 1;
+  EXPECT_EQ(
+      internal::CalculateReserveSize(min_clamping_size, min_clamping_size + 1),
+      std::numeric_limits<int>::max());
+
+#ifdef PROTOBUF_TEST_ALLOW_LARGE_ALLOC
+  // The rest of this test may allocate several GB of memory, so it is only
+  // built if explicitly requested.
+  RepeatedField<int> huge_field;
+
+  // Reserve a size for huge_field that will clamp.
+  huge_field.Reserve(min_clamping_size);
+  EXPECT_GE(huge_field.Capacity(), min_clamping_size);
+  ASSERT_LT(huge_field.Capacity(), std::numeric_limits<int>::max() - 1);
+
+#ifndef PROTOBUF_ASAN
+  // The array containing all the fields is, in theory, up to MAXINT-1 in size.
+  // However, some compilers can't handle a struct whose size is larger
+  // than 2GB, and the protocol buffer format doesn't handle more than 2GB of
+  // data at once, either.  So we limit it, but the code below accesses beyond
+  // that limit.
+
+  // Allocation may return more memory than we requested. However, the updated
+  // size must still be clamped to a valid range.
+  huge_field.Reserve(huge_field.Capacity() + 1);
+  EXPECT_EQ(huge_field.Capacity(), std::numeric_limits<int>::max());
+#endif  // PROTOBUF_ASAN
+#endif  // PROTOBUF_TEST_ALLOW_LARGE_ALLOC
+}
+
 TEST(RepeatedField, MergeFrom) {
   RepeatedField<int> source, destination;
   source.Add(4);
@@ -408,6 +488,30 @@
   ASSERT_EQ(me.Get(1), 2);
 }
 
+TEST(RepeatedField, AddAndAssignRanges) {
+  RepeatedField<int> field;
+
+  int vals[] = {2, 27, 2875, 609250};
+  field.Assign(std::begin(vals), std::end(vals));
+
+  ASSERT_EQ(field.size(), 4);
+  EXPECT_EQ(field.Get(0), 2);
+  EXPECT_EQ(field.Get(1), 27);
+  EXPECT_EQ(field.Get(2), 2875);
+  EXPECT_EQ(field.Get(3), 609250);
+
+  field.Add(std::begin(vals), std::end(vals));
+  ASSERT_EQ(field.size(), 8);
+  EXPECT_EQ(field.Get(0), 2);
+  EXPECT_EQ(field.Get(1), 27);
+  EXPECT_EQ(field.Get(2), 2875);
+  EXPECT_EQ(field.Get(3), 609250);
+  EXPECT_EQ(field.Get(4), 2);
+  EXPECT_EQ(field.Get(5), 27);
+  EXPECT_EQ(field.Get(6), 2875);
+  EXPECT_EQ(field.Get(7), 609250);
+}
+
 TEST(RepeatedField, CopyConstruct) {
   RepeatedField<int> source;
   source.Add(1);
@@ -740,10 +844,62 @@
   // strings.
 }
 
+TEST(RepeatedField, TestSAddFromSelf) {
+  RepeatedField<int> field;
+  field.Add(0);
+  for (int i = 0; i < 1000; i++) {
+    field.Add(field[0]);
+  }
+}
+
 // ===================================================================
 // RepeatedPtrField tests.  These pretty much just mirror the RepeatedField
 // tests above.
 
+TEST(RepeatedPtrField, ConstInit) {
+  PROTOBUF_CONSTINIT static RepeatedPtrField<std::string> field{};  // NOLINT
+  EXPECT_TRUE(field.empty());
+}
+
+// This helper overload set tests whether X::f can be called with a braced pair,
+// X::f({a, b}) of std::string iterators (specifically, pointers: That call is
+// ambiguous if and only if the call to ValidResolutionPointerRange is not.
+template <typename X>
+auto ValidResolutionPointerRange(const std::string* p)
+    -> decltype(X::f({p, p + 2}), std::true_type{});
+template <typename X>
+std::false_type ValidResolutionPointerRange(void*);
+
+TEST(RepeatedPtrField, UnambiguousConstructor) {
+  struct X {
+    static bool f(std::vector<std::string>) { return false; }
+    static bool f(google::protobuf::RepeatedPtrField<std::string>) { return true; }
+
+    static bool g(std::vector<int>) { return false; }
+    static bool g(google::protobuf::RepeatedPtrField<std::string>) { return true; }
+  };
+
+  // RepeatedPtrField has no initializer-list constructor, and a constructor
+  // from to const char* values is excluded by its constraints.
+  EXPECT_FALSE(X::f({"abc", "xyz"}));
+
+  // Construction from a pair of int* is also not ambiguous.
+  int a[5] = {};
+  EXPECT_FALSE(X::g({a, a + 5}));
+
+  // Construction from string iterators for the unique string overload "g"
+  // works.
+  // Disabling this for now, this is actually ambiguous with libstdc++.
+  // std::string b[2] = {"abc", "xyz"};
+  // EXPECT_TRUE(X::g({b, b + 2}));
+
+  // Construction from string iterators for "f" is ambiguous, since both
+  // containers are equally good.
+  //
+  // X::f({b, b + 2});  // error => ValidResolutionPointerRange is unambiguous.
+  EXPECT_FALSE(decltype(ValidResolutionPointerRange<X>(nullptr))::value);
+}
+
 TEST(RepeatedPtrField, Small) {
   RepeatedPtrField<std::string> field;
 
@@ -806,6 +962,30 @@
   EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage);
 }
 
+TEST(RepeatedPtrField, AddAndAssignRanges) {
+  RepeatedPtrField<std::string> field;
+
+  const char* vals[] = {"abc", "x", "yz", "xyzzy"};
+  field.Assign(std::begin(vals), std::end(vals));
+
+  ASSERT_EQ(field.size(), 4);
+  EXPECT_EQ(field.Get(0), "abc");
+  EXPECT_EQ(field.Get(1), "x");
+  EXPECT_EQ(field.Get(2), "yz");
+  EXPECT_EQ(field.Get(3), "xyzzy");
+
+  field.Add(std::begin(vals), std::end(vals));
+  ASSERT_EQ(field.size(), 8);
+  EXPECT_EQ(field.Get(0), "abc");
+  EXPECT_EQ(field.Get(1), "x");
+  EXPECT_EQ(field.Get(2), "yz");
+  EXPECT_EQ(field.Get(3), "xyzzy");
+  EXPECT_EQ(field.Get(4), "abc");
+  EXPECT_EQ(field.Get(5), "x");
+  EXPECT_EQ(field.Get(6), "yz");
+  EXPECT_EQ(field.Get(7), "xyzzy");
+}
+
 TEST(RepeatedPtrField, SwapSmallSmall) {
   RepeatedPtrField<std::string> field1;
   RepeatedPtrField<std::string> field2;
@@ -1927,39 +2107,35 @@
 TEST_F(RepeatedFieldInsertionIteratorsTest,
        UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) {
   std::vector<Nested*> data;
-  TestAllTypes goldenproto;
+  Arena arena;
+  auto* goldenproto = Arena::CreateMessage<TestAllTypes>(&arena);
   for (int i = 0; i < 10; ++i) {
-    Nested* new_data = new Nested;
+    auto* new_data = goldenproto->add_repeated_nested_message();
     new_data->set_bb(i);
     data.push_back(new_data);
-
-    new_data = goldenproto.add_repeated_nested_message();
-    new_data->set_bb(i);
   }
-  TestAllTypes testproto;
+  auto* testproto = Arena::CreateMessage<TestAllTypes>(&arena);
   std::copy(data.begin(), data.end(),
             UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
-                testproto.mutable_repeated_nested_message()));
-  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+                testproto->mutable_repeated_nested_message()));
+  EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString());
 }
 
 TEST_F(RepeatedFieldInsertionIteratorsTest,
        UnsafeArenaAllocatedRepeatedPtrFieldWithString) {
   std::vector<std::string*> data;
-  TestAllTypes goldenproto;
+  Arena arena;
+  auto* goldenproto = Arena::CreateMessage<TestAllTypes>(&arena);
   for (int i = 0; i < 10; ++i) {
-    std::string* new_data = new std::string;
+    auto* new_data = goldenproto->add_repeated_string();
     *new_data = "name-" + StrCat(i);
     data.push_back(new_data);
-
-    new_data = goldenproto.add_repeated_string();
-    *new_data = "name-" + StrCat(i);
   }
-  TestAllTypes testproto;
+  auto* testproto = Arena::CreateMessage<TestAllTypes>(&arena);
   std::copy(data.begin(), data.end(),
             UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
-                testproto.mutable_repeated_string()));
-  EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+                testproto->mutable_repeated_string()));
+  EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString());
 }
 
 TEST_F(RepeatedFieldInsertionIteratorsTest, MoveStrings) {
@@ -1997,3 +2173,5 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 9f09bec..3425dd4 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -14,26 +14,22 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class SourceContextDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<SourceContext> _instance;
-} _SourceContext_default_instance_;
+constexpr SourceContext::SourceContext(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct SourceContextDefaultTypeInternal {
+  constexpr SourceContextDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~SourceContextDefaultTypeInternal() {}
+  union {
+    SourceContext _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT SourceContextDefaultTypeInternal _SourceContext_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::SourceContext();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::SourceContext::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
@@ -57,41 +53,39 @@
 const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
   "\n$google/protobuf/source_context.proto\022\017"
   "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile"
-  "_name\030\001 \001(\tB\225\001\n\023com.google.protobufB\022Sou"
-  "rceContextProtoP\001ZAgoogle.golang.org/gen"
-  "proto/protobuf/source_context;source_con"
-  "text\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTy"
-  "pesb\006proto3"
+  "_name\030\001 \001(\tB\212\001\n\023com.google.protobufB\022Sou"
+  "rceContextProtoP\001Z6google.golang.org/pro"
+  "tobuf/types/known/sourcecontextpb\242\002\003GPB\252"
+  "\002\036Google.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_sccs[1] = {
-  &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto, "google/protobuf/source_context.proto", 251,
-  &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once, descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_sccs, descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_deps, 1, 0,
+  false, false, 240, descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto, "google/protobuf/source_context.proto", 
+  &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
+  file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fsource_5fcontext_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fsource_5fcontext_2eproto(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void SourceContext::InitAsDefaultInstance() {
-}
 class SourceContext::_Internal {
  public:
 };
 
-SourceContext::SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+SourceContext::SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceContext)
 }
 SourceContext::SourceContext(const SourceContext& from)
@@ -99,25 +93,25 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_file_name().empty()) {
-    file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(),
-      GetArena());
+    file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_file_name(), 
+      GetArenaForAllocation());
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext)
 }
 
-void SourceContext::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base);
-  file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+inline void SourceContext::SharedCtor() {
+file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 SourceContext::~SourceContext() {
   // @@protoc_insertion_point(destructor:google.protobuf.SourceContext)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void SourceContext::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void SourceContext::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -130,11 +124,6 @@
 void SourceContext::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const SourceContext& SourceContext::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void SourceContext::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext)
@@ -142,17 +131,15 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  file_name_.ClearToEmpty();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* SourceContext::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string file_name = 1;
       case 1:
@@ -165,7 +152,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -192,7 +180,7 @@
   (void) cached_has_bits;
 
   // string file_name = 1;
-  if (this->file_name().size() > 0) {
+  if (!this->_internal_file_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_file_name().data(), static_cast<int>(this->_internal_file_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -218,7 +206,7 @@
   (void) cached_has_bits;
 
   // string file_name = 1;
-  if (this->file_name().size() > 0) {
+  if (!this->_internal_file_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_file_name());
@@ -233,38 +221,29 @@
   return total_size;
 }
 
-void SourceContext::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext)
-  GOOGLE_DCHECK_NE(&from, this);
-  const SourceContext* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<SourceContext>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceContext)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceContext)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SourceContext::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    SourceContext::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SourceContext::GetClassData() const { return &_class_data_; }
+
+void SourceContext::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<SourceContext *>(to)->MergeFrom(
+      static_cast<const SourceContext &>(from));
 }
 
+
 void SourceContext::MergeFrom(const SourceContext& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.file_name().size() > 0) {
+  if (!from._internal_file_name().empty()) {
     _internal_set_file_name(from._internal_file_name());
   }
-}
-
-void SourceContext::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceContext)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void SourceContext::CopyFrom(const SourceContext& from) {
@@ -280,15 +259,20 @@
 
 void SourceContext::InternalSwap(SourceContext* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &file_name_, GetArenaForAllocation(),
+      &other->file_name_, other->GetArenaForAllocation()
+  );
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceContext::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_getter, &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index 1cf16f6..8e49a7b 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -45,7 +44,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -53,10 +52,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class SourceContext;
-class SourceContextDefaultTypeInternal;
+struct SourceContextDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -66,11 +65,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT SourceContext PROTOBUF_FINAL :
+class PROTOBUF_EXPORT SourceContext final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ {
  public:
-  inline SourceContext() : SourceContext(nullptr) {};
-  virtual ~SourceContext();
+  inline SourceContext() : SourceContext(nullptr) {}
+  ~SourceContext() override;
+  explicit constexpr SourceContext(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceContext(const SourceContext& from);
   SourceContext(SourceContext&& from) noexcept
@@ -83,8 +83,9 @@
     return *this;
   }
   inline SourceContext& operator=(SourceContext&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -95,14 +96,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const SourceContext& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const SourceContext& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceContext* internal_default_instance() {
     return reinterpret_cast<const SourceContext*>(
                &_SourceContext_default_instance_);
@@ -115,7 +116,7 @@
   }
   inline void Swap(SourceContext* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -123,23 +124,26 @@
   }
   void UnsafeArenaSwap(SourceContext* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline SourceContext* New() const final {
-    return CreateMaybeMessage<SourceContext>(nullptr);
+    return new SourceContext();
   }
 
   SourceContext* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<SourceContext>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const SourceContext& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const SourceContext& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -150,8 +154,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(SourceContext* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -159,20 +163,17 @@
     return "google.protobuf.SourceContext";
   }
   protected:
-  explicit SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -184,25 +185,14 @@
   // string file_name = 1;
   void clear_file_name();
   const std::string& file_name() const;
-  void set_file_name(const std::string& value);
-  void set_file_name(std::string&& value);
-  void set_file_name(const char* value);
-  void set_file_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_file_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_file_name();
-  std::string* release_file_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_file_name();
   void set_allocated_file_name(std::string* file_name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_file_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_file_name(
-      std::string* file_name);
   private:
   const std::string& _internal_file_name() const;
-  void _internal_set_file_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_file_name(const std::string& value);
   std::string* _internal_mutable_file_name();
   public:
 
@@ -230,54 +220,38 @@
 
 // string file_name = 1;
 inline void SourceContext::clear_file_name() {
-  file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  file_name_.ClearToEmpty();
 }
 inline const std::string& SourceContext::file_name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name)
   return _internal_file_name();
 }
-inline void SourceContext::set_file_name(const std::string& value) {
-  _internal_set_file_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void SourceContext::set_file_name(ArgT0&& arg0, ArgT... args) {
+ 
+ file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name)
 }
 inline std::string* SourceContext::mutable_file_name() {
+  std::string* _s = _internal_mutable_file_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name)
-  return _internal_mutable_file_name();
+  return _s;
 }
 inline const std::string& SourceContext::_internal_file_name() const {
   return file_name_.Get();
 }
 inline void SourceContext::_internal_set_file_name(const std::string& value) {
   
-  file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void SourceContext::set_file_name(std::string&& value) {
-  
-  file_name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceContext.file_name)
-}
-inline void SourceContext::set_file_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name)
-}
-inline void SourceContext::set_file_name(const char* value,
-    size_t size) {
-  
-  file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name)
+  file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* SourceContext::_internal_mutable_file_name() {
   
-  return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return file_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* SourceContext::release_file_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name)
-  return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void SourceContext::set_allocated_file_name(std::string* file_name) {
   if (file_name != nullptr) {
@@ -286,28 +260,9 @@
     
   }
   file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name)
 }
-inline std::string* SourceContext::unsafe_arena_release_file_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.SourceContext.file_name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return file_name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void SourceContext::unsafe_arena_set_allocated_file_name(
-    std::string* file_name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (file_name != nullptr) {
-    
-  } else {
-    
-  }
-  file_name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      file_name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.SourceContext.file_name)
-}
 
 #ifdef __GNUC__
   #pragma GCC diagnostic pop
diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto
index f3b2c96..06bfc43 100644
--- a/src/google/protobuf/source_context.proto
+++ b/src/google/protobuf/source_context.proto
@@ -37,7 +37,7 @@
 option java_outer_classname = "SourceContextProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
-option go_package = "google.golang.org/genproto/protobuf/source_context;source_context";
+option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb";
 
 // `SourceContext` represents information about the source of a
 // protobuf element, like the file in which it is defined.
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 027fef6..61a93a6 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -14,62 +14,57 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fstruct_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto;
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class Struct_FieldsEntry_DoNotUseDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Struct_FieldsEntry_DoNotUse> _instance;
-} _Struct_FieldsEntry_DoNotUse_default_instance_;
-class StructDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Struct> _instance;
-} _Struct_default_instance_;
-class ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Value> _instance;
-  int null_value_;
-  double number_value_;
-  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_;
-  bool bool_value_;
-  const PROTOBUF_NAMESPACE_ID::Struct* struct_value_;
-  const PROTOBUF_NAMESPACE_ID::ListValue* list_value_;
-} _Value_default_instance_;
-class ListValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ListValue> _instance;
-} _ListValue_default_instance_;
+constexpr Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){}
+struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal {
+  constexpr Struct_FieldsEntry_DoNotUseDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~Struct_FieldsEntry_DoNotUseDefaultTypeInternal() {}
+  union {
+    Struct_FieldsEntry_DoNotUse _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_;
+constexpr Struct::Struct(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : fields_(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}){}
+struct StructDefaultTypeInternal {
+  constexpr StructDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~StructDefaultTypeInternal() {}
+  union {
+    Struct _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT StructDefaultTypeInternal _Struct_default_instance_;
+constexpr Value::Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : _oneof_case_{}{}
+struct ValueDefaultTypeInternal {
+  constexpr ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ValueDefaultTypeInternal() {}
+  union {
+    Value _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ValueDefaultTypeInternal _Value_default_instance_;
+constexpr ListValue::ListValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : values_(){}
+struct ListValueDefaultTypeInternal {
+  constexpr ListValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ListValueDefaultTypeInternal() {}
+  union {
+    ListValue _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ListValueDefaultTypeInternal _ListValue_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_ListValue_google_2fprotobuf_2fstruct_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Struct_FieldsEntry_DoNotUse_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse();
-  }
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Struct_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Struct();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ListValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse::InitAsDefaultInstance();
-  PROTOBUF_NAMESPACE_ID::Struct::InitAsDefaultInstance();
-  PROTOBUF_NAMESPACE_ID::Value::InitAsDefaultInstance();
-  PROTOBUF_NAMESPACE_ID::ListValue::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_ListValue_google_2fprotobuf_2fstruct_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fstruct_2eproto[4];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto = nullptr;
@@ -95,12 +90,12 @@
   ~0u,  // no _extensions_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Value, _oneof_case_[0]),
   ~0u,  // no _weak_field_map_
-  offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, null_value_),
-  offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, number_value_),
-  offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, string_value_),
-  offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, bool_value_),
-  offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, struct_value_),
-  offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, list_value_),
+  ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag,
+  ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag,
+  ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag,
+  ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag,
+  ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag,
+  ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag,
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Value, kind_),
   ~0u,  // no _has_bits_
   PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ListValue, _internal_metadata_),
@@ -136,27 +131,24 @@
   "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf."
   "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu"
   "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull"
-  "Value\022\016\n\nNULL_VALUE\020\000B\201\001\n\023com.google.pro"
-  "tobufB\013StructProtoP\001Z1github.com/golang/"
-  "protobuf/ptypes/struct;structpb\370\001\001\242\002\003GPB"
-  "\252\002\036Google.Protobuf.WellKnownTypesb\006proto"
-  "3"
+  "Value\022\016\n\nNULL_VALUE\020\000B\177\n\023com.google.prot"
+  "obufB\013StructProtoP\001Z/google.golang.org/p"
+  "rotobuf/types/known/structpb\370\001\001\242\002\003GPB\252\002\036"
+  "Google.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fstruct_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fstruct_2eproto_sccs[1] = {
-  &scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fstruct_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto, "google/protobuf/struct.proto", 641,
-  &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, descriptor_table_google_2fprotobuf_2fstruct_2eproto_sccs, descriptor_table_google_2fprotobuf_2fstruct_2eproto_deps, 1, 0,
+  false, false, 638, descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto, "google/protobuf/struct.proto", 
+  &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, nullptr, 0, 4,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fstruct_2eproto, 4, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto, file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto,
+  file_level_metadata_google_2fprotobuf_2fstruct_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto, file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fstruct_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fstruct_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fstruct_2eproto(&descriptor_table_google_2fprotobuf_2fstruct_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* NullValue_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto);
@@ -181,27 +173,25 @@
   MergeFromInternal(other);
 }
 ::PROTOBUF_NAMESPACE_ID::Metadata Struct_FieldsEntry_DoNotUse::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[0]);
 }
-void Struct_FieldsEntry_DoNotUse::MergeFrom(
-    const ::PROTOBUF_NAMESPACE_ID::Message& other) {
-  ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom(other);
-}
-
 
 // ===================================================================
 
-void Struct::InitAsDefaultInstance() {
-}
 class Struct::_Internal {
  public:
 };
 
-Struct::Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+Struct::Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   fields_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Struct)
 }
 Struct::Struct(const Struct& from)
@@ -211,34 +201,33 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Struct)
 }
 
-void Struct::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
+inline void Struct::SharedCtor() {
 }
 
 Struct::~Struct() {
   // @@protoc_insertion_point(destructor:google.protobuf.Struct)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Struct::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Struct::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void Struct::ArenaDtor(void* object) {
   Struct* _this = reinterpret_cast< Struct* >(object);
   (void)_this;
+  _this->fields_. ~MapField();
 }
-void Struct::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+inline void Struct::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena) {
+  if (arena != nullptr) {
+    arena->OwnCustomDestructor(this, &Struct::ArenaDtor);
+  }
 }
 void Struct::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Struct& Struct::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Struct::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Struct)
@@ -252,11 +241,9 @@
 
 const char* Struct::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // map<string, .google.protobuf.Value> fields = 1;
       case 1:
@@ -272,7 +259,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -306,6 +294,7 @@
     typedef ::PROTOBUF_NAMESPACE_ID::internal::CompareByDerefFirst<SortItem> Less;
     struct Utf8Check {
       static void Check(ConstPtr p) {
+        (void)p;
         ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
           p->first.data(), static_cast<int>(p->first.length()),
           ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -373,36 +362,27 @@
   return total_size;
 }
 
-void Struct::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Struct* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Struct>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Struct)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Struct)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Struct::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Struct::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Struct::GetClassData() const { return &_class_data_; }
+
+void Struct::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Struct *>(to)->MergeFrom(
+      static_cast<const Struct &>(from));
 }
 
+
 void Struct::MergeFrom(const Struct& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   fields_.MergeFrom(from.fields_);
-}
-
-void Struct::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Struct)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Struct::CopyFrom(const Struct& from) {
@@ -418,28 +398,18 @@
 
 void Struct::InternalSwap(Struct* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  fields_.Swap(&other->fields_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  fields_.InternalSwap(&other->fields_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Struct::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[1]);
 }
 
-
 // ===================================================================
 
-void Value::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_Value_default_instance_.null_value_ = 0;
-  PROTOBUF_NAMESPACE_ID::_Value_default_instance_.number_value_ = 0;
-  PROTOBUF_NAMESPACE_ID::_Value_default_instance_.string_value_.UnsafeSetDefault(
-      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  PROTOBUF_NAMESPACE_ID::_Value_default_instance_.bool_value_ = false;
-  PROTOBUF_NAMESPACE_ID::_Value_default_instance_.struct_value_ = const_cast< PROTOBUF_NAMESPACE_ID::Struct*>(
-      PROTOBUF_NAMESPACE_ID::Struct::internal_default_instance());
-  PROTOBUF_NAMESPACE_ID::_Value_default_instance_.list_value_ = const_cast< PROTOBUF_NAMESPACE_ID::ListValue*>(
-      PROTOBUF_NAMESPACE_ID::ListValue::internal_default_instance());
-}
 class Value::_Internal {
  public:
   static const PROTOBUF_NAMESPACE_ID::Struct& struct_value(const Value* msg);
@@ -455,11 +425,11 @@
   return *msg->kind_.list_value_;
 }
 void Value::set_allocated_struct_value(PROTOBUF_NAMESPACE_ID::Struct* struct_value) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   clear_kind();
   if (struct_value) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(struct_value);
+      ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::Struct>::GetOwningArena(struct_value);
     if (message_arena != submessage_arena) {
       struct_value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, struct_value, submessage_arena);
@@ -470,11 +440,11 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value)
 }
 void Value::set_allocated_list_value(PROTOBUF_NAMESPACE_ID::ListValue* list_value) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   clear_kind();
   if (list_value) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(list_value);
+      ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<PROTOBUF_NAMESPACE_ID::ListValue>::GetOwningArena(list_value);
     if (message_arena != submessage_arena) {
       list_value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, list_value, submessage_arena);
@@ -484,10 +454,13 @@
   }
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value)
 }
-Value::Value(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Value::Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Value)
 }
 Value::Value(const Value& from)
@@ -526,19 +499,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Value)
 }
 
-void Value::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  clear_has_kind();
+inline void Value::SharedCtor() {
+clear_has_kind();
 }
 
 Value::~Value() {
   // @@protoc_insertion_point(destructor:google.protobuf.Value)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Value::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Value::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   if (has_kind()) {
     clear_kind();
   }
@@ -553,11 +526,6 @@
 void Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Value& Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Value::clear_kind() {
 // @@protoc_insertion_point(one_of_clear_start:google.protobuf.Value)
@@ -571,7 +539,7 @@
       break;
     }
     case kStringValue: {
-      kind_.string_value_.Destroy(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+      kind_.string_value_.Destroy(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
       break;
     }
     case kBoolValue: {
@@ -579,13 +547,13 @@
       break;
     }
     case kStructValue: {
-      if (GetArena() == nullptr) {
+      if (GetArenaForAllocation() == nullptr) {
         delete kind_.struct_value_;
       }
       break;
     }
     case kListValue: {
-      if (GetArena() == nullptr) {
+      if (GetArenaForAllocation() == nullptr) {
         delete kind_.list_value_;
       }
       break;
@@ -610,11 +578,9 @@
 
 const char* Value::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // .google.protobuf.NullValue null_value = 1;
       case 1:
@@ -663,7 +629,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -801,25 +768,22 @@
   return total_size;
 }
 
-void Value::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Value* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Value>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Value)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Value)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Value::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Value::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Value::GetClassData() const { return &_class_data_; }
+
+void Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Value *>(to)->MergeFrom(
+      static_cast<const Value &>(from));
 }
 
+
 void Value::MergeFrom(const Value& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
@@ -852,13 +816,7 @@
       break;
     }
   }
-}
-
-void Value::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Value)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Value::CopyFrom(const Value& from) {
@@ -874,29 +832,31 @@
 
 void Value::InternalSwap(Value* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(kind_, other->kind_);
   swap(_oneof_case_[0], other->_oneof_case_[0]);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[2]);
 }
 
-
 // ===================================================================
 
-void ListValue::InitAsDefaultInstance() {
-}
 class ListValue::_Internal {
  public:
 };
 
-ListValue::ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+ListValue::ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   values_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.ListValue)
 }
 ListValue::ListValue(const ListValue& from)
@@ -906,18 +866,18 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ListValue)
 }
 
-void ListValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
+inline void ListValue::SharedCtor() {
 }
 
 ListValue::~ListValue() {
   // @@protoc_insertion_point(destructor:google.protobuf.ListValue)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void ListValue::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void ListValue::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void ListValue::ArenaDtor(void* object) {
@@ -929,11 +889,6 @@
 void ListValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ListValue& ListValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ListValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue)
@@ -947,11 +902,9 @@
 
 const char* ListValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.Value values = 1;
       case 1:
@@ -967,7 +920,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1033,36 +987,27 @@
   return total_size;
 }
 
-void ListValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue)
-  GOOGLE_DCHECK_NE(&from, this);
-  const ListValue* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<ListValue>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ListValue)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ListValue)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ListValue::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    ListValue::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ListValue::GetClassData() const { return &_class_data_; }
+
+void ListValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<ListValue *>(to)->MergeFrom(
+      static_cast<const ListValue &>(from));
 }
 
+
 void ListValue::MergeFrom(const ListValue& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   values_.MergeFrom(from.values_);
-}
-
-void ListValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ListValue)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void ListValue::CopyFrom(const ListValue& from) {
@@ -1078,15 +1023,16 @@
 
 void ListValue::InternalSwap(ListValue* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   values_.InternalSwap(&other->values_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ListValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[3]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 993de2c..a9c3eba 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -49,7 +48,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fstruct_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[4]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -57,19 +56,19 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class ListValue;
-class ListValueDefaultTypeInternal;
+struct ListValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern ListValueDefaultTypeInternal _ListValue_default_instance_;
 class Struct;
-class StructDefaultTypeInternal;
+struct StructDefaultTypeInternal;
 PROTOBUF_EXPORT extern StructDefaultTypeInternal _Struct_default_instance_;
 class Struct_FieldsEntry_DoNotUse;
-class Struct_FieldsEntry_DoNotUseDefaultTypeInternal;
+struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal;
 PROTOBUF_EXPORT extern Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_;
 class Value;
-class ValueDefaultTypeInternal;
+struct ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -100,7 +99,7 @@
     NullValue_descriptor(), enum_t_value);
 }
 inline bool NullValue_Parse(
-    const std::string& name, NullValue* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, NullValue* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<NullValue>(
     NullValue_descriptor(), name, value);
 }
@@ -109,40 +108,34 @@
 class Struct_FieldsEntry_DoNotUse : public ::PROTOBUF_NAMESPACE_ID::internal::MapEntry<Struct_FieldsEntry_DoNotUse, 
     std::string, PROTOBUF_NAMESPACE_ID::Value,
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING,
-    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE,
-    0 > {
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> {
 public:
   typedef ::PROTOBUF_NAMESPACE_ID::internal::MapEntry<Struct_FieldsEntry_DoNotUse, 
     std::string, PROTOBUF_NAMESPACE_ID::Value,
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING,
-    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE,
-    0 > SuperType;
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> SuperType;
   Struct_FieldsEntry_DoNotUse();
-  Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit constexpr Struct_FieldsEntry_DoNotUse(
+      ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+  explicit Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   void MergeFrom(const Struct_FieldsEntry_DoNotUse& other);
   static const Struct_FieldsEntry_DoNotUse* internal_default_instance() { return reinterpret_cast<const Struct_FieldsEntry_DoNotUse*>(&_Struct_FieldsEntry_DoNotUse_default_instance_); }
   static bool ValidateKey(std::string* s) {
     return ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast<int>(s->size()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, "google.protobuf.Struct.FieldsEntry.key");
  }
   static bool ValidateValue(void*) { return true; }
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& other) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[0];
-  }
-
-  public:
 };
 
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Struct PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Struct final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Struct) */ {
  public:
-  inline Struct() : Struct(nullptr) {};
-  virtual ~Struct();
+  inline Struct() : Struct(nullptr) {}
+  ~Struct() override;
+  explicit constexpr Struct(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Struct(const Struct& from);
   Struct(Struct&& from) noexcept
@@ -155,8 +148,9 @@
     return *this;
   }
   inline Struct& operator=(Struct&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -167,14 +161,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Struct& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Struct& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Struct* internal_default_instance() {
     return reinterpret_cast<const Struct*>(
                &_Struct_default_instance_);
@@ -187,7 +181,7 @@
   }
   inline void Swap(Struct* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -195,23 +189,26 @@
   }
   void UnsafeArenaSwap(Struct* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Struct* New() const final {
-    return CreateMaybeMessage<Struct>(nullptr);
+    return new Struct();
   }
 
   Struct* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Struct>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Struct& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Struct& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -222,8 +219,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Struct* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -231,20 +228,17 @@
     return "google.protobuf.Struct";
   }
   protected:
-  explicit Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -282,18 +276,18 @@
       Struct_FieldsEntry_DoNotUse,
       std::string, PROTOBUF_NAMESPACE_ID::Value,
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING,
-      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE,
-      0 > fields_;
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> fields_;
   mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto;
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Value PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ {
  public:
-  inline Value() : Value(nullptr) {};
-  virtual ~Value();
+  inline Value() : Value(nullptr) {}
+  ~Value() override;
+  explicit constexpr Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Value(const Value& from);
   Value(Value&& from) noexcept
@@ -306,8 +300,9 @@
     return *this;
   }
   inline Value& operator=(Value&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -318,13 +313,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Value& default_instance();
-
+  static const Value& default_instance() {
+    return *internal_default_instance();
+  }
   enum KindCase {
     kNullValue = 1,
     kNumberValue = 2,
@@ -335,7 +331,6 @@
     KIND_NOT_SET = 0,
   };
 
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
   static inline const Value* internal_default_instance() {
     return reinterpret_cast<const Value*>(
                &_Value_default_instance_);
@@ -348,7 +343,7 @@
   }
   inline void Swap(Value* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -356,23 +351,26 @@
   }
   void UnsafeArenaSwap(Value* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Value* New() const final {
-    return CreateMaybeMessage<Value>(nullptr);
+    return new Value();
   }
 
   Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Value>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Value& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Value& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -383,8 +381,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Value* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -392,20 +390,17 @@
     return "google.protobuf.Value";
   }
   protected:
-  explicit Value(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -420,6 +415,7 @@
     kListValueFieldNumber = 6,
   };
   // .google.protobuf.NullValue null_value = 1;
+  bool has_null_value() const;
   private:
   bool _internal_has_null_value() const;
   public:
@@ -432,6 +428,7 @@
   public:
 
   // double number_value = 2;
+  bool has_number_value() const;
   private:
   bool _internal_has_number_value() const;
   public:
@@ -444,34 +441,25 @@
   public:
 
   // string string_value = 3;
+  bool has_string_value() const;
   private:
   bool _internal_has_string_value() const;
   public:
   void clear_string_value();
   const std::string& string_value() const;
-  void set_string_value(const std::string& value);
-  void set_string_value(std::string&& value);
-  void set_string_value(const char* value);
-  void set_string_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_string_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_string_value();
-  std::string* release_string_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_string_value();
   void set_allocated_string_value(std::string* string_value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_string_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_string_value(
-      std::string* string_value);
   private:
   const std::string& _internal_string_value() const;
-  void _internal_set_string_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_string_value(const std::string& value);
   std::string* _internal_mutable_string_value();
   public:
 
   // bool bool_value = 4;
+  bool has_bool_value() const;
   private:
   bool _internal_has_bool_value() const;
   public:
@@ -490,7 +478,7 @@
   public:
   void clear_struct_value();
   const PROTOBUF_NAMESPACE_ID::Struct& struct_value() const;
-  PROTOBUF_NAMESPACE_ID::Struct* release_struct_value();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::Struct* release_struct_value();
   PROTOBUF_NAMESPACE_ID::Struct* mutable_struct_value();
   void set_allocated_struct_value(PROTOBUF_NAMESPACE_ID::Struct* struct_value);
   private:
@@ -508,7 +496,7 @@
   public:
   void clear_list_value();
   const PROTOBUF_NAMESPACE_ID::ListValue& list_value() const;
-  PROTOBUF_NAMESPACE_ID::ListValue* release_list_value();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::ListValue* release_list_value();
   PROTOBUF_NAMESPACE_ID::ListValue* mutable_list_value();
   void set_allocated_list_value(PROTOBUF_NAMESPACE_ID::ListValue* list_value);
   private:
@@ -538,7 +526,8 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   union KindUnion {
-    KindUnion() {}
+    constexpr KindUnion() : _constinit_{} {}
+      ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized _constinit_;
     int null_value_;
     double number_value_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_;
@@ -553,11 +542,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT ListValue PROTOBUF_FINAL :
+class PROTOBUF_EXPORT ListValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ {
  public:
-  inline ListValue() : ListValue(nullptr) {};
-  virtual ~ListValue();
+  inline ListValue() : ListValue(nullptr) {}
+  ~ListValue() override;
+  explicit constexpr ListValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ListValue(const ListValue& from);
   ListValue(ListValue&& from) noexcept
@@ -570,8 +560,9 @@
     return *this;
   }
   inline ListValue& operator=(ListValue&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -582,14 +573,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const ListValue& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const ListValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ListValue* internal_default_instance() {
     return reinterpret_cast<const ListValue*>(
                &_ListValue_default_instance_);
@@ -602,7 +593,7 @@
   }
   inline void Swap(ListValue* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -610,23 +601,26 @@
   }
   void UnsafeArenaSwap(ListValue* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline ListValue* New() const final {
-    return CreateMaybeMessage<ListValue>(nullptr);
+    return new ListValue();
   }
 
   ListValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<ListValue>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const ListValue& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const ListValue& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -637,8 +631,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(ListValue* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -646,20 +640,17 @@
     return "google.protobuf.ListValue";
   }
   protected:
-  explicit ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -747,6 +738,9 @@
 inline bool Value::_internal_has_null_value() const {
   return kind_case() == kNullValue;
 }
+inline bool Value::has_null_value() const {
+  return _internal_has_null_value();
+}
 inline void Value::set_has_null_value() {
   _oneof_case_[0] = kNullValue;
 }
@@ -774,14 +768,17 @@
   kind_.null_value_ = value;
 }
 inline void Value::set_null_value(PROTOBUF_NAMESPACE_ID::NullValue value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value)
   _internal_set_null_value(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value)
 }
 
 // double number_value = 2;
 inline bool Value::_internal_has_number_value() const {
   return kind_case() == kNumberValue;
 }
+inline bool Value::has_number_value() const {
+  return _internal_has_number_value();
+}
 inline void Value::set_has_number_value() {
   _oneof_case_[0] = kNumberValue;
 }
@@ -817,12 +814,15 @@
 inline bool Value::_internal_has_string_value() const {
   return kind_case() == kStringValue;
 }
+inline bool Value::has_string_value() const {
+  return _internal_has_string_value();
+}
 inline void Value::set_has_string_value() {
   _oneof_case_[0] = kStringValue;
 }
 inline void Value::clear_string_value() {
   if (_internal_has_string_value()) {
-    kind_.string_value_.Destroy(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+    kind_.string_value_.Destroy(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
     clear_has_kind();
   }
 }
@@ -830,19 +830,26 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value)
   return _internal_string_value();
 }
-inline void Value::set_string_value(const std::string& value) {
-  _internal_set_string_value(value);
+template <typename ArgT0, typename... ArgT>
+inline void Value::set_string_value(ArgT0&& arg0, ArgT... args) {
+  if (!_internal_has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
 }
 inline std::string* Value::mutable_string_value() {
+  std::string* _s = _internal_mutable_string_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value)
-  return _internal_mutable_string_value();
+  return _s;
 }
 inline const std::string& Value::_internal_string_value() const {
   if (_internal_has_string_value()) {
     return kind_.string_value_.Get();
   }
-  return *&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited();
+  return ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited();
 }
 inline void Value::_internal_set_string_value(const std::string& value) {
   if (!_internal_has_string_value()) {
@@ -850,42 +857,7 @@
     set_has_string_value();
     kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   }
-  kind_.string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Value::set_string_value(std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
-  if (!_internal_has_string_value()) {
-    clear_kind();
-    set_has_string_value();
-    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  }
-  kind_.string_value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value)
-}
-inline void Value::set_string_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  if (!_internal_has_string_value()) {
-    clear_kind();
-    set_has_string_value();
-    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  }
-  kind_.string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value)
-}
-inline void Value::set_string_value(const char* value,
-                             size_t size) {
-  if (!_internal_has_string_value()) {
-    clear_kind();
-    set_has_string_value();
-    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  }
-  kind_.string_value_.Set(
-      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size),
-      GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value)
+  kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Value::_internal_mutable_string_value() {
   if (!_internal_has_string_value()) {
@@ -893,13 +865,14 @@
     set_has_string_value();
     kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   }
-  return kind_.string_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return kind_.string_value_.Mutable(
+      ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Value::release_string_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value)
   if (_internal_has_string_value()) {
     clear_has_kind();
-    return kind_.string_value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+    return kind_.string_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
   } else {
     return nullptr;
   }
@@ -911,37 +884,21 @@
   if (string_value != nullptr) {
     set_has_string_value();
     kind_.string_value_.UnsafeSetDefault(string_value);
+    ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArenaForAllocation();
+    if (arena != nullptr) {
+      arena->Own(string_value);
+    }
   }
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value)
 }
-inline std::string* Value::unsafe_arena_release_string_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.string_value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (_internal_has_string_value()) {
-    clear_has_kind();
-    return kind_.string_value_.UnsafeArenaRelease(
-        &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  } else {
-    return nullptr;
-  }
-}
-inline void Value::unsafe_arena_set_allocated_string_value(std::string* string_value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (!_internal_has_string_value()) {
-    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  }
-  clear_kind();
-  if (string_value) {
-    set_has_string_value();
-    kind_.string_value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), string_value, GetArena());
-  }
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.string_value)
-}
 
 // bool bool_value = 4;
 inline bool Value::_internal_has_bool_value() const {
   return kind_case() == kBoolValue;
 }
+inline bool Value::has_bool_value() const {
+  return _internal_has_bool_value();
+}
 inline void Value::set_has_bool_value() {
   _oneof_case_[0] = kBoolValue;
 }
@@ -985,7 +942,7 @@
 }
 inline void Value::clear_struct_value() {
   if (_internal_has_struct_value()) {
-    if (GetArena() == nullptr) {
+    if (GetArenaForAllocation() == nullptr) {
       delete kind_.struct_value_;
     }
     clear_has_kind();
@@ -996,7 +953,7 @@
   if (_internal_has_struct_value()) {
     clear_has_kind();
       PROTOBUF_NAMESPACE_ID::Struct* temp = kind_.struct_value_;
-    if (GetArena() != nullptr) {
+    if (GetArenaForAllocation() != nullptr) {
       temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
     }
     kind_.struct_value_ = nullptr;
@@ -1008,7 +965,7 @@
 inline const PROTOBUF_NAMESPACE_ID::Struct& Value::_internal_struct_value() const {
   return _internal_has_struct_value()
       ? *kind_.struct_value_
-      : *reinterpret_cast< PROTOBUF_NAMESPACE_ID::Struct*>(&PROTOBUF_NAMESPACE_ID::_Struct_default_instance_);
+      : reinterpret_cast< PROTOBUF_NAMESPACE_ID::Struct&>(PROTOBUF_NAMESPACE_ID::_Struct_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::Struct& Value::struct_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value)
@@ -1037,13 +994,14 @@
   if (!_internal_has_struct_value()) {
     clear_kind();
     set_has_struct_value();
-    kind_.struct_value_ = CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Struct >(GetArena());
+    kind_.struct_value_ = CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Struct >(GetArenaForAllocation());
   }
   return kind_.struct_value_;
 }
 inline PROTOBUF_NAMESPACE_ID::Struct* Value::mutable_struct_value() {
+  PROTOBUF_NAMESPACE_ID::Struct* _msg = _internal_mutable_struct_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value)
-  return _internal_mutable_struct_value();
+  return _msg;
 }
 
 // .google.protobuf.ListValue list_value = 6;
@@ -1058,7 +1016,7 @@
 }
 inline void Value::clear_list_value() {
   if (_internal_has_list_value()) {
-    if (GetArena() == nullptr) {
+    if (GetArenaForAllocation() == nullptr) {
       delete kind_.list_value_;
     }
     clear_has_kind();
@@ -1069,7 +1027,7 @@
   if (_internal_has_list_value()) {
     clear_has_kind();
       PROTOBUF_NAMESPACE_ID::ListValue* temp = kind_.list_value_;
-    if (GetArena() != nullptr) {
+    if (GetArenaForAllocation() != nullptr) {
       temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
     }
     kind_.list_value_ = nullptr;
@@ -1081,7 +1039,7 @@
 inline const PROTOBUF_NAMESPACE_ID::ListValue& Value::_internal_list_value() const {
   return _internal_has_list_value()
       ? *kind_.list_value_
-      : *reinterpret_cast< PROTOBUF_NAMESPACE_ID::ListValue*>(&PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_);
+      : reinterpret_cast< PROTOBUF_NAMESPACE_ID::ListValue&>(PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::ListValue& Value::list_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value)
@@ -1110,13 +1068,14 @@
   if (!_internal_has_list_value()) {
     clear_kind();
     set_has_list_value();
-    kind_.list_value_ = CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::ListValue >(GetArena());
+    kind_.list_value_ = CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::ListValue >(GetArenaForAllocation());
   }
   return kind_.list_value_;
 }
 inline PROTOBUF_NAMESPACE_ID::ListValue* Value::mutable_list_value() {
+  PROTOBUF_NAMESPACE_ID::ListValue* _msg = _internal_mutable_list_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value)
-  return _internal_mutable_list_value();
+  return _msg;
 }
 
 inline bool Value::has_kind() const {
@@ -1162,8 +1121,9 @@
   return values_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Value* ListValue::add_values() {
+  PROTOBUF_NAMESPACE_ID::Value* _add = _internal_add_values();
   // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values)
-  return _internal_add_values();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Value >&
 ListValue::values() const {
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
index ed990e3..545215c 100644
--- a/src/google/protobuf/struct.proto
+++ b/src/google/protobuf/struct.proto
@@ -34,7 +34,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
-option go_package = "github.com/golang/protobuf/ptypes/struct;structpb";
+option go_package = "google.golang.org/protobuf/types/known/structpb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "StructProto";
 option java_multiple_files = true;
diff --git a/src/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc
index a0f298e..980d6f6 100644
--- a/src/google/protobuf/stubs/bytestream.cc
+++ b/src/google/protobuf/stubs/bytestream.cc
@@ -173,12 +173,8 @@
 }
 
 StringPiece LimitByteSource::Peek() {
-  StringPiece piece(source_->Peek());
-  if (piece.size() > limit_) {
-    piece.set(piece.data(), limit_);
-  }
-
-  return piece;
+  StringPiece piece = source_->Peek();
+  return StringPiece(piece.data(), std::min(piece.size(), limit_));
 }
 
 void LimitByteSource::Skip(size_t n) {
diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h
index 0193301..c7a48de 100644
--- a/src/google/protobuf/stubs/bytestream.h
+++ b/src/google/protobuf/stubs/bytestream.h
@@ -256,11 +256,11 @@
 //
 class PROTOBUF_EXPORT StringByteSink : public ByteSink {
  public:
-  explicit StringByteSink(string* dest) : dest_(dest) {}
+  explicit StringByteSink(std::string* dest) : dest_(dest) {}
   virtual void Append(const char* data, size_t n) override;
 
  private:
-  string* dest_;
+  std::string* dest_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink);
 };
 
diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc
index 06f114a..cb11825 100644
--- a/src/google/protobuf/stubs/bytestream_unittest.cc
+++ b/src/google/protobuf/stubs/bytestream_unittest.cc
@@ -64,7 +64,7 @@
 TEST(ByteSourceTest, CopyTo) {
   StringPiece data("Hello world!");
   MockByteSource source(data, 3);
-  string str;
+  std::string str;
   StringByteSink sink(&str);
 
   source.CopyTo(&sink, data.size());
@@ -75,7 +75,7 @@
   StringPiece data("Hello world!");
   MockByteSource source(data, 3);
   source.Skip(1);
-  string str;
+  std::string str;
   StringByteSink sink(&str);
 
   source.CopyTo(&sink, data.size() - 2);
@@ -92,7 +92,7 @@
   EXPECT_EQ(5, limit_source.Available());
 
   {
-    string str;
+    std::string str;
     StringByteSink sink(&str);
     limit_source.CopyTo(&sink, limit_source.Available());
     EXPECT_EQ("ello ", str);
@@ -101,7 +101,7 @@
   }
 
   {
-    string str;
+    std::string str;
     StringByteSink sink(&str);
     source.CopyTo(&sink, source.Available());
     EXPECT_EQ("world!", str);
@@ -112,7 +112,7 @@
 TEST(ByteSourceTest, CopyToStringByteSink) {
   StringPiece data("Hello world!");
   MockByteSource source(data, 3);
-  string str;
+  std::string str;
   StringByteSink sink(&str);
   source.CopyTo(&sink, data.size());
   EXPECT_EQ(data, str);
@@ -121,7 +121,7 @@
 // Verify that ByteSink is subclassable and Flush() overridable.
 class FlushingByteSink : public StringByteSink {
  public:
-  explicit FlushingByteSink(string* dest) : StringByteSink(dest) {}
+  explicit FlushingByteSink(std::string* dest) : StringByteSink(dest) {}
   virtual void Flush() { Append("z", 1); }
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink);
@@ -134,7 +134,7 @@
 }
 
 TEST(ByteSinkTest, Flush) {
-  string str;
+  std::string str;
   FlushingByteSink f_sink(&str);
   WriteAndFlush(&f_sink);
   EXPECT_STREQ("abcz", str.c_str());
diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
index b7a3a82..43d546d 100644
--- a/src/google/protobuf/stubs/callback.h
+++ b/src/google/protobuf/stubs/callback.h
@@ -62,12 +62,12 @@
 // Note that NewCallback() is a bit touchy regarding argument types.  Generally,
 // the values you provide for the parameter bindings must exactly match the
 // types accepted by the callback function.  For example:
-//   void Foo(string s);
+//   void Foo(std::string s);
 //   NewCallback(&Foo, "foo");          // WON'T WORK:  const char* != string
-//   NewCallback(&Foo, string("foo"));  // WORKS
+//   NewCallback(&Foo, std::string("foo"));  // WORKS
 // Also note that the arguments cannot be references:
-//   void Foo(const string& s);
-//   string my_str;
+//   void Foo(const std::string& s);
+//   std::string my_str;
 //   NewCallback(&Foo, my_str);  // WON'T WORK:  Can't use references.
 // However, correctly-typed pointers will work just fine.
 class PROTOBUF_EXPORT Closure {
diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h
index 83750bd..ad29dac 100644
--- a/src/google/protobuf/stubs/casts.h
+++ b/src/google/protobuf/stubs/casts.h
@@ -47,7 +47,7 @@
 // When you use implicit_cast, the compiler checks that the cast is safe.
 // Such explicit implicit_casts are necessary in surprisingly many
 // situations where C++ demands an exact type match instead of an
-// argument type convertable to a target type.
+// argument type convertible to a target type.
 //
 // The From type can be inferred, so the preferred syntax for using
 // implicit_cast is the same as for static_cast etc.:
@@ -116,8 +116,7 @@
 
 template<typename To, typename From>
 inline To bit_cast(const From& from) {
-  GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
-                        bit_cast_with_different_sizes);
+  static_assert(sizeof(From) == sizeof(To), "bit_cast_with_different_sizes");
   To dest;
   memcpy(&dest, &from, sizeof(dest));
   return dest;
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
index 4db493b..9067818 100644
--- a/src/google/protobuf/stubs/common.cc
+++ b/src/google/protobuf/stubs/common.cc
@@ -96,7 +96,7 @@
   }
 }
 
-string VersionString(int version) {
+std::string VersionString(int version) {
   int major = version / 1000000;
   int minor = (version / 1000) % 1000;
   int micro = version % 1000;
@@ -127,7 +127,7 @@
 
 #if defined(__ANDROID__)
 inline void DefaultLogHandler(LogLevel level, const char* filename, int line,
-                              const string& message) {
+                              const std::string& message) {
   if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) {
     return;
   }
@@ -162,7 +162,7 @@
 
 #else
 void DefaultLogHandler(LogLevel level, const char* filename, int line,
-                       const string& message) {
+                       const std::string& message) {
   if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) {
     return;
   }
@@ -177,14 +177,14 @@
 #endif
 
 void NullLogHandler(LogLevel /* level */, const char* /* filename */,
-                    int /* line */, const string& /* message */) {
+                    int /* line */, const std::string& /* message */) {
   // Nothing.
 }
 
 static LogHandler* log_handler_ = &DefaultLogHandler;
 static std::atomic<int> log_silencer_count_ = ATOMIC_VAR_INIT(0);
 
-LogMessage& LogMessage::operator<<(const string& value) {
+LogMessage& LogMessage::operator<<(const std::string& value) {
   message_ += value;
   return *this;
 }
@@ -211,32 +211,29 @@
   return *this;
 }
 
-// Since this is just for logging, we don't care if the current locale changes
-// the results -- in fact, we probably prefer that.  So we use snprintf()
-// instead of Simple*toa().
+LogMessage& LogMessage::operator<<(char value) {
+  return *this << StringPiece(&value, 1);
+}
+
+LogMessage& LogMessage::operator<<(void* value) {
+  StrAppend(&message_, strings::Hex(reinterpret_cast<uintptr_t>(value)));
+  return *this;
+}
+
 #undef DECLARE_STREAM_OPERATOR
-#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT)                       \
-  LogMessage& LogMessage::operator<<(TYPE value) {                  \
-    /* 128 bytes should be big enough for any of the primitive */   \
-    /* values which we print with this, but well use snprintf() */  \
-    /* anyway to be extra safe. */                                  \
-    char buffer[128];                                               \
-    snprintf(buffer, sizeof(buffer), FORMAT, value);                \
-    /* Guard against broken MSVC snprintf(). */                     \
-    buffer[sizeof(buffer)-1] = '\0';                                \
-    message_ += buffer;                                             \
-    return *this;                                                   \
+#define DECLARE_STREAM_OPERATOR(TYPE)              \
+  LogMessage& LogMessage::operator<<(TYPE value) { \
+    StrAppend(&message_, value);                   \
+    return *this;                                  \
   }
 
-DECLARE_STREAM_OPERATOR(char         , "%c" )
-DECLARE_STREAM_OPERATOR(int          , "%d" )
-DECLARE_STREAM_OPERATOR(unsigned int , "%u" )
-DECLARE_STREAM_OPERATOR(long         , "%ld")
-DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
-DECLARE_STREAM_OPERATOR(double       , "%g" )
-DECLARE_STREAM_OPERATOR(void*        , "%p" )
-DECLARE_STREAM_OPERATOR(long long         , "%" PROTOBUF_LL_FORMAT "d")
-DECLARE_STREAM_OPERATOR(unsigned long long, "%" PROTOBUF_LL_FORMAT "u")
+DECLARE_STREAM_OPERATOR(int)
+DECLARE_STREAM_OPERATOR(unsigned int)
+DECLARE_STREAM_OPERATOR(long)           // NOLINT(runtime/int)
+DECLARE_STREAM_OPERATOR(unsigned long)  // NOLINT(runtime/int)
+DECLARE_STREAM_OPERATOR(double)
+DECLARE_STREAM_OPERATOR(long long)           // NOLINT(runtime/int)
+DECLARE_STREAM_OPERATOR(unsigned long long)  // NOLINT(runtime/int)
 #undef DECLARE_STREAM_OPERATOR
 
 LogMessage::LogMessage(LogLevel level, const char* filename, int line)
@@ -304,7 +301,7 @@
 //
 // TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in
 // google/protobuf/io/coded_stream.h and therefore can not be used here.
-// Maybe move that macro definition here in the furture.
+// Maybe move that macro definition here in the future.
 uint32 ghtonl(uint32 x) {
   union {
     uint32 result;
@@ -327,3 +324,5 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 1c9084f..23125bf 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -43,9 +43,10 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/port.h>
 #include <google/protobuf/stubs/macros.h>
 #include <google/protobuf/stubs/platform_macros.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/stringpiece.h>
 
 #ifndef PROTOBUF_USE_EXCEPTIONS
 #if defined(_MSC_VER) && defined(_CPPUNWIND)
@@ -81,7 +82,7 @@
 
 // The current version, represented as a single integer to make comparison
 // easier:  major * 10^6 + minor * 10^3 + micro
-#define GOOGLE_PROTOBUF_VERSION 3011004
+#define GOOGLE_PROTOBUF_VERSION 3017003
 
 // A suffix string for alpha, beta or rc releases. Empty for stable releases.
 #define GOOGLE_PROTOBUF_VERSION_SUFFIX ""
@@ -89,15 +90,15 @@
 // The minimum header version which works with the current version of
 // the library.  This constant should only be used by protoc's C++ code
 // generator.
-static const int kMinHeaderVersionForLibrary = 3011000;
+static const int kMinHeaderVersionForLibrary = 3017000;
 
 // The minimum protoc version which works with the current version of the
 // headers.
-#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3011000
+#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3017000
 
 // The minimum header version which works with the current version of
 // protoc.  This constant should only be used in VerifyVersion().
-static const int kMinHeaderVersionForProtoc = 3011000;
+static const int kMinHeaderVersionForProtoc = 3017000;
 
 // Verifies that the headers and libraries are compatible.  Use the macro
 // below to call this.
@@ -122,19 +123,18 @@
 // ===================================================================
 // from google3/util/utf8/public/unilib.h
 
-class StringPiece;
 namespace internal {
 
 // Checks if the buffer contains structurally-valid UTF-8.  Implemented in
 // structurally_valid.cc.
 PROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
 
-inline bool IsStructurallyValidUTF8(const std::string& str) {
+inline bool IsStructurallyValidUTF8(StringPiece str) {
   return IsStructurallyValidUTF8(str.data(), static_cast<int>(str.length()));
 }
 
 // Returns initial number of bytes of structurally valid UTF-8.
-PROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str);
+PROTOBUF_EXPORT int UTF8SpnStructurallyValid(StringPiece str);
 
 // Coerce UTF-8 byte string in src_str to be
 // a structurally-valid equal-length string by selectively
@@ -148,8 +148,7 @@
 //
 // Optimized for: all structurally valid and no byte copying is done.
 //
-PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(const StringPiece& str,
-                                                    char* dst,
+PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(StringPiece str, char* dst,
                                                     char replace_char);
 
 }  // namespace internal
@@ -177,7 +176,7 @@
       : filename_(filename), line_(line), message_(message) {}
   virtual ~FatalException() throw();
 
-  virtual const char* what() const throw();
+  virtual const char* what() const throw() override;
 
   const char* filename() const { return filename_; }
   int line() const { return line_; }
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
index 5852458..c55e452 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -53,7 +53,7 @@
   // Verify that the version string specified in config.h matches the one
   // in common.h.  The config.h version is a string which may have a suffix
   // like "beta" or "rc1", so we remove that.
-  string version = PACKAGE_VERSION;
+  std::string version = PACKAGE_VERSION;
   int pos = 0;
   while (pos < version.size() &&
          (ascii_isdigit(version[pos]) || version[pos] == '.')) {
@@ -77,10 +77,10 @@
   EXPECT_EQ(0, kuint64max + 1);
 }
 
-std::vector<string> captured_messages_;
+std::vector<std::string> captured_messages_;
 
 void CaptureLog(LogLevel level, const char* filename, int line,
-                const string& message) {
+                const std::string& message) {
   captured_messages_.push_back(
     strings::Substitute("$0 $1:$2: $3",
       implicit_cast<int>(level), filename, line, message));
@@ -93,7 +93,7 @@
   GOOGLE_LOG(WARNING) << "A warning.";
   GOOGLE_LOG(ERROR  ) << "An error.";
 
-  string text = GetCapturedTestStderr();
+  std::string text = GetCapturedTestStderr();
   EXPECT_EQ(
     "[libprotobuf INFO " __FILE__ ":" + SimpleItoa(line + 1) + "] A message.\n"
     "[libprotobuf WARNING " __FILE__ ":" + SimpleItoa(line + 2) + "] A warning.\n"
@@ -111,7 +111,7 @@
 
   EXPECT_TRUE(SetLogHandler(old_handler) == nullptr);
 
-  string text = GetCapturedTestStderr();
+  std::string text = GetCapturedTestStderr();
   EXPECT_EQ("", text);
 }
 
@@ -167,10 +167,10 @@
   static void SetA123Function() { current_instance_->a_ = 123; }
 
   void SetAMethod(int a)         { a_ = a; }
-  void SetCMethod(string c)      { c_ = c; }
+  void SetCMethod(std::string c) { c_ = c; }
 
   static void SetAFunction(int a)         { current_instance_->a_ = a; }
-  static void SetCFunction(string c)      { current_instance_->c_ = c; }
+  static void SetCFunction(std::string c) { current_instance_->c_ = c; }
 
   void SetABMethod(int a, const char* b)  { a_ = a; b_ = b; }
   static void SetABFunction(int a, const char* b) {
@@ -192,7 +192,7 @@
 
   int a_;
   const char* b_;
-  string c_;
+  std::string c_;
   Closure* permanent_closure_;
 
   static ClosureTest* current_instance_;
@@ -231,15 +231,15 @@
 }
 
 TEST_F(ClosureTest, TestClosureFunction1String) {
-  Closure* closure = NewCallback(&SetCFunction, string("test"));
+  Closure* closure = NewCallback(&SetCFunction, std::string("test"));
   EXPECT_NE("test", c_);
   closure->Run();
   EXPECT_EQ("test", c_);
 }
 
 TEST_F(ClosureTest, TestClosureMethod1String) {
-  Closure* closure = NewCallback(current_instance_,
-                                 &ClosureTest::SetCMethod, string("test"));
+  Closure* closure = NewCallback(current_instance_, &ClosureTest::SetCMethod,
+                                 std::string("test"));
   EXPECT_NE("test", c_);
   closure->Run();
   EXPECT_EQ("test", c_);
diff --git a/src/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h
deleted file mode 100644
index 76c8a3a..0000000
--- a/src/google/protobuf/stubs/fastmem.h
+++ /dev/null
@@ -1,157 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2014 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Fast memory copying and comparison routines.
-//   strings::fastmemcmp_inlined() replaces memcmp()
-//   strings::memcpy_inlined() replaces memcpy()
-//   strings::memeq(a, b, n) replaces memcmp(a, b, n) == 0
-//
-// strings::*_inlined() routines are inline versions of the
-// routines exported by this module.  Sometimes using the inlined
-// versions is faster.  Measure before using the inlined versions.
-//
-// Performance measurement:
-//   strings::fastmemcmp_inlined
-//     Analysis: memcmp, fastmemcmp_inlined, fastmemcmp
-//     2012-01-30
-
-#ifndef GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
-#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <google/protobuf/stubs/common.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-// Return true if the n bytes at a equal the n bytes at b.
-// The regions are allowed to overlap.
-//
-// The performance is similar to the performance memcmp(), but faster for
-// moderately-sized inputs, or inputs that share a common prefix and differ
-// somewhere in their last 8 bytes. Further optimizations can be added later
-// if it makes sense to do so.:w
-inline bool memeq(const char* a, const char* b, size_t n) {
-  size_t n_rounded_down = n & ~static_cast<size_t>(7);
-  if (PROTOBUF_PREDICT_FALSE(n_rounded_down == 0)) {  // n <= 7
-    return memcmp(a, b, n) == 0;
-  }
-  // n >= 8
-  uint64 u = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
-  uint64 v = GOOGLE_UNALIGNED_LOAD64(a + n - 8) ^ GOOGLE_UNALIGNED_LOAD64(b + n - 8);
-  if ((u | v) != 0) {  // The first or last 8 bytes differ.
-    return false;
-  }
-  a += 8;
-  b += 8;
-  n = n_rounded_down - 8;
-  if (n > 128) {
-    // As of 2012, memcmp on x86-64 uses a big unrolled loop with SSE2
-    // instructions, and while we could try to do something faster, it
-    // doesn't seem worth pursuing.
-    return memcmp(a, b, n) == 0;
-  }
-  for (; n >= 16; n -= 16) {
-    uint64 x = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
-    uint64 y = GOOGLE_UNALIGNED_LOAD64(a + 8) ^ GOOGLE_UNALIGNED_LOAD64(b + 8);
-    if ((x | y) != 0) {
-      return false;
-    }
-    a += 16;
-    b += 16;
-  }
-  // n must be 0 or 8 now because it was a multiple of 8 at the top of the loop.
-  return n == 0 || GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b);
-}
-
-inline int fastmemcmp_inlined(const char *a, const char *b, size_t n) {
-  if (n >= 64) {
-    return memcmp(a, b, n);
-  }
-  const char* a_limit = a + n;
-  while (a + sizeof(uint64) <= a_limit &&
-         GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b)) {
-    a += sizeof(uint64);
-    b += sizeof(uint64);
-  }
-  if (a + sizeof(uint32) <= a_limit &&
-      GOOGLE_UNALIGNED_LOAD32(a) == GOOGLE_UNALIGNED_LOAD32(b)) {
-    a += sizeof(uint32);
-    b += sizeof(uint32);
-  }
-  while (a < a_limit) {
-    int d =
-        static_cast<int>(static_cast<uint32>(*a++) - static_cast<uint32>(*b++));
-    if (d) return d;
-  }
-  return 0;
-}
-
-// The standard memcpy operation is slow for variable small sizes.
-// This implementation inlines the optimal realization for sizes 1 to 16.
-// To avoid code bloat don't use it in case of not performance-critical spots,
-// nor when you don't expect very frequent values of size <= 16.
-inline void memcpy_inlined(char *dst, const char *src, size_t size) {
-  // Compiler inlines code with minimal amount of data movement when third
-  // parameter of memcpy is a constant.
-  switch (size) {
-    case  1: memcpy(dst, src, 1); break;
-    case  2: memcpy(dst, src, 2); break;
-    case  3: memcpy(dst, src, 3); break;
-    case  4: memcpy(dst, src, 4); break;
-    case  5: memcpy(dst, src, 5); break;
-    case  6: memcpy(dst, src, 6); break;
-    case  7: memcpy(dst, src, 7); break;
-    case  8: memcpy(dst, src, 8); break;
-    case  9: memcpy(dst, src, 9); break;
-    case 10: memcpy(dst, src, 10); break;
-    case 11: memcpy(dst, src, 11); break;
-    case 12: memcpy(dst, src, 12); break;
-    case 13: memcpy(dst, src, 13); break;
-    case 14: memcpy(dst, src, 14); break;
-    case 15: memcpy(dst, src, 15); break;
-    case 16: memcpy(dst, src, 16); break;
-    default: memcpy(dst, src, size); break;
-  }
-}
-
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index a093b40..a7ec068 100644
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -33,9 +33,8 @@
 #ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
 #define GOOGLE_PROTOBUF_STUBS_HASH_H__
 
-#include <string.h>
-#include <google/protobuf/stubs/common.h>
-
+#include <cstring>
+#include <string>
 #include <unordered_map>
 #include <unordered_set>
 
@@ -78,14 +77,14 @@
 };
 
 template <>
-struct hash<string> {
-  inline size_t operator()(const string& key) const {
+struct hash<std::string> {
+  inline size_t operator()(const std::string& key) const {
     return hash<const char*>()(key.c_str());
   }
 
   static const size_t bucket_size = 4;
   static const size_t min_buckets = 8;
-  inline bool operator()(const string& a, const string& b) const {
+  inline bool operator()(const std::string& a, const std::string& b) const {
     return a < b;
   }
 };
@@ -109,14 +108,6 @@
   }
 };
 
-// Used by GCC/SGI STL only.  (Why isn't this provided by the standard
-// library?  :( )
-struct streq {
-  inline bool operator()(const char* a, const char* b) const {
-    return strcmp(a, b) == 0;
-  }
-};
-
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
index 2119e65..e5e159e 100644
--- a/src/google/protobuf/stubs/int128.cc
+++ b/src/google/protobuf/stubs/int128.cc
@@ -41,10 +41,8 @@
 namespace google {
 namespace protobuf {
 
-const uint128_pod kuint128max = {
-    static_cast<uint64>(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF)),
-    static_cast<uint64>(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF))
-};
+const uint128_pod kuint128max = {uint64_t{0xFFFFFFFFFFFFFFFFu},
+                                 uint64_t{0xFFFFFFFFFFFFFFFFu}};
 
 // Returns the 0-based position of the last set bit (i.e., most significant bit)
 // in the given uint64. The argument may not be 0.
@@ -67,7 +65,7 @@
   STEP(uint32, n32, pos, 0x10);
   STEP(uint32, n32, pos, 0x08);
   STEP(uint32, n32, pos, 0x04);
-  return pos + ((PROTOBUF_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3);
+  return pos + ((uint64_t{0x3333333322221100u} >> (n32 << 2)) & 0x3);
 }
 #undef STEP
 
@@ -134,17 +132,17 @@
   switch (flags & std::ios::basefield) {
     case std::ios::hex:
       div =
-          static_cast<uint64>(PROTOBUF_ULONGLONG(0x1000000000000000));  // 16^15
+          static_cast<uint64>(uint64_t{0x1000000000000000u});  // 16^15
       div_base_log = 15;
       break;
     case std::ios::oct:
       div = static_cast<uint64>(
-          PROTOBUF_ULONGLONG(01000000000000000000000));  // 8^21
+          uint64_t{01000000000000000000000u});  // 8^21
       div_base_log = 21;
       break;
     default:  // std::ios::dec
       div = static_cast<uint64>(
-          PROTOBUF_ULONGLONG(10000000000000000000));  // 10^19
+          uint64_t{10000000000000000000u});  // 10^19
       div_base_log = 19;
       break;
   }
@@ -190,3 +188,5 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>  // NOLINT
diff --git a/src/google/protobuf/stubs/int128_unittest.cc b/src/google/protobuf/stubs/int128_unittest.cc
index 9a8125d..77e41cc 100644
--- a/src/google/protobuf/stubs/int128_unittest.cc
+++ b/src/google/protobuf/stubs/int128_unittest.cc
@@ -293,26 +293,20 @@
   }
 
   // Verified with dc.
-  a = uint128(PROTOBUF_ULONGLONG(0xffffeeeeddddcccc),
-              PROTOBUF_ULONGLONG(0xbbbbaaaa99998888));
-  b = uint128(PROTOBUF_ULONGLONG(0x7777666655554444),
-              PROTOBUF_ULONGLONG(0x3333222211110000));
+  a = uint128(uint64_t{0xffffeeeeddddccccu}, uint64_t{0xbbbbaaaa99998888u});
+  b = uint128(uint64_t{0x7777666655554444u}, uint64_t{0x3333222211110000u});
   c = a * b;
-  EXPECT_EQ(uint128(PROTOBUF_ULONGLONG(0x530EDA741C71D4C3),
-                    PROTOBUF_ULONGLONG(0xBF25975319080000)),
-            c);
+  EXPECT_EQ(
+      uint128(uint64_t{0x530EDA741C71D4C3u}, uint64_t{0xBF25975319080000u}), c);
   EXPECT_EQ(0, c - b * a);
   EXPECT_EQ(a * a - b * b, (a + b) * (a - b));
 
   // Verified with dc.
-  a = uint128(PROTOBUF_ULONGLONG(0x0123456789abcdef),
-              PROTOBUF_ULONGLONG(0xfedcba9876543210));
-  b = uint128(PROTOBUF_ULONGLONG(0x02468ace13579bdf),
-              PROTOBUF_ULONGLONG(0xfdb97531eca86420));
+  a = uint128(uint64_t{0x0123456789abcdefu}, uint64_t{0xfedcba9876543210u});
+  b = uint128(uint64_t{0x02468ace13579bdfu}, uint64_t{0xfdb97531eca86420u});
   c = a * b;
-  EXPECT_EQ(uint128(PROTOBUF_ULONGLONG(0x97a87f4f261ba3f2),
-                    PROTOBUF_ULONGLONG(0x342d0bbf48948200)),
-            c);
+  EXPECT_EQ(
+      uint128(uint64_t{0x97a87f4f261ba3f2u}, uint64_t{0x342d0bbf48948200u}), c);
   EXPECT_EQ(0, c - b * a);
   EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
 }
@@ -359,10 +353,8 @@
   EXPECT_EQ(0, q);
   EXPECT_EQ(0, r);
 
-  a = uint128(PROTOBUF_ULONGLONG(0x530eda741c71d4c3),
-              PROTOBUF_ULONGLONG(0xbf25975319080000));
-  q = uint128(PROTOBUF_ULONGLONG(0x4de2cab081),
-              PROTOBUF_ULONGLONG(0x14c34ab4676e4bab));
+  a = uint128(uint64_t{0x530eda741c71d4c3u}, uint64_t{0xbf25975319080000u});
+  q = uint128(uint64_t{0x4de2cab081u}, uint64_t{0x14c34ab4676e4babu});
   b = uint128(0x1110001);
   r = uint128(0x3eb455);
   ASSERT_EQ(a, q * b + r);  // Sanity-check.
@@ -400,8 +392,8 @@
 
   // Try a large remainder.
   b = a / 2 + 1;
-  uint128 expected_r(PROTOBUF_ULONGLONG(0x29876d3a0e38ea61),
-                     PROTOBUF_ULONGLONG(0xdf92cba98c83ffff));
+  uint128 expected_r(uint64_t{0x29876d3a0e38ea61u},
+                     uint64_t{0xdf92cba98c83ffffu});
   // Sanity checks.
   ASSERT_EQ(a / 2 - 1, expected_r);
   ASSERT_EQ(a, b + expected_r);
@@ -471,12 +463,12 @@
       {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"},
       {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"},
       // just the top bit
-      {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0,
-       '_', "170141183460469231731687303715884105728"},
-      {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0,
-       '_', "2000000000000000000000000000000000000000000"},
-      {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0,
-       '_', "80000000000000000000000000000000"},
+      {uint128(uint64_t{0x8000000000000000u}, 0), std::ios::dec, 0, '_',
+       "170141183460469231731687303715884105728"},
+      {uint128(uint64_t{0x8000000000000000u}, 0), std::ios::oct, 0, '_',
+       "2000000000000000000000000000000000000000000"},
+      {uint128(uint64_t{0x8000000000000000u}, 0), std::ios::hex, 0, '_',
+       "80000000000000000000000000000000"},
       // maximum uint128 value
       {uint128(-1, -1), std::ios::dec, 0, '_',
        "340282366920938463463374607431768211455"},
@@ -515,3 +507,5 @@
 }
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
index f37048d..8ecc2fa 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -33,6 +33,8 @@
 
 #include <google/protobuf/stubs/macros.h>
 #include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/stringpiece.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -63,10 +65,6 @@
 #endif
 };
 
-class StringPiece;
-namespace util {
-class Status;
-}
 class uint128;
 namespace internal {
 
diff --git a/src/google/protobuf/stubs/macros.h b/src/google/protobuf/stubs/macros.h
index c556d02..ae9a8b9 100644
--- a/src/google/protobuf/stubs/macros.h
+++ b/src/google/protobuf/stubs/macros.h
@@ -31,21 +31,19 @@
 #ifndef GOOGLE_PROTOBUF_MACROS_H__
 #define GOOGLE_PROTOBUF_MACROS_H__
 
-#include <google/protobuf/stubs/port.h>
-
 namespace google {
 namespace protobuf {
 
 #undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
-#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)    \
-  TypeName(const TypeName&);                           \
-  void operator=(const TypeName&)
+#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
+  TypeName(const TypeName&) = delete;               \
+  void operator=(const TypeName&) = delete
 
 #undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
 #define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-  TypeName();                                           \
-  TypeName(const TypeName&);                            \
-  void operator=(const TypeName&)
+  TypeName() = delete;                                  \
+  TypeName(const TypeName&) = delete;                   \
+  void operator=(const TypeName&) = delete
 
 // ===================================================================
 // from google3/base/basictypes.h
@@ -89,31 +87,6 @@
   ((sizeof(a) / sizeof(*(a))) / \
    static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
 
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-//   COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
-//                  content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-
-namespace internal {
-
-template <bool>
-struct CompileAssert {
-};
-
-}  // namespace internal
-
-#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
-
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h
index b222ff7..5c025b1 100644
--- a/src/google/protobuf/stubs/mutex.h
+++ b/src/google/protobuf/stubs/mutex.h
@@ -52,10 +52,12 @@
   __attribute__((acquire_capability(__VA_ARGS__)))
 #define GOOGLE_PROTOBUF_RELEASE(...) \
   __attribute__((release_capability(__VA_ARGS__)))
+#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY __attribute__((scoped_lockable))
 #define GOOGLE_PROTOBUF_CAPABILITY(x) __attribute__((capability(x)))
 #else
 #define GOOGLE_PROTOBUF_ACQUIRE(...)
 #define GOOGLE_PROTOBUF_RELEASE(...)
+#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY
 #define GOOGLE_PROTOBUF_CAPABILITY(x)
 #endif
 
@@ -90,12 +92,37 @@
 
 #endif
 
+// In MSVC std::mutex does not have a constexpr constructor.
+// This wrapper makes the constructor constexpr.
+template <typename T>
+class CallOnceInitializedMutex {
+ public:
+  constexpr CallOnceInitializedMutex() : flag_{}, buf_{} {}
+  ~CallOnceInitializedMutex() { get().~T(); }
+
+  void lock() { get().lock(); }
+  void unlock() { get().unlock(); }
+
+ private:
+  T& get() {
+    std::call_once(flag_, [&] { ::new (static_cast<void*>(&buf_)) T(); });
+    return reinterpret_cast<T&>(buf_);
+  }
+
+  std::once_flag flag_;
+  alignas(T) char buf_[sizeof(T)];
+};
+
 // Mutex is a natural type to wrap. As both google and other organization have
 // specialized mutexes. gRPC also provides an injection mechanism for custom
 // mutexes.
 class GOOGLE_PROTOBUF_CAPABILITY("mutex") PROTOBUF_EXPORT WrappedMutex {
  public:
-  WrappedMutex() = default;
+#if defined(__QNX__)
+  constexpr WrappedMutex() = default;
+#else
+  constexpr WrappedMutex() {}
+#endif
   void Lock() GOOGLE_PROTOBUF_ACQUIRE() { mu_.lock(); }
   void Unlock() GOOGLE_PROTOBUF_RELEASE() { mu_.unlock(); }
   // Crash if this Mutex is not held exclusively by this thread.
@@ -103,20 +130,24 @@
   void AssertHeld() const {}
 
  private:
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  std::mutex mu_;
-#else  // ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  CriticalSectionLock mu_;
-#endif  // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
+#if defined(GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP)
+  CallOnceInitializedMutex<CriticalSectionLock> mu_{};
+#elif defined(_WIN32)
+  CallOnceInitializedMutex<std::mutex> mu_{};
+#else
+  std::mutex mu_{};
+#endif
 };
 
 using Mutex = WrappedMutex;
 
 // MutexLock(mu) acquires mu when constructed and releases it when destroyed.
-class PROTOBUF_EXPORT MutexLock {
+class GOOGLE_PROTOBUF_SCOPED_CAPABILITY PROTOBUF_EXPORT MutexLock {
  public:
-  explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
-  ~MutexLock() { this->mu_->Unlock(); }
+  explicit MutexLock(Mutex *mu) GOOGLE_PROTOBUF_ACQUIRE(mu) : mu_(mu) {
+    this->mu_->Lock();
+  }
+  ~MutexLock() GOOGLE_PROTOBUF_RELEASE() { this->mu_->Unlock(); }
  private:
   Mutex *const mu_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
index ce1b1e3..2479960 100644
--- a/src/google/protobuf/stubs/platform_macros.h
+++ b/src/google/protobuf/stubs/platform_macros.h
@@ -46,7 +46,11 @@
 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
 #elif defined(__QNX__)
 #define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
+#if defined(__aarch64__)
+#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+#else
 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+#endif
 #elif defined(_M_ARM) || defined(__ARMEL__)
 #define GOOGLE_PROTOBUF_ARCH_ARM 1
 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
index 31d2a10..d4d2736 100644
--- a/src/google/protobuf/stubs/port.h
+++ b/src/google/protobuf/stubs/port.h
@@ -51,22 +51,27 @@
   #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
     #define PROTOBUF_LITTLE_ENDIAN 1
   #endif
-  #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
-    // If MSVC has "/RTCc" set, it will complain about truncating casts at
-    // runtime.  This file contains some intentional truncating casts.
-    #pragma runtime_checks("c", off)
-  #endif
+#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+// If MSVC has "/RTCc" set, it will complain about truncating casts at
+// runtime.  This file contains some intentional truncating casts.
+#pragma runtime_checks("c", off)
+#endif
 #else
-  #include <sys/param.h>   // __BYTE_ORDER
-  #if defined(__OpenBSD__)
-    #include <endian.h>
-  #endif
-  #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
-         (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
-         (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \
-      !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
-    #define PROTOBUF_LITTLE_ENDIAN 1
-  #endif
+#ifdef __APPLE__
+#include <machine/endian.h>  // __BYTE_ORDER
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>  // __BYTE_ORDER
+#else
+#if !defined(__QNX__)
+#include <endian.h>  // __BYTE_ORDER
+#endif
+#endif
+#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) ||   \
+     (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
+     (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) &&      \
+    !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+#define PROTOBUF_LITTLE_ENDIAN 1
+#endif
 #endif
 
 // These #includes are for the byte swap functions declared later on.
@@ -75,7 +80,7 @@
 #include <intrin.h>
 #elif defined(__APPLE__)
 #include <libkern/OSByteOrder.h>
-#elif defined(__GLIBC__) || defined(__BIONIC__) || defined(__CYGWIN__)
+#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__)
 #include <byteswap.h>  // IWYU pragma: export
 #endif
 
@@ -117,6 +122,8 @@
 namespace google {
 namespace protobuf {
 
+using ConstStringParam = const std::string &;
+
 typedef unsigned int uint;
 
 typedef int8_t int8;
@@ -131,10 +138,10 @@
 
 static const int32 kint32max = 0x7FFFFFFF;
 static const int32 kint32min = -kint32max - 1;
-static const int64 kint64max = PROTOBUF_LONGLONG(0x7FFFFFFFFFFFFFFF);
+static const int64 kint64max = int64_t{0x7FFFFFFFFFFFFFFF};
 static const int64 kint64min = -kint64max - 1;
 static const uint32 kuint32max = 0xFFFFFFFFu;
-static const uint64 kuint64max = PROTOBUF_ULONGLONG(0xFFFFFFFFFFFFFFFF);
+static const uint64 kuint64max = uint64_t{0xFFFFFFFFFFFFFFFFu};
 
 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
     defined(MEMORY_SANITIZER)
@@ -225,12 +232,6 @@
 # define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2
 #endif
 
-#if defined(_MSC_VER)
-#define GOOGLE_THREAD_LOCAL __declspec(thread)
-#else
-#define GOOGLE_THREAD_LOCAL __thread
-#endif
-
 // The following guarantees declaration of the byte swap functions.
 #ifdef _MSC_VER
 #define bswap_16(x) _byteswap_ushort(x)
@@ -243,7 +244,7 @@
 #define bswap_32(x) OSSwapInt32(x)
 #define bswap_64(x) OSSwapInt64(x)
 
-#elif !defined(__GLIBC__) && !defined(__BIONIC__) && !defined(__CYGWIN__)
+#elif !defined(__linux__) && !defined(__ANDROID__) && !defined(__CYGWIN__)
 
 #ifndef bswap_16
 static inline uint16 bswap_16(uint16 x) {
@@ -264,14 +265,14 @@
 
 #ifndef bswap_64
 static inline uint64 bswap_64(uint64 x) {
-  return (((x & PROTOBUF_ULONGLONG(0xFF)) << 56) |
-          ((x & PROTOBUF_ULONGLONG(0xFF00)) << 40) |
-          ((x & PROTOBUF_ULONGLONG(0xFF0000)) << 24) |
-          ((x & PROTOBUF_ULONGLONG(0xFF000000)) << 8) |
-          ((x & PROTOBUF_ULONGLONG(0xFF00000000)) >> 8) |
-          ((x & PROTOBUF_ULONGLONG(0xFF0000000000)) >> 24) |
-          ((x & PROTOBUF_ULONGLONG(0xFF000000000000)) >> 40) |
-          ((x & PROTOBUF_ULONGLONG(0xFF00000000000000)) >> 56));
+  return (((x & uint64_t{0xFFu}) << 56) |
+          ((x & uint64_t{0xFF00u}) << 40) |
+          ((x & uint64_t{0xFF0000u}) << 24) |
+          ((x & uint64_t{0xFF000000u}) << 8) |
+          ((x & uint64_t{0xFF00000000u}) >> 8) |
+          ((x & uint64_t{0xFF0000000000u}) >> 24) |
+          ((x & uint64_t{0xFF000000000000u}) >> 40) |
+          ((x & uint64_t{0xFF00000000000000u}) >> 56));
 }
 #define bswap_64(x) bswap_64(x)
 #endif
diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc
index 2bfbe0b..f5c0fa4 100644
--- a/src/google/protobuf/stubs/status.cc
+++ b/src/google/protobuf/stubs/status.cc
@@ -37,42 +37,44 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace error {
-inline string CodeEnumToString(error::Code code) {
+namespace status_internal {
+namespace {
+
+inline std::string StatusCodeToString(StatusCode code) {
   switch (code) {
-    case OK:
+    case StatusCode::kOk:
       return "OK";
-    case CANCELLED:
+    case StatusCode::kCancelled:
       return "CANCELLED";
-    case UNKNOWN:
+    case StatusCode::kUnknown:
       return "UNKNOWN";
-    case INVALID_ARGUMENT:
+    case StatusCode::kInvalidArgument:
       return "INVALID_ARGUMENT";
-    case DEADLINE_EXCEEDED:
+    case StatusCode::kDeadlineExceeded:
       return "DEADLINE_EXCEEDED";
-    case NOT_FOUND:
+    case StatusCode::kNotFound:
       return "NOT_FOUND";
-    case ALREADY_EXISTS:
+    case StatusCode::kAlreadyExists:
       return "ALREADY_EXISTS";
-    case PERMISSION_DENIED:
+    case StatusCode::kPermissionDenied:
       return "PERMISSION_DENIED";
-    case UNAUTHENTICATED:
+    case StatusCode::kUnauthenticated:
       return "UNAUTHENTICATED";
-    case RESOURCE_EXHAUSTED:
+    case StatusCode::kResourceExhausted:
       return "RESOURCE_EXHAUSTED";
-    case FAILED_PRECONDITION:
+    case StatusCode::kFailedPrecondition:
       return "FAILED_PRECONDITION";
-    case ABORTED:
+    case StatusCode::kAborted:
       return "ABORTED";
-    case OUT_OF_RANGE:
+    case StatusCode::kOutOfRange:
       return "OUT_OF_RANGE";
-    case UNIMPLEMENTED:
+    case StatusCode::kUnimplemented:
       return "UNIMPLEMENTED";
-    case INTERNAL:
+    case StatusCode::kInternal:
       return "INTERNAL";
-    case UNAVAILABLE:
+    case StatusCode::kUnavailable:
       return "UNAVAILABLE";
-    case DATA_LOSS:
+    case StatusCode::kDataLoss:
       return "DATA_LOSS";
   }
 
@@ -80,18 +82,14 @@
   // above switch.
   return "UNKNOWN";
 }
-}  // namespace error.
 
-const Status Status::OK = Status();
-const Status Status::CANCELLED = Status(error::CANCELLED, "");
-const Status Status::UNKNOWN = Status(error::UNKNOWN, "");
+}  // namespace
 
-Status::Status() : error_code_(error::OK) {
-}
+Status::Status() : error_code_(StatusCode::kOk) {}
 
-Status::Status(error::Code error_code, StringPiece error_message)
+Status::Status(StatusCode error_code, StringPiece error_message)
     : error_code_(error_code) {
-  if (error_code != error::OK) {
+  if (error_code != StatusCode::kOk) {
     error_message_ = error_message.ToString();
   }
 }
@@ -111,24 +109,154 @@
       error_message_ == x.error_message_;
 }
 
-string Status::ToString() const {
-  if (error_code_ == error::OK) {
+std::string Status::ToString() const {
+  if (error_code_ == StatusCode::kOk) {
     return "OK";
   } else {
     if (error_message_.empty()) {
-      return error::CodeEnumToString(error_code_);
+      return StatusCodeToString(error_code_);
     } else {
-      return error::CodeEnumToString(error_code_) + ":" +
-          error_message_;
+      return StatusCodeToString(error_code_) + ":" + error_message_;
     }
   }
 }
 
+Status OkStatus() { return Status(); }
+
 std::ostream& operator<<(std::ostream& os, const Status& x) {
   os << x.ToString();
   return os;
 }
 
+bool IsAborted(const Status& status) {
+  return status.code() == StatusCode::kAborted;
+}
+
+bool IsAlreadyExists(const Status& status) {
+  return status.code() == StatusCode::kAlreadyExists;
+}
+
+bool IsCancelled(const Status& status) {
+  return status.code() == StatusCode::kCancelled;
+}
+
+bool IsDataLoss(const Status& status) {
+  return status.code() == StatusCode::kDataLoss;
+}
+
+bool IsDeadlineExceeded(const Status& status) {
+  return status.code() == StatusCode::kDeadlineExceeded;
+}
+
+bool IsFailedPrecondition(const Status& status) {
+  return status.code() == StatusCode::kFailedPrecondition;
+}
+
+bool IsInternal(const Status& status) {
+  return status.code() == StatusCode::kInternal;
+}
+
+bool IsInvalidArgument(const Status& status) {
+  return status.code() == StatusCode::kInvalidArgument;
+}
+
+bool IsNotFound(const Status& status) {
+  return status.code() == StatusCode::kNotFound;
+}
+
+bool IsOutOfRange(const Status& status) {
+  return status.code() == StatusCode::kOutOfRange;
+}
+
+bool IsPermissionDenied(const Status& status) {
+  return status.code() == StatusCode::kPermissionDenied;
+}
+
+bool IsResourceExhausted(const Status& status) {
+  return status.code() == StatusCode::kResourceExhausted;
+}
+
+bool IsUnauthenticated(const Status& status) {
+  return status.code() == StatusCode::kUnauthenticated;
+}
+
+bool IsUnavailable(const Status& status) {
+  return status.code() == StatusCode::kUnavailable;
+}
+
+bool IsUnimplemented(const Status& status) {
+  return status.code() == StatusCode::kUnimplemented;
+}
+
+bool IsUnknown(const Status& status) {
+  return status.code() == StatusCode::kUnknown;
+}
+
+Status AbortedError(StringPiece message) {
+  return Status(StatusCode::kAborted, message);
+}
+
+Status AlreadyExistsError(StringPiece message) {
+  return Status(StatusCode::kAlreadyExists, message);
+}
+
+Status CancelledError(StringPiece message) {
+  return Status(StatusCode::kCancelled, message);
+}
+
+Status DataLossError(StringPiece message) {
+  return Status(StatusCode::kDataLoss, message);
+}
+
+Status DeadlineExceededError(StringPiece message) {
+  return Status(StatusCode::kDeadlineExceeded, message);
+}
+
+Status FailedPreconditionError(StringPiece message) {
+  return Status(StatusCode::kFailedPrecondition, message);
+}
+
+Status InternalError(StringPiece message) {
+  return Status(StatusCode::kInternal, message);
+}
+
+Status InvalidArgumentError(StringPiece message) {
+  return Status(StatusCode::kInvalidArgument, message);
+}
+
+Status NotFoundError(StringPiece message) {
+  return Status(StatusCode::kNotFound, message);
+}
+
+Status OutOfRangeError(StringPiece message) {
+  return Status(StatusCode::kOutOfRange, message);
+}
+
+Status PermissionDeniedError(StringPiece message) {
+  return Status(StatusCode::kPermissionDenied, message);
+}
+
+Status ResourceExhaustedError(StringPiece message) {
+  return Status(StatusCode::kResourceExhausted, message);
+}
+
+Status UnauthenticatedError(StringPiece message) {
+  return Status(StatusCode::kUnauthenticated, message);
+}
+
+Status UnavailableError(StringPiece message) {
+  return Status(StatusCode::kUnavailable, message);
+}
+
+Status UnimplementedError(StringPiece message) {
+  return Status(StatusCode::kUnimplemented, message);
+}
+
+Status UnknownError(StringPiece message) {
+  return Status(StatusCode::kUnknown, message);
+}
+
+}  // namespace status_internal
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h
index 04ecc63..c858cf6 100644
--- a/src/google/protobuf/stubs/status.h
+++ b/src/google/protobuf/stubs/status.h
@@ -27,13 +27,12 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 #ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_
 #define GOOGLE_PROTOBUF_STUBS_STATUS_H_
 
-#include <iosfwd>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringpiece.h>
 
 #include <google/protobuf/port_def.inc>
@@ -41,28 +40,28 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace error {
+namespace status_internal {
+
 // These values must match error codes defined in google/rpc/code.proto.
-enum Code {
-  OK = 0,
-  CANCELLED = 1,
-  UNKNOWN = 2,
-  INVALID_ARGUMENT = 3,
-  DEADLINE_EXCEEDED = 4,
-  NOT_FOUND = 5,
-  ALREADY_EXISTS = 6,
-  PERMISSION_DENIED = 7,
-  UNAUTHENTICATED = 16,
-  RESOURCE_EXHAUSTED = 8,
-  FAILED_PRECONDITION = 9,
-  ABORTED = 10,
-  OUT_OF_RANGE = 11,
-  UNIMPLEMENTED = 12,
-  INTERNAL = 13,
-  UNAVAILABLE = 14,
-  DATA_LOSS = 15,
+enum class StatusCode : int {
+  kOk = 0,
+  kCancelled = 1,
+  kUnknown = 2,
+  kInvalidArgument = 3,
+  kDeadlineExceeded = 4,
+  kNotFound = 5,
+  kAlreadyExists = 6,
+  kPermissionDenied = 7,
+  kUnauthenticated = 16,
+  kResourceExhausted = 8,
+  kFailedPrecondition = 9,
+  kAborted = 10,
+  kOutOfRange = 11,
+  kUnimplemented = 12,
+  kInternal = 13,
+  kUnavailable = 14,
+  kDataLoss = 15,
 };
-}  // namespace error
 
 class PROTOBUF_EXPORT Status {
  public:
@@ -71,31 +70,16 @@
 
   // Create a status in the canonical error space with the specified
   // code, and error message.  If "code == 0", error_message is
-  // ignored and a Status object identical to Status::OK is
+  // ignored and a Status object identical to Status::kOk is
   // constructed.
-  Status(error::Code error_code, StringPiece error_message);
+  Status(StatusCode error_code, StringPiece error_message);
   Status(const Status&);
   Status& operator=(const Status& x);
   ~Status() {}
 
-  // Some pre-defined Status objects
-  static const Status OK;             // Identical to 0-arg constructor
-  static const Status CANCELLED;
-  static const Status UNKNOWN;
-
   // Accessor
-  bool ok() const {
-    return error_code_ == error::OK;
-  }
-  int error_code() const {
-    return error_code_;
-  }
-  error::Code code() const {
-    return error_code_;
-  }
-  StringPiece error_message() const {
-    return error_message_;
-  }
+  bool ok() const { return error_code_ == StatusCode::kOk; }
+  StatusCode code() const { return error_code_; }
   StringPiece message() const {
     return error_message_;
   }
@@ -106,16 +90,103 @@
   }
 
   // Return a combination of the error code name and message.
-  string ToString() const;
+  std::string ToString() const;
 
  private:
-  error::Code error_code_;
-  string error_message_;
+  StatusCode error_code_;
+  std::string error_message_;
 };
 
+// Returns an OK status, equivalent to a default constructed instance. Prefer
+// usage of `OkStatus()` when constructing such an OK status.
+PROTOBUF_EXPORT Status OkStatus();
+
 // Prints a human-readable representation of 'x' to 'os'.
 PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x);
 
+// These convenience functions return `true` if a given status matches the
+// `StatusCode` error code of its associated function.
+PROTOBUF_EXPORT bool IsAborted(const Status& status);
+PROTOBUF_EXPORT bool IsAlreadyExists(const Status& status);
+PROTOBUF_EXPORT bool IsCancelled(const Status& status);
+PROTOBUF_EXPORT bool IsDataLoss(const Status& status);
+PROTOBUF_EXPORT bool IsDeadlineExceeded(const Status& status);
+PROTOBUF_EXPORT bool IsFailedPrecondition(const Status& status);
+PROTOBUF_EXPORT bool IsInternal(const Status& status);
+PROTOBUF_EXPORT bool IsInvalidArgument(const Status& status);
+PROTOBUF_EXPORT bool IsNotFound(const Status& status);
+PROTOBUF_EXPORT bool IsOutOfRange(const Status& status);
+PROTOBUF_EXPORT bool IsPermissionDenied(const Status& status);
+PROTOBUF_EXPORT bool IsResourceExhausted(const Status& status);
+PROTOBUF_EXPORT bool IsUnauthenticated(const Status& status);
+PROTOBUF_EXPORT bool IsUnavailable(const Status& status);
+PROTOBUF_EXPORT bool IsUnimplemented(const Status& status);
+PROTOBUF_EXPORT bool IsUnknown(const Status& status);
+
+// These convenience functions create an `Status` object with an error code as
+// indicated by the associated function name, using the error message passed in
+// `message`.
+//
+// These functions are intentionally named `*Error` rather than `*Status` to
+// match the names from Abseil:
+// https://github.com/abseil/abseil-cpp/blob/2e9532cc6c701a8323d0cffb468999ab804095ab/absl/status/status.h#L716
+PROTOBUF_EXPORT Status AbortedError(StringPiece message);
+PROTOBUF_EXPORT Status AlreadyExistsError(StringPiece message);
+PROTOBUF_EXPORT Status CancelledError(StringPiece message);
+PROTOBUF_EXPORT Status DataLossError(StringPiece message);
+PROTOBUF_EXPORT Status DeadlineExceededError(StringPiece message);
+PROTOBUF_EXPORT Status FailedPreconditionError(StringPiece message);
+PROTOBUF_EXPORT Status InternalError(StringPiece message);
+PROTOBUF_EXPORT Status InvalidArgumentError(StringPiece message);
+PROTOBUF_EXPORT Status NotFoundError(StringPiece message);
+PROTOBUF_EXPORT Status OutOfRangeError(StringPiece message);
+PROTOBUF_EXPORT Status PermissionDeniedError(StringPiece message);
+PROTOBUF_EXPORT Status ResourceExhaustedError(StringPiece message);
+PROTOBUF_EXPORT Status UnauthenticatedError(StringPiece message);
+PROTOBUF_EXPORT Status UnavailableError(StringPiece message);
+PROTOBUF_EXPORT Status UnimplementedError(StringPiece message);
+PROTOBUF_EXPORT Status UnknownError(StringPiece message);
+
+}  // namespace status_internal
+
+using ::google::protobuf::util::status_internal::Status;
+using ::google::protobuf::util::status_internal::StatusCode;
+
+using ::google::protobuf::util::status_internal::IsAborted;
+using ::google::protobuf::util::status_internal::IsAlreadyExists;
+using ::google::protobuf::util::status_internal::IsCancelled;
+using ::google::protobuf::util::status_internal::IsDataLoss;
+using ::google::protobuf::util::status_internal::IsDeadlineExceeded;
+using ::google::protobuf::util::status_internal::IsFailedPrecondition;
+using ::google::protobuf::util::status_internal::IsInternal;
+using ::google::protobuf::util::status_internal::IsInvalidArgument;
+using ::google::protobuf::util::status_internal::IsNotFound;
+using ::google::protobuf::util::status_internal::IsOutOfRange;
+using ::google::protobuf::util::status_internal::IsPermissionDenied;
+using ::google::protobuf::util::status_internal::IsResourceExhausted;
+using ::google::protobuf::util::status_internal::IsUnauthenticated;
+using ::google::protobuf::util::status_internal::IsUnavailable;
+using ::google::protobuf::util::status_internal::IsUnimplemented;
+using ::google::protobuf::util::status_internal::IsUnknown;
+
+using ::google::protobuf::util::status_internal::AbortedError;
+using ::google::protobuf::util::status_internal::AlreadyExistsError;
+using ::google::protobuf::util::status_internal::CancelledError;
+using ::google::protobuf::util::status_internal::DataLossError;
+using ::google::protobuf::util::status_internal::DeadlineExceededError;
+using ::google::protobuf::util::status_internal::FailedPreconditionError;
+using ::google::protobuf::util::status_internal::InternalError;
+using ::google::protobuf::util::status_internal::InvalidArgumentError;
+using ::google::protobuf::util::status_internal::NotFoundError;
+using ::google::protobuf::util::status_internal::OkStatus;
+using ::google::protobuf::util::status_internal::OutOfRangeError;
+using ::google::protobuf::util::status_internal::PermissionDeniedError;
+using ::google::protobuf::util::status_internal::ResourceExhaustedError;
+using ::google::protobuf::util::status_internal::UnauthenticatedError;
+using ::google::protobuf::util::status_internal::UnavailableError;
+using ::google::protobuf::util::status_internal::UnimplementedError;
+using ::google::protobuf::util::status_internal::UnknownError;
+
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h
index 0c64317..407ff4c 100644
--- a/src/google/protobuf/stubs/status_macros.h
+++ b/src/google/protobuf/stubs/status_macros.h
@@ -60,7 +60,7 @@
 template<typename T>
 Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
   if (result.ok()) {
-    lhs = result.ValueOrDie();
+    lhs = result.value();
   }
   return result.status();
 }
diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc
index 9a18778..9e9edf7 100644
--- a/src/google/protobuf/stubs/status_test.cc
+++ b/src/google/protobuf/stubs/status_test.cc
@@ -37,26 +37,170 @@
 namespace google {
 namespace protobuf {
 namespace {
-TEST(Status, Empty) {
-  util::Status status;
-  EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
-  EXPECT_EQ(util::error::OK, util::Status::OK.code());
-  EXPECT_EQ("OK", util::Status::OK.ToString());
-}
 
-TEST(Status, GenericCodes) {
-  EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
-  EXPECT_EQ(util::error::OK, util::Status::OK.code());
-  EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code());
-  EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.code());
-  EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code());
-  EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.code());
+TEST(Status, Constructor) {
+  EXPECT_EQ(util::StatusCode::kOk,
+            util::Status(util::StatusCode::kOk, "").code());
+  EXPECT_EQ(util::StatusCode::kCancelled,
+            util::Status(util::StatusCode::kCancelled, "").code());
+  EXPECT_EQ(util::StatusCode::kUnknown,
+            util::Status(util::StatusCode::kUnknown, "").code());
+  EXPECT_EQ(util::StatusCode::kInvalidArgument,
+            util::Status(util::StatusCode::kInvalidArgument, "").code());
+  EXPECT_EQ(util::StatusCode::kDeadlineExceeded,
+            util::Status(util::StatusCode::kDeadlineExceeded, "").code());
+  EXPECT_EQ(util::StatusCode::kNotFound,
+            util::Status(util::StatusCode::kNotFound, "").code());
+  EXPECT_EQ(util::StatusCode::kAlreadyExists,
+            util::Status(util::StatusCode::kAlreadyExists, "").code());
+  EXPECT_EQ(util::StatusCode::kPermissionDenied,
+            util::Status(util::StatusCode::kPermissionDenied, "").code());
+  EXPECT_EQ(util::StatusCode::kUnauthenticated,
+            util::Status(util::StatusCode::kUnauthenticated, "").code());
+  EXPECT_EQ(util::StatusCode::kResourceExhausted,
+            util::Status(util::StatusCode::kResourceExhausted, "").code());
+  EXPECT_EQ(util::StatusCode::kFailedPrecondition,
+            util::Status(util::StatusCode::kFailedPrecondition, "").code());
+  EXPECT_EQ(util::StatusCode::kAborted,
+            util::Status(util::StatusCode::kAborted, "").code());
+  EXPECT_EQ(util::StatusCode::kOutOfRange,
+            util::Status(util::StatusCode::kOutOfRange, "").code());
+  EXPECT_EQ(util::StatusCode::kUnimplemented,
+            util::Status(util::StatusCode::kUnimplemented, "").code());
+  EXPECT_EQ(util::StatusCode::kInternal,
+            util::Status(util::StatusCode::kInternal, "").code());
+  EXPECT_EQ(util::StatusCode::kUnavailable,
+            util::Status(util::StatusCode::kUnavailable, "").code());
+  EXPECT_EQ(util::StatusCode::kDataLoss,
+            util::Status(util::StatusCode::kDataLoss, "").code());
 }
 
 TEST(Status, ConstructorZero) {
-  util::Status status(util::error::OK, "msg");
+  util::Status status(util::StatusCode::kOk, "msg");
   EXPECT_TRUE(status.ok());
   EXPECT_EQ("OK", status.ToString());
+  EXPECT_EQ(util::OkStatus(), status);
+}
+
+TEST(Status, ConvenienceConstructors) {
+  EXPECT_EQ(util::StatusCode::kOk, util::OkStatus().code());
+  EXPECT_EQ("", util::OkStatus().message());
+
+  EXPECT_EQ(util::StatusCode::kCancelled, util::CancelledError("").code());
+  EXPECT_EQ("", util::CancelledError("").message());
+  EXPECT_EQ("foo", util::CancelledError("foo").message());
+  EXPECT_EQ("bar", util::CancelledError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnknown, util::UnknownError("").code());
+  EXPECT_EQ("", util::UnknownError("").message());
+  EXPECT_EQ("foo", util::UnknownError("foo").message());
+  EXPECT_EQ("bar", util::UnknownError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kInvalidArgument,
+            util::InvalidArgumentError("").code());
+  EXPECT_EQ("", util::InvalidArgumentError("").message());
+  EXPECT_EQ("foo", util::InvalidArgumentError("foo").message());
+  EXPECT_EQ("bar", util::InvalidArgumentError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kDeadlineExceeded,
+            util::DeadlineExceededError("").code());
+  EXPECT_EQ("", util::DeadlineExceededError("").message());
+  EXPECT_EQ("foo", util::DeadlineExceededError("foo").message());
+  EXPECT_EQ("bar", util::DeadlineExceededError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kNotFound, util::NotFoundError("").code());
+  EXPECT_EQ("", util::NotFoundError("").message());
+  EXPECT_EQ("foo", util::NotFoundError("foo").message());
+  EXPECT_EQ("bar", util::NotFoundError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kAlreadyExists,
+            util::AlreadyExistsError("").code());
+  EXPECT_EQ("", util::AlreadyExistsError("").message());
+  EXPECT_EQ("foo", util::AlreadyExistsError("foo").message());
+  EXPECT_EQ("bar", util::AlreadyExistsError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kPermissionDenied,
+            util::PermissionDeniedError("").code());
+  EXPECT_EQ("", util::PermissionDeniedError("").message());
+  EXPECT_EQ("foo", util::PermissionDeniedError("foo").message());
+  EXPECT_EQ("bar", util::PermissionDeniedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnauthenticated,
+            util::UnauthenticatedError("").code());
+  EXPECT_EQ("", util::UnauthenticatedError("").message());
+  EXPECT_EQ("foo", util::UnauthenticatedError("foo").message());
+  EXPECT_EQ("bar", util::UnauthenticatedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kResourceExhausted,
+            util::ResourceExhaustedError("").code());
+  EXPECT_EQ("", util::ResourceExhaustedError("").message());
+  EXPECT_EQ("foo", util::ResourceExhaustedError("foo").message());
+  EXPECT_EQ("bar", util::ResourceExhaustedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kFailedPrecondition,
+            util::FailedPreconditionError("").code());
+  EXPECT_EQ("", util::FailedPreconditionError("").message());
+  EXPECT_EQ("foo", util::FailedPreconditionError("foo").message());
+  EXPECT_EQ("bar", util::FailedPreconditionError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kAborted, util::AbortedError("").code());
+  EXPECT_EQ("", util::AbortedError("").message());
+  EXPECT_EQ("foo", util::AbortedError("foo").message());
+  EXPECT_EQ("bar", util::AbortedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kOutOfRange, util::OutOfRangeError("").code());
+  EXPECT_EQ("", util::OutOfRangeError("").message());
+  EXPECT_EQ("foo", util::OutOfRangeError("foo").message());
+  EXPECT_EQ("bar", util::OutOfRangeError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnimplemented,
+            util::UnimplementedError("").code());
+  EXPECT_EQ("", util::UnimplementedError("").message());
+  EXPECT_EQ("foo", util::UnimplementedError("foo").message());
+  EXPECT_EQ("bar", util::UnimplementedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kInternal, util::InternalError("").code());
+  EXPECT_EQ("", util::InternalError("").message());
+  EXPECT_EQ("foo", util::InternalError("foo").message());
+  EXPECT_EQ("bar", util::InternalError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnavailable, util::UnavailableError("").code());
+  EXPECT_EQ("", util::UnavailableError("").message());
+  EXPECT_EQ("foo", util::UnavailableError("foo").message());
+  EXPECT_EQ("bar", util::UnavailableError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kDataLoss, util::DataLossError("").code());
+  EXPECT_EQ("", util::DataLossError("").message());
+  EXPECT_EQ("foo", util::DataLossError("foo").message());
+  EXPECT_EQ("bar", util::DataLossError("bar").message());
+}
+
+TEST(Status, ConvenienceTests) {
+  EXPECT_TRUE(util::OkStatus().ok());
+  EXPECT_TRUE(util::IsCancelled(util::CancelledError("")));
+  EXPECT_TRUE(util::IsUnknown(util::UnknownError("")));
+  EXPECT_TRUE(util::IsInvalidArgument(util::InvalidArgumentError("")));
+  EXPECT_TRUE(util::IsDeadlineExceeded(util::DeadlineExceededError("")));
+  EXPECT_TRUE(util::IsNotFound(util::NotFoundError("")));
+  EXPECT_TRUE(util::IsAlreadyExists(util::AlreadyExistsError("")));
+  EXPECT_TRUE(util::IsPermissionDenied(util::PermissionDeniedError("")));
+  EXPECT_TRUE(util::IsUnauthenticated(util::UnauthenticatedError("")));
+  EXPECT_TRUE(util::IsResourceExhausted(util::ResourceExhaustedError("")));
+  EXPECT_TRUE(util::IsFailedPrecondition(util::FailedPreconditionError("")));
+  EXPECT_TRUE(util::IsAborted(util::AbortedError("")));
+  EXPECT_TRUE(util::IsOutOfRange(util::OutOfRangeError("")));
+  EXPECT_TRUE(util::IsUnimplemented(util::UnimplementedError("")));
+  EXPECT_TRUE(util::IsInternal(util::InternalError("")));
+  EXPECT_TRUE(util::IsUnavailable(util::UnavailableError("")));
+  EXPECT_TRUE(util::IsDataLoss(util::DataLossError("")));
+}
+
+TEST(Status, Empty) {
+  util::Status status;
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(util::OkStatus(), status);
+  EXPECT_EQ(util::StatusCode::kOk, status.code());
+  EXPECT_EQ("OK", status.ToString());
 }
 
 TEST(Status, CheckOK) {
@@ -67,72 +211,68 @@
 }
 
 TEST(Status, ErrorMessage) {
-  util::Status status(util::error::INVALID_ARGUMENT, "");
+  util::Status status = util::InvalidArgumentError("");
   EXPECT_FALSE(status.ok());
-  EXPECT_EQ("", status.error_message().ToString());
   EXPECT_EQ("", status.message().ToString());
   EXPECT_EQ("INVALID_ARGUMENT", status.ToString());
-  status = util::Status(util::error::INVALID_ARGUMENT, "msg");
+  status = util::InvalidArgumentError("msg");
   EXPECT_FALSE(status.ok());
-  EXPECT_EQ("msg", status.error_message().ToString());
   EXPECT_EQ("msg", status.message().ToString());
   EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString());
-  status = util::Status(util::error::OK, "msg");
+  status = util::Status(util::StatusCode::kOk, "msg");
   EXPECT_TRUE(status.ok());
-  EXPECT_EQ("", status.error_message().ToString());
   EXPECT_EQ("", status.message().ToString());
   EXPECT_EQ("OK", status.ToString());
 }
 
 TEST(Status, Copy) {
-  util::Status a(util::error::UNKNOWN, "message");
+  util::Status a = util::UnknownError("message");
   util::Status b(a);
   ASSERT_EQ(a.ToString(), b.ToString());
 }
 
 TEST(Status, Assign) {
-  util::Status a(util::error::UNKNOWN, "message");
+  util::Status a = util::UnknownError("message");
   util::Status b;
   b = a;
   ASSERT_EQ(a.ToString(), b.ToString());
 }
 
 TEST(Status, AssignEmpty) {
-  util::Status a(util::error::UNKNOWN, "message");
+  util::Status a = util::UnknownError("message");
   util::Status b;
   a = b;
-  ASSERT_EQ(string("OK"), a.ToString());
+  ASSERT_EQ(std::string("OK"), a.ToString());
   ASSERT_TRUE(b.ok());
   ASSERT_TRUE(a.ok());
 }
 
-TEST(Status, EqualsOK) {
-  ASSERT_EQ(util::Status::OK, util::Status());
-}
+TEST(Status, EqualsOK) { ASSERT_EQ(util::OkStatus(), util::Status()); }
 
 TEST(Status, EqualsSame) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
-  const util::Status b = util::Status(util::error::CANCELLED, "message");
+  const util::Status a = util::CancelledError("message");
+  const util::Status b = util::CancelledError("message");
   ASSERT_EQ(a, b);
 }
 
 TEST(Status, EqualsCopy) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
+  const util::Status a = util::CancelledError("message");
   const util::Status b = a;
   ASSERT_EQ(a, b);
 }
 
 TEST(Status, EqualsDifferentCode) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
-  const util::Status b = util::Status(util::error::UNKNOWN, "message");
+  const util::Status a = util::CancelledError("message");
+  const util::Status b = util::UnknownError("message");
   ASSERT_NE(a, b);
 }
 
 TEST(Status, EqualsDifferentMessage) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
-  const util::Status b = util::Status(util::error::CANCELLED, "another");
+  const util::Status a = util::CancelledError("message");
+  const util::Status b = util::CancelledError("another");
   ASSERT_NE(a, b);
 }
+
 }  // namespace
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/statusor.cc b/src/google/protobuf/stubs/statusor.cc
index c744b8d..9c0a178 100644
--- a/src/google/protobuf/stubs/statusor.cc
+++ b/src/google/protobuf/stubs/statusor.cc
@@ -35,14 +35,14 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace internal {
+namespace statusor_internal {
 
 void StatusOrHelper::Crash(const Status& status) {
   GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
                     << status.ToString();
 }
 
-}  // namespace internal
+}  // namespace statusor_internal
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
index c02e89a..a569502 100644
--- a/src/google/protobuf/stubs/statusor.h
+++ b/src/google/protobuf/stubs/statusor.h
@@ -32,7 +32,7 @@
 // object. StatusOr models the concept of an object that is either a
 // usable value, or an error Status explaining why such a value is
 // not present. To this end, StatusOr<T> does not allow its Status
-// value to be Status::OK. Further, StatusOr<T*> does not allow the
+// value to be OkStatus(). Further, StatusOr<T*> does not allow the
 // contained pointer to be nullptr.
 //
 // The primary use-case for StatusOr<T> is as the return value of a
@@ -42,7 +42,7 @@
 //
 //  StatusOr<float> result = DoBigCalculationThatCouldFail();
 //  if (result.ok()) {
-//    float answer = result.ValueOrDie();
+//    float answer = result.value();
 //    printf("Big calculation yielded: %f", answer);
 //  } else {
 //    LOG(ERROR) << result.status();
@@ -52,17 +52,7 @@
 //
 //  StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
 //  if (result.ok()) {
-//    std::unique_ptr<Foo> foo(result.ValueOrDie());
-//    foo->DoSomethingCool();
-//  } else {
-//    LOG(ERROR) << result.status();
-//  }
-//
-// Example client usage for a StatusOr<std::unique_ptr<T>>:
-//
-//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
-//  if (result.ok()) {
-//    std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
+//    std::unique_ptr<Foo> foo(result.value());
 //    foo->DoSomethingCool();
 //  } else {
 //    LOG(ERROR) << result.status();
@@ -72,8 +62,7 @@
 //
 //  StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
 //    if (arg <= 0) {
-//      return ::util::Status(::util::error::INVALID_ARGUMENT,
-//                            "Arg must be positive");
+//      return InvalidArgumentError("Arg must be positive");
 //    } else {
 //      return new Foo(arg);
 //    }
@@ -94,30 +83,34 @@
 namespace google {
 namespace protobuf {
 namespace util {
+namespace statusor_internal {
 
 template<typename T>
 class StatusOr {
   template<typename U> friend class StatusOr;
 
  public:
-  // Construct a new StatusOr with Status::UNKNOWN status
-  StatusOr();
+  using value_type = T;
+
+  // Construct a new StatusOr with Status::UNKNOWN status.
+  // Construct a new StatusOr with UnknownError() status.
+  explicit StatusOr();
 
   // Construct a new StatusOr with the given non-ok status. After calling
-  // this constructor, calls to ValueOrDie() will CHECK-fail.
+  // this constructor, calls to value() will CHECK-fail.
   //
   // NOTE: Not explicit - we want to use StatusOr<T> as a return
   // value, so it is convenient and sensible to be able to do 'return
   // Status()' when the return type is StatusOr<T>.
   //
-  // REQUIRES: status != Status::OK. This requirement is DCHECKed.
-  // In optimized builds, passing Status::OK here will have the effect
+  // REQUIRES: status != OkStatus(). This requirement is DCHECKed.
+  // In optimized builds, passing OkStatus() here will have the effect
   // of passing PosixErrorSpace::EINVAL as a fallback.
   StatusOr(const Status& status);  // NOLINT
 
   // Construct a new StatusOr with the given value. If T is a plain pointer,
   // value must not be nullptr. After calling this constructor, calls to
-  // ValueOrDie() will succeed, and calls to status() will return OK.
+  // value() will succeed, and calls to status() will return OK.
   //
   // NOTE: Not explicit - we want to use StatusOr<T> as a return type
   // so it is convenient and sensible to be able to do 'return T()'
@@ -143,16 +136,13 @@
   StatusOr& operator=(const StatusOr<U>& other);
 
   // Returns a reference to our status. If this contains a T, then
-  // returns Status::OK.
+  // returns OkStatus().
   const Status& status() const;
 
   // Returns this->status().ok()
   bool ok() const;
 
   // Returns a reference to our current value, or CHECK-fails if !this->ok().
-  // If you need to initialize a T object from the stored value,
-  // ConsumeValueOrDie() may be more efficient.
-  const T& ValueOrDie() const;
   const T& value () const;
 
  private:
@@ -163,8 +153,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Implementation details for StatusOr<T>
 
-namespace internal {
-
 class PROTOBUF_EXPORT StatusOrHelper {
  public:
   // Move type-agnostic error handling to the .cc.
@@ -186,17 +174,13 @@
   static inline bool IsValueNull(const T* t) { return t == nullptr; }
 };
 
-}  // namespace internal
-
-template<typename T>
-inline StatusOr<T>::StatusOr()
-    : status_(util::Status::UNKNOWN) {
-}
+template <typename T>
+inline StatusOr<T>::StatusOr() : status_(util::UnknownError("")) {}
 
 template<typename T>
 inline StatusOr<T>::StatusOr(const Status& status) {
   if (status.ok()) {
-    status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
+    status_ = util::InternalError("OkStatus() is not a valid argument.");
   } else {
     status_ = status;
   }
@@ -204,10 +188,10 @@
 
 template<typename T>
 inline StatusOr<T>::StatusOr(const T& value) {
-  if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
-    status_ = Status(error::INTERNAL, "nullptr is not a valid argument.");
+  if (StatusOrHelper::Specialize<T>::IsValueNull(value)) {
+    status_ = util::InternalError("nullptr is not a valid argument.");
   } else {
-    status_ = Status::OK;
+    status_ = util::OkStatus();
     value_ = value;
   }
 }
@@ -249,20 +233,17 @@
 }
 
 template<typename T>
-inline const T& StatusOr<T>::ValueOrDie() const {
+inline const T& StatusOr<T>::value() const {
   if (!status_.ok()) {
-    internal::StatusOrHelper::Crash(status_);
+    StatusOrHelper::Crash(status_);
   }
   return value_;
 }
 
-template<typename T>
-inline const T& StatusOr<T>::value() const {
-  if (!status_.ok()) {
-    internal::StatusOrHelper::Crash(status_);
-  }
-  return value_;
-}
+}  // namespace statusor_internal
+
+using ::google::protobuf::util::statusor_internal::StatusOr;
+
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
index 6e2a9e5..403adcc 100644
--- a/src/google/protobuf/stubs/statusor_test.cc
+++ b/src/google/protobuf/stubs/statusor_test.cc
@@ -71,20 +71,20 @@
 TEST(StatusOr, TestDefaultCtor) {
   StatusOr<int> thing;
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::UNKNOWN, thing.status());
+  EXPECT_EQ(util::UnknownError(""), thing.status());
 }
 
 TEST(StatusOr, TestStatusCtor) {
-  StatusOr<int> thing(Status::CANCELLED);
+  StatusOr<int> thing(util::CancelledError(""));
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::CANCELLED, thing.status());
+  EXPECT_EQ(util::CancelledError(""), thing.status());
 }
 
 TEST(StatusOr, TestValueCtor) {
   const int kI = 4;
   StatusOr<int> thing(kI);
   EXPECT_TRUE(thing.ok());
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusOk) {
@@ -92,11 +92,11 @@
   StatusOr<int> original(kI);
   StatusOr<int> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOk) {
-  StatusOr<int> original(Status::CANCELLED);
+  StatusOr<int> original(util::CancelledError(""));
   StatusOr<int> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -106,11 +106,11 @@
   StatusOr<int>    original(kI);
   StatusOr<double> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
-  StatusOr<int>    original(Status::CANCELLED);
+  StatusOr<int> original(util::CancelledError(""));
   StatusOr<double> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -121,11 +121,11 @@
   StatusOr<int> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOk) {
-  StatusOr<int> source(Status::CANCELLED);
+  StatusOr<int> source(util::CancelledError(""));
   StatusOr<int> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -137,11 +137,11 @@
   StatusOr<double> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_DOUBLE_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
-  StatusOr<int>    source(Status::CANCELLED);
+  StatusOr<int> source(util::CancelledError(""));
   StatusOr<double> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -150,40 +150,40 @@
 TEST(StatusOr, TestStatus) {
   StatusOr<int> good(4);
   EXPECT_TRUE(good.ok());
-  StatusOr<int> bad(Status::CANCELLED);
+  StatusOr<int> bad(util::CancelledError(""));
   EXPECT_FALSE(bad.ok());
-  EXPECT_EQ(Status::CANCELLED, bad.status());
+  EXPECT_EQ(util::CancelledError(""), bad.status());
 }
 
 TEST(StatusOr, TestValue) {
   const int kI = 4;
   StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestValueConst) {
   const int kI = 4;
   const StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerDefaultCtor) {
   StatusOr<int*> thing;
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::UNKNOWN, thing.status());
+  EXPECT_EQ(util::UnknownError(""), thing.status());
 }
 
 TEST(StatusOr, TestPointerStatusCtor) {
-  StatusOr<int*> thing(Status::CANCELLED);
+  StatusOr<int*> thing(util::CancelledError(""));
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::CANCELLED, thing.status());
+  EXPECT_EQ(util::CancelledError(""), thing.status());
 }
 
 TEST(StatusOr, TestPointerValueCtor) {
   const int kI = 4;
   StatusOr<const int*> thing(&kI);
   EXPECT_TRUE(thing.ok());
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusOk) {
@@ -191,11 +191,11 @@
   StatusOr<const int*> original(&kI);
   StatusOr<const int*> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
-  StatusOr<int*> original(Status::CANCELLED);
+  StatusOr<int*> original(util::CancelledError(""));
   StatusOr<int*> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -205,12 +205,11 @@
   StatusOr<Derived*> original(&derived);
   StatusOr<Base2*>   copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(static_cast<const Base2*>(original.ValueOrDie()),
-            copy.ValueOrDie());
+  EXPECT_EQ(static_cast<const Base2*>(original.value()), copy.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
-  StatusOr<Derived*> original(Status::CANCELLED);
+  StatusOr<Derived*> original(util::CancelledError(""));
   StatusOr<Base2*>   copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -221,11 +220,11 @@
   StatusOr<const int*> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
-  StatusOr<int*> source(Status::CANCELLED);
+  StatusOr<int*> source(util::CancelledError(""));
   StatusOr<int*> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -237,12 +236,11 @@
   StatusOr<Base2*>   target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(static_cast<const Base2*>(source.ValueOrDie()),
-            target.ValueOrDie());
+  EXPECT_EQ(static_cast<const Base2*>(source.value()), target.value());
 }
 
 TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
-  StatusOr<Derived*> source(Status::CANCELLED);
+  StatusOr<Derived*> source(util::CancelledError(""));
   StatusOr<Base2*>   target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -252,20 +250,20 @@
   const int kI = 0;
   StatusOr<const int*> good(&kI);
   EXPECT_TRUE(good.ok());
-  StatusOr<const int*> bad(Status::CANCELLED);
-  EXPECT_EQ(Status::CANCELLED, bad.status());
+  StatusOr<const int*> bad(util::CancelledError(""));
+  EXPECT_EQ(util::CancelledError(""), bad.status());
 }
 
 TEST(StatusOr, TestPointerValue) {
   const int kI = 0;
   StatusOr<const int*> thing(&kI);
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerValueConst) {
   const int kI = 0;
   const StatusOr<const int*> thing(&kI);
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 }  // namespace
diff --git a/src/google/protobuf/stubs/stl_util.h b/src/google/protobuf/stubs/stl_util.h
index aa81eb6..d01f9ec 100644
--- a/src/google/protobuf/stubs/stl_util.h
+++ b/src/google/protobuf/stubs/stl_util.h
@@ -44,7 +44,7 @@
 // improve performance.  However, since it's totally non-portable it has no
 // place in open source code.  Feel free to fill this function in with your
 // own disgusting hack if you want the perf boost.
-inline void STLStringResizeUninitialized(string* s, size_t new_size) {
+inline void STLStringResizeUninitialized(std::string* s, size_t new_size) {
   s->resize(new_size);
 }
 
@@ -60,7 +60,7 @@
 // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
 // proposes this as the method. According to Matt Austern, this should
 // already work on all current implementations.
-inline char* string_as_array(string* str) {
+inline char* string_as_array(std::string* str) {
   // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
   return str->empty() ? nullptr : &*str->begin();
 }
diff --git a/src/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc
index fc2f521..7188046 100644
--- a/src/google/protobuf/stubs/stringpiece.cc
+++ b/src/google/protobuf/stubs/stringpiece.cc
@@ -39,36 +39,22 @@
 
 namespace google {
 namespace protobuf {
+namespace stringpiece_internal {
+
 std::ostream& operator<<(std::ostream& o, StringPiece piece) {
   o.write(piece.data(), piece.size());
   return o;
 }
 
-// Out-of-line error path.
 void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) {
   GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details;
 }
 
-StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos)
-    : ptr_(x.ptr_ + pos), length_(x.length_ - pos) {
-  GOOGLE_DCHECK_LE(0, pos);
-  GOOGLE_DCHECK_LE(pos, x.length_);
-}
-
-StringPiece::StringPiece(StringPiece x,
-                         stringpiece_ssize_type pos,
-                         stringpiece_ssize_type len)
-    : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) {
-  GOOGLE_DCHECK_LE(0, pos);
-  GOOGLE_DCHECK_LE(pos, x.length_);
-  GOOGLE_DCHECK_GE(len, 0);
-}
-
-void StringPiece::CopyToString(string* target) const {
+void StringPiece::CopyToString(std::string* target) const {
   target->assign(ptr_, length_);
 }
 
-void StringPiece::AppendToString(string* target) const {
+void StringPiece::AppendToString(std::string* target) const {
   target->append(ptr_, length_);
 }
 
@@ -89,10 +75,9 @@
   return false;
 }
 
-stringpiece_ssize_type StringPiece::copy(char* buf,
-                                         size_type n,
+StringPiece::size_type StringPiece::copy(char* buf, size_type n,
                                          size_type pos) const {
-  stringpiece_ssize_type ret = std::min(length_ - pos, n);
+  size_type ret = std::min(length_ - pos, n);
   memcpy(buf, ptr_ + pos, ret);
   return ret;
 }
@@ -101,7 +86,7 @@
   return find(s, 0) != npos;
 }
 
-stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const {
+StringPiece::size_type StringPiece::find(StringPiece s, size_type pos) const {
   if (length_ <= 0 || pos > static_cast<size_type>(length_)) {
     if (length_ == 0 && pos == 0 && s.length_ == 0) return 0;
     return npos;
@@ -111,7 +96,7 @@
   return result == ptr_ + length_ ? npos : result - ptr_;
 }
 
-stringpiece_ssize_type StringPiece::find(char c, size_type pos) const {
+StringPiece::size_type StringPiece::find(char c, size_type pos) const {
   if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
     return npos;
   }
@@ -120,7 +105,7 @@
   return result != nullptr ? result - ptr_ : npos;
 }
 
-stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const {
+StringPiece::size_type StringPiece::rfind(StringPiece s, size_type pos) const {
   if (length_ < s.length_) return npos;
   const size_t ulen = length_;
   if (s.length_ == 0) return std::min(ulen, pos);
@@ -131,15 +116,14 @@
 }
 
 // Search range is [0..pos] inclusive.  If pos == npos, search everything.
-stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const {
+StringPiece::size_type StringPiece::rfind(char c, size_type pos) const {
   // Note: memrchr() is not available on Windows.
-  if (length_ <= 0) return npos;
-  for (stringpiece_ssize_type i =
-      std::min(pos, static_cast<size_type>(length_ - 1));
-       i >= 0; --i) {
+  if (empty()) return npos;
+  for (size_type i = std::min(pos, length_ - 1);; --i) {
     if (ptr_[i] == c) {
       return i;
     }
+    if (i == 0) break;
   }
   return npos;
 }
@@ -154,16 +138,16 @@
 //   bool table[UCHAR_MAX + 1]
 static inline void BuildLookupTable(StringPiece characters_wanted,
                                     bool* table) {
-  const stringpiece_ssize_type length = characters_wanted.length();
+  const StringPiece::size_type length = characters_wanted.length();
   const char* const data = characters_wanted.data();
-  for (stringpiece_ssize_type i = 0; i < length; ++i) {
+  for (StringPiece::size_type i = 0; i < length; ++i) {
     table[static_cast<unsigned char>(data[i])] = true;
   }
 }
 
-stringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
+StringPiece::size_type StringPiece::find_first_of(StringPiece s,
                                                   size_type pos) const {
-  if (length_ <= 0 || s.length_ <= 0) {
+  if (empty() || s.empty()) {
     return npos;
   }
   // Avoid the cost of BuildLookupTable() for a single-character search.
@@ -171,7 +155,7 @@
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+  for (size_type i = pos; i < length_; ++i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
@@ -179,16 +163,16 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s,
+StringPiece::size_type StringPiece::find_first_not_of(StringPiece s,
                                                       size_type pos) const {
-  if (length_ <= 0) return npos;
-  if (s.length_ <= 0) return 0;
+  if (empty()) return npos;
+  if (s.empty()) return 0;
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+  for (size_type i = pos; i < length_; ++i) {
     if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
@@ -196,9 +180,9 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_first_not_of(char c,
+StringPiece::size_type StringPiece::find_first_not_of(char c,
                                                       size_type pos) const {
-  if (length_ <= 0) return npos;
+  if (empty()) return npos;
 
   for (; pos < static_cast<size_type>(length_); ++pos) {
     if (ptr_[pos] != c) {
@@ -208,63 +192,65 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_of(StringPiece s,
+StringPiece::size_type StringPiece::find_last_of(StringPiece s,
                                                  size_type pos) const {
-  if (length_ <= 0 || s.length_ <= 0) return npos;
+  if (empty() || s.empty()) return npos;
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i =
-       std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
+  for (size_type i = std::min(pos, length_ - 1);; --i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
+    if (i == 0) break;
   }
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s,
+StringPiece::size_type StringPiece::find_last_not_of(StringPiece s,
                                                      size_type pos) const {
-  if (length_ <= 0) return npos;
+  if (empty()) return npos;
 
-  stringpiece_ssize_type i = std::min(pos, static_cast<size_type>(length_ - 1));
-  if (s.length_ <= 0) return i;
+  size_type i = std::min(pos, length() - 1);
+  if (s.empty()) return i;
 
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (; i >= 0; --i) {
+  for (;; --i) {
     if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
+    if (i == 0) break;
   }
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_not_of(char c,
+StringPiece::size_type StringPiece::find_last_not_of(char c,
                                                      size_type pos) const {
-  if (length_ <= 0) return npos;
-
-  for (stringpiece_ssize_type i =
-       std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
+  if (empty()) return npos;
+  size_type i = std::min(pos, length_ - 1);
+  for (;; --i) {
     if (ptr_[i] != c) {
       return i;
     }
+    if (i == 0) break;
   }
   return npos;
 }
 
 StringPiece StringPiece::substr(size_type pos, size_type n) const {
-  if (pos > length_) pos = length_;
-  if (n > length_ - pos) n = length_ - pos;
+  if (pos > length()) pos = length();
+  if (n > length_ - pos) n = length() - pos;
   return StringPiece(ptr_ + pos, n);
 }
 
 const StringPiece::size_type StringPiece::npos = size_type(-1);
 
+}  // namespace stringpiece_internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
index 2ae3881..c63e25b 100644
--- a/src/google/protobuf/stubs/stringpiece.h
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -148,59 +148,53 @@
 #include <limits>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
+#if defined(__cpp_lib_string_view)
+#include <string_view>
+#endif
+
 #include <google/protobuf/stubs/hash.h>
 
 #include <google/protobuf/port_def.inc>
 
 namespace google {
 namespace protobuf {
-// StringPiece has *two* size types.
-// StringPiece::size_type
-//   is unsigned
-//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
-//   no future changes intended
-// stringpiece_ssize_type
-//   is signed
-//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
-//   future changes intended: http://go/64BitStringPiece
-//
-typedef string::difference_type stringpiece_ssize_type;
-
-// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows.
-// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit.
-#if !defined(NDEBUG)
-#define STRINGPIECE_CHECK_SIZE 1
-#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
-#define STRINGPIECE_CHECK_SIZE 1
-#else
-#define STRINGPIECE_CHECK_SIZE 0
-#endif
+namespace stringpiece_internal {
 
 class PROTOBUF_EXPORT StringPiece {
+ public:
+  using traits_type = std::char_traits<char>;
+  using value_type = char;
+  using pointer = char*;
+  using const_pointer = const char*;
+  using reference = char&;
+  using const_reference = const char&;
+  using const_iterator = const char*;
+  using iterator = const_iterator;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using reverse_iterator = const_reverse_iterator;
+  using size_type = size_t;
+  using difference_type = std::ptrdiff_t;
+
  private:
   const char* ptr_;
-  stringpiece_ssize_type length_;
+  size_type length_;
 
-  // Prevent overflow in debug mode or fortified mode.
-  // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t).
-  static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) {
-#if STRINGPIECE_CHECK_SIZE > 0
-#ifdef max
-#undef max
-#endif
-    if (size > static_cast<size_t>(
-        std::numeric_limits<stringpiece_ssize_type>::max())) {
+  static constexpr size_type kMaxSize =
+      (std::numeric_limits<difference_type>::max)();
+
+  static size_type CheckSize(size_type size) {
+#if !defined(NDEBUG) || defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
+    if (PROTOBUF_PREDICT_FALSE(size > kMaxSize)) {
       // Some people grep for this message in logs
       // so take care if you ever change it.
-      LogFatalSizeTooBig(size, "size_t to int conversion");
+      LogFatalSizeTooBig(size, "string length exceeds max size");
     }
 #endif
-    return static_cast<stringpiece_ssize_type>(size);
+    return size;
   }
 
   // Out-of-line error path.
-  static void LogFatalSizeTooBig(size_t size, const char* details);
+  static void LogFatalSizeTooBig(size_type size, const char* details);
 
  public:
   // We provide non-explicit singleton constructors so users can pass
@@ -214,7 +208,7 @@
   StringPiece(const char* str)  // NOLINT(runtime/explicit)
       : ptr_(str), length_(0) {
     if (str != nullptr) {
-      length_ = CheckedSsizeTFromSizeT(strlen(str));
+      length_ = CheckSize(strlen(str));
     }
   }
 
@@ -222,78 +216,48 @@
   StringPiece(  // NOLINT(runtime/explicit)
       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
       : ptr_(str.data()), length_(0) {
-    length_ = CheckedSsizeTFromSizeT(str.size());
+    length_ = CheckSize(str.size());
   }
 
-  StringPiece(const char* offset, stringpiece_ssize_type len)
-      : ptr_(offset), length_(len) {
-    assert(len >= 0);
+#if defined(__cpp_lib_string_view)
+  StringPiece(  // NOLINT(runtime/explicit)
+      std::string_view str)
+      : ptr_(str.data()), length_(0) {
+    length_ = CheckSize(str.size());
   }
+#endif
 
-  // Substring of another StringPiece.
-  // pos must be non-negative and <= x.length().
-  StringPiece(StringPiece x, stringpiece_ssize_type pos);
-  // Substring of another StringPiece.
-  // pos must be non-negative and <= x.length().
-  // len must be non-negative and will be pinned to at most x.length() - pos.
-  StringPiece(StringPiece x,
-              stringpiece_ssize_type pos,
-              stringpiece_ssize_type len);
+  StringPiece(const char* offset, size_type len)
+      : ptr_(offset), length_(CheckSize(len)) {}
 
   // data() may return a pointer to a buffer with embedded NULs, and the
   // returned buffer may or may not be null terminated.  Therefore it is
   // typically a mistake to pass data() to a routine that expects a NUL
   // terminated string.
-  const char* data() const { return ptr_; }
-  stringpiece_ssize_type size() const { return length_; }
-  stringpiece_ssize_type length() const { return length_; }
+  const_pointer data() const { return ptr_; }
+  size_type size() const { return length_; }
+  size_type length() const { return length_; }
   bool empty() const { return length_ == 0; }
 
-  void clear() {
-    ptr_ = nullptr;
-    length_ = 0;
-  }
-
-  void set(const char* data, stringpiece_ssize_type len) {
-    assert(len >= 0);
-    ptr_ = data;
-    length_ = len;
-  }
-
-  void set(const char* str) {
-    ptr_ = str;
-    if (str != nullptr)
-      length_ = CheckedSsizeTFromSizeT(strlen(str));
-    else
-      length_ = 0;
-  }
-
-  void set(const void* data, stringpiece_ssize_type len) {
-    ptr_ = reinterpret_cast<const char*>(data);
-    length_ = len;
-  }
-
-  char operator[](stringpiece_ssize_type i) const {
-    assert(0 <= i);
+  char operator[](size_type i) const {
     assert(i < length_);
     return ptr_[i];
   }
 
-  void remove_prefix(stringpiece_ssize_type n) {
+  void remove_prefix(size_type n) {
     assert(length_ >= n);
     ptr_ += n;
     length_ -= n;
   }
 
-  void remove_suffix(stringpiece_ssize_type n) {
+  void remove_suffix(size_type n) {
     assert(length_ >= n);
     length_ -= n;
   }
 
   // returns {-1, 0, 1}
   int compare(StringPiece x) const {
-    const stringpiece_ssize_type min_size =
-        length_ < x.length_ ? length_ : x.length_;
+    size_type min_size = length_ < x.length_ ? length_ : x.length_;
     int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size));
     if (r < 0) return -1;
     if (r > 0) return 1;
@@ -302,25 +266,21 @@
     return 0;
   }
 
-  string as_string() const {
-    return ToString();
-  }
+  std::string as_string() const { return ToString(); }
   // We also define ToString() here, since many other string-like
   // interfaces name the routine that converts to a C++ string
   // "ToString", and it's confusing to have the method that does that
   // for a StringPiece be called "as_string()".  We also leave the
   // "as_string()" method defined here for existing code.
-  string ToString() const {
-    if (ptr_ == nullptr) return string();
-    return string(data(), static_cast<size_type>(size()));
+  std::string ToString() const {
+    if (ptr_ == nullptr) return "";
+    return std::string(data(), static_cast<size_type>(size()));
   }
 
-  operator string() const {
-    return ToString();
-  }
+  explicit operator std::string() const { return ToString(); }
 
-  void CopyToString(string* target) const;
-  void AppendToString(string* target) const;
+  void CopyToString(std::string* target) const;
+  void AppendToString(std::string* target) const;
 
   bool starts_with(StringPiece x) const {
     return (length_ >= x.length_) &&
@@ -341,53 +301,40 @@
   bool ConsumeFromEnd(StringPiece x);
 
   // standard STL container boilerplate
-  typedef char value_type;
-  typedef const char* pointer;
-  typedef const char& reference;
-  typedef const char& const_reference;
-  typedef size_t size_type;
-  typedef ptrdiff_t difference_type;
   static const size_type npos;
-  typedef const char* const_iterator;
-  typedef const char* iterator;
-  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-  typedef std::reverse_iterator<iterator> reverse_iterator;
-  iterator begin() const { return ptr_; }
-  iterator end() const { return ptr_ + length_; }
+  const_iterator begin() const { return ptr_; }
+  const_iterator end() const { return ptr_ + length_; }
   const_reverse_iterator rbegin() const {
     return const_reverse_iterator(ptr_ + length_);
   }
   const_reverse_iterator rend() const {
     return const_reverse_iterator(ptr_);
   }
-  stringpiece_ssize_type max_size() const { return length_; }
-  stringpiece_ssize_type capacity() const { return length_; }
+  size_type max_size() const { return length_; }
+  size_type capacity() const { return length_; }
 
   // cpplint.py emits a false positive [build/include_what_you_use]
-  stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
+  size_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
 
   bool contains(StringPiece s) const;
 
-  stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const;
-  stringpiece_ssize_type find(char c, size_type pos = 0) const;
-  stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const;
-  stringpiece_ssize_type rfind(char c, size_type pos = npos) const;
+  size_type find(StringPiece s, size_type pos = 0) const;
+  size_type find(char c, size_type pos = 0) const;
+  size_type rfind(StringPiece s, size_type pos = npos) const;
+  size_type rfind(char c, size_type pos = npos) const;
 
-  stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const;
-  stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const {
+  size_type find_first_of(StringPiece s, size_type pos = 0) const;
+  size_type find_first_of(char c, size_type pos = 0) const {
     return find(c, pos);
   }
-  stringpiece_ssize_type find_first_not_of(StringPiece s,
-                                           size_type pos = 0) const;
-  stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const;
-  stringpiece_ssize_type find_last_of(StringPiece s,
-                                      size_type pos = npos) const;
-  stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const {
+  size_type find_first_not_of(StringPiece s, size_type pos = 0) const;
+  size_type find_first_not_of(char c, size_type pos = 0) const;
+  size_type find_last_of(StringPiece s, size_type pos = npos) const;
+  size_type find_last_of(char c, size_type pos = npos) const {
     return rfind(c, pos);
   }
-  stringpiece_ssize_type find_last_not_of(StringPiece s,
-                                          size_type pos = npos) const;
-  stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const;
+  size_type find_last_not_of(StringPiece s, size_type pos = npos) const;
+  size_type find_last_not_of(char c, size_type pos = npos) const;
 
   StringPiece substr(size_type pos, size_type n = npos) const;
 };
@@ -396,7 +343,7 @@
 // one of the arguments is a literal, the compiler can elide a lot of the
 // following comparisons.
 inline bool operator==(StringPiece x, StringPiece y) {
-  stringpiece_ssize_type len = x.size();
+  StringPiece::size_type len = x.size();
   if (len != y.size()) {
     return false;
   }
@@ -410,7 +357,7 @@
 }
 
 inline bool operator<(StringPiece x, StringPiece y) {
-  const stringpiece_ssize_type min_size =
+  const StringPiece::size_type min_size =
       x.size() < y.size() ? x.size() : y.size();
   const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size));
   return (r < 0) || (r == 0 && x.size() < y.size());
@@ -431,49 +378,10 @@
 // allow StringPiece to be logged
 extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
 
-namespace internal {
-// StringPiece is not a POD and can not be used in an union (pre C++11). We
-// need a POD version of it.
-struct StringPiecePod {
-  // Create from a StringPiece.
-  static StringPiecePod CreateFromStringPiece(StringPiece str) {
-    StringPiecePod pod;
-    pod.data_ = str.data();
-    pod.size_ = str.size();
-    return pod;
-  }
+}  // namespace stringpiece_internal
 
-  // Cast to StringPiece.
-  operator StringPiece() const { return StringPiece(data_, size_); }
+using ::google::protobuf::stringpiece_internal::StringPiece;
 
-  bool operator==(const char* value) const {
-    return StringPiece(data_, size_) == StringPiece(value);
-  }
-
-  char operator[](stringpiece_ssize_type i) const {
-    assert(0 <= i);
-    assert(i < size_);
-    return data_[i];
-  }
-
-  const char* data() const { return data_; }
-
-  stringpiece_ssize_type size() const {
-    return size_;
-  }
-
-  std::string ToString() const {
-    return std::string(data_, static_cast<size_t>(size_));
-  }
-
-  operator string() const { return ToString(); }
-
- private:
-  const char* data_;
-  stringpiece_ssize_type size_;
-};
-
-}  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc
index d9a32d0..ba904cb 100644
--- a/src/google/protobuf/stubs/stringpiece_unittest.cc
+++ b/src/google/protobuf/stubs/stringpiece_unittest.cc
@@ -87,7 +87,7 @@
 #if defined(HAS_GLOBAL_STRING)
   {
     // ::string
-    string bonjour = "bonjour";
+    std::string bonjour = "bonjour";
     StringPiece s40(bonjour);
     EXPECT_TRUE(s40.data() == bonjour.data());
     EXPECT_EQ(7, s40.length());
@@ -100,9 +100,9 @@
 }
 
 TEST(StringPiece, STLComparator) {
-  string s1("foo");
-  string s2("bar");
-  string s3("baz");
+  std::string s1("foo");
+  std::string s2("bar");
+  std::string s3("baz");
 
   StringPiece p1(s1);
   StringPiece p2(s2);
@@ -207,13 +207,13 @@
   COMPARE(true, >, "b",  "aa");
   COMPARE(true, >, "bb", "aa");
 
-  string x;
+  std::string x;
   for (int i = 0; i < 256; i++) {
     x += 'a';
-    string y = x;
+    std::string y = x;
     COMPARE(true, ==, x, y);
     for (int j = 0; j < i; j++) {
-      string z = x;
+      std::string z = x;
       z[j] = 'b';       // Differs in position 'j'
       COMPARE(false, ==, x, z);
       COMPARE(true, <, x, z);
@@ -240,7 +240,7 @@
   const StringPiece c("xyz");
   const StringPiece d("foobar");
   const StringPiece e;
-  string temp("123");
+  std::string temp("123");
   temp += '\0';
   temp += "456";
   const StringPiece f(temp);
@@ -305,17 +305,10 @@
   const StringPiece a("abcdefghijklmnopqrstuvwxyz");
   const StringPiece b("abc");
   const StringPiece c("xyz");
-  StringPiece d("foobar");
   const StringPiece e;
   const StringPiece f("123" "\0" "456", 7);
 
-  d.clear();
-  EXPECT_EQ(d.size(), 0);
-  EXPECT_TRUE(d.empty());
-  EXPECT_TRUE(d.data() == nullptr);
-  EXPECT_TRUE(d.begin() == d.end());
-
-  EXPECT_EQ(StringPiece::npos, string::npos);
+  EXPECT_EQ(StringPiece::npos, std::string::npos);
 
   EXPECT_EQ(a.find(b), 0);
   EXPECT_EQ(a.find(b, 1), StringPiece::npos);
@@ -324,27 +317,17 @@
   EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos);
   EXPECT_EQ(b.find(c), StringPiece::npos);
   EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos);
-  EXPECT_EQ(a.find(d), 0);
   EXPECT_EQ(a.find(e), 0);
-  EXPECT_EQ(a.find(d, 12), 12);
   EXPECT_EQ(a.find(e, 17), 17);
   StringPiece g("xx not found bb");
   EXPECT_EQ(a.find(g), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.find(b), StringPiece::npos);
   EXPECT_EQ(e.find(b), StringPiece::npos);
-  EXPECT_EQ(d.find(b, 4), StringPiece::npos);
   EXPECT_EQ(e.find(b, 7), StringPiece::npos);
 
-  size_t empty_search_pos = string().find(string());
-  EXPECT_EQ(d.find(d), empty_search_pos);
-  EXPECT_EQ(d.find(e), empty_search_pos);
-  EXPECT_EQ(e.find(d), empty_search_pos);
+  size_t empty_search_pos = std::string().find(std::string());
   EXPECT_EQ(e.find(e), empty_search_pos);
-  EXPECT_EQ(d.find(d, 4), string().find(string(), 4));
-  EXPECT_EQ(d.find(e, 4), string().find(string(), 4));
-  EXPECT_EQ(e.find(d, 4), string().find(string(), 4));
-  EXPECT_EQ(e.find(e, 4), string().find(string(), 4));
+  EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4));
 
   EXPECT_EQ(a.find('a'), 0);
   EXPECT_EQ(a.find('c'), 2);
@@ -359,13 +342,9 @@
   EXPECT_EQ(g.find('o', 5), 8);
   EXPECT_EQ(a.find('b', 5), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.find('\0'), StringPiece::npos);
   EXPECT_EQ(e.find('\0'), StringPiece::npos);
-  EXPECT_EQ(d.find('\0', 4), StringPiece::npos);
   EXPECT_EQ(e.find('\0', 7), StringPiece::npos);
-  EXPECT_EQ(d.find('x'), StringPiece::npos);
   EXPECT_EQ(e.find('x'), StringPiece::npos);
-  EXPECT_EQ(d.find('x', 4), StringPiece::npos);
   EXPECT_EQ(e.find('x', 7), StringPiece::npos);
 
   EXPECT_EQ(a.rfind(b), 0);
@@ -376,24 +355,14 @@
   EXPECT_EQ(a.rfind(c, 0), StringPiece::npos);
   EXPECT_EQ(b.rfind(c), StringPiece::npos);
   EXPECT_EQ(b.rfind(c, 0), StringPiece::npos);
-  EXPECT_EQ(a.rfind(d), a.as_string().rfind(string()));
-  EXPECT_EQ(a.rfind(e), a.as_string().rfind(string()));
-  EXPECT_EQ(a.rfind(d, 12), 12);
+  EXPECT_EQ(a.rfind(e), a.as_string().rfind(std::string()));
   EXPECT_EQ(a.rfind(e, 17), 17);
   EXPECT_EQ(a.rfind(g), StringPiece::npos);
-  EXPECT_EQ(d.rfind(b), StringPiece::npos);
   EXPECT_EQ(e.rfind(b), StringPiece::npos);
-  EXPECT_EQ(d.rfind(b, 4), StringPiece::npos);
   EXPECT_EQ(e.rfind(b, 7), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.rfind(d, 4), string().rfind(string()));
-  EXPECT_EQ(e.rfind(d, 7), string().rfind(string()));
-  EXPECT_EQ(d.rfind(e, 4), string().rfind(string()));
-  EXPECT_EQ(e.rfind(e, 7), string().rfind(string()));
-  EXPECT_EQ(d.rfind(d), string().rfind(string()));
-  EXPECT_EQ(e.rfind(d), string().rfind(string()));
-  EXPECT_EQ(d.rfind(e), string().rfind(string()));
-  EXPECT_EQ(e.rfind(e), string().rfind(string()));
+  EXPECT_EQ(e.rfind(e, 7), std::string().rfind(std::string()));
+  EXPECT_EQ(e.rfind(e), std::string().rfind(std::string()));
 
   EXPECT_EQ(g.rfind('o'), 8);
   EXPECT_EQ(g.rfind('q'), StringPiece::npos);
@@ -405,9 +374,7 @@
   EXPECT_EQ(f.rfind('3'), 2);
   EXPECT_EQ(f.rfind('5'), 5);
   // empty string nonsense
-  EXPECT_EQ(d.rfind('o'), StringPiece::npos);
   EXPECT_EQ(e.rfind('o'), StringPiece::npos);
-  EXPECT_EQ(d.rfind('o', 4), StringPiece::npos);
   EXPECT_EQ(e.rfind('o', 7), StringPiece::npos);
 
   EXPECT_EQ(a.find_first_of(b), 0);
@@ -425,13 +392,8 @@
   EXPECT_EQ(a.find_first_of(f), StringPiece::npos);
   EXPECT_EQ(f.find_first_of(a), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(a.find_first_of(d), StringPiece::npos);
   EXPECT_EQ(a.find_first_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(b), StringPiece::npos);
   EXPECT_EQ(e.find_first_of(b), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(d), StringPiece::npos);
-  EXPECT_EQ(e.find_first_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(e), StringPiece::npos);
   EXPECT_EQ(e.find_first_of(e), StringPiece::npos);
 
   EXPECT_EQ(a.find_first_not_of(b), 3);
@@ -440,14 +402,9 @@
   EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos);
   EXPECT_EQ(f.find_first_not_of(a), 0);
   EXPECT_EQ(a.find_first_not_of(f), 0);
-  EXPECT_EQ(a.find_first_not_of(d), 0);
   EXPECT_EQ(a.find_first_not_of(e), 0);
   // empty string nonsense
-  EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos);
-  EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos);
 
   StringPiece h("====");
@@ -459,9 +416,7 @@
   EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
   EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
   // empty string nonsense
-  EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos);
 
   //  StringPiece g("xx not found bb");
@@ -483,21 +438,11 @@
   EXPECT_EQ(f.find_last_of(i, 6), 6);
   EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(f.find_last_of(d), StringPiece::npos);
   EXPECT_EQ(f.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos);
   EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(d), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(f), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(f), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos);
 
   EXPECT_EQ(a.find_last_not_of(b), a.size()-1);
@@ -509,21 +454,11 @@
   EXPECT_EQ(a.find_last_not_of(b, 3), 3);
   EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
   EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
-  EXPECT_EQ(f.find_last_not_of(d, 4), 4);
   EXPECT_EQ(f.find_last_not_of(e, 4), 4);
-  EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos);
 
   EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1);
@@ -533,9 +468,7 @@
   EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos);
   EXPECT_EQ(b.find_last_not_of('b', 1), 0);
   // empty string nonsense
-  EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos);
 
   EXPECT_EQ(a.substr(0, 3), b);
@@ -546,43 +479,25 @@
   EXPECT_EQ(a.substr(3, 2), "de");
   // empty string nonsense
   EXPECT_EQ(a.substr(99, 2), e);
-  EXPECT_EQ(d.substr(99), e);
-  EXPECT_EQ(d.substr(0, 99), e);
-  EXPECT_EQ(d.substr(99, 99), e);
+  EXPECT_EQ(e.substr(99), e);
+  EXPECT_EQ(e.substr(0, 99), e);
+  EXPECT_EQ(e.substr(99, 99), e);
   // use of npos
   EXPECT_EQ(a.substr(0, StringPiece::npos), a);
   EXPECT_EQ(a.substr(23, StringPiece::npos), c);
   EXPECT_EQ(a.substr(StringPiece::npos, 0), e);
   EXPECT_EQ(a.substr(StringPiece::npos, 1), e);
   EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e);
-
-  // Substring constructors.
-  EXPECT_EQ(StringPiece(a, 0, 3), b);
-  EXPECT_EQ(StringPiece(a, 23), c);
-  EXPECT_EQ(StringPiece(a, 23, 3), c);
-  EXPECT_EQ(StringPiece(a, 23, 99), c);
-  EXPECT_EQ(StringPiece(a, 0), a);
-  EXPECT_EQ(StringPiece(a, 3, 2), "de");
-  // empty string nonsense
-  EXPECT_EQ(StringPiece(d, 0, 99), e);
-  // Verify that they work taking an actual string, not just a StringPiece.
-  string a2 = a.as_string();
-  EXPECT_EQ(StringPiece(a2, 0, 3), b);
-  EXPECT_EQ(StringPiece(a2, 23), c);
-  EXPECT_EQ(StringPiece(a2, 23, 3), c);
-  EXPECT_EQ(StringPiece(a2, 23, 99), c);
-  EXPECT_EQ(StringPiece(a2, 0), a);
-  EXPECT_EQ(StringPiece(a2, 3, 2), "de");
 }
 
 TEST(StringPiece, Custom) {
   StringPiece a("foobar");
-  string s1("123");
+  std::string s1("123");
   s1 += '\0';
   s1 += "456";
   StringPiece b(s1);
   StringPiece e;
-  string s2;
+  std::string s2;
 
   // CopyToString
   a.CopyToString(&s2);
@@ -647,54 +562,42 @@
   c.remove_suffix(c.size());
   EXPECT_EQ(c, e);
 
-  // set
-  c.set("foobar", 6);
-  EXPECT_EQ(c, a);
-  c.set("foobar", 0);
-  EXPECT_EQ(c, e);
-  c.set("foobar", 7);
-  EXPECT_NE(c, a);
-
-  c.set("foobar");
-  EXPECT_EQ(c, a);
-
-  c.set(static_cast<const void*>("foobar"), 6);
-  EXPECT_EQ(c, a);
-  c.set(static_cast<const void*>("foobar"), 0);
-  EXPECT_EQ(c, e);
-  c.set(static_cast<const void*>("foobar"), 7);
-  EXPECT_NE(c, a);
+  c = StringPiece("foobar", 7);
 
   // as_string
-  string s3(a.as_string().c_str(), 7);
+  std::string s3(a.as_string().c_str(), 7);
   EXPECT_EQ(c, s3);
-  string s4(e.as_string());
+  std::string s4(e.as_string());
   EXPECT_TRUE(s4.empty());
 
   // ToString
   {
-    string s5(a.ToString().c_str(), 7);
+    std::string s5(a.ToString().c_str(), 7);
     EXPECT_EQ(c, s5);
-    string s6(e.ToString());
+    std::string s6(e.ToString());
     EXPECT_TRUE(s6.empty());
   }
 
   // Consume
-  a.set("foobar");
-  EXPECT_TRUE(a.Consume("foo"));
-  EXPECT_EQ(a, "bar");
-  EXPECT_FALSE(a.Consume("foo"));
-  EXPECT_FALSE(a.Consume("barbar"));
-  EXPECT_FALSE(a.Consume("ar"));
-  EXPECT_EQ(a, "bar");
+  {
+    StringPiece str("foobar");
+    EXPECT_TRUE(str.Consume("foo"));
+    EXPECT_EQ(str, "bar");
+    EXPECT_FALSE(str.Consume("foo"));
+    EXPECT_FALSE(str.Consume("barbar"));
+    EXPECT_FALSE(str.Consume("ar"));
+    EXPECT_EQ(str, "bar");
+  }
 
-  a.set("foobar");
-  EXPECT_TRUE(a.ConsumeFromEnd("bar"));
-  EXPECT_EQ(a, "foo");
-  EXPECT_FALSE(a.ConsumeFromEnd("bar"));
-  EXPECT_FALSE(a.ConsumeFromEnd("foofoo"));
-  EXPECT_FALSE(a.ConsumeFromEnd("fo"));
-  EXPECT_EQ(a, "foo");
+  {
+    StringPiece str("foobar");
+    EXPECT_TRUE(str.ConsumeFromEnd("bar"));
+    EXPECT_EQ(str, "foo");
+    EXPECT_FALSE(str.ConsumeFromEnd("bar"));
+    EXPECT_FALSE(str.ConsumeFromEnd("foofoo"));
+    EXPECT_FALSE(str.ConsumeFromEnd("fo"));
+    EXPECT_EQ(str, "foo");
+  }
 }
 
 TEST(StringPiece, Contains) {
@@ -713,10 +616,6 @@
   EXPECT_EQ(s.data(), (const char*)nullptr);
   EXPECT_EQ(s.size(), 0);
 
-  s.set(nullptr);
-  EXPECT_EQ(s.data(), (const char*)nullptr);
-  EXPECT_EQ(s.size(), 0);
-
   // .ToString() on a StringPiece with nullptr should produce the empty string.
   EXPECT_EQ("", s.ToString());
   EXPECT_EQ("", s.as_string());
@@ -747,12 +646,12 @@
 }
 
 TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
-  EXPECT_EQ("hello", string("hello"));
-  EXPECT_LT("hello", string("world"));
+  EXPECT_EQ("hello", std::string("hello"));
+  EXPECT_LT("hello", std::string("world"));
 }
 
 TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) {
-  EXPECT_EQ(StringPiece("hello"), string("hello"));
+  EXPECT_EQ(StringPiece("hello"), std::string("hello"));
   EXPECT_EQ("hello", StringPiece("hello"));
 }
 
@@ -786,7 +685,7 @@
 #ifdef PROTOBUF_HAS_DEATH_TEST
 #ifndef NDEBUG
 TEST(NonNegativeLenTest, NonNegativeLen) {
-  EXPECT_DEATH(StringPiece("xyz", -1), "len >= 0");
+  EXPECT_DEATH(StringPiece("xyz", -1), "string length exceeds max size");
 }
 #endif  // ndef DEBUG
 #endif  // PROTOBUF_HAS_DEATH_TEST
diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc
index e6019fc..0761986 100644
--- a/src/google/protobuf/stubs/stringprintf.cc
+++ b/src/google/protobuf/stubs/stringprintf.cc
@@ -54,7 +54,7 @@
 enum { IS_COMPILER_MSVC = 0 };
 #endif
 
-void StringAppendV(string* dst, const char* format, va_list ap) {
+void StringAppendV(std::string* dst, const char* format, va_list ap) {
   // First try with a small fixed size buffer
   static const int kSpaceLength = 1024;
   char space[kSpaceLength];
@@ -105,17 +105,16 @@
   delete[] buf;
 }
 
-
-string StringPrintf(const char* format, ...) {
+std::string StringPrintf(const char* format, ...) {
   va_list ap;
   va_start(ap, format);
-  string result;
+  std::string result;
   StringAppendV(&result, format, ap);
   va_end(ap);
   return result;
 }
 
-const string& SStringPrintf(string* dst, const char* format, ...) {
+const std::string& SStringPrintf(std::string* dst, const char* format, ...) {
   va_list ap;
   va_start(ap, format);
   dst->clear();
@@ -124,7 +123,7 @@
   return *dst;
 }
 
-void StringAppendF(string* dst, const char* format, ...) {
+void StringAppendF(std::string* dst, const char* format, ...) {
   va_list ap;
   va_start(ap, format);
   StringAppendV(dst, format, ap);
@@ -139,7 +138,8 @@
 // and we can fix the problem or protect against an attack.
 static const char string_printf_empty_block[256] = { '\0' };
 
-string StringPrintfVector(const char* format, const std::vector<string>& v) {
+std::string StringPrintfVector(const char* format,
+                               const std::vector<std::string>& v) {
   GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs)
       << "StringPrintfVector currently only supports up to "
       << kStringPrintfVectorMaxArgs << " arguments. "
@@ -162,7 +162,7 @@
   // that accepts an array of arguments.  The best I can do is stick
   // this COMPILE_ASSERT right next to the actual statement.
 
-  GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
+  static_assert(kStringPrintfVectorMaxArgs == 32, "arg_count_mismatch");
   return StringPrintf(format,
                       cstr[0], cstr[1], cstr[2], cstr[3], cstr[4],
                       cstr[5], cstr[6], cstr[7], cstr[8], cstr[9],
diff --git a/src/google/protobuf/stubs/stringprintf.h b/src/google/protobuf/stubs/stringprintf.h
index 253d736..e3858be 100644
--- a/src/google/protobuf/stubs/stringprintf.h
+++ b/src/google/protobuf/stubs/stringprintf.h
@@ -52,18 +52,20 @@
 namespace protobuf {
 
 // Return a C++ string
-PROTOBUF_EXPORT extern string StringPrintf(const char* format, ...);
+PROTOBUF_EXPORT extern std::string StringPrintf(const char* format, ...);
 
 // Store result into a supplied string and return it
-PROTOBUF_EXPORT extern const string& SStringPrintf(string* dst,
-                                                   const char* format, ...);
+PROTOBUF_EXPORT extern const std::string& SStringPrintf(std::string* dst,
+                                                        const char* format,
+                                                        ...);
 
 // Append result to a supplied string
-PROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...);
+PROTOBUF_EXPORT extern void StringAppendF(std::string* dst, const char* format,
+                                          ...);
 
 // Lower-level routine that takes a va_list and appends to a specified
 // string.  All other routines are just convenience wrappers around it.
-PROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format,
+PROTOBUF_EXPORT extern void StringAppendV(std::string* dst, const char* format,
                                           va_list ap);
 
 // The max arguments supported by StringPrintfVector
@@ -72,8 +74,8 @@
 // You can use this version when all your arguments are strings, but
 // you don't know how many arguments you'll have at compile time.
 // StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
-PROTOBUF_EXPORT extern string StringPrintfVector(const char* format,
-                                                 const std::vector<string>& v);
+PROTOBUF_EXPORT extern std::string StringPrintfVector(
+    const char* format, const std::vector<std::string>& v);
 
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/stringprintf_unittest.cc b/src/google/protobuf/stubs/stringprintf_unittest.cc
index 7fcbf50..63f38bf 100644
--- a/src/google/protobuf/stubs/stringprintf_unittest.cc
+++ b/src/google/protobuf/stubs/stringprintf_unittest.cc
@@ -32,6 +32,7 @@
 
 #include <google/protobuf/stubs/stringprintf.h>
 
+#include <array>
 #include <cerrno>
 #include <string>
 
@@ -49,7 +50,7 @@
   // so we do not allow them in google3.
   EXPECT_EQ("", StringPrintf(""));
 #endif
-  EXPECT_EQ("", StringPrintf("%s", string().c_str()));
+  EXPECT_EQ("", StringPrintf("%s", std::string().c_str()));
   EXPECT_EQ("", StringPrintf("%s", ""));
 }
 
@@ -61,26 +62,26 @@
 }
 
 TEST(StringAppendFTest, Empty) {
-  string value("Hello");
+  std::string value("Hello");
   const char* empty = "";
   StringAppendF(&value, "%s", empty);
   EXPECT_EQ("Hello", value);
 }
 
 TEST(StringAppendFTest, EmptyString) {
-  string value("Hello");
+  std::string value("Hello");
   StringAppendF(&value, "%s", "");
   EXPECT_EQ("Hello", value);
 }
 
 TEST(StringAppendFTest, String) {
-  string value("Hello");
+  std::string value("Hello");
   StringAppendF(&value, " %s", "World");
   EXPECT_EQ("Hello World", value);
 }
 
 TEST(StringAppendFTest, Int) {
-  string value("Hello");
+  std::string value("Hello");
   StringAppendF(&value, " %d", 123);
   EXPECT_EQ("Hello 123", value);
 }
@@ -91,12 +92,14 @@
   // out of memory while trying to determine destination buffer size.
   // see b/4194543.
 
-  char* old_locale = setlocale(LC_CTYPE, nullptr);
+  char* old_locale_c = setlocale(LC_CTYPE, nullptr);
+  ASSERT_TRUE(old_locale_c != nullptr);
+  std::string old_locale = old_locale_c;
   // Push locale with multibyte mode
   setlocale(LC_CTYPE, "en_US.utf8");
 
   const char kInvalidCodePoint[] = "\375\067s";
-  string value = StringPrintf("%.*s", 3, kInvalidCodePoint);
+  std::string value = StringPrintf("%.*s", 3, kInvalidCodePoint);
 
   // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf
   // returns error given an invalid codepoint. Other versions
@@ -106,24 +109,25 @@
 
   // Repeat with longer string, to make sure that the dynamically
   // allocated path in StringAppendV is handled correctly.
-  int n = 2048;
-  char* buf = new char[n+1];
-  memset(buf, ' ', n-3);
-  memcpy(buf + n - 3, kInvalidCodePoint, 4);
-  value =  StringPrintf("%.*s", n, buf);
+  const size_t n = 2048;
+  std::array<char, n+1> buf;
+  memset(&buf[0], ' ', n-3);
+  memcpy(&buf[0] + n - 3, kInvalidCodePoint, 4);
+  value =  StringPrintf("%.*s", n, &buf[0]);
   // See GRTEv2 vs. GRTEv3 comment above.
-  EXPECT_TRUE(value.empty() || value == buf);
-  delete[] buf;
+  EXPECT_TRUE(value.empty() || value == &buf[0]);
 
-  setlocale(LC_CTYPE, old_locale);
+  setlocale(LC_CTYPE, old_locale.c_str());
 }
 
 TEST(StringPrintfTest, NoMultibyte) {
   // No multibyte handling, but the string contains funny chars.
-  char* old_locale = setlocale(LC_CTYPE, nullptr);
+  char* old_locale_c = setlocale(LC_CTYPE, nullptr);
+  ASSERT_TRUE(old_locale_c != nullptr);
+  std::string old_locale = old_locale_c;
   setlocale(LC_CTYPE, "POSIX");
-  string value = StringPrintf("%.*s", 3, "\375\067s");
-  setlocale(LC_CTYPE, old_locale);
+  std::string value = StringPrintf("%.*s", 3, "\375\067s");
+  setlocale(LC_CTYPE, old_locale.c_str());
   EXPECT_EQ("\375\067s", value);
 }
 
@@ -132,7 +136,7 @@
   // something significantly larger than what people are normally
   // printing in their badly written PLOG() statements.
   errno = ECHILD;
-  string value = StringPrintf("Hello, %s!", "World");
+  std::string value = StringPrintf("Hello, %s!", "World");
   EXPECT_EQ(ECHILD, errno);
 }
 
@@ -142,7 +146,7 @@
   char* buf = new char[n+1];
   memset(buf, ' ', n);
   buf[n] = 0;
-  string value = StringPrintf("%s", buf);
+  std::string value = StringPrintf("%s", buf);
   EXPECT_EQ(buf, value);
   delete[] buf;
 }
diff --git a/src/google/protobuf/stubs/structurally_valid.cc b/src/google/protobuf/stubs/structurally_valid.cc
index 4d424a1..9a476c3 100644
--- a/src/google/protobuf/stubs/structurally_valid.cc
+++ b/src/google/protobuf/stubs/structurally_valid.cc
@@ -561,7 +561,7 @@
   return (bytes_consumed == len);
 }
 
-int UTF8SpnStructurallyValid(const StringPiece& str) {
+int UTF8SpnStructurallyValid(StringPiece str) {
   if (!module_initialized_) return str.size();
 
   int bytes_consumed = 0;
@@ -582,8 +582,7 @@
 //
 // Fast case: all is structurally valid and no byte copying is done.
 //
-char* UTF8CoerceToStructurallyValid(const StringPiece& src_str,
-                                    char* idst,
+char* UTF8CoerceToStructurallyValid(StringPiece src_str, char* idst,
                                     const char replace_char) {
   const char* isrc = src_str.data();
   const int len = src_str.length();
diff --git a/src/google/protobuf/stubs/structurally_valid_unittest.cc b/src/google/protobuf/stubs/structurally_valid_unittest.cc
index eec07a8..ebd9c42 100644
--- a/src/google/protobuf/stubs/structurally_valid_unittest.cc
+++ b/src/google/protobuf/stubs/structurally_valid_unittest.cc
@@ -43,7 +43,8 @@
   // On GCC, this string can be written as:
   //   "abcd 1234 - \u2014\u2013\u2212"
   // MSVC seems to interpret \u differently.
-  string valid_str("abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789");
+  std::string valid_str(
+      "abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789");
   EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data(),
                                       valid_str.size()));
   // Additional check for pointer alignment
@@ -54,7 +55,7 @@
 }
 
 TEST(StructurallyValidTest, InvalidUTF8String) {
-  const string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789");
+  const std::string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789");
   EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data(),
                                        invalid_str.size()));
   // Additional check for pointer alignment
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 24ae286..0865f9f 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -84,7 +84,7 @@
 //    Replaces any occurrence of the character 'remove' (or the characters
 //    in 'remove') with the character 'replacewith'.
 // ----------------------------------------------------------------------
-void ReplaceCharacters(string *s, const char *remove, char replacewith) {
+void ReplaceCharacters(std::string *s, const char *remove, char replacewith) {
   const char *str_start = s->c_str();
   const char *str = str_start;
   for (str = strpbrk(str, remove);
@@ -94,7 +94,7 @@
   }
 }
 
-void StripWhitespace(string* str) {
+void StripWhitespace(std::string *str) {
   int str_length = str->length();
 
   // Strip off leading whitespace.
@@ -118,7 +118,7 @@
     --last;
   }
   if (last != (str_length - 1) && last >= 0) {
-    str->erase(last + 1, string::npos);
+    str->erase(last + 1, std::string::npos);
   }
 }
 
@@ -129,19 +129,19 @@
 //    it only replaces the first instance of "old."
 // ----------------------------------------------------------------------
 
-void StringReplace(const string& s, const string& oldsub,
-                   const string& newsub, bool replace_all,
-                   string* res) {
+void StringReplace(const std::string &s, const std::string &oldsub,
+                   const std::string &newsub, bool replace_all,
+                   std::string *res) {
   if (oldsub.empty()) {
     res->append(s);  // if empty, append the given string.
     return;
   }
 
-  string::size_type start_pos = 0;
-  string::size_type pos;
+  std::string::size_type start_pos = 0;
+  std::string::size_type pos;
   do {
     pos = s.find(oldsub, start_pos);
-    if (pos == string::npos) {
+    if (pos == std::string::npos) {
       break;
     }
     res->append(s, start_pos, pos - start_pos);
@@ -160,9 +160,9 @@
 //    happened or not.
 // ----------------------------------------------------------------------
 
-string StringReplace(const string& s, const string& oldsub,
-                     const string& newsub, bool replace_all) {
-  string ret;
+std::string StringReplace(const std::string &s, const std::string &oldsub,
+                          const std::string &newsub, bool replace_all) {
+  std::string ret;
   StringReplace(s, oldsub, newsub, replace_all, &ret);
   return ret;
 }
@@ -176,10 +176,8 @@
 // the characters in the string, not the entire string as a single delimiter.
 // ----------------------------------------------------------------------
 template <typename ITR>
-static inline
-void SplitStringToIteratorUsing(const string& full,
-                                const char* delim,
-                                ITR& result) {
+static inline void SplitStringToIteratorUsing(StringPiece full,
+                                              const char *delim, ITR &result) {
   // Optimize the common case where delim is a single character.
   if (delim[0] != '\0' && delim[1] == '\0') {
     char c = delim[0];
@@ -191,29 +189,29 @@
       } else {
         const char* start = p;
         while (++p != end && *p != c);
-        *result++ = string(start, p - start);
+        *result++ = std::string(start, p - start);
       }
     }
     return;
   }
 
-  string::size_type begin_index, end_index;
+  std::string::size_type begin_index, end_index;
   begin_index = full.find_first_not_of(delim);
-  while (begin_index != string::npos) {
+  while (begin_index != std::string::npos) {
     end_index = full.find_first_of(delim, begin_index);
-    if (end_index == string::npos) {
-      *result++ = full.substr(begin_index);
+    if (end_index == std::string::npos) {
+      *result++ = std::string(full.substr(begin_index));
       return;
     }
-    *result++ = full.substr(begin_index, (end_index - begin_index));
+    *result++ =
+        std::string(full.substr(begin_index, (end_index - begin_index)));
     begin_index = full.find_first_not_of(delim, end_index);
   }
 }
 
-void SplitStringUsing(const string& full,
-                      const char* delim,
-                      std::vector<string>* result) {
-  std::back_insert_iterator< std::vector<string> > it(*result);
+void SplitStringUsing(StringPiece full, const char *delim,
+                      std::vector<std::string> *result) {
+  std::back_insert_iterator<std::vector<std::string> > it(*result);
   SplitStringToIteratorUsing(full, delim, it);
 }
 
@@ -228,30 +226,29 @@
 //
 // If "pieces" is negative for some reason, it returns the whole string
 // ----------------------------------------------------------------------
-template <typename StringType, typename ITR>
-static inline
-void SplitStringToIteratorAllowEmpty(const StringType& full,
-                                     const char* delim,
-                                     int pieces,
-                                     ITR& result) {
-  string::size_type begin_index, end_index;
+template <typename ITR>
+static inline void SplitStringToIteratorAllowEmpty(StringPiece full,
+                                                   const char *delim,
+                                                   int pieces, ITR &result) {
+  std::string::size_type begin_index, end_index;
   begin_index = 0;
 
   for (int i = 0; (i < pieces-1) || (pieces == 0); i++) {
     end_index = full.find_first_of(delim, begin_index);
-    if (end_index == string::npos) {
-      *result++ = full.substr(begin_index);
+    if (end_index == std::string::npos) {
+      *result++ = std::string(full.substr(begin_index));
       return;
     }
-    *result++ = full.substr(begin_index, (end_index - begin_index));
+    *result++ =
+        std::string(full.substr(begin_index, (end_index - begin_index)));
     begin_index = end_index + 1;
   }
-  *result++ = full.substr(begin_index);
+  *result++ = std::string(full.substr(begin_index));
 }
 
-void SplitStringAllowEmpty(const string& full, const char* delim,
-                           std::vector<string>* result) {
-  std::back_insert_iterator<std::vector<string> > it(*result);
+void SplitStringAllowEmpty(StringPiece full, const char *delim,
+                           std::vector<std::string> *result) {
+  std::back_insert_iterator<std::vector<std::string> > it(*result);
   SplitStringToIteratorAllowEmpty(full, delim, 0, it);
 }
 
@@ -262,10 +259,8 @@
 //
 // ----------------------------------------------------------------------
 template <class ITERATOR>
-static void JoinStringsIterator(const ITERATOR& start,
-                                const ITERATOR& end,
-                                const char* delim,
-                                string* result) {
+static void JoinStringsIterator(const ITERATOR &start, const ITERATOR &end,
+                                const char *delim, std::string *result) {
   GOOGLE_CHECK(result != nullptr);
   result->clear();
   int delim_length = strlen(delim);
@@ -289,9 +284,8 @@
   }
 }
 
-void JoinStrings(const std::vector<string>& components,
-                 const char* delim,
-                 string * result) {
+void JoinStrings(const std::vector<std::string> &components, const char *delim,
+                 std::string *result) {
   JoinStringsIterator(components.begin(), components.end(), delim, result);
 }
 
@@ -317,8 +311,8 @@
   return UnescapeCEscapeSequences(source, dest, nullptr);
 }
 
-int UnescapeCEscapeSequences(const char* source, char* dest,
-                             std::vector<string> *errors) {
+int UnescapeCEscapeSequences(const char *source, char *dest,
+                             std::vector<std::string> *errors) {
   GOOGLE_DCHECK(errors == nullptr) << "Error reporting not implemented.";
 
   char* d = dest;
@@ -373,8 +367,10 @@
           while (isxdigit(p[1]))  // arbitrarily many hex digits
             ch = (ch << 4) + hex_digit_to_int(*++p);
           if (ch > 0xFF)
-            LOG_STRING(ERROR, errors) << "Value of " <<
-              "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits";
+            LOG_STRING(ERROR, errors)
+                << "Value of "
+                << "\\" << std::string(hex_start, p + 1 - hex_start)
+                << " exceeds 8 bits";
           *d++ = ch;
           break;
         }
@@ -389,7 +385,7 @@
             } else {
               LOG_STRING(ERROR, errors)
                 << "\\u must be followed by 4 hex digits: \\"
-                <<  string(hex_start, p+1-hex_start);
+                <<  std::string(hex_start, p+1-hex_start);
               break;
             }
           }
@@ -408,7 +404,7 @@
               if (newrune > 0x10FFFF) {
                 LOG_STRING(ERROR, errors)
                   << "Value of \\"
-                  << string(hex_start, p + 1 - hex_start)
+                  << std::string(hex_start, p + 1 - hex_start)
                   << " exceeds Unicode limit (0x10FFFF)";
                 break;
               } else {
@@ -417,7 +413,7 @@
             } else {
               LOG_STRING(ERROR, errors)
                 << "\\U must be followed by 8 hex digits: \\"
-                <<  string(hex_start, p+1-hex_start);
+                <<  std::string(hex_start, p+1-hex_start);
               break;
             }
           }
@@ -449,12 +445,12 @@
 //    In the first and second calls, the length of dest is returned. In the
 //    the third call, the new string is returned.
 // ----------------------------------------------------------------------
-int UnescapeCEscapeString(const string& src, string* dest) {
+int UnescapeCEscapeString(const std::string &src, std::string *dest) {
   return UnescapeCEscapeString(src, dest, nullptr);
 }
 
-int UnescapeCEscapeString(const string& src, string* dest,
-                          std::vector<string> *errors) {
+int UnescapeCEscapeString(const std::string &src, std::string *dest,
+                          std::vector<std::string> *errors) {
   std::unique_ptr<char[]> unescaped(new char[src.size() + 1]);
   int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors);
   GOOGLE_CHECK(dest);
@@ -462,10 +458,10 @@
   return len;
 }
 
-string UnescapeCEscapeString(const string& src) {
+std::string UnescapeCEscapeString(const std::string &src) {
   std::unique_ptr<char[]> unescaped(new char[src.size() + 1]);
   int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), nullptr);
-  return string(unescaped.get(), len);
+  return std::string(unescaped.get(), len);
 }
 
 // ----------------------------------------------------------------------
@@ -549,7 +545,7 @@
   };
 
   size_t escaped_len = 0;
-  for (int i = 0; i < src.size(); ++i) {
+  for (StringPiece::size_type i = 0; i < src.size(); ++i) {
     unsigned char c = static_cast<unsigned char>(src[i]);
     escaped_len += c_escaped_len[c];
   }
@@ -562,7 +558,7 @@
 // the required space using a lookup table, and also does not do any special
 // handling for Hex or UTF-8 characters.
 // ----------------------------------------------------------------------
-void CEscapeAndAppend(StringPiece src, string* dest) {
+void CEscapeAndAppend(StringPiece src, std::string *dest) {
   size_t escaped_len = CEscapedLength(src);
   if (escaped_len == src.size()) {
     dest->append(src.data(), src.size());
@@ -573,7 +569,7 @@
   dest->resize(cur_dest_len + escaped_len);
   char* append_ptr = &(*dest)[cur_dest_len];
 
-  for (int i = 0; i < src.size(); ++i) {
+  for (StringPiece::size_type i = 0; i < src.size(); ++i) {
     unsigned char c = static_cast<unsigned char>(src[i]);
     switch (c) {
       case '\n': *append_ptr++ = '\\'; *append_ptr++ = 'n'; break;
@@ -596,30 +592,30 @@
   }
 }
 
-string CEscape(const string& src) {
-  string dest;
+std::string CEscape(const std::string &src) {
+  std::string dest;
   CEscapeAndAppend(src, &dest);
   return dest;
 }
 
 namespace strings {
 
-string Utf8SafeCEscape(const string& src) {
+std::string Utf8SafeCEscape(const std::string &src) {
   const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
   std::unique_ptr<char[]> dest(new char[dest_length]);
   const int len = CEscapeInternal(src.data(), src.size(),
                                   dest.get(), dest_length, false, true);
   GOOGLE_DCHECK_GE(len, 0);
-  return string(dest.get(), len);
+  return std::string(dest.get(), len);
 }
 
-string CHexEscape(const string& src) {
+std::string CHexEscape(const std::string &src) {
   const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
   std::unique_ptr<char[]> dest(new char[dest_length]);
   const int len = CEscapeInternal(src.data(), src.size(),
                                   dest.get(), dest_length, true, false);
   GOOGLE_DCHECK_GE(len, 0);
-  return string(dest.get(), len);
+  return std::string(dest.get(), len);
 }
 
 }  // namespace strings
@@ -667,8 +663,8 @@
   return static_cast<uint32>(result);
 }
 
-inline bool safe_parse_sign(string* text  /*inout*/,
-                            bool* negative_ptr  /*output*/) {
+inline bool safe_parse_sign(std::string *text /*inout*/,
+                            bool *negative_ptr /*output*/) {
   const char* start = text->data();
   const char* end = start + text->size();
 
@@ -695,9 +691,8 @@
   return true;
 }
 
-template<typename IntType>
-bool safe_parse_positive_int(
-    string text, IntType* value_p) {
+template <typename IntType>
+bool safe_parse_positive_int(std::string text, IntType *value_p) {
   int base = 10;
   IntType value = 0;
   const IntType vmax = std::numeric_limits<IntType>::max();
@@ -729,9 +724,8 @@
   return true;
 }
 
-template<typename IntType>
-bool safe_parse_negative_int(
-    const string& text, IntType* value_p) {
+template <typename IntType>
+bool safe_parse_negative_int(const std::string &text, IntType *value_p) {
   int base = 10;
   IntType value = 0;
   const IntType vmin = std::numeric_limits<IntType>::min();
@@ -770,8 +764,8 @@
   return true;
 }
 
-template<typename IntType>
-bool safe_int_internal(string text, IntType* value_p) {
+template <typename IntType>
+bool safe_int_internal(std::string text, IntType *value_p) {
   *value_p = 0;
   bool negative;
   if (!safe_parse_sign(&text, &negative)) {
@@ -784,8 +778,8 @@
   }
 }
 
-template<typename IntType>
-bool safe_uint_internal(string text, IntType* value_p) {
+template <typename IntType>
+bool safe_uint_internal(std::string text, IntType *value_p) {
   *value_p = 0;
   bool negative;
   if (!safe_parse_sign(&text, &negative) || negative) {
@@ -1119,46 +1113,46 @@
 //    Return value: string
 // ----------------------------------------------------------------------
 
-string SimpleItoa(int i) {
+std::string SimpleItoa(int i) {
   char buffer[kFastToBufferSize];
   return (sizeof(i) == 4) ?
     FastInt32ToBuffer(i, buffer) :
     FastInt64ToBuffer(i, buffer);
 }
 
-string SimpleItoa(unsigned int i) {
+std::string SimpleItoa(unsigned int i) {
   char buffer[kFastToBufferSize];
-  return string(buffer, (sizeof(i) == 4) ?
-    FastUInt32ToBufferLeft(i, buffer) :
-    FastUInt64ToBufferLeft(i, buffer));
+  return std::string(buffer, (sizeof(i) == 4)
+                                 ? FastUInt32ToBufferLeft(i, buffer)
+                                 : FastUInt64ToBufferLeft(i, buffer));
 }
 
-string SimpleItoa(long i) {
+std::string SimpleItoa(long i) {
   char buffer[kFastToBufferSize];
   return (sizeof(i) == 4) ?
     FastInt32ToBuffer(i, buffer) :
     FastInt64ToBuffer(i, buffer);
 }
 
-string SimpleItoa(unsigned long i) {
+std::string SimpleItoa(unsigned long i) {
   char buffer[kFastToBufferSize];
-  return string(buffer, (sizeof(i) == 4) ?
-    FastUInt32ToBufferLeft(i, buffer) :
-    FastUInt64ToBufferLeft(i, buffer));
+  return std::string(buffer, (sizeof(i) == 4)
+                                 ? FastUInt32ToBufferLeft(i, buffer)
+                                 : FastUInt64ToBufferLeft(i, buffer));
 }
 
-string SimpleItoa(long long i) {
+std::string SimpleItoa(long long i) {
   char buffer[kFastToBufferSize];
   return (sizeof(i) == 4) ?
     FastInt32ToBuffer(i, buffer) :
     FastInt64ToBuffer(i, buffer);
 }
 
-string SimpleItoa(unsigned long long i) {
+std::string SimpleItoa(unsigned long long i) {
   char buffer[kFastToBufferSize];
-  return string(buffer, (sizeof(i) == 4) ?
-    FastUInt32ToBufferLeft(i, buffer) :
-    FastUInt64ToBufferLeft(i, buffer));
+  return std::string(buffer, (sizeof(i) == 4)
+                                 ? FastUInt32ToBufferLeft(i, buffer)
+                                 : FastUInt64ToBufferLeft(i, buffer));
 }
 
 // ----------------------------------------------------------------------
@@ -1202,12 +1196,12 @@
 //    implementation.
 // ----------------------------------------------------------------------
 
-string SimpleDtoa(double value) {
+std::string SimpleDtoa(double value) {
   char buffer[kDoubleToBufferSize];
   return DoubleToBuffer(value, buffer);
 }
 
-string SimpleFtoa(float value) {
+std::string SimpleFtoa(float value) {
   char buffer[kFloatToBufferSize];
   return FloatToBuffer(value, buffer);
 }
@@ -1250,7 +1244,7 @@
   // platforms these days.  Just in case some system exists where DBL_DIG
   // is significantly larger -- and risks overflowing our buffer -- we have
   // this assert.
-  GOOGLE_COMPILE_ASSERT(DBL_DIG < 20, DBL_DIG_is_too_big);
+  static_assert(DBL_DIG < 20, "DBL_DIG_is_too_big");
 
   if (value == std::numeric_limits<double>::infinity()) {
     strcpy(buffer, "inf");
@@ -1293,7 +1287,7 @@
   const unsigned char *us1 = reinterpret_cast<const unsigned char *>(s1);
   const unsigned char *us2 = reinterpret_cast<const unsigned char *>(s2);
 
-  for ( int i = 0; i < len; i++ ) {
+  for (size_t i = 0; i < len; i++) {
     const int diff =
       static_cast<int>(static_cast<unsigned char>(ascii_tolower(us1[i]))) -
       static_cast<int>(static_cast<unsigned char>(ascii_tolower(us2[i])));
@@ -1347,19 +1341,19 @@
   return *str != '\0' && *endptr == '\0';
 }
 
-bool safe_strto32(const string& str, int32* value) {
+bool safe_strto32(const std::string &str, int32 *value) {
   return safe_int_internal(str, value);
 }
 
-bool safe_strtou32(const string& str, uint32* value) {
+bool safe_strtou32(const std::string &str, uint32 *value) {
   return safe_uint_internal(str, value);
 }
 
-bool safe_strto64(const string& str, int64* value) {
+bool safe_strto64(const std::string &str, int64 *value) {
   return safe_int_internal(str, value);
 }
 
-bool safe_strtou64(const string& str, uint64* value) {
+bool safe_strtou64(const std::string &str, uint64 *value) {
   return safe_uint_internal(str, value);
 }
 
@@ -1368,7 +1362,7 @@
   // platforms these days.  Just in case some system exists where FLT_DIG
   // is significantly larger -- and risks overflowing our buffer -- we have
   // this assert.
-  GOOGLE_COMPILE_ASSERT(FLT_DIG < 10, FLT_DIG_is_too_big);
+  static_assert(FLT_DIG < 10, "FLT_DIG_is_too_big");
 
   if (value == std::numeric_limits<double>::infinity()) {
     strcpy(buffer, "inf");
@@ -1475,8 +1469,8 @@
   return out;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b) {
+  std::string result;
   result.resize(a.size() + b.size());
   char *const begin = &*result.begin();
   char *out = Append2(begin, a, b);
@@ -1484,8 +1478,8 @@
   return result;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+  std::string result;
   result.resize(a.size() + b.size() + c.size());
   char *const begin = &*result.begin();
   char *out = Append2(begin, a, b);
@@ -1494,9 +1488,9 @@
   return result;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
-              const AlphaNum &d) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+                   const AlphaNum &d) {
+  std::string result;
   result.resize(a.size() + b.size() + c.size() + d.size());
   char *const begin = &*result.begin();
   char *out = Append4(begin, a, b, c, d);
@@ -1504,9 +1498,9 @@
   return result;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
-              const AlphaNum &d, const AlphaNum &e) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+                   const AlphaNum &d, const AlphaNum &e) {
+  std::string result;
   result.resize(a.size() + b.size() + c.size() + d.size() + e.size());
   char *const begin = &*result.begin();
   char *out = Append4(begin, a, b, c, d);
@@ -1515,9 +1509,9 @@
   return result;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
-              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+                   const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) {
+  std::string result;
   result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
                 f.size());
   char *const begin = &*result.begin();
@@ -1527,10 +1521,10 @@
   return result;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
-              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
-              const AlphaNum &g) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+                   const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+                   const AlphaNum &g) {
+  std::string result;
   result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
                 f.size() + g.size());
   char *const begin = &*result.begin();
@@ -1541,10 +1535,10 @@
   return result;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
-              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
-              const AlphaNum &g, const AlphaNum &h) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+                   const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+                   const AlphaNum &g, const AlphaNum &h) {
+  std::string result;
   result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
                 f.size() + g.size() + h.size());
   char *const begin = &*result.begin();
@@ -1554,10 +1548,10 @@
   return result;
 }
 
-string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
-              const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
-              const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) {
-  string result;
+std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+                   const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+                   const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) {
+  std::string result;
   result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
                 f.size() + g.size() + h.size() + i.size());
   char *const begin = &*result.begin();
@@ -1576,27 +1570,27 @@
     GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \
                      uintptr_t((dest).size()))
 
-void StrAppend(string *result, const AlphaNum &a) {
+void StrAppend(std::string *result, const AlphaNum &a) {
   GOOGLE_DCHECK_NO_OVERLAP(*result, a);
   result->append(a.data(), a.size());
 }
 
-void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) {
+void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b) {
   GOOGLE_DCHECK_NO_OVERLAP(*result, a);
   GOOGLE_DCHECK_NO_OVERLAP(*result, b);
-  string::size_type old_size = result->size();
+  std::string::size_type old_size = result->size();
   result->resize(old_size + a.size() + b.size());
   char *const begin = &*result->begin();
   char *out = Append2(begin + old_size, a, b);
   GOOGLE_DCHECK_EQ(out, begin + result->size());
 }
 
-void StrAppend(string *result,
-               const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b,
+               const AlphaNum &c) {
   GOOGLE_DCHECK_NO_OVERLAP(*result, a);
   GOOGLE_DCHECK_NO_OVERLAP(*result, b);
   GOOGLE_DCHECK_NO_OVERLAP(*result, c);
-  string::size_type old_size = result->size();
+  std::string::size_type old_size = result->size();
   result->resize(old_size + a.size() + b.size() + c.size());
   char *const begin = &*result->begin();
   char *out = Append2(begin + old_size, a, b);
@@ -1604,33 +1598,32 @@
   GOOGLE_DCHECK_EQ(out, begin + result->size());
 }
 
-void StrAppend(string *result,
-               const AlphaNum &a, const AlphaNum &b,
+void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b,
                const AlphaNum &c, const AlphaNum &d) {
   GOOGLE_DCHECK_NO_OVERLAP(*result, a);
   GOOGLE_DCHECK_NO_OVERLAP(*result, b);
   GOOGLE_DCHECK_NO_OVERLAP(*result, c);
   GOOGLE_DCHECK_NO_OVERLAP(*result, d);
-  string::size_type old_size = result->size();
+  std::string::size_type old_size = result->size();
   result->resize(old_size + a.size() + b.size() + c.size() + d.size());
   char *const begin = &*result->begin();
   char *out = Append4(begin + old_size, a, b, c, d);
   GOOGLE_DCHECK_EQ(out, begin + result->size());
 }
 
-int GlobalReplaceSubstring(const string& substring,
-                           const string& replacement,
-                           string* s) {
+int GlobalReplaceSubstring(const std::string &substring,
+                           const std::string &replacement, std::string *s) {
   GOOGLE_CHECK(s != nullptr);
   if (s->empty() || substring.empty())
     return 0;
-  string tmp;
+  std::string tmp;
   int num_replacements = 0;
   int pos = 0;
-  for (int match_pos = s->find(substring.data(), pos, substring.length());
-       match_pos != string::npos;
-       pos = match_pos + substring.length(),
-           match_pos = s->find(substring.data(), pos, substring.length())) {
+  for (StringPiece::size_type match_pos =
+           s->find(substring.data(), pos, substring.length());
+       match_pos != std::string::npos; pos = match_pos + substring.length(),
+                              match_pos = s->find(substring.data(), pos,
+                                                  substring.length())) {
     ++num_replacements;
     // Append the original content before the match.
     tmp.append(*s, pos, match_pos - pos);
@@ -2060,8 +2053,8 @@
   return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64);
 }
 
-static bool Base64UnescapeInternal(const char* src, int slen, string* dest,
-                                   const signed char* unbase64) {
+static bool Base64UnescapeInternal(const char *src, int slen, std::string *dest,
+                                   const signed char *unbase64) {
   // Determine the size of the output string.  Base64 encodes every 3 bytes into
   // 4 characters.  any leftover chars are added directly for good measure.
   // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
@@ -2085,11 +2078,11 @@
   return true;
 }
 
-bool Base64Unescape(StringPiece src, string* dest) {
+bool Base64Unescape(StringPiece src, std::string *dest) {
   return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
 }
 
-bool WebSafeBase64Unescape(StringPiece src, string* dest) {
+bool WebSafeBase64Unescape(StringPiece src, std::string *dest) {
   return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
 }
 
@@ -2108,7 +2101,7 @@
   char *limit_dest = dest + szdest;
   const unsigned char *limit_src = src + szsrc;
 
-  // Three bytes of data encodes to four characters of cyphertext.
+  // Three bytes of data encodes to four characters of ciphertext.
   // So we can pump through three-byte chunks atomically.
   while (cur_src < limit_src - 3) {  // keep going as long as we have >= 32 bits
     uint32 in = BigEndian::Load32(cur_src) >> 8;
@@ -2135,7 +2128,7 @@
       break;
     case 1: {
       // One byte left: this encodes to two characters, and (optionally)
-      // two pad characters to round out the four-character cypherblock.
+      // two pad characters to round out the four-character cipherblock.
       if ((szdest -= 2) < 0) return 0;
       uint32 in = cur_src[0];
       cur_dest[0] = base64[in >> 2];
@@ -2152,7 +2145,7 @@
     }
     case 2: {
       // Two bytes left: this encodes to three characters, and (optionally)
-      // one pad character to round out the four-character cypherblock.
+      // one pad character to round out the four-character cipherblock.
       if ((szdest -= 3) < 0) return 0;
       uint32 in = BigEndian::Load16(cur_src);
       cur_dest[0] = base64[in >> 10];
@@ -2208,9 +2201,9 @@
                               kWebSafeBase64Chars, do_padding);
 }
 
-void Base64EscapeInternal(const unsigned char* src, int szsrc,
-                          string* dest, bool do_padding,
-                          const char* base64_chars) {
+void Base64EscapeInternal(const unsigned char *src, int szsrc,
+                          std::string *dest, bool do_padding,
+                          const char *base64_chars) {
   const int calc_escaped_size =
     CalculateBase64EscapedLen(szsrc, do_padding);
   dest->resize(calc_escaped_size);
@@ -2223,27 +2216,27 @@
   dest->erase(escaped_len);
 }
 
-void Base64Escape(const unsigned char *src, int szsrc,
-                  string* dest, bool do_padding) {
+void Base64Escape(const unsigned char *src, int szsrc, std::string *dest,
+                  bool do_padding) {
   Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars);
 }
 
-void WebSafeBase64Escape(const unsigned char *src, int szsrc,
-                         string *dest, bool do_padding) {
+void WebSafeBase64Escape(const unsigned char *src, int szsrc, std::string *dest,
+                         bool do_padding) {
   Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars);
 }
 
-void Base64Escape(StringPiece src, string* dest) {
+void Base64Escape(StringPiece src, std::string *dest) {
   Base64Escape(reinterpret_cast<const unsigned char*>(src.data()),
                src.size(), dest, true);
 }
 
-void WebSafeBase64Escape(StringPiece src, string* dest) {
+void WebSafeBase64Escape(StringPiece src, std::string *dest) {
   WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
                       src.size(), dest, false);
 }
 
-void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) {
+void WebSafeBase64EscapeWithPadding(StringPiece src, std::string *dest) {
   WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
                       src.size(), dest, true);
 }
@@ -2339,19 +2332,19 @@
 //       (1) determines the presence of LF (first one is ok)
 //       (2) if yes, removes any CR, else convert every CR to LF
 
-void CleanStringLineEndings(const string &src, string *dst,
+void CleanStringLineEndings(const std::string &src, std::string *dst,
                             bool auto_end_last_line) {
   if (dst->empty()) {
     dst->append(src);
     CleanStringLineEndings(dst, auto_end_last_line);
   } else {
-    string tmp = src;
+    std::string tmp = src;
     CleanStringLineEndings(&tmp, auto_end_last_line);
     dst->append(tmp);
   }
 }
 
-void CleanStringLineEndings(string *str, bool auto_end_last_line) {
+void CleanStringLineEndings(std::string *str, bool auto_end_last_line) {
   ptrdiff_t output_pos = 0;
   bool r_seen = false;
   ptrdiff_t len = str->size();
@@ -2382,7 +2375,7 @@
         continue;
       }
     }
-    string::const_reference in = p[input_pos];
+    std::string::const_reference in = p[input_pos];
     if (in == '\r') {
       if (r_seen) p[output_pos++] = '\n';
       r_seen = true;
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 79a7aeb..84fc232 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -113,18 +113,13 @@
 //    prefix string if the prefix matches, otherwise the original
 //    string.
 // ----------------------------------------------------------------------
-inline bool HasPrefixString(const string& str,
-                            const string& prefix) {
-  return str.size() >= prefix.size() &&
-         str.compare(0, prefix.size(), prefix) == 0;
-}
-
 inline bool HasPrefixString(StringPiece str, StringPiece prefix) {
   return str.size() >= prefix.size() &&
          memcmp(str.data(), prefix.data(), prefix.size()) == 0;
 }
 
-inline string StripPrefixString(const string& str, const string& prefix) {
+inline std::string StripPrefixString(const std::string& str,
+                                     const std::string& prefix) {
   if (HasPrefixString(str, prefix)) {
     return str.substr(prefix.size());
   } else {
@@ -140,13 +135,14 @@
 //    suffix string if the suffix matches, otherwise the original
 //    string.
 // ----------------------------------------------------------------------
-inline bool HasSuffixString(const string& str,
-                            const string& suffix) {
+inline bool HasSuffixString(StringPiece str, StringPiece suffix) {
   return str.size() >= suffix.size() &&
-         str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+         memcmp(str.data() + str.size() - suffix.size(), suffix.data(),
+                suffix.size()) == 0;
 }
 
-inline string StripSuffixString(const string& str, const string& suffix) {
+inline std::string StripSuffixString(const std::string& str,
+                                     const std::string& suffix) {
   if (HasSuffixString(str, suffix)) {
     return str.substr(0, str.size() - suffix.size());
   } else {
@@ -163,10 +159,10 @@
 // StripWhitespace
 //    Removes whitespaces from both ends of the given string.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT void ReplaceCharacters(string* s, const char* remove,
+PROTOBUF_EXPORT void ReplaceCharacters(std::string* s, const char* remove,
                                        char replacewith);
 
-PROTOBUF_EXPORT void StripWhitespace(string* s);
+PROTOBUF_EXPORT void StripWhitespace(std::string* s);
 
 // ----------------------------------------------------------------------
 // LowerString()
@@ -178,24 +174,26 @@
 //    strings.
 // ----------------------------------------------------------------------
 
-inline void LowerString(string * s) {
-  string::iterator end = s->end();
-  for (string::iterator i = s->begin(); i != end; ++i) {
+inline void LowerString(std::string* s) {
+  std::string::iterator end = s->end();
+  for (std::string::iterator i = s->begin(); i != end; ++i) {
     // tolower() changes based on locale.  We don't want this!
     if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
   }
 }
 
-inline void UpperString(string * s) {
-  string::iterator end = s->end();
-  for (string::iterator i = s->begin(); i != end; ++i) {
+inline void UpperString(std::string* s) {
+  std::string::iterator end = s->end();
+  for (std::string::iterator i = s->begin(); i != end; ++i) {
     // toupper() changes based on locale.  We don't want this!
     if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
   }
 }
 
-inline string ToUpper(const string& s) {
-  string out = s;
+inline void ToUpper(std::string* s) { UpperString(s); }
+
+inline std::string ToUpper(const std::string& s) {
+  std::string out = s;
   UpperString(&out);
   return out;
 }
@@ -208,8 +206,10 @@
 //    happened or not.
 // ----------------------------------------------------------------------
 
-PROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub,
-                                     const string& newsub, bool replace_all);
+PROTOBUF_EXPORT std::string StringReplace(const std::string& s,
+                                          const std::string& oldsub,
+                                          const std::string& newsub,
+                                          bool replace_all);
 
 // ----------------------------------------------------------------------
 // SplitStringUsing()
@@ -217,8 +217,8 @@
 //    to 'result'.  If there are consecutive delimiters, this function skips
 //    over all of them.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
-                                      std::vector<string>* res);
+PROTOBUF_EXPORT void SplitStringUsing(StringPiece full, const char* delim,
+                                      std::vector<std::string>* res);
 
 // Split a string using one or more byte delimiters, presented
 // as a nul-terminated c string. Append the components to 'result'.
@@ -228,17 +228,16 @@
 //
 // If "full" is the empty string, yields an empty string as the only value.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
-                                           const char* delim,
-                                           std::vector<string>* result);
+PROTOBUF_EXPORT void SplitStringAllowEmpty(StringPiece full, const char* delim,
+                                           std::vector<std::string>* result);
 
 // ----------------------------------------------------------------------
 // Split()
 //    Split a string using a character delimiter.
 // ----------------------------------------------------------------------
-inline std::vector<string> Split(
-    const string& full, const char* delim, bool skip_empty = true) {
-  std::vector<string> result;
+inline std::vector<std::string> Split(StringPiece full, const char* delim,
+                                      bool skip_empty = true) {
+  std::vector<std::string> result;
   if (skip_empty) {
     SplitStringUsing(full, delim, &result);
   } else {
@@ -255,12 +254,12 @@
 //    another takes a pointer to the target string. In the latter case the
 //    target string is cleared and overwritten.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT void JoinStrings(const std::vector<string>& components,
-                                 const char* delim, string* result);
+PROTOBUF_EXPORT void JoinStrings(const std::vector<std::string>& components,
+                                 const char* delim, std::string* result);
 
-inline string JoinStrings(const std::vector<string>& components,
-                          const char* delim) {
-  string result;
+inline std::string JoinStrings(const std::vector<std::string>& components,
+                               const char* delim) {
+  std::string result;
   JoinStrings(components, delim, &result);
   return result;
 }
@@ -298,7 +297,7 @@
 
 PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
 PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
-                                             std::vector<string>* errors);
+                                             std::vector<std::string>* errors);
 
 // ----------------------------------------------------------------------
 // UnescapeCEscapeString()
@@ -315,10 +314,12 @@
 //    the third call, the new string is returned.
 // ----------------------------------------------------------------------
 
-PROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest);
-PROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest,
-                                          std::vector<string>* errors);
-PROTOBUF_EXPORT string UnescapeCEscapeString(const string& src);
+PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src,
+                                          std::string* dest);
+PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src,
+                                          std::string* dest,
+                                          std::vector<std::string>* errors);
+PROTOBUF_EXPORT std::string UnescapeCEscapeString(const std::string& src);
 
 // ----------------------------------------------------------------------
 // CEscape()
@@ -327,21 +328,21 @@
 //
 //    Escaped chars: \n, \r, \t, ", ', \, and !isprint().
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT string CEscape(const string& src);
+PROTOBUF_EXPORT std::string CEscape(const std::string& src);
 
 // ----------------------------------------------------------------------
 // CEscapeAndAppend()
 //    Escapes 'src' using C-style escape sequences, and appends the escaped
 //    string to 'dest'.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, string* dest);
+PROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, std::string* dest);
 
 namespace strings {
 // Like CEscape() but does not escape bytes with the upper bit set.
-PROTOBUF_EXPORT string Utf8SafeCEscape(const string& src);
+PROTOBUF_EXPORT std::string Utf8SafeCEscape(const std::string& src);
 
 // Like CEscape() but uses hex (\x) escapes instead of octals.
-PROTOBUF_EXPORT string CHexEscape(const string& src);
+PROTOBUF_EXPORT std::string CHexEscape(const std::string& src);
 }  // namespace strings
 
 // ----------------------------------------------------------------------
@@ -376,14 +377,14 @@
 // For now, long long is 64-bit on all the platforms we care about, so these
 // functions can simply pass the call to strto[u]ll.
 inline int64 strto64(const char *nptr, char **endptr, int base) {
-  GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
-                        sizeof_int64_is_not_sizeof_long_long);
+  static_assert(sizeof(int64) == sizeof(long long),
+                "sizeof_int64_is_not_sizeof_long_long");
   return strtoll(nptr, endptr, base);
 }
 
 inline uint64 strtou64(const char *nptr, char **endptr, int base) {
-  GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
-                        sizeof_uint64_is_not_sizeof_long_long);
+  static_assert(sizeof(uint64) == sizeof(unsigned long long),
+                "sizeof_uint64_is_not_sizeof_long_long");
   return strtoull(nptr, endptr, base);
 }
 
@@ -398,31 +399,31 @@
 // ----------------------------------------------------------------------
 PROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);
 
-PROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value);
-PROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value);
+PROTOBUF_EXPORT bool safe_strto32(const std::string& str, int32* value);
+PROTOBUF_EXPORT bool safe_strtou32(const std::string& str, uint32* value);
 inline bool safe_strto32(const char* str, int32* value) {
-  return safe_strto32(string(str), value);
+  return safe_strto32(std::string(str), value);
 }
 inline bool safe_strto32(StringPiece str, int32* value) {
   return safe_strto32(str.ToString(), value);
 }
 inline bool safe_strtou32(const char* str, uint32* value) {
-  return safe_strtou32(string(str), value);
+  return safe_strtou32(std::string(str), value);
 }
 inline bool safe_strtou32(StringPiece str, uint32* value) {
   return safe_strtou32(str.ToString(), value);
 }
 
-PROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value);
-PROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value);
+PROTOBUF_EXPORT bool safe_strto64(const std::string& str, int64* value);
+PROTOBUF_EXPORT bool safe_strtou64(const std::string& str, uint64* value);
 inline bool safe_strto64(const char* str, int64* value) {
-  return safe_strto64(string(str), value);
+  return safe_strto64(std::string(str), value);
 }
 inline bool safe_strto64(StringPiece str, int64* value) {
   return safe_strto64(str.ToString(), value);
 }
 inline bool safe_strtou64(const char* str, uint64* value) {
-  return safe_strtou64(string(str), value);
+  return safe_strtou64(std::string(str), value);
 }
 inline bool safe_strtou64(StringPiece str, uint64* value) {
   return safe_strtou64(str.ToString(), value);
@@ -430,10 +431,10 @@
 
 PROTOBUF_EXPORT bool safe_strtof(const char* str, float* value);
 PROTOBUF_EXPORT bool safe_strtod(const char* str, double* value);
-inline bool safe_strtof(const string& str, float* value) {
+inline bool safe_strtof(const std::string& str, float* value) {
   return safe_strtof(str.c_str(), value);
 }
-inline bool safe_strtod(const string& str, double* value) {
+inline bool safe_strtod(const std::string& str, double* value) {
   return safe_strtod(str.c_str(), value);
 }
 inline bool safe_strtof(StringPiece str, float* value) {
@@ -526,9 +527,7 @@
   return buffer;
 }
 
-inline string SimpleBtoa(bool value) {
-  return value ? "true" : "false";
-}
+inline std::string SimpleBtoa(bool value) { return value ? "true" : "false"; }
 
 // ----------------------------------------------------------------------
 // SimpleItoa()
@@ -536,12 +535,12 @@
 //
 //    Return value: string
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT string SimpleItoa(int i);
-PROTOBUF_EXPORT string SimpleItoa(unsigned int i);
-PROTOBUF_EXPORT string SimpleItoa(long i);
-PROTOBUF_EXPORT string SimpleItoa(unsigned long i);
-PROTOBUF_EXPORT string SimpleItoa(long long i);
-PROTOBUF_EXPORT string SimpleItoa(unsigned long long i);
+PROTOBUF_EXPORT std::string SimpleItoa(int i);
+PROTOBUF_EXPORT std::string SimpleItoa(unsigned int i);
+PROTOBUF_EXPORT std::string SimpleItoa(long i);
+PROTOBUF_EXPORT std::string SimpleItoa(unsigned long i);
+PROTOBUF_EXPORT std::string SimpleItoa(long long i);
+PROTOBUF_EXPORT std::string SimpleItoa(unsigned long long i);
 
 // ----------------------------------------------------------------------
 // SimpleDtoa()
@@ -562,8 +561,8 @@
 //
 //    Return value: string
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT string SimpleDtoa(double value);
-PROTOBUF_EXPORT string SimpleFtoa(float value);
+PROTOBUF_EXPORT std::string SimpleDtoa(double value);
+PROTOBUF_EXPORT std::string SimpleFtoa(float value);
 
 PROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer);
 PROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
@@ -659,15 +658,12 @@
   // TODO: Add a string_ref constructor, eventually
   // AlphaNum(const StringPiece &pc) : piece(pc) {}
 
-  AlphaNum(const string& str)
+  AlphaNum(const std::string& str)
       : piece_data_(str.data()), piece_size_(str.size()) {}
 
   AlphaNum(StringPiece str)
       : piece_data_(str.data()), piece_size_(str.size()) {}
 
-  AlphaNum(internal::StringPiecePod str)
-      : piece_data_(str.data()), piece_size_(str.size()) {}
-
   size_t size() const { return piece_size_; }
   const char *data() const { return piece_data_; }
 
@@ -707,32 +703,34 @@
 //    be a reference into str.
 // ----------------------------------------------------------------------
 
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b);
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
-                              const AlphaNum& c);
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
-                              const AlphaNum& c, const AlphaNum& d);
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
-                              const AlphaNum& c, const AlphaNum& d,
-                              const AlphaNum& e);
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
-                              const AlphaNum& c, const AlphaNum& d,
-                              const AlphaNum& e, const AlphaNum& f);
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
-                              const AlphaNum& c, const AlphaNum& d,
-                              const AlphaNum& e, const AlphaNum& f,
-                              const AlphaNum& g);
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
-                              const AlphaNum& c, const AlphaNum& d,
-                              const AlphaNum& e, const AlphaNum& f,
-                              const AlphaNum& g, const AlphaNum& h);
-PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
-                              const AlphaNum& c, const AlphaNum& d,
-                              const AlphaNum& e, const AlphaNum& f,
-                              const AlphaNum& g, const AlphaNum& h,
-                              const AlphaNum& i);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                   const AlphaNum& c);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                   const AlphaNum& c, const AlphaNum& d);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                   const AlphaNum& c, const AlphaNum& d,
+                                   const AlphaNum& e);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                   const AlphaNum& c, const AlphaNum& d,
+                                   const AlphaNum& e, const AlphaNum& f);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                   const AlphaNum& c, const AlphaNum& d,
+                                   const AlphaNum& e, const AlphaNum& f,
+                                   const AlphaNum& g);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                   const AlphaNum& c, const AlphaNum& d,
+                                   const AlphaNum& e, const AlphaNum& f,
+                                   const AlphaNum& g, const AlphaNum& h);
+PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                   const AlphaNum& c, const AlphaNum& d,
+                                   const AlphaNum& e, const AlphaNum& f,
+                                   const AlphaNum& g, const AlphaNum& h,
+                                   const AlphaNum& i);
 
-inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); }
+inline std::string StrCat(const AlphaNum& a) {
+  return std::string(a.data(), a.size());
+}
 
 // ----------------------------------------------------------------------
 // StrAppend()
@@ -755,12 +753,12 @@
 //    worked around as consecutive calls to StrAppend are quite efficient.
 // ----------------------------------------------------------------------
 
-PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a);
-PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a);
+PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a,
                                const AlphaNum& b);
-PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a,
                                const AlphaNum& b, const AlphaNum& c);
-PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a,
                                const AlphaNum& b, const AlphaNum& c,
                                const AlphaNum& d);
 
@@ -770,8 +768,8 @@
 //    the C-string "delim" as a separator between components.
 // ----------------------------------------------------------------------
 template <typename Iterator>
-void Join(Iterator start, Iterator end,
-          const char* delim, string* result) {
+void Join(Iterator start, Iterator end, const char* delim,
+          std::string* result) {
   for (Iterator it = start; it != end; ++it) {
     if (it != start) {
       result->append(delim);
@@ -781,9 +779,8 @@
 }
 
 template <typename Range>
-string Join(const Range& components,
-            const char* delim) {
-  string result;
+std::string Join(const Range& components, const char* delim) {
+  std::string result;
   Join(components.begin(), components.end(), delim, &result);
   return result;
 }
@@ -792,7 +789,7 @@
 // ToHex()
 //    Return a lower-case hex string representation of the given integer.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT string ToHex(uint64 num);
+PROTOBUF_EXPORT std::string ToHex(uint64 num);
 
 // ----------------------------------------------------------------------
 // GlobalReplaceSubstring()
@@ -801,9 +798,9 @@
 //
 //    NOTE: The string pieces must not overlap s.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring,
-                                           const string& replacement,
-                                           string* s);
+PROTOBUF_EXPORT int GlobalReplaceSubstring(const std::string& substring,
+                                           const std::string& replacement,
+                                           std::string* s);
 
 // ----------------------------------------------------------------------
 // Base64Unescape()
@@ -811,7 +808,7 @@
 //    writes it to "dest". If src contains invalid characters, dest is cleared
 //    and the function returns false. Returns true on success.
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest);
+PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, std::string* dest);
 
 // ----------------------------------------------------------------------
 // WebSafeBase64Unescape()
@@ -826,7 +823,7 @@
 // ----------------------------------------------------------------------
 PROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, char* dest,
                                           int szdest);
-PROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest);
+PROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, std::string* dest);
 
 // Return the length to use for the output buffer given to the base64 escape
 // routines. Make sure to use the same value for do_padding in both.
@@ -854,17 +851,17 @@
                                         char* dest, int szdest,
                                         bool do_padding);
 // Encode src into dest with padding.
-PROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest);
+PROTOBUF_EXPORT void Base64Escape(StringPiece src, std::string* dest);
 // Encode src into dest web-safely without padding.
-PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest);
+PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, std::string* dest);
 // Encode src into dest web-safely with padding.
 PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
-                                                    string* dest);
+                                                    std::string* dest);
 
 PROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
-                                  string* dest, bool do_padding);
+                                  std::string* dest, bool do_padding);
 PROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
-                                         string* dest, bool do_padding);
+                                         std::string* dest, bool do_padding);
 
 inline bool IsValidCodePoint(uint32 code_point) {
   return code_point < 0xD800 ||
@@ -920,11 +917,12 @@
 //
 //       (1) determines the presence of LF (first one is ok)
 //       (2) if yes, removes any CR, else convert every CR to LF
-PROTOBUF_EXPORT void CleanStringLineEndings(const string& src, string* dst,
+PROTOBUF_EXPORT void CleanStringLineEndings(const std::string& src,
+                                            std::string* dst,
                                             bool auto_end_last_line);
 
 // Same as above, but transforms the argument in place.
-PROTOBUF_EXPORT void CleanStringLineEndings(string* str,
+PROTOBUF_EXPORT void CleanStringLineEndings(std::string* str,
                                             bool auto_end_last_line);
 
 namespace strings {
diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc
index 141d263..0fbfab4 100644
--- a/src/google/protobuf/stubs/strutil_unittest.cc
+++ b/src/google/protobuf/stubs/strutil_unittest.cc
@@ -52,7 +52,7 @@
   // Remember the old locale.
   char* old_locale_cstr = setlocale(LC_NUMERIC, nullptr);
   ASSERT_TRUE(old_locale_cstr != nullptr);
-  string old_locale = old_locale_cstr;
+  std::string old_locale = old_locale_cstr;
 
   // Set the locale to "C".
   ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != nullptr);
@@ -83,7 +83,7 @@
 static struct {
   int plain_length;
   const char* plaintext;
-  const char* cyphertext;
+  const char* ciphertext;
 } base64_tests[] = {
   // Empty string.
   { 0, "", ""},
@@ -343,10 +343,10 @@
 
 static struct {
   const char* plaintext;
-  const char* cyphertext;
+  const char* ciphertext;
 } base64_strings[] = {
   // Some google quotes
-  // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
+  // Ciphertext created with "uuencode (GNU sharutils) 4.6.3"
   // (Note that we're testing the websafe encoding, though, so if
   // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
   { "I was always good at math and science, and I never realized "
@@ -441,8 +441,8 @@
     int encode_length;
     char decode_buffer[100];
     int decode_length;
-    int cypher_length;
-    string decode_str;
+    int cipher_length;
+    std::string decode_str;
 
     const unsigned char* unsigned_plaintext =
       reinterpret_cast<const unsigned char*>(base64_tests[i].plaintext);
@@ -450,7 +450,7 @@
     StringPiece plaintext(base64_tests[i].plaintext,
                           base64_tests[i].plain_length);
 
-    cypher_length = strlen(base64_tests[i].cyphertext);
+    cipher_length = strlen(base64_tests[i].ciphertext);
 
     // The basic escape function:
     memset(encode_buffer, 0, sizeof(encode_buffer));
@@ -459,30 +459,30 @@
                                  encode_buffer,
                                  sizeof(encode_buffer));
     //    Is it of the expected length?
-    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(encode_length, cipher_length);
     // Would it have been okay to allocate only CalculateBase64EscapeLen()?
     EXPECT_EQ(CalculateBase64EscapedLen(base64_tests[i].plain_length),
               encode_length);
 
     //    Is it the expected encoded value?
-    ASSERT_STREQ(encode_buffer, base64_tests[i].cyphertext);
+    ASSERT_STREQ(encode_buffer, base64_tests[i].ciphertext);
 
     // If we encode it into a buffer of exactly the right length...
     memset(encode_buffer, 0, sizeof(encode_buffer));
     encode_length = Base64Escape(unsigned_plaintext,
                                           base64_tests[i].plain_length,
                                           encode_buffer,
-                                          cypher_length);
+                                          cipher_length);
     //    Is it still of the expected length?
-    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(encode_length, cipher_length);
 
     //    And is the value still correct?  (i.e., not losing the last byte)
-    EXPECT_STREQ(encode_buffer, base64_tests[i].cyphertext);
+    EXPECT_STREQ(encode_buffer, base64_tests[i].ciphertext);
 
     // If we decode it back:
     decode_str.clear();
     EXPECT_TRUE(Base64Unescape(
-        StringPiece(encode_buffer, cypher_length), &decode_str));
+        StringPiece(encode_buffer, cipher_length), &decode_str));
 
     //    Is it of the expected length?
     EXPECT_EQ(base64_tests[i].plain_length, decode_str.length());
@@ -491,15 +491,15 @@
     EXPECT_EQ(plaintext, decode_str);
 
     // Let's try with a pre-populated string.
-    string encoded("this junk should be ignored");
-    Base64Escape(string(base64_tests[i].plaintext,
-                        base64_tests[i].plain_length),
-                 &encoded);
-    EXPECT_EQ(encoded, string(encode_buffer, cypher_length));
+    std::string encoded("this junk should be ignored");
+    Base64Escape(
+        std::string(base64_tests[i].plaintext, base64_tests[i].plain_length),
+        &encoded);
+    EXPECT_EQ(encoded, std::string(encode_buffer, cipher_length));
 
-    string decoded("this junk should be ignored");
+    std::string decoded("this junk should be ignored");
     EXPECT_TRUE(Base64Unescape(
-        StringPiece(encode_buffer, cypher_length), &decoded));
+        StringPiece(encode_buffer, cipher_length), &decoded));
     EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
     EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
 
@@ -514,7 +514,7 @@
 
       // Try chopping off the equals sign(s) entirely.  The decoder
       // should still be okay with this.
-      string decoded2("this junk should also be ignored");
+      std::string decoded2("this junk should also be ignored");
       *first_equals = '\0';
       EXPECT_TRUE(Base64Unescape(
           StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2));
@@ -578,7 +578,7 @@
 
     char websafe[100];
     memset(websafe, 0, sizeof(websafe));
-    strncpy(websafe, base64_tests[i].cyphertext, cypher_length);
+    strncpy(websafe, base64_tests[i].ciphertext, cipher_length);
     for (int c = 0; c < sizeof(websafe); ++c) {
       if ('+' == websafe[c]) { websafe[c] = '-'; }
       if ('/' == websafe[c]) { websafe[c] = '_'; }
@@ -592,7 +592,7 @@
                                                  sizeof(encode_buffer),
                                                  true);
     //    Is it of the expected length?
-    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(encode_length, cipher_length);
     EXPECT_EQ(
         CalculateBase64EscapedLen(base64_tests[i].plain_length, true),
         encode_length);
@@ -605,10 +605,10 @@
     encode_length = WebSafeBase64Escape(unsigned_plaintext,
                                                  base64_tests[i].plain_length,
                                                  encode_buffer,
-                                                 cypher_length,
+                                                 cipher_length,
                                                  true);
     //    Is it still of the expected length?
-    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(encode_length, cipher_length);
 
     //    And is the value still correct?  (i.e., not losing the last byte)
     EXPECT_STREQ(encode_buffer, websafe);
@@ -618,13 +618,13 @@
     WebSafeBase64Escape(
         unsigned_plaintext, base64_tests[i].plain_length,
         &encoded, true);
-    EXPECT_EQ(encoded.size(), cypher_length);
+    EXPECT_EQ(encoded.size(), cipher_length);
     EXPECT_STREQ(encoded.c_str(), websafe);
 
     //    If we decode it back:
     memset(decode_buffer, 0, sizeof(decode_buffer));
     decode_length = WebSafeBase64Unescape(encode_buffer,
-                                                   cypher_length,
+                                                   cipher_length,
                                                    decode_buffer,
                                                    sizeof(decode_buffer));
 
@@ -638,7 +638,7 @@
     //    If we decode it into a buffer of exactly the right length...
     memset(decode_buffer, 0, sizeof(decode_buffer));
     decode_length = WebSafeBase64Unescape(encode_buffer,
-                                                   cypher_length,
+                                                   cipher_length,
                                                    decode_buffer,
                                                    decode_length);
 
@@ -650,14 +650,14 @@
               memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
 
     // Try using '.' for the pad character.
-    for (int c = cypher_length - 1; c >= 0 && '=' == encode_buffer[c]; --c) {
+    for (int c = cipher_length - 1; c >= 0 && '=' == encode_buffer[c]; --c) {
       encode_buffer[c] = '.';
     }
 
     // If we decode it back:
     memset(decode_buffer, 0, sizeof(decode_buffer));
     decode_length = WebSafeBase64Unescape(encode_buffer,
-                                                   cypher_length,
+                                                   cipher_length,
                                                    decode_buffer,
                                                    sizeof(decode_buffer));
 
@@ -671,7 +671,7 @@
     // If we decode it into a buffer of exactly the right length...
     memset(decode_buffer, 0, sizeof(decode_buffer));
     decode_length = WebSafeBase64Unescape(encode_buffer,
-                                                   cypher_length,
+                                                   cipher_length,
                                                    decode_buffer,
                                                    decode_length);
 
@@ -685,7 +685,7 @@
     // Let's try the string version of the decoder
     decoded = "this junk should be ignored";
     EXPECT_TRUE(WebSafeBase64Unescape(
-        StringPiece(encode_buffer, cypher_length), &decoded));
+        StringPiece(encode_buffer, cipher_length), &decoded));
     EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
     EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
 
@@ -695,7 +695,7 @@
     for (int c = 0; c < sizeof(websafe); ++c) {
       if ('=' == websafe[c]) {
         websafe[c] = '\0';
-        cypher_length = c;
+        cipher_length = c;
         break;
       }
     }
@@ -708,7 +708,7 @@
                                                  sizeof(encode_buffer),
                                                  false);
     //    Is it of the expected length?
-    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(encode_length, cipher_length);
     EXPECT_EQ(
         CalculateBase64EscapedLen(base64_tests[i].plain_length, false),
         encode_length);
@@ -721,25 +721,25 @@
     encode_length = WebSafeBase64Escape(unsigned_plaintext,
                                                  base64_tests[i].plain_length,
                                                  encode_buffer,
-                                                 cypher_length,
+                                                 cipher_length,
                                                  false);
     //    Is it still of the expected length?
-    EXPECT_EQ(encode_length, cypher_length);
+    EXPECT_EQ(encode_length, cipher_length);
 
     //    And is the value still correct?  (i.e., not losing the last byte)
     EXPECT_STREQ(encode_buffer, websafe);
 
     // Let's try the (other) string version of the encoder
-    string plain(base64_tests[i].plaintext, base64_tests[i].plain_length);
+    std::string plain(base64_tests[i].plaintext, base64_tests[i].plain_length);
     encoded = "this junk should be ignored";
     WebSafeBase64Escape(plain, &encoded);
-    EXPECT_EQ(encoded.size(), cypher_length);
+    EXPECT_EQ(encoded.size(), cipher_length);
     EXPECT_STREQ(encoded.c_str(), websafe);
 
     //    If we decode it back:
     memset(decode_buffer, 0, sizeof(decode_buffer));
     decode_length = WebSafeBase64Unescape(encode_buffer,
-                                                   cypher_length,
+                                                   cipher_length,
                                                    decode_buffer,
                                                    sizeof(decode_buffer));
 
@@ -753,7 +753,7 @@
     //    If we decode it into a buffer of exactly the right length...
     memset(decode_buffer, 0, sizeof(decode_buffer));
     decode_length = WebSafeBase64Unescape(encode_buffer,
-                                                   cypher_length,
+                                                   cipher_length,
                                                    decode_buffer,
                                                    decode_length);
 
@@ -768,7 +768,7 @@
     // Let's try the string version of the decoder
     decoded = "this junk should be ignored";
     EXPECT_TRUE(WebSafeBase64Unescape(
-        StringPiece(encode_buffer, cypher_length), &decoded));
+        StringPiece(encode_buffer, cipher_length), &decoded));
     EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
     EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
 
@@ -781,24 +781,24 @@
     const unsigned char* unsigned_plaintext =
       reinterpret_cast<const unsigned char*>(base64_strings[i].plaintext);
     int plain_length = strlen(base64_strings[i].plaintext);
-    int cypher_length = strlen(base64_strings[i].cyphertext);
-    std::vector<char> buffer(cypher_length+1);
+    int cipher_length = strlen(base64_strings[i].ciphertext);
+    std::vector<char> buffer(cipher_length+1);
     int encode_length = WebSafeBase64Escape(unsigned_plaintext,
                                                      plain_length,
                                                      &buffer[0],
                                                      buffer.size(),
                                                      false);
-    EXPECT_EQ(cypher_length, encode_length);
+    EXPECT_EQ(cipher_length, encode_length);
     EXPECT_EQ(
         CalculateBase64EscapedLen(plain_length, false), encode_length);
     buffer[ encode_length ] = '\0';
-    EXPECT_STREQ(base64_strings[i].cyphertext, &buffer[0]);
+    EXPECT_STREQ(base64_strings[i].ciphertext, &buffer[0]);
   }
 
   // Verify the behavior when decoding bad data
   {
     const char* bad_data = "ab-/";
-    string buf;
+    std::string buf;
     EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf));
     EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf));
     EXPECT_TRUE(buf.empty());
@@ -819,7 +819,7 @@
   const size_t size = 10;
   const intptr_t intptr = -12;
   const uintptr_t uintptr = 13;
-  string answer;
+  std::string answer;
   answer = StrCat(s, us);
   EXPECT_EQ(answer, "-12");
   answer = StrCat(i, ui);
@@ -836,12 +836,13 @@
   EXPECT_EQ(answer, "130");
 }
 
-class ReplaceChars : public ::testing::TestWithParam<
-                         std::tuple<string, string, const char*, char>> {};
+class ReplaceChars
+    : public ::testing::TestWithParam<
+          std::tuple<std::string, std::string, const char*, char>> {};
 
 TEST_P(ReplaceChars, ReplacesAllOccurencesOfAnyCharInReplaceWithAReplaceChar) {
-  string expected = std::get<0>(GetParam());
-  string string_to_replace_in = std::get<1>(GetParam());
+  std::string expected = std::get<0>(GetParam());
+  std::string string_to_replace_in = std::get<1>(GetParam());
   const char* what_to_replace = std::get<2>(GetParam());
   char replacement = std::get<3>(GetParam());
   ReplaceCharacters(&string_to_replace_in, what_to_replace, replacement);
@@ -864,11 +865,12 @@
         std::make_tuple("qvvvvvng v T", "queueing a T", "aeiou",
                         'v')));  // replace all voewls
 
-class StripWs : public ::testing::TestWithParam<std::tuple<string, string>> {};
+class StripWs
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {};
 
 TEST_P(StripWs, AlwaysStripsLeadingAndTrailingWhitespace) {
-  string expected = std::get<0>(GetParam());
-  string string_to_strip = std::get<1>(GetParam());
+  std::string expected = std::get<0>(GetParam());
+  std::string string_to_strip = std::get<1>(GetParam());
   StripWhitespace(&string_to_strip);
   ASSERT_EQ(expected, string_to_strip);
 }
diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc
index a36f2f0..d301682 100644
--- a/src/google/protobuf/stubs/substitute.cc
+++ b/src/google/protobuf/stubs/substitute.cc
@@ -52,26 +52,24 @@
   return count;
 }
 
-string Substitute(
-    const char* format,
-    const SubstituteArg& arg0, const SubstituteArg& arg1,
-    const SubstituteArg& arg2, const SubstituteArg& arg3,
-    const SubstituteArg& arg4, const SubstituteArg& arg5,
-    const SubstituteArg& arg6, const SubstituteArg& arg7,
-    const SubstituteArg& arg8, const SubstituteArg& arg9) {
-  string result;
-  SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4,
-                                       arg5, arg6, arg7, arg8, arg9);
+std::string Substitute(const std::string& format, const SubstituteArg& arg0,
+                       const SubstituteArg& arg1, const SubstituteArg& arg2,
+                       const SubstituteArg& arg3, const SubstituteArg& arg4,
+                       const SubstituteArg& arg5, const SubstituteArg& arg6,
+                       const SubstituteArg& arg7, const SubstituteArg& arg8,
+                       const SubstituteArg& arg9) {
+  std::string result;
+  SubstituteAndAppend(&result, format.c_str(), arg0, arg1, arg2, arg3, arg4,
+                      arg5, arg6, arg7, arg8, arg9);
   return result;
 }
 
-void SubstituteAndAppend(
-    string* output, const char* format,
-    const SubstituteArg& arg0, const SubstituteArg& arg1,
-    const SubstituteArg& arg2, const SubstituteArg& arg3,
-    const SubstituteArg& arg4, const SubstituteArg& arg5,
-    const SubstituteArg& arg6, const SubstituteArg& arg7,
-    const SubstituteArg& arg8, const SubstituteArg& arg9) {
+void SubstituteAndAppend(std::string* output, const char* format,
+                         const SubstituteArg& arg0, const SubstituteArg& arg1,
+                         const SubstituteArg& arg2, const SubstituteArg& arg3,
+                         const SubstituteArg& arg4, const SubstituteArg& arg5,
+                         const SubstituteArg& arg6, const SubstituteArg& arg7,
+                         const SubstituteArg& arg8, const SubstituteArg& arg9) {
   const SubstituteArg* const args_array[] = {
     &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, nullptr
   };
diff --git a/src/google/protobuf/stubs/substitute.h b/src/google/protobuf/stubs/substitute.h
index 267dead..0f851de 100644
--- a/src/google/protobuf/stubs/substitute.h
+++ b/src/google/protobuf/stubs/substitute.h
@@ -31,10 +31,12 @@
 // Author: kenton@google.com (Kenton Varda)
 // from google3/strings/substitute.h
 
-#include <string>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
 #include <google/protobuf/stubs/strutil.h>
 
+#include <string>
+
 #ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
 #define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
 
@@ -90,8 +92,10 @@
  public:
   inline SubstituteArg(const char* value)
     : text_(value), size_(strlen(text_)) {}
-  inline SubstituteArg(const string& value)
-    : text_(value.data()), size_(value.size()) {}
+  inline SubstituteArg(const std::string& value)
+      : text_(value.data()), size_(value.size()) {}
+  inline SubstituteArg(const StringPiece value)
+      : text_(value.data()), size_(value.size()) {}
 
   // Indicates that no argument was given.
   inline explicit SubstituteArg()
@@ -139,21 +143,21 @@
 
 }  // namespace internal
 
-PROTOBUF_EXPORT string
-Substitute(const char* format,
-           const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
-           const internal::SubstituteArg& arg9 = internal::SubstituteArg());
+PROTOBUF_EXPORT std::string Substitute(
+    const std::string& format,
+    const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg3 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg4 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg5 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg6 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg7 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg8 = internal::SubstituteArg(),
+    const internal::SubstituteArg& arg9 = internal::SubstituteArg());
 
 PROTOBUF_EXPORT void SubstituteAndAppend(
-    string* output, const char* format,
+    std::string* output, const char* format,
     const internal::SubstituteArg& arg0 = internal::SubstituteArg(),
     const internal::SubstituteArg& arg1 = internal::SubstituteArg(),
     const internal::SubstituteArg& arg2 = internal::SubstituteArg(),
diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc
index 64f3ceb..922be76 100644
--- a/src/google/protobuf/stubs/time.cc
+++ b/src/google/protobuf/stubs/time.cc
@@ -130,7 +130,7 @@
 
 // Format nanoseconds with either 3, 6, or 9 digits depending on the required
 // precision to represent the exact value.
-string FormatNanos(int32 nanos) {
+std::string FormatNanos(int32 nanos) {
   if (nanos % kNanosPerMillisecond == 0) {
     return StringPrintf("%03d", nanos / kNanosPerMillisecond);
   } else if (nanos % kNanosPerMicrosecond == 0) {
@@ -268,21 +268,21 @@
   *nanos = 0;
 }
 
-string FormatTime(int64 seconds, int32 nanos) {
+std::string FormatTime(int64 seconds, int32 nanos) {
   DateTime time;
   if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) {
     return "InvalidTime";
   }
-  string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
-                               time.year, time.month, time.day,
-                               time.hour, time.minute, time.second);
+  std::string result =
+      StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", time.year, time.month,
+                   time.day, time.hour, time.minute, time.second);
   if (nanos != 0) {
     result += "." + FormatNanos(nanos);
   }
   return result + "Z";
 }
 
-bool ParseTime(const string& value, int64* seconds, int32* nanos) {
+bool ParseTime(const std::string& value, int64* seconds, int32* nanos) {
   DateTime time;
   const char* data = value.c_str();
   // We only accept:
diff --git a/src/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h
index b52f3f9..b061176 100644
--- a/src/google/protobuf/stubs/time.h
+++ b/src/google/protobuf/stubs/time.h
@@ -65,10 +65,10 @@
 // value.
 //
 // Note that "nanos" must in the range of [0, 999999999].
-string PROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos);
+std::string PROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos);
 // Parses a time string. This method accepts RFC3339 date/time string with UTC
 // offset. For example, "2015-05-20T13:29:35.120-08:00".
-bool PROTOBUF_EXPORT ParseTime(const string& value, int64* seconds,
+bool PROTOBUF_EXPORT ParseTime(const std::string& value, int64* seconds,
                                int32* nanos);
 
 }  // namespace internal
diff --git a/src/google/protobuf/stubs/time_test.cc b/src/google/protobuf/stubs/time_test.cc
index fc72925..1ce0a1c 100644
--- a/src/google/protobuf/stubs/time_test.cc
+++ b/src/google/protobuf/stubs/time_test.cc
@@ -38,7 +38,7 @@
 namespace {
 static const int64 kSecondsPerDay = 3600 * 24;
 
-// For DateTime, tests will mostly focuse on the date part because that's
+// For DateTime, tests will mostly focus on the date part because that's
 // the tricky one.
 int64 CreateTimestamp(int year, int month, int day) {
   DateTime time;
diff --git a/src/google/protobuf/test_messages_proto3.proto b/src/google/protobuf/test_messages_proto3.proto
index a10f44d..4e409dc 100644
--- a/src/google/protobuf/test_messages_proto3.proto
+++ b/src/google/protobuf/test_messages_proto3.proto
@@ -203,6 +203,7 @@
     float oneof_float = 117;
     double oneof_double = 118;
     NestedEnum oneof_enum = 119;
+    google.protobuf.NullValue oneof_null_value = 120;
   }
 
   // Well-known types
@@ -232,6 +233,7 @@
   google.protobuf.Struct optional_struct = 304;
   google.protobuf.Any optional_any = 305;
   google.protobuf.Value optional_value = 306;
+  google.protobuf.NullValue optional_null_value = 307;
 
   repeated google.protobuf.Duration repeated_duration = 311;
   repeated google.protobuf.Timestamp repeated_timestamp = 312;
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index de48c1a..819f6d8 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -1212,7 +1212,8 @@
         break;
       case NOT_NULL:
         EXPECT_TRUE(released != nullptr);
-        if (message->GetArena() == nullptr) {
+        if (Arena::InternalHelper<Message>::GetArenaForAllocation(message) ==
+            nullptr) {
           // released message must be same as sub_message if source message is
           // not on arena.
           EXPECT_EQ(&sub_message, released);
diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc
index a897fe2..e7eb60a 100644
--- a/src/google/protobuf/test_util_lite.cc
+++ b/src/google/protobuf/test_util_lite.cc
@@ -1351,7 +1351,7 @@
   std::string serialized;
   ASSERT_TRUE(message.SerializeToString(&serialized));
   EXPECT_EQ("", serialized);
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
 
   // has_blah() should initially be false for all optional fields.
   EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension_lite));
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index 7d3708e..7b62887 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -66,11 +66,12 @@
 using google::protobuf::io::win32::stat;
 #endif
 
-bool File::Exists(const string& name) {
+bool File::Exists(const std::string& name) {
   return access(name.c_str(), F_OK) == 0;
 }
 
-bool File::ReadFileToString(const string& name, string* output, bool text_mode) {
+bool File::ReadFileToString(const std::string& name, std::string* output,
+                            bool text_mode) {
   char buffer[1024];
   FILE* file = fopen(name.c_str(), text_mode ? "rt" : "rb");
   if (file == NULL) return false;
@@ -86,11 +87,12 @@
   return error == 0;
 }
 
-void File::ReadFileToStringOrDie(const string& name, string* output) {
+void File::ReadFileToStringOrDie(const std::string& name, std::string* output) {
   GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name;
 }
 
-bool File::WriteStringToFile(const string& contents, const string& name) {
+bool File::WriteStringToFile(const std::string& contents,
+                             const std::string& name) {
   FILE* file = fopen(name.c_str(), "wb");
   if (file == NULL) {
     GOOGLE_LOG(ERROR) << "fopen(" << name << ", \"wb\"): " << strerror(errno);
@@ -109,7 +111,8 @@
   return true;
 }
 
-void File::WriteStringToFileOrDie(const string& contents, const string& name) {
+void File::WriteStringToFileOrDie(const std::string& contents,
+                                  const std::string& name) {
   FILE* file = fopen(name.c_str(), "wb");
   GOOGLE_CHECK(file != NULL)
       << "fopen(" << name << ", \"wb\"): " << strerror(errno);
@@ -120,21 +123,21 @@
       << "fclose(" << name << "): " << strerror(errno);
 }
 
-bool File::CreateDir(const string& name, int mode) {
+bool File::CreateDir(const std::string& name, int mode) {
   if (!name.empty()) {
     GOOGLE_CHECK_OK(name[name.size() - 1] != '.');
   }
   return mkdir(name.c_str(), mode) == 0;
 }
 
-bool File::RecursivelyCreateDir(const string& path, int mode) {
+bool File::RecursivelyCreateDir(const std::string& path, int mode) {
   if (CreateDir(path, mode)) return true;
 
   if (Exists(path)) return false;
 
   // Try creating the parent.
-  string::size_type slashpos = path.find_last_of('/');
-  if (slashpos == string::npos) {
+  std::string::size_type slashpos = path.find_last_of('/');
+  if (slashpos == std::string::npos) {
     // No parent given.
     return false;
   }
@@ -143,8 +146,8 @@
          CreateDir(path, mode);
 }
 
-void File::DeleteRecursively(const string& name,
-                             void* dummy1, void* dummy2) {
+void File::DeleteRecursively(const std::string& name, void* dummy1,
+                             void* dummy2) {
   if (name.empty()) return;
 
   // We don't care too much about error checking here since this is only used
@@ -162,9 +165,9 @@
   }
 
   do {
-    string entry_name = find_data.cFileName;
+    std::string entry_name = find_data.cFileName;
     if (entry_name != "." && entry_name != "..") {
-      string path = name + "/" + entry_name;
+      std::string path = name + "/" + entry_name;
       if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
         DeleteRecursively(path, NULL, NULL);
         RemoveDirectoryA(path.c_str());
@@ -188,7 +191,7 @@
       while (true) {
         struct dirent* entry = readdir(dir);
         if (entry == NULL) break;
-        string entry_name = entry->d_name;
+        std::string entry_name = entry->d_name;
         if (entry_name != "." && entry_name != "..") {
           DeleteRecursively(name + "/" + entry_name, NULL, NULL);
         }
@@ -204,7 +207,7 @@
 #endif
 }
 
-bool File::ChangeWorkingDirectory(const string& new_working_directory) {
+bool File::ChangeWorkingDirectory(const std::string& new_working_directory) {
   return chdir(new_working_directory.c_str()) == 0;
 }
 
diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h
index 4598996..f18f685 100644
--- a/src/google/protobuf/testing/file.h
+++ b/src/google/protobuf/testing/file.h
@@ -46,52 +46,54 @@
 class File {
  public:
   // Check if the file exists.
-  static bool Exists(const string& name);
+  static bool Exists(const std::string& name);
 
   // Read an entire file to a string.  Return true if successful, false
   // otherwise.
-  static bool ReadFileToString(const string& name, string* output, bool text_mode = false);
+  static bool ReadFileToString(const std::string& name, std::string* output,
+                               bool text_mode = false);
 
   // Same as above, but crash on failure.
-  static void ReadFileToStringOrDie(const string& name, string* output);
+  static void ReadFileToStringOrDie(const std::string& name,
+                                    std::string* output);
 
   // Create a file and write a string to it.
-  static bool WriteStringToFile(const string& contents,
-                                const string& name);
+  static bool WriteStringToFile(const std::string& contents,
+                                const std::string& name);
 
   // Same as above, but crash on failure.
-  static void WriteStringToFileOrDie(const string& contents,
-                                     const string& name);
+  static void WriteStringToFileOrDie(const std::string& contents,
+                                     const std::string& name);
 
   // Create a directory.
-  static bool CreateDir(const string& name, int mode);
+  static bool CreateDir(const std::string& name, int mode);
 
   // Create a directory and all parent directories if necessary.
-  static bool RecursivelyCreateDir(const string& path, int mode);
+  static bool RecursivelyCreateDir(const std::string& path, int mode);
 
   // If "name" is a file, we delete it.  If it is a directory, we
   // call DeleteRecursively() for each file or directory (other than
   // dot and double-dot) within it, and then delete the directory itself.
   // The "dummy" parameters have a meaning in the original version of this
   // method but they are not used anywhere in protocol buffers.
-  static void DeleteRecursively(const string& name,
-                                void* dummy1, void* dummy2);
+  static void DeleteRecursively(const std::string& name, void* dummy1,
+                                void* dummy2);
 
   // Change working directory to given directory.
-  static bool ChangeWorkingDirectory(const string& new_working_directory);
+  static bool ChangeWorkingDirectory(const std::string& new_working_directory);
 
-  static bool GetContents(
-      const string& name, string* output, bool /*is_default*/) {
+  static bool GetContents(const std::string& name, std::string* output,
+                          bool /*is_default*/) {
     return ReadFileToString(name, output);
   }
 
-  static bool GetContentsAsText(
-      const string& name, string* output, bool /*is_default*/) {
+  static bool GetContentsAsText(const std::string& name, std::string* output,
+                                bool /*is_default*/) {
     return ReadFileToString(name, output, true);
   }
 
-  static bool SetContents(
-      const string& name, const string& contents, bool /*is_default*/) {
+  static bool SetContents(const std::string& name, const std::string& contents,
+                          bool /*is_default*/) {
     return WriteStringToFile(contents, name);
   }
 
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
index 1856971..88343f9 100644
--- a/src/google/protobuf/testing/googletest.cc
+++ b/src/google/protobuf/testing/googletest.cc
@@ -70,7 +70,7 @@
 #endif
 #endif
 
-string TestSourceDir() {
+std::string TestSourceDir() {
 #ifndef GOOGLE_THIRD_PARTY_PROTOBUF
 #ifdef GOOGLE_PROTOBUF_TEST_SOURCE_PATH
   return GOOGLE_PROTOBUF_TEST_SOURCE_PATH;
@@ -84,7 +84,7 @@
 #endif  // _MSC_VER
 
   // Look for the "src" directory.
-  string prefix = ".";
+  std::string prefix = ".";
 
   // Keep looking further up the directory tree until we find
   // src/.../descriptor.cc. It is important to look for a particular file,
@@ -107,12 +107,12 @@
 
 namespace {
 
-string GetTemporaryDirectoryName() {
+std::string GetTemporaryDirectoryName() {
   // Tests run under Bazel "should not" use /tmp. Bazel sets this environment
   // variable for tests to use instead.
   char *from_environment = getenv("TEST_TMPDIR");
   if (from_environment != NULL && from_environment[0] != '\0') {
-    return string(from_environment) + "/protobuf_tmpdir";
+    return std::string(from_environment) + "/protobuf_tmpdir";
   }
 
   // tmpnam() is generally not considered safe but we're only using it for
@@ -121,7 +121,7 @@
   char b[L_tmpnam + 1];     // HPUX multithread return 0 if s is 0
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-  string result = tmpnam(b);
+  std::string result = tmpnam(b);
 #pragma GCC diagnostic pop
 #ifdef _WIN32
   // Avoid a trailing dot by changing it to an underscore. On Win32 the names of
@@ -166,7 +166,7 @@
     }
   }
 
-  string GetTempDir() {
+  std::string GetTempDir() {
     if (name_.empty()) {
       name_ = GetTemporaryDirectoryName();
       GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno);
@@ -179,21 +179,19 @@
   }
 
  private:
-  string name_;
+  std::string name_;
 };
 
 TempDirDeleter temp_dir_deleter_;
 
 }  // namespace
 
-string TestTempDir() {
-  return temp_dir_deleter_.GetTempDir();
-}
+std::string TestTempDir() { return temp_dir_deleter_.GetTempDir(); }
 
 // TODO(kenton):  Share duplicated code below.  Too busy/lazy for now.
 
-static string stdout_capture_filename_;
-static string stderr_capture_filename_;
+static std::string stdout_capture_filename_;
+static std::string stderr_capture_filename_;
 static int original_stdout_ = -1;
 static int original_stderr_ = -1;
 
@@ -227,14 +225,14 @@
   close(fd);
 }
 
-string GetCapturedTestStdout() {
+std::string GetCapturedTestStdout() {
   GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing.";
 
   close(1);
   dup2(original_stdout_, 1);
   original_stdout_ = -1;
 
-  string result;
+  std::string result;
   File::ReadFileToStringOrDie(stdout_capture_filename_, &result);
 
   remove(stdout_capture_filename_.c_str());
@@ -242,14 +240,14 @@
   return result;
 }
 
-string GetCapturedTestStderr() {
+std::string GetCapturedTestStderr() {
   GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing.";
 
   close(2);
   dup2(original_stderr_, 2);
   original_stderr_ = -1;
 
-  string result;
+  std::string result;
   File::ReadFileToStringOrDie(stderr_capture_filename_, &result);
 
   remove(stderr_capture_filename_.c_str());
@@ -270,14 +268,14 @@
   active_log_ = NULL;
 }
 
-const std::vector<string>& ScopedMemoryLog::GetMessages(LogLevel level) {
+const std::vector<std::string>& ScopedMemoryLog::GetMessages(LogLevel level) {
   GOOGLE_CHECK(level == ERROR ||
                level == WARNING);
   return messages_[level];
 }
 
-void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename,
-                                int line, const string& message) {
+void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, int line,
+                                const std::string& message) {
   GOOGLE_CHECK(active_log_ != NULL);
   if (level == ERROR || level == WARNING) {
     active_log_->messages_[level].push_back(message);
diff --git a/src/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h
index 4e0cb83..6a0c694 100644
--- a/src/google/protobuf/testing/googletest.h
+++ b/src/google/protobuf/testing/googletest.h
@@ -49,19 +49,19 @@
 namespace protobuf {
 
 // When running unittests, get the directory containing the source code.
-string TestSourceDir();
+std::string TestSourceDir();
 
 // When running unittests, get a directory where temporary files may be
 // placed.
-string TestTempDir();
+std::string TestTempDir();
 
 // Capture all text written to stdout or stderr.
 void CaptureTestStdout();
 void CaptureTestStderr();
 
 // Stop capturing stdout or stderr and return the text captured.
-string GetCapturedTestStdout();
-string GetCapturedTestStderr();
+std::string GetCapturedTestStdout();
+std::string GetCapturedTestStderr();
 
 // For use with ScopedMemoryLog::GetMessages().  Inside Google the LogLevel
 // constants don't have the LOGLEVEL_ prefix, so the code that used
@@ -84,14 +84,14 @@
   virtual ~ScopedMemoryLog();
 
   // Fetches all messages with the given severity level.
-  const std::vector<string>& GetMessages(LogLevel error);
+  const std::vector<std::string>& GetMessages(LogLevel error);
 
  private:
-  std::map<LogLevel, std::vector<string> > messages_;
+  std::map<LogLevel, std::vector<std::string> > messages_;
   LogHandler* old_handler_;
 
   static void HandleLog(LogLevel level, const char* filename, int line,
-                        const string& message);
+                        const std::string& message);
 
   static ScopedMemoryLog* active_log_;
 
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 8f4771d..449a5a6 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -54,7 +54,6 @@
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/map_field.h>
 #include <google/protobuf/message.h>
-#include <google/protobuf/port_def.inc>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/wire_format_lite.h>
@@ -63,6 +62,10 @@
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/stl_util.h>
 
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
+#define DEBUG_STRING_SILENT_MARKER "\t "
 
 namespace google {
 namespace protobuf {
@@ -161,7 +164,7 @@
 
   const std::vector<TextFormat::ParseLocation>* locations =
       FindOrNull(locations_, field);
-  if (locations == nullptr || index >= locations->size()) {
+  if (locations == nullptr || index >= static_cast<int64>(locations->size())) {
     return TextFormat::ParseLocation();
   }
 
@@ -176,7 +179,7 @@
   }
 
   auto it = nested_.find(field);
-  if (it == nested_.end() || index >= it->second.size()) {
+  if (it == nested_.end() || index >= static_cast<int64>(it->second.size())) {
     return nullptr;
   }
 
@@ -258,6 +261,7 @@
         allow_unknown_enum_(allow_unknown_enum),
         allow_field_number_(allow_field_number),
         allow_partial_(allow_partial),
+        initial_recursion_limit_(recursion_limit),
         recursion_limit_(recursion_limit),
         had_errors_(false) {
     // For backwards-compatibility with proto1, we need to allow the 'f' suffix
@@ -285,6 +289,15 @@
     // Consume fields until we cannot do so anymore.
     while (true) {
       if (LookingAtType(io::Tokenizer::TYPE_END)) {
+        // Ensures recursion limit properly unwinded, but only for success
+        // cases. This implicitly avoids the check when `Parse` returns false
+        // via `DO(...)`.
+        GOOGLE_DCHECK(had_errors_ || recursion_limit_ == initial_recursion_limit_)
+            << "Recursion limit at end of parse should be "
+            << initial_recursion_limit_ << ", but was " << recursion_limit_
+            << ". Difference of " << initial_recursion_limit_ - recursion_limit_
+            << " stack frames not accounted for stack unwind.";
+
         return !had_errors_;
       }
 
@@ -446,8 +459,7 @@
       DO(ConsumeIdentifier(&field_name));
 
       int32 field_number;
-      if (allow_field_number_ &&
-          safe_strto32(field_name, &field_number)) {
+      if (allow_field_number_ && safe_strto32(field_name, &field_number)) {
         if (descriptor->IsExtensionNumber(field_number)) {
           field = finder_
                       ? finder_->FindExtensionByNumber(descriptor, field_number)
@@ -636,7 +648,10 @@
   bool ConsumeFieldMessage(Message* message, const Reflection* reflection,
                            const FieldDescriptor* field) {
     if (--recursion_limit_ < 0) {
-      ReportError("Message is too deep");
+      ReportError(
+          StrCat("Message is too deep, the parser exceeded the "
+                       "configured recursion limit of ",
+                       initial_recursion_limit_, "."));
       return false;
     }
     // If the parse information tree is not nullptr, create a nested one
@@ -668,12 +683,22 @@
   // Skips the whole body of a message including the beginning delimiter and
   // the ending delimiter.
   bool SkipFieldMessage() {
+    if (--recursion_limit_ < 0) {
+      ReportError(
+          StrCat("Message is too deep, the parser exceeded the "
+                       "configured recursion limit of ",
+                       initial_recursion_limit_, "."));
+      return false;
+    }
+
     std::string delimiter;
     DO(ConsumeMessageDelimiter(&delimiter));
     while (!LookingAt(">") && !LookingAt("}")) {
       DO(SkipField());
     }
     DO(Consume(delimiter));
+
+    ++recursion_limit_;
     return true;
   }
 
@@ -818,10 +843,19 @@
   }
 
   bool SkipFieldValue() {
+    if (--recursion_limit_ < 0) {
+      ReportError(
+          StrCat("Message is too deep, the parser exceeded the "
+                       "configured recursion limit of ",
+                       initial_recursion_limit_, "."));
+      return false;
+    }
+
     if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
       while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
         tokenizer_.Next();
       }
+      ++recursion_limit_;
       return true;
     }
     if (TryConsume("[")) {
@@ -836,6 +870,7 @@
         }
         DO(Consume(","));
       }
+      ++recursion_limit_;
       return true;
     }
     // Possible field values other than string:
@@ -865,6 +900,7 @@
         !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
       std::string text = tokenizer_.current().text;
       ReportError("Cannot skip field value, unexpected token: " + text);
+      ++recursion_limit_;
       return false;
     }
     // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field
@@ -879,10 +915,12 @@
       if (text != "inf" &&
           text != "infinity" && text != "nan") {
         ReportError("Invalid float number: " + text);
+        ++recursion_limit_;
         return false;
       }
     }
     tokenizer_.Next();
+    ++recursion_limit_;
     return true;
   }
 
@@ -1192,6 +1230,7 @@
   const bool allow_unknown_enum_;
   const bool allow_field_number_;
   const bool allow_partial_;
+  const int initial_recursion_limit_;
   int recursion_limit_;
   bool had_errors_;
 };
@@ -1209,6 +1248,18 @@
         buffer_size_(0),
         at_start_of_line_(true),
         failed_(false),
+        insert_silent_marker_(false),
+        indent_level_(initial_indent_level),
+        initial_indent_level_(initial_indent_level) {}
+
+  explicit TextGenerator(io::ZeroCopyOutputStream* output,
+                         bool insert_silent_marker, int initial_indent_level)
+      : output_(output),
+        buffer_(nullptr),
+        buffer_size_(0),
+        at_start_of_line_(true),
+        failed_(false),
+        insert_silent_marker_(insert_silent_marker),
         indent_level_(initial_indent_level),
         initial_indent_level_(initial_indent_level) {}
 
@@ -1271,6 +1322,22 @@
   // error.)
   bool failed() const { return failed_; }
 
+  void PrintMaybeWithMarker(StringPiece text) {
+    Print(text.data(), text.size());
+    if (ConsumeInsertSilentMarker()) {
+      PrintLiteral(DEBUG_STRING_SILENT_MARKER);
+    }
+  }
+
+  void PrintMaybeWithMarker(StringPiece text_head,
+                            StringPiece text_tail) {
+    Print(text_head.data(), text_head.size());
+    if (ConsumeInsertSilentMarker()) {
+      PrintLiteral(DEBUG_STRING_SILENT_MARKER);
+    }
+    Print(text_tail.data(), text_tail.size());
+  }
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
 
@@ -1285,7 +1352,7 @@
       if (failed_) return;
     }
 
-    while (size > buffer_size_) {
+    while (static_cast<int64>(size) > buffer_size_) {
       // Data exceeds space in the buffer.  Copy what we can and request a
       // new buffer.
       if (buffer_size_ > 0) {
@@ -1331,17 +1398,68 @@
     buffer_size_ -= size;
   }
 
+  // Return the current value of insert_silent_marker_. If it is true, set it
+  // to false as we assume that a silent marker is inserted after a call to this
+  // function.
+  bool ConsumeInsertSilentMarker() {
+    if (insert_silent_marker_) {
+      insert_silent_marker_ = false;
+      return true;
+    }
+    return false;
+  }
+
   io::ZeroCopyOutputStream* const output_;
   char* buffer_;
   int buffer_size_;
   bool at_start_of_line_;
   bool failed_;
+  // This flag is false when inserting silent marker is disabled or a silent
+  // marker has been inserted.
+  bool insert_silent_marker_;
 
   int indent_level_;
   int initial_indent_level_;
 };
 
 // ===========================================================================
+//  An internal field value printer that may insert a silent marker in
+//  DebugStrings.
+class TextFormat::Printer::DebugStringFieldValuePrinter
+    : public TextFormat::FastFieldValuePrinter {
+ public:
+  void PrintMessageStart(const Message& message, int field_index,
+                         int field_count, bool single_line_mode,
+                         BaseTextGenerator* generator) const override {
+    // This is safe as only TextGenerator is used with
+    // DebugStringFieldValuePrinter.
+    TextGenerator* text_generator = static_cast<TextGenerator*>(generator);
+    if (single_line_mode) {
+      text_generator->PrintMaybeWithMarker(" ", "{ ");
+    } else {
+      text_generator->PrintMaybeWithMarker(" ", "{\n");
+    }
+  }
+};
+
+// ===========================================================================
+//  An internal field value printer that escape UTF8 strings.
+class TextFormat::Printer::FastFieldValuePrinterUtf8Escaping
+    : public TextFormat::Printer::DebugStringFieldValuePrinter {
+ public:
+  void PrintString(const std::string& val,
+                   TextFormat::BaseTextGenerator* generator) const override {
+    generator->PrintLiteral("\"");
+    generator->PrintString(strings::Utf8SafeCEscape(val));
+    generator->PrintLiteral("\"");
+  }
+  void PrintBytes(const std::string& val,
+                  TextFormat::BaseTextGenerator* generator) const override {
+    return FastFieldValuePrinter::PrintString(val, generator);
+  }
+};
+
+// ===========================================================================
 // Implementation of the default Finder for extensions.
 TextFormat::Finder::~Finder() {}
 
@@ -1417,7 +1535,7 @@
   return MergeUsingImpl(input, output, &parser);
 }
 
-bool TextFormat::Parser::ParseFromString(const std::string& input,
+bool TextFormat::Parser::ParseFromString(ConstStringParam input,
                                          Message* output) {
   DO(CheckParseInputSize(input, error_collector_));
   io::ArrayInputStream input_stream(input.data(), input.size());
@@ -1436,7 +1554,7 @@
   return MergeUsingImpl(input, output, &parser);
 }
 
-bool TextFormat::Parser::MergeFromString(const std::string& input,
+bool TextFormat::Parser::MergeFromString(ConstStringParam input,
                                          Message* output) {
   DO(CheckParseInputSize(input, error_collector_));
   io::ArrayInputStream input_stream(input.data(), input.size());
@@ -1482,12 +1600,12 @@
   return Parser().Merge(input, output);
 }
 
-/* static */ bool TextFormat::ParseFromString(const std::string& input,
+/* static */ bool TextFormat::ParseFromString(ConstStringParam input,
                                               Message* output) {
   return Parser().ParseFromString(input, output);
 }
 
-/* static */ bool TextFormat::MergeFromString(const std::string& input,
+/* static */ bool TextFormat::MergeFromString(ConstStringParam input,
                                               Message* output) {
   return Parser().MergeFromString(input, output);
 }
@@ -1510,9 +1628,9 @@
 
 // Some compilers do not support ref-qualifiers even in C++11 mode.
 // Disable the optimization for now and revisit it later.
-#if 0   // LANG_CXX11
+#if 0  // LANG_CXX11
   std::string Consume() && { return std::move(output_); }
-#else   // !LANG_CXX11
+#else  // !LANG_CXX11
   const std::string& Get() { return output_; }
 #endif  // LANG_CXX11
 
@@ -1770,29 +1888,17 @@
   std::unique_ptr<const TextFormat::FieldValuePrinter> delegate_;
 };
 
-// Our own specialization: for UTF8 escaped strings.
-class FastFieldValuePrinterUtf8Escaping
-    : public TextFormat::FastFieldValuePrinter {
- public:
-  void PrintString(const std::string& val,
-                   TextFormat::BaseTextGenerator* generator) const override {
-    generator->PrintLiteral("\"");
-    generator->PrintString(strings::Utf8SafeCEscape(val));
-    generator->PrintLiteral("\"");
-  }
-  void PrintBytes(const std::string& val,
-                  TextFormat::BaseTextGenerator* generator) const override {
-    return FastFieldValuePrinter::PrintString(val, generator);
-  }
-};
-
 }  // namespace
 
+const char* const TextFormat::Printer::kDoNotParse =
+    "DO NOT PARSE: fields may be stripped and missing.\n";
+
 TextFormat::Printer::Printer()
     : initial_indent_level_(0),
       single_line_mode_(false),
       use_field_number_(false),
       use_short_repeated_primitives_(false),
+      insert_silent_marker_(false),
       hide_unknown_fields_(false),
       print_message_fields_in_index_order_(false),
       expand_any_(false),
@@ -1803,7 +1909,7 @@
 
 void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) {
   SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping()
-                                      : new FastFieldValuePrinter());
+                                      : new DebugStringFieldValuePrinter());
 }
 
 void TextFormat::Printer::SetDefaultFieldValuePrinter(
@@ -1883,7 +1989,7 @@
 
 bool TextFormat::Printer::Print(const Message& message,
                                 io::ZeroCopyOutputStream* output) const {
-  TextGenerator generator(output, initial_indent_level_);
+  TextGenerator generator(output, insert_silent_marker_, initial_indent_level_);
 
   Print(message, &generator);
 
@@ -2004,14 +2110,17 @@
     fields.push_back(descriptor->field(0));
     fields.push_back(descriptor->field(1));
   } else {
-    reflection->ListFields(message, &fields);
+    reflection->ListFieldsOmitStripped(message, &fields);
+    if (reflection->IsMessageStripped(message.GetDescriptor())) {
+      generator->Print(kDoNotParse, std::strlen(kDoNotParse));
+    }
   }
 
   if (print_message_fields_in_index_order_) {
     std::sort(fields.begin(), fields.end(), FieldIndexSorter());
   }
-  for (int i = 0; i < fields.size(); i++) {
-    PrintField(message, reflection, fields[i], generator);
+  for (const FieldDescriptor* field : fields) {
+    PrintField(message, reflection, field, generator);
   }
   if (!hide_unknown_fields_) {
     PrintUnknownFields(reflection->GetUnknownFields(message), generator,
@@ -2086,7 +2195,7 @@
   // DynamicMapSorter::Sort cannot be used because it enfores syncing with
   // repeated field.
   static bool SortMap(const Message& message, const Reflection* reflection,
-                      const FieldDescriptor* field, MessageFactory* factory,
+                      const FieldDescriptor* field,
                       std::vector<const Message*>* sorted_map_field);
   static void CopyKey(const MapKey& key, Message* message,
                       const FieldDescriptor* field_desc);
@@ -2097,7 +2206,7 @@
 // Returns true if elements contained in sorted_map_field need to be released.
 bool MapFieldPrinterHelper::SortMap(
     const Message& message, const Reflection* reflection,
-    const FieldDescriptor* field, MessageFactory* factory,
+    const FieldDescriptor* field,
     std::vector<const Message*>* sorted_map_field) {
   bool need_release = false;
   const MapFieldBase& base = *reflection->GetMapData(message, field);
@@ -2113,7 +2222,8 @@
     // TODO(teboring): For performance, instead of creating map entry message
     // for each element, just store map keys and sort them.
     const Descriptor* map_entry_desc = field->message_type();
-    const Message* prototype = factory->GetPrototype(map_entry_desc);
+    const Message* prototype =
+        reflection->GetMessageFactory()->GetPrototype(map_entry_desc);
     for (MapIterator iter =
              reflection->MapBegin(const_cast<Message*>(&message), field);
          iter != reflection->MapEnd(const_cast<Message*>(&message), field);
@@ -2226,13 +2336,12 @@
     count = 1;
   }
 
-  DynamicMessageFactory factory;
   std::vector<const Message*> sorted_map_field;
   bool need_release = false;
   bool is_map = field->is_map();
   if (is_map) {
     need_release = internal::MapFieldPrinterHelper::SortMap(
-        message, reflection, field, &factory, &sorted_map_field);
+        message, reflection, field, &sorted_map_field);
   }
 
   for (int j = 0; j < count; ++j) {
@@ -2258,7 +2367,7 @@
       printer->PrintMessageEnd(sub_message, field_index, count,
                                single_line_mode_, generator);
     } else {
-      generator->PrintLiteral(": ");
+      generator->PrintMaybeWithMarker(": ");
       // Write the field value.
       PrintFieldValue(message, reflection, field, field_index, generator);
       if (single_line_mode_) {
@@ -2270,8 +2379,8 @@
   }
 
   if (need_release) {
-    for (int j = 0; j < sorted_map_field.size(); ++j) {
-      delete sorted_map_field[j];
+    for (const Message* message_to_delete : sorted_map_field) {
+      delete message_to_delete;
     }
   }
 }
@@ -2283,7 +2392,7 @@
   int size = reflection->FieldSize(message, field);
   PrintFieldName(message, /*field_index=*/-1, /*field_count=*/size, reflection,
                  field, generator);
-  generator->PrintLiteral(": [");
+  generator->PrintMaybeWithMarker(": ", "[");
   for (int i = 0; i < size; i++) {
     if (i > 0) generator->PrintLiteral(", ");
     PrintFieldValue(message, reflection, field, i, generator);
@@ -2351,7 +2460,8 @@
       const std::string* value_to_print = &value;
       std::string truncated_value;
       if (truncate_string_field_longer_than_ > 0 &&
-          truncate_string_field_longer_than_ < value.size()) {
+          static_cast<size_t>(truncate_string_field_longer_than_) <
+              value.size()) {
         truncated_value = value.substr(0, truncate_string_field_longer_than_) +
                           "...<truncated>...";
         value_to_print = &truncated_value;
@@ -2436,7 +2546,7 @@
     switch (field.type()) {
       case UnknownField::TYPE_VARINT:
         generator->PrintString(field_number);
-        generator->PrintLiteral(": ");
+        generator->PrintMaybeWithMarker(": ");
         generator->PrintString(StrCat(field.varint()));
         if (single_line_mode_) {
           generator->PrintLiteral(" ");
@@ -2446,7 +2556,7 @@
         break;
       case UnknownField::TYPE_FIXED32: {
         generator->PrintString(field_number);
-        generator->PrintLiteral(": 0x");
+        generator->PrintMaybeWithMarker(": ", "0x");
         generator->PrintString(
             StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8)));
         if (single_line_mode_) {
@@ -2458,7 +2568,7 @@
       }
       case UnknownField::TYPE_FIXED64: {
         generator->PrintString(field_number);
-        generator->PrintLiteral(": 0x");
+        generator->PrintMaybeWithMarker(": ", "0x");
         generator->PrintString(
             StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16)));
         if (single_line_mode_) {
@@ -2483,9 +2593,9 @@
           // This field is parseable as a Message.
           // So it is probably an embedded message.
           if (single_line_mode_) {
-            generator->PrintLiteral(" { ");
+            generator->PrintMaybeWithMarker(" ", "{ ");
           } else {
-            generator->PrintLiteral(" {\n");
+            generator->PrintMaybeWithMarker(" ", "{\n");
             generator->Indent();
           }
           PrintUnknownFields(embedded_unknown_fields, generator,
@@ -2499,7 +2609,7 @@
         } else {
           // This field is not parseable as a Message (or we ran out of
           // recursion budget). So it is probably just a plain string.
-          generator->PrintLiteral(": \"");
+          generator->PrintMaybeWithMarker(": ", "\"");
           generator->PrintString(CEscape(value));
           if (single_line_mode_) {
             generator->PrintLiteral("\" ");
@@ -2512,9 +2622,9 @@
       case UnknownField::TYPE_GROUP:
         generator->PrintString(field_number);
         if (single_line_mode_) {
-          generator->PrintLiteral(" { ");
+          generator->PrintMaybeWithMarker(" ", "{ ");
         } else {
-          generator->PrintLiteral(" {\n");
+          generator->PrintMaybeWithMarker(" ", "{\n");
           generator->Indent();
         }
         // For groups, we recurse without checking the budget. This is OK,
@@ -2534,3 +2644,5 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 26c4afb..ce4d1f4 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -62,9 +62,9 @@
 class ErrorCollector;  // tokenizer.h
 }
 
-// This class implements protocol buffer text format.  Printing and parsing
-// protocol messages in text format is useful for debugging and human editing
-// of messages.
+// This class implements protocol buffer text format, colloquially known as text
+// proto.  Printing and parsing protocol messages in text format is useful for
+// debugging and human editing of messages.
 //
 // This class is really a namespace that contains only static methods.
 class PROTOBUF_EXPORT TextFormat {
@@ -369,6 +369,16 @@
     // output to the OutputStream (see text_format.cc for implementation).
     class TextGenerator;
 
+    // Forward declaration of an internal class used to print field values for
+    // DebugString APIs (see text_format.cc for implementation).
+    class DebugStringFieldValuePrinter;
+
+    // Forward declaration of an internal class used to print UTF-8 escaped
+    // strings (see text_format.cc for implementation).
+    class FastFieldValuePrinterUtf8Escaping;
+
+    static const char* const kDoNotParse;
+
     // Internal Print method, used for writing to the OutputStream via
     // the TextGenerator class.
     void Print(const Message& message, TextGenerator* generator) const;
@@ -417,6 +427,7 @@
     bool single_line_mode_;
     bool use_field_number_;
     bool use_short_repeated_primitives_;
+    bool insert_silent_marker_;
     bool hide_unknown_fields_;
     bool print_message_fields_in_index_order_;
     bool expand_any_;
@@ -452,13 +463,13 @@
   // google::protobuf::MessageLite::ParseFromString().
   static bool Parse(io::ZeroCopyInputStream* input, Message* output);
   // Like Parse(), but reads directly from a string.
-  static bool ParseFromString(const std::string& input, Message* output);
+  static bool ParseFromString(ConstStringParam input, Message* output);
 
   // Like Parse(), but the data is merged into the given message, as if
   // using Message::MergeFrom().
   static bool Merge(io::ZeroCopyInputStream* input, Message* output);
   // Like Merge(), but reads directly from a string.
-  static bool MergeFromString(const std::string& input, Message* output);
+  static bool MergeFromString(ConstStringParam input, Message* output);
 
   // Parse the given text as a single field value and store it into the
   // given field of the given message. If the field is a repeated field,
@@ -529,11 +540,11 @@
     // Like TextFormat::Parse().
     bool Parse(io::ZeroCopyInputStream* input, Message* output);
     // Like TextFormat::ParseFromString().
-    bool ParseFromString(const std::string& input, Message* output);
+    bool ParseFromString(ConstStringParam input, Message* output);
     // Like TextFormat::Merge().
     bool Merge(io::ZeroCopyInputStream* input, Message* output);
     // Like TextFormat::MergeFromString().
-    bool MergeFromString(const std::string& input, Message* output);
+    bool MergeFromString(ConstStringParam input, Message* output);
 
     // Set where to report parse errors.  If NULL (the default), errors will
     // be printed to stderr.
@@ -567,16 +578,22 @@
                                    const FieldDescriptor* field,
                                    Message* output);
 
-    // When an unknown extension is met, parsing will fail if this option is set
-    // to false (the default). If true, unknown extensions will be ignored and
-    // a warning message will be generated.
+    // When an unknown extension is met, parsing will fail if this option is
+    // set to false (the default). If true, unknown extensions will be ignored
+    // and a warning message will be generated.
+    // Beware! Setting this option true may hide some errors (e.g. spelling
+    // error on extension name).  This allows data loss; unlike binary format,
+    // text format cannot preserve unknown extensions.  Avoid using this option
+    // if possible.
     void AllowUnknownExtension(bool allow) { allow_unknown_extension_ = allow; }
 
     // When an unknown field is met, parsing will fail if this option is set
-    // to false(the default). If true, unknown fields will be ignored and
+    // to false (the default). If true, unknown fields will be ignored and
     // a warning message will be generated.
-    // Please aware that set this option true may hide some errors (e.g.
-    // spelling error on field name). Avoid to use this option if possible.
+    // Beware! Setting this option true may hide some errors (e.g. spelling
+    // error on field name). This allows data loss; unlike binary format, text
+    // format cannot preserve unknown fields.  Avoid using this option
+    // if possible.
     void AllowUnknownField(bool allow) { allow_unknown_field_ = allow; }
 
 
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 72a2e6d..cedc928 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -42,7 +42,6 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/file.h>
 #include <google/protobuf/map_unittest.pb.h>
@@ -55,9 +54,11 @@
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
+#include <gmock/gmock.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/substitute.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -346,14 +347,13 @@
   UnknownFieldSet unknown_fields;
   EXPECT_TRUE(unknown_fields.ParseFromString(data));
   EXPECT_TRUE(TextFormat::PrintUnknownFieldsToString(unknown_fields, &text));
-  EXPECT_EQ(
-      "44: \"abc\"\n"
-      "44: \"def\"\n"
-      "44: \"\"\n"
-      "48 {\n"
-      "  1: 123\n"
-      "}\n",
-      text);
+  // Field 44 and 48 can be printed in any order.
+  EXPECT_THAT(text, testing::HasSubstr("44: \"abc\"\n"
+                                       "44: \"def\"\n"
+                                       "44: \"\"\n"));
+  EXPECT_THAT(text, testing::HasSubstr("48 {\n"
+                                       "  1: 123\n"
+                                       "}\n"));
 }
 
 TEST_F(TextFormatTest, PrintDeeplyNestedUnknownMessage) {
@@ -718,7 +718,7 @@
       text);
 }
 
-// Print strings into multiple line, with indention. Use this to test
+// Print strings into multiple line, with indentation. Use this to test
 // BaseTextGenerator::Indent and BaseTextGenerator::Outdent.
 class MultilineStringPrinter : public TextFormat::FastFieldValuePrinter {
  public:
@@ -1069,13 +1069,8 @@
 TEST_F(TextFormatTest, PrintExotic) {
   unittest::TestAllTypes message;
 
-  // Note:  In C, a negative integer literal is actually the unary negation
-  //   operator being applied to a positive integer literal, and
-  //   9223372036854775808 is outside the range of int64.  However, it is not
-  //   outside the range of uint64.  Confusingly, this means that everything
-  //   works if we make the literal unsigned, even though we are negating it.
-  message.add_repeated_int64(-PROTOBUF_ULONGLONG(9223372036854775808));
-  message.add_repeated_uint64(PROTOBUF_ULONGLONG(18446744073709551615));
+  message.add_repeated_int64(int64_t{-9223372036854775807} - 1);
+  message.add_repeated_uint64(uint64_t{18446744073709551615u});
   message.add_repeated_double(123.456);
   message.add_repeated_double(1.23e21);
   message.add_repeated_double(1.23e-18);
@@ -1240,32 +1235,19 @@
 
   ASSERT_EQ(2, message.repeated_int32_size());
   EXPECT_EQ(-1, message.repeated_int32(0));
-  // Note:  In C, a negative integer literal is actually the unary negation
-  //   operator being applied to a positive integer literal, and 2147483648 is
-  //   outside the range of int32.  However, it is not outside the range of
-  //   uint32.  Confusingly, this means that everything works if we make the
-  //   literal unsigned, even though we are negating it.
-  EXPECT_EQ(-2147483648u, message.repeated_int32(1));
+  EXPECT_EQ(-2147483648, message.repeated_int32(1));
 
   ASSERT_EQ(2, message.repeated_int64_size());
   EXPECT_EQ(-1, message.repeated_int64(0));
-  // Note:  In C, a negative integer literal is actually the unary negation
-  //   operator being applied to a positive integer literal, and
-  //   9223372036854775808 is outside the range of int64.  However, it is not
-  //   outside the range of uint64.  Confusingly, this means that everything
-  //   works if we make the literal unsigned, even though we are negating it.
-  EXPECT_EQ(-PROTOBUF_ULONGLONG(9223372036854775808),
-            message.repeated_int64(1));
+  EXPECT_EQ(int64_t{-9223372036854775807} - 1, message.repeated_int64(1));
 
   ASSERT_EQ(2, message.repeated_uint32_size());
   EXPECT_EQ(4294967295u, message.repeated_uint32(0));
   EXPECT_EQ(2147483648u, message.repeated_uint32(1));
 
   ASSERT_EQ(2, message.repeated_uint64_size());
-  EXPECT_EQ(PROTOBUF_ULONGLONG(18446744073709551615),
-            message.repeated_uint64(0));
-  EXPECT_EQ(PROTOBUF_ULONGLONG(9223372036854775808),
-            message.repeated_uint64(1));
+  EXPECT_EQ(uint64_t{18446744073709551615u}, message.repeated_uint64(0));
+  EXPECT_EQ(uint64_t{9223372036854775808u}, message.repeated_uint64(1));
 
   ASSERT_EQ(13, message.repeated_double_size());
   EXPECT_EQ(123.0, message.repeated_double(0));
@@ -1409,9 +1391,8 @@
     parser_.RecordErrorsTo(&error_collector);
     EXPECT_EQ(expected_result, parser_.ParseFromString(input, proto))
         << input << " -> " << proto->DebugString();
-    EXPECT_EQ(
-        StrCat(line) + ":" + StrCat(col) + ": " + message + "\n",
-        error_collector.text_);
+    EXPECT_EQ(StrCat(line, ":", col, ": ", message, "\n"),
+              error_collector.text_);
     parser_.RecordErrorsTo(nullptr);
   }
 
@@ -1911,7 +1892,58 @@
 
   input = strings::Substitute(format, input);
   parser_.SetRecursionLimit(100);
-  ExpectMessage(input, "Message is too deep", 1, 908, &message, false);
+  ExpectMessage(input,
+                "Message is too deep, the parser exceeded the configured "
+                "recursion limit of 100.",
+                1, 908, &message, false);
+
+  parser_.SetRecursionLimit(101);
+  ExpectSuccessAndTree(input, &message, nullptr);
+}
+
+TEST_F(TextFormatParserTest, SetRecursionLimitUnknownFieldValue) {
+  const char* format = "[$0]";
+  std::string input = "\"test_value\"";
+  for (int i = 0; i < 99; ++i) input = strings::Substitute(format, input);
+  std::string not_deep_input = StrCat("unknown_nested_array: ", input);
+
+  parser_.AllowUnknownField(true);
+  parser_.SetRecursionLimit(100);
+
+  unittest::NestedTestAllTypes message;
+  ExpectSuccessAndTree(not_deep_input, &message, nullptr);
+
+  input = strings::Substitute(format, input);
+  std::string deep_input = StrCat("unknown_nested_array: ", input);
+  ExpectMessage(
+      deep_input,
+      "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no "
+      "field named \"unknown_nested_array\".\n1:123: Message is too deep, the "
+      "parser exceeded the configured recursion limit of 100.",
+      1, 21, &message, false);
+
+  parser_.SetRecursionLimit(101);
+  ExpectSuccessAndTree(deep_input, &message, nullptr);
+}
+
+TEST_F(TextFormatParserTest, SetRecursionLimitUnknownFieldMessage) {
+  const char* format = "unknown_child: { $0 }";
+  std::string input;
+  for (int i = 0; i < 100; ++i) input = strings::Substitute(format, input);
+
+  parser_.AllowUnknownField(true);
+  parser_.SetRecursionLimit(100);
+
+  unittest::NestedTestAllTypes message;
+  ExpectSuccessAndTree(input, &message, nullptr);
+
+  input = strings::Substitute(format, input);
+  ExpectMessage(
+      input,
+      "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no "
+      "field named \"unknown_child\".\n1:1716: Message is too deep, the parser "
+      "exceeded the configured recursion limit of 100.",
+      1, 14, &message, false);
 
   parser_.SetRecursionLimit(101);
   ExpectSuccessAndTree(input, &message, nullptr);
@@ -2005,7 +2037,7 @@
                              "  }\n"
                              ">",
                              &proto));
-  // Unmatched delimeters for message body
+  // Unmatched delimiters for message body
   EXPECT_FALSE(parser.ParseFromString("unknown_message: {>", &proto));
   // Unknown extension
   EXPECT_TRUE(
@@ -2110,3 +2142,5 @@
 }  // namespace text_format_unittest
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 8b27210..f87380c 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -14,26 +14,23 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class TimestampDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Timestamp> _instance;
-} _Timestamp_default_instance_;
+constexpr Timestamp::Timestamp(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : seconds_(int64_t{0})
+  , nanos_(0){}
+struct TimestampDefaultTypeInternal {
+  constexpr TimestampDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~TimestampDefaultTypeInternal() {}
+  union {
+    Timestamp _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT TimestampDefaultTypeInternal _Timestamp_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Timestamp();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Timestamp::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
@@ -58,40 +55,39 @@
 const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
   "\n\037google/protobuf/timestamp.proto\022\017googl"
   "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003"
-  "\022\r\n\005nanos\030\002 \001(\005B~\n\023com.google.protobufB\016"
-  "TimestampProtoP\001Z+github.com/golang/prot"
-  "obuf/ptypes/timestamp\370\001\001\242\002\003GPB\252\002\036Google."
-  "Protobuf.WellKnownTypesb\006proto3"
+  "\022\r\n\005nanos\030\002 \001(\005B\205\001\n\023com.google.protobufB"
+  "\016TimestampProtoP\001Z2google.golang.org/pro"
+  "tobuf/types/known/timestamppb\370\001\001\242\002\003GPB\252\002"
+  "\036Google.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_sccs[1] = {
-  &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto, "google/protobuf/timestamp.proto", 231,
-  &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once, descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_sccs, descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_deps, 1, 0,
+  false, false, 239, descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto, "google/protobuf/timestamp.proto", 
+  &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
+  file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2ftimestamp_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftimestamp_2eproto(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void Timestamp::InitAsDefaultInstance() {
-}
 class Timestamp::_Internal {
  public:
 };
 
-Timestamp::Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Timestamp::Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp)
 }
 Timestamp::Timestamp(const Timestamp& from)
@@ -103,20 +99,22 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Timestamp)
 }
 
-void Timestamp::SharedCtor() {
-  ::memset(&seconds_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&nanos_) -
-      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
+inline void Timestamp::SharedCtor() {
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
+    reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
 }
 
 Timestamp::~Timestamp() {
   // @@protoc_insertion_point(destructor:google.protobuf.Timestamp)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Timestamp::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Timestamp::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void Timestamp::ArenaDtor(void* object) {
@@ -128,11 +126,6 @@
 void Timestamp::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Timestamp& Timestamp::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Timestamp::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp)
@@ -148,11 +141,9 @@
 
 const char* Timestamp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1:
@@ -170,7 +161,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -197,13 +189,13 @@
   (void) cached_has_bits;
 
   // int64 seconds = 1;
-  if (this->seconds() != 0) {
+  if (this->_internal_seconds() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->_internal_seconds(), target);
   }
 
   // int32 nanos = 2;
-  if (this->nanos() != 0) {
+  if (this->_internal_nanos() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_nanos(), target);
   }
@@ -225,14 +217,14 @@
   (void) cached_has_bits;
 
   // int64 seconds = 1;
-  if (this->seconds() != 0) {
+  if (this->_internal_seconds() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size(
         this->_internal_seconds());
   }
 
   // int32 nanos = 2;
-  if (this->nanos() != 0) {
+  if (this->_internal_nanos() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
         this->_internal_nanos());
@@ -247,41 +239,32 @@
   return total_size;
 }
 
-void Timestamp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Timestamp* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Timestamp>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Timestamp)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Timestamp)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Timestamp::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Timestamp::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Timestamp::GetClassData() const { return &_class_data_; }
+
+void Timestamp::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Timestamp *>(to)->MergeFrom(
+      static_cast<const Timestamp &>(from));
 }
 
+
 void Timestamp::MergeFrom(const Timestamp& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.seconds() != 0) {
+  if (from._internal_seconds() != 0) {
     _internal_set_seconds(from._internal_seconds());
   }
-  if (from.nanos() != 0) {
+  if (from._internal_nanos() != 0) {
     _internal_set_nanos(from._internal_nanos());
   }
-}
-
-void Timestamp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Timestamp)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Timestamp::CopyFrom(const Timestamp& from) {
@@ -297,7 +280,7 @@
 
 void Timestamp::InternalSwap(Timestamp* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Timestamp, nanos_)
       + sizeof(Timestamp::nanos_)
@@ -307,10 +290,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Timestamp::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index 84c7440..8ea03e2 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -45,7 +44,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftimestamp_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -53,10 +52,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class Timestamp;
-class TimestampDefaultTypeInternal;
+struct TimestampDefaultTypeInternal;
 PROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -66,11 +65,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT Timestamp PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Timestamp final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ {
  public:
-  inline Timestamp() : Timestamp(nullptr) {};
-  virtual ~Timestamp();
+  inline Timestamp() : Timestamp(nullptr) {}
+  ~Timestamp() override;
+  explicit constexpr Timestamp(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Timestamp(const Timestamp& from);
   Timestamp(Timestamp&& from) noexcept
@@ -83,8 +83,9 @@
     return *this;
   }
   inline Timestamp& operator=(Timestamp&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -95,14 +96,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Timestamp& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Timestamp& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Timestamp* internal_default_instance() {
     return reinterpret_cast<const Timestamp*>(
                &_Timestamp_default_instance_);
@@ -115,7 +116,7 @@
   }
   inline void Swap(Timestamp* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -123,23 +124,26 @@
   }
   void UnsafeArenaSwap(Timestamp* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Timestamp* New() const final {
-    return CreateMaybeMessage<Timestamp>(nullptr);
+    return new Timestamp();
   }
 
   Timestamp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Timestamp>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Timestamp& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Timestamp& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -150,8 +154,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Timestamp* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -159,20 +163,17 @@
     return "google.protobuf.Timestamp";
   }
   protected:
-  explicit Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -225,7 +226,7 @@
 
 // int64 seconds = 1;
 inline void Timestamp::clear_seconds() {
-  seconds_ = PROTOBUF_LONGLONG(0);
+  seconds_ = int64_t{0};
 }
 inline ::PROTOBUF_NAMESPACE_ID::int64 Timestamp::_internal_seconds() const {
   return seconds_;
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
index cd35786..3b2df6d 100644
--- a/src/google/protobuf/timestamp.proto
+++ b/src/google/protobuf/timestamp.proto
@@ -34,7 +34,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
-option go_package = "github.com/golang/protobuf/ptypes/timestamp";
+option go_package = "google.golang.org/protobuf/types/known/timestamppb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "TimestampProto";
 option java_multiple_files = true;
@@ -91,7 +91,16 @@
 //         .setNanos((int) ((millis % 1000) * 1000000)).build();
 //
 //
-// Example 5: Compute Timestamp from current time in Python.
+// Example 5: Compute Timestamp from Java `Instant.now()`.
+//
+//     Instant now = Instant.now();
+//
+//     Timestamp timestamp =
+//         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
+//             .setNanos(now.getNano()).build();
+//
+//
+// Example 6: Compute Timestamp from current time in Python.
 //
 //     timestamp = Timestamp()
 //     timestamp.GetCurrentTime()
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 8da70ec..06d8d7d 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -14,112 +14,95 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Field_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto;
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class TypeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Type> _instance;
-} _Type_default_instance_;
-class FieldDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Field> _instance;
-} _Field_default_instance_;
-class EnumDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Enum> _instance;
-} _Enum_default_instance_;
-class EnumValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumValue> _instance;
-} _EnumValue_default_instance_;
-class OptionDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Option> _instance;
-} _Option_default_instance_;
+constexpr Type::Type(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : fields_()
+  , oneofs_()
+  , options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , source_context_(nullptr)
+  , syntax_(0)
+{}
+struct TypeDefaultTypeInternal {
+  constexpr TypeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~TypeDefaultTypeInternal() {}
+  union {
+    Type _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT TypeDefaultTypeInternal _Type_default_instance_;
+constexpr Field::Field(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , json_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , default_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , kind_(0)
+
+  , cardinality_(0)
+
+  , number_(0)
+  , oneof_index_(0)
+  , packed_(false){}
+struct FieldDefaultTypeInternal {
+  constexpr FieldDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldDefaultTypeInternal() {}
+  union {
+    Field _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldDefaultTypeInternal _Field_default_instance_;
+constexpr Enum::Enum(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : enumvalue_()
+  , options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , source_context_(nullptr)
+  , syntax_(0)
+{}
+struct EnumDefaultTypeInternal {
+  constexpr EnumDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumDefaultTypeInternal() {}
+  union {
+    Enum _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumDefaultTypeInternal _Enum_default_instance_;
+constexpr EnumValue::EnumValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , number_(0){}
+struct EnumValueDefaultTypeInternal {
+  constexpr EnumValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumValueDefaultTypeInternal() {}
+  union {
+    EnumValue _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumValueDefaultTypeInternal _EnumValue_default_instance_;
+constexpr Option::Option(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , value_(nullptr){}
+struct OptionDefaultTypeInternal {
+  constexpr OptionDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~OptionDefaultTypeInternal() {}
+  union {
+    Option _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT OptionDefaultTypeInternal _Option_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Enum_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Enum_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Enum();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Enum::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Enum_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 3, 0, InitDefaultsscc_info_Enum_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumValue_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::EnumValue::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumValue_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
-
-static void InitDefaultsscc_info_Field_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Field_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Field();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Field::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Field_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Field_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
-
-static void InitDefaultsscc_info_Option_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Option_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Option();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Option::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Option_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Any_google_2fprotobuf_2fany_2eproto.base,}};
-
-static void InitDefaultsscc_info_Type_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Type_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Type();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Type::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Type_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 3, 0, InitDefaultsscc_info_Type_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Field_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ftype_2eproto[5];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[3];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto = nullptr;
@@ -230,32 +213,28 @@
   "\003 \003(\0132\027.google.protobuf.Option\";\n\006Option"
   "\022\014\n\004name\030\001 \001(\t\022#\n\005value\030\002 \001(\0132\024.google.p"
   "rotobuf.Any*.\n\006Syntax\022\021\n\rSYNTAX_PROTO2\020\000"
-  "\022\021\n\rSYNTAX_PROTO3\020\001B}\n\023com.google.protob"
-  "ufB\tTypeProtoP\001Z/google.golang.org/genpr"
-  "oto/protobuf/ptype;ptype\370\001\001\242\002\003GPB\252\002\036Goog"
-  "le.Protobuf.WellKnownTypesb\006proto3"
+  "\022\021\n\rSYNTAX_PROTO3\020\001B{\n\023com.google.protob"
+  "ufB\tTypeProtoP\001Z-google.golang.org/proto"
+  "buf/types/known/typepb\370\001\001\242\002\003GPB\252\002\036Google"
+  ".Protobuf.WellKnownTypesb\006proto3"
   ;
 static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2ftype_2eproto_deps[2] = {
   &::descriptor_table_google_2fprotobuf_2fany_2eproto,
   &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2ftype_2eproto_sccs[5] = {
-  &scc_info_Enum_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_Field_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_Type_google_2fprotobuf_2ftype_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ftype_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto, "google/protobuf/type.proto", 1594,
-  &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, descriptor_table_google_2fprotobuf_2ftype_2eproto_sccs, descriptor_table_google_2fprotobuf_2ftype_2eproto_deps, 5, 2,
+  false, false, 1592, descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto, "google/protobuf/type.proto", 
+  &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, descriptor_table_google_2fprotobuf_2ftype_2eproto_deps, 2, 5,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftype_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2ftype_2eproto, 5, file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto,
+  file_level_metadata_google_2fprotobuf_2ftype_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2ftype_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2ftype_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2ftype_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftype_2eproto(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Kind_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
@@ -354,10 +333,6 @@
 
 // ===================================================================
 
-void Type::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_Type_default_instance_._instance.get_mutable()->source_context_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceContext*>(
-      PROTOBUF_NAMESPACE_ID::SourceContext::internal_default_instance());
-}
 class Type::_Internal {
  public:
   static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Type* msg);
@@ -368,18 +343,21 @@
   return *msg->source_context_;
 }
 void Type::clear_source_context() {
-  if (GetArena() == nullptr && source_context_ != nullptr) {
+  if (GetArenaForAllocation() == nullptr && source_context_ != nullptr) {
     delete source_context_;
   }
   source_context_ = nullptr;
 }
-Type::Type(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+Type::Type(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   fields_(arena),
   oneofs_(arena),
   options_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Type)
 }
 Type::Type(const Type& from)
@@ -390,8 +368,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_source_context()) {
     source_context_ = new PROTOBUF_NAMESPACE_ID::SourceContext(*from.source_context_);
@@ -402,22 +380,23 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Type)
 }
 
-void Type::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Type_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&source_context_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
+inline void Type::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
 }
 
 Type::~Type() {
   // @@protoc_insertion_point(destructor:google.protobuf.Type)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Type::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Type::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete source_context_;
 }
@@ -431,11 +410,6 @@
 void Type::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Type& Type::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Type_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Type::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Type)
@@ -446,8 +420,8 @@
   fields_.Clear();
   oneofs_.Clear();
   options_.Clear();
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  if (GetArena() == nullptr && source_context_ != nullptr) {
+  name_.ClearToEmpty();
+  if (GetArenaForAllocation() == nullptr && source_context_ != nullptr) {
     delete source_context_;
   }
   source_context_ = nullptr;
@@ -457,11 +431,9 @@
 
 const char* Type::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -527,7 +499,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -554,7 +527,7 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -590,7 +563,7 @@
   }
 
   // .google.protobuf.SourceContext source_context = 5;
-  if (this->has_source_context()) {
+  if (this->_internal_has_source_context()) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(
@@ -598,7 +571,7 @@
   }
 
   // .google.protobuf.Syntax syntax = 6;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
       6, this->_internal_syntax(), target);
@@ -643,21 +616,21 @@
   }
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // .google.protobuf.SourceContext source_context = 5;
-  if (this->has_source_context()) {
+  if (this->_internal_has_source_context()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
         *source_context_);
   }
 
   // .google.protobuf.Syntax syntax = 6;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax());
   }
@@ -671,47 +644,38 @@
   return total_size;
 }
 
-void Type::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Type)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Type* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Type>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Type)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Type)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Type::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Type::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Type::GetClassData() const { return &_class_data_; }
+
+void Type::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Type *>(to)->MergeFrom(
+      static_cast<const Type &>(from));
 }
 
+
 void Type::MergeFrom(const Type& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   fields_.MergeFrom(from.fields_);
   oneofs_.MergeFrom(from.oneofs_);
   options_.MergeFrom(from.options_);
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.has_source_context()) {
+  if (from._internal_has_source_context()) {
     _internal_mutable_source_context()->PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom(from._internal_source_context());
   }
-  if (from.syntax() != 0) {
+  if (from._internal_syntax() != 0) {
     _internal_set_syntax(from._internal_syntax());
   }
-}
-
-void Type::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Type)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Type::CopyFrom(const Type& from) {
@@ -727,11 +691,15 @@
 
 void Type::InternalSwap(Type* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   fields_.InternalSwap(&other->fields_);
   oneofs_.InternalSwap(&other->oneofs_);
   options_.InternalSwap(&other->options_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Type, syntax_)
       + sizeof(Type::syntax_)
@@ -741,23 +709,25 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Type::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[0]);
 }
 
-
 // ===================================================================
 
-void Field::InitAsDefaultInstance() {
-}
 class Field::_Internal {
  public:
 };
 
-Field::Field(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+Field::Field(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   options_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Field)
 }
 Field::Field(const Field& from)
@@ -766,23 +736,23 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_type_url().empty()) {
-    type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_type_url(),
-      GetArena());
+    type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(), 
+      GetArenaForAllocation());
   }
   json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_json_name().empty()) {
-    json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_json_name(),
-      GetArena());
+    json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_json_name(), 
+      GetArenaForAllocation());
   }
   default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_default_value().empty()) {
-    default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_default_value(),
-      GetArena());
+    default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_default_value(), 
+      GetArenaForAllocation());
   }
   ::memcpy(&kind_, &from.kind_,
     static_cast<size_t>(reinterpret_cast<char*>(&packed_) -
@@ -790,25 +760,26 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Field)
 }
 
-void Field::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Field_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&kind_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&packed_) -
-      reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
+inline void Field::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&kind_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&packed_) -
+    reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
 }
 
 Field::~Field() {
   // @@protoc_insertion_point(destructor:google.protobuf.Field)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Field::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Field::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   json_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
@@ -824,11 +795,6 @@
 void Field::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Field& Field::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Field_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Field::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Field)
@@ -837,10 +803,10 @@
   (void) cached_has_bits;
 
   options_.Clear();
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  json_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  default_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
+  type_url_.ClearToEmpty();
+  json_name_.ClearToEmpty();
+  default_value_.ClearToEmpty();
   ::memset(&kind_, 0, static_cast<size_t>(
       reinterpret_cast<char*>(&packed_) -
       reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
@@ -849,11 +815,9 @@
 
 const char* Field::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // .google.protobuf.Field.Kind kind = 1;
       case 1:
@@ -942,7 +906,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -969,27 +934,27 @@
   (void) cached_has_bits;
 
   // .google.protobuf.Field.Kind kind = 1;
-  if (this->kind() != 0) {
+  if (this->_internal_kind() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
       1, this->_internal_kind(), target);
   }
 
   // .google.protobuf.Field.Cardinality cardinality = 2;
-  if (this->cardinality() != 0) {
+  if (this->_internal_cardinality() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
       2, this->_internal_cardinality(), target);
   }
 
   // int32 number = 3;
-  if (this->number() != 0) {
+  if (this->_internal_number() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_number(), target);
   }
 
   // string name = 4;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -999,7 +964,7 @@
   }
 
   // string type_url = 6;
-  if (this->type_url().size() > 0) {
+  if (!this->_internal_type_url().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1009,13 +974,13 @@
   }
 
   // int32 oneof_index = 7;
-  if (this->oneof_index() != 0) {
+  if (this->_internal_oneof_index() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(7, this->_internal_oneof_index(), target);
   }
 
   // bool packed = 8;
-  if (this->packed() != 0) {
+  if (this->_internal_packed() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(8, this->_internal_packed(), target);
   }
@@ -1029,7 +994,7 @@
   }
 
   // string json_name = 10;
-  if (this->json_name().size() > 0) {
+  if (!this->_internal_json_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_json_name().data(), static_cast<int>(this->_internal_json_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1039,7 +1004,7 @@
   }
 
   // string default_value = 11;
-  if (this->default_value().size() > 0) {
+  if (!this->_internal_default_value().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_default_value().data(), static_cast<int>(this->_internal_default_value().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1072,61 +1037,61 @@
   }
 
   // string name = 4;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // string type_url = 6;
-  if (this->type_url().size() > 0) {
+  if (!this->_internal_type_url().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_type_url());
   }
 
   // string json_name = 10;
-  if (this->json_name().size() > 0) {
+  if (!this->_internal_json_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_json_name());
   }
 
   // string default_value = 11;
-  if (this->default_value().size() > 0) {
+  if (!this->_internal_default_value().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_default_value());
   }
 
   // .google.protobuf.Field.Kind kind = 1;
-  if (this->kind() != 0) {
+  if (this->_internal_kind() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_kind());
   }
 
   // .google.protobuf.Field.Cardinality cardinality = 2;
-  if (this->cardinality() != 0) {
+  if (this->_internal_cardinality() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_cardinality());
   }
 
   // int32 number = 3;
-  if (this->number() != 0) {
+  if (this->_internal_number() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
         this->_internal_number());
   }
 
   // int32 oneof_index = 7;
-  if (this->oneof_index() != 0) {
+  if (this->_internal_oneof_index() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
         this->_internal_oneof_index());
   }
 
   // bool packed = 8;
-  if (this->packed() != 0) {
+  if (this->_internal_packed() != 0) {
     total_size += 1 + 1;
   }
 
@@ -1139,63 +1104,54 @@
   return total_size;
 }
 
-void Field::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Field)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Field* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Field>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Field)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Field)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Field::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Field::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Field::GetClassData() const { return &_class_data_; }
+
+void Field::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Field *>(to)->MergeFrom(
+      static_cast<const Field &>(from));
 }
 
+
 void Field::MergeFrom(const Field& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   options_.MergeFrom(from.options_);
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.type_url().size() > 0) {
+  if (!from._internal_type_url().empty()) {
     _internal_set_type_url(from._internal_type_url());
   }
-  if (from.json_name().size() > 0) {
+  if (!from._internal_json_name().empty()) {
     _internal_set_json_name(from._internal_json_name());
   }
-  if (from.default_value().size() > 0) {
+  if (!from._internal_default_value().empty()) {
     _internal_set_default_value(from._internal_default_value());
   }
-  if (from.kind() != 0) {
+  if (from._internal_kind() != 0) {
     _internal_set_kind(from._internal_kind());
   }
-  if (from.cardinality() != 0) {
+  if (from._internal_cardinality() != 0) {
     _internal_set_cardinality(from._internal_cardinality());
   }
-  if (from.number() != 0) {
+  if (from._internal_number() != 0) {
     _internal_set_number(from._internal_number());
   }
-  if (from.oneof_index() != 0) {
+  if (from._internal_oneof_index() != 0) {
     _internal_set_oneof_index(from._internal_oneof_index());
   }
-  if (from.packed() != 0) {
+  if (from._internal_packed() != 0) {
     _internal_set_packed(from._internal_packed());
   }
-}
-
-void Field::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Field)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Field::CopyFrom(const Field& from) {
@@ -1211,12 +1167,28 @@
 
 void Field::InternalSwap(Field* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   options_.InternalSwap(&other->options_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  type_url_.Swap(&other->type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  json_name_.Swap(&other->json_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  default_value_.Swap(&other->default_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &type_url_, GetArenaForAllocation(),
+      &other->type_url_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &json_name_, GetArenaForAllocation(),
+      &other->json_name_, other->GetArenaForAllocation()
+  );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &default_value_, GetArenaForAllocation(),
+      &other->default_value_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Field, packed_)
       + sizeof(Field::packed_)
@@ -1226,16 +1198,13 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Field::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[1]);
 }
 
-
 // ===================================================================
 
-void Enum::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_Enum_default_instance_._instance.get_mutable()->source_context_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceContext*>(
-      PROTOBUF_NAMESPACE_ID::SourceContext::internal_default_instance());
-}
 class Enum::_Internal {
  public:
   static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Enum* msg);
@@ -1246,17 +1215,20 @@
   return *msg->source_context_;
 }
 void Enum::clear_source_context() {
-  if (GetArena() == nullptr && source_context_ != nullptr) {
+  if (GetArenaForAllocation() == nullptr && source_context_ != nullptr) {
     delete source_context_;
   }
   source_context_ = nullptr;
 }
-Enum::Enum(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+Enum::Enum(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   enumvalue_(arena),
   options_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Enum)
 }
 Enum::Enum(const Enum& from)
@@ -1266,8 +1238,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_source_context()) {
     source_context_ = new PROTOBUF_NAMESPACE_ID::SourceContext(*from.source_context_);
@@ -1278,22 +1250,23 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Enum)
 }
 
-void Enum::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Enum_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(&source_context_, 0, static_cast<size_t>(
-      reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
+inline void Enum::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
 }
 
 Enum::~Enum() {
   // @@protoc_insertion_point(destructor:google.protobuf.Enum)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Enum::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Enum::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete source_context_;
 }
@@ -1307,11 +1280,6 @@
 void Enum::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Enum& Enum::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Enum_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Enum::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Enum)
@@ -1321,8 +1289,8 @@
 
   enumvalue_.Clear();
   options_.Clear();
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  if (GetArena() == nullptr && source_context_ != nullptr) {
+  name_.ClearToEmpty();
+  if (GetArenaForAllocation() == nullptr && source_context_ != nullptr) {
     delete source_context_;
   }
   source_context_ = nullptr;
@@ -1332,11 +1300,9 @@
 
 const char* Enum::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1388,7 +1354,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1415,7 +1382,7 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1441,7 +1408,7 @@
   }
 
   // .google.protobuf.SourceContext source_context = 4;
-  if (this->has_source_context()) {
+  if (this->_internal_has_source_context()) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(
@@ -1449,7 +1416,7 @@
   }
 
   // .google.protobuf.Syntax syntax = 5;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
       5, this->_internal_syntax(), target);
@@ -1486,21 +1453,21 @@
   }
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // .google.protobuf.SourceContext source_context = 4;
-  if (this->has_source_context()) {
+  if (this->_internal_has_source_context()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
         *source_context_);
   }
 
   // .google.protobuf.Syntax syntax = 5;
-  if (this->syntax() != 0) {
+  if (this->_internal_syntax() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax());
   }
@@ -1514,46 +1481,37 @@
   return total_size;
 }
 
-void Enum::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Enum)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Enum* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Enum>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Enum)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Enum)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Enum::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Enum::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Enum::GetClassData() const { return &_class_data_; }
+
+void Enum::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Enum *>(to)->MergeFrom(
+      static_cast<const Enum &>(from));
 }
 
+
 void Enum::MergeFrom(const Enum& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   enumvalue_.MergeFrom(from.enumvalue_);
   options_.MergeFrom(from.options_);
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.has_source_context()) {
+  if (from._internal_has_source_context()) {
     _internal_mutable_source_context()->PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom(from._internal_source_context());
   }
-  if (from.syntax() != 0) {
+  if (from._internal_syntax() != 0) {
     _internal_set_syntax(from._internal_syntax());
   }
-}
-
-void Enum::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Enum)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Enum::CopyFrom(const Enum& from) {
@@ -1569,10 +1527,14 @@
 
 void Enum::InternalSwap(Enum* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   enumvalue_.InternalSwap(&other->enumvalue_);
   options_.InternalSwap(&other->options_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(Enum, syntax_)
       + sizeof(Enum::syntax_)
@@ -1582,23 +1544,25 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Enum::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[2]);
 }
 
-
 // ===================================================================
 
-void EnumValue::InitAsDefaultInstance() {
-}
 class EnumValue::_Internal {
  public:
 };
 
-EnumValue::EnumValue(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena),
+EnumValue::EnumValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
   options_(arena) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValue)
 }
 EnumValue::EnumValue(const EnumValue& from)
@@ -1607,27 +1571,27 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   number_ = from.number_;
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValue)
 }
 
-void EnumValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  number_ = 0;
+inline void EnumValue::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+number_ = 0;
 }
 
 EnumValue::~EnumValue() {
   // @@protoc_insertion_point(destructor:google.protobuf.EnumValue)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void EnumValue::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void EnumValue::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -1640,11 +1604,6 @@
 void EnumValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumValue& EnumValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue)
@@ -1653,18 +1612,16 @@
   (void) cached_has_bits;
 
   options_.Clear();
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
   number_ = 0;
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* EnumValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1696,7 +1653,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1723,7 +1681,7 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1733,7 +1691,7 @@
   }
 
   // int32 number = 2;
-  if (this->number() != 0) {
+  if (this->_internal_number() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_number(), target);
   }
@@ -1770,14 +1728,14 @@
   }
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // int32 number = 2;
-  if (this->number() != 0) {
+  if (this->_internal_number() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
         this->_internal_number());
@@ -1792,42 +1750,33 @@
   return total_size;
 }
 
-void EnumValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValue)
-  GOOGLE_DCHECK_NE(&from, this);
-  const EnumValue* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<EnumValue>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValue)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValue)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumValue::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    EnumValue::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumValue::GetClassData() const { return &_class_data_; }
+
+void EnumValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<EnumValue *>(to)->MergeFrom(
+      static_cast<const EnumValue &>(from));
 }
 
+
 void EnumValue::MergeFrom(const EnumValue& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   options_.MergeFrom(from.options_);
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.number() != 0) {
+  if (from._internal_number() != 0) {
     _internal_set_number(from._internal_number());
   }
-}
-
-void EnumValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValue)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void EnumValue::CopyFrom(const EnumValue& from) {
@@ -1843,23 +1792,24 @@
 
 void EnumValue::InternalSwap(EnumValue* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   options_.InternalSwap(&other->options_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   swap(number_, other->number_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[3]);
 }
 
-
 // ===================================================================
 
-void Option::InitAsDefaultInstance() {
-  PROTOBUF_NAMESPACE_ID::_Option_default_instance_._instance.get_mutable()->value_ = const_cast< PROTOBUF_NAMESPACE_ID::Any*>(
-      PROTOBUF_NAMESPACE_ID::Any::internal_default_instance());
-}
 class Option::_Internal {
  public:
   static const PROTOBUF_NAMESPACE_ID::Any& value(const Option* msg);
@@ -1870,15 +1820,18 @@
   return *msg->value_;
 }
 void Option::clear_value() {
-  if (GetArena() == nullptr && value_ != nullptr) {
+  if (GetArenaForAllocation() == nullptr && value_ != nullptr) {
     delete value_;
   }
   value_ = nullptr;
 }
-Option::Option(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Option::Option(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Option)
 }
 Option::Option(const Option& from)
@@ -1886,8 +1839,8 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_name().empty()) {
-    name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(),
-      GetArena());
+    name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), 
+      GetArenaForAllocation());
   }
   if (from._internal_has_value()) {
     value_ = new PROTOBUF_NAMESPACE_ID::Any(*from.value_);
@@ -1897,20 +1850,20 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Option)
 }
 
-void Option::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Option_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  value_ = nullptr;
+inline void Option::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+value_ = nullptr;
 }
 
 Option::~Option() {
   // @@protoc_insertion_point(destructor:google.protobuf.Option)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Option::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Option::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (this != internal_default_instance()) delete value_;
 }
@@ -1924,11 +1877,6 @@
 void Option::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Option& Option::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Option_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Option::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Option)
@@ -1936,8 +1884,8 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
-  if (GetArena() == nullptr && value_ != nullptr) {
+  name_.ClearToEmpty();
+  if (GetArenaForAllocation() == nullptr && value_ != nullptr) {
     delete value_;
   }
   value_ = nullptr;
@@ -1946,11 +1894,9 @@
 
 const char* Option::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1970,7 +1916,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1997,7 +1944,7 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -2007,7 +1954,7 @@
   }
 
   // .google.protobuf.Any value = 2;
-  if (this->has_value()) {
+  if (this->_internal_has_value()) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(
@@ -2031,14 +1978,14 @@
   (void) cached_has_bits;
 
   // string name = 1;
-  if (this->name().size() > 0) {
+  if (!this->_internal_name().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name());
   }
 
   // .google.protobuf.Any value = 2;
-  if (this->has_value()) {
+  if (this->_internal_has_value()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
         *value_);
@@ -2053,41 +2000,32 @@
   return total_size;
 }
 
-void Option::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Option)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Option* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Option>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Option)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Option)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Option::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Option::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Option::GetClassData() const { return &_class_data_; }
+
+void Option::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Option *>(to)->MergeFrom(
+      static_cast<const Option &>(from));
 }
 
+
 void Option::MergeFrom(const Option& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.name().size() > 0) {
+  if (!from._internal_name().empty()) {
     _internal_set_name(from._internal_name());
   }
-  if (from.has_value()) {
+  if (from._internal_has_value()) {
     _internal_mutable_value()->PROTOBUF_NAMESPACE_ID::Any::MergeFrom(from._internal_value());
   }
-}
-
-void Option::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Option)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Option::CopyFrom(const Option& from) {
@@ -2103,16 +2041,21 @@
 
 void Option::InternalSwap(Option* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &name_, GetArenaForAllocation(),
+      &other->name_, other->GetArenaForAllocation()
+  );
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Option::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[4]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index 680679f..1ec987c 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -48,7 +47,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftype_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[5]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -56,22 +55,22 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class Enum;
-class EnumDefaultTypeInternal;
+struct EnumDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDefaultTypeInternal _Enum_default_instance_;
 class EnumValue;
-class EnumValueDefaultTypeInternal;
+struct EnumValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueDefaultTypeInternal _EnumValue_default_instance_;
 class Field;
-class FieldDefaultTypeInternal;
+struct FieldDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldDefaultTypeInternal _Field_default_instance_;
 class Option;
-class OptionDefaultTypeInternal;
+struct OptionDefaultTypeInternal;
 PROTOBUF_EXPORT extern OptionDefaultTypeInternal _Option_default_instance_;
 class Type;
-class TypeDefaultTypeInternal;
+struct TypeDefaultTypeInternal;
 PROTOBUF_EXPORT extern TypeDefaultTypeInternal _Type_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -121,7 +120,7 @@
     Field_Kind_descriptor(), enum_t_value);
 }
 inline bool Field_Kind_Parse(
-    const std::string& name, Field_Kind* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Kind* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Kind>(
     Field_Kind_descriptor(), name, value);
 }
@@ -148,7 +147,7 @@
     Field_Cardinality_descriptor(), enum_t_value);
 }
 inline bool Field_Cardinality_Parse(
-    const std::string& name, Field_Cardinality* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Cardinality* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Cardinality>(
     Field_Cardinality_descriptor(), name, value);
 }
@@ -173,17 +172,18 @@
     Syntax_descriptor(), enum_t_value);
 }
 inline bool Syntax_Parse(
-    const std::string& name, Syntax* value) {
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Syntax* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Syntax>(
     Syntax_descriptor(), name, value);
 }
 // ===================================================================
 
-class PROTOBUF_EXPORT Type PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Type final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Type) */ {
  public:
-  inline Type() : Type(nullptr) {};
-  virtual ~Type();
+  inline Type() : Type(nullptr) {}
+  ~Type() override;
+  explicit constexpr Type(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Type(const Type& from);
   Type(Type&& from) noexcept
@@ -196,8 +196,9 @@
     return *this;
   }
   inline Type& operator=(Type&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -208,14 +209,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Type& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Type& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Type* internal_default_instance() {
     return reinterpret_cast<const Type*>(
                &_Type_default_instance_);
@@ -228,7 +229,7 @@
   }
   inline void Swap(Type* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -236,23 +237,26 @@
   }
   void UnsafeArenaSwap(Type* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Type* New() const final {
-    return CreateMaybeMessage<Type>(nullptr);
+    return new Type();
   }
 
   Type* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Type>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Type& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Type& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -263,8 +267,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Type* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -272,20 +276,17 @@
     return "google.protobuf.Type";
   }
   protected:
-  explicit Type(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Type(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -362,25 +363,14 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -391,7 +381,7 @@
   public:
   void clear_source_context();
   const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
-  PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
   PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
   void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
   private:
@@ -429,11 +419,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Field PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Field final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Field) */ {
  public:
-  inline Field() : Field(nullptr) {};
-  virtual ~Field();
+  inline Field() : Field(nullptr) {}
+  ~Field() override;
+  explicit constexpr Field(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Field(const Field& from);
   Field(Field&& from) noexcept
@@ -446,8 +437,9 @@
     return *this;
   }
   inline Field& operator=(Field&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -458,14 +450,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Field& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Field& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Field* internal_default_instance() {
     return reinterpret_cast<const Field*>(
                &_Field_default_instance_);
@@ -478,7 +470,7 @@
   }
   inline void Swap(Field* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -486,23 +478,26 @@
   }
   void UnsafeArenaSwap(Field* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Field* New() const final {
-    return CreateMaybeMessage<Field>(nullptr);
+    return new Field();
   }
 
   Field* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Field>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Field& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Field& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -513,8 +508,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Field* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -522,20 +517,17 @@
     return "google.protobuf.Field";
   }
   protected:
-  explicit Field(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Field(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -598,7 +590,7 @@
       "Incorrect type passed to function Kind_Name.");
     return Field_Kind_Name(enum_t_value);
   }
-  static inline bool Kind_Parse(const std::string& name,
+  static inline bool Kind_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       Kind* value) {
     return Field_Kind_Parse(name, value);
   }
@@ -632,7 +624,7 @@
       "Incorrect type passed to function Cardinality_Name.");
     return Field_Cardinality_Name(enum_t_value);
   }
-  static inline bool Cardinality_Parse(const std::string& name,
+  static inline bool Cardinality_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
       Cardinality* value) {
     return Field_Cardinality_Parse(name, value);
   }
@@ -672,100 +664,56 @@
   // string name = 4;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
   // string type_url = 6;
   void clear_type_url();
   const std::string& type_url() const;
-  void set_type_url(const std::string& value);
-  void set_type_url(std::string&& value);
-  void set_type_url(const char* value);
-  void set_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_type_url();
-  std::string* release_type_url();
+  PROTOBUF_MUST_USE_RESULT std::string* release_type_url();
   void set_allocated_type_url(std::string* type_url);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_type_url();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_type_url(
-      std::string* type_url);
   private:
   const std::string& _internal_type_url() const;
-  void _internal_set_type_url(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value);
   std::string* _internal_mutable_type_url();
   public:
 
   // string json_name = 10;
   void clear_json_name();
   const std::string& json_name() const;
-  void set_json_name(const std::string& value);
-  void set_json_name(std::string&& value);
-  void set_json_name(const char* value);
-  void set_json_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_json_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_json_name();
-  std::string* release_json_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_json_name();
   void set_allocated_json_name(std::string* json_name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_json_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_json_name(
-      std::string* json_name);
   private:
   const std::string& _internal_json_name() const;
-  void _internal_set_json_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_json_name(const std::string& value);
   std::string* _internal_mutable_json_name();
   public:
 
   // string default_value = 11;
   void clear_default_value();
   const std::string& default_value() const;
-  void set_default_value(const std::string& value);
-  void set_default_value(std::string&& value);
-  void set_default_value(const char* value);
-  void set_default_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_default_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_default_value();
-  std::string* release_default_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_default_value();
   void set_allocated_default_value(std::string* default_value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_default_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_default_value(
-      std::string* default_value);
   private:
   const std::string& _internal_default_value() const;
-  void _internal_set_default_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_default_value(const std::string& value);
   std::string* _internal_mutable_default_value();
   public:
 
@@ -836,11 +784,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Enum PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Enum final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Enum) */ {
  public:
-  inline Enum() : Enum(nullptr) {};
-  virtual ~Enum();
+  inline Enum() : Enum(nullptr) {}
+  ~Enum() override;
+  explicit constexpr Enum(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Enum(const Enum& from);
   Enum(Enum&& from) noexcept
@@ -853,8 +802,9 @@
     return *this;
   }
   inline Enum& operator=(Enum&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -865,14 +815,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Enum& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Enum& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Enum* internal_default_instance() {
     return reinterpret_cast<const Enum*>(
                &_Enum_default_instance_);
@@ -885,7 +835,7 @@
   }
   inline void Swap(Enum* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -893,23 +843,26 @@
   }
   void UnsafeArenaSwap(Enum* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Enum* New() const final {
-    return CreateMaybeMessage<Enum>(nullptr);
+    return new Enum();
   }
 
   Enum* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Enum>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Enum& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Enum& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -920,8 +873,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Enum* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -929,20 +882,17 @@
     return "google.protobuf.Enum";
   }
   protected:
-  explicit Enum(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Enum(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -994,25 +944,14 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -1023,7 +962,7 @@
   public:
   void clear_source_context();
   const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
-  PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
   PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
   void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
   private:
@@ -1060,11 +999,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT EnumValue PROTOBUF_FINAL :
+class PROTOBUF_EXPORT EnumValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValue) */ {
  public:
-  inline EnumValue() : EnumValue(nullptr) {};
-  virtual ~EnumValue();
+  inline EnumValue() : EnumValue(nullptr) {}
+  ~EnumValue() override;
+  explicit constexpr EnumValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValue(const EnumValue& from);
   EnumValue(EnumValue&& from) noexcept
@@ -1077,8 +1017,9 @@
     return *this;
   }
   inline EnumValue& operator=(EnumValue&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1089,14 +1030,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const EnumValue& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const EnumValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValue* internal_default_instance() {
     return reinterpret_cast<const EnumValue*>(
                &_EnumValue_default_instance_);
@@ -1109,7 +1050,7 @@
   }
   inline void Swap(EnumValue* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1117,23 +1058,26 @@
   }
   void UnsafeArenaSwap(EnumValue* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline EnumValue* New() const final {
-    return CreateMaybeMessage<EnumValue>(nullptr);
+    return new EnumValue();
   }
 
   EnumValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<EnumValue>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const EnumValue& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const EnumValue& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1144,8 +1088,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(EnumValue* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1153,20 +1097,17 @@
     return "google.protobuf.EnumValue";
   }
   protected:
-  explicit EnumValue(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit EnumValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1198,25 +1139,14 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -1244,11 +1174,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Option PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Option final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Option) */ {
  public:
-  inline Option() : Option(nullptr) {};
-  virtual ~Option();
+  inline Option() : Option(nullptr) {}
+  ~Option() override;
+  explicit constexpr Option(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Option(const Option& from);
   Option(Option&& from) noexcept
@@ -1261,8 +1192,9 @@
     return *this;
   }
   inline Option& operator=(Option&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1273,14 +1205,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Option& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Option& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Option* internal_default_instance() {
     return reinterpret_cast<const Option*>(
                &_Option_default_instance_);
@@ -1293,7 +1225,7 @@
   }
   inline void Swap(Option* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1301,23 +1233,26 @@
   }
   void UnsafeArenaSwap(Option* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Option* New() const final {
-    return CreateMaybeMessage<Option>(nullptr);
+    return new Option();
   }
 
   Option* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Option>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Option& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Option& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1328,8 +1263,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Option* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1337,20 +1272,17 @@
     return "google.protobuf.Option";
   }
   protected:
-  explicit Option(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Option(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1363,25 +1295,14 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
-  std::string* release_name();
+  PROTOBUF_MUST_USE_RESULT std::string* release_name();
   void set_allocated_name(std::string* name);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_name();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_name(
-      std::string* name);
   private:
   const std::string& _internal_name() const;
-  void _internal_set_name(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
   std::string* _internal_mutable_name();
   public:
 
@@ -1392,7 +1313,7 @@
   public:
   void clear_value();
   const PROTOBUF_NAMESPACE_ID::Any& value() const;
-  PROTOBUF_NAMESPACE_ID::Any* release_value();
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NAMESPACE_ID::Any* release_value();
   PROTOBUF_NAMESPACE_ID::Any* mutable_value();
   void set_allocated_value(PROTOBUF_NAMESPACE_ID::Any* value);
   private:
@@ -1428,54 +1349,38 @@
 
 // string name = 1;
 inline void Type::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& Type::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Type.name)
   return _internal_name();
 }
-inline void Type::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Type::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
 }
 inline std::string* Type::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Type.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& Type::_internal_name() const {
   return name_.Get();
 }
 inline void Type::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Type::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Type.name)
-}
-inline void Type::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name)
-}
-inline void Type::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Type::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Type::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Type.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Type::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -1484,28 +1389,9 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.name)
 }
-inline std::string* Type::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Type.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Type::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Type.name)
-}
 
 // repeated .google.protobuf.Field fields = 2;
 inline int Type::_internal_fields_size() const {
@@ -1537,8 +1423,9 @@
   return fields_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Field* Type::add_fields() {
+  PROTOBUF_NAMESPACE_ID::Field* _add = _internal_add_fields();
   // @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
-  return _internal_add_fields();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Field >&
 Type::fields() const {
@@ -1557,8 +1444,9 @@
   oneofs_.Clear();
 }
 inline std::string* Type::add_oneofs() {
+  std::string* _s = _internal_add_oneofs();
   // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs)
-  return _internal_add_oneofs();
+  return _s;
 }
 inline const std::string& Type::_internal_oneofs(int index) const {
   return oneofs_.Get(index);
@@ -1572,12 +1460,12 @@
   return oneofs_.Mutable(index);
 }
 inline void Type::set_oneofs(int index, const std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
   oneofs_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
 }
 inline void Type::set_oneofs(int index, std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
   oneofs_.Mutable(index)->assign(std::move(value));
+  // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
 }
 inline void Type::set_oneofs(int index, const char* value) {
   GOOGLE_DCHECK(value != nullptr);
@@ -1650,8 +1538,9 @@
   return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* Type::add_options() {
+  PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
   // @@protoc_insertion_point(field_add:google.protobuf.Type.options)
-  return _internal_add_options();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 Type::options() const {
@@ -1668,8 +1557,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceContext& Type::_internal_source_context() const {
   const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceContext*>(
-      &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceContext&>(
+      PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceContext& Type::source_context() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
@@ -1677,7 +1566,7 @@
 }
 inline void Type::unsafe_arena_set_allocated_source_context(
     PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_);
   }
   source_context_ = source_context;
@@ -1689,10 +1578,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Type.source_context)
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Type::release_source_context() {
-  auto temp = unsafe_arena_release_source_context();
-  if (GetArena() != nullptr) {
+  
+  PROTOBUF_NAMESPACE_ID::SourceContext* temp = source_context_;
+  source_context_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Type::unsafe_arena_release_source_context() {
@@ -1705,23 +1602,26 @@
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Type::_internal_mutable_source_context() {
   
   if (source_context_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceContext>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaForAllocation());
     source_context_ = p;
   }
   return source_context_;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Type::mutable_source_context() {
+  PROTOBUF_NAMESPACE_ID::SourceContext* _msg = _internal_mutable_source_context();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context)
-  return _internal_mutable_source_context();
+  return _msg;
 }
 inline void Type::set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_);
   }
   if (source_context) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context)->GetArena();
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<
+            ::PROTOBUF_NAMESPACE_ID::MessageLite>::GetOwningArena(
+                reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context));
     if (message_arena != submessage_arena) {
       source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_context, submessage_arena);
@@ -1820,54 +1720,38 @@
 
 // string name = 4;
 inline void Field::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& Field::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Field.name)
   return _internal_name();
 }
-inline void Field::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Field::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
 }
 inline std::string* Field::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Field.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& Field::_internal_name() const {
   return name_.Get();
 }
 inline void Field::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Field::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.name)
-}
-inline void Field::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name)
-}
-inline void Field::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Field::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Field.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Field::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -1876,79 +1760,44 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.name)
 }
-inline std::string* Field::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Field.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Field::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Field.name)
-}
 
 // string type_url = 6;
 inline void Field::clear_type_url() {
-  type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  type_url_.ClearToEmpty();
 }
 inline const std::string& Field::type_url() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url)
   return _internal_type_url();
 }
-inline void Field::set_type_url(const std::string& value) {
-  _internal_set_type_url(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Field::set_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
 }
 inline std::string* Field::mutable_type_url() {
+  std::string* _s = _internal_mutable_type_url();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Field.type_url)
-  return _internal_mutable_type_url();
+  return _s;
 }
 inline const std::string& Field::_internal_type_url() const {
   return type_url_.Get();
 }
 inline void Field::_internal_set_type_url(const std::string& value) {
   
-  type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Field::set_type_url(std::string&& value) {
-  
-  type_url_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.type_url)
-}
-inline void Field::set_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url)
-}
-inline void Field::set_type_url(const char* value,
-    size_t size) {
-  
-  type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url)
+  type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_type_url() {
   
-  return type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Field::release_type_url() {
   // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url)
-  return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Field::set_allocated_type_url(std::string* type_url) {
   if (type_url != nullptr) {
@@ -1957,28 +1806,9 @@
     
   }
   type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_url,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.type_url)
 }
-inline std::string* Field::unsafe_arena_release_type_url() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Field.type_url)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return type_url_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Field::unsafe_arena_set_allocated_type_url(
-    std::string* type_url) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (type_url != nullptr) {
-    
-  } else {
-    
-  }
-  type_url_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      type_url, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Field.type_url)
-}
 
 // int32 oneof_index = 7;
 inline void Field::clear_oneof_index() {
@@ -2050,8 +1880,9 @@
   return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* Field::add_options() {
+  PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
   // @@protoc_insertion_point(field_add:google.protobuf.Field.options)
-  return _internal_add_options();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 Field::options() const {
@@ -2061,54 +1892,38 @@
 
 // string json_name = 10;
 inline void Field::clear_json_name() {
-  json_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  json_name_.ClearToEmpty();
 }
 inline const std::string& Field::json_name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name)
   return _internal_json_name();
 }
-inline void Field::set_json_name(const std::string& value) {
-  _internal_set_json_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Field::set_json_name(ArgT0&& arg0, ArgT... args) {
+ 
+ json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
 }
 inline std::string* Field::mutable_json_name() {
+  std::string* _s = _internal_mutable_json_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Field.json_name)
-  return _internal_mutable_json_name();
+  return _s;
 }
 inline const std::string& Field::_internal_json_name() const {
   return json_name_.Get();
 }
 inline void Field::_internal_set_json_name(const std::string& value) {
   
-  json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Field::set_json_name(std::string&& value) {
-  
-  json_name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.json_name)
-}
-inline void Field::set_json_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.json_name)
-}
-inline void Field::set_json_name(const char* value,
-    size_t size) {
-  
-  json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.json_name)
+  json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_json_name() {
   
-  return json_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return json_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Field::release_json_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name)
-  return json_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return json_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Field::set_allocated_json_name(std::string* json_name) {
   if (json_name != nullptr) {
@@ -2117,79 +1932,44 @@
     
   }
   json_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), json_name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.json_name)
 }
-inline std::string* Field::unsafe_arena_release_json_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Field.json_name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return json_name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Field::unsafe_arena_set_allocated_json_name(
-    std::string* json_name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (json_name != nullptr) {
-    
-  } else {
-    
-  }
-  json_name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      json_name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Field.json_name)
-}
 
 // string default_value = 11;
 inline void Field::clear_default_value() {
-  default_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  default_value_.ClearToEmpty();
 }
 inline const std::string& Field::default_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Field.default_value)
   return _internal_default_value();
 }
-inline void Field::set_default_value(const std::string& value) {
-  _internal_set_default_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Field::set_default_value(ArgT0&& arg0, ArgT... args) {
+ 
+ default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.default_value)
 }
 inline std::string* Field::mutable_default_value() {
+  std::string* _s = _internal_mutable_default_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Field.default_value)
-  return _internal_mutable_default_value();
+  return _s;
 }
 inline const std::string& Field::_internal_default_value() const {
   return default_value_.Get();
 }
 inline void Field::_internal_set_default_value(const std::string& value) {
   
-  default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Field::set_default_value(std::string&& value) {
-  
-  default_value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.default_value)
-}
-inline void Field::set_default_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.default_value)
-}
-inline void Field::set_default_value(const char* value,
-    size_t size) {
-  
-  default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.default_value)
+  default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_default_value() {
   
-  return default_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return default_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Field::release_default_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value)
-  return default_value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return default_value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Field::set_allocated_default_value(std::string* default_value) {
   if (default_value != nullptr) {
@@ -2198,28 +1978,9 @@
     
   }
   default_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), default_value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.default_value)
 }
-inline std::string* Field::unsafe_arena_release_default_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Field.default_value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return default_value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Field::unsafe_arena_set_allocated_default_value(
-    std::string* default_value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (default_value != nullptr) {
-    
-  } else {
-    
-  }
-  default_value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      default_value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Field.default_value)
-}
 
 // -------------------------------------------------------------------
 
@@ -2227,54 +1988,38 @@
 
 // string name = 1;
 inline void Enum::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& Enum::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Enum.name)
   return _internal_name();
 }
-inline void Enum::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Enum::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
 }
 inline std::string* Enum::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& Enum::_internal_name() const {
   return name_.Get();
 }
 inline void Enum::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Enum::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Enum.name)
-}
-inline void Enum::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name)
-}
-inline void Enum::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Enum::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Enum::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Enum.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Enum::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -2283,28 +2028,9 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.name)
 }
-inline std::string* Enum::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Enum.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Enum::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Enum.name)
-}
 
 // repeated .google.protobuf.EnumValue enumvalue = 2;
 inline int Enum::_internal_enumvalue_size() const {
@@ -2336,8 +2062,9 @@
   return enumvalue_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::EnumValue* Enum::add_enumvalue() {
+  PROTOBUF_NAMESPACE_ID::EnumValue* _add = _internal_add_enumvalue();
   // @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
-  return _internal_add_enumvalue();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumValue >&
 Enum::enumvalue() const {
@@ -2375,8 +2102,9 @@
   return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* Enum::add_options() {
+  PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
   // @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
-  return _internal_add_options();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 Enum::options() const {
@@ -2393,8 +2121,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceContext& Enum::_internal_source_context() const {
   const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceContext*>(
-      &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::SourceContext&>(
+      PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::SourceContext& Enum::source_context() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
@@ -2402,7 +2130,7 @@
 }
 inline void Enum::unsafe_arena_set_allocated_source_context(
     PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_);
   }
   source_context_ = source_context;
@@ -2414,10 +2142,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Enum.source_context)
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Enum::release_source_context() {
-  auto temp = unsafe_arena_release_source_context();
-  if (GetArena() != nullptr) {
+  
+  PROTOBUF_NAMESPACE_ID::SourceContext* temp = source_context_;
+  source_context_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Enum::unsafe_arena_release_source_context() {
@@ -2430,23 +2166,26 @@
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Enum::_internal_mutable_source_context() {
   
   if (source_context_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceContext>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaForAllocation());
     source_context_ = p;
   }
   return source_context_;
 }
 inline PROTOBUF_NAMESPACE_ID::SourceContext* Enum::mutable_source_context() {
+  PROTOBUF_NAMESPACE_ID::SourceContext* _msg = _internal_mutable_source_context();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context)
-  return _internal_mutable_source_context();
+  return _msg;
 }
 inline void Enum::set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_);
   }
   if (source_context) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context)->GetArena();
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<
+            ::PROTOBUF_NAMESPACE_ID::MessageLite>::GetOwningArena(
+                reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context));
     if (message_arena != submessage_arena) {
       source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_context, submessage_arena);
@@ -2485,54 +2224,38 @@
 
 // string name = 1;
 inline void EnumValue::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& EnumValue::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name)
   return _internal_name();
 }
-inline void EnumValue::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void EnumValue::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
 }
 inline std::string* EnumValue::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& EnumValue::_internal_name() const {
   return name_.Get();
 }
 inline void EnumValue::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void EnumValue::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValue.name)
-}
-inline void EnumValue::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name)
-}
-inline void EnumValue::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* EnumValue::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* EnumValue::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void EnumValue::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -2541,28 +2264,9 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValue.name)
 }
-inline std::string* EnumValue::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.EnumValue.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void EnumValue::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumValue.name)
-}
 
 // int32 number = 2;
 inline void EnumValue::clear_number() {
@@ -2614,8 +2318,9 @@
   return options_.Add();
 }
 inline PROTOBUF_NAMESPACE_ID::Option* EnumValue::add_options() {
+  PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
   // @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
-  return _internal_add_options();
+  return _add;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >&
 EnumValue::options() const {
@@ -2629,54 +2334,38 @@
 
 // string name = 1;
 inline void Option::clear_name() {
-  name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  name_.ClearToEmpty();
 }
 inline const std::string& Option::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Option.name)
   return _internal_name();
 }
-inline void Option::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Option::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
 }
 inline std::string* Option::mutable_name() {
+  std::string* _s = _internal_mutable_name();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Option.name)
-  return _internal_mutable_name();
+  return _s;
 }
 inline const std::string& Option::_internal_name() const {
   return name_.Get();
 }
 inline void Option::_internal_set_name(const std::string& value) {
   
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void Option::set_name(std::string&& value) {
-  
-  name_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Option.name)
-}
-inline void Option::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name)
-}
-inline void Option::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name)
+  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* Option::_internal_mutable_name() {
   
-  return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* Option::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.Option.name)
-  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void Option::set_allocated_name(std::string* name) {
   if (name != nullptr) {
@@ -2685,28 +2374,9 @@
     
   }
   name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.name)
 }
-inline std::string* Option::unsafe_arena_release_name() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Option.name)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return name_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void Option::unsafe_arena_set_allocated_name(
-    std::string* name) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
-  name_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      name, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Option.name)
-}
 
 // .google.protobuf.Any value = 2;
 inline bool Option::_internal_has_value() const {
@@ -2717,8 +2387,8 @@
 }
 inline const PROTOBUF_NAMESPACE_ID::Any& Option::_internal_value() const {
   const PROTOBUF_NAMESPACE_ID::Any* p = value_;
-  return p != nullptr ? *p : *reinterpret_cast<const PROTOBUF_NAMESPACE_ID::Any*>(
-      &PROTOBUF_NAMESPACE_ID::_Any_default_instance_);
+  return p != nullptr ? *p : reinterpret_cast<const PROTOBUF_NAMESPACE_ID::Any&>(
+      PROTOBUF_NAMESPACE_ID::_Any_default_instance_);
 }
 inline const PROTOBUF_NAMESPACE_ID::Any& Option::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
@@ -2726,7 +2396,7 @@
 }
 inline void Option::unsafe_arena_set_allocated_value(
     PROTOBUF_NAMESPACE_ID::Any* value) {
-  if (GetArena() == nullptr) {
+  if (GetArenaForAllocation() == nullptr) {
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(value_);
   }
   value_ = value;
@@ -2738,10 +2408,18 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Option.value)
 }
 inline PROTOBUF_NAMESPACE_ID::Any* Option::release_value() {
-  auto temp = unsafe_arena_release_value();
-  if (GetArena() != nullptr) {
+  
+  PROTOBUF_NAMESPACE_ID::Any* temp = value_;
+  value_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  if (GetArenaForAllocation() == nullptr) { delete old; }
+#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
+  if (GetArenaForAllocation() != nullptr) {
     temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
   }
+#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
   return temp;
 }
 inline PROTOBUF_NAMESPACE_ID::Any* Option::unsafe_arena_release_value() {
@@ -2754,23 +2432,26 @@
 inline PROTOBUF_NAMESPACE_ID::Any* Option::_internal_mutable_value() {
   
   if (value_ == nullptr) {
-    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::Any>(GetArena());
+    auto* p = CreateMaybeMessage<PROTOBUF_NAMESPACE_ID::Any>(GetArenaForAllocation());
     value_ = p;
   }
   return value_;
 }
 inline PROTOBUF_NAMESPACE_ID::Any* Option::mutable_value() {
+  PROTOBUF_NAMESPACE_ID::Any* _msg = _internal_mutable_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.Option.value)
-  return _internal_mutable_value();
+  return _msg;
 }
 inline void Option::set_allocated_value(PROTOBUF_NAMESPACE_ID::Any* value) {
-  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
   if (message_arena == nullptr) {
     delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(value_);
   }
   if (value) {
     ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
-      reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(value)->GetArena();
+        ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<
+            ::PROTOBUF_NAMESPACE_ID::MessageLite>::GetOwningArena(
+                reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(value));
     if (message_arena != submessage_arena) {
       value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, value, submessage_arena);
diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto
index e4b1d3a..d3f6a68 100644
--- a/src/google/protobuf/type.proto
+++ b/src/google/protobuf/type.proto
@@ -41,7 +41,7 @@
 option java_outer_classname = "TypeProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
-option go_package = "google.golang.org/genproto/protobuf/ptype;ptype";
+option go_package = "google.golang.org/protobuf/types/known/typepb";
 
 // A protocol buffer message type.
 message Type {
@@ -113,7 +113,7 @@
     CARDINALITY_REQUIRED = 2;
     // For repeated fields.
     CARDINALITY_REPEATED = 3;
-  };
+  }
 
   // The field type.
   Kind kind = 1;
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index a4d5045..0925165 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -364,6 +364,12 @@
   }
 }
 
+message TestChildExtension {
+  optional string a = 1;
+  optional string b = 2;
+  optional TestAllExtensions optional_extension = 3;
+}
+
 // We have separate messages for testing required fields because it's
 // annoying to have to fill in required fields in TestProto in order to
 // do anything with it.  Note that we don't need to test every type of
@@ -746,6 +752,10 @@
     string bar_string_piece = 15 [ctype=STRING_PIECE, default = "SPIECE"];
     bytes bar_bytes = 16 [default = "BYTES"];
     NestedEnum bar_enum = 17 [default = BAR];
+    string bar_string_with_empty_default = 20 [default = ""];
+    string bar_cord_with_empty_default = 21 [ctype=CORD, default = ""];
+    string bar_string_piece_with_empty_default = 22 [ctype=STRING_PIECE, default = ""];
+    bytes bar_bytes_with_empty_default = 23 [default = ""];
   }
 
   optional int32 baz_int = 18;
@@ -1115,3 +1125,33 @@
   ENUM_LABEL_99 = 99;
   ENUM_LABEL_100 = 100;
 };
+
+message TestExtensionRangeSerialize {
+  optional int32 foo_one = 1;
+
+  extensions 2 to 2;
+  extensions 3 to 4;
+
+  optional int32 foo_two = 6;
+  optional int32 foo_three = 7;
+
+  extensions 9 to 10;
+
+  optional int32 foo_four = 13;
+
+  extensions 15 to 15;
+  extensions 17 to 17;
+  extensions 19 to 19;
+
+  extend TestExtensionRangeSerialize {
+    optional int32 bar_one = 2;
+    optional int32 bar_two = 4;
+
+    optional int32 bar_three = 10;
+
+    optional int32 bar_four = 15;
+    optional int32 bar_five = 19;
+  }
+}
+
+
diff --git a/src/google/protobuf/unittest_arena.proto b/src/google/protobuf/unittest_arena.proto
index cd7e437..7b31739 100644
--- a/src/google/protobuf/unittest_arena.proto
+++ b/src/google/protobuf/unittest_arena.proto
@@ -30,8 +30,6 @@
 
 syntax = "proto2";
 
-import "google/protobuf/unittest_no_arena_import.proto";
-
 package proto2_arena_unittest;
 
 option cc_enable_arenas = true;
@@ -41,6 +39,5 @@
 }
 
 message ArenaMessage {
-  repeated NestedMessage  repeated_nested_message = 1;
-  repeated ImportNoArenaNestedMessage  repeated_import_no_arena_message = 2;
-};
+  repeated NestedMessage repeated_nested_message = 1;
+}
diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto
index 50bb996..f774c76 100644
--- a/src/google/protobuf/unittest_custom_options.proto
+++ b/src/google/protobuf/unittest_custom_options.proto
@@ -45,6 +45,7 @@
 // A custom file option (defined below).
 option (file_opt1) = 9876543210;
 
+import "google/protobuf/any.proto";
 import "google/protobuf/descriptor.proto";
 
 // We don't put this in a package within proto2 because we need to make sure
@@ -329,6 +330,9 @@
 
   // An embedded message set
   optional AggregateMessageSet mset = 5;
+
+  // An any
+  optional google.protobuf.Any any = 6;
 }
 
 // Allow Aggregate to be used as an option at all possible locations
@@ -376,6 +380,12 @@
       s: 'EmbeddedMessageSetElement'
     }
   }
+
+  any {
+    [type.googleapis.com/protobuf_unittest.AggregateMessageSetElement] {
+      s: 'EmbeddedMessageSetElement'
+    }
+  }
 };
 
 message AggregateMessage {
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index 4c3d845..92282a6 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -38,7 +38,7 @@
 
 import "google/protobuf/unittest_import_lite.proto";
 
-option cc_enable_arenas = false;
+option cc_enable_arenas = true;
 option optimize_for = LITE_RUNTIME;
 option java_package = "com.google.protobuf";
 
@@ -49,6 +49,10 @@
     optional int64 cc = 2;
   }
 
+  message NestedMessage2 {
+    optional int32 dd = 1;
+  }
+
   enum NestedEnum {
     FOO = 1;
     BAR = 2;
@@ -163,6 +167,7 @@
     string oneof_string = 113;
     bytes oneof_bytes = 114;
     NestedMessage oneof_lazy_nested_message = 115 [lazy = true];
+    NestedMessage2 oneof_nested_message2 = 117;
   }
 
   // Tests toString for non-repeated fields with a list suffix
@@ -489,3 +494,8 @@
     BAR2 = 2;
   }
 }
+
+message RecursiveMessage {
+  optional RecursiveMessage recurse = 1;
+  optional bytes payload = 2;
+}
diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto
deleted file mode 100644
index adc8656..0000000
--- a/src/google/protobuf/unittest_no_arena.proto
+++ /dev/null
@@ -1,206 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// This proto file contains copies of TestAllTypes and friends, but with arena
-// support disabled in code generation. It allows us to test the performance
-// impact against baseline (non-arena) google.protobuf.
-
-syntax = "proto2";
-
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;     // auto-added
-option cc_enable_arenas = false;
-option objc_class_prefix = "NOARN";
-
-import "google/protobuf/unittest_import.proto";
-import "google/protobuf/unittest_arena.proto";
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do "using namespace unittest = protobuf_unittest".
-package protobuf_unittest_no_arena;
-
-// Protos optimized for SPEED use a strict superset of the generated code
-// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
-// tests for speed unless explicitly testing code size optimization.
-option optimize_for = SPEED;
-
-option java_outer_classname = "UnittestProto";
-
-// This proto includes every type of field in both singular and repeated
-// forms.
-message TestAllTypes {
-  message NestedMessage {
-    // The field name "b" fails to compile in proto1 because it conflicts with
-    // a local variable named "b" in one of the generated methods.  Doh.
-    // This file needs to compile in proto1 to test backwards-compatibility.
-    optional int32 bb = 1;
-  }
-
-  enum NestedEnum {
-    FOO = 1;
-    BAR = 2;
-    BAZ = 3;
-    NEG = -1;  // Intentionally negative.
-  }
-
-  // Singular
-  optional    int32 optional_int32    =  1;
-  optional    int64 optional_int64    =  2;
-  optional   uint32 optional_uint32   =  3;
-  optional   uint64 optional_uint64   =  4;
-  optional   sint32 optional_sint32   =  5;
-  optional   sint64 optional_sint64   =  6;
-  optional  fixed32 optional_fixed32  =  7;
-  optional  fixed64 optional_fixed64  =  8;
-  optional sfixed32 optional_sfixed32 =  9;
-  optional sfixed64 optional_sfixed64 = 10;
-  optional    float optional_float    = 11;
-  optional   double optional_double   = 12;
-  optional     bool optional_bool     = 13;
-  optional   string optional_string   = 14;
-  optional    bytes optional_bytes    = 15;
-
-  optional group OptionalGroup = 16 {
-    optional int32 a = 17;
-  }
-
-  optional NestedMessage                        optional_nested_message  = 18;
-  optional ForeignMessage                       optional_foreign_message = 19;
-  optional protobuf_unittest_import.ImportMessage optional_import_message  = 20;
-
-  optional NestedEnum                           optional_nested_enum     = 21;
-  optional ForeignEnum                          optional_foreign_enum    = 22;
-  optional protobuf_unittest_import.ImportEnum    optional_import_enum     = 23;
-
-  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
-  optional string optional_cord = 25 [ctype=CORD];
-
-  // Defined in unittest_import_public.proto
-  optional protobuf_unittest_import.PublicImportMessage
-      optional_public_import_message = 26;
-
-  optional NestedMessage optional_message = 27 [lazy=true];
-
-  // Repeated
-  repeated    int32 repeated_int32    = 31;
-  repeated    int64 repeated_int64    = 32;
-  repeated   uint32 repeated_uint32   = 33;
-  repeated   uint64 repeated_uint64   = 34;
-  repeated   sint32 repeated_sint32   = 35;
-  repeated   sint64 repeated_sint64   = 36;
-  repeated  fixed32 repeated_fixed32  = 37;
-  repeated  fixed64 repeated_fixed64  = 38;
-  repeated sfixed32 repeated_sfixed32 = 39;
-  repeated sfixed64 repeated_sfixed64 = 40;
-  repeated    float repeated_float    = 41;
-  repeated   double repeated_double   = 42;
-  repeated     bool repeated_bool     = 43;
-  repeated   string repeated_string   = 44;
-  repeated    bytes repeated_bytes    = 45;
-
-  repeated group RepeatedGroup = 46 {
-    optional int32 a = 47;
-  }
-
-  repeated NestedMessage                        repeated_nested_message  = 48;
-  repeated ForeignMessage                       repeated_foreign_message = 49;
-  repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
-
-  repeated NestedEnum                           repeated_nested_enum     = 51;
-  repeated ForeignEnum                          repeated_foreign_enum    = 52;
-  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
-
-  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord = 55 [ctype=CORD];
-
-  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
-
-  // Singular with defaults
-  optional    int32 default_int32    = 61 [default =  41    ];
-  optional    int64 default_int64    = 62 [default =  42    ];
-  optional   uint32 default_uint32   = 63 [default =  43    ];
-  optional   uint64 default_uint64   = 64 [default =  44    ];
-  optional   sint32 default_sint32   = 65 [default = -45    ];
-  optional   sint64 default_sint64   = 66 [default =  46    ];
-  optional  fixed32 default_fixed32  = 67 [default =  47    ];
-  optional  fixed64 default_fixed64  = 68 [default =  48    ];
-  optional sfixed32 default_sfixed32 = 69 [default =  49    ];
-  optional sfixed64 default_sfixed64 = 70 [default = -50    ];
-  optional    float default_float    = 71 [default =  51.5  ];
-  optional   double default_double   = 72 [default =  52e3  ];
-  optional     bool default_bool     = 73 [default = true   ];
-  optional   string default_string   = 74 [default = "hello"];
-  optional    bytes default_bytes    = 75 [default = "world"];
-
-  optional NestedEnum  default_nested_enum  = 81 [default = BAR        ];
-  optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
-  optional protobuf_unittest_import.ImportEnum
-      default_import_enum = 83 [default = IMPORT_BAR];
-
-  optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
-  optional string default_cord = 85 [ctype=CORD,default="123"];
-
-  // For oneof test
-  oneof oneof_field {
-    uint32 oneof_uint32 = 111;
-    NestedMessage oneof_nested_message = 112;
-    string oneof_string = 113;
-    bytes oneof_bytes = 114;
-    NestedMessage lazy_oneof_nested_message = 115 [lazy=true];
-  }
-}
-
-// Define these after TestAllTypes to make sure the compiler can handle
-// that.
-message ForeignMessage {
-  optional int32 c = 1;
-}
-
-enum ForeignEnum {
-  FOREIGN_FOO = 4;
-  FOREIGN_BAR = 5;
-  FOREIGN_BAZ = 6;
-}
-
-message TestNoArenaMessage {
-  optional proto2_arena_unittest.ArenaMessage arena_message = 1;
-};
-
-message OneString {
-  optional string data = 1;
-}
diff --git a/src/google/protobuf/unittest_no_arena_lite.proto b/src/google/protobuf/unittest_no_arena_lite.proto
deleted file mode 100644
index 58d8553..0000000
--- a/src/google/protobuf/unittest_no_arena_lite.proto
+++ /dev/null
@@ -1,44 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-// We don't put this in a package within proto2 because we need to make sure
-// that the generated code doesn't depend on being in the proto2 namespace.
-// In test_util.h we do "using namespace unittest = protobuf_unittest".
-package protobuf_unittest_no_arena;
-
-option cc_enable_arenas = false;
-
-message ForeignMessageLite {
-  optional int32 c = 1;
-}
diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
index fa26488..1752939 100644
--- a/src/google/protobuf/unittest_proto3_arena.proto
+++ b/src/google/protobuf/unittest_proto3_arena.proto
@@ -116,6 +116,23 @@
   repeated   string repeated_string   = 44;
   repeated    bytes repeated_bytes    = 45;
 
+  // Optional
+  optional    int32 proto3_optional_int32    = 116;
+  optional    int64 proto3_optional_int64    = 117;
+  optional   uint32 proto3_optional_uint32   = 118;
+  optional   uint64 proto3_optional_uint64   = 119;
+  optional   sint32 proto3_optional_sint32   = 120;
+  optional   sint64 proto3_optional_sint64   = 121;
+  optional  fixed32 proto3_optional_fixed32  = 122;
+  optional  fixed64 proto3_optional_fixed64  = 123;
+  optional sfixed32 proto3_optional_sfixed32 = 124;
+  optional sfixed64 proto3_optional_sfixed64 = 125;
+  optional    float proto3_optional_float    = 126;
+  optional   double proto3_optional_double   = 127;
+  optional     bool proto3_optional_bool     = 128;
+  optional   string proto3_optional_string   = 129;
+  optional    bytes proto3_optional_bytes    = 130;
+
   // Groups are not allowed in proto3.
   // repeated group RepeatedGroup = 46 {
   //   optional int32 a = 47;
diff --git a/src/google/protobuf/unittest_proto3_optional.proto b/src/google/protobuf/unittest_proto3_optional.proto
index b32a5d2..09d1718 100644
--- a/src/google/protobuf/unittest_proto3_optional.proto
+++ b/src/google/protobuf/unittest_proto3_optional.proto
@@ -32,6 +32,8 @@
 
 package protobuf_unittest;
 
+import "google/protobuf/descriptor.proto";
+
 option java_multiple_files = true;
 option java_package = "com.google.protobuf.testing.proto";
 
@@ -72,4 +74,27 @@
   optional NestedMessage optional_nested_message = 18;
   optional NestedMessage lazy_nested_message = 19 [lazy = true];
   optional NestedEnum optional_nested_enum = 21;
+
+  // Add some non-optional fields to verify we can mix them.
+  int32 singular_int32 = 22;
+  int64 singular_int64 = 23;
+}
+
+message TestProto3OptionalMessage {
+  message NestedMessage {
+    string s = 1;
+  }
+
+  NestedMessage nested_message = 1;
+  optional NestedMessage optional_nested_message = 2;
+}
+
+message Proto3OptionalExtensions {
+  option (protobuf_unittest.Proto3OptionalExtensions.ext_no_optional) = 8;
+  option (protobuf_unittest.Proto3OptionalExtensions.ext_with_optional) = 16;
+
+  extend google.protobuf.MessageOptions {
+    int32 ext_no_optional = 355886728;
+    optional int32 ext_with_optional = 355886729;
+  }
 }
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 451209c..1e81116 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -37,11 +37,14 @@
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_tctable_decl.h>
+#include <google/protobuf/generated_message_tctable_impl.h>
 #include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
 #include <google/protobuf/stubs/stl_util.h>
 
 #include <google/protobuf/port_def.inc>
@@ -108,8 +111,7 @@
 
   size_t total_size = sizeof(fields_) + sizeof(UnknownField) * fields_.size();
 
-  for (int i = 0; i < fields_.size(); i++) {
-    const UnknownField& field = (fields_)[i];
+  for (const UnknownField& field : fields_) {
     switch (field.type()) {
       case UnknownField::TYPE_LENGTH_DELIMITED:
         total_size += sizeof(*field.data_.length_delimited_.string_value) +
@@ -184,7 +186,7 @@
     (fields_)[i + start].Delete();
   }
   // Slide down the remaining fields.
-  for (int i = start + num; i < fields_.size(); ++i) {
+  for (size_t i = start + num; i < fields_.size(); ++i) {
     (fields_)[i - num] = (fields_)[i];
   }
   // Pop off the # of deleted fields.
@@ -194,8 +196,8 @@
 }
 
 void UnknownFieldSet::DeleteByNumber(int number) {
-  int left = 0;  // The number of fields left after deletion.
-  for (int i = 0; i < fields_.size(); ++i) {
+  size_t left = 0;  // The number of fields left after deletion.
+  for (size_t i = 0; i < fields_.size(); ++i) {
     UnknownField* field = &(fields_)[i];
     if (field->number() == number) {
       field->Delete();
@@ -325,3 +327,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index 0083208..bc8db5f 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -37,6 +37,8 @@
 
 #include <google/protobuf/unknown_field_set.h>
 
+#include <unordered_set>
+
 #include <google/protobuf/stubs/callback.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
@@ -113,30 +115,32 @@
 namespace {
 
 TEST_F(UnknownFieldSetTest, AllFieldsPresent) {
-  // All fields of TestAllTypes should be present, in numeric order (because
-  // that's the order we parsed them in).  Fields that are not valid field
-  // numbers of TestAllTypes should NOT be present.
+  // Verifies the following:
+  // --all unknown tags belong to TestAllTypes.
+  // --all fields in TestAllTypes is present in UnknownFieldSet except unset
+  //   oneof fields.
+  //
+  // Should handle repeated fields that may appear multiple times in
+  // UnknownFieldSet.
 
-  int pos = 0;
-
-  for (int i = 0; i < 1000; i++) {
-    const FieldDescriptor* field = descriptor_->FindFieldByNumber(i);
-    if (field != NULL) {
-      ASSERT_LT(pos, unknown_fields_->field_count());
-      // Do not check oneof field if it is not set.
-      if (field->containing_oneof() == NULL) {
-        EXPECT_EQ(i, unknown_fields_->field(pos++).number());
-      } else if (i == unknown_fields_->field(pos).number()) {
-        pos++;
-      }
-      if (field->is_repeated()) {
-        // Should have a second instance.
-        ASSERT_LT(pos, unknown_fields_->field_count());
-        EXPECT_EQ(i, unknown_fields_->field(pos++).number());
-      }
+  int non_oneof_count = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      non_oneof_count++;
     }
   }
-  EXPECT_EQ(unknown_fields_->field_count(), pos);
+
+  std::unordered_set<uint32> unknown_tags;
+  for (int i = 0; i < unknown_fields_->field_count(); i++) {
+    unknown_tags.insert(unknown_fields_->field(i).number());
+  }
+
+  for (uint32 t : unknown_tags) {
+    EXPECT_NE(descriptor_->FindFieldByNumber(t), nullptr);
+  }
+
+  EXPECT_EQ(non_oneof_count + descriptor_->oneof_decl_count(),
+            unknown_tags.size());
 }
 
 TEST_F(UnknownFieldSetTest, Varint) {
@@ -246,7 +250,7 @@
   {
     io::StringOutputStream raw_output(&data);
     io::CodedOutputStream output(&raw_output);
-    int size = WireFormat::ByteSize(empty_message_);
+    size_t size = WireFormat::ByteSize(empty_message_);
     WireFormat::SerializeWithCachedSizes(empty_message_, size, &output);
     ASSERT_FALSE(output.HadError());
   }
@@ -536,29 +540,29 @@
 
   // Make sure an unknown field set has zero space used until a field is
   // actually added.
-  int base_size = empty_message.SpaceUsed();
+  size_t base_size = empty_message.SpaceUsedLong();
   UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields();
-  EXPECT_EQ(base_size, empty_message.SpaceUsed());
+  EXPECT_EQ(base_size, empty_message.SpaceUsedLong());
 
-  // Make sure each thing we add to the set increases the SpaceUsed().
+  // Make sure each thing we add to the set increases the SpaceUsedLong().
   unknown_fields->AddVarint(1, 0);
-  EXPECT_LT(base_size, empty_message.SpaceUsed());
-  base_size = empty_message.SpaceUsed();
+  EXPECT_LT(base_size, empty_message.SpaceUsedLong());
+  base_size = empty_message.SpaceUsedLong();
 
   std::string* str = unknown_fields->AddLengthDelimited(1);
-  EXPECT_LT(base_size, empty_message.SpaceUsed());
-  base_size = empty_message.SpaceUsed();
+  EXPECT_LT(base_size, empty_message.SpaceUsedLong());
+  base_size = empty_message.SpaceUsedLong();
 
   str->assign(sizeof(std::string) + 1, 'x');
-  EXPECT_LT(base_size, empty_message.SpaceUsed());
-  base_size = empty_message.SpaceUsed();
+  EXPECT_LT(base_size, empty_message.SpaceUsedLong());
+  base_size = empty_message.SpaceUsedLong();
 
   UnknownFieldSet* group = unknown_fields->AddGroup(1);
-  EXPECT_LT(base_size, empty_message.SpaceUsed());
-  base_size = empty_message.SpaceUsed();
+  EXPECT_LT(base_size, empty_message.SpaceUsedLong());
+  base_size = empty_message.SpaceUsedLong();
 
   group->AddVarint(1, 0);
-  EXPECT_LT(base_size, empty_message.SpaceUsed());
+  EXPECT_LT(base_size, empty_message.SpaceUsedLong());
 }
 
 
diff --git a/src/google/protobuf/util/delimited_message_util.cc b/src/google/protobuf/util/delimited_message_util.cc
index 425dc2c..80cab30 100644
--- a/src/google/protobuf/util/delimited_message_util.cc
+++ b/src/google/protobuf/util/delimited_message_util.cc
@@ -74,12 +74,18 @@
     return false;
   }
 
+  // Get the position after any size bytes have been read (and only the message
+  // itself remains).
+  int position_after_size = input->CurrentPosition();
+
   // Tell the stream not to read beyond that size.
   io::CodedInputStream::Limit limit = input->PushLimit(size);
 
   // Parse the message.
   if (!message->MergeFromCodedStream(input)) return false;
   if (!input->ConsumedEntireMessage()) return false;
+  if (input->CurrentPosition() - position_after_size != static_cast<int>(size))
+    return false;
 
   // Release the limit.
   input->PopLimit(limit);
diff --git a/src/google/protobuf/util/delimited_message_util_test.cc b/src/google/protobuf/util/delimited_message_util_test.cc
index 9ed6778..9483a64 100644
--- a/src/google/protobuf/util/delimited_message_util_test.cc
+++ b/src/google/protobuf/util/delimited_message_util_test.cc
@@ -82,6 +82,35 @@
   }
 }
 
+TEST(DelimitedMessageUtilTest, FailsAtEndOfStream) {
+  std::stringstream full_stream;
+  std::stringstream partial_stream;
+
+  {
+    protobuf_unittest::ForeignMessage message;
+    message.set_c(42);
+    message.set_d(24);
+    EXPECT_TRUE(SerializeDelimitedToOstream(message, &full_stream));
+
+    std::string full_output = full_stream.str();
+    ASSERT_GT(full_output.size(), size_t{2});
+    ASSERT_EQ(full_output[0], 4);
+
+    partial_stream << full_output[0] << full_output[1] << full_output[2];
+  }
+
+  {
+    bool clean_eof;
+    io::IstreamInputStream zstream(&partial_stream);
+
+    protobuf_unittest::ForeignMessage message;
+    clean_eof = true;
+    EXPECT_FALSE(ParseDelimitedFromZeroCopyStream(&message,
+        &zstream, &clean_eof));
+    EXPECT_FALSE(clean_eof);
+  }
+}
+
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
index 54abcd4..46d5dba 100644
--- a/src/google/protobuf/util/field_comparator.cc
+++ b/src/google/protobuf/util/field_comparator.cc
@@ -48,14 +48,14 @@
 FieldComparator::FieldComparator() {}
 FieldComparator::~FieldComparator() {}
 
-DefaultFieldComparator::DefaultFieldComparator()
+SimpleFieldComparator::SimpleFieldComparator()
     : float_comparison_(EXACT),
       treat_nan_as_equal_(false),
       has_default_tolerance_(false) {}
 
-DefaultFieldComparator::~DefaultFieldComparator() {}
+SimpleFieldComparator::~SimpleFieldComparator() {}
 
-FieldComparator::ComparisonResult DefaultFieldComparator::Compare(
+FieldComparator::ComparisonResult SimpleFieldComparator::SimpleCompare(
     const Message& message_1, const Message& message_2,
     const FieldDescriptor* field, int index_1, int index_2,
     const util::FieldContext* field_context) {
@@ -127,23 +127,22 @@
   }
 }
 
-bool DefaultFieldComparator::Compare(MessageDifferencer* differencer,
-                                     const Message& message1,
-                                     const Message& message2,
-                                     const util::FieldContext* field_context) {
+bool SimpleFieldComparator::CompareWithDifferencer(
+    MessageDifferencer* differencer, const Message& message1,
+    const Message& message2, const util::FieldContext* field_context) {
   return differencer->Compare(message1, message2,
                               field_context->parent_fields());
 }
 
-void DefaultFieldComparator::SetDefaultFractionAndMargin(double fraction,
-                                                         double margin) {
+void SimpleFieldComparator::SetDefaultFractionAndMargin(double fraction,
+                                                        double margin) {
   default_tolerance_ = Tolerance(fraction, margin);
   has_default_tolerance_ = true;
 }
 
-void DefaultFieldComparator::SetFractionAndMargin(const FieldDescriptor* field,
-                                                  double fraction,
-                                                  double margin) {
+void SimpleFieldComparator::SetFractionAndMargin(const FieldDescriptor* field,
+                                                 double fraction,
+                                                 double margin) {
   GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() ||
         FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type())
       << "Field has to be float or double type. Field name is: "
@@ -151,25 +150,25 @@
   map_tolerance_[field] = Tolerance(fraction, margin);
 }
 
-bool DefaultFieldComparator::CompareDouble(const FieldDescriptor& field,
-                                           double value_1, double value_2) {
+bool SimpleFieldComparator::CompareDouble(const FieldDescriptor& field,
+                                          double value_1, double value_2) {
   return CompareDoubleOrFloat(field, value_1, value_2);
 }
 
-bool DefaultFieldComparator::CompareEnum(const FieldDescriptor& field,
-                                         const EnumValueDescriptor* value_1,
-                                         const EnumValueDescriptor* value_2) {
+bool SimpleFieldComparator::CompareEnum(const FieldDescriptor& field,
+                                        const EnumValueDescriptor* value_1,
+                                        const EnumValueDescriptor* value_2) {
   return value_1->number() == value_2->number();
 }
 
-bool DefaultFieldComparator::CompareFloat(const FieldDescriptor& field,
-                                          float value_1, float value_2) {
+bool SimpleFieldComparator::CompareFloat(const FieldDescriptor& field,
+                                         float value_1, float value_2) {
   return CompareDoubleOrFloat(field, value_1, value_2);
 }
 
 template <typename T>
-bool DefaultFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field,
-                                                  T value_1, T value_2) {
+bool SimpleFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field,
+                                                 T value_1, T value_2) {
   if (value_1 == value_2) {
     // Covers +inf and -inf (which are not within margin or fraction of
     // themselves), and is a shortcut for finite values.
@@ -201,7 +200,7 @@
   }
 }
 
-FieldComparator::ComparisonResult DefaultFieldComparator::ResultFromBoolean(
+FieldComparator::ComparisonResult SimpleFieldComparator::ResultFromBoolean(
     bool boolean_result) const {
   return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT;
 }
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
index 7b5ce52..dd1a486 100644
--- a/src/google/protobuf/util/field_comparator.h
+++ b/src/google/protobuf/util/field_comparator.h
@@ -33,12 +33,12 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
 #define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
-
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -97,7 +97,7 @@
 // Basic implementation of FieldComparator.  Supports three modes of floating
 // point value comparison: exact, approximate using MathUtil::AlmostEqual
 // method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
-class PROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator {
+class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
  public:
   enum FloatComparison {
     EXACT,        // Floats and doubles are compared exactly.
@@ -109,14 +109,9 @@
   };
 
   // Creates new comparator with float comparison set to EXACT.
-  DefaultFieldComparator();
+  SimpleFieldComparator();
 
-  ~DefaultFieldComparator() override;
-
-  ComparisonResult Compare(const Message& message_1, const Message& message_2,
-                           const FieldDescriptor* field, int index_1,
-                           int index_2,
-                           const util::FieldContext* field_context) override;
+  ~SimpleFieldComparator() override;
 
   void set_float_comparison(FloatComparison float_comparison) {
     float_comparison_ = float_comparison;
@@ -151,12 +146,27 @@
   void SetDefaultFractionAndMargin(double fraction, double margin);
 
  protected:
+  // Returns the comparison result for the given field in two messages.
+  //
+  // This function is called directly by DefaultFieldComparator::Compare.
+  // Subclasses can call this function to compare fields they do not need to
+  // handle specially.
+  ComparisonResult SimpleCompare(const Message& message_1,
+                                 const Message& message_2,
+                                 const FieldDescriptor* field, int index_1,
+                                 int index_2,
+                                 const util::FieldContext* field_context);
+
   // Compare using the provided message_differencer. For example, a subclass can
   // use this method to compare some field in a certain way using the same
   // message_differencer instance and the field context.
-  bool Compare(MessageDifferencer* differencer, const Message& message1,
-               const Message& message2,
-               const util::FieldContext* field_context);
+  bool CompareWithDifferencer(MessageDifferencer* differencer,
+                              const Message& message1, const Message& message2,
+                              const util::FieldContext* field_context);
+
+  // Returns FieldComparator::SAME if boolean_result is true and
+  // FieldComparator::DIFFERENT otherwise.
+  ComparisonResult ResultFromBoolean(bool boolean_result) const;
 
  private:
   // Defines the tolerance for floating point comparison (fraction and margin).
@@ -170,6 +180,7 @@
   // Defines the map to store the tolerances for floating point comparison.
   typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap;
 
+  friend class MessageDifferencer;
   // The following methods get executed when CompareFields is called for the
   // basic types (instead of submessages). They return true on success. One
   // can use ResultFromBoolean() to convert that boolean to a ComparisonResult
@@ -192,13 +203,13 @@
   // CompareFloat.
   bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2);
 
-  bool CompareInt32(const FieldDescriptor& /* unused */, int32 value_1,
-                    int32 value_2) {
+  bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1,
+                    int32_t value_2) {
     return value_1 == value_2;
   }
 
-  bool CompareInt64(const FieldDescriptor& /* unused */, int64 value_1,
-                    int64 value_2) {
+  bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1,
+                    int64_t value_2) {
     return value_1 == value_2;
   }
 
@@ -207,13 +218,13 @@
     return value_1 == value_2;
   }
 
-  bool CompareUInt32(const FieldDescriptor& /* unused */, uint32 value_1,
-                     uint32 value_2) {
+  bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1,
+                     uint32_t value_2) {
     return value_1 == value_2;
   }
 
-  bool CompareUInt64(const FieldDescriptor& /* unused */, uint64 value_1,
-                     uint64 value_2) {
+  bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1,
+                     uint64_t value_2) {
     return value_1 == value_2;
   }
 
@@ -223,10 +234,6 @@
   template <typename T>
   bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2);
 
-  // Returns FieldComparator::SAME if boolean_result is true and
-  // FieldComparator::DIFFERENT otherwise.
-  ComparisonResult ResultFromBoolean(bool boolean_result) const;
-
   FloatComparison float_comparison_;
 
   // If true, floats and doubles that are both NaN are considered to be
@@ -248,7 +255,25 @@
   // those particular fields.
   ToleranceMap map_tolerance_;
 
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator);
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleFieldComparator);
+};
+
+// Default field comparison: use the basic implementation of FieldComparator.
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+class PROTOBUF_EXPORT DefaultFieldComparator final
+    : public SimpleFieldComparator
+#else   // PROTOBUF_FUTURE_BREAKING_CHANGES
+class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator
+#endif  // PROTOBUF_FUTURE_BREAKING_CHANGES
+{
+ public:
+  ComparisonResult Compare(const Message& message_1, const Message& message_2,
+                           const FieldDescriptor* field, int index_1,
+                           int index_2,
+                           const util::FieldContext* field_context) override {
+    return SimpleCompare(message_1, message_2, field, index_1, index_2,
+                         field_context);
+  }
 };
 
 }  // namespace util
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index 547a4dc..646f807 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -30,10 +30,13 @@
 
 #include <google/protobuf/util/field_mask_util.h>
 
+#include <cstdint>
+
 #include <google/protobuf/message.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -49,9 +52,9 @@
 void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
   out->Clear();
   std::vector<std::string> paths = Split(str, ",");
-  for (int i = 0; i < paths.size(); ++i) {
-    if (paths[i].empty()) continue;
-    out->add_paths(paths[i]);
+  for (const std::string& path : paths) {
+    if (path.empty()) continue;
+    out->add_paths(path);
   }
 }
 
@@ -59,23 +62,23 @@
                                          std::string* output) {
   output->clear();
   bool after_underscore = false;
-  for (int i = 0; i < input.size(); ++i) {
-    if (input[i] >= 'A' && input[i] <= 'Z') {
+  for (const char& input_char : input) {
+    if (input_char >= 'A' && input_char <= 'Z') {
       // The field name must not contain uppercase letters.
       return false;
     }
     if (after_underscore) {
-      if (input[i] >= 'a' && input[i] <= 'z') {
-        output->push_back(input[i] + 'A' - 'a');
+      if (input_char >= 'a' && input_char <= 'z') {
+        output->push_back(input_char + 'A' - 'a');
         after_underscore = false;
       } else {
         // The character after a "_" must be a lowercase letter.
         return false;
       }
-    } else if (input[i] == '_') {
+    } else if (input_char == '_') {
       after_underscore = true;
     } else {
-      output->push_back(input[i]);
+      output->push_back(input_char);
     }
   }
   if (after_underscore) {
@@ -88,16 +91,16 @@
 bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input,
                                          std::string* output) {
   output->clear();
-  for (int i = 0; i < input.size(); ++i) {
-    if (input[i] == '_') {
+  for (const char c : input) {
+    if (c == '_') {
       // The field name must not contain "_"s.
       return false;
     }
-    if (input[i] >= 'A' && input[i] <= 'Z') {
+    if (c >= 'A' && c <= 'Z') {
       output->push_back('_');
-      output->push_back(input[i] + 'a' - 'A');
+      output->push_back(c + 'a' - 'A');
     } else {
-      output->push_back(input[i]);
+      output->push_back(c);
     }
   }
   return true;
@@ -122,10 +125,10 @@
 bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
   out->Clear();
   std::vector<std::string> paths = Split(str, ",");
-  for (int i = 0; i < paths.size(); ++i) {
-    if (paths[i].empty()) continue;
+  for (const std::string& path : paths) {
+    if (path.empty()) continue;
     std::string snakecase_path;
-    if (!CamelCaseToSnakeCase(paths[i], &snakecase_path)) {
+    if (!CamelCaseToSnakeCase(path, &snakecase_path)) {
       return false;
     }
     out->add_paths(snakecase_path);
@@ -140,8 +143,7 @@
     field_descriptors->clear();
   }
   std::vector<std::string> parts = Split(path, ".");
-  for (int i = 0; i < parts.size(); ++i) {
-    const std::string& field_name = parts[i];
+  for (const std::string& field_name : parts) {
     if (descriptor == nullptr) {
       return false;
     }
@@ -199,7 +201,7 @@
 
   // Remove a path from the tree.
   // If the path is a sub-path of an existing field path in the tree, it means
-  // we need remove the existing fied path and add all sub-paths except
+  // we need remove the existing field path and add all sub-paths except
   // specified path. If the path matches an existing node in the tree, this node
   // will be moved.
   void RemovePath(const std::string& path, const Descriptor* descriptor);
@@ -329,14 +331,13 @@
   }
   bool new_branch = false;
   Node* node = &root_;
-  for (int i = 0; i < parts.size(); ++i) {
+  for (const std::string& node_name : parts) {
     if (!new_branch && node != &root_ && node->children.empty()) {
       // Path matches an existing leaf node. This means the path is already
-      // coverred by this tree (for example, adding "foo.bar.baz" to a tree
+      // covered by this tree (for example, adding "foo.bar.baz" to a tree
       // which already contains "foo.bar").
       return;
     }
-    const std::string& node_name = parts[i];
     Node*& child = node->children[node_name];
     if (child == NULL) {
       new_branch = true;
@@ -414,14 +415,13 @@
     return;
   }
   const Node* node = &root_;
-  for (int i = 0; i < parts.size(); ++i) {
+  for (const std::string& node_name : parts) {
     if (node->children.empty()) {
       if (node != &root_) {
         out->AddPath(path);
       }
       return;
     }
-    const std::string& node_name = parts[i];
     const Node* result = FindPtrOrNull(node->children, node_name);
     if (result == NULL) {
       // No intersection found.
@@ -552,7 +552,7 @@
 
 void FieldMaskTree::AddRequiredFieldPath(Node* node,
                                          const Descriptor* descriptor) {
-  const int32 field_count = descriptor->field_count();
+  const int32_t field_count = descriptor->field_count();
   for (int index = 0; index < field_count; ++index) {
     const FieldDescriptor* field = descriptor->field(index);
     if (field->is_required()) {
@@ -589,7 +589,7 @@
   GOOGLE_DCHECK(!node->children.empty());
   const Reflection* reflection = message->GetReflection();
   const Descriptor* descriptor = message->GetDescriptor();
-  const int32 field_count = descriptor->field_count();
+  const int32_t field_count = descriptor->field_count();
   bool modified = false;
   for (int index = 0; index < field_count; ++index) {
     const FieldDescriptor* field = descriptor->field(index);
@@ -707,7 +707,7 @@
   // fields.
   FieldMaskTree tree;
   tree.MergeFromFieldMask(mask);
-  // If keep_required_fields is true, implicitely add required fields of
+  // If keep_required_fields is true, implicitly add required fields of
   // a message present in the tree to prevent from trimming.
   if (options.keep_required_fields()) {
     tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(message->GetDescriptor()));
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
index ea6c5cc..84cd120 100644
--- a/src/google/protobuf/util/field_mask_util.h
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -33,6 +33,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
 #define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
 
+#include <cstdint>
 #include <string>
 
 #include <google/protobuf/field_mask.pb.h>
@@ -58,13 +59,14 @@
   // Populates the FieldMask with the paths corresponding to the fields with the
   // given numbers, after checking that all field numbers are valid.
   template <typename T>
-  static void FromFieldNumbers(const std::vector<int64>& field_numbers,
+  static void FromFieldNumbers(const std::vector<int64_t>& field_numbers,
                                FieldMask* out) {
     for (const auto field_number : field_numbers) {
       const FieldDescriptor* field_desc =
           T::descriptor()->FindFieldByNumber(field_number);
-      GOOGLE_CHECK(field_desc != nullptr) << "Invalid field number for "
-                                   << typeid(T).name() << ": " << field_number;
+      GOOGLE_CHECK(field_desc != nullptr)
+          << "Invalid field number for " << T::descriptor()->full_name() << ": "
+          << field_number;
       AddPathToFieldMask<T>(field_desc->lowercase_name(), out);
     }
   }
@@ -105,7 +107,7 @@
   template <typename T>
   static void AddPathToFieldMask(StringPiece path, FieldMask* mask) {
     GOOGLE_CHECK(IsValidPath<T>(path)) << path;
-    mask->add_paths(path);
+    mask->add_paths(std::string(path));
   }
 
   // Creates a FieldMask with all fields of type T. This FieldMask only
diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
index 5fe9f65..df5d087 100644
--- a/src/google/protobuf/util/field_mask_util_test.cc
+++ b/src/google/protobuf/util/field_mask_util_test.cc
@@ -31,14 +31,15 @@
 #include <google/protobuf/util/field_mask_util.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/field_mask.pb.h>
 #include <google/protobuf/test_util.h>
 #include <google/protobuf/unittest.pb.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
 
 namespace google {
 namespace protobuf {
@@ -46,7 +47,7 @@
 
 class SnakeCaseCamelCaseTest : public ::testing::Test {
  protected:
-  string SnakeCaseToCamelCase(const std::string& input) {
+  std::string SnakeCaseToCamelCase(const std::string& input) {
     std::string output;
     if (FieldMaskUtil::SnakeCaseToCamelCase(input, &output)) {
       return output;
@@ -55,7 +56,7 @@
     }
   }
 
-  string CamelCaseToSnakeCase(const std::string& input) {
+  std::string CamelCaseToSnakeCase(const std::string& input) {
     std::string output;
     if (FieldMaskUtil::CamelCaseToSnakeCase(input, &output)) {
       return output;
@@ -164,7 +165,7 @@
 
 TEST(FieldMaskUtilTest, FromFieldNumbers) {
   FieldMask mask;
-  std::vector<int64> field_numbers = {
+  std::vector<int64_t> field_numbers = {
       TestAllTypes::kOptionalInt64FieldNumber,
       TestAllTypes::kOptionalBoolFieldNumber,
       TestAllTypes::kRepeatedStringFieldNumber,
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
index 6acf970..65f1a34 100644
--- a/src/google/protobuf/util/internal/constants.h
+++ b/src/google/protobuf/util/internal/constants.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 
 // This file contains constants used by //net/proto2/util/converter.
@@ -49,20 +51,20 @@
 // timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z".
 const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
 
-// Minimun seconds allowed in a google.protobuf.Timestamp value.
-const int64 kTimestampMinSeconds = -62135596800LL;
+// Minimum seconds allowed in a google.protobuf.Timestamp value.
+const int64_t kTimestampMinSeconds = -62135596800LL;
 
 // Maximum seconds allowed in a google.protobuf.Timestamp value.
-const int64 kTimestampMaxSeconds = 253402300799LL;
+const int64_t kTimestampMaxSeconds = 253402300799LL;
 
 // Minimum seconds allowed in a google.protobuf.Duration value.
-const int64 kDurationMinSeconds = -315576000000LL;
+const int64_t kDurationMinSeconds = -315576000000LL;
 
 // Maximum seconds allowed in a google.protobuf.Duration value.
-const int64 kDurationMaxSeconds = 315576000000LL;
+const int64_t kDurationMaxSeconds = 315576000000LL;
 
 // Nano seconds in a second.
-const int32 kNanosPerSecond = 1000000000;
+const int32_t kNanosPerSecond = 1000000000;
 
 // Type url representing NULL values in google.protobuf.Struct type.
 const char kStructNullValueTypeUrl[] =
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index 0d88606..52c335d 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -31,12 +31,14 @@
 #include <google/protobuf/util/internal/datapiece.h>
 
 #include <cmath>
+#include <cstdint>
 #include <limits>
 
 #include <google/protobuf/struct.pb.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/mathutil.h>
 
@@ -46,26 +48,19 @@
 namespace converter {
 
 using util::Status;
-using util::StatusOr;
-using util::error::Code;
 
 namespace {
 
-inline Status InvalidArgument(StringPiece value_str) {
-  return Status(util::error::INVALID_ARGUMENT, value_str);
-}
-
 template <typename To, typename From>
-StatusOr<To> ValidateNumberConversion(To after, From before) {
+util::StatusOr<To> ValidateNumberConversion(To after, From before) {
   if (after == before &&
       MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
     return after;
   } else {
-    return InvalidArgument(std::is_integral<From>::value
-                               ? ValueAsString(before)
-                               : std::is_same<From, double>::value
-                                     ? DoubleAsString(before)
-                                     : FloatAsString(before));
+    return util::InvalidArgumentError(
+        std::is_integral<From>::value       ? ValueAsString(before)
+        : std::is_same<From, double>::value ? DoubleAsString(before)
+                                            : FloatAsString(before));
   }
 }
 
@@ -73,7 +68,7 @@
 //     int32, int64, uint32, uint64, double and float
 // except conversion between double and float.
 template <typename To, typename From>
-StatusOr<To> NumberConvertAndCheck(From before) {
+util::StatusOr<To> NumberConvertAndCheck(From before) {
   if (std::is_same<From, To>::value) return before;
 
   To after = static_cast<To>(before);
@@ -83,7 +78,7 @@
 // For conversion to integer types (int32, int64, uint32, uint64) from floating
 // point types (double, float) only.
 template <typename To, typename From>
-StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
+util::StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
   if (std::is_same<From, To>::value) return before;
 
   To after = static_cast<To>(before);
@@ -91,13 +86,13 @@
 }
 
 // For conversion between double and float only.
-StatusOr<double> FloatToDouble(float before) {
+util::StatusOr<double> FloatToDouble(float before) {
   // Casting float to double should just work as double has more precision
   // than float.
   return static_cast<double>(before);
 }
 
-StatusOr<float> DoubleToFloat(double before) {
+util::StatusOr<float> DoubleToFloat(double before) {
   if (std::isnan(before)) {
     return std::numeric_limits<float>::quiet_NaN();
   } else if (!std::isfinite(before)) {
@@ -106,7 +101,7 @@
   } else if (before > std::numeric_limits<float>::max() ||
              before < -std::numeric_limits<float>::max()) {
     // Double value outside of the range of float.
-    return InvalidArgument(DoubleAsString(before));
+    return util::InvalidArgumentError(DoubleAsString(before));
   } else {
     return static_cast<float>(before);
   }
@@ -114,57 +109,59 @@
 
 }  // namespace
 
-StatusOr<int32> DataPiece::ToInt32() const {
-  if (type_ == TYPE_STRING) return StringToNumber<int32>(safe_strto32);
-
-  if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<int32, double>(double_);
-
-  if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<int32, float>(float_);
-
-  return GenericConvert<int32>();
-}
-
-StatusOr<uint32> DataPiece::ToUint32() const {
+util::StatusOr<int32_t> DataPiece::ToInt32() const {
   if (type_ == TYPE_STRING)
-    return StringToNumber<uint32>(safe_strtou32);
+    return StringToNumber<int32_t>(safe_strto32);
 
   if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<uint32, double>(double_);
+    return FloatingPointToIntConvertAndCheck<int32_t, double>(double_);
 
   if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<uint32, float>(float_);
+    return FloatingPointToIntConvertAndCheck<int32_t, float>(float_);
 
-  return GenericConvert<uint32>();
+  return GenericConvert<int32_t>();
 }
 
-StatusOr<int64> DataPiece::ToInt64() const {
-  if (type_ == TYPE_STRING) return StringToNumber<int64>(safe_strto64);
-
-  if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<int64, double>(double_);
-
-  if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<int64, float>(float_);
-
-  return GenericConvert<int64>();
-}
-
-StatusOr<uint64> DataPiece::ToUint64() const {
+util::StatusOr<uint32_t> DataPiece::ToUint32() const {
   if (type_ == TYPE_STRING)
-    return StringToNumber<uint64>(safe_strtou64);
+    return StringToNumber<uint32_t>(safe_strtou32);
 
   if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<uint64, double>(double_);
+    return FloatingPointToIntConvertAndCheck<uint32_t, double>(double_);
 
   if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<uint64, float>(float_);
+    return FloatingPointToIntConvertAndCheck<uint32_t, float>(float_);
 
-  return GenericConvert<uint64>();
+  return GenericConvert<uint32_t>();
 }
 
-StatusOr<double> DataPiece::ToDouble() const {
+util::StatusOr<int64_t> DataPiece::ToInt64() const {
+  if (type_ == TYPE_STRING)
+    return StringToNumber<int64_t>(safe_strto64);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<int64_t, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<int64_t, float>(float_);
+
+  return GenericConvert<int64_t>();
+}
+
+util::StatusOr<uint64_t> DataPiece::ToUint64() const {
+  if (type_ == TYPE_STRING)
+    return StringToNumber<uint64_t>(safe_strtou64);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<uint64_t, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<uint64_t, float>(float_);
+
+  return GenericConvert<uint64_t>();
+}
+
+util::StatusOr<double> DataPiece::ToDouble() const {
   if (type_ == TYPE_FLOAT) {
     return FloatToDouble(float_);
   }
@@ -172,11 +169,11 @@
     if (str_ == "Infinity") return std::numeric_limits<double>::infinity();
     if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
     if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
-    StatusOr<double> value = StringToNumber<double>(safe_strtod);
+    util::StatusOr<double> value = StringToNumber<double>(safe_strtod);
     if (value.ok() && !std::isfinite(value.value())) {
       // safe_strtod converts out-of-range values to +inf/-inf, but we want
       // to report them as errors.
-      return InvalidArgument(StrCat("\"", str_, "\""));
+      return util::InvalidArgumentError(StrCat("\"", str_, "\""));
     } else {
       return value;
     }
@@ -184,7 +181,7 @@
   return GenericConvert<double>();
 }
 
-StatusOr<float> DataPiece::ToFloat() const {
+util::StatusOr<float> DataPiece::ToFloat() const {
   if (type_ == TYPE_DOUBLE) {
     return DoubleToFloat(double_);
   }
@@ -199,19 +196,19 @@
   return GenericConvert<float>();
 }
 
-StatusOr<bool> DataPiece::ToBool() const {
+util::StatusOr<bool> DataPiece::ToBool() const {
   switch (type_) {
     case TYPE_BOOL:
       return bool_;
     case TYPE_STRING:
       return StringToNumber<bool>(safe_strtob);
     default:
-      return InvalidArgument(
+      return util::InvalidArgumentError(
           ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
   }
 }
 
-StatusOr<std::string> DataPiece::ToString() const {
+util::StatusOr<std::string> DataPiece::ToString() const {
   switch (type_) {
     case TYPE_STRING:
       return std::string(str_);
@@ -221,7 +218,7 @@
       return base64;
     }
     default:
-      return InvalidArgument(
+      return util::InvalidArgumentError(
           ValueAsStringOrDefault("Cannot convert to string."));
   }
 }
@@ -257,25 +254,26 @@
   }
 }
 
-StatusOr<std::string> DataPiece::ToBytes() const {
+util::StatusOr<std::string> DataPiece::ToBytes() const {
   if (type_ == TYPE_BYTES) return str_.ToString();
   if (type_ == TYPE_STRING) {
     std::string decoded;
     if (!DecodeBase64(str_, &decoded)) {
-      return InvalidArgument(ValueAsStringOrDefault("Invalid data in input."));
+      return util::InvalidArgumentError(
+          ValueAsStringOrDefault("Invalid data in input."));
     }
     return decoded;
   } else {
-    return InvalidArgument(ValueAsStringOrDefault(
+    return util::InvalidArgumentError(ValueAsStringOrDefault(
         "Wrong type. Only String or Bytes can be converted to Bytes."));
   }
 }
 
-StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
-                                bool use_lower_camel_for_enums,
-                                bool case_insensitive_enum_parsing,
-                                bool ignore_unknown_enum_values,
-                                bool* is_unknown_enum_value) const {
+util::StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
+                                      bool use_lower_camel_for_enums,
+                                      bool case_insensitive_enum_parsing,
+                                      bool ignore_unknown_enum_values,
+                                      bool* is_unknown_enum_value) const {
   if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;
 
   if (type_ == TYPE_STRING) {
@@ -286,7 +284,7 @@
     if (value != nullptr) return value->number();
 
     // Check if int version of enum is sent as string.
-    StatusOr<int32> int_value = ToInt32();
+    util::StatusOr<int32_t> int_value = ToInt32();
     if (int_value.ok()) {
       if (const google::protobuf::EnumValue* enum_value =
               FindEnumValueByNumberOrNull(enum_type, int_value.value())) {
@@ -326,41 +324,42 @@
     // enum because we preserve unknown enum values as well.
     return ToInt32();
   }
-  return InvalidArgument(
+  return util::InvalidArgumentError(
       ValueAsStringOrDefault("Cannot find enum with given value."));
 }
 
 template <typename To>
-StatusOr<To> DataPiece::GenericConvert() const {
+util::StatusOr<To> DataPiece::GenericConvert() const {
   switch (type_) {
     case TYPE_INT32:
-      return NumberConvertAndCheck<To, int32>(i32_);
+      return NumberConvertAndCheck<To, int32_t>(i32_);
     case TYPE_INT64:
-      return NumberConvertAndCheck<To, int64>(i64_);
+      return NumberConvertAndCheck<To, int64_t>(i64_);
     case TYPE_UINT32:
-      return NumberConvertAndCheck<To, uint32>(u32_);
+      return NumberConvertAndCheck<To, uint32_t>(u32_);
     case TYPE_UINT64:
-      return NumberConvertAndCheck<To, uint64>(u64_);
+      return NumberConvertAndCheck<To, uint64_t>(u64_);
     case TYPE_DOUBLE:
       return NumberConvertAndCheck<To, double>(double_);
     case TYPE_FLOAT:
       return NumberConvertAndCheck<To, float>(float_);
     default:  // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL
-      return InvalidArgument(ValueAsStringOrDefault(
+      return util::InvalidArgumentError(ValueAsStringOrDefault(
           "Wrong type. Bool, Enum, String and Cord not supported in "
           "GenericConvert."));
   }
 }
 
 template <typename To>
-StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece,
-                                                    To*)) const {
+util::StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece,
+                                                          To*)) const {
   if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
-    return InvalidArgument(StrCat("\"", str_, "\""));
+    return util::InvalidArgumentError(StrCat("\"", str_, "\""));
   }
   To result;
   if (func(str_, &result)) return result;
-  return InvalidArgument(StrCat("\"", std::string(str_), "\""));
+  return util::InvalidArgumentError(
+      StrCat("\"", std::string(str_), "\""));
 }
 
 bool DataPiece::DecodeBase64(StringPiece src, std::string* dest) const {
@@ -384,9 +383,8 @@
   if (Base64Unescape(src, dest)) {
     if (use_strict_base64_decoding_) {
       std::string encoded;
-      Base64Escape(
-          reinterpret_cast<const unsigned char*>(dest->data()), dest->length(),
-          &encoded, false);
+      Base64Escape(reinterpret_cast<const unsigned char*>(dest->data()),
+                         dest->length(), &encoded, false);
       StringPiece src_no_padding = StringPiece(src).substr(
           0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1
                                       : src.length());
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index 1b0ccfa..c27ea5c 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -31,13 +31,14 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
 
+#include <cstdint>
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/type.pb.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/statusor.h>
+#include <google/protobuf/stubs/strutil.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -75,13 +76,13 @@
   };
 
   // Constructors and Destructor
-  explicit DataPiece(const int32 value)
+  explicit DataPiece(const int32_t value)
       : type_(TYPE_INT32), i32_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const int64 value)
+  explicit DataPiece(const int64_t value)
       : type_(TYPE_INT64), i64_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const uint32 value)
+  explicit DataPiece(const uint32_t value)
       : type_(TYPE_UINT32), u32_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const uint64 value)
+  explicit DataPiece(const uint64_t value)
       : type_(TYPE_UINT64), u64_(value), use_strict_base64_decoding_(false) {}
   explicit DataPiece(const double value)
       : type_(TYPE_DOUBLE),
@@ -93,12 +94,12 @@
       : type_(TYPE_BOOL), bool_(value), use_strict_base64_decoding_(false) {}
   DataPiece(StringPiece value, bool use_strict_base64_decoding)
       : type_(TYPE_STRING),
-        str_(StringPiecePod::CreateFromStringPiece(value)),
+        str_(value),
         use_strict_base64_decoding_(use_strict_base64_decoding) {}
   // Constructor for bytes. The second parameter is not used.
   DataPiece(StringPiece value, bool dummy, bool use_strict_base64_decoding)
       : type_(TYPE_BYTES),
-        str_(StringPiecePod::CreateFromStringPiece(value)),
+        str_(value),
         use_strict_base64_decoding_(use_strict_base64_decoding) {}
 
   DataPiece(const DataPiece& r) : type_(r.type_) { InternalCopy(r); }
@@ -125,16 +126,16 @@
 
 
   // Parses, casts or converts the value stored in the DataPiece into an int32.
-  util::StatusOr<int32> ToInt32() const;
+  util::StatusOr<int32_t> ToInt32() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a uint32.
-  util::StatusOr<uint32> ToUint32() const;
+  util::StatusOr<uint32_t> ToUint32() const;
 
   // Parses, casts or converts the value stored in the DataPiece into an int64.
-  util::StatusOr<int64> ToInt64() const;
+  util::StatusOr<int64_t> ToInt64() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a uint64.
-  util::StatusOr<uint64> ToUint64() const;
+  util::StatusOr<uint64_t> ToUint64() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a double.
   util::StatusOr<double> ToDouble() const;
@@ -161,16 +162,16 @@
   DataPiece();
 
   // Helper to create NULL or ENUM types.
-  DataPiece(Type type, int32 val)
+  DataPiece(Type type, int32_t val)
       : type_(type), i32_(val), use_strict_base64_decoding_(false) {}
 
   // Same as the ToEnum() method above but with additional flag to ignore
   // unknown enum values.
   util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type,
-                               bool use_lower_camel_for_enums,
-                               bool case_insensitive_enum_parsing,
-                               bool ignore_unknown_enum_values,
-                               bool* is_unknown_enum_value) const;
+                             bool use_lower_camel_for_enums,
+                             bool case_insensitive_enum_parsing,
+                             bool ignore_unknown_enum_values,
+                             bool* is_unknown_enum_value) const;
 
   // For numeric conversion between
   //     int32, int64, uint32, uint64, double, float and bool
@@ -180,8 +181,7 @@
   // For conversion from string to
   //     int32, int64, uint32, uint64, double, float and bool
   template <typename To>
-  util::StatusOr<To> StringToNumber(bool (*func)(StringPiece,
-                                                   To*)) const;
+  util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const;
 
   // Decodes a base64 string. Returns true on success.
   bool DecodeBase64(StringPiece src, std::string* dest) const;
@@ -192,18 +192,16 @@
   // Data type for this piece of data.
   Type type_;
 
-  typedef ::google::protobuf::internal::StringPiecePod StringPiecePod;
-
   // Stored piece of data.
   union {
-    int32 i32_;
-    int64 i64_;
-    uint32 u32_;
-    uint64 u64_;
+    int32_t i32_;
+    int64_t i64_;
+    uint32_t u32_;
+    uint64_t u64_;
     double double_;
     float float_;
     bool bool_;
-    StringPiecePod str_;
+    StringPiece str_;
   };
 
   // Uses a stricter version of base64 decoding for byte fields.
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index a78a862..74fd53f 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/default_value_objectwriter.h>
 
+#include <cstdint>
 #include <unordered_map>
 
 #include <google/protobuf/util/internal/constants.h>
@@ -39,8 +40,6 @@
 namespace google {
 namespace protobuf {
 namespace util {
-using util::Status;
-using util::StatusOr;
 namespace converter {
 
 namespace {
@@ -49,9 +48,10 @@
 // If value is empty or if conversion fails, the default_value is returned.
 template <typename T>
 T ConvertTo(StringPiece value,
-            StatusOr<T> (DataPiece::*converter_fn)() const, T default_value) {
+            util::StatusOr<T> (DataPiece::*converter_fn)() const,
+            T default_value) {
   if (value.empty()) return default_value;
-  StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
+  util::StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
   return result.ok() ? result.value() : default_value;
 }
 }  // namespace
@@ -86,7 +86,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32(
-    StringPiece name, int32 value) {
+    StringPiece name, int32_t value) {
   if (current_ == nullptr) {
     ow_->RenderInt32(name, value);
   } else {
@@ -96,7 +96,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32(
-    StringPiece name, uint32 value) {
+    StringPiece name, uint32_t value) {
   if (current_ == nullptr) {
     ow_->RenderUint32(name, value);
   } else {
@@ -106,7 +106,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64(
-    StringPiece name, int64 value) {
+    StringPiece name, int64_t value) {
   if (current_ == nullptr) {
     ow_->RenderInt64(name, value);
   } else {
@@ -116,7 +116,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64(
-    StringPiece name, uint64 value) {
+    StringPiece name, uint64_t value) {
   if (current_ == nullptr) {
     ow_->RenderUint64(name, value);
   } else {
@@ -220,8 +220,7 @@
   if (name.empty() || kind_ != OBJECT) {
     return nullptr;
   }
-  for (int i = 0; i < children_.size(); ++i) {
-    Node* child = children_[i];
+  for (Node* child : children_) {
     if (child->name() == name) {
       return child;
     }
@@ -265,8 +264,7 @@
 }
 
 void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) {
-  for (int i = 0; i < children_.size(); ++i) {
-    Node* child = children_[i];
+  for (Node* child : children_) {
     child->WriteTo(ow);
   }
 }
@@ -446,19 +444,20 @@
     case google::protobuf::Field::TYPE_INT64:
     case google::protobuf::Field::TYPE_SINT64:
     case google::protobuf::Field::TYPE_SFIXED64: {
-      return DataPiece(ConvertTo<int64>(
-          field.default_value(), &DataPiece::ToInt64, static_cast<int64>(0)));
+      return DataPiece(ConvertTo<int64_t>(
+          field.default_value(), &DataPiece::ToInt64, static_cast<int64_t>(0)));
     }
     case google::protobuf::Field::TYPE_UINT64:
     case google::protobuf::Field::TYPE_FIXED64: {
-      return DataPiece(ConvertTo<uint64>(
-          field.default_value(), &DataPiece::ToUint64, static_cast<uint64>(0)));
+      return DataPiece(ConvertTo<uint64_t>(field.default_value(),
+                                           &DataPiece::ToUint64,
+                                           static_cast<uint64_t>(0)));
     }
     case google::protobuf::Field::TYPE_INT32:
     case google::protobuf::Field::TYPE_SINT32:
     case google::protobuf::Field::TYPE_SFIXED32: {
-      return DataPiece(ConvertTo<int32>(
-          field.default_value(), &DataPiece::ToInt32, static_cast<int32>(0)));
+      return DataPiece(ConvertTo<int32_t>(
+          field.default_value(), &DataPiece::ToInt32, static_cast<int32_t>(0)));
     }
     case google::protobuf::Field::TYPE_BOOL: {
       return DataPiece(
@@ -472,8 +471,9 @@
     }
     case google::protobuf::Field::TYPE_UINT32:
     case google::protobuf::Field::TYPE_FIXED32: {
-      return DataPiece(ConvertTo<uint32>(
-          field.default_value(), &DataPiece::ToUint32, static_cast<uint32>(0)));
+      return DataPiece(ConvertTo<uint32_t>(field.default_value(),
+                                           &DataPiece::ToUint32,
+                                           static_cast<uint32_t>(0)));
     }
     case google::protobuf::Field::TYPE_ENUM: {
       return FindEnumDefault(field, typeinfo, use_ints_for_enums);
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 30c0304..8236f0a 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
 
+#include <cstdint>
 #include <functional>
 #include <memory>
 #include <stack>
@@ -95,16 +96,16 @@
                                        bool value) override;
 
   DefaultValueObjectWriter* RenderInt32(StringPiece name,
-                                        int32 value) override;
+                                        int32_t value) override;
 
   DefaultValueObjectWriter* RenderUint32(StringPiece name,
-                                         uint32 value) override;
+                                         uint32_t value) override;
 
   DefaultValueObjectWriter* RenderInt64(StringPiece name,
-                                        int64 value) override;
+                                        int64_t value) override;
 
   DefaultValueObjectWriter* RenderUint64(StringPiece name,
-                                         uint64 value) override;
+                                         uint64_t value) override;
 
   DefaultValueObjectWriter* RenderDouble(StringPiece name,
                                          double value) override;
@@ -201,7 +202,7 @@
     // Returns the Value Type of a map given the Type of the map entry and a
     // TypeInfo instance.
     const google::protobuf::Type* GetMapValueType(
-        const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);
+        const google::protobuf::Type& found_type, const TypeInfo* typeinfo);
 
     // Calls WriteTo() on every child in children_.
     void WriteChildren(ObjectWriter* ow);
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
index 032d112..7af3579 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
@@ -29,6 +29,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <google/protobuf/util/internal/default_value_objectwriter.h>
+
 #include <google/protobuf/util/internal/expecting_objectwriter.h>
 #include <google/protobuf/util/internal/testdata/default_value_test.pb.h>
 #include <google/protobuf/util/internal/type_info_test_helper.h>
diff --git a/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h
index 71ecb1d..0f2eb1e 100644
--- a/src/google/protobuf/util/internal/expecting_objectwriter.h
+++ b/src/google/protobuf/util/internal/expecting_objectwriter.h
@@ -50,6 +50,8 @@
 //         ->RenderString("key", "value")
 //       ->EndObject();
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/util/internal/object_writer.h>
 #include <gmock/gmock.h>
@@ -60,6 +62,7 @@
 namespace util {
 namespace converter {
 
+using testing::Eq;
 using testing::IsEmpty;
 using testing::NanSensitiveDoubleEq;
 using testing::NanSensitiveFloatEq;
@@ -76,13 +79,13 @@
   MOCK_METHOD(ObjectWriter*, StartList, (StringPiece), (override));
   MOCK_METHOD(ObjectWriter*, EndList, (), (override));
   MOCK_METHOD(ObjectWriter*, RenderBool, (StringPiece, bool), (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32),
+  MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32),
+  MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64),
+  MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64),
+  MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64_t),
               (override));
   MOCK_METHOD(ObjectWriter*, RenderDouble, (StringPiece, double),
               (override));
@@ -90,7 +93,7 @@
               (override));
   MOCK_METHOD(ObjectWriter*, RenderString,
               (StringPiece, StringPiece), (override));
-  MOCK_METHOD(ObjectWriter*, RenderBytes, (StringPiece, StringPiece));
+  MOCK_METHOD(ObjectWriter*, RenderBytes, (StringPiece, StringPiece), (override));
   MOCK_METHOD(ObjectWriter*, RenderNull, (StringPiece), (override));
 };
 
@@ -100,7 +103,7 @@
 
   virtual ObjectWriter* StartObject(StringPiece name) {
     (name.empty() ? EXPECT_CALL(*mock_, StartObject(IsEmpty()))
-                  : EXPECT_CALL(*mock_, StartObject(StrEq(std::string(name)))))
+                  : EXPECT_CALL(*mock_, StartObject(Eq(std::string(name)))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
@@ -115,7 +118,7 @@
 
   virtual ObjectWriter* StartList(StringPiece name) {
     (name.empty() ? EXPECT_CALL(*mock_, StartList(IsEmpty()))
-                  : EXPECT_CALL(*mock_, StartList(StrEq(std::string(name)))))
+                  : EXPECT_CALL(*mock_, StartList(Eq(std::string(name)))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
@@ -131,48 +134,48 @@
   virtual ObjectWriter* RenderBool(StringPiece name, bool value) {
     (name.empty()
          ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value)))
-         : EXPECT_CALL(*mock_, RenderBool(StrEq(std::string(name)),
-                                          TypedEq<bool>(value))))
+         : EXPECT_CALL(*mock_,
+                       RenderBool(Eq(std::string(name)), TypedEq<bool>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) {
+  virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) {
     (name.empty()
-         ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32>(value)))
-         : EXPECT_CALL(*mock_, RenderInt32(StrEq(std::string(name)),
-                                           TypedEq<int32>(value))))
+         ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32_t>(value)))
+         : EXPECT_CALL(*mock_, RenderInt32(Eq(std::string(name)),
+                                           TypedEq<int32_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) {
-    (name.empty()
-         ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), TypedEq<uint32>(value)))
-         : EXPECT_CALL(*mock_, RenderUint32(StrEq(std::string(name)),
-                                            TypedEq<uint32>(value))))
+  virtual ObjectWriter* RenderUint32(StringPiece name, uint32_t value) {
+    (name.empty() ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(),
+                                                     TypedEq<uint32_t>(value)))
+                  : EXPECT_CALL(*mock_, RenderUint32(Eq(std::string(name)),
+                                                     TypedEq<uint32_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) {
+  virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) {
     (name.empty()
-         ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64>(value)))
-         : EXPECT_CALL(*mock_, RenderInt64(StrEq(std::string(name)),
-                                           TypedEq<int64>(value))))
+         ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64_t>(value)))
+         : EXPECT_CALL(*mock_, RenderInt64(Eq(std::string(name)),
+                                           TypedEq<int64_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) {
-    (name.empty()
-         ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), TypedEq<uint64>(value)))
-         : EXPECT_CALL(*mock_, RenderUint64(StrEq(std::string(name)),
-                                            TypedEq<uint64>(value))))
+  virtual ObjectWriter* RenderUint64(StringPiece name, uint64_t value) {
+    (name.empty() ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(),
+                                                     TypedEq<uint64_t>(value)))
+                  : EXPECT_CALL(*mock_, RenderUint64(Eq(std::string(name)),
+                                                     TypedEq<uint64_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
@@ -182,7 +185,7 @@
     (name.empty()
          ? EXPECT_CALL(*mock_,
                        RenderDouble(IsEmpty(), NanSensitiveDoubleEq(value)))
-         : EXPECT_CALL(*mock_, RenderDouble(StrEq(std::string(name)),
+         : EXPECT_CALL(*mock_, RenderDouble(Eq(std::string(name)),
                                             NanSensitiveDoubleEq(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
@@ -193,7 +196,7 @@
     (name.empty()
          ? EXPECT_CALL(*mock_,
                        RenderFloat(IsEmpty(), NanSensitiveFloatEq(value)))
-         : EXPECT_CALL(*mock_, RenderFloat(StrEq(std::string(name)),
+         : EXPECT_CALL(*mock_, RenderFloat(Eq(std::string(name)),
                                            NanSensitiveFloatEq(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
@@ -205,7 +208,7 @@
     (name.empty() ? EXPECT_CALL(*mock_, RenderString(IsEmpty(),
                                                      TypedEq<StringPiece>(
                                                          std::string(value))))
-                  : EXPECT_CALL(*mock_, RenderString(StrEq(std::string(name)),
+                  : EXPECT_CALL(*mock_, RenderString(Eq(std::string(name)),
                                                      TypedEq<StringPiece>(
                                                          std::string(value)))))
         .WillOnce(Return(mock_))
@@ -217,7 +220,7 @@
          ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(), TypedEq<StringPiece>(
                                                           value.ToString())))
          : EXPECT_CALL(*mock_,
-                       RenderBytes(StrEq(name.ToString()),
+                       RenderBytes(Eq(std::string(name)),
                                    TypedEq<StringPiece>(value.ToString()))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
@@ -226,7 +229,7 @@
 
   virtual ObjectWriter* RenderNull(StringPiece name) {
     (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty()))
-                  : EXPECT_CALL(*mock_, RenderNull(StrEq(std::string(name))))
+                  : EXPECT_CALL(*mock_, RenderNull(Eq(std::string(name))))
                         .WillOnce(Return(mock_))
                         .RetiresOnSaturation());
     return this;
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
index 40e193e..f211a54 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ b/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -31,6 +31,7 @@
 #include <google/protobuf/util/internal/field_mask_utility.h>
 
 #include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status_macros.h>
 
@@ -107,7 +108,7 @@
 }
 
 util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
-                                           PathSinkCallback path_sink) {
+                                         PathSinkCallback path_sink) {
   std::stack<std::string> prefix;
   int length = paths.length();
   int previous_position = 0;
@@ -133,11 +134,9 @@
         }
         // Un-escaped '"' must be followed with a ']'.
         if (i >= length - 1 || paths[i + 1] != ']') {
-          return util::Status(
-              util::error::INVALID_ARGUMENT,
-              StrCat(
-                  "Invalid FieldMask '", paths,
-                  "'. Map keys should be represented as [\"some_key\"]."));
+          return util::InvalidArgumentError(StrCat(
+              "Invalid FieldMask '", paths,
+              "'. Map keys should be represented as [\"some_key\"]."));
         }
         // The end of the map key ("\"]") has been found.
         in_map_key = false;
@@ -146,11 +145,9 @@
         // Checks whether the key ends at the end of a path segment.
         if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
             paths[i + 1] != ')' && paths[i + 1] != '(') {
-          return util::Status(
-              util::error::INVALID_ARGUMENT,
-              StrCat(
-                  "Invalid FieldMask '", paths,
-                  "'. Map keys should be at the end of a path segment."));
+          return util::InvalidArgumentError(StrCat(
+              "Invalid FieldMask '", paths,
+              "'. Map keys should be at the end of a path segment."));
         }
         is_escaping = false;
         continue;
@@ -159,11 +156,9 @@
       // We are not in a map key, look for the start of one.
       if (paths[i] == '[') {
         if (i >= length - 1 || paths[i + 1] != '\"') {
-          return util::Status(
-              util::error::INVALID_ARGUMENT,
-              StrCat(
-                  "Invalid FieldMask '", paths,
-                  "'. Map keys should be represented as [\"some_key\"]."));
+          return util::InvalidArgumentError(StrCat(
+              "Invalid FieldMask '", paths,
+              "'. Map keys should be represented as [\"some_key\"]."));
         }
         // "[\"" starts a map key.
         in_map_key = true;
@@ -196,8 +191,7 @@
     // Removes the last prefix after seeing a ')'.
     if (i < length && paths[i] == ')') {
       if (prefix.empty()) {
-        return util::Status(
-            util::error::INVALID_ARGUMENT,
+        return util::InvalidArgumentError(
             StrCat("Invalid FieldMask '", paths,
                          "'. Cannot find matching '(' for all ')'."));
       }
@@ -206,14 +200,12 @@
     previous_position = i + 1;
   }
   if (in_map_key) {
-    return util::Status(
-        util::error::INVALID_ARGUMENT,
+    return util::InvalidArgumentError(
         StrCat("Invalid FieldMask '", paths,
                      "'. Cannot find matching ']' for all '['."));
   }
   if (!prefix.empty()) {
-    return util::Status(
-        util::error::INVALID_ARGUMENT,
+    return util::InvalidArgumentError(
         StrCat("Invalid FieldMask '", paths,
                      "'. Cannot find matching ')' for all '('."));
   }
diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h
index 7335af5..bc41321 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.h
+++ b/src/google/protobuf/util/internal/field_mask_utility.h
@@ -38,6 +38,7 @@
 
 #include <google/protobuf/stubs/callback.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
 
@@ -63,7 +64,7 @@
 // Note that we also support Apiary style FieldMask form. The above example in
 // the Apiary style will look like "a.b,a.c(d,e)".
 util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
-                                           PathSinkCallback path_sink);
+                                         PathSinkCallback path_sink);
 
 }  // namespace converter
 }  // namespace util
diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
index c5c406f..e4fa8cf 100644
--- a/src/google/protobuf/util/internal/json_escaping.cc
+++ b/src/google/protobuf/util/internal/json_escaping.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/internal/json_escaping.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 
@@ -77,7 +79,7 @@
 
 // Determines if the given char value is a unicode surrogate code unit (either
 // high-surrogate or low-surrogate).
-inline bool IsSurrogate(uint32 c) {
+inline bool IsSurrogate(uint32_t c) {
   // Optimized form of:
   // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate;
   // (Reduced from 3 ALU instructions to 2 ALU instructions)
@@ -86,13 +88,13 @@
 
 // Returns true if the given unicode code point cp is a valid
 // unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint).
-inline bool IsValidCodePoint(uint32 cp) {
+inline bool IsValidCodePoint(uint32_t cp) {
   return cp <= JsonEscaping::kMaxCodePoint;
 }
 
 // Returns the low surrogate for the given unicode code point. The result is
 // meaningless if the given code point is not a supplementary character.
-inline uint16 ToLowSurrogate(uint32 cp) {
+inline uint16_t ToLowSurrogate(uint32_t cp) {
   return (cp &
           (JsonEscaping::kMaxLowSurrogate - JsonEscaping::kMinLowSurrogate)) +
          JsonEscaping::kMinLowSurrogate;
@@ -100,7 +102,7 @@
 
 // Returns the high surrogate for the given unicode code point. The result is
 // meaningless if the given code point is not a supplementary character.
-inline uint16 ToHighSurrogate(uint32 cp) {
+inline uint16_t ToHighSurrogate(uint32_t cp) {
   return (cp >> 10) + (JsonEscaping::kMinHighSurrogate -
                        (JsonEscaping::kMinSupplementaryCodePoint >> 10));
 }
@@ -125,11 +127,11 @@
 // Returns false if we encounter an invalid UTF-8 string. Returns true
 // otherwise, including the case when we reach the end of the input (str)
 // before a complete unicode code point is read.
-bool ReadCodePoint(StringPiece str, int index, uint32* cp, int* num_left,
-                   int* num_read) {
+bool ReadCodePoint(StringPiece str, int index, uint32_t* cp,
+                   int* num_left, int* num_read) {
   if (*num_left == 0) {
     // Last read was complete. Start reading a new unicode code point.
-    *cp = static_cast<uint8>(str[index++]);
+    *cp = static_cast<uint8_t>(str[index++]);
     *num_read = 1;
     // The length of the code point is determined from reading the first byte.
     //
@@ -178,7 +180,7 @@
     *num_read = 0;
   }
   while (*num_left > 0 && index < str.size()) {
-    uint32 ch = static_cast<uint8>(str[index++]);
+    uint32_t ch = static_cast<uint8_t>(str[index++]);
     --(*num_left);
     ++(*num_read);
     *cp = (*cp << 6) | (ch & 0x3f);
@@ -190,7 +192,7 @@
 // Stores the 16-bit unicode code point as its hexadecimal digits in buffer
 // and returns a StringPiece that points to this buffer. The input buffer needs
 // to be at least 6 bytes long.
-StringPiece ToHex(uint16 cp, char* buffer) {
+StringPiece ToHex(uint16_t cp, char* buffer) {
   buffer[5] = kHex[cp & 0x0f];
   cp >>= 4;
   buffer[4] = kHex[cp & 0x0f];
@@ -204,9 +206,9 @@
 // Stores the 32-bit unicode code point as its hexadecimal digits in buffer
 // and returns a StringPiece that points to this buffer. The input buffer needs
 // to be at least 12 bytes long.
-StringPiece ToSurrogateHex(uint32 cp, char* buffer) {
-  uint16 low = ToLowSurrogate(cp);
-  uint16 high = ToHighSurrogate(cp);
+StringPiece ToSurrogateHex(uint32_t cp, char* buffer) {
+  uint16_t low = ToLowSurrogate(cp);
+  uint16_t high = ToHighSurrogate(cp);
 
   buffer[11] = kHex[low & 0x0f];
   low >>= 4;
@@ -234,7 +236,7 @@
 //
 // If the given unicode code point does not need escaping, an empty
 // StringPiece is returned.
-StringPiece EscapeCodePoint(uint32 cp, char* buffer) {
+StringPiece EscapeCodePoint(uint32_t cp, char* buffer) {
   if (cp < 0xa0) return kCommonEscapes[cp];
   switch (cp) {
     // These are not required by json spec
@@ -272,7 +274,8 @@
 // Tries to escape the given code point first. If the given code point
 // does not need to be escaped, but force_output is true, then render
 // the given multi-byte code point in UTF8 in the buffer and returns it.
-StringPiece EscapeCodePoint(uint32 cp, char* buffer, bool force_output) {
+StringPiece EscapeCodePoint(uint32_t cp, char* buffer,
+                                  bool force_output) {
   StringPiece sp = EscapeCodePoint(cp, buffer);
   if (force_output && sp.empty()) {
     buffer[5] = (cp & 0x3f) | 0x80;
@@ -301,7 +304,7 @@
 void JsonEscaping::Escape(strings::ByteSource* input,
                           strings::ByteSink* output) {
   char buffer[12] = "\\udead\\ubee";
-  uint32 cp = 0;     // Current unicode code point.
+  uint32_t cp = 0;   // Current unicode code point.
   int num_left = 0;  // Num of chars to read to complete the code point.
   while (input->Available() > 0) {
     StringPiece str = input->Peek();
diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h
index 4ba765c..38cb645 100644
--- a/src/google/protobuf/util/internal/json_escaping.h
+++ b/src/google/protobuf/util/internal/json_escaping.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__
 #define GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/bytestream.h>
 
@@ -44,34 +46,34 @@
   // The minimum value of a unicode high-surrogate code unit in the utf-16
   // encoding. A high-surrogate is also known as a leading-surrogate.
   // See http://www.unicode.org/glossary/#high_surrogate_code_unit
-  static const uint16 kMinHighSurrogate = 0xd800;
+  static constexpr uint16_t kMinHighSurrogate = 0xd800;
 
   // The maximum value of a unicide high-surrogate code unit in the utf-16
   // encoding. A high-surrogate is also known as a leading-surrogate.
   // See http://www.unicode.org/glossary/#high_surrogate_code_unit
-  static const uint16 kMaxHighSurrogate = 0xdbff;
+  static constexpr uint16_t kMaxHighSurrogate = 0xdbff;
 
   // The minimum value of a unicode low-surrogate code unit in the utf-16
   // encoding. A low-surrogate is also known as a trailing-surrogate.
   // See http://www.unicode.org/glossary/#low_surrogate_code_unit
-  static const uint16 kMinLowSurrogate = 0xdc00;
+  static constexpr uint16_t kMinLowSurrogate = 0xdc00;
 
   // The maximum value of a unicode low-surrogate code unit in the utf-16
   // encoding. A low-surrogate is also known as a trailing surrogate.
   // See http://www.unicode.org/glossary/#low_surrogate_code_unit
-  static const uint16 kMaxLowSurrogate = 0xdfff;
+  static constexpr uint16_t kMaxLowSurrogate = 0xdfff;
 
   // The minimum value of a unicode supplementary code point.
   // See http://www.unicode.org/glossary/#supplementary_code_point
-  static const uint32 kMinSupplementaryCodePoint = 0x010000;
+  static constexpr uint32_t kMinSupplementaryCodePoint = 0x010000;
 
   // The minimum value of a unicode code point.
   // See http://www.unicode.org/glossary/#code_point
-  static const uint32 kMinCodePoint = 0x000000;
+  static constexpr uint32_t kMinCodePoint = 0x000000;
 
   // The maximum value of a unicode code point.
   // See http://www.unicode.org/glossary/#code_point
-  static const uint32 kMaxCodePoint = 0x10ffff;
+  static constexpr uint32_t kMaxCodePoint = 0x10ffff;
 
   JsonEscaping() {}
   virtual ~JsonEscaping() {}
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index a98e7ba..c03eb1d 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -31,6 +31,7 @@
 #include <google/protobuf/util/internal/json_objectwriter.h>
 
 #include <cmath>
+#include <cstdint>
 #include <limits>
 
 #include <google/protobuf/stubs/casts.h>
@@ -86,17 +87,17 @@
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name,
-                                                int32 value) {
+                                                int32_t value) {
   return RenderSimple(name, StrCat(value));
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name,
-                                                 uint32 value) {
+                                                 uint32_t value) {
   return RenderSimple(name, StrCat(value));
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name,
-                                                int64 value) {
+                                                int64_t value) {
   WritePrefix(name);
   WriteChar('"');
   WriteRawString(StrCat(value));
@@ -105,7 +106,7 @@
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
-                                                 uint64 value) {
+                                                 uint64_t value) {
   WritePrefix(name);
   WriteChar('"');
   WriteRawString(StrCat(value));
@@ -148,7 +149,7 @@
   std::string base64;
 
   if (use_websafe_base64_for_bytes_)
-    WebSafeBase64EscapeWithPadding(value.ToString(), &base64);
+    WebSafeBase64EscapeWithPadding(std::string(value), &base64);
   else
     Base64Escape(value, &base64);
 
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
index 9e00712..2e9c684 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.h
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
 
+#include <cstdint>
 #include <memory>
 #include <string>
 
@@ -118,10 +119,12 @@
   JsonObjectWriter* StartList(StringPiece name) override;
   JsonObjectWriter* EndList() override;
   JsonObjectWriter* RenderBool(StringPiece name, bool value) override;
-  JsonObjectWriter* RenderInt32(StringPiece name, int32 value) override;
-  JsonObjectWriter* RenderUint32(StringPiece name, uint32 value) override;
-  JsonObjectWriter* RenderInt64(StringPiece name, int64 value) override;
-  JsonObjectWriter* RenderUint64(StringPiece name, uint64 value) override;
+  JsonObjectWriter* RenderInt32(StringPiece name, int32_t value) override;
+  JsonObjectWriter* RenderUint32(StringPiece name,
+                                 uint32_t value) override;
+  JsonObjectWriter* RenderInt64(StringPiece name, int64_t value) override;
+  JsonObjectWriter* RenderUint64(StringPiece name,
+                                 uint64_t value) override;
   JsonObjectWriter* RenderDouble(StringPiece name, double value) override;
   JsonObjectWriter* RenderFloat(StringPiece name, float value) override;
   JsonObjectWriter* RenderString(StringPiece name,
@@ -152,7 +155,7 @@
       return false;
     }
 
-    // Whether we are currently renderring inside a JSON object (i.e., between
+    // Whether we are currently rendering inside a JSON object (i.e., between
     // StartObject() and EndObject()).
     bool is_json_object() const { return is_json_object_; }
 
@@ -218,7 +221,7 @@
       // Take the slow-path if we don't have sufficient characters remaining in
       // our buffer or we have a non-trivial indent string which would prevent
       // us from using memset.
-      uint8* out = nullptr;
+      uint8_t* out = nullptr;
       if (indent_count_ > 0) {
         out = stream_->GetDirectBufferForNBytesAndAdvance(len);
       }
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
index e9f252b..03395da 100644
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/internal/json_objectwriter.h>
 
+#include <cstdint>
+
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/util/internal/utility.h>
 #include <gtest/gtest.h>
@@ -147,8 +149,8 @@
       ->RenderBool("bool", true)
       ->RenderDouble("double", std::numeric_limits<double>::max())
       ->RenderFloat("float", std::numeric_limits<float>::max())
-      ->RenderInt32("int", std::numeric_limits<int32>::min())
-      ->RenderInt64("long", std::numeric_limits<int64>::min())
+      ->RenderInt32("int", std::numeric_limits<int32_t>::min())
+      ->RenderInt64("long", std::numeric_limits<int64_t>::min())
       ->RenderBytes("bytes", "abracadabra")
       ->RenderString("string", "string")
       ->RenderBytes("emptybytes", "")
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index b94e3c2..c3030b5 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -32,16 +32,15 @@
 
 #include <algorithm>
 #include <cctype>
-#include <cerrno>
 #include <cmath>
-#include <cstdlib>
-#include <cstring>
-#include <limits>
 #include <memory>
+#include <stack>
+#include <string>
 
-#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/util/internal/object_writer.h>
 #include <google/protobuf/util/internal/json_escaping.h>
 
@@ -50,15 +49,6 @@
 namespace protobuf {
 namespace util {
 
-// Allow these symbols to be referenced as util::Status, util::error::* in
-// this file.
-using util::Status;
-namespace error {
-using util::error::CANCELLED;
-using util::error::INTERNAL;
-using util::error::INVALID_ARGUMENT;
-}  // namespace error
-
 namespace converter {
 
 // Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X)
@@ -82,8 +72,8 @@
 
 // Indicates a character may not be part of an unquoted key.
 inline bool IsKeySeparator(char c) {
-  return (ascii_isspace(c) || c == '"' || c == '\'' || c == '{' || c == '}' ||
-          c == '[' || c == ']' || c == ':' || c == ',');
+  return (ascii_isspace(c) || c == '"' || c == '\'' || c == '{' ||
+          c == '}' || c == '[' || c == ']' || c == ':' || c == ',');
 }
 
 inline void ReplaceInvalidCodePoints(StringPiece str,
@@ -147,6 +137,8 @@
       key_(),
       key_storage_(),
       finishing_(false),
+      seen_non_whitespace_(false),
+      allow_no_root_element_(false),
       parsed_(),
       parsed_storage_(),
       string_open_(0),
@@ -215,7 +207,8 @@
   } else {
     p_ = json_ = leftover_;
     if (!is_valid_utf8) {
-      return ReportFailure("Encountered non UTF-8 code points.");
+      return ReportFailure("Encountered non UTF-8 code points.",
+                           ParseErrorType::NON_UTF_8);
     }
   }
 
@@ -226,7 +219,9 @@
   if (result.ok()) {
     SkipWhitespace();
     if (!p_.empty()) {
-      result = ReportFailure("Parsing terminated before end of input.");
+      result =
+          ReportFailure("Parsing terminated before end of input.",
+                        ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
     }
   }
   return result;
@@ -250,7 +245,9 @@
     // If we do not expect anything i.e. stack is empty, and we have non-empty
     // string left to parse, we report an error.
     if (stack_.empty()) {
-      return ReportFailure("Parsing terminated before end of input.");
+      return ReportFailure(
+          "Parsing terminated before end of input.",
+          ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
     }
     // If we expect future data i.e. stack is non-empty, and we have some
     // unparsed data left, we save it for later parse.
@@ -259,6 +256,17 @@
   return util::Status();
 }
 
+bool JsonStreamParser::IsInputAllWhiteSpaces(TokenType type) {
+  // Conclude the whole input is full of white spaces by:
+  // - it is at the finishing stage
+  // - we have run out of the input data
+  // - haven't seen non-whitespace char so far
+  if (finishing_ && p_.empty() && type == UNKNOWN && !seen_non_whitespace_) {
+    return true;
+  }
+  return false;
+}
+
 util::Status JsonStreamParser::RunParser() {
   while (!stack_.empty()) {
     ParseType type = stack_.top();
@@ -267,6 +275,9 @@
     util::Status result;
     switch (type) {
       case VALUE:
+        if (allow_no_root_element_ && IsInputAllWhiteSpaces(t)) {
+          return util::Status();
+        }
         result = ParseValue(t);
         break;
 
@@ -291,14 +302,13 @@
         break;
 
       default:
-        result = util::Status(util::error::INTERNAL,
-                              StrCat("Unknown parse type: ", type));
+        result =
+            util::InternalError(StrCat("Unknown parse type: ", type));
         break;
     }
     if (!result.ok()) {
       // If we were cancelled, save our state and try again later.
-      if (!finishing_ &&
-          result == util::Status(util::error::CANCELLED, "")) {
+      if (!finishing_ && util::IsCancelled(result)) {
         stack_.push(type);
         // If we have a key we still need to render, make sure to save off the
         // contents in our own storage.
@@ -331,7 +341,7 @@
     case BEGIN_NULL:
       return ParseNull();
     case UNKNOWN:
-      return ReportUnknown("Expected a value.");
+      return ReportUnknown("Expected a value.", ParseErrorType::EXPECTED_VALUE);
     default: {
       if (allow_empty_null_ && IsEmptyNullAllowed(type)) {
         return ParseEmptyNull();
@@ -342,9 +352,10 @@
       // don't know if the next char would be e, completing it, or something
       // else, making it invalid.
       if (!finishing_ && p_.length() < kKeywordFalse.length()) {
-        return util::Status(util::error::CANCELLED, "");
+        return util::CancelledError("");
       }
-      return ReportFailure("Unexpected token.");
+      return ReportFailure("Unexpected token.",
+                           ParseErrorType::UNEXPECTED_TOKEN);
     }
   }
 }
@@ -380,9 +391,10 @@
       // depending on if we expect more data later.
       if (p_.length() == 1) {
         if (!finishing_) {
-          return util::Status(util::error::CANCELLED, "");
+          return util::CancelledError("");
         }
-        return ReportFailure("Closing quote expected in string.");
+        return ReportFailure("Closing quote expected in string.",
+                             ParseErrorType::EXPECTED_CLOSING_QUOTE);
       }
       // Parse a unicode escape if we found \u in the string.
       if (data[1] == 'u') {
@@ -448,11 +460,12 @@
   }
   // If we didn't find the closing quote but we expect more data, cancel for now
   if (!finishing_) {
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
   // End of string reached without a closing quote, report an error.
   string_open_ = 0;
-  return ReportFailure("Closing quote expected in string.");
+  return ReportFailure("Closing quote expected in string.",
+                       ParseErrorType::EXPECTED_CLOSING_QUOTE);
 }
 
 // Converts a unicode escaped character to a decimal value stored in a char32
@@ -465,16 +478,18 @@
 util::Status JsonStreamParser::ParseUnicodeEscape() {
   if (p_.length() < kUnicodeEscapedLength) {
     if (!finishing_) {
-      return util::Status(util::error::CANCELLED, "");
+      return util::CancelledError("");
     }
-    return ReportFailure("Illegal hex string.");
+    return ReportFailure("Illegal hex string.",
+                         ParseErrorType::ILLEGAL_HEX_STRING);
   }
   GOOGLE_DCHECK_EQ('\\', p_.data()[0]);
   GOOGLE_DCHECK_EQ('u', p_.data()[1]);
   uint32 code = 0;
   for (int i = 2; i < kUnicodeEscapedLength; ++i) {
     if (!isxdigit(p_.data()[i])) {
-      return ReportFailure("Invalid escape sequence.");
+      return ReportFailure("Invalid escape sequence.",
+                           ParseErrorType::INVALID_ESCAPE_SEQUENCE);
     }
     code = (code << 4) + hex_digit_to_int(p_.data()[i]);
   }
@@ -482,10 +497,11 @@
       code <= JsonEscaping::kMaxHighSurrogate) {
     if (p_.length() < 2 * kUnicodeEscapedLength) {
       if (!finishing_) {
-        return util::Status(util::error::CANCELLED, "");
+        return util::CancelledError("");
       }
       if (!coerce_to_utf8_) {
-        return ReportFailure("Missing low surrogate.");
+        return ReportFailure("Missing low surrogate.",
+                             ParseErrorType::MISSING_LOW_SURROGATE);
       }
     } else if (p_.data()[kUnicodeEscapedLength] == '\\' &&
                p_.data()[kUnicodeEscapedLength + 1] == 'u') {
@@ -493,7 +509,8 @@
       for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength;
            ++i) {
         if (!isxdigit(p_.data()[i])) {
-          return ReportFailure("Invalid escape sequence.");
+          return ReportFailure("Invalid escape sequence.",
+                               ParseErrorType::INVALID_ESCAPE_SEQUENCE);
         }
         low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]);
       }
@@ -505,14 +522,17 @@
         // Advance past the first code unit escape.
         p_.remove_prefix(kUnicodeEscapedLength);
       } else if (!coerce_to_utf8_) {
-        return ReportFailure("Invalid low surrogate.");
+        return ReportFailure("Invalid low surrogate.",
+                             ParseErrorType::INVALID_LOW_SURROGATE);
       }
     } else if (!coerce_to_utf8_) {
-      return ReportFailure("Missing low surrogate.");
+      return ReportFailure("Missing low surrogate.",
+                           ParseErrorType::MISSING_LOW_SURROGATE);
     }
   }
   if (!coerce_to_utf8_ && !IsValidCodePoint(code)) {
-    return ReportFailure("Invalid unicode code point.");
+    return ReportFailure("Invalid unicode code point.",
+                         ParseErrorType::INVALID_UNICODE);
   }
   char buf[UTFmax];
   int len = EncodeAsUTF8Char(code, buf);
@@ -543,7 +563,8 @@
         break;
 
       default:
-        return ReportFailure("Unable to parse number.");
+        return ReportFailure("Unable to parse number.",
+                             ParseErrorType::UNABLE_TO_PARSE_NUMBER);
     }
   }
   return result;
@@ -552,10 +573,12 @@
 util::Status JsonStreamParser::ParseDoubleHelper(const std::string& number,
                                                  NumberResult* result) {
   if (!safe_strtod(number, &result->double_val)) {
-    return ReportFailure("Unable to parse number.");
+    return ReportFailure("Unable to parse number.",
+                         ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
   if (!loose_float_number_conversion_ && !std::isfinite(result->double_val)) {
-    return ReportFailure("Number exceeds the range of double.");
+    return ReportFailure("Number exceeds the range of double.",
+                         ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
   }
   result->type = NumberResult::DOUBLE;
   return util::Status();
@@ -588,7 +611,7 @@
   // If the entire input is a valid number, and we may have more content in the
   // future, we abort for now and resume when we know more.
   if (index == length && !finishing_) {
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
 
   // Create a string containing just the number, so we can use safe_strtoX
@@ -607,7 +630,9 @@
   if (!negative) {
     // Octal/Hex numbers are not valid JSON values.
     if (number.length() >= 2 && number[0] == '0') {
-      return ReportFailure("Octal/hex numbers are not valid JSON values.");
+      return ReportFailure(
+          "Octal/hex numbers are not valid JSON values.",
+          ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
     }
     if (safe_strtou64(number, &result->uint_val)) {
       result->type = NumberResult::UINT;
@@ -625,7 +650,9 @@
 
   // Octal/Hex numbers are not valid JSON values.
   if (number.length() >= 3 && number[1] == '0') {
-    return ReportFailure("Octal/hex numbers are not valid JSON values.");
+    return ReportFailure(
+        "Octal/hex numbers are not valid JSON values.",
+        ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   // Negative non-floating point number, parse as an int64.
   if (safe_strto64(number, &result->int_val)) {
@@ -657,7 +684,8 @@
 
 util::Status JsonStreamParser::ParseObjectMid(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected , or } after key:value pair.");
+    return ReportUnknown("Expected , or } after key:value pair.",
+                         ParseErrorType::EXPECTED_COMMA_OR_BRACES);
   }
 
   // Object is complete, advance past the comma and render the EndObject.
@@ -674,12 +702,14 @@
     return util::Status();
   }
   // Illegal token after key:value pair.
-  return ReportFailure("Expected , or } after key:value pair.");
+  return ReportFailure("Expected , or } after key:value pair.",
+                       ParseErrorType::EXPECTED_COMMA_OR_BRACES);
 }
 
 util::Status JsonStreamParser::ParseEntry(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected an object key or }.");
+    return ReportUnknown("Expected an object key or }.",
+                         ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 
   // Close the object and return. This allows for trailing commas.
@@ -712,11 +742,13 @@
     result = ParseKey();
     if (result.ok() && (key_ == kKeywordNull || key_ == kKeywordTrue ||
                         key_ == kKeywordFalse)) {
-      result = ReportFailure("Expected an object key or }.");
+      result = ReportFailure("Expected an object key or }.",
+                             ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
     }
   } else {
     // Unknown key type, report an error.
-    result = ReportFailure("Expected an object key or }.");
+    result = ReportFailure("Expected an object key or }.",
+                           ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
   // On success we next expect an entry mid ':' then an object mid ',' or '}'
   if (result.ok()) {
@@ -728,14 +760,16 @@
 
 util::Status JsonStreamParser::ParseEntryMid(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected : between key:value pair.");
+    return ReportUnknown("Expected : between key:value pair.",
+                         ParseErrorType::EXPECTED_COLON);
   }
   if (type == ENTRY_SEPARATOR) {
     Advance();
     stack_.push(VALUE);
     return util::Status();
   }
-  return ReportFailure("Expected : between key:value pair.");
+  return ReportFailure("Expected : between key:value pair.",
+                       ParseErrorType::EXPECTED_COLON);
 }
 
 util::Status JsonStreamParser::HandleBeginArray() {
@@ -749,7 +783,8 @@
 
 util::Status JsonStreamParser::ParseArrayValue(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected a value or ] within an array.");
+    return ReportUnknown("Expected a value or ] within an array.",
+                         ParseErrorType::EXPECTED_VALUE_OR_BRACKET);
   }
 
   if (type == END_ARRAY) {
@@ -763,7 +798,7 @@
   // empty-null array value is relying on this ARRAY_MID token.
   stack_.push(ARRAY_MID);
   util::Status result = ParseValue(type);
-  if (result == util::Status(util::error::CANCELLED, "")) {
+  if (util::IsCancelled(result)) {
     // If we were cancelled, pop back off the ARRAY_MID so we don't try to
     // push it on again when we try over.
     stack_.pop();
@@ -773,7 +808,8 @@
 
 util::Status JsonStreamParser::ParseArrayMid(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected , or ] after array value.");
+    return ReportUnknown("Expected , or ] after array value.",
+                         ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
   }
 
   if (type == END_ARRAY) {
@@ -789,7 +825,8 @@
     return util::Status();
   }
   // Illegal token after array value.
-  return ReportFailure("Expected , or ] after array value.");
+  return ReportFailure("Expected , or ] after array value.",
+                       ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
 }
 
 util::Status JsonStreamParser::ParseTrue() {
@@ -825,7 +862,8 @@
          stack_.top() == OBJ_MID;
 }
 
-util::Status JsonStreamParser::ReportFailure(StringPiece message) {
+util::Status JsonStreamParser::ReportFailure(StringPiece message,
+                                             ParseErrorType parse_code) {
   static const int kContextLength = 20;
   const char* p_start = p_.data();
   const char* json_start = json_.data();
@@ -835,28 +873,29 @@
   StringPiece segment(begin, end - begin);
   std::string location(p_start - begin, ' ');
   location.push_back('^');
-  return util::Status(util::error::INVALID_ARGUMENT,
-                      StrCat(message, "\n", segment, "\n", location));
+  auto status = util::InvalidArgumentError(
+      StrCat(message, "\n", segment, "\n", location));
+  return status;
 }
 
-util::Status JsonStreamParser::ReportUnknown(StringPiece message) {
+util::Status JsonStreamParser::ReportUnknown(StringPiece message,
+                                             ParseErrorType parse_code) {
   // If we aren't finishing the parse, cancel parsing and try later.
   if (!finishing_) {
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
   if (p_.empty()) {
-    return ReportFailure(StrCat("Unexpected end of string. ", message));
+    return ReportFailure(StrCat("Unexpected end of string. ", message),
+                         parse_code);
   }
-  return ReportFailure(message);
+  return ReportFailure(message, parse_code);
 }
 
 util::Status JsonStreamParser::IncrementRecursionDepth(
     StringPiece key) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return Status(
-        util::error::INVALID_ARGUMENT,
-        StrCat("Message too deep. Max recursion depth reached for key '",
-                     key, "'"));
+    return util::InvalidArgumentError(StrCat(
+        "Message too deep. Max recursion depth reached for key '", key, "'"));
   }
   return util::Status();
 }
@@ -865,6 +904,9 @@
   while (!p_.empty() && ascii_isspace(*p_.data())) {
     Advance();
   }
+  if (!p_.empty() && !ascii_isspace(*p_.data())) {
+    seen_non_whitespace_ = true;
+  }
 }
 
 void JsonStreamParser::Advance() {
@@ -879,11 +921,13 @@
 
   if (allow_permissive_key_naming_) {
     if (!ConsumeKeyPermissive(&p_, &key_)) {
-      return ReportFailure("Invalid key or variable name.");
+      return ReportFailure("Invalid key or variable name.",
+                           ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME);
     }
   } else {
     if (!ConsumeKey(&p_, &key_)) {
-      return ReportFailure("Invalid key or variable name.");
+      return ReportFailure("Invalid key or variable name.",
+                           ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME);
     }
   }
 
@@ -891,7 +935,7 @@
   // we can't know if the key was complete or not.
   if (!finishing_ && p_.empty()) {
     p_ = original;
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
   // Since we aren't using the key storage, clear it out.
   key_storage_.clear();
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index c2993e5..47dfe82 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -31,10 +31,12 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
 
+#include <cstdint>
 #include <stack>
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
 
@@ -45,6 +47,7 @@
 namespace util {
 namespace converter {
 
+
 class ObjectWriter;
 
 // A JSON parser that can parse a stream of JSON chunks rather than needing the
@@ -73,11 +76,17 @@
   explicit JsonStreamParser(ObjectWriter* ow);
   virtual ~JsonStreamParser();
 
-  // Parses a UTF-8 encoded JSON string from a StringPiece.
+  // Parses a UTF-8 encoded JSON string from a StringPiece. If the returned
+  // status is non-ok, the status might contain a payload ParseErrorType with
+  // type_url kParseErrorTypeUrl and a payload containing string snippet of the
+  // error with type_url kParseErrorSnippetUrl.
   util::Status Parse(StringPiece json);
 
 
-  // Finish parsing the JSON string.
+  // Finish parsing the JSON string. If the returned status is non-ok, the
+  // status might contain a payload ParseErrorType with type_url
+  // kParseErrorTypeUrl and a payload containing string snippet of the error
+  // with type_url kParseErrorSnippetUrl.
   util::Status FinishParse();
 
 
@@ -88,6 +97,30 @@
     max_recursion_depth_ = max_depth;
   }
 
+  // Denotes the cause of error.
+  enum ParseErrorType {
+    UNKNOWN_PARSE_ERROR,
+    OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES,
+    EXPECTED_COLON,
+    EXPECTED_COMMA_OR_BRACKET,
+    EXPECTED_VALUE,
+    EXPECTED_COMMA_OR_BRACES,
+    EXPECTED_OBJECT_KEY_OR_BRACES,
+    EXPECTED_VALUE_OR_BRACKET,
+    INVALID_KEY_OR_VARIABLE_NAME,
+    NON_UTF_8,
+    PARSING_TERMINATED_BEFORE_END_OF_INPUT,
+    UNEXPECTED_TOKEN,
+    EXPECTED_CLOSING_QUOTE,
+    ILLEGAL_HEX_STRING,
+    INVALID_ESCAPE_SEQUENCE,
+    MISSING_LOW_SURROGATE,
+    INVALID_LOW_SURROGATE,
+    INVALID_UNICODE,
+    UNABLE_TO_PARSE_NUMBER,
+    NUMBER_EXCEEDS_RANGE_DOUBLE
+  };
+
  private:
   friend class JsonStreamParserTest;
   // Return the current recursion depth.
@@ -124,13 +157,13 @@
     Type type;
     union {
       double double_val;
-      int64 int_val;
-      uint64 uint_val;
+      int64_t int_val;
+      uint64_t uint_val;
     };
   };
 
   // Parses a single chunk of JSON, returning an error if the JSON was invalid.
-  util::Status ParseChunk(StringPiece json);
+  util::Status ParseChunk(StringPiece chunk);
 
   // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs
   // out of data. If we unexpectedly run out of p_ we push the latest back onto
@@ -165,7 +198,7 @@
 
   // Parse a number as double into a NumberResult.
   util::Status ParseDoubleHelper(const std::string& number,
-                                   NumberResult* result);
+                                 NumberResult* result);
 
   // Handles a { during parsing of a value.
   util::Status HandleBeginObject();
@@ -197,16 +230,21 @@
   // Whether an empty-null is allowed in the current state.
   bool IsEmptyNullAllowed(TokenType type);
 
+  // Whether the whole input is all whitespaces.
+  bool IsInputAllWhiteSpaces(TokenType type);
+
   // Report a failure as a util::Status.
-  util::Status ReportFailure(StringPiece message);
+  util::Status ReportFailure(StringPiece message,
+                             ParseErrorType parse_code);
 
   // Report a failure due to an UNKNOWN token type. We check if we hit the
   // end of the stream and if we're finishing or not to detect what type of
   // status to return in this case.
-  util::Status ReportUnknown(StringPiece message);
+  util::Status ReportUnknown(StringPiece message,
+                             ParseErrorType parse_code);
 
   // Helper function to check recursion depth and increment it. It will return
-  // Status::OK if the current depth is allowed. Otherwise an error is returned.
+  // OkStatus() if the current depth is allowed. Otherwise an error is returned.
   // key is used for error reporting.
   util::Status IncrementRecursionDepth(StringPiece key) const;
 
@@ -252,6 +290,15 @@
   // trying during the next chunk, but during FinishParse() it is an error.
   bool finishing_;
 
+  // Whether non whitespace tokens have been seen during parsing.
+  // It is used to handle the case of a pure whitespace stream input.
+  bool seen_non_whitespace_;
+
+  // The JsonStreamParser requires a root element by default and it will raise
+  // error if the root element is missing. If `allow_no_root_element_` is true,
+  // the JsonStreamParser can also handle this case.
+  bool allow_no_root_element_;
+
   // String we parsed during a call to ParseStringHelper().
   StringPiece parsed_;
 
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index 6638ce8..4bb1025 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/internal/json_stream_parser.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/util/internal/expecting_objectwriter.h>
@@ -42,13 +44,11 @@
 namespace google {
 namespace protobuf {
 namespace util {
-using util::Status;
-namespace error {
-using util::error::INVALID_ARGUMENT;
-}  // namespace error
 namespace converter {
 
-using util::Status;
+using ParseErrorType =
+    ::google::protobuf::util::converter::JsonStreamParser::ParseErrorType;
+
 
 // Tests for the JSON Stream Parser. These tests are intended to be
 // comprehensive and cover the following:
@@ -138,15 +138,26 @@
       std::function<void(JsonStreamParser*)> setup = [](JsonStreamParser* p) {
       }) {
     util::Status result = RunTest(json, split, setup);
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.code());
-    StringPiece error_message(result.error_message());
+    EXPECT_TRUE(util::IsInvalidArgument(result));
+    StringPiece error_message(result.message());
+    EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
+  }
+
+  void DoErrorTest(
+      StringPiece json, int split, StringPiece error_prefix,
+      ParseErrorType expected_parse_error_type,
+      std::function<void(JsonStreamParser*)> setup = [](JsonStreamParser* p) {
+      }) {
+    util::Status result = RunTest(json, split, setup);
+    EXPECT_TRUE(util::IsInvalidArgument(result));
+    StringPiece error_message(result.message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
   }
 
 
 #ifndef _MSC_VER
   // TODO(xiaofeng): We have to disable InSequence check for MSVC because it
-  // causes stack overflow due to its use of a linked list that is desctructed
+  // causes stack overflow due to its use of a linked list that is destructed
   // recursively.
   ::testing::InSequence in_sequence_;
 #endif  // !_MSC_VER
@@ -235,7 +246,7 @@
 TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
   StringPiece str = "-79497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderInt64("", -79497823553162765LL);
+    ow_.RenderInt64("", int64_t{-79497823553162765});
     DoTest(str, i);
   }
 }
@@ -243,7 +254,7 @@
 TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
   StringPiece str = "11779497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderUint64("", 11779497823553162765ULL);
+    ow_.RenderUint64("", uint64_t{11779497823553162765u});
     DoTest(str, i);
   }
 }
@@ -251,26 +262,31 @@
 TEST_F(JsonStreamParserTest, OctalNumberIsInvalid) {
   StringPiece str = "01234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   str = "-01234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
 }
 
 TEST_F(JsonStreamParserTest, HexNumberIsInvalid) {
   StringPiece str = "0x1234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   str = "-0x1234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   str = "12x34";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Unable to parse number.");
+    DoErrorTest(str, i, "Unable to parse number.",
+                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
 }
 
@@ -340,14 +356,16 @@
 TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithReservedKeyword) {
   StringPiece str = "{ null: \"a\", true: \"b\", false: \"c\"}";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
 TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithEmbeddedNonAlphanumeric) {
   StringPiece str = "{ foo-bar-baz: \"a\"}";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Expected : between key:value pair.");
+    DoErrorTest(str, i, "Expected : between key:value pair.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -378,7 +396,7 @@
         ->RenderInt64("", -127)
         ->RenderDouble("", 45.3)
         ->RenderDouble("", -1056.4)
-        ->RenderUint64("", 11779497823553162765ULL)
+        ->RenderUint64("", uint64_t{11779497823553162765u})
         ->EndList()
         ->StartObject("")
         ->RenderBool("key", true)
@@ -406,7 +424,7 @@
         ->RenderInt64("ni", -127)
         ->RenderDouble("pd", 45.3)
         ->RenderDouble("nd", -1056.4)
-        ->RenderUint64("pl", 11779497823553162765ULL)
+        ->RenderUint64("pl", uint64_t{11779497823553162765u})
         ->StartList("l")
         ->StartList("")
         ->EndList()
@@ -423,13 +441,16 @@
 TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
   StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}";
   for (int i = 0; i <= json.length(); ++i) {
-    DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+    DoErrorTest(json, i, "Encountered non UTF-8 code points.",
+                ParseErrorType::NON_UTF_8);
   }
   json = "{\"address\": \"חרושת 23,\xFFרעננה, ישראל\"}";
   for (int i = 0; i <= json.length(); ++i) {
-    DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+    DoErrorTest(json, i, "Encountered non UTF-8 code points.",
+                ParseErrorType::NON_UTF_8);
   }
-  DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.");
+  DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.",
+              ParseErrorType::NON_UTF_8);
 }
 
 // - unicode handling in strings
@@ -462,7 +483,8 @@
   // A low surrogate alone.
   StringPiece str = "[\"\\ude36\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid unicode code point.");
+    DoErrorTest(str, i, "Invalid unicode code point.",
+                ParseErrorType::INVALID_UNICODE);
   }
 }
 
@@ -470,22 +492,26 @@
   // A high surrogate alone.
   StringPiece str = "[\"\\ud83d\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Missing low surrogate.");
+    DoErrorTest(str, i, "Missing low surrogate.",
+                ParseErrorType::MISSING_LOW_SURROGATE);
   }
   // A high surrogate with some trailing characters.
   str = "[\"\\ud83d|ude36\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Missing low surrogate.");
+    DoErrorTest(str, i, "Missing low surrogate.",
+                ParseErrorType::MISSING_LOW_SURROGATE);
   }
   // A high surrogate with half a low surrogate.
   str = "[\"\\ud83d\\ude--\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
   // Two high surrogates.
   str = "[\"\\ud83d\\ud83d\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid low surrogate.");
+    DoErrorTest(str, i, "Invalid low surrogate.",
+                ParseErrorType::INVALID_LOW_SURROGATE);
   }
 }
 
@@ -529,21 +555,24 @@
   StringPiece str = "truee";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderBool("", true);
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
 TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) {
   StringPiece str = "-";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Unable to parse number.");
+    DoErrorTest(str, i, "Unable to parse number.",
+                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
 }
 
 TEST_F(JsonStreamParserTest, InvalidNumberDashName) {
   StringPiece str = "-foo";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Unable to parse number.");
+    DoErrorTest(str, i, "Unable to parse number.",
+                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
 }
 
@@ -551,7 +580,7 @@
   StringPiece str = "[nule]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Unexpected token.");
+    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
   }
 }
 
@@ -559,7 +588,8 @@
   StringPiece str = "{123false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -567,14 +597,16 @@
 TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) {
   StringPiece str = "'Some str\"";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
 TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) {
   StringPiece str = "\"Another string that ends poorly!'";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -582,14 +614,16 @@
 TEST_F(JsonStreamParserTest, UnterminatedLiteralString) {
   StringPiece str = "\"Forgot the rest of i";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
 TEST_F(JsonStreamParserTest, UnterminatedStringEscape) {
   StringPiece str = "\"Forgot the rest of \\";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -597,7 +631,8 @@
   StringPiece str = "[\"Forgot to close the string]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -605,7 +640,8 @@
   StringPiece str = "{f: \"Forgot to close the string}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -613,7 +649,8 @@
   StringPiece str = "{";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected end of string.");
+    DoErrorTest(str, i, "Unexpected end of string.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -623,7 +660,8 @@
   StringPiece str = "{'key': true]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderBool("key", true);
-    DoErrorTest(str, i, "Expected , or } after key:value pair.");
+    DoErrorTest(str, i, "Expected , or } after key:value pair.",
+                ParseErrorType::EXPECTED_COMMA_OR_BRACES);
   }
 }
 
@@ -631,7 +669,8 @@
   StringPiece str = "[true, null}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderBool("", true)->RenderNull("");
-    DoErrorTest(str, i, "Expected , or ] after array value.");
+    DoErrorTest(str, i, "Expected , or ] after array value.",
+                ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
   }
 }
 
@@ -640,7 +679,8 @@
   StringPiece str = "{42: true}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -648,7 +688,8 @@
   StringPiece str = "{{bob: true}}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -656,7 +697,8 @@
   StringPiece str = "{[null]}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -664,7 +706,8 @@
   StringPiece str = "{false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -672,7 +715,8 @@
   StringPiece str = "{\"key\"}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected : between key:value pair.");
+    DoErrorTest(str, i, "Expected : between key:value pair.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -680,7 +724,8 @@
   StringPiece str = "{key}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected : between key:value pair.");
+    DoErrorTest(str, i, "Expected : between key:value pair.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -688,7 +733,8 @@
   StringPiece str = "{key";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected end of string.");
+    DoErrorTest(str, i, "Unexpected end of string.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -696,7 +742,7 @@
   StringPiece str = "{key:}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected token.");
+    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
   }
 }
 
@@ -704,7 +750,8 @@
   StringPiece str = "{key:20 'hello': true}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderUint64("key", 20);
-    DoErrorTest(str, i, "Expected , or } after key:value pair.");
+    DoErrorTest(str, i, "Expected , or } after key:value pair.",
+                ParseErrorType::EXPECTED_COMMA_OR_BRACES);
   }
 }
 
@@ -712,7 +759,8 @@
   StringPiece str = "{false: 20}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -720,7 +768,8 @@
   StringPiece str = "{}}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->EndObject();
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -744,12 +793,14 @@
   StringPiece str = "[1.89769e+308]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Number exceeds the range of double.");
+    DoErrorTest(str, i, "Number exceeds the range of double.",
+                ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
   }
   str = "[-1.89769e+308]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Number exceeds the range of double.");
+    DoErrorTest(str, i, "Number exceeds the range of double.",
+                ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
   }
 }
 
@@ -758,7 +809,8 @@
 TEST_F(JsonStreamParserTest, UnfinishedEscape) {
   StringPiece str = "\"\\";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -766,7 +818,8 @@
 TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
   StringPiece str = "\"\\u";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Illegal hex string.");
+    DoErrorTest(str, i, "Illegal hex string.",
+                ParseErrorType::ILLEGAL_HEX_STRING);
   }
 }
 
@@ -774,7 +827,8 @@
 TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
   StringPiece str = "\"\\u12";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Illegal hex string.");
+    DoErrorTest(str, i, "Illegal hex string.",
+                ParseErrorType::ILLEGAL_HEX_STRING);
   }
 }
 
@@ -782,7 +836,8 @@
 TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
   StringPiece str = "\"\\u{1f36f}\"";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
 }
 
@@ -790,7 +845,8 @@
 TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
   StringPiece str = "\"\\u12$4hello";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
 }
 
@@ -798,7 +854,8 @@
 TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
   StringPiece str = "\"\\ud800\\udcfg\"";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
 }
 
@@ -807,7 +864,8 @@
   StringPiece str = "{'k1': true,,'k2': false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderBool("k1", true);
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -815,7 +873,7 @@
   StringPiece str = "[true,,false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderBool("", true);
-    DoErrorTest(str, i, "Unexpected token.");
+    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
   }
 }
 
@@ -824,7 +882,8 @@
   StringPiece str = "'hello', 'world'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderString("", "hello");
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -832,7 +891,8 @@
   StringPiece str = "{'key': true} 'oops'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderBool("key", true)->EndObject();
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -840,7 +900,8 @@
   StringPiece str = "[null] 'oops'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderNull("")->EndList();
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -848,7 +909,7 @@
 TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) {
   StringPiece str = "*&#25";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Expected a value.");
+    DoErrorTest(str, i, "Expected a value.", ParseErrorType::EXPECTED_VALUE);
   }
 }
 
@@ -856,7 +917,8 @@
   StringPiece str = "[*&#25]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Expected a value or ] within an array.");
+    DoErrorTest(str, i, "Expected a value or ] within an array.",
+                ParseErrorType::EXPECTED_VALUE_OR_BRACKET);
   }
 }
 
@@ -864,7 +926,7 @@
   StringPiece str = "{'key': *&#25}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected a value.");
+    DoErrorTest(str, i, "Expected a value.", ParseErrorType::EXPECTED_VALUE);
   }
 }
 
diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h
index 28b1aae..de548c1 100644
--- a/src/google/protobuf/util/internal/object_source.h
+++ b/src/google/protobuf/util/internal/object_source.h
@@ -32,6 +32,7 @@
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
 
@@ -64,7 +65,7 @@
   // This is useful when you chain ObjectSource together by embedding one
   // within another.
   virtual util::Status NamedWriteTo(StringPiece name,
-                                      ObjectWriter* ow) const = 0;
+                                    ObjectWriter* ow) const = 0;
 
  protected:
   ObjectSource() {}
diff --git a/src/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc
index b7667b6..4dabd37 100644
--- a/src/google/protobuf/util/internal/object_writer.cc
+++ b/src/google/protobuf/util/internal/object_writer.cc
@@ -74,7 +74,7 @@
       break;
     }
     case DataPiece::TYPE_BYTES: {
-      ow->RenderBytes(name, data.ToBytes().ValueOrDie());
+      ow->RenderBytes(name, data.ToBytes().value());
       break;
     }
     case DataPiece::TYPE_NULL: {
diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
index 29b05c1..917a280 100644
--- a/src/google/protobuf/util/internal/object_writer.h
+++ b/src/google/protobuf/util/internal/object_writer.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -79,16 +81,18 @@
   virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0;
 
   // Renders an 32-bit integer value.
-  virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) = 0;
+  virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) = 0;
 
   // Renders an 32-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) = 0;
+  virtual ObjectWriter* RenderUint32(StringPiece name,
+                                     uint32_t value) = 0;
 
   // Renders a 64-bit integer value.
-  virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) = 0;
+  virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) = 0;
 
   // Renders an 64-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) = 0;
+  virtual ObjectWriter* RenderUint64(StringPiece name,
+                                     uint64_t value) = 0;
 
 
   // Renders a double value.
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index ea95932..717cee4 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/proto_writer.h>
 
+#include <cstdint>
 #include <functional>
 #include <stack>
 
@@ -40,9 +41,9 @@
 #include <google/protobuf/util/internal/constants.h>
 #include <google/protobuf/util/internal/utility.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/time.h>
 #include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/statusor.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -54,10 +55,6 @@
 
 using io::CodedOutputStream;
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
-using util::Status;
-using util::StatusOr;
-using util::error::INVALID_ARGUMENT;
-
 
 ProtoWriter::ProtoWriter(TypeResolver* type_resolver,
                          const google::protobuf::Type& type,
@@ -70,6 +67,7 @@
       ignore_unknown_enum_values_(false),
       use_lower_camel_for_enums_(false),
       case_insensitive_enum_parsing_(true),
+      use_json_name_in_missing_fields_(false),
       element_(nullptr),
       size_insert_(),
       output_(output),
@@ -91,6 +89,7 @@
       ignore_unknown_enum_values_(false),
       use_lower_camel_for_enums_(false),
       case_insensitive_enum_parsing_(true),
+      use_json_name_in_missing_fields_(false),
       element_(nullptr),
       size_insert_(),
       output_(output),
@@ -120,9 +119,9 @@
 namespace {
 
 // Writes an INT32 field, including tag to the stream.
-inline Status WriteInt32(int field_number, const DataPiece& data,
-                         CodedOutputStream* stream) {
-  StatusOr<int32> i32 = data.ToInt32();
+inline util::Status WriteInt32(int field_number, const DataPiece& data,
+                               CodedOutputStream* stream) {
+  util::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteInt32(field_number, i32.value(), stream);
   }
@@ -130,9 +129,9 @@
 }
 
 // writes an SFIXED32 field, including tag, to the stream.
-inline Status WriteSFixed32(int field_number, const DataPiece& data,
-                            CodedOutputStream* stream) {
-  StatusOr<int32> i32 = data.ToInt32();
+inline util::Status WriteSFixed32(int field_number, const DataPiece& data,
+                                  CodedOutputStream* stream) {
+  util::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteSFixed32(field_number, i32.value(), stream);
   }
@@ -140,9 +139,9 @@
 }
 
 // Writes an SINT32 field, including tag, to the stream.
-inline Status WriteSInt32(int field_number, const DataPiece& data,
-                          CodedOutputStream* stream) {
-  StatusOr<int32> i32 = data.ToInt32();
+inline util::Status WriteSInt32(int field_number, const DataPiece& data,
+                                CodedOutputStream* stream) {
+  util::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteSInt32(field_number, i32.value(), stream);
   }
@@ -150,9 +149,9 @@
 }
 
 // Writes a FIXED32 field, including tag, to the stream.
-inline Status WriteFixed32(int field_number, const DataPiece& data,
-                           CodedOutputStream* stream) {
-  StatusOr<uint32> u32 = data.ToUint32();
+inline util::Status WriteFixed32(int field_number, const DataPiece& data,
+                                 CodedOutputStream* stream) {
+  util::StatusOr<uint32_t> u32 = data.ToUint32();
   if (u32.ok()) {
     WireFormatLite::WriteFixed32(field_number, u32.value(), stream);
   }
@@ -160,9 +159,9 @@
 }
 
 // Writes a UINT32 field, including tag, to the stream.
-inline Status WriteUInt32(int field_number, const DataPiece& data,
-                          CodedOutputStream* stream) {
-  StatusOr<uint32> u32 = data.ToUint32();
+inline util::Status WriteUInt32(int field_number, const DataPiece& data,
+                                CodedOutputStream* stream) {
+  util::StatusOr<uint32_t> u32 = data.ToUint32();
   if (u32.ok()) {
     WireFormatLite::WriteUInt32(field_number, u32.value(), stream);
   }
@@ -170,9 +169,9 @@
 }
 
 // Writes an INT64 field, including tag, to the stream.
-inline Status WriteInt64(int field_number, const DataPiece& data,
-                         CodedOutputStream* stream) {
-  StatusOr<int64> i64 = data.ToInt64();
+inline util::Status WriteInt64(int field_number, const DataPiece& data,
+                               CodedOutputStream* stream) {
+  util::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteInt64(field_number, i64.value(), stream);
   }
@@ -180,9 +179,9 @@
 }
 
 // Writes an SFIXED64 field, including tag, to the stream.
-inline Status WriteSFixed64(int field_number, const DataPiece& data,
-                            CodedOutputStream* stream) {
-  StatusOr<int64> i64 = data.ToInt64();
+inline util::Status WriteSFixed64(int field_number, const DataPiece& data,
+                                  CodedOutputStream* stream) {
+  util::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteSFixed64(field_number, i64.value(), stream);
   }
@@ -190,9 +189,9 @@
 }
 
 // Writes an SINT64 field, including tag, to the stream.
-inline Status WriteSInt64(int field_number, const DataPiece& data,
-                          CodedOutputStream* stream) {
-  StatusOr<int64> i64 = data.ToInt64();
+inline util::Status WriteSInt64(int field_number, const DataPiece& data,
+                                CodedOutputStream* stream) {
+  util::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteSInt64(field_number, i64.value(), stream);
   }
@@ -200,9 +199,9 @@
 }
 
 // Writes a FIXED64 field, including tag, to the stream.
-inline Status WriteFixed64(int field_number, const DataPiece& data,
-                           CodedOutputStream* stream) {
-  StatusOr<uint64> u64 = data.ToUint64();
+inline util::Status WriteFixed64(int field_number, const DataPiece& data,
+                                 CodedOutputStream* stream) {
+  util::StatusOr<uint64_t> u64 = data.ToUint64();
   if (u64.ok()) {
     WireFormatLite::WriteFixed64(field_number, u64.value(), stream);
   }
@@ -210,9 +209,9 @@
 }
 
 // Writes a UINT64 field, including tag, to the stream.
-inline Status WriteUInt64(int field_number, const DataPiece& data,
-                          CodedOutputStream* stream) {
-  StatusOr<uint64> u64 = data.ToUint64();
+inline util::Status WriteUInt64(int field_number, const DataPiece& data,
+                                CodedOutputStream* stream) {
+  util::StatusOr<uint64_t> u64 = data.ToUint64();
   if (u64.ok()) {
     WireFormatLite::WriteUInt64(field_number, u64.value(), stream);
   }
@@ -220,9 +219,9 @@
 }
 
 // Writes a DOUBLE field, including tag, to the stream.
-inline Status WriteDouble(int field_number, const DataPiece& data,
-                          CodedOutputStream* stream) {
-  StatusOr<double> d = data.ToDouble();
+inline util::Status WriteDouble(int field_number, const DataPiece& data,
+                                CodedOutputStream* stream) {
+  util::StatusOr<double> d = data.ToDouble();
   if (d.ok()) {
     WireFormatLite::WriteDouble(field_number, d.value(), stream);
   }
@@ -230,9 +229,9 @@
 }
 
 // Writes a FLOAT field, including tag, to the stream.
-inline Status WriteFloat(int field_number, const DataPiece& data,
-                         CodedOutputStream* stream) {
-  StatusOr<float> f = data.ToFloat();
+inline util::Status WriteFloat(int field_number, const DataPiece& data,
+                               CodedOutputStream* stream) {
+  util::StatusOr<float> f = data.ToFloat();
   if (f.ok()) {
     WireFormatLite::WriteFloat(field_number, f.value(), stream);
   }
@@ -240,9 +239,9 @@
 }
 
 // Writes a BOOL field, including tag, to the stream.
-inline Status WriteBool(int field_number, const DataPiece& data,
-                        CodedOutputStream* stream) {
-  StatusOr<bool> b = data.ToBool();
+inline util::Status WriteBool(int field_number, const DataPiece& data,
+                              CodedOutputStream* stream) {
+  util::StatusOr<bool> b = data.ToBool();
   if (b.ok()) {
     WireFormatLite::WriteBool(field_number, b.value(), stream);
   }
@@ -250,19 +249,19 @@
 }
 
 // Writes a BYTES field, including tag, to the stream.
-inline Status WriteBytes(int field_number, const DataPiece& data,
-                         CodedOutputStream* stream) {
-  StatusOr<std::string> c = data.ToBytes();
+inline util::Status WriteBytes(int field_number, const DataPiece& data,
+                               CodedOutputStream* stream) {
+  util::StatusOr<std::string> c = data.ToBytes();
   if (c.ok()) {
-    WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream);
+    WireFormatLite::WriteBytes(field_number, c.value(), stream);
   }
   return c.status();
 }
 
 // Writes a STRING field, including tag, to the stream.
-inline Status WriteString(int field_number, const DataPiece& data,
-                          CodedOutputStream* stream) {
-  StatusOr<std::string> s = data.ToString();
+inline util::Status WriteString(int field_number, const DataPiece& data,
+                                CodedOutputStream* stream) {
+  util::StatusOr<std::string> s = data.ToString();
   if (s.ok()) {
     WireFormatLite::WriteString(field_number, s.value(), stream);
   }
@@ -350,7 +349,9 @@
     for (std::set<const google::protobuf::Field*>::iterator it =
              required_fields_.begin();
          it != required_fields_.end(); ++it) {
-      ow_->MissingField((*it)->name());
+      ow_->MissingField(ow_->use_json_name_in_missing_fields_
+                            ? (*it)->json_name()
+                            : (*it)->name());
     }
   }
   // Computes the total number of proto bytes used by a message, also adjusts
@@ -406,7 +407,9 @@
         now->parent()->parent_field_ != now->parent_field_) {
       std::string name = now->parent_field_->name();
       int i = 0;
-      while (i < name.size() && (ascii_isalnum(name[i]) || name[i] == '_')) ++i;
+      while (i < name.size() &&
+             (ascii_isalnum(name[i]) || name[i] == '_'))
+        ++i;
       if (i > 0 && i == name.size()) {  // safe field name
         if (loc.empty()) {
           loc = name;
@@ -427,11 +430,11 @@
   return loc;
 }
 
-bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) {
+bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32_t index) {
   return oneof_indices_[index];
 }
 
-void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) {
+void ProtoWriter::ProtoElement::TakeOneofIndex(int32_t index) {
   oneof_indices_[index] = true;
 }
 
@@ -537,7 +540,7 @@
 
 ProtoWriter* ProtoWriter::RenderDataPiece(
     StringPiece name, const DataPiece& data) {
-  Status status;
+  util::Status status;
   if (invalid_depth_ > 0) return this;
 
   const google::protobuf::Field* field = Lookup(name);
@@ -591,16 +594,16 @@
   return this;
 }
 
-Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data,
-                              const google::protobuf::Enum* enum_type,
-                              CodedOutputStream* stream,
-                              bool use_lower_camel_for_enums,
-                              bool case_insensitive_enum_parsing,
-                              bool ignore_unknown_values) {
+util::Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data,
+                                    const google::protobuf::Enum* enum_type,
+                                    CodedOutputStream* stream,
+                                    bool use_lower_camel_for_enums,
+                                    bool case_insensitive_enum_parsing,
+                                    bool ignore_unknown_values) {
   bool is_unknown_enum_value = false;
-  StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums,
-                                case_insensitive_enum_parsing,
-                                ignore_unknown_values, &is_unknown_enum_value);
+  util::StatusOr<int> e = data.ToEnum(
+      enum_type, use_lower_camel_for_enums, case_insensitive_enum_parsing,
+      ignore_unknown_values, &is_unknown_enum_value);
   if (e.ok() && !is_unknown_enum_value) {
     WireFormatLite::WriteEnum(field_number, e.value(), stream);
   }
@@ -610,31 +613,17 @@
 ProtoWriter* ProtoWriter::RenderPrimitiveField(
     const google::protobuf::Field& field, const google::protobuf::Type& type,
     const DataPiece& data) {
-  Status status;
+  util::Status status;
 
   // Pushing a ProtoElement and then pop it off at the end for 2 purposes:
   // error location reporting and required field accounting.
   //
-  // For proto3, since there is no required field tracking, we only need to push
-  // ProtoElement for error cases.
+  // For proto3, since there is no required field tracking, we only need to
+  // push ProtoElement for error cases.
   if (!element_->proto3()) {
     element_.reset(new ProtoElement(element_.release(), &field, type, false));
   }
 
-  if (field.kind() == google::protobuf::Field::TYPE_UNKNOWN ||
-      field.kind() == google::protobuf::Field::TYPE_MESSAGE) {
-    // Push a ProtoElement for location reporting purposes.
-    if (element_->proto3()) {
-      element_.reset(new ProtoElement(element_.release(), &field, type, false));
-    }
-    InvalidValue(field.type_url().empty()
-                     ? google::protobuf::Field_Kind_Name(field.kind())
-                     : field.type_url(),
-                 data.ValueAsStringOrDefault(""));
-    element_.reset(element()->pop());
-    return this;
-  }
-
   switch (field.kind()) {
     case google::protobuf::Field::TYPE_INT32: {
       status = WriteInt32(field.number(), data, stream_.get());
@@ -703,9 +692,8 @@
           case_insensitive_enum_parsing_, ignore_unknown_enum_values_);
       break;
     }
-    default:  // TYPE_GROUP or TYPE_MESSAGE
-      status =
-          Status(util::error::INVALID_ARGUMENT, data.ToString().value());
+    default:  // TYPE_GROUP, TYPE_MESSAGE, TYPE_UNKNOWN.
+      status = util::InvalidArgumentError(data.ValueAsStringOrDefault(""));
   }
 
   if (!status.ok()) {
@@ -713,7 +701,9 @@
     if (element_->proto3()) {
       element_.reset(new ProtoElement(element_.release(), &field, type, false));
     }
-    InvalidValue(google::protobuf::Field_Kind_Name(field.kind()),
+    InvalidValue(field.type_url().empty()
+                     ? google::protobuf::Field_Kind_Name(field.kind())
+                     : field.type_url(),
                  status.message());
     element_.reset(element()->pop());
     return this;
@@ -809,8 +799,8 @@
     //   size_insert_.front().size: the size (integer) to be inserted.
     if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) {
       // Varint32 occupies at most 10 bytes.
-      uint8 insert_buffer[10];
-      uint8* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray(
+      uint8_t insert_buffer[10];
+      uint8_t* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray(
           size_insert_.front().size, insert_buffer);
       output_->Append(reinterpret_cast<const char*>(insert_buffer),
                       insert_buffer_pos - insert_buffer);
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index 7e79ce3..109c198 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
 
+#include <cstdint>
 #include <deque>
 #include <string>
 #include <vector>
@@ -46,6 +47,7 @@
 #include <google/protobuf/util/internal/structured_objectwriter.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/hash.h>
 #include <google/protobuf/stubs/status.h>
 
@@ -81,16 +83,16 @@
   ProtoWriter* RenderBool(StringPiece name, bool value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderInt32(StringPiece name, int32 value) override {
+  ProtoWriter* RenderInt32(StringPiece name, int32_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderUint32(StringPiece name, uint32 value) override {
+  ProtoWriter* RenderUint32(StringPiece name, uint32_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderInt64(StringPiece name, int64 value) override {
+  ProtoWriter* RenderInt64(StringPiece name, int64_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderUint64(StringPiece name, uint64 value) override {
+  ProtoWriter* RenderUint64(StringPiece name, uint64_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
   ProtoWriter* RenderDouble(StringPiece name, double value) override {
@@ -159,6 +161,11 @@
     case_insensitive_enum_parsing_ = case_insensitive_enum_parsing;
   }
 
+  void set_use_json_name_in_missing_fields(
+      bool use_json_name_in_missing_fields) {
+    use_json_name_in_missing_fields_ = use_json_name_in_missing_fields;
+  }
+
  protected:
   class PROTOBUF_EXPORT ProtoElement : public BaseElement,
                                        public LocationTrackerInterface {
@@ -198,11 +205,11 @@
     }
 
     // Returns true if the index is already taken by a preceding oneof input.
-    bool IsOneofIndexTaken(int32 index);
+    bool IsOneofIndexTaken(int32_t index);
 
     // Marks the oneof 'index' as taken. Future inputs to this oneof will
     // generate an error.
-    void TakeOneofIndex(int32 index);
+    void TakeOneofIndex(int32_t index);
 
     bool proto3() { return proto3_; }
 
@@ -309,11 +316,11 @@
  private:
   // Writes an ENUM field, including tag, to the stream.
   static util::Status WriteEnum(int field_number, const DataPiece& data,
-                                  const google::protobuf::Enum* enum_type,
-                                  io::CodedOutputStream* stream,
-                                  bool use_lower_camel_for_enums,
-                                  bool case_insensitive_enum_parsing,
-                                  bool ignore_unknown_values);
+                                const google::protobuf::Enum* enum_type,
+                                io::CodedOutputStream* stream,
+                                bool use_lower_camel_for_enums,
+                                bool case_insensitive_enum_parsing,
+                                bool ignore_unknown_values);
 
   // Variables for describing the structure of the input tree:
   // master_type_: descriptor for the whole protobuf message.
@@ -339,6 +346,9 @@
   // If true, check if enum name in UPPER_CASE matches the field name.
   bool case_insensitive_enum_parsing_;
 
+  // If true, use the json name in missing fields errors.
+  bool use_json_name_in_missing_fields_;
+
   // Variable for internal state processing:
   // element_    : the current element.
   // size_insert_: sizes of nested messages.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 80b1def..3a37d9c 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/protostream_objectsource.h>
 
+#include <cstdint>
 #include <unordered_map>
 #include <utility>
 
@@ -48,6 +49,7 @@
 #include <google/protobuf/util/internal/utility.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/time.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/status_macros.h>
@@ -58,17 +60,10 @@
 namespace google {
 namespace protobuf {
 namespace util {
-using util::Status;
-using util::StatusOr;
-namespace error {
-using util::error::Code;
-using util::error::INTERNAL;
-}  // namespace error
 namespace converter {
+
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat;
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
-using util::Status;
-using util::StatusOr;
 
 namespace {
 
@@ -86,9 +81,9 @@
     const google::protobuf::Enum& tech_enum, int number);
 
 // Utility function to format nanos.
-const std::string FormatNanos(uint32 nanos, bool with_trailing_zeros);
+const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros);
 
-StatusOr<std::string> MapKeyDefaultValueAsString(
+util::StatusOr<std::string> MapKeyDefaultValueAsString(
     const google::protobuf::Field& field) {
   switch (field.kind()) {
     case google::protobuf::Field::TYPE_BOOL:
@@ -107,7 +102,7 @@
     case google::protobuf::Field::TYPE_STRING:
       return std::string();
     default:
-      return Status(util::error::INTERNAL, "Invalid map key type.");
+      return util::InternalError("Invalid map key type.");
   }
 }
 }  // namespace
@@ -115,41 +110,27 @@
 
 ProtoStreamObjectSource::ProtoStreamObjectSource(
     io::CodedInputStream* stream, TypeResolver* type_resolver,
-    const google::protobuf::Type& type)
+    const google::protobuf::Type& type, const RenderOptions& render_options)
     : stream_(stream),
       typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
       own_typeinfo_(true),
       type_(type),
-      use_lower_camel_for_enums_(false),
-      use_ints_for_enums_(false),
-      preserve_proto_field_names_(false),
+      render_options_(render_options),
       recursion_depth_(0),
-      max_recursion_depth_(kDefaultMaxRecursionDepth),
-      render_unknown_fields_(false),
-      render_unknown_enum_values_(true),
-      add_trailing_zeros_for_timestamp_and_duration_(false),
-      suppress_empty_object_(false),
-      use_legacy_json_map_format_(false) {
+      max_recursion_depth_(kDefaultMaxRecursionDepth) {
   GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr.";
 }
 
 ProtoStreamObjectSource::ProtoStreamObjectSource(
     io::CodedInputStream* stream, const TypeInfo* typeinfo,
-    const google::protobuf::Type& type)
+    const google::protobuf::Type& type, const RenderOptions& render_options)
     : stream_(stream),
       typeinfo_(typeinfo),
       own_typeinfo_(false),
       type_(type),
-      use_lower_camel_for_enums_(false),
-      use_ints_for_enums_(false),
-      preserve_proto_field_names_(false),
+      render_options_(render_options),
       recursion_depth_(0),
-      max_recursion_depth_(kDefaultMaxRecursionDepth),
-      render_unknown_fields_(false),
-      render_unknown_enum_values_(true),
-      add_trailing_zeros_for_timestamp_and_duration_(false),
-      suppress_empty_object_(false),
-      use_legacy_json_map_format_(false) {
+      max_recursion_depth_(kDefaultMaxRecursionDepth) {
   GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr.";
 }
 
@@ -159,13 +140,13 @@
   }
 }
 
-Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name,
-                                             ObjectWriter* ow) const {
+util::Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name,
+                                                   ObjectWriter* ow) const {
   return WriteMessage(type_, name, 0, true, ow);
 }
 
 const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField(
-    const google::protobuf::Type& type, uint32 tag) const {
+    const google::protobuf::Type& type, uint32_t tag) const {
   // Lookup the new field in the type by tag number.
   const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3);
   // Verify if the field corresponds to the wire type in tag.
@@ -184,11 +165,10 @@
   return field;
 }
 
-Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
-                                             StringPiece name,
-                                             const uint32 end_tag,
-                                             bool include_start_and_end,
-                                             ObjectWriter* ow) const {
+util::Status ProtoStreamObjectSource::WriteMessage(
+    const google::protobuf::Type& type, StringPiece name,
+    const uint32_t end_tag, bool include_start_and_end,
+    ObjectWriter* ow) const {
 
   const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
   if (type_renderer != nullptr) {
@@ -198,12 +178,9 @@
   const google::protobuf::Field* field = nullptr;
   std::string field_name;
   // last_tag set to dummy value that is different from tag.
-  uint32 tag = stream_->ReadTag(), last_tag = tag + 1;
+  uint32_t tag = stream_->ReadTag(), last_tag = tag + 1;
   UnknownFieldSet unknown_fields;
 
-  if (!name.empty() && tag == end_tag && suppress_empty_object_) {
-    return util::Status();
-  }
 
   if (include_start_and_end) {
     ow->StartObject(name);
@@ -213,7 +190,7 @@
       last_tag = tag;
       field = FindAndVerifyField(type, tag);
       if (field != nullptr) {
-        if (preserve_proto_field_names_) {
+        if (render_options_.preserve_proto_field_names) {
           field_name = field->name();
         } else {
           field_name = field->json_name();
@@ -223,8 +200,9 @@
     if (field == nullptr) {
       // If we didn't find a field, skip this unknown tag.
       // TODO(wpoon): Check return boolean value.
-      WireFormat::SkipField(stream_, tag,
-                            render_unknown_fields_ ? &unknown_fields : nullptr);
+      WireFormat::SkipField(
+          stream_, tag,
+                                                nullptr);
       tag = stream_->ReadTag();
       continue;
     }
@@ -251,10 +229,10 @@
   return util::Status();
 }
 
-StatusOr<uint32> ProtoStreamObjectSource::RenderList(
+util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderList(
     const google::protobuf::Field* field, StringPiece name,
-    uint32 list_tag, ObjectWriter* ow) const {
-  uint32 tag_to_return = 0;
+    uint32_t list_tag, ObjectWriter* ow) const {
+  uint32_t tag_to_return = 0;
   ow->StartList(name);
   if (IsPackable(*field) &&
       list_tag ==
@@ -273,19 +251,20 @@
   return tag_to_return;
 }
 
-StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
+util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderMap(
     const google::protobuf::Field* field, StringPiece name,
-    uint32 list_tag, ObjectWriter* ow) const {
+    uint32_t list_tag, ObjectWriter* ow) const {
   const google::protobuf::Type* field_type =
       typeinfo_->GetTypeByTypeUrl(field->type_url());
-  uint32 tag_to_return = 0;
+  uint32_t tag_to_return = 0;
   do {
     // Render map entry message type.
-    uint32 buffer32;
+    uint32_t buffer32;
     stream_->ReadVarint32(&buffer32);  // message length
     int old_limit = stream_->PushLimit(buffer32);
     std::string map_key;
-    for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
+    for (uint32_t tag = stream_->ReadTag(); tag != 0;
+         tag = stream_->ReadTag()) {
       const google::protobuf::Field* field =
           FindAndVerifyField(*field_type, tag);
       if (field == nullptr) {
@@ -303,7 +282,7 @@
           if (key_field == nullptr) {
             // The Type info for this map entry is incorrect. It should always
             // have a field named "key" and with field number 1.
-            return Status(util::error::INTERNAL, "Invalid map entry.");
+            return util::InternalError("Invalid map entry.");
           }
           ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
         }
@@ -311,7 +290,7 @@
       } else {
         // The Type info for this map entry is incorrect. It should contain
         // exactly two fields with field number 1 and 2.
-        return Status(util::error::INTERNAL, "Invalid map entry.");
+        return util::InternalError("Invalid map entry.");
       }
     }
     stream_->PopLimit(old_limit);
@@ -319,9 +298,9 @@
   return tag_to_return;
 }
 
-Status ProtoStreamObjectSource::RenderPacked(
+util::Status ProtoStreamObjectSource::RenderPacked(
     const google::protobuf::Field* field, ObjectWriter* ow) const {
-  uint32 length;
+  uint32_t length;
   stream_->ReadVarint32(&length);
   int old_limit = stream_->PushLimit(length);
   while (stream_->BytesUntilLimit() > 0) {
@@ -331,21 +310,19 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderTimestamp(
+util::Status ProtoStreamObjectSource::RenderTimestamp(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  std::pair<int64, int32> p = os->ReadSecondsAndNanos(type);
-  int64 seconds = p.first;
-  int32 nanos = p.second;
+  std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type);
+  int64_t seconds = p.first;
+  int32_t nanos = p.second;
   if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
-    return Status(util::error::INTERNAL,
-                  StrCat("Timestamp seconds exceeds limit for field: ",
-                               field_name));
+    return util::InternalError(StrCat(
+        "Timestamp seconds exceeds limit for field: ", field_name));
   }
 
   if (nanos < 0 || nanos >= kNanosPerSecond) {
-    return Status(
-        util::error::INTERNAL,
+    return util::InternalError(
         StrCat("Timestamp nanos exceeds limit for field: ", field_name));
   }
 
@@ -355,29 +332,26 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderDuration(
+util::Status ProtoStreamObjectSource::RenderDuration(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  std::pair<int64, int32> p = os->ReadSecondsAndNanos(type);
-  int64 seconds = p.first;
-  int32 nanos = p.second;
+  std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type);
+  int64_t seconds = p.first;
+  int32_t nanos = p.second;
   if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) {
-    return Status(
-        util::error::INTERNAL,
+    return util::InternalError(
         StrCat("Duration seconds exceeds limit for field: ", field_name));
   }
 
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
-    return Status(
-        util::error::INTERNAL,
+    return util::InternalError(
         StrCat("Duration nanos exceeds limit for field: ", field_name));
   }
 
   std::string sign = "";
   if (seconds < 0) {
     if (nanos > 0) {
-      return Status(
-          util::error::INTERNAL,
+      return util::InternalError(
           StrCat("Duration nanos is non-negative, but seconds is "
                        "negative for field: ",
                        field_name));
@@ -391,18 +365,20 @@
   }
   std::string formatted_duration = StringPrintf(
       "%s%lld%ss", sign.c_str(), static_cast<long long>(seconds),  // NOLINT
-      FormatNanos(nanos, os->add_trailing_zeros_for_timestamp_and_duration_)
+      FormatNanos(
+          nanos,
+          false
+          )
           .c_str());
   ow->RenderString(field_name, formatted_duration);
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os,
-                                             const google::protobuf::Type& type,
-                                             StringPiece field_name,
-                                             ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // default value of Double wrapper value
+util::Status ProtoStreamObjectSource::RenderDouble(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // default value of Double wrapper value
   if (tag != 0) {
     os->stream_->ReadLittleEndian64(&buffer64);
     os->stream_->ReadTag();
@@ -411,12 +387,11 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os,
-                                            const google::protobuf::Type& type,
-                                            StringPiece field_name,
-                                            ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32 = 0;  // default value of Float wrapper value
+util::Status ProtoStreamObjectSource::RenderFloat(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32 = 0;  // default value of Float wrapper value
   if (tag != 0) {
     os->stream_->ReadLittleEndian32(&buffer32);
     os->stream_->ReadTag();
@@ -425,69 +400,64 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os,
-                                            const google::protobuf::Type& type,
-                                            StringPiece field_name,
-                                            ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // default value of Int64 wrapper value
+util::Status ProtoStreamObjectSource::RenderInt64(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // default value of Int64 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint64(&buffer64);
     os->stream_->ReadTag();
   }
-  ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+  ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64));
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os,
-                                             const google::protobuf::Type& type,
-                                             StringPiece field_name,
-                                             ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // default value of UInt64 wrapper value
+util::Status ProtoStreamObjectSource::RenderUInt64(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // default value of UInt64 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint64(&buffer64);
     os->stream_->ReadTag();
   }
-  ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+  ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64));
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os,
-                                            const google::protobuf::Type& type,
-                                            StringPiece field_name,
-                                            ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32 = 0;  // default value of Int32 wrapper value
+util::Status ProtoStreamObjectSource::RenderInt32(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32 = 0;  // default value of Int32 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);
     os->stream_->ReadTag();
   }
-  ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+  ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os,
-                                             const google::protobuf::Type& type,
-                                             StringPiece field_name,
-                                             ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32 = 0;  // default value of UInt32 wrapper value
+util::Status ProtoStreamObjectSource::RenderUInt32(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32 = 0;  // default value of UInt32 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);
     os->stream_->ReadTag();
   }
-  ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+  ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os,
-                                           const google::protobuf::Type& type,
-                                           StringPiece field_name,
-                                           ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // results in 'false' value as default, which is the
-                        // default value of Bool wrapper
+util::Status ProtoStreamObjectSource::RenderBool(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // results in 'false' value as default, which is the
+                          // default value of Bool wrapper
   if (tag != 0) {
     os->stream_->ReadVarint64(&buffer64);
     os->stream_->ReadTag();
@@ -496,12 +466,11 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os,
-                                             const google::protobuf::Type& type,
-                                             StringPiece field_name,
-                                             ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32;
+util::Status ProtoStreamObjectSource::RenderString(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32;
   std::string str;  // default value of empty for String wrapper
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);  // string size.
@@ -512,12 +481,11 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os,
-                                            const google::protobuf::Type& type,
-                                            StringPiece field_name,
-                                            ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32;
+util::Status ProtoStreamObjectSource::RenderBytes(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32;
   std::string str;
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);
@@ -528,15 +496,19 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os,
-                                             const google::protobuf::Type& type,
-                                             StringPiece field_name,
-                                             ObjectWriter* ow) {
+util::Status ProtoStreamObjectSource::RenderStruct(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
   const google::protobuf::Field* field = nullptr;
-  uint32 tag = os->stream_->ReadTag();
+  uint32_t tag = os->stream_->ReadTag();
   ow->StartObject(field_name);
   while (tag != 0) {
     field = os->FindAndVerifyField(type, tag);
+    if (field == nullptr) {
+      WireFormat::SkipField(os->stream_, tag, nullptr);
+      tag = os->stream_->ReadTag();
+      continue;
+    }
     // google.protobuf.Struct has only one field that is a map. Hence we use
     // RenderMap to render that field.
     if (os->IsMap(*field)) {
@@ -547,11 +519,11 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderStructValue(
+util::Status ProtoStreamObjectSource::RenderStructValue(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
   const google::protobuf::Field* field = nullptr;
-  for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+  for (uint32_t tag = os->stream_->ReadTag(); tag != 0;
        tag = os->stream_->ReadTag()) {
     field = os->FindAndVerifyField(type, tag);
     if (field == nullptr) {
@@ -564,10 +536,10 @@
 }
 
 // TODO(skarvaje): Avoid code duplication of for loops and SkipField logic.
-Status ProtoStreamObjectSource::RenderStructListValue(
+util::Status ProtoStreamObjectSource::RenderStructListValue(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
+  uint32_t tag = os->stream_->ReadTag();
 
   // Render empty list when we find empty ListValue message.
   if (tag == 0) {
@@ -588,12 +560,11 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os,
-                                          const google::protobuf::Type& type,
-                                          StringPiece field_name,
-                                          ObjectWriter* ow) {
+util::Status ProtoStreamObjectSource::RenderAny(
+    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+    StringPiece field_name, ObjectWriter* ow) {
   // An Any is of the form { string type_url = 1; bytes value = 2; }
-  uint32 tag;
+  uint32_t tag;
   std::string type_url;
   std::string value;
 
@@ -608,12 +579,12 @@
     // //google/protobuf/any.proto
     if (field->number() == 1) {
       // read type_url
-      uint32 type_url_size;
+      uint32_t type_url_size;
       os->stream_->ReadVarint32(&type_url_size);
       os->stream_->ReadString(&type_url, type_url_size);
     } else if (field->number() == 2) {
       // read value
-      uint32 value_size;
+      uint32_t value_size;
       os->stream_->ReadVarint32(&value_size);
       os->stream_->ReadString(&value, value_size);
     }
@@ -633,8 +604,7 @@
   // If there is a value but no type, we cannot render it, so report an error.
   if (type_url.empty()) {
     // TODO(sven): Add an external message once those are ready.
-    return util::Status(util::error::INTERNAL,
-                        "Invalid Any, the type_url is missing.");
+    return util::InternalError("Invalid Any, the type_url is missing.");
   }
 
   util::StatusOr<const google::protobuf::Type*> resolved_type =
@@ -643,8 +613,7 @@
   if (!resolved_type.ok()) {
     // Convert into an internal error, since this means the backend gave us
     // an invalid response (missing or invalid type information).
-    return util::Status(util::error::INTERNAL,
-                        resolved_type.status().message());
+    return util::InternalError(resolved_type.status().message());
   }
   // nested_type cannot be null at this time.
   const google::protobuf::Type* nested_type = resolved_type.value();
@@ -653,14 +622,8 @@
   io::CodedInputStream in_stream(&zero_copy_stream);
   // We know the type so we can render it. Recursively parse the nested stream
   // using a nested ProtoStreamObjectSource using our nested type information.
-  ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type);
-
-  // TODO(htuch): This is somewhat fragile, since new options may be omitted.
-  // We should probably do this via the constructor or some object grouping
-  // options.
-  nested_os.set_use_lower_camel_for_enums(os->use_lower_camel_for_enums_);
-  nested_os.set_use_ints_for_enums(os->use_ints_for_enums_);
-  nested_os.set_preserve_proto_field_names(os->preserve_proto_field_names_);
+  ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type,
+                                    os->render_options_);
 
   // We manually call start and end object here so we can inject the @type.
   ow->StartObject(field_name);
@@ -671,13 +634,13 @@
   return result;
 }
 
-Status ProtoStreamObjectSource::RenderFieldMask(
+util::Status ProtoStreamObjectSource::RenderFieldMask(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
   std::string combined;
-  uint32 buffer32;
-  uint32 paths_field_tag = 0;
-  for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+  uint32_t buffer32;
+  uint32_t paths_field_tag = 0;
+  for (uint32_t tag = os->stream_->ReadTag(); tag != 0;
        tag = os->stream_->ReadTag()) {
     if (paths_field_tag == 0) {
       const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
@@ -687,8 +650,7 @@
       }
     }
     if (paths_field_tag != tag) {
-      return util::Status(util::error::INTERNAL,
-                          "Invalid FieldMask, unexpected field.");
+      return util::InternalError("Invalid FieldMask, unexpected field.");
     }
     std::string str;
     os->stream_->ReadVarint32(&buffer32);  // string size.
@@ -704,7 +666,7 @@
 
 
 std::unordered_map<std::string, ProtoStreamObjectSource::TypeRenderer>*
-    ProtoStreamObjectSource::renderers_ = NULL;
+    ProtoStreamObjectSource::renderers_ = nullptr;
 PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_;
 
 
@@ -747,7 +709,7 @@
 
 void ProtoStreamObjectSource::DeleteRendererMap() {
   delete ProtoStreamObjectSource::renderers_;
-  renderers_ = NULL;
+  renderers_ = nullptr;
 }
 
 // static
@@ -758,22 +720,21 @@
   return FindOrNull(*renderers_, type_url);
 }
 
-Status ProtoStreamObjectSource::RenderField(
+util::Status ProtoStreamObjectSource::RenderField(
     const google::protobuf::Field* field, StringPiece field_name,
     ObjectWriter* ow) const {
   // Short-circuit message types as it tends to call WriteMessage recursively
   // and ends up using a lot of stack space. Keep the stack usage of this
   // message small in order to preserve stack space and not crash.
   if (field->kind() == google::protobuf::Field::TYPE_MESSAGE) {
-    uint32 buffer32;
+    uint32_t buffer32;
     stream_->ReadVarint32(&buffer32);  // message length
     int old_limit = stream_->PushLimit(buffer32);
     // Get the nested message type for this field.
     const google::protobuf::Type* type =
         typeinfo_->GetTypeByTypeUrl(field->type_url());
     if (type == nullptr) {
-      return Status(
-          util::error::INTERNAL,
+      return util::InternalError(
           StrCat("Invalid configuration. Could not find the type: ",
                        field->type_url()));
     }
@@ -790,8 +751,8 @@
     --recursion_depth_;
 
     if (!stream_->ConsumedEntireMessage()) {
-      return Status(util::error::INVALID_ARGUMENT,
-                    "Nested protocol message not parsed in its entirety.");
+      return util::InvalidArgumentError(
+          "Nested protocol message not parsed in its entirety.");
     }
     stream_->PopLimit(old_limit);
   } else {
@@ -801,12 +762,12 @@
   return util::Status();
 }
 
-Status ProtoStreamObjectSource::RenderNonMessageField(
+util::Status ProtoStreamObjectSource::RenderNonMessageField(
     const google::protobuf::Field* field, StringPiece field_name,
     ObjectWriter* ow) const {
   // Temporary buffers of different types.
-  uint32 buffer32;
-  uint64 buffer64;
+  uint32_t buffer32 = 0;
+  uint64_t buffer64 = 0;
   std::string strbuffer;
   switch (field->kind()) {
     case google::protobuf::Field::TYPE_BOOL: {
@@ -816,7 +777,7 @@
     }
     case google::protobuf::Field::TYPE_INT32: {
       stream_->ReadVarint32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_INT64: {
@@ -826,7 +787,7 @@
     }
     case google::protobuf::Field::TYPE_UINT32: {
       stream_->ReadVarint32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_UINT64: {
@@ -846,7 +807,7 @@
     }
     case google::protobuf::Field::TYPE_SFIXED32: {
       stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED64: {
@@ -856,7 +817,7 @@
     }
     case google::protobuf::Field::TYPE_FIXED32: {
       stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED64: {
@@ -894,19 +855,19 @@
         const google::protobuf::EnumValue* enum_value =
             FindEnumValueByNumber(*en, buffer32);
         if (enum_value != nullptr) {
-          if (use_ints_for_enums_) {
+          if (render_options_.use_ints_for_enums) {
             ow->RenderInt32(field_name, buffer32);
-          } else if (use_lower_camel_for_enums_) {
+          } else if (render_options_.use_lower_camel_for_enums) {
             ow->RenderString(field_name,
                              EnumValueNameToLowerCamelCase(enum_value->name()));
           } else {
             ow->RenderString(field_name, enum_value->name());
           }
-        } else if (render_unknown_enum_values_) {
-          ow->RenderInt32(field_name, buffer32);
+        } else {
+            ow->RenderInt32(field_name, buffer32);
         }
-      } else if (render_unknown_enum_values_) {
-        ow->RenderInt32(field_name, buffer32);
+      } else {
+          ow->RenderInt32(field_name, buffer32);
       }
       break;
     }
@@ -934,85 +895,85 @@
   std::string result;
   switch (field.kind()) {
     case google::protobuf::Field::TYPE_BOOL: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
       result = buffer64 != 0 ? "true" : "false";
       break;
     }
     case google::protobuf::Field::TYPE_INT32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
-      result = StrCat(bit_cast<int32>(buffer32));
+      result = StrCat(bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_INT64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
-      result = StrCat(bit_cast<int64>(buffer64));
+      result = StrCat(bit_cast<int64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_UINT32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
-      result = StrCat(bit_cast<uint32>(buffer32));
+      result = StrCat(bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_UINT64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
-      result = StrCat(bit_cast<uint64>(buffer64));
+      result = StrCat(bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_SINT32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
       result = StrCat(WireFormatLite::ZigZagDecode32(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SINT64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
       result = StrCat(WireFormatLite::ZigZagDecode64(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
-      result = StrCat(bit_cast<int32>(buffer32));
+      result = StrCat(bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadLittleEndian64(&buffer64);
-      result = StrCat(bit_cast<int64>(buffer64));
+      result = StrCat(bit_cast<int64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
-      result = StrCat(bit_cast<uint32>(buffer32));
+      result = StrCat(bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadLittleEndian64(&buffer64);
-      result = StrCat(bit_cast<uint64>(buffer64));
+      result = StrCat(bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_FLOAT: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
       result = SimpleFtoa(bit_cast<float>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_DOUBLE: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadLittleEndian64(&buffer64);
       result = SimpleDtoa(bit_cast<double>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_ENUM: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
       // Get the nested enum type for this field.
       // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
@@ -1030,13 +991,13 @@
       break;
     }
     case google::protobuf::Field::TYPE_STRING: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);  // string size.
       stream_->ReadString(&result, buffer32);
       break;
     }
     case google::protobuf::Field::TYPE_BYTES: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);  // bytes size.
       stream_->ReadString(&result, buffer32);
       break;
@@ -1057,13 +1018,13 @@
          util::converter::IsMap(field, *field_type);
 }
 
-std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
+std::pair<int64_t, int32_t> ProtoStreamObjectSource::ReadSecondsAndNanos(
     const google::protobuf::Type& type) const {
-  uint64 seconds = 0;
-  uint32 nanos = 0;
-  uint32 tag = 0;
-  int64 signed_seconds = 0;
-  int32 signed_nanos = 0;
+  uint64_t seconds = 0;
+  uint32_t nanos = 0;
+  uint32_t tag = 0;
+  int64_t signed_seconds = 0;
+  int32_t signed_nanos = 0;
 
   for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
     const google::protobuf::Field* field = FindAndVerifyField(type, tag);
@@ -1076,21 +1037,20 @@
     if (field->number() == 1) {
       // read seconds
       stream_->ReadVarint64(&seconds);
-      signed_seconds = bit_cast<int64>(seconds);
+      signed_seconds = bit_cast<int64_t>(seconds);
     } else if (field->number() == 2) {
       // read nanos
       stream_->ReadVarint32(&nanos);
-      signed_nanos = bit_cast<int32>(nanos);
+      signed_nanos = bit_cast<int32_t>(nanos);
     }
   }
-  return std::pair<int64, int32>(signed_seconds, signed_nanos);
+  return std::pair<int64_t, int32_t>(signed_seconds, signed_nanos);
 }
 
-Status ProtoStreamObjectSource::IncrementRecursionDepth(
+util::Status ProtoStreamObjectSource::IncrementRecursionDepth(
     StringPiece type_name, StringPiece field_name) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return Status(
-        util::error::INVALID_ARGUMENT,
+    return util::InvalidArgumentError(
         StrCat("Message too deep. Max recursion depth reached for type '",
                      type_name, "', field '", field_name, "'"));
   }
@@ -1131,13 +1091,14 @@
 
 // TODO(skarvaje): Look into optimizing this by not doing computation on
 // double.
-const std::string FormatNanos(uint32 nanos, bool with_trailing_zeros) {
+const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros) {
   if (nanos == 0) {
     return with_trailing_zeros ? ".000" : "";
   }
 
-  const char* format =
-      (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f";
+  const char* format = (nanos % 1000 != 0)      ? "%.9f"
+                       : (nanos % 1000000 != 0) ? "%.6f"
+                                                : "%.3f";
   std::string formatted =
       StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond);
   // remove the leading 0 before decimal.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index a83031d..60eaf4e 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -31,20 +31,23 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
 
+#include <cstdint>
 #include <functional>
 #include <string>
 #include <unordered_map>
 
+#include <google/protobuf/stubs/status.h>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/util/internal/type_info.h>
 #include <google/protobuf/util/internal/object_source.h>
 #include <google/protobuf/util/internal/object_writer.h>
 #include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/hash.h>
 #include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -71,51 +74,59 @@
 //   Status status = os.WriteTo(<some ObjectWriter>);
 class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
  public:
+
+  struct RenderOptions {
+    RenderOptions() = default;
+    RenderOptions(const RenderOptions&) = default;
+
+    // Sets whether or not to use lowerCamelCase casing for enum values. If set
+    // to false, enum values are output without any case conversions.
+    //
+    // For example, if we have an enum:
+    // enum Type {
+    //   ACTION_AND_ADVENTURE = 1;
+    // }
+    // Type type = 20;
+    //
+    // And this option is set to true. Then the rendered "type" field will have
+    // the string "actionAndAdventure".
+    // {
+    //   ...
+    //   "type": "actionAndAdventure",
+    //   ...
+    // }
+    //
+    // If set to false, the rendered "type" field will have the string
+    // "ACTION_AND_ADVENTURE".
+    // {
+    //   ...
+    //   "type": "ACTION_AND_ADVENTURE",
+    //   ...
+    // }
+    bool use_lower_camel_for_enums = false;
+
+    // Sets whether to always output enums as ints, by default this is off, and
+    // enums are rendered as strings.
+    bool use_ints_for_enums = false;
+
+    // Whether to preserve proto field names
+    bool preserve_proto_field_names = false;
+
+  };
+
   ProtoStreamObjectSource(io::CodedInputStream* stream,
                           TypeResolver* type_resolver,
-                          const google::protobuf::Type& type);
+                          const google::protobuf::Type& type)
+      : ProtoStreamObjectSource(stream, type_resolver, type, RenderOptions()) {}
+  ProtoStreamObjectSource(io::CodedInputStream* stream,
+                          TypeResolver* type_resolver,
+                          const google::protobuf::Type& type,
+                          const RenderOptions& render_options);
 
   ~ProtoStreamObjectSource() override;
 
   util::Status NamedWriteTo(StringPiece name,
-                              ObjectWriter* ow) const override;
-
-  // Sets whether or not to use lowerCamelCase casing for enum values. If set to
-  // false, enum values are output without any case conversions.
-  //
-  // For example, if we have an enum:
-  // enum Type {
-  //   ACTION_AND_ADVENTURE = 1;
-  // }
-  // Type type = 20;
-  //
-  // And this option is set to true. Then the rendered "type" field will have
-  // the string "actionAndAdventure".
-  // {
-  //   ...
-  //   "type": "actionAndAdventure",
-  //   ...
-  // }
-  //
-  // If set to false, the rendered "type" field will have the string
-  // "ACTION_AND_ADVENTURE".
-  // {
-  //   ...
-  //   "type": "ACTION_AND_ADVENTURE",
-  //   ...
-  // }
-  void set_use_lower_camel_for_enums(bool value) {
-    use_lower_camel_for_enums_ = value;
-  }
-
-  // Sets whether to always output enums as ints, by default this is off, and
-  // enums are rendered as strings.
-  void set_use_ints_for_enums(bool value) { use_ints_for_enums_ = value; }
-
-  // Sets whether to use original proto field names
-  void set_preserve_proto_field_names(bool value) {
-    preserve_proto_field_names_ = value;
-  }
+                            ObjectWriter* ow) const override;
 
   // Sets the max recursion depth of proto message to be deserialized. Proto
   // messages over this depth will fail to be deserialized.
@@ -124,34 +135,33 @@
     max_recursion_depth_ = max_depth;
   }
 
-
  protected:
   // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
   // found this method will complete, allowing it to be used for parsing both
   // nested messages (end with 0) and nested groups (end with group end tag).
   // The include_start_and_end parameter allows this method to be called when
   // already inside of an object, and skip calling StartObject and EndObject.
-  virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
-                                      StringPiece name,
-                                      const uint32 end_tag,
-                                      bool include_start_and_end,
-                                      ObjectWriter* ow) const;
+  virtual util::Status WriteMessage(const google::protobuf::Type& type,
+                                    StringPiece name,
+                                    const uint32_t end_tag,
+                                    bool include_start_and_end,
+                                    ObjectWriter* ow) const;
 
   // Renders a repeating field (packed or unpacked).  Returns the next tag after
   // reading all sequential repeating elements. The caller should use this tag
   // before reading more tags from the stream.
-  virtual util::StatusOr<uint32> RenderList(
+  virtual util::StatusOr<uint32_t> RenderList(
       const google::protobuf::Field* field, StringPiece name,
-      uint32 list_tag, ObjectWriter* ow) const;
+      uint32_t list_tag, ObjectWriter* ow) const;
 
   // Looks up a field and verify its consistency with wire type in tag.
   const google::protobuf::Field* FindAndVerifyField(
-      const google::protobuf::Type& type, uint32 tag) const;
+      const google::protobuf::Type& type, uint32_t tag) const;
 
   // Renders a field value to the ObjectWriter.
   virtual util::Status RenderField(const google::protobuf::Field* field,
-                                     StringPiece field_name,
-                                     ObjectWriter* ow) const;
+                                   StringPiece field_name,
+                                   ObjectWriter* ow) const;
 
   // Reads field value according to Field spec in 'field' and returns the read
   // value as string. This only works for primitive datatypes (no message
@@ -160,14 +170,18 @@
       const google::protobuf::Field& field) const;
 
 
+  // Returns the input stream.
+  io::CodedInputStream* stream() const { return stream_; }
+
  private:
   ProtoStreamObjectSource(io::CodedInputStream* stream,
                           const TypeInfo* typeinfo,
-                          const google::protobuf::Type& type);
+                          const google::protobuf::Type& type,
+                          const RenderOptions& render_options);
   // Function that renders a well known type with a modified behavior.
   typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
-                                         const google::protobuf::Type&,
-                                         StringPiece, ObjectWriter*);
+                                       const google::protobuf::Type&,
+                                       StringPiece, ObjectWriter*);
 
   // TODO(skarvaje): Mark these methods as non-const as they modify internal
   // state (stream_).
@@ -175,85 +189,83 @@
   // Renders a NWP map.
   // Returns the next tag after reading all map entries. The caller should use
   // this tag before reading more tags from the stream.
-  util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
-                                     StringPiece name, uint32 list_tag,
+  util::StatusOr<uint32_t> RenderMap(const google::protobuf::Field* field,
+                                     StringPiece name, uint32_t list_tag,
                                      ObjectWriter* ow) const;
 
   // Renders a packed repeating field. A packed field is stored as:
   // {tag length item1 item2 item3} instead of the less efficient
   // {tag item1 tag item2 tag item3}.
   util::Status RenderPacked(const google::protobuf::Field* field,
-                              ObjectWriter* ow) const;
+                            ObjectWriter* ow) const;
 
   // Renders a google.protobuf.Timestamp value to ObjectWriter
   static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
-                                        const google::protobuf::Type& type,
-                                        StringPiece name,
-                                        ObjectWriter* ow);
+                                      const google::protobuf::Type& type,
+                                      StringPiece name, ObjectWriter* ow);
 
   // Renders a google.protobuf.Duration value to ObjectWriter
   static util::Status RenderDuration(const ProtoStreamObjectSource* os,
-                                       const google::protobuf::Type& type,
-                                       StringPiece name,
-                                       ObjectWriter* ow);
+                                     const google::protobuf::Type& type,
+                                     StringPiece name, ObjectWriter* ow);
 
   // Following RenderTYPE functions render well known types in
   // google/protobuf/wrappers.proto corresponding to TYPE.
   static util::Status RenderDouble(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-  static util::Status RenderFloat(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-  static util::Status RenderInt64(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-  static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-  static util::Status RenderInt32(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-  static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-  static util::Status RenderBool(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
                                    StringPiece name, ObjectWriter* ow);
+  static util::Status RenderFloat(const ProtoStreamObjectSource* os,
+                                  const google::protobuf::Type& type,
+                                  StringPiece name, ObjectWriter* ow);
+  static util::Status RenderInt64(const ProtoStreamObjectSource* os,
+                                  const google::protobuf::Type& type,
+                                  StringPiece name, ObjectWriter* ow);
+  static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
+  static util::Status RenderInt32(const ProtoStreamObjectSource* os,
+                                  const google::protobuf::Type& type,
+                                  StringPiece name, ObjectWriter* ow);
+  static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
+  static util::Status RenderBool(const ProtoStreamObjectSource* os,
+                                 const google::protobuf::Type& type,
+                                 StringPiece name, ObjectWriter* ow);
   static util::Status RenderString(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
   static util::Status RenderBytes(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-
-  // Renders a google.protobuf.Struct to ObjectWriter.
-  static util::Status RenderStruct(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-
-  // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
-  static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
-                                          const google::protobuf::Type& type,
-                                          StringPiece name,
-                                          ObjectWriter* ow);
-
-  // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
-  static util::Status RenderStructListValue(
-      const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-      StringPiece name, ObjectWriter* ow);
-
-  // Render the "Any" type.
-  static util::Status RenderAny(const ProtoStreamObjectSource* os,
                                   const google::protobuf::Type& type,
                                   StringPiece name, ObjectWriter* ow);
 
-  // Render the "FieldMask" type.
-  static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
+  // Renders a google.protobuf.Struct to ObjectWriter.
+  static util::Status RenderStruct(const ProtoStreamObjectSource* os,
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
+
+  // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
+  static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
                                         const google::protobuf::Type& type,
                                         StringPiece name,
                                         ObjectWriter* ow);
 
+  // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
+  static util::Status RenderStructListValue(const ProtoStreamObjectSource* os,
+                                            const google::protobuf::Type& type,
+                                            StringPiece name,
+                                            ObjectWriter* ow);
+
+  // Render the "Any" type.
+  static util::Status RenderAny(const ProtoStreamObjectSource* os,
+                                const google::protobuf::Type& type,
+                                StringPiece name, ObjectWriter* ow);
+
+  // Render the "FieldMask" type.
+  static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
+                                      const google::protobuf::Type& type,
+                                      StringPiece name, ObjectWriter* ow);
+
   static std::unordered_map<std::string, TypeRenderer>* renderers_;
   static void InitRendererMap();
   static void DeleteRendererMap();
@@ -262,8 +274,8 @@
   // Same as above but renders all non-message field types. Callers don't call
   // this function directly. They just use RenderField.
   util::Status RenderNonMessageField(const google::protobuf::Field* field,
-                                       StringPiece field_name,
-                                       ObjectWriter* ow) const;
+                                     StringPiece field_name,
+                                     ObjectWriter* ow) const;
 
 
   // Utility function to detect proto maps. The 'field' MUST be repeated.
@@ -271,17 +283,17 @@
 
   // Utility to read int64 and int32 values from a message type in stream_.
   // Used for reading google.protobuf.Timestamp and Duration messages.
-  std::pair<int64, int32> ReadSecondsAndNanos(
+  std::pair<int64_t, int32_t> ReadSecondsAndNanos(
       const google::protobuf::Type& type) const;
 
   // Helper function to check recursion depth and increment it. It will return
-  // Status::OK if the current depth is allowed. Otherwise an error is returned.
+  // OkStatus() if the current depth is allowed. Otherwise an error is returned.
   // type_name and field_name are used for error reporting.
   util::Status IncrementRecursionDepth(StringPiece type_name,
-                                         StringPiece field_name) const;
+                                       StringPiece field_name) const;
 
   // Input stream to read from. Ownership rests with the caller.
-  io::CodedInputStream* stream_;
+  mutable io::CodedInputStream* stream_;
 
   // Type information for all the types used in the descriptor. Used to find
   // google::protobuf::Type of nested messages/enums.
@@ -295,14 +307,7 @@
   const google::protobuf::Type& type_;
 
 
-  // Whether to render enums using lowerCamelCase. Defaults to false.
-  bool use_lower_camel_for_enums_;
-
-  // Whether to render enums as ints always. Defaults to false.
-  bool use_ints_for_enums_;
-
-  // Whether to preserve proto field names
-  bool preserve_proto_field_names_;
+  const RenderOptions render_options_;
 
   // Tracks current recursion depth.
   mutable int recursion_depth_;
@@ -310,22 +315,6 @@
   // Maximum allowed recursion depth.
   int max_recursion_depth_;
 
-  // Whether to render unknown fields.
-  bool render_unknown_fields_;
-
-  // Whether to render unknown enum values.
-  bool render_unknown_enum_values_;
-
-  // Whether to add trailing zeros for timestamp and duration.
-  bool add_trailing_zeros_for_timestamp_and_duration_;
-
-  // Whether output the empty object or not. If false, output JSON string like:
-  // "'objectName' : {}". If true, then no outputs. This only happens when all
-  // the fields of the message are filtered out by field mask.
-  bool suppress_empty_object_;
-
-  bool use_legacy_json_map_format_;
-
   GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
 };
 
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 22fc3f6..6ea8b29 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/protostream_objectsource.h>
 
+#include <cstdint>
 #include <memory>
 #include <sstream>
 
@@ -49,6 +50,7 @@
 #include <google/protobuf/util/internal/constants.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/status.h>
 
 
 namespace google {
@@ -78,7 +80,6 @@
 using proto_util_converter::testing::StructType;
 using proto_util_converter::testing::TimestampDuration;
 using ::testing::_;
-using util::Status;
 
 
 namespace {
@@ -105,23 +106,23 @@
   virtual ~ProtostreamObjectSourceTest() {}
 
   void DoTest(const Message& msg, const Descriptor* descriptor) {
-    Status status = ExecuteTest(msg, descriptor);
+    util::Status status = ExecuteTest(msg, descriptor);
     EXPECT_EQ(util::Status(), status);
   }
 
-  Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
+  util::Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
     std::ostringstream oss;
     msg.SerializePartialToOstream(&oss);
     std::string proto = oss.str();
     ArrayInputStream arr_stream(proto.data(), proto.size());
     CodedInputStream in_stream(&arr_stream);
 
-    std::unique_ptr<ProtoStreamObjectSource> os(
-        helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
-    if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
-    if (use_ints_for_enums_) os->set_use_ints_for_enums(true);
-    if (use_preserve_proto_field_names_)
-      os->set_preserve_proto_field_names(true);
+    ProtoStreamObjectSource::RenderOptions render_options;
+    render_options.use_lower_camel_for_enums = use_lower_camel_for_enums_;
+    render_options.use_ints_for_enums = use_ints_for_enums_;
+    render_options.preserve_proto_field_names = use_preserve_proto_field_names_;
+    std::unique_ptr<ProtoStreamObjectSource> os(helper_.NewProtoSource(
+        &in_stream, GetTypeUrl(descriptor), render_options));
     os->set_max_recursion_depth(64);
     return os->WriteTo(&mock_);
   }
@@ -129,13 +130,13 @@
   void PrepareExpectingObjectWriterForRepeatedPrimitive() {
     ow_.StartObject("")
         ->StartList("repFix32")
-        ->RenderUint32("", bit_cast<uint32>(3201))
-        ->RenderUint32("", bit_cast<uint32>(0))
-        ->RenderUint32("", bit_cast<uint32>(3202))
+        ->RenderUint32("", bit_cast<uint32_t>(3201))
+        ->RenderUint32("", bit_cast<uint32_t>(0))
+        ->RenderUint32("", bit_cast<uint32_t>(3202))
         ->EndList()
         ->StartList("repU32")
-        ->RenderUint32("", bit_cast<uint32>(3203))
-        ->RenderUint32("", bit_cast<uint32>(0))
+        ->RenderUint32("", bit_cast<uint32_t>(3203))
+        ->RenderUint32("", bit_cast<uint32_t>(0))
         ->EndList()
         ->StartList("repI32")
         ->RenderInt32("", 0)
@@ -152,13 +153,13 @@
         ->RenderInt32("", 3208)
         ->EndList()
         ->StartList("repFix64")
-        ->RenderUint64("", bit_cast<uint64>(6401LL))
-        ->RenderUint64("", bit_cast<uint64>(0LL))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6401}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{0}))
         ->EndList()
         ->StartList("repU64")
-        ->RenderUint64("", bit_cast<uint64>(0LL))
-        ->RenderUint64("", bit_cast<uint64>(6402LL))
-        ->RenderUint64("", bit_cast<uint64>(6403LL))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{0}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6402}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6403}))
         ->EndList()
         ->StartList("repI64")
         ->RenderInt64("", 6404L)
@@ -320,13 +321,13 @@
   primitive.set_bool_(true);
 
   ow_.StartObject("")
-      ->RenderUint32("fix32", bit_cast<uint32>(3201))
-      ->RenderUint32("u32", bit_cast<uint32>(3202))
+      ->RenderUint32("fix32", bit_cast<uint32_t>(3201))
+      ->RenderUint32("u32", bit_cast<uint32_t>(3202))
       ->RenderInt32("i32", 3203)
       ->RenderInt32("sf32", 3204)
       ->RenderInt32("s32", 3205)
-      ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
-      ->RenderUint64("u64", bit_cast<uint64>(6402LL))
+      ->RenderUint64("fix64", bit_cast<uint64_t>(int64_t{6401}))
+      ->RenderUint64("u64", bit_cast<uint64_t>(int64_t{6402}))
       ->RenderInt64("i64", 6403L)
       ->RenderInt64("sf64", 6404L)
       ->RenderInt64("s64", 6405L)
@@ -424,10 +425,10 @@
       ->RenderBool("", false)
       ->EndList()
       ->StartList("name")
-      ->RenderUint64("", static_cast<uint64>('j'))
-      ->RenderUint64("", static_cast<uint64>('o'))
-      ->RenderUint64("", static_cast<uint64>('h'))
-      ->RenderUint64("", static_cast<uint64>('n'))
+      ->RenderUint64("", static_cast<uint64_t>('j'))
+      ->RenderUint64("", static_cast<uint64_t>('o'))
+      ->RenderUint64("", static_cast<uint64_t>('h'))
+      ->RenderUint64("", static_cast<uint64_t>('n'))
       ->EndList()
       ->RenderString("pseudonym", "phil")
       ->RenderString("pseudonym", "bob")
@@ -595,8 +596,8 @@
     current = next;
   }
 
-  Status status = ExecuteTest(cyclic, Cyclic::descriptor());
-  EXPECT_EQ(util::error::INVALID_ARGUMENT, status.code());
+  util::Status status = ExecuteTest(cyclic, Cyclic::descriptor());
+  EXPECT_TRUE(util::IsInvalidArgument(status));
 }
 
 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
@@ -941,8 +942,8 @@
   // We start the "AnyOut" part and then fail when we hit the Any object.
   ow_.StartObject("");
 
-  Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  util::Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
@@ -957,8 +958,8 @@
   // We start the "AnyOut" part and then fail when we hit the Any object.
   ow_.StartObject("");
 
-  Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  util::Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
@@ -973,8 +974,8 @@
   // We start the "AnyOut" part and then fail when we hit the Any object.
   ow_.StartObject("");
 
-  Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  util::Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
@@ -1106,8 +1107,8 @@
   ts->set_seconds(kTimestampMinSeconds - 1);
   ow_.StartObject("");
 
-  Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
@@ -1117,8 +1118,8 @@
   ts->set_seconds(kTimestampMaxSeconds + 1);
   ow_.StartObject("");
 
-  Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
@@ -1128,8 +1129,8 @@
   dur->set_seconds(kDurationMinSeconds - 1);
   ow_.StartObject("");
 
-  Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
@@ -1139,8 +1140,8 @@
   dur->set_seconds(kDurationMaxSeconds + 1);
   ow_.StartObject("");
 
-  Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index 527d5e7..ec9a2ce 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/protostream_objectwriter.h>
 
+#include <cstdint>
 #include <functional>
 #include <stack>
 #include <unordered_map>
@@ -42,9 +43,10 @@
 #include <google/protobuf/util/internal/constants.h>
 #include <google/protobuf/util/internal/utility.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/time.h>
 #include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/statusor.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -57,8 +59,6 @@
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
 using std::placeholders::_1;
 using util::Status;
-using util::StatusOr;
-using util::error::INVALID_ARGUMENT;
 
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
@@ -73,6 +73,7 @@
   set_ignore_unknown_enum_values(options_.ignore_unknown_enum_values);
   set_use_lower_camel_for_enums(options_.use_lower_camel_for_enums);
   set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing);
+  set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields);
 }
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
@@ -86,6 +87,7 @@
   set_ignore_unknown_fields(options_.ignore_unknown_fields);
   set_use_lower_camel_for_enums(options.use_lower_camel_for_enums);
   set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing);
+  set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields);
 }
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
@@ -127,7 +129,7 @@
 Status GetNanosFromStringPiece(StringPiece s_nanos,
                                const char* parse_failure_message,
                                const char* exceeded_limit_message,
-                               int32* nanos) {
+                               int32_t* nanos) {
   *nanos = 0;
 
   // Count the number of leading 0s and consume them.
@@ -135,30 +137,30 @@
   while (s_nanos.Consume("0")) {
     num_leading_zeros++;
   }
-  int32 i_nanos = 0;
+  int32_t i_nanos = 0;
   // 's_nanos' contains fractional seconds -- i.e. 'nanos' is equal to
   // "0." + s_nanos.ToString() seconds. An int32 is used for the
   // conversion to 'nanos', rather than a double, so that there is no
   // loss of precision.
   if (!s_nanos.empty() && !safe_strto32(s_nanos, &i_nanos)) {
-    return Status(util::error::INVALID_ARGUMENT, parse_failure_message);
+    return util::InvalidArgumentError(parse_failure_message);
   }
   if (i_nanos > kNanosPerSecond || i_nanos < 0) {
-    return Status(util::error::INVALID_ARGUMENT, exceeded_limit_message);
+    return util::InvalidArgumentError(exceeded_limit_message);
   }
   // s_nanos should only have digits. No whitespace.
   if (s_nanos.find_first_not_of("0123456789") != StringPiece::npos) {
-    return Status(util::error::INVALID_ARGUMENT, parse_failure_message);
+    return util::InvalidArgumentError(parse_failure_message);
   }
 
   if (i_nanos > 0) {
     // 'scale' is the number of digits to the right of the decimal
     // point in "0." + s_nanos.ToString()
-    int32 scale = num_leading_zeros + s_nanos.size();
+    int32_t scale = num_leading_zeros + s_nanos.size();
     // 'conversion' converts i_nanos into nanoseconds.
     // conversion = kNanosPerSecond / static_cast<int32>(std::pow(10, scale))
     // For efficiency, we precompute the conversion factor.
-    int32 conversion = 0;
+    int32_t conversion = 0;
     switch (scale) {
       case 1:
         conversion = 100000000;
@@ -188,8 +190,7 @@
         conversion = 1;
         break;
       default:
-        return Status(util::error::INVALID_ARGUMENT,
-                      exceeded_limit_message);
+        return util::InvalidArgumentError(exceeded_limit_message);
     }
     *nanos = i_nanos * conversion;
   }
@@ -328,7 +329,7 @@
   if (value.type() == DataPiece::TYPE_STRING) {
     type_url_ = std::string(value.str());
   } else {
-    StatusOr<std::string> s = value.ToString();
+    util::StatusOr<std::string> s = value.ToString();
     if (!s.ok()) {
       parent_->InvalidValue("String", s.status().message());
       invalid_ = true;
@@ -337,7 +338,7 @@
     type_url_ = s.value();
   }
   // Resolve the type url, and report an error if we failed to resolve it.
-  StatusOr<const google::protobuf::Type*> resolved_type =
+  util::StatusOr<const google::protobuf::Type*> resolved_type =
       parent_->typeinfo()->ResolveTypeUrl(type_url_);
   if (!resolved_type.ok()) {
     parent_->InvalidValue("Any", resolved_type.status().message());
@@ -435,7 +436,7 @@
     StrAppend(&value_storage_, value_.str());
     value_ = DataPiece(value_storage_, value_.use_strict_base64_decoding());
   } else if (value_.type() == DataPiece::TYPE_BYTES) {
-    value_storage_ = value_.ToBytes().ValueOrDie();
+    value_storage_ = value_.ToBytes().value();
     value_ =
         DataPiece(value_storage_, true, value_.use_strict_base64_decoding());
   }
@@ -587,6 +588,38 @@
 
   if (field == nullptr) return this;
 
+  // Legacy JSON map is a list of key value pairs. Starts a map entry object.
+  if (options_.use_legacy_json_map_format && name.empty()) {
+    Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false);
+    return this;
+  }
+
+  if (IsMap(*field)) {
+    // Begin a map. A map is triggered by a StartObject() call if the current
+    // field has a map type.
+    // A map type is always repeated, hence set is_list to true.
+    // Render
+    // "<name>": [
+    Push(name, Item::MAP, false, true);
+    return this;
+  }
+
+  if (options_.disable_implicit_message_list) {
+    // If the incoming object is repeated, the top-level object on stack should
+    // be list. Report an error otherwise.
+    if (IsRepeated(*field) && !current_->is_list()) {
+      IncrementInvalidDepth();
+
+      if (!options_.suppress_implicit_message_list_error) {
+        InvalidValue(
+            field->name(),
+            "Starting an object in a repeated field but the parent object "
+            "is not a list");
+      }
+      return this;
+    }
+  }
+
   if (IsStruct(*field)) {
     // Start a struct object.
     // Render
@@ -610,19 +643,13 @@
     return this;
   }
 
-  // Legacy JSON map is a list of key value pairs. Starts a map entry object.
-  if (options_.use_legacy_json_map_format && name.empty()) {
-    Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false);
-    return this;
-  }
+  if (field->kind() != google::protobuf::Field::TYPE_GROUP &&
+      field->kind() != google::protobuf::Field::TYPE_MESSAGE) {
+    IncrementInvalidDepth();
+    if (!options_.suppress_object_to_scalar_error) {
+      InvalidValue(field->name(), "Starting an object on a scalar field");
+    }
 
-  if (IsMap(*field)) {
-    // Begin a map. A map is triggered by a StartObject() call if the current
-    // field has a map type.
-    // A map type is always repeated, hence set is_list to true.
-    // Render
-    // "<name>": [
-    Push(name, Item::MAP, false, true);
     return this;
   }
 
@@ -893,7 +920,7 @@
   switch (data.type()) {
     case DataPiece::TYPE_INT32: {
       if (ow->options_.struct_integers_as_strings) {
-        StatusOr<int32> int_value = data.ToInt32();
+        util::StatusOr<int32_t> int_value = data.ToInt32();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -906,7 +933,7 @@
     }
     case DataPiece::TYPE_UINT32: {
       if (ow->options_.struct_integers_as_strings) {
-        StatusOr<uint32> int_value = data.ToUint32();
+        util::StatusOr<uint32_t> int_value = data.ToUint32();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -921,7 +948,7 @@
       // If the option to treat integers as strings is set, then render them as
       // strings. Otherwise, fallback to rendering them as double.
       if (ow->options_.struct_integers_as_strings) {
-        StatusOr<int64> int_value = data.ToInt64();
+        util::StatusOr<int64_t> int_value = data.ToInt64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value", DataPiece(StrCat(int_value.value()), true));
@@ -935,7 +962,7 @@
       // If the option to treat integers as strings is set, then render them as
       // strings. Otherwise, fallback to rendering them as double.
       if (ow->options_.struct_integers_as_strings) {
-        StatusOr<uint64> int_value = data.ToUint64();
+        util::StatusOr<uint64_t> int_value = data.ToUint64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value", DataPiece(StrCat(int_value.value()), true));
@@ -947,7 +974,7 @@
     }
     case DataPiece::TYPE_FLOAT: {
       if (ow->options_.struct_integers_as_strings) {
-        StatusOr<float> float_value = data.ToFloat();
+        util::StatusOr<float> float_value = data.ToFloat();
         if (float_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -960,7 +987,7 @@
     }
     case DataPiece::TYPE_DOUBLE: {
       if (ow->options_.struct_integers_as_strings) {
-        StatusOr<double> double_value = data.ToDouble();
+        util::StatusOr<double> double_value = data.ToDouble();
         if (double_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -984,9 +1011,9 @@
       break;
     }
     default: {
-      return Status(util::error::INVALID_ARGUMENT,
-                    "Invalid struct data type. Only number, string, boolean or "
-                    "null values are supported.");
+      return util::InvalidArgumentError(
+          "Invalid struct data type. Only number, string, boolean or  null "
+          "values are supported.");
     }
   }
   ow->ProtoWriter::RenderDataPiece(struct_field_name, data);
@@ -997,9 +1024,9 @@
                                                 const DataPiece& data) {
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  StrCat("Invalid data type for timestamp, value is ",
-                               data.ValueAsStringOrDefault("")));
+    return util::InvalidArgumentError(
+        StrCat("Invalid data type for timestamp, value is ",
+                     data.ValueAsStringOrDefault("")));
   }
 
   StringPiece value(data.str());
@@ -1008,7 +1035,7 @@
   int32 nanos;
   if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds,
                                                &nanos)) {
-    return Status(INVALID_ARGUMENT, StrCat("Invalid time format: ", value));
+    return util::InvalidArgumentError(StrCat("Invalid time format: ", value));
   }
 
 
@@ -1018,7 +1045,7 @@
 }
 
 static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
-                                                StringPiece path) {
+                                              StringPiece path) {
   ow->ProtoWriter::RenderDataPiece(
       "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
   return Status();
@@ -1028,9 +1055,9 @@
                                                 const DataPiece& data) {
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  StrCat("Invalid data type for field mask, value is ",
-                               data.ValueAsStringOrDefault("")));
+    return util::InvalidArgumentError(
+        StrCat("Invalid data type for field mask, value is ",
+                     data.ValueAsStringOrDefault("")));
   }
 
   // TODO(tsun): figure out how to do proto descriptor based snake case
@@ -1044,16 +1071,16 @@
                                                const DataPiece& data) {
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  StrCat("Invalid data type for duration, value is ",
-                               data.ValueAsStringOrDefault("")));
+    return util::InvalidArgumentError(
+        StrCat("Invalid data type for duration, value is ",
+                     data.ValueAsStringOrDefault("")));
   }
 
   StringPiece value(data.str());
 
   if (!HasSuffixString(value, "s")) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  "Illegal duration format; duration must end with 's'");
+    return util::InvalidArgumentError(
+        "Illegal duration format; duration must end with 's'");
   }
   value = value.substr(0, value.size() - 1);
   int sign = 1;
@@ -1064,13 +1091,13 @@
 
   StringPiece s_secs, s_nanos;
   SplitSecondsAndNanos(value, &s_secs, &s_nanos);
-  uint64 unsigned_seconds;
+  uint64_t unsigned_seconds;
   if (!safe_strtou64(s_secs, &unsigned_seconds)) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  "Invalid duration format, failed to parse seconds");
+    return util::InvalidArgumentError(
+        "Invalid duration format, failed to parse seconds");
   }
 
-  int32 nanos = 0;
+  int32_t nanos = 0;
   Status nanos_status = GetNanosFromStringPiece(
       s_nanos, "Invalid duration format, failed to parse nano seconds",
       "Duration value exceeds limits", &nanos);
@@ -1079,11 +1106,10 @@
   }
   nanos = sign * nanos;
 
-  int64 seconds = sign * unsigned_seconds;
+  int64_t seconds = sign * unsigned_seconds;
   if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
       nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  "Duration value exceeds limits");
+    return util::InvalidArgumentError("Duration value exceeds limits");
   }
 
   ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
@@ -1212,6 +1238,19 @@
     return this;
   }
 
+  if (IsRepeated(*field) && !current_->is_list()) {
+    if (options_.disable_implicit_scalar_list) {
+      if (!options_.suppress_implicit_scalar_list_error) {
+        InvalidValue(
+            field->name(),
+            "Starting an primitive in a repeated field but the parent field "
+            "is not a list");
+      }
+
+      return this;
+    }
+  }
+
   ProtoWriter::RenderDataPiece(name, data);
   return this;
 }
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index f3aeb61..0befd1c 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -48,6 +48,7 @@
 #include <google/protobuf/util/internal/structured_objectwriter.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/hash.h>
 
 #include <google/protobuf/port_def.inc>
@@ -100,6 +101,27 @@
     // If true, accepts repeated key/value pair for a map proto field.
     bool use_legacy_json_map_format;
 
+    // If true, disable implicitly creating message list.
+    bool disable_implicit_message_list;
+
+    // If true, suppress the error of implicitly creating message list when it
+    // is disabled.
+    bool suppress_implicit_message_list_error;
+
+    // If true, disable implicitly creating scalar list.
+    bool disable_implicit_scalar_list;
+
+    // If true, suppress the error of implicitly creating scalar list when it
+    // is disabled.
+    bool suppress_implicit_scalar_list_error;
+
+    // If true, suppress the error of rendering scalar field if the source is an
+    // object.
+    bool suppress_object_to_scalar_error;
+
+    // If true, use the json name in missing fields errors.
+    bool use_json_name_in_missing_fields;
+
     Options()
         : struct_integers_as_strings(false),
           ignore_unknown_fields(false),
@@ -107,7 +129,13 @@
           use_lower_camel_for_enums(false),
           case_insensitive_enum_parsing(false),
           ignore_null_value_map_entry(false),
-          use_legacy_json_map_format(false) {}
+          use_legacy_json_map_format(false),
+          disable_implicit_message_list(false),
+          suppress_implicit_message_list_error(false),
+          disable_implicit_scalar_list(false),
+          suppress_implicit_scalar_list_error(false),
+          suppress_object_to_scalar_error(false),
+          use_json_name_in_missing_fields(false) {}
 
     // Default instance of Options with all options set to defaults.
     static const Options& Defaults() {
@@ -138,7 +166,7 @@
  protected:
   // Function that renders a well known type with modified behavior.
   typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
-                                         const DataPiece&);
+                                       const DataPiece&);
 
   // Handles writing Anys out using nested object writers and the like.
   class PROTOBUF_EXPORT AnyWriter {
@@ -347,24 +375,24 @@
   // Renders google.protobuf.Value in struct.proto. It picks the right oneof
   // type based on value's type.
   static util::Status RenderStructValue(ProtoStreamObjectWriter* ow,
-                                          const DataPiece& data);
+                                        const DataPiece& data);
 
   // Renders google.protobuf.Timestamp value.
   static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
-                                        const DataPiece& data);
+                                      const DataPiece& data);
 
   // Renders google.protobuf.FieldMask value.
   static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
-                                        const DataPiece& data);
+                                      const DataPiece& data);
 
   // Renders google.protobuf.Duration value.
   static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
-                                       const DataPiece& data);
+                                     const DataPiece& data);
 
   // Renders wrapper message types for primitive types in
   // google/protobuf/wrappers.proto.
   static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
-                                          const DataPiece& data);
+                                        const DataPiece& data);
 
   static void InitRendererMap();
   static void DeleteRendererMap();
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
index b1d76a5..2232bec 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -93,12 +93,6 @@
 }
 }  // namespace
 
-#if __cplusplus >= 201103L
-using std::get;
-#else
-using std::tr1::get;
-#endif
-
 class BaseProtoStreamObjectWriterTest
     : public ::testing::TestWithParam<testing::TypeInfoSource> {
  protected:
@@ -171,8 +165,8 @@
 
 MATCHER_P(HasObjectLocation, expected,
           "Verifies the expected object location") {
-  std::string actual = get<0>(arg).ToString();
-  if (actual.compare(expected) == 0) return true;
+  std::string actual = std::get<0>(arg).ToString();
+  if (actual == expected) return true;
   *result_listener << "actual location is: " << actual;
   return false;
 }
@@ -705,6 +699,61 @@
   CheckOutput(expected);
 }
 
+TEST_P(ProtoStreamObjectWriterTest, DisableImplicitMessageList) {
+  options_.disable_implicit_message_list = true;
+  options_.suppress_implicit_message_list_error = true;
+  ResetProtoWriter();
+
+  Book expected;
+  // The repeated friend field of the author is empty.
+  expected.mutable_author();
+
+  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->StartObject("friend")
+      ->RenderString("name", "first")
+      ->EndObject()
+      ->StartObject("friend")
+      ->RenderString("name", "second")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest,
+       DisableImplicitMessageListWithoutErrorSuppressed) {
+  options_.disable_implicit_message_list = true;
+  ResetProtoWriter();
+
+  Book expected;
+  // The repeated friend field of the author is empty.
+  expected.mutable_author();
+  EXPECT_CALL(
+      listener_,
+      InvalidValue(
+          _, StringPiece("friend"),
+          StringPiece(
+              "Starting an object in a repeated field but the parent object "
+              "is not a list")))
+      .With(Args<0>(HasObjectLocation("author")))
+      .Times(2);
+
+  ow_->StartObject("")
+      ->StartObject("author")
+      ->StartObject("friend")
+      ->RenderString("name", "first")
+      ->EndObject()
+      ->StartObject("friend")
+      ->RenderString("name", "second")
+      ->EndObject()
+      ->EndObject()
+      ->EndObject();
+  CheckOutput(expected);
+}
+
 TEST_P(ProtoStreamObjectWriterTest,
        LastWriteWinsOnNonRepeatedMessageFieldWithDuplicates) {
   Book expected;
@@ -1006,7 +1055,10 @@
   Proto3Message expected;
   EXPECT_CALL(
       listener_,
-      InvalidValue(_, StringPiece("TYPE_ENUM"),
+      InvalidValue(_,
+                   StringPiece(
+                       "type.googleapis.com/"
+                       "proto_util_converter.testing.Proto3Message.NestedEnum"),
                    StringPiece("\"someunknownvalueyouwillneverknow\"")))
       .With(Args<0>(HasObjectLocation("enum_value")));
   ow_->StartObject("")
diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h
index bccea71..01cbb9e 100644
--- a/src/google/protobuf/util/internal/structured_objectwriter.h
+++ b/src/google/protobuf/util/internal/structured_objectwriter.h
@@ -69,7 +69,8 @@
    public:
     // Takes ownership of the parent Element.
     explicit BaseElement(BaseElement* parent)
-        : parent_(parent), level_(parent == NULL ? 0 : parent->level() + 1) {}
+        : parent_(parent),
+          level_(parent == nullptr ? 0 : parent->level() + 1) {}
     virtual ~BaseElement() {}
 
     // Releases ownership of the parent and returns a pointer to it.
diff --git a/src/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto
index 64b9f9d..b6fc3f6 100644
--- a/src/google/protobuf/util/internal/testdata/anys.proto
+++ b/src/google/protobuf/util/internal/testdata/anys.proto
@@ -34,6 +34,7 @@
 
 import "google/protobuf/any.proto";
 import "google/protobuf/duration.proto";
+import "google/protobuf/empty.proto";
 import "google/protobuf/struct.proto";
 import "google/protobuf/timestamp.proto";
 import "google/protobuf/wrappers.proto";
@@ -59,6 +60,8 @@
   AnyWrapper recursive_any_with_type_field_at_end = 15;
   AnyWrapper repeated_any = 16;
   AnyWrapper empty_any_with_null_type_url = 17;
+  AnyWrapper any_with_empty = 18;
+  AnyWrapper any_with_default_timestamp = 19;
 
   google.protobuf.Any top_level_any = 50;
   google.protobuf.Any top_level_any_with_type_field_at_end = 51;
@@ -79,6 +82,7 @@
   google.protobuf.Timestamp timestamp = 3;
   google.protobuf.Duration duration = 4;
   google.protobuf.Int32Value i32 = 5;
+  google.protobuf.Empty empty = 6;
   Data data = 100;
 }
 
diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
index e8b2103..aaa37d1 100644
--- a/src/google/protobuf/util/internal/type_info.cc
+++ b/src/google/protobuf/util/internal/type_info.cc
@@ -36,10 +36,11 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
index eb5c857..d8d679e 100644
--- a/src/google/protobuf/util/internal/type_info.h
+++ b/src/google/protobuf/util/internal/type_info.h
@@ -34,9 +34,9 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
 
 // Must be included last.
 #include <google/protobuf/port_def.inc>
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
index cc2dcd7..e8c3c5a 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.cc
+++ b/src/google/protobuf/util/internal/type_info_test_helper.cc
@@ -86,16 +86,17 @@
 TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); }
 
 ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
-    io::CodedInputStream* coded_input, const std::string& type_url) {
+    io::CodedInputStream* coded_input, const std::string& type_url,
+    ProtoStreamObjectSource::RenderOptions render_options) {
   const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
   switch (type_) {
     case USE_TYPE_RESOLVER: {
       return new ProtoStreamObjectSource(coded_input, type_resolver_.get(),
-                                         *type);
+                                         *type, render_options);
     }
   }
   GOOGLE_LOG(FATAL) << "Can not reach here.";
-  return NULL;
+  return nullptr;
 }
 
 ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
@@ -109,7 +110,7 @@
     }
   }
   GOOGLE_LOG(FATAL) << "Can not reach here.";
-  return NULL;
+  return nullptr;
 }
 
 DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter(
@@ -121,7 +122,7 @@
     }
   }
   GOOGLE_LOG(FATAL) << "Can not reach here.";
-  return NULL;
+  return nullptr;
 }
 
 }  // namespace testing
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h
index 3cafbce..c42289e 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.h
+++ b/src/google/protobuf/util/internal/type_info_test_helper.h
@@ -63,7 +63,7 @@
   // Creates a TypeInfo object for the given set of descriptors.
   void ResetTypeInfo(const std::vector<const Descriptor*>& descriptors);
 
-  // Convinent overloads.
+  // Convenient overloads.
   void ResetTypeInfo(const Descriptor* descriptor);
   void ResetTypeInfo(const Descriptor* descriptor1,
                      const Descriptor* descriptor2);
@@ -71,8 +71,9 @@
   // Returns the TypeInfo created after ResetTypeInfo.
   TypeInfo* GetTypeInfo();
 
-  ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input,
-                                          const std::string& type_url);
+  ProtoStreamObjectSource* NewProtoSource(
+      io::CodedInputStream* coded_input, const std::string& type_url,
+      ProtoStreamObjectSource::RenderOptions render_options = {});
 
   ProtoStreamObjectWriter* NewProtoWriter(
       const std::string& type_url, strings::ByteSink* output,
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index e3cdbcb..17ff6dd 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -32,6 +32,7 @@
 
 #include <algorithm>
 #include <cmath>
+#include <cstdint>
 #include <limits>
 
 #include <google/protobuf/stubs/callback.h>
@@ -63,9 +64,9 @@
   return GetBoolFromAny(opt->value());
 }
 
-int64 GetInt64OptionOrDefault(
+int64_t GetInt64OptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, int64 default_value) {
+    StringPiece option_name, int64_t default_value) {
   const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
   if (opt == nullptr) {
     return default_value;
@@ -106,7 +107,7 @@
   return b.value();
 }
 
-int64 GetInt64FromAny(const google::protobuf::Any& any) {
+int64_t GetInt64FromAny(const google::protobuf::Any& any) {
   google::protobuf::Int64Value i;
   ParseFromAny(any.value(), &i);
   return i.value();
@@ -179,7 +180,7 @@
 }
 
 const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
-    const google::protobuf::Type* type, int32 number) {
+    const google::protobuf::Type* type, int32_t number) {
   if (type != nullptr) {
     for (int i = 0; i < type->fields_size(); ++i) {
       const google::protobuf::Field& field = type->fields(i);
@@ -205,7 +206,7 @@
 }
 
 const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
-    const google::protobuf::Enum* enum_type, int32 value) {
+    const google::protobuf::Enum* enum_type, int32_t value) {
   if (enum_type != nullptr) {
     for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
       const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
@@ -270,7 +271,8 @@
       // 1) following a lowercase:   "...aB..."
       // 2) followed by a lowercase: "...ABc..."
       if (!result.empty() && is_cap &&
-          (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
+          (!was_cap ||
+           (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
         first_word = false;
         result.push_back(input[i]);
       } else {
@@ -310,9 +312,9 @@
       //    (e.g. "GoogleLAB" => "google_lab")
       // 4) Followed by a lowercase: "...ABc..." => "...a_bc..."
       //    (e.g. "GBike" => "g_bike")
-      if (was_not_underscore &&               //            case 1 out
-          (was_not_cap ||                     // case 2 in, case 3 out
-           (i + 1 < input.size() &&           //            case 3 out
+      if (was_not_underscore &&                     //            case 1 out
+          (was_not_cap ||                           // case 2 in, case 3 out
+           (i + 1 < input.size() &&                 //            case 3 out
             ascii_islower(input[i + 1])))) {  // case 4 in
         // We add an underscore for case 2 and case 4.
         result.push_back('_');
@@ -329,7 +331,7 @@
   return result;
 }
 
-std::set<std::string>* well_known_types_ = NULL;
+std::set<std::string>* well_known_types_ = nullptr;
 PROTOBUF_NAMESPACE_ID::internal::once_flag well_known_types_init_;
 const char* well_known_types_name_array_[] = {
     "google.protobuf.Timestamp",   "google.protobuf.Duration",
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
index 6ce9023..b689e84 100644
--- a/src/google/protobuf/util/internal/utility.h
+++ b/src/google/protobuf/util/internal/utility.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
 
+#include <cstdint>
 #include <memory>
 #include <string>
 #include <utility>
@@ -41,8 +42,8 @@
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/statusor.h>
+#include <google/protobuf/stubs/status.h>
 
 // Must be included last.
 #include <google/protobuf/port_def.inc>
@@ -53,7 +54,7 @@
 namespace converter {
 
 // Size of "type.googleapis.com"
-static const int64 kTypeUrlSize = 19;
+static const int64_t kTypeUrlSize = 19;
 
 // Finds the tech option identified by option_name. Parses the boolean value and
 // returns it.
@@ -64,9 +65,9 @@
 
 // Returns int64 option value. If the option isn't found, returns the
 // default_value.
-PROTOBUF_EXPORT int64 GetInt64OptionOrDefault(
+PROTOBUF_EXPORT int64_t GetInt64OptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, int64 default_value);
+    StringPiece option_name, int64_t default_value);
 
 // Returns double option value. If the option isn't found, returns the
 // default_value.
@@ -82,12 +83,12 @@
 
 // Returns a boolean value contained in Any type.
 // TODO(skarvaje): Make these utilities dealing with Any types more generic,
-// add more error checking and move to a more public/sharable location so others
-// can use.
+// add more error checking and move to a more public/shareable location so
+// others can use.
 PROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any);
 
 // Returns int64 value contained in Any type.
-PROTOBUF_EXPORT int64 GetInt64FromAny(const google::protobuf::Any& any);
+PROTOBUF_EXPORT int64_t GetInt64FromAny(const google::protobuf::Any& any);
 
 // Returns double value contained in Any type.
 PROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any);
@@ -127,7 +128,7 @@
 
 // Similar to FindFieldInTypeOrNull, but this looks up fields by number.
 const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
-    const google::protobuf::Type* type, int32 number);
+    const google::protobuf::Type* type, int32_t number);
 
 // Finds and returns the EnumValue identified by enum_name in the passed tech
 // Enum object. Returns nullptr if none found.
@@ -137,7 +138,7 @@
 // Finds and returns the EnumValue identified by value in the passed tech
 // Enum object. Returns nullptr if none found.
 const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
-    const google::protobuf::Enum* enum_type, int32 value);
+    const google::protobuf::Enum* enum_type, int32_t value);
 
 // Finds and returns the EnumValue identified by enum_name without underscore in
 // the passed tech Enum object. Returns nullptr if none found.
diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto
index b62487a..0eec9da 100644
--- a/src/google/protobuf/util/json_format_proto3.proto
+++ b/src/google/protobuf/util/json_format_proto3.proto
@@ -91,6 +91,7 @@
     bytes oneof_bytes_value = 3;
     EnumType oneof_enum_value = 4;
     MessageType oneof_message_value = 5;
+    google.protobuf.NullValue oneof_null_value = 6;
   }
 }
 
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index 2f3e6c6..3597f9e 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -43,10 +43,13 @@
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/util/type_resolver_util.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status_macros.h>
 
+// clang-format off
 #include <google/protobuf/port_def.inc>
+// clang-format on
 
 namespace google {
 namespace protobuf {
@@ -82,17 +85,19 @@
 }  // namespace internal
 
 util::Status BinaryToJsonStream(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  io::ZeroCopyInputStream* binary_input,
-                                  io::ZeroCopyOutputStream* json_output,
-                                  const JsonPrintOptions& options) {
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* binary_input,
+                                io::ZeroCopyOutputStream* json_output,
+                                const JsonPrintOptions& options) {
   io::CodedInputStream in_stream(binary_input);
   google::protobuf::Type type;
   RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
-  converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type);
-  proto_source.set_use_ints_for_enums(options.always_print_enums_as_ints);
-  proto_source.set_preserve_proto_field_names(
-      options.preserve_proto_field_names);
+  converter::ProtoStreamObjectSource::RenderOptions render_options;
+  render_options.use_ints_for_enums = options.always_print_enums_as_ints;
+  render_options.preserve_proto_field_names =
+      options.preserve_proto_field_names;
+  converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type,
+                                                  render_options);
   io::CodedOutputStream out_stream(json_output);
   converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "",
                                           &out_stream);
@@ -110,10 +115,10 @@
 }
 
 util::Status BinaryToJsonString(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  const std::string& binary_input,
-                                  std::string* json_output,
-                                  const JsonPrintOptions& options) {
+                                const std::string& type_url,
+                                const std::string& binary_input,
+                                std::string* json_output,
+                                const JsonPrintOptions& options) {
   io::ArrayInputStream input_stream(binary_input.data(), binary_input.size());
   io::StringOutputStream output_stream(json_output);
   return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream,
@@ -135,25 +140,22 @@
     if (!loc_string.empty()) {
       loc_string.append(" ");
     }
-    status_ =
-        util::Status(util::error::INVALID_ARGUMENT,
-                       StrCat(loc_string, unknown_name, ": ", message));
+    status_ = util::InvalidArgumentError(
+        StrCat(loc_string, unknown_name, ": ", message));
   }
 
   void InvalidValue(const converter::LocationTrackerInterface& loc,
                     StringPiece type_name,
                     StringPiece value) override {
-    status_ = util::Status(
-        util::error::INVALID_ARGUMENT,
-        StrCat(GetLocString(loc), ": invalid value ", string(value),
-                     " for type ", string(type_name)));
+    status_ = util::InvalidArgumentError(
+        StrCat(GetLocString(loc), ": invalid value ", std::string(value),
+                     " for type ", std::string(type_name)));
   }
 
   void MissingField(const converter::LocationTrackerInterface& loc,
                     StringPiece missing_name) override {
-    status_ = util::Status(util::error::INVALID_ARGUMENT,
-                             StrCat(GetLocString(loc), ": missing field ",
-                                          std::string(missing_name)));
+    status_ = util::InvalidArgumentError(StrCat(
+        GetLocString(loc), ": missing field ", std::string(missing_name)));
   }
 
  private:
@@ -173,10 +175,10 @@
 }  // namespace
 
 util::Status JsonToBinaryStream(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  io::ZeroCopyInputStream* json_input,
-                                  io::ZeroCopyOutputStream* binary_output,
-                                  const JsonParseOptions& options) {
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* json_input,
+                                io::ZeroCopyOutputStream* binary_output,
+                                const JsonParseOptions& options) {
   google::protobuf::Type type;
   RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
   internal::ZeroCopyStreamByteSink sink(binary_output);
@@ -204,10 +206,10 @@
 }
 
 util::Status JsonToBinaryString(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  StringPiece json_input,
-                                  std::string* binary_output,
-                                  const JsonParseOptions& options) {
+                                const std::string& type_url,
+                                StringPiece json_input,
+                                std::string* binary_output,
+                                const JsonParseOptions& options) {
   io::ArrayInputStream input_stream(json_input.data(), json_input.size());
   io::StringOutputStream output_stream(binary_output);
   return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream,
@@ -240,7 +242,7 @@
 }  // namespace
 
 util::Status MessageToJsonString(const Message& message, std::string* output,
-                                   const JsonOptions& options) {
+                                 const JsonOptions& options) {
   const DescriptorPool* pool = message.GetDescriptor()->file()->pool();
   TypeResolver* resolver =
       pool == DescriptorPool::generated_pool()
@@ -256,7 +258,7 @@
 }
 
 util::Status JsonStringToMessage(StringPiece input, Message* message,
-                                   const JsonParseOptions& options) {
+                                 const JsonParseOptions& options) {
   const DescriptorPool* pool = message->GetDescriptor()->file()->pool();
   TypeResolver* resolver =
       pool == DescriptorPool::generated_pool()
@@ -264,11 +266,10 @@
           : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
   std::string binary;
   util::Status result = JsonToBinaryString(resolver, GetTypeUrl(*message),
-                                             input, &binary, options);
+                                           input, &binary, options);
   if (result.ok() && !message->ParseFromString(binary)) {
-    result =
-        util::Status(util::error::INVALID_ARGUMENT,
-                       "JSON transcoder produced invalid protobuf output.");
+    result = util::InvalidArgumentError(
+        "JSON transcoder produced invalid protobuf output.");
   }
   if (pool != DescriptorPool::generated_pool()) {
     delete resolver;
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
index 9954587..73f2783 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -36,6 +36,7 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 
 #include <google/protobuf/port_def.inc>
@@ -93,11 +94,11 @@
 // simple wrapper of BinaryToJsonString(). It will use the DescriptorPool of the
 // passed-in message to resolve Any types.
 PROTOBUF_EXPORT util::Status MessageToJsonString(const Message& message,
-                                                   std::string* output,
-                                                   const JsonOptions& options);
+                                                 std::string* output,
+                                                 const JsonOptions& options);
 
 inline util::Status MessageToJsonString(const Message& message,
-                                          std::string* output) {
+                                        std::string* output) {
   return MessageToJsonString(message, output, JsonOptions());
 }
 
@@ -108,7 +109,7 @@
     StringPiece input, Message* message, const JsonParseOptions& options);
 
 inline util::Status JsonStringToMessage(StringPiece input,
-                                          Message* message) {
+                                        Message* message) {
   return JsonStringToMessage(input, message, JsonParseOptions());
 }
 
@@ -123,10 +124,10 @@
     io::ZeroCopyInputStream* binary_input,
     io::ZeroCopyOutputStream* json_output, const JsonPrintOptions& options);
 
-inline util::Status BinaryToJsonStream(
-    TypeResolver* resolver, const std::string& type_url,
-    io::ZeroCopyInputStream* binary_input,
-    io::ZeroCopyOutputStream* json_output) {
+inline util::Status BinaryToJsonStream(TypeResolver* resolver,
+                                       const std::string& type_url,
+                                       io::ZeroCopyInputStream* binary_input,
+                                       io::ZeroCopyOutputStream* json_output) {
   return BinaryToJsonStream(resolver, type_url, binary_input, json_output,
                             JsonPrintOptions());
 }
@@ -137,9 +138,9 @@
     const JsonPrintOptions& options);
 
 inline util::Status BinaryToJsonString(TypeResolver* resolver,
-                                         const std::string& type_url,
-                                         const std::string& binary_input,
-                                         std::string* json_output) {
+                                       const std::string& type_url,
+                                       const std::string& binary_input,
+                                       std::string* json_output) {
   return BinaryToJsonString(resolver, type_url, binary_input, json_output,
                             JsonPrintOptions());
 }
@@ -168,9 +169,9 @@
     const JsonParseOptions& options);
 
 inline util::Status JsonToBinaryString(TypeResolver* resolver,
-                                         const std::string& type_url,
-                                         StringPiece json_input,
-                                         std::string* binary_output) {
+                                       const std::string& type_url,
+                                       StringPiece json_input,
+                                       std::string* binary_output) {
   return JsonToBinaryString(resolver, type_url, json_input, binary_output,
                             JsonParseOptions());
 }
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index 9851cc5..c5d8315 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/json_util.h>
 
+#include <cstdint>
 #include <list>
 #include <string>
 
@@ -524,7 +525,7 @@
  private:
   std::list<Segment> segments_;
   Segment last_segment_;
-  int64 byte_count_;
+  int64_t byte_count_;
 };
 
 // This test splits the output buffer and also the input data into multiple
@@ -632,8 +633,7 @@
   delete resolver;
 
   EXPECT_FALSE(result_status.ok());
-  EXPECT_EQ(result_status.code(),
-            util::error::INVALID_ARGUMENT);
+  EXPECT_TRUE(util::IsInvalidArgument(result_status));
 }
 
 TEST_F(JsonUtilTest, HtmlEscape) {
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index f5e0860..88e01df 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -35,7 +35,10 @@
 #include <google/protobuf/util/message_differencer.h>
 
 #include <algorithm>
+#include <cstddef>
+#include <cstdint>
 #include <functional>
+#include <limits>
 #include <memory>
 #include <utility>
 
@@ -46,7 +49,11 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/map_field.h>
+#include <google/protobuf/message.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/util/field_comparator.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -66,7 +73,7 @@
   NumDiffsReporter() : num_diffs_(0) {}
 
   // Returns the total number of diffs.
-  int32 GetNumDiffs() const { return num_diffs_; }
+  int32_t GetNumDiffs() const { return num_diffs_; }
   void Reset() { num_diffs_ = 0; }
 
   // Report that a field has been added into Message2.
@@ -94,7 +101,7 @@
   }
 
  private:
-  int32 num_diffs_;
+  int32_t num_diffs_;
 };
 
 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can
@@ -111,8 +118,8 @@
       : message_differencer_(message_differencer),
         key_field_paths_(key_field_paths) {
     GOOGLE_CHECK(!key_field_paths_.empty());
-    for (int i = 0; i < key_field_paths_.size(); ++i) {
-      GOOGLE_CHECK(!key_field_paths_[i].empty());
+    for (const auto& path : key_field_paths_) {
+      GOOGLE_CHECK(!path.empty());
     }
   }
   MultipleFieldsMapKeyComparator(MessageDifferencer* message_differencer,
@@ -124,9 +131,8 @@
   }
   bool IsMatch(const Message& message1, const Message& message2,
                const std::vector<SpecificField>& parent_fields) const override {
-    for (int i = 0; i < key_field_paths_.size(); ++i) {
-      if (!IsMatchInternal(message1, message2, parent_fields,
-                           key_field_paths_[i], 0)) {
+    for (const auto& path : key_field_paths_) {
+      if (!IsMatchInternal(message1, message2, parent_fields, path, 0)) {
         return false;
       }
     }
@@ -141,19 +147,17 @@
       int path_index) const {
     const FieldDescriptor* field = key_field_path[path_index];
     std::vector<SpecificField> current_parent_fields(parent_fields);
-    if (path_index == key_field_path.size() - 1) {
-      if (field->is_repeated()) {
-        if (!message_differencer_->CompareRepeatedField(
-                message1, message2, field, &current_parent_fields)) {
-          return false;
-        }
+    if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) {
+      if (field->is_map()) {
+        return message_differencer_->CompareMapField(message1, message2, field,
+                                                     &current_parent_fields);
+      } else if (field->is_repeated()) {
+        return message_differencer_->CompareRepeatedField(
+            message1, message2, field, &current_parent_fields);
       } else {
-        if (!message_differencer_->CompareFieldValueUsingParentFields(
-                message1, message2, field, -1, -1, &current_parent_fields)) {
-          return false;
-        }
+        return message_differencer_->CompareFieldValueUsingParentFields(
+            message1, message2, field, -1, -1, &current_parent_fields);
       }
-      return true;
     } else {
       const Reflection* reflection1 = message1.GetReflection();
       const Reflection* reflection2 = message2.GetReflection();
@@ -184,10 +188,10 @@
 // element. The optimal solution requires to use //util/diff/lcs.h, which is
 // not open sourced yet. Overwrite this method if you want to have that.
 // TODO(ykzhu): change to use LCS once it is open sourced.
-void MatchIndicesPostProcessorForSmartList(
-    std::vector<int>* match_list1, std::vector<int>* match_list2) {
+void MatchIndicesPostProcessorForSmartList(std::vector<int>* match_list1,
+                                           std::vector<int>* match_list2) {
   int last_matched_index = -1;
-  for (int i = 0; i < match_list1->size(); ++i) {
+  for (size_t i = 0; i < match_list1->size(); ++i) {
     if (match_list1->at(i) < 0) {
       continue;
     }
@@ -262,7 +266,6 @@
 
 MessageDifferencer::MessageDifferencer()
     : reporter_(NULL),
-      field_comparator_(NULL),
       message_field_comparison_(EQUAL),
       scope_(FULL),
       repeated_field_comparison_(AS_LIST),
@@ -275,19 +278,29 @@
           MatchIndicesPostProcessorForSmartList) {}
 
 MessageDifferencer::~MessageDifferencer() {
-  for (int i = 0; i < owned_key_comparators_.size(); ++i) {
-    delete owned_key_comparators_[i];
+  for (MapKeyComparator* comparator : owned_key_comparators_) {
+    delete comparator;
   }
-  for (int i = 0; i < ignore_criteria_.size(); ++i) {
-    delete ignore_criteria_[i];
+  for (IgnoreCriteria* criteria : ignore_criteria_) {
+    delete criteria;
   }
 }
 
 void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
   GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
-  field_comparator_ = comparator;
+  field_comparator_kind_ = kFCBase;
+  field_comparator_.base = comparator;
 }
 
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+void MessageDifferencer::set_field_comparator(
+    DefaultFieldComparator* comparator) {
+  GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
+  field_comparator_kind_ = kFCDefault;
+  field_comparator_.default_impl = comparator;
+}
+#endif  // PROTOBUF_FUTURE_BREAKING_CHANGES
+
 void MessageDifferencer::set_message_field_comparison(
     MessageFieldComparison comparison) {
   message_field_comparison_ = comparison;
@@ -321,14 +334,7 @@
   const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
   GOOGLE_CHECK(key_comparator == NULL)
       << "Cannot treat this repeated field as both MAP and " << new_comparison
-      << " for"
-      << " comparison.  Field name is: " << field->full_name();
-  GOOGLE_CHECK(repeated_field_comparisons_.find(field) ==
-            repeated_field_comparisons_.end() ||
-        repeated_field_comparisons_[field] == new_comparison)
-      << "Cannot treat the same field as both "
-      << repeated_field_comparisons_[field] << " and " << new_comparison
-      << ". Field name is: " << field->full_name();
+      << " for comparison.  Field name is: " << field->full_name();
 }
 
 void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
@@ -379,9 +385,9 @@
     const FieldDescriptor* field,
     const std::vector<const FieldDescriptor*>& key_fields) {
   std::vector<std::vector<const FieldDescriptor*> > key_field_paths;
-  for (int i = 0; i < key_fields.size(); ++i) {
+  for (const FieldDescriptor* key_filed : key_fields) {
     std::vector<const FieldDescriptor*> key_field_path;
-    key_field_path.push_back(key_fields[i]);
+    key_field_path.push_back(key_filed);
     key_field_paths.push_back(key_field_path);
   }
   TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths);
@@ -394,10 +400,8 @@
       << "Field must be repeated: " << field->full_name();
   GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
       << "Field has to be message type.  Field name is: " << field->full_name();
-  for (int i = 0; i < key_field_paths.size(); ++i) {
-    const std::vector<const FieldDescriptor*>& key_field_path =
-        key_field_paths[i];
-    for (int j = 0; j < key_field_path.size(); ++j) {
+  for (const auto& key_field_path : key_field_paths) {
+    for (size_t j = 0; j < key_field_path.size(); ++j) {
       const FieldDescriptor* parent_field =
           j == 0 ? field : key_field_path[j - 1];
       const FieldDescriptor* child_field = key_field_path[j];
@@ -487,18 +491,17 @@
   std::vector<SpecificField> parent_fields;
 
   bool result = false;
-
   // Setup the internal reporter if need be.
   if (output_string_) {
     io::StringOutputStream output_stream(output_string_);
     StreamReporter reporter(&output_stream);
+    reporter.SetMessages(message1, message2);
     reporter_ = &reporter;
     result = Compare(message1, message2, &parent_fields);
     reporter_ = NULL;
   } else {
     result = Compare(message1, message2, &parent_fields);
   }
-
   return result;
 }
 
@@ -558,11 +561,13 @@
                 << descriptor2->full_name();
     return false;
   }
+
   // Expand google.protobuf.Any payload if possible.
   if (descriptor1->full_name() == internal::kAnyFullTypeName) {
     std::unique_ptr<Message> data1;
     std::unique_ptr<Message> data2;
-    if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) {
+    if (unpack_any_field_.UnpackAny(message1, &data1) &&
+        unpack_any_field_.UnpackAny(message2, &data2)) {
       // Avoid DFATAL for different descriptors in google.protobuf.Any payloads.
       if (data1->GetDescriptor() != data2->GetDescriptor()) {
         return false;
@@ -592,10 +597,10 @@
   FieldDescriptorArray message1_fields = RetrieveFields(message1, true);
   FieldDescriptorArray message2_fields = RetrieveFields(message2, false);
 
-  return CompareRequestedFieldsUsingSettings(
-      message1, message2,
-      message1_fields, message2_fields,
-      parent_fields) && unknown_compare_result;
+  return CompareRequestedFieldsUsingSettings(message1, message2,
+                                             message1_fields, message2_fields,
+                                             parent_fields) &&
+         unknown_compare_result;
 }
 
 FieldDescriptorArray MessageDifferencer::RetrieveFields(const Message& message,
@@ -671,8 +676,8 @@
 FieldDescriptorArray MessageDifferencer::CombineFields(
     const FieldDescriptorArray& fields1, Scope fields1_scope,
     const FieldDescriptorArray& fields2, Scope fields2_scope) {
-  int index1 = 0;
-  int index2 = 0;
+  size_t index1 = 0;
+  size_t index2 = 0;
 
   tmp_message_fields_.clear();
 
@@ -735,7 +740,6 @@
         if (reporter_ != NULL) {
           SpecificField specific_field;
           specific_field.field = field1;
-
           parent_fields->push_back(specific_field);
           if (report_ignores_) {
             reporter_->ReportIgnored(message1, message2, *parent_fields);
@@ -777,7 +781,6 @@
         if (reporter_ != NULL) {
           SpecificField specific_field;
           specific_field.field = field2;
-
           parent_fields->push_back(specific_field);
           if (report_ignores_) {
             reporter_->ReportIgnored(message1, message2, *parent_fields);
@@ -820,7 +823,6 @@
       if (reporter_ != NULL) {
         SpecificField specific_field;
         specific_field.field = field1;
-
         parent_fields->push_back(specific_field);
         if (report_ignores_) {
           reporter_->ReportIgnored(message1, message2, *parent_fields);
@@ -835,24 +837,17 @@
 
     bool fieldDifferent = false;
     assert(field1 != NULL);
-    if (field1->is_repeated()) {
+    if (field1->is_map()) {
+      fieldDifferent =
+          !CompareMapField(message1, message2, field1, parent_fields);
+    } else if (field1->is_repeated()) {
       fieldDifferent =
           !CompareRepeatedField(message1, message2, field1, parent_fields);
-      if (fieldDifferent) {
-        if (reporter_ == NULL) return false;
-        isDifferent = true;
-      }
     } else {
       fieldDifferent = !CompareFieldValueUsingParentFields(
           message1, message2, field1, -1, -1, parent_fields);
 
-      // If we have found differences, either report them or terminate if
-      // no reporter is present.
-      if (fieldDifferent && reporter_ == NULL) {
-        return false;
-      }
-
-      if (reporter_ != NULL) {
+      if (reporter_ != nullptr) {
         SpecificField specific_field;
         specific_field.field = field1;
         parent_fields->push_back(specific_field);
@@ -865,6 +860,10 @@
         parent_fields->pop_back();
       }
     }
+    if (fieldDifferent) {
+      if (reporter_ == nullptr) return false;
+      isDifferent = true;
+    }
     // Increment the field indices.
     ++field_index1;
     ++field_index2;
@@ -916,13 +915,154 @@
   return match;
 }
 
+bool MessageDifferencer::CompareMapFieldByMapReflection(
+    const Message& message1, const Message& message2,
+    const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields,
+    DefaultFieldComparator* comparator) {
+  GOOGLE_DCHECK_EQ(nullptr, reporter_);
+  GOOGLE_DCHECK(map_field->is_map());
+  GOOGLE_DCHECK(map_field_key_comparator_.find(map_field) ==
+         map_field_key_comparator_.end());
+  GOOGLE_DCHECK_EQ(repeated_field_comparison_, AS_LIST);
+  const Reflection* reflection1 = message1.GetReflection();
+  const Reflection* reflection2 = message2.GetReflection();
+  const int count1 = reflection1->MapSize(message1, map_field);
+  const int count2 = reflection2->MapSize(message2, map_field);
+  const bool treated_as_subset = IsTreatedAsSubset(map_field);
+  if (count1 != count2 && !treated_as_subset) {
+    return false;
+  }
+  if (count1 > count2) {
+    return false;
+  }
+
+  // First pass: check whether the same keys are present.
+  for (MapIterator it = reflection1->MapBegin(const_cast<Message*>(&message1),
+                                              map_field),
+                   it_end = reflection1->MapEnd(const_cast<Message*>(&message1),
+                                                map_field);
+       it != it_end; ++it) {
+    if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
+      return false;
+    }
+  }
+
+  // Second pass: compare values for matching keys.
+  const FieldDescriptor* val_des = map_field->message_type()->map_value();
+  switch (val_des->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD)                           \
+  case FieldDescriptor::CPPTYPE_##CPPTYPE: {                                  \
+    for (MapIterator it = reflection1->MapBegin(                              \
+                         const_cast<Message*>(&message1), map_field),         \
+                     it_end = reflection1->MapEnd(                            \
+                         const_cast<Message*>(&message1), map_field);         \
+         it != it_end; ++it) {                                                \
+      MapValueConstRef value2;                                                \
+      reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \
+      if (!comparator->Compare##COMPAREMETHOD(*val_des,                       \
+                                              it.GetValueRef().Get##METHOD(), \
+                                              value2.Get##METHOD())) {        \
+        return false;                                                         \
+      }                                                                       \
+    }                                                                         \
+    break;                                                                    \
+  }
+    HANDLE_TYPE(INT32, Int32Value, Int32);
+    HANDLE_TYPE(INT64, Int64Value, Int64);
+    HANDLE_TYPE(UINT32, UInt32Value, UInt32);
+    HANDLE_TYPE(UINT64, UInt64Value, UInt64);
+    HANDLE_TYPE(DOUBLE, DoubleValue, Double);
+    HANDLE_TYPE(FLOAT, FloatValue, Float);
+    HANDLE_TYPE(BOOL, BoolValue, Bool);
+    HANDLE_TYPE(STRING, StringValue, String);
+    HANDLE_TYPE(ENUM, EnumValue, Int32);
+#undef HANDLE_TYPE
+    case FieldDescriptor::CPPTYPE_MESSAGE: {
+      for (MapIterator it = reflection1->MapBegin(
+               const_cast<Message*>(&message1), map_field);
+           it !=
+           reflection1->MapEnd(const_cast<Message*>(&message1), map_field);
+           ++it) {
+        if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
+          return false;
+        }
+        bool compare_result;
+        MapValueConstRef value2;
+        reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2);
+        // Append currently compared field to the end of parent_fields.
+        SpecificField specific_value_field;
+        specific_value_field.field = val_des;
+        parent_fields->push_back(specific_value_field);
+        compare_result = Compare(it.GetValueRef().GetMessageValue(),
+                                 value2.GetMessageValue(), parent_fields);
+        parent_fields->pop_back();
+        if (!compare_result) {
+          return false;
+        }
+      }
+      break;
+    }
+  }
+  return true;
+}
+
+bool MessageDifferencer::CompareMapField(
+    const Message& message1, const Message& message2,
+    const FieldDescriptor* repeated_field,
+    std::vector<SpecificField>* parent_fields) {
+  GOOGLE_DCHECK(repeated_field->is_map());
+
+  // the input FieldDescriptor is guaranteed to be repeated field.
+  const Reflection* reflection1 = message1.GetReflection();
+  const Reflection* reflection2 = message2.GetReflection();
+
+  // When both map fields are on map, do not sync to repeated field.
+  if (reflection1->GetMapData(message1, repeated_field)->IsMapValid() &&
+      reflection2->GetMapData(message2, repeated_field)->IsMapValid() &&
+      // TODO(jieluo): Add support for reporter
+      reporter_ == nullptr &&
+      // Users didn't set custom map field key comparator
+      map_field_key_comparator_.find(repeated_field) ==
+          map_field_key_comparator_.end() &&
+      // Users didn't set repeated field comparison
+      repeated_field_comparison_ == AS_LIST &&
+      // Users didn't set their own FieldComparator implementation
+      field_comparator_kind_ == kFCDefault) {
+    const FieldDescriptor* key_des = repeated_field->message_type()->map_key();
+    const FieldDescriptor* val_des =
+        repeated_field->message_type()->map_value();
+    std::vector<SpecificField> current_parent_fields(*parent_fields);
+    SpecificField specific_field;
+    specific_field.field = repeated_field;
+    current_parent_fields.push_back(specific_field);
+    if (!IsIgnored(message1, message2, key_des, current_parent_fields) &&
+        !IsIgnored(message1, message2, val_des, current_parent_fields)) {
+      return CompareMapFieldByMapReflection(message1, message2, repeated_field,
+                                            &current_parent_fields,
+                                            field_comparator_.default_impl);
+    }
+  }
+
+  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
+}
+
 bool MessageDifferencer::CompareRepeatedField(
     const Message& message1, const Message& message2,
     const FieldDescriptor* repeated_field,
     std::vector<SpecificField>* parent_fields) {
+  GOOGLE_DCHECK(!repeated_field->is_map());
+  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
+}
+
+bool MessageDifferencer::CompareRepeatedRep(
+    const Message& message1, const Message& message2,
+    const FieldDescriptor* repeated_field,
+    std::vector<SpecificField>* parent_fields) {
   // the input FieldDescriptor is guaranteed to be repeated field.
+  GOOGLE_DCHECK(repeated_field->is_repeated());
   const Reflection* reflection1 = message1.GetReflection();
   const Reflection* reflection2 = message2.GetReflection();
+
   const int count1 = reflection1->FieldSize(message1, repeated_field);
   const int count2 = reflection2->FieldSize(message2, repeated_field);
   const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
@@ -1116,10 +1256,11 @@
 
 bool MessageDifferencer::CheckPathChanged(
     const std::vector<SpecificField>& field_path) {
-  for (int i = 0; i < field_path.size(); ++i) {
+  for (const SpecificField& specific_field : field_path) {
     // Don't check indexes for map entries -- maps are unordered.
-    if (field_path[i].field != NULL && field_path[i].field->is_map()) continue;
-    if (field_path[i].index != field_path[i].new_index) return true;
+    if (specific_field.field != nullptr && specific_field.field->is_map())
+      continue;
+    if (specific_field.index != specific_field.new_index) return true;
   }
   return false;
 }
@@ -1130,7 +1271,8 @@
       repeated_field_comparisons_.end()) {
     return repeated_field_comparisons_[field] == AS_SET;
   }
-  return repeated_field_comparison_ == AS_SET;
+  return GetMapKeyComparator(field) == nullptr &&
+         repeated_field_comparison_ == AS_SET;
 }
 
 bool MessageDifferencer::IsTreatedAsSmartSet(const FieldDescriptor* field) {
@@ -1139,7 +1281,8 @@
       repeated_field_comparisons_.end()) {
     return repeated_field_comparisons_[field] == AS_SMART_SET;
   }
-  return repeated_field_comparison_ == AS_SMART_SET;
+  return GetMapKeyComparator(field) == nullptr &&
+         repeated_field_comparison_ == AS_SMART_SET;
 }
 
 bool MessageDifferencer::IsTreatedAsSmartList(const FieldDescriptor* field) {
@@ -1148,7 +1291,8 @@
       repeated_field_comparisons_.end()) {
     return repeated_field_comparisons_[field] == AS_SMART_LIST;
   }
-  return repeated_field_comparison_ == AS_SMART_LIST;
+  return GetMapKeyComparator(field) == nullptr &&
+         repeated_field_comparison_ == AS_SMART_LIST;
 }
 
 bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) {
@@ -1163,9 +1307,8 @@
   if (ignored_fields_.find(field) != ignored_fields_.end()) {
     return true;
   }
-  for (int i = 0; i < ignore_criteria_.size(); ++i) {
-    if (ignore_criteria_[i]->IsIgnored(message1, message2, field,
-                                       parent_fields)) {
+  for (IgnoreCriteria* criteria : ignore_criteria_) {
+    if (criteria->IsIgnored(message1, message2, field, parent_fields)) {
       return true;
     }
   }
@@ -1176,9 +1319,9 @@
     const Message& message1, const Message& message2,
     const SpecificField& field,
     const std::vector<SpecificField>& parent_fields) {
-  for (int i = 0; i < ignore_criteria_.size(); ++i) {
-    if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field,
-                                                   parent_fields)) {
+  for (IgnoreCriteria* criteria : ignore_criteria_) {
+    if (criteria->IsUnknownFieldIgnored(message1, message2, field,
+                                        parent_fields)) {
       return true;
     }
   }
@@ -1216,8 +1359,8 @@
 
 }  // namespace
 
-bool MessageDifferencer::UnpackAny(const Message& any,
-                                   std::unique_ptr<Message>* data) {
+bool MessageDifferencer::UnpackAnyField::UnpackAny(
+    const Message& any, std::unique_ptr<Message>* data) {
   const Reflection* reflection = any.GetReflection();
   const FieldDescriptor* type_url_field;
   const FieldDescriptor* value_field;
@@ -1297,8 +1440,8 @@
 
   // Now that we have two sorted lists, we can detect fields which appear only
   // in one list or the other by traversing them simultaneously.
-  int index1 = 0;
-  int index2 = 0;
+  size_t index1 = 0;
+  size_t index2 = 0;
   while (index1 < fields1.size() || index2 < fields2.size()) {
     enum {
       ADDITION,
@@ -1403,12 +1546,14 @@
 
     if (IsUnknownFieldIgnored(message1, message2, specific_field,
                               *parent_field)) {
-      if (reporter_ != NULL) {
+      if (report_ignores_ && reporter_ != NULL) {
         parent_field->push_back(specific_field);
         reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
         parent_field->pop_back();
       }
-      return true;
+      if (change_type != ADDITION) ++index1;
+      if (change_type != DELETION) ++index2;
+      continue;
     }
 
     if (change_type == ADDITION || change_type == DELETION ||
@@ -1526,7 +1671,7 @@
     }
   }
   // Backfill match_list1_ as we only filled match_list2_ when finding
-  // argumenting pathes.
+  // argumenting paths.
   for (int i = 0; i < count2_; ++i) {
     if ((*match_list2_)[i] != -1) {
       (*match_list1_)[(*match_list2_)[i]] = i;
@@ -1599,9 +1744,9 @@
   Reporter* reporter = reporter_;
   reporter_ = NULL;
   NumDiffsReporter num_diffs_reporter;
-  std::vector<int32> num_diffs_list1;
+  std::vector<int32_t> num_diffs_list1;
   if (is_treated_as_smart_set) {
-    num_diffs_list1.assign(count1, kint32max);
+    num_diffs_list1.assign(count1, std::numeric_limits<int32_t>::max());
   }
 
   bool success = true;
@@ -1669,7 +1814,7 @@
           } else if (repeated_field->cpp_type() ==
                      FieldDescriptor::CPPTYPE_MESSAGE) {
             // Replace with the one with fewer diffs.
-            const int32 num_diffs = num_diffs_reporter.GetNumDiffs();
+            const int32_t num_diffs = num_diffs_reporter.GetNumDiffs();
             if (num_diffs < num_diffs_list1[i]) {
               // If j has been already matched to some element, ensure the
               // current num_diffs is smaller.
@@ -1718,9 +1863,9 @@
     const Message& message1, const Message& message2,
     const FieldDescriptor* field, int index1, int index2,
     const FieldContext* field_context) {
-  FieldComparator* comparator = field_comparator_ != NULL
-                                    ? field_comparator_
-                                    : &default_field_comparator_;
+  FieldComparator* comparator = field_comparator_kind_ == kFCBase
+                                    ? field_comparator_.base
+                                    : field_comparator_.default_impl;
   return comparator->Compare(message1, message2, field, index1, index2,
                              field_context);
 }
@@ -1748,12 +1893,16 @@
     io::ZeroCopyOutputStream* output)
     : printer_(new io::Printer(output, '$')),
       delete_printer_(true),
-      report_modified_aggregates_(false) {}
+      report_modified_aggregates_(false),
+      message1_(nullptr),
+      message2_(nullptr) {}
 
 MessageDifferencer::StreamReporter::StreamReporter(io::Printer* printer)
     : printer_(printer),
       delete_printer_(false),
-      report_modified_aggregates_(false) {}
+      report_modified_aggregates_(false),
+      message1_(nullptr),
+      message2_(nullptr) {}
 
 MessageDifferencer::StreamReporter::~StreamReporter() {
   if (delete_printer_) delete printer_;
@@ -1761,21 +1910,29 @@
 
 void MessageDifferencer::StreamReporter::PrintPath(
     const std::vector<SpecificField>& field_path, bool left_side) {
-  for (int i = 0; i < field_path.size(); ++i) {
+  for (size_t i = 0; i < field_path.size(); ++i) {
+    SpecificField specific_field = field_path[i];
+
+    if (specific_field.field != nullptr &&
+        specific_field.field->name() == "value") {
+      // check to see if this the value label of a map value.  If so, skip it
+      // because it isn't meaningful
+      if (i > 0 && field_path[i - 1].field->is_map()) {
+        continue;
+      }
+    }
     if (i > 0) {
       printer_->Print(".");
     }
-
-    SpecificField specific_field = field_path[i];
-
     if (specific_field.field != NULL) {
       if (specific_field.field->is_extension()) {
         printer_->Print("($name$)", "name", specific_field.field->full_name());
       } else {
         printer_->PrintRaw(specific_field.field->name());
       }
+
       if (specific_field.field->is_map()) {
-        // Don't print index in a map field; they are semantically unordered.
+        PrintMapKey(field_path, left_side, specific_field, i);
         continue;
       }
     } else {
@@ -1791,11 +1948,6 @@
   }
 }
 
-void MessageDifferencer::StreamReporter::PrintPath(
-    const std::vector<SpecificField>& field_path, bool left_side,
-    const Message& message) {
-  PrintPath(field_path, left_side);
-}
 
 void MessageDifferencer::StreamReporter::PrintValue(
     const Message& message, const std::vector<SpecificField>& field_path,
@@ -1811,11 +1963,29 @@
           field->is_repeated()
               ? reflection->GetRepeatedMessage(message, field, index)
               : reflection->GetMessage(message, field);
-      output = field_message.ShortDebugString();
+      const FieldDescriptor* fd = nullptr;
+
+      if (field->is_map() && message1_ != nullptr && message2_ != nullptr) {
+        fd = field_message.GetDescriptor()->field(1);
+        if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+          output = field_message.GetReflection()
+                       ->GetMessage(field_message, fd)
+                       .ShortDebugString();
+        } else {
+          TextFormat::PrintFieldValueToString(field_message, fd, -1, &output);
+        }
+      } else {
+        output = field_message.ShortDebugString();
+      }
       if (output.empty()) {
         printer_->Print("{ }");
       } else {
-        printer_->Print("{ $name$ }", "name", output);
+        if ((fd != nullptr) &&
+            (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) {
+          printer_->PrintRaw(output);
+        } else {
+          printer_->Print("{ $name$ }", "name", output);
+        }
       }
     } else {
       TextFormat::PrintFieldValueToString(message, field, index, &output);
@@ -1867,11 +2037,86 @@
   printer_->Print(str.c_str());
 }
 
+void MessageDifferencer::StreamReporter::PrintMapKey(
+    const std::vector<SpecificField>& field_path, bool left_side,
+    const SpecificField& specific_field, size_t target_field_index) {
+  if (message1_ == nullptr || message2_ == nullptr) {
+    GOOGLE_LOG(WARNING) << "PrintPath cannot log map keys; "
+                    "use SetMessages to provide the messages "
+                    "being compared prior to any processing.";
+    return;
+  }
+  auto get_target_message = [=](const SpecificField& specific_field,
+                                const Reflection* reflection,
+                                const Message* message) {
+    return &(
+        specific_field.field->is_repeated()
+            ? reflection->GetRepeatedMessage(
+                  *message, specific_field.field,
+                  left_side ? specific_field.index : specific_field.new_index)
+            : reflection->GetMessage(*message, specific_field.field));
+  };
+
+  std::unique_ptr<Message> deserialized_msg;  // used for protobuf.Any case
+  std::unique_ptr<DynamicMessageFactory> dynamic_message_factory;
+  const Message* found_message = left_side ? message1_ : message2_;
+  for (size_t j = 0; j <= target_field_index;
+       j++) {  // iterate until we find target field
+    if (specific_field.field->is_repeated()) {
+      int index = left_side ? specific_field.index : specific_field.new_index;
+      if (index < 0) {
+        // Filtered messages fall in this case
+        GOOGLE_LOG(WARNING) << "Invalid index " << index << " for map.\n";
+        found_message = nullptr;
+        break;
+      }
+    }
+    if (found_message->GetTypeName() == "google.protobuf.Any") {
+      if (!unpack_any_field_.UnpackAny(*found_message, &deserialized_msg)) {
+        GOOGLE_LOG(ERROR) << "Cannot print Any message map key due to "
+                      "unpacking error\n";
+        found_message = nullptr;
+        break;
+      }
+
+      found_message =
+          get_target_message(field_path[j], deserialized_msg->GetReflection(),
+                             deserialized_msg.get());
+
+    } else {
+      found_message = get_target_message(
+          field_path[j], found_message->GetReflection(), found_message);
+    }
+  }
+
+  std::string key_string = "";
+  if (found_message != nullptr) {
+    // NB: the map key is always the first field
+    const FieldDescriptor* fd = found_message->GetDescriptor()->field(0);
+    if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      key_string = found_message->GetReflection()
+                       ->GetMessage(*found_message, fd)
+                       .ShortDebugString();
+    } else if (fd->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+      // Not using PrintFieldValueToString for strings to avoid extra
+      // characters
+      key_string = found_message->GetReflection()->GetString(
+          *found_message, found_message->GetDescriptor()->field(0));
+    } else {
+      TextFormat::PrintFieldValueToString(*found_message, fd, -1, &key_string);
+    }
+    if (key_string.empty()) {
+      key_string = "''";
+    }
+    printer_->PrintRaw(StrCat("[", key_string, "]"));
+  }
+}
+
 void MessageDifferencer::StreamReporter::ReportAdded(
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("added: ");
-  PrintPath(field_path, false, message2);
+  PrintPath(field_path, false);
   printer_->Print(": ");
   PrintValue(message2, field_path, false);
   printer_->Print("\n");  // Print for newlines.
@@ -1881,7 +2126,7 @@
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("deleted: ");
-  PrintPath(field_path, true, message1);
+  PrintPath(field_path, true);
   printer_->Print(": ");
   PrintValue(message1, field_path, true);
   printer_->Print("\n");  // Print for newlines
@@ -1904,10 +2149,10 @@
   }
 
   printer_->Print("modified: ");
-  PrintPath(field_path, true, message1);
+  PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false, message2);
+    PrintPath(field_path, false);
   }
   printer_->Print(": ");
   PrintValue(message1, field_path, true);
@@ -1920,9 +2165,9 @@
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("moved: ");
-  PrintPath(field_path, true, message1);
+  PrintPath(field_path, true);
   printer_->Print(" -> ");
-  PrintPath(field_path, false, message2);
+  PrintPath(field_path, false);
   printer_->Print(" : ");
   PrintValue(message1, field_path, true);
   printer_->Print("\n");  // Print for newlines.
@@ -1932,10 +2177,10 @@
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("matched: ");
-  PrintPath(field_path, true, message1);
+  PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false, message2);
+    PrintPath(field_path, false);
   }
   printer_->Print(" : ");
   PrintValue(message1, field_path, true);
@@ -1946,22 +2191,28 @@
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("ignored: ");
-  PrintPath(field_path, true, message1);
+  PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false, message2);
+    PrintPath(field_path, false);
   }
   printer_->Print("\n");  // Print for newlines.
 }
 
+void MessageDifferencer::StreamReporter::SetMessages(const Message& message1,
+                                                     const Message& message2) {
+  message1_ = &message1;
+  message2_ = &message2;
+}
+
 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("ignored: ");
-  PrintPath(field_path, true, message1);
+  PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false, message2);
+    PrintPath(field_path, false);
   }
   printer_->Print("\n");  // Print for newlines.
 }
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index f7317c8..4cdb817 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -37,13 +37,15 @@
 //
 // Aug. 2008: Added Unknown Fields Comparison for messages.
 // Aug. 2009: Added different options to compare repeated fields.
-// Apr. 2010: Moved field comparison to FieldComparator.
+// Apr. 2010: Moved field comparison to FieldComparator
+// Sep. 2020: Added option to output map keys in path
 
 #ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
 #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
 
 #include <functional>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -177,43 +179,47 @@
     // For known fields, "field" is filled in and "unknown_field_number" is -1.
     // For unknown fields, "field" is NULL, "unknown_field_number" is the field
     // number, and "unknown_field_type" is its type.
-    const FieldDescriptor* field;
-    int unknown_field_number;
-    UnknownField::Type unknown_field_type;
+    const FieldDescriptor* field = nullptr;
+    int unknown_field_number = -1;
+    UnknownField::Type unknown_field_type = UnknownField::Type::TYPE_VARINT;
 
     // If this a repeated field, "index" is the index within it.  For unknown
     // fields, this is the index of the field among all unknown fields of the
     // same field number and type.
-    int index;
+    int index = -1;
 
     // If "field" is a repeated field which is being treated as a map or
     // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
     // the index the position to which the element has moved.  If the element
     // has not moved, "new_index" will have the same value as "index".
-    int new_index;
+    int new_index = -1;
 
     // For unknown fields, these are the pointers to the UnknownFieldSet
     // containing the unknown fields. In certain cases (e.g. proto1's
     // MessageSet, or nested groups of unknown fields), these may differ from
     // the messages' internal UnknownFieldSets.
-    const UnknownFieldSet* unknown_field_set1;
-    const UnknownFieldSet* unknown_field_set2;
+    const UnknownFieldSet* unknown_field_set1 = nullptr;
+    const UnknownFieldSet* unknown_field_set2 = nullptr;
 
     // For unknown fields, these are the index of the field within the
     // UnknownFieldSets. One or the other will be -1 when
     // reporting an addition or deletion.
-    int unknown_field_index1;
-    int unknown_field_index2;
+    int unknown_field_index1 = -1;
+    int unknown_field_index2 = -1;
+  };
 
-    SpecificField()
-        : field(NULL),
-          unknown_field_number(-1),
-          index(-1),
-          new_index(-1),
-          unknown_field_set1(NULL),
-          unknown_field_set2(NULL),
-          unknown_field_index1(-1),
-          unknown_field_index2(-1) {}
+  // Class for processing Any deserialization.  This logic is used by both the
+  // MessageDifferencer and StreamReporter classes.
+  class UnpackAnyField {
+   private:
+    std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
+
+   public:
+    UnpackAnyField() = default;
+    ~UnpackAnyField() = default;
+    // If "any" is of type google.protobuf.Any, extract its payload using
+    // DynamicMessageFactory and store in "data".
+    bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
   };
 
   // Abstract base class from which all MessageDifferencer
@@ -328,7 +334,7 @@
 
   // Abstract base class from which all IgnoreCriteria derive.
   // By adding IgnoreCriteria more complex ignore logic can be implemented.
-  // IgnoreCriteria are registed with AddIgnoreCriteria. For each compared
+  // IgnoreCriteria are registered with AddIgnoreCriteria. For each compared
   // field IsIgnored is called on each added IgnoreCriteria until one returns
   // true or all return false.
   // IsIgnored is called for fields where at least one side has a value.
@@ -425,7 +431,7 @@
   // + n^3) in which n^3 is the time complexity of the maximum matching
   // algorithm.
   //
-  // REQUIRES:  field->is_repeated() and field not registered with TreatAsList
+  // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
   void TreatAsSet(const FieldDescriptor* field);
   void TreatAsSmartSet(const FieldDescriptor* field);
 
@@ -433,7 +439,7 @@
   // diffing purposes, so different orderings of the same elements will NOT be
   // considered equal.
   //
-  // REQUIRED: field->is_repeated() and field not registered with TreatAsSet
+  // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
   void TreatAsList(const FieldDescriptor* field);
   // Note that the complexity is similar to treating as SET.
   void TreatAsSmartList(const FieldDescriptor* field);
@@ -527,6 +533,9 @@
   // Note that this method must be called before Compare for the comparator to
   // be used.
   void set_field_comparator(FieldComparator* comparator);
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+  void set_field_comparator(DefaultFieldComparator* comparator);
+#endif  // PROTOBUF_FUTURE_BREAKING_CHANGES
 
   // DEPRECATED. Pass a DefaultFieldComparator instance instead.
   // Sets the fraction and margin for the float comparison of a given field.
@@ -662,12 +671,11 @@
         const Message& message1, const Message& message2,
         const std::vector<SpecificField>& field_path) override;
 
-   protected:
-    // Prints the specified path of fields to the buffer.  message is used to
-    // print map keys.
-    virtual void PrintPath(const std::vector<SpecificField>& field_path,
-                           bool left_side, const Message& message);
+    // Messages that are being compared must be provided to StreamReporter prior
+    // to processing
+    void SetMessages(const Message& message1, const Message& message2);
 
+   protected:
     // Prints the specified path of fields to the buffer.
     virtual void PrintPath(const std::vector<SpecificField>& field_path,
                            bool left_side);
@@ -687,16 +695,23 @@
     // Just print a string
     void Print(const std::string& str);
 
+    // helper function for PrintPath that contains logic for printing maps
+    void PrintMapKey(const std::vector<SpecificField>& field_path,
+                     bool left_side, const SpecificField& specific_field,
+                     size_t target_field_index);
+
    private:
     io::Printer* printer_;
     bool delete_printer_;
     bool report_modified_aggregates_;
-
+    const Message* message1_;
+    const Message* message2_;
+    MessageDifferencer::UnpackAnyField unpack_any_field_;
     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
   };
 
  private:
-  friend class DefaultFieldComparator;
+  friend class SimpleFieldComparator;
 
   // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
   // Implementation of this class needs to do field value comparison which
@@ -767,6 +782,26 @@
                             const FieldDescriptor* field,
                             std::vector<SpecificField>* parent_fields);
 
+  // Compares map fields, and report the error.
+  bool CompareMapField(const Message& message1, const Message& message2,
+                       const FieldDescriptor* field,
+                       std::vector<SpecificField>* parent_fields);
+
+  // Helper for CompareRepeatedField and CompareMapField: compares and reports
+  // differences element-wise. This is the implementation for non-map fields,
+  // and can also compare map fields by using the underlying representation.
+  bool CompareRepeatedRep(const Message& message1, const Message& message2,
+                          const FieldDescriptor* field,
+                          std::vector<SpecificField>* parent_fields);
+
+  // Helper for CompareMapField: compare the map fields using map reflection
+  // instead of sync to repeated.
+  bool CompareMapFieldByMapReflection(const Message& message1,
+                                      const Message& message2,
+                                      const FieldDescriptor* field,
+                                      std::vector<SpecificField>* parent_fields,
+                                      DefaultFieldComparator* comparator);
+
   // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
   bool CompareFieldValue(const Message& message1, const Message& message2,
                          const FieldDescriptor* field, int index1, int index2);
@@ -851,10 +886,6 @@
       const std::vector<SpecificField>& parent_fields,
       std::vector<int>* match_list1, std::vector<int>* match_list2);
 
-  // If "any" is of type google.protobuf.Any, extract its payload using
-  // DynamicMessageFactory and store in "data".
-  bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
-
   // Checks if index is equal to new_index in all the specific fields.
   static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields);
 
@@ -876,7 +907,6 @@
 
   Reporter* reporter_;
   DefaultFieldComparator default_field_comparator_;
-  FieldComparator* field_comparator_;
   MessageFieldComparison message_field_comparison_;
   Scope scope_;
   RepeatedFieldComparison repeated_field_comparison_;
@@ -897,6 +927,12 @@
 
   FieldSet ignored_fields_;
 
+  union {
+    DefaultFieldComparator* default_impl;
+    FieldComparator* base;
+  } field_comparator_ = {&default_field_comparator_};
+  enum { kFCDefault, kFCBase } field_comparator_kind_ = kFCDefault;
+
   bool report_matches_;
   bool report_moves_;
   bool report_ignores_;
@@ -907,7 +943,7 @@
   std::function<void(std::vector<int>*, std::vector<int>*)>
       match_indices_for_smart_list_callback_;
 
-  std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
+  MessageDifferencer::UnpackAnyField unpack_any_field_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
 };
 
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index 637d4d3..fbbcd3c 100644
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -39,8 +39,11 @@
 #include <string>
 #include <vector>
 
+#include <google/protobuf/stubs/common.h>
+
 #include <google/protobuf/stubs/strutil.h>
 
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/any_test.pb.h>
 #include <google/protobuf/map_test_util.h>
 #include <google/protobuf/map_unittest.pb.h>
@@ -53,9 +56,6 @@
 #include <google/protobuf/util/message_differencer_unittest.pb.h>
 #include <google/protobuf/util/field_comparator.h>
 #include <google/protobuf/util/message_differencer.h>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
@@ -160,6 +160,29 @@
 
   // Compare
   EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+
+  // Get map entries by index will sync map to repeated field
+  MapTestUtil::GetMapEntries(msg1, 0);
+  EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+
+  // Compare values not match
+  (*msg1.mutable_map_int32_int32())[1] = 2;
+  (*msg2.mutable_map_int32_int32())[1] = 3;
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+
+  // Compare keys not match
+  msg1.Clear();
+  msg2.Clear();
+  (*msg1.mutable_map_string_string())["1"] = "";
+  (*msg2.mutable_map_string_string())["2"] = "";
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+
+  // Compare message values not match
+  msg1.Clear();
+  msg2.Clear();
+  (*msg1.mutable_map_int32_foreign_message())[1].set_c(1);
+  (*msg2.mutable_map_int32_foreign_message())[1].set_c(2);
+  EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
 }
 
 TEST(MessageDifferencerTest, BasicPartialEqualityTest) {
@@ -1037,6 +1060,42 @@
   EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
 }
 
+TEST(MessageDifferencerTest, RepeatedFieldTreatmentChangeListToSet) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  msg1.add_rv(1);
+  msg1.add_rv(2);
+  msg2.add_rv(2);
+  msg2.add_rv(1);
+
+  util::MessageDifferencer differencer;
+  differencer.TreatAsList(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+  differencer.TreatAsSet(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldTreatmentChangeSetToList) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  msg1.add_rv(1);
+  msg1.add_rv(2);
+  msg2.add_rv(2);
+  msg2.add_rv(1);
+
+  util::MessageDifferencer differencer;
+  differencer.TreatAsSet(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+  differencer.TreatAsList(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
 TEST(MessageDifferencerTest, RepeatedFieldSmartListTest) {
   // Create the testing protos
   protobuf_unittest::TestDiffMessage msg1;
@@ -1205,7 +1264,7 @@
   *msg2.add_rm() = elem1_2;
   *msg2.add_rm() = elem2_2;
 
-  string diff_report;
+  std::string diff_report;
   util::MessageDifferencer differencer;
   differencer.ReportDifferencesToString(&diff_report);
   differencer.set_repeated_field_comparison(
@@ -1760,6 +1819,43 @@
       output);
 }
 
+TEST(MessageDifferencerTest, PrintMapKeysTest) {
+  // Note that because map is unordered, the comparison
+  // output string for test evaluation cannot assume order of
+  // output of fields (IOW if two fields are deleted
+  // one cannot assume which deleted field log will be printed first).
+  // Test currently just has a single record per operation to address this.
+  // This should only be a limitation for EXPECT_EQ evaluation.
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->mutable_mp()->insert({{"key_a", 1}, {"key_b", 2}, {"key_c", 3}});
+  item = msg2.add_item();
+  item->mutable_mp()->insert({{"key_a", 1}, {"key_b", 3}, {"key_d", 4}});
+
+  util::MessageDifferencer differencer;
+  std::string diff;
+  differencer.ReportDifferencesToString(&diff);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "modified: item[0].mp[key_b]: 2 -> 3\n"
+      "added: item[0].mp[key_d]: 4\n"
+      "deleted: item[0].mp[key_c]: 3\n",
+      diff);
+
+  google::protobuf::Any any1, any2;
+  any1.PackFrom(msg1);
+  any2.PackFrom(msg2);
+  std::string diff_with_any;
+  differencer.ReportDifferencesToString(&diff_with_any);
+  EXPECT_FALSE(differencer.Compare(any1, any2));
+  EXPECT_EQ(
+      "modified: item[0].mp[key_b]: 2 -> 3\n"
+      "added: item[0].mp[key_d]: 4\n"
+      "deleted: item[0].mp[key_c]: 3\n",
+      diff_with_any);
+}
+
 static const char* const kIgnoredFields[] = {"rm.b", "rm.m.b"};
 
 class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria {
@@ -2385,7 +2481,7 @@
 
   void field_as_set(const std::string& field) { set_field_ = field; }
 
-  void field_as_map(const string& field, const std::string& key) {
+  void field_as_map(const std::string& field, const std::string& key) {
     map_field_ = field;
     map_key_ = key;
   }
@@ -3198,25 +3294,29 @@
 }
 
 TEST_F(ComparisonTest, MapTest) {
-  Map<string, std::string>& map1 = *map_proto1_.mutable_map_string_string();
+  Map<std::string, std::string>& map1 =
+      *map_proto1_.mutable_map_string_string();
   map1["key1"] = "1";
   map1["key2"] = "2";
   map1["key3"] = "3";
-  Map<string, std::string>& map2 = *map_proto2_.mutable_map_string_string();
+  Map<std::string, std::string>& map2 =
+      *map_proto2_.mutable_map_string_string();
   map2["key3"] = "0";
   map2["key2"] = "2";
   map2["key1"] = "1";
 
-  EXPECT_EQ("modified: map_string_string.value: \"3\" -> \"0\"\n",
+  EXPECT_EQ("modified: map_string_string[key3]: \"3\" -> \"0\"\n",
             Run(map_proto1_, map_proto2_));
 }
 
 TEST_F(ComparisonTest, MapIgnoreKeyTest) {
-  Map<string, std::string>& map1 = *map_proto1_.mutable_map_string_string();
+  Map<std::string, std::string>& map1 =
+      *map_proto1_.mutable_map_string_string();
   map1["key1"] = "1";
   map1["key2"] = "2";
   map1["key3"] = "3";
-  Map<string, std::string>& map2 = *map_proto2_.mutable_map_string_string();
+  Map<std::string, std::string>& map2 =
+      *map_proto2_.mutable_map_string_string();
   map2["key4"] = "2";
   map2["key5"] = "3";
   map2["key6"] = "1";
@@ -3258,7 +3358,7 @@
   ASSERT_TRUE(parser.ParseFromString(
       "map_int32_foreign_message { key: 1 value { c: 2 }}", &map2));
   EXPECT_FALSE(differencer.Compare(map1, map2));
-  EXPECT_EQ("modified: map_int32_foreign_message.value.c: 1 -> 2\n", output);
+  EXPECT_EQ("modified: map_int32_foreign_message[1].c: 1 -> 2\n", output);
 
   ASSERT_TRUE(
       parser.ParseFromString("map_int32_foreign_message { key: 1 }", &map1));
@@ -3275,7 +3375,11 @@
 
   util::MessageDifferencer differencer;
   differencer.set_scope(util::MessageDifferencer::PARTIAL);
-  EXPECT_TRUE(differencer.Compare(map1, map2));
+  // TODO(jieluo): Remove the round trip
+  std::string serialized_value;
+  map1.SerializeToString(&serialized_value);
+  map1.ParseFromString(serialized_value);
+  EXPECT_FALSE(differencer.Compare(map1, map2));
 }
 
 TEST_F(ComparisonTest, MapEntryMissingEmptyFieldIsOkTest) {
@@ -3331,13 +3435,14 @@
   // equal.  However, in value comparison, all fields of the message are taken
   // into consideration, so they are reported as different.
   EXPECT_FALSE(differencer.Compare(msg1, msg2));
-  EXPECT_EQ("modified: map_string_foreign_message.key: \"key1\" -> \"key2\"\n",
-            output);
+  EXPECT_EQ(
+      "modified: map_string_foreign_message[key1].key: \"key1\" -> \"key2\"\n",
+      output);
   differencer.IgnoreField(
       GetFieldDescriptor(msg1, "map_string_foreign_message.key"));
   output.clear();
   EXPECT_TRUE(differencer.Compare(msg1, msg2));
-  EXPECT_EQ("ignored: map_string_foreign_message.key\n", output);
+  EXPECT_EQ("ignored: map_string_foreign_message[key1].key\n", output);
 }
 
 class MatchingTest : public testing::Test {
diff --git a/src/google/protobuf/util/message_differencer_unittest.proto b/src/google/protobuf/util/message_differencer_unittest.proto
index cbc36fa..0ad6792 100644
--- a/src/google/protobuf/util/message_differencer_unittest.proto
+++ b/src/google/protobuf/util/message_differencer_unittest.proto
@@ -33,6 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 //
 // This file contains messages for testing repeated field comparison
+// LINT: ALLOW_GROUPS
 
 syntax = "proto2";
 
@@ -63,6 +64,7 @@
     optional TestField m = 6;   // Test TreatAsMap when key is a message
     repeated TestField rm = 7;  // Test TreatAsMap when key is a repeated
                                 // message
+    map<string, int32> mp = 8;  // Test for map comparisons
   }
 
   optional int32 v = 13 [deprecated = true];
@@ -73,6 +75,5 @@
   repeated TestField rm = 12 [deprecated = true];  // Test for combinations
   repeated google.protobuf.Any rany =
       16;  // Test for repeated Any type resolution
-
   extensions 100 to 199;
 }
diff --git a/src/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc
index 4b80e7c..6b9c665 100644
--- a/src/google/protobuf/util/time_util.cc
+++ b/src/google/protobuf/util/time_util.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/time_util.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/duration.pb.h>
@@ -57,10 +59,10 @@
 static const int kSecondsPerHour = 3600;
 
 template <typename T>
-T CreateNormalized(int64 seconds, int64 nanos);
+T CreateNormalized(int64_t seconds, int64_t nanos);
 
 template <>
-Timestamp CreateNormalized(int64 seconds, int64 nanos) {
+Timestamp CreateNormalized(int64_t seconds, int64_t nanos) {
   // Make sure nanos is in the range.
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     seconds += nanos / kNanosPerSecond;
@@ -75,12 +77,12 @@
          seconds <= TimeUtil::kTimestampMaxSeconds);
   Timestamp result;
   result.set_seconds(seconds);
-  result.set_nanos(static_cast<int32>(nanos));
+  result.set_nanos(static_cast<int32_t>(nanos));
   return result;
 }
 
 template <>
-Duration CreateNormalized(int64 seconds, int64 nanos) {
+Duration CreateNormalized(int64_t seconds, int64_t nanos) {
   // Make sure nanos is in the range.
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     seconds += nanos / kNanosPerSecond;
@@ -98,13 +100,13 @@
          seconds <= TimeUtil::kDurationMaxSeconds);
   Duration result;
   result.set_seconds(seconds);
-  result.set_nanos(static_cast<int32>(nanos));
+  result.set_nanos(static_cast<int32_t>(nanos));
   return result;
 }
 
 // Format nanoseconds with either 3, 6, or 9 digits depending on the required
 // precision to represent the exact value.
-std::string FormatNanos(int32 nanos) {
+std::string FormatNanos(int32_t nanos) {
   if (nanos % kNanosPerMillisecond == 0) {
     return StringPrintf("%03d", nanos / kNanosPerMillisecond);
   } else if (nanos % kNanosPerMicrosecond == 0) {
@@ -127,9 +129,9 @@
 }
 
 // Truncates the remainder part after division.
-int64 RoundTowardZero(int64 value, int64 divider) {
-  int64 result = value / divider;
-  int64 remainder = value % divider;
+int64_t RoundTowardZero(int64_t value, int64_t divider) {
+  int64_t result = value / divider;
+  int64_t remainder = value % divider;
   // Before C++11, the sign of the remainder is implementation dependent if
   // any of the operands is negative. Here we try to enforce C++11's "rounded
   // toward zero" semantics. For example, for (-5) / 2 an implementation may
@@ -146,10 +148,10 @@
 // Actually define these static const integers. Required by C++ standard (but
 // some compilers don't like it).
 #ifndef _MSC_VER
-const int64 TimeUtil::kTimestampMinSeconds;
-const int64 TimeUtil::kTimestampMaxSeconds;
-const int64 TimeUtil::kDurationMaxSeconds;
-const int64 TimeUtil::kDurationMinSeconds;
+const int64_t TimeUtil::kTimestampMinSeconds;
+const int64_t TimeUtil::kTimestampMaxSeconds;
+const int64_t TimeUtil::kDurationMaxSeconds;
+const int64_t TimeUtil::kDurationMinSeconds;
 #endif  // !_MSC_VER
 
 std::string TimeUtil::ToString(const Timestamp& timestamp) {
@@ -157,8 +159,8 @@
 }
 
 bool TimeUtil::FromString(const std::string& value, Timestamp* timestamp) {
-  int64 seconds;
-  int32 nanos;
+  int64_t seconds;
+  int32_t nanos;
   if (!ParseTime(value, &seconds, &nanos)) {
     return false;
   }
@@ -167,8 +169,8 @@
 }
 
 Timestamp TimeUtil::GetCurrentTime() {
-  int64 seconds;
-  int32 nanos;
+  int64_t seconds;
+  int32_t nanos;
   CurrentTime(&seconds, &nanos);
   return CreateNormalized<Timestamp>(seconds, nanos);
 }
@@ -177,8 +179,8 @@
 
 std::string TimeUtil::ToString(const Duration& duration) {
   std::string result;
-  int64 seconds = duration.seconds();
-  int32 nanos = duration.nanos();
+  int64_t seconds = duration.seconds();
+  int32_t nanos = duration.nanos();
   if (seconds < 0 || nanos < 0) {
     result += "-";
     seconds = -seconds;
@@ -192,8 +194,8 @@
   return result;
 }
 
-static int64 Pow(int64 x, int y) {
-  int64 result = 1;
+static int64_t Pow(int64_t x, int y) {
+  int64_t result = 1;
   for (int i = 0; i < y; ++i) {
     result *= x;
   }
@@ -209,7 +211,7 @@
   // Parse the duration value as two integers rather than a float value
   // to avoid precision loss.
   std::string seconds_part, nanos_part;
-  size_t pos = value.find_last_of(".");
+  size_t pos = value.find_last_of('.');
   if (pos == std::string::npos) {
     seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
     nanos_part = "0";
@@ -218,11 +220,11 @@
     nanos_part = value.substr(pos + 1, value.length() - pos - 2);
   }
   char* end;
-  int64 seconds = strto64(seconds_part.c_str(), &end, 10);
+  int64_t seconds = strto64(seconds_part.c_str(), &end, 10);
   if (end != seconds_part.c_str() + seconds_part.length()) {
     return false;
   }
-  int64 nanos = strto64(nanos_part.c_str(), &end, 10);
+  int64_t nanos = strto64(nanos_part.c_str(), &end, 10);
   if (end != nanos_part.c_str() + nanos_part.length()) {
     return false;
   }
@@ -233,106 +235,106 @@
     nanos = -nanos;
   }
   duration->set_seconds(seconds);
-  duration->set_nanos(static_cast<int32>(nanos));
+  duration->set_nanos(static_cast<int32_t>(nanos));
   return true;
 }
 
-Duration TimeUtil::NanosecondsToDuration(int64 nanos) {
+Duration TimeUtil::NanosecondsToDuration(int64_t nanos) {
   return CreateNormalized<Duration>(nanos / kNanosPerSecond,
                                     nanos % kNanosPerSecond);
 }
 
-Duration TimeUtil::MicrosecondsToDuration(int64 micros) {
+Duration TimeUtil::MicrosecondsToDuration(int64_t micros) {
   return CreateNormalized<Duration>(
       micros / kMicrosPerSecond,
       (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
 }
 
-Duration TimeUtil::MillisecondsToDuration(int64 millis) {
+Duration TimeUtil::MillisecondsToDuration(int64_t millis) {
   return CreateNormalized<Duration>(
       millis / kMillisPerSecond,
       (millis % kMillisPerSecond) * kNanosPerMillisecond);
 }
 
-Duration TimeUtil::SecondsToDuration(int64 seconds) {
+Duration TimeUtil::SecondsToDuration(int64_t seconds) {
   return CreateNormalized<Duration>(seconds, 0);
 }
 
-Duration TimeUtil::MinutesToDuration(int64 minutes) {
+Duration TimeUtil::MinutesToDuration(int64_t minutes) {
   return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
 }
 
-Duration TimeUtil::HoursToDuration(int64 hours) {
+Duration TimeUtil::HoursToDuration(int64_t hours) {
   return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
 }
 
-int64 TimeUtil::DurationToNanoseconds(const Duration& duration) {
+int64_t TimeUtil::DurationToNanoseconds(const Duration& duration) {
   return duration.seconds() * kNanosPerSecond + duration.nanos();
 }
 
-int64 TimeUtil::DurationToMicroseconds(const Duration& duration) {
+int64_t TimeUtil::DurationToMicroseconds(const Duration& duration) {
   return duration.seconds() * kMicrosPerSecond +
          RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
 }
 
-int64 TimeUtil::DurationToMilliseconds(const Duration& duration) {
+int64_t TimeUtil::DurationToMilliseconds(const Duration& duration) {
   return duration.seconds() * kMillisPerSecond +
          RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
 }
 
-int64 TimeUtil::DurationToSeconds(const Duration& duration) {
+int64_t TimeUtil::DurationToSeconds(const Duration& duration) {
   return duration.seconds();
 }
 
-int64 TimeUtil::DurationToMinutes(const Duration& duration) {
+int64_t TimeUtil::DurationToMinutes(const Duration& duration) {
   return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
 }
 
-int64 TimeUtil::DurationToHours(const Duration& duration) {
+int64_t TimeUtil::DurationToHours(const Duration& duration) {
   return RoundTowardZero(duration.seconds(), kSecondsPerHour);
 }
 
-Timestamp TimeUtil::NanosecondsToTimestamp(int64 nanos) {
+Timestamp TimeUtil::NanosecondsToTimestamp(int64_t nanos) {
   return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
                                      nanos % kNanosPerSecond);
 }
 
-Timestamp TimeUtil::MicrosecondsToTimestamp(int64 micros) {
+Timestamp TimeUtil::MicrosecondsToTimestamp(int64_t micros) {
   return CreateNormalized<Timestamp>(
       micros / kMicrosPerSecond,
       micros % kMicrosPerSecond * kNanosPerMicrosecond);
 }
 
-Timestamp TimeUtil::MillisecondsToTimestamp(int64 millis) {
+Timestamp TimeUtil::MillisecondsToTimestamp(int64_t millis) {
   return CreateNormalized<Timestamp>(
       millis / kMillisPerSecond,
       millis % kMillisPerSecond * kNanosPerMillisecond);
 }
 
-Timestamp TimeUtil::SecondsToTimestamp(int64 seconds) {
+Timestamp TimeUtil::SecondsToTimestamp(int64_t seconds) {
   return CreateNormalized<Timestamp>(seconds, 0);
 }
 
-int64 TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
   return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
 }
 
-int64 TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
   return timestamp.seconds() * kMicrosPerSecond +
          RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
 }
 
-int64 TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
   return timestamp.seconds() * kMillisPerSecond +
          RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
 }
 
-int64 TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
   return timestamp.seconds();
 }
 
 Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
-  return CreateNormalized<Timestamp>(static_cast<int64>(value), 0);
+  return CreateNormalized<Timestamp>(static_cast<int64_t>(value), 0);
 }
 
 time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
@@ -382,19 +384,20 @@
 void ToUint128(const Duration& value, uint128* result, bool* negative) {
   if (value.seconds() < 0 || value.nanos() < 0) {
     *negative = true;
-    *result = static_cast<uint64>(-value.seconds());
-    *result = *result * kNanosPerSecond + static_cast<uint32>(-value.nanos());
+    *result = static_cast<uint64_t>(-value.seconds());
+    *result = *result * kNanosPerSecond + static_cast<uint32_t>(-value.nanos());
   } else {
     *negative = false;
-    *result = static_cast<uint64>(value.seconds());
-    *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
+    *result = static_cast<uint64_t>(value.seconds());
+    *result = *result * kNanosPerSecond + static_cast<uint32_t>(value.nanos());
   }
 }
 
 void ToDuration(const uint128& value, bool negative, Duration* duration) {
-  int64 seconds =
-      static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
-  int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
+  int64_t seconds =
+      static_cast<int64_t>(Uint128Low64(value / kNanosPerSecond));
+  int32_t nanos =
+      static_cast<int32_t>(Uint128Low64(value % kNanosPerSecond));
   if (negative) {
     seconds = -seconds;
     nanos = -nanos;
@@ -416,15 +419,15 @@
   return d1;
 }
 
-Duration& operator*=(Duration& d, int64 r) {  // NOLINT
+Duration& operator*=(Duration& d, int64_t r) {  // NOLINT
   bool negative;
   uint128 value;
   ToUint128(d, &value, &negative);
   if (r > 0) {
-    value *= static_cast<uint64>(r);
+    value *= static_cast<uint64_t>(r);
   } else {
     negative = !negative;
-    value *= static_cast<uint64>(-r);
+    value *= static_cast<uint64_t>(-r);
   }
   ToDuration(value, negative, &d);
   return d;
@@ -432,8 +435,8 @@
 
 Duration& operator*=(Duration& d, double r) {  // NOLINT
   double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r;
-  int64 seconds = static_cast<int64>(result);
-  int32 nanos = static_cast<int32>((result - seconds) * kNanosPerSecond);
+  int64_t seconds = static_cast<int64_t>(result);
+  int32_t nanos = static_cast<int32_t>((result - seconds) * kNanosPerSecond);
   // Note that we normalize here not just because nanos can have a different
   // sign from seconds but also that nanos can be any arbitrary value when
   // overflow happens (i.e., the result is a much larger value than what
@@ -442,15 +445,15 @@
   return d;
 }
 
-Duration& operator/=(Duration& d, int64 r) {  // NOLINT
+Duration& operator/=(Duration& d, int64_t r) {  // NOLINT
   bool negative;
   uint128 value;
   ToUint128(d, &value, &negative);
   if (r > 0) {
-    value /= static_cast<uint64>(r);
+    value /= static_cast<uint64_t>(r);
   } else {
     negative = !negative;
-    value /= static_cast<uint64>(-r);
+    value /= static_cast<uint64_t>(-r);
   }
   ToDuration(value, negative, &d);
   return d;
@@ -476,12 +479,12 @@
   return d1;
 }
 
-int64 operator/(const Duration& d1, const Duration& d2) {
+int64_t operator/(const Duration& d1, const Duration& d2) {
   bool negative1, negative2;
   uint128 value1, value2;
   ToUint128(d1, &value1, &negative1);
   ToUint128(d2, &value2, &negative2);
-  int64 result = Uint128Low64(value1 / value2);
+  int64_t result = Uint128Low64(value1 / value2);
   if (negative1 != negative2) {
     result = -result;
   }
diff --git a/src/google/protobuf/util/time_util.h b/src/google/protobuf/util/time_util.h
index 95063fc..96b1aac 100644
--- a/src/google/protobuf/util/time_util.h
+++ b/src/google/protobuf/util/time_util.h
@@ -33,6 +33,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
 #define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
 
+#include <cstdint>
 #include <ctime>
 #include <ostream>
 #include <string>
@@ -67,11 +68,11 @@
   // The min/max Timestamp/Duration values we support.
   //
   // For "0001-01-01T00:00:00Z".
-  static const int64 kTimestampMinSeconds = -62135596800LL;
+  static const int64_t kTimestampMinSeconds = -62135596800LL;
   // For "9999-12-31T23:59:59.999999999Z".
-  static const int64 kTimestampMaxSeconds = 253402300799LL;
-  static const int64 kDurationMinSeconds = -315576000000LL;
-  static const int64 kDurationMaxSeconds = 315576000000LL;
+  static const int64_t kTimestampMaxSeconds = 253402300799LL;
+  static const int64_t kDurationMinSeconds = -315576000000LL;
+  static const int64_t kDurationMaxSeconds = 315576000000LL;
 
   // Converts Timestamp to/from RFC 3339 date string format.
   // Generated output will always be Z-normalized and uses 3, 6 or 9
@@ -110,12 +111,12 @@
 
   // Converts between Duration and integer types. The behavior is undefined if
   // the input value is not in the valid range of Duration.
-  static Duration NanosecondsToDuration(int64 nanos);
-  static Duration MicrosecondsToDuration(int64 micros);
-  static Duration MillisecondsToDuration(int64 millis);
-  static Duration SecondsToDuration(int64 seconds);
-  static Duration MinutesToDuration(int64 minutes);
-  static Duration HoursToDuration(int64 hours);
+  static Duration NanosecondsToDuration(int64_t nanos);
+  static Duration MicrosecondsToDuration(int64_t micros);
+  static Duration MillisecondsToDuration(int64_t millis);
+  static Duration SecondsToDuration(int64_t seconds);
+  static Duration MinutesToDuration(int64_t minutes);
+  static Duration HoursToDuration(int64_t hours);
   // Result will be truncated towards zero. For example, "-1.5s" will be
   // truncated to "-1s", and "1.5s" to "1s" when converting to seconds.
   // It's undefined behavior if the input duration is not valid or the result
@@ -123,28 +124,28 @@
   // valid range of Duration, or have an invalid nanos value (i.e., larger
   // than 999999999, less than -999999999, or have a different sign from the
   // seconds part).
-  static int64 DurationToNanoseconds(const Duration& duration);
-  static int64 DurationToMicroseconds(const Duration& duration);
-  static int64 DurationToMilliseconds(const Duration& duration);
-  static int64 DurationToSeconds(const Duration& duration);
-  static int64 DurationToMinutes(const Duration& duration);
-  static int64 DurationToHours(const Duration& duration);
+  static int64_t DurationToNanoseconds(const Duration& duration);
+  static int64_t DurationToMicroseconds(const Duration& duration);
+  static int64_t DurationToMilliseconds(const Duration& duration);
+  static int64_t DurationToSeconds(const Duration& duration);
+  static int64_t DurationToMinutes(const Duration& duration);
+  static int64_t DurationToHours(const Duration& duration);
   // Creates Timestamp from integer types. The integer value indicates the
   // time elapsed from Epoch time. The behavior is undefined if the input
   // value is not in the valid range of Timestamp.
-  static Timestamp NanosecondsToTimestamp(int64 nanos);
-  static Timestamp MicrosecondsToTimestamp(int64 micros);
-  static Timestamp MillisecondsToTimestamp(int64 millis);
-  static Timestamp SecondsToTimestamp(int64 seconds);
+  static Timestamp NanosecondsToTimestamp(int64_t nanos);
+  static Timestamp MicrosecondsToTimestamp(int64_t micros);
+  static Timestamp MillisecondsToTimestamp(int64_t millis);
+  static Timestamp SecondsToTimestamp(int64_t seconds);
   // Result will be truncated down to the nearest integer value. For example,
   // with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100
   // and TimestampToSeconds() returns -1. It's undefined behavior if the input
   // Timestamp is not valid (i.e., its seconds part or nanos part does not fall
   // in the valid range) or the return value doesn't fit into int64.
-  static int64 TimestampToNanoseconds(const Timestamp& timestamp);
-  static int64 TimestampToMicroseconds(const Timestamp& timestamp);
-  static int64 TimestampToMilliseconds(const Timestamp& timestamp);
-  static int64 TimestampToSeconds(const Timestamp& timestamp);
+  static int64_t TimestampToNanoseconds(const Timestamp& timestamp);
+  static int64_t TimestampToMicroseconds(const Timestamp& timestamp);
+  static int64_t TimestampToMilliseconds(const Timestamp& timestamp);
+  static int64_t TimestampToSeconds(const Timestamp& timestamp);
 
   // Conversion to/from other time/date types. Note that these types may
   // have a different precision and time range from Timestamp/Duration.
@@ -176,19 +177,19 @@
                                      const Duration& d2);  // NOLINT
 PROTOBUF_EXPORT Duration& operator-=(Duration& d1,
                                      const Duration& d2);     // NOLINT
-PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64 r);   // NOLINT
+PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64_t r);  // NOLINT
 PROTOBUF_EXPORT Duration& operator*=(Duration& d, double r);  // NOLINT
-PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64 r);   // NOLINT
+PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64_t r);  // NOLINT
 PROTOBUF_EXPORT Duration& operator/=(Duration& d, double r);  // NOLINT
 // Overload for other integer types.
 template <typename T>
 Duration& operator*=(Duration& d, T r) {  // NOLINT
-  int64 x = r;
+  int64_t x = r;
   return d *= x;
 }
 template <typename T>
 Duration& operator/=(Duration& d, T r) {  // NOLINT
-  int64 x = r;
+  int64_t x = r;
   return d /= x;
 }
 PROTOBUF_EXPORT Duration& operator%=(Duration& d1,
@@ -243,7 +244,7 @@
 inline Duration operator/(Duration d, T r) {
   return d /= r;
 }
-PROTOBUF_EXPORT int64 operator/(const Duration& d1, const Duration& d2);
+PROTOBUF_EXPORT int64_t operator/(const Duration& d1, const Duration& d2);
 
 inline Duration operator%(const Duration& d1, const Duration& d2) {
   Duration result = d1;
diff --git a/src/google/protobuf/util/time_util_test.cc b/src/google/protobuf/util/time_util_test.cc
index 9f0d17f..d38a27d 100644
--- a/src/google/protobuf/util/time_util_test.cc
+++ b/src/google/protobuf/util/time_util_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/time_util.h>
 
+#include <cstdint>
 #include <ctime>
 
 #include <google/protobuf/duration.pb.h>
@@ -119,10 +120,10 @@
   // Duration must support range from -315,576,000,000s to +315576000000s
   // which includes negative values.
   EXPECT_TRUE(TimeUtil::FromString("315576000000.999999999s", &d));
-  EXPECT_EQ(315576000000LL, d.seconds());
+  EXPECT_EQ(int64_t{315576000000}, d.seconds());
   EXPECT_EQ(999999999, d.nanos());
   EXPECT_TRUE(TimeUtil::FromString("-315576000000.999999999s", &d));
-  EXPECT_EQ(-315576000000LL, d.seconds());
+  EXPECT_EQ(int64_t{-315576000000}, d.seconds());
   EXPECT_EQ(-999999999, d.nanos());
 }
 
@@ -277,21 +278,24 @@
   EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b * 0.5));
   // Multiplication should not overflow if the result fits into the supported
   // range of Duration (intermediate result may be larger than int64).
-  EXPECT_EQ("315575999684.424s",
-            TimeUtil::ToString((one_second - one_nano) * 315576000000LL));
-  EXPECT_EQ("-315575999684.424s",
-            TimeUtil::ToString((one_nano - one_second) * 315576000000LL));
-  EXPECT_EQ("-315575999684.424s",
-            TimeUtil::ToString((one_second - one_nano) * (-315576000000LL)));
+  EXPECT_EQ("315575999684.424s", TimeUtil::ToString((one_second - one_nano) *
+                                                    int64_t{315576000000}));
+  EXPECT_EQ("-315575999684.424s", TimeUtil::ToString((one_nano - one_second) *
+                                                     int64_t{315576000000}));
+  EXPECT_EQ("-315575999684.424s", TimeUtil::ToString((one_second - one_nano) *
+                                                     (int64_t{-315576000000})));
 
   // Test / and %
   EXPECT_EQ("0.999999999s", TimeUtil::ToString(a / 2));
   EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b / 2));
-  Duration large = TimeUtil::SecondsToDuration(315576000000LL) - one_nano;
+  Duration large =
+      TimeUtil::SecondsToDuration(int64_t{315576000000}) - one_nano;
   // We have to handle division with values beyond 64 bits.
-  EXPECT_EQ("0.999999999s", TimeUtil::ToString(large / 315576000000LL));
-  EXPECT_EQ("-0.999999999s", TimeUtil::ToString((-large) / 315576000000LL));
-  EXPECT_EQ("-0.999999999s", TimeUtil::ToString(large / (-315576000000LL)));
+  EXPECT_EQ("0.999999999s", TimeUtil::ToString(large / int64_t{315576000000}));
+  EXPECT_EQ("-0.999999999s",
+            TimeUtil::ToString((-large) / int64_t{315576000000}));
+  EXPECT_EQ("-0.999999999s",
+            TimeUtil::ToString(large / (int64_t{-315576000000})));
   Duration large2 = large + one_nano;
   EXPECT_EQ(large, large % large2);
   EXPECT_EQ(-large, (-large) % large2);
diff --git a/src/google/protobuf/util/type_resolver.h b/src/google/protobuf/util/type_resolver.h
index 698441b..2bda5c8 100644
--- a/src/google/protobuf/util/type_resolver.h
+++ b/src/google/protobuf/util/type_resolver.h
@@ -38,6 +38,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/status.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -60,7 +61,7 @@
 
   // Resolves a type url for an enum type.
   virtual util::Status ResolveEnumType(const std::string& type_url,
-                                         google::protobuf::Enum* enum_type) = 0;
+                                       google::protobuf::Enum* enum_type) = 0;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver);
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index 35736f1..c5d4fdf 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -38,6 +38,7 @@
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/status.h>
 
 // clang-format off
 #include <google/protobuf/port_def.inc>
@@ -63,47 +64,44 @@
 using google::protobuf::UInt32Value;
 using google::protobuf::UInt64Value;
 
-using util::Status;
-using util::error::INVALID_ARGUMENT;
-using util::error::NOT_FOUND;
-
 class DescriptorPoolTypeResolver : public TypeResolver {
  public:
   DescriptorPoolTypeResolver(const std::string& url_prefix,
                              const DescriptorPool* pool)
       : url_prefix_(url_prefix), pool_(pool) {}
 
-  Status ResolveMessageType(const std::string& type_url, Type* type) override {
+  util::Status ResolveMessageType(const std::string& type_url,
+                                  Type* type) override {
     std::string type_name;
-    Status status = ParseTypeUrl(type_url, &type_name);
+    util::Status status = ParseTypeUrl(type_url, &type_name);
     if (!status.ok()) {
       return status;
     }
 
     const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name);
     if (descriptor == NULL) {
-      return Status(util::error::NOT_FOUND,
-                    "Invalid type URL, unknown type: " + type_name);
+      return util::NotFoundError("Invalid type URL, unknown type: " +
+                                 type_name);
     }
     ConvertDescriptor(descriptor, type);
-    return Status();
+    return util::Status();
   }
 
-  Status ResolveEnumType(const std::string& type_url,
-                         Enum* enum_type) override {
+  util::Status ResolveEnumType(const std::string& type_url,
+                               Enum* enum_type) override {
     std::string type_name;
-    Status status = ParseTypeUrl(type_url, &type_name);
+    util::Status status = ParseTypeUrl(type_url, &type_name);
     if (!status.ok()) {
       return status;
     }
 
     const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
     if (descriptor == NULL) {
-      return Status(util::error::NOT_FOUND,
-                    "Invalid type URL, unknown type: " + type_name);
+      return util::InvalidArgumentError("Invalid type URL, unknown type: " +
+                                        type_name);
     }
     ConvertEnumDescriptor(descriptor, enum_type);
-    return Status();
+    return util::Status();
   }
 
  private:
@@ -305,15 +303,15 @@
     return url_prefix_ + "/" + descriptor->full_name();
   }
 
-  Status ParseTypeUrl(const string& type_url, std::string* type_name) {
+  util::Status ParseTypeUrl(const std::string& type_url,
+                            std::string* type_name) {
     if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") {
-      return Status(
-          util::error::INVALID_ARGUMENT,
+      return util::InvalidArgumentError(
           StrCat("Invalid type URL, type URLs must be of the form '",
                        url_prefix_, "/<typename>', got: ", type_url));
     }
     *type_name = type_url.substr(url_prefix_.size() + 1);
-    return Status();
+    return util::Status();
   }
 
   std::string DefaultValueAsString(const FieldDescriptor* descriptor) {
diff --git a/src/google/protobuf/util/type_resolver_util_test.cc b/src/google/protobuf/util/type_resolver_util_test.cc
index f9b9ad6..f0a0a74 100644
--- a/src/google/protobuf/util/type_resolver_util_test.cc
+++ b/src/google/protobuf/util/type_resolver_util_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/type_resolver_util.h>
 
+#include <cstdint>
 #include <limits>
 #include <memory>
 #include <string>
@@ -135,12 +136,12 @@
   }
 
   bool HasInt32Option(const RepeatedPtrField<Option>& options,
-                      const std::string& name, int32 value) {
+                      const std::string& name, int32_t value) {
     return HasOption<Int32Value>(options, name, value);
   }
 
   bool HasUInt64Option(const RepeatedPtrField<Option>& options,
-                       const std::string& name, uint64 value) {
+                       const std::string& name, uint64_t value) {
     return HasOption<UInt64Value>(options, name, value);
   }
 
@@ -158,7 +159,7 @@
     return false;
   }
 
-  string GetTypeUrl(std::string full_name) {
+  std::string GetTypeUrl(std::string full_name) {
     return kUrlPrefix + std::string("/") + full_name;
   }
 
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index 444510c..c30b7ab 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -64,10 +64,8 @@
 namespace internal {
 
 // Forward declare static functions
-static size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
-                                     const MapKey& value);
 static size_t MapValueRefDataOnlyByteSize(const FieldDescriptor* field,
-                                          const MapValueRef& value);
+                                          const MapValueConstRef& value);
 
 // ===================================================================
 
@@ -661,6 +659,7 @@
     auto metadata = reflection->MutableInternalMetadata(msg);
     std::string payload;
     uint32 type_id = 0;
+    bool payload_read = false;
     while (!ctx->Done(&ptr)) {
       // We use 64 bit tags in order to allow typeid's that span the whole
       // range of 32 bit numbers.
@@ -670,7 +669,7 @@
         ptr = ParseBigVarint(ptr, &tmp);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         type_id = tmp;
-        if (!payload.empty()) {
+        if (payload_read) {
           const FieldDescriptor* field;
           if (ctx->data().pool == nullptr) {
             field = reflection->FindKnownExtensionByNumber(type_id);
@@ -706,6 +705,7 @@
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ptr = ctx->ReadString(ptr, size, &payload);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          payload_read = true;
         } else {
           // We're now parsing the payload
           const FieldDescriptor* field = nullptr;
@@ -1059,9 +1059,9 @@
   }
 }
 
-static uint8* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field,
-                                             const MapKey& value, uint8* target,
-                                             io::EpsCopyOutputStream* stream) {
+uint8* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field,
+                                      const MapKey& value, uint8* target,
+                                      io::EpsCopyOutputStream* stream) {
   target = stream->EnsureSpace(target);
   switch (field->type()) {
     case FieldDescriptor::TYPE_DOUBLE:
@@ -1097,7 +1097,7 @@
 }
 
 static uint8* SerializeMapValueRefWithCachedSizes(
-    const FieldDescriptor* field, const MapValueRef& value, uint8* target,
+    const FieldDescriptor* field, const MapValueConstRef& value, uint8* target,
     io::EpsCopyOutputStream* stream) {
   target = stream->EnsureSpace(target);
   switch (field->type()) {
@@ -1182,7 +1182,8 @@
 
 static uint8* InternalSerializeMapEntry(const FieldDescriptor* field,
                                         const MapKey& key,
-                                        const MapValueRef& value, uint8* target,
+                                        const MapValueConstRef& value,
+                                        uint8* target,
                                         io::EpsCopyOutputStream* stream) {
   const FieldDescriptor* key_field = field->message_type()->field(0);
   const FieldDescriptor* value_field = field->message_type()->field(1);
@@ -1235,9 +1236,8 @@
             MapKeySorter::SortKey(message, message_reflection, field);
         for (std::vector<MapKey>::iterator it = sorted_key_list.begin();
              it != sorted_key_list.end(); ++it) {
-          MapValueRef map_value;
-          message_reflection->InsertOrLookupMapValue(
-              const_cast<Message*>(&message), field, *it, &map_value);
+          MapValueConstRef map_value;
+          message_reflection->LookupMapValue(message, field, *it, &map_value);
           target =
               InternalSerializeMapEntry(field, *it, map_value, target, stream);
         }
@@ -1460,8 +1460,8 @@
     message_reflection->ListFields(message, &fields);
   }
 
-  for (int i = 0; i < fields.size(); i++) {
-    our_size += FieldByteSize(fields[i], message);
+  for (const FieldDescriptor* field : fields) {
+    our_size += FieldByteSize(field, message);
   }
 
   if (descriptor->options().message_set_wire_format()) {
@@ -1522,8 +1522,8 @@
   return our_size;
 }
 
-static size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
-                                     const MapKey& value) {
+size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
+                              const MapKey& value) {
   GOOGLE_DCHECK_EQ(FieldDescriptor::TypeToCppType(field->type()), value.type());
   switch (field->type()) {
     case FieldDescriptor::TYPE_DOUBLE:
@@ -1564,7 +1564,7 @@
 }
 
 static size_t MapValueRefDataOnlyByteSize(const FieldDescriptor* field,
-                                          const MapValueRef& value) {
+                                          const MapValueConstRef& value) {
   switch (field->type()) {
     case FieldDescriptor::TYPE_GROUP:
       GOOGLE_LOG(FATAL) << "Unsupported";
@@ -1643,7 +1643,7 @@
 #define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD)                      \
   case FieldDescriptor::TYPE_##TYPE:                                        \
     if (field->is_repeated()) {                                             \
-      for (int j = 0; j < count; j++) {                                     \
+      for (size_t j = 0; j < count; j++) {                                  \
         data_size += WireFormatLite::TYPE_METHOD##Size(                     \
             message_reflection->GetRepeated##CPPTYPE_METHOD(message, field, \
                                                             j));            \
@@ -1683,7 +1683,7 @@
 
     case FieldDescriptor::TYPE_ENUM: {
       if (field->is_repeated()) {
-        for (int j = 0; j < count; j++) {
+        for (size_t j = 0; j < count; j++) {
           data_size += WireFormatLite::EnumSize(
               message_reflection->GetRepeatedEnum(message, field, j)->number());
         }
@@ -1698,7 +1698,7 @@
     // instead of copying.
     case FieldDescriptor::TYPE_STRING:
     case FieldDescriptor::TYPE_BYTES: {
-      for (int j = 0; j < count; j++) {
+      for (size_t j = 0; j < count; j++) {
         std::string scratch;
         const std::string& value =
             field->is_repeated()
@@ -1746,3 +1746,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index d42cefb..d4ffbdf 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -59,6 +59,7 @@
 
 namespace google {
 namespace protobuf {
+class MapKey;           // map_field.h
 class UnknownFieldSet;  // unknown_field_set.h
 }  // namespace protobuf
 }  // namespace google
@@ -398,6 +399,12 @@
 size_t ComputeUnknownFieldsSize(const InternalMetadata& metadata, size_t size,
                                 CachedSize* cached_size);
 
+size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
+                              const MapKey& value);
+
+uint8* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field,
+                                      const MapKey& value, uint8* target,
+                                      io::EpsCopyOutputStream* stream);
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 47ad0f1..7af7bf4 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -479,7 +479,7 @@
                                  io::CodedOutputStream* output) {
   // String is for UTF-8 text only
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK_LE(value.size(), kint32max);
+  GOOGLE_CHECK_LE(value.size(), static_cast<size_t>(kint32max));
   output->WriteVarint32(value.size());
   output->WriteString(value);
 }
@@ -488,14 +488,14 @@
                                              io::CodedOutputStream* output) {
   // String is for UTF-8 text only
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK_LE(value.size(), kint32max);
+  GOOGLE_CHECK_LE(value.size(), static_cast<size_t>(kint32max));
   output->WriteVarint32(value.size());
   output->WriteRawMaybeAliased(value.data(), value.size());
 }
 void WireFormatLite::WriteBytes(int field_number, const std::string& value,
                                 io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK_LE(value.size(), kint32max);
+  GOOGLE_CHECK_LE(value.size(), static_cast<size_t>(kint32max));
   output->WriteVarint32(value.size());
   output->WriteString(value);
 }
@@ -503,7 +503,7 @@
                                             const std::string& value,
                                             io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  GOOGLE_CHECK_LE(value.size(), kint32max);
+  GOOGLE_CHECK_LE(value.size(), static_cast<size_t>(kint32max));
   output->WriteVarint32(value.size());
   output->WriteRawMaybeAliased(value.data(), value.size());
 }
@@ -547,7 +547,7 @@
   WriteSubMessageMaybeToArray(size, value, output);
 }
 
-PROTOBUF_ALWAYS_INLINE static bool ReadBytesToString(
+PROTOBUF_NDEBUG_INLINE static bool ReadBytesToString(
     io::CodedInputStream* input, std::string* value);
 inline static bool ReadBytesToString(io::CodedInputStream* input,
                                      std::string* value) {
@@ -603,7 +603,6 @@
 // efficient SSE code.
 template <bool ZigZag, bool SignExtended, typename T>
 static size_t VarintSize(const T* data, const int n) {
-#if __cplusplus >= 201103L
   static_assert(sizeof(T) == 4, "This routine only works for 32 bit integers");
   // is_unsigned<T> => !ZigZag
   static_assert(
@@ -615,7 +614,6 @@
       "Cannot SignExtended unsigned types");
   static_assert(!(SignExtended && ZigZag),
                 "Cannot SignExtended and ZigZag on the same type");
-#endif
   uint32 sum = n;
   uint32 msb_sum = 0;
   for (int i = 0; i < n; i++) {
@@ -640,12 +638,10 @@
 
 template <bool ZigZag, typename T>
 static size_t VarintSize64(const T* data, const int n) {
-#if __cplusplus >= 201103L
   static_assert(sizeof(T) == 8, "This routine only works for 64 bit integers");
   // is_unsigned<T> => !ZigZag
   static_assert(!ZigZag || !std::is_unsigned<T>::value,
                 "Cannot ZigZag encode unsigned types");
-#endif
   uint64 sum = n;
   for (int i = 0; i < n; i++) {
     uint64 x = data[i];
@@ -780,3 +776,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index d022e42..c1abaf1 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -66,13 +66,12 @@
 // #pragma pop_macro("TYPE_BOOL")
 #undef TYPE_BOOL
 
+#include <google/protobuf/port_def.inc>
 
 namespace google {
 namespace protobuf {
 namespace internal {
 
-#include <google/protobuf/port_def.inc>
-
 // This class is for internal use by the protocol buffer library and by
 // protocol-compiler-generated message classes.  It must not be called
 // directly by clients.
@@ -156,9 +155,9 @@
   }
 
   // Number of bits in a tag which identify the wire type.
-  static const int kTagTypeBits = 3;
+  static constexpr int kTagTypeBits = 3;
   // Mask for those bits.
-  static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
+  static constexpr uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
 
   // Helper functions for encoding and decoding tags.  (Inlined below and in
   // _inl.h)
@@ -210,9 +209,9 @@
   //       required string message = 3;
   //     }
   //   }
-  static const int kMessageSetItemNumber = 1;
-  static const int kMessageSetTypeIdNumber = 2;
-  static const int kMessageSetMessageNumber = 3;
+  static constexpr int kMessageSetItemNumber = 1;
+  static constexpr int kMessageSetTypeIdNumber = 2;
+  static constexpr int kMessageSetMessageNumber = 3;
   static const int kMessageSetItemStartTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
       kMessageSetItemNumber, WireFormatLite::WIRETYPE_START_GROUP);
   static const int kMessageSetItemEndTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
@@ -254,14 +253,14 @@
   // the represented type and the FieldType. These are specialized with the
   // appropriate definition for each declared type.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadPrimitive(io::CodedInputStream* input,
+  PROTOBUF_NDEBUG_INLINE static bool ReadPrimitive(io::CodedInputStream* input,
                                                    CType* value);
 
   // Reads repeated primitive values, with optimizations for repeats.
   // tag_size and tag should both be compile-time constants provided by the
   // protocol compiler.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadRepeatedPrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedPrimitive(
       int tag_size, uint32 tag, io::CodedInputStream* input,
       RepeatedField<CType>* value);
 
@@ -278,14 +277,14 @@
   // This is only implemented for the types with fixed wire size, e.g.
   // float, double, and the (s)fixed* types.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static const uint8* ReadPrimitiveFromArray(
+  PROTOBUF_NDEBUG_INLINE static const uint8* ReadPrimitiveFromArray(
       const uint8* buffer, CType* value);
 
   // Reads a primitive packed field.
   //
   // This is only implemented for packable types.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadPackedPrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadPackedPrimitive(
       io::CodedInputStream* input, RepeatedField<CType>* value);
 
   // Identical to ReadPackedPrimitive, except will not inline the
@@ -346,37 +345,37 @@
   // Write a tag.  The Write*() functions typically include the tag, so
   // normally there's no need to call this unless using the Write*NoTag()
   // variants.
-  PROTOBUF_ALWAYS_INLINE static void WriteTag(int field_number, WireType type,
+  PROTOBUF_NDEBUG_INLINE static void WriteTag(int field_number, WireType type,
                                               io::CodedOutputStream* output);
 
   // Write fields, without tags.
-  PROTOBUF_ALWAYS_INLINE static void WriteInt32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteInt32NoTag(
       int32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteInt64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteInt64NoTag(
       int64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteUInt32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteUInt32NoTag(
       uint32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteUInt64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteUInt64NoTag(
       uint64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSInt32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSInt32NoTag(
       int32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSInt64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSInt64NoTag(
       int64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteFixed32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteFixed32NoTag(
       uint32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteFixed64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteFixed64NoTag(
       uint64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSFixed32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSFixed32NoTag(
       int32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSFixed64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSFixed64NoTag(
       int64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteFloatNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteFloatNoTag(
       float value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteDoubleNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteDoubleNoTag(
       double value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteBoolNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteBoolNoTag(
       bool value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteEnumNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteEnumNoTag(
       int value, io::CodedOutputStream* output);
 
   // Write array of primitive fields, without tags
@@ -460,160 +459,160 @@
                                            io::CodedOutputStream* output);
 
   // Like above, but use only *ToArray methods of CodedOutputStream.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteTagToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteTagToArray(int field_number,
                                                        WireType type,
                                                        uint8* target);
 
   // Write fields, without tags.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32NoTagToArray(int32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32NoTagToArray(int32 value,
                                                               uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64NoTagToArray(int64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64NoTagToArray(int64 value,
                                                               uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32NoTagToArray(uint32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32NoTagToArray(uint32 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64NoTagToArray(uint64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64NoTagToArray(uint64 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32NoTagToArray(int32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32NoTagToArray(int32 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64NoTagToArray(int64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64NoTagToArray(int64 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32NoTagToArray(uint32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32NoTagToArray(uint32 value,
                                                                 uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64NoTagToArray(uint64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64NoTagToArray(uint64 value,
                                                                 uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32NoTagToArray(int32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32NoTagToArray(int32 value,
                                                                  uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64NoTagToArray(int64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64NoTagToArray(int64 value,
                                                                  uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatNoTagToArray(float value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatNoTagToArray(float value,
                                                               uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleNoTagToArray(double value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleNoTagToArray(double value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolNoTagToArray(bool value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolNoTagToArray(bool value,
                                                              uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumNoTagToArray(int value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumNoTagToArray(int value,
                                                              uint8* target);
 
   // Write fields, without tags.  These require that value.size() > 0.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static uint8* WritePrimitiveNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WritePrimitiveNoTagToArray(
       const RepeatedField<T>& value, uint8* (*Writer)(T, uint8*),
       uint8* target);
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixedNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixedNoTagToArray(
       const RepeatedField<T>& value, uint8* (*Writer)(T, uint8*),
       uint8* target);
 
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32NoTagToArray(
       const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64NoTagToArray(
       const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32NoTagToArray(
       const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64NoTagToArray(
       const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32NoTagToArray(
       const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64NoTagToArray(
       const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32NoTagToArray(
       const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64NoTagToArray(
       const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32NoTagToArray(
       const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64NoTagToArray(
       const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatNoTagToArray(
       const RepeatedField<float>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleNoTagToArray(
       const RepeatedField<double>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolNoTagToArray(
       const RepeatedField<bool>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumNoTagToArray(
       const RepeatedField<int>& value, uint8* output);
 
   // Write fields, including tags.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32ToArray(int field_number,
                                                          int32 value,
                                                          uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64ToArray(int field_number,
                                                          int64 value,
                                                          uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32ToArray(int field_number,
                                                           uint32 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64ToArray(int field_number,
                                                           uint64 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32ToArray(int field_number,
                                                           int32 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64ToArray(int field_number,
                                                           int64 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32ToArray(int field_number,
                                                            uint32 value,
                                                            uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64ToArray(int field_number,
                                                            uint64 value,
                                                            uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32ToArray(int field_number,
                                                             int32 value,
                                                             uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64ToArray(int field_number,
                                                             int64 value,
                                                             uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatToArray(int field_number,
                                                          float value,
                                                          uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleToArray(int field_number,
                                                           double value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolToArray(int field_number,
                                                         bool value,
                                                         uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumToArray(int field_number,
                                                         int value,
                                                         uint8* target);
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static uint8* WritePrimitiveToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WritePrimitiveToArray(
       int field_number, const RepeatedField<T>& value,
       uint8* (*Writer)(int, T, uint8*), uint8* target);
 
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32ToArray(
       int field_number, const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64ToArray(
       int field_number, const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32ToArray(
       int field_number, const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64ToArray(
       int field_number, const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32ToArray(
       int field_number, const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64ToArray(
       int field_number, const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32ToArray(
       int field_number, const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64ToArray(
       int field_number, const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32ToArray(
       int field_number, const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64ToArray(
       int field_number, const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatToArray(
       int field_number, const RepeatedField<float>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleToArray(
       int field_number, const RepeatedField<double>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolToArray(
       int field_number, const RepeatedField<bool>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumToArray(
       int field_number, const RepeatedField<int>& value, uint8* output);
 
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteStringToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteStringToArray(
       int field_number, const std::string& value, uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBytesToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBytesToArray(
       int field_number, const std::string& value, uint8* target);
 
   // Whether to serialize deterministically (e.g., map keys are
@@ -622,11 +621,11 @@
   // have a CodedOutputStream available, so they get an additional parameter
   // telling them whether to serialize deterministically.
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteGroup(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteGroup(
       int field_number, const MessageType& value, uint8* target,
       io::EpsCopyOutputStream* stream);
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteMessage(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteMessage(
       int field_number, const MessageType& value, uint8* target,
       io::EpsCopyOutputStream* stream);
 
@@ -634,15 +633,15 @@
   // pointer must point at an instance of MessageType, *not* a subclass (or
   // the subclass must not override SerializeWithCachedSizes()).
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteGroupNoVirtualToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteGroupNoVirtualToArray(
       int field_number, const MessageType& value, uint8* target);
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteMessageNoVirtualToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteMessageNoVirtualToArray(
       int field_number, const MessageType& value, uint8* target);
 
   // For backward-compatibility, the last four methods also have versions
   // that are non-deterministic always.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteGroupToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteGroupToArray(
       int field_number, const MessageLite& value, uint8* target) {
     io::EpsCopyOutputStream stream(
         target,
@@ -652,7 +651,7 @@
         io::CodedOutputStream::IsDefaultSerializationDeterministic());
     return InternalWriteGroup(field_number, value, target, &stream);
   }
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteMessageToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteMessageToArray(
       int field_number, const MessageLite& value, uint8* target) {
     int size = value.GetCachedSize();
     io::EpsCopyOutputStream stream(
@@ -685,13 +684,13 @@
   static size_t EnumSize(const RepeatedField<int>& value);
 
   // These types always have the same size.
-  static const size_t kFixed32Size = 4;
-  static const size_t kFixed64Size = 8;
-  static const size_t kSFixed32Size = 4;
-  static const size_t kSFixed64Size = 8;
-  static const size_t kFloatSize = 4;
-  static const size_t kDoubleSize = 8;
-  static const size_t kBoolSize = 1;
+  static constexpr size_t kFixed32Size = 4;
+  static constexpr size_t kFixed64Size = 8;
+  static constexpr size_t kSFixed32Size = 4;
+  static constexpr size_t kSFixed64Size = 8;
+  static constexpr size_t kFloatSize = 4;
+  static constexpr size_t kDoubleSize = 8;
+  static constexpr size_t kBoolSize = 1;
 
   static inline size_t StringSize(const std::string& value);
   static inline size_t BytesSize(const std::string& value);
@@ -718,13 +717,13 @@
   // optimizations for primitive types that have fixed size on the wire, and
   // can be read using potentially faster paths.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadRepeatedFixedSizePrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedFixedSizePrimitive(
       int tag_size, uint32 tag, io::CodedInputStream* input,
       RepeatedField<CType>* value);
 
   // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadPackedFixedSizePrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadPackedFixedSizePrimitive(
       io::CodedInputStream* input, RepeatedField<CType>* value);
 
   static const CppType kFieldTypeToCppTypeMap[];
@@ -1692,7 +1691,7 @@
     int field_number, const MessageType& value, uint8* target,
     io::EpsCopyOutputStream* stream) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
-  target = io::CodedOutputStream::WriteVarint32ToArray(
+  target = io::CodedOutputStream::WriteVarint32ToArrayOutOfLine(
       static_cast<uint32>(value.GetCachedSize()), target);
   return value._InternalSerialize(target, stream);
 }
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 24cb58f..4393066 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -36,8 +36,8 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/test_util.h>
+#include <google/protobuf/test_util2.h>
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_mset.pb.h>
 #include <google/protobuf/unittest_mset_wire_format.pb.h>
@@ -48,12 +48,16 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/wire_format_lite.h>
 #include <google/protobuf/testing/googletest.h>
+#include <google/protobuf/stubs/logging.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/casts.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/stl_util.h>
 
+// clang-format off
 #include <google/protobuf/port_def.inc>
+// clang-format on
 
 namespace google {
 namespace protobuf {
@@ -209,8 +213,16 @@
   source.set_foo_int(100);
   source.set_foo_string("101");
 
-  // Serialize and parse to oneof message.
-  source.SerializeToString(&data);
+  // Serialize and parse to oneof message. Generated serializer may not order
+  // fields in tag order. Use WireFormat::SerializeWithCachedSizes instead as
+  // it sorts fields beforehand.
+  {
+    io::StringOutputStream raw_output(&data);
+    io::CodedOutputStream output(&raw_output);
+    WireFormat::SerializeWithCachedSizes(source, source.ByteSizeLong(),
+                                         &output);
+    ASSERT_FALSE(output.HadError());
+  }
   io::ArrayInputStream raw_input(data.data(), data.size());
   io::CodedInputStream input(&raw_input);
   WireFormat::ParseAndMergePartial(&input, &oneof_dest);
@@ -224,9 +236,9 @@
   unittest::TestAllTypes message;
   TestUtil::SetAllFields(&message);
 
-  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  EXPECT_EQ(message.ByteSizeLong(), WireFormat::ByteSize(message));
   message.Clear();
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
   EXPECT_EQ(0, WireFormat::ByteSize(message));
 }
 
@@ -234,9 +246,9 @@
   unittest::TestAllExtensions message;
   TestUtil::SetAllExtensions(&message);
 
-  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  EXPECT_EQ(message.ByteSizeLong(), WireFormat::ByteSize(message));
   message.Clear();
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
   EXPECT_EQ(0, WireFormat::ByteSize(message));
 }
 
@@ -244,9 +256,9 @@
   unittest::TestPackedTypes message;
   TestUtil::SetPackedFields(&message);
 
-  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  EXPECT_EQ(message.ByteSizeLong(), WireFormat::ByteSize(message));
   message.Clear();
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
   EXPECT_EQ(0, WireFormat::ByteSize(message));
 }
 
@@ -254,9 +266,9 @@
   unittest::TestPackedExtensions message;
   TestUtil::SetPackedExtensions(&message);
 
-  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  EXPECT_EQ(message.ByteSizeLong(), WireFormat::ByteSize(message));
   message.Clear();
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
   EXPECT_EQ(0, WireFormat::ByteSize(message));
 }
 
@@ -264,10 +276,10 @@
   unittest::TestOneof2 message;
   TestUtil::SetOneof1(&message);
 
-  EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
+  EXPECT_EQ(message.ByteSizeLong(), WireFormat::ByteSize(message));
   message.Clear();
 
-  EXPECT_EQ(0, message.ByteSize());
+  EXPECT_EQ(0, message.ByteSizeLong());
   EXPECT_EQ(0, WireFormat::ByteSize(message));
 }
 
@@ -277,7 +289,7 @@
   std::string dynamic_data;
 
   TestUtil::SetAllFields(&message);
-  int size = message.ByteSize();
+  size_t size = message.ByteSizeLong();
 
   // Serialize using the generated code.
   {
@@ -295,10 +307,9 @@
     ASSERT_FALSE(output.HadError());
   }
 
-  // Should be the same.
-  // Don't use EXPECT_EQ here because we're comparing raw binary data and
-  // we really don't want it dumped to stdout on failure.
-  EXPECT_TRUE(dynamic_data == generated_data);
+  // Should parse to the same message.
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, generated_data));
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, dynamic_data));
 }
 
 TEST(WireFormatTest, SerializeExtensions) {
@@ -307,7 +318,7 @@
   std::string dynamic_data;
 
   TestUtil::SetAllExtensions(&message);
-  int size = message.ByteSize();
+  size_t size = message.ByteSizeLong();
 
   // Serialize using the generated code.
   {
@@ -325,10 +336,9 @@
     ASSERT_FALSE(output.HadError());
   }
 
-  // Should be the same.
-  // Don't use EXPECT_EQ here because we're comparing raw binary data and
-  // we really don't want it dumped to stdout on failure.
-  EXPECT_TRUE(dynamic_data == generated_data);
+  // Should parse to the same message.
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, generated_data));
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, dynamic_data));
 }
 
 TEST(WireFormatTest, SerializeFieldsAndExtensions) {
@@ -337,7 +347,7 @@
   std::string dynamic_data;
 
   TestUtil::SetAllFieldsAndExtensions(&message);
-  int size = message.ByteSize();
+  size_t size = message.ByteSizeLong();
 
   // Serialize using the generated code.
   {
@@ -355,14 +365,9 @@
     ASSERT_FALSE(output.HadError());
   }
 
-  // Should be the same.
-  // Don't use EXPECT_EQ here because we're comparing raw binary data and
-  // we really don't want it dumped to stdout on failure.
-  EXPECT_TRUE(dynamic_data == generated_data);
-
-  // Should output in canonical order.
-  TestUtil::ExpectAllFieldsAndExtensionsInOrder(dynamic_data);
-  TestUtil::ExpectAllFieldsAndExtensionsInOrder(generated_data);
+  // Should parse to the same message.
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, generated_data));
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, dynamic_data));
 }
 
 TEST(WireFormatTest, SerializeOneof) {
@@ -371,7 +376,7 @@
   std::string dynamic_data;
 
   TestUtil::SetOneof1(&message);
-  int size = message.ByteSize();
+  size_t size = message.ByteSizeLong();
 
   // Serialize using the generated code.
   {
@@ -389,10 +394,9 @@
     ASSERT_FALSE(output.HadError());
   }
 
-  // Should be the same.
-  // Don't use EXPECT_EQ here because we're comparing raw binary data and
-  // we really don't want it dumped to stdout on failure.
-  EXPECT_TRUE(dynamic_data == generated_data);
+  // Should parse to the same message.
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, generated_data));
+  EXPECT_TRUE(TestUtil::EqualsToSerialized(message, dynamic_data));
 }
 
 TEST(WireFormatTest, ParseMultipleExtensionRanges) {
@@ -482,7 +486,7 @@
   message_set.mutable_unknown_fields()->AddLengthDelimited(kUnknownTypeId,
                                                            "bar");
 
-  int size = message_set.ByteSize();
+  size_t size = message_set.ByteSizeLong();
   EXPECT_EQ(size, message_set.GetCachedSize());
   ASSERT_EQ(size, WireFormat::ByteSize(message_set));
 
@@ -595,7 +599,7 @@
     WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber,
                              WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
                              &coded_output);
-    coded_output.WriteVarint32(message.ByteSize());
+    coded_output.WriteVarint32(message.ByteSizeLong());
     message.SerializeWithCachedSizes(&coded_output);
     // Write the type id.
     uint32 type_id = message.GetDescriptor()->extension(0)->number();
@@ -637,7 +641,7 @@
                            io::CodedOutputStream* coded_output) {
   WireFormatLite::WriteTag(15,  // i
                            WireFormatLite::WIRETYPE_VARINT, coded_output);
-  coded_output->WriteVarint32(message.i());
+  coded_output->WriteVarint64(message.i());
   WireFormatLite::WriteTag(16,  // recursive
                            WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
                            coded_output);
@@ -688,6 +692,66 @@
   EXPECT_FALSE(message_set.ParseFromString(data));
 }
 
+TEST(WireFormatTest, ParseFailMalformedMessageSet) {
+  constexpr int kDepth = 5;
+  std::string data;
+  {
+    proto2_wireformat_unittest::TestMessageSet message_set;
+    proto2_wireformat_unittest::TestMessageSet* mset = &message_set;
+    for (int i = 0; i < kDepth; i++) {
+      auto m = mset->MutableExtension(
+          unittest::TestMessageSetExtension1::message_set_extension);
+      m->set_i(i);
+      mset = m->mutable_recursive();
+    }
+    auto m = mset->MutableExtension(
+        unittest::TestMessageSetExtension1::message_set_extension);
+    // -1 becomes \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1
+    m->set_i(-1);
+
+    EXPECT_TRUE(message_set.SerializeToString(&data));
+    // Make the proto mal-formed.
+    data[data.size() - 2 - kDepth] = 0xFF;
+  }
+
+  proto2_wireformat_unittest::TestMessageSet message_set;
+  EXPECT_FALSE(message_set.ParseFromString(data));
+}
+
+TEST(WireFormatTest, ParseFailMalformedMessageSetReverseOrder) {
+  constexpr int kDepth = 5;
+  std::string data;
+  {
+    proto2_wireformat_unittest::TestMessageSet message_set;
+    proto2_wireformat_unittest::TestMessageSet* mset = &message_set;
+    for (int i = 0; i < kDepth; i++) {
+      auto m = mset->MutableExtension(
+          unittest::TestMessageSetExtension1::message_set_extension);
+      m->set_i(i);
+      mset = m->mutable_recursive();
+    }
+    auto m = mset->MutableExtension(
+        unittest::TestMessageSetExtension1::message_set_extension);
+    // -1 becomes \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1
+    m->set_i(-1);
+    // SerializeReverseOrder() assumes "recursive" is always present.
+    m->mutable_recursive();
+
+    message_set.ByteSizeLong();
+
+    // Serialize with reverse payload tag order
+    io::StringOutputStream output_stream(&data);
+    io::CodedOutputStream coded_output(&output_stream);
+    SerializeReverseOrder(message_set, &coded_output);
+  }
+
+  // Make varint for -1 malformed.
+  data[data.size() - 5 * (kDepth + 1) - 4] = 0xFF;
+
+  proto2_wireformat_unittest::TestMessageSet message_set;
+  EXPECT_FALSE(message_set.ParseFromString(data));
+}
+
 TEST(WireFormatTest, ParseBrokenMessageSet) {
   proto2_wireformat_unittest::TestMessageSet message_set;
   std::string input("goodbye");  // Invalid wire format data.
@@ -747,8 +811,8 @@
 
 TEST(WireFormatTest, ZigZag) {
 // avoid line-wrapping
-#define LL(x) PROTOBUF_LONGLONG(x)
-#define ULL(x) PROTOBUF_ULONGLONG(x)
+#define LL(x) static_cast<int64_t>(ULL(x))
+#define ULL(x) uint64_t{x##u}
 #define ZigZagEncode32(x) WireFormatLite::ZigZagEncode32(x)
 #define ZigZagDecode32(x) WireFormatLite::ZigZagDecode32(x)
 #define ZigZagEncode64(x) WireFormatLite::ZigZagEncode64(x)
@@ -989,7 +1053,7 @@
   void TestSerialization(Proto* message, const std::string& expected) {
     SetProto3PrimitiveRepeatedFields(message);
 
-    int size = message->ByteSize();
+    size_t size = message->ByteSizeLong();
 
     // Serialize using the generated code.
     std::string generated_data;
@@ -999,7 +1063,7 @@
       message->SerializeWithCachedSizes(&output);
       ASSERT_FALSE(output.HadError());
     }
-    EXPECT_TRUE(expected == generated_data);
+    EXPECT_TRUE(TestUtil::EqualsToSerialized(*message, generated_data));
 
     // Serialize using the dynamic code.
     std::string dynamic_data;
@@ -1522,3 +1586,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index be039b4..9987581 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -14,170 +14,118 @@
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class DoubleValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DoubleValue> _instance;
-} _DoubleValue_default_instance_;
-class FloatValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FloatValue> _instance;
-} _FloatValue_default_instance_;
-class Int64ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Int64Value> _instance;
-} _Int64Value_default_instance_;
-class UInt64ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UInt64Value> _instance;
-} _UInt64Value_default_instance_;
-class Int32ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Int32Value> _instance;
-} _Int32Value_default_instance_;
-class UInt32ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UInt32Value> _instance;
-} _UInt32Value_default_instance_;
-class BoolValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<BoolValue> _instance;
-} _BoolValue_default_instance_;
-class StringValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<StringValue> _instance;
-} _StringValue_default_instance_;
-class BytesValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<BytesValue> _instance;
-} _BytesValue_default_instance_;
+constexpr DoubleValue::DoubleValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0){}
+struct DoubleValueDefaultTypeInternal {
+  constexpr DoubleValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DoubleValueDefaultTypeInternal() {}
+  union {
+    DoubleValue _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DoubleValueDefaultTypeInternal _DoubleValue_default_instance_;
+constexpr FloatValue::FloatValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0){}
+struct FloatValueDefaultTypeInternal {
+  constexpr FloatValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FloatValueDefaultTypeInternal() {}
+  union {
+    FloatValue _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FloatValueDefaultTypeInternal _FloatValue_default_instance_;
+constexpr Int64Value::Int64Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(int64_t{0}){}
+struct Int64ValueDefaultTypeInternal {
+  constexpr Int64ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~Int64ValueDefaultTypeInternal() {}
+  union {
+    Int64Value _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT Int64ValueDefaultTypeInternal _Int64Value_default_instance_;
+constexpr UInt64Value::UInt64Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(uint64_t{0u}){}
+struct UInt64ValueDefaultTypeInternal {
+  constexpr UInt64ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UInt64ValueDefaultTypeInternal() {}
+  union {
+    UInt64Value _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_;
+constexpr Int32Value::Int32Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0){}
+struct Int32ValueDefaultTypeInternal {
+  constexpr Int32ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~Int32ValueDefaultTypeInternal() {}
+  union {
+    Int32Value _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT Int32ValueDefaultTypeInternal _Int32Value_default_instance_;
+constexpr UInt32Value::UInt32Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0u){}
+struct UInt32ValueDefaultTypeInternal {
+  constexpr UInt32ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UInt32ValueDefaultTypeInternal() {}
+  union {
+    UInt32Value _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_;
+constexpr BoolValue::BoolValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(false){}
+struct BoolValueDefaultTypeInternal {
+  constexpr BoolValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~BoolValueDefaultTypeInternal() {}
+  union {
+    BoolValue _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT BoolValueDefaultTypeInternal _BoolValue_default_instance_;
+constexpr StringValue::StringValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct StringValueDefaultTypeInternal {
+  constexpr StringValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~StringValueDefaultTypeInternal() {}
+  union {
+    StringValue _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT StringValueDefaultTypeInternal _StringValue_default_instance_;
+constexpr BytesValue::BytesValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct BytesValueDefaultTypeInternal {
+  constexpr BytesValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~BytesValueDefaultTypeInternal() {}
+  union {
+    BytesValue _instance;
+  };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT BytesValueDefaultTypeInternal _BytesValue_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_BoolValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::BoolValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::BoolValue::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_BytesValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::BytesValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::BytesValue::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DoubleValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DoubleValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::DoubleValue::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FloatValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FloatValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::FloatValue::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Int32Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Int32Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Int32Value::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Int64Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Int64Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::Int64Value::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_StringValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::StringValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::StringValue::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UInt32Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UInt32Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::UInt32Value::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UInt64Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UInt64Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  PROTOBUF_NAMESPACE_ID::UInt64Value::InitAsDefaultInstance();
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[9];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
@@ -270,49 +218,40 @@
   "e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013"
   "UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022"
   "\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001"
-  " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B|\n\023com"
-  ".google.protobufB\rWrappersProtoP\001Z*githu"
-  "b.com/golang/protobuf/ptypes/wrappers\370\001\001"
-  "\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb"
-  "\006proto3"
+  " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B\203\001\n\023co"
+  "m.google.protobufB\rWrappersProtoP\001Z1goog"
+  "le.golang.org/protobuf/types/known/wrapp"
+  "erspb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKno"
+  "wnTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fwrappers_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fwrappers_2eproto_sccs[9] = {
-  &scc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto, "google/protobuf/wrappers.proto", 447,
-  &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, descriptor_table_google_2fprotobuf_2fwrappers_2eproto_sccs, descriptor_table_google_2fprotobuf_2fwrappers_2eproto_deps, 9, 0,
+  false, false, 455, descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto, "google/protobuf/wrappers.proto", 
+  &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, nullptr, 0, 9,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fwrappers_2eproto, 9, file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto, file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto,
+  file_level_metadata_google_2fprotobuf_2fwrappers_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto, file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fwrappers_2eproto;
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
-static bool dynamic_init_dummy_google_2fprotobuf_2fwrappers_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto)), true);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fwrappers_2eproto(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
-void DoubleValue::InitAsDefaultInstance() {
-}
 class DoubleValue::_Internal {
  public:
 };
 
-DoubleValue::DoubleValue(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+DoubleValue::DoubleValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.DoubleValue)
 }
 DoubleValue::DoubleValue(const DoubleValue& from)
@@ -322,18 +261,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DoubleValue)
 }
 
-void DoubleValue::SharedCtor() {
-  value_ = 0;
+inline void DoubleValue::SharedCtor() {
+value_ = 0;
 }
 
 DoubleValue::~DoubleValue() {
   // @@protoc_insertion_point(destructor:google.protobuf.DoubleValue)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void DoubleValue::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void DoubleValue::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void DoubleValue::ArenaDtor(void* object) {
@@ -345,11 +285,6 @@
 void DoubleValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DoubleValue& DoubleValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DoubleValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue)
@@ -363,11 +298,9 @@
 
 const char* DoubleValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // double value = 1;
       case 1:
@@ -378,7 +311,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -405,7 +339,7 @@
   (void) cached_has_bits;
 
   // double value = 1;
-  if (!(this->value() <= 0 && this->value() >= 0)) {
+  if (!(this->_internal_value() <= 0 && this->_internal_value() >= 0)) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteDoubleToArray(1, this->_internal_value(), target);
   }
@@ -427,7 +361,7 @@
   (void) cached_has_bits;
 
   // double value = 1;
-  if (!(this->value() <= 0 && this->value() >= 0)) {
+  if (!(this->_internal_value() <= 0 && this->_internal_value() >= 0)) {
     total_size += 1 + 8;
   }
 
@@ -440,38 +374,29 @@
   return total_size;
 }
 
-void DoubleValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DoubleValue)
-  GOOGLE_DCHECK_NE(&from, this);
-  const DoubleValue* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<DoubleValue>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DoubleValue)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DoubleValue)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DoubleValue::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    DoubleValue::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DoubleValue::GetClassData() const { return &_class_data_; }
+
+void DoubleValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<DoubleValue *>(to)->MergeFrom(
+      static_cast<const DoubleValue &>(from));
 }
 
+
 void DoubleValue::MergeFrom(const DoubleValue& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (!(from.value() <= 0 && from.value() >= 0)) {
+  if (!(from._internal_value() <= 0 && from._internal_value() >= 0)) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void DoubleValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DoubleValue)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void DoubleValue::CopyFrom(const DoubleValue& from) {
@@ -487,27 +412,29 @@
 
 void DoubleValue::InternalSwap(DoubleValue* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DoubleValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[0]);
 }
 
-
 // ===================================================================
 
-void FloatValue::InitAsDefaultInstance() {
-}
 class FloatValue::_Internal {
  public:
 };
 
-FloatValue::FloatValue(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+FloatValue::FloatValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FloatValue)
 }
 FloatValue::FloatValue(const FloatValue& from)
@@ -517,18 +444,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FloatValue)
 }
 
-void FloatValue::SharedCtor() {
-  value_ = 0;
+inline void FloatValue::SharedCtor() {
+value_ = 0;
 }
 
 FloatValue::~FloatValue() {
   // @@protoc_insertion_point(destructor:google.protobuf.FloatValue)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void FloatValue::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void FloatValue::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void FloatValue::ArenaDtor(void* object) {
@@ -540,11 +468,6 @@
 void FloatValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FloatValue& FloatValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FloatValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue)
@@ -558,11 +481,9 @@
 
 const char* FloatValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // float value = 1;
       case 1:
@@ -573,7 +494,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -600,7 +522,7 @@
   (void) cached_has_bits;
 
   // float value = 1;
-  if (!(this->value() <= 0 && this->value() >= 0)) {
+  if (!(this->_internal_value() <= 0 && this->_internal_value() >= 0)) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(1, this->_internal_value(), target);
   }
@@ -622,7 +544,7 @@
   (void) cached_has_bits;
 
   // float value = 1;
-  if (!(this->value() <= 0 && this->value() >= 0)) {
+  if (!(this->_internal_value() <= 0 && this->_internal_value() >= 0)) {
     total_size += 1 + 4;
   }
 
@@ -635,38 +557,29 @@
   return total_size;
 }
 
-void FloatValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FloatValue)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FloatValue* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<FloatValue>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FloatValue)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FloatValue)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FloatValue::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    FloatValue::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FloatValue::GetClassData() const { return &_class_data_; }
+
+void FloatValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<FloatValue *>(to)->MergeFrom(
+      static_cast<const FloatValue &>(from));
 }
 
+
 void FloatValue::MergeFrom(const FloatValue& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (!(from.value() <= 0 && from.value() >= 0)) {
+  if (!(from._internal_value() <= 0 && from._internal_value() >= 0)) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void FloatValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FloatValue)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void FloatValue::CopyFrom(const FloatValue& from) {
@@ -682,27 +595,29 @@
 
 void FloatValue::InternalSwap(FloatValue* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FloatValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[1]);
 }
 
-
 // ===================================================================
 
-void Int64Value::InitAsDefaultInstance() {
-}
 class Int64Value::_Internal {
  public:
 };
 
-Int64Value::Int64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Int64Value::Int64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Int64Value)
 }
 Int64Value::Int64Value(const Int64Value& from)
@@ -712,18 +627,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Int64Value)
 }
 
-void Int64Value::SharedCtor() {
-  value_ = PROTOBUF_LONGLONG(0);
+inline void Int64Value::SharedCtor() {
+value_ = int64_t{0};
 }
 
 Int64Value::~Int64Value() {
   // @@protoc_insertion_point(destructor:google.protobuf.Int64Value)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Int64Value::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Int64Value::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void Int64Value::ArenaDtor(void* object) {
@@ -735,11 +651,6 @@
 void Int64Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Int64Value& Int64Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Int64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value)
@@ -747,17 +658,15 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  value_ = PROTOBUF_LONGLONG(0);
+  value_ = int64_t{0};
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Int64Value::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int64 value = 1;
       case 1:
@@ -768,7 +677,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -795,7 +705,7 @@
   (void) cached_has_bits;
 
   // int64 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->_internal_value(), target);
   }
@@ -817,7 +727,7 @@
   (void) cached_has_bits;
 
   // int64 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size(
         this->_internal_value());
@@ -832,38 +742,29 @@
   return total_size;
 }
 
-void Int64Value::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int64Value)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Int64Value* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Int64Value>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int64Value)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int64Value)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Int64Value::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Int64Value::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Int64Value::GetClassData() const { return &_class_data_; }
+
+void Int64Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Int64Value *>(to)->MergeFrom(
+      static_cast<const Int64Value &>(from));
 }
 
+
 void Int64Value::MergeFrom(const Int64Value& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.value() != 0) {
+  if (from._internal_value() != 0) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void Int64Value::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int64Value)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Int64Value::CopyFrom(const Int64Value& from) {
@@ -879,27 +780,29 @@
 
 void Int64Value::InternalSwap(Int64Value* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Int64Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[2]);
 }
 
-
 // ===================================================================
 
-void UInt64Value::InitAsDefaultInstance() {
-}
 class UInt64Value::_Internal {
  public:
 };
 
-UInt64Value::UInt64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+UInt64Value::UInt64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt64Value)
 }
 UInt64Value::UInt64Value(const UInt64Value& from)
@@ -909,18 +812,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt64Value)
 }
 
-void UInt64Value::SharedCtor() {
-  value_ = PROTOBUF_ULONGLONG(0);
+inline void UInt64Value::SharedCtor() {
+value_ = uint64_t{0u};
 }
 
 UInt64Value::~UInt64Value() {
   // @@protoc_insertion_point(destructor:google.protobuf.UInt64Value)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void UInt64Value::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void UInt64Value::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void UInt64Value::ArenaDtor(void* object) {
@@ -932,11 +836,6 @@
 void UInt64Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UInt64Value& UInt64Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UInt64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value)
@@ -944,17 +843,15 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  value_ = PROTOBUF_ULONGLONG(0);
+  value_ = uint64_t{0u};
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* UInt64Value::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // uint64 value = 1;
       case 1:
@@ -965,7 +862,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -992,7 +890,7 @@
   (void) cached_has_bits;
 
   // uint64 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(1, this->_internal_value(), target);
   }
@@ -1014,7 +912,7 @@
   (void) cached_has_bits;
 
   // uint64 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size(
         this->_internal_value());
@@ -1029,38 +927,29 @@
   return total_size;
 }
 
-void UInt64Value::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt64Value)
-  GOOGLE_DCHECK_NE(&from, this);
-  const UInt64Value* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<UInt64Value>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt64Value)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt64Value)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UInt64Value::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    UInt64Value::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UInt64Value::GetClassData() const { return &_class_data_; }
+
+void UInt64Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<UInt64Value *>(to)->MergeFrom(
+      static_cast<const UInt64Value &>(from));
 }
 
+
 void UInt64Value::MergeFrom(const UInt64Value& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.value() != 0) {
+  if (from._internal_value() != 0) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void UInt64Value::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt64Value)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void UInt64Value::CopyFrom(const UInt64Value& from) {
@@ -1076,27 +965,29 @@
 
 void UInt64Value::InternalSwap(UInt64Value* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UInt64Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[3]);
 }
 
-
 // ===================================================================
 
-void Int32Value::InitAsDefaultInstance() {
-}
 class Int32Value::_Internal {
  public:
 };
 
-Int32Value::Int32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+Int32Value::Int32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Int32Value)
 }
 Int32Value::Int32Value(const Int32Value& from)
@@ -1106,18 +997,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Int32Value)
 }
 
-void Int32Value::SharedCtor() {
-  value_ = 0;
+inline void Int32Value::SharedCtor() {
+value_ = 0;
 }
 
 Int32Value::~Int32Value() {
   // @@protoc_insertion_point(destructor:google.protobuf.Int32Value)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void Int32Value::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void Int32Value::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void Int32Value::ArenaDtor(void* object) {
@@ -1129,11 +1021,6 @@
 void Int32Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Int32Value& Int32Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Int32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value)
@@ -1147,11 +1034,9 @@
 
 const char* Int32Value::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int32 value = 1;
       case 1:
@@ -1162,7 +1047,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1189,7 +1075,7 @@
   (void) cached_has_bits;
 
   // int32 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_value(), target);
   }
@@ -1211,7 +1097,7 @@
   (void) cached_has_bits;
 
   // int32 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size(
         this->_internal_value());
@@ -1226,38 +1112,29 @@
   return total_size;
 }
 
-void Int32Value::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int32Value)
-  GOOGLE_DCHECK_NE(&from, this);
-  const Int32Value* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Int32Value>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int32Value)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int32Value)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Int32Value::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    Int32Value::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Int32Value::GetClassData() const { return &_class_data_; }
+
+void Int32Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<Int32Value *>(to)->MergeFrom(
+      static_cast<const Int32Value &>(from));
 }
 
+
 void Int32Value::MergeFrom(const Int32Value& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.value() != 0) {
+  if (from._internal_value() != 0) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void Int32Value::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int32Value)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void Int32Value::CopyFrom(const Int32Value& from) {
@@ -1273,27 +1150,29 @@
 
 void Int32Value::InternalSwap(Int32Value* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Int32Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[4]);
 }
 
-
 // ===================================================================
 
-void UInt32Value::InitAsDefaultInstance() {
-}
 class UInt32Value::_Internal {
  public:
 };
 
-UInt32Value::UInt32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+UInt32Value::UInt32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt32Value)
 }
 UInt32Value::UInt32Value(const UInt32Value& from)
@@ -1303,18 +1182,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt32Value)
 }
 
-void UInt32Value::SharedCtor() {
-  value_ = 0u;
+inline void UInt32Value::SharedCtor() {
+value_ = 0u;
 }
 
 UInt32Value::~UInt32Value() {
   // @@protoc_insertion_point(destructor:google.protobuf.UInt32Value)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void UInt32Value::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void UInt32Value::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void UInt32Value::ArenaDtor(void* object) {
@@ -1326,11 +1206,6 @@
 void UInt32Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UInt32Value& UInt32Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UInt32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value)
@@ -1344,11 +1219,9 @@
 
 const char* UInt32Value::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // uint32 value = 1;
       case 1:
@@ -1359,7 +1232,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1386,7 +1260,7 @@
   (void) cached_has_bits;
 
   // uint32 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_value(), target);
   }
@@ -1408,7 +1282,7 @@
   (void) cached_has_bits;
 
   // uint32 value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32Size(
         this->_internal_value());
@@ -1423,38 +1297,29 @@
   return total_size;
 }
 
-void UInt32Value::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt32Value)
-  GOOGLE_DCHECK_NE(&from, this);
-  const UInt32Value* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<UInt32Value>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt32Value)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt32Value)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UInt32Value::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    UInt32Value::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UInt32Value::GetClassData() const { return &_class_data_; }
+
+void UInt32Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<UInt32Value *>(to)->MergeFrom(
+      static_cast<const UInt32Value &>(from));
 }
 
+
 void UInt32Value::MergeFrom(const UInt32Value& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.value() != 0) {
+  if (from._internal_value() != 0) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void UInt32Value::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt32Value)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void UInt32Value::CopyFrom(const UInt32Value& from) {
@@ -1470,27 +1335,29 @@
 
 void UInt32Value::InternalSwap(UInt32Value* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UInt32Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[5]);
 }
 
-
 // ===================================================================
 
-void BoolValue::InitAsDefaultInstance() {
-}
 class BoolValue::_Internal {
  public:
 };
 
-BoolValue::BoolValue(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+BoolValue::BoolValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.BoolValue)
 }
 BoolValue::BoolValue(const BoolValue& from)
@@ -1500,18 +1367,19 @@
   // @@protoc_insertion_point(copy_constructor:google.protobuf.BoolValue)
 }
 
-void BoolValue::SharedCtor() {
-  value_ = false;
+inline void BoolValue::SharedCtor() {
+value_ = false;
 }
 
 BoolValue::~BoolValue() {
   // @@protoc_insertion_point(destructor:google.protobuf.BoolValue)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void BoolValue::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void BoolValue::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
 }
 
 void BoolValue::ArenaDtor(void* object) {
@@ -1523,11 +1391,6 @@
 void BoolValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const BoolValue& BoolValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void BoolValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue)
@@ -1541,11 +1404,9 @@
 
 const char* BoolValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // bool value = 1;
       case 1:
@@ -1556,7 +1417,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1583,7 +1445,7 @@
   (void) cached_has_bits;
 
   // bool value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     target = stream->EnsureSpace(target);
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(1, this->_internal_value(), target);
   }
@@ -1605,7 +1467,7 @@
   (void) cached_has_bits;
 
   // bool value = 1;
-  if (this->value() != 0) {
+  if (this->_internal_value() != 0) {
     total_size += 1 + 1;
   }
 
@@ -1618,38 +1480,29 @@
   return total_size;
 }
 
-void BoolValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BoolValue)
-  GOOGLE_DCHECK_NE(&from, this);
-  const BoolValue* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<BoolValue>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BoolValue)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BoolValue)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData BoolValue::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    BoolValue::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*BoolValue::GetClassData() const { return &_class_data_; }
+
+void BoolValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<BoolValue *>(to)->MergeFrom(
+      static_cast<const BoolValue &>(from));
 }
 
+
 void BoolValue::MergeFrom(const BoolValue& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.value() != 0) {
+  if (from._internal_value() != 0) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void BoolValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BoolValue)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void BoolValue::CopyFrom(const BoolValue& from) {
@@ -1665,27 +1518,29 @@
 
 void BoolValue::InternalSwap(BoolValue* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
   swap(value_, other->value_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata BoolValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[6]);
 }
 
-
 // ===================================================================
 
-void StringValue::InitAsDefaultInstance() {
-}
 class StringValue::_Internal {
  public:
 };
 
-StringValue::StringValue(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+StringValue::StringValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.StringValue)
 }
 StringValue::StringValue(const StringValue& from)
@@ -1693,25 +1548,25 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_value().empty()) {
-    value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_value(),
-      GetArena());
+    value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(), 
+      GetArenaForAllocation());
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.StringValue)
 }
 
-void StringValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+inline void StringValue::SharedCtor() {
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 StringValue::~StringValue() {
   // @@protoc_insertion_point(destructor:google.protobuf.StringValue)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void StringValue::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void StringValue::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -1724,11 +1579,6 @@
 void StringValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const StringValue& StringValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void StringValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue)
@@ -1736,17 +1586,15 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  value_.ClearToEmpty();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* StringValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string value = 1;
       case 1:
@@ -1759,7 +1607,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1786,7 +1635,7 @@
   (void) cached_has_bits;
 
   // string value = 1;
-  if (this->value().size() > 0) {
+  if (!this->_internal_value().empty()) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_value().data(), static_cast<int>(this->_internal_value().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -1812,7 +1661,7 @@
   (void) cached_has_bits;
 
   // string value = 1;
-  if (this->value().size() > 0) {
+  if (!this->_internal_value().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_value());
@@ -1827,38 +1676,29 @@
   return total_size;
 }
 
-void StringValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.StringValue)
-  GOOGLE_DCHECK_NE(&from, this);
-  const StringValue* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<StringValue>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.StringValue)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.StringValue)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData StringValue::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    StringValue::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*StringValue::GetClassData() const { return &_class_data_; }
+
+void StringValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<StringValue *>(to)->MergeFrom(
+      static_cast<const StringValue &>(from));
 }
 
+
 void StringValue::MergeFrom(const StringValue& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.value().size() > 0) {
+  if (!from._internal_value().empty()) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void StringValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.StringValue)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void StringValue::CopyFrom(const StringValue& from) {
@@ -1874,27 +1714,33 @@
 
 void StringValue::InternalSwap(StringValue* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &value_, GetArenaForAllocation(),
+      &other->value_, other->GetArenaForAllocation()
+  );
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata StringValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[7]);
 }
 
-
 // ===================================================================
 
-void BytesValue::InitAsDefaultInstance() {
-}
 class BytesValue::_Internal {
  public:
 };
 
-BytesValue::BytesValue(::PROTOBUF_NAMESPACE_ID::Arena* arena)
-  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+BytesValue::BytesValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                         bool is_message_owned)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
   SharedCtor();
-  RegisterArenaDtor(arena);
+  if (!is_message_owned) {
+    RegisterArenaDtor(arena);
+  }
   // @@protoc_insertion_point(arena_constructor:google.protobuf.BytesValue)
 }
 BytesValue::BytesValue(const BytesValue& from)
@@ -1902,25 +1748,25 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
   if (!from._internal_value().empty()) {
-    value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_value(),
-      GetArena());
+    value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(), 
+      GetArenaForAllocation());
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.BytesValue)
 }
 
-void BytesValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+inline void BytesValue::SharedCtor() {
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 BytesValue::~BytesValue() {
   // @@protoc_insertion_point(destructor:google.protobuf.BytesValue)
+  if (GetArenaForAllocation() != nullptr) return;
   SharedDtor();
   _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
-void BytesValue::SharedDtor() {
-  GOOGLE_DCHECK(GetArena() == nullptr);
+inline void BytesValue::SharedDtor() {
+  GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
   value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
@@ -1933,11 +1779,6 @@
 void BytesValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const BytesValue& BytesValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void BytesValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue)
@@ -1945,17 +1786,15 @@
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  value_.ClearToEmpty();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* BytesValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
-  ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena;
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // bytes value = 1;
       case 1:
@@ -1967,7 +1806,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1994,7 +1834,7 @@
   (void) cached_has_bits;
 
   // bytes value = 1;
-  if (this->value().size() > 0) {
+  if (!this->_internal_value().empty()) {
     target = stream->WriteBytesMaybeAliased(
         1, this->_internal_value(), target);
   }
@@ -2016,7 +1856,7 @@
   (void) cached_has_bits;
 
   // bytes value = 1;
-  if (this->value().size() > 0) {
+  if (!this->_internal_value().empty()) {
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
         this->_internal_value());
@@ -2031,38 +1871,29 @@
   return total_size;
 }
 
-void BytesValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BytesValue)
-  GOOGLE_DCHECK_NE(&from, this);
-  const BytesValue* source =
-      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<BytesValue>(
-          &from);
-  if (source == nullptr) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BytesValue)
-    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BytesValue)
-    MergeFrom(*source);
-  }
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData BytesValue::_class_data_ = {
+    ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+    BytesValue::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*BytesValue::GetClassData() const { return &_class_data_; }
+
+void BytesValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to,
+                      const ::PROTOBUF_NAMESPACE_ID::Message&from) {
+  static_cast<BytesValue *>(to)->MergeFrom(
+      static_cast<const BytesValue &>(from));
 }
 
+
 void BytesValue::MergeFrom(const BytesValue& from) {
 // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue)
   GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
-  if (from.value().size() > 0) {
+  if (!from._internal_value().empty()) {
     _internal_set_value(from._internal_value());
   }
-}
-
-void BytesValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BytesValue)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
 }
 
 void BytesValue::CopyFrom(const BytesValue& from) {
@@ -2078,15 +1909,20 @@
 
 void BytesValue::InternalSwap(BytesValue* other) {
   using std::swap;
-  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
-  value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+      &value_, GetArenaForAllocation(),
+      &other->value_, other->GetArenaForAllocation()
+  );
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata BytesValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[8]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index 7a1cc4d..1be7ae0 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <google/protobuf/port_def.inc>
-#if PROTOBUF_VERSION < 3011000
+#if PROTOBUF_VERSION < 3017000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3017003 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -25,7 +25,6 @@
 #include <google/protobuf/arenastring.h>
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata_lite.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message.h>
@@ -45,7 +44,7 @@
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fwrappers_2eproto {
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
-  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[]
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
   static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[9]
     PROTOBUF_SECTION_VARIABLE(protodesc_cold);
@@ -53,34 +52,34 @@
   static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
-extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto;
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 class BoolValue;
-class BoolValueDefaultTypeInternal;
+struct BoolValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern BoolValueDefaultTypeInternal _BoolValue_default_instance_;
 class BytesValue;
-class BytesValueDefaultTypeInternal;
+struct BytesValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern BytesValueDefaultTypeInternal _BytesValue_default_instance_;
 class DoubleValue;
-class DoubleValueDefaultTypeInternal;
+struct DoubleValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern DoubleValueDefaultTypeInternal _DoubleValue_default_instance_;
 class FloatValue;
-class FloatValueDefaultTypeInternal;
+struct FloatValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern FloatValueDefaultTypeInternal _FloatValue_default_instance_;
 class Int32Value;
-class Int32ValueDefaultTypeInternal;
+struct Int32ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern Int32ValueDefaultTypeInternal _Int32Value_default_instance_;
 class Int64Value;
-class Int64ValueDefaultTypeInternal;
+struct Int64ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern Int64ValueDefaultTypeInternal _Int64Value_default_instance_;
 class StringValue;
-class StringValueDefaultTypeInternal;
+struct StringValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern StringValueDefaultTypeInternal _StringValue_default_instance_;
 class UInt32Value;
-class UInt32ValueDefaultTypeInternal;
+struct UInt32ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_;
 class UInt64Value;
-class UInt64ValueDefaultTypeInternal;
+struct UInt64ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -98,11 +97,12 @@
 
 // ===================================================================
 
-class PROTOBUF_EXPORT DoubleValue PROTOBUF_FINAL :
+class PROTOBUF_EXPORT DoubleValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DoubleValue) */ {
  public:
-  inline DoubleValue() : DoubleValue(nullptr) {};
-  virtual ~DoubleValue();
+  inline DoubleValue() : DoubleValue(nullptr) {}
+  ~DoubleValue() override;
+  explicit constexpr DoubleValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DoubleValue(const DoubleValue& from);
   DoubleValue(DoubleValue&& from) noexcept
@@ -115,8 +115,9 @@
     return *this;
   }
   inline DoubleValue& operator=(DoubleValue&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -127,14 +128,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const DoubleValue& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const DoubleValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DoubleValue* internal_default_instance() {
     return reinterpret_cast<const DoubleValue*>(
                &_DoubleValue_default_instance_);
@@ -147,7 +148,7 @@
   }
   inline void Swap(DoubleValue* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -155,23 +156,26 @@
   }
   void UnsafeArenaSwap(DoubleValue* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline DoubleValue* New() const final {
-    return CreateMaybeMessage<DoubleValue>(nullptr);
+    return new DoubleValue();
   }
 
   DoubleValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<DoubleValue>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const DoubleValue& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const DoubleValue& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -182,8 +186,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(DoubleValue* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -191,20 +195,17 @@
     return "google.protobuf.DoubleValue";
   }
   protected:
-  explicit DoubleValue(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit DoubleValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -235,11 +236,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT FloatValue PROTOBUF_FINAL :
+class PROTOBUF_EXPORT FloatValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FloatValue) */ {
  public:
-  inline FloatValue() : FloatValue(nullptr) {};
-  virtual ~FloatValue();
+  inline FloatValue() : FloatValue(nullptr) {}
+  ~FloatValue() override;
+  explicit constexpr FloatValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FloatValue(const FloatValue& from);
   FloatValue(FloatValue&& from) noexcept
@@ -252,8 +254,9 @@
     return *this;
   }
   inline FloatValue& operator=(FloatValue&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -264,14 +267,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const FloatValue& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const FloatValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FloatValue* internal_default_instance() {
     return reinterpret_cast<const FloatValue*>(
                &_FloatValue_default_instance_);
@@ -284,7 +287,7 @@
   }
   inline void Swap(FloatValue* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -292,23 +295,26 @@
   }
   void UnsafeArenaSwap(FloatValue* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline FloatValue* New() const final {
-    return CreateMaybeMessage<FloatValue>(nullptr);
+    return new FloatValue();
   }
 
   FloatValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<FloatValue>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const FloatValue& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const FloatValue& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -319,8 +325,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(FloatValue* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -328,20 +334,17 @@
     return "google.protobuf.FloatValue";
   }
   protected:
-  explicit FloatValue(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit FloatValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -372,11 +375,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Int64Value PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Int64Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int64Value) */ {
  public:
-  inline Int64Value() : Int64Value(nullptr) {};
-  virtual ~Int64Value();
+  inline Int64Value() : Int64Value(nullptr) {}
+  ~Int64Value() override;
+  explicit constexpr Int64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Int64Value(const Int64Value& from);
   Int64Value(Int64Value&& from) noexcept
@@ -389,8 +393,9 @@
     return *this;
   }
   inline Int64Value& operator=(Int64Value&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -401,14 +406,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Int64Value& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Int64Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Int64Value* internal_default_instance() {
     return reinterpret_cast<const Int64Value*>(
                &_Int64Value_default_instance_);
@@ -421,7 +426,7 @@
   }
   inline void Swap(Int64Value* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -429,23 +434,26 @@
   }
   void UnsafeArenaSwap(Int64Value* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Int64Value* New() const final {
-    return CreateMaybeMessage<Int64Value>(nullptr);
+    return new Int64Value();
   }
 
   Int64Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Int64Value>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Int64Value& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Int64Value& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -456,8 +464,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Int64Value* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -465,20 +473,17 @@
     return "google.protobuf.Int64Value";
   }
   protected:
-  explicit Int64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Int64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -509,11 +514,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT UInt64Value PROTOBUF_FINAL :
+class PROTOBUF_EXPORT UInt64Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt64Value) */ {
  public:
-  inline UInt64Value() : UInt64Value(nullptr) {};
-  virtual ~UInt64Value();
+  inline UInt64Value() : UInt64Value(nullptr) {}
+  ~UInt64Value() override;
+  explicit constexpr UInt64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UInt64Value(const UInt64Value& from);
   UInt64Value(UInt64Value&& from) noexcept
@@ -526,8 +532,9 @@
     return *this;
   }
   inline UInt64Value& operator=(UInt64Value&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -538,14 +545,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const UInt64Value& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const UInt64Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UInt64Value* internal_default_instance() {
     return reinterpret_cast<const UInt64Value*>(
                &_UInt64Value_default_instance_);
@@ -558,7 +565,7 @@
   }
   inline void Swap(UInt64Value* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -566,23 +573,26 @@
   }
   void UnsafeArenaSwap(UInt64Value* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline UInt64Value* New() const final {
-    return CreateMaybeMessage<UInt64Value>(nullptr);
+    return new UInt64Value();
   }
 
   UInt64Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<UInt64Value>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const UInt64Value& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const UInt64Value& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -593,8 +603,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(UInt64Value* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -602,20 +612,17 @@
     return "google.protobuf.UInt64Value";
   }
   protected:
-  explicit UInt64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit UInt64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -646,11 +653,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT Int32Value PROTOBUF_FINAL :
+class PROTOBUF_EXPORT Int32Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int32Value) */ {
  public:
-  inline Int32Value() : Int32Value(nullptr) {};
-  virtual ~Int32Value();
+  inline Int32Value() : Int32Value(nullptr) {}
+  ~Int32Value() override;
+  explicit constexpr Int32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Int32Value(const Int32Value& from);
   Int32Value(Int32Value&& from) noexcept
@@ -663,8 +671,9 @@
     return *this;
   }
   inline Int32Value& operator=(Int32Value&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -675,14 +684,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const Int32Value& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const Int32Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Int32Value* internal_default_instance() {
     return reinterpret_cast<const Int32Value*>(
                &_Int32Value_default_instance_);
@@ -695,7 +704,7 @@
   }
   inline void Swap(Int32Value* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -703,23 +712,26 @@
   }
   void UnsafeArenaSwap(Int32Value* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline Int32Value* New() const final {
-    return CreateMaybeMessage<Int32Value>(nullptr);
+    return new Int32Value();
   }
 
   Int32Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<Int32Value>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const Int32Value& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const Int32Value& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -730,8 +742,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(Int32Value* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -739,20 +751,17 @@
     return "google.protobuf.Int32Value";
   }
   protected:
-  explicit Int32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit Int32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -783,11 +792,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT UInt32Value PROTOBUF_FINAL :
+class PROTOBUF_EXPORT UInt32Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt32Value) */ {
  public:
-  inline UInt32Value() : UInt32Value(nullptr) {};
-  virtual ~UInt32Value();
+  inline UInt32Value() : UInt32Value(nullptr) {}
+  ~UInt32Value() override;
+  explicit constexpr UInt32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UInt32Value(const UInt32Value& from);
   UInt32Value(UInt32Value&& from) noexcept
@@ -800,8 +810,9 @@
     return *this;
   }
   inline UInt32Value& operator=(UInt32Value&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -812,14 +823,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const UInt32Value& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const UInt32Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UInt32Value* internal_default_instance() {
     return reinterpret_cast<const UInt32Value*>(
                &_UInt32Value_default_instance_);
@@ -832,7 +843,7 @@
   }
   inline void Swap(UInt32Value* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -840,23 +851,26 @@
   }
   void UnsafeArenaSwap(UInt32Value* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline UInt32Value* New() const final {
-    return CreateMaybeMessage<UInt32Value>(nullptr);
+    return new UInt32Value();
   }
 
   UInt32Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<UInt32Value>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const UInt32Value& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const UInt32Value& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -867,8 +881,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(UInt32Value* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -876,20 +890,17 @@
     return "google.protobuf.UInt32Value";
   }
   protected:
-  explicit UInt32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit UInt32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -920,11 +931,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT BoolValue PROTOBUF_FINAL :
+class PROTOBUF_EXPORT BoolValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BoolValue) */ {
  public:
-  inline BoolValue() : BoolValue(nullptr) {};
-  virtual ~BoolValue();
+  inline BoolValue() : BoolValue(nullptr) {}
+  ~BoolValue() override;
+  explicit constexpr BoolValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   BoolValue(const BoolValue& from);
   BoolValue(BoolValue&& from) noexcept
@@ -937,8 +949,9 @@
     return *this;
   }
   inline BoolValue& operator=(BoolValue&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -949,14 +962,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const BoolValue& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const BoolValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const BoolValue* internal_default_instance() {
     return reinterpret_cast<const BoolValue*>(
                &_BoolValue_default_instance_);
@@ -969,7 +982,7 @@
   }
   inline void Swap(BoolValue* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -977,23 +990,26 @@
   }
   void UnsafeArenaSwap(BoolValue* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline BoolValue* New() const final {
-    return CreateMaybeMessage<BoolValue>(nullptr);
+    return new BoolValue();
   }
 
   BoolValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<BoolValue>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const BoolValue& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const BoolValue& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1004,8 +1020,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(BoolValue* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1013,20 +1029,17 @@
     return "google.protobuf.BoolValue";
   }
   protected:
-  explicit BoolValue(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit BoolValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1057,11 +1070,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT StringValue PROTOBUF_FINAL :
+class PROTOBUF_EXPORT StringValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.StringValue) */ {
  public:
-  inline StringValue() : StringValue(nullptr) {};
-  virtual ~StringValue();
+  inline StringValue() : StringValue(nullptr) {}
+  ~StringValue() override;
+  explicit constexpr StringValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   StringValue(const StringValue& from);
   StringValue(StringValue&& from) noexcept
@@ -1074,8 +1088,9 @@
     return *this;
   }
   inline StringValue& operator=(StringValue&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1086,14 +1101,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const StringValue& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const StringValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const StringValue* internal_default_instance() {
     return reinterpret_cast<const StringValue*>(
                &_StringValue_default_instance_);
@@ -1106,7 +1121,7 @@
   }
   inline void Swap(StringValue* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1114,23 +1129,26 @@
   }
   void UnsafeArenaSwap(StringValue* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline StringValue* New() const final {
-    return CreateMaybeMessage<StringValue>(nullptr);
+    return new StringValue();
   }
 
   StringValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<StringValue>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const StringValue& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const StringValue& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1141,8 +1159,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(StringValue* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1150,20 +1168,17 @@
     return "google.protobuf.StringValue";
   }
   protected:
-  explicit StringValue(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit StringValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1175,25 +1190,14 @@
   // string value = 1;
   void clear_value();
   const std::string& value() const;
-  void set_value(const std::string& value);
-  void set_value(std::string&& value);
-  void set_value(const char* value);
-  void set_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_value();
-  std::string* release_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_value();
   void set_allocated_value(std::string* value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_value(
-      std::string* value);
   private:
   const std::string& _internal_value() const;
-  void _internal_set_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value);
   std::string* _internal_mutable_value();
   public:
 
@@ -1210,11 +1214,12 @@
 };
 // -------------------------------------------------------------------
 
-class PROTOBUF_EXPORT BytesValue PROTOBUF_FINAL :
+class PROTOBUF_EXPORT BytesValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BytesValue) */ {
  public:
-  inline BytesValue() : BytesValue(nullptr) {};
-  virtual ~BytesValue();
+  inline BytesValue() : BytesValue(nullptr) {}
+  ~BytesValue() override;
+  explicit constexpr BytesValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   BytesValue(const BytesValue& from);
   BytesValue(BytesValue&& from) noexcept
@@ -1227,8 +1232,9 @@
     return *this;
   }
   inline BytesValue& operator=(BytesValue&& from) noexcept {
-    if (GetArena() == from.GetArena()) {
-      if (this != &from) InternalSwap(&from);
+    if (this == &from) return *this;
+    if (GetOwningArena() == from.GetOwningArena()) {
+      InternalSwap(&from);
     } else {
       CopyFrom(from);
     }
@@ -1239,14 +1245,14 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
-  static const BytesValue& default_instance();
-
-  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static const BytesValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const BytesValue* internal_default_instance() {
     return reinterpret_cast<const BytesValue*>(
                &_BytesValue_default_instance_);
@@ -1259,7 +1265,7 @@
   }
   inline void Swap(BytesValue* other) {
     if (other == this) return;
-    if (GetArena() == other->GetArena()) {
+    if (GetOwningArena() == other->GetOwningArena()) {
       InternalSwap(other);
     } else {
       ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
@@ -1267,23 +1273,26 @@
   }
   void UnsafeArenaSwap(BytesValue* other) {
     if (other == this) return;
-    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
     InternalSwap(other);
   }
 
   // implements Message ----------------------------------------------
 
   inline BytesValue* New() const final {
-    return CreateMaybeMessage<BytesValue>(nullptr);
+    return new BytesValue();
   }
 
   BytesValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
     return CreateMaybeMessage<BytesValue>(arena);
   }
-  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
-  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
   void CopyFrom(const BytesValue& from);
+  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
   void MergeFrom(const BytesValue& from);
+  private:
+  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message*to, const ::PROTOBUF_NAMESPACE_ID::Message&from);
+  public:
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
@@ -1294,8 +1303,8 @@
   int GetCachedSize() const final { return _cached_size_.Get(); }
 
   private:
-  inline void SharedCtor();
-  inline void SharedDtor();
+  void SharedCtor();
+  void SharedDtor();
   void SetCachedSize(int size) const final;
   void InternalSwap(BytesValue* other);
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
@@ -1303,20 +1312,17 @@
     return "google.protobuf.BytesValue";
   }
   protected:
-  explicit BytesValue(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  explicit BytesValue(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+                       bool is_message_owned = false);
   private:
   static void ArenaDtor(void* object);
   inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   public:
 
-  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
-  }
+  static const ClassData _class_data_;
+  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
 
-  public:
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -1328,25 +1334,14 @@
   // bytes value = 1;
   void clear_value();
   const std::string& value() const;
-  void set_value(const std::string& value);
-  void set_value(std::string&& value);
-  void set_value(const char* value);
-  void set_value(const void* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_value();
-  std::string* release_value();
+  PROTOBUF_MUST_USE_RESULT std::string* release_value();
   void set_allocated_value(std::string* value);
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  std::string* unsafe_arena_release_value();
-  GOOGLE_PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for"
-  "    string fields are deprecated and will be removed in a"
-  "    future release.")
-  void unsafe_arena_set_allocated_value(
-      std::string* value);
   private:
   const std::string& _internal_value() const;
-  void _internal_set_value(const std::string& value);
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value);
   std::string* _internal_mutable_value();
   public:
 
@@ -1422,7 +1417,7 @@
 
 // int64 value = 1;
 inline void Int64Value::clear_value() {
-  value_ = PROTOBUF_LONGLONG(0);
+  value_ = int64_t{0};
 }
 inline ::PROTOBUF_NAMESPACE_ID::int64 Int64Value::_internal_value() const {
   return value_;
@@ -1446,7 +1441,7 @@
 
 // uint64 value = 1;
 inline void UInt64Value::clear_value() {
-  value_ = PROTOBUF_ULONGLONG(0);
+  value_ = uint64_t{0u};
 }
 inline ::PROTOBUF_NAMESPACE_ID::uint64 UInt64Value::_internal_value() const {
   return value_;
@@ -1542,54 +1537,38 @@
 
 // string value = 1;
 inline void StringValue::clear_value() {
-  value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  value_.ClearToEmpty();
 }
 inline const std::string& StringValue::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value)
   return _internal_value();
 }
-inline void StringValue::set_value(const std::string& value) {
-  _internal_set_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void StringValue::set_value(ArgT0&& arg0, ArgT... args) {
+ 
+ value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
 }
 inline std::string* StringValue::mutable_value() {
+  std::string* _s = _internal_mutable_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.StringValue.value)
-  return _internal_mutable_value();
+  return _s;
 }
 inline const std::string& StringValue::_internal_value() const {
   return value_.Get();
 }
 inline void StringValue::_internal_set_value(const std::string& value) {
   
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void StringValue::set_value(std::string&& value) {
-  
-  value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.StringValue.value)
-}
-inline void StringValue::set_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.StringValue.value)
-}
-inline void StringValue::set_value(const char* value,
-    size_t size) {
-  
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.StringValue.value)
+  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* StringValue::_internal_mutable_value() {
   
-  return value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* StringValue::release_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value)
-  return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void StringValue::set_allocated_value(std::string* value) {
   if (value != nullptr) {
@@ -1598,28 +1577,9 @@
     
   }
   value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value)
 }
-inline std::string* StringValue::unsafe_arena_release_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.StringValue.value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void StringValue::unsafe_arena_set_allocated_value(
-    std::string* value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (value != nullptr) {
-    
-  } else {
-    
-  }
-  value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.StringValue.value)
-}
 
 // -------------------------------------------------------------------
 
@@ -1627,54 +1587,38 @@
 
 // bytes value = 1;
 inline void BytesValue::clear_value() {
-  value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  value_.ClearToEmpty();
 }
 inline const std::string& BytesValue::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value)
   return _internal_value();
 }
-inline void BytesValue::set_value(const std::string& value) {
-  _internal_set_value(value);
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void BytesValue::set_value(ArgT0&& arg0, ArgT... args) {
+ 
+ value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
   // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
 }
 inline std::string* BytesValue::mutable_value() {
+  std::string* _s = _internal_mutable_value();
   // @@protoc_insertion_point(field_mutable:google.protobuf.BytesValue.value)
-  return _internal_mutable_value();
+  return _s;
 }
 inline const std::string& BytesValue::_internal_value() const {
   return value_.Get();
 }
 inline void BytesValue::_internal_set_value(const std::string& value) {
   
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena());
-}
-inline void BytesValue::set_value(std::string&& value) {
-  
-  value_.Set(
-    &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.BytesValue.value)
-}
-inline void BytesValue::set_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
-              GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.BytesValue.value)
-}
-inline void BytesValue::set_value(const void* value,
-    size_t size) {
-  
-  value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.BytesValue.value)
+  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
 }
 inline std::string* BytesValue::_internal_mutable_value() {
   
-  return value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
 }
 inline std::string* BytesValue::release_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value)
-  return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
 }
 inline void BytesValue::set_allocated_value(std::string* value) {
   if (value != nullptr) {
@@ -1683,28 +1627,9 @@
     
   }
   value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value,
-      GetArena());
+      GetArenaForAllocation());
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value)
 }
-inline std::string* BytesValue::unsafe_arena_release_value() {
-  // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.BytesValue.value)
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  
-  return value_.UnsafeArenaRelease(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      GetArena());
-}
-inline void BytesValue::unsafe_arena_set_allocated_value(
-    std::string* value) {
-  GOOGLE_DCHECK(GetArena() != nullptr);
-  if (value != nullptr) {
-    
-  } else {
-    
-  }
-  value_.UnsafeArenaSetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
-      value, GetArena());
-  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value)
-}
 
 #ifdef __GNUC__
   #pragma GCC diagnostic pop
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
index 9ee41e3..d49dd53 100644
--- a/src/google/protobuf/wrappers.proto
+++ b/src/google/protobuf/wrappers.proto
@@ -44,7 +44,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
-option go_package = "github.com/golang/protobuf/ptypes/wrappers";
+option go_package = "google.golang.org/protobuf/types/known/wrapperspb";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "WrappersProto";
 option java_multiple_files = true;
diff --git a/tests.sh b/tests.sh
index 84fb0b1..f633881 100755
--- a/tests.sh
+++ b/tests.sh
@@ -62,9 +62,9 @@
 
   # List all files that should be included in the distribution package.
   git ls-files | grep "^\(java\|python\|objectivec\|csharp\|js\|ruby\|php\|cmake\|examples\|src/google/protobuf/.*\.proto\)" |\
-    grep -v ".gitignore" | grep -v "java/compatibility_tests" | grep -v "java/lite/proguard.pgcfg" |\
+    grep -v ".gitignore" | grep -v "java/lite/proguard.pgcfg" |\
     grep -v "python/compatibility_tests" | grep -v "python/docs" | grep -v "python/.repo-metadata.json" |\
-    grep -v "csharp/compatibility_tests" > dist.lst
+    grep -v "python/protobuf_distutils" | grep -v "csharp/compatibility_tests" > dist.lst
   # Unzip the dist tar file.
   DIST=`ls *.tar.gz`
   tar -xf $DIST
@@ -104,7 +104,7 @@
 
   # Try to install Java
   pushd java
-  use_java jdk7
+  use_java jdk8
   $MVN install
   popd
 
@@ -163,10 +163,13 @@
 
   export GOPATH="$HOME/gocode"
   mkdir -p "$GOPATH/src/github.com/protocolbuffers"
+  mkdir -p "$GOPATH/src/github.com/golang"
   rm -f "$GOPATH/src/github.com/protocolbuffers/protobuf"
+  rm -f "$GOPATH/src/github.com/golang/protobuf"
   ln -s "`pwd`" "$GOPATH/src/github.com/protocolbuffers/protobuf"
   export PATH="$GOPATH/bin:$PATH"
-  go get github.com/golang/protobuf/protoc-gen-go
+  (cd $GOPATH/src/github.com/golang && git clone https://github.com/golang/protobuf.git && cd protobuf && git checkout v1.3.5)
+  go install github.com/golang/protobuf/protoc-gen-go
 
   cd examples && PROTO_PATH="-I../src -I." make gotest && cd ..
 }
@@ -205,7 +208,13 @@
   # Java build needs `protoc`.
   internal_build_cpp
   cp -r java $dir
-  cd $dir && $MVN clean && $MVN test
+  cd $dir && $MVN clean
+  # Skip the Kotlin tests on Oracle 7
+  if [ "$version" == "oracle7" ]; then
+    $MVN test -pl bom,lite,core,util
+  else
+    $MVN test
+  fi
   cd ../..
 }
 
@@ -217,8 +226,13 @@
   # This local installation avoids the problem caused by a new version not yet in Maven Central
   cd java/bom && $MVN install
   cd ../..
-  cd java && $MVN test && $MVN install
-  cd util && $MVN package assembly:single
+  cd java/core && $MVN test && $MVN install
+  cd ../lite && $MVN test && $MVN install
+  cd ../util && $MVN test && $MVN install && $MVN package assembly:single
+  if [ "$version" == "jdk8" ]; then
+    cd ../kotlin && $MVN test && $MVN install
+    cd ../kotlin-lite && $MVN test && $MVN install
+  fi
   cd ../..
   cd conformance && make test_java && cd ..
 }
@@ -231,17 +245,6 @@
   use_java oracle7
   build_java oracle7
 }
-build_java_compatibility() {
-  use_java jdk7
-  internal_build_cpp
-  # Use the unit-tests extracted from 2.5.0 to test the compatibility between
-  # 3.0.0-beta-4 and the current version.
-  cd java/compatibility_tests/v2.5.0
-  ./test.sh 3.0.0-beta-4
-
-  # Test the last released and current version.
-  ./test.sh $LAST_RELEASED
-}
 build_java_linkage_monitor() {
   # Linkage Monitor checks compatibility with other Google libraries
   # https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor
@@ -302,8 +305,6 @@
 }
 
 build_objectivec_cocoapods_integration() {
-  # Update pod to the latest version.
-  gem install cocoapods --no_document
   objectivec/Tests/CocoaPods/run_tests.sh
 }
 
@@ -313,9 +314,9 @@
   if [ $(uname -s) == "Linux" ]; then
     envlist=py\{27,33,34,35,36\}-python
   else
-    envlist=py27-python
+    envlist=py\{27,36\}-python
   fi
-  tox -e $envlist
+  python -m tox -e $envlist
   cd ..
 }
 
@@ -323,7 +324,7 @@
   internal_build_cpp
   cd python
   envlist=$1
-  tox -e $envlist
+  python -m tox -e $envlist
   cd ..
 }
 
@@ -355,6 +356,10 @@
   build_python_version py38-python
 }
 
+build_python39() {
+  build_python_version py39-python
+}
+
 build_python_cpp() {
   internal_build_cpp
   export LD_LIBRARY_PATH=../src/.libs # for Linux
@@ -363,7 +368,7 @@
   if [ $(uname -s) == "Linux" ]; then
     envlist=py\{27,33,34,35,36\}-cpp
   else
-    envlist=py27-cpp
+    envlist=py\{27,36\}-cpp
   fi
   tox -e $envlist
   cd ..
@@ -407,17 +412,8 @@
   build_python_cpp_version py38-cpp
 }
 
-build_python_compatibility() {
-  internal_build_cpp
-  # Use the unit-tests extracted from 2.5.0 to test the compatibility.
-  cd python/compatibility_tests/v2.5.0
-  # Test between 2.5.0 and the current version.
-  ./test.sh 2.5.0
-  # Test between 3.0.0-beta-1 and the current version.
-  ./test.sh 3.0.0-beta-1
-
-  # Test between last released and current version.
-  ./test.sh $LAST_RELEASED
+build_python39_cpp() {
+  build_python_cpp_version py39-cpp
 }
 
 build_ruby23() {
@@ -440,263 +436,70 @@
   internal_build_cpp  # For conformance tests.
   cd ruby && bash travis-test.sh ruby-2.7.0 && cd ..
 }
+build_ruby30() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-3.0.0 && cd ..
+}
+
+build_jruby() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh jruby-9.2.11.1 && cd ..
+}
 
 build_javascript() {
   internal_build_cpp
+  NODE_VERSION=node-v12.16.3-darwin-x64
+  NODE_TGZ="$NODE_VERSION.tar.gz"
+  pushd /tmp
+  curl -OL https://nodejs.org/dist/v12.16.3/$NODE_TGZ
+  tar zxvf $NODE_TGZ
+  export PATH=$PATH:`pwd`/$NODE_VERSION/bin
+  popd
   cd js && npm install && npm test && cd ..
   cd conformance && make test_nodejs && cd ..
 }
 
-generate_php_test_proto() {
-  internal_build_cpp
-  pushd php/tests
-  # Generate test file
-  rm -rf generated
-  mkdir generated
-  ../../src/protoc --php_out=generated         \
-    -I../../src -I.                            \
-    proto/empty/echo.proto                     \
-    proto/test.proto                           \
-    proto/test_include.proto                   \
-    proto/test_no_namespace.proto              \
-    proto/test_prefix.proto                    \
-    proto/test_php_namespace.proto             \
-    proto/test_empty_php_namespace.proto       \
-    proto/test_reserved_enum_lower.proto       \
-    proto/test_reserved_enum_upper.proto       \
-    proto/test_reserved_enum_value_lower.proto \
-    proto/test_reserved_enum_value_upper.proto \
-    proto/test_reserved_message_lower.proto    \
-    proto/test_reserved_message_upper.proto    \
-    proto/test_service.proto                   \
-    proto/test_service_namespace.proto         \
-    proto/test_wrapper_type_setters.proto      \
-    proto/test_descriptors.proto
-  pushd ../../src
-  ./protoc --php_out=../php/tests/generated -I../php/tests -I. \
-    ../php/tests/proto/test_import_descriptor_proto.proto
-  popd
-  popd
-}
-
 use_php() {
   VERSION=$1
   export PATH=/usr/local/php-${VERSION}/bin:$PATH
-  export CPLUS_INCLUDE_PATH=/usr/local/php-${VERSION}/include/php/main:/usr/local/php-${VERSION}/include/php/:$CPLUS_INCLUDE_PATH
-  export C_INCLUDE_PATH=/usr/local/php-${VERSION}/include/php/main:/usr/local/php-${VERSION}/include/php/:$C_INCLUDE_PATH
-  generate_php_test_proto
+  internal_build_cpp
 }
 
-use_php_zts() {
-  VERSION=$1
-  export PATH=/usr/local/php-${VERSION}-zts/bin:$PATH
-  export CPLUS_INCLUDE_PATH=/usr/local/php-${VERSION}-zts/include/php/main:/usr/local/php-${VERSION}-zts/include/php/:$CPLUS_INCLUDE_PATH
-  export C_INCLUDE_PATH=/usr/local/php-${VERSION}-zts/include/php/main:/usr/local/php-${VERSION}-zts/include/php/:$C_INCLUDE_PATH
-  generate_php_test_proto
-}
-
-use_php_bc() {
-  VERSION=$1
-  export PATH=/usr/local/php-${VERSION}-bc/bin:$PATH
-  export CPLUS_INCLUDE_PATH=/usr/local/php-${VERSION}-bc/include/php/main:/usr/local/php-${VERSION}-bc/include/php/:$CPLUS_INCLUDE_PATH
-  export C_INCLUDE_PATH=/usr/local/php-${VERSION}-bc/include/php/main:/usr/local/php-${VERSION}-bc/include/php/:$C_INCLUDE_PATH
-  generate_php_test_proto
-}
-
-build_php5.5() {
-  use_php 5.5
-
+build_php() {
+  use_php $1
   pushd php
   rm -rf vendor
   composer update
-  ./vendor/bin/phpunit
+  composer test
   popd
-  pushd conformance
-  make test_php
-  popd
+  (cd conformance && make test_php)
 }
 
-build_php5.5_c() {
-  IS_64BIT=$1
-  use_php 5.5
-  pushd php/tests
-  /bin/bash ./test.sh 5.5
-  popd
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-}
-
-build_php5.5_mixed() {
-  use_php 5.5
+test_php_c() {
   pushd php
   rm -rf vendor
   composer update
-  pushd tests
-  /bin/bash ./compile_extension.sh 5.5
+  composer test_c
   popd
-  php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit
-  popd
+  (cd conformance && make test_php_c)
 }
 
-build_php5.5_zts_c() {
-  IS_64BIT=$1
-  use_php_zts 5.5
-  cd php/tests && /bin/bash ./test.sh 5.5-zts && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-}
-
-build_php5.6() {
-  use_php 5.6
-  pushd php
-  rm -rf vendor
-  composer update
-  ./vendor/bin/phpunit
-  popd
-  pushd conformance
-  make test_php
-  popd
-}
-
-build_php5.6_c() {
-  IS_64BIT=$1
-  use_php 5.6
-  cd php/tests && /bin/bash ./test.sh 5.6 && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-}
-
-build_php5.6_mixed() {
-  use_php 5.6
-  pushd php
-  rm -rf vendor
-  composer update
-  pushd tests
-  /bin/bash ./compile_extension.sh 5.6
-  popd
-  php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit
-  popd
-}
-
-build_php5.6_zts_c() {
-  IS_64BIT=$1
-  use_php_zts 5.6
-  cd php/tests && /bin/bash ./test.sh 5.6-zts && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-}
-
-build_php5.6_mac() {
-  generate_php_test_proto
-  # Install PHP
-  curl -s https://php-osx.liip.ch/install.sh | bash -s 5.6
-  PHP_FOLDER=`find /usr/local -type d -name "php5-5.6*"`  # The folder name may change upon time
-  export PATH="$PHP_FOLDER/bin:$PATH"
-
-  # Install phpunit
-  curl https://phar.phpunit.de/phpunit-5.6.8.phar -L -o phpunit.phar
-  chmod +x phpunit.phar
-  sudo mv phpunit.phar /usr/local/bin/phpunit
-
-  # Install valgrind
-  echo "#! /bin/bash" > valgrind
-  chmod ug+x valgrind
-  sudo mv valgrind /usr/local/bin/valgrind
-
-  # Test
-  cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
-  make test_php_c
-  popd
-}
-
-build_php7.0() {
-  use_php 7.0
-  pushd php
-  rm -rf vendor
-  composer update
-  ./vendor/bin/phpunit
-  popd
-  pushd conformance
-  make test_php
-  popd
-}
-
-build_php7.0_c() {
-  IS_64BIT=$1
-  use_php 7.0
-  cd php/tests && /bin/bash ./test.sh 7.0 && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-}
-
-build_php7.0_mixed() {
-  use_php 7.0
-  pushd php
-  rm -rf vendor
-  composer update
-  pushd tests
-  /bin/bash ./compile_extension.sh 7.0
-  popd
-  php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit
-  popd
-}
-
-build_php7.0_zts_c() {
-  IS_64BIT=$1
-  use_php_zts 7.0
-  cd php/tests && /bin/bash ./test.sh 7.0-zts && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
+build_php_c() {
+  use_php $1
+  test_php_c
 }
 
 build_php7.0_mac() {
-  generate_php_test_proto
+  internal_build_cpp
   # Install PHP
   curl -s https://php-osx.liip.ch/install.sh | bash -s 7.0
-  PHP_FOLDER=`find /usr/local -type d -name "php7-7.0*"`  # The folder name may change upon time
+  PHP_FOLDER=`find /usr/local -type d -name "php5-7.0*"`  # The folder name may change upon time
+  test ! -z "$PHP_FOLDER"
   export PATH="$PHP_FOLDER/bin:$PATH"
 
-  # Install phpunit
-  curl https://phar.phpunit.de/phpunit-5.6.0.phar -L -o phpunit.phar
-  chmod +x phpunit.phar
-  sudo mv phpunit.phar /usr/local/bin/phpunit
+  # Install Composer
+  wget https://getcomposer.org/download/2.0.13/composer.phar --progress=dot:mega -O /usr/local/bin/composer
+  chmod a+x /usr/local/bin/composer
 
   # Install valgrind
   echo "#! /bin/bash" > valgrind
@@ -704,23 +507,22 @@
   sudo mv valgrind /usr/local/bin/valgrind
 
   # Test
-  cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
-  make test_php_c
-  popd
+  test_php_c
 }
 
-build_php7.4_mac() {
-  generate_php_test_proto
+build_php7.3_mac() {
+  internal_build_cpp
   # Install PHP
-  curl -s https://php-osx.liip.ch/install.sh | bash -s 7.4
-  PHP_FOLDER=`find /usr/local -type d -name "php7-7.4*"`  # The folder name may change upon time
+  # We can't test PHP 7.4 with these binaries yet:
+  #   https://github.com/liip/php-osx/issues/276
+  curl -s https://php-osx.liip.ch/install.sh | bash -s 7.3
+  PHP_FOLDER=`find /usr/local -type d -name "php5-7.3*"`  # The folder name may change upon time
+  test ! -z "$PHP_FOLDER"
   export PATH="$PHP_FOLDER/bin:$PATH"
 
-  # Install phpunit
-  curl https://phar.phpunit.de/phpunit-8.phar -L -o phpunit.phar
-  chmod +x phpunit.phar
-  sudo mv phpunit.phar /usr/local/bin/phpunit
+  # Install Composer
+  wget https://getcomposer.org/download/2.0.13/composer.phar --progress=dot:mega -O /usr/local/bin/composer
+  chmod a+x /usr/local/bin/composer
 
   # Install valgrind
   echo "#! /bin/bash" > valgrind
@@ -728,10 +530,7 @@
   sudo mv valgrind /usr/local/bin/valgrind
 
   # Test
-  cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
-  make test_php_c
-  popd
+  test_php_c
 }
 
 build_php_compatibility() {
@@ -741,149 +540,28 @@
 
 build_php_multirequest() {
   use_php 7.4
-  pushd php/tests
-  ./multirequest.sh
-  popd
+  php/tests/multirequest.sh
 }
 
-build_php7.1() {
-  use_php 7.1
-  pushd php
-  rm -rf vendor
-  composer update
-  ./vendor/bin/phpunit
-  popd
-  pushd conformance
-  make test_php
-  popd
-}
-
-build_php7.1_c() {
-  IS_64BIT=$1
-  use_php 7.1
-  cd php/tests && /bin/bash ./test.sh 7.1 && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-}
-
-build_php7.1_mixed() {
-  use_php 7.1
-  pushd php
-  rm -rf vendor
-  composer update
-  pushd tests
-  /bin/bash ./compile_extension.sh 7.1
-  popd
-  php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit
-  popd
-}
-
-build_php7.1_zts_c() {
-  IS_64BIT=$1
-  use_php_zts 7.1
-  cd php/tests && /bin/bash ./test.sh 7.1-zts && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-}
-
-build_php7.4() {
-  use_php 7.4
-  pushd php
-  rm -rf vendor
-  composer update
-  ./vendor/bin/phpunit
-  popd
-  pushd conformance
-  make test_php
-  popd
-}
-
-build_php7.4_c() {
-  IS_64BIT=$1
-  use_php 7.4
-  cd php/tests && /bin/bash ./test.sh 7.4 && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-  pushd php/ext/google/protobuf
-  phpize --clean
-  popd
-}
-
-build_php7.4_mixed() {
-  use_php 7.4
-  pushd php
-  rm -rf vendor
-  composer update
-  pushd tests
-  /bin/bash ./compile_extension.sh 7.4
-  popd
-  php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit
-  popd
-  pushd php/ext/google/protobuf
-  phpize --clean
-  popd
-}
-
-build_php7.4_zts_c() {
-  IS_64BIT=$1
-  use_php_zts 7.4
-  cd php/tests && /bin/bash ./test.sh 7.4-zts && cd ../..
-  pushd conformance
-  if [ "$IS_64BIT" = "true" ]
-  then
-    make test_php_c
-  else
-    make test_php_c_32
-  fi
-  popd
-  pushd php/ext/google/protobuf
-  phpize --clean
-  popd
+build_php8.0_all() {
+  build_php 8.0
+  build_php_c 8.0
 }
 
 build_php_all_32() {
-  build_php5.5
-  build_php5.6
-  build_php7.0
-  build_php7.1
-  build_php7.4
-  build_php5.5_c $1
-  build_php5.6_c $1
-  build_php7.0_c $1
-  build_php7.1_c $1
-  build_php7.4_c $1
-  build_php5.5_mixed
-  build_php5.6_mixed
-  build_php7.0_mixed
-  build_php7.1_mixed
-  build_php7.4_mixed
-  build_php5.5_zts_c $1
-  build_php5.6_zts_c $1
-  build_php7.0_zts_c $1
-  build_php7.1_zts_c $1
-  build_php7.4_zts_c $1
+  build_php 7.0
+  build_php 7.1
+  build_php 7.4
+  build_php_c 7.0
+  build_php_c 7.1
+  build_php_c 7.4
+  build_php_c 7.1-zts
+  build_php_c 7.2-zts
+  build_php_c 7.5-zts
 }
 
 build_php_all() {
-  build_php_all_32 true
+  build_php_all_32
   build_php_multirequest
   build_php_compatibility
 }
@@ -902,7 +580,6 @@
             csharp |
             java_jdk7 |
             java_oracle7 |
-            java_compatibility |
             java_linkage_monitor |
             objectivec_ios |
             objectivec_ios_debug |
@@ -919,18 +596,14 @@
             ruby24 |
             ruby25 |
             ruby26 |
+            ruby27 |
+            ruby30 |
             jruby |
             ruby_all |
-            php5.5   |
-            php5.5_c |
-            php5.6   |
-            php5.6_c |
-            php7.0   |
-            php7.0_c |
-            php_compatibility |
-            php7.1   |
-            php7.1_c |
             php_all |
+            php_all_32 |
+            php7.0_mac |
+            php7.3_mac |
             dist_install |
             benchmark)
 "
diff --git a/third_party/wyhash/LICENSE b/third_party/wyhash/LICENSE
new file mode 100644
index 0000000..471f09f
--- /dev/null
+++ b/third_party/wyhash/LICENSE
@@ -0,0 +1,25 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
+
diff --git a/third_party/wyhash/wyhash.h b/third_party/wyhash/wyhash.h
new file mode 100644
index 0000000..bb247a9
--- /dev/null
+++ b/third_party/wyhash/wyhash.h
@@ -0,0 +1,145 @@
+/* Copyright 2020 王一 Wang Yi <godspeed_china@yeah.net>
+   This is free and unencumbered software released into the public domain. http://unlicense.org/
+   See github.com/wangyi-fudan/wyhash/ LICENSE
+ */
+#ifndef wyhash_final_version
+#define wyhash_final_version
+//defines that change behavior
+#ifndef WYHASH_CONDOM
+#define WYHASH_CONDOM 1 //0: read 8 bytes before and after boundaries, dangerous but fastest. 1: normal valid behavior 2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication"
+#endif
+#define WYHASH_32BIT_MUM 0	//faster on 32 bit system
+//includes
+#include <stdint.h>
+#include <string.h>
+#if defined(_MSC_VER) && defined(_M_X64)
+  #include <intrin.h>
+  #pragma intrinsic(_umul128)
+#endif
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
+  #define _likely_(x)	__builtin_expect(x,1)
+  #define _unlikely_(x)	__builtin_expect(x,0)
+#else
+  #define _likely_(x) (x)
+  #define _unlikely_(x) (x)
+#endif
+//mum function
+static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); }
+static inline void _wymum(uint64_t *A, uint64_t *B){
+#if(WYHASH_32BIT_MUM)
+  uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(unsigned)*B, lh=(unsigned)*A*(*B>>32), ll=(uint64_t)(unsigned)*A*(unsigned)*B;
+  #if(WYHASH_CONDOM>1)
+  *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll;
+  #else
+  *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll;
+  #endif
+#elif defined(__SIZEOF_INT128__)
+  __uint128_t r=*A; r*=*B; 
+  #if(WYHASH_CONDOM>1)
+  *A^=(uint64_t)r; *B^=(uint64_t)(r>>64);
+  #else
+  *A=(uint64_t)r; *B=(uint64_t)(r>>64);
+  #endif
+#elif defined(_MSC_VER) && defined(_M_X64)
+  #if(WYHASH_CONDOM>1)
+  uint64_t  a,  b;
+  a=_umul128(*A,*B,&b);
+  *A^=a;  *B^=b;
+  #else
+  *A=_umul128(*A,*B,B);
+  #endif
+#else
+  uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo;
+  uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t<rl;
+  lo=t+(rm1<<32); c+=lo<t; hi=rh+(rm0>>32)+(rm1>>32)+c;
+  #if(WYHASH_CONDOM>1)
+  *A^=lo;  *B^=hi;
+  #else
+  *A=lo;  *B=hi;
+  #endif
+#endif
+}
+static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; }
+//read functions
+#ifndef WYHASH_LITTLE_ENDIAN
+  #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+    #define WYHASH_LITTLE_ENDIAN 1
+  #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+    #define WYHASH_LITTLE_ENDIAN 0
+  #endif
+#endif
+#if (WYHASH_LITTLE_ENDIAN)
+static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;}
+static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;}
+#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
+static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);}
+static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);}
+#elif defined(_MSC_VER)
+static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);}
+static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);}
+#endif
+static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];}
+//wyhash function
+static inline uint64_t _wyfinish16(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
+#if(WYHASH_CONDOM>0)
+  uint64_t a, b;
+  if(_likely_(i<=8)){
+    if(_likely_(i>=4)){ a=_wyr4(p); b=_wyr4(p+i-4); }
+    else if (_likely_(i)){ a=_wyr3(p,i); b=0; }
+    else a=b=0;
+  } 
+  else{ a=_wyr8(p); b=_wyr8(p+i-8); }
+  return _wymix(secret[1]^len,_wymix(a^secret[1], b^seed));
+#else
+  #define oneshot_shift ((i<8)*((8-i)<<3))
+  return _wymix(secret[1]^len,_wymix((_wyr8(p)<<oneshot_shift)^secret[1],(_wyr8(p+i-8)>>oneshot_shift)^seed));
+#endif
+}
+
+static inline uint64_t _wyfinish(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
+  if(_likely_(i<=16)) return _wyfinish16(p,len,seed,secret,i);
+  return _wyfinish(p+16,len,_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed),secret,i-16);
+}
+
+static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t *secret){
+  const uint8_t *p=(const uint8_t *)key;
+  uint64_t i=len; seed^=*secret;
+  if(_unlikely_(i>64)){
+    uint64_t see1=seed;
+    do{
+      seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed)^_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^seed);
+      see1=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see1)^_wymix(_wyr8(p+48)^secret[4],_wyr8(p+56)^see1);
+      p+=64; i-=64;
+    }while(i>64);
+    seed^=see1;
+  }
+  return _wyfinish(p,len,seed,secret,i);
+}
+//utility functions
+static const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 0x1d8e4e27c47d124full};
+static inline uint64_t wyhash64(uint64_t A, uint64_t B){  A^=_wyp[0]; B^=_wyp[1];  _wymum(&A,&B);  return _wymix(A^_wyp[0],B^_wyp[1]);}
+static inline uint64_t wyrand(uint64_t *seed){  *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);}
+static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;}
+static inline double wy2gau(uint64_t r){ const double _wynorm=1.0/(1ull<<20); return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0;}
+static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; }
+
+static inline void make_secret(uint64_t seed, uint64_t *secret){
+  uint8_t c[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90, 92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135, 139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166, 169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202, 204, 209, 210, 212, 216, 225, 226, 228, 232, 240 };
+  for(size_t i=0;i<5;i++){
+    uint8_t ok;
+    do{
+      ok=1; secret[i]=0;
+      for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])<<j;
+      if(secret[i]%2==0){ ok=0; continue; }
+      for(size_t j=0;j<i;j++)
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
+        if(__builtin_popcountll(secret[j]^secret[i])!=32){ ok=0; break; }
+#elif defined(_MSC_VER) && defined(_M_X64)
+        if(_mm_popcnt_u64(secret[j]^secret[i])!=32){ ok=0; break; }
+#endif
+       if(!ok)continue;
+       for(uint64_t j=3;j<0x100000000ull;j+=2) if(secret[i]%j==0){ ok=0; break; }
+    }while(!ok);
+  }
+}
+#endif
diff --git a/update_version.py b/update_version.py
index 1f3332d..9cf1dbf 100755
--- a/update_version.py
+++ b/update_version.py
@@ -13,25 +13,25 @@
 from xml.dom import minidom
 
 if len(sys.argv) < 2 or len(sys.argv) > 3:
-  print """
+  print("""
 [ERROR] Please specify a version.
 
 ./update_version.py <MAJOR>.<MINOR>.<MICRO> [<RC version>]
 
 Example:
 ./update_version.py 3.7.1 2
-"""
+""")
   exit(1)
 
 NEW_VERSION = sys.argv[1]
 NEW_VERSION_INFO = [int(x) for x in NEW_VERSION.split('.')]
 if len(NEW_VERSION_INFO) != 3:
-  print """
+  print("""
 [ERROR] Version must be in the format <MAJOR>.<MINOR>.<MICRO>
 
 Example:
 ./update_version.py 3.7.3
-"""
+""")
   exit(1)
 
 RC_VERSION = -1
@@ -71,9 +71,9 @@
   content = document.toxml().replace('<?xml version="1.0" ?>', '')
   file_handle = open(filename, 'wb')
   if add_xml_prefix:
-    file_handle.write('<?xml version="1.0" encoding="UTF-8"?>\n')
-  file_handle.write(content)
-  file_handle.write('\n')
+    file_handle.write(b'<?xml version="1.0" encoding="UTF-8"?>\n')
+  file_handle.write(content.encode('utf-8'))
+  file_handle.write(b'\n')
   file_handle.close()
 
 
@@ -83,7 +83,7 @@
   for line in lines:
     updated_lines.append(line_rewriter(line))
   if lines == updated_lines:
-    print '%s was not updated. Please double check.' % filename
+    print('%s was not updated. Please double check.' % filename)
   f = open(filename, 'w')
   f.write(''.join(updated_lines))
   f.close()
@@ -101,6 +101,9 @@
 def UpdateCpp():
   cpp_version = '%d%03d%03d' % (
     NEW_VERSION_INFO[0], NEW_VERSION_INFO[1], NEW_VERSION_INFO[2])
+  version_suffix = ''
+  if RC_VERSION != -1:
+    version_suffix = '-rc%s' % RC_VERSION
   def RewriteCommon(line):
     line = re.sub(
       r'^#define GOOGLE_PROTOBUF_VERSION .*$',
@@ -110,6 +113,14 @@
       r'^#define PROTOBUF_VERSION .*$',
       '#define PROTOBUF_VERSION %s' % cpp_version,
       line)
+    line = re.sub(
+        r'^#define GOOGLE_PROTOBUF_VERSION_SUFFIX .*$',
+        '#define GOOGLE_PROTOBUF_VERSION_SUFFIX "%s"' % version_suffix,
+        line)
+    line = re.sub(
+        r'^#define PROTOBUF_VERSION_SUFFIX .*$',
+        '#define PROTOBUF_VERSION_SUFFIX "%s"' % version_suffix,
+        line)
     if NEW_VERSION_INFO[2] == 0:
       line = re.sub(
         r'^#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC .*$',
@@ -128,12 +139,16 @@
         'static const int kMinHeaderVersionForProtoc = %s;' % cpp_version,
         line)
     return line
-  
+
   def RewritePortDef(line):
     line = re.sub(
       r'^#define PROTOBUF_VERSION .*$',
       '#define PROTOBUF_VERSION %s' % cpp_version,
       line)
+    line = re.sub(
+        r'^#define PROTOBUF_VERSION_SUFFIX .*$',
+        '#define PROTOBUF_VERSION_SUFFIX "%s"' % version_suffix,
+        line)
     if NEW_VERSION_INFO[2] == 0:
       line = re.sub(
         r'^#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC .*$',
@@ -213,6 +228,16 @@
       Find(Find(document.documentElement, 'parent'), 'version'),
       GetFullVersion()))
 
+  RewriteXml('java/kotlin/pom.xml',
+    lambda document : ReplaceText(
+      Find(Find(document.documentElement, 'parent'), 'version'),
+      GetFullVersion()))
+
+  RewriteXml('java/kotlin-lite/pom.xml',
+    lambda document : ReplaceText(
+      Find(Find(document.documentElement, 'parent'), 'version'),
+      GetFullVersion()))
+
   RewriteXml('protoc-artifacts/pom.xml',
     lambda document : ReplaceText(
       Find(document.documentElement, 'version'), GetFullVersion()))
@@ -230,11 +255,11 @@
   protobuf_version_offset = 11
   expected_major_version = 3
   if NEW_VERSION_INFO[0] != expected_major_version:
-    print """[ERROR] Major protobuf version has changed. Please update
+    print("""[ERROR] Major protobuf version has changed. Please update
 update_version.py to readjust the protobuf_version_offset and
 expected_major_version such that the PROTOBUF_VERSION in src/Makefile.am is
 always increasing.
-    """
+    """)
     exit(1)
 
   protobuf_version_info = '%d:%d:0' % (
@@ -302,7 +327,7 @@
           FindAndClone(root, 'date'),
           FindAndClone(root, 'time'),
           FindAndClone(root, 'license'),
-          FindAndClone(root, 'notes')
+          CreateNode('notes', 3, []),
         ])
       changelog.appendChild(release)
       changelog.appendChild(document.createTextNode('\n '))
@@ -339,6 +364,13 @@
       '  s.version     = "%s"' % GetFullVersion(rc_suffix = '.rc.'),
       line))
 
+def UpdateBazel():
+  RewriteTextFile('protobuf_version.bzl',
+    lambda line : re.sub(
+     r"^PROTOBUF_VERSION = '.*'$",
+     "PROTOBUF_VERSION = '%s'" % GetFullVersion(),
+     line))
+
 
 UpdateConfigure()
 UpdateCsharp()
@@ -350,3 +382,4 @@
 UpdatePhp()
 UpdatePython()
 UpdateRuby()
+UpdateBazel()